@downcity/agent 1.1.222 → 1.1.224
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/agent/local/Agent.d.ts +1 -34
- package/bin/agent/local/Agent.d.ts.map +1 -1
- package/bin/agent/local/Agent.js +1 -44
- package/bin/agent/local/Agent.js.map +1 -1
- package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -1
- package/bin/agent/local/services/AgentAssemblyService.js +35 -2
- package/bin/agent/local/services/AgentAssemblyService.js.map +1 -1
- package/bin/agent/local/services/AgentSessions.d.ts +6 -0
- package/bin/agent/local/services/AgentSessions.d.ts.map +1 -1
- package/bin/agent/local/services/AgentSessions.js +42 -0
- package/bin/agent/local/services/AgentSessions.js.map +1 -1
- package/bin/agent/remote/RemoteAgent.d.ts +1 -35
- package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
- package/bin/agent/remote/RemoteAgent.js +1 -37
- package/bin/agent/remote/RemoteAgent.js.map +1 -1
- package/bin/agent/remote/RemoteSession.d.ts +24 -45
- package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
- package/bin/agent/remote/RemoteSession.js +74 -121
- package/bin/agent/remote/RemoteSession.js.map +1 -1
- package/bin/agent/remote/RemoteTransport.d.ts +11 -27
- package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +7 -21
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +11 -47
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +7 -20
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +8 -17
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +2 -2
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
- package/bin/executor/types/SessionHistoryPaths.d.ts +1 -1
- package/bin/index.d.ts +3 -3
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +1 -1
- package/bin/index.js.map +1 -1
- package/bin/rpc/Client.d.ts +7 -36
- package/bin/rpc/Client.d.ts.map +1 -1
- package/bin/rpc/Client.js +28 -78
- package/bin/rpc/Client.js.map +1 -1
- package/bin/session/Session.d.ts +16 -8
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +66 -21
- package/bin/session/Session.js.map +1 -1
- package/bin/session/browse/Browse.d.ts.map +1 -1
- package/bin/session/browse/Browse.js +49 -18
- package/bin/session/browse/Browse.js.map +1 -1
- package/bin/session/recorder/JsonlSessionMessageStore.d.ts +30 -24
- package/bin/session/recorder/JsonlSessionMessageStore.d.ts.map +1 -1
- package/bin/session/recorder/JsonlSessionMessageStore.js +163 -59
- package/bin/session/recorder/JsonlSessionMessageStore.js.map +1 -1
- package/bin/session/recorder/SessionMessageCodec.d.ts.map +1 -1
- package/bin/session/recorder/SessionMessageCodec.js +6 -1
- package/bin/session/recorder/SessionMessageCodec.js.map +1 -1
- package/bin/session/recorder/SessionRecorder.d.ts +20 -11
- package/bin/session/recorder/SessionRecorder.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorder.js +148 -103
- package/bin/session/recorder/SessionRecorder.js.map +1 -1
- package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorderCompaction.js +1 -0
- package/bin/session/recorder/SessionRecorderCompaction.js.map +1 -1
- package/bin/session/recorder/SessionRecorderHistoryStore.d.ts +5 -5
- package/bin/session/recorder/SessionRecorderHistoryStore.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorderHistoryStore.js +5 -5
- package/bin/session/recorder/SessionRecorderHistoryStore.js.map +1 -1
- package/bin/session/runtime/SessionEventHub.d.ts +12 -5
- package/bin/session/runtime/SessionEventHub.d.ts.map +1 -1
- package/bin/session/runtime/SessionEventHub.js +11 -6
- package/bin/session/runtime/SessionEventHub.js.map +1 -1
- package/bin/session/runtime/SessionPromptRuntime.d.ts +2 -2
- package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
- package/bin/session/runtime/SessionPromptRuntime.js +35 -17
- package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
- package/bin/session/services/SessionStateService.d.ts +2 -2
- package/bin/session/services/SessionStateService.d.ts.map +1 -1
- package/bin/session/services/SessionStateService.js +6 -2
- package/bin/session/services/SessionStateService.js.map +1 -1
- package/bin/session/services/SessionTurnService.d.ts +2 -7
- package/bin/session/services/SessionTurnService.d.ts.map +1 -1
- package/bin/session/services/SessionTurnService.js +2 -8
- package/bin/session/services/SessionTurnService.js.map +1 -1
- package/bin/session/storage/Paths.d.ts +1 -1
- package/bin/session/storage/Paths.d.ts.map +1 -1
- package/bin/session/storage/Paths.js +2 -2
- package/bin/session/storage/Paths.js.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.d.ts +3 -4
- package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.js +2 -2
- package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
- package/bin/types/agent/SessionActor.d.ts +11 -7
- package/bin/types/agent/SessionActor.d.ts.map +1 -1
- package/bin/types/rpc/RpcProtocol.d.ts +35 -62
- package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.d.ts +4 -4
- package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.js.map +1 -1
- package/bin/types/session/SessionApproval.d.ts +97 -0
- package/bin/types/session/SessionApproval.d.ts.map +1 -0
- package/bin/types/session/SessionApproval.js +7 -0
- package/bin/types/session/SessionApproval.js.map +1 -0
- package/bin/types/session/SessionMessage.d.ts +10 -4
- package/bin/types/session/SessionMessage.d.ts.map +1 -1
- package/bin/types/session/SessionMutation.d.ts +116 -0
- package/bin/types/session/SessionMutation.d.ts.map +1 -0
- package/bin/types/session/SessionMutation.js +19 -0
- package/bin/types/session/SessionMutation.js.map +1 -0
- package/bin/types/session/SessionOptions.d.ts +9 -0
- package/bin/types/session/SessionOptions.d.ts.map +1 -1
- package/package.json +3 -3
- package/scripts/remote-session-reconnect.test.mjs +7 -3
- package/scripts/session-history-inflight.test.mjs +2 -2
- package/scripts/session-prompt-runtime.test.mjs +3 -3
- package/scripts/session-recorder.test.mjs +100 -146
- package/src/agent/local/Agent.ts +1 -55
- package/src/agent/local/services/AgentAssemblyService.ts +39 -3
- package/src/agent/local/services/AgentSessions.ts +47 -0
- package/src/agent/remote/RemoteAgent.ts +1 -54
- package/src/agent/remote/RemoteSession.ts +105 -163
- package/src/agent/remote/RemoteTransport.ts +23 -34
- package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +33 -90
- package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +22 -39
- package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +2 -2
- package/src/executor/types/SessionHistoryPaths.ts +1 -1
- package/src/index.ts +20 -12
- package/src/rpc/Client.ts +48 -106
- package/src/session/Session.ts +91 -34
- package/src/session/browse/Browse.ts +51 -22
- package/src/session/recorder/JsonlSessionMessageStore.ts +170 -86
- package/src/session/recorder/SessionMessageCodec.ts +6 -1
- package/src/session/recorder/SessionRecorder.ts +183 -124
- package/src/session/recorder/SessionRecorderCompaction.ts +1 -0
- package/src/session/recorder/SessionRecorderHistoryStore.ts +5 -5
- package/src/session/runtime/SessionEventHub.ts +25 -12
- package/src/session/runtime/SessionPromptRuntime.ts +37 -19
- package/src/session/services/SessionStateService.ts +8 -6
- package/src/session/services/SessionTurnService.ts +3 -14
- package/src/session/storage/Paths.ts +2 -2
- package/src/session/storage/RuntimeSessionPort.ts +8 -11
- package/src/types/agent/SessionActor.ts +23 -20
- package/src/types/rpc/RpcProtocol.ts +34 -71
- package/src/types/runtime/agent/AgentContext.ts +7 -11
- package/src/types/session/SessionApproval.ts +108 -0
- package/src/types/session/SessionMessage.ts +10 -4
- package/src/types/session/SessionMutation.ts +141 -0
- package/src/types/session/SessionOptions.ts +25 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/bin/session/recorder/SessionMessageReducer.d.ts +0 -12
- package/bin/session/recorder/SessionMessageReducer.d.ts.map +0 -1
- package/bin/session/recorder/SessionMessageReducer.js +0 -109
- package/bin/session/recorder/SessionMessageReducer.js.map +0 -1
- package/bin/session/runtime/SessionMessageEventHub.d.ts +0 -15
- package/bin/session/runtime/SessionMessageEventHub.d.ts.map +0 -1
- package/bin/session/runtime/SessionMessageEventHub.js +0 -28
- package/bin/session/runtime/SessionMessageEventHub.js.map +0 -1
- package/bin/types/sdk/AgentSessionEvent.d.ts +0 -303
- package/bin/types/sdk/AgentSessionEvent.d.ts.map +0 -1
- package/bin/types/sdk/AgentSessionEvent.js +0 -9
- package/bin/types/sdk/AgentSessionEvent.js.map +0 -1
- package/bin/types/session/SessionMessageMutation.d.ts +0 -92
- package/bin/types/session/SessionMessageMutation.d.ts.map +0 -1
- package/bin/types/session/SessionMessageMutation.js +0 -21
- package/bin/types/session/SessionMessageMutation.js.map +0 -1
- package/src/session/recorder/SessionMessageReducer.ts +0 -155
- package/src/session/runtime/SessionMessageEventHub.ts +0 -35
- package/src/types/sdk/AgentSessionEvent.ts +0 -372
- package/src/types/session/SessionMessageMutation.ts +0 -121
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RemoteSession
|
|
2
|
+
* RemoteSession:统一 SessionMutation 协议的远程 Session 客户端。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* - 这里只负责 session 级 API、turn lifecycle 与事件泵。
|
|
6
|
-
* - 具体 HTTP / RPC 细节由 RemoteSessionTransport 提供。
|
|
4
|
+
* 事件泵只传输一种 Mutation;审批查询、模式和决策全部绑定当前 Session。
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
7
|
import type {
|
|
@@ -14,29 +12,29 @@ import type {
|
|
|
14
12
|
AgentSessionSystemSnapshot,
|
|
15
13
|
} from "@/types/agent/SessionTypes.js";
|
|
16
14
|
import type { RemoteAgentSession } from "@/types/agent/SessionActor.js";
|
|
17
|
-
import { isAgentSessionPromptInputEmpty } from "@/types/sdk/AgentSessionPrompt.js";
|
|
18
|
-
import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
|
|
19
15
|
import type {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
ResolveSessionApprovalInput,
|
|
17
|
+
SessionApproval,
|
|
18
|
+
SessionApprovalModeSnapshot,
|
|
19
|
+
SessionApprovalResult,
|
|
20
|
+
SetSessionApprovalModeInput,
|
|
21
|
+
} from "@/types/session/SessionApproval.js";
|
|
25
22
|
import type {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
SessionMutation,
|
|
24
|
+
SessionMutationSubscriber,
|
|
25
|
+
SessionMutationUnsubscribe,
|
|
26
|
+
} from "@/types/session/SessionMutation.js";
|
|
29
27
|
import type {
|
|
30
28
|
ListSessionMessagesInput,
|
|
31
29
|
SessionMessagePage,
|
|
32
30
|
} from "@/types/session/SessionMessage.js";
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} from "@/types/
|
|
31
|
+
import { isAgentSessionPromptInputEmpty } from "@/types/sdk/AgentSessionPrompt.js";
|
|
32
|
+
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
33
|
+
import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
|
|
34
|
+
import type {
|
|
35
|
+
AgentSessionTurnHandle,
|
|
36
|
+
AgentSessionTurnResult,
|
|
37
|
+
} from "@/types/sdk/AgentSessionTurn.js";
|
|
40
38
|
import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
|
|
41
39
|
import type {
|
|
42
40
|
RemoteSessionTransport,
|
|
@@ -46,29 +44,27 @@ import type {
|
|
|
46
44
|
type Deferred<T> = {
|
|
47
45
|
/** 当前延迟 Promise。 */
|
|
48
46
|
promise: Promise<T>;
|
|
49
|
-
/**
|
|
47
|
+
/** 兑现当前 Promise。 */
|
|
50
48
|
resolve: (value: T) => void;
|
|
51
49
|
};
|
|
52
50
|
|
|
53
51
|
type RemoteTurnLifecycle = {
|
|
54
|
-
/** 当前
|
|
55
|
-
|
|
56
|
-
/** 当前
|
|
52
|
+
/** 当前 Turn 标识。 */
|
|
53
|
+
turn_id: string;
|
|
54
|
+
/** 当前 Turn 的最终结果;运行中为 null。 */
|
|
57
55
|
result: AgentSessionTurnResult | null;
|
|
58
|
-
/** 当前
|
|
56
|
+
/** 当前 Turn 完成 Promise 控制器。 */
|
|
59
57
|
deferred_finished: Deferred<AgentSessionTurnResult>;
|
|
60
58
|
};
|
|
61
59
|
|
|
62
|
-
/**
|
|
63
|
-
* 远程 Session 客户端。
|
|
64
|
-
*/
|
|
60
|
+
/** 远程 Session 客户端。 */
|
|
65
61
|
export class RemoteSession implements RemoteAgentSession {
|
|
66
62
|
readonly id: string;
|
|
67
63
|
readonly agentId: string;
|
|
68
64
|
readonly config: AgentSessionConfigSnapshot;
|
|
69
65
|
|
|
70
66
|
private readonly transport: RemoteSessionTransport;
|
|
71
|
-
private readonly event_hub
|
|
67
|
+
private readonly event_hub: SessionEventHub;
|
|
72
68
|
private readonly turns_by_id = new Map<string, RemoteTurnLifecycle>();
|
|
73
69
|
private readonly completed_turn_ids: string[] = [];
|
|
74
70
|
private event_pump_connect_promise: Promise<void> | null = null;
|
|
@@ -80,72 +76,60 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
80
76
|
this.transport = transport;
|
|
81
77
|
this.id = info.sessionId;
|
|
82
78
|
this.agentId = info.agentId;
|
|
83
|
-
// 远程 session 不暴露服务端模型实例,只保留可序列化配置。
|
|
84
79
|
this.config = {
|
|
85
80
|
...(info.modelId ? { modelId: info.modelId } : {}),
|
|
86
81
|
...(info.modelLabel ? { modelLabel: info.modelLabel } : {}),
|
|
87
82
|
};
|
|
83
|
+
this.event_hub = new SessionEventHub({
|
|
84
|
+
create_reply: (mutation) => ({
|
|
85
|
+
approval: async ({ decision }) => {
|
|
86
|
+
return await this.resolve_approval({
|
|
87
|
+
approval_id: require_approval_id(mutation),
|
|
88
|
+
decision,
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
});
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
/** 按稳定模型 ID 更新远程 Session 模型。 */
|
|
91
96
|
async set(input: AgentSessionSetInput): Promise<void> {
|
|
92
|
-
if (input.model)
|
|
93
|
-
throw new Error("Remote session.set does not accept a local model instance.");
|
|
94
|
-
}
|
|
97
|
+
if (input.model) throw new Error("Remote session.set does not accept a local model instance.");
|
|
95
98
|
const model_id = String(input.modelId || "").trim();
|
|
96
|
-
if (!model_id)
|
|
97
|
-
throw new Error("Remote session.set requires modelId.");
|
|
98
|
-
}
|
|
99
|
+
if (!model_id) throw new Error("Remote session.set requires modelId.");
|
|
99
100
|
const info = await this.transport.set(this.id, { modelId: model_id });
|
|
100
101
|
this.config.modelId = info.modelId;
|
|
101
102
|
this.config.modelLabel = info.modelLabel;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
/**
|
|
105
|
-
* 读取当前远程 session 详情。
|
|
106
|
-
*/
|
|
105
|
+
/** 读取当前远程 Session 详情。 */
|
|
107
106
|
async get_info(): Promise<AgentSessionInfo> {
|
|
108
107
|
return await this.transport.get_info(this.id);
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
/**
|
|
112
|
-
* 向当前远程 session 追加一条新的 prompt。
|
|
113
|
-
*/
|
|
110
|
+
/** 向当前远程 Session 追加 Prompt。 */
|
|
114
111
|
async prompt(input: AgentSessionPromptInput): Promise<AgentSessionTurnHandle> {
|
|
115
112
|
if (isAgentSessionPromptInputEmpty(input)) {
|
|
116
113
|
throw new Error("remote session.prompt requires a non-empty query");
|
|
117
114
|
}
|
|
118
|
-
|
|
119
115
|
await this.ensure_event_pump();
|
|
120
116
|
const turn = await this.transport.prompt(this.id, input);
|
|
121
|
-
|
|
122
|
-
return create_turn_handle(lifecycle);
|
|
117
|
+
return create_turn_handle(this.ensure_turn_lifecycle(turn.id));
|
|
123
118
|
}
|
|
124
119
|
|
|
125
|
-
/**
|
|
126
|
-
* 停止当前远程 session turn,并取消未吸收队列。
|
|
127
|
-
*/
|
|
120
|
+
/** 停止当前远程 Session Turn。 */
|
|
128
121
|
async stop(): Promise<AgentSessionStopResult> {
|
|
129
122
|
await this.ensure_event_pump();
|
|
130
123
|
return await this.transport.stop(this.id);
|
|
131
124
|
}
|
|
132
125
|
|
|
133
|
-
/**
|
|
134
|
-
|
|
135
|
-
*/
|
|
136
|
-
subscribe(
|
|
137
|
-
subscriber: SessionMessageMutationSubscriber,
|
|
138
|
-
): SessionMessageMutationUnsubscribe {
|
|
126
|
+
/** 订阅当前 Session 的全部未来 Mutation。 */
|
|
127
|
+
subscribe(subscriber: SessionMutationSubscriber): SessionMutationUnsubscribe {
|
|
139
128
|
this.event_subscriber_count += 1;
|
|
140
129
|
void this.ensure_event_pump().catch((error) => {
|
|
141
|
-
this.
|
|
142
|
-
type: "error",
|
|
143
|
-
message: error instanceof Error ? error.message : String(error),
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
const unsubscribe = this.event_hub.subscribe((event) => {
|
|
147
|
-
if (is_session_message_mutation(event)) subscriber(event);
|
|
130
|
+
this.fail_pending_turns(error instanceof Error ? error.message : String(error));
|
|
148
131
|
});
|
|
132
|
+
const unsubscribe = this.event_hub.subscribe(subscriber);
|
|
149
133
|
return () => {
|
|
150
134
|
unsubscribe();
|
|
151
135
|
this.event_subscriber_count = Math.max(0, this.event_subscriber_count - 1);
|
|
@@ -153,47 +137,44 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
153
137
|
};
|
|
154
138
|
}
|
|
155
139
|
|
|
156
|
-
/**
|
|
157
|
-
subscribe_transport(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
|
|
158
|
-
return this.event_hub.subscribe(subscriber);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* 读取远程消息历史。
|
|
163
|
-
*/
|
|
140
|
+
/** 读取远程 Message 快照。 */
|
|
164
141
|
async messages(input?: ListSessionMessagesInput): Promise<SessionMessagePage> {
|
|
165
142
|
return await this.transport.messages(this.id, input);
|
|
166
143
|
}
|
|
167
144
|
|
|
168
|
-
/**
|
|
169
|
-
async message_changes(
|
|
170
|
-
input: ListSessionMessageChangesInput,
|
|
171
|
-
): Promise<SessionMessageMutationPage> {
|
|
172
|
-
return await this.transport.message_changes(this.id, input);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* 读取远程 session 当前生效的 system prompt 快照。
|
|
177
|
-
*/
|
|
145
|
+
/** 读取远程 Session 的 System 快照。 */
|
|
178
146
|
async system(): Promise<AgentSessionSystemSnapshot> {
|
|
179
147
|
return await this.transport.system(this.id);
|
|
180
148
|
}
|
|
181
149
|
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
|
|
150
|
+
/** 列出当前远程 Session 的 pending 工具审批。 */
|
|
151
|
+
async approvals(): Promise<SessionApproval[]> {
|
|
152
|
+
return await this.transport.approvals(this.id);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** 读取当前远程 Session 的工具审批模式。 */
|
|
156
|
+
async approval_mode(): Promise<SessionApprovalModeSnapshot> {
|
|
157
|
+
return await this.transport.approval_mode(this.id);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** 更新当前远程 Session 的工具审批模式。 */
|
|
161
|
+
async set_approval_mode(input: SetSessionApprovalModeInput): Promise<SessionApprovalModeSnapshot> {
|
|
162
|
+
return await this.transport.set_approval_mode(this.id, input);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** 处理当前远程 Session 的 pending 工具审批。 */
|
|
166
|
+
async resolve_approval(input: ResolveSessionApprovalInput): Promise<SessionApprovalResult> {
|
|
167
|
+
return await this.transport.resolve_approval(this.id, input);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** 从当前远程 Session 创建分支。 */
|
|
185
171
|
async fork(input?: AgentSessionForkInput | string): Promise<RemoteAgentSession> {
|
|
186
|
-
|
|
187
|
-
return new RemoteSession(this.transport, info);
|
|
172
|
+
return new RemoteSession(this.transport, await this.transport.fork(this.id, input));
|
|
188
173
|
}
|
|
189
174
|
|
|
190
175
|
private async ensure_event_pump(): Promise<void> {
|
|
191
|
-
if (this.event_pump_connect_promise)
|
|
192
|
-
await this.event_pump_connect_promise;
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
176
|
+
if (this.event_pump_connect_promise) return await this.event_pump_connect_promise;
|
|
195
177
|
if (this.event_pump_running) return;
|
|
196
|
-
|
|
197
178
|
this.event_pump_connect_promise = (async () => {
|
|
198
179
|
let resolved_ready = false;
|
|
199
180
|
this.event_subscription = await this.transport.subscribe({
|
|
@@ -201,19 +182,12 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
201
182
|
on_ready: () => {
|
|
202
183
|
resolved_ready = true;
|
|
203
184
|
},
|
|
204
|
-
on_event: (
|
|
205
|
-
|
|
206
|
-
},
|
|
207
|
-
on_close: (error) => {
|
|
208
|
-
this.handle_event_pump_closed(error);
|
|
209
|
-
},
|
|
185
|
+
on_event: (mutation) => this.handle_mutation(mutation),
|
|
186
|
+
on_close: (error) => this.handle_event_pump_closed(error),
|
|
210
187
|
});
|
|
211
188
|
this.event_pump_running = true;
|
|
212
|
-
if (!resolved_ready)
|
|
213
|
-
throw new Error("Remote session events connection closed before ready");
|
|
214
|
-
}
|
|
189
|
+
if (!resolved_ready) throw new Error("Remote session events connection closed before ready");
|
|
215
190
|
})();
|
|
216
|
-
|
|
217
191
|
try {
|
|
218
192
|
await this.event_pump_connect_promise;
|
|
219
193
|
} finally {
|
|
@@ -221,53 +195,38 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
221
195
|
}
|
|
222
196
|
}
|
|
223
197
|
|
|
224
|
-
private
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (turn_id) {
|
|
230
|
-
this.ensure_turn_lifecycle(turn_id);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (event.type === "turn-finish") {
|
|
234
|
-
const lifecycle = this.ensure_turn_lifecycle(event.turnId);
|
|
198
|
+
private handle_mutation(mutation: SessionMutation): void {
|
|
199
|
+
const turn_id = "turn_id" in mutation ? mutation.turn_id : undefined;
|
|
200
|
+
if (turn_id) this.ensure_turn_lifecycle(turn_id);
|
|
201
|
+
if (mutation.variant === "turn" && mutation.type === "finish") {
|
|
202
|
+
const lifecycle = this.ensure_turn_lifecycle(mutation.turn_id);
|
|
235
203
|
const result: AgentSessionTurnResult = {
|
|
236
|
-
turnId:
|
|
237
|
-
text:
|
|
238
|
-
success:
|
|
239
|
-
...(
|
|
204
|
+
turnId: mutation.turn_id,
|
|
205
|
+
text: mutation.text || "",
|
|
206
|
+
success: mutation.status === "completed",
|
|
207
|
+
...(mutation.error ? { error: mutation.error } : {}),
|
|
240
208
|
};
|
|
241
209
|
lifecycle.result = result;
|
|
242
210
|
lifecycle.deferred_finished.resolve(result);
|
|
243
|
-
this.remember_completed_turn(
|
|
211
|
+
this.remember_completed_turn(mutation.turn_id);
|
|
244
212
|
void this.maybe_stop_event_pump();
|
|
245
213
|
}
|
|
246
|
-
|
|
247
|
-
this.event_hub.publish(event);
|
|
214
|
+
this.event_hub.publish(mutation);
|
|
248
215
|
}
|
|
249
216
|
|
|
250
|
-
/**
|
|
251
|
-
* 收口底层事件连接断开后的运行态。
|
|
252
|
-
*
|
|
253
|
-
* 关键点(中文)
|
|
254
|
-
* - 连接已经结束时必须清除 running 标记,后续 prompt 才会重新订阅。
|
|
255
|
-
* - 当前未完成 turn 立即失败,避免调用侧永久等待 finished。
|
|
256
|
-
*/
|
|
257
217
|
private handle_event_pump_closed(error?: unknown): void {
|
|
258
218
|
this.event_subscription = null;
|
|
259
219
|
this.event_pump_running = false;
|
|
260
|
-
|
|
261
|
-
? error.message
|
|
262
|
-
|
|
263
|
-
this.fail_pending_turns(message);
|
|
220
|
+
this.fail_pending_turns(
|
|
221
|
+
error instanceof Error ? error.message : String(error || "Remote session events connection closed"),
|
|
222
|
+
);
|
|
264
223
|
}
|
|
265
224
|
|
|
266
225
|
private ensure_turn_lifecycle(turn_id: string): RemoteTurnLifecycle {
|
|
267
226
|
const cached = this.turns_by_id.get(turn_id);
|
|
268
227
|
if (cached) return cached;
|
|
269
228
|
const created: RemoteTurnLifecycle = {
|
|
270
|
-
|
|
229
|
+
turn_id,
|
|
271
230
|
result: null,
|
|
272
231
|
deferred_finished: create_deferred<AgentSessionTurnResult>(),
|
|
273
232
|
};
|
|
@@ -279,14 +238,14 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
279
238
|
for (const lifecycle of this.turns_by_id.values()) {
|
|
280
239
|
if (lifecycle.result) continue;
|
|
281
240
|
const result: AgentSessionTurnResult = {
|
|
282
|
-
turnId: lifecycle.
|
|
241
|
+
turnId: lifecycle.turn_id,
|
|
283
242
|
text: "",
|
|
284
243
|
success: false,
|
|
285
244
|
error: message,
|
|
286
245
|
};
|
|
287
246
|
lifecycle.result = result;
|
|
288
247
|
lifecycle.deferred_finished.resolve(result);
|
|
289
|
-
this.remember_completed_turn(lifecycle.
|
|
248
|
+
this.remember_completed_turn(lifecycle.turn_id);
|
|
290
249
|
}
|
|
291
250
|
}
|
|
292
251
|
|
|
@@ -294,9 +253,7 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
294
253
|
this.completed_turn_ids.push(turn_id);
|
|
295
254
|
while (this.completed_turn_ids.length > 200) {
|
|
296
255
|
const oldest_turn_id = this.completed_turn_ids.shift();
|
|
297
|
-
if (oldest_turn_id)
|
|
298
|
-
this.turns_by_id.delete(oldest_turn_id);
|
|
299
|
-
}
|
|
256
|
+
if (oldest_turn_id) this.turns_by_id.delete(oldest_turn_id);
|
|
300
257
|
}
|
|
301
258
|
}
|
|
302
259
|
|
|
@@ -308,9 +265,7 @@ export class RemoteSession implements RemoteAgentSession {
|
|
|
308
265
|
this.event_pump_running = false;
|
|
309
266
|
if (!current) return;
|
|
310
267
|
await current.close().catch((error) => {
|
|
311
|
-
this.fail_pending_turns(
|
|
312
|
-
error instanceof Error ? error.message : String(error),
|
|
313
|
-
);
|
|
268
|
+
this.fail_pending_turns(error instanceof Error ? error.message : String(error));
|
|
314
269
|
});
|
|
315
270
|
}
|
|
316
271
|
}
|
|
@@ -320,17 +275,12 @@ function create_deferred<T>(): Deferred<T> {
|
|
|
320
275
|
const promise = new Promise<T>((inner_resolve) => {
|
|
321
276
|
resolve = inner_resolve;
|
|
322
277
|
});
|
|
323
|
-
return {
|
|
324
|
-
promise,
|
|
325
|
-
resolve,
|
|
326
|
-
};
|
|
278
|
+
return { promise, resolve };
|
|
327
279
|
}
|
|
328
280
|
|
|
329
|
-
function create_turn_handle(
|
|
330
|
-
lifecycle: RemoteTurnLifecycle,
|
|
331
|
-
): AgentSessionTurnHandle {
|
|
281
|
+
function create_turn_handle(lifecycle: RemoteTurnLifecycle): AgentSessionTurnHandle {
|
|
332
282
|
return {
|
|
333
|
-
id: lifecycle.
|
|
283
|
+
id: lifecycle.turn_id,
|
|
334
284
|
get result() {
|
|
335
285
|
return lifecycle.result;
|
|
336
286
|
},
|
|
@@ -338,22 +288,14 @@ function create_turn_handle(
|
|
|
338
288
|
};
|
|
339
289
|
}
|
|
340
290
|
|
|
341
|
-
function
|
|
342
|
-
if (
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
case "tool-call":
|
|
350
|
-
case "tool-result":
|
|
351
|
-
case "assistant-step":
|
|
352
|
-
case "turn-finish":
|
|
353
|
-
return event.turnId;
|
|
354
|
-
case "action":
|
|
355
|
-
return event.metadata.turnId || null;
|
|
356
|
-
default:
|
|
357
|
-
return null;
|
|
291
|
+
function require_approval_id(mutation: SessionMutation): string {
|
|
292
|
+
if (
|
|
293
|
+
mutation.variant === "part" &&
|
|
294
|
+
mutation.type === "tool" &&
|
|
295
|
+
mutation.part.state === "approval-required" &&
|
|
296
|
+
mutation.part.approval_id
|
|
297
|
+
) {
|
|
298
|
+
return mutation.part.approval_id;
|
|
358
299
|
}
|
|
300
|
+
throw new Error("Current Session Mutation is not an approval-required Tool Part");
|
|
359
301
|
}
|
|
@@ -24,25 +24,20 @@ import type {
|
|
|
24
24
|
RemoteAgentPluginActionInput,
|
|
25
25
|
RemoteAgentPluginActionResult,
|
|
26
26
|
} from "@/types/agent/RemoteAgentPluginAction.js";
|
|
27
|
-
import type {
|
|
27
|
+
import type { SessionMutation } from "@/types/session/SessionMutation.js";
|
|
28
|
+
import type {
|
|
29
|
+
ResolveSessionApprovalInput,
|
|
30
|
+
SessionApproval,
|
|
31
|
+
SessionApprovalModeSnapshot,
|
|
32
|
+
SessionApprovalResult,
|
|
33
|
+
SetSessionApprovalModeInput,
|
|
34
|
+
} from "@/types/session/SessionApproval.js";
|
|
28
35
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
29
36
|
import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
|
|
30
37
|
import type {
|
|
31
38
|
ListSessionMessagesInput,
|
|
32
39
|
SessionMessagePage,
|
|
33
40
|
} from "@/types/session/SessionMessage.js";
|
|
34
|
-
import type {
|
|
35
|
-
ListSessionMessageChangesInput,
|
|
36
|
-
SessionMessageMutationPage,
|
|
37
|
-
} from "@/types/session/SessionMessageMutation.js";
|
|
38
|
-
import type {
|
|
39
|
-
ShellApprovalMode,
|
|
40
|
-
ShellApprovalDecisionResult,
|
|
41
|
-
ShellApprovalModeUpdateResult,
|
|
42
|
-
ShellApprovalModeOption,
|
|
43
|
-
ShellSessionApprovalModeView,
|
|
44
|
-
ShellApprovalView,
|
|
45
|
-
} from "@downcity/shell";
|
|
46
41
|
|
|
47
42
|
/**
|
|
48
43
|
* Transport 持有的事件订阅句柄。
|
|
@@ -71,7 +66,7 @@ export type RemoteSessionTransport = {
|
|
|
71
66
|
subscribe(params: {
|
|
72
67
|
session_id: string;
|
|
73
68
|
on_ready: () => void;
|
|
74
|
-
on_event: (
|
|
69
|
+
on_event: (mutation: SessionMutation) => void;
|
|
75
70
|
/** 底层事件连接结束后的通知;主动关闭不触发。 */
|
|
76
71
|
on_close: (error?: unknown) => void;
|
|
77
72
|
}): Promise<TransportSubscription>;
|
|
@@ -80,11 +75,6 @@ export type RemoteSessionTransport = {
|
|
|
80
75
|
session_id: string,
|
|
81
76
|
input?: ListSessionMessagesInput,
|
|
82
77
|
): Promise<SessionMessagePage>;
|
|
83
|
-
/** 读取增量 Message Mutation。 */
|
|
84
|
-
message_changes(
|
|
85
|
-
session_id: string,
|
|
86
|
-
input: ListSessionMessageChangesInput,
|
|
87
|
-
): Promise<SessionMessageMutationPage>;
|
|
88
78
|
/** 读取 system snapshot。 */
|
|
89
79
|
system(session_id: string): Promise<AgentSessionSystemSnapshot>;
|
|
90
80
|
/** 分叉 session。 */
|
|
@@ -92,6 +82,20 @@ export type RemoteSessionTransport = {
|
|
|
92
82
|
session_id: string,
|
|
93
83
|
input?: AgentSessionForkInput | string,
|
|
94
84
|
): Promise<AgentSessionInfo>;
|
|
85
|
+
/** 列出指定 Session 的 pending 工具审批。 */
|
|
86
|
+
approvals(session_id: string): Promise<SessionApproval[]>;
|
|
87
|
+
/** 读取指定 Session 的工具审批模式。 */
|
|
88
|
+
approval_mode(session_id: string): Promise<SessionApprovalModeSnapshot>;
|
|
89
|
+
/** 更新指定 Session 的工具审批模式。 */
|
|
90
|
+
set_approval_mode(
|
|
91
|
+
session_id: string,
|
|
92
|
+
input: SetSessionApprovalModeInput,
|
|
93
|
+
): Promise<SessionApprovalModeSnapshot>;
|
|
94
|
+
/** 处理指定 Session 的 pending 工具审批。 */
|
|
95
|
+
resolve_approval(
|
|
96
|
+
session_id: string,
|
|
97
|
+
input: ResolveSessionApprovalInput,
|
|
98
|
+
): Promise<SessionApprovalResult>;
|
|
95
99
|
};
|
|
96
100
|
|
|
97
101
|
/**
|
|
@@ -112,21 +116,6 @@ export type RemoteAgentTransport = RemoteSessionTransport & {
|
|
|
112
116
|
run_plugin_action(
|
|
113
117
|
input: RemoteAgentPluginActionInput,
|
|
114
118
|
): Promise<RemoteAgentPluginActionResult>;
|
|
115
|
-
/** 列出 shell approvals。 */
|
|
116
|
-
approvals(): Promise<ShellApprovalView[]>;
|
|
117
|
-
/** 列出 shell approval modes。 */
|
|
118
|
-
approval_modes(): Promise<ShellApprovalModeOption[]>;
|
|
119
|
-
/** 读取 shell approval mode。 */
|
|
120
|
-
approval_mode(input: { session_id: string }): Promise<ShellSessionApprovalModeView>;
|
|
121
|
-
/** 设置 shell approval mode。 */
|
|
122
|
-
set_approval_mode(input: {
|
|
123
|
-
session_id: string;
|
|
124
|
-
mode: ShellApprovalMode;
|
|
125
|
-
}): Promise<ShellApprovalModeUpdateResult>;
|
|
126
|
-
/** 批准 shell approval。 */
|
|
127
|
-
approve(input: { approval_id: string }): Promise<ShellApprovalDecisionResult>;
|
|
128
|
-
/** 拒绝 shell approval。 */
|
|
129
|
-
deny(input: { approval_id: string }): Promise<ShellApprovalDecisionResult>;
|
|
130
119
|
/** 关闭 transport 持有的长期连接。 */
|
|
131
120
|
close?(): Promise<void>;
|
|
132
121
|
};
|