@botlearn-course/daemon 0.0.13-beta.1 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/agent-service-sandbox.d.ts +5 -0
- package/dist/agent-service-sandbox.js +81 -19
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/course-skills-relay.d.ts +2 -0
- package/dist/mcp/course-skills-relay.js +54 -0
- package/dist/mcp/course-skills-server.d.ts +49 -0
- package/dist/mcp/course-skills-server.js +439 -0
- package/dist/run-dispatcher.d.ts +3 -0
- package/dist/run-dispatcher.js +64 -2
- package/dist/runtime-capabilities.d.ts +1 -0
- package/dist/runtime-capabilities.js +4 -0
- package/dist/runtime-env.js +2 -0
- package/dist/runtime-skills.d.ts +93 -0
- package/dist/runtime-skills.js +401 -0
- package/dist/runtimes/deepseek-tui.d.ts +11 -3
- package/dist/runtimes/deepseek-tui.js +488 -48
- package/dist/runtimes/engine.d.ts +10 -0
- package/dist/runtimes/engine.js +12 -5
- package/dist/runtimes/progress.d.ts +2 -0
- package/dist/runtimes/progress.js +34 -0
- package/dist/tool-observation.d.ts +21 -0
- package/dist/tool-observation.js +120 -0
- package/dist/types.d.ts +28 -2
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type CourseRuntime, type RuntimeFailureSummary, type RuntimeProgressDispositions, type RuntimeUsage } from "../types.js";
|
|
2
2
|
import type { Logger } from "../log.js";
|
|
3
3
|
import type { ProgressReport } from "../mcp/report-progress.js";
|
|
4
|
+
import type { PreparedRuntimeSkillProvider, RuntimeSkillEvent } from "../runtime-skills.js";
|
|
4
5
|
/**
|
|
5
6
|
* 内部引擎契约:CLI/ACP 基类实现的是 pull-style options + 回调,
|
|
6
7
|
* 由 wrapEngineAdapter 折叠成对外的 CourseRuntime(sink 语义)。
|
|
@@ -34,19 +35,28 @@ export type RuntimeStatusEvent = {
|
|
|
34
35
|
};
|
|
35
36
|
export interface EngineRunOptions {
|
|
36
37
|
text: string;
|
|
38
|
+
/** Full durable conversation bootstrap, used only if a resumed native thread is missing. */
|
|
39
|
+
recoveryText?: string;
|
|
37
40
|
/** runtime 原生会话 id(resume 用);null 表示新会话。 */
|
|
38
41
|
sessionId: string | null;
|
|
39
42
|
cwd: string;
|
|
43
|
+
/** Daemon-owned state directory for runtime metadata that the model must not mutate. */
|
|
44
|
+
runtimeStateDir?: string;
|
|
40
45
|
signal: AbortSignal;
|
|
41
46
|
extraArgs?: string[];
|
|
42
47
|
systemContext?: string;
|
|
43
48
|
onBlock?: (block: StreamBlock) => void;
|
|
44
49
|
onStatus?: (event: RuntimeStatusEvent) => void;
|
|
45
50
|
env?: NodeJS.ProcessEnv;
|
|
51
|
+
/** Control-side binding. Runtime adapters must not copy its credential into child env. */
|
|
52
|
+
skillProvider?: PreparedRuntimeSkillProvider;
|
|
53
|
+
onSkillEvent?: (event: RuntimeSkillEvent) => Promise<void>;
|
|
46
54
|
}
|
|
47
55
|
export interface EngineRunResult {
|
|
48
56
|
text: string;
|
|
49
57
|
newSessionId: string;
|
|
58
|
+
/** Model identity returned by the runtime API for this turn. */
|
|
59
|
+
model?: string;
|
|
50
60
|
costUsd?: number;
|
|
51
61
|
usage?: RuntimeUsage;
|
|
52
62
|
/** adapter 自身在 emit 前丢弃的进度计数;不包含 accepted,避免 dispatcher 重复计数。 */
|
package/dist/runtimes/engine.js
CHANGED
|
@@ -152,14 +152,14 @@ export function wrapEngineAdapter(id, engine, opts) {
|
|
|
152
152
|
const payload = run.payload;
|
|
153
153
|
// DeepSeek persists and replays the native thread history. The durable Course Service
|
|
154
154
|
// conversation is recovery/bootstrap data, not a second history to inject on every turn.
|
|
155
|
-
|
|
156
|
-
// credential expires with the turn, so a cached thread id cannot suppress durable context.
|
|
157
|
-
const managedActivation = Boolean(run.runtimeEnv?.BOTLEARN_AGENT_SERVICE_ACTIVATION_ID?.trim());
|
|
158
|
-
const resumesDeepseekThread = id === "deepseek-tui" && !managedActivation && Boolean(run.nativeSessionId?.trim());
|
|
155
|
+
const resumesDeepseekThread = id === "deepseek-tui" && Boolean(run.nativeSessionId?.trim());
|
|
159
156
|
const learnerInput = resumesDeepseekThread
|
|
160
157
|
? renderCurrentLearnerRequest(payload)
|
|
161
158
|
: renderConversationInput(payload);
|
|
162
159
|
const text = renderInputAttachments(run, learnerInput);
|
|
160
|
+
const recoveryText = resumesDeepseekThread
|
|
161
|
+
? renderInputAttachments(run, renderConversationInput(payload))
|
|
162
|
+
: undefined;
|
|
163
163
|
if (!text.trim()) {
|
|
164
164
|
throw new RuntimeExecutionError("empty task brief");
|
|
165
165
|
}
|
|
@@ -190,10 +190,16 @@ export function wrapEngineAdapter(id, engine, opts) {
|
|
|
190
190
|
};
|
|
191
191
|
const result = await engine.run({
|
|
192
192
|
text,
|
|
193
|
+
...(recoveryText !== undefined ? { recoveryText } : {}),
|
|
193
194
|
sessionId: run.nativeSessionId ?? null,
|
|
194
195
|
cwd: run.workspaceDir,
|
|
196
|
+
...(run.runtimeStateDir ? { runtimeStateDir: run.runtimeStateDir } : {}),
|
|
195
197
|
signal,
|
|
196
198
|
...(run.runtimeEnv ? { env: run.runtimeEnv } : {}),
|
|
199
|
+
...(run.skillProvider ? { skillProvider: run.skillProvider } : {}),
|
|
200
|
+
...(run.skillProvider && sink.skillEvent
|
|
201
|
+
? { onSkillEvent: (event) => sink.skillEvent(event) }
|
|
202
|
+
: {}),
|
|
197
203
|
...(extraArgs.length > 0 ? { extraArgs } : {}),
|
|
198
204
|
...(systemContext !== undefined ? { systemContext } : {}),
|
|
199
205
|
onBlock: (block) => {
|
|
@@ -232,9 +238,10 @@ export function wrapEngineAdapter(id, engine, opts) {
|
|
|
232
238
|
if (result.progressDispositions) {
|
|
233
239
|
await sink.progressDispositions?.(result.progressDispositions);
|
|
234
240
|
}
|
|
235
|
-
if (result.usage || result.costUsd !== undefined) {
|
|
241
|
+
if (result.model || result.usage || result.costUsd !== undefined) {
|
|
236
242
|
await sink.usage?.({
|
|
237
243
|
...(result.usage ?? {}),
|
|
244
|
+
...(result.model ? { model: result.model } : {}),
|
|
238
245
|
...(result.costUsd !== undefined ? { cost_usd: result.costUsd } : {}),
|
|
239
246
|
});
|
|
240
247
|
}
|
|
@@ -28,6 +28,8 @@ export interface ProgressMcpConfigOptions {
|
|
|
28
28
|
* config, and a path writes a sanitized runtime-readable config below that root.
|
|
29
29
|
*/
|
|
30
30
|
managedRoot?: string | null;
|
|
31
|
+
/** Activation-scoped daemon socket exposed through the clean-env course_skills relay. */
|
|
32
|
+
courseSkillsSocketPath?: string;
|
|
31
33
|
platform?: NodeJS.Platform;
|
|
32
34
|
}
|
|
33
35
|
export declare class ProgressMcpConfigError extends Error {
|
|
@@ -141,6 +141,7 @@ export function createProgressMcpConfig(options = {}) {
|
|
|
141
141
|
throw new ProgressMcpConfigError("managed progress MCP config cannot preserve an existing DeepSeek MCP config");
|
|
142
142
|
}
|
|
143
143
|
const serverPath = fileURLToPath(new URL("../mcp/report-progress-server.js", import.meta.url));
|
|
144
|
+
const courseSkillsRelayPath = fileURLToPath(new URL("../mcp/course-skills-relay.js", import.meta.url));
|
|
144
145
|
const baseConfigPath = managedRoot
|
|
145
146
|
? null
|
|
146
147
|
: options.baseConfigPath === undefined
|
|
@@ -151,6 +152,12 @@ export function createProgressMcpConfig(options = {}) {
|
|
|
151
152
|
if (Object.hasOwn(baseServers, "botlearn")) {
|
|
152
153
|
throw new ProgressMcpConfigError("DeepSeek MCP server key 'botlearn' is reserved for BotLearn progress reporting");
|
|
153
154
|
}
|
|
155
|
+
const courseSkillsSocketPath = options.courseSkillsSocketPath
|
|
156
|
+
? validCourseSkillsSocketPath(options.courseSkillsSocketPath)
|
|
157
|
+
: undefined;
|
|
158
|
+
if (courseSkillsSocketPath && Object.hasOwn(baseServers, "course_skills")) {
|
|
159
|
+
throw new ProgressMcpConfigError("DeepSeek MCP server key 'course_skills' is reserved for BotLearn Course Skills");
|
|
160
|
+
}
|
|
154
161
|
const dir = mkdtempSync(path.join(managedRoot ?? tmpdir(), "botlearn-progress-mcp-"));
|
|
155
162
|
const configPath = path.join(dir, "mcp.json");
|
|
156
163
|
const stagingPath = path.join(dir, ".mcp.json.tmp");
|
|
@@ -170,6 +177,25 @@ export function createProgressMcpConfig(options = {}) {
|
|
|
170
177
|
enabled: true,
|
|
171
178
|
required: false,
|
|
172
179
|
},
|
|
180
|
+
...(courseSkillsSocketPath
|
|
181
|
+
? {
|
|
182
|
+
course_skills: {
|
|
183
|
+
command: "/usr/bin/env",
|
|
184
|
+
args: [
|
|
185
|
+
"-i",
|
|
186
|
+
`PATH=${minimalPath}`,
|
|
187
|
+
process.execPath,
|
|
188
|
+
courseSkillsRelayPath,
|
|
189
|
+
"--socket",
|
|
190
|
+
courseSkillsSocketPath,
|
|
191
|
+
],
|
|
192
|
+
env: {},
|
|
193
|
+
disabled: false,
|
|
194
|
+
enabled: true,
|
|
195
|
+
required: true,
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
: {}),
|
|
173
199
|
},
|
|
174
200
|
};
|
|
175
201
|
try {
|
|
@@ -186,6 +212,14 @@ export function createProgressMcpConfig(options = {}) {
|
|
|
186
212
|
throw error;
|
|
187
213
|
}
|
|
188
214
|
}
|
|
215
|
+
function validCourseSkillsSocketPath(value) {
|
|
216
|
+
if (!path.isAbsolute(value)
|
|
217
|
+
|| value.includes("\0")
|
|
218
|
+
|| Buffer.byteLength(value, "utf8") > 240) {
|
|
219
|
+
throw new ProgressMcpConfigError("course_skills MCP socket path must be a bounded absolute path");
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
189
223
|
function resolveManagedProgressRoot(explicit) {
|
|
190
224
|
if (explicit === null)
|
|
191
225
|
return null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RuntimeBlock } from "./types.js";
|
|
2
|
+
export declare const AGENT_TOOL_OBSERVATION_SCHEMA_VERSION = "agent-tool-observation/0.1";
|
|
3
|
+
export interface ToolObservationPayload extends Record<string, unknown> {
|
|
4
|
+
schema_version: typeof AGENT_TOOL_OBSERVATION_SCHEMA_VERSION;
|
|
5
|
+
kind: "tool_call" | "tool_result";
|
|
6
|
+
runtime: string;
|
|
7
|
+
status: "started" | "completed" | "error";
|
|
8
|
+
name?: string;
|
|
9
|
+
detail_preview?: string;
|
|
10
|
+
detail_truncated: boolean;
|
|
11
|
+
redacted: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Project a provider tool envelope into durable teacher evidence.
|
|
15
|
+
*
|
|
16
|
+
* The projection is deliberately lossy: only operational argument/result fields survive,
|
|
17
|
+
* credentials are removed, host paths become workspace-relative, and the JSON preview is
|
|
18
|
+
* bounded. Provider reasoning, message text, request IDs, and arbitrary envelope metadata
|
|
19
|
+
* never cross this boundary.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildToolObservation(block: RuntimeBlock, runtime: string, workspaceDir: string): ToolObservationPayload | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { REDACTED, redactSecretsDeep, } from "./redaction.js";
|
|
3
|
+
export const AGENT_TOOL_OBSERVATION_SCHEMA_VERSION = "agent-tool-observation/0.1";
|
|
4
|
+
const DETAIL_MAX_CHARS = 4_000;
|
|
5
|
+
const MAX_PROJECT_DEPTH = 8;
|
|
6
|
+
const SAFE_TOOL_NAME = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,79}$/;
|
|
7
|
+
const CALL_FIELDS = new Set([
|
|
8
|
+
"arguments",
|
|
9
|
+
"args",
|
|
10
|
+
"input",
|
|
11
|
+
"command",
|
|
12
|
+
"cmd",
|
|
13
|
+
"cwd",
|
|
14
|
+
"path",
|
|
15
|
+
"file_path",
|
|
16
|
+
"query",
|
|
17
|
+
"url",
|
|
18
|
+
"pattern",
|
|
19
|
+
"patch",
|
|
20
|
+
"changes",
|
|
21
|
+
"edits",
|
|
22
|
+
]);
|
|
23
|
+
const RESULT_FIELDS = new Set([
|
|
24
|
+
"result",
|
|
25
|
+
"output",
|
|
26
|
+
"stdout",
|
|
27
|
+
"stderr",
|
|
28
|
+
"exit_code",
|
|
29
|
+
"status",
|
|
30
|
+
"status_code",
|
|
31
|
+
"error",
|
|
32
|
+
"diff",
|
|
33
|
+
"path",
|
|
34
|
+
"file_path",
|
|
35
|
+
"bytes",
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Project a provider tool envelope into durable teacher evidence.
|
|
39
|
+
*
|
|
40
|
+
* The projection is deliberately lossy: only operational argument/result fields survive,
|
|
41
|
+
* credentials are removed, host paths become workspace-relative, and the JSON preview is
|
|
42
|
+
* bounded. Provider reasoning, message text, request IDs, and arbitrary envelope metadata
|
|
43
|
+
* never cross this boundary.
|
|
44
|
+
*/
|
|
45
|
+
export function buildToolObservation(block, runtime, workspaceDir) {
|
|
46
|
+
if (block.kind !== "tool_call" && block.kind !== "tool_result")
|
|
47
|
+
return null;
|
|
48
|
+
const fields = block.kind === "tool_call" ? CALL_FIELDS : RESULT_FIELDS;
|
|
49
|
+
const projected = collectAllowedFields(block.raw, fields);
|
|
50
|
+
if (typeof block.text === "string" && block.text) {
|
|
51
|
+
projected[block.kind === "tool_call" ? "target" : "summary"] = block.text;
|
|
52
|
+
}
|
|
53
|
+
const normalized = normalizeWorkspacePaths(redactSecretsDeep(projected), path.resolve(workspaceDir));
|
|
54
|
+
const serialized = Object.keys(projected).length > 0
|
|
55
|
+
? JSON.stringify(normalized, null, 2)
|
|
56
|
+
: "";
|
|
57
|
+
const detailTruncated = serialized.length > DETAIL_MAX_CHARS;
|
|
58
|
+
const detailPreview = detailTruncated
|
|
59
|
+
? `${serialized.slice(0, DETAIL_MAX_CHARS - 1)}…`
|
|
60
|
+
: serialized;
|
|
61
|
+
return {
|
|
62
|
+
schema_version: AGENT_TOOL_OBSERVATION_SCHEMA_VERSION,
|
|
63
|
+
kind: block.kind,
|
|
64
|
+
runtime,
|
|
65
|
+
status: block.kind === "tool_call"
|
|
66
|
+
? "started"
|
|
67
|
+
: block.status === "error"
|
|
68
|
+
? "error"
|
|
69
|
+
: "completed",
|
|
70
|
+
...(block.name && SAFE_TOOL_NAME.test(block.name) ? { name: block.name } : {}),
|
|
71
|
+
...(detailPreview ? { detail_preview: detailPreview } : {}),
|
|
72
|
+
detail_truncated: detailTruncated,
|
|
73
|
+
redacted: detailPreview.includes(REDACTED),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function collectAllowedFields(value, allowed, depth = 0, out = {}) {
|
|
77
|
+
if (value === null || typeof value !== "object" || depth >= MAX_PROJECT_DEPTH) {
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(value)) {
|
|
81
|
+
for (const item of value.slice(0, 50)) {
|
|
82
|
+
collectAllowedFields(item, allowed, depth + 1, out);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
for (const [key, item] of Object.entries(value)) {
|
|
87
|
+
if (allowed === RESULT_FIELDS
|
|
88
|
+
&& key === "content"
|
|
89
|
+
&& value.type === "tool_result") {
|
|
90
|
+
if (!("content" in out))
|
|
91
|
+
out.content = item;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (allowed.has(key)) {
|
|
95
|
+
if (!(key in out))
|
|
96
|
+
out[key] = item;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
collectAllowedFields(item, allowed, depth + 1, out);
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
function normalizeWorkspacePaths(value, workspaceDir) {
|
|
104
|
+
if (typeof value === "string") {
|
|
105
|
+
const normalizedWorkspace = workspaceDir.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
106
|
+
const normalizedValue = value.replaceAll("\\", "/");
|
|
107
|
+
return normalizedValue
|
|
108
|
+
.replaceAll(`${normalizedWorkspace}/`, "")
|
|
109
|
+
.replaceAll(normalizedWorkspace, ".");
|
|
110
|
+
}
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
return value.map((item) => normalizeWorkspacePaths(item, workspaceDir));
|
|
113
|
+
}
|
|
114
|
+
if (value === null || typeof value !== "object")
|
|
115
|
+
return value;
|
|
116
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
117
|
+
key,
|
|
118
|
+
normalizeWorkspacePaths(item, workspaceDir),
|
|
119
|
+
]));
|
|
120
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* `services/course-api/botlearn_course/schemas.py` 的 daemon 契约严格对齐。
|
|
6
6
|
*/
|
|
7
7
|
import type { ProgressStatus } from "./mcp/report-progress.js";
|
|
8
|
+
import type { PreparedRuntimeSkillProvider, RuntimeSkillEvent } from "./runtime-skills.js";
|
|
8
9
|
export interface RunInputAttachment {
|
|
9
10
|
attachment_id: string;
|
|
10
11
|
filename: string;
|
|
@@ -53,7 +54,7 @@ export interface RunStartPayload {
|
|
|
53
54
|
* `POST /daemon/runs/{id}/events` 接受的事件类型。
|
|
54
55
|
* 与后端 DaemonRunEventIn.type 的 Literal 严格一致 —— 发送其他类型会得到 422。
|
|
55
56
|
*/
|
|
56
|
-
export type RunEventType = "run.accepted" | "run.started" | "run.block" | "run.message" | "run.completed" | "run.failed" | "run.cancelled";
|
|
57
|
+
export type RunEventType = "run.accepted" | "run.started" | "run.block" | "run.observation" | "run.message" | "run.completed" | "run.failed" | "run.cancelled";
|
|
57
58
|
export interface RunEvent {
|
|
58
59
|
type: RunEventType;
|
|
59
60
|
/** End-to-end correlation id assigned by Course Service. */
|
|
@@ -125,7 +126,10 @@ export interface AppliedRunRuntimeProfile {
|
|
|
125
126
|
export interface RuntimeContentBlock {
|
|
126
127
|
kind: "text_delta" | "text" | "thinking" | "tool_call" | "tool_result" | "status" | "error";
|
|
127
128
|
text?: string;
|
|
128
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Safe provider-normalized tool identifier. Raw envelopes stay local; the dispatcher may
|
|
131
|
+
* derive a separate bounded/redacted teacher observation from explicit operation fields.
|
|
132
|
+
*/
|
|
129
133
|
name?: string;
|
|
130
134
|
/** Public lifecycle metadata; never carries provider reasoning or tool output. */
|
|
131
135
|
phase?: "in_progress" | "completed";
|
|
@@ -149,13 +153,26 @@ export interface RuntimeProgressDispositions {
|
|
|
149
153
|
}
|
|
150
154
|
/** Content-free model usage; adapters populate only fields actually reported upstream. */
|
|
151
155
|
export interface RuntimeUsage {
|
|
156
|
+
/** Model identity resolved by the runtime/provider, not inferred by the daemon. */
|
|
157
|
+
model?: string;
|
|
152
158
|
input_tokens?: number;
|
|
153
159
|
cached_input_tokens?: number;
|
|
154
160
|
output_tokens?: number;
|
|
161
|
+
reasoning_tokens?: number;
|
|
155
162
|
total_tokens?: number;
|
|
156
163
|
cost_usd?: number;
|
|
157
164
|
provider_request_ids?: string[];
|
|
158
165
|
}
|
|
166
|
+
/** Content-free shape of one runtime-native completion. */
|
|
167
|
+
export interface RuntimeCompletionSummary {
|
|
168
|
+
assistant_message_count: number;
|
|
169
|
+
reasoning_message_count: number;
|
|
170
|
+
assistant_content_present: boolean;
|
|
171
|
+
reasoning_content_present: boolean;
|
|
172
|
+
tool_call_count: number;
|
|
173
|
+
turn_status?: string;
|
|
174
|
+
finish_reason?: string;
|
|
175
|
+
}
|
|
159
176
|
export interface RuntimeAuthProbe {
|
|
160
177
|
checked: boolean;
|
|
161
178
|
ok: boolean;
|
|
@@ -179,12 +196,16 @@ export interface CourseRuntimeSink {
|
|
|
179
196
|
usage?(usage: RuntimeUsage): Promise<void>;
|
|
180
197
|
/** Persist the runtime-native thread/session id before a terminal turn event is emitted. */
|
|
181
198
|
runtimeSession?(sessionId: string): Promise<void>;
|
|
199
|
+
/** Content-free technical evidence from the control-side Runtime Skill Provider. */
|
|
200
|
+
skillEvent?(event: RuntimeSkillEvent): Promise<void>;
|
|
182
201
|
}
|
|
183
202
|
/** 一次 run 的本地执行上下文:服务器 payload + daemon 本地准备产物。 */
|
|
184
203
|
export interface RunExecution {
|
|
185
204
|
payload: RunStartPayload;
|
|
186
205
|
/** Runtime cwd. Managed persistent sessions reuse one session-scoped workspace. */
|
|
187
206
|
workspaceDir: string;
|
|
207
|
+
/** Daemon-owned state directory for one managed RuntimeSession; never exposed to the model. */
|
|
208
|
+
runtimeStateDir?: string;
|
|
188
209
|
/** Runtime-native thread/session id to resume; null creates the first native session. */
|
|
189
210
|
nativeSessionId?: string | null;
|
|
190
211
|
/** Monotonic Course Service context revision accepted for this turn. */
|
|
@@ -193,6 +214,8 @@ export interface RunExecution {
|
|
|
193
214
|
runtimeEnv?: NodeJS.ProcessEnv;
|
|
194
215
|
/** Verified learner files materialized beneath the runtime workspace. */
|
|
195
216
|
inputAttachments?: MaterializedInputAttachment[];
|
|
217
|
+
/** Activation-scoped provider held by the daemon control process, never runtime env. */
|
|
218
|
+
skillProvider?: PreparedRuntimeSkillProvider;
|
|
196
219
|
}
|
|
197
220
|
export interface CourseRuntime {
|
|
198
221
|
id: string;
|
|
@@ -224,7 +247,10 @@ export interface RuntimeFailureSummary {
|
|
|
224
247
|
stderr_tail?: string;
|
|
225
248
|
stdout_tail?: string;
|
|
226
249
|
error_name?: string;
|
|
250
|
+
error_code?: string;
|
|
227
251
|
error_message?: string;
|
|
252
|
+
model?: string;
|
|
253
|
+
completion?: RuntimeCompletionSummary;
|
|
228
254
|
}
|
|
229
255
|
export interface RuntimeModule {
|
|
230
256
|
id: string;
|
package/package.json
CHANGED