@dv.nghiem/flowdeck 0.4.5 → 0.4.7
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/agents/index.d.ts.map +1 -1
- package/dist/hooks/event-log-hook.d.ts +18 -0
- package/dist/hooks/event-log-hook.d.ts.map +1 -1
- package/dist/hooks/notifications.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +270 -172
- package/dist/lib/research-gate.d.ts +6 -2
- package/dist/lib/research-gate.d.ts.map +1 -1
- package/dist/services/event-logger.d.ts +1 -1
- package/dist/services/event-logger.d.ts.map +1 -1
- package/dist/tools/delegate.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,8CAA8C;AAC9C,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EA2B/B,CAAC;AAGX,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC;AAmBvD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,EACrB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,eAAe,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,22 @@
|
|
|
1
|
+
type AppLog = (msg: string) => void;
|
|
1
2
|
export declare function setStaleThresholdMs(ms: number): void;
|
|
2
3
|
export declare function cleanupStaleToolStartTimes(): void;
|
|
4
|
+
/**
|
|
5
|
+
* Create event log hooks wired to the OpenCode TUI via client.app.log.
|
|
6
|
+
* All tool and session events are persisted to .opencode/flowdeck-events.jsonl
|
|
7
|
+
* AND displayed in the TUI's bounded log panel through the provided appLog fn.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createEventLogHooks(appLog: AppLog): {
|
|
10
|
+
before(ctx: {
|
|
11
|
+
directory: string;
|
|
12
|
+
}, toolInput: any, toolOutput: any): Promise<void>;
|
|
13
|
+
after(ctx: {
|
|
14
|
+
directory: string;
|
|
15
|
+
}, toolInput: any, toolOutput: any): Promise<void>;
|
|
16
|
+
session(ctx: {
|
|
17
|
+
directory: string;
|
|
18
|
+
}, event: any): Promise<void>;
|
|
19
|
+
};
|
|
3
20
|
export declare function eventLogBeforeHook(ctx: {
|
|
4
21
|
directory: string;
|
|
5
22
|
}, toolInput: any, toolOutput: any): Promise<void>;
|
|
@@ -9,4 +26,5 @@ export declare function eventLogAfterHook(ctx: {
|
|
|
9
26
|
export declare function eventLogSessionHook(ctx: {
|
|
10
27
|
directory: string;
|
|
11
28
|
}, event: any): Promise<void>;
|
|
29
|
+
export {};
|
|
12
30
|
//# sourceMappingURL=event-log-hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-log-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/event-log-hook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-log-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/event-log-hook.ts"],"names":[],"mappings":"AAEA,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;AASnC,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAOjD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM;gBAE5B;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,aAAa,GAAG,cAAc,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;eA2BvE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,aAAa,GAAG,cAAc,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;iBAsCpE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,SAAS,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;EA+CvE;AAGD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAC1B,SAAS,EAAE,GAAG,EACd,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAC1B,SAAS,EAAE,GAAG,EACd,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAC1B,KAAK,EAAE,GAAG,GACT,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/hooks/notifications.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAA;AAE7C;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,gBAAgB,GAChB,uBAAuB,GACvB,OAAO,CAAA;AAEX;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,WAAoB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/hooks/notifications.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAA;AAE7C;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,gBAAgB,GAChB,uBAAuB,GACvB,OAAO,CAAA;AAEX;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,WAAoB,GAAG,IAAI,CAmCrF;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;AAEjF;;;;;;;;;;;;;;GAcG;AACH,qBAAa,sBAAsB;IACjC,2EAA2E;IAC3E,OAAO,CAAC,cAAc,CAAsB;IAC5C,2EAA2E;IAC3E,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuB;gBAE/B,QAAQ,GAAE,QAAiB,EAAE,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe;IAK9E;;;;OAIG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAc3C;;;;;;;OAOG;IACH,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IA4CtC;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgBtC;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAClC,kBAAkB,IAAI,MAAM,GAAG,IAAI;CACpC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzD;AAID;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE/D"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA6GjD,QAAA,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA6GjD,QAAA,MAAM,MAAM,EAAE,MAsWb,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1155,9 +1155,7 @@ function loadFlowDeckConfig(directory) {
|
|
|
1155
1155
|
try {
|
|
1156
1156
|
const content = readFileSync9(configPath, "utf-8");
|
|
1157
1157
|
return JSON.parse(content);
|
|
1158
|
-
} catch {
|
|
1159
|
-
console.warn(`[flowdeck] Failed to load config from ${configPath}`);
|
|
1160
|
-
}
|
|
1158
|
+
} catch {}
|
|
1161
1159
|
}
|
|
1162
1160
|
}
|
|
1163
1161
|
return {};
|
|
@@ -1238,6 +1236,136 @@ function extractText2(parts) {
|
|
|
1238
1236
|
return parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join(`
|
|
1239
1237
|
`);
|
|
1240
1238
|
}
|
|
1239
|
+
async function runWithStreaming(client, childId, agentName, fullPrompt, toolsConfig, directory, abort, onTitle) {
|
|
1240
|
+
const sseResult = await client.event.subscribe({ query: { directory } });
|
|
1241
|
+
const stream = sseResult.stream;
|
|
1242
|
+
const asyncRes = await client.session.promptAsync({
|
|
1243
|
+
path: { id: childId },
|
|
1244
|
+
query: { directory },
|
|
1245
|
+
body: {
|
|
1246
|
+
agent: agentName,
|
|
1247
|
+
tools: toolsConfig,
|
|
1248
|
+
parts: [{ type: "text", text: fullPrompt }]
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
if (asyncRes.error) {
|
|
1252
|
+
return {
|
|
1253
|
+
output: "",
|
|
1254
|
+
error: `promptAsync failed: ${JSON.stringify(asyncRes.error)}`
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
let streamedText = "";
|
|
1258
|
+
let currentTool = "";
|
|
1259
|
+
onTitle(`⏳ ${agentName} — starting…`);
|
|
1260
|
+
try {
|
|
1261
|
+
for await (const raw of stream) {
|
|
1262
|
+
if (abort.aborted)
|
|
1263
|
+
break;
|
|
1264
|
+
const event = typeof raw === "object" && raw !== null ? Object.values(raw)[0] ?? raw : raw;
|
|
1265
|
+
if (!event || typeof event !== "object")
|
|
1266
|
+
continue;
|
|
1267
|
+
const sid = event.properties?.sessionID;
|
|
1268
|
+
if (sid && sid !== childId)
|
|
1269
|
+
continue;
|
|
1270
|
+
switch (event.type) {
|
|
1271
|
+
case "session.next.step.started": {
|
|
1272
|
+
const model = event.properties?.model?.id ?? "";
|
|
1273
|
+
onTitle(`\uD83E\uDD14 ${agentName} — thinking${model ? ` (${model})` : ""}…`);
|
|
1274
|
+
break;
|
|
1275
|
+
}
|
|
1276
|
+
case "session.next.text.delta": {
|
|
1277
|
+
const delta = event.properties?.delta ?? "";
|
|
1278
|
+
streamedText += delta;
|
|
1279
|
+
const preview = streamedText.slice(-80).replace(/\n/g, " ").trim();
|
|
1280
|
+
onTitle(`✍️ ${agentName} — ${preview}`);
|
|
1281
|
+
break;
|
|
1282
|
+
}
|
|
1283
|
+
case "session.next.text.ended": {
|
|
1284
|
+
const text = event.properties?.text ?? streamedText;
|
|
1285
|
+
streamedText = text;
|
|
1286
|
+
break;
|
|
1287
|
+
}
|
|
1288
|
+
case "session.next.reasoning.delta": {
|
|
1289
|
+
const delta = event.properties?.delta ?? "";
|
|
1290
|
+
const preview = delta.slice(0, 60).replace(/\n/g, " ").trim();
|
|
1291
|
+
onTitle(`\uD83D\uDCAD ${agentName} — ${preview}`);
|
|
1292
|
+
break;
|
|
1293
|
+
}
|
|
1294
|
+
case "session.next.tool.called": {
|
|
1295
|
+
currentTool = event.properties?.tool ?? "tool";
|
|
1296
|
+
onTitle(`\uD83D\uDD27 ${agentName} → ${currentTool}…`);
|
|
1297
|
+
break;
|
|
1298
|
+
}
|
|
1299
|
+
case "session.next.tool.progress": {
|
|
1300
|
+
const content = event.properties?.content ?? [];
|
|
1301
|
+
const progressText = content.filter((c) => c.type === "text").map((c) => c.text).join(" ").slice(0, 80).replace(/\n/g, " ").trim();
|
|
1302
|
+
if (progressText) {
|
|
1303
|
+
onTitle(`\uD83D\uDD27 ${agentName} → ${currentTool}: ${progressText}`);
|
|
1304
|
+
}
|
|
1305
|
+
break;
|
|
1306
|
+
}
|
|
1307
|
+
case "session.next.tool.success": {
|
|
1308
|
+
onTitle(`✅ ${agentName} → ${currentTool} done`);
|
|
1309
|
+
currentTool = "";
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1312
|
+
case "session.next.tool.failed": {
|
|
1313
|
+
onTitle(`❌ ${agentName} → ${currentTool} failed`);
|
|
1314
|
+
currentTool = "";
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
case "session.next.retried": {
|
|
1318
|
+
onTitle(`↻ ${agentName} — retrying…`);
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
case "session.next.step.ended": {
|
|
1322
|
+
const cost = event.properties?.cost ?? 0;
|
|
1323
|
+
const finish = event.properties?.finish ?? "";
|
|
1324
|
+
if (cost > 0) {
|
|
1325
|
+
onTitle(`\uD83D\uDCCA ${agentName} — step done ($${cost.toFixed(4)}) [${finish}]`);
|
|
1326
|
+
} else {
|
|
1327
|
+
onTitle(`\uD83D\uDCCA ${agentName} — step done [${finish}]`);
|
|
1328
|
+
}
|
|
1329
|
+
break;
|
|
1330
|
+
}
|
|
1331
|
+
case "session.error": {
|
|
1332
|
+
const msg = event.properties?.error?.message ?? JSON.stringify(event.properties?.error);
|
|
1333
|
+
return { output: streamedText, error: `Session error: ${msg}` };
|
|
1334
|
+
}
|
|
1335
|
+
case "session.idle": {
|
|
1336
|
+
onTitle(`✓ ${agentName} — complete`);
|
|
1337
|
+
goto_done:
|
|
1338
|
+
break goto_done;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
if (event.type === "session.idle")
|
|
1342
|
+
break;
|
|
1343
|
+
}
|
|
1344
|
+
} catch (err) {
|
|
1345
|
+
if (!abort.aborted) {
|
|
1346
|
+
onTitle(`⚠️ ${agentName} — stream closed (${err?.message ?? err})`);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
if (streamedText) {
|
|
1350
|
+
return { output: streamedText };
|
|
1351
|
+
}
|
|
1352
|
+
try {
|
|
1353
|
+
const msgsRes = await client.session.messages({
|
|
1354
|
+
path: { id: childId },
|
|
1355
|
+
query: { directory }
|
|
1356
|
+
});
|
|
1357
|
+
const messages = msgsRes.data ?? [];
|
|
1358
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
1359
|
+
const msg = messages[i];
|
|
1360
|
+
if (msg.role === "assistant") {
|
|
1361
|
+
const text = extractText2(msg.parts ?? []);
|
|
1362
|
+
if (text)
|
|
1363
|
+
return { output: text };
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
} catch {}
|
|
1367
|
+
return { output: "" };
|
|
1368
|
+
}
|
|
1241
1369
|
function createDelegateTool(client) {
|
|
1242
1370
|
return tool4({
|
|
1243
1371
|
description: "Delegate a task to a single agent via a child session. Returns the agent's output.",
|
|
@@ -1252,14 +1380,14 @@ function createDelegateTool(client) {
|
|
|
1252
1380
|
workflow_id: tool4.schema.string().optional(),
|
|
1253
1381
|
stage: tool4.schema.string().optional()
|
|
1254
1382
|
},
|
|
1255
|
-
async execute(args,
|
|
1383
|
+
async execute(args, execContext) {
|
|
1256
1384
|
const startTime = Date.now();
|
|
1257
1385
|
const taskType = normalizeTaskType(args.task_type, args.agent);
|
|
1258
1386
|
const retryAttempts = typeof args.retry_attempts === "number" ? args.retry_attempts : 1;
|
|
1259
1387
|
const maxRetries = Math.max(0, Math.floor(retryAttempts));
|
|
1260
1388
|
let agentModel = "";
|
|
1261
1389
|
try {
|
|
1262
|
-
const cfg = loadFlowDeckConfig(
|
|
1390
|
+
const cfg = loadFlowDeckConfig(execContext.directory);
|
|
1263
1391
|
agentModel = cfg.agents?.[args.agent]?.model ?? "";
|
|
1264
1392
|
} catch {}
|
|
1265
1393
|
const metricsWorkflowId = args.workflow_id ?? "";
|
|
@@ -1273,16 +1401,16 @@ ${args.prompt}` : args.prompt;
|
|
|
1273
1401
|
let stateVersion = 0;
|
|
1274
1402
|
let indexVersion = 0;
|
|
1275
1403
|
if (safe_to_cache) {
|
|
1276
|
-
const index = readCodebaseIndex(
|
|
1277
|
-
const sp = statePath(
|
|
1404
|
+
const index = readCodebaseIndex(execContext.directory);
|
|
1405
|
+
const sp = statePath(execContext.directory);
|
|
1278
1406
|
const rawState = existsSync10(sp) ? readFileSync10(sp, "utf-8") : "";
|
|
1279
1407
|
const state = rawState ? parseState(rawState) : {};
|
|
1280
1408
|
stateVersion = typeof state.summaryVersion === "number" ? state.summaryVersion : 0;
|
|
1281
1409
|
indexVersion = typeof index.summaryVersion === "number" ? index.summaryVersion : 0;
|
|
1282
|
-
const cached = getCached(
|
|
1410
|
+
const cached = getCached(execContext.directory, args.agent, fullPrompt, args.context ?? "", stateVersion, indexVersion, true);
|
|
1283
1411
|
if (cached !== null) {
|
|
1284
1412
|
if (metricsWorkflowId) {
|
|
1285
|
-
recordCacheHit(
|
|
1413
|
+
recordCacheHit(execContext.directory, metricsWorkflowId, metricsStage, fullPrompt, args.agent, agentModel);
|
|
1286
1414
|
}
|
|
1287
1415
|
return JSON.stringify({
|
|
1288
1416
|
agent: args.agent,
|
|
@@ -1297,8 +1425,8 @@ ${args.prompt}` : args.prompt;
|
|
|
1297
1425
|
}
|
|
1298
1426
|
}
|
|
1299
1427
|
const createRes = await client.session.create({
|
|
1300
|
-
body: { parentID:
|
|
1301
|
-
query: { directory:
|
|
1428
|
+
body: { parentID: execContext.sessionID, title: `${args.agent}-delegate` },
|
|
1429
|
+
query: { directory: execContext.directory }
|
|
1302
1430
|
});
|
|
1303
1431
|
if (createRes.error || !createRes.data?.id) {
|
|
1304
1432
|
return JSON.stringify({
|
|
@@ -1309,84 +1437,61 @@ ${args.prompt}` : args.prompt;
|
|
|
1309
1437
|
});
|
|
1310
1438
|
}
|
|
1311
1439
|
const childId = createRes.data.id;
|
|
1312
|
-
|
|
1440
|
+
execContext.abort.addEventListener("abort", () => {
|
|
1313
1441
|
client.session.abort({
|
|
1314
1442
|
path: { id: childId },
|
|
1315
|
-
query: { directory:
|
|
1443
|
+
query: { directory: execContext.directory }
|
|
1316
1444
|
}).catch(() => {});
|
|
1317
1445
|
});
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
---
|
|
1321
|
-
|
|
1322
|
-
${args.prompt}` : args.prompt;
|
|
1323
|
-
let promptRes = null;
|
|
1446
|
+
let lastOutput = "";
|
|
1447
|
+
let lastError;
|
|
1324
1448
|
let retriesUsed = 0;
|
|
1325
1449
|
for (let attempt = 0;attempt <= maxRetries; attempt++) {
|
|
1326
1450
|
const attemptStart = Date.now();
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
});
|
|
1336
|
-
if (!shouldRetry(promptRes) || attempt === maxRetries)
|
|
1451
|
+
if (attempt > 0) {
|
|
1452
|
+
execContext.metadata({ title: `↻ ${args.agent} — retry ${attempt}/${maxRetries}…` });
|
|
1453
|
+
}
|
|
1454
|
+
const result = await runWithStreaming(client, childId, args.agent, fullPrompt, { question: false }, execContext.directory, execContext.abort, (title) => execContext.metadata({ title }));
|
|
1455
|
+
lastOutput = result.output;
|
|
1456
|
+
lastError = result.error;
|
|
1457
|
+
const shouldRetryAttempt = !!(lastError || !lastOutput.trim());
|
|
1458
|
+
if (!shouldRetryAttempt || attempt === maxRetries)
|
|
1337
1459
|
break;
|
|
1338
1460
|
if (metricsWorkflowId) {
|
|
1339
|
-
const retryInputTokens = estimateTokens(
|
|
1461
|
+
const retryInputTokens = estimateTokens(fullPrompt);
|
|
1340
1462
|
const retryCostUsd = agentModel ? estimateCostUSD(agentModel, retryInputTokens, 0) : undefined;
|
|
1341
|
-
recordRetryCall(
|
|
1463
|
+
recordRetryCall(execContext.directory, metricsWorkflowId, metricsStage, fullPrompt, "", args.agent, Date.now() - attemptStart, agentModel, retryCostUsd);
|
|
1342
1464
|
}
|
|
1343
1465
|
retriesUsed++;
|
|
1344
1466
|
}
|
|
1345
|
-
if (
|
|
1346
|
-
|
|
1347
|
-
recordRun(context.directory, args.agent, "", taskType, false, Date.now() - startTime);
|
|
1467
|
+
if (lastError && !lastOutput.trim()) {
|
|
1468
|
+
recordRun(execContext.directory, args.agent, "", taskType, false, Date.now() - startTime);
|
|
1348
1469
|
return JSON.stringify({
|
|
1349
1470
|
agent: args.agent,
|
|
1350
1471
|
session_id: childId,
|
|
1351
1472
|
success: false,
|
|
1352
|
-
error:
|
|
1473
|
+
error: lastError,
|
|
1353
1474
|
task_type: taskType,
|
|
1354
1475
|
model: "",
|
|
1355
1476
|
retries_used: retriesUsed,
|
|
1356
1477
|
duration_ms: Date.now() - startTime
|
|
1357
1478
|
});
|
|
1358
1479
|
}
|
|
1359
|
-
|
|
1360
|
-
if (info?.error) {
|
|
1361
|
-
const errMsg = `Agent error: ${JSON.stringify(info.error)}`;
|
|
1362
|
-
recordRun(context.directory, args.agent, "", taskType, false, Date.now() - startTime);
|
|
1363
|
-
return JSON.stringify({
|
|
1364
|
-
agent: args.agent,
|
|
1365
|
-
session_id: childId,
|
|
1366
|
-
success: false,
|
|
1367
|
-
error: errMsg,
|
|
1368
|
-
task_type: taskType,
|
|
1369
|
-
model: "",
|
|
1370
|
-
retries_used: retriesUsed,
|
|
1371
|
-
duration_ms: Date.now() - startTime
|
|
1372
|
-
});
|
|
1373
|
-
}
|
|
1374
|
-
const output = extractText2(promptRes.data?.parts ?? []);
|
|
1375
|
-
recordRun(context.directory, args.agent, "", taskType, true, Date.now() - startTime);
|
|
1480
|
+
recordRun(execContext.directory, args.agent, "", taskType, true, Date.now() - startTime);
|
|
1376
1481
|
if (metricsWorkflowId) {
|
|
1377
|
-
const inputTokens = estimateTokens(
|
|
1378
|
-
const outputTokens = estimateTokens(
|
|
1482
|
+
const inputTokens = estimateTokens(fullPrompt);
|
|
1483
|
+
const outputTokens = estimateTokens(lastOutput);
|
|
1379
1484
|
const costUsd = agentModel ? estimateCostUSD(agentModel, inputTokens, outputTokens) : undefined;
|
|
1380
|
-
recordModelCall(
|
|
1485
|
+
recordModelCall(execContext.directory, metricsWorkflowId, metricsStage, fullPrompt, lastOutput, args.agent, Date.now() - startTime, agentModel, costUsd);
|
|
1381
1486
|
}
|
|
1382
|
-
if (safe_to_cache &&
|
|
1383
|
-
setCached(
|
|
1487
|
+
if (safe_to_cache && lastOutput) {
|
|
1488
|
+
setCached(execContext.directory, args.agent, fullPrompt, args.context ?? "", stateVersion, indexVersion, lastOutput, true, args.cache_ttl_ms);
|
|
1384
1489
|
}
|
|
1385
1490
|
return JSON.stringify({
|
|
1386
1491
|
agent: args.agent,
|
|
1387
1492
|
session_id: childId,
|
|
1388
1493
|
success: true,
|
|
1389
|
-
output:
|
|
1494
|
+
output: lastOutput || "(no text output)",
|
|
1390
1495
|
task_type: taskType,
|
|
1391
1496
|
model: "",
|
|
1392
1497
|
retries_used: retriesUsed,
|
|
@@ -3056,8 +3161,7 @@ async function sessionStartHook(ctx) {
|
|
|
3056
3161
|
result.flowdeck_is_workspace_root = ctx.directory === workspaceRoot;
|
|
3057
3162
|
}
|
|
3058
3163
|
return result;
|
|
3059
|
-
} catch
|
|
3060
|
-
console.warn("[flowdeck] Warning: State file unreadable. Continuing without flowdeck context.");
|
|
3164
|
+
} catch {
|
|
3061
3165
|
const result = {
|
|
3062
3166
|
flowdeck_phase: null,
|
|
3063
3167
|
flowdeck_status: "error",
|
|
@@ -3101,9 +3205,7 @@ function notify(title, body, level = "info") {
|
|
|
3101
3205
|
if (platform === "linux") {
|
|
3102
3206
|
const urgency = level === "critical" ? "critical" : "normal";
|
|
3103
3207
|
const proc = execFile("notify-send", ["--urgency", urgency, "--app-name", "FlowDeck", "--icon", "dialog-information", title, body], { timeout: 3000 });
|
|
3104
|
-
proc.on("error", () => {
|
|
3105
|
-
tryTerminalBell();
|
|
3106
|
-
});
|
|
3208
|
+
proc.on("error", () => {});
|
|
3107
3209
|
} else if (platform === "darwin") {
|
|
3108
3210
|
const script = `display notification "${body.replace(/"/g, "\\\"")}" with title "${title.replace(/"/g, "\\\"")}" subtitle "FlowDeck"`;
|
|
3109
3211
|
const proc = execFile("osascript", ["-e", script], { timeout: 3000 });
|
|
@@ -3121,11 +3223,6 @@ function notify(title, body, level = "info") {
|
|
|
3121
3223
|
}
|
|
3122
3224
|
} catch {}
|
|
3123
3225
|
}
|
|
3124
|
-
function tryTerminalBell() {
|
|
3125
|
-
try {
|
|
3126
|
-
process.stdout.write("\x07");
|
|
3127
|
-
} catch {}
|
|
3128
|
-
}
|
|
3129
3226
|
|
|
3130
3227
|
class NotificationController {
|
|
3131
3228
|
pendingCommand = null;
|
|
@@ -3457,14 +3554,11 @@ function isValidDirectory(directory) {
|
|
|
3457
3554
|
return false;
|
|
3458
3555
|
}
|
|
3459
3556
|
}
|
|
3460
|
-
function logEvent(directory, event) {
|
|
3557
|
+
function logEvent(directory, event, log) {
|
|
3461
3558
|
if (process.env.FLOWDECK_EVENT_LOG === "off")
|
|
3462
3559
|
return;
|
|
3463
|
-
if (!isValidDirectory(directory))
|
|
3464
|
-
process.stderr.write(`[FlowDeck] Invalid log directory: ${directory}
|
|
3465
|
-
`);
|
|
3560
|
+
if (!isValidDirectory(directory))
|
|
3466
3561
|
return;
|
|
3467
|
-
}
|
|
3468
3562
|
const logDir = join24(directory, ".opencode");
|
|
3469
3563
|
const logPath = join24(logDir, "flowdeck-events.jsonl");
|
|
3470
3564
|
try {
|
|
@@ -3474,9 +3568,9 @@ function logEvent(directory, event) {
|
|
|
3474
3568
|
appendFileSync5(logPath, JSON.stringify(event) + `
|
|
3475
3569
|
`, "utf-8");
|
|
3476
3570
|
rotateLogFile(logPath);
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3571
|
+
if (log) {
|
|
3572
|
+
log(formatEventForStderr(event));
|
|
3573
|
+
}
|
|
3480
3574
|
} catch {}
|
|
3481
3575
|
}
|
|
3482
3576
|
function rotateLogFile(logPath) {
|
|
@@ -3585,97 +3679,101 @@ function cleanupStaleToolStartTimes() {
|
|
|
3585
3679
|
}
|
|
3586
3680
|
}
|
|
3587
3681
|
}
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
}
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3682
|
+
function createEventLogHooks(appLog) {
|
|
3683
|
+
return {
|
|
3684
|
+
async before(ctx, toolInput, toolOutput) {
|
|
3685
|
+
const toolName = toolInput.tool ?? toolInput.name ?? "unknown";
|
|
3686
|
+
const sessionId = toolInput.sessionID ?? toolInput.sessionId ?? "unknown";
|
|
3687
|
+
const args = toolOutput?.args ?? toolInput?.args ?? {};
|
|
3688
|
+
const startKey = `${sessionId}:${toolName}`;
|
|
3689
|
+
beforeHookCallCount++;
|
|
3690
|
+
if (beforeHookCallCount >= CLEANUP_INTERVAL) {
|
|
3691
|
+
beforeHookCallCount = 0;
|
|
3692
|
+
cleanupStaleToolStartTimes();
|
|
3693
|
+
}
|
|
3694
|
+
toolStartTimes.set(startKey, Date.now());
|
|
3695
|
+
const event = {
|
|
3696
|
+
timestamp: new Date().toISOString(),
|
|
3697
|
+
type: "tool.before",
|
|
3698
|
+
agent: getCurrentAgent() ?? undefined,
|
|
3699
|
+
tool: toolName,
|
|
3700
|
+
args: sanitizeArgs(args),
|
|
3701
|
+
session_id: sessionId
|
|
3702
|
+
};
|
|
3703
|
+
logEvent(ctx.directory, event, appLog);
|
|
3704
|
+
},
|
|
3705
|
+
async after(ctx, toolInput, toolOutput) {
|
|
3706
|
+
const toolName = toolInput.tool ?? toolInput.name ?? "unknown";
|
|
3707
|
+
const sessionId = toolInput.sessionID ?? toolInput.sessionId ?? "unknown";
|
|
3708
|
+
const args = toolOutput?.args ?? toolInput?.args ?? {};
|
|
3709
|
+
const startKey = `${sessionId}:${toolName}`;
|
|
3710
|
+
const startTime = toolStartTimes.get(startKey);
|
|
3711
|
+
const durationMs = startTime ? Date.now() - startTime : undefined;
|
|
3712
|
+
toolStartTimes.delete(startKey);
|
|
3713
|
+
let status = "success";
|
|
3714
|
+
let error;
|
|
3715
|
+
if (toolOutput?.error != null) {
|
|
3716
|
+
status = "error";
|
|
3717
|
+
error = typeof toolOutput.error === "string" ? toolOutput.error : String(toolOutput.error);
|
|
3718
|
+
} else if (toolOutput?.status === "error") {
|
|
3719
|
+
status = "error";
|
|
3720
|
+
error = typeof toolOutput.error === "string" ? toolOutput.error : "Unknown error";
|
|
3721
|
+
} else if (toolOutput?.status === "blocked") {
|
|
3722
|
+
status = "blocked";
|
|
3723
|
+
}
|
|
3724
|
+
const event = {
|
|
3725
|
+
timestamp: new Date().toISOString(),
|
|
3726
|
+
type: "tool.after",
|
|
3727
|
+
agent: getCurrentAgent() ?? undefined,
|
|
3728
|
+
tool: toolName,
|
|
3729
|
+
args: sanitizeArgs(args),
|
|
3730
|
+
duration_ms: durationMs,
|
|
3731
|
+
status,
|
|
3732
|
+
error,
|
|
3733
|
+
session_id: sessionId
|
|
3734
|
+
};
|
|
3735
|
+
logEvent(ctx.directory, event, appLog);
|
|
3736
|
+
},
|
|
3737
|
+
async session(ctx, event) {
|
|
3738
|
+
const type = event?.type ?? "";
|
|
3739
|
+
const props = event?.properties ?? {};
|
|
3740
|
+
if (type === "session.created") {
|
|
3741
|
+
if (props.parentID) {
|
|
3742
|
+
const agentName = extractAgentFromEvent(props);
|
|
3743
|
+
setCurrentAgent(agentName);
|
|
3744
|
+
}
|
|
3745
|
+
const toolEvent = {
|
|
3746
|
+
timestamp: new Date().toISOString(),
|
|
3747
|
+
type: "session.created",
|
|
3748
|
+
session_id: props.id ?? props.sessionId ?? undefined
|
|
3749
|
+
};
|
|
3750
|
+
logEvent(ctx.directory, toolEvent, appLog);
|
|
3751
|
+
} else if (type === "session.idle") {
|
|
3752
|
+
if (props.parentID) {
|
|
3753
|
+
setCurrentAgent(null);
|
|
3754
|
+
}
|
|
3755
|
+
const toolEvent = {
|
|
3756
|
+
timestamp: new Date().toISOString(),
|
|
3757
|
+
type: "session.idle",
|
|
3758
|
+
session_id: props.id ?? props.sessionId ?? undefined
|
|
3759
|
+
};
|
|
3760
|
+
logEvent(ctx.directory, toolEvent, appLog);
|
|
3761
|
+
} else if (type === "session.error") {
|
|
3762
|
+
if (props.parentID) {
|
|
3763
|
+
setCurrentAgent(null);
|
|
3764
|
+
}
|
|
3765
|
+
const err = props.error;
|
|
3766
|
+
const errorMsg = (err && typeof err === "object" && "message" in err ? String(err.message) : undefined) ?? (typeof err === "string" ? err : undefined) ?? undefined;
|
|
3767
|
+
const toolEvent = {
|
|
3768
|
+
timestamp: new Date().toISOString(),
|
|
3769
|
+
type: "session.error",
|
|
3770
|
+
session_id: props.id ?? props.sessionId ?? undefined,
|
|
3771
|
+
error: errorMsg
|
|
3772
|
+
};
|
|
3773
|
+
logEvent(ctx.directory, toolEvent, appLog);
|
|
3774
|
+
}
|
|
3658
3775
|
}
|
|
3659
|
-
|
|
3660
|
-
timestamp: new Date().toISOString(),
|
|
3661
|
-
type: "session.idle",
|
|
3662
|
-
session_id: props.id ?? props.sessionId ?? undefined
|
|
3663
|
-
};
|
|
3664
|
-
logEvent(ctx.directory, toolEvent);
|
|
3665
|
-
} else if (type === "session.error") {
|
|
3666
|
-
if (props.parentID) {
|
|
3667
|
-
setCurrentAgent(null);
|
|
3668
|
-
}
|
|
3669
|
-
const err = props.error;
|
|
3670
|
-
const errorMsg = (err && typeof err === "object" && "message" in err ? String(err.message) : undefined) ?? (typeof err === "string" ? err : undefined) ?? undefined;
|
|
3671
|
-
const toolEvent = {
|
|
3672
|
-
timestamp: new Date().toISOString(),
|
|
3673
|
-
type: "session.error",
|
|
3674
|
-
session_id: props.id ?? props.sessionId ?? undefined,
|
|
3675
|
-
error: errorMsg
|
|
3676
|
-
};
|
|
3677
|
-
logEvent(ctx.directory, toolEvent);
|
|
3678
|
-
}
|
|
3776
|
+
};
|
|
3679
3777
|
}
|
|
3680
3778
|
function extractAgentFromEvent(props) {
|
|
3681
3779
|
if (typeof props.agent === "string")
|
|
@@ -7323,7 +7421,6 @@ function createAgent(name, model, customPrompt, customAppendPrompt) {
|
|
|
7323
7421
|
case "supervisor":
|
|
7324
7422
|
return createSupervisorAgent(model, customPrompt, customAppendPrompt);
|
|
7325
7423
|
default:
|
|
7326
|
-
console.warn(`[flowdeck] Unknown agent: ${name}`);
|
|
7327
7424
|
return;
|
|
7328
7425
|
}
|
|
7329
7426
|
}
|
|
@@ -8013,6 +8110,7 @@ var plugin = async (input, _options) => {
|
|
|
8013
8110
|
const compactionHook = createCompactionHook({ directory }, fileTracker);
|
|
8014
8111
|
const orchestratorGuard = new OrchestratorGuard;
|
|
8015
8112
|
const autoLearnHook = createAutoLearnHook(client, fileTracker, directory, appLog);
|
|
8113
|
+
const eventLog = createEventLogHooks(appLog);
|
|
8016
8114
|
const notifCtrl = new NotificationController(undefined, appLog);
|
|
8017
8115
|
const agentConfigs = getAgentConfigs({});
|
|
8018
8116
|
const mcps = createFlowDeckMcps();
|
|
@@ -8126,7 +8224,7 @@ var plugin = async (input, _options) => {
|
|
|
8126
8224
|
if (type === "session.created" || type === "session.started") {
|
|
8127
8225
|
await sessionStartHook({ directory });
|
|
8128
8226
|
if (type === "session.created") {
|
|
8129
|
-
await
|
|
8227
|
+
await eventLog.session({ directory }, event);
|
|
8130
8228
|
}
|
|
8131
8229
|
}
|
|
8132
8230
|
if (type === "command.executed") {
|
|
@@ -8138,7 +8236,7 @@ var plugin = async (input, _options) => {
|
|
|
8138
8236
|
await contextMonitor.event({ event });
|
|
8139
8237
|
orchestratorGuard.onEvent(event);
|
|
8140
8238
|
if (type === "session.idle") {
|
|
8141
|
-
await
|
|
8239
|
+
await eventLog.session({ directory }, event);
|
|
8142
8240
|
const hasEdits = fileTracker.getEditedPaths().length > 0;
|
|
8143
8241
|
if (lastExecutedCommand) {
|
|
8144
8242
|
lastExecutedCommand = null;
|
|
@@ -8152,7 +8250,7 @@ var plugin = async (input, _options) => {
|
|
|
8152
8250
|
}
|
|
8153
8251
|
}
|
|
8154
8252
|
if (type === "session.error") {
|
|
8155
|
-
await
|
|
8253
|
+
await eventLog.session({ directory }, event);
|
|
8156
8254
|
lastExecutedCommand = null;
|
|
8157
8255
|
const err = event?.properties?.error;
|
|
8158
8256
|
const errorMsg = (err && typeof err === "object" && "message" in err ? String(err.message) : undefined) ?? (typeof err === "string" ? err : undefined) ?? "An unexpected error occurred";
|
|
@@ -8203,10 +8301,10 @@ var plugin = async (input, _options) => {
|
|
|
8203
8301
|
await toolGuardHook({ directory }, toolInput, toolOutput);
|
|
8204
8302
|
await patchTrustHook({ directory }, toolInput, toolOutput);
|
|
8205
8303
|
await decisionTraceHook({ directory }, toolInput, toolOutput);
|
|
8206
|
-
await
|
|
8304
|
+
await eventLog.before({ directory }, toolInput, toolOutput);
|
|
8207
8305
|
},
|
|
8208
8306
|
"tool.execute.after": async (toolInput, toolOutput) => {
|
|
8209
|
-
await
|
|
8307
|
+
await eventLog.after({ directory }, toolInput, toolOutput);
|
|
8210
8308
|
const afterToolName = toolInput.tool ?? toolInput.name ?? "";
|
|
8211
8309
|
if (afterToolName === "delegate" || afterToolName === "run-pipeline") {
|
|
8212
8310
|
try {
|
|
@@ -73,9 +73,11 @@ export declare function loadResearchEvidence(dir: string, scope: ResearchScope):
|
|
|
73
73
|
*/
|
|
74
74
|
export declare function buildResearchDiagnostics(evidence: ResearchEvidence): ResearchDiagnostics;
|
|
75
75
|
/**
|
|
76
|
-
* Log research diagnostics
|
|
76
|
+
* Log research diagnostics via the provided logger (safe for TUI environments).
|
|
77
|
+
* Defaults to a no-op so raw stdout is never written from the plugin runtime.
|
|
78
|
+
* Pass `logger: console.log` only in non-TUI contexts (e.g. standalone scripts).
|
|
77
79
|
*/
|
|
78
|
-
export declare function logResearchDiagnostics(diags: ResearchDiagnostics): void;
|
|
80
|
+
export declare function logResearchDiagnostics(diags: ResearchDiagnostics, logger?: (msg: string) => void): void;
|
|
79
81
|
/**
|
|
80
82
|
* Perform a research pass for a given scope, checking freshness first.
|
|
81
83
|
*
|
|
@@ -85,6 +87,8 @@ export declare function logResearchDiagnostics(diags: ResearchDiagnostics): void
|
|
|
85
87
|
export declare function runResearchGate(dir: string, scope: ResearchScope, options?: {
|
|
86
88
|
forceRefresh?: boolean;
|
|
87
89
|
customEvidence?: Partial<ResearchEvidence>;
|
|
90
|
+
/** Optional logger for diagnostics. Defaults to no-op to avoid corrupting TUI output. */
|
|
91
|
+
logger?: (msg: string) => void;
|
|
88
92
|
}): Promise<ResearchEvidence>;
|
|
89
93
|
/**
|
|
90
94
|
* Check if a stage should proceed or block based on research gate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research-gate.d.ts","sourceRoot":"","sources":["../../src/lib/research-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAA0F,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAGxJ,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;AAEtE,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,KAAK,EAAE,aAAa,CAAA;IACpB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,mCAAmC;IACnC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,0EAA0E;IAC1E,aAAa,EAAE,OAAO,CAAA;IACtB,2EAA2E;IAC3E,kBAAkB,EAAE,OAAO,CAAA;IAC3B,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,KAAK,EAAE,aAAa,CAAA;IACpB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,yBAAyB;IACzB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,kCAAkC;IAClC,aAAa,EAAE,OAAO,CAAA;IACtB,kDAAkD;IAClD,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAInF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CA0B3G;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAa/F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,mBAAmB,CAUxF;AAED
|
|
1
|
+
{"version":3,"file":"research-gate.d.ts","sourceRoot":"","sources":["../../src/lib/research-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAA0F,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAGxJ,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;AAEtE,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,KAAK,EAAE,aAAa,CAAA;IACpB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,mCAAmC;IACnC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,0EAA0E;IAC1E,aAAa,EAAE,OAAO,CAAA;IACtB,2EAA2E;IAC3E,kBAAkB,EAAE,OAAO,CAAA;IAC3B,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,KAAK,EAAE,aAAa,CAAA;IACpB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,yBAAyB;IACzB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,kCAAkC;IAClC,aAAa,EAAE,OAAO,CAAA;IACtB,kDAAkD;IAClD,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAInF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CA0B3G;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAa/F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,mBAAmB,CAUxF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,mBAAmB,EAC1B,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,GACvC,IAAI,CAUN;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,aAAa,EACpB,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC1C,yFAAyF;IACzF,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,GACA,OAAO,CAAC,gBAAgB,CAAC,CA0H3B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAQvG"}
|
|
@@ -13,6 +13,6 @@ export interface ToolEvent {
|
|
|
13
13
|
export declare function getCurrentAgent(): string | null;
|
|
14
14
|
export declare function setCurrentAgent(agent: string | null): void;
|
|
15
15
|
export declare function sanitizeArgs(args: unknown): Record<string, unknown>;
|
|
16
|
-
export declare function logEvent(directory: string, event: ToolEvent): void;
|
|
16
|
+
export declare function logEvent(directory: string, event: ToolEvent, log?: (msg: string) => void): void;
|
|
17
17
|
export declare function formatEventForStderr(event: ToolEvent): string;
|
|
18
18
|
//# sourceMappingURL=event-logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../../src/services/event-logger.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,aAAa,GAAG,YAAY,GAAG,iBAAiB,GAAG,cAAc,GAAG,eAAe,GAAG,iBAAiB,CAAA;IAC7G,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAUD,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmBnE;AAoBD,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../../src/services/event-logger.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,aAAa,GAAG,YAAY,GAAG,iBAAiB,GAAG,cAAc,GAAG,eAAe,GAAG,iBAAiB,CAAA;IAC7G,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAUD,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmBnE;AAoBD,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAqB/F;AAwBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CA2D7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../src/tools/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../src/tools/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAgOtD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CA6NzE"}
|