@posthog/wizard 2.24.1 → 2.26.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/{add-mcp-server-to-clients-CfwEQT_z.js → add-mcp-server-to-clients-C58l_KpV.js} +4 -4
- package/dist/{add-mcp-server-to-clients-CfwEQT_z.js.map → add-mcp-server-to-clients-C58l_KpV.js.map} +1 -1
- package/dist/{agent-interface-D1vtN6Wn.js → agent-interface-Dq_4h2eN.js} +435 -45
- package/dist/agent-interface-Dq_4h2eN.js.map +1 -0
- package/dist/{agent-runner-CBbkS0Ro.js → agent-runner-BNGW3osc.js} +748 -132
- package/dist/agent-runner-BNGW3osc.js.map +1 -0
- package/dist/{analytics-CUr82BDl.js → analytics-BX3LKPch.js} +51 -17
- package/dist/analytics-BX3LKPch.js.map +1 -0
- package/dist/{api-CI3Z74NG.js → api-DCHci5SD.js} +9 -5
- package/dist/api-DCHci5SD.js.map +1 -0
- package/dist/bin.js +830 -120
- package/dist/bin.js.map +1 -1
- package/dist/{ci-install-D_kxNmbJ.js → ci-install-CHIbwXio.js} +5 -5
- package/dist/{ci-install-D_kxNmbJ.js.map → ci-install-CHIbwXio.js.map} +1 -1
- package/dist/{debug-DxA_f5QT.js → debug-BizeRFR0.js} +17 -8
- package/dist/debug-BizeRFR0.js.map +1 -0
- package/dist/{debug-zMvpNYb2.js → debug-fg4BAKKA.js} +1 -1
- package/dist/{environment-CyS37cmM.js → environment-DS5Pq9Wm.js} +3 -3
- package/dist/{environment-CyS37cmM.js.map → environment-DS5Pq9Wm.js.map} +1 -1
- package/dist/{interactive-CG6FFqSw.js → interactive-DE3WDjk7.js} +3 -3
- package/dist/{interactive-CG6FFqSw.js.map → interactive-DE3WDjk7.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DQz4FSb1.js → mcp-prompt-streaming-zsYd1zJx.js} +7 -26
- package/dist/mcp-prompt-streaming-zsYd1zJx.js.map +1 -0
- package/dist/{non-interactive-DWtHX3ZR.js → non-interactive-DNah9u3t.js} +2 -2
- package/dist/{non-interactive-DWtHX3ZR.js.map → non-interactive-DNah9u3t.js.map} +1 -1
- package/dist/{package-manager-BWUS4CP0.js → package-manager-Dma9-zGs.js} +2 -2
- package/dist/{package-manager-BWUS4CP0.js.map → package-manager-Dma9-zGs.js.map} +1 -1
- package/dist/{playground-D7AhMMF5.js → playground-Cwe0Q9HW.js} +146 -49
- package/dist/playground-Cwe0Q9HW.js.map +1 -0
- package/dist/{posthog-integration-DexZ2uHU.js → posthog-integration-CAYZdk0r.js} +11 -11
- package/dist/{posthog-integration-DexZ2uHU.js.map → posthog-integration-CAYZdk0r.js.map} +1 -1
- package/dist/{provisioning-9c-AQbsa.js → provisioning-BmL4ro-o.js} +10 -6
- package/dist/{provisioning-9c-AQbsa.js.map → provisioning-BmL4ro-o.js.map} +1 -1
- package/dist/{registry-CO7JVZyE.js → registry-C3wcDM3X.js} +4 -4
- package/dist/{registry-CO7JVZyE.js.map → registry-C3wcDM3X.js.map} +1 -1
- package/dist/{setup-utils-0U-_Md2G.js → setup-utils-CNWIMZ-d.js} +71 -16
- package/dist/setup-utils-CNWIMZ-d.js.map +1 -0
- package/dist/smoke-test.sh +36 -1
- package/dist/{start-tui-WNb3ET14.js → start-tui-CS802Ww9.js} +311 -54
- package/dist/start-tui-CS802Ww9.js.map +1 -0
- package/dist/{steps-BAUXDCC4.js → steps-BX44xr30.js} +6 -6
- package/dist/{steps-BAUXDCC4.js.map → steps-BX44xr30.js.map} +1 -1
- package/dist/{task-stream-CZawuzlz.js → task-stream-BQNSp0qR.js} +4 -3
- package/dist/task-stream-BQNSp0qR.js.map +1 -0
- package/dist/{telemetry-ycqCpNPr.js → telemetry-BH-MgWPT.js} +3 -3
- package/dist/{telemetry-ycqCpNPr.js.map → telemetry-BH-MgWPT.js.map} +1 -1
- package/dist/{AiOptInRequiredScreen-_33FOcVo.js → terminal-BSiupnOQ.js} +1058 -92
- package/dist/terminal-BSiupnOQ.js.map +1 -0
- package/dist/{urls-C8aJWvgh.js → urls-BuEABcmF.js} +2 -2
- package/dist/{urls-C8aJWvgh.js.map → urls-BuEABcmF.js.map} +1 -1
- package/dist/{wizard-abort-DWXyJdws.js → wizard-abort-CR3w2Efg.js} +1 -1
- package/dist/{wizard-abort-C6gRLxUE.js → wizard-abort-Dl2MJOP9.js} +3 -3
- package/dist/{wizard-abort-C6gRLxUE.js.map → wizard-abort-Dl2MJOP9.js.map} +1 -1
- package/dist/wizard-session-G3VWD6hv.js.map +1 -1
- package/dist/{wizard-ui-YdGFRyu_.js → wizard-ui-WZ48rUgr.js} +2 -1
- package/dist/wizard-ui-WZ48rUgr.js.map +1 -0
- package/package.json +1 -1
- package/dist/AiOptInRequiredScreen-_33FOcVo.js.map +0 -1
- package/dist/agent-interface-D1vtN6Wn.js.map +0 -1
- package/dist/agent-runner-CBbkS0Ro.js.map +0 -1
- package/dist/analytics-CUr82BDl.js.map +0 -1
- package/dist/api-CI3Z74NG.js.map +0 -1
- package/dist/debug-DxA_f5QT.js.map +0 -1
- package/dist/mcp-prompt-streaming-DQz4FSb1.js.map +0 -1
- package/dist/playground-D7AhMMF5.js.map +0 -1
- package/dist/setup-utils-0U-_Md2G.js.map +0 -1
- package/dist/start-tui-WNb3ET14.js.map +0 -1
- package/dist/task-stream-CZawuzlz.js.map +0 -1
- package/dist/wizard-ui-YdGFRyu_.js.map +0 -1
|
@@ -1,18 +1,47 @@
|
|
|
1
1
|
import { n as __require } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
-
import { F as POSTHOG_FLAG_HEADER_PREFIX,
|
|
3
|
-
import { t as analytics } from "./analytics-
|
|
4
|
-
import { i as getLlmGatewayUrlFromHost } from "./urls-
|
|
2
|
+
import { F as POSTHOG_FLAG_HEADER_PREFIX, J as WIZARD_REMARK_EVENT_NAME, K as WIZARD_ORCHESTRATOR_FLAG_KEY, Q as WIZARD_VARIANT_FLAG_KEY, X as WIZARD_USER_AGENT, Z as WIZARD_VARIANTS, a as getLogFilePath, f as skillTmpPath, o as initLogFile, p as getUI, r as debug, s as logToFile, u as WIZARD_YARA_REPORT_FILE, z as POSTHOG_PROPERTY_HEADER_PREFIX } from "./debug-BizeRFR0.js";
|
|
3
|
+
import { t as analytics } from "./analytics-BX3LKPch.js";
|
|
4
|
+
import { i as getLlmGatewayUrlFromHost } from "./urls-BuEABcmF.js";
|
|
5
5
|
import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-G3VWD6hv.js";
|
|
6
|
-
import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-
|
|
6
|
+
import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-Dl2MJOP9.js";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import * as fs$1 from "fs";
|
|
9
9
|
import fs from "fs";
|
|
10
|
+
import * as path$1 from "path";
|
|
10
11
|
import path from "path";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
import fg from "fast-glob";
|
|
13
14
|
import { execFileSync } from "child_process";
|
|
14
15
|
import { randomUUID } from "crypto";
|
|
15
16
|
import * as os from "os";
|
|
17
|
+
//#region src/utils/atomic-ledger.ts
|
|
18
|
+
/**
|
|
19
|
+
* Small shared primitives for on-disk ledgers: an atomic JSON writer and a
|
|
20
|
+
* single-chain async mutex. Used by the audit tools and by the orchestrator
|
|
21
|
+
* queue. Lifted here so both share one implementation.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Atomically write JSON: write to a `.tmp` file then rename over the target. The
|
|
25
|
+
* rename bumps the file's mtime in one step, which is what a file watcher polls.
|
|
26
|
+
*/
|
|
27
|
+
function writeJsonAtomic(targetPath, data) {
|
|
28
|
+
const tmpPath = `${targetPath}.tmp`;
|
|
29
|
+
fs$1.writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf8");
|
|
30
|
+
fs$1.renameSync(tmpPath, targetPath);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A single async mutex. Serializes read-modify-write cycles so concurrent callers
|
|
34
|
+
* (parallel task agents, audit tool calls) never interleave a mutation.
|
|
35
|
+
*/
|
|
36
|
+
function makeMutex() {
|
|
37
|
+
let chain = Promise.resolve();
|
|
38
|
+
return async function run(fn) {
|
|
39
|
+
const next = chain.then(() => fn());
|
|
40
|
+
chain = next.catch(() => void 0);
|
|
41
|
+
return next;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
16
45
|
//#region src/lib/programs/audit/types.ts
|
|
17
46
|
/** Single source of truth for status glyph + color across audit views. */
|
|
18
47
|
const AUDIT_SEVERITY_STYLE = {
|
|
@@ -103,6 +132,336 @@ function createSecretVault() {
|
|
|
103
132
|
};
|
|
104
133
|
}
|
|
105
134
|
//#endregion
|
|
135
|
+
//#region src/lib/agent/runner/orchestrator/queue.ts
|
|
136
|
+
/**
|
|
137
|
+
* The orchestrator task queue.
|
|
138
|
+
*
|
|
139
|
+
* In memory, synchronous, single-owner: one Node process drives the run, so
|
|
140
|
+
* there is no locking. The queue imposes no execution policy — `nextRunnable`
|
|
141
|
+
* returns every pending task whose dependencies are satisfied, and how many of
|
|
142
|
+
* those run at once is decided by the task graph, not the queue.
|
|
143
|
+
*
|
|
144
|
+
* Every transition rewrites `<installDir>/.posthog-wizard-cache/queue.json`, a
|
|
145
|
+
* small file holding the whole queue, handoffs included. It is the run's log
|
|
146
|
+
* and the report's source. The whole cache folder is run-scoped and wiped when
|
|
147
|
+
* the run ends.
|
|
148
|
+
*/
|
|
149
|
+
const TaskStatus = {
|
|
150
|
+
Pending: "pending",
|
|
151
|
+
Running: "running",
|
|
152
|
+
Done: "done",
|
|
153
|
+
Skipped: "skipped",
|
|
154
|
+
Failed: "failed"
|
|
155
|
+
};
|
|
156
|
+
const QUEUE_DIR_NAME = ".posthog-wizard-cache";
|
|
157
|
+
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
158
|
+
function nowIso() {
|
|
159
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
160
|
+
}
|
|
161
|
+
/** Dropped in the cache folder so an orphaned copy explains itself. */
|
|
162
|
+
const DELETE_ME_FILE = ".DELETE-ME.md";
|
|
163
|
+
const DELETE_ME_BODY = `# Safe to delete
|
|
164
|
+
|
|
165
|
+
This folder contains run artifacts from the PostHog Wizard. This should have
|
|
166
|
+
been deleted if the Wizard has finished running. If this wasn't deleted for
|
|
167
|
+
some reason, you can safely delete the entire \`${QUEUE_DIR_NAME}/\` folder.
|
|
168
|
+
`;
|
|
169
|
+
var QueueStore = class {
|
|
170
|
+
tasks = [];
|
|
171
|
+
onTransition;
|
|
172
|
+
runId;
|
|
173
|
+
queuePath;
|
|
174
|
+
constructor(installDir, runId, opts) {
|
|
175
|
+
this.onTransition = opts?.onTransition;
|
|
176
|
+
this.runId = runId;
|
|
177
|
+
const dir = path$1.join(installDir, QUEUE_DIR_NAME);
|
|
178
|
+
this.queuePath = path$1.join(dir, "queue.json");
|
|
179
|
+
fs$1.mkdirSync(dir, { recursive: true });
|
|
180
|
+
fs$1.writeFileSync(path$1.join(dir, DELETE_ME_FILE), DELETE_ME_BODY);
|
|
181
|
+
}
|
|
182
|
+
list() {
|
|
183
|
+
return this.tasks;
|
|
184
|
+
}
|
|
185
|
+
get(id) {
|
|
186
|
+
return this.tasks.find((t) => t.id === id);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Every pending task whose dependencies are all satisfied (`done` or
|
|
190
|
+
* `skipped`). A skipped dependency does not block downstream work.
|
|
191
|
+
*/
|
|
192
|
+
nextRunnable() {
|
|
193
|
+
const doneIds = new Set(this.tasks.filter((t) => t.status === TaskStatus.Done || t.status === TaskStatus.Skipped).map((t) => t.id));
|
|
194
|
+
return this.tasks.filter((t) => t.status === TaskStatus.Pending && t.dependsOn.every((d) => doneIds.has(d)));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* True when no task is running and none can be started. Either everything
|
|
198
|
+
* is terminal, or the only pending tasks are blocked by a failed dependency.
|
|
199
|
+
*/
|
|
200
|
+
isDrained() {
|
|
201
|
+
if (this.tasks.some((t) => t.status === TaskStatus.Running)) return false;
|
|
202
|
+
return this.nextRunnable().length === 0;
|
|
203
|
+
}
|
|
204
|
+
summary() {
|
|
205
|
+
const counts = {
|
|
206
|
+
[TaskStatus.Pending]: 0,
|
|
207
|
+
[TaskStatus.Running]: 0,
|
|
208
|
+
[TaskStatus.Done]: 0,
|
|
209
|
+
[TaskStatus.Skipped]: 0,
|
|
210
|
+
[TaskStatus.Failed]: 0
|
|
211
|
+
};
|
|
212
|
+
for (const t of this.tasks) counts[t.status] += 1;
|
|
213
|
+
return {
|
|
214
|
+
...counts,
|
|
215
|
+
total: this.tasks.length
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
readHandoff(id) {
|
|
219
|
+
return this.get(id)?.handoff ?? null;
|
|
220
|
+
}
|
|
221
|
+
/** Handoffs of completed tasks of a given type, oldest first. */
|
|
222
|
+
readHandoffsByType(type) {
|
|
223
|
+
return this.tasks.filter((t) => t.type === type && t.handoff).map((t) => t.handoff);
|
|
224
|
+
}
|
|
225
|
+
enqueue(input) {
|
|
226
|
+
const task = {
|
|
227
|
+
id: randomUUID(),
|
|
228
|
+
type: input.type,
|
|
229
|
+
label: input.label,
|
|
230
|
+
status: TaskStatus.Pending,
|
|
231
|
+
dependsOn: input.dependsOn ?? [],
|
|
232
|
+
inputs: input.inputs ?? {},
|
|
233
|
+
model: input.model,
|
|
234
|
+
attempts: 0,
|
|
235
|
+
maxAttempts: input.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
236
|
+
enqueuedBy: input.enqueuedBy ?? "orchestrator",
|
|
237
|
+
createdAt: nowIso()
|
|
238
|
+
};
|
|
239
|
+
this.tasks.push(task);
|
|
240
|
+
this.reflect();
|
|
241
|
+
this.notify("enqueue", task);
|
|
242
|
+
return task;
|
|
243
|
+
}
|
|
244
|
+
start(id) {
|
|
245
|
+
const t = this.require(id);
|
|
246
|
+
t.status = TaskStatus.Running;
|
|
247
|
+
t.startedAt = nowIso();
|
|
248
|
+
t.attempts += 1;
|
|
249
|
+
this.reflect();
|
|
250
|
+
this.notify("start", t);
|
|
251
|
+
return t;
|
|
252
|
+
}
|
|
253
|
+
complete(id, handoff) {
|
|
254
|
+
return this.finish(id, TaskStatus.Done, handoff);
|
|
255
|
+
}
|
|
256
|
+
/** Terminal: the agent could not do the task. Not done, not failed. */
|
|
257
|
+
skip(id, handoff) {
|
|
258
|
+
return this.finish(id, TaskStatus.Skipped, handoff);
|
|
259
|
+
}
|
|
260
|
+
fail(id, error, handoff) {
|
|
261
|
+
const t = this.require(id);
|
|
262
|
+
t.error = error;
|
|
263
|
+
return this.finish(id, TaskStatus.Failed, handoff);
|
|
264
|
+
}
|
|
265
|
+
/** Put a failed/running task back to pending for a retry within the run. */
|
|
266
|
+
requeue(id) {
|
|
267
|
+
const t = this.require(id);
|
|
268
|
+
t.status = TaskStatus.Pending;
|
|
269
|
+
t.startedAt = void 0;
|
|
270
|
+
t.finishedAt = void 0;
|
|
271
|
+
this.reflect();
|
|
272
|
+
this.notify("requeue", t);
|
|
273
|
+
return t;
|
|
274
|
+
}
|
|
275
|
+
finish(id, status, handoff) {
|
|
276
|
+
const t = this.require(id);
|
|
277
|
+
if (handoff) t.handoff = handoff;
|
|
278
|
+
t.status = status;
|
|
279
|
+
t.finishedAt = nowIso();
|
|
280
|
+
this.reflect();
|
|
281
|
+
this.notify(status === TaskStatus.Done ? "complete" : status === TaskStatus.Skipped ? "skip" : "fail", t);
|
|
282
|
+
return t;
|
|
283
|
+
}
|
|
284
|
+
reflect() {
|
|
285
|
+
const file = {
|
|
286
|
+
version: 1,
|
|
287
|
+
runId: this.runId,
|
|
288
|
+
tasks: this.tasks
|
|
289
|
+
};
|
|
290
|
+
writeJsonAtomic(this.queuePath, file);
|
|
291
|
+
}
|
|
292
|
+
notify(event, task) {
|
|
293
|
+
try {
|
|
294
|
+
this.onTransition?.(event, task);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
analytics.captureException(error instanceof Error ? error : new Error(String(error)), {
|
|
297
|
+
step: "orchestrator_queue_listener",
|
|
298
|
+
event
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
require(id) {
|
|
303
|
+
const t = this.get(id);
|
|
304
|
+
if (!t) throw new Error(`No task ${id} in the queue`);
|
|
305
|
+
return t;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/lib/agent/runner/orchestrator/queue-tools.ts
|
|
310
|
+
/**
|
|
311
|
+
* Orchestrator MCP tools, registered into the existing `wizard-tools` server when
|
|
312
|
+
* a queue is present. They let the orchestrator agent and task agents grow the
|
|
313
|
+
* queue, report completion with a structured handoff, and read prior handoffs.
|
|
314
|
+
*
|
|
315
|
+
* The guard logic and the apply functions are plain, exported, and unit-tested.
|
|
316
|
+
* `buildOrchestratorTools` wraps them in the SDK `tool()` shape.
|
|
317
|
+
*/
|
|
318
|
+
function stableStringify(value) {
|
|
319
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
320
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
321
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
322
|
+
}
|
|
323
|
+
function dedupKey(type, inputs) {
|
|
324
|
+
return `${type}::${stableStringify(inputs)}`;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* A backstop on total queue size. Tasks can enqueue tasks, so a misbehaving
|
|
328
|
+
* type could grow the queue without bound. Keeping the graph small is the job
|
|
329
|
+
* of good agent and skill design, not this number — it only stops a runaway.
|
|
330
|
+
* The real flow is ~9 tasks, so this sits well clear of it.
|
|
331
|
+
*/
|
|
332
|
+
const MAX_QUEUE_TASKS = 30;
|
|
333
|
+
/**
|
|
334
|
+
* Validate an enqueue. Structural checks only — a real type, real dependencies,
|
|
335
|
+
* not a literal duplicate, and not past the runaway backstop. How much runs,
|
|
336
|
+
* and in what shape, is the task graph's business, not a knob's.
|
|
337
|
+
*/
|
|
338
|
+
function checkEnqueueGuards(ctx, args) {
|
|
339
|
+
const tasks = ctx.store.list();
|
|
340
|
+
if (tasks.length >= MAX_QUEUE_TASKS) return {
|
|
341
|
+
ok: false,
|
|
342
|
+
guard: "queue-full",
|
|
343
|
+
message: `The queue already holds ${tasks.length} tasks (cap ${MAX_QUEUE_TASKS}). Refine the existing tasks rather than adding more.`
|
|
344
|
+
};
|
|
345
|
+
if (!ctx.validTypes.includes(args.type)) return {
|
|
346
|
+
ok: false,
|
|
347
|
+
guard: "unknown-type",
|
|
348
|
+
message: `Unknown task type "${args.type}". Valid types: ${ctx.validTypes.join(", ")}.`
|
|
349
|
+
};
|
|
350
|
+
for (const dep of args.dependsOn ?? []) if (!ctx.store.get(dep)) return {
|
|
351
|
+
ok: false,
|
|
352
|
+
guard: "unknown-dep",
|
|
353
|
+
message: `Dependency "${dep}" is not a known task id.`
|
|
354
|
+
};
|
|
355
|
+
const key = dedupKey(args.type, args.inputs ?? {});
|
|
356
|
+
if (tasks.some((t) => t.status !== TaskStatus.Failed && dedupKey(t.type, t.inputs) === key)) return {
|
|
357
|
+
ok: false,
|
|
358
|
+
guard: "dedup",
|
|
359
|
+
message: `A "${args.type}" task with these inputs already exists.`
|
|
360
|
+
};
|
|
361
|
+
return { ok: true };
|
|
362
|
+
}
|
|
363
|
+
function applyEnqueue(ctx, args) {
|
|
364
|
+
const guard = checkEnqueueGuards(ctx, args);
|
|
365
|
+
if (!guard.ok) return guard;
|
|
366
|
+
return {
|
|
367
|
+
ok: true,
|
|
368
|
+
task: ctx.store.enqueue({
|
|
369
|
+
type: args.type,
|
|
370
|
+
label: args.label,
|
|
371
|
+
inputs: args.inputs ?? {},
|
|
372
|
+
dependsOn: args.dependsOn ?? [],
|
|
373
|
+
model: args.model,
|
|
374
|
+
enqueuedBy: ctx.currentTaskId ?? "orchestrator"
|
|
375
|
+
})
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function applyComplete(ctx, args) {
|
|
379
|
+
const id = ctx.currentTaskId;
|
|
380
|
+
if (!id) return {
|
|
381
|
+
ok: false,
|
|
382
|
+
message: "complete_task can only be called by a running task agent."
|
|
383
|
+
};
|
|
384
|
+
if (args.status === TaskStatus.Failed) ctx.store.fail(id, {
|
|
385
|
+
type: "self-reported",
|
|
386
|
+
message: args.handoff.forNextAgent
|
|
387
|
+
}, args.handoff);
|
|
388
|
+
else if (args.status === TaskStatus.Skipped) ctx.store.skip(id, args.handoff);
|
|
389
|
+
else ctx.store.complete(id, args.handoff);
|
|
390
|
+
return { ok: true };
|
|
391
|
+
}
|
|
392
|
+
function applyReadHandoffs(ctx, args) {
|
|
393
|
+
if (args.taskId) {
|
|
394
|
+
const h = ctx.store.readHandoff(args.taskId);
|
|
395
|
+
return h ? [h] : [];
|
|
396
|
+
}
|
|
397
|
+
if (args.type) return ctx.store.readHandoffsByType(args.type);
|
|
398
|
+
const currentId = ctx.currentTaskId;
|
|
399
|
+
const current = currentId ? ctx.store.get(currentId) : void 0;
|
|
400
|
+
if (!current) return [];
|
|
401
|
+
return current.dependsOn.map((depId) => ctx.store.readHandoff(depId)).filter((h) => h !== null);
|
|
402
|
+
}
|
|
403
|
+
const HANDOFF_SHAPE = {
|
|
404
|
+
goals: z.string().describe("What this task was asked to achieve."),
|
|
405
|
+
did: z.string().describe("What you actually did."),
|
|
406
|
+
forNextAgent: z.string().describe("What the next agent should know."),
|
|
407
|
+
filesTouched: z.array(z.string()).optional(),
|
|
408
|
+
conflict: z.string().optional().describe("A one-line summary of any conflict you could not cleanly resolve (e.g. a dependency or build conflict). Put full detail in your work; this line is surfaced to the user.")
|
|
409
|
+
};
|
|
410
|
+
function textResult(text, isError = false) {
|
|
411
|
+
return {
|
|
412
|
+
isError,
|
|
413
|
+
content: [{
|
|
414
|
+
type: "text",
|
|
415
|
+
text
|
|
416
|
+
}]
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Build the orchestrator tools in the SDK `tool()` shape. Called from
|
|
421
|
+
* createWizardToolsServer only when a queue context is present.
|
|
422
|
+
*/
|
|
423
|
+
function buildOrchestratorTools(tool, ctx) {
|
|
424
|
+
return [
|
|
425
|
+
tool("enqueue_task", "Add a task to the orchestrator queue. Use it to seed work and to enqueue follow-up work you discover. Keep tasks small and discrete.", {
|
|
426
|
+
type: z.string().describe(`The task type. One of: ${ctx.validTypes.join(", ")}.`),
|
|
427
|
+
label: z.string().optional().describe("A short label for the UI — the action in a few words (e.g. \"Add the PostHog SDK\", \"Initialize PostHog\"). Leave out file names, class names, and other specifics."),
|
|
428
|
+
inputs: z.record(z.unknown()).optional(),
|
|
429
|
+
dependsOn: z.array(z.string()).optional().describe("Task ids that must be done before this task runs."),
|
|
430
|
+
model: z.string().optional(),
|
|
431
|
+
reason: z.string().describe("One line on why this task is needed.")
|
|
432
|
+
}, ((args) => {
|
|
433
|
+
const res = applyEnqueue(ctx, args);
|
|
434
|
+
if (!res.ok) {
|
|
435
|
+
analytics.wizardCapture("orchestrator guard tripped", {
|
|
436
|
+
guard: res.guard,
|
|
437
|
+
type: args.type
|
|
438
|
+
});
|
|
439
|
+
return textResult(res.message, true);
|
|
440
|
+
}
|
|
441
|
+
return textResult(JSON.stringify({ id: res.task.id }));
|
|
442
|
+
})),
|
|
443
|
+
tool("complete_task", "Report the outcome of your task. Always call this exactly once when you finish, with a structured handoff for the next agent. Use status 'skipped' when the task does not apply to this project and you cannot do it (say why in the handoff) — not 'done'.", {
|
|
444
|
+
status: z.enum([
|
|
445
|
+
"done",
|
|
446
|
+
"failed",
|
|
447
|
+
"skipped"
|
|
448
|
+
]),
|
|
449
|
+
handoff: z.object(HANDOFF_SHAPE)
|
|
450
|
+
}, ((args) => {
|
|
451
|
+
const res = applyComplete(ctx, args);
|
|
452
|
+
if (!res.ok) return textResult(res.message, true);
|
|
453
|
+
return textResult("ok");
|
|
454
|
+
})),
|
|
455
|
+
tool("read_handoffs", "Read structured handoffs from earlier tasks. With no argument, returns the handoffs of your dependencies.", {
|
|
456
|
+
type: z.string().optional(),
|
|
457
|
+
taskId: z.string().optional()
|
|
458
|
+
}, ((args) => {
|
|
459
|
+
const handoffs = applyReadHandoffs(ctx, args);
|
|
460
|
+
return textResult(JSON.stringify(handoffs, null, 2));
|
|
461
|
+
}))
|
|
462
|
+
];
|
|
463
|
+
}
|
|
464
|
+
//#endregion
|
|
106
465
|
//#region src/lib/wizard-tools.ts
|
|
107
466
|
/**
|
|
108
467
|
* Unified in-process MCP server for the PostHog wizard.
|
|
@@ -204,17 +563,24 @@ async function installSkillById(skillId, installDir, skillsBaseUrl, skillsRoot)
|
|
|
204
563
|
* upcoming call should proceed and, if not, the error message to surface
|
|
205
564
|
* to the agent. Extracted so the policy can be unit-tested without
|
|
206
565
|
* spinning up an MCP server.
|
|
566
|
+
*
|
|
567
|
+
* The adjacency nudge fires exactly once per run (the caller records it
|
|
568
|
+
* via `adjacencyNudged`) — flows that legitimately need several
|
|
569
|
+
* sequential, answer-dependent asks then proceed up to `maxQuestions`.
|
|
570
|
+
* Without the flag the rejected call would never advance the counter and
|
|
571
|
+
* every later call would be rejected, making caps above the threshold
|
|
572
|
+
* unreachable.
|
|
207
573
|
*/
|
|
208
|
-
function evaluateAskCap(callCount, maxQuestions) {
|
|
574
|
+
function evaluateAskCap(callCount, maxQuestions, adjacencyNudged = false) {
|
|
209
575
|
if (callCount >= maxQuestions) return {
|
|
210
576
|
kind: "capped",
|
|
211
577
|
reason: "max_questions",
|
|
212
578
|
message: `Error: wizard_ask cap reached (${maxQuestions} calls in this run). Proceed with sensible defaults using the answers you already have, or emit [ABORT] requirements-incomplete.`
|
|
213
579
|
};
|
|
214
|
-
if (callCount >= 3) return {
|
|
580
|
+
if (!adjacencyNudged && callCount >= 3) return {
|
|
215
581
|
kind: "capped",
|
|
216
582
|
reason: "adjacency",
|
|
217
|
-
message: `Error: too many wizard_ask calls in a row (${callCount} so far). Batch the remaining questions into a single call — the schema accepts up to 8 questions per invocation.`
|
|
583
|
+
message: `Error: too many wizard_ask calls in a row (${callCount} so far). Batch the remaining questions into a single call — the schema accepts up to 8 questions per invocation. If the remaining questions truly depend on earlier answers, ask again and they will go through.`
|
|
218
584
|
};
|
|
219
585
|
return { kind: "ok" };
|
|
220
586
|
}
|
|
@@ -292,14 +658,9 @@ const auditUpdateSchema = z.object({
|
|
|
292
658
|
file: z.string().optional(),
|
|
293
659
|
details: z.string().optional()
|
|
294
660
|
});
|
|
295
|
-
/**
|
|
296
|
-
* Atomically write JSON: write to .tmp then rename. The rename is what bumps
|
|
297
|
-
* the file's mtime, which is what the UI's file watcher polls on.
|
|
298
|
-
*/
|
|
661
|
+
/** Atomically write the audit ledger. Thin typed wrapper over writeJsonAtomic. */
|
|
299
662
|
function writeLedgerAtomic(targetPath, checks) {
|
|
300
|
-
|
|
301
|
-
fs.writeFileSync(tmpPath, JSON.stringify(checks, null, 2), "utf8");
|
|
302
|
-
fs.renameSync(tmpPath, targetPath);
|
|
663
|
+
writeJsonAtomic(targetPath, checks);
|
|
303
664
|
}
|
|
304
665
|
/**
|
|
305
666
|
* Apply a batch of patches to the ledger by id. Returns the new array and the
|
|
@@ -375,27 +736,16 @@ function appendAuditChecksToLedger(targetPath, additions) {
|
|
|
375
736
|
added: additions.length
|
|
376
737
|
};
|
|
377
738
|
}
|
|
378
|
-
/**
|
|
379
|
-
* Single async mutex shared by audit tools — guarantees a read-modify-write
|
|
380
|
-
* cycle on the ledger is atomic across concurrent tool calls (e.g. future subagents).
|
|
381
|
-
*/
|
|
382
|
-
function makeMutex() {
|
|
383
|
-
let chain = Promise.resolve();
|
|
384
|
-
return async function run(fn) {
|
|
385
|
-
const next = chain.then(() => fn());
|
|
386
|
-
chain = next.catch(() => void 0);
|
|
387
|
-
return next;
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
739
|
const SERVER_NAME = "wizard-tools";
|
|
391
740
|
/**
|
|
392
741
|
* Create the unified in-process MCP server with all wizard tools.
|
|
393
742
|
* Must be called asynchronously because the SDK is an ESM module loaded via dynamic import.
|
|
394
743
|
*/
|
|
395
744
|
async function createWizardToolsServer(options) {
|
|
396
|
-
const { workingDirectory, detectPackageManager, skillsBaseUrl, askBridge, askMaxQuestions = 10, secretVault = createSecretVault() } = options;
|
|
745
|
+
const { workingDirectory, detectPackageManager, skillsBaseUrl, askBridge, askMaxQuestions = 10, secretVault = createSecretVault(), orchestrator } = options;
|
|
397
746
|
const { tool, createSdkMcpServer } = await getSDKModule$1();
|
|
398
747
|
let askCallCount = 0;
|
|
748
|
+
let askAdjacencyNudged = false;
|
|
399
749
|
let cachedSkillMenu = {};
|
|
400
750
|
let categoryNames = ["integration"];
|
|
401
751
|
const menu = await fetchSkillMenu(skillsBaseUrl);
|
|
@@ -575,7 +925,8 @@ async function createWizardToolsServer(options) {
|
|
|
575
925
|
]).describe("'single' = pick one option, 'multi' = pick any, 'text' = free-form single-line answer"),
|
|
576
926
|
options: z.array(z.object({
|
|
577
927
|
label: z.string(),
|
|
578
|
-
value: z.string()
|
|
928
|
+
value: z.string(),
|
|
929
|
+
description: z.string().optional().describe("Optional secondary line shown dimmed and wrapped beneath the label (multi-select only). Use when a choice needs more than a title — e.g. what a custom scout watches and what makes it speak up.")
|
|
579
930
|
})).optional().describe("Required for kind=single|multi; ignored for kind=text"),
|
|
580
931
|
required: z.boolean().optional().describe("Defaults to true"),
|
|
581
932
|
sensitive: z.boolean().optional().describe("Only valid for kind='text'. When true, the user's answer is stored in the wizard's secret vault and returned to you as { secretRef: 'secret:...' } instead of the raw string. Use for API keys, tokens, and any other secret the user types in.")
|
|
@@ -600,8 +951,9 @@ async function createWizardToolsServer(options) {
|
|
|
600
951
|
}],
|
|
601
952
|
isError: true
|
|
602
953
|
};
|
|
603
|
-
const capDecision = evaluateAskCap(askCallCount, askMaxQuestions);
|
|
954
|
+
const capDecision = evaluateAskCap(askCallCount, askMaxQuestions, askAdjacencyNudged);
|
|
604
955
|
if (capDecision.kind === "capped") {
|
|
956
|
+
if (capDecision.reason === "adjacency") askAdjacencyNudged = true;
|
|
605
957
|
analytics.wizardCapture("wizard_ask capped", {
|
|
606
958
|
reason: capDecision.reason,
|
|
607
959
|
call_count: askCallCount,
|
|
@@ -673,7 +1025,8 @@ async function createWizardToolsServer(options) {
|
|
|
673
1025
|
isError: true
|
|
674
1026
|
};
|
|
675
1027
|
}
|
|
676
|
-
})
|
|
1028
|
+
}),
|
|
1029
|
+
...orchestrator ? buildOrchestratorTools(tool, orchestrator) : []
|
|
677
1030
|
]
|
|
678
1031
|
});
|
|
679
1032
|
}
|
|
@@ -687,7 +1040,10 @@ const WIZARD_TOOL_NAMES = {
|
|
|
687
1040
|
auditSeedChecks: `mcp__${SERVER_NAME}__audit_seed_checks`,
|
|
688
1041
|
auditAddChecks: `mcp__${SERVER_NAME}__audit_add_checks`,
|
|
689
1042
|
auditResolveChecks: `mcp__${SERVER_NAME}__audit_resolve_checks`,
|
|
690
|
-
wizardAsk: `mcp__${SERVER_NAME}__wizard_ask
|
|
1043
|
+
wizardAsk: `mcp__${SERVER_NAME}__wizard_ask`,
|
|
1044
|
+
enqueueTask: `mcp__${SERVER_NAME}__enqueue_task`,
|
|
1045
|
+
completeTask: `mcp__${SERVER_NAME}__complete_task`,
|
|
1046
|
+
readHandoffs: `mcp__${SERVER_NAME}__read_handoffs`
|
|
691
1047
|
};
|
|
692
1048
|
//#endregion
|
|
693
1049
|
//#region src/utils/custom-headers.ts
|
|
@@ -1454,6 +1810,19 @@ function getWizardCommandments() {
|
|
|
1454
1810
|
return WIZARD_COMMANDMENTS;
|
|
1455
1811
|
}
|
|
1456
1812
|
//#endregion
|
|
1813
|
+
//#region src/lib/agent/agent-phase.ts
|
|
1814
|
+
/** Maps a Claude SDK tool name to the phase that tool implies. Returns null
|
|
1815
|
+
* when the tool doesn't drive the visualizer (Task*, TodoWrite, etc.). */
|
|
1816
|
+
function classifyToolToStage(toolName) {
|
|
1817
|
+
if (toolName.includes("install_skill") || toolName.includes("load_skill_menu")) return "skill-install";
|
|
1818
|
+
if (toolName.includes("set_env_values") || toolName.includes("check_env_keys")) return "env-setup";
|
|
1819
|
+
if (toolName.includes("mcp__posthog")) return "dashboards";
|
|
1820
|
+
if (toolName === "Bash") return "dep-install";
|
|
1821
|
+
if (toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") return "code-edits";
|
|
1822
|
+
if (toolName === "Read" || toolName === "Glob" || toolName === "Grep") return "codebase-scan";
|
|
1823
|
+
return null;
|
|
1824
|
+
}
|
|
1825
|
+
//#endregion
|
|
1457
1826
|
//#region src/lib/agent/signals.ts
|
|
1458
1827
|
/**
|
|
1459
1828
|
* Agent signal vocabulary — the marker strings the agent emits and the error
|
|
@@ -1761,7 +2130,7 @@ function buildAuthErrorContext(workingDirectory, gatewayUrl, homeDir = os.homedi
|
|
|
1761
2130
|
* Phase 2 — collect remark (once): block with remark prompt
|
|
1762
2131
|
* Phase 3 — allow stop: return {}
|
|
1763
2132
|
*/
|
|
1764
|
-
function createStopHook(featureQueue, signals) {
|
|
2133
|
+
function createStopHook(featureQueue, signals, requestRemark = true) {
|
|
1765
2134
|
let featureIndex = 0;
|
|
1766
2135
|
let remarkRequested = false;
|
|
1767
2136
|
return (input) => {
|
|
@@ -1784,7 +2153,7 @@ function createStopHook(featureQueue, signals) {
|
|
|
1784
2153
|
reason: prompt
|
|
1785
2154
|
};
|
|
1786
2155
|
}
|
|
1787
|
-
if (!remarkRequested) {
|
|
2156
|
+
if (requestRemark && !remarkRequested) {
|
|
1788
2157
|
remarkRequested = true;
|
|
1789
2158
|
logToFile("Stop hook: requesting reflection");
|
|
1790
2159
|
return {
|
|
@@ -1805,6 +2174,14 @@ function buildWizardMetadata(flags = {}) {
|
|
|
1805
2174
|
return { ...(variantKey && WIZARD_VARIANTS[variantKey]) ?? WIZARD_VARIANTS["base"] };
|
|
1806
2175
|
}
|
|
1807
2176
|
/**
|
|
2177
|
+
* Whether this run uses the experimental task-queue orchestrator. Gated by the
|
|
2178
|
+
* boolean `wizard-orchestrator` feature flag, targeted to the user in the wizard's
|
|
2179
|
+
* analytics project.
|
|
2180
|
+
*/
|
|
2181
|
+
function isOrchestratorEnabled(flags = {}) {
|
|
2182
|
+
return flags[WIZARD_ORCHESTRATOR_FLAG_KEY] === "true";
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
1808
2185
|
* Build env for the SDK subprocess: process.env plus ANTHROPIC_CUSTOM_HEADERS, which always
|
|
1809
2186
|
* includes `x-posthog-use-bedrock-fallback: true` so the LLM gateway falls back to Bedrock on
|
|
1810
2187
|
* Anthropic 5xx, plus any wizard metadata/flags.
|
|
@@ -2008,7 +2385,6 @@ async function initializeAgent(config, options) {
|
|
|
2008
2385
|
initLogFile();
|
|
2009
2386
|
logToFile("Agent initialization starting");
|
|
2010
2387
|
logToFile("Install directory:", options.installDir);
|
|
2011
|
-
getUI().log.step("Initializing Claude agent...");
|
|
2012
2388
|
try {
|
|
2013
2389
|
const gatewayUrl = getLlmGatewayUrlFromHost(config.posthogApiHost);
|
|
2014
2390
|
process.env.ANTHROPIC_BASE_URL = gatewayUrl;
|
|
@@ -2038,7 +2414,8 @@ async function initializeAgent(config, options) {
|
|
|
2038
2414
|
detectPackageManager: config.detectPackageManager,
|
|
2039
2415
|
skillsBaseUrl: config.skillsBaseUrl,
|
|
2040
2416
|
askBridge: config.askBridge,
|
|
2041
|
-
askMaxQuestions: config.askMaxQuestions
|
|
2417
|
+
askMaxQuestions: config.askMaxQuestions,
|
|
2418
|
+
orchestrator: config.orchestrator
|
|
2042
2419
|
});
|
|
2043
2420
|
const agentRunConfig = {
|
|
2044
2421
|
workingDirectory: config.workingDirectory,
|
|
@@ -2062,8 +2439,6 @@ async function initializeAgent(config, options) {
|
|
|
2062
2439
|
gatewayUrl,
|
|
2063
2440
|
apiKeyPresent: !!config.posthogApiKey
|
|
2064
2441
|
});
|
|
2065
|
-
getUI().log.step(`Verbose logs: ${getLogFilePath()}`);
|
|
2066
|
-
getUI().log.success("Agent initialized. Let's get cooking!");
|
|
2067
2442
|
return agentRunConfig;
|
|
2068
2443
|
} catch (error) {
|
|
2069
2444
|
getUI().log.error(`Failed to initialize agent: ${error.message}`);
|
|
@@ -2130,9 +2505,18 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
|
|
|
2130
2505
|
} else logToFile(`Agent run completed in ${durationSeconds}s`);
|
|
2131
2506
|
const remark = signals.remark();
|
|
2132
2507
|
if (remark) analytics.capture(WIZARD_REMARK_EVENT_NAME, { remark });
|
|
2508
|
+
const usage = lastResultMessage?.usage;
|
|
2133
2509
|
analytics.wizardCapture("agent completed", {
|
|
2134
2510
|
duration_ms: durationMs,
|
|
2135
|
-
duration_seconds: durationSeconds
|
|
2511
|
+
duration_seconds: durationSeconds,
|
|
2512
|
+
model: agentConfig.model,
|
|
2513
|
+
num_turns: lastResultMessage?.num_turns,
|
|
2514
|
+
total_cost_usd: lastResultMessage?.total_cost_usd,
|
|
2515
|
+
input_tokens: usage?.input_tokens,
|
|
2516
|
+
output_tokens: usage?.output_tokens,
|
|
2517
|
+
cache_creation_input_tokens: usage?.cache_creation_input_tokens,
|
|
2518
|
+
cache_read_input_tokens: usage?.cache_read_input_tokens,
|
|
2519
|
+
...config?.analyticsProperties
|
|
2136
2520
|
});
|
|
2137
2521
|
try {
|
|
2138
2522
|
middleware?.finalize(lastResultMessage, durationMs);
|
|
@@ -2239,7 +2623,7 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
|
|
|
2239
2623
|
PreToolUse: createPreToolUseYaraHooks(),
|
|
2240
2624
|
PostToolUse: createPostToolUseYaraHooks(),
|
|
2241
2625
|
Stop: [{
|
|
2242
|
-
hooks: [createStopHook(config?.additionalFeatureQueue ?? [], signals)],
|
|
2626
|
+
hooks: [createStopHook(config?.additionalFeatureQueue ?? [], signals, config?.requestRemark ?? true)],
|
|
2243
2627
|
timeout: 30
|
|
2244
2628
|
}]
|
|
2245
2629
|
}
|
|
@@ -2263,7 +2647,7 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
|
|
|
2263
2647
|
}
|
|
2264
2648
|
loggedInitialContext = true;
|
|
2265
2649
|
}
|
|
2266
|
-
handleSDKMessage(message, options, spinner, signals, receivedSuccessResult, tasks);
|
|
2650
|
+
handleSDKMessage(message, options, spinner, signals, receivedSuccessResult, tasks, isOrchestratorEnabled(agentConfig.wizardFlags ?? {}));
|
|
2267
2651
|
if (abortCases.length > 0 && !abortReason && message.type === "assistant") {
|
|
2268
2652
|
const content = message.message?.content;
|
|
2269
2653
|
if (Array.isArray(content)) {
|
|
@@ -2390,7 +2774,9 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
|
|
|
2390
2774
|
const durationMs = Date.now() - startTime;
|
|
2391
2775
|
analytics.wizardCapture("agent aborted", {
|
|
2392
2776
|
duration_ms: durationMs,
|
|
2393
|
-
duration_seconds: Math.round(durationMs / 1e3)
|
|
2777
|
+
duration_seconds: Math.round(durationMs / 1e3),
|
|
2778
|
+
model: agentConfig.model,
|
|
2779
|
+
...config?.analyticsProperties
|
|
2394
2780
|
});
|
|
2395
2781
|
}
|
|
2396
2782
|
}
|
|
@@ -2500,14 +2886,14 @@ function extractTaskIdFromResult(content) {
|
|
|
2500
2886
|
}
|
|
2501
2887
|
}
|
|
2502
2888
|
}
|
|
2503
|
-
function handleSDKMessage(message, options, spinner, signals, receivedSuccessResult = false, tasks) {
|
|
2889
|
+
function handleSDKMessage(message, options, spinner, signals, receivedSuccessResult = false, tasks, suppressTaskRender = false) {
|
|
2504
2890
|
const STATUS_RANK = {
|
|
2505
2891
|
completed: 0,
|
|
2506
2892
|
in_progress: 1
|
|
2507
2893
|
};
|
|
2508
2894
|
const rank = (status) => STATUS_RANK[status] ?? 2;
|
|
2509
2895
|
const syncTasks = () => {
|
|
2510
|
-
if (!tasks) return;
|
|
2896
|
+
if (!tasks || suppressTaskRender) return;
|
|
2511
2897
|
const sorted = Array.from(tasks.values()).sort((a, b) => rank(a.status) - rank(b.status));
|
|
2512
2898
|
getUI().syncTodos(sorted);
|
|
2513
2899
|
};
|
|
@@ -2537,6 +2923,10 @@ function handleSDKMessage(message, options, spinner, signals, receivedSuccessRes
|
|
|
2537
2923
|
tasks,
|
|
2538
2924
|
sync: syncTasks
|
|
2539
2925
|
});
|
|
2926
|
+
if (block.type === "tool_use") {
|
|
2927
|
+
const stage = classifyToolToStage(block.name);
|
|
2928
|
+
if (stage) getUI().setStage(stage);
|
|
2929
|
+
}
|
|
2540
2930
|
}
|
|
2541
2931
|
break;
|
|
2542
2932
|
}
|
|
@@ -2586,6 +2976,6 @@ function handleSDKMessage(message, options, spinner, signals, receivedSuccessRes
|
|
|
2586
2976
|
}
|
|
2587
2977
|
}
|
|
2588
2978
|
//#endregion
|
|
2589
|
-
export {
|
|
2979
|
+
export { AUDIT_SEVERITY_STYLE as C, AUDIT_REPORT_FILE as S, getAuditChecks as T, QUEUE_DIR_NAME as _, runAgent as a, AUDIT_CHECKS_FILE as b, recoverOrphanedSettingsBackups as c, formatScanReport as d, writeScanReport as f, installSkillById as g, fetchSkillMenu as h, isOrchestratorEnabled as i, restoreClaudeSettings as l, downloadSkill as m, buildWizardMetadata as n, backupAndFixClaudeSettings as o, WIZARD_TOOL_NAMES as p, initializeAgent as r, checkAllSettingsConflicts as s, buildAgentEnv as t, AgentSignals as u, QueueStore as v, coerceAuditChecks as w, AUDIT_CHECKS_KEY as x, TaskStatus as y };
|
|
2590
2980
|
|
|
2591
|
-
//# sourceMappingURL=agent-interface-
|
|
2981
|
+
//# sourceMappingURL=agent-interface-Dq_4h2eN.js.map
|