@zhanguym/chatroom 1.0.0 → 1.1.0-beta.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/dist/app/application.d.ts +0 -1
- package/dist/app/application.js +8 -7
- package/dist/app/event-bus.d.ts +13 -10
- package/dist/app/git-access.d.ts +50 -0
- package/dist/app/git-access.js +2 -0
- package/dist/app/service-registry.d.ts +11 -0
- package/dist/app/service-registry.js +17 -0
- package/dist/app/workspace-access.d.ts +24 -0
- package/dist/app/workspace-access.js +2 -0
- package/dist/auth/ingress-policy.d.ts +2 -0
- package/dist/auth/ingress-policy.js +14 -2
- package/dist/auth/passkey-service.js +1 -1
- package/dist/cli/run-cli.js +1 -1
- package/dist/core/fs/safe-directory.d.ts +9 -0
- package/dist/core/fs/safe-directory.js +129 -0
- package/dist/core/operations/repository.d.ts +2 -0
- package/dist/core/runtime/line-process.d.ts +19 -0
- package/dist/core/runtime/line-process.js +51 -0
- package/dist/infrastructure/database/operation-repository.js +8 -2
- package/dist/infrastructure/database/schema.d.ts +1 -1
- package/dist/infrastructure/database/schema.js +62 -0
- package/dist/infrastructure/http/http-server.js +1 -1
- package/dist/native/linux/chatroom-computer-helper +0 -0
- package/dist/native/macos/ChatRoomComputerHelper.app/Contents/MacOS/chatroom-computer-helper +0 -0
- package/dist/native/windows/chatroom-computer-helper.exe +0 -0
- package/dist/operations/operation-log.js +16 -4
- package/dist/plugins/agent/async-queue.d.ts +10 -0
- package/dist/plugins/agent/async-queue.js +49 -0
- package/dist/plugins/agent/mcp.d.ts +3 -0
- package/dist/plugins/agent/mcp.js +502 -0
- package/dist/plugins/agent/plugin.d.ts +4 -0
- package/dist/plugins/agent/plugin.js +35 -0
- package/dist/plugins/agent/provider.d.ts +132 -0
- package/dist/plugins/agent/providers/codex/mapping.d.ts +56 -0
- package/dist/plugins/agent/providers/codex/mapping.js +427 -0
- package/dist/plugins/agent/providers/codex/provider.d.ts +84 -0
- package/dist/plugins/agent/providers/codex/provider.js +828 -0
- package/dist/plugins/agent/providers/codex/rpc.d.ts +40 -0
- package/dist/plugins/agent/providers/codex/rpc.js +227 -0
- package/dist/plugins/agent/providers/common.d.ts +11 -0
- package/dist/plugins/agent/providers/common.js +75 -0
- package/dist/plugins/agent/providers/index.d.ts +3 -0
- package/dist/plugins/agent/providers/index.js +4 -0
- package/dist/plugins/agent/repository.d.ts +21 -0
- package/dist/plugins/agent/repository.js +226 -0
- package/dist/plugins/agent/runtime-config.d.ts +5 -0
- package/dist/plugins/agent/runtime-config.js +60 -0
- package/dist/plugins/agent/runtime-files.d.ts +8 -0
- package/dist/plugins/agent/runtime-files.js +170 -0
- package/dist/plugins/agent/runtime-state.d.ts +17 -0
- package/dist/plugins/agent/runtime-state.js +133 -0
- package/dist/plugins/agent/runtime.d.ts +60 -0
- package/dist/plugins/agent/runtime.js +928 -0
- package/dist/plugins/agent/store.d.ts +17 -0
- package/dist/plugins/agent/store.js +1 -0
- package/dist/plugins/agent/types.d.ts +320 -0
- package/dist/plugins/agent/types.js +13 -0
- package/dist/plugins/cloud/plugin.d.ts +1 -1
- package/dist/plugins/cloud/plugin.js +3 -3
- package/dist/plugins/cloud/tunnel-client.js +6 -7
- package/dist/plugins/computer/computer-schemas.d.ts +7 -7
- package/dist/plugins/computer/computer-service.d.ts +3 -0
- package/dist/plugins/computer/computer-service.js +33 -1
- package/dist/plugins/computer/plugin.d.ts +1 -1
- package/dist/plugins/computer/plugin.js +1 -1
- package/dist/plugins/git/git-service.d.ts +3 -2
- package/dist/plugins/git/git-service.js +37 -1
- package/dist/plugins/git/plugin.d.ts +0 -2
- package/dist/plugins/git/plugin.js +3 -3
- package/dist/plugins/process/plugin.d.ts +1 -1
- package/dist/plugins/process/plugin.js +3 -3
- package/dist/plugins/process/process-supervisor.d.ts +1 -0
- package/dist/plugins/process/process-supervisor.js +15 -4
- package/dist/plugins/types.d.ts +1 -11
- package/dist/plugins/types.js +1 -17
- package/dist/plugins/web/api-types.d.ts +20 -5
- package/dist/plugins/web/http/agent-api-router.d.ts +3 -0
- package/dist/plugins/web/http/agent-api-router.js +254 -0
- package/dist/plugins/web/http/api-router.js +9 -0
- package/dist/plugins/web/http/computer-api-router.js +21 -6
- package/dist/plugins/web/http/process-api-router.js +3 -0
- package/dist/plugins/web/http/workspace-api-router.js +79 -6
- package/dist/plugins/web/plugin.d.ts +1 -1
- package/dist/plugins/web/plugin.js +5 -4
- package/dist/plugins/web/runtime.d.ts +6 -3
- package/dist/plugins/web/runtime.js +6 -1
- package/dist/plugins/workspace/mcp.js +16 -0
- package/dist/plugins/workspace/metadata.d.ts +1 -1
- package/dist/plugins/workspace/plugin.d.ts +1 -1
- package/dist/plugins/workspace/plugin.js +5 -2
- package/dist/plugins/workspace/types.d.ts +1 -18
- package/dist/plugins/workspace/workspace-fs.d.ts +9 -3
- package/dist/plugins/workspace/workspace-fs.js +78 -125
- package/dist/plugins/workspace/workspace-root-policy.d.ts +9 -0
- package/dist/plugins/workspace/workspace-root-policy.js +56 -0
- package/dist/plugins/workspace/workspace-service.d.ts +11 -6
- package/dist/plugins/workspace/workspace-service.js +39 -49
- package/dist/web/assets/AgentView-DKuspiki.js +4 -0
- package/dist/web/assets/AgentView-DYJeMJLX.css +1 -0
- package/dist/web/assets/{CloudView-CHjVbp-5.css → CloudView-DVVvwuWW.css} +1 -1
- package/dist/web/assets/CloudView-PbREbJgz.js +1 -0
- package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-CiFNEpWo.js +3 -0
- package/dist/web/assets/ComputerView-BM0u3wSF.css +1 -0
- package/dist/web/assets/ComputerView-BRb2sE0Z.js +1 -0
- package/dist/web/assets/McpToolsView-B8NSFdf4.js +1 -0
- package/dist/web/assets/McpToolsView-C22ZbSuV.css +1 -0
- package/dist/web/assets/OperationsView-BjTY2lIh.css +1 -0
- package/dist/web/assets/OperationsView-Cavi-6SZ.js +4 -0
- package/dist/web/assets/ProcessesView-Ce6iVwjA.css +1 -0
- package/dist/web/assets/ProcessesView-UO48Nh2q.js +4 -0
- package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-Bvc9wRyA.js +1 -0
- package/dist/web/assets/SystemLogsView-BXmOrmu5.js +1 -0
- package/dist/web/assets/SystemLogsView-CofP4Jvi.css +1 -0
- package/dist/web/assets/VSelect-BPRXx8KM.js +1 -0
- package/dist/web/assets/VSpacer-Cl-QiwaM.js +1 -0
- package/dist/web/assets/VSwitch-C0XNj1lR.js +1 -0
- package/dist/web/assets/{VTabs-qBcuuXh3.js → VTabs-CHj39Ket.js} +1 -1
- package/dist/web/assets/VTextarea-BIcUWOU6.js +16 -0
- package/dist/web/assets/VTextarea-DG1zE1as.css +1 -0
- package/dist/web/assets/WorkspacesView-DPCt6kYy.css +1 -0
- package/dist/web/assets/WorkspacesView-rY6RXeiR.js +2 -0
- package/dist/web/assets/entity-refresh-queue-wQii8Dl5.js +1 -0
- package/dist/web/assets/{index-CkjqXRSj.css → index-BPpl3-sP.css} +1 -1
- package/dist/web/assets/index-Dt-pWiW1.js +19 -0
- package/dist/web/assets/{syntax-highlight-B5ArnyrC.js → syntax-highlight-C_fuMcwC.js} +1 -1
- package/dist/web/assets/useMasterDetailFocus-D0j-KcXv.js +1 -0
- package/dist/web/assets/useOperationLabels-DR8r6Vrl.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +4 -2
- package/dist/plugins/git/types.d.ts +0 -32
- package/dist/web/assets/CloudView-CvX0dkgu.js +0 -1
- package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-B5TxGkUW.js +0 -3
- package/dist/web/assets/ComputerView-91Z9Cefw.css +0 -1
- package/dist/web/assets/ComputerView-OOyEqWml.js +0 -1
- package/dist/web/assets/McpToolsView-BTnolyS6.css +0 -1
- package/dist/web/assets/McpToolsView-DjXWTKrZ.js +0 -1
- package/dist/web/assets/OperationsView-DqTY51Cr.js +0 -4
- package/dist/web/assets/ProcessesView-C13BykIa.js +0 -4
- package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-DyOhJmR6.js +0 -1
- package/dist/web/assets/SystemLogsView-Ci0u4BTb.js +0 -1
- package/dist/web/assets/VSelect-DrRpKyYI.js +0 -1
- package/dist/web/assets/VSpacer-C3wAY3F0.js +0 -1
- package/dist/web/assets/VSwitch-CxusR4iO.js +0 -1
- package/dist/web/assets/WorkspacesView-BzQ0aH74.css +0 -1
- package/dist/web/assets/WorkspacesView-CijIvfsp.js +0 -2
- package/dist/web/assets/index-BegKQ3Yd.js +0 -19
- package/dist/web/assets/useOperationLabels-BDjzGDkT.js +0 -1
- /package/dist/{plugins/process → core/runtime}/head-tail-buffer.d.ts +0 -0
- /package/dist/{plugins/process → core/runtime}/head-tail-buffer.js +0 -0
- /package/dist/plugins/{git/types.js → agent/provider.js} +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { LogWriter } from "#core/logging/types";
|
|
2
|
+
export type CodexRequestId = string | number;
|
|
3
|
+
export interface CodexNotification {
|
|
4
|
+
method: string;
|
|
5
|
+
params?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export interface CodexServerRequest extends CodexNotification {
|
|
8
|
+
id: CodexRequestId;
|
|
9
|
+
}
|
|
10
|
+
interface InitializeResult {
|
|
11
|
+
userAgent: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class CodexRpcClient {
|
|
14
|
+
private readonly logs;
|
|
15
|
+
private process;
|
|
16
|
+
private readonly pending;
|
|
17
|
+
private readonly notificationListeners;
|
|
18
|
+
private readonly requestListeners;
|
|
19
|
+
private readonly closeListeners;
|
|
20
|
+
private nextId;
|
|
21
|
+
private starting;
|
|
22
|
+
private initialized;
|
|
23
|
+
constructor(logs: LogWriter);
|
|
24
|
+
ensureStarted(): Promise<InitializeResult>;
|
|
25
|
+
request<T>(method: string, params?: unknown, timeoutMs?: number): Promise<T>;
|
|
26
|
+
notify(method: string, params?: unknown): void;
|
|
27
|
+
respond(id: CodexRequestId, result: unknown): void;
|
|
28
|
+
respondError(id: CodexRequestId, code: number, message: string): void;
|
|
29
|
+
onNotification(listener: (notification: CodexNotification) => void): () => void;
|
|
30
|
+
onServerRequest(listener: (request: CodexServerRequest) => void): () => void;
|
|
31
|
+
onTransportClose(listener: (error: Error) => void): () => void;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
private start;
|
|
34
|
+
private requestReady;
|
|
35
|
+
private failTransport;
|
|
36
|
+
private handleLine;
|
|
37
|
+
private write;
|
|
38
|
+
private requireProcess;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { LineProcess } from "#core/runtime/line-process";
|
|
2
|
+
import { CHATROOM_VERSION } from "#core/runtime/identity";
|
|
3
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
4
|
+
export class CodexRpcClient {
|
|
5
|
+
logs;
|
|
6
|
+
process = null;
|
|
7
|
+
pending = new Map();
|
|
8
|
+
notificationListeners = new Set();
|
|
9
|
+
requestListeners = new Set();
|
|
10
|
+
closeListeners = new Set();
|
|
11
|
+
nextId = 1;
|
|
12
|
+
starting = null;
|
|
13
|
+
initialized = null;
|
|
14
|
+
constructor(logs) {
|
|
15
|
+
this.logs = logs;
|
|
16
|
+
}
|
|
17
|
+
async ensureStarted() {
|
|
18
|
+
if (this.initialized)
|
|
19
|
+
return this.initialized;
|
|
20
|
+
if (!this.starting)
|
|
21
|
+
this.starting = this.start();
|
|
22
|
+
try {
|
|
23
|
+
this.initialized = await this.starting;
|
|
24
|
+
return this.initialized;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
this.starting = null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async request(method, params, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
31
|
+
await this.ensureStarted();
|
|
32
|
+
return this.requestReady(method, params, timeoutMs);
|
|
33
|
+
}
|
|
34
|
+
notify(method, params) {
|
|
35
|
+
this.write(params === undefined ? { method } : { method, params });
|
|
36
|
+
}
|
|
37
|
+
respond(id, result) {
|
|
38
|
+
this.write({ id, result });
|
|
39
|
+
}
|
|
40
|
+
respondError(id, code, message) {
|
|
41
|
+
this.write({ id, error: { code, message } });
|
|
42
|
+
}
|
|
43
|
+
onNotification(listener) {
|
|
44
|
+
this.notificationListeners.add(listener);
|
|
45
|
+
return () => this.notificationListeners.delete(listener);
|
|
46
|
+
}
|
|
47
|
+
onServerRequest(listener) {
|
|
48
|
+
this.requestListeners.add(listener);
|
|
49
|
+
return () => this.requestListeners.delete(listener);
|
|
50
|
+
}
|
|
51
|
+
onTransportClose(listener) {
|
|
52
|
+
this.closeListeners.add(listener);
|
|
53
|
+
return () => this.closeListeners.delete(listener);
|
|
54
|
+
}
|
|
55
|
+
async close() {
|
|
56
|
+
const process = this.process;
|
|
57
|
+
if (!process)
|
|
58
|
+
return;
|
|
59
|
+
this.failTransport(process, new Error("Codex app-server closed"));
|
|
60
|
+
process.terminate();
|
|
61
|
+
await process.waitForExit(1500);
|
|
62
|
+
process.forceKill();
|
|
63
|
+
}
|
|
64
|
+
async start() {
|
|
65
|
+
let process;
|
|
66
|
+
process = new LineProcess({
|
|
67
|
+
command: "codex",
|
|
68
|
+
args: ["app-server", "--listen", "stdio://", "-c", "mcp_servers={}"],
|
|
69
|
+
onStdout: (line) => this.handleLine(line),
|
|
70
|
+
onStderr: (line) => {
|
|
71
|
+
const message = line.trim();
|
|
72
|
+
if (message)
|
|
73
|
+
this.logs.debug("agent.codex", "codex.stderr", message.slice(0, 4000));
|
|
74
|
+
},
|
|
75
|
+
onExit: (code, signal) => {
|
|
76
|
+
if (this.process !== process)
|
|
77
|
+
return;
|
|
78
|
+
this.failTransport(process, new Error("Codex app-server exited" +
|
|
79
|
+
(code === null ? "" : " with code " + code) +
|
|
80
|
+
(signal ? " (" + signal + ")" : "")));
|
|
81
|
+
},
|
|
82
|
+
onError: (error) => {
|
|
83
|
+
if (this.process === process)
|
|
84
|
+
this.failTransport(process, error);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
await process.spawned();
|
|
88
|
+
this.process = process;
|
|
89
|
+
try {
|
|
90
|
+
const initialized = await this.requestReady("initialize", {
|
|
91
|
+
clientInfo: {
|
|
92
|
+
name: "chatroom",
|
|
93
|
+
title: "ChatRoom",
|
|
94
|
+
version: CHATROOM_VERSION,
|
|
95
|
+
},
|
|
96
|
+
capabilities: { experimentalApi: false, requestAttestation: false },
|
|
97
|
+
});
|
|
98
|
+
this.notify("initialized");
|
|
99
|
+
return initialized;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
103
|
+
this.failTransport(process, failure);
|
|
104
|
+
process.terminate();
|
|
105
|
+
await process.waitForExit(500);
|
|
106
|
+
process.forceKill();
|
|
107
|
+
throw failure;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
requestReady(method, params, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
111
|
+
this.requireProcess();
|
|
112
|
+
const id = this.nextId++;
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
const timer = setTimeout(() => {
|
|
115
|
+
if (!this.pending.delete(id))
|
|
116
|
+
return;
|
|
117
|
+
reject(new Error(`Codex app-server request timed out: ${method}`));
|
|
118
|
+
}, timeoutMs);
|
|
119
|
+
timer.unref();
|
|
120
|
+
this.pending.set(id, {
|
|
121
|
+
resolve: (value) => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
resolve(value);
|
|
124
|
+
},
|
|
125
|
+
reject: (error) => {
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
reject(error);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
this.write(params === undefined ? { id, method } : { id, method, params });
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.pending.delete(id);
|
|
135
|
+
clearTimeout(timer);
|
|
136
|
+
reject(error);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
failTransport(process, error) {
|
|
141
|
+
if (this.process !== process)
|
|
142
|
+
return;
|
|
143
|
+
this.process = null;
|
|
144
|
+
this.initialized = null;
|
|
145
|
+
this.starting = null;
|
|
146
|
+
for (const pending of this.pending.values())
|
|
147
|
+
pending.reject(error);
|
|
148
|
+
this.pending.clear();
|
|
149
|
+
for (const listener of this.closeListeners)
|
|
150
|
+
listener(error);
|
|
151
|
+
}
|
|
152
|
+
handleLine(line) {
|
|
153
|
+
let message;
|
|
154
|
+
try {
|
|
155
|
+
message = JSON.parse(line);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
this.logs.warn("agent.codex", "codex.invalid_json", "Codex app-server emitted invalid JSON", { line: line.slice(0, 1000) });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (!isRecord(message))
|
|
162
|
+
return;
|
|
163
|
+
if ("method" in message && typeof message.method === "string") {
|
|
164
|
+
const notification = {
|
|
165
|
+
method: message.method,
|
|
166
|
+
...("params" in message ? { params: message.params } : {}),
|
|
167
|
+
};
|
|
168
|
+
const params = isRecord(notification.params) ? notification.params : null;
|
|
169
|
+
if (params &&
|
|
170
|
+
(notification.method === "configWarning" ||
|
|
171
|
+
notification.method === "deprecationNotice" ||
|
|
172
|
+
(notification.method === "warning" && params.threadId === null))) {
|
|
173
|
+
const summary = notification.method === "warning" ? params.message : params.summary;
|
|
174
|
+
if (typeof summary === "string")
|
|
175
|
+
this.logs.warn("agent.codex", "codex." + notification.method, [
|
|
176
|
+
summary,
|
|
177
|
+
typeof params.details === "string" ? params.details : null,
|
|
178
|
+
]
|
|
179
|
+
.filter(Boolean)
|
|
180
|
+
.join("\n"));
|
|
181
|
+
}
|
|
182
|
+
if ("id" in message && isRequestId(message.id)) {
|
|
183
|
+
const request = {
|
|
184
|
+
...notification,
|
|
185
|
+
id: message.id,
|
|
186
|
+
};
|
|
187
|
+
for (const listener of this.requestListeners)
|
|
188
|
+
listener(request);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
for (const listener of this.notificationListeners)
|
|
192
|
+
listener(notification);
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!("id" in message) || typeof message.id !== "number")
|
|
197
|
+
return;
|
|
198
|
+
const pending = this.pending.get(message.id);
|
|
199
|
+
if (!pending)
|
|
200
|
+
return;
|
|
201
|
+
this.pending.delete(message.id);
|
|
202
|
+
if ("error" in message && message.error) {
|
|
203
|
+
pending.reject(new Error(rpcErrorMessage(message.error)));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
pending.resolve("result" in message ? message.result : null);
|
|
207
|
+
}
|
|
208
|
+
write(message) {
|
|
209
|
+
this.requireProcess().writeLine(JSON.stringify(message));
|
|
210
|
+
}
|
|
211
|
+
requireProcess() {
|
|
212
|
+
if (!this.process)
|
|
213
|
+
throw new Error("Codex app-server is not running");
|
|
214
|
+
return this.process;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function isRequestId(value) {
|
|
218
|
+
return typeof value === "string" || typeof value === "number";
|
|
219
|
+
}
|
|
220
|
+
function isRecord(value) {
|
|
221
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
222
|
+
}
|
|
223
|
+
function rpcErrorMessage(value) {
|
|
224
|
+
if (isRecord(value) && typeof value.message === "string")
|
|
225
|
+
return value.message;
|
|
226
|
+
return "Codex app-server request failed";
|
|
227
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentError, AgentInteractionOption } from "#plugins/agent/types";
|
|
2
|
+
export declare function array(value: unknown): unknown[];
|
|
3
|
+
export declare function record(value: unknown): Record<string, unknown> | null;
|
|
4
|
+
export declare function questionOptions(value: unknown): AgentInteractionOption[];
|
|
5
|
+
export declare function stringifyOptional(value: unknown): string | null;
|
|
6
|
+
export declare function continuityInstructions(context: string): string;
|
|
7
|
+
export declare function workspaceInstructions(prompt: string): string;
|
|
8
|
+
export declare function combinedProviderInstructions(workspacePrompt: string | null, continuityContext: string | null): string | null;
|
|
9
|
+
export declare function errorMessage(error: unknown): string;
|
|
10
|
+
export declare function isMissingExecutable(error: unknown): boolean;
|
|
11
|
+
export declare function providerError(error: unknown): AgentError;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export function array(value) {
|
|
2
|
+
return Array.isArray(value) ? value : [];
|
|
3
|
+
}
|
|
4
|
+
export function record(value) {
|
|
5
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value)
|
|
6
|
+
? value
|
|
7
|
+
: null;
|
|
8
|
+
}
|
|
9
|
+
export function questionOptions(value) {
|
|
10
|
+
return array(value)
|
|
11
|
+
.map(record)
|
|
12
|
+
.filter((option) => Boolean(option))
|
|
13
|
+
.map((option, index) => ({
|
|
14
|
+
id: typeof option.label === "string" ? option.label : "option_" + index,
|
|
15
|
+
label: typeof option.label === "string"
|
|
16
|
+
? option.label
|
|
17
|
+
: "Option " + (index + 1),
|
|
18
|
+
description: typeof option.description === "string" ? option.description : null,
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
export function stringifyOptional(value) {
|
|
22
|
+
if (value === null || value === undefined)
|
|
23
|
+
return null;
|
|
24
|
+
if (typeof value === "string")
|
|
25
|
+
return value;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.stringify(value);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return String(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function continuityInstructions(context) {
|
|
34
|
+
return [
|
|
35
|
+
"ChatRoom conversation continuity follows.",
|
|
36
|
+
"This is prior conversation context from periods handled by another coding-agent provider in the same ChatRoom session.",
|
|
37
|
+
"Treat it as authoritative prior conversation context alongside the current workspace state.",
|
|
38
|
+
"Do not mention this continuity injection unless it is directly relevant to the user's request.",
|
|
39
|
+
"",
|
|
40
|
+
context,
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
export function workspaceInstructions(prompt) {
|
|
44
|
+
return [
|
|
45
|
+
"ChatRoom workspace preset instructions follow.",
|
|
46
|
+
"These instructions are configured for the current workspace and apply to work performed in it.",
|
|
47
|
+
"",
|
|
48
|
+
prompt,
|
|
49
|
+
].join("\n");
|
|
50
|
+
}
|
|
51
|
+
export function combinedProviderInstructions(workspacePrompt, continuityContext) {
|
|
52
|
+
const sections = [];
|
|
53
|
+
if (workspacePrompt)
|
|
54
|
+
sections.push(workspaceInstructions(workspacePrompt));
|
|
55
|
+
if (continuityContext)
|
|
56
|
+
sections.push(continuityInstructions(continuityContext));
|
|
57
|
+
return sections.length ? sections.join("\n\n") : null;
|
|
58
|
+
}
|
|
59
|
+
export function errorMessage(error) {
|
|
60
|
+
return error instanceof Error ? error.message : String(error);
|
|
61
|
+
}
|
|
62
|
+
export function isMissingExecutable(error) {
|
|
63
|
+
return (Boolean(error) &&
|
|
64
|
+
typeof error === "object" &&
|
|
65
|
+
error !== null &&
|
|
66
|
+
"code" in error &&
|
|
67
|
+
error.code === "ENOENT");
|
|
68
|
+
}
|
|
69
|
+
export function providerError(error) {
|
|
70
|
+
return {
|
|
71
|
+
message: errorMessage(error),
|
|
72
|
+
details: null,
|
|
73
|
+
providerData: null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentStore } from "./store.js";
|
|
2
|
+
import type { AgentHistory, AgentHistoryUpdate, AgentItem, AgentProviderSessionState, AgentSession, AgentTurn } from "./types.js";
|
|
3
|
+
import type { AppDatabase } from "#infrastructure/database/app-database";
|
|
4
|
+
export declare class AgentRepository implements AgentStore {
|
|
5
|
+
private readonly database;
|
|
6
|
+
constructor(database: AppDatabase);
|
|
7
|
+
reconcileInterrupted(now: string): void;
|
|
8
|
+
insertSession(session: AgentSession): void;
|
|
9
|
+
updateSession(session: AgentSession): void;
|
|
10
|
+
getSession(id: string): AgentSession | null;
|
|
11
|
+
listSessions(): AgentSession[];
|
|
12
|
+
deleteSession(id: string): void;
|
|
13
|
+
getProviderState(sessionId: string, provider: AgentProviderSessionState["provider"]): AgentProviderSessionState | null;
|
|
14
|
+
upsertProviderState(state: AgentProviderSessionState): void;
|
|
15
|
+
insertTurn(turn: AgentTurn): void;
|
|
16
|
+
updateTurn(turn: AgentTurn): void;
|
|
17
|
+
insertItem(item: AgentItem): void;
|
|
18
|
+
updateItem(item: AgentItem): void;
|
|
19
|
+
history(sessionId: string): AgentHistory | null;
|
|
20
|
+
historyUpdate(sessionId: string, turnIds: readonly string[], itemIds: readonly string[]): AgentHistoryUpdate | null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
export class AgentRepository {
|
|
2
|
+
database;
|
|
3
|
+
constructor(database) {
|
|
4
|
+
this.database = database;
|
|
5
|
+
}
|
|
6
|
+
reconcileInterrupted(now) {
|
|
7
|
+
this.database.raw.exec("BEGIN IMMEDIATE");
|
|
8
|
+
try {
|
|
9
|
+
this.database.raw
|
|
10
|
+
.prepare("UPDATE agent_items SET status='interrupted', updated_at=? WHERE status IN ('running','waiting')")
|
|
11
|
+
.run(now);
|
|
12
|
+
this.database.raw
|
|
13
|
+
.prepare("UPDATE agent_turns SET status='interrupted', completed_at=? WHERE status='running'")
|
|
14
|
+
.run(now);
|
|
15
|
+
const interruptedSessions = this.database.raw
|
|
16
|
+
.prepare("SELECT id, updated_at FROM agent_sessions WHERE status IN ('running','waiting_input')")
|
|
17
|
+
.all();
|
|
18
|
+
const updateSession = this.database.raw.prepare("UPDATE agent_sessions SET status='idle', updated_at=? WHERE id=?");
|
|
19
|
+
for (const session of interruptedSessions)
|
|
20
|
+
updateSession.run(monotonicTimestamp(session.updated_at, now), session.id);
|
|
21
|
+
this.database.raw.exec("COMMIT");
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
this.database.raw.exec("ROLLBACK");
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
insertSession(session) {
|
|
29
|
+
this.database.raw
|
|
30
|
+
.prepare("INSERT INTO agent_sessions(id, workspace_root, provider, status, created_at, updated_at) VALUES(?,?,?,?,?,?)")
|
|
31
|
+
.run(session.id, session.workspaceRoot, session.provider, session.status, session.createdAt, session.updatedAt);
|
|
32
|
+
}
|
|
33
|
+
updateSession(session) {
|
|
34
|
+
this.database.raw
|
|
35
|
+
.prepare("UPDATE agent_sessions SET workspace_root=?, provider=?, status=?, created_at=?, updated_at=? WHERE id=?")
|
|
36
|
+
.run(session.workspaceRoot, session.provider, session.status, session.createdAt, session.updatedAt, session.id);
|
|
37
|
+
}
|
|
38
|
+
getSession(id) {
|
|
39
|
+
const row = this.database.raw
|
|
40
|
+
.prepare("SELECT s.*, p.model AS model, p.reasoning_effort, p.reasoning_summary, p.service_tier, p.approval_policy_json, p.approvals_reviewer, p.permission_mode, p.token_usage_json, CASE WHEN EXISTS (SELECT 1 FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting' AND json_extract(ai.payload_json,'$.interaction.kind')='approval') THEN 'approval' WHEN EXISTS (SELECT 1 FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting') THEN 'input' ELSE NULL END AS attention_kind, (SELECT COUNT(*) FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting') AS attention_count FROM agent_sessions s LEFT JOIN agent_session_providers p ON p.session_id=s.id AND p.provider=s.provider WHERE s.id=?")
|
|
41
|
+
.get(id);
|
|
42
|
+
return row ? sessionFromRow(row) : null;
|
|
43
|
+
}
|
|
44
|
+
listSessions() {
|
|
45
|
+
return this.database.raw
|
|
46
|
+
.prepare("SELECT s.*, p.model AS model, p.reasoning_effort, p.reasoning_summary, p.service_tier, p.approval_policy_json, p.approvals_reviewer, p.permission_mode, p.token_usage_json, CASE WHEN EXISTS (SELECT 1 FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting' AND json_extract(ai.payload_json,'$.interaction.kind')='approval') THEN 'approval' WHEN EXISTS (SELECT 1 FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting') THEN 'input' ELSE NULL END AS attention_kind, (SELECT COUNT(*) FROM agent_items ai JOIN agent_turns at ON at.id=ai.turn_id WHERE at.session_id=s.id AND ai.type='interaction' AND ai.status='waiting') AS attention_count FROM agent_sessions s LEFT JOIN agent_session_providers p ON p.session_id=s.id AND p.provider=s.provider ORDER BY s.updated_at DESC")
|
|
47
|
+
.all().map(sessionFromRow);
|
|
48
|
+
}
|
|
49
|
+
deleteSession(id) {
|
|
50
|
+
this.database.raw.prepare("DELETE FROM agent_sessions WHERE id=?").run(id);
|
|
51
|
+
}
|
|
52
|
+
getProviderState(sessionId, provider) {
|
|
53
|
+
const row = this.database.raw
|
|
54
|
+
.prepare("SELECT * FROM agent_session_providers WHERE session_id=? AND provider=?")
|
|
55
|
+
.get(sessionId, provider);
|
|
56
|
+
return row ? providerStateFromRow(row) : null;
|
|
57
|
+
}
|
|
58
|
+
upsertProviderState(state) {
|
|
59
|
+
this.database.raw
|
|
60
|
+
.prepare("INSERT INTO agent_session_providers(session_id, provider, provider_session_id, model, reasoning_effort, reasoning_summary, service_tier, approval_policy_json, approvals_reviewer, permission_mode, token_usage_json, continuity_context, synced_through_turn_id, created_at, updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(session_id, provider) DO UPDATE SET provider_session_id=excluded.provider_session_id, model=excluded.model, reasoning_effort=excluded.reasoning_effort, reasoning_summary=excluded.reasoning_summary, service_tier=excluded.service_tier, approval_policy_json=excluded.approval_policy_json, approvals_reviewer=excluded.approvals_reviewer, permission_mode=excluded.permission_mode, token_usage_json=excluded.token_usage_json, continuity_context=excluded.continuity_context, synced_through_turn_id=excluded.synced_through_turn_id, updated_at=excluded.updated_at")
|
|
61
|
+
.run(state.sessionId, state.provider, state.providerSessionId, state.model, state.reasoningEffort, state.reasoningSummary, state.serviceTier, state.approvalPolicy === null
|
|
62
|
+
? null
|
|
63
|
+
: JSON.stringify(state.approvalPolicy), state.approvalsReviewer, state.permissionMode, JSON.stringify(state.tokenUsage), state.continuityContext, state.syncedThroughTurnId, state.createdAt, state.updatedAt);
|
|
64
|
+
}
|
|
65
|
+
insertTurn(turn) {
|
|
66
|
+
this.database.raw
|
|
67
|
+
.prepare("INSERT INTO agent_turns(id, session_id, provider_turn_id, provider, model, reasoning_effort, reasoning_summary, service_tier, approval_policy_json, approvals_reviewer, permission_mode, usage_json, origin, status, error_json, started_at, completed_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
|
68
|
+
.run(turn.id, turn.sessionId, turn.providerTurnId, turn.provider, turn.model, turn.reasoningEffort, turn.reasoningSummary, turn.serviceTier, turn.approvalPolicy === null
|
|
69
|
+
? null
|
|
70
|
+
: JSON.stringify(turn.approvalPolicy), turn.approvalsReviewer, turn.permissionMode, JSON.stringify(turn.usage), turnOriginCode(turn.source), turn.status, JSON.stringify(turn.error), turn.startedAt, turn.completedAt);
|
|
71
|
+
}
|
|
72
|
+
updateTurn(turn) {
|
|
73
|
+
this.database.raw
|
|
74
|
+
.prepare("UPDATE agent_turns SET session_id=?, provider_turn_id=?, provider=?, model=?, reasoning_effort=?, reasoning_summary=?, service_tier=?, approval_policy_json=?, approvals_reviewer=?, permission_mode=?, usage_json=?, origin=?, status=?, error_json=?, started_at=?, completed_at=? WHERE id=?")
|
|
75
|
+
.run(turn.sessionId, turn.providerTurnId, turn.provider, turn.model, turn.reasoningEffort, turn.reasoningSummary, turn.serviceTier, turn.approvalPolicy === null
|
|
76
|
+
? null
|
|
77
|
+
: JSON.stringify(turn.approvalPolicy), turn.approvalsReviewer, turn.permissionMode, JSON.stringify(turn.usage), turnOriginCode(turn.source), turn.status, JSON.stringify(turn.error), turn.startedAt, turn.completedAt, turn.id);
|
|
78
|
+
}
|
|
79
|
+
insertItem(item) {
|
|
80
|
+
this.database.raw
|
|
81
|
+
.prepare("INSERT INTO agent_items(id, turn_id, provider_item_id, type, sequence, status, payload_json, created_at, updated_at) VALUES(?,?,?,?,?,?,?,?,?)")
|
|
82
|
+
.run(item.id, item.turnId, item.providerItemId, item.type, item.sequence, item.status, JSON.stringify(itemPayload(item)), item.createdAt, item.updatedAt);
|
|
83
|
+
}
|
|
84
|
+
updateItem(item) {
|
|
85
|
+
this.database.raw
|
|
86
|
+
.prepare("UPDATE agent_items SET turn_id=?, provider_item_id=?, type=?, sequence=?, status=?, payload_json=?, created_at=?, updated_at=? WHERE id=?")
|
|
87
|
+
.run(item.turnId, item.providerItemId, item.type, item.sequence, item.status, JSON.stringify(itemPayload(item)), item.createdAt, item.updatedAt, item.id);
|
|
88
|
+
}
|
|
89
|
+
history(sessionId) {
|
|
90
|
+
const session = this.getSession(sessionId);
|
|
91
|
+
if (!session)
|
|
92
|
+
return null;
|
|
93
|
+
const turns = this.database.raw
|
|
94
|
+
.prepare("SELECT * FROM agent_turns WHERE session_id=? ORDER BY started_at ASC")
|
|
95
|
+
.all(sessionId).map(turnFromRow);
|
|
96
|
+
const items = this.database.raw
|
|
97
|
+
.prepare("SELECT i.* FROM agent_items i JOIN agent_turns t ON t.id=i.turn_id WHERE t.session_id=? ORDER BY i.sequence ASC")
|
|
98
|
+
.all(sessionId);
|
|
99
|
+
const itemsByTurn = new Map();
|
|
100
|
+
for (const row of items) {
|
|
101
|
+
const turnItems = itemsByTurn.get(row.turn_id) ?? [];
|
|
102
|
+
turnItems.push(itemFromRow(row));
|
|
103
|
+
itemsByTurn.set(row.turn_id, turnItems);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
session,
|
|
107
|
+
turns: turns.map((turn) => ({
|
|
108
|
+
turn,
|
|
109
|
+
items: itemsByTurn.get(turn.id) ?? [],
|
|
110
|
+
})),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
historyUpdate(sessionId, turnIds, itemIds) {
|
|
114
|
+
const session = this.getSession(sessionId);
|
|
115
|
+
if (!session)
|
|
116
|
+
return null;
|
|
117
|
+
const items = selectByIds(this.database, "SELECT i.* FROM agent_items i JOIN agent_turns t ON t.id=i.turn_id WHERE t.session_id=? AND i.id IN", sessionId, itemIds).map(itemFromRow);
|
|
118
|
+
const turns = selectByIds(this.database, "SELECT * FROM agent_turns WHERE session_id=? AND id IN", sessionId, [...turnIds, ...items.map((item) => item.turnId)]).map(turnFromRow);
|
|
119
|
+
return { session, turns, items };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function selectByIds(database, prefix, sessionId, ids) {
|
|
123
|
+
const unique = [...new Set(ids)].filter(Boolean);
|
|
124
|
+
if (!unique.length)
|
|
125
|
+
return [];
|
|
126
|
+
const placeholders = unique.map(() => "?").join(",");
|
|
127
|
+
return database.raw
|
|
128
|
+
.prepare(prefix + " (" + placeholders + ")")
|
|
129
|
+
.all(sessionId, ...unique);
|
|
130
|
+
}
|
|
131
|
+
function sessionFromRow(row) {
|
|
132
|
+
return {
|
|
133
|
+
id: row.id,
|
|
134
|
+
workspaceRoot: row.workspace_root,
|
|
135
|
+
tokenUsage: parseJson(row.token_usage_json),
|
|
136
|
+
provider: row.provider,
|
|
137
|
+
model: row.model,
|
|
138
|
+
reasoningEffort: row.reasoning_effort,
|
|
139
|
+
reasoningSummary: row.reasoning_summary,
|
|
140
|
+
serviceTier: row.service_tier,
|
|
141
|
+
approvalPolicy: parseJson(row.approval_policy_json),
|
|
142
|
+
approvalsReviewer: row.approvals_reviewer,
|
|
143
|
+
permissionMode: row.permission_mode,
|
|
144
|
+
status: row.status,
|
|
145
|
+
attention: row.attention_kind && row.attention_count > 0
|
|
146
|
+
? { kind: row.attention_kind, count: row.attention_count }
|
|
147
|
+
: null,
|
|
148
|
+
createdAt: row.created_at,
|
|
149
|
+
updatedAt: row.updated_at,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function providerStateFromRow(row) {
|
|
153
|
+
return {
|
|
154
|
+
sessionId: row.session_id,
|
|
155
|
+
provider: row.provider,
|
|
156
|
+
providerSessionId: row.provider_session_id,
|
|
157
|
+
tokenUsage: parseJson(row.token_usage_json),
|
|
158
|
+
model: row.model,
|
|
159
|
+
reasoningEffort: row.reasoning_effort,
|
|
160
|
+
reasoningSummary: row.reasoning_summary,
|
|
161
|
+
serviceTier: row.service_tier,
|
|
162
|
+
approvalPolicy: parseJson(row.approval_policy_json),
|
|
163
|
+
approvalsReviewer: row.approvals_reviewer,
|
|
164
|
+
permissionMode: row.permission_mode,
|
|
165
|
+
continuityContext: row.continuity_context,
|
|
166
|
+
syncedThroughTurnId: row.synced_through_turn_id,
|
|
167
|
+
createdAt: row.created_at,
|
|
168
|
+
updatedAt: row.updated_at,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function turnFromRow(row) {
|
|
172
|
+
return {
|
|
173
|
+
id: row.id,
|
|
174
|
+
sessionId: row.session_id,
|
|
175
|
+
providerTurnId: row.provider_turn_id,
|
|
176
|
+
usage: parseJson(row.usage_json),
|
|
177
|
+
provider: row.provider,
|
|
178
|
+
model: row.model,
|
|
179
|
+
reasoningEffort: row.reasoning_effort,
|
|
180
|
+
reasoningSummary: row.reasoning_summary,
|
|
181
|
+
serviceTier: row.service_tier,
|
|
182
|
+
approvalPolicy: parseJson(row.approval_policy_json),
|
|
183
|
+
approvalsReviewer: row.approvals_reviewer,
|
|
184
|
+
permissionMode: row.permission_mode,
|
|
185
|
+
source: turnSourceFromCode(row.origin),
|
|
186
|
+
status: row.status,
|
|
187
|
+
error: parseJson(row.error_json),
|
|
188
|
+
startedAt: row.started_at,
|
|
189
|
+
completedAt: row.completed_at,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function itemPayload(item) {
|
|
193
|
+
const { id: _id, turnId: _turnId, providerItemId: _providerItemId, type: _type, sequence: _sequence, status: _status, createdAt: _createdAt, updatedAt: _updatedAt, ...payload } = item;
|
|
194
|
+
return payload;
|
|
195
|
+
}
|
|
196
|
+
function itemFromRow(row) {
|
|
197
|
+
const payload = parseJson(row.payload_json);
|
|
198
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
199
|
+
throw new Error("Invalid agent item payload: " + row.id);
|
|
200
|
+
return {
|
|
201
|
+
id: row.id,
|
|
202
|
+
turnId: row.turn_id,
|
|
203
|
+
providerItemId: row.provider_item_id,
|
|
204
|
+
type: row.type,
|
|
205
|
+
sequence: row.sequence,
|
|
206
|
+
status: row.status,
|
|
207
|
+
createdAt: row.created_at,
|
|
208
|
+
updatedAt: row.updated_at,
|
|
209
|
+
...payload,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function turnOriginCode(source) {
|
|
213
|
+
return source === "mcp" ? 1 : 0;
|
|
214
|
+
}
|
|
215
|
+
function turnSourceFromCode(origin) {
|
|
216
|
+
return origin === 1 ? "mcp" : "human";
|
|
217
|
+
}
|
|
218
|
+
function parseJson(value) {
|
|
219
|
+
return value === null ? null : JSON.parse(value);
|
|
220
|
+
}
|
|
221
|
+
function monotonicTimestamp(current, candidate) {
|
|
222
|
+
const currentMs = Date.parse(current);
|
|
223
|
+
const candidateMs = Date.parse(candidate);
|
|
224
|
+
const nextMs = Math.max(Number.isFinite(candidateMs) ? candidateMs : Date.now(), Number.isFinite(currentMs) ? currentMs + 1 : 0);
|
|
225
|
+
return new Date(nextMs).toISOString();
|
|
226
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AgentProviderNativeSetting, AgentReviewTarget, AgentSessionConfig } from "./types.js";
|
|
2
|
+
export declare function emptyAgentSessionConfig(): AgentSessionConfig;
|
|
3
|
+
export declare function copyAgentSessionConfig(config: AgentSessionConfig): AgentSessionConfig;
|
|
4
|
+
export declare function approvalPolicySupported(value: AgentSessionConfig["approvalPolicy"], setting: AgentProviderNativeSetting): boolean;
|
|
5
|
+
export declare function validateReviewTarget(target: AgentReviewTarget): void;
|