Skip to content

Commit ac2bea2

Browse files
authored
Merge branch 'main' into hiro/cli-project-support
2 parents 3093664 + 202394c commit ac2bea2

26 files changed

Lines changed: 1641 additions & 55 deletions

‎.github/workflows/semgrep.yml‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Semgrep
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
jobs:
12+
scan:
13+
uses: kernel/security-workflows/.github/workflows/semgrep.yml@main
14+
with:
15+
extra-configs: '--config p/golang --config p/trailofbits'
16+
codebase-description: 'Kernel CLI tool authenticating with customer API keys'
17+
secrets: inherit

‎.semgrepignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
vendor/
3+
dist/
4+
*_test.go
5+
go.sum

‎cmd/browsers.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"strconv"
1616
"strings"
1717

18+
"github.com/kernel/cli/pkg/table"
1819
"github.com/kernel/cli/pkg/util"
1920
"github.com/kernel/kernel-go-sdk"
2021
"github.com/kernel/kernel-go-sdk/option"
@@ -3256,6 +3257,9 @@ func runBrowsersComputerWriteClipboard(cmd *cobra.Command, args []string) error
32563257
}
32573258

32583259
func truncateURL(url string, maxLen int) string {
3260+
if !table.IsStdoutTTY() {
3261+
return url
3262+
}
32593263
if len(url) <= maxLen {
32603264
return url
32613265
}

‎pkg/auth/success.html‎

Lines changed: 74 additions & 50 deletions
Large diffs are not rendered by default.

‎pkg/create/templates.go‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
TemplateOpenAGIComputerUse = "openagi-computer-use"
2020
TemplateClaudeAgentSDK = "claude-agent-sdk"
2121
TemplateYutoriComputerUse = "yutori"
22+
TemplateTzafonComputerUse = "tzafon"
2223
)
2324

2425
type TemplateInfo struct {
@@ -90,6 +91,11 @@ var Templates = map[string]TemplateInfo{
9091
Description: "Implements a Yutori n1 computer use agent",
9192
Languages: []string{LanguageTypeScript, LanguagePython},
9293
},
94+
TemplateTzafonComputerUse: {
95+
Name: "Tzafon Northstar Computer Use",
96+
Description: "Implements a Tzafon Northstar CUA Fast computer use agent",
97+
Languages: []string{LanguageTypeScript, LanguagePython},
98+
},
9399
}
94100

95101
// GetSupportedTemplatesForLanguage returns a list of all supported template names for a given language
@@ -116,6 +122,8 @@ func GetSupportedTemplatesForLanguage(language string) TemplateKeyValues {
116122
return 2
117123
case TemplateYutoriComputerUse:
118124
return 3
125+
case TemplateTzafonComputerUse:
126+
return 4
119127
default:
120128
return 10
121129
}
@@ -213,6 +221,11 @@ var Commands = map[string]map[string]DeployConfig{
213221
NeedsEnvFile: true,
214222
InvokeCommand: `kernel invoke ts-yutori-cua cua-task --payload '{"query": "Navigate to https://example.com and describe the page"}'`,
215223
},
224+
TemplateTzafonComputerUse: {
225+
EntryPoint: "index.ts",
226+
NeedsEnvFile: true,
227+
InvokeCommand: `kernel invoke ts-tzafon-cua cua-task --payload '{"query": "Go to wikipedia.org and search for Alan Turing"}'`,
228+
},
216229
},
217230
LanguagePython: {
218231
TemplateSampleApp: {
@@ -260,6 +273,11 @@ var Commands = map[string]map[string]DeployConfig{
260273
NeedsEnvFile: true,
261274
InvokeCommand: `kernel invoke python-yutori-cua cua-task --payload '{"query": "Navigate to https://example.com and describe the page"}'`,
262275
},
276+
TemplateTzafonComputerUse: {
277+
EntryPoint: "main.py",
278+
NeedsEnvFile: true,
279+
InvokeCommand: `kernel invoke python-tzafon-cua cua-task --payload '{"query": "Go to wikipedia.org and search for Alan Turing"}'`,
280+
},
263281
},
264282
}
265283

‎pkg/table/table.go‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package table
22

33
import (
4+
"os"
45
"strings"
56
"unicode/utf8"
67

78
"github.com/pterm/pterm"
9+
"golang.org/x/term"
810
)
911

