@agents-tower/core 0.1.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/adapters/claude.d.ts +2 -0
- package/dist/adapters/claude.js +43 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex-cloud.d.ts +4 -0
- package/dist/adapters/codex-cloud.js +80 -0
- package/dist/adapters/codex-cloud.js.map +1 -0
- package/dist/adapters/codex-local.d.ts +17 -0
- package/dist/adapters/codex-local.js +180 -0
- package/dist/adapters/codex-local.js.map +1 -0
- package/dist/adapters/cursor-cloud.d.ts +2 -0
- package/dist/adapters/cursor-cloud.js +54 -0
- package/dist/adapters/cursor-cloud.js.map +1 -0
- package/dist/adapters/cursor-local.d.ts +2 -0
- package/dist/adapters/cursor-local.js +37 -0
- package/dist/adapters/cursor-local.js.map +1 -0
- package/dist/adapters/helpers.d.ts +15 -0
- package/dist/adapters/helpers.js +33 -0
- package/dist/adapters/helpers.js.map +1 -0
- package/dist/adapters/hermes.d.ts +2 -0
- package/dist/adapters/hermes.js +41 -0
- package/dist/adapters/hermes.js.map +1 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/openclaw.d.ts +2 -0
- package/dist/adapters/openclaw.js +41 -0
- package/dist/adapters/openclaw.js.map +1 -0
- package/dist/adapters/presence.d.ts +2 -0
- package/dist/adapters/presence.js +36 -0
- package/dist/adapters/presence.js.map +1 -0
- package/dist/adapters/static-source.d.ts +15 -0
- package/dist/adapters/static-source.js +41 -0
- package/dist/adapters/static-source.js.map +1 -0
- package/dist/adapters/types.d.ts +44 -0
- package/dist/adapters/types.js +3 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/app-server.d.ts +94 -0
- package/dist/app-server.js +382 -0
- package/dist/app-server.js.map +1 -0
- package/dist/app-settings.d.ts +52 -0
- package/dist/app-settings.js +268 -0
- package/dist/app-settings.js.map +1 -0
- package/dist/appearance.d.ts +6 -0
- package/dist/appearance.js +84 -0
- package/dist/appearance.js.map +1 -0
- package/dist/aseprite.d.ts +4 -0
- package/dist/aseprite.js +42 -0
- package/dist/aseprite.js.map +1 -0
- package/dist/claude-agent-sdk.d.ts +44 -0
- package/dist/claude-agent-sdk.js +347 -0
- package/dist/claude-agent-sdk.js.map +1 -0
- package/dist/claude-home-cache.d.ts +61 -0
- package/dist/claude-home-cache.js +438 -0
- package/dist/claude-home-cache.js.map +1 -0
- package/dist/claude.d.ts +154 -0
- package/dist/claude.js +3495 -0
- package/dist/claude.js.map +1 -0
- package/dist/cloud.d.ts +2 -0
- package/dist/cloud.js +25 -0
- package/dist/cloud.js.map +1 -0
- package/dist/codex-command.d.ts +25 -0
- package/dist/codex-command.js +235 -0
- package/dist/codex-command.js.map +1 -0
- package/dist/codex-session-files.d.ts +8 -0
- package/dist/codex-session-files.js +509 -0
- package/dist/codex-session-files.js.map +1 -0
- package/dist/codex-thread-query.d.ts +14 -0
- package/dist/codex-thread-query.js +82 -0
- package/dist/codex-thread-query.js.map +1 -0
- package/dist/cursor-cloud-data.d.ts +34 -0
- package/dist/cursor-cloud-data.js +344 -0
- package/dist/cursor-cloud-data.js.map +1 -0
- package/dist/cursor-lib/local-discovery.d.ts +17 -0
- package/dist/cursor-lib/local-discovery.js +251 -0
- package/dist/cursor-lib/local-discovery.js.map +1 -0
- package/dist/cursor-lib/shared.d.ts +5 -0
- package/dist/cursor-lib/shared.js +88 -0
- package/dist/cursor-lib/shared.js.map +1 -0
- package/dist/cursor.d.ts +8 -0
- package/dist/cursor.js +1584 -0
- package/dist/cursor.js.map +1 -0
- package/dist/domain/codex-turn-semantics.d.ts +4 -0
- package/dist/domain/codex-turn-semantics.js +49 -0
- package/dist/domain/codex-turn-semantics.js.map +1 -0
- package/dist/domain/workload-policy.d.ts +8 -0
- package/dist/domain/workload-policy.js +268 -0
- package/dist/domain/workload-policy.js.map +1 -0
- package/dist/domain/workspace-activity.d.ts +10 -0
- package/dist/domain/workspace-activity.js +372 -0
- package/dist/domain/workspace-activity.js.map +1 -0
- package/dist/goal.d.ts +11 -0
- package/dist/goal.js +76 -0
- package/dist/goal.js.map +1 -0
- package/dist/hermes-hook-install.d.ts +12 -0
- package/dist/hermes-hook-install.js +335 -0
- package/dist/hermes-hook-install.js.map +1 -0
- package/dist/hermes.d.ts +97 -0
- package/dist/hermes.js +2446 -0
- package/dist/hermes.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/live-monitor-lib/events.d.ts +43 -0
- package/dist/live-monitor-lib/events.js +1463 -0
- package/dist/live-monitor-lib/events.js.map +1 -0
- package/dist/live-monitor-lib/rollout-hooks.d.ts +13 -0
- package/dist/live-monitor-lib/rollout-hooks.js +253 -0
- package/dist/live-monitor-lib/rollout-hooks.js.map +1 -0
- package/dist/live-monitor.d.ts +102 -0
- package/dist/live-monitor.js +1461 -0
- package/dist/live-monitor.js.map +1 -0
- package/dist/local-thread-selection.d.ts +2 -0
- package/dist/local-thread-selection.js +58 -0
- package/dist/local-thread-selection.js.map +1 -0
- package/dist/openclaw.d.ts +41 -0
- package/dist/openclaw.js +715 -0
- package/dist/openclaw.js.map +1 -0
- package/dist/presence.d.ts +9 -0
- package/dist/presence.js +108 -0
- package/dist/presence.js.map +1 -0
- package/dist/project-identity.d.ts +7 -0
- package/dist/project-identity.js +162 -0
- package/dist/project-identity.js.map +1 -0
- package/dist/project-paths.d.ts +23 -0
- package/dist/project-paths.js +394 -0
- package/dist/project-paths.js.map +1 -0
- package/dist/project-storage.d.ts +7 -0
- package/dist/project-storage.js +79 -0
- package/dist/project-storage.js.map +1 -0
- package/dist/room-config.d.ts +21 -0
- package/dist/room-config.js +230 -0
- package/dist/room-config.js.map +1 -0
- package/dist/services/project-discovery.d.ts +1 -0
- package/dist/services/project-discovery.js +16 -0
- package/dist/services/project-discovery.js.map +1 -0
- package/dist/services/project-live-monitor.d.ts +1 -0
- package/dist/services/project-live-monitor.js +6 -0
- package/dist/services/project-live-monitor.js.map +1 -0
- package/dist/services/project-snapshot-coordinator.d.ts +49 -0
- package/dist/services/project-snapshot-coordinator.js +152 -0
- package/dist/services/project-snapshot-coordinator.js.map +1 -0
- package/dist/services/refresh-scheduler.d.ts +8 -0
- package/dist/services/refresh-scheduler.js +44 -0
- package/dist/services/refresh-scheduler.js.map +1 -0
- package/dist/services/snapshot-assembler.d.ts +8 -0
- package/dist/services/snapshot-assembler.js +167 -0
- package/dist/services/snapshot-assembler.js.map +1 -0
- package/dist/services/thread-store.d.ts +4 -0
- package/dist/services/thread-store.js +8 -0
- package/dist/services/thread-store.js.map +1 -0
- package/dist/snapshot-lib/activity-summary.d.ts +3 -0
- package/dist/snapshot-lib/activity-summary.js +220 -0
- package/dist/snapshot-lib/activity-summary.js.map +1 -0
- package/dist/snapshot-lib/dashboard-builder.d.ts +21 -0
- package/dist/snapshot-lib/dashboard-builder.js +146 -0
- package/dist/snapshot-lib/dashboard-builder.js.map +1 -0
- package/dist/snapshot-lib/thread-summary.d.ts +27 -0
- package/dist/snapshot-lib/thread-summary.js +953 -0
- package/dist/snapshot-lib/thread-summary.js.map +1 -0
- package/dist/snapshot.d.ts +2 -0
- package/dist/snapshot.js +21 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/types.d.ts +368 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.js +29 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/text.d.ts +3 -0
- package/dist/utils/text.js +26 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/web-search.d.ts +1 -0
- package/dist/web-search.js +52 -0
- package/dist/web-search.js.map +1 -0
- package/dist/workload.d.ts +1 -0
- package/dist/workload.js +12 -0
- package/dist/workload.js.map +1 -0
- package/package.json +19 -0
|
@@ -0,0 +1,1463 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asRecord = asRecord;
|
|
4
|
+
exports.asString = asString;
|
|
5
|
+
exports.extractThreadId = extractThreadId;
|
|
6
|
+
exports.collectPaths = collectPaths;
|
|
7
|
+
exports.latestThreadAgentMessage = latestThreadAgentMessage;
|
|
8
|
+
exports.latestThreadAgentMessageIsInLastTurn = latestThreadAgentMessageIsInLastTurn;
|
|
9
|
+
exports.isFinalAgentMessageNotification = isFinalAgentMessageNotification;
|
|
10
|
+
exports.shouldMarkThreadLiveFromAppServerNotification = shouldMarkThreadLiveFromAppServerNotification;
|
|
11
|
+
exports.shouldMarkThreadStoppedFromAppServerNotification = shouldMarkThreadStoppedFromAppServerNotification;
|
|
12
|
+
exports.hasEquivalentRecentMessageEvent = hasEquivalentRecentMessageEvent;
|
|
13
|
+
exports.extractCollabReceiverThreadIds = extractCollabReceiverThreadIds;
|
|
14
|
+
exports.buildThreadReadAgentMessageEvent = buildThreadReadAgentMessageEvent;
|
|
15
|
+
exports.buildDashboardEventFromAppServerMessage = buildDashboardEventFromAppServerMessage;
|
|
16
|
+
exports.appServerDiagnosticNotePrefix = appServerDiagnosticNotePrefix;
|
|
17
|
+
exports.buildAppServerDiagnosticNote = buildAppServerDiagnosticNote;
|
|
18
|
+
exports.buildNeedsUserStateFromServerRequest = buildNeedsUserStateFromServerRequest;
|
|
19
|
+
exports.shouldStopDormantThreadAfterAppServerNotification = shouldStopDormantThreadAfterAppServerNotification;
|
|
20
|
+
const project_paths_1 = require("../project-paths");
|
|
21
|
+
const web_search_1 = require("../web-search");
|
|
22
|
+
function asRecord(value) {
|
|
23
|
+
return typeof value === "object" && value ? value : null;
|
|
24
|
+
}
|
|
25
|
+
function asString(value) {
|
|
26
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
27
|
+
}
|
|
28
|
+
function asStringArray(value) {
|
|
29
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
30
|
+
}
|
|
31
|
+
function asNeedsUserQuestionOption(value) {
|
|
32
|
+
const record = asRecord(value);
|
|
33
|
+
const label = asString(record?.label);
|
|
34
|
+
const description = asString(record?.description);
|
|
35
|
+
if (!label || !description) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return { label, description };
|
|
39
|
+
}
|
|
40
|
+
function asNeedsUserQuestion(value) {
|
|
41
|
+
const record = asRecord(value);
|
|
42
|
+
const header = asString(record?.header);
|
|
43
|
+
const id = asString(record?.id);
|
|
44
|
+
const question = asString(record?.question);
|
|
45
|
+
if (!header || !id || !question) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const rawOptions = Array.isArray(record?.options) ? record.options : null;
|
|
49
|
+
const options = rawOptions
|
|
50
|
+
? rawOptions
|
|
51
|
+
.map((entry) => asNeedsUserQuestionOption(entry))
|
|
52
|
+
.filter((entry) => Boolean(entry))
|
|
53
|
+
: null;
|
|
54
|
+
return {
|
|
55
|
+
header,
|
|
56
|
+
id,
|
|
57
|
+
question,
|
|
58
|
+
required: record?.required === false ? false : undefined,
|
|
59
|
+
isOther: record?.isOther === true,
|
|
60
|
+
isSecret: record?.isSecret === true,
|
|
61
|
+
options
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function asNeedsUserQuestions(value) {
|
|
65
|
+
return Array.isArray(value)
|
|
66
|
+
? value
|
|
67
|
+
.map((entry) => asNeedsUserQuestion(entry))
|
|
68
|
+
.filter((entry) => Boolean(entry))
|
|
69
|
+
: [];
|
|
70
|
+
}
|
|
71
|
+
function titleCaseIdentifier(value) {
|
|
72
|
+
return value
|
|
73
|
+
.replace(/[_-]+/g, " ")
|
|
74
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
75
|
+
.split(/\s+/)
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
78
|
+
.join(" ");
|
|
79
|
+
}
|
|
80
|
+
function parseSchemaOptions(schema) {
|
|
81
|
+
const enumValues = asStringArray(schema.enum);
|
|
82
|
+
if (enumValues.length > 0) {
|
|
83
|
+
return enumValues.map((value) => ({
|
|
84
|
+
label: value,
|
|
85
|
+
description: value
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
const oneOf = Array.isArray(schema.oneOf) ? schema.oneOf : [];
|
|
89
|
+
const oneOfOptions = oneOf
|
|
90
|
+
.map((entry) => {
|
|
91
|
+
const option = asRecord(entry);
|
|
92
|
+
const constValue = asString(option?.const);
|
|
93
|
+
if (!constValue) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
label: constValue,
|
|
98
|
+
description: asString(option?.title) ?? asString(option?.description) ?? constValue
|
|
99
|
+
};
|
|
100
|
+
})
|
|
101
|
+
.filter((option) => Boolean(option));
|
|
102
|
+
if (oneOfOptions.length > 0) {
|
|
103
|
+
return oneOfOptions;
|
|
104
|
+
}
|
|
105
|
+
const items = asRecord(schema.items);
|
|
106
|
+
const itemEnumValues = asStringArray(items?.enum);
|
|
107
|
+
if (itemEnumValues.length > 0) {
|
|
108
|
+
return itemEnumValues.map((value) => ({
|
|
109
|
+
label: value,
|
|
110
|
+
description: value
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
const nestedItems = asRecord(items?.items);
|
|
114
|
+
const anyOf = Array.isArray(nestedItems?.anyOf)
|
|
115
|
+
? nestedItems.anyOf
|
|
116
|
+
: Array.isArray(items?.anyOf)
|
|
117
|
+
? items.anyOf
|
|
118
|
+
: [];
|
|
119
|
+
const anyOfOptions = anyOf
|
|
120
|
+
.map((entry) => {
|
|
121
|
+
const option = asRecord(entry);
|
|
122
|
+
const constValue = asString(option?.const);
|
|
123
|
+
if (!constValue) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
label: constValue,
|
|
128
|
+
description: asString(option?.title) ?? asString(option?.description) ?? constValue
|
|
129
|
+
};
|
|
130
|
+
})
|
|
131
|
+
.filter((option) => Boolean(option));
|
|
132
|
+
return anyOfOptions.length > 0 ? anyOfOptions : null;
|
|
133
|
+
}
|
|
134
|
+
function parseMcpElicitationQuestions(schema) {
|
|
135
|
+
const properties = asRecord(schema?.properties);
|
|
136
|
+
if (!properties) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const required = new Set(asStringArray(schema?.required));
|
|
140
|
+
return Object.entries(properties)
|
|
141
|
+
.map((entry) => {
|
|
142
|
+
const [id, rawSchema] = entry;
|
|
143
|
+
const propertySchema = asRecord(rawSchema);
|
|
144
|
+
if (!propertySchema) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const header = asString(propertySchema.title) ?? titleCaseIdentifier(id);
|
|
148
|
+
const type = asString(propertySchema.type);
|
|
149
|
+
const question = asString(propertySchema.description) ?? header;
|
|
150
|
+
const options = type === "boolean"
|
|
151
|
+
? [
|
|
152
|
+
{ label: "true", description: "True" },
|
|
153
|
+
{ label: "false", description: "False" }
|
|
154
|
+
]
|
|
155
|
+
: parseSchemaOptions(propertySchema);
|
|
156
|
+
return {
|
|
157
|
+
header,
|
|
158
|
+
id,
|
|
159
|
+
question,
|
|
160
|
+
required: required.has(id),
|
|
161
|
+
isSecret: propertySchema.format === "password",
|
|
162
|
+
options
|
|
163
|
+
};
|
|
164
|
+
})
|
|
165
|
+
.filter((question) => Boolean(question));
|
|
166
|
+
}
|
|
167
|
+
function shorten(text, maxLength = 88) {
|
|
168
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
169
|
+
if (normalized.length <= maxLength) {
|
|
170
|
+
return normalized;
|
|
171
|
+
}
|
|
172
|
+
return `${normalized.slice(0, maxLength - 1)}…`;
|
|
173
|
+
}
|
|
174
|
+
function summarizePlanUpdate(params) {
|
|
175
|
+
const explanation = asString(params.explanation);
|
|
176
|
+
if (explanation) {
|
|
177
|
+
return shorten(explanation);
|
|
178
|
+
}
|
|
179
|
+
const plan = Array.isArray(params.plan) ? params.plan : [];
|
|
180
|
+
const entries = plan
|
|
181
|
+
.map((entry) => asRecord(entry))
|
|
182
|
+
.filter((entry) => Boolean(entry))
|
|
183
|
+
.map((entry) => ({
|
|
184
|
+
step: asString(entry.step),
|
|
185
|
+
status: asString(entry.status)
|
|
186
|
+
}))
|
|
187
|
+
.filter((entry) => entry.step);
|
|
188
|
+
if (entries.length === 0) {
|
|
189
|
+
return "Plan";
|
|
190
|
+
}
|
|
191
|
+
const current = entries.find((entry) => entry.status === "inProgress")
|
|
192
|
+
?? entries.find((entry) => entry.status === "pending")
|
|
193
|
+
?? entries.at(-1)
|
|
194
|
+
?? null;
|
|
195
|
+
if (!current?.step) {
|
|
196
|
+
return "Plan";
|
|
197
|
+
}
|
|
198
|
+
const statusLabel = current.status === "inProgress" ? "In progress"
|
|
199
|
+
: current.status === "pending" ? "Pending"
|
|
200
|
+
: current.status === "completed" ? "Completed"
|
|
201
|
+
: null;
|
|
202
|
+
return shorten(statusLabel ? `${statusLabel}: ${current.step}` : current.step);
|
|
203
|
+
}
|
|
204
|
+
function summarizeDiffUpdate(params) {
|
|
205
|
+
const diff = asString(params.diff);
|
|
206
|
+
if (!diff) {
|
|
207
|
+
return "Diff";
|
|
208
|
+
}
|
|
209
|
+
const files = new Set();
|
|
210
|
+
for (const line of diff.split(/\r?\n/)) {
|
|
211
|
+
const gitMatch = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
212
|
+
if (gitMatch) {
|
|
213
|
+
files.add(gitMatch[2] || gitMatch[1]);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const plusMatch = line.match(/^\+\+\+ b\/(.+)$/);
|
|
217
|
+
if (plusMatch && plusMatch[1] !== "/dev/null") {
|
|
218
|
+
files.add(plusMatch[1]);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (files.size === 1) {
|
|
222
|
+
return shorten(Array.from(files)[0] || "Diff");
|
|
223
|
+
}
|
|
224
|
+
if (files.size > 1) {
|
|
225
|
+
return `${files.size} files changed`;
|
|
226
|
+
}
|
|
227
|
+
return shorten(diff);
|
|
228
|
+
}
|
|
229
|
+
function isMeaningfulAgentText(text) {
|
|
230
|
+
if (typeof text !== "string") {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
234
|
+
if (!normalized) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return !/^[.\-_~`"'!,;:|/\\()[\]{}]+$/.test(normalized);
|
|
238
|
+
}
|
|
239
|
+
function extractNumberValue(value, ...keys) {
|
|
240
|
+
const record = asRecord(value);
|
|
241
|
+
if (!record) {
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
for (const key of keys) {
|
|
245
|
+
const candidate = record[key];
|
|
246
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) {
|
|
247
|
+
return candidate;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
function extractThreadId(value) {
|
|
253
|
+
const record = asRecord(value);
|
|
254
|
+
const direct = record ? asString(record.threadId ?? record.thread_id ?? record.conversationId ?? record.conversation_id) : undefined;
|
|
255
|
+
return direct ?? null;
|
|
256
|
+
}
|
|
257
|
+
function extractTurnId(value) {
|
|
258
|
+
const record = asRecord(value);
|
|
259
|
+
return record ? asString(record.turnId ?? record.turn_id) : undefined;
|
|
260
|
+
}
|
|
261
|
+
function extractItemId(value) {
|
|
262
|
+
const record = asRecord(value);
|
|
263
|
+
return record ? asString(record.itemId ?? record.item_id ?? record.callId ?? record.call_id ?? record.id) : undefined;
|
|
264
|
+
}
|
|
265
|
+
function collectPaths(value, output = new Set()) {
|
|
266
|
+
if (typeof value === "string") {
|
|
267
|
+
const normalized = (0, project_paths_1.canonicalizeProjectPath)(value);
|
|
268
|
+
if (normalized) {
|
|
269
|
+
output.add(normalized);
|
|
270
|
+
}
|
|
271
|
+
return output;
|
|
272
|
+
}
|
|
273
|
+
if (Array.isArray(value)) {
|
|
274
|
+
value.forEach((entry) => collectPaths(entry, output));
|
|
275
|
+
return output;
|
|
276
|
+
}
|
|
277
|
+
const record = asRecord(value);
|
|
278
|
+
if (!record) {
|
|
279
|
+
return output;
|
|
280
|
+
}
|
|
281
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
282
|
+
if (/^(\/|[A-Za-z]:[\\/])/.test(key)) {
|
|
283
|
+
collectPaths(key, output);
|
|
284
|
+
}
|
|
285
|
+
if (/(path|cwd|file|grantRoot)/i.test(key)) {
|
|
286
|
+
collectPaths(entry, output);
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (typeof entry === "object" && entry) {
|
|
290
|
+
collectPaths(entry, output);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return output;
|
|
294
|
+
}
|
|
295
|
+
function primaryPath(value) {
|
|
296
|
+
return [...collectPaths(value)][0] ?? null;
|
|
297
|
+
}
|
|
298
|
+
function latestThreadAgentMessage(thread) {
|
|
299
|
+
for (const turn of [...thread.turns].reverse()) {
|
|
300
|
+
for (const item of [...turn.items].reverse()) {
|
|
301
|
+
const record = asRecord(item);
|
|
302
|
+
if (!record || asString(record.type) !== "agentMessage") {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const text = asString(record.text);
|
|
306
|
+
if (!isMeaningfulAgentText(text)) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
turnId: asString(record.turnId ?? record.turn_id) ?? turn.id,
|
|
311
|
+
itemId: extractItemId(record),
|
|
312
|
+
phase: asString(record.phase) ?? undefined,
|
|
313
|
+
text
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
function latestThreadAgentMessageIsInLastTurn(thread) {
|
|
320
|
+
const lastTurn = thread.turns.at(-1);
|
|
321
|
+
const latestMessage = latestThreadAgentMessage(thread);
|
|
322
|
+
return Boolean(lastTurn && latestMessage?.turnId === lastTurn.id);
|
|
323
|
+
}
|
|
324
|
+
function isLiveAppServerMethod(method) {
|
|
325
|
+
return (method === "thread/started"
|
|
326
|
+
|| method === "thread/unarchived"
|
|
327
|
+
|| method === "turn/started"
|
|
328
|
+
|| method === "item/started"
|
|
329
|
+
|| method === "item/agentMessage/delta"
|
|
330
|
+
|| method === "item/plan/delta"
|
|
331
|
+
|| method === "item/reasoning/summaryTextDelta"
|
|
332
|
+
|| method === "item/reasoning/summaryPartAdded"
|
|
333
|
+
|| method === "item/reasoning/textDelta"
|
|
334
|
+
|| method === "item/commandExecution/outputDelta"
|
|
335
|
+
|| method === "item/commandExecution/terminalInteraction"
|
|
336
|
+
|| method === "item/fileChange/outputDelta"
|
|
337
|
+
|| method === "item/fileChange/patchUpdated"
|
|
338
|
+
|| method === "item/mcpToolCall/progress"
|
|
339
|
+
|| method === "item/commandExecution/requestApproval"
|
|
340
|
+
|| method === "item/fileChange/requestApproval"
|
|
341
|
+
|| method === "item/tool/requestUserInput"
|
|
342
|
+
|| method === "item/tool/call"
|
|
343
|
+
|| method === "item/autoApprovalReview/started"
|
|
344
|
+
|| method === "item/autoApprovalReview/completed"
|
|
345
|
+
|| method === "hook/started"
|
|
346
|
+
|| method === "hook/completed"
|
|
347
|
+
|| method === "model/rerouted"
|
|
348
|
+
|| method === "model/verification"
|
|
349
|
+
|| method === "turn/plan/updated"
|
|
350
|
+
|| method === "turn/diff/updated");
|
|
351
|
+
}
|
|
352
|
+
function isTurnTerminalAppServerMethod(method) {
|
|
353
|
+
return method === "turn/failed";
|
|
354
|
+
}
|
|
355
|
+
function isFinalAgentMessageNotification(message) {
|
|
356
|
+
if (message.method !== "item/completed") {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
const item = asRecord(message.params?.item);
|
|
360
|
+
return asString(item?.type) === "agentMessage" && asString(item?.phase) === "final_answer";
|
|
361
|
+
}
|
|
362
|
+
function shouldMarkThreadLiveFromAppServerNotification(method, statusType) {
|
|
363
|
+
return isLiveAppServerMethod(method) || (method === "thread/status/changed" && statusType === "active");
|
|
364
|
+
}
|
|
365
|
+
function shouldMarkThreadStoppedFromAppServerNotification(method, statusType) {
|
|
366
|
+
return (method === "thread/archived"
|
|
367
|
+
|| isTurnTerminalAppServerMethod(method)
|
|
368
|
+
|| (method === "thread/status/changed" && statusType === "systemError"));
|
|
369
|
+
}
|
|
370
|
+
function shouldStopDormantThreadAfterNotification(input) {
|
|
371
|
+
if (!input.wasOngoing) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
return input.method === "thread/status/changed" && input.statusType === "notLoaded";
|
|
375
|
+
}
|
|
376
|
+
function hasEquivalentRecentMessageEvent(recentEvents, candidate) {
|
|
377
|
+
if (candidate.kind !== "message") {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
return recentEvents.some((event) => {
|
|
381
|
+
if (event.kind !== "message") {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
if (event.threadId !== candidate.threadId) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
if (event.itemId && candidate.itemId && event.itemId === candidate.itemId) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
const left = event.detail.trim();
|
|
391
|
+
const right = candidate.detail.trim();
|
|
392
|
+
return left === right || left.startsWith(right) || right.startsWith(left);
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
function buildEventId(input) {
|
|
396
|
+
return [
|
|
397
|
+
input.projectRoot,
|
|
398
|
+
input.method,
|
|
399
|
+
input.threadId ?? "",
|
|
400
|
+
input.turnId ?? "",
|
|
401
|
+
input.itemId ?? "",
|
|
402
|
+
input.requestId ?? "",
|
|
403
|
+
input.path ?? ""
|
|
404
|
+
].join("::");
|
|
405
|
+
}
|
|
406
|
+
function summarizeFileChange(item, fallbackPath) {
|
|
407
|
+
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
408
|
+
const primaryChange = changes.find((entry) => {
|
|
409
|
+
const record = asRecord(entry);
|
|
410
|
+
return Boolean(record && typeof record.path === "string");
|
|
411
|
+
});
|
|
412
|
+
const changeRecord = asRecord(primaryChange);
|
|
413
|
+
const rawPath = asString(changeRecord?.path) ?? fallbackPath ?? null;
|
|
414
|
+
const path = rawPath ? (0, project_paths_1.canonicalizeProjectPath)(rawPath) ?? rawPath : null;
|
|
415
|
+
const changeKind = asString(changeRecord?.kind) ?? "edit";
|
|
416
|
+
const action = changeKind === "create" ? "created"
|
|
417
|
+
: changeKind === "delete" ? "deleted"
|
|
418
|
+
: changeKind === "move" || changeKind === "rename" ? "moved"
|
|
419
|
+
: "edited";
|
|
420
|
+
return {
|
|
421
|
+
path,
|
|
422
|
+
action,
|
|
423
|
+
title: action === "created" ? "File created"
|
|
424
|
+
: action === "deleted" ? "File deleted"
|
|
425
|
+
: action === "moved" ? "File moved"
|
|
426
|
+
: "File edited",
|
|
427
|
+
detail: path ?? "Files",
|
|
428
|
+
isImage: Boolean(path && /\.(png|jpe?g|gif|webp|svg|bmp)$/i.test(path)),
|
|
429
|
+
linesAdded: extractNumberValue(changeRecord, "linesAdded", "lines_added", "added")
|
|
430
|
+
?? extractNumberValue(item, "linesAdded", "lines_added"),
|
|
431
|
+
linesRemoved: extractNumberValue(changeRecord, "linesRemoved", "lines_removed", "removed")
|
|
432
|
+
?? extractNumberValue(item, "linesRemoved", "lines_removed")
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
function summarizeCommand(item, method) {
|
|
436
|
+
const command = asString(item.command) ?? method;
|
|
437
|
+
const cwd = asString(item.cwd) ?? null;
|
|
438
|
+
const status = asString(item.status) ?? "inProgress";
|
|
439
|
+
const phase = status === "failed" || status === "declined" ? "failed"
|
|
440
|
+
: status === "completed" || status === "success" ? "completed"
|
|
441
|
+
: "started";
|
|
442
|
+
return { command, cwd, phase };
|
|
443
|
+
}
|
|
444
|
+
function summarizeTool(item, fallbackLabel = "MCP tool") {
|
|
445
|
+
const tool = asString(item.tool)
|
|
446
|
+
?? asString(item.name)
|
|
447
|
+
?? asString(item.server)
|
|
448
|
+
?? fallbackLabel;
|
|
449
|
+
const status = asString(item.status) ?? "inProgress";
|
|
450
|
+
const phase = status === "failed" || status === "declined" ? "failed"
|
|
451
|
+
: status === "completed" || status === "success" ? "completed"
|
|
452
|
+
: "started";
|
|
453
|
+
return {
|
|
454
|
+
tool,
|
|
455
|
+
phase,
|
|
456
|
+
detail: shorten(tool)
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
function asReceiverThreadIds(item) {
|
|
460
|
+
const receiverThreadIds = item.receiverThreadIds ?? item.receiver_thread_ids;
|
|
461
|
+
if (Array.isArray(receiverThreadIds)) {
|
|
462
|
+
return receiverThreadIds.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
463
|
+
}
|
|
464
|
+
const receiverThreadId = asString(item.receiverThreadId ?? item.receiver_thread_id);
|
|
465
|
+
return receiverThreadId ? [receiverThreadId] : [];
|
|
466
|
+
}
|
|
467
|
+
function normalizeCollabToolName(tool) {
|
|
468
|
+
const normalized = tool.replace(/[_\s-]+/g, "").toLowerCase();
|
|
469
|
+
if (normalized === "spawnagent" || normalized === "spawnagents") {
|
|
470
|
+
return "spawn";
|
|
471
|
+
}
|
|
472
|
+
if (normalized === "waitagent" || normalized === "wait") {
|
|
473
|
+
return "wait";
|
|
474
|
+
}
|
|
475
|
+
if (normalized === "sendinput" || normalized === "sendmessage" || normalized === "followuptask") {
|
|
476
|
+
return "send";
|
|
477
|
+
}
|
|
478
|
+
if (normalized === "closeagent") {
|
|
479
|
+
return "close";
|
|
480
|
+
}
|
|
481
|
+
if (normalized === "resumeagent") {
|
|
482
|
+
return "resume";
|
|
483
|
+
}
|
|
484
|
+
return normalized;
|
|
485
|
+
}
|
|
486
|
+
function summarizeCollabAgentTool(item) {
|
|
487
|
+
const rawTool = asString(item.tool) ?? "subagent";
|
|
488
|
+
const receiverCount = asReceiverThreadIds(item).length;
|
|
489
|
+
switch (normalizeCollabToolName(rawTool)) {
|
|
490
|
+
case "spawn":
|
|
491
|
+
return receiverCount > 0
|
|
492
|
+
? `Spawning ${receiverCount} subagent${receiverCount === 1 ? "" : "s"}`
|
|
493
|
+
: "Spawning subagent";
|
|
494
|
+
case "wait":
|
|
495
|
+
return receiverCount > 1 ? `Waiting on ${receiverCount} subagents` : "Waiting on subagents";
|
|
496
|
+
case "send":
|
|
497
|
+
return receiverCount > 1 ? `Messaging ${receiverCount} subagents` : "Messaging subagent";
|
|
498
|
+
case "close":
|
|
499
|
+
return receiverCount > 1 ? `Closing ${receiverCount} subagents` : "Closing subagent";
|
|
500
|
+
case "resume":
|
|
501
|
+
return receiverCount > 1 ? `Resuming ${receiverCount} subagents` : "Resuming subagent";
|
|
502
|
+
default:
|
|
503
|
+
return rawTool;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
function collabReceiverIsNotFound(item, receiverThreadId) {
|
|
507
|
+
const agentsStates = asRecord(item.agentsStates) ?? asRecord(item.agents_states);
|
|
508
|
+
const state = asRecord(agentsStates?.[receiverThreadId]);
|
|
509
|
+
return asString(state?.status) === "notFound";
|
|
510
|
+
}
|
|
511
|
+
function extractCollabReceiverThreadIds(message) {
|
|
512
|
+
const params = asRecord(message.params) ?? {};
|
|
513
|
+
const item = asRecord(params.item);
|
|
514
|
+
if (!item || asString(item.type) !== "collabAgentToolCall") {
|
|
515
|
+
return [];
|
|
516
|
+
}
|
|
517
|
+
return asReceiverThreadIds(item).filter((threadId) => !collabReceiverIsNotFound(item, threadId));
|
|
518
|
+
}
|
|
519
|
+
function summarizeDynamicTool(params) {
|
|
520
|
+
const namespace = asString(params.namespace);
|
|
521
|
+
const tool = asString(params.tool) ?? asString(params.name) ?? "Tool";
|
|
522
|
+
return namespace ? `${namespace}.${tool}` : tool;
|
|
523
|
+
}
|
|
524
|
+
function summarizeHookRun(params) {
|
|
525
|
+
const run = asRecord(params.run);
|
|
526
|
+
return shorten(asString(run?.statusMessage)
|
|
527
|
+
?? asString(run?.eventName)
|
|
528
|
+
?? asString(run?.sourcePath)
|
|
529
|
+
?? "Hook");
|
|
530
|
+
}
|
|
531
|
+
function summarizeGuardianAction(action) {
|
|
532
|
+
const record = asRecord(action);
|
|
533
|
+
const type = asString(record?.type);
|
|
534
|
+
if (!record || !type) {
|
|
535
|
+
return "Approval review";
|
|
536
|
+
}
|
|
537
|
+
if (type === "command") {
|
|
538
|
+
return shorten(asString(record.command) ?? "Command approval review");
|
|
539
|
+
}
|
|
540
|
+
if (type === "execve") {
|
|
541
|
+
const argv = Array.isArray(record.argv)
|
|
542
|
+
? record.argv.filter((entry) => typeof entry === "string")
|
|
543
|
+
: [];
|
|
544
|
+
return shorten([asString(record.program), ...argv].filter(Boolean).join(" ") || "Exec approval review");
|
|
545
|
+
}
|
|
546
|
+
if (type === "applyPatch") {
|
|
547
|
+
const files = Array.isArray(record.files)
|
|
548
|
+
? record.files.filter((entry) => typeof entry === "string")
|
|
549
|
+
: [];
|
|
550
|
+
return files.length === 1 ? shorten(files[0]) : `${files.length || "Patch"} file approval review`;
|
|
551
|
+
}
|
|
552
|
+
if (type === "networkAccess") {
|
|
553
|
+
return shorten(asString(record.target) ?? asString(record.host) ?? "Network approval review");
|
|
554
|
+
}
|
|
555
|
+
if (type === "mcpToolCall") {
|
|
556
|
+
const server = asString(record.server);
|
|
557
|
+
const tool = asString(record.toolTitle) ?? asString(record.toolName);
|
|
558
|
+
return shorten([server, tool].filter(Boolean).join(".") || "MCP tool approval review");
|
|
559
|
+
}
|
|
560
|
+
if (type === "requestPermissions") {
|
|
561
|
+
return shorten(asString(record.reason) ?? "Permission approval review");
|
|
562
|
+
}
|
|
563
|
+
return titleCaseIdentifier(type);
|
|
564
|
+
}
|
|
565
|
+
function summarizeRawResponseItem(item) {
|
|
566
|
+
if (!item) {
|
|
567
|
+
return "Raw response item";
|
|
568
|
+
}
|
|
569
|
+
const type = asString(item.type) ?? "response item";
|
|
570
|
+
const text = asString(item.text)
|
|
571
|
+
?? asString(item.output_text)
|
|
572
|
+
?? asString(item.name)
|
|
573
|
+
?? asString(item.call_id)
|
|
574
|
+
?? asString(item.id);
|
|
575
|
+
return shorten(text ?? titleCaseIdentifier(type));
|
|
576
|
+
}
|
|
577
|
+
function rateLimitDetail(params) {
|
|
578
|
+
const rateLimits = asRecord(params.rateLimits);
|
|
579
|
+
const reached = asString(rateLimits?.rateLimitReachedType);
|
|
580
|
+
const limitName = asString(rateLimits?.limitName);
|
|
581
|
+
if (reached && limitName) {
|
|
582
|
+
return `${limitName}: ${reached}`;
|
|
583
|
+
}
|
|
584
|
+
return reached ?? limitName ?? "Rate limits updated";
|
|
585
|
+
}
|
|
586
|
+
function diagnosticMessage(params, ...keys) {
|
|
587
|
+
for (const key of keys) {
|
|
588
|
+
const value = asString(params[key]);
|
|
589
|
+
if (value) {
|
|
590
|
+
return value;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return "";
|
|
594
|
+
}
|
|
595
|
+
function eventBase(context, method, params, overrides) {
|
|
596
|
+
const threadId = overrides.threadId ?? extractThreadId(params) ?? null;
|
|
597
|
+
const turnId = overrides.turnId ?? extractTurnId(params);
|
|
598
|
+
const itemId = overrides.itemId ?? extractItemId(params.item ?? params);
|
|
599
|
+
const requestId = overrides.requestId;
|
|
600
|
+
const path = overrides.path ?? primaryPath(params);
|
|
601
|
+
return {
|
|
602
|
+
id: buildEventId({
|
|
603
|
+
projectRoot: context.projectRoot,
|
|
604
|
+
method,
|
|
605
|
+
threadId,
|
|
606
|
+
turnId,
|
|
607
|
+
itemId,
|
|
608
|
+
requestId,
|
|
609
|
+
path
|
|
610
|
+
}),
|
|
611
|
+
source: "codex",
|
|
612
|
+
confidence: "typed",
|
|
613
|
+
threadId,
|
|
614
|
+
createdAt: context.createdAt ?? new Date().toISOString(),
|
|
615
|
+
method,
|
|
616
|
+
turnId,
|
|
617
|
+
itemId,
|
|
618
|
+
itemType: overrides.itemType,
|
|
619
|
+
requestId,
|
|
620
|
+
kind: "other",
|
|
621
|
+
phase: "updated",
|
|
622
|
+
title: method,
|
|
623
|
+
detail: method,
|
|
624
|
+
path,
|
|
625
|
+
...overrides
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function buildThreadReadAgentMessageEvent(context, thread) {
|
|
629
|
+
const latestMessage = latestThreadAgentMessage(thread);
|
|
630
|
+
if (!latestMessage) {
|
|
631
|
+
return null;
|
|
632
|
+
}
|
|
633
|
+
const path = (0, project_paths_1.canonicalizeProjectPath)(thread.cwd) ?? thread.cwd;
|
|
634
|
+
const isFinalAnswer = latestMessage.phase === "final_answer";
|
|
635
|
+
return {
|
|
636
|
+
id: buildEventId({
|
|
637
|
+
projectRoot: context.projectRoot,
|
|
638
|
+
method: "thread/read/agentMessage",
|
|
639
|
+
threadId: thread.id,
|
|
640
|
+
turnId: latestMessage.turnId,
|
|
641
|
+
itemId: latestMessage.itemId,
|
|
642
|
+
path
|
|
643
|
+
}),
|
|
644
|
+
source: "codex",
|
|
645
|
+
confidence: "typed",
|
|
646
|
+
threadId: thread.id,
|
|
647
|
+
createdAt: context.createdAt ?? new Date().toISOString(),
|
|
648
|
+
method: "thread/read/agentMessage",
|
|
649
|
+
turnId: latestMessage.turnId,
|
|
650
|
+
itemId: latestMessage.itemId,
|
|
651
|
+
kind: "message",
|
|
652
|
+
phase: isFinalAnswer ? "completed" : "updated",
|
|
653
|
+
title: isFinalAnswer ? "Reply completed" : "Reply updated",
|
|
654
|
+
detail: shorten(latestMessage.text),
|
|
655
|
+
path
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function buildEventFromItem(context, method, params) {
|
|
659
|
+
const item = asRecord(params.item);
|
|
660
|
+
if (!item) {
|
|
661
|
+
return eventBase(context, method, params, {
|
|
662
|
+
kind: "item",
|
|
663
|
+
title: "Item updated",
|
|
664
|
+
detail: method
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
const itemType = asString(item.type) ?? "item";
|
|
668
|
+
const itemId = extractItemId(item);
|
|
669
|
+
const phase = method === "item/started" ? "started"
|
|
670
|
+
: method === "item/completed"
|
|
671
|
+
? (asString(item.status) === "failed" || asString(item.status) === "declined" ? "failed" : "completed")
|
|
672
|
+
: "updated";
|
|
673
|
+
if (itemType === "fileChange") {
|
|
674
|
+
const change = summarizeFileChange(item, primaryPath(params));
|
|
675
|
+
return eventBase(context, method, params, {
|
|
676
|
+
itemId,
|
|
677
|
+
kind: "fileChange",
|
|
678
|
+
phase,
|
|
679
|
+
title: change.title,
|
|
680
|
+
detail: change.detail,
|
|
681
|
+
path: change.path,
|
|
682
|
+
action: change.action,
|
|
683
|
+
isImage: change.isImage,
|
|
684
|
+
linesAdded: change.linesAdded,
|
|
685
|
+
linesRemoved: change.linesRemoved
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
if (itemType === "commandExecution") {
|
|
689
|
+
const summary = summarizeCommand(item, method);
|
|
690
|
+
return eventBase(context, method, params, {
|
|
691
|
+
itemId,
|
|
692
|
+
itemType,
|
|
693
|
+
kind: "command",
|
|
694
|
+
phase,
|
|
695
|
+
title: phase === "failed" ? "Command failed"
|
|
696
|
+
: phase === "completed" ? "Command completed"
|
|
697
|
+
: "Command started",
|
|
698
|
+
detail: summary.command,
|
|
699
|
+
command: summary.command,
|
|
700
|
+
cwd: summary.cwd ?? undefined,
|
|
701
|
+
path: summary.cwd
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
if (itemType === "enteredReviewMode" || itemType === "exitedReviewMode") {
|
|
705
|
+
return eventBase(context, method, params, {
|
|
706
|
+
itemId,
|
|
707
|
+
itemType,
|
|
708
|
+
kind: "item",
|
|
709
|
+
phase,
|
|
710
|
+
title: itemType === "enteredReviewMode" ? "Review started" : "Review finished",
|
|
711
|
+
detail: shorten(asString(item.review) ?? itemType)
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
if (itemType === "collabToolCall" || itemType === "collabAgentToolCall") {
|
|
715
|
+
const detail = summarizeCollabAgentTool(item);
|
|
716
|
+
return eventBase(context, method, params, {
|
|
717
|
+
itemId,
|
|
718
|
+
itemType,
|
|
719
|
+
kind: "subagent",
|
|
720
|
+
phase,
|
|
721
|
+
title: phase === "failed" ? "Subagent failed"
|
|
722
|
+
: phase === "completed" ? "Subagent updated"
|
|
723
|
+
: "Subagent started",
|
|
724
|
+
detail: shorten(detail)
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
if (itemType === "agentMessage") {
|
|
728
|
+
const messageText = asString(item.text);
|
|
729
|
+
if (!isMeaningfulAgentText(messageText)) {
|
|
730
|
+
return null;
|
|
731
|
+
}
|
|
732
|
+
return eventBase(context, method, params, {
|
|
733
|
+
itemId,
|
|
734
|
+
itemType,
|
|
735
|
+
kind: "message",
|
|
736
|
+
phase,
|
|
737
|
+
title: phase === "completed" ? "Reply completed" : "Reply updated",
|
|
738
|
+
detail: shorten(messageText)
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
if (itemType === "plan") {
|
|
742
|
+
return eventBase(context, method, params, {
|
|
743
|
+
itemId,
|
|
744
|
+
itemType,
|
|
745
|
+
kind: "turn",
|
|
746
|
+
phase: "updated",
|
|
747
|
+
title: "Plan updated",
|
|
748
|
+
detail: shorten(asString(item.text) ?? "Plan")
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
if (itemType === "dynamicToolCall" || itemType === "mcpToolCall") {
|
|
752
|
+
return eventBase(context, method, params, {
|
|
753
|
+
itemId,
|
|
754
|
+
itemType,
|
|
755
|
+
kind: "tool",
|
|
756
|
+
phase,
|
|
757
|
+
title: itemType === "dynamicToolCall"
|
|
758
|
+
? (phase === "failed" ? "Tool failed" : phase === "completed" ? "Tool completed" : "Tool started")
|
|
759
|
+
: (phase === "failed" ? "MCP tool failed" : phase === "completed" ? "MCP tool completed" : "MCP tool started"),
|
|
760
|
+
detail: summarizeTool(item).detail
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (itemType === "webSearch") {
|
|
764
|
+
return eventBase(context, method, params, {
|
|
765
|
+
itemId,
|
|
766
|
+
itemType,
|
|
767
|
+
kind: "tool",
|
|
768
|
+
phase,
|
|
769
|
+
title: phase === "failed" ? "Web search failed"
|
|
770
|
+
: phase === "completed" ? "Web search completed"
|
|
771
|
+
: "Web search started",
|
|
772
|
+
detail: shorten((0, web_search_1.summarizeWebSearch)(item))
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
if (itemType === "imageView") {
|
|
776
|
+
return eventBase(context, method, params, {
|
|
777
|
+
itemId,
|
|
778
|
+
itemType,
|
|
779
|
+
kind: "item",
|
|
780
|
+
phase,
|
|
781
|
+
title: phase === "completed" ? "Image viewed" : "Viewing image",
|
|
782
|
+
detail: shorten(asString(item.path) ?? "Image")
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
if (itemType === "reasoning") {
|
|
786
|
+
return eventBase(context, method, params, {
|
|
787
|
+
itemId,
|
|
788
|
+
itemType,
|
|
789
|
+
kind: "item",
|
|
790
|
+
phase,
|
|
791
|
+
title: "Reasoning updated",
|
|
792
|
+
detail: shorten(asString(item.text) ?? asString(item.summary) ?? "Reasoning")
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
if (itemType === "contextCompaction") {
|
|
796
|
+
return eventBase(context, method, params, {
|
|
797
|
+
itemId,
|
|
798
|
+
itemType,
|
|
799
|
+
kind: "item",
|
|
800
|
+
phase,
|
|
801
|
+
title: "Context compacted",
|
|
802
|
+
detail: "Conversation history compacted"
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
return eventBase(context, method, params, {
|
|
806
|
+
itemId,
|
|
807
|
+
itemType,
|
|
808
|
+
kind: "item",
|
|
809
|
+
phase,
|
|
810
|
+
title: `Item ${phase}`,
|
|
811
|
+
detail: itemType
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
function buildDashboardEventFromAppServerMessage(context, message) {
|
|
815
|
+
const method = message.method;
|
|
816
|
+
const params = asRecord(message.params) ?? {};
|
|
817
|
+
const requestId = "id" in message ? String(message.id) : undefined;
|
|
818
|
+
switch (method) {
|
|
819
|
+
case "error": {
|
|
820
|
+
const detail = diagnosticMessage(params, "message", "error") || "Codex app-server error";
|
|
821
|
+
return eventBase(context, method, params, {
|
|
822
|
+
kind: "item",
|
|
823
|
+
phase: "failed",
|
|
824
|
+
title: "Codex error",
|
|
825
|
+
detail: shorten(detail)
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
case "warning":
|
|
829
|
+
case "guardianWarning": {
|
|
830
|
+
const detail = diagnosticMessage(params, "message") || "Codex warning";
|
|
831
|
+
return eventBase(context, method, params, {
|
|
832
|
+
kind: "item",
|
|
833
|
+
phase: "failed",
|
|
834
|
+
title: method === "guardianWarning" ? "Guardian warning" : "Codex warning",
|
|
835
|
+
detail: shorten(detail)
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
case "configWarning": {
|
|
839
|
+
const detail = diagnosticMessage(params, "details", "summary") || "Configuration warning";
|
|
840
|
+
return eventBase(context, method, params, {
|
|
841
|
+
kind: "item",
|
|
842
|
+
phase: "failed",
|
|
843
|
+
title: "Config warning",
|
|
844
|
+
detail: shorten(detail),
|
|
845
|
+
path: asString(params.path) ?? null
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
case "deprecationNotice": {
|
|
849
|
+
const detail = diagnosticMessage(params, "details", "summary") || "Deprecation notice";
|
|
850
|
+
return eventBase(context, method, params, {
|
|
851
|
+
kind: "item",
|
|
852
|
+
phase: "updated",
|
|
853
|
+
title: "Deprecation notice",
|
|
854
|
+
detail: shorten(detail)
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
case "thread/started":
|
|
858
|
+
case "thread/archived":
|
|
859
|
+
case "thread/unarchived":
|
|
860
|
+
case "thread/closed":
|
|
861
|
+
return eventBase(context, method, params, {
|
|
862
|
+
kind: "status",
|
|
863
|
+
phase: method === "thread/started" ? "started"
|
|
864
|
+
: method === "thread/archived" || method === "thread/closed" ? "completed"
|
|
865
|
+
: "updated",
|
|
866
|
+
title: method === "thread/started" ? "Thread started"
|
|
867
|
+
: method === "thread/archived" ? "Thread archived"
|
|
868
|
+
: method === "thread/unarchived" ? "Thread unarchived"
|
|
869
|
+
: "Thread closed",
|
|
870
|
+
detail: extractThreadId(params) ?? method
|
|
871
|
+
});
|
|
872
|
+
case "thread/tokenUsage/updated":
|
|
873
|
+
return eventBase(context, method, params, {
|
|
874
|
+
kind: "status",
|
|
875
|
+
phase: "updated",
|
|
876
|
+
title: "Token usage updated",
|
|
877
|
+
detail: "Token usage updated"
|
|
878
|
+
});
|
|
879
|
+
case "thread/status/changed": {
|
|
880
|
+
const status = asRecord(params.status);
|
|
881
|
+
const type = asString(status?.type) ?? "unknown";
|
|
882
|
+
const activeFlags = asStringArray(status?.activeFlags);
|
|
883
|
+
return eventBase(context, method, params, {
|
|
884
|
+
kind: "status",
|
|
885
|
+
phase: activeFlags.includes("waitingOnApproval") || activeFlags.includes("waitingOnUserInput")
|
|
886
|
+
? "waiting"
|
|
887
|
+
: "updated",
|
|
888
|
+
title: activeFlags.includes("waitingOnApproval") ? "Waiting on approval"
|
|
889
|
+
: activeFlags.includes("waitingOnUserInput") ? "Waiting on input"
|
|
890
|
+
: `Thread ${type}`,
|
|
891
|
+
detail: activeFlags.length > 0 ? activeFlags.join(", ") : type
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
case "turn/started": {
|
|
895
|
+
const turn = asRecord(params.turn);
|
|
896
|
+
const turnId = extractTurnId(turn ?? params);
|
|
897
|
+
return eventBase(context, method, params, {
|
|
898
|
+
turnId,
|
|
899
|
+
kind: "turn",
|
|
900
|
+
phase: "started",
|
|
901
|
+
title: "Turn started",
|
|
902
|
+
detail: turnId ?? method
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
case "turn/completed": {
|
|
906
|
+
const turn = asRecord(params.turn);
|
|
907
|
+
const turnId = extractTurnId(turn ?? params);
|
|
908
|
+
const turnStatus = asString(turn?.status) ?? "completed";
|
|
909
|
+
const phase = turnStatus === "failed" ? "failed"
|
|
910
|
+
: turnStatus === "interrupted" ? "interrupted"
|
|
911
|
+
: "completed";
|
|
912
|
+
const error = asRecord(turn?.error);
|
|
913
|
+
return eventBase(context, method, params, {
|
|
914
|
+
turnId,
|
|
915
|
+
kind: "turn",
|
|
916
|
+
phase,
|
|
917
|
+
title: phase === "failed" ? "Turn failed"
|
|
918
|
+
: phase === "interrupted" ? "Turn interrupted"
|
|
919
|
+
: "Turn completed",
|
|
920
|
+
detail: phase === "failed"
|
|
921
|
+
? shorten(asString(error?.message) ?? turnId ?? method)
|
|
922
|
+
: turnId ?? method
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
case "turn/interrupted":
|
|
926
|
+
return eventBase(context, method, params, {
|
|
927
|
+
kind: "turn",
|
|
928
|
+
phase: "interrupted",
|
|
929
|
+
title: "Turn interrupted",
|
|
930
|
+
detail: extractTurnId(params) ?? method
|
|
931
|
+
});
|
|
932
|
+
case "turn/failed":
|
|
933
|
+
return eventBase(context, method, params, {
|
|
934
|
+
kind: "turn",
|
|
935
|
+
phase: "failed",
|
|
936
|
+
title: "Turn failed",
|
|
937
|
+
detail: shorten(asString(params.message) ?? extractTurnId(params) ?? method)
|
|
938
|
+
});
|
|
939
|
+
case "turn/plan/updated":
|
|
940
|
+
return eventBase(context, method, params, {
|
|
941
|
+
kind: "turn",
|
|
942
|
+
phase: "updated",
|
|
943
|
+
title: "Plan updated",
|
|
944
|
+
detail: summarizePlanUpdate(params)
|
|
945
|
+
});
|
|
946
|
+
case "turn/diff/updated":
|
|
947
|
+
return eventBase(context, method, params, {
|
|
948
|
+
kind: "turn",
|
|
949
|
+
phase: "updated",
|
|
950
|
+
title: "Diff updated",
|
|
951
|
+
detail: summarizeDiffUpdate(params)
|
|
952
|
+
});
|
|
953
|
+
case "item/started":
|
|
954
|
+
case "item/completed":
|
|
955
|
+
return buildEventFromItem(context, method, params);
|
|
956
|
+
case "item/agentMessage/delta":
|
|
957
|
+
return eventBase(context, method, params, {
|
|
958
|
+
itemId: extractItemId(params),
|
|
959
|
+
kind: "message",
|
|
960
|
+
phase: "updated",
|
|
961
|
+
title: "Reply updated",
|
|
962
|
+
detail: shorten(asString(params.delta) ?? asString(params.textDelta) ?? "Reply")
|
|
963
|
+
});
|
|
964
|
+
case "item/plan/delta":
|
|
965
|
+
return eventBase(context, method, params, {
|
|
966
|
+
itemId: extractItemId(params),
|
|
967
|
+
kind: "turn",
|
|
968
|
+
phase: "updated",
|
|
969
|
+
title: "Plan streaming",
|
|
970
|
+
detail: shorten(asString(params.delta) ?? asString(params.textDelta) ?? "Plan")
|
|
971
|
+
});
|
|
972
|
+
case "item/reasoning/summaryTextDelta":
|
|
973
|
+
case "item/reasoning/summaryPartAdded":
|
|
974
|
+
case "item/reasoning/textDelta":
|
|
975
|
+
return eventBase(context, method, params, {
|
|
976
|
+
itemId: extractItemId(params),
|
|
977
|
+
kind: "message",
|
|
978
|
+
phase: "updated",
|
|
979
|
+
title: "Reasoning updated",
|
|
980
|
+
detail: shorten(asString(params.delta) ?? asString(params.textDelta) ?? "Reasoning")
|
|
981
|
+
});
|
|
982
|
+
case "item/commandExecution/outputDelta":
|
|
983
|
+
return eventBase(context, method, params, {
|
|
984
|
+
itemId: extractItemId(params),
|
|
985
|
+
kind: "command",
|
|
986
|
+
phase: "updated",
|
|
987
|
+
title: "Command output",
|
|
988
|
+
detail: shorten(asString(params.delta) ?? asString(params.textDelta) ?? "Command output")
|
|
989
|
+
});
|
|
990
|
+
case "item/commandExecution/terminalInteraction":
|
|
991
|
+
return eventBase(context, method, params, {
|
|
992
|
+
itemId: extractItemId(params),
|
|
993
|
+
kind: "command",
|
|
994
|
+
phase: "updated",
|
|
995
|
+
title: "Terminal input",
|
|
996
|
+
detail: shorten(asString(params.stdin) ?? "Terminal input"),
|
|
997
|
+
command: asString(params.stdin)
|
|
998
|
+
});
|
|
999
|
+
case "item/fileChange/outputDelta":
|
|
1000
|
+
return eventBase(context, method, params, {
|
|
1001
|
+
itemId: extractItemId(params),
|
|
1002
|
+
kind: "fileChange",
|
|
1003
|
+
phase: "updated",
|
|
1004
|
+
title: "Patch updated",
|
|
1005
|
+
detail: shorten(asString(params.delta) ?? asString(params.textDelta) ?? "Patch output")
|
|
1006
|
+
});
|
|
1007
|
+
case "item/fileChange/patchUpdated": {
|
|
1008
|
+
const change = summarizeFileChange({ changes: params.changes }, primaryPath(params));
|
|
1009
|
+
return eventBase(context, method, params, {
|
|
1010
|
+
itemId: extractItemId(params),
|
|
1011
|
+
kind: "fileChange",
|
|
1012
|
+
phase: "updated",
|
|
1013
|
+
title: "Patch updated",
|
|
1014
|
+
detail: change.detail,
|
|
1015
|
+
path: change.path,
|
|
1016
|
+
action: change.action,
|
|
1017
|
+
isImage: change.isImage,
|
|
1018
|
+
linesAdded: change.linesAdded,
|
|
1019
|
+
linesRemoved: change.linesRemoved
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
case "item/mcpToolCall/progress":
|
|
1023
|
+
return eventBase(context, method, params, {
|
|
1024
|
+
itemId: extractItemId(params),
|
|
1025
|
+
itemType: "mcpToolCall",
|
|
1026
|
+
kind: "tool",
|
|
1027
|
+
phase: "updated",
|
|
1028
|
+
title: "MCP tool progress",
|
|
1029
|
+
detail: shorten(asString(params.message) ?? "MCP tool progress")
|
|
1030
|
+
});
|
|
1031
|
+
case "hook/started":
|
|
1032
|
+
case "hook/completed":
|
|
1033
|
+
return eventBase(context, method, params, {
|
|
1034
|
+
itemType: "hook",
|
|
1035
|
+
kind: "tool",
|
|
1036
|
+
phase: method === "hook/completed" ? "completed" : "started",
|
|
1037
|
+
title: method === "hook/completed" ? "Hook completed" : "Hook started",
|
|
1038
|
+
detail: summarizeHookRun(params),
|
|
1039
|
+
path: primaryPath(params.run)
|
|
1040
|
+
});
|
|
1041
|
+
case "item/autoApprovalReview/started":
|
|
1042
|
+
case "item/autoApprovalReview/completed": {
|
|
1043
|
+
const review = asRecord(params.review);
|
|
1044
|
+
const actionDetail = summarizeGuardianAction(params.action);
|
|
1045
|
+
const riskLevel = asString(review?.riskLevel);
|
|
1046
|
+
return eventBase(context, method, params, {
|
|
1047
|
+
itemId: extractItemId(params),
|
|
1048
|
+
kind: "item",
|
|
1049
|
+
phase: method.endsWith("/completed") ? "completed" : "started",
|
|
1050
|
+
title: method.endsWith("/completed") ? "Approval review completed" : "Approval review started",
|
|
1051
|
+
detail: shorten(riskLevel ? `${actionDetail} (${riskLevel})` : actionDetail)
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
case "item/commandExecution/requestApproval": {
|
|
1055
|
+
const networkApprovalContext = asRecord(params.networkApprovalContext) ?? null;
|
|
1056
|
+
return eventBase(context, method, params, {
|
|
1057
|
+
requestId,
|
|
1058
|
+
itemId: extractItemId(params),
|
|
1059
|
+
kind: "approval",
|
|
1060
|
+
phase: "waiting",
|
|
1061
|
+
title: networkApprovalContext ? "Network approval requested" : "Command approval requested",
|
|
1062
|
+
detail: shorten(asString(params.command) ?? asString(params.reason) ?? "Approval requested"),
|
|
1063
|
+
command: asString(params.command),
|
|
1064
|
+
cwd: asString(params.cwd),
|
|
1065
|
+
reason: asString(params.reason),
|
|
1066
|
+
availableDecisions: asStringArray(params.availableDecisions),
|
|
1067
|
+
networkApprovalContext
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
case "item/fileChange/requestApproval":
|
|
1071
|
+
return eventBase(context, method, params, {
|
|
1072
|
+
requestId,
|
|
1073
|
+
itemId: extractItemId(params),
|
|
1074
|
+
kind: "approval",
|
|
1075
|
+
phase: "waiting",
|
|
1076
|
+
title: "File approval requested",
|
|
1077
|
+
detail: shorten(asString(params.reason) ?? primaryPath(params) ?? "Approval requested"),
|
|
1078
|
+
reason: asString(params.reason),
|
|
1079
|
+
grantRoot: asString(params.grantRoot),
|
|
1080
|
+
availableDecisions: asStringArray(params.availableDecisions)
|
|
1081
|
+
});
|
|
1082
|
+
case "item/permissions/requestApproval":
|
|
1083
|
+
return eventBase(context, method, params, {
|
|
1084
|
+
requestId,
|
|
1085
|
+
itemId: extractItemId(params),
|
|
1086
|
+
kind: "approval",
|
|
1087
|
+
phase: "waiting",
|
|
1088
|
+
title: "Permission approval requested",
|
|
1089
|
+
detail: shorten(asString(params.reason) ?? "Permission approval requested"),
|
|
1090
|
+
cwd: asString(params.cwd),
|
|
1091
|
+
reason: asString(params.reason),
|
|
1092
|
+
availableDecisions: ["accept", "acceptForSession"]
|
|
1093
|
+
});
|
|
1094
|
+
case "item/tool/requestUserInput":
|
|
1095
|
+
return eventBase(context, method, params, {
|
|
1096
|
+
requestId,
|
|
1097
|
+
itemId: extractItemId(params),
|
|
1098
|
+
kind: "input",
|
|
1099
|
+
phase: "waiting",
|
|
1100
|
+
title: "User input requested",
|
|
1101
|
+
detail: shorten(asString(params.reason) ?? asString(params.prompt) ?? "Needs input"),
|
|
1102
|
+
reason: asString(params.reason),
|
|
1103
|
+
availableDecisions: asStringArray(params.availableDecisions)
|
|
1104
|
+
});
|
|
1105
|
+
case "mcpServer/elicitation/request":
|
|
1106
|
+
return eventBase(context, method, params, {
|
|
1107
|
+
requestId,
|
|
1108
|
+
kind: "input",
|
|
1109
|
+
phase: "waiting",
|
|
1110
|
+
title: "MCP input requested",
|
|
1111
|
+
detail: shorten(asString(params.message) ?? "MCP server needs input"),
|
|
1112
|
+
reason: asString(params.message)
|
|
1113
|
+
});
|
|
1114
|
+
case "applyPatchApproval":
|
|
1115
|
+
return eventBase(context, method, params, {
|
|
1116
|
+
requestId,
|
|
1117
|
+
kind: "approval",
|
|
1118
|
+
phase: "waiting",
|
|
1119
|
+
title: "Patch approval requested",
|
|
1120
|
+
detail: shorten(asString(params.reason) ?? primaryPath(params) ?? "Patch approval requested"),
|
|
1121
|
+
reason: asString(params.reason),
|
|
1122
|
+
grantRoot: asString(params.grantRoot),
|
|
1123
|
+
availableDecisions: ["accept", "acceptForSession", "decline", "cancel"]
|
|
1124
|
+
});
|
|
1125
|
+
case "execCommandApproval": {
|
|
1126
|
+
const command = Array.isArray(params.command)
|
|
1127
|
+
? params.command.filter((entry) => typeof entry === "string").join(" ")
|
|
1128
|
+
: undefined;
|
|
1129
|
+
return eventBase(context, method, params, {
|
|
1130
|
+
requestId,
|
|
1131
|
+
kind: "approval",
|
|
1132
|
+
phase: "waiting",
|
|
1133
|
+
title: "Command approval requested",
|
|
1134
|
+
detail: shorten(command ?? asString(params.reason) ?? "Command approval requested"),
|
|
1135
|
+
command,
|
|
1136
|
+
cwd: asString(params.cwd),
|
|
1137
|
+
reason: asString(params.reason),
|
|
1138
|
+
availableDecisions: ["accept", "acceptForSession", "decline", "cancel"]
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
case "item/tool/call":
|
|
1142
|
+
return eventBase(context, method, params, {
|
|
1143
|
+
requestId,
|
|
1144
|
+
itemId: extractItemId(params),
|
|
1145
|
+
itemType: "dynamicToolCall",
|
|
1146
|
+
kind: "tool",
|
|
1147
|
+
phase: "started",
|
|
1148
|
+
title: "Tool call requested",
|
|
1149
|
+
detail: shorten(summarizeDynamicTool(params))
|
|
1150
|
+
});
|
|
1151
|
+
case "rawResponseItem/completed": {
|
|
1152
|
+
const item = asRecord(params.item);
|
|
1153
|
+
return eventBase(context, method, params, {
|
|
1154
|
+
itemId: extractItemId(item ?? params),
|
|
1155
|
+
itemType: asString(item?.type) ?? "responseItem",
|
|
1156
|
+
kind: "item",
|
|
1157
|
+
phase: "completed",
|
|
1158
|
+
title: "Response item completed",
|
|
1159
|
+
detail: summarizeRawResponseItem(item)
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
case "model/rerouted":
|
|
1163
|
+
return eventBase(context, method, params, {
|
|
1164
|
+
kind: "item",
|
|
1165
|
+
phase: "updated",
|
|
1166
|
+
title: "Model rerouted",
|
|
1167
|
+
detail: shorten(`${asString(params.fromModel) ?? "model"} -> ${asString(params.toModel) ?? "model"}`)
|
|
1168
|
+
});
|
|
1169
|
+
case "model/verification":
|
|
1170
|
+
return eventBase(context, method, params, {
|
|
1171
|
+
kind: "item",
|
|
1172
|
+
phase: "updated",
|
|
1173
|
+
title: "Model verification",
|
|
1174
|
+
detail: asStringArray(params.verifications).join(", ") || "Model verification"
|
|
1175
|
+
});
|
|
1176
|
+
case "mcpServer/startupStatus/updated": {
|
|
1177
|
+
const status = asString(params.status) ?? "updated";
|
|
1178
|
+
return eventBase(context, method, params, {
|
|
1179
|
+
kind: "tool",
|
|
1180
|
+
phase: status === "failed" || status === "cancelled" ? "failed"
|
|
1181
|
+
: status === "ready" ? "completed"
|
|
1182
|
+
: "started",
|
|
1183
|
+
title: status === "failed" ? "MCP server failed"
|
|
1184
|
+
: status === "ready" ? "MCP server ready"
|
|
1185
|
+
: "MCP server starting",
|
|
1186
|
+
detail: shorten(asString(params.error) ?? asString(params.name) ?? status)
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
case "mcpServer/oauthLogin/completed": {
|
|
1190
|
+
const success = params.success === true;
|
|
1191
|
+
return eventBase(context, method, params, {
|
|
1192
|
+
kind: "tool",
|
|
1193
|
+
phase: success ? "completed" : "failed",
|
|
1194
|
+
title: success ? "MCP login completed" : "MCP login failed",
|
|
1195
|
+
detail: shorten(asString(params.error) ?? asString(params.name) ?? "MCP OAuth")
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
case "account/rateLimits/updated":
|
|
1199
|
+
return eventBase(context, method, params, {
|
|
1200
|
+
kind: "status",
|
|
1201
|
+
phase: "updated",
|
|
1202
|
+
title: "Rate limits updated",
|
|
1203
|
+
detail: rateLimitDetail(params)
|
|
1204
|
+
});
|
|
1205
|
+
case "windows/worldWritableWarning": {
|
|
1206
|
+
const sampleCount = Array.isArray(params.samplePaths) ? params.samplePaths.length : 0;
|
|
1207
|
+
const extraCount = typeof params.extraCount === "number" && Number.isFinite(params.extraCount) ? params.extraCount : 0;
|
|
1208
|
+
return eventBase(context, method, params, {
|
|
1209
|
+
kind: "item",
|
|
1210
|
+
phase: "failed",
|
|
1211
|
+
title: "Windows permission warning",
|
|
1212
|
+
detail: `${sampleCount + extraCount} world-writable path${sampleCount + extraCount === 1 ? "" : "s"} found`
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
case "windowsSandbox/setupCompleted": {
|
|
1216
|
+
const success = params.success === true;
|
|
1217
|
+
return eventBase(context, method, params, {
|
|
1218
|
+
kind: "item",
|
|
1219
|
+
phase: success ? "completed" : "failed",
|
|
1220
|
+
title: success ? "Windows sandbox ready" : "Windows sandbox failed",
|
|
1221
|
+
detail: shorten(asString(params.error) ?? asString(params.mode) ?? "Windows sandbox setup")
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
case "serverRequest/resolved": {
|
|
1225
|
+
const pending = context.pendingRequest ?? null;
|
|
1226
|
+
const resolvedRequestId = asString(params.requestId) ?? requestId;
|
|
1227
|
+
if (pending) {
|
|
1228
|
+
return eventBase(context, method, params, {
|
|
1229
|
+
requestId: resolvedRequestId ?? pending.requestId,
|
|
1230
|
+
threadId: pending.threadId,
|
|
1231
|
+
turnId: pending.turnId,
|
|
1232
|
+
itemId: pending.itemId,
|
|
1233
|
+
kind: pending.kind === "approval" ? "approval" : "input",
|
|
1234
|
+
phase: "completed",
|
|
1235
|
+
title: pending.kind === "approval" ? "Approval resolved" : "Input resolved",
|
|
1236
|
+
detail: pending.reason ?? pending.command ?? pending.kind
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
return eventBase(context, method, params, {
|
|
1240
|
+
requestId: resolvedRequestId,
|
|
1241
|
+
kind: "other",
|
|
1242
|
+
phase: "completed",
|
|
1243
|
+
title: "Request resolved",
|
|
1244
|
+
detail: resolvedRequestId ?? method
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
default:
|
|
1248
|
+
return null;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
function appServerDiagnosticNotePrefix(method) {
|
|
1252
|
+
switch (method) {
|
|
1253
|
+
case "error":
|
|
1254
|
+
return "Codex app-server error:";
|
|
1255
|
+
case "warning":
|
|
1256
|
+
return "Codex warning:";
|
|
1257
|
+
case "guardianWarning":
|
|
1258
|
+
return "Codex guardian warning:";
|
|
1259
|
+
case "configWarning":
|
|
1260
|
+
return "Codex config warning:";
|
|
1261
|
+
case "deprecationNotice":
|
|
1262
|
+
return "Codex deprecation notice:";
|
|
1263
|
+
case "mcpServer/startupStatus/updated":
|
|
1264
|
+
return "Codex MCP server status:";
|
|
1265
|
+
case "mcpServer/oauthLogin/completed":
|
|
1266
|
+
return "Codex MCP login:";
|
|
1267
|
+
case "account/rateLimits/updated":
|
|
1268
|
+
return "Codex rate limit:";
|
|
1269
|
+
case "windows/worldWritableWarning":
|
|
1270
|
+
return "Codex Windows permission warning:";
|
|
1271
|
+
case "windowsSandbox/setupCompleted":
|
|
1272
|
+
return "Codex Windows sandbox:";
|
|
1273
|
+
default:
|
|
1274
|
+
return `Codex ${method}:`;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
function buildAppServerDiagnosticNote(message) {
|
|
1278
|
+
const params = asRecord(message.params) ?? {};
|
|
1279
|
+
const prefix = appServerDiagnosticNotePrefix(message.method);
|
|
1280
|
+
switch (message.method) {
|
|
1281
|
+
case "error": {
|
|
1282
|
+
const detail = diagnosticMessage(params, "message", "error") || "Unknown app-server error";
|
|
1283
|
+
return `${prefix} ${shorten(detail, 160)}`;
|
|
1284
|
+
}
|
|
1285
|
+
case "warning": {
|
|
1286
|
+
const detail = diagnosticMessage(params, "message") || "Warning";
|
|
1287
|
+
return `${prefix} ${shorten(detail, 160)}`;
|
|
1288
|
+
}
|
|
1289
|
+
case "guardianWarning": {
|
|
1290
|
+
const detail = diagnosticMessage(params, "message") || "Guardian warning";
|
|
1291
|
+
return `${prefix} ${shorten(detail, 160)}`;
|
|
1292
|
+
}
|
|
1293
|
+
case "configWarning": {
|
|
1294
|
+
const summary = diagnosticMessage(params, "summary") || "Configuration warning";
|
|
1295
|
+
const details = diagnosticMessage(params, "details");
|
|
1296
|
+
return `${prefix} ${shorten(details ? `${summary}: ${details}` : summary, 160)}`;
|
|
1297
|
+
}
|
|
1298
|
+
case "deprecationNotice": {
|
|
1299
|
+
const summary = diagnosticMessage(params, "summary") || "Deprecation notice";
|
|
1300
|
+
const details = diagnosticMessage(params, "details");
|
|
1301
|
+
return `${prefix} ${shorten(details ? `${summary}: ${details}` : summary, 160)}`;
|
|
1302
|
+
}
|
|
1303
|
+
case "mcpServer/startupStatus/updated": {
|
|
1304
|
+
const status = asString(params.status);
|
|
1305
|
+
if (status !== "failed" && status !== "cancelled") {
|
|
1306
|
+
return null;
|
|
1307
|
+
}
|
|
1308
|
+
const name = asString(params.name) ?? "MCP server";
|
|
1309
|
+
const error = asString(params.error);
|
|
1310
|
+
return `${prefix} ${shorten(error ? `${name} ${status}: ${error}` : `${name} ${status}`, 160)}`;
|
|
1311
|
+
}
|
|
1312
|
+
case "mcpServer/oauthLogin/completed": {
|
|
1313
|
+
if (params.success === true) {
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
const name = asString(params.name) ?? "MCP server";
|
|
1317
|
+
const error = asString(params.error);
|
|
1318
|
+
return `${prefix} ${shorten(error ? `${name}: ${error}` : `${name} failed`, 160)}`;
|
|
1319
|
+
}
|
|
1320
|
+
case "account/rateLimits/updated": {
|
|
1321
|
+
const detail = rateLimitDetail(params);
|
|
1322
|
+
return detail === "Rate limits updated" ? null : `${prefix} ${shorten(detail, 160)}`;
|
|
1323
|
+
}
|
|
1324
|
+
case "windows/worldWritableWarning": {
|
|
1325
|
+
const sampleCount = Array.isArray(params.samplePaths) ? params.samplePaths.length : 0;
|
|
1326
|
+
const extraCount = typeof params.extraCount === "number" && Number.isFinite(params.extraCount) ? params.extraCount : 0;
|
|
1327
|
+
if (sampleCount + extraCount <= 0 && params.failedScan !== true) {
|
|
1328
|
+
return null;
|
|
1329
|
+
}
|
|
1330
|
+
const scanDetail = params.failedScan === true ? " scan incomplete" : "";
|
|
1331
|
+
return `${prefix} ${sampleCount + extraCount} world-writable path${sampleCount + extraCount === 1 ? "" : "s"} found${scanDetail}`;
|
|
1332
|
+
}
|
|
1333
|
+
case "windowsSandbox/setupCompleted": {
|
|
1334
|
+
if (params.success === true) {
|
|
1335
|
+
return null;
|
|
1336
|
+
}
|
|
1337
|
+
return `${prefix} ${shorten(asString(params.error) ?? "setup failed", 160)}`;
|
|
1338
|
+
}
|
|
1339
|
+
default:
|
|
1340
|
+
return null;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
function buildNeedsUserStateFromServerRequest(message) {
|
|
1344
|
+
const params = asRecord(message.params) ?? {};
|
|
1345
|
+
const threadId = extractThreadId(params);
|
|
1346
|
+
if (!threadId) {
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
const requestId = String(message.id);
|
|
1350
|
+
if (message.method === "item/commandExecution/requestApproval") {
|
|
1351
|
+
return {
|
|
1352
|
+
kind: "approval",
|
|
1353
|
+
requestId,
|
|
1354
|
+
threadId,
|
|
1355
|
+
createdAt: new Date().toISOString(),
|
|
1356
|
+
requestMethod: message.method,
|
|
1357
|
+
responseKind: "approvalDecision",
|
|
1358
|
+
turnId: extractTurnId(params),
|
|
1359
|
+
itemId: extractItemId(params),
|
|
1360
|
+
reason: asString(params.reason),
|
|
1361
|
+
command: asString(params.command),
|
|
1362
|
+
cwd: asString(params.cwd),
|
|
1363
|
+
availableDecisions: asStringArray(params.availableDecisions),
|
|
1364
|
+
networkApprovalContext: asRecord(params.networkApprovalContext) ?? null
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
if (message.method === "item/fileChange/requestApproval") {
|
|
1368
|
+
return {
|
|
1369
|
+
kind: "approval",
|
|
1370
|
+
requestId,
|
|
1371
|
+
threadId,
|
|
1372
|
+
createdAt: new Date().toISOString(),
|
|
1373
|
+
requestMethod: message.method,
|
|
1374
|
+
responseKind: "approvalDecision",
|
|
1375
|
+
turnId: extractTurnId(params),
|
|
1376
|
+
itemId: extractItemId(params),
|
|
1377
|
+
reason: asString(params.reason),
|
|
1378
|
+
grantRoot: asString(params.grantRoot),
|
|
1379
|
+
availableDecisions: asStringArray(params.availableDecisions)
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
if (message.method === "item/tool/requestUserInput") {
|
|
1383
|
+
return {
|
|
1384
|
+
kind: "input",
|
|
1385
|
+
requestId,
|
|
1386
|
+
threadId,
|
|
1387
|
+
createdAt: new Date().toISOString(),
|
|
1388
|
+
requestMethod: message.method,
|
|
1389
|
+
responseKind: "toolInput",
|
|
1390
|
+
turnId: extractTurnId(params),
|
|
1391
|
+
itemId: extractItemId(params),
|
|
1392
|
+
reason: asString(params.reason) ?? asString(params.prompt),
|
|
1393
|
+
questions: asNeedsUserQuestions(params.questions),
|
|
1394
|
+
availableDecisions: asStringArray(params.availableDecisions)
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
if (message.method === "mcpServer/elicitation/request") {
|
|
1398
|
+
const schema = asRecord(params.requestedSchema);
|
|
1399
|
+
return {
|
|
1400
|
+
kind: "input",
|
|
1401
|
+
requestId,
|
|
1402
|
+
threadId,
|
|
1403
|
+
createdAt: new Date().toISOString(),
|
|
1404
|
+
requestMethod: message.method,
|
|
1405
|
+
responseKind: "mcpElicitation",
|
|
1406
|
+
turnId: extractTurnId(params),
|
|
1407
|
+
reason: asString(params.message),
|
|
1408
|
+
questions: parseMcpElicitationQuestions(schema),
|
|
1409
|
+
requestedSchema: schema
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
if (message.method === "item/permissions/requestApproval") {
|
|
1413
|
+
return {
|
|
1414
|
+
kind: "approval",
|
|
1415
|
+
requestId,
|
|
1416
|
+
threadId,
|
|
1417
|
+
createdAt: new Date().toISOString(),
|
|
1418
|
+
requestMethod: message.method,
|
|
1419
|
+
responseKind: "permissionsApproval",
|
|
1420
|
+
turnId: extractTurnId(params),
|
|
1421
|
+
itemId: extractItemId(params),
|
|
1422
|
+
reason: asString(params.reason),
|
|
1423
|
+
cwd: asString(params.cwd),
|
|
1424
|
+
availableDecisions: ["accept", "acceptForSession"],
|
|
1425
|
+
requestedPermissions: asRecord(params.permissions)
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
if (message.method === "applyPatchApproval") {
|
|
1429
|
+
return {
|
|
1430
|
+
kind: "approval",
|
|
1431
|
+
requestId,
|
|
1432
|
+
threadId,
|
|
1433
|
+
createdAt: new Date().toISOString(),
|
|
1434
|
+
requestMethod: message.method,
|
|
1435
|
+
responseKind: "legacyReview",
|
|
1436
|
+
reason: asString(params.reason),
|
|
1437
|
+
grantRoot: asString(params.grantRoot),
|
|
1438
|
+
availableDecisions: ["accept", "acceptForSession", "decline", "cancel"]
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
if (message.method === "execCommandApproval") {
|
|
1442
|
+
const command = Array.isArray(params.command)
|
|
1443
|
+
? params.command.filter((entry) => typeof entry === "string").join(" ")
|
|
1444
|
+
: undefined;
|
|
1445
|
+
return {
|
|
1446
|
+
kind: "approval",
|
|
1447
|
+
requestId,
|
|
1448
|
+
threadId,
|
|
1449
|
+
createdAt: new Date().toISOString(),
|
|
1450
|
+
requestMethod: message.method,
|
|
1451
|
+
responseKind: "legacyReview",
|
|
1452
|
+
reason: asString(params.reason),
|
|
1453
|
+
command,
|
|
1454
|
+
cwd: asString(params.cwd),
|
|
1455
|
+
availableDecisions: ["accept", "acceptForSession", "decline", "cancel"]
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
return null;
|
|
1459
|
+
}
|
|
1460
|
+
function shouldStopDormantThreadAfterAppServerNotification(input) {
|
|
1461
|
+
return shouldStopDormantThreadAfterNotification(input);
|
|
1462
|
+
}
|
|
1463
|
+
//# sourceMappingURL=events.js.map
|