background-agents 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -364
- package/app/assets/icon.png +0 -0
- package/app/assets/tray-icon.png +0 -0
- package/app/assets/tray-icon.svg +4 -0
- package/app/dist/main.js +932 -0
- package/app/dist/preload.cjs +70 -0
- package/bin/background-agents.js +298 -0
- package/lib/ui.js +110 -0
- package/package.json +32 -47
- package/dist/debug.d.ts +0 -7
- package/dist/debug.d.ts.map +0 -1
- package/dist/debug.js +0 -19
- package/dist/debug.js.map +0 -1
- package/dist/factory.d.ts +0 -31
- package/dist/factory.d.ts.map +0 -1
- package/dist/factory.js +0 -47
- package/dist/factory.js.map +0 -1
- package/dist/index.d.ts +0 -30
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -35
- package/dist/index.js.map +0 -1
- package/dist/providers/base.d.ts +0 -160
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js +0 -656
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/claude.d.ts +0 -14
- package/dist/providers/claude.d.ts.map +0 -1
- package/dist/providers/claude.js +0 -122
- package/dist/providers/claude.js.map +0 -1
- package/dist/providers/codex.d.ts +0 -14
- package/dist/providers/codex.d.ts.map +0 -1
- package/dist/providers/codex.js +0 -160
- package/dist/providers/codex.js.map +0 -1
- package/dist/providers/gemini.d.ts +0 -16
- package/dist/providers/gemini.d.ts.map +0 -1
- package/dist/providers/gemini.js +0 -91
- package/dist/providers/gemini.js.map +0 -1
- package/dist/providers/index.d.ts +0 -6
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -6
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/opencode.d.ts +0 -14
- package/dist/providers/opencode.d.ts.map +0 -1
- package/dist/providers/opencode.js +0 -100
- package/dist/providers/opencode.js.map +0 -1
- package/dist/sandbox/daytona-ssh.d.ts +0 -9
- package/dist/sandbox/daytona-ssh.d.ts.map +0 -1
- package/dist/sandbox/daytona-ssh.js +0 -113
- package/dist/sandbox/daytona-ssh.js.map +0 -1
- package/dist/sandbox/daytona.d.ts +0 -4
- package/dist/sandbox/daytona.d.ts.map +0 -1
- package/dist/sandbox/daytona.js +0 -238
- package/dist/sandbox/daytona.js.map +0 -1
- package/dist/sandbox/index.d.ts +0 -14
- package/dist/sandbox/index.d.ts.map +0 -1
- package/dist/sandbox/index.js +0 -15
- package/dist/sandbox/index.js.map +0 -1
- package/dist/session.d.ts +0 -64
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -113
- package/dist/session.js.map +0 -1
- package/dist/types/events.d.ts +0 -114
- package/dist/types/events.d.ts.map +0 -1
- package/dist/types/events.js +0 -50
- package/dist/types/events.js.map +0 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/types/provider.d.ts +0 -124
- package/dist/types/provider.d.ts.map +0 -1
- package/dist/types/provider.js +0 -2
- package/dist/types/provider.js.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -4
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/install.d.ts +0 -27
- package/dist/utils/install.d.ts.map +0 -1
- package/dist/utils/install.js +0 -86
- package/dist/utils/install.js.map +0 -1
- package/dist/utils/json.d.ts +0 -8
- package/dist/utils/json.d.ts.map +0 -1
- package/dist/utils/json.js +0 -15
- package/dist/utils/json.js.map +0 -1
- package/dist/utils/session.d.ts +0 -17
- package/dist/utils/session.d.ts.map +0 -1
- package/dist/utils/session.js +0 -59
- package/dist/utils/session.js.map +0 -1
- package/next.config.codeagentsdk.cjs +0 -22
package/README.md
CHANGED
|
@@ -1,402 +1,83 @@
|
|
|
1
|
-
#
|
|
1
|
+
# background-agents
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { Daytona } from "@daytonaio/sdk"
|
|
7
|
-
import { createSession } from "background-agents"
|
|
8
|
-
|
|
9
|
-
const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY })
|
|
10
|
-
const sandbox = await daytona.create({ envVars: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY } })
|
|
11
|
-
const session = await createSession("claude", { sandbox })
|
|
12
|
-
|
|
13
|
-
for await (const event of session.run("Hello!")) {
|
|
14
|
-
if (event.type === "token") process.stdout.write(event.text)
|
|
15
|
-
if (event.type === "end") break
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
await sandbox.delete()
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Same pattern for any provider: create a sandbox, create a session, stream events, then tear down. Swap the provider name and env keys as needed.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Features
|
|
26
|
-
|
|
27
|
-
- **Secure by default** — Execution runs in isolated Daytona sandboxes
|
|
28
|
-
- **Real-time streaming** — PTY-based streaming for live token output
|
|
29
|
-
- **Unified API** — One interface for [Claude](https://docs.anthropic.com/en/docs/claude-code), [Codex](https://developers.openai.com/codex/cli), [Gemini](https://geminicli.com/docs/), and [OpenCode](https://opencode.ai/docs/)
|
|
30
|
-
- **Zero-friction setup** — Provider CLI is installed when you create a session (`skipInstall: true` to skip). Env and Codex login run on every `run()`.
|
|
31
|
-
- **Session persistence** — Resume conversations across runs
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## Provider support
|
|
36
|
-
|
|
37
|
-
| Provider | Status | Auth |
|
|
38
|
-
|----------|--------|------|
|
|
39
|
-
| [Claude](https://docs.anthropic.com/en/docs/claude-code) | ✅ | `ANTHROPIC_API_KEY` |
|
|
40
|
-
| [Codex](https://developers.openai.com/codex/cli) | ✅ | `OPENAI_API_KEY` |
|
|
41
|
-
| [OpenCode](https://opencode.ai/docs/) | ✅ | Provider-specific (e.g. `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`) |
|
|
42
|
-
| [Gemini](https://geminicli.com/docs/) | 🚧 | `GOOGLE_API_KEY` |
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Prerequisites
|
|
47
|
-
|
|
48
|
-
A [Daytona](https://daytona.io) API key (or [run locally](#local-mode-dangerous) without a sandbox).
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
export DAYTONA_API_KEY=dtn_your_api_key
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## Installation
|
|
3
|
+
Launch the **Background Agents** desktop app with a single command — no install, always the latest version:
|
|
57
4
|
|
|
58
5
|
```bash
|
|
59
|
-
|
|
6
|
+
npx background-agents@latest
|
|
60
7
|
```
|
|
61
8
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
npm install @daytonaio/sdk
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**Next.js:** Merge the SDK's Next config so native deps (e.g. `ssh2` / `cpu-features`) are not bundled:
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
// next.config.js or next.config.mjs
|
|
72
|
-
import codeagentsdk from 'background-agents/next.config'
|
|
73
|
-
export default { ...codeagentsdk, ...yourConfig }
|
|
74
|
-
```
|
|
9
|
+
That's it. The first run downloads the Electron runtime (~once, then cached); every run loads the production app at <https://backgrounder.dev>.
|
|
75
10
|
|
|
76
|
-
|
|
11
|
+
> **Naming:** the TypeScript SDK previously published as `background-agents` now lives at [`@background-agents/sdk`](../agents), which freed the `background-agents` name for this desktop launcher.
|
|
77
12
|
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
**1. Create a sandbox** — Pass provider API keys via the sandbox; the SDK does not read your host env.
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
import { Daytona } from "@daytonaio/sdk"
|
|
84
|
-
import { createSession } from "background-agents"
|
|
85
|
-
|
|
86
|
-
const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY })
|
|
87
|
-
const sandbox = await daytona.create({
|
|
88
|
-
envVars: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
|
|
89
|
-
})
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
**2. Create a session** — The provider CLI is installed in the sandbox (unless `skipInstall: true`).
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
const session = await createSession("claude", {
|
|
96
|
-
sandbox,
|
|
97
|
-
model: "sonnet",
|
|
98
|
-
timeout: 120,
|
|
99
|
-
systemPrompt: "You are a helpful coding assistant.",
|
|
100
|
-
})
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**3. Stream responses**
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
for await (const event of session.run("Hello!")) {
|
|
107
|
-
if (event.type === "token") process.stdout.write(event.text)
|
|
108
|
-
if (event.type === "tool_start") console.log(`\n[Tool: ${event.name}]`)
|
|
109
|
-
if (event.type === "end") break
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
**4. Cleanup**
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
await sandbox.delete()
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Optional: Git workflow** — Use the [Daytona Git SDK](https://www.daytona.io/docs/en/typescript-sdk/git/) to clone before and push after:
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const repoPath = "workspace/repo"
|
|
123
|
-
await sandbox.git.clone("https://github.com/user/repo.git", repoPath)
|
|
124
|
-
// ... run session ...
|
|
125
|
-
await sandbox.git.push(repoPath)
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## Full example
|
|
131
|
-
|
|
132
|
-
End-to-end example with event handling and cleanup:
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
import { Daytona } from "@daytonaio/sdk"
|
|
136
|
-
import { createSession } from "background-agents"
|
|
137
|
-
|
|
138
|
-
async function main() {
|
|
139
|
-
const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY })
|
|
140
|
-
const sandbox = await daytona.create({
|
|
141
|
-
envVars: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
const session = await createSession("claude", { sandbox })
|
|
146
|
-
|
|
147
|
-
for await (const event of session.run("List /tmp then write /tmp/out.txt with 'done'")) {
|
|
148
|
-
switch (event.type) {
|
|
149
|
-
case "token":
|
|
150
|
-
process.stdout.write(event.text)
|
|
151
|
-
break
|
|
152
|
-
case "tool_start":
|
|
153
|
-
console.log("\n🛠️", event.name, event.input ?? "")
|
|
154
|
-
break
|
|
155
|
-
case "end":
|
|
156
|
-
console.log("\nDone.")
|
|
157
|
-
break
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
} finally {
|
|
161
|
-
await sandbox.delete()
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
main()
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### CLI commands (reference)
|
|
169
|
-
|
|
170
|
-
Each provider is invoked via its CLI. Optional flags in brackets.
|
|
171
|
-
|
|
172
|
-
| Provider | Command |
|
|
173
|
-
|----------|---------|
|
|
174
|
-
| **Claude** | `claude -p --output-format stream-json --verbose --dangerously-skip-permissions` `[--model <m>] [--resume <id>]` `<prompt>` |
|
|
175
|
-
| **Codex** | `codex exec --json --skip-git-repo-check --yolo` `[--model <m>] [resume <id>]` `<prompt>` |
|
|
176
|
-
| **OpenCode** | `opencode run --format json --variant medium -m <model>` `[-s <id>]` `<prompt>` (via `bash -lc "…"`) |
|
|
177
|
-
| **Gemini** | `gemini -p --output-format stream-json --yolo` `[--model <m>] [--resume <id>]` `<prompt>` |
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
## API reference
|
|
182
|
-
|
|
183
|
-
### `createSession(provider, options)`
|
|
184
|
-
|
|
185
|
-
Creates a session with the given provider and options (e.g. `sandbox`, `model`, `timeout`). Installs the provider CLI in the sandbox before returning unless `skipInstall: true`. Codex login runs automatically on each `run()` when needed.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const session = await createSession("claude", {
|
|
189
|
-
sandbox,
|
|
190
|
-
model: "sonnet",
|
|
191
|
-
timeout: 120,
|
|
192
|
-
})
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### `session.run(prompt)`
|
|
13
|
+
## How it works
|
|
196
14
|
|
|
197
|
-
|
|
15
|
+
This is a thin launcher published to npm as [`background-agents`](https://www.npmjs.com/package/background-agents):
|
|
198
16
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
```
|
|
17
|
+
1. `npx background-agents@latest` resolves the **latest published version** of this package from the npm registry.
|
|
18
|
+
2. npm installs it and its one dependency, **Electron**, downloading the platform binary on first run (cached for later runs).
|
|
19
|
+
3. The launcher spawns the bundled Electron app (`app/`) pointed at the production backend, showing a small terminal UI while it starts.
|
|
204
20
|
|
|
205
|
-
|
|
21
|
+
Because every launch pulls the latest npm version, **publishing a new version is the update mechanism** — there's no separate auto-updater to configure or code-sign.
|
|
206
22
|
|
|
207
|
-
|
|
208
|
-
|-------|-------------|--------|
|
|
209
|
-
| `session` | Session started (for resumption) | `id: string` |
|
|
210
|
-
| `token` | Streamed assistant text | `text: string` |
|
|
211
|
-
| `tool_start` | Tool invoked | `name: string`, `input?: unknown` |
|
|
212
|
-
| `tool_delta` | Streaming tool input | `text: string` |
|
|
213
|
-
| `tool_end` | Tool finished | `output?: string` |
|
|
214
|
-
| `end` | Turn complete | — |
|
|
215
|
-
| `agent_crashed` | Process exited without completing (crash/kill) | `message?: string`, `output?: string` (raw tail of stdout/stderr; often not JSONL) |
|
|
23
|
+
## Usage
|
|
216
24
|
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
| { type: "session"; id: string }
|
|
220
|
-
| { type: "token"; text: string }
|
|
221
|
-
| { type: "tool_start"; name: string; input?: unknown }
|
|
222
|
-
| { type: "tool_delta"; text: string }
|
|
223
|
-
| { type: "tool_end"; output?: string }
|
|
224
|
-
| { type: "end" }
|
|
225
|
-
| { type: "agent_crashed"; message?: string; output?: string }
|
|
25
|
+
```bash
|
|
26
|
+
npx background-agents [options]
|
|
226
27
|
```
|
|
227
28
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
|
233
|
-
|
|
234
|
-
|
|
|
235
|
-
| **read** | `{ file_path }` | ✅ | — | ✅ |
|
|
236
|
-
| **edit** | `{ file_path, ... }` | ✅ | — | ✅ |
|
|
237
|
-
| **glob** | `{ pattern }` | ✅ | — | ✅ |
|
|
238
|
-
| **grep** | `{ pattern, path? }` | ✅ | — | ✅ |
|
|
239
|
-
| **shell** | `{ command, description? }` | ✅ | ✅ | ✅ |
|
|
240
|
-
|
|
241
|
-
---
|
|
242
|
-
|
|
243
|
-
## Model selection
|
|
244
|
-
|
|
245
|
-
Set `model` when creating the session.
|
|
246
|
-
|
|
247
|
-
| Provider | Example | Docs |
|
|
248
|
-
|----------|---------|------|
|
|
249
|
-
| **Claude** | `model: "sonnet"` or `"opus"`, `"haiku"` | [Claude Code models](https://code.claude.com/docs/en/model-config) |
|
|
250
|
-
| **Codex** | `model: "gpt-4o"` or `"o1"`, `"o3"` | [Codex CLI models](https://developers.openai.com/codex/models) |
|
|
251
|
-
| **OpenCode** | `model: "openai/gpt-4o"` (provider/model) | [OpenCode models](https://opencode.ai/docs/models/) |
|
|
252
|
-
| **Gemini** | `model: "gemini-2.0-flash"` or `"gemini-1.5-pro"` | [Gemini CLI model](https://geminicli.com/docs/cli/model) |
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## Sandboxed background sessions
|
|
257
|
-
|
|
258
|
-
For long-running or restart-tolerant flows: start the agent in the sandbox, write the event stream to log files there, and poll with **getEvents**. All state except the session ID lives in the sandbox.
|
|
259
|
-
|
|
260
|
-
- **Session ID** — One UUID per background session; host stores only this.
|
|
261
|
-
- **start()** — Returns immediately with `{ executionId, pid, outputFile }`; the agent runs in the background.
|
|
262
|
-
- **isRunning()** — True while the turn is in progress, false after.
|
|
263
|
-
- **Crash detection** — If the process exits without completing, **getEvents** returns an `agent_crashed` event. You can treat it like `end` to stop polling and show a warning.
|
|
264
|
-
|
|
265
|
-
**Example:** start, persist `sandboxId` and `backgroundSessionId`, then reattach after a restart.
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
import { Daytona } from "@daytonaio/sdk"
|
|
269
|
-
import { createBackgroundSession, getBackgroundSession } from "background-agents"
|
|
29
|
+
| Option | Description |
|
|
30
|
+
|--------|-------------|
|
|
31
|
+
| `--url <url>` | Backend URL to load (default: `https://backgrounder.dev`) |
|
|
32
|
+
| `--dev` | Use the local dev server (`http://localhost:4000`) |
|
|
33
|
+
| `--verbose` | Stream the desktop app's logs to the terminal |
|
|
34
|
+
| `-v`, `--version` | Print the launcher version |
|
|
35
|
+
| `-h`, `--help` | Show help |
|
|
270
36
|
|
|
271
|
-
|
|
272
|
-
const sandbox = await daytona.create({
|
|
273
|
-
envVars: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
|
|
274
|
-
})
|
|
37
|
+
Environment variable `BACKGROUND_AGENTS_URL` does the same as `--url` (the flag wins).
|
|
275
38
|
|
|
276
|
-
|
|
277
|
-
sandbox,
|
|
278
|
-
model: "sonnet",
|
|
279
|
-
// Optional: per-session system prompt (applied once, persisted across turns).
|
|
280
|
-
systemPrompt: "You are a helpful coding assistant.",
|
|
281
|
-
})
|
|
282
|
-
await bgSession.start("Do a long-running refactor...")
|
|
283
|
-
// Persist sandbox.id and bgSession.id, then exit.
|
|
39
|
+
> Tip: plain `npx background-agents` may reuse an npx-cached copy. Use `npx background-agents@latest` to force the newest version.
|
|
284
40
|
|
|
285
|
-
|
|
286
|
-
const sandboxAgain = await daytona.get(sandboxId)
|
|
287
|
-
const bgAgain = await getBackgroundSession({
|
|
288
|
-
sandbox: sandboxAgain,
|
|
289
|
-
backgroundSessionId,
|
|
290
|
-
// Re-apply session options so the provider is recreated with the same model
|
|
291
|
-
// and system prompt when reattaching.
|
|
292
|
-
model: "sonnet",
|
|
293
|
-
systemPrompt: "You are a helpful coding assistant.",
|
|
294
|
-
})
|
|
41
|
+
## Caveats
|
|
295
42
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (e.type === "token") process.stdout.write(e.text)
|
|
300
|
-
else if (e.type === "tool_start") console.log("[Tool]", e.name)
|
|
301
|
-
}
|
|
302
|
-
if (!(await bgAgain.isRunning())) return
|
|
303
|
-
setTimeout(poll, 2000)
|
|
304
|
-
}
|
|
305
|
-
poll()
|
|
43
|
+
- **First run downloads Electron** (~100–150 MB) via npm; it's cached afterward and re-downloaded only when a new version ships a different Electron.
|
|
44
|
+
- The app runs **unpackaged**, so it relies on programmatic `background-agents://` deep-link registration for the OAuth round-trip (same code path as running the app from source). For a fully signed/notarized native install, use the packaged builds from GitHub Releases instead.
|
|
45
|
+
- This package was **0.1.1 / 0.1.2 as the SDK**; the launcher is published from **1.0.0** onward, so `latest` cleanly points at the desktop app.
|
|
306
46
|
|
|
307
|
-
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
---
|
|
311
|
-
|
|
312
|
-
## Local mode (dangerous)
|
|
313
|
-
|
|
314
|
-
Runs the provider CLI on your machine instead of a sandbox. Only use when you fully trust the code.
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
const session = await createSession("claude", { dangerouslyAllowLocalExecution: true })
|
|
318
|
-
for await (const event of session.run("Hello")) {
|
|
319
|
-
if (event.type === "token") process.stdout.write(event.text)
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
---
|
|
47
|
+
## Development
|
|
324
48
|
|
|
325
|
-
|
|
49
|
+
This package lives in the monorepo at `packages/launcher`. Its `app/` directory is generated — it's a copy of the compiled `@background-agents/electron` output.
|
|
326
50
|
|
|
327
51
|
```bash
|
|
328
|
-
#
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
# Other providers
|
|
332
|
-
npx tsx scripts/repl.ts --provider codex # OPENAI_API_KEY
|
|
333
|
-
npx tsx scripts/repl.ts --provider opencode
|
|
334
|
-
npx tsx scripts/repl.ts --provider gemini # GEMINI_API_KEY (or GOOGLE_API_KEY)
|
|
52
|
+
# From the repo root:
|
|
53
|
+
npm run bundle -w background-agents # build the Electron app + copy it into app/
|
|
54
|
+
npm start -w background-agents # run the launcher locally (after bundling)
|
|
335
55
|
|
|
336
|
-
#
|
|
337
|
-
|
|
56
|
+
# Verify the published tarball contents:
|
|
57
|
+
cd packages/launcher && npm pack --dry-run
|
|
338
58
|
```
|
|
339
59
|
|
|
340
|
-
|
|
341
|
-
npx tsx scripts/repl.ts -h # help; providers: claude, codex, opencode, gemini
|
|
342
|
-
```
|
|
60
|
+
`prepack` runs the bundle step automatically, so `npm publish` always ships a fresh build.
|
|
343
61
|
|
|
344
|
-
|
|
62
|
+
## Publishing
|
|
345
63
|
|
|
346
|
-
|
|
64
|
+
Two ways:
|
|
347
65
|
|
|
348
|
-
|
|
349
|
-
2. **CLI** — Provider CLI is installed in the sandbox at session creation (unless `skipInstall: true`). Each `run()` sets env and, for Codex, runs `codex login --with-api-key`.
|
|
350
|
-
3. **PTY** — Commands run in a PTY for real-time streaming.
|
|
351
|
-
4. **Events** — JSON from the CLI is parsed into typed events.
|
|
352
|
-
5. **Cleanup** — You call `sandbox.delete()` when done.
|
|
66
|
+
### Automatic — on a version tag (GitHub Actions)
|
|
353
67
|
|
|
354
|
-
|
|
355
|
-
┌─────────────┐ ┌──────────────────────────────────────┐
|
|
356
|
-
│ Your App │────▶│ Daytona Sandbox │
|
|
357
|
-
│ │◀────│ ┌─────────────┐ ┌─────────────┐ │
|
|
358
|
-
│ │ │ │ PTY Stream │◀──▶│ Agent CLI │ │
|
|
359
|
-
│ │ │ └─────────────┘ └─────────────┘ │
|
|
360
|
-
└─────────────┘ └──────────────────────────────────────┘
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
---
|
|
364
|
-
|
|
365
|
-
## Debug mode
|
|
366
|
-
|
|
367
|
-
Set `CODING_AGENTS_DEBUG=1` (or any non-empty value) to log debugging information to stderr:
|
|
368
|
-
|
|
369
|
-
- **Agent lifecycle** — when sessions and background sessions are created, when runs start and end
|
|
370
|
-
- **Background agents** — when a turn starts (session dir, turn number, output file), when the background process is started (pid), and each time events are polled (cursor, event count)
|
|
371
|
-
- **Unparsed output** — any CLI line that didn’t parse as an event (helps spot hangs where the agent prints something the SDK doesn’t recognize)
|
|
68
|
+
Pushing a `v*` tag runs the publish workflow, which sets the package version from the tag and publishes to npm (requires the `NPM_TOKEN` repo secret).
|
|
372
69
|
|
|
373
70
|
```bash
|
|
374
|
-
|
|
71
|
+
git tag v1.0.1 && git push origin v1.0.1
|
|
375
72
|
```
|
|
376
73
|
|
|
377
|
-
|
|
74
|
+
> The workflow ships as `.github/npm-publish-workflow.yml` (outside `.github/workflows/`, mirroring `release-workflow.yml`, because pushing into `.github/workflows/` needs the GitHub `workflow` OAuth scope). **Move it into `.github/workflows/` to activate it.** Note the same `v*` tag also triggers `release-workflow.yml` (the Electron installers), so the desktop installers and the npm launcher publish together.
|
|
378
75
|
|
|
379
|
-
|
|
76
|
+
### Manual
|
|
380
77
|
|
|
381
78
|
```bash
|
|
382
|
-
npm
|
|
383
|
-
npm
|
|
384
|
-
npm test # unit tests (integration/sandbox-background skipped without keys)
|
|
385
|
-
DAYTONA_API_KEY=... ANTHROPIC_API_KEY=... npm run test -- tests/integration/sandbox-background.test.ts # real sandbox background test
|
|
386
|
-
DAYTONA_API_KEY=... ANTHROPIC_API_KEY=... npx tsx scripts/test-sdk-full.ts # integration
|
|
387
|
-
DAYTONA_API_KEY=... ANTHROPIC_API_KEY=... npx tsx scripts/repl.ts # REPL
|
|
79
|
+
npm ci # from the repo root
|
|
80
|
+
npm publish -w background-agents --access public
|
|
388
81
|
```
|
|
389
82
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
## Resources
|
|
393
|
-
|
|
394
|
-
**Sandbox** — [Daytona Docs](https://www.daytona.io/docs/) · [Daytona GitHub](https://github.com/daytonaio/daytona)
|
|
395
|
-
|
|
396
|
-
**Agents** — [Claude Code](https://docs.anthropic.com/en/docs/claude-code) · [Codex CLI](https://developers.openai.com/codex/cli) · [Gemini CLI](https://geminicli.com/docs/) · [OpenCode](https://opencode.ai/docs/)
|
|
397
|
-
|
|
398
|
-
---
|
|
399
|
-
|
|
400
|
-
## License
|
|
401
|
-
|
|
402
|
-
MIT
|
|
83
|
+
You must be logged in (`npm login`) with publish rights to the `background-agents` package. The first launcher publish must be version **≥ 1.0.0** (0.1.1 / 0.1.2 already exist from the SDK era).
|
|
Binary file
|
|
Binary file
|