agent-worker 0.6.0 → 0.8.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.
@@ -0,0 +1,3 @@
1
+ import { C as SDK_MODEL_ALIASES, S as CURSOR_MODEL_MAP, _ as execWithIdleTimeout, a as createMockBackend, b as CLAUDE_MODEL_MAP, c as CodexBackend, d as codexAdapter, f as createStreamParser, g as IdleTimeoutError, h as formatEvent, i as MockAIBackend, l as ClaudeCodeBackend, m as extractCodexResult, n as createBackend, o as SdkBackend, p as extractClaudeResult, r as listBackends, s as CursorBackend, t as checkBackends, u as claudeAdapter, v as DEFAULT_IDLE_TIMEOUT, w as getModelForBackend, x as CODEX_MODEL_MAP, y as BACKEND_DEFAULT_MODELS } from "./backends-rQZxF7Fl.mjs";
2
+
3
+ export { listBackends };
@@ -297,6 +297,14 @@ function parseModel(model) {
297
297
  };
298
298
  }
299
299
 
300
+ //#endregion
301
+ //#region src/backends/types.ts
302
+ /**
303
+ * Default idle timeout for CLI backends (10 minutes).
304
+ * Timeout resets on any stdout activity, so this is an inactivity threshold.
305
+ */
306
+ const DEFAULT_IDLE_TIMEOUT = 6e5;
307
+
300
308
  //#endregion
301
309
  //#region src/backends/idle-timeout.ts
302
310
  /**
@@ -456,6 +464,10 @@ function formatEvent(event, backendName) {
456
464
  if (event.sessionId) details.push(`session: ${event.sessionId}`);
457
465
  return `${backendName} initialized${details.length > 0 ? ` (${details.join(", ")})` : ""}`;
458
466
  }
467
+ case "tool_call_started": {
468
+ const callIdSuffix = event.callId ? ` [${event.callId.slice(0, 8)}]` : "";
469
+ return `STARTING ${event.name}${callIdSuffix}`;
470
+ }
459
471
  case "tool_call": {
460
472
  const truncated = event.args.length > 100 ? event.args.slice(0, 100) + "..." : event.args;
461
473
  return `CALL ${event.name}(${truncated})`;
@@ -469,6 +481,10 @@ function formatEvent(event, backendName) {
469
481
  if (details.length > 0) parts.push(`(${details.join(", ")})`);
470
482
  return parts.join(" ");
471
483
  }
484
+ case "unknown": {
485
+ const preview = JSON.stringify(event.raw).slice(0, 100);
486
+ return `[DEBUG] ${backendName} unknown event type="${event.type}": ${preview}...`;
487
+ }
472
488
  }
473
489
  }
474
490
  /**
@@ -480,30 +496,28 @@ function formatEvent(event, backendName) {
480
496
  * { type: "result", duration_ms: N, total_cost_usd: N }
481
497
  */