1012
// PrintTableNoPad renders a table similar to pterm.DefaultTable, but it avoids
@@ -17,12 +19,15 @@ func PrintTableNoPad(data pterm.TableData, hasHeader bool) {
1719
return
1820
}
1921

20-
// Get terminal width and truncate data to fit
21-
termWidth := pterm.GetTerminalWidth()
22-
if termWidth <= 0 {
23-
termWidth = 80 // fallback
22+
// Only truncate columns when outputting to a terminal.
23+
// When piped (non-TTY), output full values so grep/awk/etc. work correctly.
24+
if term.IsTerminal(int(os.Stdout.Fd())) {
25+
termWidth := pterm.GetTerminalWidth()
26+
if termWidth <= 0 {
27+
termWidth = 80 // fallback
28+
}
29+
data = truncateTableData(data, termWidth)
2430
}
25-
data = truncateTableData(data, termWidth)
2631

2732
// Determine number of columns from the first row
2833
numCols := len(data[0])
@@ -90,6 +95,11 @@ func PrintTableNoPad(data pterm.TableData, hasHeader bool) {
9095
pterm.Print(b.String())
9196
}
9297

98+
// IsStdoutTTY reports whether stdout is connected to a terminal.
99+
func IsStdoutTTY() bool {
100+
return term.IsTerminal(int(os.Stdout.Fd()))
101+
}
102+
93103
// truncateTableData intelligently truncates table cells to fit within terminal width
94104
func truncateTableData(data pterm.TableData, termWidth int) pterm.TableData {
95105
if len(data) == 0 {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TZAFON_API_KEY=your-tzafon-api-key
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Kernel Python Sample App - Tzafon Northstar Computer Use
2+
3+
This is a Kernel application that implements a CUA (computer use agent) loop using Tzafon's Northstar CUA Fast model with Kernel's Computer Controls API. The model is accessed via Tzafon's [Lightcone](https://docs.lightcone.ai) API platform.
4+
5+
[Northstar CUA Fast](https://docs.lightcone.ai) is a vision language model trained with reinforcement learning for computer use tasks.
6+
7+
## Setup
8+
9+
1. Get your API keys:
10+
- **Kernel**: [dashboard.onkernel.com](https://dashboard.onkernel.com)
11+
- **Tzafon**: [tzafon.ai](https://www.tzafon.ai)
12+
13+
2. Deploy the app:
14+
```bash
15+
kernel login
16+
cp .env.example .env # Add your TZAFON_API_KEY
17+
kernel deploy main.py --env-file .env
18+
```
19+
20+
## Usage
21+
22+
```bash
23+
kernel invoke python-tzafon-cua cua-task --payload '{"query": "Go to wikipedia.org and search for Alan Turing"}'
24+
```
25+
26+
## Recording Replays
27+
28+
> **Note:** Replay recording is only available to Kernel users on paid plans.
29+
30+
Add `"record_replay": true` to your payload to capture a video of the browser session:
31+
32+
```bash
33+
kernel invoke python-tzafon-cua cua-task --payload '{"query": "Navigate to https://example.com", "record_replay": true}'
34+
```
35+
36+
When enabled, the response will include a `replay_url` field with a link to view the recorded session.
37+
38+
## Viewport Configuration
39+
40+
Northstar CUA Fast works well with a **1280x800** viewport, which is the default.
41+
42+
## Supported Actions
43+
44+
| Action | Description |
45+
|--------|-------------|
46+
| `click` | Left or right mouse click at coordinates |
47+
| `double_click` | Double-click at coordinates |
48+
| `point_and_type` | Click at coordinates then type text (with optional Enter) |
49+
| `key` | Press key combo (e.g. `Enter`, `ctrl+a`) |
50+
| `scroll` | Scroll at coordinates |
51+
| `drag` | Click-and-drag from start to end coordinates |
52+
| `done` | Signal task completion with a result summary |
53+
54+
## Resources
55+
56+
- [Lightcone API Documentation](https://docs.lightcone.ai)
57+
- [Kernel Documentation](https://www.kernel.sh/docs/quickstart)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__pycache__/
2+
*.py[cod]
3+
*$py.class
4+
.env
5+
*.log
6+
.venv/
7+
venv/

0 commit comments

Comments
 (0)