@botlearn-course/daemon 0.0.7 → 0.0.8
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/dist/agent-service-client.js +8 -8
- package/dist/agent-service-sandbox.d.ts +108 -0
- package/dist/agent-service-sandbox.js +1400 -0
- package/dist/agent-service-ws-protocol.d.ts +15 -7
- package/dist/agent-service-ws-protocol.js +86 -24
- package/dist/cli.js +26 -53
- package/dist/course-client.js +9 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run-dispatcher.d.ts +3 -0
- package/dist/run-dispatcher.js +21 -2
- package/dist/runtime-env.d.ts +6 -0
- package/dist/runtime-env.js +35 -2
- package/dist/runtime-profile.js +12 -1
- package/dist/runtimes/deepseek-tui.d.ts +3 -2
- package/dist/runtimes/deepseek-tui.js +33 -7
- package/dist/runtimes/engine.js +4 -1
- package/dist/runtimes/fake.js +102 -6
- package/dist/sandbox-supervisor.d.ts +1 -1
- package/dist/sandbox-supervisor.js +23 -23
- package/dist/workspace.d.ts +27 -4
- package/dist/workspace.js +96 -23
- package/package.json +1 -1
- package/dist/agent-service-session.d.ts +0 -67
- package/dist/agent-service-session.js +0 -799
|
@@ -17,8 +17,8 @@ export class AgentServiceRunClient {
|
|
|
17
17
|
}
|
|
18
18
|
url(path) {
|
|
19
19
|
const base = this.baseUrl.replace(/\/+$/, "");
|
|
20
|
-
if (base.endsWith("/
|
|
21
|
-
return `${base}${path.slice("/
|
|
20
|
+
if (base.endsWith("/course/v1") && path.startsWith("/course/v1/")) {
|
|
21
|
+
return `${base}${path.slice("/course/v1".length)}`;
|
|
22
22
|
}
|
|
23
23
|
return `${base}${path}`;
|
|
24
24
|
}
|
|
@@ -40,7 +40,7 @@ export class AgentServiceRunClient {
|
|
|
40
40
|
return (raw ? JSON.parse(raw) : null);
|
|
41
41
|
}
|
|
42
42
|
async getRun() {
|
|
43
|
-
const payload = await this.request("GET", `/
|
|
43
|
+
const payload = await this.request("GET", `/course/v1/agent-service/runs/${this.agentRunId}`);
|
|
44
44
|
this.traceId = payload.trace_id;
|
|
45
45
|
return payload;
|
|
46
46
|
}
|
|
@@ -48,14 +48,14 @@ export class AgentServiceRunClient {
|
|
|
48
48
|
this.assertRunId(agentRunId);
|
|
49
49
|
this.traceId = event.trace_id ?? this.traceId;
|
|
50
50
|
const sanitized = redactSecretsDeep(event, 8, [this.runToken]);
|
|
51
|
-
await this.request("POST", `/
|
|
51
|
+
await this.request("POST", `/course/v1/agent-service/runs/${agentRunId}/events`, sanitized);
|
|
52
52
|
}
|
|
53
53
|
async postFile(agentRunId, file) {
|
|
54
54
|
this.assertRunId(agentRunId);
|
|
55
55
|
const sanitized = redactSecretsDeep(file, 8, [this.runToken]);
|
|
56
56
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
57
57
|
try {
|
|
58
|
-
return await this.request("POST", `/
|
|
58
|
+
return await this.request("POST", `/course/v1/agent-service/runs/${agentRunId}/files`, sanitized);
|
|
59
59
|
}
|
|
60
60
|
catch (err) {
|
|
61
61
|
const retryable = !(err instanceof CourseClientError) || err.status === 429 || err.status >= 500;
|
|
@@ -70,7 +70,7 @@ export class AgentServiceRunClient {
|
|
|
70
70
|
this.assertRunId(agentRunId);
|
|
71
71
|
const data = await readFile(absPath);
|
|
72
72
|
assertNoInjectedCredentials(data, [this.runToken]);
|
|
73
|
-
const path = `/
|
|
73
|
+
const path = `/course/v1/agent-service/runs/${agentRunId}/files/${fileId}/content`;
|
|
74
74
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
75
75
|
let response;
|
|
76
76
|
try {
|
|
@@ -102,10 +102,10 @@ export class AgentServiceRunClient {
|
|
|
102
102
|
}
|
|
103
103
|
async getRunRuntimeProfile(agentRunId) {
|
|
104
104
|
this.assertRunId(agentRunId);
|
|
105
|
-
return this.request("GET", `/
|
|
105
|
+
return this.request("GET", `/course/v1/agent-service/runs/${agentRunId}/runtime-profile`);
|
|
106
106
|
}
|
|
107
107
|
async heartbeat() {
|
|
108
|
-
await this.request("POST", `/
|
|
108
|
+
await this.request("POST", `/course/v1/agent-service/runs/${this.agentRunId}/heartbeat`, { worker_id: this.workerId });
|
|
109
109
|
}
|
|
110
110
|
assertRunId(value) {
|
|
111
111
|
if (value !== this.agentRunId)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type Logger } from "./log.js";
|
|
2
|
+
import { type PersistentSessionExecution, type PreparedPersistentTurn, type RunReportingClient } from "./run-dispatcher.js";
|
|
3
|
+
import type { CourseRuntime, CourseRuntimeProfile, RunEvent, RunFileCandidate, RunFileRecord, RunStartPayload } from "./types.js";
|
|
4
|
+
export interface AgentServiceSandboxOptions {
|
|
5
|
+
wsUrl: string;
|
|
6
|
+
sandboxId: string;
|
|
7
|
+
sandboxToken: string;
|
|
8
|
+
runtimes: Map<string, CourseRuntime>;
|
|
9
|
+
daemonVersion: string;
|
|
10
|
+
log?: Logger;
|
|
11
|
+
random?: () => number;
|
|
12
|
+
sleep?: (ms: number) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Long-running daemon client for one user-scoped managed sandbox (ADR-015).
|
|
16
|
+
*
|
|
17
|
+
* 一个 sandbox 内可承载多个 runtime session(CourseRun Session)。server 通过显式命令帧
|
|
18
|
+
* (session.open/activate/close、turn.start/cancel、sandbox.drain/shutdown/sync)驱动;
|
|
19
|
+
* daemon 同时只允许一个 active session,且整个 sandbox 同时只有一个 active turn。
|
|
20
|
+
*/
|
|
21
|
+
export declare class AgentServiceSandboxClient implements RunReportingClient, PersistentSessionExecution {
|
|
22
|
+
private readonly options;
|
|
23
|
+
private readonly log;
|
|
24
|
+
private readonly random;
|
|
25
|
+
private readonly sleep;
|
|
26
|
+
private readonly state;
|
|
27
|
+
private readonly dispatcher;
|
|
28
|
+
/** agent_run_id → TURN scope(session/attempt/activation),事件与文件帧路由用。 */
|
|
29
|
+
private readonly turnScopes;
|
|
30
|
+
/** 每 run 内嵌 profile(turn payload 自带时优先)。 */
|
|
31
|
+
private readonly runProfiles;
|
|
32
|
+
/** activate 时装配的 per-session profile,turn.start 复用。 */
|
|
33
|
+
private readonly sessionProfiles;
|
|
34
|
+
/** activation-scoped 模型短凭据;只保存在内存中,绝不进入 state.json。 */
|
|
35
|
+
private readonly activationContexts;
|
|
36
|
+
private readonly pendingAcks;
|
|
37
|
+
private readonly pendingFilePrepares;
|
|
38
|
+
private readonly pendingFileCommits;
|
|
39
|
+
private readonly fileGrants;
|
|
40
|
+
private readonly inflightCommands;
|
|
41
|
+
private socket;
|
|
42
|
+
private sandboxGeneration;
|
|
43
|
+
private connectionEpoch;
|
|
44
|
+
private outboundSeq;
|
|
45
|
+
private inboundSeq;
|
|
46
|
+
private activeSessionId;
|
|
47
|
+
/** 全局串行下当前正在执行 turn 的 session(persistNativeSession 路由用)。 */
|
|
48
|
+
private currentTurnSessionId;
|
|
49
|
+
private heartbeatMs;
|
|
50
|
+
private staleMs;
|
|
51
|
+
private stopped;
|
|
52
|
+
private permanentFailure;
|
|
53
|
+
private lifecycleChain;
|
|
54
|
+
constructor(options: AgentServiceSandboxOptions);
|
|
55
|
+
prepareTurn(payload: RunStartPayload): PreparedPersistentTurn;
|
|
56
|
+
persistNativeSession(nativeSessionId: string): void;
|
|
57
|
+
finishTurn(payload: RunStartPayload): void;
|
|
58
|
+
private completePendingActivationCleanup;
|
|
59
|
+
private recoverPendingActivationCleanups;
|
|
60
|
+
run(): Promise<void>;
|
|
61
|
+
stop(): void;
|
|
62
|
+
postEvent(agentRunId: string, event: RunEvent): Promise<void>;
|
|
63
|
+
postFile(agentRunId: string, file: RunFileCandidate): Promise<RunFileRecord>;
|
|
64
|
+
uploadFileContent(agentRunId: string, fileId: string, absPath: string, mimeType?: string): Promise<RunFileRecord>;
|
|
65
|
+
getRunRuntimeProfile(agentRunId: string): Promise<CourseRuntimeProfile>;
|
|
66
|
+
private connectOnce;
|
|
67
|
+
private handleHello;
|
|
68
|
+
private assertServerFrame;
|
|
69
|
+
private handleServerFrame;
|
|
70
|
+
/** sandbox.sync 只做对账:重放 spool、关闭待关 session、应用 drain/shutdown。 */
|
|
71
|
+
private applySync;
|
|
72
|
+
private handleSessionOpen;
|
|
73
|
+
private handleSessionActivate;
|
|
74
|
+
private handleTurnStart;
|
|
75
|
+
private handleTurnCancel;
|
|
76
|
+
/**
|
|
77
|
+
* 幂等关闭一个 runtime session:终止其 runtime 子进程、删除 workspace/native state、
|
|
78
|
+
* 清空本地状态分片,并回 session.closed。未知 session 直接回 closed。
|
|
79
|
+
*/
|
|
80
|
+
private closeSession;
|
|
81
|
+
private reconcileInterruptedCommand;
|
|
82
|
+
private turnContextRevision;
|
|
83
|
+
private activationInstructions;
|
|
84
|
+
private validTurnPayload;
|
|
85
|
+
private scheduleLifecycle;
|
|
86
|
+
private currentLifecycleFence;
|
|
87
|
+
private isCurrentLifecycleFence;
|
|
88
|
+
private runIdsForSession;
|
|
89
|
+
private deactivateSession;
|
|
90
|
+
private sameTurnScope;
|
|
91
|
+
private matchesTurnScope;
|
|
92
|
+
private assertTurnScope;
|
|
93
|
+
private ackEventOrFile;
|
|
94
|
+
private acceptFileGrant;
|
|
95
|
+
private replaySpool;
|
|
96
|
+
private sendHeartbeat;
|
|
97
|
+
private sendCommandAck;
|
|
98
|
+
private sendControlFrame;
|
|
99
|
+
private sendSessionFrame;
|
|
100
|
+
private sendFrame;
|
|
101
|
+
private nextOutboundSeq;
|
|
102
|
+
private spoolFrameCount;
|
|
103
|
+
private spoolBytes;
|
|
104
|
+
private enforceSpoolLimit;
|
|
105
|
+
private rejectPending;
|
|
106
|
+
private rejectPendingFiles;
|
|
107
|
+
private persist;
|
|
108
|
+
}
|