@guildai/cli 0.10.0 → 0.12.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/auth-CRMO5O3N.js +29 -0
- package/dist/auth-CRMO5O3N.js.map +7 -0
- package/dist/chat-5VX2WJH2.js +303 -0
- package/dist/chat-5VX2WJH2.js.map +7 -0
- package/dist/chat-SIKDYZQK.js +31 -0
- package/dist/chat-SIKDYZQK.js.map +7 -0
- package/dist/chunk-56YCMGL3.js +522 -0
- package/dist/chunk-56YCMGL3.js.map +7 -0
- package/dist/chunk-6EX6E7WP.js +7042 -0
- package/dist/chunk-6EX6E7WP.js.map +7 -0
- package/dist/chunk-B7VAF5UG.js +532 -0
- package/dist/chunk-B7VAF5UG.js.map +7 -0
- package/dist/chunk-DOIYVBNY.js +3057 -0
- package/dist/chunk-DOIYVBNY.js.map +7 -0
- package/dist/chunk-ENKEEJ45.js +17 -0
- package/dist/chunk-ENKEEJ45.js.map +7 -0
- package/dist/chunk-IBRKVGMZ.js +97041 -0
- package/dist/chunk-IBRKVGMZ.js.map +7 -0
- package/dist/chunk-LFMQJOKC.js +19778 -0
- package/dist/chunk-LFMQJOKC.js.map +7 -0
- package/dist/chunk-M347HP6M.js +22896 -0
- package/dist/chunk-M347HP6M.js.map +7 -0
- package/dist/chunk-OYQ476FQ.js +44 -0
- package/dist/chunk-OYQ476FQ.js.map +7 -0
- package/dist/chunk-PNCUR4OB.js +257 -0
- package/dist/chunk-PNCUR4OB.js.map +7 -0
- package/dist/chunk-RIG2HZWM.js +317 -0
- package/dist/chunk-RIG2HZWM.js.map +7 -0
- package/dist/chunk-SPZPZXUN.js +826 -0
- package/dist/chunk-SPZPZXUN.js.map +7 -0
- package/dist/chunk-VVSOU6ON.js +53 -0
- package/dist/chunk-VVSOU6ON.js.map +7 -0
- package/dist/chunk-X3ADGWOF.js +3643 -0
- package/dist/chunk-X3ADGWOF.js.map +7 -0
- package/dist/commands/agent/logs.d.ts +3 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/skill/create.d.ts +3 -0
- package/dist/commands/skill/get.d.ts +3 -0
- package/dist/commands/skill/list.d.ts +3 -0
- package/dist/commands/skill/update.d.ts +3 -0
- package/dist/commands/skill/version/create.d.ts +3 -0
- package/dist/commands/skill/version/get.d.ts +3 -0
- package/dist/commands/skill/version/list.d.ts +3 -0
- package/dist/devtools-AO7YSDOD.js +67 -0
- package/dist/devtools-AO7YSDOD.js.map +7 -0
- package/dist/dist-4CBK6X5H.js +1566 -0
- package/dist/dist-4CBK6X5H.js.map +7 -0
- package/dist/esm-FRAVZP4J.js +13 -0
- package/dist/esm-FRAVZP4J.js.map +7 -0
- package/dist/execa-XQMWSABC.js +35 -0
- package/dist/execa-XQMWSABC.js.map +7 -0
- package/dist/index.js +8231 -253
- package/dist/index.js.map +7 -0
- package/dist/lib/api-types.d.ts +44 -0
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/output-mode.d.ts +9 -2
- package/dist/lib/output.d.ts +17 -1
- package/dist/lib/session-events.d.ts +14 -3
- package/dist/lib/session-polling.d.ts +24 -1
- package/dist/lib/session-resume.d.ts +15 -1
- package/dist/lib/stdin.d.ts +5 -1
- package/dist/lib/websocket-client.d.ts +46 -0
- package/dist/open-RF4X5MOP.js +13 -0
- package/dist/open-RF4X5MOP.js.map +7 -0
- package/dist/server-JYVH64FD.js +27659 -0
- package/dist/server-JYVH64FD.js.map +7 -0
- package/dist/test-SNIYRJ32.js +692 -0
- package/dist/test-SNIYRJ32.js.map +7 -0
- package/docs/skills/codex-agent-dev.md +2 -2
- package/package.json +8 -12
- package/dist/commands/agent/chat.js +0 -278
- package/dist/commands/agent/clone.js +0 -116
- package/dist/commands/agent/code.js +0 -87
- package/dist/commands/agent/fork.js +0 -218
- package/dist/commands/agent/get.js +0 -37
- package/dist/commands/agent/grep.js +0 -107
- package/dist/commands/agent/init.js +0 -390
- package/dist/commands/agent/list.js +0 -110
- package/dist/commands/agent/owners.js +0 -74
- package/dist/commands/agent/publish.js +0 -91
- package/dist/commands/agent/pull.js +0 -198
- package/dist/commands/agent/revalidate.js +0 -56
- package/dist/commands/agent/save.js +0 -346
- package/dist/commands/agent/search.js +0 -61
- package/dist/commands/agent/tags/add.js +0 -73
- package/dist/commands/agent/tags/list.js +0 -43
- package/dist/commands/agent/tags/remove.js +0 -84
- package/dist/commands/agent/tags/set.js +0 -71
- package/dist/commands/agent/test.js +0 -486
- package/dist/commands/agent/unpublish.js +0 -64
- package/dist/commands/agent/update.js +0 -110
- package/dist/commands/agent/versions.js +0 -55
- package/dist/commands/agent/workspaces.js +0 -54
- package/dist/commands/auth/login.js +0 -33
- package/dist/commands/auth/logout.js +0 -24
- package/dist/commands/auth/status.js +0 -38
- package/dist/commands/auth/token.js +0 -19
- package/dist/commands/chat.js +0 -1345
- package/dist/commands/config/get.js +0 -64
- package/dist/commands/config/list.js +0 -47
- package/dist/commands/config/path.js +0 -38
- package/dist/commands/config/set.js +0 -132
- package/dist/commands/credentials/endpoint-list.js +0 -88
- package/dist/commands/credentials/list.js +0 -50
- package/dist/commands/credentials/policy-create.js +0 -66
- package/dist/commands/credentials/policy-delete.js +0 -33
- package/dist/commands/credentials/policy-list.js +0 -45
- package/dist/commands/credentials/policy-update.js +0 -66
- package/dist/commands/doctor.js +0 -233
- package/dist/commands/integration/connect.js +0 -76
- package/dist/commands/integration/create.js +0 -298
- package/dist/commands/integration/get.js +0 -95
- package/dist/commands/integration/list.js +0 -62
- package/dist/commands/integration/operation/create.js +0 -164
- package/dist/commands/integration/operation/list.js +0 -92
- package/dist/commands/integration/update.js +0 -139
- package/dist/commands/integration/version/build.js +0 -86
- package/dist/commands/integration/version/create.js +0 -45
- package/dist/commands/integration/version/get.js +0 -72
- package/dist/commands/integration/version/list.js +0 -45
- package/dist/commands/integration/version/publish.js +0 -79
- package/dist/commands/integration/version/test.js +0 -104
- package/dist/commands/job/get-step.js +0 -40
- package/dist/commands/job/get.js +0 -44
- package/dist/commands/mcp.js +0 -34
- package/dist/commands/session/create.js +0 -59
- package/dist/commands/session/events.js +0 -56
- package/dist/commands/session/get.js +0 -33
- package/dist/commands/session/interrupt.js +0 -33
- package/dist/commands/session/list.js +0 -59
- package/dist/commands/session/send.js +0 -54
- package/dist/commands/session/tasks.js +0 -45
- package/dist/commands/setup.js +0 -230
- package/dist/commands/trigger/activate.js +0 -41
- package/dist/commands/trigger/create.js +0 -197
- package/dist/commands/trigger/deactivate.js +0 -41
- package/dist/commands/trigger/get.js +0 -33
- package/dist/commands/trigger/list.js +0 -57
- package/dist/commands/trigger/sessions.js +0 -48
- package/dist/commands/trigger/update.js +0 -128
- package/dist/commands/version.js +0 -24
- package/dist/commands/workspace/agent/add.js +0 -114
- package/dist/commands/workspace/agent/list.js +0 -78
- package/dist/commands/workspace/agent/remove.js +0 -78
- package/dist/commands/workspace/clear.js +0 -45
- package/dist/commands/workspace/context/edit.js +0 -107
- package/dist/commands/workspace/context/get.js +0 -47
- package/dist/commands/workspace/context/list.js +0 -51
- package/dist/commands/workspace/context/publish.js +0 -42
- package/dist/commands/workspace/create.js +0 -51
- package/dist/commands/workspace/current.js +0 -63
- package/dist/commands/workspace/get.js +0 -39
- package/dist/commands/workspace/list.js +0 -70
- package/dist/commands/workspace/select.js +0 -184
- package/dist/components/AgentInstallPrompt.js +0 -97
- package/dist/components/SplashAnimation.js +0 -321
- package/dist/components/TaskView.js +0 -268
- package/dist/lib/agent-helpers.js +0 -306
- package/dist/lib/alternate-screen.js +0 -59
- package/dist/lib/api-client.js +0 -154
- package/dist/lib/api-types.js +0 -10
- package/dist/lib/auth.js +0 -284
- package/dist/lib/braille-canvas.js +0 -321
- package/dist/lib/colors.js +0 -46
- package/dist/lib/config-cache.js +0 -45
- package/dist/lib/config.js +0 -153
- package/dist/lib/did-you-mean.js +0 -144
- package/dist/lib/errors.js +0 -375
- package/dist/lib/event-filter.js +0 -91
- package/dist/lib/generated-types.js +0 -56
- package/dist/lib/git.js +0 -176
- package/dist/lib/gk.js +0 -91
- package/dist/lib/guild-config.js +0 -178
- package/dist/lib/iap.js +0 -117
- package/dist/lib/integration-helpers.js +0 -38
- package/dist/lib/loading-messages.js +0 -72
- package/dist/lib/logo.js +0 -141
- package/dist/lib/lottie-serverside.js +0 -181
- package/dist/lib/markdown.js +0 -38
- package/dist/lib/npmrc.js +0 -59
- package/dist/lib/output-mode.js +0 -33
- package/dist/lib/output.js +0 -591
- package/dist/lib/owner-helpers.js +0 -112
- package/dist/lib/polling.js +0 -76
- package/dist/lib/progress.js +0 -324
- package/dist/lib/session-events-fetch.js +0 -25
- package/dist/lib/session-events.js +0 -112
- package/dist/lib/session-polling.js +0 -160
- package/dist/lib/session-resume.js +0 -96
- package/dist/lib/spinners.js +0 -770
- package/dist/lib/splash.js +0 -41
- package/dist/lib/stdin.js +0 -84
- package/dist/lib/svg-to-braille.js +0 -76
- package/dist/lib/table.js +0 -59
- package/dist/lib/update-check.js +0 -65
- package/dist/lib/validate-input-schema.js +0 -208
- package/dist/lib/version-helpers.js +0 -121
- package/dist/lib/workspace-helpers.js +0 -49
- package/dist/mcp/resources.js +0 -67
- package/dist/mcp/server.js +0 -64
- package/dist/mcp/tools.js +0 -753
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
import { createRequire as _cjsReq } from 'module'; if(typeof require === 'undefined') var require = _cjsReq(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
shouldShowEvent
|
|
4
|
+
} from "./chunk-RIG2HZWM.js";
|
|
5
|
+
import {
|
|
6
|
+
ErrorCodes,
|
|
7
|
+
GuildCLIError,
|
|
8
|
+
debug,
|
|
9
|
+
getAuthToken,
|
|
10
|
+
getGuildcoreWsUrl,
|
|
11
|
+
getIapHeaders,
|
|
12
|
+
isDebugMode
|
|
13
|
+
} from "./chunk-LFMQJOKC.js";
|
|
14
|
+
import {
|
|
15
|
+
wrapper_default
|
|
16
|
+
} from "./chunk-X3ADGWOF.js";
|
|
17
|
+
|
|
18
|
+
// src/lib/session-events-fetch.ts
|
|
19
|
+
async function fetchEvents(client, sessionId, options = {}) {
|
|
20
|
+
const { fromId, limit = 1e3 } = options;
|
|
21
|
+
let url = `/sessions/${sessionId}/events?limit=${limit}`;
|
|
22
|
+
if (fromId) {
|
|
23
|
+
url += `&from_id=${fromId}`;
|
|
24
|
+
}
|
|
25
|
+
const response = await client.get(url);
|
|
26
|
+
return response?.items || [];
|
|
27
|
+
}
|
|
28
|
+
async function fetchTasks(client, sessionId) {
|
|
29
|
+
const response = await client.get(
|
|
30
|
+
`/sessions/${sessionId}/tasks?limit=1000`
|
|
31
|
+
);
|
|
32
|
+
return response?.items || [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/lib/session-events.ts
|
|
36
|
+
var FILTERED_TASK_NAMES = /* @__PURE__ */ new Set([
|
|
37
|
+
"ui_notify",
|
|
38
|
+
"ui_prompt",
|
|
39
|
+
"__submit__",
|
|
40
|
+
"guild_credentials_request"
|
|
41
|
+
]);
|
|
42
|
+
function isFilteredTaskName(name) {
|
|
43
|
+
return FILTERED_TASK_NAMES.has(name);
|
|
44
|
+
}
|
|
45
|
+
function isAgentTask(task) {
|
|
46
|
+
return "agent" in task;
|
|
47
|
+
}
|
|
48
|
+
function isToolTask(task) {
|
|
49
|
+
return "tool_name" in task;
|
|
50
|
+
}
|
|
51
|
+
function getAgentName(agent) {
|
|
52
|
+
return agent?.full_name || "assistant";
|
|
53
|
+
}
|
|
54
|
+
function getTaskDisplayName(task) {
|
|
55
|
+
if (isAgentTask(task)) {
|
|
56
|
+
return getAgentName(task.agent);
|
|
57
|
+
}
|
|
58
|
+
if (isToolTask(task)) {
|
|
59
|
+
return task.tool_name;
|
|
60
|
+
}
|
|
61
|
+
return "Unknown";
|
|
62
|
+
}
|
|
63
|
+
function isUnfulfilledAgentInstallRequest(event) {
|
|
64
|
+
return event.type === "agent_install_request" && !event.is_fulfilled;
|
|
65
|
+
}
|
|
66
|
+
function isResponseStreamEvent(event) {
|
|
67
|
+
return event.type === "agent_notification_message" && event.content.type === "application/guild-response-stream";
|
|
68
|
+
}
|
|
69
|
+
function isDoneResponseStreamEvent(event) {
|
|
70
|
+
return isResponseStreamEvent(event) && event.content.status === "done";
|
|
71
|
+
}
|
|
72
|
+
function applyResponseStreamText(currentText, content) {
|
|
73
|
+
return content.is_delta ? currentText + content.text : content.text;
|
|
74
|
+
}
|
|
75
|
+
function getAgentNotificationText(event) {
|
|
76
|
+
if (event.content.type === "text") {
|
|
77
|
+
return event.content.data;
|
|
78
|
+
}
|
|
79
|
+
if (event.content.type === "application/guild-response-stream") {
|
|
80
|
+
return event.content.text;
|
|
81
|
+
}
|
|
82
|
+
if (event.content.type === "multipart/mixed" && event.content.parts.length === 1) {
|
|
83
|
+
const part = event.content.parts[0];
|
|
84
|
+
return part.type === "text" && typeof part.data === "string" ? part.data : "";
|
|
85
|
+
}
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
function isRootTaskEvent(event) {
|
|
89
|
+
const task = event.task;
|
|
90
|
+
if (!task) return true;
|
|
91
|
+
if ("parent_task_id" in task) return task.parent_task_id === null;
|
|
92
|
+
return task.parent_task === null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/lib/websocket-client.ts
|
|
96
|
+
var BASE_RECONNECT_DELAY = 3e3;
|
|
97
|
+
var MAX_RECONNECT_DELAY = 3e4;
|
|
98
|
+
var CONNECT_TIMEOUT = 15e3;
|
|
99
|
+
var MAX_RECONNECT_ATTEMPTS = 10;
|
|
100
|
+
var AUTH_CLOSE_CODES = /* @__PURE__ */ new Set([4001, 4003, 4004]);
|
|
101
|
+
var GuildWebSocketClient = class _GuildWebSocketClient {
|
|
102
|
+
ws = null;
|
|
103
|
+
state = "disconnected";
|
|
104
|
+
options;
|
|
105
|
+
reconnectTimer = null;
|
|
106
|
+
connectTimeout = null;
|
|
107
|
+
reconnectAttempts = 0;
|
|
108
|
+
constructor(options) {
|
|
109
|
+
this.options = options;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create and connect a WebSocket client.
|
|
113
|
+
* Rejects if initial connection or auth fails.
|
|
114
|
+
*/
|
|
115
|
+
static async create(options) {
|
|
116
|
+
const client = new _GuildWebSocketClient(options);
|
|
117
|
+
await client.connect();
|
|
118
|
+
return client;
|
|
119
|
+
}
|
|
120
|
+
buildUrl() {
|
|
121
|
+
const baseUrl = getGuildcoreWsUrl();
|
|
122
|
+
const params = new URLSearchParams();
|
|
123
|
+
if (this.options.queryParams) {
|
|
124
|
+
for (const [key, value] of Object.entries(this.options.queryParams)) {
|
|
125
|
+
params.set(key, value);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const resumeId = this.options.getFromId?.();
|
|
129
|
+
if (resumeId) {
|
|
130
|
+
params.set("from_id", resumeId);
|
|
131
|
+
}
|
|
132
|
+
const queryString = params.toString();
|
|
133
|
+
const separator = queryString ? "?" : "";
|
|
134
|
+
return `${baseUrl}${this.options.path}${separator}${queryString}`;
|
|
135
|
+
}
|
|
136
|
+
async getHeaders() {
|
|
137
|
+
const headers = {};
|
|
138
|
+
const token = await getAuthToken();
|
|
139
|
+
if (!token) {
|
|
140
|
+
throw new GuildCLIError(
|
|
141
|
+
ErrorCodes.AUTH_REQUIRED,
|
|
142
|
+
"Authentication required. Please run: guild auth login"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
146
|
+
const baseUrl = getGuildcoreWsUrl();
|
|
147
|
+
const httpUrl = baseUrl.replace(/^ws/, "http");
|
|
148
|
+
const iapHeaders = await getIapHeaders(httpUrl);
|
|
149
|
+
Object.assign(headers, iapHeaders);
|
|
150
|
+
return headers;
|
|
151
|
+
}
|
|
152
|
+
cleanupSocket() {
|
|
153
|
+
if (this.ws) {
|
|
154
|
+
this.ws.removeAllListeners();
|
|
155
|
+
try {
|
|
156
|
+
this.ws.close();
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
this.ws = null;
|
|
160
|
+
}
|
|
161
|
+
if (this.connectTimeout) {
|
|
162
|
+
clearTimeout(this.connectTimeout);
|
|
163
|
+
this.connectTimeout = null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async connect() {
|
|
167
|
+
this.cleanupSocket();
|
|
168
|
+
this.state = "connecting";
|
|
169
|
+
let headers;
|
|
170
|
+
try {
|
|
171
|
+
headers = await this.getHeaders();
|
|
172
|
+
} catch (err) {
|
|
173
|
+
this.state = "disconnected";
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
const url = this.buildUrl();
|
|
177
|
+
debug(`[WS ${this.options.label}] Connecting to ${url}`);
|
|
178
|
+
return new Promise((resolve, reject) => {
|
|
179
|
+
const ws = new wrapper_default(url, { headers });
|
|
180
|
+
this.connectTimeout = setTimeout(() => {
|
|
181
|
+
this.connectTimeout = null;
|
|
182
|
+
if (this.state === "connecting") {
|
|
183
|
+
debug(
|
|
184
|
+
`[WS ${this.options.label}] Connection timeout after ${CONNECT_TIMEOUT}ms`
|
|
185
|
+
);
|
|
186
|
+
ws.removeAllListeners();
|
|
187
|
+
ws.close();
|
|
188
|
+
const err = new Error("WebSocket connection timeout");
|
|
189
|
+
if (this.reconnectAttempts === 0) {
|
|
190
|
+
this.state = "disconnected";
|
|
191
|
+
reject(err);
|
|
192
|
+
} else {
|
|
193
|
+
this.scheduleReconnect();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}, CONNECT_TIMEOUT);
|
|
197
|
+
ws.on("open", () => {
|
|
198
|
+
if (this.connectTimeout) {
|
|
199
|
+
clearTimeout(this.connectTimeout);
|
|
200
|
+
this.connectTimeout = null;
|
|
201
|
+
}
|
|
202
|
+
debug(`[WS ${this.options.label}] Connected`);
|
|
203
|
+
this.state = "connected";
|
|
204
|
+
this.reconnectAttempts = 0;
|
|
205
|
+
resolve();
|
|
206
|
+
});
|
|
207
|
+
ws.on("message", (data) => {
|
|
208
|
+
try {
|
|
209
|
+
const message = JSON.parse(data.toString());
|
|
210
|
+
this.options.onMessage(message);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
debug(`[WS ${this.options.label}] Failed to parse message: ${err}`);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
ws.on("error", (err) => {
|
|
216
|
+
debug(`[WS ${this.options.label}] Error: ${err.message}`);
|
|
217
|
+
});
|
|
218
|
+
ws.on("close", (code) => {
|
|
219
|
+
debug(`[WS ${this.options.label}] Closed with code ${code}`);
|
|
220
|
+
if (this.state === "disconnected") return;
|
|
221
|
+
if (code === 1e3) {
|
|
222
|
+
this.state = "disconnected";
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (AUTH_CLOSE_CODES.has(code)) {
|
|
226
|
+
this.state = "disconnected";
|
|
227
|
+
const authErr = new Error(`WebSocket auth failure (close code ${code})`);
|
|
228
|
+
this.options.onError?.(authErr);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.scheduleReconnect();
|
|
232
|
+
});
|
|
233
|
+
this.ws = ws;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
scheduleReconnect() {
|
|
237
|
+
if (this.state === "disconnected") return;
|
|
238
|
+
this.reconnectAttempts++;
|
|
239
|
+
if (this.reconnectAttempts > MAX_RECONNECT_ATTEMPTS) {
|
|
240
|
+
debug(
|
|
241
|
+
`[WS ${this.options.label}] Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached`
|
|
242
|
+
);
|
|
243
|
+
this.state = "disconnected";
|
|
244
|
+
this.options.onError?.(
|
|
245
|
+
new Error(`WebSocket failed after ${MAX_RECONNECT_ATTEMPTS} reconnect attempts`)
|
|
246
|
+
);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this.state = "reconnecting";
|
|
250
|
+
const backoff = Math.min(
|
|
251
|
+
BASE_RECONNECT_DELAY * Math.pow(2, this.reconnectAttempts - 1),
|
|
252
|
+
MAX_RECONNECT_DELAY
|
|
253
|
+
);
|
|
254
|
+
const jitter = Math.random() * 2e3;
|
|
255
|
+
const delay = backoff + jitter;
|
|
256
|
+
debug(
|
|
257
|
+
`[WS ${this.options.label}] Reconnecting in ${Math.round(delay)}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`
|
|
258
|
+
);
|
|
259
|
+
this.reconnectTimer = setTimeout(() => {
|
|
260
|
+
this.reconnectTimer = null;
|
|
261
|
+
if (this.state === "disconnected") return;
|
|
262
|
+
this.connect().catch((err) => {
|
|
263
|
+
debug(`[WS ${this.options.label}] Reconnect failed: ${err}`);
|
|
264
|
+
if (err instanceof GuildCLIError && err.code === ErrorCodes.AUTH_REQUIRED) {
|
|
265
|
+
this.state = "disconnected";
|
|
266
|
+
this.options.onError?.(err);
|
|
267
|
+
} else {
|
|
268
|
+
this.scheduleReconnect();
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}, delay);
|
|
272
|
+
}
|
|
273
|
+
/** Close the connection cleanly. No reconnection will be attempted. */
|
|
274
|
+
close() {
|
|
275
|
+
this.state = "disconnected";
|
|
276
|
+
if (this.reconnectTimer) {
|
|
277
|
+
clearTimeout(this.reconnectTimer);
|
|
278
|
+
this.reconnectTimer = null;
|
|
279
|
+
}
|
|
280
|
+
this.cleanupSocket();
|
|
281
|
+
debug(`[WS ${this.options.label}] Closed by client`);
|
|
282
|
+
}
|
|
283
|
+
/** Current connection state */
|
|
284
|
+
getState() {
|
|
285
|
+
return this.state;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/lib/session-polling.ts
|
|
290
|
+
async function pollForResponse(client, sessionId, afterEventId, maxWaitTime = 6e4) {
|
|
291
|
+
const existingEvents = await fetchEvents(client, sessionId, {
|
|
292
|
+
fromId: afterEventId
|
|
293
|
+
});
|
|
294
|
+
let lastAgentRuntimeDone = null;
|
|
295
|
+
let latestEventId = afterEventId;
|
|
296
|
+
let rootRuntimeDone = false;
|
|
297
|
+
let responseStreamDone = null;
|
|
298
|
+
const responseStreamTexts = /* @__PURE__ */ new Map();
|
|
299
|
+
for (const event of existingEvents) {
|
|
300
|
+
latestEventId = event.id;
|
|
301
|
+
if (event.type === "agent_notification_message") {
|
|
302
|
+
if (isResponseStreamEvent(event)) {
|
|
303
|
+
const streamText = applyResponseStreamText(
|
|
304
|
+
responseStreamTexts.get(event.content.stream_id) ?? "",
|
|
305
|
+
event.content
|
|
306
|
+
);
|
|
307
|
+
responseStreamTexts.set(event.content.stream_id, streamText);
|
|
308
|
+
if (isRootTaskEvent(event) && isDoneResponseStreamEvent(event)) {
|
|
309
|
+
responseStreamDone = {
|
|
310
|
+
response: streamText,
|
|
311
|
+
lastEventId: event.id
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (!isRootTaskEvent(event)) continue;
|
|
317
|
+
return {
|
|
318
|
+
response: getAgentNotificationText(event),
|
|
319
|
+
lastEventId: event.id
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
if (event.type === "runtime_done" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
323
|
+
rootRuntimeDone = true;
|
|
324
|
+
if (event.content !== void 0) {
|
|
325
|
+
lastAgentRuntimeDone = JSON.stringify(event.content);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (event.type === "runtime_error" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
329
|
+
return {
|
|
330
|
+
response: JSON.stringify({ error: event.content }),
|
|
331
|
+
lastEventId: event.id
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (event.type === "agent_console" && isDebugMode()) {
|
|
335
|
+
process.stderr.write(`[console.${event.level}] ${event.content}
|
|
336
|
+
`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (lastAgentRuntimeDone !== null) {
|
|
340
|
+
return { response: lastAgentRuntimeDone, lastEventId: latestEventId };
|
|
341
|
+
}
|
|
342
|
+
if (rootRuntimeDone && responseStreamDone !== null) {
|
|
343
|
+
return { response: responseStreamDone.response, lastEventId: latestEventId };
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
return await pollViaWebSocket(
|
|
347
|
+
sessionId,
|
|
348
|
+
latestEventId,
|
|
349
|
+
maxWaitTime,
|
|
350
|
+
responseStreamTexts
|
|
351
|
+
);
|
|
352
|
+
} catch (err) {
|
|
353
|
+
debug(`pollForResponse: WebSocket failed (${err}), falling back to HTTP polling`);
|
|
354
|
+
return await pollViaHttp(
|
|
355
|
+
client,
|
|
356
|
+
sessionId,
|
|
357
|
+
latestEventId,
|
|
358
|
+
maxWaitTime,
|
|
359
|
+
responseStreamTexts
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function pollViaWebSocket(sessionId, fromId, maxWaitTime, inheritedStreamTexts) {
|
|
364
|
+
return new Promise((resolve, reject) => {
|
|
365
|
+
let settled = false;
|
|
366
|
+
let pendingRuntimeDone = null;
|
|
367
|
+
let latestEventId = fromId;
|
|
368
|
+
let runtimeDoneTimer = null;
|
|
369
|
+
let wsClient = null;
|
|
370
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
371
|
+
let responseStreamDone = null;
|
|
372
|
+
const responseStreamTexts = new Map(inheritedStreamTexts);
|
|
373
|
+
const timer = setTimeout(() => {
|
|
374
|
+
if (!settled) {
|
|
375
|
+
settled = true;
|
|
376
|
+
debug("pollViaWebSocket: timeout reached");
|
|
377
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
378
|
+
wsClient?.close();
|
|
379
|
+
const fallback = responseStreamDone ? { response: responseStreamDone.response, lastEventId: latestEventId } : { response: pendingRuntimeDone, lastEventId: latestEventId };
|
|
380
|
+
resolve(fallback);
|
|
381
|
+
}
|
|
382
|
+
}, maxWaitTime);
|
|
383
|
+
const cleanup = (result) => {
|
|
384
|
+
if (settled) return;
|
|
385
|
+
settled = true;
|
|
386
|
+
clearTimeout(timer);
|
|
387
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
388
|
+
wsClient?.close();
|
|
389
|
+
resolve(result);
|
|
390
|
+
};
|
|
391
|
+
GuildWebSocketClient.create({
|
|
392
|
+
path: `/sessions/${sessionId}/events/ws`,
|
|
393
|
+
label: `poll-${sessionId.substring(0, 8)}`,
|
|
394
|
+
getFromId: () => latestEventId,
|
|
395
|
+
onMessage: (event) => {
|
|
396
|
+
if (seenIds.has(event.id)) {
|
|
397
|
+
debug(`pollViaWebSocket: skipping duplicate event ${event.id}`);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
seenIds.add(event.id);
|
|
401
|
+
latestEventId = event.id;
|
|
402
|
+
if (event.type === "agent_notification_message") {
|
|
403
|
+
if (isResponseStreamEvent(event)) {
|
|
404
|
+
const streamText = applyResponseStreamText(
|
|
405
|
+
responseStreamTexts.get(event.content.stream_id) ?? "",
|
|
406
|
+
event.content
|
|
407
|
+
);
|
|
408
|
+
responseStreamTexts.set(event.content.stream_id, streamText);
|
|
409
|
+
if (isRootTaskEvent(event) && isDoneResponseStreamEvent(event)) {
|
|
410
|
+
responseStreamDone = {
|
|
411
|
+
response: streamText,
|
|
412
|
+
lastEventId: event.id
|
|
413
|
+
};
|
|
414
|
+
if (pendingRuntimeDone !== null) {
|
|
415
|
+
cleanup({
|
|
416
|
+
response: streamText,
|
|
417
|
+
lastEventId: event.id
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (!isRootTaskEvent(event)) return;
|
|
424
|
+
cleanup({
|
|
425
|
+
response: getAgentNotificationText(event),
|
|
426
|
+
lastEventId: event.id
|
|
427
|
+
});
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (event.type === "runtime_done" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
431
|
+
if (event.content !== void 0) {
|
|
432
|
+
pendingRuntimeDone = JSON.stringify(event.content);
|
|
433
|
+
}
|
|
434
|
+
if (responseStreamDone !== null) {
|
|
435
|
+
cleanup({
|
|
436
|
+
response: responseStreamDone.response,
|
|
437
|
+
lastEventId: latestEventId
|
|
438
|
+
});
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
442
|
+
runtimeDoneTimer = setTimeout(() => {
|
|
443
|
+
runtimeDoneTimer = null;
|
|
444
|
+
if (!settled && pendingRuntimeDone !== null) {
|
|
445
|
+
cleanup({
|
|
446
|
+
response: pendingRuntimeDone,
|
|
447
|
+
lastEventId: latestEventId
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}, 500);
|
|
451
|
+
}
|
|
452
|
+
if (event.type === "runtime_error" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
453
|
+
cleanup({
|
|
454
|
+
response: JSON.stringify({ error: event.content }),
|
|
455
|
+
lastEventId: event.id
|
|
456
|
+
});
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (event.type === "agent_console" && isDebugMode()) {
|
|
460
|
+
process.stderr.write(`[console.${event.level}] ${event.content}
|
|
461
|
+
`);
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
onError: (err) => {
|
|
465
|
+
debug(`pollViaWebSocket: fatal error: ${err.message}`);
|
|
466
|
+
if (!settled) {
|
|
467
|
+
settled = true;
|
|
468
|
+
clearTimeout(timer);
|
|
469
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
470
|
+
reject(err);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}).then((ws) => {
|
|
474
|
+
wsClient = ws;
|
|
475
|
+
if (settled) {
|
|
476
|
+
ws.close();
|
|
477
|
+
}
|
|
478
|
+
}).catch((err) => {
|
|
479
|
+
debug(`pollViaWebSocket: connection failed: ${err}`);
|
|
480
|
+
if (!settled) {
|
|
481
|
+
settled = true;
|
|
482
|
+
clearTimeout(timer);
|
|
483
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
484
|
+
reject(err);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
async function pollViaHttp(client, sessionId, fromId, maxWaitTime, inheritedStreamTexts) {
|
|
490
|
+
const startTime = Date.now();
|
|
491
|
+
let currentFromId = fromId;
|
|
492
|
+
let responseStreamDone = null;
|
|
493
|
+
const responseStreamTexts = new Map(inheritedStreamTexts);
|
|
494
|
+
while (Date.now() - startTime < maxWaitTime) {
|
|
495
|
+
const events = await fetchEvents(client, sessionId, {
|
|
496
|
+
fromId: currentFromId
|
|
497
|
+
});
|
|
498
|
+
let lastAgentRuntimeDone = null;
|
|
499
|
+
let rootRuntimeDone = false;
|
|
500
|
+
for (const event of events) {
|
|
501
|
+
debug(`pollViaHttp event: ${event.type}`);
|
|
502
|
+
if (event.type === "agent_notification_message") {
|
|
503
|
+
if (isResponseStreamEvent(event)) {
|
|
504
|
+
const streamText = applyResponseStreamText(
|
|
505
|
+
responseStreamTexts.get(event.content.stream_id) ?? "",
|
|
506
|
+
event.content
|
|
507
|
+
);
|
|
508
|
+
responseStreamTexts.set(event.content.stream_id, streamText);
|
|
509
|
+
if (isRootTaskEvent(event) && isDoneResponseStreamEvent(event)) {
|
|
510
|
+
responseStreamDone = {
|
|
511
|
+
response: streamText,
|
|
512
|
+
lastEventId: event.id
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
if (!isRootTaskEvent(event)) continue;
|
|
518
|
+
return {
|
|
519
|
+
response: getAgentNotificationText(event),
|
|
520
|
+
lastEventId: event.id
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (event.type === "runtime_done" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
524
|
+
rootRuntimeDone = true;
|
|
525
|
+
if (event.content !== void 0) {
|
|
526
|
+
lastAgentRuntimeDone = JSON.stringify(event.content);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (event.type === "runtime_error" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
530
|
+
return {
|
|
531
|
+
response: JSON.stringify({ error: event.content }),
|
|
532
|
+
lastEventId: event.id
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
if (event.type === "agent_console" && isDebugMode()) {
|
|
536
|
+
process.stderr.write(`[console.${event.level}] ${event.content}
|
|
537
|
+
`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (events.length > 0) {
|
|
541
|
+
currentFromId = events[events.length - 1].id;
|
|
542
|
+
}
|
|
543
|
+
if (lastAgentRuntimeDone !== null) {
|
|
544
|
+
return { response: lastAgentRuntimeDone, lastEventId: currentFromId };
|
|
545
|
+
}
|
|
546
|
+
if (rootRuntimeDone && responseStreamDone !== null) {
|
|
547
|
+
return { response: responseStreamDone.response, lastEventId: currentFromId };
|
|
548
|
+
}
|
|
549
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
550
|
+
}
|
|
551
|
+
return responseStreamDone ? { response: responseStreamDone.response, lastEventId: currentFromId } : { response: null, lastEventId: currentFromId };
|
|
552
|
+
}
|
|
553
|
+
async function pollForResponseWithEvents(client, sessionId, eventFilter, afterEventId, maxWaitTime = 6e4) {
|
|
554
|
+
const startTime = Date.now();
|
|
555
|
+
let fromId = afterEventId;
|
|
556
|
+
let responseStreamDone = null;
|
|
557
|
+
const responseStreamTexts = /* @__PURE__ */ new Map();
|
|
558
|
+
while (Date.now() - startTime < maxWaitTime) {
|
|
559
|
+
const events = await fetchEvents(client, sessionId, { fromId });
|
|
560
|
+
let lastAgentRuntimeDone = null;
|
|
561
|
+
let rootRuntimeDone = false;
|
|
562
|
+
for (const event of events) {
|
|
563
|
+
debug(`pollForResponseWithEvents event: ${event.type}`);
|
|
564
|
+
if (shouldShowEvent(event.type, eventFilter) && !isResponseStreamEvent(event)) {
|
|
565
|
+
process.stdout.write(JSON.stringify(event) + "\n");
|
|
566
|
+
}
|
|
567
|
+
if (event.type === "agent_notification_message") {
|
|
568
|
+
if (isResponseStreamEvent(event)) {
|
|
569
|
+
const streamText = applyResponseStreamText(
|
|
570
|
+
responseStreamTexts.get(event.content.stream_id) ?? "",
|
|
571
|
+
event.content
|
|
572
|
+
);
|
|
573
|
+
responseStreamTexts.set(event.content.stream_id, streamText);
|
|
574
|
+
if (isRootTaskEvent(event) && isDoneResponseStreamEvent(event)) {
|
|
575
|
+
responseStreamDone = {
|
|
576
|
+
response: streamText,
|
|
577
|
+
lastEventId: event.id
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
if (!isRootTaskEvent(event)) continue;
|
|
583
|
+
return {
|
|
584
|
+
response: getAgentNotificationText(event),
|
|
585
|
+
lastEventId: event.id
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
if (event.type === "runtime_done" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
589
|
+
rootRuntimeDone = true;
|
|
590
|
+
if (event.content !== void 0) {
|
|
591
|
+
lastAgentRuntimeDone = JSON.stringify(event.content);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (event.type === "runtime_error" && event.task && "agent" in event.task && isRootTaskEvent(event)) {
|
|
595
|
+
return {
|
|
596
|
+
response: JSON.stringify({ error: event.content }),
|
|
597
|
+
lastEventId: event.id
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
if (event.type === "agent_console" && isDebugMode()) {
|
|
601
|
+
process.stderr.write(`[console.${event.level}] ${event.content}
|
|
602
|
+
`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
if (events.length > 0) {
|
|
606
|
+
fromId = events[events.length - 1].id;
|
|
607
|
+
}
|
|
608
|
+
if (lastAgentRuntimeDone !== null) {
|
|
609
|
+
return { response: lastAgentRuntimeDone, lastEventId: fromId };
|
|
610
|
+
}
|
|
611
|
+
if (rootRuntimeDone && responseStreamDone !== null) {
|
|
612
|
+
return { response: responseStreamDone.response, lastEventId: fromId };
|
|
613
|
+
}
|
|
614
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
615
|
+
}
|
|
616
|
+
return responseStreamDone ? { response: responseStreamDone.response, lastEventId: fromId } : { response: null, lastEventId: fromId };
|
|
617
|
+
}
|
|
618
|
+
function checkOnceCompletion(events) {
|
|
619
|
+
const hasRootError = events.some(
|
|
620
|
+
(e) => e.type === "runtime_error" && isRootTaskEvent(e)
|
|
621
|
+
);
|
|
622
|
+
if (hasRootError) return "error";
|
|
623
|
+
const hasUIPrompt = events.some(
|
|
624
|
+
(e) => e.type === "agent_notification_message" && !isResponseStreamEvent(e) && e.task?.tool_name === "ui_prompt"
|
|
625
|
+
);
|
|
626
|
+
if (hasUIPrompt) return "ui_prompt";
|
|
627
|
+
const hasRootDone = events.some(
|
|
628
|
+
(e) => e.type === "runtime_done" && isRootTaskEvent(e)
|
|
629
|
+
);
|
|
630
|
+
const hasAgentMessage = events.some(
|
|
631
|
+
(e) => e.type === "agent_notification_message" && isRootTaskEvent(e) && !isResponseStreamEvent(e)
|
|
632
|
+
);
|
|
633
|
+
if (hasRootDone || hasAgentMessage) return "completion";
|
|
634
|
+
return null;
|
|
635
|
+
}
|
|
636
|
+
async function pollForOnce(client, sessionId, options) {
|
|
637
|
+
const inactivityTimeoutMs = options?.inactivityTimeoutMs ?? 3e5;
|
|
638
|
+
const pollIntervalMs = options?.pollIntervalMs ?? 2e3;
|
|
639
|
+
const initialEvents = await fetchEvents(client, sessionId, {});
|
|
640
|
+
const allEvents = [...initialEvents];
|
|
641
|
+
let latestEventId = initialEvents.length > 0 ? initialEvents[initialEvents.length - 1].id : void 0;
|
|
642
|
+
for (const evt of initialEvents) {
|
|
643
|
+
logOnceEvent(evt);
|
|
644
|
+
}
|
|
645
|
+
const immediateReason = checkOnceCompletion(allEvents);
|
|
646
|
+
if (immediateReason) {
|
|
647
|
+
debug("pollForOnce: immediate completion via initial fetch");
|
|
648
|
+
return { events: allEvents, lastEventId: latestEventId, reason: immediateReason };
|
|
649
|
+
}
|
|
650
|
+
try {
|
|
651
|
+
return await pollOnceViaWebSocket(
|
|
652
|
+
sessionId,
|
|
653
|
+
allEvents,
|
|
654
|
+
latestEventId,
|
|
655
|
+
inactivityTimeoutMs
|
|
656
|
+
);
|
|
657
|
+
} catch (err) {
|
|
658
|
+
debug(`pollForOnce: WebSocket failed (${err}), falling back to HTTP`);
|
|
659
|
+
return await pollOnceViaHttp(
|
|
660
|
+
client,
|
|
661
|
+
sessionId,
|
|
662
|
+
allEvents,
|
|
663
|
+
latestEventId,
|
|
664
|
+
inactivityTimeoutMs,
|
|
665
|
+
pollIntervalMs
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
function logOnceEvent(evt) {
|
|
670
|
+
const taskInfo = evt.task;
|
|
671
|
+
if (taskInfo) {
|
|
672
|
+
debug(
|
|
673
|
+
`Event: ${evt.type}, task=${taskInfo.agent || taskInfo.tool_name || "unknown"}:${(taskInfo.id || "").substring(0, 8)}, status=${taskInfo.status}`
|
|
674
|
+
);
|
|
675
|
+
} else {
|
|
676
|
+
debug(`Event: ${evt.type} (no task info)`);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
function pollOnceViaWebSocket(sessionId, initialEvents, fromId, inactivityTimeoutMs) {
|
|
680
|
+
return new Promise((resolve, reject) => {
|
|
681
|
+
let settled = false;
|
|
682
|
+
let latestEventId = fromId;
|
|
683
|
+
let wsClient = null;
|
|
684
|
+
const allEvents = [...initialEvents];
|
|
685
|
+
const seenIds = new Set(initialEvents.map((e) => e.id));
|
|
686
|
+
let runtimeDoneTimer = null;
|
|
687
|
+
let inactivityTimer = null;
|
|
688
|
+
const resetInactivityTimer = () => {
|
|
689
|
+
if (inactivityTimer) clearTimeout(inactivityTimer);
|
|
690
|
+
inactivityTimer = setTimeout(() => {
|
|
691
|
+
if (!settled) {
|
|
692
|
+
debug("pollOnceViaWebSocket: inactivity timeout");
|
|
693
|
+
cleanup({
|
|
694
|
+
events: allEvents,
|
|
695
|
+
lastEventId: latestEventId,
|
|
696
|
+
reason: "inactivity_timeout"
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
}, inactivityTimeoutMs);
|
|
700
|
+
};
|
|
701
|
+
const cleanup = (result) => {
|
|
702
|
+
if (settled) return;
|
|
703
|
+
settled = true;
|
|
704
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
705
|
+
if (inactivityTimer) clearTimeout(inactivityTimer);
|
|
706
|
+
wsClient?.close();
|
|
707
|
+
resolve(result);
|
|
708
|
+
};
|
|
709
|
+
resetInactivityTimer();
|
|
710
|
+
GuildWebSocketClient.create({
|
|
711
|
+
path: `/sessions/${sessionId}/events/ws`,
|
|
712
|
+
label: `poll-${sessionId.substring(0, 8)}`,
|
|
713
|
+
getFromId: () => latestEventId,
|
|
714
|
+
onMessage: (event) => {
|
|
715
|
+
if (seenIds.has(event.id)) return;
|
|
716
|
+
seenIds.add(event.id);
|
|
717
|
+
latestEventId = event.id;
|
|
718
|
+
allEvents.push(event);
|
|
719
|
+
logOnceEvent(event);
|
|
720
|
+
resetInactivityTimer();
|
|
721
|
+
const reason = checkOnceCompletion(allEvents);
|
|
722
|
+
if (reason) {
|
|
723
|
+
if (reason === "completion" && !runtimeDoneTimer) {
|
|
724
|
+
runtimeDoneTimer = setTimeout(() => {
|
|
725
|
+
runtimeDoneTimer = null;
|
|
726
|
+
const finalReason = checkOnceCompletion(allEvents) ?? "completion";
|
|
727
|
+
cleanup({
|
|
728
|
+
events: allEvents,
|
|
729
|
+
lastEventId: latestEventId,
|
|
730
|
+
reason: finalReason
|
|
731
|
+
});
|
|
732
|
+
}, 500);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (reason !== "completion") {
|
|
736
|
+
cleanup({ events: allEvents, lastEventId: latestEventId, reason });
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
onError: (err) => {
|
|
741
|
+
debug(`pollOnceViaWebSocket: fatal error: ${err.message}`);
|
|
742
|
+
if (!settled) {
|
|
743
|
+
settled = true;
|
|
744
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
745
|
+
if (inactivityTimer) clearTimeout(inactivityTimer);
|
|
746
|
+
reject(err);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}).then((ws) => {
|
|
750
|
+
wsClient = ws;
|
|
751
|
+
if (settled) ws.close();
|
|
752
|
+
}).catch((err) => {
|
|
753
|
+
debug(`pollOnceViaWebSocket: connection failed: ${err}`);
|
|
754
|
+
if (!settled) {
|
|
755
|
+
settled = true;
|
|
756
|
+
if (runtimeDoneTimer) clearTimeout(runtimeDoneTimer);
|
|
757
|
+
if (inactivityTimer) clearTimeout(inactivityTimer);
|
|
758
|
+
reject(err);
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
async function pollOnceViaHttp(client, sessionId, initialEvents, fromId, inactivityTimeoutMs, pollIntervalMs) {
|
|
764
|
+
const allEvents = [...initialEvents];
|
|
765
|
+
let currentFromId = fromId;
|
|
766
|
+
const maxInactivityAttempts = inactivityTimeoutMs / pollIntervalMs;
|
|
767
|
+
let inactivityCounter = 0;
|
|
768
|
+
while (true) {
|
|
769
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
770
|
+
const newEvents = await fetchEvents(client, sessionId, {
|
|
771
|
+
fromId: currentFromId
|
|
772
|
+
});
|
|
773
|
+
if (newEvents.length > 0) {
|
|
774
|
+
for (const evt of newEvents) {
|
|
775
|
+
logOnceEvent(evt);
|
|
776
|
+
}
|
|
777
|
+
allEvents.push(...newEvents);
|
|
778
|
+
currentFromId = newEvents[newEvents.length - 1].id;
|
|
779
|
+
inactivityCounter = 0;
|
|
780
|
+
} else {
|
|
781
|
+
inactivityCounter++;
|
|
782
|
+
}
|
|
783
|
+
const reason = checkOnceCompletion(allEvents);
|
|
784
|
+
if (reason) {
|
|
785
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
786
|
+
const trailingEvents = await fetchEvents(client, sessionId, {
|
|
787
|
+
fromId: currentFromId
|
|
788
|
+
});
|
|
789
|
+
if (trailingEvents.length > 0) {
|
|
790
|
+
for (const evt of trailingEvents) {
|
|
791
|
+
logOnceEvent(evt);
|
|
792
|
+
}
|
|
793
|
+
allEvents.push(...trailingEvents);
|
|
794
|
+
currentFromId = trailingEvents[trailingEvents.length - 1].id;
|
|
795
|
+
}
|
|
796
|
+
const finalReason = checkOnceCompletion(allEvents) ?? reason;
|
|
797
|
+
return { events: allEvents, lastEventId: currentFromId, reason: finalReason };
|
|
798
|
+
}
|
|
799
|
+
if (inactivityCounter >= maxInactivityAttempts) {
|
|
800
|
+
debug(`pollOnceViaHttp: inactivity timeout (${inactivityCounter} empty polls)`);
|
|
801
|
+
return {
|
|
802
|
+
events: allEvents,
|
|
803
|
+
lastEventId: currentFromId,
|
|
804
|
+
reason: "inactivity_timeout"
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
export {
|
|
811
|
+
fetchEvents,
|
|
812
|
+
fetchTasks,
|
|
813
|
+
isFilteredTaskName,
|
|
814
|
+
getAgentName,
|
|
815
|
+
getTaskDisplayName,
|
|
816
|
+
isUnfulfilledAgentInstallRequest,
|
|
817
|
+
isResponseStreamEvent,
|
|
818
|
+
isDoneResponseStreamEvent,
|
|
819
|
+
applyResponseStreamText,
|
|
820
|
+
getAgentNotificationText,
|
|
821
|
+
isRootTaskEvent,
|
|
822
|
+
pollForResponse,
|
|
823
|
+
pollForResponseWithEvents,
|
|
824
|
+
pollForOnce
|
|
825
|
+
};
|
|
826
|
+
//# sourceMappingURL=chunk-SPZPZXUN.js.map
|