dsh-edge 0.3.0-alpha.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +174 -34
- package/README.zh.md +174 -34
- package/package.json +1 -1
- package/scripts/cli.mjs +53 -1
- package/scripts/install.d.mts +9 -3
- package/scripts/install.mjs +131 -22
- package/worker/direct/index.js +81 -81
- package/worker/isolated/index.js +43 -43
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: f341a64cd11e666f6bc70c18635b0e7212eb5a50
|
|
6
|
+
README.zh.md: fea9635e544b436cadb2bf33159ae1b8ca866938
|
package/README.md
CHANGED
|
@@ -8,9 +8,29 @@ English | [中文](README.zh.md)
|
|
|
8
8
|
|
|
9
9
|
The checked-in Wrangler configuration exposes two deployment targets from the same application graph. The default target is direct mode for Workers Free and has no Worker Loader binding. The named `isolated` target adds the `LOADER` binding and requires Workers Paid, but does not fork the DSH protocol, storage, UI, or tool implementation.
|
|
10
10
|
|
|
11
|
-
The runtime
|
|
11
|
+
The runtime keeps upstream ownership clear:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- `ReactLoopAgent`, `AgentRegistry`, `LlmRuntime`, `ToolRuntime`, `SystemPrompt`, `SessionStore`, and `SessionPersistence` run through the upstream Cordis composition.
|
|
14
|
+
- Edge binds a request-scoped DeepSeek adapter and maps the native DSH `bash` tool onto Cloudflare Computer.
|
|
15
|
+
- Durable Object SQLite implements the upstream persistence backend contract. `PersistenceCoordinator` still owns write-behind, revisions, resume preparation, and crash recovery.
|
|
16
|
+
- Model history is projected from canonical events rather than persisted in a second Edge schema.
|
|
17
|
+
|
|
18
|
+
The browser also remains upstream-owned:
|
|
19
|
+
|
|
20
|
+
- A build-time assembler derives the Web roster from upstream configs, injects the standard `window.__DSH_BOOT__` graph, and emits Cloudflare static assets.
|
|
21
|
+
- The Durable Object implements supported upstream `ApiProxy` methods through the standard HTTP carrier and supplies both downlinks as hibernatable WebSockets.
|
|
22
|
+
- The image composer, gallery, lightbox, attachment wire contract, and DeepSeek serializer are reused unchanged.
|
|
23
|
+
- The storage seam chooses private R2 for new permanent deployments, bounded Durable Object storage for temporary deployments, and a one-time owner choice for pre-0.3 Workers.
|
|
24
|
+
- Client plugins whose host domains are unavailable are excluded instead of forked. Session-log export and optional local-host plugins remain unavailable.
|
|
25
|
+
- A small Edge-owned login shell protects the upstream UI and protocol without changing either one.
|
|
26
|
+
|
|
27
|
+
## Find what you need
|
|
28
|
+
|
|
29
|
+
- [Install or upgrade on Cloudflare](#install-on-cloudflare)
|
|
30
|
+
- [Compare native, adapted, and unavailable capabilities](#cloudflare-compatibility-matrix)
|
|
31
|
+
- [Configure DeepSeek credentials, models, timeouts, and owner authentication](#api-key-boundary)
|
|
32
|
+
- [Run the release runtime locally](#run-locally)
|
|
33
|
+
- [Inspect routes, limits, and durability behavior](#edge-api)
|
|
14
34
|
|
|
15
35
|
## Run locally
|
|
16
36
|
|
|
@@ -70,13 +90,15 @@ curl -b /tmp/dsh-edge-cookie -N -X POST -H 'content-type: application/json' \
|
|
|
70
90
|
http://localhost:8787/api/sessions/SESSION_ID/turn
|
|
71
91
|
```
|
|
72
92
|
|
|
73
|
-
The
|
|
74
|
-
|
|
75
|
-
Session listing is also bounded: `GET /api/sessions?after=SESSION_ID&limit=COUNT` defaults to 50 summaries, accepts at most 100, and returns `hasMore` plus `nextAfter` in the JSON body. The Durable Object derives titles and latest timestamps from canonical rows without loading each session log. The upstream Web session list additionally includes retained blank headers that have no canonical event yet.
|
|
76
|
-
|
|
77
|
-
The upstream `session.history` browser RPC uses one Edge admission budget before live and cold paths diverge: every request is capped at the browser's 50-message page size. Cold logs apply that boundary in Durable Object SQL before decoding payloads and validate the selected contiguous window under 8,192-event and 8 MiB stored-payload ceilings. Live logs locate the same boundary without first copying the complete in-memory window, then enforce the same event ceiling and an 8 MiB encoded-response ceiling. An over-budget window is refused instead of truncated. Model-directory, model-selection, and turn-admission existence checks use header point reads; only a turn that must resume the agent decodes canonical history.
|
|
93
|
+
The diagnostic session APIs preserve upstream events while bounding every read:
|
|
78
94
|
|
|
79
|
-
|
|
95
|
+
- A turn streams upstream `SessionEvent` values directly as SSE, including inbox splices, assistant chunks/messages, tool calls/results, and turn/step boundaries.
|
|
96
|
+
- A live stream queues at most 1 MiB per client. A slower reader is disconnected without cancelling the turn or its persistence.
|
|
97
|
+
- Session detail returns bounded metadata. Event replay defaults to 128 events, accepts at most 256, preflights stored bytes, retains at most 1 MiB of encoded SSE, and exposes continuation headers.
|
|
98
|
+
- Session listing defaults to 50 summaries and accepts at most 100. The Durable Object derives titles and timestamps from canonical rows without loading each log; upstream Web also receives retained blank headers.
|
|
99
|
+
- Browser history is capped at 50 messages and refuses, rather than truncates, windows above 8,192 events or 8 MiB. Cold paths apply the boundary in SQL; live paths locate it without copying the complete in-memory log.
|
|
100
|
+
- Sidebar search uses canonical current user/assistant messages without a second index or wire format. It examines at most 32 recent sessions, requires complete logs of at most 512 events and 256 KiB when cold, and returns at most 20 snippets with `hasMore` when a bound is reached.
|
|
101
|
+
- Model lookup and selection use header point reads. Only a turn that resumes the agent decodes canonical history.
|
|
80
102
|
|
|
81
103
|
Every authenticated request uses the deployment's fixed `owner` Durable Object. The legacy `x-dsh-edge-instance` header and `instance` query parameter are rejected rather than treated as identities. `/api/sessions/SESSION_ID/turn` continues the stored canonical history.
|
|
82
104
|
|
|
@@ -93,13 +115,13 @@ This reference separates code that runs natively in Workers, code adapted at an
|
|
|
93
115
|
| 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. |
|
|
94
116
|
| Workspace filesystem | Local filesystem services and host paths | Adapted | Store `/workspace` in the owner's SQLite-backed Durable Object VFS. |
|
|
95
117
|
| 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. |
|
|
96
|
-
| Settings and credentials | File-backed settings, launch environment, and credential services | Read-only edge projection | Resolve the Worker secret per operation; never persist or return the literal key. Blank secrets are unconfigured, while surrounding whitespace is removed before use. `credentials.describe` reports only whether `DEEPSEEK_API_KEY` is configured and that its read-only source is `worker-secret`. The built-in `dsh-edge` preset projects its effective release, shell/VFS, model, limits, credential state, prompt, and tools through the upstream read-only composition viewer. Writable settings and authenticated per-user secret storage remain open. |
|
|
118
|
+
| Settings and credentials | File-backed settings, launch environment, and credential services | Read-only edge projection | Resolve the Worker secret per operation; never persist or return the literal key. Blank secrets are unconfigured, while surrounding whitespace is removed before use. `credentials.describe` reports only whether `DEEPSEEK_API_KEY` is configured and that its read-only source is `worker-secret`. The built-in `dsh-edge` preset projects its effective release, shell/VFS, deployment-default model, runtime-derived upstream model catalog, per-session selection scope, limits, credential state, prompt, and tools through the upstream read-only composition viewer. Writable settings and authenticated per-user secret storage remain open. |
|
|
97
119
|
| 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. |
|
|
98
120
|
| 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. |
|
|
99
121
|
| 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. |
|
|
100
122
|
| 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. |
|
|
101
123
|
| Other tools | Web Search, filesystem editor tools, MCP, skills, workflows, jobs, and subagents | Search ported; others not ported | Reuse upstream DeepSeek Web Search with its 30-second tool-call timeout. Add the remaining tools individually against Worker-compatible capabilities; do not advertise unavailable host behavior. |
|
|
102
|
-
| 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/JPEG bytes under their SHA-256 identities in private R2 for new permanent deployments or in a 64 MiB, 512 KiB-chunked DO
|
|
124
|
+
| 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/JPEG bytes under their SHA-256 identities in private R2 for new permanent deployments or in a 64 MiB, 512 KiB-chunked DO backend for temporary deployments and owners who select it while upgrading a pre-attachment Worker; session events retain only upstream refs. The first backend is pinned per owner instance so claiming or upgrading cannot strand existing references. |
|
|
103
125
|
| Authentication and tenancy | Local trusted-user boundary | Single-owner adaptation | Require one high-entropy Worker secret, exchange it for a signed 30-day HttpOnly `SameSite=Strict` cookie, and route every accepted request to one fixed owner object. This intentionally provides no registration, user database, roles, or multi-tenant routing. |
|
|
104
126
|
|
|
105
127
|
The browser request path is:
|
|
@@ -109,7 +131,7 @@ Cloudflare static assets -> upstream Web shell + client plugin graph
|
|
|
109
131
|
-> POST /api/session.create through the upstream HTTP carrier
|
|
110
132
|
-> host/workspace-changed + session/subscribed over Durable Object WebSockets
|
|
111
133
|
-> POST /api/session.prompt with the client rpcId
|
|
112
|
-
-> upstream image admission validates and stores immutable bytes in
|
|
134
|
+
-> upstream image admission validates and stores immutable bytes in the selected R2 or DO backend
|
|
113
135
|
-> canonical session events retain upstream sha256 attachment refs only
|
|
114
136
|
-> AgentRegistry live lookup or resume
|
|
115
137
|
-> sessionPersistence.prepare through PersistenceCoordinator on cold resume
|
|
@@ -131,23 +153,63 @@ Cloudflare static assets -> upstream Web shell + client plugin graph
|
|
|
131
153
|
-> upstream Web runtime reconciles and renders the canonical events
|
|
132
154
|
```
|
|
133
155
|
|
|
134
|
-
The local integration
|
|
156
|
+
The local integration suite uses an SSE stand-in with real Wrangler, Durable Object SQLite, local R2, the Direct Computer workspace backend, static assets, the HTTP carrier, and WebSockets. Direct mode exercises DO attachment storage; Isolated mode exercises private R2. Together they verify:
|
|
157
|
+
|
|
158
|
+
- owner login, API/WebSocket cookie enforcement, legacy-selector rejection, and disabled Direct-shell networking;
|
|
159
|
+
- upstream session create/list/history/search/prompt/rename/fork and queue edit/remove/steering flows;
|
|
160
|
+
- image admission through the upstream composer, protocol, provider, authorization, fork reuse, and restart persistence;
|
|
161
|
+
- Workspace create/list/rename/delete/reorder/archive, live/reconnect baselines, and Host frames;
|
|
162
|
+
- real browser boot, UI-issued Workspace rename, image turn, content search, branch, archive, and expired-session login recovery;
|
|
163
|
+
- conversation continuity, event replay, two-step bash and Web Search tool exchanges, and Wrangler-restart restoration.
|
|
164
|
+
|
|
165
|
+
A focused failure test proves that post-enqueue durability failure blocks model use without reporting the already-woken prompt as rejected. Committed model-visible and ARIA goldens pin tool transcripts and the assembled upstream Web client. A live DeepSeek call requires the developer's key and is intentionally outside the repository test suite.
|
|
135
166
|
|
|
136
167
|
## API-key boundary
|
|
137
168
|
|
|
138
|
-
`DEEPSEEK_API_KEY` from `.dev.vars` is the local credential source. A read-only Edge provider exposes
|
|
169
|
+
`DEEPSEEK_API_KEY` from `.dev.vars` is the local credential source. A read-only Edge provider exposes it through upstream `ctx.credentials` for each chat or search operation without writing the value to Durable Object storage, the VFS, session events, or responses. Surrounding whitespace is removed; a blank value is unconfigured.
|
|
170
|
+
|
|
171
|
+
| Variable | Purpose and validation |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `DEEPSEEK_BASE_URL` | Chat endpoint. Must be HTTP(S) without URL userinfo. The browser projection omits query and fragment components that may carry gateway credentials. |
|
|
174
|
+
| `DEEPSEEK_SEARCH_BASE_URL` | Anthropic-compatible Messages endpoint for native Web Search. Defaults to `https://api.deepseek.com/anthropic/v1`; must be HTTP(S) without userinfo, query, or fragment. Search does not follow redirects. |
|
|
175
|
+
| `DEEPSEEK_MODEL` | Validated deployment default; defaults to `deepseek-v4-flash`. Each session may choose another upstream catalog entry. |
|
|
176
|
+
| `DEEPSEEK_REASONING_EFFORT` | `off`, `low`, `high`, or `max`; defaults to `off`. |
|
|
177
|
+
| `DEEPSEEK_MAX_OUTPUT_TOKENS` | Optional positive safe integer overriding the 8,192-token chat default. |
|
|
178
|
+
| `DEEPSEEK_STREAM_IDLE_TIMEOUT_MS` | Optional positive integer up to 2,147,483,647; defaults to 120,000 ms. |
|
|
179
|
+
| `DSH_EDGE_DEFAULT_COMMAND_TIMEOUT_MS` | Default Computer command timeout; defaults to 120,000 ms. |
|
|
180
|
+
| `DSH_EDGE_MAX_COMMAND_TIMEOUT_MS` | Caller-selectable timeout ceiling; defaults to 120,000 ms and cannot be lower than the default. |
|
|
139
181
|
|
|
140
|
-
|
|
182
|
+
Invalid deployment configuration fails before session lookup or SSE response creation. Edge mounts upstream `web_search` with a 30-second tool-call timeout and structured results. `web_fetch` remains disabled because the runtime has no arbitrary-URL network policy.
|
|
141
183
|
|
|
142
|
-
|
|
184
|
+
### Owner authentication
|
|
185
|
+
|
|
186
|
+
- `DSH_EDGE_ACCESS_KEY` is the single-owner boundary. It must contain 32–512 UTF-8 bytes without surrounding whitespace or control characters; generate a random value instead of reusing a human password.
|
|
187
|
+
- Login creates a signed 30-day HttpOnly `SameSite=Strict` cookie. HTTPS uses the host-only `__Host-dsh_edge_owner` name with `Secure`; local HTTP uses an unprefixed cookie.
|
|
188
|
+
- The cookie carries no user data, is never forwarded to the Durable Object, and becomes invalid when the access key rotates.
|
|
189
|
+
- Unauthenticated API and WebSocket requests return 401. Only an owner-authentication 401 carrying `WWW-Authenticate: DshEdgeOwner` makes the same-origin shell navigate to `/login`; provider/configuration 401 diagnostics remain visible.
|
|
190
|
+
- Authenticated browser API and WebSocket requests from another origin return 403 even with a same-site cookie.
|
|
191
|
+
- The asset policy prevents framing through `/`, `/index.html`, or an SPA fallback. `/` redirects to `/login`; `/api/health` and immutable assets remain public.
|
|
192
|
+
|
|
193
|
+
This deliberately is not an account system or multi-tenant boundary.
|
|
143
194
|
|
|
144
195
|
## Install on Cloudflare
|
|
145
196
|
|
|
146
|
-
|
|
197
|
+
| Target | Cloudflare requirement | Command boundary | Health identifier |
|
|
198
|
+
| --- | --- | --- | --- |
|
|
199
|
+
| Direct (default top level) | Workers Free; no Loader binding | Hardened just-bash in the agent/VFS Durable Object, with explicit timeouts, bounded output/environment, and no network command | `just-bash-direct` |
|
|
200
|
+
| `env.isolated` | Workers Paid with `LOADER` | Computer Worker Shell in a separate Dynamic Worker | `just-bash-isolated` |
|
|
147
201
|
|
|
148
|
-
|
|
202
|
+
Direct mode is lighter isolation than a separate Worker; do not expose the single-owner deployment to untrusted users. Workers Paid is a Workers subscription starting at $5 per month, not the Cloudflare Pro website plan. Worker names have independent Durable Object storage and secrets, so use different names when both modes should remain live.
|
|
149
203
|
|
|
150
|
-
`wrangler.jsonc` remains the
|
|
204
|
+
`wrangler.jsonc` remains the canonical source for both modes:
|
|
205
|
+
|
|
206
|
+
- Release packaging builds one tested, minified artifact per mode.
|
|
207
|
+
- Direct replaces only Computer's unreachable Dynamic Worker shell-core module; its Workspace adapter and command exports remain upstream.
|
|
208
|
+
- Isolated preserves that shell core and replaces the unreachable Direct backend with a fail-closed module. Each artifact therefore carries only its selected command runtime.
|
|
209
|
+
- The installer generates a private mode-specific config, points it at the selected artifact, and uploads with `no_bundle`. The user's machine does not rebuild dsh-edge or resolve Harness packages into a new Worker.
|
|
210
|
+
- CI starts the Direct artifact from an installed tarball and rejects gzip output above 900 KiB, preserving headroom below the 1 MiB anonymous temporary-account limit.
|
|
211
|
+
|
|
212
|
+
### Install and upgrade
|
|
151
213
|
|
|
152
214
|
Run the stable installer without cloning this repository:
|
|
153
215
|
|
|
@@ -155,7 +217,7 @@ Run the stable installer without cloning this repository:
|
|
|
155
217
|
npx dsh-edge install
|
|
156
218
|
```
|
|
157
219
|
|
|
158
|
-
This resolves through npm's `latest` channel. Use `npx dsh-edge@next install` to
|
|
220
|
+
This resolves through npm's `latest` channel. Use `npx dsh-edge@next install` only to opt into a newer prerelease when one is available.
|
|
159
221
|
|
|
160
222
|
Upgrade an existing named Worker with the same runtime choice. The deployment keeps its Durable Object data; because Cloudflare secrets are write-only, the upgrade asks for the owner access key and DeepSeek API key again and replaces their active values:
|
|
161
223
|
|
|
@@ -165,13 +227,32 @@ For a stable deployment, run:
|
|
|
165
227
|
npx dsh-edge upgrade
|
|
166
228
|
```
|
|
167
229
|
|
|
168
|
-
If the installed version
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
230
|
+
If the installed version contains `-alpha` or `-rc`, promote it to the stable channel once with `npx dsh-edge@latest upgrade`. The Edge settings page derives its command from the installed version; without that explicit `@latest` command, an existing prerelease remains on `next`.
|
|
231
|
+
|
|
232
|
+
### Accounts and attachment storage
|
|
233
|
+
|
|
234
|
+
- The installer asks for the runtime before the account.
|
|
235
|
+
- Recommended `Free — Direct Shell` works on Workers Free with a detected account, a new sign-in/registration, or a temporary account without login.
|
|
236
|
+
- `Isolated — Dynamic Worker` requires Workers Paid and offers only a detected or newly authenticated account. Cloudflare authorizes the Loader upload; rejection becomes a choice between enabling Workers Paid and switching to Direct mode.
|
|
237
|
+
- New permanent installs create or reuse a private `<worker-name>-attachments` R2 bucket and place only its binding in the generated private Wrangler config. Deployment failure never deletes the bucket.
|
|
238
|
+
- R2 Standard has an included monthly free tier, but the account must enable its separate usage-based subscription. The installer checks R2 before collecting Worker secrets.
|
|
239
|
+
- Cloudflare error `10042` offers account-specific activation, retry, and cancellation. Only an unmarked pre-attachment Worker may safely switch to DO storage; a new or R2-pinned deployment cannot switch and strand references.
|
|
240
|
+
- Temporary accounts use the same image UI with a 64 MiB DO backend. Claiming preserves that backend and history; automatic R2 migration is not implemented.
|
|
241
|
+
- Every new deployment records its attachment-storage marker. Upgrades inspect every active version and preserve the marked or bound backend.
|
|
242
|
+
- A pre-image Worker has no marker, binding, or image references, so its first 0.3 upgrade asks once between 64 MiB DO storage and private R2, then pins the choice. Mixed active rollouts are refused rather than guessed.
|
|
243
|
+
|
|
244
|
+
### Credential handoff and activation
|
|
245
|
+
|
|
246
|
+
- The remaining prompts select a Worker name, generate or accept the owner access key, collect the DeepSeek key through hidden input, and show a final cost summary. Temporary installs also require explicit acceptance of Cloudflare's terms and privacy policy.
|
|
247
|
+
- Existing Workers are never overwritten without confirmation.
|
|
248
|
+
- Both credentials travel through a mode-`0600` temporary secrets file. Wrangler receives only an allowlisted runtime environment and the selected Cloudflare authentication; unrelated ambient secrets and Node injection options do not reach the child.
|
|
249
|
+
- The secret file is removed after the command. Wrangler's structured output supplies the deployed URL. Add `--verbose` to inspect full deployment diagnostics.
|
|
250
|
+
- After upload, the installer observes public `/api/health` for up to 45 seconds without credentials or redirects. Only the exact package version and selected runtime produce a ready card; propagation, challenge, placeholder, transport, and older-release responses remain pending.
|
|
251
|
+
- Observation expiry exits successfully and asks the owner to refresh shortly. It never calls DeepSeek or touches Durable Object state.
|
|
252
|
+
- The final card prints the URL, active owner key, and next steps. Temporary accounts also receive a bearer claim URL that must be claimed within 60 minutes.
|
|
253
|
+
- A rejected upload is reported as not installed. If Wrangler created a temporary account, its claim URL is still shown without presenting the unused owner key as active.
|
|
254
|
+
- If upload succeeds but handoff fails, a recovery card prints the active owner key and all known URLs before the command exits unsuccessfully.
|
|
255
|
+
- Installation uploads directly through Wrangler; it does not create or bind a GitHub repository, Cloudflare Builds project, or source-build pipeline.
|
|
175
256
|
|
|
176
257
|
Contributors working from a checkout can reproduce the two release artifacts locally with `pnpm --filter dsh-edge bundle:direct` and `pnpm --filter dsh-edge bundle:isolated`. The first command also enforces the compressed-size budget.
|
|
177
258
|
|
|
@@ -183,11 +264,27 @@ pnpm --filter dsh-edge example:install
|
|
|
183
264
|
|
|
184
265
|
## Edge API
|
|
185
266
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
- `
|
|
189
|
-
-
|
|
190
|
-
- `
|
|
267
|
+
### Upstream RPC carrier
|
|
268
|
+
|
|
269
|
+
- `POST /api/<upstream-method>` accepts the upstream `ClientRequest` envelope for supported `ApiProxy` methods.
|
|
270
|
+
- 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.
|
|
271
|
+
- `agentPreset.read` renders the programmatic Edge composition through the upstream read-only viewer. `credentials.describe` returns credential state without a value.
|
|
272
|
+
- Search projects canonical current-message surfaces and returns bounded upstream result values.
|
|
273
|
+
- Fork copies a completed-turn prefix through the canonical session seed format and retains parent lineage. Edge refuses seeds above 8,192 events or 8 MiB instead of materializing unbounded history.
|
|
274
|
+
- 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.
|
|
275
|
+
- 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.
|
|
276
|
+
|
|
277
|
+
### Authentication and downlinks
|
|
278
|
+
|
|
279
|
+
- `GET /login` renders the owner form. `POST /api/auth/login` exchanges the configured key for a signed cookie; `GET /api/auth/session` reports validity; `POST /api/auth/logout` clears it.
|
|
280
|
+
- `GET /api/events.mux` and `GET /api/events.host` upgrade to upstream downlink WebSockets. The Durable Object serializes each socket's channel and verified owner-session expiry as a hibernation attachment, closes it at expiry through an alarm, and reconstructs canonical sessions plus retained blank headers from SQL.
|
|
281
|
+
- After each committed inbox splice, mux publishes a complete `session/queue` snapshot. Reconnecting clients receive pending live-inbox baselines.
|
|
282
|
+
- `POST /api/commands/list` uses the upstream generated-Remote envelope with an empty catalog because the Edge preset registers no human commands.
|
|
283
|
+
- `GET /api/health` returns the public release/mode identifier and configured attachment default (`private-r2` or `temporary-do`). It validates owner authentication, deployment-scoped DeepSeek credentials, model/transport choices, and command timeouts before reporting ready.
|
|
284
|
+
- Health does not call the provider, Durable Object, R2, VFS, or shell. The authenticated agent-preset projection reports the pinned backend, temporary cap, deployment-default model, and runtime-derived upstream catalog with session selection scope.
|
|
285
|
+
|
|
286
|
+
### Diagnostic REST routes
|
|
287
|
+
|
|
191
288
|
- `PUT /api/workspace/file?path=/workspace/...` writes a UTF-8 file.
|
|
192
289
|
- `GET /api/workspace/file?path=/workspace/...` reads a UTF-8 file.
|
|
193
290
|
- `DELETE /api/workspace/file?path=/workspace/...` removes a file.
|
|
@@ -198,6 +295,49 @@ pnpm --filter dsh-edge example:install
|
|
|
198
295
|
- `GET /api/sessions/:sessionId/events?after=...&limit=...` replays a bounded event page and returns continuation headers.
|
|
199
296
|
- `POST /api/sessions/:sessionId/cancel` aborts the active turn owned by the current Durable Object process.
|
|
200
297
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
298
|
+
### Session and Workspace behavior
|
|
299
|
+
|
|
300
|
+
- Session creation and fork return `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.
|
|
301
|
+
- 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.
|
|
302
|
+
- Because Edge has no directory-flow provider, the upstream browser hides Delete on its sole Workspace and exposes it again whenever restoration remains possible.
|
|
303
|
+
|
|
304
|
+
### Limits and request admission
|
|
305
|
+
|
|
306
|
+
| Surface | Limit |
|
|
307
|
+
| --- | --- |
|
|
308
|
+
| UTF-8 text file | 1 MiB |
|
|
309
|
+
| Shell command | 16 KiB |
|
|
310
|
+
| User message or queue-edit text | 64 KiB |
|
|
311
|
+
| Retained shell stdout + stderr | 64 KiB |
|
|
312
|
+
| Session-create JSON body | 8 KiB |
|
|
313
|
+
| Workspace-exec JSON body | 128 KiB |
|
|
314
|
+
| Message-bearing turn or queue-update RPC | 10 MiB |
|
|
315
|
+
| Images | PNG/JPEG; 4 per message; 3.5 MiB each; 7 MiB total; 40 million pixels; 2,000 px per side |
|
|
316
|
+
|
|
317
|
+
- 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.
|
|
318
|
+
- 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.
|
|
319
|
+
- Image admission fully decodes the declared raster format before writing.
|
|
320
|
+
- When combined shell output crosses its retention bound, the runtime requests interruption and stops accumulating later output. `cancelled` reflects an adapter-requested interruption; `timedOut` independently records deadline expiry.
|
|
321
|
+
|
|
322
|
+
### Durability and concurrency
|
|
323
|
+
|
|
324
|
+
- Failed initial session persistence discards the retained unmaterialized batch before disposing the new upstream agent handle, so teardown cannot commit a session whose create request returned an error.
|
|
325
|
+
- A lazy blank session retains only its upstream header. The first canonical event removes that header in the same SQL transaction.
|
|
326
|
+
- Each turn owns one upstream handle and disposes it after streaming, so previously accessed conversations do not remain resident for the Durable Object lifetime.
|
|
327
|
+
- Deployment settings resolve before the process-local owner claim. One owner process rejects concurrent turns; cancellation uses the native agent path.
|
|
328
|
+
- A prompt is accepted and running state is published only after its inbox event crosses `SessionStore.flush()`. Streamed events cross the same durability barrier before WebSocket or SSE delivery.
|
|
329
|
+
- Queue edits, removals, and steering promotion use the synchronous live-inbox mutation as their acceptance point. `PersistenceCoordinator` owns later write-behind and retirement retries, so a later storage attempt cannot reverse an accepted mutation.
|
|
330
|
+
- Session rename uses the synchronous title append as its acceptance point for both active and cold sessions.
|
|
331
|
+
- Workspace global state and records keep upstream logical schemas under Edge-specific physical keys. DO transactions atomically pair record and registry-order changes; a process-local chain serializes Workspace mutations.
|
|
332
|
+
- Committed rename, delete, recreation, session reorder, attachment, and archive changes publish matching upstream Host frames. `workspace.list` restores the complete baseline after restart.
|
|
333
|
+
- Cold resume uses upstream interrupted-turn repair to close an open persisted tail. Canonical `session/end-seed` markers preserve lifecycle boundaries.
|
|
334
|
+
|
|
335
|
+
### Bounded reads and canonical history
|
|
336
|
+
|
|
337
|
+
- Replay checks session absence separately, so persistence corruption and SQL failures do not collapse into 404. It reads one bounded SQL page and caps the encoded response.
|
|
338
|
+
- `PersistenceCoordinator.readValidatedPage()` validates identity, format, legacy shape, and event vocabulary on every page without adding Edge pagination to the public persistence service.
|
|
339
|
+
- If legacy normalization needs earlier messages, it rereads one prefix through the same byte-bounded loader and refuses the page when that prefix does not fit.
|
|
340
|
+
- Cold browser history selects its message boundary in SQL and loads only the resulting contiguous range under fixed event and stored-byte ceilings.
|
|
341
|
+
- Session listing queries one bounded canonical header/title summary page. Detail reads a canonical point summary or retained blank header; turn existence checks use point queries instead of projecting a complete log.
|
|
342
|
+
- Effective model, system prompt, adapter defaults, and tools remain standard `request/header` events. The request-scoped adapter applies validated deployment reasoning and output policies.
|
|
343
|
+
- Workspace paths must stay below `/workspace/`.
|