@rebon/cli-linux-x64 0.17.3 → 0.19.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/bin/compose-runtime/package.json +17 -0
- package/bin/compose-runtime/payload/compose/credentials-runtime.js +38 -0
- package/bin/compose-runtime/payload/compose/llm-runtime.js +330 -0
- package/bin/compose-runtime/payload/compose/loop-assembly.js +149 -0
- package/bin/compose-runtime/payload/compose/serve-dispatch.js +82 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-llm.js +313 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-settings.js +43 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-tools.js +20 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-web.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/llm-adapter.js +32 -0
- package/bin/compose-runtime/payload/compose/shims/zod-lite.js +49 -0
- package/bin/compose-runtime/payload/compose/systemprompt-runtime.js +74 -0
- package/bin/compose-runtime/payload/compose/tools-runtime.js +228 -0
- package/bin/compose-runtime/payload/compose/web-runtime.js +204 -0
- package/bin/compose-runtime/payload/vendor/cordis/index.js +1530 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent.js +714 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-core.js +269 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -0
- package/bin/compose-runtime/payload/vendor/dsh/logger-console.js +83 -0
- package/bin/compose-runtime/payload/vendor/dsh/scope.js +287 -0
- package/bin/compose-runtime/payload/vendor/dsh/session.js +1668 -0
- package/bin/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -0
- package/bin/compose-runtime/payload/vendor/dsh/timeout.js +100 -0
- package/bin/compose-runtime/payload/vendor/dsh/timer.js +128 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -0
- package/bin/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -0
- package/bin/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -0
- package/bin/compose-runtime/payload/vendor/schemastery/index.mjs +656 -0
- package/bin/compose-runtime/payload-manifests.json +48 -0
- package/bin/compose-runtime/src/bridge.mjs +142 -0
- package/bin/compose-runtime/src/credentials-runtime.mjs +50 -0
- package/bin/compose-runtime/src/eventsource-stream.mjs +48 -0
- package/bin/compose-runtime/src/index.mjs +7 -0
- package/bin/compose-runtime/src/llm-runtime.mjs +326 -0
- package/bin/compose-runtime/src/loader.mjs +78 -0
- package/bin/compose-runtime/src/loop-assembly.mjs +237 -0
- package/bin/compose-runtime/src/payload.mjs +49 -0
- package/bin/compose-runtime/src/plugin.mjs +59 -0
- package/bin/compose-runtime/src/realm.mjs +223 -0
- package/bin/compose-runtime/src/registry.mjs +191 -0
- package/bin/compose-runtime/src/resolve.mjs +115 -0
- package/bin/compose-runtime/src/systemprompt-runtime.mjs +67 -0
- package/bin/compose-runtime/src/tools-runtime.mjs +239 -0
- package/bin/compose-runtime/src/web-runtime.mjs +209 -0
- package/bin/plugin-host/package.json +11 -0
- package/bin/plugin-host/src/bridge.mjs +64 -0
- package/bin/plugin-host/src/cli.mjs +105 -0
- package/bin/plugin-host/src/framing.mjs +113 -0
- package/bin/plugin-host/src/host.mjs +624 -0
- package/bin/plugin-host/src/json.mjs +196 -0
- package/bin/plugin-host/src/lifecycle.mjs +114 -0
- package/bin/plugin-host/src/loader.mjs +142 -0
- package/bin/plugin-host/src/methods.mjs +256 -0
- package/bin/plugin-host/src/protocol.mjs +129 -0
- package/bin/plugin-host/src/sdk.mjs +7 -0
- package/bin/rebon +0 -0
- package/bin/rebon-boa-helper +0 -0
- package/package.json +4 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// packages/core/system-prompt/src/index.ts
|
|
2
|
+
import { Service } from "@deepseek-ai/cordis";
|
|
3
|
+
import z from "@deepseek-ai/schemastery";
|
|
4
|
+
import { AnonymousEntries, NamedEntries, ScopedLayers, scopeTarget } from "@deepseek-ai/dsh-scope";
|
|
5
|
+
var PERSONA_SECTION = "deployment:persona";
|
|
6
|
+
var PERSONA_ORDER = 0;
|
|
7
|
+
var VARIABLE_NAME = /^[a-z][a-z0-9_]*$/;
|
|
8
|
+
var GROUP_AT = /^\{\{([^{}]*)\}\}/;
|
|
9
|
+
var TOOL_ORDER_REST = "<unlisted-tools>";
|
|
10
|
+
function validateToolOrder(toolOrder) {
|
|
11
|
+
if (toolOrder === void 0) return void 0;
|
|
12
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13
|
+
for (const name of toolOrder) {
|
|
14
|
+
if (seen.has(name)) throw new Error(`toolOrder lists "${name}" more than once`);
|
|
15
|
+
seen.add(name);
|
|
16
|
+
}
|
|
17
|
+
if (!seen.has(TOOL_ORDER_REST)) {
|
|
18
|
+
throw new Error(`toolOrder must contain the "${TOOL_ORDER_REST}" rest entry (where unlisted tools are inserted)`);
|
|
19
|
+
}
|
|
20
|
+
return toolOrder;
|
|
21
|
+
}
|
|
22
|
+
function orderTools(tools, toolOrder, knownNames) {
|
|
23
|
+
const reserved = tools.find((tool) => tool.name === TOOL_ORDER_REST);
|
|
24
|
+
if (reserved !== void 0) {
|
|
25
|
+
throw new Error(`tool provider returned reserved tool name "${TOOL_ORDER_REST}" (reserved for toolOrder's rest entry)`);
|
|
26
|
+
}
|
|
27
|
+
if (toolOrder === void 0) return tools.sort(compareToolNames);
|
|
28
|
+
const unknown = toolOrder.filter((name) => name !== TOOL_ORDER_REST && !knownNames.has(name));
|
|
29
|
+
if (unknown.length > 0) {
|
|
30
|
+
throw new Error(`toolOrder lists unregistered tool${unknown.length > 1 ? "s" : ""} ${unknown.map((name) => `"${name}"`).join(", ")}; known tools: ${[...knownNames].sort().join(", ") || "(none)"}`);
|
|
31
|
+
}
|
|
32
|
+
const listed = new Set(toolOrder);
|
|
33
|
+
const rest = tools.filter((tool) => !listed.has(tool.name)).sort(compareToolNames);
|
|
34
|
+
return toolOrder.flatMap((name) => name === TOOL_ORDER_REST ? rest : tools.filter((tool) => tool.name === name));
|
|
35
|
+
}
|
|
36
|
+
function compareToolNames(a, b) {
|
|
37
|
+
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
38
|
+
}
|
|
39
|
+
function renderPrompt(assembly) {
|
|
40
|
+
return assembly.sections.map((section) => interpolate(section, assembly.variables, "section")).filter((text) => text.length > 0).join("\n\n");
|
|
41
|
+
}
|
|
42
|
+
function renderContextSnapshot(assembly) {
|
|
43
|
+
return joinContextSections(renderContextSections(assembly));
|
|
44
|
+
}
|
|
45
|
+
function joinContextSections(sections) {
|
|
46
|
+
const body = sections.map((section) => section.text).join("\n\n");
|
|
47
|
+
if (body.length === 0) return "";
|
|
48
|
+
return `Current runtime context. This snapshot supersedes earlier runtime-context snapshots.
|
|
49
|
+
|
|
50
|
+
${body}`;
|
|
51
|
+
}
|
|
52
|
+
function renderContextSections(assembly) {
|
|
53
|
+
return assembly.contexts.map((context) => ({ name: context.name, text: interpolate(context, assembly.variables, "context") })).filter((section) => section.text.length > 0);
|
|
54
|
+
}
|
|
55
|
+
function interpolate(input, variables, kind) {
|
|
56
|
+
const text = input.text;
|
|
57
|
+
let result = "";
|
|
58
|
+
let last = 0;
|
|
59
|
+
for (let open = text.indexOf("{{"); open >= 0; open = text.indexOf("{{", last)) {
|
|
60
|
+
const group = GROUP_AT.exec(text.slice(open));
|
|
61
|
+
if (group === null) {
|
|
62
|
+
if (text.indexOf("}}", open + 2) >= 0) {
|
|
63
|
+
throw new Error(`malformed prompt variable reference at "${text.slice(open, open + 16)}\u2026" in ${kind} "${input.name}" (references are complete simple {{name}} groups)`);
|
|
64
|
+
}
|
|
65
|
+
result += text.slice(last, open + 2);
|
|
66
|
+
last = open + 2;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const name = group[0].slice(2, -2);
|
|
70
|
+
if (!VARIABLE_NAME.test(name)) {
|
|
71
|
+
throw new Error(`malformed prompt variable reference "{{${name}}}" in ${kind} "${input.name}" (variable names match ${String(VARIABLE_NAME)})`);
|
|
72
|
+
}
|
|
73
|
+
if (!Object.hasOwn(variables, name)) {
|
|
74
|
+
const known = Object.keys(variables);
|
|
75
|
+
throw new Error(`unknown prompt variable "{{${name}}}" in ${kind} "${input.name}"; registered variables: ${known.length > 0 ? known.join(", ") : "(none)"}`);
|
|
76
|
+
}
|
|
77
|
+
const value = variables[name];
|
|
78
|
+
if (value === void 0) {
|
|
79
|
+
throw new Error(`prompt variable "{{${name}}}" has no value for this assembly (${kind} "${input.name}")`);
|
|
80
|
+
}
|
|
81
|
+
result += text.slice(last, open) + value;
|
|
82
|
+
last = open + group[0].length;
|
|
83
|
+
}
|
|
84
|
+
return result + text.slice(last);
|
|
85
|
+
}
|
|
86
|
+
var PromptLayer = class {
|
|
87
|
+
sections;
|
|
88
|
+
contexts;
|
|
89
|
+
runtimeContextSuppressors = new AnonymousEntries();
|
|
90
|
+
toolProviders = new AnonymousEntries();
|
|
91
|
+
variables;
|
|
92
|
+
/**
|
|
93
|
+
* Create one prompt layer with diagnostics specific to its ownership scope.
|
|
94
|
+
* @param scope - the scoped owner, or `undefined` for global registrations.
|
|
95
|
+
*/
|
|
96
|
+
constructor(scope) {
|
|
97
|
+
this.sections = new NamedEntries((name) => new Error(scope === void 0 ? `prompt section "${name}" is already registered (for a per-agent override, register through that agent's \`agent.ctx\` instead)` : `prompt section "${name}" is already registered in this scope`));
|
|
98
|
+
this.contexts = new NamedEntries((name) => new Error(scope === void 0 ? `prompt context "${name}" is already registered (for a per-agent override, register through that agent's \`agent.ctx\` instead)` : `prompt context "${name}" is already registered in this scope`));
|
|
99
|
+
this.variables = new NamedEntries((name) => new Error(scope === void 0 ? `prompt variable "${name}" is already registered (for a per-agent value, register through that agent's \`agent.ctx\` instead)` : `prompt variable "${name}" is already registered in this scope`));
|
|
100
|
+
}
|
|
101
|
+
/** @returns whether this layer owns no prompt registrations. */
|
|
102
|
+
isEmpty() {
|
|
103
|
+
return this.sections.isEmpty() && this.contexts.isEmpty() && this.runtimeContextSuppressors.isEmpty() && this.toolProviders.isEmpty() && this.variables.isEmpty();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var SystemPrompt = class extends Service {
|
|
107
|
+
static Config = z.object({
|
|
108
|
+
includeHarnessIdentity: z.boolean().default(true),
|
|
109
|
+
includeRuntimeContext: z.boolean().default(true),
|
|
110
|
+
persona: z.string().default(""),
|
|
111
|
+
// Preserve omission because an explicit empty order lacks the rest marker.
|
|
112
|
+
toolOrder: z.array(z.string()).default(void 0)
|
|
113
|
+
});
|
|
114
|
+
layers = new ScopedLayers(
|
|
115
|
+
(scope) => new PromptLayer(scope),
|
|
116
|
+
() => {
|
|
117
|
+
this.ctx.emit("system-prompt/change");
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
toolOrder;
|
|
121
|
+
constructor(ctx, config) {
|
|
122
|
+
super(ctx, "systemPrompt");
|
|
123
|
+
this.toolOrder = validateToolOrder(config.toolOrder);
|
|
124
|
+
if (config.includeHarnessIdentity ?? true) {
|
|
125
|
+
this.section({
|
|
126
|
+
name: "harness:identity",
|
|
127
|
+
order: -100,
|
|
128
|
+
text: "You are an AI agent powered by DeepSeek Harness."
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
this.section({
|
|
132
|
+
name: PERSONA_SECTION,
|
|
133
|
+
order: PERSONA_ORDER,
|
|
134
|
+
// The fallback narrows the optional input type; the schema already defaults it.
|
|
135
|
+
text: config.persona ?? ""
|
|
136
|
+
});
|
|
137
|
+
if (!(config.includeRuntimeContext ?? true)) this.suppressRuntimeContext();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Register an ordered prompt section in the calling context's scope. A scoped
|
|
141
|
+
* section shadows a global section with the same name; duplicates within one
|
|
142
|
+
* layer and non-finite orders throw. Registration and disposal emit
|
|
143
|
+
* `system-prompt/change`.
|
|
144
|
+
* @param section - the section to register.
|
|
145
|
+
* @returns the exact Cordis effect disposer.
|
|
146
|
+
*/
|
|
147
|
+
section(section) {
|
|
148
|
+
if (!Number.isFinite(section.order)) {
|
|
149
|
+
throw new TypeError(`prompt section "${section.name}" order must be a finite number`);
|
|
150
|
+
}
|
|
151
|
+
return this.layers.effect(
|
|
152
|
+
this.ctx,
|
|
153
|
+
(layer) => layer.sections.insert(section.name, section),
|
|
154
|
+
{ label: "systemPrompt.section()" }
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Register ordered dynamic context in the calling context's scope. Scoped
|
|
159
|
+
* entries shadow global entries with the same name.
|
|
160
|
+
* @param context - the context contribution to register.
|
|
161
|
+
* @returns the exact Cordis effect disposer.
|
|
162
|
+
*/
|
|
163
|
+
context(context) {
|
|
164
|
+
if (!Number.isFinite(context.order)) {
|
|
165
|
+
throw new TypeError(`prompt context "${context.name}" order must be a finite number`);
|
|
166
|
+
}
|
|
167
|
+
return this.layers.effect(
|
|
168
|
+
this.ctx,
|
|
169
|
+
(layer) => layer.contexts.insert(context.name, context),
|
|
170
|
+
{ label: "systemPrompt.context()" }
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Suppress every dynamic runtime-context contribution in the calling
|
|
175
|
+
* context's scope without changing the services that own or enforce those
|
|
176
|
+
* facts. Multiple suppressors remain independently disposable.
|
|
177
|
+
* @returns the exact Cordis effect disposer.
|
|
178
|
+
*/
|
|
179
|
+
suppressRuntimeContext() {
|
|
180
|
+
return this.layers.effect(
|
|
181
|
+
this.ctx,
|
|
182
|
+
(layer) => layer.runtimeContextSuppressors.append(true),
|
|
183
|
+
{ label: "systemPrompt.suppressRuntimeContext()" }
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Register a tool-schema provider in the calling context's scope. Global and
|
|
188
|
+
* matching scoped providers both contribute; returning the reserved
|
|
189
|
+
* {@link TOOL_ORDER_REST} name makes assembly fail.
|
|
190
|
+
* @param provider - evaluated for each assembly with its context.
|
|
191
|
+
* @returns the exact Cordis effect disposer.
|
|
192
|
+
*/
|
|
193
|
+
tools(provider) {
|
|
194
|
+
return this.layers.effect(
|
|
195
|
+
this.ctx,
|
|
196
|
+
(layer) => layer.toolProviders.append(provider),
|
|
197
|
+
{ label: "systemPrompt.tools()" }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Register a prompt variable in the calling context's scope. Scoped values
|
|
202
|
+
* shadow globals; invalid or duplicate names throw. A provider may return
|
|
203
|
+
* `undefined`, but rendering a section that references that value then fails.
|
|
204
|
+
* @param name - the `[a-z][a-z0-9_]*` reference name.
|
|
205
|
+
* @param provider - evaluated for each assembly.
|
|
206
|
+
* @returns the exact Cordis effect disposer.
|
|
207
|
+
*/
|
|
208
|
+
variable(name, provider) {
|
|
209
|
+
if (!VARIABLE_NAME.test(name)) {
|
|
210
|
+
throw new Error(`invalid prompt variable name "${name}" (must match ${String(VARIABLE_NAME)})`);
|
|
211
|
+
}
|
|
212
|
+
return this.layers.effect(
|
|
213
|
+
this.ctx,
|
|
214
|
+
(layer) => layer.variables.insert(name, provider),
|
|
215
|
+
{ label: "systemPrompt.variable()" }
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Assemble global and scoped providers, detach tool parameters, apply
|
|
220
|
+
* canonical ordering, then run the assembly waterfall. Scoped sections and
|
|
221
|
+
* variables shadow globals. The returned waterfall value is authoritative
|
|
222
|
+
* except that an effective complete section is restored afterwards as the
|
|
223
|
+
* sole prompt section.
|
|
224
|
+
* @param context - the optional scope and plugin-defined assembly fields.
|
|
225
|
+
* @returns the post-waterfall assembly with any complete prompt enforced.
|
|
226
|
+
*/
|
|
227
|
+
// Keep configuration failures on the declared asynchronous error path.
|
|
228
|
+
async assemble(context = {}) {
|
|
229
|
+
const scope = context.scope;
|
|
230
|
+
const scopeLayers = this.layers.chainLayers(scope);
|
|
231
|
+
const runtimeContextSuppressed = !this.layers.global.runtimeContextSuppressors.isEmpty() || scopeLayers.some((layer) => !layer.runtimeContextSuppressors.isEmpty());
|
|
232
|
+
const variables = {};
|
|
233
|
+
for (const [name, provider] of this.layers.global.variables.entries()) {
|
|
234
|
+
variables[name] = provider(context);
|
|
235
|
+
}
|
|
236
|
+
for (const layer of scopeLayers) {
|
|
237
|
+
for (const [name, provider] of layer.variables.entries()) {
|
|
238
|
+
variables[name] = provider(context);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const sectionByName = this.layers.merge(scope, (layer) => layer.sections);
|
|
242
|
+
const contextByName = this.layers.merge(scope, (layer) => layer.contexts);
|
|
243
|
+
const providers = [
|
|
244
|
+
...this.layers.global.toolProviders.values(),
|
|
245
|
+
...scopeLayers.flatMap((layer) => [...layer.toolProviders.values()])
|
|
246
|
+
];
|
|
247
|
+
const collected = [];
|
|
248
|
+
const knownNames = /* @__PURE__ */ new Set();
|
|
249
|
+
for (const provider of providers) {
|
|
250
|
+
const result = provider(context);
|
|
251
|
+
const schemas = result.schemas.map(({ name, description, parameters }) => ({
|
|
252
|
+
name,
|
|
253
|
+
description,
|
|
254
|
+
parameters: structuredClone(parameters)
|
|
255
|
+
}));
|
|
256
|
+
const acceptedKnownNames = result.knownNames ?? schemas.map((tool) => tool.name);
|
|
257
|
+
collected.push(...schemas);
|
|
258
|
+
for (const name of acceptedKnownNames) knownNames.add(name);
|
|
259
|
+
}
|
|
260
|
+
const sectionDefinitions = [...sectionByName.values()].sort((a, b) => a.order - b.order);
|
|
261
|
+
const completeSections = sectionDefinitions.filter((section) => section.complete === true);
|
|
262
|
+
if (completeSections.length > 1) {
|
|
263
|
+
throw new Error(`multiple complete prompt sections are active: ${completeSections.map((section) => JSON.stringify(section.name)).join(", ")}`);
|
|
264
|
+
}
|
|
265
|
+
let completeSection;
|
|
266
|
+
const sections = sectionDefinitions.map((section) => {
|
|
267
|
+
const assembled = {
|
|
268
|
+
name: section.name,
|
|
269
|
+
text: typeof section.text === "function" ? section.text(context) : section.text
|
|
270
|
+
};
|
|
271
|
+
if (section.complete === true) completeSection = { ...assembled };
|
|
272
|
+
return assembled;
|
|
273
|
+
});
|
|
274
|
+
const assembly = {
|
|
275
|
+
sections,
|
|
276
|
+
contexts: runtimeContextSuppressed ? [] : [...contextByName.values()].sort((a, b) => a.order - b.order).map((entry) => ({
|
|
277
|
+
name: entry.name,
|
|
278
|
+
text: typeof entry.text === "function" ? entry.text(context) : entry.text
|
|
279
|
+
})),
|
|
280
|
+
tools: orderTools(collected, this.toolOrder, knownNames),
|
|
281
|
+
variables
|
|
282
|
+
};
|
|
283
|
+
const transformed = await this.ctx.waterfall(
|
|
284
|
+
scopeTarget(this, scope),
|
|
285
|
+
"system-prompt/assemble",
|
|
286
|
+
assembly,
|
|
287
|
+
context,
|
|
288
|
+
() => Promise.resolve(assembly)
|
|
289
|
+
);
|
|
290
|
+
if (completeSection === void 0 && !runtimeContextSuppressed) return transformed;
|
|
291
|
+
return {
|
|
292
|
+
...transformed,
|
|
293
|
+
sections: completeSection === void 0 ? transformed.sections : [completeSection],
|
|
294
|
+
contexts: runtimeContextSuppressed ? [] : transformed.contexts
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
var index_default = SystemPrompt;
|
|
299
|
+
export {
|
|
300
|
+
PERSONA_ORDER,
|
|
301
|
+
PERSONA_SECTION,
|
|
302
|
+
SystemPrompt,
|
|
303
|
+
TOOL_ORDER_REST,
|
|
304
|
+
index_default as default,
|
|
305
|
+
joinContextSections,
|
|
306
|
+
renderContextSections,
|
|
307
|
+
renderContextSnapshot,
|
|
308
|
+
renderPrompt
|
|
309
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// packages/util/timeout/src/index.ts
|
|
2
|
+
var TimeoutReason = class extends Error {
|
|
3
|
+
/**
|
|
4
|
+
* @param code Capability-owned timeout code (e.g. `BASH_TIMEOUT`).
|
|
5
|
+
* @param timeoutMs The deadline that elapsed, in milliseconds.
|
|
6
|
+
*/
|
|
7
|
+
constructor(code, timeoutMs) {
|
|
8
|
+
super(`${code} after ${timeoutMs}ms`);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.timeoutMs = timeoutMs;
|
|
11
|
+
}
|
|
12
|
+
code;
|
|
13
|
+
timeoutMs;
|
|
14
|
+
name = "TimeoutReason";
|
|
15
|
+
};
|
|
16
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
17
|
+
function assertTimerDelay(timeoutMs, name) {
|
|
18
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_TIMER_DELAY_MS) {
|
|
19
|
+
throw new Error(`${name} must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function clampTimeout(requested, def, max, name = "timeoutMs") {
|
|
23
|
+
if (requested !== void 0 && (!Number.isFinite(requested) || requested <= 0)) {
|
|
24
|
+
throw new Error(`${name} must be a positive finite number`);
|
|
25
|
+
}
|
|
26
|
+
return Math.min(requested ?? def, max);
|
|
27
|
+
}
|
|
28
|
+
function deadline(upstream, timeoutMs, code) {
|
|
29
|
+
if (timeoutMs <= 0) {
|
|
30
|
+
return { signal: upstream ?? new AbortController().signal, [Symbol.dispose]() {
|
|
31
|
+
} };
|
|
32
|
+
}
|
|
33
|
+
assertTimerDelay(timeoutMs, "deadline timeoutMs");
|
|
34
|
+
const timer = new AbortController();
|
|
35
|
+
const id = setTimeout(() => {
|
|
36
|
+
timer.abort(new TimeoutReason(code, timeoutMs));
|
|
37
|
+
}, timeoutMs);
|
|
38
|
+
return {
|
|
39
|
+
// AbortSignal.any adopts the reason of whichever source aborts FIRST, so a
|
|
40
|
+
// race resolves to a single cause: timeoutOf() reads TimeoutReason only
|
|
41
|
+
// when the timeout won, and upstream-wins leaves an ordinary abort reason.
|
|
42
|
+
signal: upstream !== void 0 ? AbortSignal.any([upstream, timer.signal]) : timer.signal,
|
|
43
|
+
[Symbol.dispose]() {
|
|
44
|
+
clearTimeout(id);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function idleWatchdog(upstream, timeoutMs, code) {
|
|
49
|
+
assertTimerDelay(timeoutMs, "idleWatchdog timeoutMs");
|
|
50
|
+
const timeout = new AbortController();
|
|
51
|
+
const signal = upstream === void 0 ? timeout.signal : AbortSignal.any([upstream, timeout.signal]);
|
|
52
|
+
let timer;
|
|
53
|
+
let outstanding = false;
|
|
54
|
+
let disposed = false;
|
|
55
|
+
const arm = () => {
|
|
56
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
57
|
+
timer = setTimeout(() => {
|
|
58
|
+
timeout.abort(new TimeoutReason(code, timeoutMs));
|
|
59
|
+
}, timeoutMs);
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
signal,
|
|
63
|
+
async next(iterator) {
|
|
64
|
+
if (disposed) throw new Error("idleWatchdog is disposed");
|
|
65
|
+
if (outstanding) throw new Error("idleWatchdog next is already outstanding");
|
|
66
|
+
outstanding = true;
|
|
67
|
+
arm();
|
|
68
|
+
try {
|
|
69
|
+
return await iterator.next();
|
|
70
|
+
} finally {
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
timer = void 0;
|
|
73
|
+
outstanding = false;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
pulse() {
|
|
77
|
+
if (disposed || !outstanding) return;
|
|
78
|
+
arm();
|
|
79
|
+
},
|
|
80
|
+
[Symbol.dispose]() {
|
|
81
|
+
if (disposed) return;
|
|
82
|
+
disposed = true;
|
|
83
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
84
|
+
timer = void 0;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function timeoutOf(x, code) {
|
|
89
|
+
const reason = x.reason;
|
|
90
|
+
if (!(reason instanceof TimeoutReason)) return void 0;
|
|
91
|
+
return code === void 0 || reason.code === code ? reason : void 0;
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
MAX_TIMER_DELAY_MS,
|
|
95
|
+
TimeoutReason,
|
|
96
|
+
clampTimeout,
|
|
97
|
+
deadline,
|
|
98
|
+
idleWatchdog,
|
|
99
|
+
timeoutOf
|
|
100
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// dsh-vendor/timer/src/index.ts
|
|
2
|
+
import { Service } from "@deepseek-ai/cordis";
|
|
3
|
+
var TimerService = class extends Service {
|
|
4
|
+
constructor(ctx) {
|
|
5
|
+
super(ctx, "timer");
|
|
6
|
+
ctx.mixin("timer", ["timeout", "interval", "throttle", "debounce", "setTimeout", "setInterval"]);
|
|
7
|
+
}
|
|
8
|
+
/** @deprecated use `ctx.timeout()` instead */
|
|
9
|
+
setTimeout(callback, delay) {
|
|
10
|
+
return this.timeout(callback, delay);
|
|
11
|
+
}
|
|
12
|
+
/** @deprecated use `ctx.interval()` instead */
|
|
13
|
+
setInterval(callback, delay) {
|
|
14
|
+
return this.interval(callback, delay);
|
|
15
|
+
}
|
|
16
|
+
timeout(...args) {
|
|
17
|
+
const callback = typeof args[0] === "function" ? args.shift() : void 0;
|
|
18
|
+
const delay = args[0];
|
|
19
|
+
if (callback) {
|
|
20
|
+
const dispose = this.ctx.effect(() => {
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
dispose();
|
|
23
|
+
callback();
|
|
24
|
+
}, delay);
|
|
25
|
+
return () => clearTimeout(timer);
|
|
26
|
+
}, "ctx.timeout()");
|
|
27
|
+
return dispose;
|
|
28
|
+
} else {
|
|
29
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
30
|
+
const dispose = this.ctx.effect(() => {
|
|
31
|
+
const timer = setTimeout(resolve, delay);
|
|
32
|
+
return () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
reject(new Error("Context has been disposed"));
|
|
35
|
+
};
|
|
36
|
+
}, "ctx.timeout()");
|
|
37
|
+
return promise.finally(dispose);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
interval(...args) {
|
|
41
|
+
const callback = typeof args[0] === "function" ? args.shift() : void 0;
|
|
42
|
+
const delay = args[0];
|
|
43
|
+
if (callback) {
|
|
44
|
+
return this.ctx.effect(() => {
|
|
45
|
+
const timer = setInterval(callback, delay);
|
|
46
|
+
return () => clearInterval(timer);
|
|
47
|
+
}, "ctx.interval()");
|
|
48
|
+
} else {
|
|
49
|
+
let done;
|
|
50
|
+
let nextTask;
|
|
51
|
+
const dispose = this.ctx.effect(() => {
|
|
52
|
+
const timer = setInterval(() => {
|
|
53
|
+
nextTask?.resolve({ done: false, value: void 0 });
|
|
54
|
+
}, delay);
|
|
55
|
+
return () => {
|
|
56
|
+
clearInterval(timer);
|
|
57
|
+
if (done) return;
|
|
58
|
+
done = { kind: "throw", reason: new Error("Context has been disposed") };
|
|
59
|
+
nextTask?.reject(done.reason);
|
|
60
|
+
};
|
|
61
|
+
}, "ctx.interval()");
|
|
62
|
+
return {
|
|
63
|
+
next: () => {
|
|
64
|
+
if (!done) return (nextTask = Promise.withResolvers()).promise;
|
|
65
|
+
if (done.kind === "return") return Promise.resolve({ done: true, value: done.value });
|
|
66
|
+
return Promise.reject(done.reason);
|
|
67
|
+
},
|
|
68
|
+
return: (value) => {
|
|
69
|
+
if (!done) done = { kind: "return", value };
|
|
70
|
+
nextTask?.resolve({ done: true, value });
|
|
71
|
+
dispose();
|
|
72
|
+
return Promise.resolve({ done: true, value });
|
|
73
|
+
},
|
|
74
|
+
throw: (reason) => {
|
|
75
|
+
if (!done) done = { kind: "throw", reason };
|
|
76
|
+
nextTask?.reject(reason);
|
|
77
|
+
dispose();
|
|
78
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
79
|
+
},
|
|
80
|
+
[Symbol.asyncIterator]() {
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
_schedule(label, trigger, isDisposed = false) {
|
|
87
|
+
let timer;
|
|
88
|
+
const dispose = this.ctx.effect(() => () => {
|
|
89
|
+
isDisposed = true;
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
}, label);
|
|
92
|
+
const wrapper = (...args) => {
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
timer = trigger(args, isDisposed);
|
|
95
|
+
};
|
|
96
|
+
wrapper.dispose = dispose;
|
|
97
|
+
return wrapper;
|
|
98
|
+
}
|
|
99
|
+
/** Return a throttled function whose timer is disposed with the current fiber. */
|
|
100
|
+
throttle(callback, delay, noTrailing) {
|
|
101
|
+
let lastCall = -Infinity;
|
|
102
|
+
const execute = (...args) => {
|
|
103
|
+
lastCall = Date.now();
|
|
104
|
+
callback(...args);
|
|
105
|
+
};
|
|
106
|
+
return this._schedule("ctx.throttle()", (args, isDisposed) => {
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
const remaining = delay - now + lastCall;
|
|
109
|
+
if (remaining <= 0) {
|
|
110
|
+
execute(...args);
|
|
111
|
+
} else if (!isDisposed) {
|
|
112
|
+
return setTimeout(execute, remaining, ...args);
|
|
113
|
+
}
|
|
114
|
+
}, noTrailing);
|
|
115
|
+
}
|
|
116
|
+
/** Return a debounced function whose timer is disposed with the current fiber. */
|
|
117
|
+
debounce(callback, delay) {
|
|
118
|
+
return this._schedule("ctx.debounce()", (args, isDisposed) => {
|
|
119
|
+
if (isDisposed) return;
|
|
120
|
+
return setTimeout(callback, delay, ...args);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var index_default = TimerService;
|
|
125
|
+
export {
|
|
126
|
+
TimerService,
|
|
127
|
+
index_default as default
|
|
128
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// packages/todo/tool-todo/src/index.ts
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
import { z as zod } from "zod";
|
|
4
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
|
+
var name = "tool-todo";
|
|
6
|
+
var inject = ["tools"];
|
|
7
|
+
var STATUSES = ["pending", "in_progress", "completed"];
|
|
8
|
+
var Config = z.object({
|
|
9
|
+
allowParallelInProgress: z.boolean().required()
|
|
10
|
+
});
|
|
11
|
+
var DESCRIPTION_HEAD = "Record and update a structured task list for the current work. Send the ENTIRE list every call \u2014 it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. ";
|
|
12
|
+
var DESCRIPTION_PARALLEL = "Mark every todo being actively worked on `in_progress` \u2014 several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. ";
|
|
13
|
+
var DESCRIPTION_SINGLE = "Keep AT MOST ONE todo `in_progress` at a time; while work remains, exactly one active task should be `in_progress`. ";
|
|
14
|
+
var DESCRIPTION_TAIL = "Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).";
|
|
15
|
+
function describe(allowParallel) {
|
|
16
|
+
return DESCRIPTION_HEAD + (allowParallel ? DESCRIPTION_PARALLEL : DESCRIPTION_SINGLE) + DESCRIPTION_TAIL;
|
|
17
|
+
}
|
|
18
|
+
function toTodoList(raw, allowParallel) {
|
|
19
|
+
const todos = [];
|
|
20
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21
|
+
let active = 0;
|
|
22
|
+
for (const item of raw) {
|
|
23
|
+
const content = item.content.trim();
|
|
24
|
+
if (content.length === 0) {
|
|
25
|
+
throw new Error("invalid todo: `content` must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
if (seen.has(content)) {
|
|
28
|
+
throw new Error(`invalid todos: duplicate content ${JSON.stringify(content)}`);
|
|
29
|
+
}
|
|
30
|
+
seen.add(content);
|
|
31
|
+
if (item.status === "in_progress") active++;
|
|
32
|
+
todos.push({ content, status: item.status });
|
|
33
|
+
}
|
|
34
|
+
if (!allowParallel && active > 1) {
|
|
35
|
+
throw new Error(`invalid todos: at most one task may be in_progress (got ${active})`);
|
|
36
|
+
}
|
|
37
|
+
return todos;
|
|
38
|
+
}
|
|
39
|
+
var todosProjectionSchema = zod.union([
|
|
40
|
+
zod.array(zod.object({
|
|
41
|
+
content: zod.string(),
|
|
42
|
+
status: zod.union([zod.literal("pending"), zod.literal("in_progress"), zod.literal("completed")])
|
|
43
|
+
})),
|
|
44
|
+
zod.null()
|
|
45
|
+
]);
|
|
46
|
+
function apply(ctx, config) {
|
|
47
|
+
const allowParallel = config.allowParallelInProgress;
|
|
48
|
+
ctx.inject(["sessionProjections"], (projectionCtx) => {
|
|
49
|
+
projectionCtx.sessionProjections.register({
|
|
50
|
+
key: "todos",
|
|
51
|
+
schema: todosProjectionSchema,
|
|
52
|
+
init: () => null,
|
|
53
|
+
apply: (state, event) => {
|
|
54
|
+
if (event.type === "todo/write") return event.data.todos;
|
|
55
|
+
if (event.type === "turn/start") return null;
|
|
56
|
+
return state;
|
|
57
|
+
},
|
|
58
|
+
view: (state) => state,
|
|
59
|
+
stateVersion: 2
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
ctx.tools.register(defineTool({
|
|
63
|
+
name: "todo_write",
|
|
64
|
+
description: describe(allowParallel),
|
|
65
|
+
parameters: {
|
|
66
|
+
todos: {
|
|
67
|
+
type: "array",
|
|
68
|
+
required: true,
|
|
69
|
+
description: "The COMPLETE task list, replacing any previous list.",
|
|
70
|
+
items: {
|
|
71
|
+
type: "object",
|
|
72
|
+
additionalProperties: false,
|
|
73
|
+
properties: {
|
|
74
|
+
content: { type: "string", required: true, description: "What the task is \u2014 a short imperative line." },
|
|
75
|
+
status: {
|
|
76
|
+
type: "string",
|
|
77
|
+
required: true,
|
|
78
|
+
enum: [...STATUSES],
|
|
79
|
+
description: "pending (not started) | in_progress (now) | completed (done)."
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
output: {
|
|
86
|
+
schema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
properties: {
|
|
90
|
+
todos: {
|
|
91
|
+
type: "array",
|
|
92
|
+
required: true,
|
|
93
|
+
items: {
|
|
94
|
+
type: "object",
|
|
95
|
+
additionalProperties: false,
|
|
96
|
+
properties: {
|
|
97
|
+
content: { type: "string", required: true },
|
|
98
|
+
status: { type: "string", required: true, enum: [...STATUSES] }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
counts: {
|
|
103
|
+
type: "object",
|
|
104
|
+
additionalProperties: false,
|
|
105
|
+
required: true,
|
|
106
|
+
properties: {
|
|
107
|
+
pending: { type: "integer", required: true },
|
|
108
|
+
inProgress: { type: "integer", required: true },
|
|
109
|
+
completed: { type: "integer", required: true }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
render: (_args, value) => [{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `Updated todo list: ${value.counts.pending} pending, ${value.counts.inProgress} in progress, ${value.counts.completed} completed.`
|
|
117
|
+
}]
|
|
118
|
+
},
|
|
119
|
+
execute(args, exec) {
|
|
120
|
+
const todos = toTodoList(args.todos, allowParallel);
|
|
121
|
+
if (!exec.agent) {
|
|
122
|
+
throw new Error("todo_write requires an owning agent session");
|
|
123
|
+
}
|
|
124
|
+
exec.agent.session.append("todo/write", { todos });
|
|
125
|
+
const count = (status) => todos.filter((t) => t.status === status).length;
|
|
126
|
+
return Promise.resolve({
|
|
127
|
+
todos: todos.map((todo) => ({ content: todo.content, status: todo.status })),
|
|
128
|
+
counts: {
|
|
129
|
+
pending: count("pending"),
|
|
130
|
+
inProgress: count("in_progress"),
|
|
131
|
+
completed: count("completed")
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
presentCall: (args) => ({ card: "generic", title: "Update todo list", kind: "other", rawInput: args.todos })
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
Config,
|
|
140
|
+
apply,
|
|
141
|
+
inject,
|
|
142
|
+
name
|
|
143
|
+
};
|