@toddzheng024/dscode-bundle 0.7.26 → 0.7.28

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.
Files changed (99) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +10 -10
  3. package/bootstrap.mjs +1 -1
  4. package/cordis.patch.yml +418 -45
  5. package/package.json +279 -245
  6. package/plugins/auto-review/index.mjs +8 -5
  7. package/plugins/code-review/index.mjs +1 -1
  8. package/plugins/computer-use/index.mjs +37 -0
  9. package/plugins/cordis-config/plain.mjs +31 -0
  10. package/plugins/exec/cli.mjs +1 -1
  11. package/plugins/grok/index.mjs +28 -24
  12. package/plugins/memory/index.mjs +1 -1
  13. package/plugins/message-source/kind.mjs +20 -0
  14. package/plugins/openrouter/adapter.mjs +29 -13
  15. package/plugins/openrouter/index.mjs +31 -28
  16. package/plugins/session-bridge/communication.mjs +6 -3
  17. package/plugins/session-bridge/server.mjs +3 -2
  18. package/plugins/session-bridge/tasks.mjs +3 -1
  19. package/plugins/session-cards/index.mjs +1 -1
  20. package/plugins/time-marks/index.mjs +3 -2
  21. package/plugins/time-marks/marks.mjs +6 -5
  22. package/plugins/triggers/config.mjs +1 -1
  23. package/plugins/triggers/tools.mjs +1 -1
  24. package/plugins/tui-tools/doctor.mjs +1 -1
  25. package/plugins/tui-tools/index.mjs +16 -4
  26. package/plugins/ultra/policy.mjs +16 -0
  27. package/vendor/bash/index.js +455 -186
  28. package/vendor/bash/types/background.d.ts +38 -7
  29. package/vendor/bash/types/index.d.ts +20 -4
  30. package/vendor/bash/types/render.d.ts +28 -9
  31. package/vendor/command-goal/index.js +3 -1
  32. package/vendor/deepseek/index.js +1378 -1246
  33. package/vendor/deepseek/types/adapter.d.ts +16 -155
  34. package/vendor/deepseek/types/config.d.ts +127 -0
  35. package/vendor/deepseek/types/defaults.d.ts +24 -0
  36. package/vendor/deepseek/types/file-store.d.ts +5 -3
  37. package/vendor/deepseek/types/files-api.d.ts +12 -9
  38. package/vendor/deepseek/types/image-tokens.d.ts +24 -9
  39. package/vendor/deepseek/types/images.d.ts +35 -0
  40. package/vendor/deepseek/types/index.d.ts +10 -94
  41. package/vendor/deepseek/types/messages-api.d.ts +10 -0
  42. package/vendor/deepseek/types/model-info.d.ts +16 -0
  43. package/vendor/deepseek/types/models.d.ts +4 -0
  44. package/vendor/deepseek/types/replay.d.ts +27 -0
  45. package/vendor/deepseek/types/request-extensions.d.ts +16 -0
  46. package/vendor/deepseek/types/request-files.d.ts +49 -0
  47. package/vendor/deepseek/types/request-pricing.d.ts +32 -20
  48. package/vendor/deepseek/types/serialize.d.ts +17 -82
  49. package/vendor/deepseek/types/sse.d.ts +6 -22
  50. package/vendor/deepseek/types/translate.d.ts +13 -36
  51. package/vendor/deepseek/types/transport.d.ts +15 -0
  52. package/vendor/deepseek/types/types.d.ts +106 -167
  53. package/vendor/deepseek/types/wire-types.d.ts +62 -0
  54. package/vendor/persistent/index.js +9 -3
  55. package/vendor/subagent/index.js +11 -8
  56. package/vendor/subagent/model-selection-settings.js +12 -38
  57. package/vendor/subagent/types/index.d.ts +4 -3
  58. package/vendor/subagent/types/model-selection-settings.d.ts +12 -10
  59. package/vendor/subagent-core/index.js +401 -264
  60. package/vendor/subagent-core/typert.host.js +103 -113
  61. package/vendor/subagent-core/typert.remote-client.d.ts +1 -3
  62. package/vendor/subagent-core/typert.remote-client.js +23 -69
  63. package/vendor/subagent-core/types/archive-admission.d.ts +16 -0
  64. package/vendor/subagent-core/types/archive-admission.js +151 -0
  65. package/vendor/subagent-core/types/assistant-output.d.ts +2 -2
  66. package/vendor/subagent-core/types/catalog.d.ts +17 -10
  67. package/vendor/subagent-core/types/catalog.js +12 -6
  68. package/vendor/subagent-core/types/child-agent.d.ts +8 -5
  69. package/vendor/subagent-core/types/child-agent.js +11 -5
  70. package/vendor/subagent-core/types/continuation-activation.d.ts +17 -1
  71. package/vendor/subagent-core/types/continuation-activation.js +41 -4
  72. package/vendor/subagent-core/types/continuation-messages.d.ts +1 -1
  73. package/vendor/subagent-core/types/continuation-messages.js +7 -3
  74. package/vendor/subagent-core/types/continuation.d.ts +1 -1
  75. package/vendor/subagent-core/types/continuation.js +2 -2
  76. package/vendor/subagent-core/types/control-types.d.ts +29 -36
  77. package/vendor/subagent-core/types/control-types.js +2 -3
  78. package/vendor/subagent-core/types/control.d.ts +2 -28
  79. package/vendor/subagent-core/types/control.js +3 -40
  80. package/vendor/subagent-core/types/index.d.ts +45 -41
  81. package/vendor/subagent-core/types/index.js +46 -82
  82. package/vendor/subagent-core/types/internal.d.ts +2 -2
  83. package/vendor/subagent-core/types/internal.js +2 -2
  84. package/vendor/subagent-core/types/lifecycle.d.ts +1 -1
  85. package/vendor/subagent-core/types/lifecycle.js +5 -3
  86. package/vendor/subagent-core/types/list-children.d.ts +15 -32
  87. package/vendor/subagent-core/types/list-children.js +45 -49
  88. package/vendor/subagent-core/types/out-of-process.d.ts +1 -1
  89. package/vendor/subagent-core/types/projection-types.d.ts +9 -1
  90. package/vendor/subagent-core/types/projection.d.ts +5 -0
  91. package/vendor/subagent-core/types/projection.js +10 -4
  92. package/vendor/subagent-core/types/run-settlement.js +1 -1
  93. package/vendor/subagent-core/types/types.d.ts +2 -2
  94. package/vendor/terminal/index.js +94 -30
  95. package/vendor/tui/lib/index.mjs +2 -1
  96. package/vendor/tui/lib/kernel-panels.mjs +1 -1
  97. package/vendor/tui/lib/render/projection.mjs +50 -36
  98. package/presets/dscode/agent.cordis.yml +0 -321
  99. package/presets/dscode/preset.yml +0 -3
