dsh-edge 0.29.0-alpha.1 → 0.30.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +11 -9
- package/README.zh.md +11 -9
- package/package.json +1 -1
- package/worker/direct/index.js +1072 -1068
- package/worker/isolated/index.js +870 -866
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# last confirmed-consistent state. Both languages carry equal authority.
|
|
3
3
|
# After editing either side, update both and re-record every pair with:
|
|
4
4
|
# pnpm run doc-pairs -- --write
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 86bf330b284d6ffa83a2a61e173cae2b7b03645c
|
|
6
|
+
README.zh.md: 3334fff3f0c1953d7d8778da3b6ff089bccf41dd
|
package/README.md
CHANGED
|
@@ -145,16 +145,16 @@ This reference separates code that runs natively in Workers, code adapted at an
|
|
|
145
145
|
| Agent loop | Cordis-composed `ReactLoopAgent` with hooks, guards, sessions, and tools | Reused | Create and cold-resume agents through `AgentRegistry`. Context compaction, token metering, tool-result pruning, automatic session title generation, the repeated-tool-call reminder (after 3, 5, and 8 identical consecutive calls), model-request retry (a rate limit, server error, timeout, transport error, or empty response is retried up to five times within the turn, with 0.5–10 s backoff or the provider's `Retry-After`), and durability checkpoints (the session log is stored before each model request, each top-level tool call, and each step) run as upstream cordis plugins. The upstream `/compact` command (`dsh-command-compact`) compacts the session's history on request. |
|
|
146
146
|
| Bash tool | Node subprocess, sandbox, terminal, and job services | Adapted at the native tool seam | Register an upstream `ToolDefinition`, but execute its body through the configured Computer workspace backend and just-bash. The default direct backend runs inside the owner Durable Object with hardened interpreter limits and no network command; adding a `LOADER` binding selects Computer's isolated Worker Shell backend. Native tool cancellation sends `SIGINT` through the Computer execution handle. Deployment configuration supplies an explicit default timeout and caller-selectable ceiling, while `timedOut` reports the deadline independently from exit and cancellation status. Native binaries, background processes, PTYs, and arbitrary Linux behavior are unavailable. The bash tool has no `run_in_background` and never moves a long command to a background job. |
|
|
147
147
|
| Workspace filesystem | Local filesystem services and host paths | Adapted | Store `/workspace` in the owner's SQLite-backed Durable Object VFS. |
|
|
148
|
-
| Session persistence | `SessionPersistence` service, `PersistenceCoordinator`, and local JSONL/SQLite backends | Native backend adaptation | Reuse the upstream service and coordinator ownership. Implement storage primitives over Durable Object SQL with the upstream header/event mapping. One Edge-only table retains empty session headers across transparent hibernation and is removed when canonical rows materialize; no Edge turn or message schema exists. Internal coordinator helpers validate the bounded replay loader and abandon a failed unmaterialized creation before disposal. |
|
|
149
|
-
| Settings and credentials | File-backed settings, launch environment, and credential services | Writable with DO storage | The upstream `dsh-settings` plugin persists user sections in Durable Object KV via `DurableObjectSettingsProvider`. The upstream `dsh-llm-deepseek` cordis plugin is installed directly, auto-registering the `llm-deepseek` settings namespace and configurable provider entry; the Settings → Models page can read and modify provider configuration (base URL, model catalog, API key reference, reasoning effort) at runtime without redeployment. `EdgeCredentialProvider` resolves credentials from DO KV first, then falls back to Worker environment secrets; `set`/`unset` persist through the upstream seam. Deployment defaults (maxTokens 256,000, reasoningEffort high) are aligned with the upstream plugin so unset deployment variables match upstream behavior. Settings → Built-in plugins also has a Settings tab with upstream's agent-loop and web-search cards: the Edge registers their `agent-loop` (parallel tool calls) and `web-search-deepseek` (searches per request, endpoint, and the DeepSeek key the search uses) namespaces, applies a saved value to the running plugin, and refuses an endpoint that `DEEPSEEK_SEARCH_BASE_URL` would refuse. Upstream's Shell card edits the `bash-sandbox` namespace, which the Edge registers for its own bash: the command timeout defaults to `DSH_EDGE_DEFAULT_COMMAND_TIMEOUT_MS` and may not exceed `DSH_EDGE_MAX_COMMAND_TIMEOUT_MS`, the output cap per stream (64,000 bytes by default, 1 KiB to 1 MiB because each stream holds it in memory) is the inline tail before output spills, and both apply from the next command, in both shells and the HTTP exec route. Upstream's Subagent card edits the subagent runtime's `subagent` namespace: maximum recursion depth (default 1) and the parallelism limit for resident subagents (default 8); its models section edits `subagent-model-selection-settings`: off by default, as upstream; when on, a new session records the allowed models once (a `subagent/model-selection-policy` event), and its `subagent` tool gains `list_subagent_models` and may run a child on one of them. Edge sessions are resumed on first use, so the Edge records the setting on a root session that has not run a turn yet, where upstream records it on a session never seeded. `subagent_fork` children keep the parent's model. Upstream's plugin manager page, which hosts these cards upstream, is not shipped, because it installs and removes plugins through a runtime Loader the Edge does not have. |
|
|
148
|
+
| Session persistence | `SessionPersistence` service, `PersistenceCoordinator`, and local JSONL/SQLite backends | Native backend adaptation | Reuse the upstream service and coordinator ownership. Implement storage primitives over Durable Object SQL with the upstream header/event mapping. One Edge-only table retains empty session headers across transparent hibernation and is removed when canonical rows materialize; no Edge turn or message schema exists. Internal coordinator helpers validate the bounded replay loader and abandon a failed unmaterialized creation before disposal. It enforces upstream's storage contract with upstream's own checks: a read refuses an event type this build does not know unless its writer marked it ignorable, and so does a write open, which then releases its ownership: each session's summary row keeps its stored event types, updated by the append that already writes that row, so the open reads one row (a session stored by an earlier release, or repaired or migrated since, is scanned once and its types recorded); an append stores the lossless-JSON snapshot it checked and only when it continues the stored log; a bounded `read(offset, length)` selects only its rows and reports an unparsable row in its range as corruption. Two parts of that contract differ: a created session's header row is written at create rather than at the first append or flush, and an empty created session is kept as a retained blank, so a flush does not make it durable. |
|
|
149
|
+
| Settings and credentials | File-backed settings, launch environment, and credential services | Writable with DO storage | The upstream `dsh-settings` plugin persists user sections in Durable Object KV via `DurableObjectSettingsProvider`. The upstream `dsh-llm-deepseek` cordis plugin is installed directly, auto-registering the `llm-deepseek` settings namespace and configurable provider entry; the Settings → Models page can read and modify provider configuration (base URL, model catalog, API key reference, reasoning effort) at runtime without redeployment. `EdgeCredentialProvider` resolves credentials from DO KV first, then falls back to Worker environment secrets; `set`/`unset` persist through the upstream seam and, as upstream's providers do, announce each stored change as `credentials/reference-updated`, so an open Models page, model menu, or web-search card refreshes without a reload. Deployment defaults (maxTokens 256,000, reasoningEffort high) are aligned with the upstream plugin so unset deployment variables match upstream behavior. Settings → Built-in plugins also has a Settings tab with upstream's agent-loop and web-search cards: the Edge registers their `agent-loop` (parallel tool calls) and `web-search-deepseek` (searches per request, endpoint, and the DeepSeek key the search uses) namespaces, applies a saved value to the running plugin, and refuses an endpoint that `DEEPSEEK_SEARCH_BASE_URL` would refuse. Upstream's Shell card edits the `bash-sandbox` namespace, which the Edge registers for its own bash: the command timeout defaults to `DSH_EDGE_DEFAULT_COMMAND_TIMEOUT_MS` and may not exceed `DSH_EDGE_MAX_COMMAND_TIMEOUT_MS`, the output cap per stream (64,000 bytes by default, 1 KiB to 1 MiB because each stream holds it in memory) is the inline tail before output spills, and both apply from the next command, in both shells and the HTTP exec route. Upstream's Subagent card edits the subagent runtime's `subagent` namespace: maximum recursion depth (default 1) and the parallelism limit for resident subagents (default 8); its models section edits `subagent-model-selection-settings`: off by default, as upstream; when on, a new session records the allowed models once (a `subagent/model-selection-policy` event), and its `subagent` tool gains `list_subagent_models` and may run a child on one of them. Edge sessions are resumed on first use, so the Edge records the setting on a root session that has not run a turn yet, where upstream records it on a session never seeded. `subagent_fork` children keep the parent's model. Upstream's plugin manager page, which hosts these cards upstream, is not shipped, because it installs and removes plugins through a runtime Loader the Edge does not have. |
|
|
150
150
|
| Host boot and plugins | Node command line, Cordis profile loading, package resolution, and HMR | Explicit Edge composition | Keep the local boot profile out of Workerd. Build immutable client bundles ahead of deployment; exclude HMR and host domains that the Edge `ApiProxy` does not expose. The upstream `dsh-host-plugin-inventory` Remote serves Settings → Plugins; `EdgeLoader` projects `host:` entries from the live plugin registry with their fiber phase and `web:` entries from `expected-boot-graph.json`. |
|
|
151
151
|
| DSH transport | Typed HTTP RPC plus mux and host WebSocket downlinks | Reused with an Edge server implementation | Use the upstream fetch carrier for unary methods and preserve its envelopes, schemas, projections, lazy blank-session behavior, bounded content search, prompt and queue mutations, workspace mutations, queue snapshots, and event frames. Durable Object WebSocket hibernation owns both downlinks; mux reconnects replay pending live inbox state, while REST/SSE routes remain a diagnostic compatibility path. |
|
|
152
152
|
| Workspace registry | Storage-domain global state plus `WorkspaceRecord` rows | Native backend adaptation | Keep the upstream global and record value shapes, including manual session order and archive membership, but map their physical keys and atomic writes to Durable Object storage. Edge constrains the registry to the one native `/workspace` VFS; rename, delete, recreation, and session reordering retain the upstream RPC and Host-frame semantics. |
|
|
153
153
|
| Directory picker | `ctx.directoryPicker` seam with the `-native` OS chooser or the `-browse` filesystem backend, chosen at boot by `dsh-host-directory-picker-auto`, plus the Web browse dialog | Reused with an Edge browse backend | Install the upstream seam and pin the upstream `dsh-client-ui-directory-picker-browse` dialog in the Web roster; Edge answers the `browse` capability from the `/workspace` Computer VFS one level per call, rooted at `/workspace` with the upstream hidden, bound, and failure vocabulary, so the upstream `DirectoryPickerController` serves `directoryPicker/list` and `createDirectory` and refuses the native `pick`. |
|
|
154
154
|
| Conversation file links | `session/openWorkspacePath` hands a clicked path to the Host desktop opener through `dsh-native-command`; `session/canOpenWorkspacePath` gates the affordance | Adapted at the upstream `SessionControllerInternals` seam plus a Web download fallback | Compose `SessionController` with Edge internals so the native probe answers false and an open attempt fails with a readable reason instead of a `child_process` error. The V3 Web client opens file links in its right-sidebar preview. Edge composes the upstream `workspaceFiles` controller over request-scoped VFS reads, including bounded text/byte windows and metadata subscriptions. The legacy `ctx.remote.session.openWorkspacePath` fallback and owner-authenticated `GET /api/workspace/file` download remain available. |
|
|
155
155
|
| Existing Web UI | Runtime-loaded shell and `dsh.client` plugin graph | Reused with generic composition fallbacks | Assemble the upstream shell and supported upstream client bundles as Worker assets. Shared slot-occupancy rules hide actions whose provider is absent; Cloudflare serves ordinary assets directly, while `/`, `/login`, and `/api/*` enter the Worker for owner access control. The assembled asset policy prevents every direct or SPA-fallback shell alias from being framed. |
|
|
156
|
-
| Other tools | Web Search, filesystem editor tools, MCP, skills, workflows, jobs, and subagents | Search, file, glob/grep, goal, todo, skill, subagent, and MCP tools ported; workflow and run_code ported for the isolated build | Reuse upstream DeepSeek Web Search with its 30-second tool-call timeout. The web search card's "Use the new Web Search API" switch (off by default) moves search and fetch to the DeepSeek Search and Fetch APIs (`dsh-web-deepseek-api`): DeepSeek fetches the page, so the Worker reads no third-party page itself, and no auxiliary model request is made. They use the DeepSeek API key the Models page stores (the key name may not be another Edge feature's credential, and a literal key is refused in settings), their API base must be an HTTP(S) URL without credentials, a query, or a fragment, a redirect is refused, and the account sign-in route is not offered. The Search and Fetch APIs may bill separately from model tokens. The upstream `workflow` tool is offered only by the Dynamic Worker runtime (the isolated, Paid-plan build); the Direct build does not register it. Each run loads its script into its own Dynamic Worker with no outbound network and a 30-second Worker Loader `cpuMs` limit (enforced by the Cloudflare runtime, not by local development), because workerd forbids in-process `eval`/`new Function`/`node:vm`; `agent()`, `phase()`, and `log()` cross an RPC bridge to the Durable Object, which enforces the caps: at most 4 children run at once (below the Workers six-connection limit) and one run starts at most 100 children to bound child-session row writes. The same runtime offers upstream's `ralph` tool (`dsh-tool-ralph`), which runs a foreground loop of fresh `subagent` children toward one objective, each round handing only a bounded report to the next, until a child reports completion or a blocker. Like upstream, its prompt reserves it for an explicit request. It runs on the workflow engine, so a run is capped at 100 rounds (upstream defaults to 256), and the PTC mode preset does not offer it, as it does not offer `workflow`. The upstream `run_code` tool (`dsh-tools` PTC mode) is offered by the same runtime, but only to sessions started in the upstream `ptc` agent preset (PTC mode), which isolated deployments offer under its upstream id so the Web client shows its built-in bilingual name. That preset presents every tool through the generated SDK and, as upstream does, does not offer `workflow`, because `run_code` is its only orchestration surface. The default upstream `standard` preset (Standard mode; sessions recorded under the earlier `dsh-edge` id read as `standard`) presents tools natively and keeps `workflow`. As upstream, Settings → Agent presets writes `selectedDefault` in the `agent-preset-registry` settings namespace to choose which offered preset new sessions start on; a default saved by an earlier release under `agent-presets` moves there on start. In PTC mode, each program is type-stripped with sucrase and runs in its own Dynamic Worker with a 30-second `cpuMs` limit and no outbound network; its `tools.*` calls cross an RPC bridge where the Durable Object caps them at 200 per run (each is a nested tool dispatch with its own session events), 256 KiB of arguments, and 2 MiB per result, and nested calls stay approval-gated. File tools (read/write/edit/read_image) adapted via `EdgeFileSystem` backed by Computer VFS. `glob` and `grep` keep upstream `dsh-tool-fs-search`'s names, schemas, result text, search cards, and spill of results over 100 paths or 250 matches, but Workers cannot spawn its ripgrep binary, so Edge runs them over the VFS: both skip VCS metadata; `grep` also skips binary files and files over 4 MiB and, like ripgrep's defaults that upstream's `grep` keeps, hidden entries and those `.rgignore`, `.ignore`, and (inside a git repository) `.gitignore` files exclude, without entering an ignored directory, so a large ignored `node_modules` costs one entry (as ripgrep's `--glob`, a file `include` matches is searched even when ignored or hidden); `glob`, like upstream's (`--no-ignore --hidden`), lists hidden and ignored files. Ignore globs match by character, where ripgrep matches `?` and classes by byte on Unix, so a rule such as `?` also matches a one-character non-ASCII name. Global gitignore files and `.git/info/exclude` are not read, and an ignore file over 256 KiB, or one that would bring a search past 5,000 compiled matchers (one per rule, or per alternative of its `{a,b}` groups, each kept in memory for the walk), is not applied (the budget is taken in walk order, so an ignore file that comes after it is skipped even when its kind would outrank an earlier `.gitignore`, which ripgrep would honor), and a walk that would test ignore patterns more than 5,000,000 times fails like one past its entry cap. `grep` patterns use RE2 syntax (no lookaround or backreferences) through re2js, which matches in linear time, so a pathological pattern cannot stall the Durable Object. A search walks at most 20,000 entries, and `grep` collects at most 20,000 matching lines or 20 MB of their text; past a cap it fails and asks for a narrower path or pattern. Glob syntax that ripgrep 15 rejects (an unclosed `[` or `{`, a reversed range such as `[z-a]`, a dangling `\`) fails as an invalid pattern; nested alternates such as `a{b,{c,d}}` work. A search checks for cancellation before and after each directory listing, so the 30-second tool timeout stops a long walk. As upstream, the file observation policy (`dsh-fs-observation-policy`) guards them: `write` may not overwrite a file the session has not read, `edit` requires a prior read, and a file changed since it was read (by `bash` or the Linux container, for example) fails as stale until it is read again; a restarted session starts with no reads recorded. Goal tools (`ToolGoal`) composed directly with `GoalService` as upstream cordis plugins. Subagents follow upstream's standard composition: `subagent` starts a fresh child and `subagent_fork` one that starts from the parent's completed turns (`dsh-subagent-spawn-in-process`, `dsh-subagent-fork-in-process`). Both run the child in the background by default as a continuable subagent, and the parent continues it with `send_message`, stops its current turn with `interrupt_agent`, and finds it with `list_agents` (`dsh-tool-subagent-control`). A child keeps working after the parent's turn ends, and its closing message wakes the parent for another turn; as upstream, Stop on the parent does not stop running children. A child that is not running resumes from storage when messaged, also after a restart. The upstream `todo_write` tool (`dsh-tool-todo`) keeps the session's task list, with several tasks allowed in progress as in upstream's composition; its `todos` projection drives the Web client's todo dock. The upstream `present` tool (`dsh-tool-present`) declares workspace files as a turn's deliverables, which the Web client shows as file cards with a sidebar preview; the Edge has no desktop, so it answers the cards' Host check (`/api/present.host`) as unavailable and they offer no native opening. As upstream, `dsh-agent-instructions` loads `AGENTS.md` and `CLAUDE.md` (and their `.local.md` overlays) from the project root (the nearest ancestor directory containing `.git`, or else the session's working directory) down to the working directory, through the workspace VFS, into a 64 KiB baseline message before the first request; a `read`, `write`, or `edit` that reaches a deeper directory adds its instructions to the next request. Workers have no home directory, so the user-global files are `/.dsh/AGENTS.md` and the shared agent root's `/.agents/AGENTS.md` (the Edge sets `DSH_HOME` and `DSH_AGENTS_HOME` itself, because the plugin reads its homes only from those variables). The `working_directory` tool (`dsh-tool-working-directory`) reads the session's working directory or changes it to an existing directory; the change is a durable `working-directory/change` event that a downgrade to a release before this one cannot read, and the Edge always offers `/workspace` as an existing directory. Skill tool via `SkillRegistry`. As upstream `dsh-skill-filesystem`, skills are `<name>/SKILL.md` or `<name>.md` files with `name` and `description` frontmatter under the project's `.dsh/skills` and `.agents/skills` and the user roots `/.dsh/skills` and `/.agents/skills` (Workers have no home directory), read through the workspace VFS, up to 100 entries per root and 64 KiB per skill file; an added or edited skill applies from the next turn, and the `/` menu of a session opened after the change lists it; as upstream, the Web client keeps an open session's `/` list until the page reloads. Skills stored through the owner API `GET/PUT/DELETE /api/skills` (`EdgeSkillProvider`, DO KV) rank below them. MCP runs on the Edge's own client (`edge-mcp-client.ts`; upstream `dsh-mcp-client` is not mounted): Streamable HTTP only (stdio is unavailable on Workers) and one connection per call. A server whose probe reports the `resources` capability is registered with upstream `dsh-mcp-resources`, whose `list_mcp_resources`, `list_mcp_resource_templates`, and `read_mcp_resource` tools exist while one such server is configured (probe an existing server again to record the capability); a server without the tools capability probes as an empty tool catalog. Resource calls follow the connector's tool permission as its read-only tools do, so they ask first only when it asks before every call. Each resources response body is limited to 1 MiB and fails while it streams in past that, because the SDK parses a response whole and a read result, binary data included, is kept in the session log; a list without a cursor follows at most 10 pages or 1 MiB of entries and returns the cursor where it stopped. As upstream, binary contents reach the model only as a description. Configure servers in Settings → DSH Edge → MCP Servers; tools appear as `mcp__<serverName>__<tool>`. Add the remaining tools individually against Worker-compatible capabilities; do not advertise unavailable host behavior. |
|
|
157
|
-
| Attachments | Local attachment storage, upstream image references, composer, gallery, lightbox, and provider conversion | Adapted at the native storage seam | Reuse upstream `AttachmentStore`, admission, protocol, authorization, UI, and DeepSeek conversion unchanged. Store immutable PNG
|
|
156
|
+
| Other tools | Web Search, filesystem editor tools, MCP, skills, workflows, jobs, and subagents | Search, file, glob/grep, goal, todo, skill, subagent, and MCP tools ported; workflow and run_code ported for the isolated build | Reuse upstream DeepSeek Web Search with its 30-second tool-call timeout. The web search card's "Use the new Web Search API" switch (off by default) moves search and fetch to the DeepSeek Search and Fetch APIs (`dsh-web-deepseek-api`): DeepSeek fetches the page, so the Worker reads no third-party page itself, and no auxiliary model request is made. They use the DeepSeek API key the Models page stores (the key name may not be another Edge feature's credential, and a literal key is refused in settings), their API base must be an HTTP(S) URL without credentials, a query, or a fragment, a redirect is refused, and the account sign-in route is not offered. The Search and Fetch APIs may bill separately from model tokens. The upstream `workflow` tool is offered only by the Dynamic Worker runtime (the isolated, Paid-plan build); the Direct build does not register it. Each run loads its script into its own Dynamic Worker with no outbound network and a 30-second Worker Loader `cpuMs` limit (enforced by the Cloudflare runtime, not by local development), because workerd forbids in-process `eval`/`new Function`/`node:vm`; `agent()`, `phase()`, and `log()` cross an RPC bridge to the Durable Object, which enforces the caps: at most 4 children run at once (below the Workers six-connection limit) and one run starts at most 100 children to bound child-session row writes. The same runtime offers upstream's `ralph` tool (`dsh-tool-ralph`), which runs a foreground loop of fresh `subagent` children toward one objective, each round handing only a bounded report to the next, until a child reports completion or a blocker. Like upstream, its prompt reserves it for an explicit request. It runs on the workflow engine, so a run is capped at 100 rounds (upstream defaults to 256), and the PTC mode preset does not offer it, as it does not offer `workflow`. The upstream `run_code` tool (`dsh-tools` PTC mode) is offered by the same runtime, but only to sessions started in the upstream `ptc` agent preset (PTC mode), which isolated deployments offer under its upstream id so the Web client shows its built-in bilingual name. That preset presents every tool through the generated SDK and, as upstream does, does not offer `workflow`, because `run_code` is its only orchestration surface. The default upstream `standard` preset (Standard mode; sessions recorded under the earlier `dsh-edge` id read as `standard`) presents tools natively and keeps `workflow`. As upstream, Settings → Agent presets writes `selectedDefault` in the `agent-preset-registry` settings namespace to choose which offered preset new sessions start on; a default saved by an earlier release under `agent-presets` moves there on start. In PTC mode, each program is type-stripped with sucrase and runs in its own Dynamic Worker with a 30-second `cpuMs` limit and no outbound network; its `tools.*` calls cross an RPC bridge where the Durable Object caps them at 200 per run (each is a nested tool dispatch with its own session events), 256 KiB of arguments, and 2 MiB per result, and nested calls stay approval-gated. `run_code`'s description tells the model this environment and these limits, as upstream's Node runtime describes its own. File tools (read/write/edit/read_image) adapted via `EdgeFileSystem` backed by Computer VFS. `glob` and `grep` keep upstream `dsh-tool-fs-search`'s names, schemas, result text, search cards, and spill of results over 100 paths or 250 matches, but Workers cannot spawn its ripgrep binary, so Edge runs them over the VFS: both skip VCS metadata; `grep` also skips binary files and files over 4 MiB and, like ripgrep's defaults that upstream's `grep` keeps, hidden entries and those `.rgignore`, `.ignore`, and (inside a git repository) `.gitignore` files exclude, without entering an ignored directory, so a large ignored `node_modules` costs one entry (as ripgrep's `--glob`, a file `include` matches is searched even when ignored or hidden); `glob`, like upstream's (`--no-ignore --hidden`), lists hidden and ignored files. Ignore globs match by character, where ripgrep matches `?` and classes by byte on Unix, so a rule such as `?` also matches a one-character non-ASCII name. Global gitignore files and `.git/info/exclude` are not read, and an ignore file over 256 KiB, or one that would bring a search past 5,000 compiled matchers (one per rule, or per alternative of its `{a,b}` groups, each kept in memory for the walk), is not applied (the budget is taken in walk order, so an ignore file that comes after it is skipped even when its kind would outrank an earlier `.gitignore`, which ripgrep would honor), and a walk that would test ignore patterns more than 5,000,000 times fails like one past its entry cap. `grep` patterns use RE2 syntax (no lookaround or backreferences) through re2js, which matches in linear time, so a pathological pattern cannot stall the Durable Object. A search walks at most 20,000 entries, and `grep` collects at most 20,000 matching lines or 20 MB of their text; past a cap it fails and asks for a narrower path or pattern. Glob syntax that ripgrep 15 rejects (an unclosed `[` or `{`, a reversed range such as `[z-a]`, a dangling `\`) fails as an invalid pattern; nested alternates such as `a{b,{c,d}}` work. A search checks for cancellation before and after each directory listing, so the 30-second tool timeout stops a long walk. As upstream, the file observation policy (`dsh-fs-observation-policy`) guards them: `write` may not overwrite a file the session has not read, `edit` requires a prior read, and a file changed since it was read (by `bash` or the Linux container, for example) fails as stale until it is read again; a restarted session starts with no reads recorded. Goal tools (`ToolGoal`) composed directly with `GoalService` as upstream cordis plugins. Subagents follow upstream's standard composition: `subagent` starts a fresh child and `subagent_fork` one that starts from the parent's completed turns (`dsh-subagent-spawn-in-process`, `dsh-subagent-fork-in-process`). Both run the child in the background by default as a continuable subagent, and the parent continues it with `send_message`, stops its current turn with `interrupt_agent`, and finds it with `list_agents` (`dsh-tool-subagent-control`). A child keeps working after the parent's turn ends, and its closing message wakes the parent for another turn; as upstream, Stop on the parent does not stop running children. A child that is not running resumes from storage when messaged, also after a restart. The upstream `todo_write` tool (`dsh-tool-todo`) keeps the session's task list, with several tasks allowed in progress as in upstream's composition; its `todos` projection drives the Web client's todo dock. The upstream `present` tool (`dsh-tool-present`) declares workspace files as a turn's deliverables, which the Web client shows as file cards with a sidebar preview; the Edge has no desktop, so it answers the cards' Host check (`/api/present.host`) as unavailable and they offer no native opening. As upstream, `dsh-agent-instructions` loads `AGENTS.md` and `CLAUDE.md` (and their `.local.md` overlays) from the project root (the nearest ancestor directory containing `.git`, or else the session's working directory) down to the working directory, through the workspace VFS, into a 64 KiB baseline message before the first request; a `read`, `write`, or `edit` that reaches a deeper directory adds its instructions to the next request. Workers have no home directory, so the user-global files are `/.dsh/AGENTS.md` and the shared agent root's `/.agents/AGENTS.md` (the Edge sets `DSH_HOME` and `DSH_AGENTS_HOME` itself, because the plugin reads its homes only from those variables). The `working_directory` tool (`dsh-tool-working-directory`) reads the session's working directory or changes it to an existing directory; the change is a durable `working-directory/change` event that a downgrade to a release before this one cannot read, and the Edge always offers `/workspace` as an existing directory. Skill tool via `SkillRegistry`. As upstream `dsh-skill-filesystem`, skills are `<name>/SKILL.md` or `<name>.md` files with `name` and `description` frontmatter under the project's `.dsh/skills` and `.agents/skills` and the user roots `/.dsh/skills` and `/.agents/skills` (Workers have no home directory), read through the workspace VFS, up to 100 entries per root and 64 KiB per skill file; an added or edited skill applies from the next turn, and the `/` menu of a session opened after the change lists it; as upstream, the Web client keeps an open session's `/` list until the page reloads. Upstream's session skill catalog (`skills/list`) answers that menu, with each skill's file path; Workers have no file watches, so the Edge rechecks the session's skill roots before it lists, and gives it the workspace's file metadata, which a resident session's working-directory check reads outside a turn. Skills stored through the owner API `GET/PUT/DELETE /api/skills` (`EdgeSkillProvider`, DO KV) rank below them. MCP runs on the Edge's own client (`edge-mcp-client.ts`; upstream `dsh-mcp-client` is not mounted): Streamable HTTP only (stdio is unavailable on Workers) and one connection per call. A server whose probe reports the `resources` capability is registered with upstream `dsh-mcp-resources`, whose `list_mcp_resources`, `list_mcp_resource_templates`, and `read_mcp_resource` tools exist while one such server is configured (probe an existing server again to record the capability); a server without the tools capability probes as an empty tool catalog. Resource calls follow the connector's tool permission as its read-only tools do, so they ask first only when it asks before every call. Each resources response body is limited to 1 MiB and fails while it streams in past that, because the SDK parses a response whole and a read result, binary data included, is kept in the session log; a list without a cursor follows at most 10 pages or 1 MiB of entries and returns the cursor where it stopped. As upstream, binary contents reach the model only as a description. Configure servers in Settings → DSH Edge → MCP Servers; tools appear as `mcp__<serverName>__<tool>`. Add the remaining tools individually against Worker-compatible capabilities; do not advertise unavailable host behavior. |
|
|
157
|
+
| Attachments | Local attachment storage, upstream image references, composer, gallery, lightbox, and provider conversion | Adapted at the native storage seam | Reuse upstream `AttachmentStore`, admission, protocol, authorization, UI, and DeepSeek conversion unchanged. Store immutable image bytes (PNG or JPEG, or WebP when image optimization keeps transparency) under their SHA-256 identities in a 64 MiB, 512 KiB-chunked DO backend for new and pre-attachment deployments, or in private R2 for deployments already pinned to it; session events retain only upstream refs. The first backend is pinned per owner instance so claiming or upgrading cannot strand existing references. Images are PNG or JPEG, at most 3.5 MiB each and 4 per message. Other files stream through upstream's upload route and are kept verbatim, at most 64 MiB each (an upload must declare its length, so a larger one is refused before any byte is stored), in the workspace VFS at upstream's `files/<prefix>/<digest>/<name>` layout below `/.dsh/attachments/v1`, the path the model is told; its file tools and the lightweight shell read them there, but commands routed to a Linux Container do not see them. |
|
|
158
158
|
| Goal tracking | `GoalService` with create/edit/pause/resume/complete/clear mutations and GoalBar UI | Reused | Install upstream `GoalService` and `ToolGoal` as cordis plugins (direct composition). Browser GoalBar mutations route through `TypertGatewayService` at `/api/goals/<method>`. `SessionProjectionCache` persists goal state across DO restart. The upstream `/goal` command (`dsh-command-goal`) shows, sets, edits, pauses, resumes, or clears the session's goal. Every goal round runs inside an Edge turn, with its workspace, deadline, and live events: a turn stays open while upstream's round driver queues the next round, and a call that arms a goal outside a turn (`/goal`, GoalBar Resume) runs inside a new one. |
|
|
159
159
|
| Context compaction | Token metering, automatic compaction, and session title generation | Reused | Install upstream cordis plugins directly. Context compaction, token metering, tool-result pruning, and automatic session title generation run unchanged. Upstream image offload (`dsh-compaction-image-offload`) keeps a turn going when its images exceed the route's budget (600 images per request by default): it marks the oldest occurrences offloaded with an `image/offload` session event and the request is retried. |
|
|
160
160
|
| Session projection | Real-time derived state push to connected clients | Reused with Edge bridge | Upstream `onChanged` callback pushes title, model, goal, and session-stats projection frames to connected WebSocket clients. Upstream `dsh-session-stats` (whole-session turn and step counts and model, tool, and first-token times) feeds the Web chat view. `SessionProjectionCache` caches projections in DO KV for cold-session recovery. |
|
|
@@ -295,7 +295,7 @@ The installer asks in this order: account, Worker name, then what to change. Eve
|
|
|
295
295
|
- **Images** are stored in the instance's Durable Object (64 MiB), so a new install needs no R2 setup. Every deployment records its attachment-storage marker, and updates keep the marked or bound backend. A Worker already on private R2 stays there; if R2 is no longer enabled (Cloudflare error `10042`), the installer offers the account's activation link, a retry, or cancellation, never a switch that would strand image references. A pre-image Worker has no references to strand and moves to the Durable Object default. Mixed active rollouts are refused rather than guessed.
|
|
296
296
|
- **The owner access key** is generated for a new instance and shown when installation finishes. To choose your own, set `DSH_EDGE_ACCESS_KEY` (32–512 UTF-8 bytes) in the installer's environment; it stays out of shell history and the process list. An ordinary update keeps the existing key. Cloudflare cannot show a stored key again, so if you lose it, run the upgrade command for your deployment's release channel and choose **Update and reset the access key**: `npx dsh-edge upgrade` on a stable release, or `npx dsh-edge@next upgrade` if the installed version contains `-alpha` or `-rc` (the login page shows the one for your deployment). The installer deploys the release with a new key (generated, or `DSH_EDGE_ACCESS_KEY`) and shows it once. Conversations, files, and the DeepSeek key are kept; the old key stops working, and every signed-in browser must sign in again.
|
|
297
297
|
- **The DeepSeek API key** is added after installation in Settings → Models. The installer never asks for it.
|
|
298
|
-
- **Image optimization** (the Cloudflare Images binding) is on for accounts you own and off for temporary accounts.
|
|
298
|
+
- **Image optimization** (the Cloudflare Images binding) is on for accounts you own and off for temporary accounts. With it, an image over upstream's 2048 × 2048 pixel budget or 4 MiB, a WebP or GIF, or a rotated JPEG is normalized as upstream does (downscaled, upright, first frame, JPEG or WebP), while a PNG or JPEG that already fits is stored as sent and costs nothing. Cloudflare counts each image's transformation once a month: 5,000 a month are free, after which a Free plan refuses new ones and a paid plan bills them. When Images refuses or fails, an image within the limits that apply without it is stored as sent, and a larger one is refused with the reason. The Worker never decodes such images itself: an 8,192-pixel bitmap would not fit its memory.
|
|
299
299
|
|
|
300
300
|
### Credential handoff and activation
|
|
301
301
|
|
|
@@ -324,7 +324,8 @@ pnpm --filter dsh-edge example:install
|
|
|
324
324
|
- The Web client uses session list/search/create/history/models/select/prompt/updateQueue/rename/fork/cancel; host description; Workspace list/create/rename/delete/reorder/archive; skills; agent presets; settings and credential descriptions; and LLM catalogs.
|
|
325
325
|
- `agentPreset.read` renders the programmatic Edge composition through the upstream read-only viewer. `credentials.describe` returns credential state without a value.
|
|
326
326
|
- Search projects canonical current-message surfaces and returns bounded upstream result values.
|
|
327
|
-
- Fork
|
|
327
|
+
- Fork follows upstream's session controller: an `atSeq` is the exact inclusive cut (an event that does not exist is refused), an omitted one selects the latest completed-turn prefix, and upstream's `buildForkSeed` marks the cut and closes a turn left open as forked; the fork retains parent lineage. Edge reads a stored source only through the cut and refuses seeds above 8,192 events or 8 MiB instead of materializing unbounded history. `allowMigration` is accepted; the Edge migrates every stored session when its Durable Object starts, so a fork never meets one that still needs migration.
|
|
328
|
+
- Rename goes through upstream's `sessionTitle.rename`, which also stops automatic title generation still running, so a late generated title cannot replace the user's.
|
|
328
329
|
- Queue mutations edit, remove, or promote an item through the live upstream Agent inbox. The synchronous mutation is the acceptance point; the persistence coordinator owns later write-behind and retirement retry.
|
|
329
330
|
- Workspace mutations persist upstream workspace-domain global and record shapes through the Durable Object backend. Archive preserves the session log and Workspace slot; unary responses and Host frames carry the same full snapshots as upstream.
|
|
330
331
|
- Goal mutations (create, edit, pause, resume, complete, clear) route through `TypertGatewayService` at `/api/goals/<method>`. Each `@Remote` service requires its Typert descriptor to be registered via `ctx.typert.register()`; no per-method HTTP handler is needed.
|
|
@@ -360,7 +361,7 @@ SQLite `DELETE` operations consume the daily row-write allowance too. During for
|
|
|
360
361
|
- Session creation and fork return `session/workspace-attach-failed` with the published session and Workspace ids when publication succeeds but Workspace attachment fails. The diagnostic route returns the same code plus the complete created session.
|
|
361
362
|
- Prompt and queue-edit text share a 64 KiB semantic limit. Their 10 MiB RPC carrier leaves room for a 7 MiB raw-image batch after base64 and envelope overhead.
|
|
362
363
|
- Because Edge has no directory-flow provider, the upstream browser hides Delete on its sole Workspace and exposes it again whenever restoration remains possible.
|
|
363
|
-
- `@file` completion serves the upstream `fileReferences/list` Remote from the Computer VFS
|
|
364
|
+
- `@file` completion serves the upstream `fileReferences/list` Remote from the Computer VFS as upstream's local provider (`dsh-file-reference-local`) does: a query with a `/` lists that directory, relative to the session's working directory or absolute inside it, and a bare fragment fuzzy-ranks a recursive index of the working directory (exact, prefix, and substring names, then path substrings and in-order subsequences, so `rdm` finds `docs/README.md`). The index skips upstream's excluded directories (`.git`, `node_modules`, `dist`, `build`, and other dependency and build-output names) and holds at most 10,000 entries and 1,000,000 path characters, where upstream holds 50,000 entries, because every listing reads Durable Object rows: reading the index costs about 3.5 rows per entry. Sessions in the same working directory share one index, and at most 4 working directories' indexes are kept, the least recently queried dropped first. Only the first bare query waits for it; as upstream, a tool result in any session (they share one workspace) makes it stale, and the next bare query answers from it while the replacement is read. Like upstream's index, it does not notice files changed outside tools (owner API writes, uploads) until the next tool result; a query with a `/` always reads the directory. `@session` mentions and their pre-step snapshots come from the upstream session-reference service unchanged; its candidate discovery and either agent-scoped Remote resume a cold session through the upstream controller and keep it resident until the Durable Object is evicted.
|
|
364
365
|
|
|
365
366
|
### Limits and request admission
|
|
366
367
|
|
|
@@ -373,12 +374,13 @@ SQLite `DELETE` operations consume the daily row-write allowance too. During for
|
|
|
373
374
|
| Session-create JSON body | 8 KiB |
|
|
374
375
|
| Workspace-exec JSON body | 128 KiB |
|
|
375
376
|
| Message-bearing turn or queue-update RPC | 10 MiB |
|
|
376
|
-
| Images | PNG
|
|
377
|
+
| Images, with image optimization (the Cloudflare Images binding) | PNG, JPEG, WebP, and GIF (first frame); 8 per message; 7 MiB each and in total, which the 10 MiB message body holds after base64; 64 million pixels; 8,192 px per side; stored inside upstream's 2048 × 2048 pixel budget and 4 MiB |
|
|
378
|
+
| Images, without it | PNG/JPEG; 4 per message; 3.5 MiB each; 7 MiB total; 40 million pixels; 2,000 px per side |
|
|
377
379
|
|
|
378
380
|
- Request bodies are consumed incrementally. Once a route limit is crossed, later chunks are drained without being retained and the route returns 413. File uploads also reject malformed UTF-8.
|
|
379
381
|
- File reads check VFS metadata, then collect the opened byte stream through the same 1 MiB cap. This closes the growth race between `stat()` and `readFile()` without retaining an unbounded value.
|
|
380
382
|
- Image admission fully decodes the declared raster format before writing.
|
|
381
|
-
- As upstream `bash-local`, a command keeps running past the output cap: each stream keeps its last 64,000 bytes inline by default (the Shell card's output cap, 1 KiB to 1 MiB), and the whole stream is saved to `/workspace/.spill/bash-<execution>.<stream>.txt` (deleted with the other spills after 30 days), up to 16 MiB per stream (upstream allows 64 MiB; each 512 KiB costs about five Durable Object rows written, and the workspace storage does not free deleted bytes, #358), past which the file keeps its start and the result says so. Memory stays at the tail plus a 1 MiB write queue per stream: reading the command's output waits while the spill is written. Output under the cap writes nothing. The lightweight shell (just-bash) returns a command's output whole instead of streaming it, so it still stops a command whose output passes 8 MiB (exit 126, reported as `[stopped: …]`); that buffer lives in its isolate, the Durable Object in Direct mode. The bash tool renders upstream's layout: stdout, a `[stderr]` section, `[output truncated; full output: <path>]` per stream, `[timed out after Nms]`, and `[exit code: N]` last, and its terminal card shows the working directory. A `timeoutMs` above the deployment ceiling is lowered to it, as upstream clamps it; the HTTP exec route still refuses one. `cancelled` reflects an adapter-requested interruption; `timedOut` independently records deadline expiry.
|
|
383
|
+
- As upstream `bash-local`, a command keeps running past the output cap: each stream keeps its last 64,000 bytes inline by default (the Shell card's output cap, 1 KiB to 1 MiB), and the whole stream is saved to `/workspace/.spill/bash-<execution>.<stream>.txt` (deleted with the other spills after 30 days), up to 16 MiB per stream (upstream allows 64 MiB; each 512 KiB costs about five Durable Object rows written, and the workspace storage does not free deleted bytes, #358), past which the file keeps its start and the result says so. Memory stays at the tail plus a 1 MiB write queue per stream: reading the command's output waits while the spill is written. Output under the cap writes nothing. The lightweight shell (just-bash) returns a command's output whole instead of streaming it, so it still stops a command whose output passes 8 MiB (exit 126, reported as `[stopped: …]`); that buffer lives in its isolate, the Durable Object in Direct mode. The bash tool renders upstream's layout: stdout, a `[stderr]` section, `[output truncated; full output: <path>]` per stream, `[timed out after Nms]`, and `[exit code: N]` last, and its terminal card shows the working directory. In the Linux Container, output that reaches computerd after its command has exited stops the container: computerd 0.3.1 throws on it and exits, so on Cloudflare a command that prints a few hundred KB faster than the Durable Object reads it usually fails with an internal error, and the container restarts. The fix waits for the Computer release that carries cloudflare/computer#260 (#373). A `timeoutMs` above the deployment ceiling is lowered to it, as upstream clamps it; the HTTP exec route still refuses one. `cancelled` reflects an adapter-requested interruption; `timedOut` independently records deadline expiry.
|
|
382
384
|
|
|
383
385
|
### Durability and concurrency
|
|
384
386
|
|
package/README.zh.md
CHANGED
|
@@ -145,16 +145,16 @@ curl -b /tmp/dsh-edge-cookie -N -X POST -H 'content-type: application/json' \
|
|
|
145
145
|
| Agent loop | 由 Cordis 组合、带 hooks、guards、sessions 和 tools 的 `ReactLoopAgent` | 复用 | 通过 `AgentRegistry` 创建和冷恢复 agent。上下文压缩、token 计量、工具结果修剪、自动 session 标题生成、重复工具调用提醒(连续 3、5、8 次完全相同的调用时提醒)、模型请求重试(遇到限流、服务端错误、超时、网络错误或空响应时,在同一轮内最多重试 5 次,等待 0.5–10 秒,或按服务端的 `Retry-After`),以及持久化检查点(每次模型请求、每次顶层工具调用和每一步之前先保存 session 日志),作为上游 cordis 插件运行。上游的 `/compact` 命令(`dsh-command-compact`)按需压缩会话历史。 |
|
|
146
146
|
| Bash tool | Node subprocess、sandbox、terminal 和 job services | 在原生 tool seam 上适配 | 注册上游 `ToolDefinition`,但通过配置的 Computer workspace backend 和 just-bash 执行其 body。默认 direct backend 在 owner Durable Object 内运行,启用 hardened interpreter limits 且不提供网络命令;添加 `LOADER` binding 后会选择 Computer 的 isolated Worker Shell backend。原生 tool cancellation 会通过 Computer execution handle 发送 `SIGINT`。部署配置提供明确的默认 timeout 与调用方可选值上限,`timedOut` 则独立于 exit 与 cancellation status 报告 deadline。不支持原生二进制、后台进程、PTY 和任意 Linux 行为。bash 工具没有 `run_in_background`,也不会把耗时命令转为后台任务。 |
|
|
147
147
|
| Workspace filesystem | 本地 filesystem services 和 host paths | 适配 | 在 owner 基于 SQLite 的 Durable Object VFS 中保存 `/workspace`。 |
|
|
148
|
-
| Session persistence | `SessionPersistence` service、`PersistenceCoordinator` 及本地 JSONL/SQLite backends | 原生 backend 适配 | 复用上游 service 及 coordinator 的职责划分,在 Durable Object SQL 上实现存储原语,并使用上游 header/event 映射。一个 Edge 独有表会在透明休眠期间保留 empty session header,并在 canonical rows 物化时删除;Edge 不定义 turn 或 message schema。内部 coordinator helper 负责校验有界 replay loader,并在 disposal
|
|
149
|
-
| Settings and credentials | 基于文件的 settings、launch environment 和 credential services | 可写,使用 DO 存储 | 上游 `dsh-settings` 插件通过 `DurableObjectSettingsProvider` 把 user section 持久化到 Durable Object KV。上游 `dsh-llm-deepseek` cordis 插件直接安装,自动注册 `llm-deepseek` Settings 命名空间和可配置 Provider 条目;Settings → Models 页面可在运行时读取和修改 Provider 配置(base URL、model catalog、API key reference、reasoning effort),无需重新部署。`EdgeCredentialProvider` 先从 DO KV 解析凭证,然后降级到 Worker 环境变量 secret;`set`/`unset`
|
|
148
|
+
| Session persistence | `SessionPersistence` service、`PersistenceCoordinator` 及本地 JSONL/SQLite backends | 原生 backend 适配 | 复用上游 service 及 coordinator 的职责划分,在 Durable Object SQL 上实现存储原语,并使用上游 header/event 映射。一个 Edge 独有表会在透明休眠期间保留 empty session header,并在 canonical rows 物化时删除;Edge 不定义 turn 或 message schema。内部 coordinator helper 负责校验有界 replay loader,并在 disposal 前放弃失败且尚未物化的创建。它用上游自己的检查执行上游的存储契约:读取时拒绝本版本不认识且写入方未标记为 ignorable 的事件类型;以写方式打开时也会拒绝,并释放占用:每个会话的摘要行记录它已存的事件类型,由本来就会写这一行的追加更新,因此打开时只读一行(早期版本存储的会话,或之后被修复、迁移过的会话,会扫描一次并记录类型);追加时只存储已检查过的无损 JSON 快照,且必须接续已存日志;有界的 `read(offset, length)` 只选取所需的行,范围内无法解析的行按数据损坏报告。该契约有两处不同:已创建会话的 header 行在 create 时写入,而不是在第一次追加或 flush 时;空的已创建会话作为保留的 blank 保存,因此 flush 不会让它持久化。 |
|
|
149
|
+
| Settings and credentials | 基于文件的 settings、launch environment 和 credential services | 可写,使用 DO 存储 | 上游 `dsh-settings` 插件通过 `DurableObjectSettingsProvider` 把 user section 持久化到 Durable Object KV。上游 `dsh-llm-deepseek` cordis 插件直接安装,自动注册 `llm-deepseek` Settings 命名空间和可配置 Provider 条目;Settings → Models 页面可在运行时读取和修改 Provider 配置(base URL、model catalog、API key reference、reasoning effort),无需重新部署。`EdgeCredentialProvider` 先从 DO KV 解析凭证,然后降级到 Worker 环境变量 secret;`set`/`unset` 通过上游接缝持久化,并与上游的 provider 一样,把每次已保存的修改发布为 `credentials/reference-updated`,因此已打开的 Models 页面、模型菜单或网页搜索卡片无需刷新页面即可更新。部署默认值(maxTokens 256,000,reasoningEffort high)与上游插件对齐,未设置部署变量时与上游行为一致。 Settings → 内置插件还有一个“设置”标签页,提供上游的 Agent 循环和网页搜索两张卡片:Edge 注册它们的 `agent-loop`(并行工具调用数)和 `web-search-deepseek`(每次请求的搜索次数、接口地址,以及搜索使用的 DeepSeek Key)命名空间,把保存的值应用到正在运行的插件,并拒绝 `DEEPSEEK_SEARCH_BASE_URL` 同样会拒绝的接口地址。上游的 Shell 卡片编辑 `bash-sandbox` 命名空间,Edge 为自己的 bash 注册了它:命令超时默认取 `DSH_EDGE_DEFAULT_COMMAND_TIMEOUT_MS`,不能超过 `DSH_EDGE_MAX_COMMAND_TIMEOUT_MS`;单流输出上限(默认 64,000 字节,范围 1 KiB 到 1 MiB,因为每个流都要在内存中保留这么多)是输出转存前内联保留的尾部;两者都从下一条命令起生效,两种 shell 和 HTTP exec 路由都适用。上游的子 agent 卡片编辑子 agent 运行时的 `subagent` 命名空间:最大递归深度(默认 1)和常驻子 agent 的并行上限(默认 8);卡片的选模型部分编辑 `subagent-model-selection-settings`:与上游一样默认关闭;开启后,新会话会记录一次允许的模型(一条 `subagent/model-selection-policy` 事件),其 `subagent` 工具会多出 `list_subagent_models`,并可让子 agent 使用其中的模型运行。Edge 的会话在首次使用时恢复,所以 Edge 在尚未运行过 turn 的根会话上记录该设置,而上游在从未加种子的会话上记录。`subagent_fork` 的子 agent 沿用父 agent 的模型。上游承载这些卡片的插件管理器页面没有提供,因为它通过 Edge 没有的运行时 Loader 安装和卸载插件。 |
|
|
150
150
|
| Host boot and plugins | Node 命令行、Cordis profile loading、package resolution 和 HMR | 显式 Edge composition | 不在 Workerd 中运行本地 boot profile。部署前构建 immutable 客户端包,并排除 HMR 及 Edge `ApiProxy` 未暴露的 host domain。上游 `dsh-host-plugin-inventory` Remote 为 Settings → Plugins 提供数据;`EdgeLoader` 从实时插件 registry 投影带 fiber phase 的 `host:` 条目,并从 `expected-boot-graph.json` 投影 `web:` 条目。 |
|
|
151
151
|
| DSH transport | Typed HTTP RPC 加 mux/host WebSocket downlink | 复用并提供 Edge 服务端实现 | 对 unary method 使用上游 fetch carrier,并保留其 envelope、schema、projection、lazy blank-session 行为、有界内容搜索、prompt 与 queue mutation、workspace mutation、queue snapshot 和 event frame。两条 downlink 都由 Durable Object WebSocket 休眠机制持有;mux 重连会重放 live inbox 的待处理状态,REST/SSE 路由则保留为诊断兼容路径。 |
|
|
152
152
|
| Workspace registry | Storage-domain global state 加 `WorkspaceRecord` rows | 原生 backend 适配 | 保持上游 global 和 record value shape,包括手动 session 顺序与 archive membership;仅把物理 key 和原子写入映射到 Durable Object storage。Edge 把 registry 限制为一个原生 `/workspace` VFS;rename、delete、recreate 与 session reorder 保持上游 RPC 和 Host-frame 语义。 |
|
|
153
153
|
| Directory picker | `ctx.directoryPicker` seam,由 `dsh-host-directory-picker-auto` 在启动时选择 `-native` OS 选择器或 `-browse` 文件系统 backend,加 Web browse 对话框 | 复用并提供 Edge browse backend | 安装上游 seam,并把上游 `dsh-client-ui-directory-picker-browse` 对话框固定进 Web roster;Edge 从 `/workspace` Computer VFS 按每次一层回答 `browse` capability,以 `/workspace` 为根并沿用上游的 hidden、bound 与失败词汇,因此上游 `DirectoryPickerController` 提供 `directoryPicker/list` 与 `createDirectory`,并拒绝原生 `pick`。 |
|
|
154
154
|
| 对话文件链接 | `session/openWorkspacePath` 经 `dsh-native-command` 把点击的路径交给宿主桌面打开器;`session/canOpenWorkspacePath` 决定是否展示该入口 | 在上游 `SessionControllerInternals` seam 适配,加 Web 端下载回退 | 用 Edge internals 组合 `SessionController`,让原生探测返回 false、打开尝试以可读原因失败而不是 `child_process` 错误。V3 Web 客户端在右侧栏预览文件链接。Edge 将上游 `workspaceFiles` 控制器接入请求作用域内的 VFS 读取,支持有界文本/字节分页和元数据订阅。旧版 `ctx.remote.session.openWorkspacePath` 回退以及经 owner 鉴权的 `GET /api/workspace/file` 下载仍然可用。 |
|
|
155
155
|
| Existing Web UI | 运行时加载的 shell 和 `dsh.client` 插件 graph | 复用并采用通用 composition fallback | 把上游 shell 和受支持的上游客户端包组装成 Worker 静态资源;共享的 slot occupancy 规则会隐藏缺少 provider 的 action。Cloudflare 直接提供普通资源,`/`、`/login` 与 `/api/*` 则进入 Worker 执行 owner access control。组装后的 asset policy 会阻止所有直接或 SPA-fallback shell alias 被嵌入 frame。 |
|
|
156
|
-
| Other tools | Web Search、filesystem editor tools、MCP、skills、workflows、jobs 和 subagents | Search、文件、glob/grep、goal、todo、skill、subagent 和 MCP 工具已移植;workflow 与 run_code 已在 isolated 构建中移植 | 复用上游 DeepSeek Web Search 及其 30 秒 tool-call timeout。网页搜索卡片里的“Use the new Web Search API”开关(默认关闭)会把搜索和抓取切换到 DeepSeek Search and Fetch API(`dsh-web-deepseek-api`):页面由 DeepSeek 抓取,Worker 自己不读取任何第三方页面,也不产生辅助模型请求。它们使用 Models 页面保存的 DeepSeek API key(key 名称不能是其他 Edge 功能的凭据,设置里不接受明文 key),API 地址必须是不含凭据、查询或片段的 HTTP(S) URL,重定向会被拒绝,也不提供账号登录路径。Search and Fetch API 可能与模型 token 分开计费。上游 `workflow` 工具仅由 Dynamic Worker 运行时提供(isolated、Paid 计划构建);Direct 构建不注册该工具。由于 workerd 禁止在进程内使用 `eval`/`new Function`/`node:vm`,每次运行都会把脚本加载到独立的 Dynamic Worker 中执行,该 Worker 无出站网络,并受 30 秒 Worker Loader `cpuMs` 上限约束(由 Cloudflare 运行时强制执行,本地开发环境不执行);`agent()`、`phase()`、`log()` 经 RPC 桥回到 Durable Object,由其执行各项上限:同时最多运行 4 个子 agent(低于 Workers 六连接上限),单次运行最多启动 100 个子 agent,以限制子会话的行写入。同一运行时还提供上游的 `ralph` 工具(`dsh-tool-ralph`):它在前台循环启动全新的 `subagent` 子 agent,朝同一个目标推进,每一轮只把一份有大小上限的报告交给下一轮,直到某个子 agent 报告完成或遇到阻碍。与上游一样,它的提示词要求只在用户明确要求时使用。它运行在 workflow 引擎上,因此一次最多 100 轮(上游默认 256 轮);与 `workflow` 一样,PTC 模式预设不提供它。上游 `run_code` 工具(`dsh-tools` PTC 模式)由同一运行时提供,但只提供给以上游 `ptc` agent 预设(PTC 模式)开始的会话。isolated 部署沿用上游 id 提供该预设,因此 Web 客户端显示其内置的双语名称。该预设通过生成的 SDK 呈现全部工具,并与上游一样不提供 `workflow`,因为 `run_code` 是它唯一的编排方式。默认使用上游的 `standard` 预设(标准模式;以早先 `dsh-edge` id 记录的会话按 `standard` 读取),以原生方式呈现工具,并保留 `workflow`。与上游一致,Settings → Agent presets 写入 `agent-preset-registry` 设置命名空间的 `selectedDefault`,从可用预设中选择新会话的起始预设;早期版本保存在 `agent-presets` 下的默认值会在启动时迁移过来。在 PTC 模式下,每个程序先用 sucrase 去除类型,再在独立 Dynamic Worker 中运行,受 30 秒 `cpuMs` 上限约束且无出站网络;其中的 `tools.*` 调用经 RPC 桥回到 Durable Object,由其限制为每次运行最多 200 次(每次都是一次写入 session 事件的嵌套工具派发)、参数最多 256 KiB、单次结果最多 2 MiB
|
|
157
|
-
| Attachments | 本地 attachment storage、上游 image reference、composer、gallery、lightbox 与 provider conversion | 在原生 storage seam 上适配 | 原样复用上游 `AttachmentStore`、admission、协议、授权、UI 与 DeepSeek conversion
|
|
156
|
+
| Other tools | Web Search、filesystem editor tools、MCP、skills、workflows、jobs 和 subagents | Search、文件、glob/grep、goal、todo、skill、subagent 和 MCP 工具已移植;workflow 与 run_code 已在 isolated 构建中移植 | 复用上游 DeepSeek Web Search 及其 30 秒 tool-call timeout。网页搜索卡片里的“Use the new Web Search API”开关(默认关闭)会把搜索和抓取切换到 DeepSeek Search and Fetch API(`dsh-web-deepseek-api`):页面由 DeepSeek 抓取,Worker 自己不读取任何第三方页面,也不产生辅助模型请求。它们使用 Models 页面保存的 DeepSeek API key(key 名称不能是其他 Edge 功能的凭据,设置里不接受明文 key),API 地址必须是不含凭据、查询或片段的 HTTP(S) URL,重定向会被拒绝,也不提供账号登录路径。Search and Fetch API 可能与模型 token 分开计费。上游 `workflow` 工具仅由 Dynamic Worker 运行时提供(isolated、Paid 计划构建);Direct 构建不注册该工具。由于 workerd 禁止在进程内使用 `eval`/`new Function`/`node:vm`,每次运行都会把脚本加载到独立的 Dynamic Worker 中执行,该 Worker 无出站网络,并受 30 秒 Worker Loader `cpuMs` 上限约束(由 Cloudflare 运行时强制执行,本地开发环境不执行);`agent()`、`phase()`、`log()` 经 RPC 桥回到 Durable Object,由其执行各项上限:同时最多运行 4 个子 agent(低于 Workers 六连接上限),单次运行最多启动 100 个子 agent,以限制子会话的行写入。同一运行时还提供上游的 `ralph` 工具(`dsh-tool-ralph`):它在前台循环启动全新的 `subagent` 子 agent,朝同一个目标推进,每一轮只把一份有大小上限的报告交给下一轮,直到某个子 agent 报告完成或遇到阻碍。与上游一样,它的提示词要求只在用户明确要求时使用。它运行在 workflow 引擎上,因此一次最多 100 轮(上游默认 256 轮);与 `workflow` 一样,PTC 模式预设不提供它。上游 `run_code` 工具(`dsh-tools` PTC 模式)由同一运行时提供,但只提供给以上游 `ptc` agent 预设(PTC 模式)开始的会话。isolated 部署沿用上游 id 提供该预设,因此 Web 客户端显示其内置的双语名称。该预设通过生成的 SDK 呈现全部工具,并与上游一样不提供 `workflow`,因为 `run_code` 是它唯一的编排方式。默认使用上游的 `standard` 预设(标准模式;以早先 `dsh-edge` id 记录的会话按 `standard` 读取),以原生方式呈现工具,并保留 `workflow`。与上游一致,Settings → Agent presets 写入 `agent-preset-registry` 设置命名空间的 `selectedDefault`,从可用预设中选择新会话的起始预设;早期版本保存在 `agent-presets` 下的默认值会在启动时迁移过来。在 PTC 模式下,每个程序先用 sucrase 去除类型,再在独立 Dynamic Worker 中运行,受 30 秒 `cpuMs` 上限约束且无出站网络;其中的 `tools.*` 调用经 RPC 桥回到 Durable Object,由其限制为每次运行最多 200 次(每次都是一次写入 session 事件的嵌套工具派发)、参数最多 256 KiB、单次结果最多 2 MiB,嵌套调用仍走审批。与上游 Node 运行时描述自身环境一样,`run_code` 的描述会把这个环境和这些上限告诉模型。文件工具(read/write/edit/read_image)通过 `EdgeFileSystem` 适配 Computer VFS。`glob` 和 `grep` 保持上游 `dsh-tool-fs-search` 的工具名、参数结构、结果文本、搜索卡片,以及超过 100 条路径或 250 条匹配时把完整结果另存为文件;但 Workers 无法启动它所需的 ripgrep 程序,所以 Edge 在 VFS 上运行它们:两者都跳过版本控制元数据目录;`grep` 还跳过二进制文件和超过 4 MiB 的文件,并与上游 `grep` 沿用的 ripgrep 默认行为一致,跳过隐藏条目,以及 `.rgignore`、`.ignore` 和(在 git 仓库内的)`.gitignore` 文件排除的条目,且不进入被忽略的目录,因此一个很大的被忽略的 `node_modules` 只占一个条目(与 ripgrep 的 `--glob` 一致,`include` 匹配的文件即使被忽略或隐藏也会被搜索);`glob` 与上游一致(`--no-ignore --hidden`),会列出隐藏和被忽略的文件。ignore 规则按字符匹配,而 ripgrep 在 Unix 上按字节匹配 `?` 和字符类,所以像 `?` 这样的规则也会匹配只有一个非 ASCII 字符的文件名。不读取全局 gitignore 文件和 `.git/info/exclude`,超过 256 KiB 的 ignore 文件,或会让一次搜索编译的匹配器超过 5,000 个(每条规则一个,带 `{a,b}` 分组的规则按展开后的每个分支计,遍历期间都保留在内存中)的 ignore 文件不生效(预算按遍历顺序分配,所以预算用完后遇到的 ignore 文件即使优先级高于先前的 `.gitignore` 也会被跳过,而 ripgrep 会应用它);一次遍历若要测试 ignore 规则超过 5,000,000 次,会像超出条目上限一样失败。`grep` 的正则使用 RE2 语法(不支持环视和反向引用),由 re2js 以线性时间匹配,所以病态正则不会卡住 Durable Object。一次搜索最多遍历 20,000 个条目,`grep` 最多收集 20,000 行匹配或 20 MB 文本;超出上限时会失败,并提示缩小路径或模式。ripgrep 15 会拒绝的 glob 语法(未闭合的 `[` 或 `{`、`[z-a]` 这样的反向范围、末尾悬空的 `\`)会作为无效模式报错;`a{b,{c,d}}` 这样的嵌套分组可以使用。搜索在每次列出目录前后检查是否已取消,所以 30 秒的工具超时能中止耗时的遍历。与上游一致,文件观察策略(`dsh-fs-observation-policy`)为它们把关:`write` 不能覆盖本会话尚未读过的文件,`edit` 必须先读过目标文件,读取之后被改动过的文件(例如被 `bash` 或 Linux 容器改动)在重新读取之前会作为过期而失败;会话重启后不保留读取记录。Goal 工具(`ToolGoal`)作为上游 cordis 插件直接与 `GoalService` 组合。子 agent 沿用上游标准组合:`subagent` 启动一个全新的子 agent,`subagent_fork` 启动一个从父 agent 已完成的 turn 开始的子 agent(`dsh-subagent-spawn-in-process`、`dsh-subagent-fork-in-process`)。两者默认都在后台以可续接子 agent 运行,父 agent 用 `send_message` 继续它、用 `interrupt_agent` 停止它当前的 turn、用 `list_agents` 找到它(`dsh-tool-subagent-control`)。父 agent 的 turn 结束后子 agent 仍继续工作,它的结束消息会唤醒父 agent 再跑一个 turn;与上游一致,停止父 agent 不会停止正在运行的子 agent。未在运行的子 agent 收到消息时会从存储恢复,重启后也一样。上游 `todo_write` 工具(`dsh-tool-todo`)维护会话的任务列表,与上游的组合一样允许多个任务同时进行;它的 `todos` projection 驱动 Web 客户端的待办面板。上游 `present` 工具(`dsh-tool-present`)把工作区文件声明为本 turn 的交付物,Web 客户端将其显示为可在侧边栏预览的文件卡片;Edge 没有桌面,所以对卡片的 Host 检查(`/api/present.host`)回答不可用,卡片不提供用本机应用打开。与上游一样,`dsh-agent-instructions` 在第一次请求前,通过工作区 VFS 从项目根目录(最近一个包含 `.git` 的上级目录,没有则为会话工作目录)到工作目录逐级加载 `AGENTS.md` 和 `CLAUDE.md`(以及它们的 `.local.md` 覆盖文件),合成一条不超过 64 KiB 的基线消息;`read`、`write` 或 `edit` 进入更深的目录时,下一次请求会加入该目录的说明。Workers 没有用户主目录,所以用户全局文件是 `/.dsh/AGENTS.md` 和共享 agent 根目录下的 `/.agents/AGENTS.md`(Edge 自己设置 `DSH_HOME` 和 `DSH_AGENTS_HOME`,因为该插件只从这两个变量读取主目录)。`working_directory` 工具(`dsh-tool-working-directory`)读取会话的工作目录,或把它切换到一个已存在的目录;切换是一条持久化的 `working-directory/change` 事件,早于本版本的发布无法读取它,降级后无法打开已写入该事件的会话,Edge 始终把 `/workspace` 视为已存在的目录。Skill 工具通过 `SkillRegistry` 提供。与上游 `dsh-skill-filesystem` 一致,skill 是带 `name` 和 `description` frontmatter 的 `<name>/SKILL.md` 或 `<name>.md` 文件,位于项目的 `.dsh/skills`、`.agents/skills`,以及用户目录 `/.dsh/skills`、`/.agents/skills`(Workers 没有用户主目录),通过工作区 VFS 读取,每个目录最多读取 100 个条目,每个 skill 文件不超过 64 KiB;新增或修改的 skill 从下一个 turn 起生效,变更后打开的会话的 `/` 菜单也会列出它;与上游一致,Web 客户端在页面刷新前保留已打开会话的 `/` 列表。这个菜单由上游的会话 skill 目录(`skills/list`)应答,并带有每个 skill 的文件路径;Workers 没有文件监听,因此 Edge 在列出前重新检查该会话的 skill 根目录,并为它提供工作区文件元数据,因为常驻会话的工作目录检查要在 turn 之外读取这些元数据。通过 owner 接口 `GET/PUT/DELETE /api/skills` 存储的 skill(`EdgeSkillProvider`,DO KV)优先级低于它们。MCP 使用 Edge 自己的客户端(`edge-mcp-client.ts`;未挂载上游 `dsh-mcp-client`):仅支持 Streamable HTTP(Workers 上不可用 stdio),每次调用单独建立连接。probe 显示具备 `resources` 能力的服务器会注册到上游 `dsh-mcp-resources`;只要配置了一个这样的服务器,就会提供它的 `list_mcp_resources`、`list_mcp_resource_templates` 和 `read_mcp_resource` 工具(已有服务器需重新 probe 一次才会记录该能力);不具备 tools 能力的服务器 probe 后工具目录为空。资源调用与该连接器的只读工具一样遵循其工具权限,只有设为每次调用前询问时才会先询问。每个资源响应体限制为 1 MiB,传输中一旦超过就失败,因为 SDK 会整体解析响应,而读取结果(包括二进制数据)会保存在会话日志中;不带 cursor 的列表最多跟随 10 页或 1 MiB 的条目,并返回停下处的 cursor。与上游一致,二进制内容只以描述的形式交给模型。在 Settings → DSH Edge → MCP Servers 中配置服务器;工具名格式为 `mcp__<serverName>__<tool>`。逐个针对 Worker-compatible capabilities 增加其余工具,不宣称不可用的 host 行为。 |
|
|
157
|
+
| Attachments | 本地 attachment storage、上游 image reference、composer、gallery、lightbox 与 provider conversion | 在原生 storage seam 上适配 | 原样复用上游 `AttachmentStore`、admission、协议、授权、UI 与 DeepSeek conversion。不可变的图片字节(PNG 或 JPEG;图片优化为保留透明而转换时为 WebP)按 SHA-256 identity 存入新部署与 pre-attachment 部署使用的 64 MiB、按 512 KiB 分块的 DO backend,或存入已固定使用私有 R2 的部署的 R2;session event 只保留上游 ref。每个 owner instance 首次选择的 backend 会被固定,认领或升级不会让既有引用失联。图片为 PNG 或 JPEG,每张最多 3.5 MiB,每条消息最多 4 张。其他文件经上游上传路由流式写入,按上游 `files/<prefix>/<digest>/<name>` 布局原样保存在工作区 VFS 的 `/.dsh/attachments/v1` 下,每个最多 64 MiB(上传必须声明长度,超限的在写入任何字节前即被拒绝),告知模型的就是这个路径;模型的文件工具与轻量 shell 可在此读取,但路由到 Linux Container 的命令看不到这些文件。 |
|
|
158
158
|
| Goal tracking | `GoalService` 提供 create/edit/pause/resume/complete/clear mutation 与 GoalBar UI | 复用 | 作为 cordis 插件安装上游 `GoalService` 和 `ToolGoal`(直接组合)。浏览器 GoalBar mutation 通过 `TypertGatewayService` 路由到 `/api/goals/<method>`。`SessionProjectionCache` 在 DO 重启后持久化 goal 状态。上游的 `/goal` 命令(`dsh-command-goal`)可以查看、设定、编辑、暂停、恢复或清除会话的目标。每一轮目标都在 Edge 的 turn 内运行,带有工作区、时限和实时事件:上游的轮次驱动排入下一轮期间,turn 保持打开;在 turn 之外启用目标的调用(`/goal`、GoalBar 的恢复)在一个新的 turn 内运行。 |
|
|
159
159
|
| Context compaction | Token 计量、自动压缩和 session 标题生成 | 复用 | 直接安装上游 cordis 插件。上下文压缩、token 计量、工具结果修剪和自动 session 标题生成原样运行。上游的图片卸载(`dsh-compaction-image-offload`)在请求中的图片超出路由预算(默认每个请求 600 张)时让 turn 继续:它用一条 `image/offload` 会话事件把最早的图片标记为已卸载,然后重试请求。 |
|
|
160
160
|
| Session projection | 向已连接客户端实时推送派生状态 | 复用并添加 Edge bridge | 上游 `onChanged` 回调向已连接 WebSocket 客户端推送 title、model、goal 和会话统计 projection frame。上游 `dsh-session-stats`(整个会话的 turn 数和 step 数,以及模型、工具和首 token 耗时)为 Web 聊天视图提供数据。`SessionProjectionCache` 在 DO KV 中缓存 projection,用于冷 session 恢复。 |
|
|
@@ -295,7 +295,7 @@ npx dsh-edge upgrade
|
|
|
295
295
|
- **图片** 存入实例的 Durable Object(64 MiB),因此新安装无需配置 R2。每个部署都会记录 attachment-storage marker,更新时保留 marker 或 binding 指定的 backend。已使用私有 R2 的 Worker 会继续使用 R2;如果 R2 不再启用(Cloudflare 错误 `10042`),安装器提供账户专属的启用链接、重试或取消,绝不切换到会让图片引用失联的 backend。图片功能之前的 Worker 没有可失联的引用,会改用 Durable Object 默认值。Active rollout 混用 backend 时会拒绝猜测。
|
|
296
296
|
- **Owner access key** 在新实例上自动生成,并在安装完成时显示。如需自定义,请在安装器环境中设置 `DSH_EDGE_ACCESS_KEY`(32–512 个 UTF-8 字节);它不会进入 shell 历史或进程列表。普通更新会保留现有 key。Cloudflare 无法再次显示已存的 key,所以丢失时请按部署所在的发布渠道运行升级命令,并选择 **Update and reset the access key**:稳定版运行 `npx dsh-edge upgrade`;已安装版本包含 `-alpha` 或 `-rc` 时运行 `npx dsh-edge@next upgrade`(登录页会显示适用于该部署的命令)。安装器会用新 key(自动生成,或取自 `DSH_EDGE_ACCESS_KEY`)部署该版本,并只显示一次。对话、文件与 DeepSeek key 均保留;旧 key 随即失效,所有已登录的浏览器都需要用新 key 重新登录。
|
|
297
297
|
- **DeepSeek API key** 在安装完成后于 Settings → Models 中添加。安装器不会询问它。
|
|
298
|
-
- **图片优化**(Cloudflare Images binding
|
|
298
|
+
- **图片优化**(Cloudflare Images binding)对你自己的账户开启,对临时账户关闭。开启后,超过上游 2048 × 2048 像素预算或 4 MiB 的图片、WebP 或 GIF、以及带旋转方向的 JPEG,会按上游的方式规范化(缩小、转正、取第一帧、转为 JPEG 或 WebP);已经符合要求的 PNG 或 JPEG 按原样保存,不产生费用。Cloudflare 每个月对同一张图的处理只计一次:每月前 5,000 次免费,之后免费计划会拒绝新的处理,付费计划按量计费。Images 拒绝或失败时,未超出无 Images 时限制的图片按原样保存,更大的图片会被拒绝并说明原因。Worker 自己从不解码这类图片:一张 8,192 像素的位图放不进它的内存。
|
|
299
299
|
|
|
300
300
|
### Credential 交接与激活
|
|
301
301
|
|
|
@@ -324,7 +324,8 @@ pnpm --filter dsh-edge example:install
|
|
|
324
324
|
- Web client 使用 session list/search/create/history/models/select/prompt/updateQueue/rename/fork/cancel;host description;Workspace list/create/rename/delete/reorder/archive;skills;agent presets;settings 与 credential description;以及 LLM catalog。
|
|
325
325
|
- `agentPreset.read` 通过上游只读 viewer 渲染程序化 Edge composition。`credentials.describe` 返回不含 value 的 credential state。
|
|
326
326
|
- Search 投影 canonical current-message surface,并返回有界的上游 result value。
|
|
327
|
-
- Fork
|
|
327
|
+
- Fork 与上游 session controller 一致:`atSeq` 是包含在内的精确切点(不存在的事件会被拒绝),省略时选最近的完整回合前缀,并由上游的 `buildForkSeed` 标记切点、把未结束的回合以 forked 收尾;fork 保留 parent lineage。对已存的源会话,Edge 只读到切点为止,并拒绝超过 8,192 个事件或 8 MiB 的 seed,不会物化无界 history。`allowMigration` 会被接受;Edge 在 Durable Object 启动时已迁移所有已存会话,因此 fork 不会遇到仍需迁移的会话。
|
|
328
|
+
- 改名通过上游的 `sessionTitle.rename` 进行,它会同时停止仍在运行的自动标题生成,因此晚到的自动标题不会覆盖用户设置的标题。
|
|
328
329
|
- Queue mutation 通过 live upstream Agent inbox 编辑、移除或提升条目。同步 mutation 是接纳点;后续 write-behind 与 retirement retry 由 persistence coordinator 负责。
|
|
329
330
|
- Workspace mutation 通过 Durable Object backend 持久化上游 workspace-domain global 与 record shape。Archive 保留 session log 与 Workspace slot;unary response 与 Host frame 携带和上游一致的完整 snapshot。
|
|
330
331
|
- Goal mutation(create、edit、pause、resume、complete、clear)通过 `TypertGatewayService` 路由到 `/api/goals/<method>`。每个 `@Remote` Service 需要通过 `ctx.typert.register()` 注册其 Typert 描述符;不需要编写 per-method HTTP handler。
|
|
@@ -360,7 +361,7 @@ SQLite 的 `DELETE` 操作也会消耗每日行写入额度。迁移格式时,
|
|
|
360
361
|
- Session 创建与 fork 在发布成功但 Workspace attachment 失败时返回 `session/workspace-attach-failed`,并携带已发布的 session 与 Workspace id。诊断路由返回相同 code 及完整的已创建 session。
|
|
361
362
|
- Prompt 和 queue-edit 文本共用 64 KiB 语义上限。10 MiB RPC 载体为 7 MiB 原始图片在 base64 与 envelope 膨胀后留出空间。
|
|
362
363
|
- Edge 没有目录流 provider,因此上游浏览器会在仅剩一个 Workspace 时隐藏 Delete,并在仍有恢复路径时重新显示。
|
|
363
|
-
- `@file` 补全通过 Computer VFS 为上游 `fileReferences/list` Remote
|
|
364
|
+
- `@file` 补全通过 Computer VFS 为上游 `fileReferences/list` Remote 提供服务,行为与上游本地 provider(`dsh-file-reference-local`)一致:带 `/` 的查询列出那个目录,可以相对会话工作目录,也可以是工作目录内的绝对路径;裸片段在工作目录的递归索引上模糊排序(依次是完全相同、前缀、包含的文件名,然后是包含于路径和按顺序的子序列,因此 `rdm` 能找到 `docs/README.md`)。索引跳过上游排除的目录(`.git`、`node_modules`、`dist`、`build` 以及其他依赖和构建输出目录),最多保存 10,000 个条目、共 1,000,000 个路径字符,而上游是 50,000 个条目,因为每次列目录都会读取 Durable Object 的行:读取索引大约每个条目 3.5 行。同一工作目录的会话共用一份索引,最多保留 4 个工作目录的索引,最久未查询的先被丢弃。只有第一次裸查询需要等待索引;与上游一样,任一会话的工具返回结果后(各会话共用一个工作区)索引变为过期,下一次裸查询先用它回答,同时读取替换的索引。与上游的索引一样,工具之外的文件变更(属主 API 写入、上传)要到下一次工具返回结果后才会进入索引;带 `/` 的查询始终实时读取目录。`@session` 提及及其 pre-step 快照原样来自上游 session-reference 服务;它的候选发现以及任一 agent 作用域 Remote 都会通过上游 controller 恢复冷 session,并使其常驻直到 Durable Object 被驱逐。
|
|
364
365
|
|
|
365
366
|
### 限制与请求准入
|
|
366
367
|
|
|
@@ -373,12 +374,13 @@ SQLite 的 `DELETE` 操作也会消耗每日行写入额度。迁移格式时,
|
|
|
373
374
|
| Session-create JSON body | 8 KiB |
|
|
374
375
|
| Workspace-exec JSON body | 128 KiB |
|
|
375
376
|
| 承载消息的 turn 或 queue-update RPC | 10 MiB |
|
|
376
|
-
|
|
|
377
|
+
| 图片,开启图片优化(Cloudflare Images binding)时 | PNG、JPEG、WebP 和 GIF(取第一帧);每条消息 8 张;每张及合计 7 MiB,即 10 MiB 消息体经 base64 后能容纳的大小;6,400 万像素;单边 8,192 px;存储时缩到上游的 2048 × 2048 像素预算和 4 MiB 以内 |
|
|
378
|
+
| 图片,未开启时 | PNG/JPEG;每条消息 4 张;每张 3.5 MiB;合计 7 MiB;4,000 万像素;单边 2,000 px |
|
|
377
379
|
|
|
378
380
|
- Request body 会增量消费。一旦越过路由上限,后续 chunk 只会排空而不会保留,路由返回 413。文件上传也会拒绝非法 UTF-8。
|
|
379
381
|
- 读取文件时先检查 VFS metadata,再通过相同的 1 MiB 上限收集已打开的 byte stream,从而关闭 `stat()` 与 `readFile()` 之间的增长竞态,且不保留无界值。
|
|
380
382
|
- 写入前,图片准入会完整解码声明的 raster 格式。
|
|
381
|
-
- 与上游 `bash-local` 一致,输出超过上限后命令会继续运行:每个流内联保留最后 64,000 字节(默认值,即 Shell 卡片的输出上限,可设为 1 KiB 到 1 MiB),整个流保存到 `/workspace/.spill/bash-<execution>.<stream>.txt`(与其他 spill 一样 30 天后删除),每个流最多 16 MiB(上游允许 64 MiB;每 512 KiB 约写 5 行 Durable Object 数据,且工作区存储不会释放已删除的字节,#358),超过后文件只保留开头部分,结果中会注明。内存只占尾部加每个流 1 MiB 的写入队列:写 spill 时会暂停读取命令输出。未超过上限的输出不写任何文件。轻量 shell(just-bash)一次性返回命令的完整输出而不是流式输出,所以输出超过 8 MiB 时仍会停止命令(exit 126,显示为 `[stopped: …]`);这块缓冲位于它所在的 isolate 中,Direct 模式下就是 Durable Object。bash 工具按上游格式呈现结果:stdout、`[stderr]` 段、每个流的 `[output truncated; full output: <path>]`、`[timed out after Nms]`,最后是 `[exit code: N]
|
|
383
|
+
- 与上游 `bash-local` 一致,输出超过上限后命令会继续运行:每个流内联保留最后 64,000 字节(默认值,即 Shell 卡片的输出上限,可设为 1 KiB 到 1 MiB),整个流保存到 `/workspace/.spill/bash-<execution>.<stream>.txt`(与其他 spill 一样 30 天后删除),每个流最多 16 MiB(上游允许 64 MiB;每 512 KiB 约写 5 行 Durable Object 数据,且工作区存储不会释放已删除的字节,#358),超过后文件只保留开头部分,结果中会注明。内存只占尾部加每个流 1 MiB 的写入队列:写 spill 时会暂停读取命令输出。未超过上限的输出不写任何文件。轻量 shell(just-bash)一次性返回命令的完整输出而不是流式输出,所以输出超过 8 MiB 时仍会停止命令(exit 126,显示为 `[stopped: …]`);这块缓冲位于它所在的 isolate 中,Direct 模式下就是 Durable Object。bash 工具按上游格式呈现结果:stdout、`[stderr]` 段、每个流的 `[output truncated; full output: <path>]`、`[timed out after Nms]`,最后是 `[exit code: N]`;终端卡片会显示工作目录。在 Linux Container 中,命令退出后才到达 computerd 的输出会让容器停止:computerd 0.3.1 遇到这种输出会抛出异常并退出,所以在 Cloudflare 上,一条输出几百 KB、且输出速度快于 Durable Object 读取速度的命令通常会以内部错误失败,容器随后重启。修复要等包含 cloudflare/computer#260 的 Computer 版本(#373)。超过部署上限的 `timeoutMs` 会像上游一样被降到上限;HTTP exec 路由仍会拒绝它。`cancelled` 反映 adapter 请求的中断;`timedOut` 独立记录 deadline expiry。
|
|
382
384
|
|
|
383
385
|
### 持久性与并发
|
|
384
386
|
|
package/package.json
CHANGED