482
498
  const claudeAdapter = (raw) => {
483
- const type = raw.type;
484
- if (type === "system" && raw.subtype === "init") return {
499
+ const event = raw;
500
+ if (event.type === "system" && event.subtype === "init") return {
485
501
  kind: "init",
486
- model: raw.model || void 0,
487
- sessionId: raw.session_id
502
+ model: event.model,
503
+ sessionId: event.session_id
488
504
  };
489
- if (type === "assistant") {
490
- const message = raw.message;
491
- if (!message?.content) return null;
492
- const toolCalls = message.content.filter((c) => c.type === "tool_use");
505
+ if (event.type === "assistant") {
506
+ const toolCalls = event.message.content.filter((c) => c.type === "tool_use");
493
507
  if (toolCalls.length > 0) {
494
508
  const tc = toolCalls[0];
495
509
  return {
496
510
  kind: "tool_call",
497
- name: tc.name || "unknown",
511
+ name: tc.name,
498
512
  args: formatToolInput(tc.input)
499
513
  };
500
514
  }
501
515
  return null;
502
516
  }
503
- if (type === "result") return {
517
+ if (event.type === "result") return {
504
518
  kind: "completed",
505
- durationMs: raw.duration_ms,
506
- costUsd: raw.total_cost_usd
519
+ durationMs: event.duration_ms,
520
+ costUsd: event.total_cost_usd
507
521
  };
508
522
  return null;
509
523
  };
@@ -531,6 +545,43 @@ function extractClaudeResult(stdout) {
531
545
  return { content: stdout.trim() };
532
546
  }
533
547
  /**
548
+ * Adapter for Cursor stream-json format.
549
+ *
550
+ * Events:
551
+ * { type: "system", subtype: "init", model: "..." }
552
+ * { type: "tool_call", subtype: "started", call_id: "...", tool_call: { shellToolCall: {...} } }
553
+ * { type: "tool_call", subtype: "completed", call_id: "..." }
554
+ * { type: "result", duration_ms: N }
555
+ */
556
+ const cursorAdapter = (raw) => {
557
+ const event = raw;
558
+ if (event.type === "system" && event.subtype === "init") return {
559
+ kind: "init",
560
+ model: event.model,
561
+ sessionId: event.session_id
562
+ };
563
+ if (event.type === "tool_call") {
564
+ if (event.subtype === "started" && event.tool_call) {
565
+ if (event.tool_call.shellToolCall) return {
566
+ kind: "tool_call_started",
567
+ name: "bash",
568
+ callId: event.call_id
569
+ };
570
+ return {
571
+ kind: "tool_call_started",
572
+ name: "tool",
573
+ callId: event.call_id
574
+ };
575
+ }
576
+ return null;
577
+ }
578
+ if (event.type === "result") return {
579
+ kind: "completed",
580
+ durationMs: event.duration_ms
581
+ };
582
+ return null;
583
+ };
584
+ /**
534
585
  * Adapter for Codex --json format.
535
586
  *
536
587
  * Events:
@@ -540,34 +591,26 @@ function extractClaudeResult(stdout) {
540
591
  * { type: "turn.completed", usage: { input_tokens, output_tokens } }
541
592
  */
542
593
  const codexAdapter = (raw) => {
543
- const type = raw.type;
544
- if (type === "thread.started") {
545
- const threadId = raw.thread_id;
546
- return {
547
- kind: "init",
548
- sessionId: threadId ? `${threadId.slice(0, 8)}...` : void 0
549
- };
550
- }
551
- if (type === "item.completed") {
552
- const item = raw.item;
553
- if (!item) return null;
554
- if (item.type === "function_call") return {
594
+ const event = raw;
595
+ if (event.type === "thread.started") return {
596
+ kind: "init",
597
+ sessionId: `${event.thread_id.slice(0, 8)}...`
598
+ };
599
+ if (event.type === "item.completed") {
600
+ if (event.item.type === "function_call") return {
555
601
  kind: "tool_call",
556
- name: item.name || "unknown",
557
- args: item.arguments ?? ""
602
+ name: event.item.name,
603
+ args: event.item.arguments
558
604
  };
559
605
  return null;
560
606
  }
561
- if (type === "turn.completed") {
562
- const usage = raw.usage;
563
- return {
564
- kind: "completed",
565
- usage: usage ? {
566
- input: usage.input_tokens ?? 0,
567
- output: usage.output_tokens ?? 0
568
- } : void 0
569
- };
570
- }
607
+ if (event.type === "turn.completed") return {
608
+ kind: "completed",
609
+ usage: {
610
+ input: event.usage.input_tokens,
611
+ output: event.usage.output_tokens
612
+ }
613
+ };
571
614
  return null;
572
615
  };
573
616
  /**
@@ -604,7 +647,13 @@ function createStreamParser(debugLog, backendName, adapter) {
604
647
  for (const line of lines) {
605
648
  if (!line.trim()) continue;
606
649
  try {
607
- const event = adapter(JSON.parse(line));
650
+ const raw = JSON.parse(line);
651
+ let event = adapter(raw);
652
+ if (!event && raw.type) event = {
653
+ kind: "unknown",
654
+ type: raw.type,
655
+ raw
656
+ };
608
657
  if (event) {
609
658
  const progress = formatEvent(event, backendName);
610
659
  if (progress) debugLog(progress);
@@ -644,7 +693,7 @@ var ClaudeCodeBackend = class {
644
693
  currentAbort;
645
694
  constructor(options = {}) {
646
695
  this.options = {
647
- timeout: 3e5,
696
+ timeout: DEFAULT_IDLE_TIMEOUT,
648
697
  ...options
649
698
  };
650
699
  }
@@ -664,7 +713,7 @@ var ClaudeCodeBackend = class {
664
713
  const cwd = this.options.workspace || this.options.cwd;
665
714
  const debugLog = this.options.debugLog;
666
715
  const outputFormat = this.options.outputFormat ?? "stream-json";
667
- const timeout = this.options.timeout ?? 3e5;
716
+ const timeout = this.options.timeout ?? DEFAULT_IDLE_TIMEOUT;
668
717
  try {
669
718
  const { promise, abort } = execWithIdleTimeoutAbortable({
670
719
  command: "claude",
@@ -769,7 +818,7 @@ var CodexBackend = class {
769
818
  options;
770
819
  constructor(options = {}) {
771
820
  this.options = {
772
- timeout: 3e5,
821
+ timeout: DEFAULT_IDLE_TIMEOUT,
773
822
  ...options
774
823
  };
775
824
  }
@@ -788,7 +837,7 @@ var CodexBackend = class {
788
837
  const args = this.buildArgs(message);
789
838
  const cwd = this.options.workspace || this.options.cwd;
790
839
  const debugLog = this.options.debugLog;
791
- const timeout = this.options.timeout ?? 3e5;
840
+ const timeout = this.options.timeout ?? DEFAULT_IDLE_TIMEOUT;
792
841
  try {
793
842
  const { stdout } = await execWithIdleTimeout({
794
843
  command: "codex",
@@ -858,7 +907,7 @@ var CursorBackend = class {
858
907
  resolvedCommand = null;
859
908
  constructor(options = {}) {
860
909
  this.options = {
861
- timeout: 3e5,
910
+ timeout: DEFAULT_IDLE_TIMEOUT,
862
911
  ...options
863
912
  };
864
913
  }
@@ -876,14 +925,14 @@ var CursorBackend = class {
876
925
  const { command, args } = await this.buildCommand(message);
877
926
  const cwd = this.options.workspace || this.options.cwd;
878
927
  const debugLog = this.options.debugLog;
879
- const timeout = this.options.timeout ?? 3e5;
928
+ const timeout = this.options.timeout ?? DEFAULT_IDLE_TIMEOUT;
880
929
  try {
881
930
  const { stdout } = await execWithIdleTimeout({
882
931
  command,
883
932
  args,
884
933
  cwd,
885
934
  timeout,
886
- onStdout: debugLog ? createStreamParser(debugLog, "Cursor", claudeAdapter) : void 0
935
+ onStdout: debugLog ? createStreamParser(debugLog, "Cursor", cursorAdapter) : void 0
887
936
  });
888
937
  return extractClaudeResult(stdout);
889
938
  } catch (error) {
@@ -1113,4 +1162,4 @@ async function listBackends() {
1113
1162
  }
1114
1163
 
1115
1164
  //#endregion
1116
- export { getModelForBackend as C, createModel as D, SUPPORTED_PROVIDERS as E, createModelAsync as O, SDK_MODEL_ALIASES as S, FRONTIER_MODELS as T, execWithIdleTimeout as _, createMockBackend as a, CODEX_MODEL_MAP as b, CodexBackend as c, codexAdapter as d, createStreamParser as f, IdleTimeoutError as g, formatEvent as h, MockAIBackend as i, getDefaultModel as k, ClaudeCodeBackend as l, extractCodexResult as m, createBackend as n, SdkBackend as o, extractClaudeResult as p, listBackends as r, CursorBackend as s, checkBackends as t, claudeAdapter as u, BACKEND_DEFAULT_MODELS as v, parseModel as w, CURSOR_MODEL_MAP as x, CLAUDE_MODEL_MAP as y };
1165
+ export { getDefaultModel as A, SDK_MODEL_ALIASES as C, SUPPORTED_PROVIDERS as D, FRONTIER_MODELS as E, createModel as O, CURSOR_MODEL_MAP as S, parseModel as T, execWithIdleTimeout as _, createMockBackend as a, CLAUDE_MODEL_MAP as b, CodexBackend as c, codexAdapter as d, createStreamParser as f, IdleTimeoutError as g, formatEvent as h, MockAIBackend as i, createModelAsync as k, ClaudeCodeBackend as l, extractCodexResult as m, createBackend as n, SdkBackend as o, extractClaudeResult as p, listBackends as r, CursorBackend as s, checkBackends as t, claudeAdapter as u, DEFAULT_IDLE_TIMEOUT as v, getModelForBackend as w, CODEX_MODEL_MAP as x, BACKEND_DEFAULT_MODELS as y };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { T as FRONTIER_MODELS, k as getDefaultModel, n as createBackend } from "../backends-BJyk6zvs.mjs";
3
- import { a as createSkillsTool, c as createFeedbackTool, l as AgentSession, o as SkillsProvider, s as FEEDBACK_PROMPT, t as SkillImporter } from "../skills-CuAfAkHU.mjs";
2
+ import { A as getDefaultModel, E as FRONTIER_MODELS, n as createBackend } from "../backends-rQZxF7Fl.mjs";
3
+ import { a as createSkillsTool, c as createFeedbackTool, l as AgentSession, o as SkillsProvider, s as FEEDBACK_PROMPT, t as SkillImporter } from "../skills-ks27oet6.mjs";
4
4
  import { jsonSchema, tool } from "ai";
5
5
  import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
6
6
  import { dirname, isAbsolute, join, relative } from "node:path";
@@ -604,6 +604,7 @@ function calculatePriority(msg) {
604
604
  const KEYS = {
605
605
  channel: "channel.jsonl",
606
606
  inboxState: "_state/inbox.json",
607
+ agentStatus: "_state/agent-status.json",
607
608
  documentPrefix: "documents/",
608
609
  resourcePrefix: "resources/"
609
610
  };
@@ -662,6 +663,7 @@ var ContextProviderImpl = class {
662
663
  };
663
664
  if (options?.to) msg.to = options.to;
664
665
  if (options?.kind) msg.kind = options.kind;
666
+ if (options?.toolCall) msg.toolCall = options.toolCall;
665
667
  const line = JSON.stringify(msg) + "\n";
666
668
  await this.storage.append(KEYS.channel, line);
667
669
  return msg;
@@ -796,6 +798,42 @@ var ContextProviderImpl = class {
796
798
  }
797
799
  return null;
798
800
  }
801
+ async loadAgentStatus() {
802
+ const raw = await this.storage.read(KEYS.agentStatus);
803
+ if (!raw) return {};
804
+ try {
805
+ return JSON.parse(raw);
806
+ } catch {
807
+ return {};
808
+ }
809
+ }
810
+ async saveAgentStatus(statuses) {
811
+ await this.storage.write(KEYS.agentStatus, JSON.stringify(statuses, null, 2));
812
+ }
813
+ async setAgentStatus(agent, status) {
814
+ const statuses = await this.loadAgentStatus();
815
+ const existing = statuses[agent] || {
816
+ state: "idle",
817
+ lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
818
+ };
819
+ statuses[agent] = {
820
+ ...existing,
821
+ ...status,
822
+ lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
823
+ };
824
+ if (status.state === "running" && existing.state !== "running") statuses[agent].startedAt = (/* @__PURE__ */ new Date()).toISOString();
825
+ if (status.state === "idle") {
826
+ statuses[agent].startedAt = void 0;
827
+ statuses[agent].task = void 0;
828
+ }
829
+ await this.saveAgentStatus(statuses);
830
+ }
831
+ async getAgentStatus(agent) {
832
+ return (await this.loadAgentStatus())[agent] || null;
833
+ }
834
+ async listAgentStatus() {
835
+ return this.loadAgentStatus();
836
+ }
799
837
  async markRunStart() {
800
838
  this.runStartIndex = (await this.syncChannel()).length;
801
839
  }
@@ -2119,7 +2157,7 @@ Examples:
2119
2157
 
2120
2158
  Note: Workflow name is inferred from YAML 'name' field or filename
2121
2159
  `).action(async (file, options) => {
2122
- const { parseWorkflowFile, runWorkflowWithControllers } = await import("../workflow-C26F4PpH.mjs");
2160
+ const { parseWorkflowFile, runWorkflowWithControllers } = await import("../workflow-B_y98Ood.mjs");
2123
2161
  const tag = options.tag || DEFAULT_TAG;
2124
2162
  const parsedWorkflow = await parseWorkflowFile(file, { tag });
2125
2163
  const workflowName = parsedWorkflow.name;
@@ -2130,8 +2168,8 @@ Note: Workflow name is inferred from YAML 'name' field or filename
2130
2168
  isCleaningUp = true;
2131
2169
  console.log("\nInterrupted, cleaning up...");
2132
2170
  if (controllers) {
2133
- const { shutdownControllers } = await import("../workflow-C26F4PpH.mjs");
2134
- const { createSilentLogger } = await import("../logger-L9AtbIPS.mjs");
2171
+ const { shutdownControllers } = await import("../workflow-B_y98Ood.mjs");
2172
+ const { createSilentLogger } = await import("../logger-C3ekEOzi.mjs");
2135
2173
  await shutdownControllers(controllers, createSilentLogger());
2136
2174
  }
2137
2175
  process.exit(130);
@@ -2144,11 +2182,13 @@ Note: Workflow name is inferred from YAML 'name' field or filename
2144
2182
  workflow: parsedWorkflow,
2145
2183
  workflowName,
2146
2184
  tag,
2185
+ workflowPath: file,
2147
2186
  instance: `${workflowName}:${tag}`,
2148
2187
  debug: options.debug,
2149
2188
  log,
2150
2189
  mode: "run",
2151
- feedback: options.feedback
2190
+ feedback: options.feedback,
2191
+ prettyDisplay: !options.debug && !options.json
2152
2192
  });
2153
2193
  controllers = result.controllers;
2154
2194
  process.off("SIGINT", cleanup);
@@ -2165,15 +2205,24 @@ Note: Workflow name is inferred from YAML 'name' field or filename
2165
2205
  document: finalDoc,
2166
2206
  feedback: result.feedback
2167
2207
  }, null, 2));
2168
- else if (finalDoc) {
2169
- console.log("\n--- Document ---");
2170
- console.log(finalDoc);
2208
+ else if (!options.debug) {
2209
+ const { showWorkflowSummary } = await import("../display-pretty-BL9H2ocr.mjs");
2210
+ showWorkflowSummary({
2211
+ duration: result.duration,
2212
+ document: finalDoc,
2213
+ feedback: result.feedback
2214
+ });
2215
+ } else {
2216
+ if (finalDoc) {
2217
+ console.log("\n--- Document ---");
2218
+ console.log(finalDoc);
2219
+ }
2220
+ if (result.feedback && result.feedback.length > 0) {
2221
+ console.log(`\n--- Feedback (${result.feedback.length}) ---`);
2222
+ for (const entry of result.feedback) console.log(` [${entry.type}] ${entry.target}: ${entry.description}`);
2223
+ }
2171
2224
  }
2172
2225
  }
2173
- if (result.feedback && result.feedback.length > 0 && !options.json) {
2174
- console.log(`\n--- Feedback (${result.feedback.length}) ---`);
2175
- for (const entry of result.feedback) console.log(` [${entry.type}] ${entry.target}: ${entry.description}`);
2176
- }
2177
2226
  } catch (error) {
2178
2227
  process.off("SIGINT", cleanup);
2179
2228
  process.off("SIGTERM", cleanup);
@@ -2189,7 +2238,7 @@ Examples:
2189
2238
 
2190
2239
  Note: Workflow name is inferred from YAML 'name' field or filename
2191
2240
  `).action(async (file, options) => {
2192
- const { parseWorkflowFile, runWorkflowWithControllers } = await import("../workflow-C26F4PpH.mjs");
2241
+ const { parseWorkflowFile, runWorkflowWithControllers } = await import("../workflow-B_y98Ood.mjs");
2193
2242
  const tag = options.tag || DEFAULT_TAG;
2194
2243
  const parsedWorkflow = await parseWorkflowFile(file, { tag });
2195
2244
  const workflowName = parsedWorkflow.name;
@@ -2384,7 +2433,7 @@ function registerInfoCommands(program) {
2384
2433
  console.log(`\nDefault: ${defaultModel} (when no model specified)`);
2385
2434
  });
2386
2435
  program.command("backends").description("Check available backends (SDK, CLI tools)").action(async () => {
2387
- const { listBackends } = await import("../backends-fLwD_6G_.mjs");
2436
+ const { listBackends } = await import("../backends-CoOMoMcP.mjs");
2388
2437
  const backends = await listBackends();
2389
2438
  console.log("Backend Status:\n");
2390
2439
  for (const backend of backends) {
@@ -2414,7 +2463,7 @@ Examples:
2414
2463
  $ agent-worker doc read @review:pr-123 # Read specific workflow:tag document
2415
2464
  `).action(async (targetInput) => {
2416
2465
  const dir = await resolveDir(targetInput);
2417
- const { createFileContextProvider } = await import("../context-DW7xrslO.mjs");
2466
+ const { createFileContextProvider } = await import("../context-dgI2YCGG.mjs");
2418
2467
  const content = await createFileContextProvider(dir, []).readDocument();
2419
2468
  console.log(content || "(empty document)");
2420
2469
  });
@@ -2432,7 +2481,7 @@ Examples:
2432
2481
  process.exit(1);
2433
2482
  }
2434
2483
  const dir = await resolveDir(targetInput);
2435
- const { createFileContextProvider } = await import("../context-DW7xrslO.mjs");
2484
+ const { createFileContextProvider } = await import("../context-dgI2YCGG.mjs");
2436
2485
  await createFileContextProvider(dir, []).writeDocument(content);
2437
2486
  console.log("Document written");
2438
2487
  });
@@ -2450,7 +2499,7 @@ Examples:
2450
2499
  process.exit(1);
2451
2500
  }
2452
2501
  const dir = await resolveDir(targetInput);
2453
- const { createFileContextProvider } = await import("../context-DW7xrslO.mjs");
2502
+ const { createFileContextProvider } = await import("../context-dgI2YCGG.mjs");
2454
2503
  await createFileContextProvider(dir, []).appendDocument(content);
2455
2504
  console.log("Content appended");
2456
2505
  });
@@ -2532,7 +2581,7 @@ Note: Requires agent to be created with --feedback flag
2532
2581
 
2533
2582
  //#endregion
2534
2583
  //#region package.json
2535
- var version = "0.6.0";
2584
+ var version = "0.8.0";
2536
2585
 
2537
2586
  //#endregion
2538
2587
  //#region src/cli/index.ts
@@ -1,4 +1,4 @@
1
1
  import { _ as shouldUseResource, a as FileStorage, c as CONTEXT_DEFAULTS, d as RESOURCE_PREFIX, f as RESOURCE_SCHEME, g as generateResourceId, h as extractMentions, i as resolveContextDir, l as MENTION_PATTERN, m as createResourceRef, n as createFileContextProvider, o as MemoryStorage, p as calculatePriority, r as getDefaultContextDir, s as ContextProviderImpl, t as FileContextProvider, u as MESSAGE_LENGTH_THRESHOLD } from "./cli/index.mjs";
2
- import { a as createMemoryContextProvider, i as MemoryContextProvider, n as formatProposal, r as formatProposalList, t as createContextMCPServer } from "./mcp-server-ONSDOpt5.mjs";
2
+ import { a as createMemoryContextProvider, i as MemoryContextProvider, n as formatProposal, r as formatProposalList, t as createContextMCPServer } from "./mcp-server-BQCQxv2v.mjs";
3
3
 
4
4
  export { createFileContextProvider };
@@ -0,0 +1,169 @@
1
+ import * as p from "@clack/prompts";
2
+ import pc from "picocolors";
3
+
4
+ //#region src/workflow/display-pretty.ts
5
+ /**
6
+ * Pretty display mode using @clack/prompts
7
+ *
8
+ * Clean, step-based CLI output:
9
+ * - Each message/event is a step
10
+ * - Uses clack's native symbols
11
+ * - Minimal decoration, maximum clarity
12
+ */
13
+ const BANNER_LINES = [
14
+ " █████╗ ██████╗ ███████╗███╗ ██╗████████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗██████╗",
15
+ "██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝██╔════╝██╔══██╗",
16
+ "███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝ █████╗ ██████╔╝",
17
+ "██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║███╗██║██║ ██║██╔══██╗██╔═██╗ ██╔══╝ ██╔══██╗",
18
+ "██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗███████╗██║ ██║",
19
+ "╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝"
20
+ ];
21
+ /**
22
+ * Apply gradient colors to banner lines
23
+ * Creates a smooth cyan gradient effect (bright → dark) using ANSI 256 colors
24
+ * Inspired by vercel-labs/skills gradient approach
25
+ */
26
+ function applyBannerGradient(lines) {
27
+ const CYAN_GRADIENT = [
28
+ "\x1B[38;5;51m",
29
+ "\x1B[38;5;45m",
30
+ "\x1B[38;5;39m",
31
+ "\x1B[38;5;33m",
32
+ "\x1B[38;5;27m",
33
+ "\x1B[38;5;21m"
34
+ ];
35
+ const RESET = "\x1B[0m";
36
+ return lines.map((line, i) => `${CYAN_GRADIENT[i]}${line}${RESET}`).join("\n");
37
+ }
38
+ const AGENT_COLORS = [
39
+ pc.cyan,
40
+ pc.yellow,
41
+ pc.magenta,
42
+ pc.green,
43
+ pc.blue
44
+ ];
45
+ function getAgentColor(name, agentNames) {
46
+ if (name === "system" || name === "user") return pc.dim;
47
+ const idx = agentNames.indexOf(name);
48
+ if (idx < 0) return AGENT_COLORS[name.split("").reduce((acc, c) => acc + c.charCodeAt(0), 0) % AGENT_COLORS.length];
49
+ return AGENT_COLORS[idx % AGENT_COLORS.length];
50
+ }
51
+ /**
52
+ * Process a channel entry for pretty display
53
+ */
54
+ function processEntry(entry, state, agentNames) {
55
+ const { kind, from, content, toolCall } = entry;
56
+ if (kind === "debug") return;
57
+ if (kind === "tool_call" && toolCall) {
58
+ const caller = from.includes(":") ? from.split(":").pop() : from;
59
+ if (caller) {
60
+ const color = getAgentColor(caller, agentNames);
61
+ const tool = pc.bold(pc.cyan(toolCall.name));
62
+ const args = toolCall.args ? pc.dim(`(${toolCall.args})`) : pc.dim("()");
63
+ p.log.message(`${color(caller)} called ${tool}${args}`, { symbol: pc.cyan("▶") });
64
+ } else p.log.message(`called ${pc.cyan(pc.bold(toolCall.name))}${pc.dim(`(${toolCall.args || ""})`)}`, { symbol: pc.cyan("▶") });
65
+ return;
66
+ }
67
+ if (kind === "log") {
68
+ if (content.includes("Running workflow:")) {
69
+ state.phase = "running";
70
+ return;
71
+ }
72
+ if (content.includes("Agents:")) return;
73
+ if (content.includes("Starting agents")) {
74
+ if (state.spinner) {
75
+ const agentList = agentNames.join(", ");
76
+ state.spinner.stop(`Initialized: ${pc.dim(agentList)}`);
77
+ }
78
+ state.spinner = p.spinner();
79
+ state.spinner.start("Starting agents");
80
+ } else if (content.includes("Workflow complete")) {
81
+ if (state.spinner) {
82
+ state.spinner.stop();
83
+ state.spinner = null;
84
+ }
85
+ const match = content.match(/\(([0-9.]+)s\)/);
86
+ if (match) p.log.success(`Completed in ${pc.bold(match[1])}s`);
87
+ else p.log.success("Workflow complete");
88
+ state.phase = "complete";
89
+ } else if (content.startsWith("[ERROR]")) {
90
+ if (state.spinner) {
91
+ state.spinner.stop();
92
+ state.spinner = null;
93
+ }
94
+ p.log.error(content.replace("[ERROR] ", ""));
95
+ state.phase = "error";
96
+ } else if (content.startsWith("[WARN]")) p.log.warn(content.replace("[WARN] ", ""));
97
+ else if (content.match(/Inbox: \d+ message/)) p.log.step(pc.dim(content));
98
+ else if (content.match(/Running \(attempt/)) p.log.step(pc.dim(content));
99
+ else if (content.startsWith("DONE")) {
100
+ const details = content.replace("DONE ", "");
101
+ p.log.info(pc.green("✓") + " " + pc.dim(details));
102
+ }
103
+ return;
104
+ }
105
+ const color = getAgentColor(from, agentNames);
106
+ if (state.spinner && state.phase === "running" && !state.hasShownAgentsStarted) {
107
+ state.spinner.stop();
108
+ state.spinner = null;
109
+ p.log.info("Agents ready and processing");
110
+ state.hasShownAgentsStarted = true;
111
+ }
112
+ p.note(content.trim(), color(from));
113
+ }
114
+ /**
115
+ * Start pretty display watcher
116
+ */
117
+ function startPrettyDisplay(config) {
118
+ const { contextProvider, agentNames, workflowName, tag, workflowPath, pollInterval = 500, initialCursor = 0 } = config;
119
+ const state = {
120
+ spinner: null,
121
+ phase: "init",
122
+ hasShownAgentsStarted: false
123
+ };
124
+ console.log("\n" + applyBannerGradient(BANNER_LINES));
125
+ console.log("");
126
+ const introText = ` ${workflowName}${tag === "main" ? "" : `:${tag}`}${workflowPath ? ` ${pc.dim(`(${workflowPath})`)}` : ""} `;
127
+ p.intro(pc.bgCyan(pc.black(introText)));
128
+ state.spinner = p.spinner();
129
+ const agentCount = agentNames.length;
130
+ const agentWord = agentCount === 1 ? "agent" : "agents";
131
+ state.spinner.start(`Initializing ${agentCount} ${agentWord}`);
132
+ let cursor = initialCursor;
133
+ let running = true;
134
+ const poll = async () => {
135
+ while (running) {
136
+ try {
137
+ const tail = await contextProvider.tailChannel(cursor);
138
+ for (const entry of tail.entries) processEntry(entry, state, agentNames);
139
+ cursor = tail.cursor;
140
+ } catch (error) {
141
+ console.error("Display polling error:", error instanceof Error ? error.message : error);
142
+ }
143
+ await sleep(pollInterval);
144
+ }
145
+ };
146
+ poll();
147
+ return { stop: () => {
148
+ running = false;
149
+ if (state.spinner) state.spinner.stop("Stopped");
150
+ } };
151
+ }
152
+ /**
153
+ * Show workflow completion summary
154
+ */
155
+ function showWorkflowSummary(options) {
156
+ const { document, feedback } = options;
157
+ if (document && document.trim()) p.note(document, "Document");
158
+ if (feedback && feedback.length > 0) {
159
+ const feedbackLines = feedback.map((f) => `[${f.type}] ${f.target}: ${f.description}`);
160
+ p.note(feedbackLines.join("\n"), `Feedback (${feedback.length})`);
161
+ }
162
+ p.outro("Done");
163
+ }
164
+ function sleep(ms) {
165
+ return new Promise((resolve) => setTimeout(resolve, ms));
166
+ }
167
+
168
+ //#endregion
169
+ export { showWorkflowSummary, startPrettyDisplay };
package/dist/index.d.mts CHANGED
@@ -94,7 +94,7 @@ interface SessionConfig {
94
94
  approval?: Record<string, ApprovalCheck>;
95
95
  /** Maximum tokens for response (default: 4096) */
96
96
  maxTokens?: number;
97
- /** Maximum tool call steps per turn (default: 10) */
97
+ /** Maximum tool call steps per turn (default: 200) */
98
98
  maxSteps?: number;
99
99
  }
100
100
  /**
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { D as createModel, E as SUPPORTED_PROVIDERS, O as createModelAsync, T as FRONTIER_MODELS, a as createMockBackend, c as CodexBackend, i as MockAIBackend, l as ClaudeCodeBackend, n as createBackend, o as SdkBackend, r as listBackends, s as CursorBackend, t as checkBackends } from "./backends-BJyk6zvs.mjs";
2
- import { a as createSkillsTool, c as createFeedbackTool, i as parseImportSpec, l as AgentSession, n as buildGitUrl, o as SkillsProvider, r as getSpecDisplayName, s as FEEDBACK_PROMPT, t as SkillImporter } from "./skills-CuAfAkHU.mjs";
1
+ import { D as SUPPORTED_PROVIDERS, E as FRONTIER_MODELS, O as createModel, a as createMockBackend, c as CodexBackend, i as MockAIBackend, k as createModelAsync, l as ClaudeCodeBackend, n as createBackend, o as SdkBackend, r as listBackends, s as CursorBackend, t as checkBackends } from "./backends-rQZxF7Fl.mjs";
2
+ import { a as createSkillsTool, c as createFeedbackTool, i as parseImportSpec, l as AgentSession, n as buildGitUrl, o as SkillsProvider, r as getSpecDisplayName, s as FEEDBACK_PROMPT, t as SkillImporter } from "./skills-ks27oet6.mjs";
3
3
  import { jsonSchema, tool } from "ai";
4
4
  import { createBashTool } from "bash-tool";
5
5
 
@@ -121,7 +121,7 @@ function formatProposalList(proposals) {
121
121
  * Tool Taxonomy:
122
122
  * - Channel: channel_send, channel_read (public append-only log)
123
123
  * - Team: team_members, team_doc_*, team_proposal_*, team_vote (shared workspace)
124
- * - My: my_inbox, my_inbox_ack (personal agent tools)
124
+ * - My: my_inbox, my_inbox_ack, my_status_set (personal agent tools)
125
125
  * - Resource: resource_create, resource_read (general-purpose reference mechanism)
126
126
  * - Feedback: feedback_submit (agent observations about tools/workflows, opt-in)
127
127
  */
@@ -152,17 +152,25 @@ function formatInbox(messages) {
152
152
  * - Team: team_members, team_doc_read, team_doc_write, team_doc_append,
153
153
  * team_doc_list, team_doc_create, team_proposal_create, team_vote,
154
154
  * team_proposal_status, team_proposal_cancel
155
- * - My: my_inbox, my_inbox_ack
155
+ * - My: my_inbox, my_inbox_ack, my_status_set
156
156
  * - Resource: resource_create, resource_read
157
157
  */
158
158
  function createContextMCPServer(options) {
159
159
  const { provider, validAgents, name = "workflow-context", version = "1.0.0", onMention, proposalManager, feedback: feedbackEnabled, debugLog } = options;
160
160
  const feedbackEntries = [];
161
161
  const logTool = (tool, agent, params) => {
162
- if (debugLog) debugLog(`[mcp:${agent || "anonymous"}] ${tool}(${Object.entries(params).filter(([_, v]) => v !== void 0).map(([k, v]) => {
162
+ if (!agent) return;
163
+ const paramsStr = Object.entries(params).filter(([_, v]) => v !== void 0).map(([k, v]) => {
163
164
  const val = typeof v === "string" && v.length > 50 ? v.slice(0, 50) + "..." : v;
164
165
  return `${k}=${JSON.stringify(val)}`;
165
- }).join(", ")})`);
166
+ }).join(", ");
167
+ provider.appendChannel(agent, `${tool}(${paramsStr})`, {
168
+ kind: "tool_call",
169
+ toolCall: {
170
+ name: tool,
171
+ args: paramsStr
172
+ }
173
+ }).catch(() => {});
166
174
  };
167
175
  const server = new McpServer({
168
176
  name,
@@ -268,20 +276,44 @@ function createContextMCPServer(options) {
268
276
  })
269
277
  }] };
270
278
  });
271
- server.tool("team_members", "List all agents in this workflow. Use to discover who you can @mention.", {}, async (_args, extra) => {
279
+ server.tool("my_status_set", "Update your status and current task. Call when starting or completing work.", {
280
+ task: z.string().optional().describe("Current task description (what you're working on)"),
281
+ state: z.enum(["idle", "running"]).optional().describe("Agent state (running = working, idle = available)"),
282
+ metadata: z.record(z.unknown()).optional().describe("Additional metadata (e.g., PR number, file path)")
283
+ }, async (args, extra) => {
284
+ const agent = getAgentId(extra) || "anonymous";
285
+ logTool("my_status_set", agent, args);
286
+ const status = {};
287
+ if (args.task !== void 0) status.task = args.task;
288
+ if (args.state !== void 0) status.state = args.state;
289
+ if (args.metadata !== void 0) status.metadata = args.metadata;
290
+ await provider.setAgentStatus(agent, status);
291
+ return { content: [{
292
+ type: "text",
293
+ text: JSON.stringify({
294
+ status: "updated",
295
+ agent,
296
+ ...status
297
+ })
298
+ }] };
299
+ });
300
+ server.tool("team_members", "List all agents in this workflow. Use to discover who you can @mention. Optionally includes agent status (state, current task).", { includeStatus: z.boolean().optional().describe("Include agent status information") }, async (args, extra) => {
272
301
  const currentAgent = getAgentId(extra) || "anonymous";
302
+ const includeStatus = args.includeStatus ?? false;
273
303
  const agents = validAgents.map((name) => ({
274
304
  name,
275
305
  mention: `@${name}`,
276
306
  isYou: name === currentAgent
277
307
  }));
308
+ const result = {
309
+ agents,
310
+ count: agents.length,
311
+ hint: "Use @agent in channel_send to mention other agents"
312
+ };
313
+ if (includeStatus) result.status = await provider.listAgentStatus();
278
314
  return { content: [{
279
315
  type: "text",
280
- text: JSON.stringify({
281
- agents,
282
- count: agents.length,
283
- hint: "Use @agent in channel_send to mention other agents"
284
- })
316
+ text: JSON.stringify(result)
285
317
  }] };
286
318
  });
287
319
  server.tool("team_doc_read", "Read a shared team document.", { file: z.string().optional().describe("Document file path (default: notes.md)") }, async ({ file }, extra) => {
@@ -1,4 +1,4 @@
1
- import { O as createModelAsync } from "./backends-BJyk6zvs.mjs";
1
+ import { k as createModelAsync } from "./backends-rQZxF7Fl.mjs";
2
2
  import { ToolLoopAgent, jsonSchema, stepCountIs, tool } from "ai";
3
3
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
4
4
  import { join, normalize } from "node:path";
@@ -70,7 +70,7 @@ var AgentSession = class {
70
70
  this.tools = config.tools ? { ...config.tools } : {};
71
71
  this.approval = config.approval ? { ...config.approval } : {};
72
72
  this.maxTokens = config.maxTokens ?? 4096;
73
- this.maxSteps = config.maxSteps ?? 10;
73
+ this.maxSteps = config.maxSteps ?? 200;
74
74
  this.backend = config.backend ?? null;
75
75
  }
76
76
  /**
@@ -238,6 +238,7 @@ var AgentSession = class {
238
238
  this.totalUsage.input += usage.input;
239
239
  this.totalUsage.output += usage.output;
240
240
  this.totalUsage.total += usage.total;
241
+ if (this.maxSteps > 0 && stepNumber >= this.maxSteps && allToolCalls.length > 0) console.warn(`⚠️ Agent reached maxSteps limit (${this.maxSteps}) but wanted to continue. Consider increasing maxSteps or removing the limit.`);
241
242
  const currentPending = this.pendingApprovals.filter((p) => p.status === "pending");
242
243
  return {
243
244
  content: result.text,
@@ -1,7 +1,7 @@
1
- import { O as createModelAsync, a as createMockBackend, n as createBackend, w as parseModel } from "./backends-BJyk6zvs.mjs";
1
+ import { T as parseModel, a as createMockBackend, k as createModelAsync, n as createBackend } from "./backends-rQZxF7Fl.mjs";
2
2
  import { c as CONTEXT_DEFAULTS, i as resolveContextDir, n as createFileContextProvider, t as FileContextProvider } from "./cli/index.mjs";
3
- import { a as createMemoryContextProvider, t as createContextMCPServer } from "./mcp-server-ONSDOpt5.mjs";
4
- import { createChannelLogger, createSilentLogger } from "./logger-L9AtbIPS.mjs";
3
+ import { a as createMemoryContextProvider, t as createContextMCPServer } from "./mcp-server-BQCQxv2v.mjs";
4
+ import { createChannelLogger, createSilentLogger } from "./logger-C3ekEOzi.mjs";
5
5
  import { generateText, jsonSchema, stepCountIs, tool } from "ai";
6
6
  import { existsSync, mkdirSync, readFileSync } from "node:fs";
7
7
  import { basename, dirname, join, resolve } from "node:path";
@@ -15,9 +15,9 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
15
15
  import { MockLanguageModelV3, mockValues } from "ai/test";
16
16
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
17
17
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
18
+ import stringWidth from "string-width";
18
19
  import chalk from "chalk";
19
20
  import wrapAnsi from "wrap-ansi";
20
- import stringWidth from "string-width";
21
21
 
22
22
  //#region src/workflow/parser.ts
23
23
  /**
@@ -493,12 +493,13 @@ function buildAgentPrompt(ctx) {
493
493
  sections.push("- **channel_read**: Read recent channel messages (DMs and logs are auto-filtered).");
494
494
  sections.push("");
495
495
  sections.push("### Team Tools");
496
- sections.push("- **team_members**: List all agents you can @mention.");
496
+ sections.push("- **team_members**: List all agents you can @mention. Pass includeStatus=true to see their current state and tasks.");
497
497
  sections.push("- **team_doc_read/write/append/list/create**: Shared team documents.");
498
498
  sections.push("");
499
499
  sections.push("### Personal Tools");
500
500
  sections.push("- **my_inbox**: Check your unread messages.");
501
- sections.push("- **my_inbox_ack**: Acknowledge messages after processing (pass the latest timestamp).");
501
+ sections.push("- **my_inbox_ack**: Acknowledge messages after processing (pass the latest message ID).");
502
+ sections.push("- **my_status_set**: Update your status. Call when starting work (state='running', task='...') or when done (state='idle').");
502
503
  sections.push("");
503
504
  sections.push("### Proposal & Voting Tools");
504
505
  sections.push("- **team_proposal_create**: Create a proposal for team voting (types: election, decision, approval, assignment).");
@@ -809,13 +810,30 @@ async function runSdkAgent(ctx, debugLog) {
809
810
  system: ctx.agent.resolvedSystemPrompt,
810
811
  prompt,
811
812
  maxOutputTokens: ctx.agent.max_tokens ?? 8192,
812
- stopWhen: stepCountIs(ctx.agent.max_steps ?? 30),
813
+ stopWhen: stepCountIs(ctx.agent.max_steps ?? 200),
813
814
  onStepFinish: (step) => {
814
815
  _stepNum++;
815
- if (step.toolCalls?.length) for (const tc of step.toolCalls) log(`CALL ${formatToolCall(tc)}`);
816
+ if (step.toolCalls?.length) {
817
+ for (const tc of step.toolCalls) if (tc.toolName === "bash") {
818
+ const args = formatToolCall(tc);
819
+ ctx.provider.appendChannel(ctx.name, args, {
820
+ kind: "tool_call",
821
+ toolCall: {
822
+ name: tc.toolName,
823
+ args
824
+ }
825
+ }).catch(() => {});
826
+ }
827
+ }
816
828
  }
817
829
  });
818
830
  const totalToolCalls = result.steps.reduce((n, s) => n + s.toolCalls.length, 0);
831
+ const lastStep = result.steps[result.steps.length - 1];
832
+ if (ctx.agent.max_steps && result.steps.length >= ctx.agent.max_steps && (lastStep?.toolCalls?.length ?? 0) > 0) {
833
+ const warning = `⚠️ Agent reached max_steps limit (${ctx.agent.max_steps}) but wanted to continue. Consider increasing max_steps or removing the limit.`;
834
+ log(warning);
835
+ await ctx.provider.appendChannel(ctx.name, warning, { kind: "log" }).catch(() => {});
836
+ }
819
837
  await mcp.close();
820
838
  return {
821
839
  success: true,
@@ -884,6 +902,7 @@ function createAgentController(config) {
884
902
  const inbox = await contextProvider.getInbox(name);
885
903
  if (inbox.length === 0) {
886
904
  state = "idle";
905
+ await contextProvider.setAgentStatus(name, { state: "idle" });
887
906
  continue;
888
907
  }
889
908
  const senders = inbox.map((m) => m.entry.from);
@@ -899,6 +918,7 @@ function createAgentController(config) {
899
918
  while (attempt < retryConfig.maxAttempts && shouldContinue(state)) {
900
919
  attempt++;
901
920
  state = "running";
921
+ await contextProvider.setAgentStatus(name, { state: "running" });
902
922
  infoLog(`Running (attempt ${attempt}/${retryConfig.maxAttempts})`);
903
923
  lastResult = await runAgent(backend, {
904
924
  name,
@@ -913,12 +933,14 @@ function createAgentController(config) {
913
933
  workspaceDir,
914
934
  projectDir,
915
935
  retryAttempt: attempt,
936
+ provider: contextProvider,
916
937
  feedback
917
938
  }, log, infoLog);
918
939
  if (lastResult.success) {
919
940
  infoLog(`DONE ${lastResult.steps ? `${lastResult.steps} steps, ${lastResult.toolCalls} tool calls, ${lastResult.duration}ms` : `${lastResult.duration}ms`}`);
920
941
  if (lastResult.content) await contextProvider.appendChannel(name, lastResult.content);
921
942
  await contextProvider.ackInbox(name, latestId);
943
+ await contextProvider.setAgentStatus(name, { state: "idle" });
922
944
  break;
923
945
  }
924
946
  errorLog(`ERROR ${lastResult.error}`);
@@ -934,6 +956,7 @@ function createAgentController(config) {
934
956
  }
935
957
  if (lastResult && onRunComplete) onRunComplete(lastResult);
936
958
  state = "idle";
959
+ await contextProvider.setAgentStatus(name, { state: "idle" });
937
960
  }
938
961
  }
939
962
  return {
@@ -946,15 +969,18 @@ function createAgentController(config) {
946
969
  async start() {
947
970
  if (state !== "stopped") throw new Error(`Controller ${name} is already running`);
948
971
  state = "idle";
972
+ await contextProvider.setAgentStatus(name, { state: "idle" });
949
973
  infoLog(`Starting`);
950
974
  runLoop().catch((error) => {
951
975
  errorLog(`ERROR ${error instanceof Error ? error.message : String(error)}`);
952
976
  state = "stopped";
977
+ contextProvider.setAgentStatus(name, { state: "stopped" }).catch(() => {});
953
978
  });
954
979
  },
955
980
  async stop() {
956
981
  log(`Stopping`);
957
982
  state = "stopped";
983
+ await contextProvider.setAgentStatus(name, { state: "stopped" });
958
984
  if (backend.abort) backend.abort();
959
985
  if (pollTimeout) {
960
986
  clearTimeout(pollTimeout);
@@ -1262,46 +1288,6 @@ function formatStandardLog(entry, includeMillis = false) {
1262
1288
  //#endregion
1263
1289
  //#region src/workflow/display.ts
1264
1290
  /**
1265
- * Channel display formatting
1266
- *
1267
- * All output flows through the channel. This module formats and filters
1268
- * channel entries for terminal display:
1269
- * - kind=undefined (agent messages): always shown, colored
1270
- * - kind="log" (operational logs): always shown, dimmed
1271
- * - kind="debug" (debug details): only shown with --debug flag
1272
- *
1273
- * Two display modes:
1274
- * - TTY (human): colored, aligned columns, smart wrapping
1275
- * - Non-TTY (agent/pipe): plain text, no colors, simple separators
1276
- *
1277
- * Best practices implemented:
1278
- * - Adaptive layout based on terminal width and agent names
1279
- * - Smart text wrapping preserving ANSI colors
1280
- * - Message grouping to reduce visual noise
1281
- * - Background-agnostic color scheme
1282
- */
1283
- /** Whether to use rich terminal formatting */
1284
- const isTTY = !!process.stdout.isTTY && !process.env.NO_COLOR;
1285
- /**
1286
- * Background-agnostic color scheme
1287
- * Uses only bold and standard colors that work on any theme
1288
- */
1289
- const C = {
1290
- dim: isTTY ? chalk.dim : (s) => s,
1291
- bold: isTTY ? chalk.bold : (s) => s,
1292
- yellow: isTTY ? chalk.yellow : (s) => s,
1293
- red: isTTY ? chalk.red : (s) => s,
1294
- agents: isTTY ? [
1295
- chalk.cyan,
1296
- chalk.yellow,
1297
- chalk.magenta,
1298
- chalk.green,
1299
- chalk.blue,
1300
- chalk.redBright
1301
- ] : Array(6).fill((s) => s),
1302
- system: isTTY ? chalk.gray : (s) => s
1303
- };
1304
- /**
1305
1291
  * Create display context for a workflow
1306
1292
  */
1307
1293
  function createDisplayContext(agentNames, options) {
@@ -1570,8 +1556,7 @@ async function runWorkflowWithControllers(config) {
1570
1556
  } else logger.debug(`@mention: ${from} → @${target} (no controller found!)`);
1571
1557
  },
1572
1558
  debugLog: (msg) => {
1573
- if (msg.startsWith("CALL ")) logger.info(msg);
1574
- else logger.debug(msg);
1559
+ logger.debug(msg);
1575
1560
  },
1576
1561
  feedback: feedbackEnabled
1577
1562
  });
@@ -1586,9 +1571,9 @@ async function runWorkflowWithControllers(config) {
1586
1571
  backend: agentDef.backend,
1587
1572
  model: agentDef.model
1588
1573
  });
1574
+ const agentLogger = logger.child(agentName);
1589
1575
  const backendDebugLog = (msg) => {
1590
- if (msg.startsWith("CALL ")) logger.info(msg);
1591
- else logger.debug(msg);
1576
+ agentLogger.debug(msg);
1592
1577
  };
1593
1578
  let backend;
1594
1579
  if (createBackend) backend = createBackend(agentName, agentDef);
@@ -1624,7 +1609,19 @@ async function runWorkflowWithControllers(config) {
1624
1609
  logger.debug("Sending kickoff message...");
1625
1610
  await runtime.sendKickoff();
1626
1611
  logger.debug("Kickoff sent");
1627
- const channelWatcher = startChannelWatcher({
1612
+ let channelWatcher;
1613
+ if (config.prettyDisplay) {
1614
+ const { startPrettyDisplay } = await import("./display-pretty-BL9H2ocr.mjs");
1615
+ channelWatcher = startPrettyDisplay({
1616
+ contextProvider: runtime.contextProvider,
1617
+ agentNames: runtime.agentNames,
1618
+ workflowName,
1619
+ tag,
1620
+ workflowPath: config.workflowPath,
1621
+ initialCursor: channelStart,
1622
+ pollInterval: 250
1623
+ });
1624
+ } else channelWatcher = startChannelWatcher({
1628
1625
  contextProvider: runtime.contextProvider,
1629
1626
  agentNames: runtime.agentNames,
1630
1627
  log,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-worker",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "SDK and CLI for creating and testing agent workers with Vercel AI SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -30,6 +30,7 @@
30
30
  "prepublishOnly": "bun run build"
31
31
  },
32
32
  "dependencies": {
33
+ "@clack/prompts": "^1.0.0",
33
34
  "@modelcontextprotocol/sdk": "^1.26.0",
34
35
  "ai": "^6.0.69",
35
36
  "bash-tool": "^1.3.12",
@@ -38,6 +39,7 @@
38
39
  "execa": "^9.6.1",
39
40
  "just-bash": "^2.8.0",
40
41
  "nanoid": "^5.1.6",
42
+ "picocolors": "^1.1.1",
41
43
  "string-width": "^8.1.1",
42
44
  "wrap-ansi": "^9.0.2",
43
45
  "yaml": "^2.7.0",
@@ -1,3 +0,0 @@
1
- import { C as getModelForBackend, S as SDK_MODEL_ALIASES, _ as execWithIdleTimeout, a as createMockBackend, b as CODEX_MODEL_MAP, c as CodexBackend, d as codexAdapter, f as createStreamParser, g as IdleTimeoutError, h as formatEvent, i as MockAIBackend, l as ClaudeCodeBackend, m as extractCodexResult, n as createBackend, o as SdkBackend, p as extractClaudeResult, r as listBackends, s as CursorBackend, t as checkBackends, u as claudeAdapter, v as BACKEND_DEFAULT_MODELS, x as CURSOR_MODEL_MAP, y as CLAUDE_MODEL_MAP } from "./backends-BJyk6zvs.mjs";
2
-
3
- export { listBackends };