mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
maxTitleBytes: 80
|
||||
|
||||
- id: session-title-llm
|
||||
name: '@deepseek-ai/dsh-session-title-first-message-llm'
|
||||
name: '@deepseek-ai/dsh-session-title-first-prompt-llm'
|
||||
config:
|
||||
targetWords: 5
|
||||
targetCjkCharacters: 10
|
||||
@@ -52,8 +52,8 @@
|
||||
maxOutputTokens: 64
|
||||
timeoutMs: 60000
|
||||
|
||||
- id: user-interaction
|
||||
name: '@deepseek-ai/dsh-user-interaction'
|
||||
- id: user-questions
|
||||
name: '@deepseek-ai/dsh-user-questions'
|
||||
|
||||
- id: agent
|
||||
name: '@deepseek-ai/dsh-agent'
|
||||
@@ -66,8 +66,8 @@
|
||||
provider: deepseek-official
|
||||
model: deepseek-v4-flash
|
||||
|
||||
- id: tasks
|
||||
name: '@deepseek-ai/dsh-tasks-local'
|
||||
- id: jobs
|
||||
name: '@deepseek-ai/dsh-jobs-local'
|
||||
|
||||
- id: llm-retry
|
||||
name: '@deepseek-ai/dsh-llm-retry'
|
||||
@@ -76,7 +76,7 @@
|
||||
# `llm-deepseek:` or `llm-pi-ai:` section there overrides the adapter entries
|
||||
# below without a restart, and is what the web Models page writes.
|
||||
- id: settings
|
||||
name: '@deepseek-ai/dsh-settings-local'
|
||||
name: '@deepseek-ai/dsh-settings-file'
|
||||
|
||||
# Credential sources: inherited environment over the managed
|
||||
# `$DSH_HOME/.credentials.yaml`, with project and user `.env` fallbacks.
|
||||
@@ -122,13 +122,13 @@
|
||||
|
||||
# Session telemetry is mounted but disabled by default. DSH_TELEMETRY_MODE
|
||||
# explicitly opts into FULL or FEEDBACK_ONLY reporting; uploading mirrors
|
||||
# session-log records onto OTLP/HTTP logs with no telemetry/record redaction
|
||||
# session-log records onto OTLP/HTTP logs with no session-telemetry/record redaction
|
||||
# rule, so exports are the raw captured copy. The deployment stance, env
|
||||
# seams, and follow-ups are pinned in the default-off Agent Note.
|
||||
# DSH_TELEMETRY_OTLP_URL overrides the production endpoint. A non-empty
|
||||
# DSH_TELEMETRY_DISABLED — any value, including '0'/'false' — opts the
|
||||
# process out (the launchers patch the row disabled; config cannot disable
|
||||
# a row). Exports carry the harness home's anonymous user id ($DSH_HOME/.userid,
|
||||
# a row). Exports carry the harness home's anonymous user id ($DSH_HOME/.anonymous-user-id,
|
||||
# random UUID; delete the file to reset the identity) as the Resource's
|
||||
# user.id. The exporter/processor values normally bound the shutdown drain
|
||||
# to ~1s against an unreachable collector: exporter.timeoutMillis is both
|
||||
@@ -139,7 +139,7 @@
|
||||
# shutdownTimeoutMillis is the load-bearing outer bound when a transport
|
||||
# promise never settles. Every CLI exit path drains it by disposing the root
|
||||
# on SIGINT/SIGTERM.
|
||||
- id: telemetry-otel
|
||||
- id: session-telemetry-otel
|
||||
name: '@deepseek-ai/dsh-session-telemetry-otel'
|
||||
config:
|
||||
mode: !!js process.env.DSH_TELEMETRY_MODE || 'DISABLED'
|
||||
@@ -185,7 +185,7 @@
|
||||
policy: !!js "(process.env.DSH_PERMISSION_MODE ?? 'workspace-write') === 'danger-full-access' ? 'never' : 'ask'"
|
||||
|
||||
- id: permission
|
||||
name: '@deepseek-ai/dsh-permission'
|
||||
name: '@deepseek-ai/dsh-permission-presets'
|
||||
config:
|
||||
presets:
|
||||
read-only:
|
||||
@@ -198,8 +198,8 @@
|
||||
sandbox: danger-full-access
|
||||
approval: never
|
||||
|
||||
- id: bash-env
|
||||
name: '@deepseek-ai/dsh-bash-env'
|
||||
- id: shell-env
|
||||
name: '@deepseek-ai/dsh-shell-env'
|
||||
|
||||
- id: tool-bash
|
||||
name: '@deepseek-ai/dsh-tool-bash'
|
||||
@@ -209,11 +209,11 @@
|
||||
name: '@deepseek-ai/dsh-tool-pwsh'
|
||||
disabled: !!js process.platform !== 'win32'
|
||||
|
||||
- id: tool-tasks
|
||||
name: '@deepseek-ai/dsh-tool-tasks'
|
||||
- id: tool-jobs
|
||||
name: '@deepseek-ai/dsh-tool-jobs'
|
||||
|
||||
- id: fs-policy
|
||||
name: '@deepseek-ai/dsh-fs-policy'
|
||||
- id: fs-observation-policy
|
||||
name: '@deepseek-ai/dsh-fs-observation-policy'
|
||||
|
||||
- id: tool-fs
|
||||
name: '@deepseek-ai/dsh-tool-fs'
|
||||
@@ -223,16 +223,16 @@
|
||||
config:
|
||||
sampleOverCapGlobResults: false
|
||||
|
||||
- id: workspace-context
|
||||
name: '@deepseek-ai/dsh-workspace-context'
|
||||
- id: agent-instructions
|
||||
name: '@deepseek-ai/dsh-agent-instructions'
|
||||
config:
|
||||
maxBytes: 65536
|
||||
|
||||
- id: skill
|
||||
name: '@deepseek-ai/dsh-skill'
|
||||
|
||||
- id: skill-local
|
||||
name: '@deepseek-ai/dsh-skill-local'
|
||||
- id: skill-filesystem
|
||||
name: '@deepseek-ai/dsh-skill-filesystem'
|
||||
|
||||
- id: skill-badge
|
||||
name: '@deepseek-ai/dsh-skill-badge'
|
||||
@@ -250,8 +250,8 @@
|
||||
- id: goal
|
||||
name: '@deepseek-ai/dsh-goal'
|
||||
|
||||
- id: goal-session
|
||||
name: '@deepseek-ai/dsh-goal-session'
|
||||
- id: goal-round-driver
|
||||
name: '@deepseek-ai/dsh-goal-round-driver'
|
||||
|
||||
- id: command-goal
|
||||
name: '@deepseek-ai/dsh-command-goal'
|
||||
@@ -275,8 +275,8 @@
|
||||
- id: token-meter
|
||||
name: '@deepseek-ai/dsh-token-meter'
|
||||
|
||||
- id: compact-basic
|
||||
name: '@deepseek-ai/dsh-compact-basic'
|
||||
- id: compaction-basic
|
||||
name: '@deepseek-ai/dsh-compaction-basic'
|
||||
|
||||
# Human `/compact`: one useful reduction below the automatic threshold. Backend
|
||||
# independent, so it follows whichever compaction service this leaf mounts.
|
||||
@@ -286,13 +286,13 @@
|
||||
- id: subagent
|
||||
name: '@deepseek-ai/dsh-subagent'
|
||||
|
||||
- id: subagent-spawn
|
||||
name: '@deepseek-ai/dsh-subagent-spawn'
|
||||
- id: subagent-spawn-in-process
|
||||
name: '@deepseek-ai/dsh-subagent-spawn-in-process'
|
||||
config:
|
||||
providerName: spawn
|
||||
|
||||
- id: subagent-fork
|
||||
name: '@deepseek-ai/dsh-subagent-fork'
|
||||
- id: subagent-fork-in-process
|
||||
name: '@deepseek-ai/dsh-subagent-fork-in-process'
|
||||
config:
|
||||
providerName: fork
|
||||
|
||||
@@ -335,8 +335,8 @@
|
||||
- id: tool-subagent-report
|
||||
name: '@deepseek-ai/dsh-tool-subagent-report'
|
||||
|
||||
- id: workflow-workerthread
|
||||
name: '@deepseek-ai/dsh-workflow-workerthread'
|
||||
- id: workflow-worker-thread
|
||||
name: '@deepseek-ai/dsh-workflow-worker-thread'
|
||||
config:
|
||||
provider: spawn
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
name: '@deepseek-ai/dsh-tool-workflow'
|
||||
|
||||
- id: timeout-policy
|
||||
name: '@deepseek-ai/dsh-timeout-policy'
|
||||
name: '@deepseek-ai/dsh-tool-call-timeout-policy'
|
||||
|
||||
- id: spill-local
|
||||
name: '@deepseek-ai/dsh-spill-local'
|
||||
@@ -360,8 +360,8 @@
|
||||
|
||||
# Compacts oversized tool results before the broader conversation compactor
|
||||
# runs, preserving the model-visible result within the configured budget.
|
||||
- id: tool-result-prune
|
||||
name: '@deepseek-ai/dsh-compact-tool-result-prune'
|
||||
- id: tool-result-pruner
|
||||
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
||||
config:
|
||||
thresholdChars: 8192
|
||||
headChars: 4096
|
||||
@@ -390,8 +390,8 @@
|
||||
maxOutputChars: 16000
|
||||
|
||||
# Consecutive-repeat reminders on the tool chain.
|
||||
- id: repeat-tool-guard
|
||||
name: '@deepseek-ai/dsh-repeat-tool-guard'
|
||||
- id: repeat-tool-reminder
|
||||
name: '@deepseek-ai/dsh-repeat-tool-reminder'
|
||||
config:
|
||||
thresholds: [3, 5, 8]
|
||||
argumentsPreviewChars: 500
|
||||
|
||||
@@ -45,29 +45,29 @@
|
||||
"@deepseek-ai/dsh-agent-default-model": "workspace:^",
|
||||
"@deepseek-ai/dsh-agent-loop": "workspace:^",
|
||||
"@deepseek-ai/dsh-attachment-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-shell-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-sandbox": "workspace:^",
|
||||
"@deepseek-ai/dsh-command-compact": "workspace:^",
|
||||
"@deepseek-ai/dsh-command-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-command-goal": "workspace:^",
|
||||
"@deepseek-ai/dsh-commands": "workspace:^",
|
||||
"@deepseek-ai/dsh-compact-basic": "workspace:^",
|
||||
"@deepseek-ai/dsh-compact-tool-result-prune": "workspace:^",
|
||||
"@deepseek-ai/dsh-compaction-basic": "workspace:^",
|
||||
"@deepseek-ai/dsh-compaction-tool-result-pruner": "workspace:^",
|
||||
"@deepseek-ai/dsh-credentials-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-fs-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-fs-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-fs-observation-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-fs-sandbox": "workspace:^",
|
||||
"@deepseek-ai/dsh-goal": "workspace:^",
|
||||
"@deepseek-ai/dsh-goal-session": "workspace:^",
|
||||
"@deepseek-ai/dsh-goal-round-driver": "workspace:^",
|
||||
"@deepseek-ai/dsh-api-gateway": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm-deepseek": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm-pi-ai": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm-retry": "workspace:^",
|
||||
"@deepseek-ai/dsh-permission": "workspace:^",
|
||||
"@deepseek-ai/dsh-permission-presets": "workspace:^",
|
||||
"@deepseek-ai/dsh-plan-mode": "workspace:^",
|
||||
"@deepseek-ai/dsh-pwsh-sandbox": "workspace:^",
|
||||
"@deepseek-ai/dsh-repeat-tool-guard": "workspace:^",
|
||||
"@deepseek-ai/dsh-repeat-tool-reminder": "workspace:^",
|
||||
"@deepseek-ai/dsh-sandbox-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-sandbox-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-session": "workspace:^",
|
||||
@@ -77,22 +77,22 @@
|
||||
"@deepseek-ai/dsh-session-query-sqlite": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-telemetry-otel": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-title": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-title-first-message-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-settings-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-title-first-prompt-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-settings-file": "workspace:^",
|
||||
"@deepseek-ai/dsh-skill": "workspace:^",
|
||||
"@deepseek-ai/dsh-skill-badge": "workspace:^",
|
||||
"@deepseek-ai/dsh-skill-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-skill-filesystem": "workspace:^",
|
||||
"@deepseek-ai/dsh-spill-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-spill-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-claude-code": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-codex": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-fork": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-spawn": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-fork-in-process": "workspace:^",
|
||||
"@deepseek-ai/dsh-subagent-spawn-in-process": "workspace:^",
|
||||
"@deepseek-ai/dsh-subprocess-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/dsh-tasks-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-jobs-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-call-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-token-meter": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-bash": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-fs": "workspace:^",
|
||||
@@ -105,7 +105,7 @@
|
||||
"@deepseek-ai/dsh-tool-subagent": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-subagent-control": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-subagent-report": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-tasks": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-jobs": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-todo": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-web": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-workflow": "workspace:^",
|
||||
@@ -113,11 +113,11 @@
|
||||
"@deepseek-ai/dsh-typert-loader": "workspace:^",
|
||||
"@deepseek-ai/dsh-typert-registry": "workspace:^",
|
||||
"@deepseek-ai/dsh-user-approval": "workspace:^",
|
||||
"@deepseek-ai/dsh-user-interaction": "workspace:^",
|
||||
"@deepseek-ai/dsh-user-questions": "workspace:^",
|
||||
"@deepseek-ai/dsh-web": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-search-deepseek": "workspace:^",
|
||||
"@deepseek-ai/dsh-workflow-workerthread": "workspace:^",
|
||||
"@deepseek-ai/dsh-workspace-context": "workspace:^"
|
||||
"@deepseek-ai/dsh-workflow-worker-thread": "workspace:^",
|
||||
"@deepseek-ai/dsh-agent-instructions": "workspace:^"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('dsh-base bundle', () => {
|
||||
)
|
||||
expect(rows.length).toBeGreaterThan(50)
|
||||
expect(rows.some(row => row.id === 'agent-loop')).toBe(true)
|
||||
expect(rows.find(row => row.id === 'telemetry-otel')?.config?.['mode']).toEqual({
|
||||
expect(rows.find(row => row.id === 'session-telemetry-otel')?.config?.['mode']).toEqual({
|
||||
__jsExpr: "process.env.DSH_TELEMETRY_MODE || 'DISABLED'",
|
||||
})
|
||||
expect(rows.filter(row => row.id === 'subagent-codex')).toHaveLength(1)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"path": "../../../vendor/cordis"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- insert:
|
||||
# Code Mode is a core execution capability, not a Web component.
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
|
||||
- id: headless-startup
|
||||
name: '@deepseek-ai/dsh-headless/startup'
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@deepseek-ai/dsh-cmdline": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker-thread": "workspace:^",
|
||||
"@deepseek-ai/schemastery": "workspace:^",
|
||||
"commander": "^15.0.0"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentHandle, CreateAgentOptions } from '@deepseek-ai/dsh-agent'
|
||||
import AgentDefaultModelService from '@deepseek-ai/dsh-agent-default-model'
|
||||
import AgentDefaultModelConfig from '@deepseek-ai/dsh-agent-default-model'
|
||||
import { createAssistantMessage } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore from '@deepseek-ai/dsh-session'
|
||||
import type { Session, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
@@ -55,7 +55,7 @@ async function bench(script: Script): Promise<{
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(AgentDefaultModelService, { provider: 'test-provider', model: 'test-model' })
|
||||
await ctx.plugin(AgentDefaultModelConfig, { provider: 'test-provider', model: 'test-model' })
|
||||
ctx.agents.setFactory({
|
||||
async createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle> {
|
||||
const session = ctx.sessions.create(options.sessionId, {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"path": "../../core/session"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
},
|
||||
{
|
||||
"path": "../../boot/cmdline"
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/bundle/web-app/README.md
|
||||
README.md: 06856a47cd8ccc2c6ee5a53c40928b1bd2933cc7
|
||||
README.zh.md: 8befc7c7404ea1b082842f122769967fff32df2f
|
||||
README.md: 3f7fbe7bbbeba2ee753ab2dfa8c945e798dd6a02
|
||||
README.zh.md: 357ca9946ed7fef1bf4c691c6666156bb293b5e0
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true, after its Loader tree settles so a sibling failure cannot announce a dead app. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, and the app's `--help`, then provides `webStartup`. Flag-configured rows inject that service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
|
||||
The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true, after its Loader tree settles so a sibling failure cannot announce a dead app. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, and the app's `--help`, then provides `webStartup`. Flag-configured rows inject that service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
|
||||
## 模型体验
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
- id: tools
|
||||
config:
|
||||
# TEMPORARY workaround: DSH_TOOLS_MODE (native|code|both) opts a whole dsh
|
||||
# process into Code Mode while per-session tool-mode selection is being
|
||||
# process into Code Mode while per-session tool-presentation selection is being
|
||||
# designed; unset keeps the schema default (native). Remove the env seam
|
||||
# once the web UI owns the choice per session.
|
||||
mode: !!js process.env.DSH_TOOLS_MODE
|
||||
@@ -45,7 +45,7 @@
|
||||
# window.__DSH_BOOT__; the modules row is simultaneously a host row.
|
||||
- insert:
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
|
||||
- id: storage
|
||||
name: '@deepseek-ai/dsh-storage'
|
||||
@@ -66,8 +66,8 @@
|
||||
maxNoteBytes: 8192
|
||||
|
||||
# Browser Session export: `/export` command plus the shared download dialog.
|
||||
- id: session-export
|
||||
name: '@deepseek-ai/dsh-session-export'
|
||||
- id: session-log-download
|
||||
name: '@deepseek-ai/dsh-session-log-download'
|
||||
|
||||
- id: workspace
|
||||
name: '@deepseek-ai/dsh-workspace'
|
||||
@@ -182,11 +182,11 @@
|
||||
- id: ui-settings-general
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-general'
|
||||
|
||||
- id: ui-models
|
||||
name: '@deepseek-ai/dsh-client-ui-models'
|
||||
- id: ui-settings-models
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-models'
|
||||
|
||||
- id: ui-plugins
|
||||
name: '@deepseek-ai/dsh-client-ui-plugins'
|
||||
- id: ui-settings-plugin-inventory
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-plugin-inventory'
|
||||
|
||||
- id: ui-conversation
|
||||
name: '@deepseek-ai/dsh-client-ui-conversation'
|
||||
@@ -209,13 +209,13 @@
|
||||
- id: ui-workspace
|
||||
name: '@deepseek-ai/dsh-client-ui-workspace'
|
||||
|
||||
# Input triggers: the '/' | '@' pipeline (ui-slash), the command surface over
|
||||
# it (ui-command), and the two reference sources (ui-skill / ui-subagent).
|
||||
- id: ui-slash
|
||||
name: '@deepseek-ai/dsh-client-ui-slash'
|
||||
# Input triggers: the '/' | '@' pipeline (ui-input-trigger), the command surface over
|
||||
# it (ui-commands), and the two reference sources (ui-skill / ui-subagent).
|
||||
- id: ui-input-trigger
|
||||
name: '@deepseek-ai/dsh-client-ui-input-trigger'
|
||||
|
||||
- id: ui-command
|
||||
name: '@deepseek-ai/dsh-client-ui-command'
|
||||
- id: ui-commands
|
||||
name: '@deepseek-ai/dsh-client-ui-commands'
|
||||
|
||||
- id: ui-skill
|
||||
name: '@deepseek-ai/dsh-client-ui-skill'
|
||||
@@ -223,9 +223,9 @@
|
||||
- id: ui-subagent
|
||||
name: '@deepseek-ai/dsh-client-ui-subagent'
|
||||
|
||||
# Background tasks: the session-header list over the tasksBySession mirror.
|
||||
- id: ui-task
|
||||
name: '@deepseek-ai/dsh-client-ui-task'
|
||||
# Background jobs: the session-header list over the jobsBySession mirror.
|
||||
- id: ui-jobs
|
||||
name: '@deepseek-ai/dsh-client-ui-jobs'
|
||||
|
||||
# Goal surface: GoalBar in the input dock over the goal session projection.
|
||||
- id: ui-goal
|
||||
@@ -233,15 +233,15 @@
|
||||
|
||||
# Per-message feedback: Like/Dislike plus an optional note in the
|
||||
# assistant-message action strip, over the messageFeedback Remote.
|
||||
- id: ui-feedback
|
||||
name: '@deepseek-ai/dsh-client-ui-feedback'
|
||||
- id: ui-message-feedback
|
||||
name: '@deepseek-ai/dsh-client-ui-message-feedback'
|
||||
|
||||
# Model selection: the /model popupSelect + composer seat over session.models.
|
||||
- id: ui-model
|
||||
name: '@deepseek-ai/dsh-client-ui-model'
|
||||
- id: ui-model-selection
|
||||
name: '@deepseek-ai/dsh-client-ui-model-selection'
|
||||
|
||||
- id: ui-permission
|
||||
name: '@deepseek-ai/dsh-client-ui-permission'
|
||||
name: '@deepseek-ai/dsh-client-ui-permission-presets'
|
||||
|
||||
# The agent-preset row in General settings: the default preset for
|
||||
# sessions created later. Absent a roster it renders nothing.
|
||||
@@ -250,15 +250,15 @@
|
||||
|
||||
# Plugin configuration: the host-plane sections a user owns, as expandable
|
||||
# cards. A namespace this deployment does not expose renders nothing.
|
||||
- id: ui-plugin-config
|
||||
name: '@deepseek-ai/dsh-client-ui-plugin-config'
|
||||
- id: ui-settings-plugins
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-plugins'
|
||||
|
||||
# Plan control: the composer plan seat over the plan projection + /plan channel.
|
||||
- id: ui-plan
|
||||
name: '@deepseek-ai/dsh-client-ui-plan'
|
||||
|
||||
- id: ui-question
|
||||
name: '@deepseek-ai/dsh-client-ui-question'
|
||||
- id: ui-user-questions
|
||||
name: '@deepseek-ai/dsh-client-ui-user-questions'
|
||||
|
||||
- id: ui-trajectory
|
||||
name: '@deepseek-ai/dsh-client-ui-trajectory'
|
||||
@@ -274,7 +274,7 @@
|
||||
# absent from a surface overlay would silently reappear the day someone reorders
|
||||
# the composition.
|
||||
|
||||
# `bash-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
|
||||
# `shell-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
|
||||
# publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
|
||||
# the criterion for host-plane ownership — injection resolves before any session
|
||||
# exists, so there is no agent to key by. Behind a preset realm those variables
|
||||
@@ -286,17 +286,17 @@
|
||||
- id: tool-pwsh
|
||||
disabled: true
|
||||
|
||||
# The background-task REGISTRY stays on the host plane; only the model-facing
|
||||
# `task_*` controls move. Its producers — `tool-bash` here, `tool-pty` and a
|
||||
# The background-job REGISTRY stays on the host plane; only the model-facing
|
||||
# `job_*` controls move. Its producers — `tool-bash` here, `tool-terminal` and a
|
||||
# non-continuable `tool-subagent` elsewhere — are preset rows that resolve it
|
||||
# with `ctx.get`, and an entry-local realm around the registry is invisible to
|
||||
# every sibling row outside that realm, so `run_in_background` answered
|
||||
# "background tasks unavailable" while the controls sat in the catalog. That is
|
||||
# "background jobs unavailable" while the controls sat in the catalog. That is
|
||||
# the `goals` criterion read from inside the preset: a Service a row outside its
|
||||
# realm READS belongs to the plane both can see. The registry is keyed by owning
|
||||
# agent, so one host instance serves every session exactly as before presets.
|
||||
|
||||
- id: tool-tasks
|
||||
- id: tool-jobs
|
||||
disabled: true
|
||||
|
||||
- id: tool-fs
|
||||
@@ -310,14 +310,14 @@
|
||||
|
||||
# The `skill` REGISTRY stays in the host plane. It is host+per-scope layered
|
||||
# (the tools-registry shape): deployment-level providers — repository plugins,
|
||||
# a host skill-local row — register into its global layer, while a preset's
|
||||
# `skill-local` registers into that preset's layer, and each agent reads the
|
||||
# a host skill-filesystem row — register into its global layer, while a preset's
|
||||
# `skill-filesystem` registers into that preset's layer, and each agent reads the
|
||||
# merged catalog its scope chain selects. Only the per-agent rows move behind
|
||||
# presets: the base host `skill-local` row is disabled here (presets own local
|
||||
# presets: the base host `skill-filesystem` row is disabled here (presets own local
|
||||
# discovery), and `tool-skill` is what a preset mounts to give its agent the
|
||||
# catalog and loader at all.
|
||||
|
||||
- id: skill-local
|
||||
- id: skill-filesystem
|
||||
disabled: true
|
||||
|
||||
- id: tool-skill
|
||||
@@ -328,7 +328,7 @@
|
||||
# domain as Remote endpoints, and a Remote method picks its receiver Service
|
||||
# from a generated descriptor — it resolves `goals` on the host, so a
|
||||
# per-session realm would answer `service-unavailable` for every browser call.
|
||||
# That is the `bash-env` criterion read from the other side: injection is not
|
||||
# That is the `shell-env` criterion read from the other side: injection is not
|
||||
# the only host relationship a Service can have. The registry is keyed by
|
||||
# session, so one host instance serves every session exactly as before presets.
|
||||
|
||||
@@ -345,13 +345,13 @@
|
||||
# `tasks` and `goals`; the reasoning has one home in
|
||||
# `.agents/notes/implemented/architecture/2026-08-10-host-plane-ownership-after-presets.md`.
|
||||
|
||||
- id: compact-basic
|
||||
- id: compaction-basic
|
||||
disabled: true
|
||||
|
||||
- id: command-compact
|
||||
disabled: true
|
||||
|
||||
- id: tool-result-prune
|
||||
- id: tool-result-pruner
|
||||
disabled: true
|
||||
|
||||
# The subagent registry and its backends STAY in the host plane. `subagents` is
|
||||
@@ -379,7 +379,7 @@
|
||||
# scope-aware — one copy per mounted preset means every child gets `report`
|
||||
# registered once per live session, which throws on the second.
|
||||
|
||||
- id: workflow-workerthread
|
||||
- id: workflow-worker-thread
|
||||
disabled: true
|
||||
|
||||
- id: tool-workflow
|
||||
@@ -388,7 +388,7 @@
|
||||
- id: tool-ralph
|
||||
disabled: true
|
||||
|
||||
- id: workspace-context
|
||||
- id: agent-instructions
|
||||
disabled: true
|
||||
|
||||
- id: tool-todo
|
||||
|
||||
@@ -53,37 +53,37 @@
|
||||
"@deepseek-ai/dsh-client-modules": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-runtime": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-agent-preset": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-command": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-commands": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-conversation": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-deliverables": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker-browse": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker-native": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-message-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-goal": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-layout": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-model": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-models": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plugins": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-permission": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-model-selection": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-models": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-permission-presets": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plan": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plugin-config": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-question": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-plugins": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-user-questions": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-general": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-sidebar": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-skill": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-slash": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-input-trigger": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-subagent": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-task": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-jobs": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-theme": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-tool": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-workflow-run": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-trajectory": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-workspace": "workspace:^",
|
||||
"@deepseek-ai/dsh-cmdline": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker": "workspace:^",
|
||||
"@deepseek-ai/dsh-frontend": "workspace:^",
|
||||
"@deepseek-ai/dsh-frontend-static": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker-thread": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-frontend": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-frontend-static": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-apiproxy": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-directory-picker-auto": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-directory-picker-browse": "workspace:^",
|
||||
@@ -92,7 +92,7 @@
|
||||
"@deepseek-ai/dsh-host-webserver": "workspace:^",
|
||||
"@deepseek-ai/dsh-message-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-projection-cache": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-export": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-log-download": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-stats": "workspace:^",
|
||||
"@deepseek-ai/dsh-storage": "workspace:^",
|
||||
"@deepseek-ai/dsh-storage-domain": "workspace:^",
|
||||
@@ -103,14 +103,14 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis-plugin-loader": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-shell-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis-plugin-loader": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-shell-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
|
||||
@@ -16,11 +16,11 @@ import { fileURLToPath } from 'node:url'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import z from '@deepseek-ai/schemastery'
|
||||
import { addHarnessSourceSection } from '@deepseek-ai/dsh-app-boot'
|
||||
import * as FrontendStatic from '@deepseek-ai/dsh-frontend-static'
|
||||
import * as FrontendStatic from '@deepseek-ai/dsh-host-frontend-static'
|
||||
import type {} from '@deepseek-ai/cordis-plugin-loader'
|
||||
import type {} from '@deepseek-ai/dsh-host-webserver'
|
||||
import type {} from '@deepseek-ai/dsh-system-prompt'
|
||||
import type {} from '@deepseek-ai/dsh-bash-env'
|
||||
import type {} from '@deepseek-ai/dsh-shell-env'
|
||||
|
||||
/** Stable Cordis plugin name. */
|
||||
export const name = 'web-app'
|
||||
@@ -32,7 +32,7 @@ const SOURCE_ROOT = fileURLToPath(new URL('../../../..', import.meta.url))
|
||||
const WEB_RUNTIME_SERVICE = 'webRuntime'
|
||||
|
||||
/** Services required before the web runtime can mount. */
|
||||
export const inject = ['httpServer']
|
||||
export const inject = ['webServer']
|
||||
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
@@ -102,13 +102,13 @@ function webSurfacePrompt(webUrl: string): string {
|
||||
+ updateContract
|
||||
+ 'Starting another server does not update this GUI. '
|
||||
+ 'The apps/web Vite entry builds the shell but is not a standalone application because only dsh web injects window.__DSH_BOOT__. '
|
||||
+ 'Do not start a replacement server unless the user asks; if one is needed, use a managed background task and verify its exact URL.'
|
||||
+ 'Do not start a replacement server unless the user asks; if one is needed, use a managed background job and verify its exact URL.'
|
||||
}
|
||||
|
||||
/** Resolve the canonical loopback URL from the active Web server. */
|
||||
function localWebUrl(ctx: Context): string {
|
||||
const port = ctx.get('httpServer')?.port
|
||||
if (port === undefined) throw new Error('web-app: httpServer service missing while resolving Web runtime')
|
||||
const port = ctx.get('webServer')?.port
|
||||
if (port === undefined) throw new Error('web-app: webServer service missing while resolving Web runtime')
|
||||
return `http://${LOOPBACK_HOST}:${String(port)}`
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ function localWebUrl(ctx: Context): string {
|
||||
function resolveDistIndex(): string {
|
||||
const require = createRequire(import.meta.url)
|
||||
try {
|
||||
return require.resolve('@deepseek-ai/dsh-frontend/dist/index.html')
|
||||
return require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')
|
||||
} catch {
|
||||
/* v8 ignore next 2 -- reachable only on a checkout without a built dist; the test tree builds it */
|
||||
throw new Error('web-app: frontend dist not built; run pnpm run build from the repository root first')
|
||||
@@ -129,11 +129,11 @@ export const internals: { resolveDistIndex: () => string } = { resolveDistIndex
|
||||
/**
|
||||
* Mount the Web runtime: dist serving, surface prompt, the bash runtime
|
||||
* variable, and the URL line.
|
||||
* @param ctx - plugin context carrying the httpServer service.
|
||||
* @param ctx - plugin context carrying the webServer service.
|
||||
* @param config - validated {@link Config}.
|
||||
*/
|
||||
export function apply(ctx: Context, config: Config): void {
|
||||
const runtime = resolveLanTrust(ctx.httpServer.host, config.trustedHosts)
|
||||
const runtime = resolveLanTrust(ctx.webServer.host, config.trustedHosts)
|
||||
// Release dependent rows only after bind-dependent trust has been sampled once.
|
||||
ctx.provide(WEB_RUNTIME_SERVICE, runtime)
|
||||
ctx.plugin(FrontendStatic, { distIndex: internals.resolveDistIndex() })
|
||||
@@ -146,8 +146,8 @@ export function apply(ctx: Context, config: Config): void {
|
||||
text: () => webSurfacePrompt(localWebUrl(promptCtx)),
|
||||
})
|
||||
})
|
||||
ctx.inject(['bashEnv'], (runtimeCtx) => {
|
||||
runtimeCtx.bashEnv.register({
|
||||
ctx.inject(['shellEnv'], (runtimeCtx) => {
|
||||
runtimeCtx.shellEnv.register({
|
||||
name: 'web-runtime',
|
||||
variables: {
|
||||
[DSH_WEB_URL]: { description: 'Canonical local URL of the DeepSeek Harness Web GUI serving this session.' },
|
||||
@@ -164,7 +164,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
const printUrl = (): void => {
|
||||
// Reuse the exact LAN snapshot provided to the /api trust fence.
|
||||
const lanCandidate = runtime.lanAddresses[0]
|
||||
const port = ctx.httpServer.port
|
||||
const port = ctx.webServer.port
|
||||
console.log(`dsh web: ${localWebUrl(ctx)}${lanCandidate === undefined ? '' : ` (LAN: http://${lanCandidate}:${String(port)})`}`)
|
||||
}
|
||||
// This row's own activation can precede a sibling failure. The app owns
|
||||
@@ -177,7 +177,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
// The tree can be disposed while the boot was in flight (early
|
||||
// SIGTERM); a URL line for a dead server would only mislead, and
|
||||
// reading the torn-down port would turn a clean shutdown into a crash.
|
||||
if (ctx.get('httpServer') !== undefined) printUrl()
|
||||
if (ctx.get('webServer') !== undefined) printUrl()
|
||||
// Loader reports a failed boot; this row only stays quiet.
|
||||
}, () => {})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import type { HttpServerService } from '@deepseek-ai/dsh-host-webserver'
|
||||
import type { WebServer } from '@deepseek-ai/dsh-host-webserver'
|
||||
import { apply, Config, internals } from '../src/index.ts'
|
||||
|
||||
vi.mock('node:os', async importOriginal => ({
|
||||
@@ -43,8 +43,8 @@ function stageDist(): string {
|
||||
return index
|
||||
}
|
||||
|
||||
/** A fake httpServer capturing the fallback seat and index taps. */
|
||||
function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server: HttpServerService; seat: () => unknown } {
|
||||
/** A fake webServer capturing the fallback seat and index taps. */
|
||||
function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server: WebServer; seat: () => unknown } {
|
||||
let fallback: unknown
|
||||
const server = {
|
||||
host,
|
||||
@@ -54,7 +54,7 @@ function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server:
|
||||
return () => { fallback = undefined }
|
||||
},
|
||||
applyIndexTaps: (html: string) => html,
|
||||
} as unknown as HttpServerService
|
||||
} as unknown as WebServer
|
||||
return { server, seat: () => fallback }
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ describe('web-app runtime glue', () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
const { server, seat } = fakeHttpServer('0.0.0.0')
|
||||
ctx.provide('httpServer', server)
|
||||
ctx.provide('webServer', server)
|
||||
const contributions: BashContribution[] = []
|
||||
ctx.provide('bashEnv', {
|
||||
ctx.provide('shellEnv', {
|
||||
register: (contribution: BashContribution) => {
|
||||
contributions.push(contribution)
|
||||
return () => {}
|
||||
@@ -110,7 +110,7 @@ describe('web-app runtime glue', () => {
|
||||
it('stays quiet with printUrl off', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
apply(ctx, new Config({ printUrl: false, surfaceContext: true, trustedHosts: [] }))
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
@@ -125,9 +125,9 @@ describe('web-app runtime glue', () => {
|
||||
it('skips the surface context when disabled (the one-shot layer): no prompt section, no bash variables', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const contributions: BashContribution[] = []
|
||||
ctx.provide('bashEnv', {
|
||||
ctx.provide('shellEnv', {
|
||||
register: (contribution: BashContribution) => {
|
||||
contributions.push(contribution)
|
||||
return () => {}
|
||||
@@ -146,7 +146,7 @@ describe('web-app runtime glue', () => {
|
||||
it('prints the loopback-only URL line when no LAN snapshot exists', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
apply(ctx, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
@@ -159,7 +159,7 @@ describe('web-app runtime glue', () => {
|
||||
// Settlement path: the line waits for loader.await() so supervisors can
|
||||
// RPC immediately after observing it.
|
||||
const settled = new Context()
|
||||
settled.provide('httpServer', fakeHttpServer().server)
|
||||
settled.provide('webServer', fakeHttpServer().server)
|
||||
let release: () => void
|
||||
const settlement = new Promise<void>((resolve) => { release = resolve })
|
||||
provideLoader(settled, () => settlement)
|
||||
@@ -176,7 +176,7 @@ describe('web-app runtime glue', () => {
|
||||
// for a process that is about to exit.
|
||||
log.mockClear()
|
||||
const failed = new Context()
|
||||
failed.provide('httpServer', fakeHttpServer().server)
|
||||
failed.provide('webServer', fakeHttpServer().server)
|
||||
provideLoader(failed, async () => { throw new Error('boot failed') })
|
||||
apply(failed, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
@@ -188,14 +188,14 @@ describe('web-app runtime glue', () => {
|
||||
log.mockClear()
|
||||
const torn = new Context()
|
||||
const child = torn.plugin((childCtx: Context) => {
|
||||
childCtx.provide('httpServer', fakeHttpServer().server)
|
||||
childCtx.provide('webServer', fakeHttpServer().server)
|
||||
})
|
||||
await child
|
||||
let releaseTorn: () => void
|
||||
const tornSettlement = new Promise<void>((resolve) => { releaseTorn = resolve })
|
||||
provideLoader(torn, () => tornSettlement)
|
||||
apply(torn, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await child.dispose() // the httpServer service goes away
|
||||
await child.dispose() // the webServer service goes away
|
||||
releaseTorn!()
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
expect(log).not.toHaveBeenCalled()
|
||||
@@ -209,11 +209,11 @@ describe('web-app runtime glue', () => {
|
||||
// section must throw, never render a URL with an undefined port.
|
||||
const { server } = fakeHttpServer()
|
||||
Object.defineProperty(server, 'port', { get: () => undefined })
|
||||
ctx.provide('httpServer', server)
|
||||
ctx.provide('webServer', server)
|
||||
apply(ctx, new Config({ printUrl: false, surfaceContext: true, trustedHosts: [] }))
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
await expect(ctx.systemPrompt.assemble()).rejects.toThrow('httpServer service missing')
|
||||
await expect(ctx.systemPrompt.assemble()).rejects.toThrow('webServer service missing')
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
"path": "../../core/system-prompt"
|
||||
},
|
||||
{
|
||||
"path": "../../bash/bash-env"
|
||||
"path": "../../shell/shell-env"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user