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.
- package/dist/backends-CoOMoMcP.mjs +3 -0
- package/dist/{backends-BJyk6zvs.mjs → backends-rQZxF7Fl.mjs} +94 -45
- package/dist/cli/index.mjs +68 -19
- package/dist/{context-DW7xrslO.mjs → context-dgI2YCGG.mjs} +1 -1
- package/dist/display-pretty-BL9H2ocr.mjs +169 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{mcp-server-ONSDOpt5.mjs → mcp-server-BQCQxv2v.mjs} +42 -10
- package/dist/{skills-CuAfAkHU.mjs → skills-ks27oet6.mjs} +3 -2
- package/dist/{workflow-C26F4PpH.mjs → workflow-B_y98Ood.mjs} +50 -53
- package/package.json +3 -1
- package/dist/backends-fLwD_6G_.mjs +0 -3
- /package/dist/{logger-L9AtbIPS.mjs → logger-C3ekEOzi.mjs} +0 -0
|
@@ -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
|
|
484
|
-
if (type === "system" &&
|
|
499
|
+
const event = raw;
|
|
500
|
+
if (event.type === "system" && event.subtype === "init") return {
|
|
485
501
|
kind: "init",
|
|
486
|
-
model:
|
|
487
|
-
sessionId:
|
|
502
|
+
model: event.model,
|
|
503
|
+
sessionId: event.session_id
|
|
488
504
|
};
|
|
489
|
-
if (type === "assistant") {
|
|
490
|
-
const
|
|
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
|
|
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:
|
|
506
|
-
costUsd:
|
|
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
|
|
544
|
-
if (type === "thread.started") {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
|
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
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
|
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:
|
|
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 ??
|
|
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:
|
|
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 ??
|
|
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:
|
|
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 ??
|
|
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",
|
|
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 {
|
|
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 };
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { a as createSkillsTool, c as createFeedbackTool, l as AgentSession, o as SkillsProvider, s as FEEDBACK_PROMPT, t as SkillImporter } from "../skills-
|
|
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-
|
|
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-
|
|
2134
|
-
const { createSilentLogger } = await import("../logger-
|
|
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 (
|
|
2169
|
-
|
|
2170
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
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-
|
|
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:
|
|
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
|
|
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-
|
|
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 (
|
|
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("
|
|
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 {
|
|
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 ??
|
|
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 {
|
|
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-
|
|
4
|
-
import { createChannelLogger, createSilentLogger } from "./logger-
|
|
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
|
|
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 ??
|
|
813
|
+
stopWhen: stepCountIs(ctx.agent.max_steps ?? 200),
|
|
813
814
|
onStepFinish: (step) => {
|
|
814
815
|
_stepNum++;
|
|
815
|
-
if (step.toolCalls?.length)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 };
|
|
File without changes
|