@@ -1,178 +1,117 @@
1
- /**
2
- * DeepSeek chat-completions wire format (OpenAI-compatible). Types only.
3
- *
4
- * Source of truth: the official API docs at
5
- * `~/repos/deepsuite-docs/apps/docs/docs` (api/create-chat-completion,
6
- * guides/thinking_mode.mdx, guides/tool_calls.md), cross-checked against
7
- * live streams from the internal endpoint (2026-06).
8
- *
9
- * @module dsh-llm-deepseek/types
10
- */
11
- /** Request body for `POST {baseURL}/chat/completions`. */
12
- export interface WireRequest {
13
- model: string;
14
- messages: WireMessage[];
15
- stream: true;
16
- stream_options: {
17
- include_usage: true;
18
- };
19
- /** Thinking-mode toggle (top level, NOT inside extra_body on the wire). */
20
- thinking?: {
21
- type: 'enabled' | 'disabled';
22
- };
23
- /** Thinking effort (official levels). */
24
- reasoning_effort?: 'low' | 'high' | 'max';
25
- tools?: WireTool[];
26
- temperature?: number;
27
- max_tokens?: number;
1
+ /** Model catalog and request-local dependencies for DeepSeek Messages. */
2
+ import type { ModelModality, SystemPromptUpdate, ResolvedRetryPolicy, ImageAttachmentAccess } from '@deepseek-ai/dsh-llm';
3
+ import type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
4
+ import type { CredentialRef } from '@deepseek-ai/dsh-credentials';
5
+ import type { AnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id';
6
+ import type { DeepSeekLlmApiExtensionRequest, PreparedDeepSeekLlmApiExtensions } from '@deepseek-ai/dsh-deepseek-llm-api-extensions';
7
+ import type { DeepSeekFileStore, DeepSeekFilePolicy } from './file-store.ts';
8
+ /** One optional model entry advertised by the direct-fetch adapter. */
9
+ export interface DeepSeekCatalogModel {
10
+ /** Wire model id accepted by the configured endpoint. */
11
+ id: string;
12
+ /** Selector label; defaults to {@link id}. */
13
+ name?: string;
14
+ /** Optional selector detail for deployments with similar model variants. */
15
+ description?: string;
16
+ /** Known combined request/response context capacity; omitted when deployment metadata is unavailable. */
17
+ contextWindow?: number;
18
+ /** Per-request output cap for this model; omission falls back to the profile's {@link DeepSeekConnectionOptions.maxTokens}. */
19
+ maxTokens?: number;
20
+ /** Accepted request modalities; omission is text-only. */
21
+ inputModalities?: ModelModality[];
28
22
  /**
29
- * Stop sequences (OpenAI `stop`): generation halts as soon as the model
30
- * produces any one of these strings. Mapped from `GenerateOptions.stop`.
23
+ * Total-pixel budget replacing the published token-grid projection for one
24
+ * deterministic request preview, or the 512-by-512 `low` preset; omission
25
+ * projects onto the token grid.
31
26
  */
32
- stop?: string[];
33
- }
34
- /** System-role message: a single string of instructions. */
35
- export interface WireSystemMessage {
36
- role: 'system';
37
- content: string;
38
- }
39
- /** Text part inside a multimodal user message. */
40
- export interface WireTextContentPart {
41
- type: 'text';
42
- text: string;
43
- }
44
- /** Files API reference inside a multimodal user message. */
45
- export interface WireFileContentPart {
46
- type: 'file';
47
- file_id: string;
48
- }
49
- /** Inline base64 data URL inside a multimodal user message. */
50
- export interface WireImageUrlContentPart {
51
- type: 'image_url';
52
- image_url: {
53
- url: string;
54
- };
55
- }
56
- /** One image representation accepted by a multimodal user message. */
57
- export type WireImageContentPart = WireFileContentPart | WireImageUrlContentPart;
58
- /** Ordered input part accepted by a multimodal user message. */
59
- export type WireUserContentPart = WireTextContentPart | WireImageContentPart;
60
- /** User-role message: text-only string or ordered multimodal input. */
61
- export interface WireUserMessage {
62
- role: 'user';
63
- content: string | WireUserContentPart[];
64
- }
65
- /** Tool-role message: the result of one tool call, keyed by its call id. */
66
- export interface WireToolMessage {
67
- role: 'tool';
68
- tool_call_id: string;
69
- content: string;
70
- }
71
- /** One entry of the request `messages` array, discriminated on `role`. */
72
- export type WireMessage = WireSystemMessage | WireUserMessage | WireAssistantMessage | WireToolMessage;
73
- /**
74
- * Assistant-role history message. The harness replays `content: ""` (never
75
- * null) on tool-call-only turns — some gateways reject null — and sends null
76
- * only when the turn carried neither text nor tool calls.
77
- */
78
- export interface WireAssistantMessage {
79
- role: 'assistant';
80
- content: string | null;
27
+ imagePixelBudget?: number | 'low';
28
+ /** Encoded-byte target for one deterministic request preview; the smallest quality-ladder output is used when no quality fits. */
29
+ imageMaxBytes?: number;
81
30
  /**
82
- * CoT passback, present on every turn whose assistant content carried
83
- * reasoning. REQUIRED on tool-call turns in thinking mode (see
84
- * guides/thinking_mode.mdx § Tool Calls); DeepSeek ignores it elsewhere,
85
- * while a gateway re-encoding for another vendor recovers that turn's
86
- * thinking signature by hashing it.
31
+ * `'in-history'` declares that the endpoint reads the latest `system`
32
+ * message at any position of the conversation as the complete effective
33
+ * system prompt; omission means only a leading system message is read.
87
34
  */
88
- reasoning_content?: string;
89
- tool_calls?: WireToolCall[];
35
+ systemPromptUpdate?: SystemPromptUpdate;
90
36
  }
91
- /** A completed tool call replayed on an assistant history message; `arguments` is the raw JSON string. */
92
- export interface WireToolCall {
93
- id: string;
94
- type: 'function';
95
- function: {
96
- name: string;
97
- arguments: string;
98
- };
99
- }
100
- /** One entry of the request `tools` array; `parameters` is a JSON Schema object. */
101
- export interface WireTool {
102
- type: 'function';
103
- function: {
104
- name: string;
105
- description: string;
106
- parameters: Record<string, unknown>;
107
- };
108
- }
109
- /** One parsed SSE `data:` payload (a chat.completion.chunk). */
110
- export interface WireChunk {
111
- choices?: WireChoice[];
112
- /** Arrives attached to the finish chunk and/or as a trailing usage-only chunk. */
113
- usage?: WireUsage | null;
114
- }
115
- /** One streamed choice (requests always ask for a single one); `finish_reason` is non-null only on its terminal chunk. */
116
- export interface WireChoice {
117
- delta?: WireDelta;
118
- finish_reason?: string | null;
119
- }
120
- /** The incremental content of one streamed choice; any subset of fields may be present per chunk. */
121
- export interface WireDelta {
122
- role?: string;
123
- /** Visible text. Null/empty on reasoning/tool-call chunks. */
124
- content?: string | null;
37
+ /**
38
+ * Validated connection facts for one operation. The plugin's
39
+ * `resolveAdapterOptions` is the one explicit resolve step producing this
40
+ * shape; the adapter trusts it and re-reads it per operation, which is what
41
+ * makes a configuration change reach the next request without re-registration.
42
+ */
43
+ export interface DeepSeekConnectionOptions {
44
+ /** Messages API root; custom paths remain unchanged. */
45
+ baseURL: string;
125
46
  /**
126
- * Thinking-mode CoT. The FIRST chunk carries an empty string (must not
127
- * open a reasoning block); absent entirely in non-thinking mode.
47
+ * Credential reference of this same resolution, resolved per request.
48
+ * Travelling with the endpoint is the point: a request can never pair one
49
+ * generation's URL with another generation's secret. Configuration carries
50
+ * only this name — a literal key is not a configuration value.
128
51
  */
129
- reasoning_content?: string | null;
130
- tool_calls?: WireToolCallDelta[];
131
- }
132
- /** A streamed fragment of one tool call; fragments sharing an `index` concatenate into one call. */
133
- export interface WireToolCallDelta {
134
- /** Disambiguates parallel tool calls; stable across a call's deltas. */
135
- index: number;
52
+ apiKeyEnv: CredentialRef;
53
+ /** Request defaults applied to every call (thinking mode, effort). */
54
+ defaults: RequestDefaults;
55
+ /** Default per-request output cap; explicit request values win. */
56
+ maxTokens: number;
57
+ /** Positive context capacity used when the selected model has no exact value. */
58
+ defaultContextWindow: number;
59
+ /** Advisory models exposed to discovery consumers; requests remain unrestricted. */
60
+ models: readonly DeepSeekCatalogModel[];
61
+ /** Maximum provider idle time while one stream read is outstanding. */
62
+ streamIdleTimeoutMs: number;
63
+ /** Maximum accumulated file-referenced image bytes in one request. */
64
+ maxRequestFilesBytes: number;
65
+ /** Maximum accumulated base64 image payload after Files API fallback. */
66
+ maxInlineRequestImageBytes: number;
67
+ /** Maximum number of represented images in one request. */
68
+ maxImagesPerRequest: number;
69
+ /** Raw-byte removal step after the file-reference bound is exceeded. */
70
+ imageOffloadByteQuantum: number;
71
+ /** Base64-byte removal step after the inline fallback bound is exceeded. */
72
+ inlineImageOffloadByteQuantum: number;
73
+ /** Image-count removal step after the count bound is exceeded. */
74
+ imageOffloadCountQuantum: number;
75
+ /** Maximum duration of one request-image Files API resolution. */
76
+ filesApiTimeoutMs: number;
77
+ /** Upload expiry, refresh, and quota-recovery policy. */
78
+ filePolicy: DeepSeekFilePolicy;
79
+ /** Provider-owned model-request retry policy, already resolved. */
80
+ retryPolicy: ResolvedRetryPolicy;
81
+ }
82
+ /** Constructor options for {@link DeepSeekAdapter}: the operation-local resolution hooks the plugin owns. */
83
+ export interface DeepSeekAdapterOptions {
84
+ /** Report unusable native Messages replay metadata without exposing content or signatures. */
85
+ onReplayDegrade?: (detail: {
86
+ provider: string;
87
+ model: string;
88
+ reason: string;
89
+ }) => void;
90
+ /** Current validated connection facts; called once per operation. */
91
+ options: () => DeepSeekConnectionOptions;
136
92
  /**
137
- * Carried by the first delta of each call. Gateways observed in the wild
138
- * repeat it on continuation deltas as `''` or `null`; both mean "unchanged".
93
+ * Resolve the API key for the connection facts of one request. The
94
+ * snapshot is passed in never re-read so the key can only ever come
95
+ * from the same resolution as the endpoint it is sent to. Throws `LlmError`
96
+ * `MISSING_CREDENTIAL` when no key is available anywhere.
139
97
  */
140
- id?: string | null;
141
- type?: 'function';
142
- function?: {
143
- /** Carried by the first delta of each call, with the same `''`/`null` repetition as {@link WireToolCallDelta.id}. */
144
- name?: string | null;
145
- /** Argument JSON fragment (concatenate across deltas). */
146
- arguments?: string | null;
147
- };
148
- }
149
- /**
150
- * Wire token accounting. `prompt_tokens` INCLUDES cache hits (it equals
151
- * `prompt_cache_hit_tokens + prompt_cache_miss_tokens`); `mapUsage` subtracts
152
- * them to keep the harness convention of disjoint counts.
153
- * `prompt_tokens_details.cached_tokens` is the OpenAI-compat spelling of the
154
- * hit count.
155
- */
156
- export interface WireUsage {
157
- prompt_tokens: number;
158
- completion_tokens: number;
159
- /** Provider-reported aggregate across prompt and completion tokens. */
160
- total_tokens?: number;
161
- prompt_cache_hit_tokens?: number;
162
- prompt_cache_miss_tokens?: number;
163
- prompt_tokens_details?: {
164
- cached_tokens?: number;
165
- };
166
- completion_tokens_details?: {
167
- reasoning_tokens?: number;
168
- };
169
- }
170
- /** Non-2xx error body. */
171
- export interface WireError {
172
- error?: {
173
- message?: string;
174
- type?: string;
175
- code?: string;
176
- };
98
+ resolveApiKey: (connection: DeepSeekConnectionOptions) => Promise<string>;
99
+ /** Resolve a DSH account token only for an eligible official endpoint. */
100
+ resolveAccountToken?: (connection: DeepSeekConnectionOptions) => Promise<string | undefined>;
101
+ /** Resolve the harness-home anonymous id shared with telemetry and feedback. */
102
+ resolveUserId: () => AnonymousUserId;
103
+ /** Resolve the current durable attachment service; absence rejects image input. */
104
+ resolveAttachments?: () => AttachmentStore | undefined;
105
+ /** Bridge one attachment reference into the current model-tool execution world. */
106
+ resolveImageAccess?: (attachments: AttachmentStore, ref: ImageAttachmentRef) => ImageAttachmentAccess | undefined;
107
+ /** Resolve the process-wide upload reuse store. */
108
+ resolveFiles?: () => DeepSeekFileStore;
109
+ /** Prepare the official API's plugin-contributed top-level fields for one exact wire request. */
110
+ prepareExtensions: (request: DeepSeekLlmApiExtensionRequest) => Promise<PreparedDeepSeekLlmApiExtensions>;
111
+ }
112
+ /** Adapter-level request defaults (from plugin config). */
113
+ export interface RequestDefaults {
114
+ thinking?: 'enabled' | 'disabled' | undefined;
115
+ reasoningEffort?: 'off' | 'low' | 'high' | 'max' | undefined;
177
116
  }
178
117
  //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,62 @@
1
+ /** DeepSeek's supported subset of the Anthropic Messages request protocol. */
2
+ /** Text and inline or file-referenced images accepted in user messages and tool results. */
3
+ export type WireInput = {
4
+ type: 'text';
5
+ text: string;
6
+ } | {
7
+ type: 'image';
8
+ source: {
9
+ type: 'base64';
10
+ media_type: string;
11
+ data: string;
12
+ };
13
+ } | {
14
+ type: 'image';
15
+ source: {
16
+ type: 'file';
17
+ file_id: string;
18
+ };
19
+ };
20
+ /** Content serialized into one Messages conversation turn. */
21
+ export type WireBlock = WireInput | {
22
+ type: 'thinking';
23
+ thinking: string;
24
+ signature?: string;
25
+ } | {
26
+ type: 'tool_use';
27
+ id: string;
28
+ name: string;
29
+ input: Record<string, unknown>;
30
+ } | {
31
+ type: 'tool_result';
32
+ tool_use_id: string;
33
+ content: WireInput[];
34
+ is_error?: boolean;
35
+ };
36
+ /** Conversation turn; capable routes retain later system updates in message history. */
37
+ export type WireMessage = {
38
+ role: 'user' | 'assistant' | 'system';
39
+ content: WireBlock[];
40
+ };
41
+ /** JSON body submitted to the resolved Messages endpoint. */
42
+ export type WireRequest = {
43
+ model: string;
44
+ stream: true;
45
+ max_tokens: number;
46
+ messages: WireMessage[];
47
+ system?: string;
48
+ thinking: {
49
+ type: 'enabled' | 'disabled';
50
+ };
51
+ output_config?: {
52
+ effort: 'low' | 'high' | 'max';
53
+ };
54
+ temperature?: number;
55
+ stop_sequences?: string[];
56
+ tools?: {
57
+ name: string;
58
+ description: string;
59
+ input_schema: Record<string, unknown>;
60
+ }[];
61
+ };
62
+ //# sourceMappingURL=wire-types.d.ts.map
@@ -257,7 +257,13 @@ async function executeCommand(ctx, shells, owner, command, config, upstream) {
257
257
  };
258
258
  try {
259
259
  const commandDeadline = __addDisposableResource(env_1, deadline(upstream, config.timeoutMs, TIMEOUT_CODE), false);
260
- const id = await shells.get(owner, commandDeadline.signal);
260
+ let id;
261
+ try {
262
+ id = await shells.get(owner, commandDeadline.signal);
263
+ } catch (error) {
264
+ if (upstream.aborted && error === upstream.reason) return "";
265
+ throw error;
266
+ }
261
267
  const marker = markers();
262
268
  const wrapped = wrapCommand(command, marker);
263
269
  const startedAt = Date.now();
@@ -301,7 +307,7 @@ async function executeCommand(ctx, shells, owner, command, config, upstream) {
301
307
  }
302
308
  if (commandDeadline.signal.aborted) {
303
309
  await shells.reset(owner, "persistent bash command aborted");
304
- commandDeadline.signal.throwIfAborted();
310
+ return "";
305
311
  }
306
312
  if (captured.text.includes(marker.end)) {
307
313
  const complete = commandOutput(captured, marker);
@@ -367,7 +373,7 @@ function registerPersistentBash(ctx, config) {
367
373
  const owner = exec.agent;
368
374
  if (owner === void 0) throw new Error("bash requires an owning agent session");
369
375
  return serialized(owner, async () => {
370
- exec.signal.throwIfAborted();
376
+ if (exec.signal.aborted) return "";
371
377
  return executeCommand(ctx, shells, owner, args.command, config, exec.signal);
372
378
  });
373
379
  },
@@ -270,7 +270,7 @@ const Config = z.object({
270
270
  allow: z.array(z.string()).default(void 0),
271
271
  deny: z.array(z.string()).default(void 0)
272
272
  }).default(void 0),
273
- maxDepth: z.union([z.natural().max(Number.MAX_SAFE_INTEGER), z.const("provider-managed")]).default(3)
273
+ maxDepth: z.union([z.natural().max(Number.MAX_SAFE_INTEGER), z.const("provider-managed")])
274
274
  });
275
275
  /** Render text blocks from the canonical JSON block array without trusting arbitrary values. */
276
276
  function outputValueText(values) {
@@ -378,7 +378,7 @@ function apply(ctx, config, session) {
378
378
  const modelSelectionCapable = config.modelSelectionSettings === true;
379
379
  ctx.sessionProjections.register(subagentModelSelectionProjectionDefinition);
380
380
  const assertSubagentProviderConfiguration = (subagentProvider) => {
381
- if (typeof config.maxDepth === "number" && !subagentProvider.capabilities.depthLimit) throw new Error(`tool-subagent: provider "${subagentProvider.name}" cannot enforce maxDepth (no depthLimit capability) — set maxDepth: 'provider-managed' to leave the recursion budget to the provider`);
381
+ if (ctx.subagents.resolveMaxDepth(config.maxDepth) !== void 0 && !subagentProvider.capabilities.depthLimit) throw new Error(`tool-subagent: provider "${subagentProvider.name}" cannot enforce maxDepth (no depthLimit capability) — set maxDepth: 'provider-managed' to leave the recursion budget to the provider`);
382
382
  if (config.agentOptions !== void 0 && !subagentProvider.capabilities.agentOptions) throw new Error(`tool-subagent: provider "${subagentProvider.name}" does not support child agentOptions`);
383
383
  if (modelSelectionCapable && !subagentProvider.capabilities.agentOptions) throw new Error(`tool-subagent: provider "${subagentProvider.name}" does not support child model selection`);
384
384
  if (continuable && subagentProvider.prepareContinuable === void 0) throw new Error(`tool-subagent: provider "${subagentProvider.name}" does not support \`backgroundMode: continuable\``);
@@ -401,7 +401,7 @@ function apply(ctx, config, session) {
401
401
  subagentProvider,
402
402
  disposeTool: runtimeCtx.tools.register(defineTool({
403
403
  name: toolName,
404
- description: wording.description + (backgroundEnabled ? continuable ? " This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` steers the child's nearest step while it is running and starts a turn while it is idle. Set `run_in_background: false` only when your next action depends on receiving the result." : " This call waits for the result by default. Set `run_in_background: true` to return a job id; collect with `job_output` and stop with `job_kill`." : " This call waits for the subagent and returns its result.") + choiceDescription + (continuable && (config.provider === "spawn" || config.provider === "fork") ? " Set worktree: true for an isolated Git checkout when agents edit in parallel. It starts at HEAD and refuses a dirty parent workspace; omit for read-only tasks or when the child needs uncommitted parent edits. You must inspect and integrate its changes; the worktree remains after completion." : ""),
404
+ description: wording.description + (backgroundEnabled ? continuable ? " This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` steers the child's nearest step while it is running and starts or resumes a turn while it is inactive. Set `run_in_background: false` only when your next action depends on receiving the result." : " This call waits for the result by default. Set `run_in_background: true` to return a job id; collect with `job_output` and stop with `job_kill`." : " This call waits for the subagent and returns its result.") + choiceDescription + (continuable && (config.provider === "spawn" || config.provider === "fork") ? " Set worktree: true for an isolated Git checkout when agents edit in parallel. It starts at HEAD and refuses a dirty parent workspace; omit for read-only tasks or when the child needs uncommitted parent edits. You must inspect and integrate its changes; the worktree remains after completion." : ""),
405
405
  parameters: {
406
406
  name: {
407
407
  type: "string",
@@ -530,7 +530,7 @@ Inspect and integrate its changes before removing it.` : "")
530
530
  exec.signal.throwIfAborted();
531
531
  if (args.worktree === true && !(continuable && (config.provider === "spawn" || config.provider === "fork"))) throw new Error("worktree is unavailable for this subagent provider");
532
532
  const childWorktree = args.worktree === true ? await createChildWorktree(parent.session.header.cwd, exec.signal) : void 0;
533
- const maxDepth = typeof config.maxDepth === "number" ? config.maxDepth : void 0;
533
+ const maxDepth = runtimeCtx.subagents.resolveMaxDepth(config.maxDepth);
534
534
  const request = {
535
535
  label: "/" + args.name + " · " + args.description,
536
536
  ...childWorktree ? { workspaceCwd: childWorktree.cwd } : {},
@@ -566,7 +566,7 @@ Inspect and integrate its changes before removing it.` : "")
566
566
  jobId: jobs.start({
567
567
  kind: "subagent",
568
568
  label: "/" + args.name + " · " + args.description,
569
- owner: parent,
569
+ owner: parent.id,
570
570
  run: () => {
571
571
  const controller = new AbortController();
572
572
  return {
@@ -648,7 +648,9 @@ Inspect and integrate its changes before removing it.` : "")
648
648
  const installing = /* @__PURE__ */ new WeakSet();
649
649
  const belongsToComposition = (candidate) => scopeChainOf(scopeOf(candidate.ctx)).includes(compositionScope);
650
650
  const installScoped = (candidate) => {
651
- if (scopedInstalls.has(candidate) || installing.has(candidate)) return;
651
+ const existing = scopedInstalls.get(candidate);
652
+ if (existing !== void 0) return existing;
653
+ if (installing.has(candidate)) return;
652
654
  installing.add(candidate);
653
655
  let fiber;
654
656
  try {
@@ -664,6 +666,7 @@ Inspect and integrate its changes before removing it.` : "")
664
666
  installing.delete(candidate);
665
667
  }
666
668
  scopedInstalls.set(candidate, fiber);
669
+ return fiber;
667
670
  };
668
671
  const removeScoped = (candidate) => {
669
672
  const fiber = scopedInstalls.get(candidate);
@@ -678,8 +681,8 @@ Inspect and integrate its changes before removing it.` : "")
678
681
  for (const candidate of agents.list()) if (belongsToComposition(candidate)) installScoped(candidate);
679
682
  else removeScoped(candidate);
680
683
  };
681
- ctx.on("agent/created", ({ agent: created }) => {
682
- installScoped(created);
684
+ ctx.on("agent/created", async ({ agent: created }) => {
685
+ await installScoped(created);
683
686
  });
684
687
  ctx.on("agent/disposed", ({ agent: disposed }) => {
685
688
  removeScoped(disposed);
@@ -37,58 +37,32 @@ function assertAllowedModelRoutes(routes) {
37
37
  }
38
38
  //#endregion
39
39
  //#region lib/types/model-selection-settings.js
40
- /** Host-owned opt-in setting for model-selectable subagent delegation. */
41
- /** User-settings section for model-selectable subagent delegation. */
42
- const SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE = "subagent-model-selection";
43
- /** Schema served to settings clients for the opt-in preference. */
44
- const SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA = z.object({
45
- enabled: z.boolean().default(false),
46
- allowedModels: z.array(AllowedModelRouteSchema).default([])
47
- });
48
40
  /** Singleton settings owner read when delegation tools are composed for a Session. */
49
41
  var SubagentModelSelectionConfig = class extends Service {
42
+ config;
50
43
  static Config = z.object({
51
- enabled: z.boolean().default(false),
52
- allowedModels: z.array(AllowedModelRouteSchema).default([])
44
+ enabled: z.boolean().default(false).volatile(),
45
+ allowedModels: z.array(AllowedModelRouteSchema).default([]).volatile()
53
46
  });
54
- source;
55
- constructor(ctx, config = {}) {
47
+ constructor(ctx, config) {
56
48
  super(ctx, "subagentModelSelection");
57
- /* v8 ignore next */
58
- const entry = {
59
- enabled: config.enabled ?? false,
60
- allowedModels: config.allowedModels ?? []
61
- };
62
- this.validate(entry);
63
- this.source = () => entry;
64
- ctx.inject(["settings"], (settingsCtx) => {
65
- settingsCtx.settings.installSection(ctx, SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE, SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA, entry, {
66
- setSource: (source) => {
67
- this.source = source;
68
- },
69
- validate: (value) => {
70
- this.validate(value);
71
- },
72
- onChange: () => {}
73
- });
74
- });
49
+ this.config = config;
75
50
  }
76
51
  /**
77
52
  * Read a detached selection preference for the next eligible Session composition.
78
53
  * @returns the enabled state and exact allowed routes.
79
54
  */
80
55
  current() {
81
- const current = this.source();
56
+ const enabled = this.config.enabled.get();
57
+ const allowedModels = this.config.allowedModels.get();
58
+ assertAllowedModelRoutes(allowedModels);
59
+ if (enabled && allowedModels.length === 0) throw new Error("enabled subagent model selection requires at least one allowed model");
82
60
  return {
83
- enabled: current.enabled,
84
- allowedModels: current.allowedModels.map((route) => ({ ...route }))
61
+ enabled,
62
+ allowedModels: allowedModels.map((route) => ({ ...route }))
85
63
  };
86
64
  }
87
- validate(value) {
88
- assertAllowedModelRoutes(value.allowedModels);
89
- if (value.enabled && value.allowedModels.length === 0) throw new Error("enabled subagent model selection requires at least one allowed model");
90
- }
91
65
  };
92
66
  const name = "subagent-model-selection-settings";
93
67
  //#endregion
94
- export { SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE, SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA, SubagentModelSelectionConfig, SubagentModelSelectionConfig as default, name };
68
+ export { SubagentModelSelectionConfig, SubagentModelSelectionConfig as default, name };
@@ -60,13 +60,14 @@ export interface Config {
60
60
  deny?: string[];
61
61
  };
62
62
  /**
63
- * Maximum child depth: a non-negative safe integer (default `3`; `0` forbids
64
- * delegation entirely), or `'provider-managed'` to send no cap. A numeric cap
63
+ * Maximum child depth: a non-negative safe integer (`0` forbids delegation),
64
+ * or `'provider-managed'` to send no cap. A numeric cap
65
65
  * requires the provider's `depthLimit` capability (mount fails loud
66
66
  * otherwise). The provider checks the calling agent's current depth at every
67
67
  * start; the tool remains model-visible so runtime policy owns rejection.
68
68
  * `'provider-managed'` is for an out-of-process provider whose recursion
69
- * budget belongs to the child runtime or its own deployment.
69
+ * budget belongs to the child runtime or its own deployment. Omission reads
70
+ * the current Host subagent depth setting (default `1`) at each delegation.
70
71
  */
71
72
  maxDepth?: number | 'provider-managed';
72
73
  }
@@ -1,4 +1,5 @@
1
1
  /** Host-owned opt-in setting for model-selectable subagent delegation. */
2
+ import type { Volatile } from '@deepseek-ai/cordis';
2
3
  import { Context, Service } from '@deepseek-ai/cordis';
3
4
  import z from '@deepseek-ai/schemastery';
4
5
  import { type AllowedModelRoute } from './model-selection.ts';
@@ -8,8 +9,6 @@ declare module '@deepseek-ai/cordis' {
8
9
  subagentModelSelection: SubagentModelSelectionConfig;
9
10
  }
10
11
  }
11
- /** User-settings section for model-selectable subagent delegation. */
12
- export declare const SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE = "subagent-model-selection";
13
12
  /** Stored user preference; the shipped composition defaults it off. */
14
13
  export interface SubagentModelSelectionSettings {
15
14
  /** Whether newly composed top-level Sessions receive model selection. */
@@ -17,26 +16,29 @@ export interface SubagentModelSelectionSettings {
17
16
  /** Exact child LLM routes offered to newly composed top-level Sessions. */
18
17
  allowedModels: AllowedModelRoute[];
19
18
  }
20
- /** Schema served to settings clients for the opt-in preference. */
21
- export declare const SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA: z<SubagentModelSelectionSettings>;
22
19
  /** Optional deployment base for the preference. */
23
20
  export interface Config {
24
21
  /** Initial enabled state inherited when the user document does not override it. */
25
- enabled?: boolean;
22
+ enabled: Volatile<boolean>;
26
23
  /** Initial route list inherited when the user document does not override it. */
27
- allowedModels?: AllowedModelRoute[];
24
+ allowedModels: Volatile<AllowedModelRoute[]>;
28
25
  }
29
26
  /** Singleton settings owner read when delegation tools are composed for a Session. */
30
27
  export declare class SubagentModelSelectionConfig extends Service {
31
- static Config: z<Config>;
32
- private source;
33
- constructor(ctx: Context, config?: Config);
28
+ private config;
29
+ static Config: z<Schemastery.ObjectS<NoInfer<{
30
+ enabled: z<boolean, boolean, "volatile-defined">;
31
+ allowedModels: z<NoInfer<AllowedModelRoute[]>, NoInfer<AllowedModelRoute[]>, "volatile-defined">;
32
+ }>>, Schemastery.ObjectT<NoInfer<{
33
+ enabled: z<boolean, boolean, "volatile-defined">;
34
+ allowedModels: z<NoInfer<AllowedModelRoute[]>, NoInfer<AllowedModelRoute[]>, "volatile-defined">;
35
+ }>>, "plain">;
36
+ constructor(ctx: Context, config: Config);
34
37
  /**
35
38
  * Read a detached selection preference for the next eligible Session composition.
36
39
  * @returns the enabled state and exact allowed routes.
37
40
  */
38
41
  current(): SubagentModelSelectionSettings;
39
- private validate;
40
42
  }
41
43
  export declare const name = "subagent-model-selection-settings";
42
44
  export default SubagentModelSelectionConfig;