Merge master into compact-tool-result-prune
This commit is contained in:
@@ -33,11 +33,15 @@ The full-screen terminal sibling of `repl-agent`: it reuses the same coding back
|
||||
|
||||
Run with: `pnpm run demo:tui` (needs `DEEPSEEK_API_KEY`). See [tui-agent/README.md](tui-agent/README.md) for controls and composition.
|
||||
|
||||
## jsonrpc-agent
|
||||
|
||||
An unattended coding agent driven through the Python SDK: JSON-RPC stdio, foreground-only `bash`, `read` / `write` / `edit`, one foreground `subagent`, `todo_write`, JSONL persistence, and compaction. It excludes terminal UI, stdout logging, approvals, skills, and background task controls. See [jsonrpc-agent/README.md](jsonrpc-agent/README.md).
|
||||
|
||||
## cordis-agent
|
||||
|
||||
The **self-referential** demo: the coding spine plus [`@deepseek-ai/dsh-tool-cordis`](../packages/cordis/tool-cordis), whose three tools (`cordis_inspect` / `cordis_mount` / `cordis_unmount`) let the agent inspect the live cordis runtime it runs inside, mount model-written plugins into it (an event listener, a brand-new tool for itself, or a service another mount injects), and dispose them again — all dynamic mounts grouped under one `cordis-dynamic` fiber subtree. The `ctx.fs`/`ctx.web` services ride along provider-only, as the capabilities those plugins build on.
|
||||
|
||||
Run with: `pnpm run demo:cordis` (needs `DEEPSEEK_API_KEY`). See [cordis-agent/README.md](cordis-agent/README.md) for the staged demo script and [the toolset RFC](../docs/rfc/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) for the design and sandbox caveats.
|
||||
Run with: `pnpm run demo:cordis` (needs `DEEPSEEK_API_KEY`). See [cordis-agent/README.md](cordis-agent/README.md) for the staged demo script and [the toolset Agent Note](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) for the design and sandbox caveats.
|
||||
|
||||
## acp-agent
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ pnpm run demo:acp # needs DEEPSEEK_API_KEY (repo-root .env or env)
|
||||
pnpm run demo:code-mode acp # the same server in Code Mode: one wire tool, run_code
|
||||
```
|
||||
|
||||
The leaf config loads the ACP app, DeepSeek adapter, sandboxed bash, approval and permission services, model-facing tools, and repeat guard. The app bundles the agent spine, JSONL persistence, and bridge, creates agents on `session/new`, and keeps stdout logger-free. [`fs.cordis.yml`](fs.cordis.yml) adds the unconfined in-process filesystem stack and local tool-result spill storage for its dedicated scenarios; [`code-mode.cordis.yml`](code-mode.cordis.yml) adds `run_code` and its generated TypeScript SDK. See [Code Mode](../../packages/core/tools/README.md#code-mode).
|
||||
The leaf config loads the ACP app, DeepSeek adapter, sandboxed bash, the sandboxed filesystem stack, approval and permission services, model-facing tools, and repeat guard. The app bundles the agent spine, JSONL persistence, and bridge, creates agents on `session/new`, and keeps stdout logger-free. [`fs.cordis.yml`](fs.cordis.yml) adds local tool-result spill storage for its dedicated scenarios; [`code-mode.cordis.yml`](code-mode.cordis.yml) adds `run_code` and its generated TypeScript SDK. See [Code Mode](../../packages/core/tools/README.md#code-mode).
|
||||
|
||||
## stdout is the protocol
|
||||
|
||||
@@ -29,19 +29,19 @@ Add to your Zed `settings.json` under `agent_servers`:
|
||||
}
|
||||
```
|
||||
|
||||
The editor sets each session's `cwd` to the project it opens, and bash uses that directory as its workdir. The current sandbox write boundary is nevertheless fixed when the server starts (`workspaceRoot: process.cwd()`), so launch the server from the workspace it should be allowed to modify; making that root session-scoped is deferred in the [sandbox RFC](../../docs/rfc/implemented/feature/2026-07-06-sandbox.md). Filesystem tools are omitted from the confined default because they execute in-process and do not ride the bash sandbox.
|
||||
The editor sets each session's `cwd` to the project it opens, and bash uses that directory as its workdir. The current sandbox write boundary is nevertheless fixed when the server starts (`workspaceRoot: process.cwd()`), so launch the server from the workspace it should be allowed to modify; making that root session-scoped is deferred in the [sandbox Agent Note](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md). The filesystem tools now ride the same sandbox policy through [`@deepseek-ai/dsh-fs-sandbox`](../../packages/fs/fs-sandbox/), so `read`/`write`/`edit` are available under every mode and confined to the same `workspaceRoot`.
|
||||
|
||||
## Snapshot tests (record-once / replay-deterministic)
|
||||
|
||||
This example hosts the ACP snapshot suite. It replays through `dsh-llm-replay`, which reconstructs model streams from `assistant/chunk` events in each scenario's session JSONL. Recording runs the real ACP agent and harvests its logs; refresh keeps the committed transcript as mock input and rewrites current replay outputs. `replay.override.json` covers throw and hang cases that chunks cannot express, and an optional `workspace/` seeds files. The [snapshot RFC](../../docs/rfc/implemented/testing/2026-06-19-acp-snapshot-tests.md) owns the ACP harness design.
|
||||
This example hosts the ACP snapshot suite. It replays through `dsh-llm-replay`, which reconstructs model streams from `assistant/chunk` events in each scenario's session JSONL. Recording runs the real ACP agent and harvests its logs; refresh keeps the committed transcript as mock input and rewrites current replay outputs. `replay.override.json` covers throw and hang cases that chunks cannot express, and an optional `workspace/` seeds files. The [snapshot Agent Note](../../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md) owns the ACP harness design.
|
||||
|
||||
## Permissions and sandboxing
|
||||
|
||||
The default tree composes [`@deepseek-ai/dsh-sandbox-local`](../../packages/sandbox/sandbox-local/), [`@deepseek-ai/dsh-bash-sandbox`](../../packages/bash/bash-sandbox/), [`@deepseek-ai/dsh-user-approval`](../../packages/ui/user-approval/), and [`@deepseek-ai/dsh-permission`](../../packages/ui/permission/). Bash starts in `workspace-write`; a denied operation returns a structured marker, and a retry with `sandbox_permissions` plus `justification` becomes a one-shot `session/request_permission` prompt in the editor. "Allow once" runs exactly that retry under the wider mode ([sandbox RFC § Escalation](../../docs/rfc/implemented/feature/2026-07-06-sandbox.md)).
|
||||
The default tree composes [`@deepseek-ai/dsh-sandbox-local`](../../packages/sandbox/sandbox-local/), [`@deepseek-ai/dsh-sandbox-policy`](../../packages/sandbox/sandbox-policy/), [`@deepseek-ai/dsh-bash-sandbox`](../../packages/bash/bash-sandbox/), [`@deepseek-ai/dsh-fs-sandbox`](../../packages/fs/fs-sandbox/), [`@deepseek-ai/dsh-user-approval`](../../packages/ui/user-approval/), and [`@deepseek-ai/dsh-permission`](../../packages/ui/permission/). Bash and the `read`/`write`/`edit` tools start in `workspace-write`; a denied operation returns a structured marker, and a retry with `sandbox_permissions` plus `justification` becomes a one-shot `session/request_permission` prompt in the editor. "Allow once" runs exactly that retry under the wider mode ([sandbox Agent Note § Escalation](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)).
|
||||
|
||||
- **One session config option is live**: a capable client shows one `Permissions` select. `workspace-write` means workspace-confined bash plus `ask`; `danger-full-access` means unconfined bash plus `never`. Switching writes one `permission/preset` event through to the sandbox-mode and approval-policy events, and `session/load` reports the resumed value.
|
||||
- **Every approval is one-shot**: the choices are `Allow once` and `Reject`; a dismissal, rejection, missing editor, or unavailable runner fails closed.
|
||||
- **The boundary is bash-only and config-fixed today**: in-process filesystem tools are omitted from the confined live default, while the sandbox workspace root remains the server's launch directory.
|
||||
- **The boundary spans bash and the filesystem tools, and is config-fixed today**: bash confines through the OS runner and the `read`/`write`/`edit` tools through an in-process path fence ([`dsh-fs-sandbox`](../../packages/fs/fs-sandbox/)), both keyed to the same `workspaceRoot` — which remains the server's launch directory (a per-session root is deferred).
|
||||
|
||||
`tests/escalation.e2e.ts` boots this default tree keyless, drives the permission select, and—with a key and usable runner—proves both approval outcomes against the filesystem. Most snapshots use that tree and start at `danger-full-access` so bash fixtures remain runner-independent; scenarios that call `read`, `write`, or `edit` use the fixed full-access fs overlay and a separate request-header pin. The permission-switching and escalation inputs select `workspace-write` before exercising the bash policy path. No fixture pins a real denial because kernel error text is backend-specific; real confinement remains covered by the sandbox packages' kernel e2e suites.
|
||||
|
||||
|
||||
@@ -23,14 +23,6 @@
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
- id: llm-replay
|
||||
|
||||
@@ -20,13 +20,5 @@
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
|
||||
@@ -12,6 +12,8 @@ flowchart LR
|
||||
cfg --> plugin_acp_llm_deepseek
|
||||
plugin_acp_sandbox["sandbox<br/>@deepseek-ai/dsh-sandbox-local"]
|
||||
cfg --> plugin_acp_sandbox
|
||||
plugin_acp_sandbox_policy["sandbox-policy<br/>@deepseek-ai/dsh-sandbox-policy"]
|
||||
cfg --> plugin_acp_sandbox_policy
|
||||
plugin_acp_bash["bash<br/>@deepseek-ai/dsh-bash-sandbox"]
|
||||
cfg --> plugin_acp_bash
|
||||
plugin_acp_approval["approval<br/>@deepseek-ai/dsh-user-approval"]
|
||||
@@ -27,6 +29,10 @@ flowchart LR
|
||||
bundle_agent_core --> spine_sessions["ctx.sessions"]
|
||||
bundle_agent_core --> spine_tools["ctx.tools + tool-bash"]
|
||||
bundle_agent_core --> spine_loop["ctx.agents + ctx.agentLoop"]
|
||||
plugin_acp_token_meter["token-meter<br/>@deepseek-ai/dsh-token-meter"]
|
||||
cfg --> plugin_acp_token_meter
|
||||
plugin_acp_compact_basic["compact-basic<br/>@deepseek-ai/dsh-compact-basic"]
|
||||
cfg --> plugin_acp_compact_basic
|
||||
plugin_acp_subagent["subagent<br/>@deepseek-ai/dsh-subagent"]
|
||||
cfg --> plugin_acp_subagent
|
||||
plugin_acp_subagent_spawn["subagent-spawn<br/>@deepseek-ai/dsh-subagent-spawn"]
|
||||
@@ -45,6 +51,12 @@ flowchart LR
|
||||
cfg --> plugin_acp_tool_todo
|
||||
plugin_acp_repeat_tool_guard["repeat-tool-guard<br/>@deepseek-ai/dsh-repeat-tool-guard"]
|
||||
cfg --> plugin_acp_repeat_tool_guard
|
||||
plugin_acp_fs_sandbox["fs-sandbox<br/>@deepseek-ai/dsh-fs-sandbox"]
|
||||
cfg --> plugin_acp_fs_sandbox
|
||||
plugin_acp_fs_policy["fs-policy<br/>@deepseek-ai/dsh-fs-policy"]
|
||||
cfg --> plugin_acp_fs_policy
|
||||
plugin_acp_tool_fs["tool-fs<br/>@deepseek-ai/dsh-tool-fs"]
|
||||
cfg --> plugin_acp_tool_fs
|
||||
plugin_acp_hooks_claude["hooks-claude<br/>@deepseek-ai/dsh-hooks-claude"]
|
||||
cfg --> plugin_acp_hooks_claude
|
||||
plugin_acp_hooks_codex["hooks-codex<br/>@deepseek-ai/dsh-hooks-codex"]
|
||||
@@ -55,10 +67,13 @@ flowchart LR
|
||||
| --- | --- |
|
||||
| `llm-deepseek` | `@deepseek-ai/dsh-llm-deepseek` |
|
||||
| `sandbox` | `@deepseek-ai/dsh-sandbox-local` |
|
||||
| `sandbox-policy` | `@deepseek-ai/dsh-sandbox-policy` |
|
||||
| `bash` | `@deepseek-ai/dsh-bash-sandbox` |
|
||||
| `approval` | `@deepseek-ai/dsh-user-approval` |
|
||||
| `permission` | `@deepseek-ai/dsh-permission` |
|
||||
| `acp-agent` | `@deepseek-ai/dsh-acp-demo` |
|
||||
| `token-meter` | `@deepseek-ai/dsh-token-meter` |
|
||||
| `compact-basic` | `@deepseek-ai/dsh-compact-basic` |
|
||||
| `subagent` | `@deepseek-ai/dsh-subagent` |
|
||||
| `subagent-spawn` | `@deepseek-ai/dsh-subagent-spawn` |
|
||||
| `subagent-fork` | `@deepseek-ai/dsh-subagent-fork` |
|
||||
@@ -68,6 +83,9 @@ flowchart LR
|
||||
| `tool-workflow` | `@deepseek-ai/dsh-tool-workflow` |
|
||||
| `tool-todo` | `@deepseek-ai/dsh-tool-todo` |
|
||||
| `repeat-tool-guard` | `@deepseek-ai/dsh-repeat-tool-guard` |
|
||||
| `fs-sandbox` | `@deepseek-ai/dsh-fs-sandbox` |
|
||||
| `fs-policy` | `@deepseek-ai/dsh-fs-policy` |
|
||||
| `tool-fs` | `@deepseek-ai/dsh-tool-fs` |
|
||||
| `hooks-claude` | `@deepseek-ai/dsh-hooks-claude` |
|
||||
| `hooks-codex` | `@deepseek-ai/dsh-hooks-codex` |
|
||||
|
||||
|
||||
@@ -10,17 +10,25 @@
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
baseURL: !!js process.env.DEEPSEEK_BASE_URL
|
||||
|
||||
# The default composition confines bash to the workspace and asks before a
|
||||
# wider retry. Snapshots use danger-full-access; DSH_PERMISSION_MODE overrides
|
||||
# both mode and approval policy for deployments and tests.
|
||||
# The default composition confines bash AND the filesystem tools to the
|
||||
# workspace and asks before a wider retry. Snapshot runs select
|
||||
# danger-full-access so the established scenarios remain runner-independent;
|
||||
# DSH_PERMISSION_MODE provides the same explicit deployment/test override
|
||||
# outside the snapshot harness. The sandbox mode + workspace root live on
|
||||
# ctx.sandboxPolicy — the one home both enforcing families (bash, fs) read.
|
||||
- id: sandbox
|
||||
name: '@deepseek-ai/dsh-sandbox-local'
|
||||
|
||||
- id: sandbox-policy
|
||||
name: '@deepseek-ai/dsh-sandbox-policy'
|
||||
config:
|
||||
mode: !!js "process.env.DSH_PERMISSION_MODE ?? (process.env.DSH_SNAPSHOT === undefined ? 'workspace-write' : 'danger-full-access')"
|
||||
workspaceRoot: !!js process.cwd()
|
||||
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-sandbox'
|
||||
config:
|
||||
timeoutMs: 60000
|
||||
mode: !!js "process.env.DSH_PERMISSION_MODE ?? (process.env.DSH_SNAPSHOT === undefined ? 'workspace-write' : 'danger-full-access')"
|
||||
workspaceRoot: !!js process.cwd()
|
||||
|
||||
- id: approval
|
||||
name: '@deepseek-ai/dsh-user-approval'
|
||||
@@ -48,6 +56,23 @@
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
# Replay-aware request pressure with one service-wide context window.
|
||||
- id: token-meter
|
||||
name: '@deepseek-ai/dsh-token-meter'
|
||||
config:
|
||||
# FIXME: Resolve compaction config per model; this capacity assumes a 256k context window.
|
||||
contextWindow: 256000
|
||||
|
||||
# Summarize an older range after measured pressure or a canonical provider overflow.
|
||||
# Service-wide policy provides pressure, retention, and one overflow-retry default.
|
||||
- id: compact-basic
|
||||
name: '@deepseek-ai/dsh-compact-basic'
|
||||
config:
|
||||
thresholdRatio: 0.8
|
||||
retainTokens: 20480
|
||||
maxTokens: 8192
|
||||
compactionRetries: 1
|
||||
|
||||
# Expose fresh-child `spawn` and completed-prefix `fork` through separate tool
|
||||
# names so multi-child scenarios exercise both transports. These leaves follow
|
||||
# the app because it provides `ctx.agents` and `ctx.tools`.
|
||||
@@ -95,6 +120,22 @@
|
||||
- id: repeat-tool-guard
|
||||
name: '@deepseek-ai/dsh-repeat-tool-guard'
|
||||
|
||||
# The filesystem stack rides the SAME sandbox policy as bash: dsh-fs-sandbox
|
||||
# replaces dsh-fs-local behind ctx.fs and fences write/edit by the effective
|
||||
# mode (read-only denies, workspace-write contains to the workspace + temp
|
||||
# roots, danger-full-access passes through), so read/write/edit are available
|
||||
# under every mode. fs-policy (read-before-edit) composes orthogonally on top.
|
||||
- id: fs-sandbox
|
||||
name: '@deepseek-ai/dsh-fs-sandbox'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
|
||||
# `configPath` is read once at load and resolves from the server launch cwd, not
|
||||
# `session/new.cwd`; one `hooks.json` therefore applies to every session and a
|
||||
# project-local file is not discovered. Missing config registers nothing. Hook
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Keyless filesystem snapshots apply the filesystem and replay overlays directly
|
||||
# because include patches cannot target entries behind a nested include.
|
||||
# Keyless filesystem snapshots apply the spill and replay overlays directly
|
||||
# because include patches cannot target entries behind a nested include. The
|
||||
# sandboxed filesystem stack already lives in the base cordis.yml.
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
@@ -9,14 +10,6 @@
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
disabled: true
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
- id: spill-local
|
||||
name: '@deepseek-ai/dsh-spill-local'
|
||||
config:
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
# Filesystem snapshots need the in-process local provider, policy gate, and
|
||||
# model-facing tools. This explicit overlay is always full-access: the session
|
||||
# permission preset controls bash only and cannot confine or unmount these plugins.
|
||||
# Filesystem-scenario overlay: the sandboxed filesystem stack already lives in
|
||||
# the base cordis.yml, so this overlay adds only the local tool-result spill
|
||||
# storage those scenarios exercise.
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
path: ./cordis.yml
|
||||
patches:
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
- id: spill-local
|
||||
name: '@deepseek-ai/dsh-spill-local'
|
||||
config:
|
||||
|
||||
@@ -5,12 +5,12 @@ import { defineAcpSnapshotSuite, type Scenario, type SnapshotSuiteOptions } from
|
||||
/**
|
||||
* The acp-agent example's snapshot suite: the scenario table for
|
||||
* `dsh-acp-snapshot`'s suite factory, which owns every compare/guard mechanic
|
||||
* (golden + re-persisted-log diffs, record/refresh write-back, the pinned-header
|
||||
* (expected-output + re-persisted-log diffs, record/refresh write-back, the pinned-header
|
||||
* uniformity guard, the fixture guards). Fixtures live under `snapshots/<name>/`;
|
||||
* `pnpm run test:snapshot:record` re-records model transcripts against the real
|
||||
* API; `pnpm run test:snapshot:refresh` rewrites current replay goldens keyless.
|
||||
* See the package README (packages/support/acp-snapshot) and the snapshot RFC,
|
||||
* docs/rfc/implemented/testing/2026-06-19-acp-snapshot-tests.md.
|
||||
* API; `pnpm run test:snapshot:refresh` rewrites current replay expected outputs keyless.
|
||||
* See the package README (packages/support/acp-snapshot) and the snapshot Agent Note,
|
||||
* .agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md.
|
||||
*/
|
||||
|
||||
// The dsh-acp-demo bin (the demo:acp entry), this example's cordis.yml, and
|
||||
@@ -53,24 +53,25 @@ const SCENARIOS: Scenario[] = [
|
||||
// Its prompt and tool-schema sidecars pin the composed header.
|
||||
{ name: 'text-turn', hasModelTurn: true, recorded: true, pinsHeader: true },
|
||||
{ name: 'tool-call-turn', hasModelTurn: true, recorded: true },
|
||||
// The fs overlay only adds the spill stack (the sandboxed filesystem tools
|
||||
// live in the base tree), so these scenarios share the default header class.
|
||||
{
|
||||
name: 'parallel-tool-calls',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
headerClass: 'fs',
|
||||
configPath: FS_CONFIG,
|
||||
},
|
||||
{ name: 'bash-spill', hasModelTurn: true, recorded: false, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'bash-spill', hasModelTurn: true, recorded: false, configPath: FS_CONFIG },
|
||||
{ name: 'fs-terminal-card', hasModelTurn: true, recorded: true },
|
||||
{ name: 'todo-plan', hasModelTurn: true, recorded: true },
|
||||
{ name: 'skill-load', hasModelTurn: true, recorded: false, pinsHeader: true, headerClass: 'skill' },
|
||||
{ name: 'workspace-edit', hasModelTurn: true, recorded: true, pinsHeader: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-read', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-write', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-edit', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-write-overwrite', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-read-window', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'fs-policy-reject', hasModelTurn: true, recorded: true, headerClass: 'fs', configPath: FS_CONFIG },
|
||||
{ name: 'workspace-edit', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-read', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-write', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-edit', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-write-overwrite', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-read-window', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-policy-reject', hasModelTurn: true, recorded: true },
|
||||
{ name: 'multi-turn', hasModelTurn: true, recorded: true },
|
||||
// ACP exposes the adapter catalog as a session-scoped model select. This
|
||||
// scenario pins the default flash request, the switch response, and the
|
||||
@@ -137,8 +138,8 @@ const SCENARIOS: Scenario[] = [
|
||||
// The mid-turn seams fire during a real model turn, so each is recorded with its hook active
|
||||
// (the model's reaction to a deny/block/force-continue is part of the captured transcript).
|
||||
// SessionStart/SubagentStart are excluded because detached injection races log
|
||||
// order; SubagentStop writes no transcript, so a golden could not prove it ran.
|
||||
// Unit tests cover those points; the hook-snapshot-matrix RFC owns the rationale.
|
||||
// order; SubagentStop writes no transcript, so an expected output could not prove it ran.
|
||||
// Unit tests cover those points; the hook-snapshot-matrix Agent Note owns the rationale.
|
||||
{ name: 'hook-cc-promptsubmit-context', hasModelTurn: true, recorded: true },
|
||||
{ name: 'hook-cc-pretool-deny', hasModelTurn: true, recorded: true },
|
||||
{ name: 'hook-cc-pretool-ask', hasModelTurn: true, recorded: true },
|
||||
@@ -175,6 +176,7 @@ const SCENARIOS: Scenario[] = [
|
||||
{ name: 'permission-switching', hasModelTurn: true, recorded: true, pinsHeader: true, expectedHeaderChanges: 1, headerClass: 'sandbox' },
|
||||
{ name: 'escalation-approved', hasModelTurn: true, recorded: true, headerClass: 'sandbox' },
|
||||
{ name: 'escalation-rejected', hasModelTurn: true, recorded: true, headerClass: 'sandbox' },
|
||||
{ name: 'fs-escalation-approved', hasModelTurn: true, recorded: true, headerClass: 'sandbox' },
|
||||
]
|
||||
|
||||
defineAcpSnapshotSuite({
|
||||
|
||||
2212
examples/acp-agent/tests/fixtures/live-mode-switching-2026-07-07.session.jsonl
vendored
Normal file
2212
examples/acp-agent/tests/fixtures/live-mode-switching-2026-07-07.session.jsonl
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -61,6 +67,30 @@ declare const tools: {
|
||||
/** The dynamic mount id returned by cordis_mount (e.g. "dyn-1"). */
|
||||
id: string;
|
||||
}): Promise<string>;
|
||||
/** Edit an existing UTF-8 text file by replacing literal text. */
|
||||
edit(args: {
|
||||
/** Path to edit, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Literal text to replace. Must match exactly. */
|
||||
old_string: string;
|
||||
/** Literal replacement text. Use an empty string to delete the match. */
|
||||
new_string: string;
|
||||
/** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */
|
||||
replace_all?: boolean;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Read a UTF-8 text file and return line-numbered content. */
|
||||
read(args: {
|
||||
/** Path to read, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** 1-based first line to return. Defaults to 1. */
|
||||
offset?: number;
|
||||
/** Maximum number of lines to return. Defaults to 2000. */
|
||||
limit?: number;
|
||||
}): Promise<string>;
|
||||
/** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */
|
||||
skill(args: {
|
||||
/** The exact skill name from the available skills list. */
|
||||
@@ -139,5 +169,16 @@ declare const tools: {
|
||||
/** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {"files": [...]}). */
|
||||
args?: Record<string, unknown>;
|
||||
}): Promise<string>;
|
||||
/** Create or fully replace a UTF-8 text file. */
|
||||
write(args: {
|
||||
/** Path to write, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Full UTF-8 text content to write. */
|
||||
content: string;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
}
|
||||
```
|
||||
@@ -102,6 +102,72 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_code",
|
||||
"description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.",
|
||||
@@ -344,6 +410,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": []
|
||||
@@ -10,7 +10,7 @@
|
||||
{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
|
||||
{"type":"assistant/message","seq":9,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"tool-call","id":"call_spill","name":"bash","arguments":"{\"command\":\"node -e \\\"process.stdout.write('SPILL_START-' + 'x'.repeat(2000) + '-SPILL_END')\\\"\",\"description\":\"Print large deterministic output\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":10,"outputTokens":5}},"sourceEventSeqs":[4,5,6,7,8],"surfaceOp":"append"}
|
||||
{"type":"tool/call","seq":10,"time":0,"data":{"turn":1,"step":1,"callId":"call_spill","name":"bash","arguments":"{\"command\":\"node -e \\\"process.stdout.write('SPILL_START-' + 'x'.repeat(2000) + '-SPILL_END')\\\"\",\"description\":\"Print large deterministic output\"}"}}
|
||||
{"type":"tool/result","seq":11,"time":0,"data":{"turn":1,"step":1,"callId":"call_spill","content":[{"type":"text","text":"SPILL_START-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-SPILL_END\n\n(Omitted 1417 bytes. Full formatted result stored at: /tmp/dsh-acp-snapshot-spill/session-8d519f752b89/93e1b6e8dc7e-bash.txt. Use read with offset/limit, or grep this path to search within it.)"}],"isError":false},"sourceEventSeqs":[10],"surfaceOp":"append"}
|
||||
{"type":"tool/result","seq":11,"time":0,"data":{"turn":1,"step":1,"callId":"call_spill","content":[{"type":"text","text":"SPILL_START-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-SPILL_END\n\n(Omitted 1417 bytes. Full formatted result stored at: /tmp/dsh-acp-snapshot-spill/session-2ef0a5f14624/b5e2b8c5e6a6-bash.txt. Use read with offset/limit, or grep this path to search within it.)"}],"isError":false},"sourceEventSeqs":[10],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":12,"time":0,"data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","seq":13,"time":0,"data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
|
||||
|
||||
@@ -60,6 +60,10 @@ declare const tools: {
|
||||
new_string: string;
|
||||
/** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */
|
||||
replace_all?: boolean;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Read a UTF-8 text file and return line-numbered content. */
|
||||
read(args: {
|
||||
@@ -154,6 +158,10 @@ declare const tools: {
|
||||
file_path: string;
|
||||
/** Full UTF-8 text content to write. */
|
||||
content: string;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
}
|
||||
```
|
||||
@@ -45,6 +45,88 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_code",
|
||||
"description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The program: the body of an async TypeScript function."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
@@ -271,6 +353,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": []
|
||||
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -44,6 +50,30 @@ declare const tools: {
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact command needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Edit an existing UTF-8 text file by replacing literal text. */
|
||||
edit(args: {
|
||||
/** Path to edit, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Literal text to replace. Must match exactly. */
|
||||
old_string: string;
|
||||
/** Literal replacement text. Use an empty string to delete the match. */
|
||||
new_string: string;
|
||||
/** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */
|
||||
replace_all?: boolean;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Read a UTF-8 text file and return line-numbered content. */
|
||||
read(args: {
|
||||
/** Path to read, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** 1-based first line to return. Defaults to 1. */
|
||||
offset?: number;
|
||||
/** Maximum number of lines to return. Defaults to 2000. */
|
||||
limit?: number;
|
||||
}): Promise<string>;
|
||||
/** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */
|
||||
skill(args: {
|
||||
/** The exact skill name from the available skills list. */
|
||||
@@ -122,5 +152,16 @@ declare const tools: {
|
||||
/** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {"files": [...]}). */
|
||||
args?: Record<string, unknown>;
|
||||
}): Promise<string>;
|
||||
/** Create or fully replace a UTF-8 text file. */
|
||||
write(args: {
|
||||
/** Path to write, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Full UTF-8 text content to write. */
|
||||
content: string;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
}
|
||||
```
|
||||
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -44,6 +50,30 @@ declare const tools: {
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact command needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Edit an existing UTF-8 text file by replacing literal text. */
|
||||
edit(args: {
|
||||
/** Path to edit, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Literal text to replace. Must match exactly. */
|
||||
old_string: string;
|
||||
/** Literal replacement text. Use an empty string to delete the match. */
|
||||
new_string: string;
|
||||
/** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */
|
||||
replace_all?: boolean;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
/** Read a UTF-8 text file and return line-numbered content. */
|
||||
read(args: {
|
||||
/** Path to read, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** 1-based first line to return. Defaults to 1. */
|
||||
offset?: number;
|
||||
/** Maximum number of lines to return. Defaults to 2000. */
|
||||
limit?: number;
|
||||
}): Promise<string>;
|
||||
/** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */
|
||||
skill(args: {
|
||||
/** The exact skill name from the available skills list. */
|
||||
@@ -122,5 +152,16 @@ declare const tools: {
|
||||
/** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {"files": [...]}). */
|
||||
args?: Record<string, unknown>;
|
||||
}): Promise<string>;
|
||||
/** Create or fully replace a UTF-8 text file. */
|
||||
write(args: {
|
||||
/** Path to write, resolved by the filesystem backend. */
|
||||
file_path: string;
|
||||
/** Full UTF-8 text content to write. */
|
||||
content: string;
|
||||
/** The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval. */
|
||||
sandbox_permissions?: "workspace-write" | "danger-full-access";
|
||||
/** Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access. */
|
||||
justification?: string;
|
||||
}): Promise<string>;
|
||||
}
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
{"type":"session","version":0,"id":"f3cbd087-fb45-4b32-b0f2-3082d65bfcb4","createdAt":1783860675270,"cwd":"/var/folders/2g/b32ct0qn1d728l_v6tdkjytr0000gn/T/acp-snap-cwd-cbBLh2"}
|
||||
{"type":"turn/start","seq":0,"time":1783860675271,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"permission/preset","seq":1,"time":1783962245380,"data":{"preset":"workspace-write"}}
|
||||
{"type":"bash/sandbox-mode","seq":2,"time":1783962245380,"data":{"mode":"workspace-write"}}
|
||||
{"type":"sandbox/mode","seq":2,"time":1784518116517,"data":{"mode":"workspace-write"}}
|
||||
{"type":"approval/policy","seq":3,"time":1783962245380,"data":{"policy":"ask"}}
|
||||
{"type":"user/message","seq":4,"time":1783962245380,"data":{"content":[{"type":"text","text":"The sandbox already denied writing /tmp/dsh-escalated.txt earlier (it is outside this workspace). Retry it now exactly once: one single bash call with the command printf 'escalated\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt, with sandbox_permissions set to danger-full-access and the justification 'the user asked to write a file outside the workspace'. Do not run it without sandbox_permissions first. I will approve the permission prompt. After the result, reply with the single word DONE and stop."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"step/start","seq":5,"time":1783962245382,"data":{"turn":1,"step":1}}
|
||||
@@ -131,8 +131,8 @@
|
||||
{"type":"assistant/chunk","seq":129,"time":1783962245385,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
|
||||
{"type":"assistant/message","seq":130,"time":1783962245385,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to run a command with sandbox_permissions set to danger-full-access, no prior run needed, justified as instructed."},{"type":"tool-call","id":"call_00_d0sAHpJ9mYOJi0z7KNy30441","name":"bash","arguments":"{\"command\": \"printf 'escalated\\\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt\", \"description\": \"Write file outside workspace and verify\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to write a file outside the workspace\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":1501,"outputTokens":174,"cacheReadTokens":0,"reasoningTokens":28}},"sourceEventSeqs":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129],"surfaceOp":"append"}
|
||||
{"type":"tool/call","seq":131,"time":1783962245385,"data":{"turn":1,"step":1,"callId":"call_00_d0sAHpJ9mYOJi0z7KNy30441","name":"bash","arguments":"{\"command\": \"printf 'escalated\\\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt\", \"description\": \"Write file outside workspace and verify\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to write a file outside the workspace\"}"}}
|
||||
{"type":"approval/asked","seq":132,"time":1783962245386,"data":{"id":"4ba41d82-153a-4587-8c22-dd35783c3d87","toolName":"bash","callId":"call_00_d0sAHpJ9mYOJi0z7KNy30441","reason":"escalate sandbox to danger-full-access: the user asked to write a file outside the workspace"}}
|
||||
{"type":"approval/decided","seq":133,"time":1783962245387,"data":{"id":"4ba41d82-153a-4587-8c22-dd35783c3d87","outcome":"allowed-once"}}
|
||||
{"type":"approval/asked","seq":132,"time":1783962245386,"data":{"id":"e2d45b4a-ff48-488d-aeb6-8edc9dc5c3de","toolName":"bash","callId":"call_00_d0sAHpJ9mYOJi0z7KNy30441","reason":"escalate sandbox to danger-full-access: the user asked to write a file outside the workspace"}}
|
||||
{"type":"approval/decided","seq":133,"time":1783962245387,"data":{"id":"e2d45b4a-ff48-488d-aeb6-8edc9dc5c3de","outcome":"allowed-once"}}
|
||||
{"type":"tool/result","seq":134,"time":1783962245399,"data":{"turn":1,"step":1,"callId":"call_00_d0sAHpJ9mYOJi0z7KNy30441","content":[{"type":"text","text":"escalated\n"}],"isError":false},"sourceEventSeqs":[131],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":135,"time":1783962245400,"data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","seq":136,"time":1783962245400,"data":{"turn":1,"step":2}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{"type":"session","version":0,"id":"d692fe7f-7079-4ee4-8b06-f44fd026d4ea","createdAt":1783860679475,"cwd":"/var/folders/2g/b32ct0qn1d728l_v6tdkjytr0000gn/T/acp-snap-cwd-Hn29Od"}
|
||||
{"type":"turn/start","seq":0,"time":1783860679476,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"permission/preset","seq":1,"time":1783962246267,"data":{"preset":"workspace-write"}}
|
||||
{"type":"bash/sandbox-mode","seq":2,"time":1783962246267,"data":{"mode":"workspace-write"}}
|
||||
{"type":"sandbox/mode","seq":2,"time":1784518117237,"data":{"mode":"workspace-write"}}
|
||||
{"type":"approval/policy","seq":3,"time":1783962246267,"data":{"policy":"ask"}}
|
||||
{"type":"user/message","seq":4,"time":1783962246267,"data":{"content":[{"type":"text","text":"The sandbox already denied writing /tmp/dsh-escalated.txt earlier (it is outside this workspace). Retry it now exactly once: one single bash call with the command printf 'escalated\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt, with sandbox_permissions set to danger-full-access and the justification 'the user asked to write a file outside the workspace'. Do not run it without sandbox_permissions first. I will reject the permission prompt; after the rejection, do not retry and do not work around it — explain in one short sentence and stop."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"step/start","seq":5,"time":1783962246269,"data":{"turn":1,"step":1}}
|
||||
@@ -155,8 +155,8 @@
|
||||
{"type":"assistant/chunk","seq":153,"time":1783962246274,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
|
||||
{"type":"assistant/message","seq":154,"time":1783962246274,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to run a specific command with `sandbox_permissions` set to `danger-full-access` and a specific justification. They explicitly said NOT to run it without sandbox_permissions first. Let me do exactly that."},{"type":"tool-call","id":"call_00_WB1vnPomi8yr6MlcFKTj7912","name":"bash","arguments":"{\"command\": \"printf 'escalated\\\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt\", \"description\": \"Write to /tmp and verify, then clean up\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to write a file outside the workspace\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":1509,"outputTokens":198,"cacheReadTokens":0,"reasoningTokens":48}},"sourceEventSeqs":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153],"surfaceOp":"append"}
|
||||
{"type":"tool/call","seq":155,"time":1783962246274,"data":{"turn":1,"step":1,"callId":"call_00_WB1vnPomi8yr6MlcFKTj7912","name":"bash","arguments":"{\"command\": \"printf 'escalated\\\\n' > /tmp/dsh-escalated.txt && cat /tmp/dsh-escalated.txt && rm /tmp/dsh-escalated.txt\", \"description\": \"Write to /tmp and verify, then clean up\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to write a file outside the workspace\"}"}}
|
||||
{"type":"approval/asked","seq":156,"time":1783962246275,"data":{"id":"84c78b9b-8955-4d4f-8dad-824dcac4d9ed","toolName":"bash","callId":"call_00_WB1vnPomi8yr6MlcFKTj7912","reason":"escalate sandbox to danger-full-access: the user asked to write a file outside the workspace"}}
|
||||
{"type":"approval/decided","seq":157,"time":1783962246275,"data":{"id":"84c78b9b-8955-4d4f-8dad-824dcac4d9ed","outcome":"rejected"}}
|
||||
{"type":"approval/asked","seq":156,"time":1783962246275,"data":{"id":"46c8dba4-52c9-4a6a-b6a6-5f34c95c28df","toolName":"bash","callId":"call_00_WB1vnPomi8yr6MlcFKTj7912","reason":"escalate sandbox to danger-full-access: the user asked to write a file outside the workspace"}}
|
||||
{"type":"approval/decided","seq":157,"time":1783962246275,"data":{"id":"46c8dba4-52c9-4a6a-b6a6-5f34c95c28df","outcome":"rejected"}}
|
||||
{"type":"tool/result","seq":158,"time":1783962246275,"data":{"turn":1,"step":1,"callId":"call_00_WB1vnPomi8yr6MlcFKTj7912","content":[{"type":"text","text":"Error: the user rejected escalating this command to \"danger-full-access\""}],"isError":true},"sourceEventSeqs":[155],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":159,"time":1783962246276,"data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","seq":160,"time":1783962246276,"data":{"turn":1,"step":2}}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"steps": [
|
||||
{ "op": "initialize" },
|
||||
{ "op": "newSession" },
|
||||
{ "op": "setConfigOption", "configId": "permission", "value": "workspace-write" },
|
||||
{ "op": "prompt", "text": "Use the write tool (NOT bash) to create escalated.md in the current directory containing exactly the single line: escalated. An equivalent write was denied earlier, so make this one single write call with sandbox_permissions set to danger-full-access and the justification 'the user asked to escalate this write'. Do not call write without sandbox_permissions first. I will approve the permission prompt. After the result, reply with exactly the single word DONE." }
|
||||
],
|
||||
"permissionAnswers": [
|
||||
{ "kind": "allow_once" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
{"type":"session","version":0,"id":"977a4820-f609-4b48-9039-adcdd921c5fe","createdAt":1784045702340,"cwd":"/var/folders/2g/b32ct0qn1d728l_v6tdkjytr0000gn/T/acp-snap-cwd-vmEGzd"}
|
||||
{"type":"turn/start","seq":0,"time":1784045702342,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"permission/preset","seq":1,"time":1784045702343,"data":{"preset":"workspace-write"}}
|
||||
{"type":"sandbox/mode","seq":2,"time":1784045702343,"data":{"mode":"workspace-write"}}
|
||||
{"type":"approval/policy","seq":3,"time":1784045702343,"data":{"policy":"ask"}}
|
||||
{"type":"user/message","seq":4,"time":1784045702343,"data":{"content":[{"type":"text","text":"Use the write tool (NOT bash) to create escalated.md in the current directory containing exactly the single line: escalated. An equivalent write was denied earlier, so make this one single write call with sandbox_permissions set to danger-full-access and the justification 'the user asked to escalate this write'. Do not call write without sandbox_permissions first. I will approve the permission prompt. After the result, reply with exactly the single word DONE."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"step/start","seq":5,"time":1784045702345,"data":{"turn":1,"step":1}}
|
||||
{"type":"request/header","seq":6,"time":1784045702345,"data":{"header":{"config":{"provider":"deepseek","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
|
||||
{"type":"assistant/chunk","seq":7,"time":1784045703046,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}}
|
||||
{"type":"assistant/chunk","seq":8,"time":1784045703046,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}}
|
||||
{"type":"assistant/chunk","seq":9,"time":1784045703162,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}}
|
||||
{"type":"assistant/chunk","seq":10,"time":1784045703172,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}}
|
||||
{"type":"assistant/chunk","seq":11,"time":1784045703172,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}}
|
||||
{"type":"assistant/chunk","seq":12,"time":1784045703173,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}}
|
||||
{"type":"assistant/chunk","seq":13,"time":1784045703173,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" create"}}}
|
||||
{"type":"assistant/chunk","seq":14,"time":1784045703173,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}}
|
||||
{"type":"assistant/chunk","seq":15,"time":1784045703173,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}}
|
||||
{"type":"assistant/chunk","seq":16,"time":1784045703199,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" using"}}}
|
||||
{"type":"assistant/chunk","seq":17,"time":1784045703225,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}}
|
||||
{"type":"assistant/chunk","seq":18,"time":1784045703251,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" write"}}}
|
||||
{"type":"assistant/chunk","seq":19,"time":1784045703252,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tool"}}}
|
||||
{"type":"assistant/chunk","seq":20,"time":1784045703252,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}}
|
||||
{"type":"assistant/chunk","seq":21,"time":1784045703252,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" sand"}}}
|
||||
{"type":"assistant/chunk","seq":22,"time":1784045703252,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"box"}}}
|
||||
{"type":"assistant/chunk","seq":23,"time":1784045703252,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"_per"}}}
|
||||
{"type":"assistant/chunk","seq":24,"time":1784045703277,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"missions"}}}
|
||||
{"type":"assistant/chunk","seq":25,"time":1784045703278,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}}
|
||||
{"type":"assistant/chunk","seq":26,"time":1784045703278,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Let"}}}
|
||||
{"type":"assistant/chunk","seq":27,"time":1784045703278,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}}
|
||||
{"type":"assistant/chunk","seq":28,"time":1784045703278,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}}
|
||||
{"type":"assistant/chunk","seq":29,"time":1784045703304,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" that"}}}
|
||||
{"type":"assistant/chunk","seq":30,"time":1784045703304,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}}
|
||||
{"type":"assistant/chunk","seq":31,"time":1784045703356,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}}
|
||||
{"type":"assistant/chunk","seq":32,"time":1784045703356,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":""}}}
|
||||
{"type":"assistant/chunk","seq":33,"time":1784045703381,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"{"}}}
|
||||
{"type":"assistant/chunk","seq":34,"time":1784045703381,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":35,"time":1784045703381,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"file"}}}
|
||||
{"type":"assistant/chunk","seq":36,"time":1784045703405,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"_path"}}}
|
||||
{"type":"assistant/chunk","seq":37,"time":1784045703406,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":38,"time":1784045703406,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":": "}}}
|
||||
{"type":"assistant/chunk","seq":39,"time":1784045703406,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":40,"time":1784045703431,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"es"}}}
|
||||
{"type":"assistant/chunk","seq":41,"time":1784045703432,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"cal"}}}
|
||||
{"type":"assistant/chunk","seq":42,"time":1784045703432,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"ated"}}}
|
||||
{"type":"assistant/chunk","seq":43,"time":1784045703432,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":".md"}}}
|
||||
{"type":"assistant/chunk","seq":44,"time":1784045703432,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":45,"time":1784045703483,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":", "}}}
|
||||
{"type":"assistant/chunk","seq":46,"time":1784045703483,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":47,"time":1784045703483,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"content"}}}
|
||||
{"type":"assistant/chunk","seq":48,"time":1784045703483,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":49,"time":1784045703483,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":": "}}}
|
||||
{"type":"assistant/chunk","seq":50,"time":1784045703509,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":51,"time":1784045703509,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"es"}}}
|
||||
{"type":"assistant/chunk","seq":52,"time":1784045703509,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"cal"}}}
|
||||
{"type":"assistant/chunk","seq":53,"time":1784045703509,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"ated"}}}
|
||||
{"type":"assistant/chunk","seq":54,"time":1784045703509,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":55,"time":1784045703565,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":", "}}}
|
||||
{"type":"assistant/chunk","seq":56,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":57,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"sand"}}}
|
||||
{"type":"assistant/chunk","seq":58,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"box"}}}
|
||||
{"type":"assistant/chunk","seq":59,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"_per"}}}
|
||||
{"type":"assistant/chunk","seq":60,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"missions"}}}
|
||||
{"type":"assistant/chunk","seq":61,"time":1784045703566,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":62,"time":1784045703591,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":": "}}}
|
||||
{"type":"assistant/chunk","seq":63,"time":1784045703591,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":64,"time":1784045703591,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"danger"}}}
|
||||
{"type":"assistant/chunk","seq":65,"time":1784045703591,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"-full"}}}
|
||||
{"type":"assistant/chunk","seq":66,"time":1784045703617,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"-access"}}}
|
||||
{"type":"assistant/chunk","seq":67,"time":1784045703618,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":68,"time":1784045703644,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":", "}}}
|
||||
{"type":"assistant/chunk","seq":69,"time":1784045703645,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":70,"time":1784045703645,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"just"}}}
|
||||
{"type":"assistant/chunk","seq":71,"time":1784045703645,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"ification"}}}
|
||||
{"type":"assistant/chunk","seq":72,"time":1784045703669,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":73,"time":1784045703669,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":": "}}}
|
||||
{"type":"assistant/chunk","seq":74,"time":1784045703669,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":75,"time":1784045703669,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"the"}}}
|
||||
{"type":"assistant/chunk","seq":76,"time":1784045703696,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" user"}}}
|
||||
{"type":"assistant/chunk","seq":77,"time":1784045703696,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" asked"}}}
|
||||
{"type":"assistant/chunk","seq":78,"time":1784045703696,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" to"}}}
|
||||
{"type":"assistant/chunk","seq":79,"time":1784045703696,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" escalate"}}}
|
||||
{"type":"assistant/chunk","seq":80,"time":1784045703724,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" this"}}}
|
||||
{"type":"assistant/chunk","seq":81,"time":1784045703724,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":" write"}}}
|
||||
{"type":"assistant/chunk","seq":82,"time":1784045703724,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"\""}}}
|
||||
{"type":"assistant/chunk","seq":83,"time":1784045703749,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","argumentsDelta":"}"}}}
|
||||
{"type":"assistant/chunk","seq":84,"time":1784045703776,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to create a file using the write tool with sandbox_permissions. Let me do that."}}}}
|
||||
{"type":"assistant/chunk","seq":85,"time":1784045703776,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","arguments":"{\"file_path\": \"escalated.md\", \"content\": \"escalated\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to escalate this write\"}"}}}}
|
||||
{"type":"assistant/chunk","seq":86,"time":1784045703776,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3871,"outputTokens":132,"cacheReadTokens":0,"reasoningTokens":23}}}}
|
||||
{"type":"assistant/chunk","seq":87,"time":1784045703776,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
|
||||
{"type":"assistant/message","seq":88,"time":1784045703780,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to create a file using the write tool with sandbox_permissions. Let me do that."},{"type":"tool-call","id":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","arguments":"{\"file_path\": \"escalated.md\", \"content\": \"escalated\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to escalate this write\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":3871,"outputTokens":132,"cacheReadTokens":0,"reasoningTokens":23}},"sourceEventSeqs":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87],"surfaceOp":"append"}
|
||||
{"type":"tool/call","seq":89,"time":1784045703780,"data":{"turn":1,"step":1,"callId":"call_00_Fnymmavpr4klMDy4Fdej3227","name":"write","arguments":"{\"file_path\": \"escalated.md\", \"content\": \"escalated\", \"sandbox_permissions\": \"danger-full-access\", \"justification\": \"the user asked to escalate this write\"}"}}
|
||||
{"type":"approval/asked","seq":90,"time":1784045703782,"data":{"id":"c37500b3-c252-4a9b-ad0d-9c4349419b30","toolName":"write","callId":"call_00_Fnymmavpr4klMDy4Fdej3227","reason":"escalate sandbox to danger-full-access: the user asked to escalate this write"}}
|
||||
{"type":"approval/decided","seq":91,"time":1784045703786,"data":{"id":"c37500b3-c252-4a9b-ad0d-9c4349419b30","outcome":"allowed-once"}}
|
||||
{"type":"tool/result","seq":92,"time":1784045703798,"data":{"turn":1,"step":1,"callId":"call_00_Fnymmavpr4klMDy4Fdej3227","content":[{"type":"text","text":"<path>/var/folders/2g/b32ct0qn1d728l_v6tdkjytr0000gn/T/acp-snap-cwd-vmEGzd/escalated.md</path>\n<type>file</type>\n<content>\nCreated file\n</content>"}],"isError":false},"sourceEventSeqs":[89],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":93,"time":1784045703798,"data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","seq":94,"time":1784045703799,"data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/chunk","seq":95,"time":1784045704512,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}}
|
||||
{"type":"assistant/chunk","seq":96,"time":1784045704512,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}}
|
||||
{"type":"assistant/chunk","seq":97,"time":1784045704620,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}}
|
||||
{"type":"assistant/chunk","seq":98,"time":1784045704645,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" was"}}}
|
||||
{"type":"assistant/chunk","seq":99,"time":1784045704646,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" created"}}}
|
||||
{"type":"assistant/chunk","seq":100,"time":1784045704646,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}}
|
||||
{"type":"assistant/chunk","seq":101,"time":1784045704646,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}}
|
||||
{"type":"assistant/chunk","seq":102,"time":1784045704646,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" The"}}}
|
||||
{"type":"assistant/chunk","seq":103,"time":1784045704646,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}}
|
||||
{"type":"assistant/chunk","seq":104,"time":1784045704672,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" asked"}}}
|
||||
{"type":"assistant/chunk","seq":105,"time":1784045704673,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}}
|
||||
{"type":"assistant/chunk","seq":106,"time":1784045704673,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}}
|
||||
{"type":"assistant/chunk","seq":107,"time":1784045704673,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}}
|
||||
{"type":"assistant/chunk","seq":108,"time":1784045704699,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}}
|
||||
{"type":"assistant/chunk","seq":109,"time":1784045704699,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}}
|
||||
{"type":"assistant/chunk","seq":110,"time":1784045704699,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}}
|
||||
{"type":"assistant/chunk","seq":111,"time":1784045704726,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}}
|
||||
{"type":"assistant/chunk","seq":112,"time":1784045704726,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}}
|
||||
{"type":"assistant/chunk","seq":113,"time":1784045704726,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" D"}}}
|
||||
{"type":"assistant/chunk","seq":114,"time":1784045704754,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}}
|
||||
{"type":"assistant/chunk","seq":115,"time":1784045704754,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}}
|
||||
{"type":"assistant/chunk","seq":116,"time":1784045704754,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"text"}}}
|
||||
{"type":"assistant/chunk","seq":117,"time":1784045704754,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"D"}}}
|
||||
{"type":"assistant/chunk","seq":118,"time":1784045704754,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}}
|
||||
{"type":"assistant/chunk","seq":119,"time":1784045704755,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file was created successfully. The user asked me to reply with exactly the single word DONE."}}}}
|
||||
{"type":"assistant/chunk","seq":120,"time":1784045704755,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}}
|
||||
{"type":"assistant/chunk","seq":121,"time":1784045704755,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":107,"outputTokens":23,"cacheReadTokens":3968,"reasoningTokens":20}}}}
|
||||
{"type":"assistant/chunk","seq":122,"time":1784045704755,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
|
||||
{"type":"assistant/message","seq":123,"time":1784045704755,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The file was created successfully. The user asked me to reply with exactly the single word DONE."},{"type":"text","text":"DONE"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":107,"outputTokens":23,"cacheReadTokens":3968,"reasoningTokens":20}},"sourceEventSeqs":[95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":124,"time":1784045704755,"data":{"turn":1,"step":2}}
|
||||
{"type":"turn/end","seq":125,"time":1784045704756,"data":{"turn":1,"reason":{"kind":"completed"}}}
|
||||
@@ -0,0 +1,52 @@
|
||||
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"loadSession":true,"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}}
|
||||
{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}","configOptions":[{"id":"model","name":"Model","description":"Sets this session's provider and model.","category":"model","type":"select","currentValue":"[\"deepseek\",\"deepseek-v4-flash\"]","options":[{"value":"[\"deepseek\",\"deepseek-v4-flash\"]","name":"deepseek-v4-flash"},{"value":"[\"deepseek\",\"deepseek-v4-pro\"]","name":"deepseek-v4-pro"}]},{"id":"permission","name":"Permissions","description":"The session permission preset: each choice bundles a sandbox mode and an approval policy.","category":"mode","type":"select","currentValue":"danger-full-access","options":[{"value":"workspace-write","name":"workspace-write","description":"Write inside the workspace and permitted temporary directories; wider retries require approval."},{"value":"danger-full-access","name":"danger-full-access","description":"Full file access without approval prompts."}]}]}}
|
||||
{"jsonrpc":"2.0","id":3,"result":{"configOptions":[{"id":"model","name":"Model","description":"Sets this session's provider and model.","category":"model","type":"select","currentValue":"[\"deepseek\",\"deepseek-v4-flash\"]","options":[{"value":"[\"deepseek\",\"deepseek-v4-flash\"]","name":"deepseek-v4-flash"},{"value":"[\"deepseek\",\"deepseek-v4-pro\"]","name":"deepseek-v4-pro"}]},{"id":"permission","name":"Permissions","description":"The session permission preset: each choice bundles a sandbox mode and an approval policy.","category":"mode","type":"select","currentValue":"workspace-write","options":[{"value":"workspace-write","name":"workspace-write","description":"Write inside the workspace and permitted temporary directories; wider retries require approval."},{"value":"danger-full-access","name":"danger-full-access","description":"Full file access without approval prompts."}]}]}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"The"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" user"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" wants"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" me"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" to"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" create"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" a"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" file"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" using"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" the"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" write"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" tool"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" with"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" sand"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"box"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"_per"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"missions"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"."}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" Let"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" me"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" do"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" that"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"."}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call","toolCallId":"call_00_Fnymmavpr4klMDy4Fdej3227","title":"Write escalated.md","kind":"edit","status":"in_progress","locations":[{"path":"escalated.md"}],"content":[{"type":"diff","path":"escalated.md","oldText":null,"newText":"escalated"}]}}}
|
||||
{"jsonrpc":"2.0","id":1,"method":"session/request_permission","params":{"sessionId":"{{sessionId}}","toolCall":{"toolCallId":"call_00_Fnymmavpr4klMDy4Fdej3227"},"options":[{"optionId":"allow-once","name":"Allow once","kind":"allow_once"},{"optionId":"reject-once","name":"Reject","kind":"reject_once"}]}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_Fnymmavpr4klMDy4Fdej3227","status":"completed","content":[{"type":"diff","path":"escalated.md","oldText":null,"newText":"escalated"}],"title":"Write escalated.md"}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"The"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" file"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" was"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" created"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" successfully"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"."}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" The"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" user"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" asked"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" me"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" to"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" reply"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" with"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" exactly"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" the"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" single"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" word"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" D"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"ONE"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"."}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"D"}}}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ONE"}}}}
|
||||
{"jsonrpc":"2.0","id":4,"result":{"stopReason":"end_turn"}}
|
||||
@@ -55,8 +55,8 @@
|
||||
{"type":"tool/call","seq":53,"time":1783352172557,"data":{"turn":1,"step":1,"callId":"call_00_6k0oGSliVHxGSgqBmMEO4311","name":"bash","arguments":"{\"command\": \"echo HELLO\", \"description\": \"Echo HELLO\"}"}}
|
||||
{"type":"hook/invoked","seq":54,"time":1783352172558,"data":{"turn":1,"point":"PreToolUse","dialect":"claude","handlerId":"claude:PreToolUse:1","matcher":"bash"}}
|
||||
{"type":"hook/result","seq":55,"time":1783352172573,"data":{"turn":1,"point":"PreToolUse","handlerId":"claude:PreToolUse:1","decision":"ask","exitCode":0,"durationMs":14.113374999999905}}
|
||||
{"type":"approval/asked","seq":56,"time":1783962235813,"data":{"id":"9ba4bf87-d8b5-448f-94e6-6a8a0e43a8ad","toolName":"bash","callId":"call_00_6k0oGSliVHxGSgqBmMEO4311","reason":"bash requires manual approval in this session"}}
|
||||
{"type":"approval/decided","seq":57,"time":1783962235813,"data":{"id":"9ba4bf87-d8b5-448f-94e6-6a8a0e43a8ad","outcome":"rejected"}}
|
||||
{"type":"approval/asked","seq":56,"time":1783962235813,"data":{"id":"68f1e09d-f3e5-4e39-8a51-da082ba3ba99","toolName":"bash","callId":"call_00_6k0oGSliVHxGSgqBmMEO4311","reason":"bash requires manual approval in this session"}}
|
||||
{"type":"approval/decided","seq":57,"time":1783962235813,"data":{"id":"68f1e09d-f3e5-4e39-8a51-da082ba3ba99","outcome":"rejected"}}
|
||||
{"type":"tool/result","seq":58,"time":1783962235814,"data":{"turn":1,"step":1,"callId":"call_00_6k0oGSliVHxGSgqBmMEO4311","content":[{"type":"text","text":"Error: the user rejected tool \"bash\""}],"isError":true},"sourceEventSeqs":[53],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":59,"time":1783962235814,"data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","seq":60,"time":1783962235814,"data":{"turn":1,"step":2}}
|
||||
|
||||
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -23,6 +29,12 @@ You are a coding assistant powered by the deepseek-v4-pro model. Your working di
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -45,6 +45,72 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
@@ -271,6 +337,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": [
|
||||
@@ -320,6 +419,72 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
@@ -546,6 +711,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
{"type":"session","version":0,"id":"df041acb-2f14-4d5f-b6e2-2fb6b9eb6427","createdAt":1783860666204,"cwd":"/var/folders/2g/b32ct0qn1d728l_v6tdkjytr0000gn/T/acp-snap-cwd-4oJKT4"}
|
||||
{"type":"turn/start","seq":0,"time":1783860666206,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"permission/preset","seq":1,"time":1783962244578,"data":{"preset":"workspace-write"}}
|
||||
{"type":"bash/sandbox-mode","seq":2,"time":1783962244578,"data":{"mode":"workspace-write"}}
|
||||
{"type":"sandbox/mode","seq":2,"time":1784518115721,"data":{"mode":"workspace-write"}}
|
||||
{"type":"approval/policy","seq":3,"time":1783962244578,"data":{"policy":"ask"}}
|
||||
{"type":"user/message","seq":4,"time":1783962244578,"data":{"content":[{"type":"text","text":"Use the bash tool to run exactly this one command in a single call: printf 'before\\n' > out.txt && cat out.txt. Then reply with the single word DONE and stop."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"step/start","seq":5,"time":1783962244579,"data":{"turn":1,"step":1}}
|
||||
@@ -102,7 +102,7 @@
|
||||
{"type":"turn/end","seq":100,"time":1783962244601,"data":{"turn":1,"reason":{"kind":"completed"}}}
|
||||
{"type":"turn/start","seq":101,"time":1783962244623,"data":{"turn":2,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"permission/preset","seq":102,"time":1783962244624,"data":{"preset":"danger-full-access"}}
|
||||
{"type":"bash/sandbox-mode","seq":103,"time":1783962244624,"data":{"mode":"danger-full-access"}}
|
||||
{"type":"sandbox/mode","seq":103,"time":1784518115842,"data":{"mode":"danger-full-access"}}
|
||||
{"type":"approval/policy","seq":104,"time":1783962244624,"data":{"policy":"never"}}
|
||||
{"type":"user/message","seq":105,"time":1783962244624,"data":{"content":[{"type":"text","text":"Use the bash tool to run exactly: cat out.txt. Then reply with the single word DONE and stop."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"context/message","seq":106,"time":1783962244624,"data":{"content":[{"type":"text","text":"The approval policy changed from \"ask\" to \"never\" (changed by the user)."}],"source":{"kind":"plugin","plugin":"user-approval"}},"surfaceOp":"append"}
|
||||
|
||||
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -22,6 +28,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -45,6 +45,72 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
@@ -271,6 +337,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": [
|
||||
@@ -320,6 +419,72 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
@@ -546,6 +711,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -66,6 +66,18 @@
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -339,6 +351,18 @@
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1,277 +0,0 @@
|
||||
{
|
||||
"initial": [
|
||||
{
|
||||
"name": "bash",
|
||||
"description": "Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under <mode> mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a task id immediately; read its output with `task_output` and stop it with `task_kill`. Attempting a command the sandbox may deny is safe and expected: run it and read the marker rather than assuming the denial. When a command is denied and a wider mode would let it succeed, escalate immediately in the same turn — the one sanctioned exception to a denial: retry the exact same command once with `sandbox_permissions` (the narrowest wider mode that suffices) plus a one-sentence `justification`. Do not detour through chat to ask permission first — the approval prompt raised by that retry is how the user consents. If the session states approval prompts are disabled, there is no exception: a denial is final — do not set `sandbox_permissions`. Never escalate speculatively: ground the request in a real denial — normally the one this command just hit; escalating up front is fine only when this session already denied the same access. A rejected escalation is final for that command — stop and explain, never work around it — but it does not forbid attempting or escalating other commands later.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The bash command to execute."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."
|
||||
},
|
||||
"timeoutMs": {
|
||||
"type": "number",
|
||||
"description": "Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."
|
||||
},
|
||||
"workdir": {
|
||||
"type": "string",
|
||||
"description": "Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."
|
||||
},
|
||||
"run_in_background": {
|
||||
"type": "boolean",
|
||||
"description": "Run in the background and return a task id immediately (collect with task_output, stop with task_kill). No timeout applies."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this command needs. Only valid as a one-shot retry of a command the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact command needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"description"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "skill",
|
||||
"description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The exact skill name from the available skills list."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) and return its final result. Use this to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent runs to completion and you receive only its final answer, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "A short (3-5 word) description of the delegated task, for display."
|
||||
},
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
|
||||
},
|
||||
"run_in_background": {
|
||||
"type": "boolean",
|
||||
"description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"prompt"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent_fork",
|
||||
"description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn), returning only its final result. Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive only its final answer, not its intermediate steps. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "A short (3-5 word) description of the delegated task, for display."
|
||||
},
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"description": "The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."
|
||||
},
|
||||
"run_in_background": {
|
||||
"type": "boolean",
|
||||
"description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"prompt"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "task_kill",
|
||||
"description": "Request cancellation of a running background task by task id. Returns immediately; the task settles as killed once its work actually stops.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"task_id": {
|
||||
"type": "string",
|
||||
"description": "Task id returned by the tool that started the background work."
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "Optional short reason, recorded in the log and forwarded to the task."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"task_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "task_list",
|
||||
"description": "List your background tasks (running and finished) with their ids, kinds, and statuses.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "task_output",
|
||||
"description": "Read a background task. Stream tasks return only output since the previous read; final-output tasks return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"task_id": {
|
||||
"type": "string",
|
||||
"description": "Task id returned by the tool that started the background work."
|
||||
},
|
||||
"wait": {
|
||||
"type": "boolean",
|
||||
"description": "Block until the task reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the task alive."
|
||||
},
|
||||
"timeout_ms": {
|
||||
"type": "number",
|
||||
"description": "Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"task_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "todo_write",
|
||||
"description": "Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Keep AT MOST ONE todo `in_progress` at a time; while work remains, exactly one active task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"todos": {
|
||||
"type": "array",
|
||||
"description": "The COMPLETE task list, replacing any previous list.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "What the task is — a short imperative line."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "pending (not started) | in_progress (now) | completed (done).",
|
||||
"enum": [
|
||||
"pending",
|
||||
"in_progress",
|
||||
"completed"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"content",
|
||||
"status"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"todos"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "workflow",
|
||||
"description": "Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return <value>` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise<any>` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const — no oneOf/pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise<any[]>` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise<any[]>` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"script": {
|
||||
"type": "string",
|
||||
"description": "The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return <json-value>`)."
|
||||
},
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"description": "The workflow identity block (plain JSON — never code).",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Short kebab-case workflow name."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "One-line description of what the workflow does."
|
||||
},
|
||||
"whenToUse": {
|
||||
"type": "string",
|
||||
"description": "Optional guidance on when this workflow applies."
|
||||
},
|
||||
"phases": {
|
||||
"type": "array",
|
||||
"description": "Optional phase declarations matched by phase() calls.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "The phase title phase() calls match by exact string."
|
||||
},
|
||||
"detail": {
|
||||
"type": "string",
|
||||
"description": "Optional one-line description of the phase."
|
||||
},
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"description": "Optional provider override this phase is expected to use."
|
||||
},
|
||||
"model": {
|
||||
"type": "string",
|
||||
"description": "Optional model override this phase is expected to use."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"title"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"description"
|
||||
]
|
||||
},
|
||||
"args": {
|
||||
"type": "object",
|
||||
"description": "Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]})."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"script",
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": []
|
||||
}
|
||||
@@ -5,6 +5,12 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your working
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
@@ -1,15 +0,0 @@
|
||||
You are an AI agent powered by the DeepSeek Harness SDK.
|
||||
|
||||
You are a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
@@ -66,6 +66,18 @@
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -339,6 +351,18 @@
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -46,18 +46,68 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_code",
|
||||
"description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.",
|
||||
"name": "edit",
|
||||
"description": "Edit an existing UTF-8 text file by replacing literal text.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "The program: the body of an async TypeScript function."
|
||||
"description": "Path to edit, resolved by the filesystem backend."
|
||||
},
|
||||
"old_string": {
|
||||
"type": "string",
|
||||
"description": "Literal text to replace. Must match exactly."
|
||||
},
|
||||
"new_string": {
|
||||
"type": "string",
|
||||
"description": "Literal replacement text. Use an empty string to delete the match."
|
||||
},
|
||||
"replace_all": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"code"
|
||||
"file_path",
|
||||
"old_string",
|
||||
"new_string"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"description": "Read a UTF-8 text file and return line-numbered content.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to read, resolved by the filesystem backend."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "1-based first line to return. Defaults to 1."
|
||||
},
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of lines to return. Defaults to 2000."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -287,6 +337,39 @@
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "write",
|
||||
"description": "Create or fully replace a UTF-8 text file.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to write, resolved by the filesystem backend."
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Full UTF-8 text content to write."
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"type": "string",
|
||||
"description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
|
||||
"enum": [
|
||||
"workspace-write",
|
||||
"danger-full-access"
|
||||
]
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file_path",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"changes": []
|
||||
@@ -25,13 +25,5 @@
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
- id: llm-replay
|
||||
name: '@deepseek-ai/dsh-llm-replay'
|
||||
|
||||
@@ -21,12 +21,3 @@
|
||||
You are a coding assistant powered by the {{model}} model. Your working directory is {{cwd}}.
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
- insert:
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# cordis-agent
|
||||
|
||||
The self-referential harness demo: the coding spine (DeepSeek V4 + local bash on the stdio chat app) plus [`@deepseek-ai/dsh-tool-cordis`](../../packages/cordis/tool-cordis/README.md), which hands the model three tools over the **live cordis runtime it is running inside** — inspect it, mount new plugins into it, and dispose them again. The `ctx.fs` and `ctx.web` services are mounted (provider-only, no model-facing file/web tools) so the plugins the agent writes have real capabilities to build on; Node built-ins are trapped in the sandbox and redirect to those services. The design (sandbox semantics, mount lifecycle, cross-mount composition, caveats) lives in [the toolset RFC](../../docs/rfc/implemented/feature/2026-07-08-self-referential-cordis-toolset.md).
|
||||
The self-referential harness demo: the coding spine (DeepSeek V4 + local bash on the stdio chat app) plus [`@deepseek-ai/dsh-tool-cordis`](../../packages/cordis/tool-cordis/README.md), which hands the model three tools over the **live cordis runtime it is running inside** — inspect it, mount new plugins into it, and dispose them again. The `ctx.fs` and `ctx.web` services are mounted (provider-only, no model-facing file/web tools) so the plugins the agent writes have real capabilities to build on; Node built-ins are trapped in the sandbox and redirect to those services. The design (sandbox semantics, mount lifecycle, cross-mount composition, caveats) lives in [the toolset Agent Note](../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md).
|
||||
|
||||
## Run it
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Trust stance: the vm and context façade limit accidental global/framework
|
||||
# access but are not a security boundary; mounted code can reach live capabilities
|
||||
# such as `ctx.bash`. Grant this toolset like bash access. See
|
||||
# ../../docs/rfc/implemented/feature/2026-07-08-self-referential-cordis-toolset.md.
|
||||
# ../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md.
|
||||
|
||||
# Hot-module reload for the dev/demo loop (needs `node --expose-internals`).
|
||||
- id: hmr
|
||||
|
||||
@@ -13,7 +13,7 @@ import { describe, expect, it } from 'vitest'
|
||||
const snapshotsDir = join(dirname(fileURLToPath(import.meta.url)), 'snapshots')
|
||||
const scenarioDir = join(snapshotsDir, 'advanced-toolchain')
|
||||
const sessionFixture = join(scenarioDir, 'session.jsonl')
|
||||
const streamGolden = join(scenarioDir, 'stream-json.golden.jsonl')
|
||||
const streamExpected = join(scenarioDir, 'stream-json.expected.jsonl')
|
||||
const configPath = fileURLToPath(new URL('../advanced.cordis.snapshot.yml', import.meta.url))
|
||||
const binScript = fileURLToPath(new URL('../../../packages/examples/cli-demo/src/bin.ts', import.meta.url))
|
||||
const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url))
|
||||
@@ -134,7 +134,7 @@ describe('headless stream-json snapshots', () => {
|
||||
|
||||
expect(result.stderr).toBe('')
|
||||
const normalized = normalizeHeadlessStream(result.stdout, runCwd)
|
||||
if (refreshing) await writeFile(streamGolden, normalized)
|
||||
expect(normalized).toBe(await readFile(streamGolden, 'utf8'))
|
||||
if (refreshing) await writeFile(streamExpected, normalized)
|
||||
expect(normalized).toBe(await readFile(streamExpected, 'utf8'))
|
||||
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
||||
})
|
||||
|
||||
25
examples/jsonrpc-agent/README.md
Normal file
25
examples/jsonrpc-agent/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# jsonrpc-agent
|
||||
|
||||
The unattended coding-agent composition for the Python SDK's bundled JSON-RPC runtime. It intentionally loads no terminal UI, console logger, approval surface, or user-interaction tool because stdout belongs to the SDK protocol and turns are driven by the SDK.
|
||||
|
||||
The model-facing tools are:
|
||||
|
||||
- `bash`, foreground only
|
||||
- `read`, `write`, and `edit`
|
||||
- `subagent`, using one foreground in-process spawn provider
|
||||
- `todo_write`
|
||||
|
||||
The surrounding runtime also loads JSONL session persistence and automatic context compaction. `maxTokensAsSuccess` keeps a token-limited model turn as an accepted evaluation result while preserving its `max-tokens` reason.
|
||||
|
||||
## Runtime environment
|
||||
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `DEEPSEEK_API_KEY` | Credential passed to the OpenAI-compatible host endpoint |
|
||||
| `DEEPSEEK_BASE_URL` | Host endpoint used by `dsh-llm-deepseek` |
|
||||
| `DSH_CWD` | Agent workspace for bash and filesystem tools |
|
||||
| `DSH_MAX_TOKENS_AS_SUCCESS` | `true` (default) accepts token-limited results; `false` reports them as errors |
|
||||
| `DSH_SESSION_ROOT` | JSONL trajectory directory |
|
||||
| `DSH_SYSTEM_PROMPT` | Deployment-provided coding persona |
|
||||
|
||||
Pass the config path through the Python SDK's `cordis` option or `DSH_CORDIS_CONFIG`. The bundled executable already carries every plugin named by this file; the target machine does not need Node.js.
|
||||
74
examples/jsonrpc-agent/cordis.yml
Normal file
74
examples/jsonrpc-agent/cordis.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
# Unattended coding-agent deployment for the bundled dsh-jsonrpc-agent runtime.
|
||||
# stdout is reserved for JSON-RPC; do not add a console logger or terminal UI.
|
||||
|
||||
- id: jsonrpc
|
||||
name: '@deepseek-ai/dsh-jsonrpc'
|
||||
config:
|
||||
maxTokensAsSuccess: !!js "process.env.DSH_MAX_TOKENS_AS_SUCCESS === undefined ? true : JSON.parse(process.env.DSH_MAX_TOKENS_AS_SUCCESS)"
|
||||
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
baseURL: !!js process.env.DEEPSEEK_BASE_URL
|
||||
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-local'
|
||||
config:
|
||||
cwd: !!js process.env.DSH_CWD ?? process.cwd()
|
||||
timeoutMs: 60000
|
||||
|
||||
- id: agent-spine
|
||||
name: '@deepseek-ai/dsh-agent-spine-demo'
|
||||
config:
|
||||
persona: !!js process.env.DSH_SYSTEM_PROMPT ?? 'You are a coding agent.'
|
||||
workspaceContext: false
|
||||
skills:
|
||||
enabled: false
|
||||
toolBash:
|
||||
enableRunInBackground: false
|
||||
toolTasks: false
|
||||
|
||||
- id: sessions
|
||||
name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
||||
config:
|
||||
root: !!js process.env.DSH_SESSION_ROOT ?? './.sessions'
|
||||
|
||||
- id: subagent
|
||||
name: '@deepseek-ai/dsh-subagent'
|
||||
|
||||
- id: subagent-spawn
|
||||
name: '@deepseek-ai/dsh-subagent-spawn'
|
||||
config:
|
||||
providerName: spawn
|
||||
|
||||
- id: tool-subagent
|
||||
name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: spawn
|
||||
toolName: subagent
|
||||
enableRunInBackground: false
|
||||
|
||||
- id: tool-todo
|
||||
name: '@deepseek-ai/dsh-tool-todo'
|
||||
|
||||
- id: fs-local
|
||||
name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.env.DSH_CWD ?? process.cwd()
|
||||
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
|
||||
- id: compact-basic
|
||||
name: '@deepseek-ai/dsh-compact-basic'
|
||||
config:
|
||||
contextWindow: 128000
|
||||
thresholdRatio: 0.8
|
||||
retainTokens: 20480
|
||||
summarizationModel: ''
|
||||
maxTokens: 8192
|
||||
compactionRetries: 1
|
||||
7
examples/jsonrpc-agent/package.json
Normal file
7
examples/jsonrpc-agent/package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "jsonrpc-agent-example",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"description": "Unattended JSON-RPC coding-agent composition"
|
||||
}
|
||||
194
examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts
Normal file
194
examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import { createServer } from 'node:http'
|
||||
import { mkdtemp, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
const binScript = fileURLToPath(new URL('../../../packages/examples/jsonrpc-demo/src/bin.ts', import.meta.url))
|
||||
const configPath = fileURLToPath(new URL('../cordis.yml', import.meta.url))
|
||||
const repoRoot = fileURLToPath(new URL('../../..', import.meta.url))
|
||||
|
||||
function waitForLine(
|
||||
lines: string[],
|
||||
predicate: (value: Record<string, unknown>) => boolean,
|
||||
stderr: () => string,
|
||||
): Promise<Record<string, unknown>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const deadline = Date.now() + 30_000
|
||||
const poll = (): void => {
|
||||
while (lines.length > 0) {
|
||||
const line = lines.shift()!
|
||||
if (!line.trim()) continue
|
||||
try {
|
||||
const value = JSON.parse(line) as Record<string, unknown>
|
||||
if (predicate(value)) {
|
||||
resolve(value)
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
reject(new Error(`non-JSON stdout from JSON-RPC agent runtime: ${line}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Date.now() >= deadline) {
|
||||
reject(new Error(`timed out waiting for JSON-RPC response; stderr=${stderr()}`))
|
||||
return
|
||||
}
|
||||
setTimeout(poll, 10)
|
||||
}
|
||||
poll()
|
||||
})
|
||||
}
|
||||
|
||||
describe('jsonrpc-agent keyless smoke', () => {
|
||||
it.each([
|
||||
{ label: 'accepts max-token results by default', envValue: undefined, expectedStatus: 'ok' },
|
||||
{ label: 'accepts max-token results when enabled through env', envValue: 'true', expectedStatus: 'ok' },
|
||||
{ label: 'reports max-token results as errors when disabled through env', envValue: 'false', expectedStatus: 'error' },
|
||||
])('$label', async ({ envValue, expectedStatus }) => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'dsh-jsonrpc-agent-smoke-'))
|
||||
const modelRequests: Record<string, unknown>[] = []
|
||||
const modelServer = createServer((request, response) => {
|
||||
let body = ''
|
||||
request.setEncoding('utf8')
|
||||
request.on('data', (chunk: string) => { body += chunk })
|
||||
request.on('end', () => {
|
||||
modelRequests.push(JSON.parse(body) as Record<string, unknown>)
|
||||
response.writeHead(200, { 'content-type': 'text/event-stream' })
|
||||
response.write('data: {"choices":[{"delta":{"role":"assistant","content":null}}]}\n\n')
|
||||
response.write('data: {"choices":[{"delta":{"content":"done"}}]}\n\n')
|
||||
response.write('data: {"choices":[{"delta":{},"finish_reason":"length"}],"usage":{"prompt_tokens":3,"completion_tokens":1}}\n\n')
|
||||
response.end('data: [DONE]\n\n')
|
||||
})
|
||||
})
|
||||
await new Promise<void>(resolve => modelServer.listen(0, '127.0.0.1', resolve))
|
||||
const address = modelServer.address()
|
||||
if (address === null || typeof address === 'string') throw new Error('model server did not bind a TCP port')
|
||||
const child = spawn(process.execPath, [
|
||||
'--expose-internals',
|
||||
'--import',
|
||||
'tsx',
|
||||
binScript,
|
||||
configPath,
|
||||
], {
|
||||
cwd: repoRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
DEEPSEEK_API_KEY: 'keyless-smoke-no-call',
|
||||
DEEPSEEK_BASE_URL: `http://127.0.0.1:${address.port}`,
|
||||
DSH_CWD: root,
|
||||
DSH_SESSION_ROOT: join(root, '.sessions'),
|
||||
...(envValue === undefined ? {} : { DSH_MAX_TOKENS_AS_SUCCESS: envValue }),
|
||||
},
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
})
|
||||
const lines: string[] = []
|
||||
let stdoutBuffer = ''
|
||||
let stderr = ''
|
||||
child.stdout.setEncoding('utf8')
|
||||
child.stdout.on('data', (chunk: string) => {
|
||||
stdoutBuffer += chunk
|
||||
const parts = stdoutBuffer.split('\n')
|
||||
stdoutBuffer = parts.pop() ?? ''
|
||||
lines.push(...parts)
|
||||
})
|
||||
child.stderr.setEncoding('utf8')
|
||||
child.stderr.on('data', (chunk: string) => { stderr += chunk })
|
||||
|
||||
try {
|
||||
child.stdin.write(`${JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'initialize',
|
||||
params: { cwd: root, provider: 'deepseek', model: 'deepseek-v4-pro' },
|
||||
})}\n`)
|
||||
const initialized = await waitForLine(lines, value => value.id === 1, () => stderr)
|
||||
expect(initialized).toMatchObject({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
result: { serverInfo: { name: 'deepseek-harness-sdk-runtime' } },
|
||||
})
|
||||
|
||||
child.stdin.write(`${JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 2,
|
||||
method: 'session/prompt',
|
||||
params: { sessionId: 'main', contentBlocks: [{ type: 'text', text: 'inspect tools' }] },
|
||||
})}\n`)
|
||||
const finished = await waitForLine(lines, value => value.method === 'session.finished', () => stderr)
|
||||
expect(finished).toMatchObject({
|
||||
jsonrpc: '2.0',
|
||||
method: 'session.finished',
|
||||
params: {
|
||||
sessionId: 'main',
|
||||
status: expectedStatus,
|
||||
reason: { kind: 'max-tokens' },
|
||||
},
|
||||
})
|
||||
const prompt = await waitForLine(lines, value => value.id === 2, () => stderr)
|
||||
expect(prompt).toMatchObject({ jsonrpc: '2.0', id: 2, result: { accepted: true } })
|
||||
const tools = modelRequests[0]?.tools as { function?: { name?: string } }[]
|
||||
expect(tools.map(tool => tool.function?.name).sort()).toEqual([
|
||||
'bash',
|
||||
'edit',
|
||||
'read',
|
||||
'subagent',
|
||||
'todo_write',
|
||||
'write',
|
||||
])
|
||||
|
||||
child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id: 3, method: 'shutdown' })}\n`)
|
||||
const shutdown = await waitForLine(lines, value => value.id === 3, () => stderr)
|
||||
expect(shutdown).toMatchObject({ jsonrpc: '2.0', id: 3, result: {} })
|
||||
if (child.exitCode === null) {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
child.once('exit', (code) => {
|
||||
if (code === 0) resolve()
|
||||
else reject(new Error(`runtime exited ${code}; stderr=${stderr}`))
|
||||
})
|
||||
})
|
||||
} else {
|
||||
expect(child.exitCode, stderr).toBe(0)
|
||||
}
|
||||
} finally {
|
||||
if (child.exitCode === null) child.kill('SIGKILL')
|
||||
await new Promise<void>(resolve => modelServer.close(() => { resolve() }))
|
||||
await rm(root, { recursive: true, force: true })
|
||||
}
|
||||
}, 40_000)
|
||||
|
||||
it('rejects an invalid max-token success env value', async () => {
|
||||
const child = spawn(process.execPath, [
|
||||
'--expose-internals',
|
||||
'--import',
|
||||
'tsx',
|
||||
binScript,
|
||||
configPath,
|
||||
], {
|
||||
cwd: repoRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
DEEPSEEK_API_KEY: 'keyless-smoke-no-call',
|
||||
DSH_MAX_TOKENS_AS_SUCCESS: 'sometimes',
|
||||
},
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
})
|
||||
let stdout = ''
|
||||
let stderr = ''
|
||||
child.stdout.setEncoding('utf8')
|
||||
child.stdout.on('data', (chunk: string) => { stdout += chunk })
|
||||
child.stderr.setEncoding('utf8')
|
||||
child.stderr.on('data', (chunk: string) => { stderr += chunk })
|
||||
|
||||
const exitCode = await new Promise<number | null>((resolve, reject) => {
|
||||
child.once('error', reject)
|
||||
child.once('exit', resolve)
|
||||
})
|
||||
|
||||
expect(exitCode, stderr).toBe(1)
|
||||
expect(stdout).toBe('')
|
||||
expect(stderr).toContain('plugin(s) failed to load: @deepseek-ai/dsh-jsonrpc')
|
||||
}, 10_000)
|
||||
})
|
||||
@@ -3,11 +3,12 @@
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"description": "Workspace umbrella for runnable demos and example-owned test compositions: declares their cordis.yml packages so plain Node resolves real exports→lib. Not a build target.",
|
||||
"description": "Workspace umbrella for runnable demos and example-owned test compositions: declares their cordis.yml packages so plain Node resolves real exports\u2192lib. Not a build target.",
|
||||
"dependencies": {
|
||||
"@cordisjs/plugin-hmr": "workspace:*",
|
||||
"@cordisjs/plugin-include": "workspace:*",
|
||||
"@deepseek-ai/dsh-acp-demo": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent-spine-demo": "workspace:*",
|
||||
"@deepseek-ai/dsh-bash-local": "workspace:*",
|
||||
"@deepseek-ai/dsh-bash-sandbox": "workspace:*",
|
||||
"@deepseek-ai/dsh-cli-demo": "workspace:*",
|
||||
@@ -16,14 +17,18 @@
|
||||
"@deepseek-ai/dsh-compact-tool-result-prune": "workspace:*",
|
||||
"@deepseek-ai/dsh-fs-local": "workspace:*",
|
||||
"@deepseek-ai/dsh-fs-policy": "workspace:*",
|
||||
"@deepseek-ai/dsh-fs-sandbox": "workspace:^",
|
||||
"@deepseek-ai/dsh-hooks-claude": "workspace:*",
|
||||
"@deepseek-ai/dsh-hooks-codex": "workspace:*",
|
||||
"@deepseek-ai/dsh-jsonrpc": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm-deepseek": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm-replay": "workspace:*",
|
||||
"@deepseek-ai/dsh-permission": "workspace:*",
|
||||
"@deepseek-ai/dsh-repeat-tool-guard": "workspace:*",
|
||||
"@deepseek-ai/dsh-sandbox-local": "workspace:*",
|
||||
"@deepseek-ai/dsh-sandbox-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-persistence-jsonl": "workspace:*",
|
||||
"@deepseek-ai/dsh-spill-local": "workspace:*",
|
||||
"@deepseek-ai/dsh-spill-policy": "workspace:*",
|
||||
"@deepseek-ai/dsh-stdio-demo": "workspace:*",
|
||||
|
||||
@@ -27,7 +27,7 @@ The id is wired through `cordis.yml` (`resumeSessionId: !!js process.env.RESUME_
|
||||
|
||||
## Code Mode
|
||||
|
||||
[`code-mode.cordis.yml`](code-mode.cordis.yml) overlays the same tree with the worker-thread runtime and `tools: { mode: code }`. The model receives one `run_code` transport plus a generated TypeScript SDK for the visible tools; only program output returns to model context. Use `mode: both` to expose native calls alongside `run_code`. See the [Code Mode RFC](../../docs/rfc/implemented/feature/2026-06-15-code-mode.md) for the execution contract.
|
||||
[`code-mode.cordis.yml`](code-mode.cordis.yml) overlays the same tree with the worker-thread runtime and `tools: { mode: code }`. The model receives one `run_code` transport plus a generated TypeScript SDK for the visible tools; only program output returns to model context. Use `mode: both` to expose native calls alongside `run_code`. See the [Code Mode Agent Note](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) for the execution contract.
|
||||
|
||||
```sh
|
||||
pnpm run demo:code-mode # this overlay under the REPL (default UI)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user