@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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"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"}
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":"AASA,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAOjD;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAC1B,SAAS,EAAE,GAAG,EACd,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,IAAI,CAAC,CAyBf;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,CAoCf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAC1B,KAAK,EAAE,GAAG,GACT,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
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,CAoCrF;AAUD,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"}
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"}
@@ -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,MAmWb,CAAA;AAED,eAAe,MAAM,CAAA"}
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, context) {
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(context.directory);
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(context.directory);
1277
- const sp = statePath(context.directory);
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(context.directory, args.agent, fullPrompt, args.context ?? "", stateVersion, indexVersion, true);
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(context.directory, metricsWorkflowId, metricsStage, fullPrompt, args.agent, agentModel);
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: context.sessionID, title: `${args.agent}-delegate` },
1301
- query: { directory: context.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
- context.abort.addEventListener("abort", () => {
1440
+ execContext.abort.addEventListener("abort", () => {
1313
1441
  client.session.abort({
1314
1442
  path: { id: childId },
1315
- query: { directory: context.directory }
1443
+ query: { directory: execContext.directory }
1316
1444
  }).catch(() => {});
1317
1445
  });
1318
- const fullPromptForSession = args.context ? `${args.context}
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
- promptRes = await client.session.prompt({
1328
- path: { id: childId },
1329
- body: {
1330
- agent: args.agent,
1331
- parts: [{ type: "text", text: fullPromptForSession }],
1332
- tools: { question: false }
1333
- },
1334
- query: { directory: context.directory }
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(fullPromptForSession);
1461
+ const retryInputTokens = estimateTokens(fullPrompt);
1340
1462
  const retryCostUsd = agentModel ? estimateCostUSD(agentModel, retryInputTokens, 0) : undefined;
1341
- recordRetryCall(context.directory, metricsWorkflowId, metricsStage, fullPromptForSession, "", args.agent, Date.now() - attemptStart, agentModel, retryCostUsd);
1463
+ recordRetryCall(execContext.directory, metricsWorkflowId, metricsStage, fullPrompt, "", args.agent, Date.now() - attemptStart, agentModel, retryCostUsd);
1342
1464
  }
1343
1465
  retriesUsed++;
1344
1466
  }
1345
- if (!promptRes || promptRes.error) {
1346
- const errMsg = `Prompt failed: ${promptRes?.error?.detail ?? "unknown"}`;
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: errMsg,
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
- const info = promptRes.data?.info;
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(fullPromptForSession);
1378
- const outputTokens = estimateTokens(output);
1482
+ const inputTokens = estimateTokens(fullPrompt);
1483
+ const outputTokens = estimateTokens(lastOutput);
1379
1484
  const costUsd = agentModel ? estimateCostUSD(agentModel, inputTokens, outputTokens) : undefined;
1380
- recordModelCall(context.directory, metricsWorkflowId, metricsStage, fullPromptForSession, output, args.agent, Date.now() - startTime, agentModel, costUsd);
1485
+ recordModelCall(execContext.directory, metricsWorkflowId, metricsStage, fullPrompt, lastOutput, args.agent, Date.now() - startTime, agentModel, costUsd);
1381
1486
  }
1382
- if (safe_to_cache && output) {
1383
- setCached(context.directory, args.agent, fullPromptForSession, args.context ?? "", stateVersion, indexVersion, output, true, args.cache_ttl_ms);
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: output || "(no text 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 (err) {
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
- const line = formatEventForStderr(event);
3478
- process.stderr.write(line + `
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
- async function eventLogBeforeHook(ctx, toolInput, toolOutput) {
3589
- const toolName = toolInput.tool ?? toolInput.name ?? "unknown";
3590
- const sessionId = toolInput.sessionID ?? toolInput.sessionId ?? "unknown";
3591
- const args = toolOutput?.args ?? toolInput?.args ?? {};
3592
- const startKey = `${sessionId}:${toolName}`;
3593
- beforeHookCallCount++;
3594
- if (beforeHookCallCount >= CLEANUP_INTERVAL) {
3595
- beforeHookCallCount = 0;
3596
- cleanupStaleToolStartTimes();
3597
- }
3598
- toolStartTimes.set(startKey, Date.now());
3599
- const event = {
3600
- timestamp: new Date().toISOString(),
3601
- type: "tool.before",
3602
- agent: getCurrentAgent() ?? undefined,
3603
- tool: toolName,
3604
- args: sanitizeArgs(args),
3605
- session_id: sessionId
3606
- };
3607
- logEvent(ctx.directory, event);
3608
- }
3609
- async function eventLogAfterHook(ctx, toolInput, toolOutput) {
3610
- const toolName = toolInput.tool ?? toolInput.name ?? "unknown";
3611
- const sessionId = toolInput.sessionID ?? toolInput.sessionId ?? "unknown";
3612
- const args = toolOutput?.args ?? toolInput?.args ?? {};
3613
- const startKey = `${sessionId}:${toolName}`;
3614
- const startTime = toolStartTimes.get(startKey);
3615
- const durationMs = startTime ? Date.now() - startTime : undefined;
3616
- toolStartTimes.delete(startKey);
3617
- let status = "success";
3618
- let error;
3619
- if (toolOutput?.error != null) {
3620
- status = "error";
3621
- error = typeof toolOutput.error === "string" ? toolOutput.error : String(toolOutput.error);
3622
- } else if (toolOutput?.status === "error") {
3623
- status = "error";
3624
- error = typeof toolOutput.error === "string" ? toolOutput.error : "Unknown error";
3625
- } else if (toolOutput?.status === "blocked") {
3626
- status = "blocked";
3627
- }
3628
- const event = {
3629
- timestamp: new Date().toISOString(),
3630
- type: "tool.after",
3631
- agent: getCurrentAgent() ?? undefined,
3632
- tool: toolName,
3633
- args: sanitizeArgs(args),
3634
- duration_ms: durationMs,
3635
- status,
3636
- error,
3637
- session_id: sessionId
3638
- };
3639
- logEvent(ctx.directory, event);
3640
- }
3641
- async function eventLogSessionHook(ctx, event) {
3642
- const type = event?.type ?? "";
3643
- const props = event?.properties ?? {};
3644
- if (type === "session.created") {
3645
- if (props.parentID) {
3646
- const agentName = extractAgentFromEvent(props);
3647
- setCurrentAgent(agentName);
3648
- }
3649
- const toolEvent = {
3650
- timestamp: new Date().toISOString(),
3651
- type: "session.created",
3652
- session_id: props.id ?? props.sessionId ?? undefined
3653
- };
3654
- logEvent(ctx.directory, toolEvent);
3655
- } else if (type === "session.idle") {
3656
- if (props.parentID) {
3657
- setCurrentAgent(null);
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
- const toolEvent = {
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 eventLogSessionHook({ directory }, event);
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 eventLogSessionHook({ directory }, event);
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 eventLogSessionHook({ directory }, event);
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 eventLogBeforeHook({ directory }, toolInput, toolOutput);
8304
+ await eventLog.before({ directory }, toolInput, toolOutput);
8207
8305
  },
8208
8306
  "tool.execute.after": async (toolInput, toolOutput) => {
8209
- await eventLogAfterHook({ directory }, toolInput, toolOutput);
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 to console (for agent visibility).
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;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAUvE;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;CAC3C,GACA,OAAO,CAAC,gBAAgB,CAAC,CAyH3B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAQvG"}
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,CAuBlE;AAwBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CA2D7D"}
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;AAkBtD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAqPzE"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dv.nghiem/flowdeck",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "FlowDeck — structured planning and execution workflows for OpenCode",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",