@rebon/cli-win32-x64 1.3.0 → 1.5.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/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +239 -144
- package/THIRD_PARTY_NOTICES.txt +1232 -1232
- package/bin/rebon.js +22 -22
- package/lib/windows-managed.js +390 -390
- package/package.json +9 -2
- package/payload/compose-runtime/package.json +17 -17
- package/payload/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -13
- package/payload/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -21
- package/payload/compose-runtime/payload/compose/shims/dsh-llm.js +313 -313
- package/payload/compose-runtime/payload/compose/shims/dsh-settings.js +43 -43
- package/payload/compose-runtime/payload/compose/shims/dsh-tools.js +20 -20
- package/payload/compose-runtime/payload/compose/shims/dsh-web.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/llm-adapter.js +32 -32
- package/payload/compose-runtime/payload/compose/shims/zod-lite.js +49 -49
- package/payload/compose-runtime/payload/vendor/cordis/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/cordis/index.js +1530 -1530
- package/payload/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -357
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown-plugin-gfm +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -1193
- package/payload/compose-runtime/payload/vendor/dsh/agent.js +714 -714
- package/payload/compose-runtime/payload/vendor/dsh/llm-core.js +269 -269
- package/payload/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -672
- package/payload/compose-runtime/payload/vendor/dsh/logger-console.js +83 -83
- package/payload/compose-runtime/payload/vendor/dsh/scope.js +287 -287
- package/payload/compose-runtime/payload/vendor/dsh/session.js +1668 -1668
- package/payload/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -309
- package/payload/compose-runtime/payload/vendor/dsh/timeout.js +100 -100
- package/payload/compose-runtime/payload/vendor/dsh/timer.js +128 -128
- package/payload/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -143
- package/payload/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -1527
- package/payload/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -849
- package/payload/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -122
- package/payload/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -177
- package/payload/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -48
- package/payload/compose-runtime/payload/vendor/schemastery/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/schemastery/index.mjs +656 -656
- package/payload/compose-runtime/payload-manifests.json +48 -48
- package/payload/compose-runtime/src/bridge.mjs +193 -195
- package/payload/compose-runtime/src/credentials-runtime.mjs +50 -50
- package/payload/compose-runtime/src/eventsource-stream.mjs +48 -48
- package/payload/compose-runtime/src/index.mjs +7 -7
- package/payload/compose-runtime/src/llm-runtime.mjs +326 -326
- package/payload/compose-runtime/src/loader.mjs +78 -78
- package/payload/compose-runtime/src/loop-assembly.mjs +237 -237
- package/payload/compose-runtime/src/payload.mjs +49 -49
- package/payload/compose-runtime/src/plugin.mjs +59 -59
- package/payload/compose-runtime/src/realm.mjs +223 -223
- package/payload/compose-runtime/src/registry.mjs +191 -191
- package/payload/compose-runtime/src/resolve.mjs +115 -115
- package/payload/compose-runtime/src/systemprompt-runtime.mjs +67 -67
- package/payload/compose-runtime/src/tools-runtime.mjs +239 -239
- package/payload/compose-runtime/src/web-runtime.mjs +209 -209
- package/payload/plugin-host/package.json +11 -11
- package/payload/plugin-host/src/bridge.mjs +64 -64
- package/payload/plugin-host/src/cli.mjs +147 -147
- package/payload/plugin-host/src/framing.mjs +113 -113
- package/payload/plugin-host/src/host.mjs +691 -691
- package/payload/plugin-host/src/json.mjs +208 -208
- package/payload/plugin-host/src/lifecycle.mjs +114 -114
- package/payload/plugin-host/src/loader.mjs +183 -183
- package/payload/plugin-host/src/methods.mjs +377 -377
- package/payload/plugin-host/src/ownership.mjs +57 -57
- package/payload/plugin-host/src/protocol.mjs +129 -129
- package/payload/plugin-host/src/sdk.mjs +7 -7
- package/payload/rebon-boa-helper.exe +0 -0
- package/payload/rebon-browser-mcp.exe +0 -0
- package/payload/rebon-computer-use.exe +0 -0
- package/payload/rebon-lsp-mcp.exe +0 -0
- package/payload/rebon.exe +2 -2
- package/payload/sandbox-win.exe +0 -0
- package/scripts/postinstall.js +112 -112
|
@@ -1,309 +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
|
-
};
|
|
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
|
+
};
|