@oxgeneral/orch 0.3.3 → 0.3.4
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/App-RKAPZNZO.js +6682 -0
- package/dist/agent-KBTLGGCT.js +183 -0
- package/dist/agent-shop-YN2BSLHM.js +2 -0
- package/dist/chunk-2C2TFQ7K.js +136 -0
- package/dist/chunk-45K2XID7.js +29 -0
- package/dist/chunk-52BFUGDD.js +220 -0
- package/dist/chunk-7X2GI5OV.js +181 -0
- package/dist/{chunk-HSBYJ5C5.js → chunk-A36WAF2S.js} +89 -2
- package/dist/chunk-CHIP7O6V.js +83 -0
- package/dist/chunk-D6RFF3KN.js +85 -0
- package/dist/{chunk-BCPUTULS.js → chunk-DAVHOWGD.js} +188 -16
- package/dist/chunk-FRTKB575.js +87 -0
- package/dist/chunk-HXYAZGLP.js +15 -0
- package/dist/chunk-I3SMISEF.js +29 -0
- package/dist/chunk-K6DMQERQ.js +89 -0
- package/dist/chunk-LV6GDBBI.js +297 -0
- package/dist/chunk-P6ATSXGL.js +107 -0
- package/dist/chunk-PNE6LQRF.js +5 -0
- package/dist/chunk-U2VDNUZL.js +52 -0
- package/dist/{chunk-BGHCY7WY.js → chunk-VMDQVRBR.js} +18 -8
- package/dist/chunk-VMDQVRBR.js.map +1 -0
- package/dist/chunk-W6RSVMXR.js +66 -0
- package/dist/claude-NHUNA5RZ.js +5 -0
- package/dist/cli.js +199 -1
- package/dist/clipboard-service-RTDUUQQU.js +200 -0
- package/dist/codex-DIXT44JR.js +123 -0
- package/dist/config-OTAVSMOD.js +75 -0
- package/dist/container-LJU4QNDH.js +1594 -0
- package/dist/context-OL4BVUV5.js +83 -0
- package/dist/cursor-C3TR2IJC.js +97 -0
- package/dist/doctor-V2FPS236.js +67 -0
- package/dist/doctor-service-TPOMFAIG.js +2 -0
- package/dist/goal-FMYYN2FR.js +138 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/init-U7MCIOB2.js +165 -0
- package/dist/logs-PHPYWQ6I.js +207 -0
- package/dist/msg-FUWWLEKM.js +95 -0
- package/dist/orchestrator-ADO66XZ3.js +5 -0
- package/dist/{orchestrator-KF4UY5GD.js.map → orchestrator-ADO66XZ3.js.map} +1 -1
- package/dist/orchestrator-E3FQ4SOE.js +1424 -0
- package/dist/process-manager-HUVNAPQV.js +2 -0
- package/dist/registry-PQWRVNF2.js +2 -0
- package/dist/run-N72G5V2H.js +95 -0
- package/dist/shell-3S4VLYEG.js +4 -0
- package/dist/{shell-UXJNTNBC.js → shell-JXOPKDXH.js} +3 -3
- package/dist/shell-JXOPKDXH.js.map +1 -0
- package/dist/shop-picker-2HY67UWP.js +79 -0
- package/dist/status-RZWN2C6C.js +56 -0
- package/dist/task-2TJW6Z7O.js +221 -0
- package/dist/team-PFLP4PPL.js +97 -0
- package/dist/template-engine-4IZKRRHG.js +3 -0
- package/dist/tui-IM3YUUVD.js +245 -0
- package/dist/update-YLP7FPNY.js +64 -0
- package/dist/update-check-4YKLGBFB.js +2 -0
- package/dist/workspace-manager-JM6U7JOH.js +215 -0
- package/package.json +1 -1
- package/readme.md +9 -2
- package/scripts/postinstall.js +44 -2
- package/dist/App-NN7HR7UE.js +0 -20
- package/dist/agent-S4DKSX63.js +0 -9
- package/dist/agent-shop-D2RS4BZK.js +0 -2
- package/dist/chunk-3MQNQ7QW.js +0 -2
- package/dist/chunk-5AJ4LYO5.js +0 -8
- package/dist/chunk-6MJ7V6VY.js +0 -2
- package/dist/chunk-BGHCY7WY.js.map +0 -1
- package/dist/chunk-CDFA4IIQ.js +0 -2
- package/dist/chunk-CHRW4CLD.js +0 -2
- package/dist/chunk-HMMPM7MF.js +0 -3
- package/dist/chunk-HXOMNULD.js +0 -2
- package/dist/chunk-IS3YBE2B.js +0 -3
- package/dist/chunk-KPCT44WU.js +0 -2
- package/dist/chunk-L26TK7Y5.js +0 -2
- package/dist/chunk-LXNRCJ22.js +0 -2
- package/dist/chunk-OQKREZUF.js +0 -11
- package/dist/chunk-PJ5DKXGR.js +0 -2
- package/dist/chunk-QFKVCNKL.js +0 -2
- package/dist/chunk-UMZEA3JT.js +0 -5
- package/dist/claude-GQZNDJ6L.js +0 -2
- package/dist/clipboard-service-MYLSWM5E.js +0 -25
- package/dist/codex-SJV7ZZBY.js +0 -2
- package/dist/config-CCSS2P7R.js +0 -2
- package/dist/container-NEKK5W2B.js +0 -6
- package/dist/context-GSMQHQES.js +0 -7
- package/dist/cursor-4JQOCP5X.js +0 -2
- package/dist/doctor-UAII4VWN.js +0 -2
- package/dist/doctor-service-PB7YBH3F.js +0 -2
- package/dist/goal-RFKFPR7M.js +0 -8
- package/dist/init-2D4RAN7B.js +0 -53
- package/dist/logs-UXFXVYCP.js +0 -12
- package/dist/msg-4SCLBO4K.js +0 -9
- package/dist/orchestrator-KF4UY5GD.js +0 -5
- package/dist/orchestrator-MFL3XK5L.js +0 -13
- package/dist/process-manager-33H27MQF.js +0 -2
- package/dist/registry-BO2PPRNG.js +0 -2
- package/dist/run-HSHRELOP.js +0 -3
- package/dist/shell-F42UUF3U.js +0 -2
- package/dist/shell-UXJNTNBC.js.map +0 -1
- package/dist/shop-picker-LE3SKFOX.js +0 -5
- package/dist/status-DLBNWSWM.js +0 -2
- package/dist/task-AP2TIOOF.js +0 -20
- package/dist/team-MSIBKOQC.js +0 -4
- package/dist/template-engine-ONIDVD4F.js +0 -2
- package/dist/tui-PIQT4ZZ2.js +0 -2
- package/dist/update-PC2ENCKU.js +0 -2
- package/dist/update-check-HGMBDYHL.js +0 -2
- package/dist/workspace-manager-DYN3XJ7X.js +0 -3
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { DEFAULT_PROMPT_TEMPLATE } from './chunk-A36WAF2S.js';
|
|
3
|
+
import { DEFAULT_CONFIG } from './chunk-I3SMISEF.js';
|
|
4
|
+
import './chunk-PNE6LQRF.js';
|
|
5
|
+
import { printWarning, printSuccess, dim } from './chunk-7X2GI5OV.js';
|
|
6
|
+
import { Paths, pathExists, ensureDir, writeYaml, atomicWrite } from './chunk-LV6GDBBI.js';
|
|
7
|
+
import './chunk-2C2TFQ7K.js';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
|
|
11
|
+
// src/domain/default-agents.ts
|
|
12
|
+
var AGENT_CREATOR_ROLE = `Agent architect \u2014 designs and creates AI agents for the orchestrator via \`orch agent add\`.
|
|
13
|
+
|
|
14
|
+
## CREATION PROCESS
|
|
15
|
+
|
|
16
|
+
1) ANALYZE \u2014 determine: agent function, required skills, adapter, team interactions.
|
|
17
|
+
|
|
18
|
+
2) WRITE THE ROLE \u2014 this is the most important part. A good role includes:
|
|
19
|
+
- Identity and specialization (who you are)
|
|
20
|
+
- Concrete workflow (numbered steps)
|
|
21
|
+
- Which skills to invoke (\`/skill-name\`)
|
|
22
|
+
- Rules and constraints
|
|
23
|
+
Do NOT include CLI documentation or goal-mode instructions \u2014 these are already injected by the system prompt template.
|
|
24
|
+
|
|
25
|
+
3) CHOOSE CONFIGURATION:
|
|
26
|
+
- adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE)
|
|
27
|
+
- model: \`claude-opus-4-6\` (complex/architectural), \`claude-sonnet-4-6\` (fast/routine), \`claude-haiku-4-5-20251001\` (simple/templated)
|
|
28
|
+
- approval_policy: \`auto\` (no confirmation) / \`suggest\` (proposes actions) / \`manual\` (human approval)
|
|
29
|
+
- max_turns: 50 (default), up to 100 for complex tasks
|
|
30
|
+
|
|
31
|
+
4) CREATE:
|
|
32
|
+
\`orch agent add "<name>" --adapter claude --model <model> --skills "<skills>" --role "<role>" --approval-policy auto\`
|
|
33
|
+
|
|
34
|
+
## AVAILABLE SKILLS
|
|
35
|
+
|
|
36
|
+
Development: feature-dev:feature-dev, feature-dev:code-explorer, feature-dev:code-architect, feature-dev:code-reviewer, simplify, claude-api
|
|
37
|
+
Testing: testing-suite:generate-tests, testing-suite:test-coverage, testing-suite:e2e-setup, testing-suite:test-quality-analyzer
|
|
38
|
+
Frontend: frontend-design, document-skills:frontend-design
|
|
39
|
+
Documents: pdf, xlsx, docx, pptx
|
|
40
|
+
Marketing: marketing-psychology, product-manager-toolkit
|
|
41
|
+
|
|
42
|
+
## ANTI-PATTERNS
|
|
43
|
+
|
|
44
|
+
- Never create agents without skills \u2014 they cannot be auto-matched to tasks.
|
|
45
|
+
- Never write generic roles like "helper" \u2014 be specific about actions and tools.
|
|
46
|
+
- Never use opus for simple tasks \u2014 it is expensive; use sonnet or haiku.
|
|
47
|
+
- Never assign more than 3-4 skills per agent \u2014 create specialized agents instead.
|
|
48
|
+
- Never use the -e/--edit flag in automated mode \u2014 it opens an interactive editor.
|
|
49
|
+
- Always specify --role when calling \`orch agent add\`.
|
|
50
|
+
|
|
51
|
+
After creation \u2014 \`orch context set agent-<name> "<capabilities>"\`.`;
|
|
52
|
+
function getDefaultAgents() {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
id: "agt_creator",
|
|
56
|
+
name: "Agent Creator",
|
|
57
|
+
adapter: "claude",
|
|
58
|
+
role: AGENT_CREATOR_ROLE,
|
|
59
|
+
config: {
|
|
60
|
+
model: "claude-sonnet-4-6",
|
|
61
|
+
approval_policy: "suggest",
|
|
62
|
+
max_turns: 50,
|
|
63
|
+
timeout_ms: 36e5,
|
|
64
|
+
stall_timeout_ms: 3e5,
|
|
65
|
+
skills: ["document-skills:skill-creator"]
|
|
66
|
+
},
|
|
67
|
+
status: "idle",
|
|
68
|
+
stats: {
|
|
69
|
+
tasks_completed: 0,
|
|
70
|
+
tasks_failed: 0,
|
|
71
|
+
total_runs: 0,
|
|
72
|
+
total_runtime_ms: 0
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/cli/commands/init.ts
|
|
79
|
+
async function runInit(opts = {}) {
|
|
80
|
+
const projectRoot = process.cwd();
|
|
81
|
+
const paths = new Paths(projectRoot);
|
|
82
|
+
if (await pathExists(paths.root)) {
|
|
83
|
+
printWarning("Already initialized");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await Promise.all([
|
|
87
|
+
ensureDir(paths.tasksDir),
|
|
88
|
+
ensureDir(paths.agentsDir),
|
|
89
|
+
ensureDir(paths.goalsDir),
|
|
90
|
+
ensureDir(paths.runsDir),
|
|
91
|
+
ensureDir(paths.templatesDir),
|
|
92
|
+
ensureDir(paths.logsDir)
|
|
93
|
+
]);
|
|
94
|
+
const config = { ...DEFAULT_CONFIG };
|
|
95
|
+
config.project.name = opts.name ?? path.basename(projectRoot);
|
|
96
|
+
const gitignoreContent = [
|
|
97
|
+
"# Runtime state",
|
|
98
|
+
"state.json",
|
|
99
|
+
"*.lock",
|
|
100
|
+
"",
|
|
101
|
+
"# Logs and runs",
|
|
102
|
+
"runs/",
|
|
103
|
+
"logs/",
|
|
104
|
+
"",
|
|
105
|
+
"# Agent workspaces",
|
|
106
|
+
"workspaces/"
|
|
107
|
+
].join("\n") + "\n";
|
|
108
|
+
const excludeContent = [
|
|
109
|
+
".orchestry",
|
|
110
|
+
"node_modules",
|
|
111
|
+
".env",
|
|
112
|
+
".env.*",
|
|
113
|
+
"dist",
|
|
114
|
+
"build",
|
|
115
|
+
".next",
|
|
116
|
+
"__pycache__",
|
|
117
|
+
"*.pyc",
|
|
118
|
+
".venv"
|
|
119
|
+
].join("\n") + "\n";
|
|
120
|
+
const defaultAgents = getDefaultAgents();
|
|
121
|
+
await Promise.all([
|
|
122
|
+
writeYaml(paths.configPath, config),
|
|
123
|
+
atomicWrite(paths.gitignorePath, gitignoreContent),
|
|
124
|
+
atomicWrite(paths.workspaceExcludePath, excludeContent),
|
|
125
|
+
atomicWrite(paths.defaultTemplatePath(), DEFAULT_PROMPT_TEMPLATE),
|
|
126
|
+
...defaultAgents.map((agent) => writeYaml(paths.agentPath(agent.id), agent))
|
|
127
|
+
]);
|
|
128
|
+
await ensureRootGitignore(projectRoot);
|
|
129
|
+
console.log();
|
|
130
|
+
printSuccess("initialized");
|
|
131
|
+
console.log();
|
|
132
|
+
console.log(` Created ${dim(".orchestry/")}`);
|
|
133
|
+
console.log(` ${dim("\u251C\u2500\u2500")} config.yml`);
|
|
134
|
+
console.log(` ${dim("\u251C\u2500\u2500")} tasks/`);
|
|
135
|
+
console.log(` ${dim("\u251C\u2500\u2500")} agents/`);
|
|
136
|
+
for (const agent of defaultAgents) {
|
|
137
|
+
console.log(` ${dim("\u2502 \u2514\u2500\u2500")} ${agent.id}.yml ${dim(`(${agent.name})`)}`);
|
|
138
|
+
}
|
|
139
|
+
console.log(` ${dim("\u251C\u2500\u2500")} templates/default.md`);
|
|
140
|
+
console.log(` ${dim("\u2514\u2500\u2500")} .gitignore`);
|
|
141
|
+
console.log();
|
|
142
|
+
}
|
|
143
|
+
async function ensureRootGitignore(projectRoot) {
|
|
144
|
+
const gitignorePath = path.join(projectRoot, ".gitignore");
|
|
145
|
+
try {
|
|
146
|
+
const content = await fs.readFile(gitignorePath, "utf-8");
|
|
147
|
+
if (content.split("\n").some((line) => line.trim() === ".orchestry")) return;
|
|
148
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
149
|
+
await fs.appendFile(gitignorePath, `${separator}
|
|
150
|
+
# Orchestry state
|
|
151
|
+
.orchestry
|
|
152
|
+
`);
|
|
153
|
+
} catch {
|
|
154
|
+
await atomicWrite(gitignorePath, "# Orchestry state\n.orchestry\n");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function registerInitCommand(program) {
|
|
158
|
+
program.command("init").description("Initialize .orchestry/ in the current directory").option("--name <name>", "Project name").action(async (opts) => {
|
|
159
|
+
await runInit(opts);
|
|
160
|
+
console.log(` Next: ${dim('orch task add "Create backend agent" --assignee agt_creator')}`);
|
|
161
|
+
console.log();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { registerInitCommand, runInit };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { printError, dim, getIcon } from './chunk-7X2GI5OV.js';
|
|
3
|
+
import { InvalidArgumentsError } from './chunk-2C2TFQ7K.js';
|
|
4
|
+
|
|
5
|
+
// src/cli/commands/logs.ts
|
|
6
|
+
function registerLogsCommand(program, container) {
|
|
7
|
+
program.command("logs [run-id]").description("View run logs").option("--agent <agent-id>", "Filter by agent").option("--task <task-id>", "Filter by task").option("--follow", "Live stream").option("--since <duration>", "Filter by time (e.g. 5m, 1h)").action(async (runId, opts) => {
|
|
8
|
+
await container.paths.requireInit();
|
|
9
|
+
const sinceMs = opts.since ? parseDuration(opts.since) : void 0;
|
|
10
|
+
if (opts.follow) {
|
|
11
|
+
await followLive(container, { runId, taskId: opts.task, agentId: opts.agent });
|
|
12
|
+
} else if (runId) {
|
|
13
|
+
await showRunLogs(container, runId, sinceMs);
|
|
14
|
+
} else if (opts.task) {
|
|
15
|
+
await showTaskLogs(container, opts.task, sinceMs);
|
|
16
|
+
} else if (opts.agent) {
|
|
17
|
+
await showAgentLogs(container, opts.agent, sinceMs);
|
|
18
|
+
} else {
|
|
19
|
+
printError("Specify a run ID, --task, or --agent");
|
|
20
|
+
process.exit(2);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function formatEvent(event) {
|
|
25
|
+
const time = new Date(event.timestamp).toLocaleTimeString("en-US", {
|
|
26
|
+
hour12: false,
|
|
27
|
+
hour: "2-digit",
|
|
28
|
+
minute: "2-digit",
|
|
29
|
+
second: "2-digit"
|
|
30
|
+
});
|
|
31
|
+
const icon = event.type === "error" ? getIcon("failed") : getIcon("agentAction");
|
|
32
|
+
const data = typeof event.data === "string" ? event.data : JSON.stringify(event.data);
|
|
33
|
+
return ` ${dim(time)} ${icon} ${data.slice(0, 80)}`;
|
|
34
|
+
}
|
|
35
|
+
function filterBySince(events, sinceMs) {
|
|
36
|
+
if (!sinceMs) return events;
|
|
37
|
+
const cutoff = Date.now() - sinceMs;
|
|
38
|
+
return events.filter((e) => new Date(e.timestamp).getTime() >= cutoff);
|
|
39
|
+
}
|
|
40
|
+
async function showRunLogs(container, runId, sinceMs) {
|
|
41
|
+
let events = sinceMs ? filterBySince(await container.runService.readEventsTail(runId, 500), sinceMs) : await container.runService.readEventsTail(runId, 50);
|
|
42
|
+
if (container.context.json) {
|
|
43
|
+
console.log(JSON.stringify(events, null, 2));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (events.length === 0) {
|
|
47
|
+
console.log(`
|
|
48
|
+
No events for run ${runId}
|
|
49
|
+
`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.log();
|
|
53
|
+
for (const event of events) {
|
|
54
|
+
console.log(formatEvent(event));
|
|
55
|
+
}
|
|
56
|
+
console.log();
|
|
57
|
+
}
|
|
58
|
+
async function showTaskLogs(container, taskId, sinceMs) {
|
|
59
|
+
const runs = await container.runService.listForTask(taskId);
|
|
60
|
+
if (container.context.json) {
|
|
61
|
+
console.log(JSON.stringify(runs, null, 2));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (runs.length === 0) {
|
|
65
|
+
console.log(`
|
|
66
|
+
No runs for task ${taskId}
|
|
67
|
+
`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const recentRuns = sinceMs ? runs.slice(-20) : runs;
|
|
71
|
+
const eventsPerRun = await Promise.all(
|
|
72
|
+
recentRuns.map(
|
|
73
|
+
(run) => sinceMs ? container.runService.readEventsTail(run.id, 500).then((e) => filterBySince(e, sinceMs)) : container.runService.readEventsTail(run.id, 10)
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
for (let i = 0; i < recentRuns.length; i++) {
|
|
77
|
+
const run = recentRuns[i];
|
|
78
|
+
const events = eventsPerRun[i];
|
|
79
|
+
console.log(`
|
|
80
|
+
Run ${run.id} \xB7 attempt ${run.attempt} \xB7 ${run.status}`);
|
|
81
|
+
for (const event of events.slice(-10)) {
|
|
82
|
+
console.log(formatEvent(event));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
console.log();
|
|
86
|
+
}
|
|
87
|
+
async function showAgentLogs(container, agentId, sinceMs) {
|
|
88
|
+
const runs = await container.runService.listForAgent(agentId);
|
|
89
|
+
if (container.context.json) {
|
|
90
|
+
console.log(JSON.stringify(runs, null, 2));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (runs.length === 0) {
|
|
94
|
+
console.log(`
|
|
95
|
+
No runs for agent ${agentId}
|
|
96
|
+
`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const recentRuns = runs.slice(-5);
|
|
100
|
+
const eventsPerRun = await Promise.all(
|
|
101
|
+
recentRuns.map(
|
|
102
|
+
(run) => sinceMs ? container.runService.readEventsTail(run.id, 500).then((e) => filterBySince(e, sinceMs)) : container.runService.readEventsTail(run.id, 5)
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
for (let i = 0; i < recentRuns.length; i++) {
|
|
106
|
+
const run = recentRuns[i];
|
|
107
|
+
const events = eventsPerRun[i];
|
|
108
|
+
console.log(`
|
|
109
|
+
Run ${run.id} \xB7 task ${run.task_id} \xB7 ${run.status}`);
|
|
110
|
+
for (const event of events.slice(-5)) {
|
|
111
|
+
console.log(formatEvent(event));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
async function followLive(container, filter) {
|
|
117
|
+
const runIds = /* @__PURE__ */ new Set();
|
|
118
|
+
const agentIds = /* @__PURE__ */ new Set();
|
|
119
|
+
if (filter.runId) {
|
|
120
|
+
runIds.add(filter.runId);
|
|
121
|
+
}
|
|
122
|
+
if (filter.taskId) {
|
|
123
|
+
const runs = await container.runService.listForTask(filter.taskId);
|
|
124
|
+
for (const r of runs) runIds.add(r.id);
|
|
125
|
+
}
|
|
126
|
+
if (filter.agentId) {
|
|
127
|
+
agentIds.add(filter.agentId);
|
|
128
|
+
}
|
|
129
|
+
const hasFilter = runIds.size > 0 || agentIds.size > 0;
|
|
130
|
+
console.log(`
|
|
131
|
+
${dim("Following live events...")} ${dim("(Ctrl+C to stop)")}
|
|
132
|
+
`);
|
|
133
|
+
const unsub = container.eventBus.onAny((event) => {
|
|
134
|
+
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
|
|
135
|
+
hour12: false,
|
|
136
|
+
hour: "2-digit",
|
|
137
|
+
minute: "2-digit",
|
|
138
|
+
second: "2-digit"
|
|
139
|
+
});
|
|
140
|
+
if (hasFilter) {
|
|
141
|
+
if ("runId" in event && runIds.size > 0 && !runIds.has(event.runId)) return;
|
|
142
|
+
if ("agentId" in event && agentIds.size > 0) {
|
|
143
|
+
const evt = event;
|
|
144
|
+
if (!agentIds.has(evt.agentId)) return;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
switch (event.type) {
|
|
148
|
+
case "agent:output": {
|
|
149
|
+
const data = typeof event.data === "string" ? event.data.slice(0, 80) : "";
|
|
150
|
+
console.log(` ${dim(time)} ${getIcon("agentAction")} ${data}`);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "agent:file_changed":
|
|
154
|
+
console.log(` ${dim(time)} ${getIcon("agentAction")} Modified ${event.path}`);
|
|
155
|
+
break;
|
|
156
|
+
case "agent:error":
|
|
157
|
+
console.log(` ${dim(time)} ${getIcon("failed")} ${event.error}`);
|
|
158
|
+
break;
|
|
159
|
+
case "agent:started":
|
|
160
|
+
console.log(` ${dim(time)} ${getIcon("orchestratorEvent")} Started ${event.runId} (agent: ${event.agentId})`);
|
|
161
|
+
break;
|
|
162
|
+
case "agent:completed":
|
|
163
|
+
if (event.success) {
|
|
164
|
+
console.log(` ${dim(time)} ${getIcon("done")} DONE ${event.runId}`);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(` ${dim(time)} ${getIcon("failed")} FAIL ${event.runId}`);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
case "run:retry":
|
|
170
|
+
console.log(` ${dim(time)} ${getIcon("retrying")} RETRY attempt ${event.attempt} \xB7 next in ${Math.round(event.delay_ms / 1e3)}s`);
|
|
171
|
+
break;
|
|
172
|
+
case "orchestrator:stall_detected":
|
|
173
|
+
console.log(` ${dim(time)} ${getIcon("warning")} STALL ${event.runId}`);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
await new Promise((resolve) => {
|
|
178
|
+
const cleanup = () => {
|
|
179
|
+
unsub();
|
|
180
|
+
resolve();
|
|
181
|
+
};
|
|
182
|
+
process.once("SIGINT", cleanup);
|
|
183
|
+
process.once("SIGTERM", cleanup);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function parseDuration(input) {
|
|
187
|
+
const match = input.match(/^(\d+)(s|m|h|d)$/);
|
|
188
|
+
if (!match) {
|
|
189
|
+
throw new InvalidArgumentsError(`Invalid duration: "${input}". Use format: 5m, 1h, 30s, 1d`);
|
|
190
|
+
}
|
|
191
|
+
const value = parseInt(match[1], 10);
|
|
192
|
+
const unit = match[2];
|
|
193
|
+
switch (unit) {
|
|
194
|
+
case "s":
|
|
195
|
+
return value * 1e3;
|
|
196
|
+
case "m":
|
|
197
|
+
return value * 6e4;
|
|
198
|
+
case "h":
|
|
199
|
+
return value * 36e5;
|
|
200
|
+
case "d":
|
|
201
|
+
return value * 864e5;
|
|
202
|
+
default:
|
|
203
|
+
return value * 6e4;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export { registerLogsCommand };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { printSuccess, dim, formatDurationSince, printTable } from './chunk-7X2GI5OV.js';
|
|
3
|
+
|
|
4
|
+
// src/cli/commands/msg.ts
|
|
5
|
+
function registerMsgCommand(program, container) {
|
|
6
|
+
const msg = program.command("msg").description("Inter-agent messaging");
|
|
7
|
+
msg.command("send <to-agent-id> <body>").description("Send a direct message to an agent").option("-s, --subject <subject>", "Message subject").option("--from <agent-id>", "Sender agent ID (default: cli)").option("--ttl <ms>", "TTL in milliseconds").option("--reply-to <msg-id>", "Reply to a message").action(async (toAgentId, body, opts) => {
|
|
8
|
+
await container.paths.requireInit();
|
|
9
|
+
const messages = await container.messageService.send({
|
|
10
|
+
channel: "direct",
|
|
11
|
+
from_agent_id: opts.from ?? "cli",
|
|
12
|
+
to_agent_id: toAgentId,
|
|
13
|
+
subject: opts.subject ?? "",
|
|
14
|
+
body,
|
|
15
|
+
ttl_ms: opts.ttl ? parseInt(opts.ttl, 10) : void 0,
|
|
16
|
+
reply_to: opts.replyTo
|
|
17
|
+
});
|
|
18
|
+
if (container.context.json) {
|
|
19
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
20
|
+
} else if (container.context.quiet) {
|
|
21
|
+
console.log(messages[0]?.id);
|
|
22
|
+
} else {
|
|
23
|
+
printSuccess(`Message sent: ${messages[0]?.id} \u2192 ${toAgentId}`);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
msg.command("broadcast <body>").description("Broadcast a message to all agents (or team members)").option("-s, --subject <subject>", "Message subject").option("--from <agent-id>", "Sender agent ID (default: cli)").option("--team <team-id>", "Limit broadcast to team members").option("--ttl <ms>", "TTL in milliseconds").action(async (body, opts) => {
|
|
27
|
+
await container.paths.requireInit();
|
|
28
|
+
const messages = await container.messageService.send({
|
|
29
|
+
channel: "broadcast",
|
|
30
|
+
from_agent_id: opts.from ?? "cli",
|
|
31
|
+
subject: opts.subject ?? "",
|
|
32
|
+
body,
|
|
33
|
+
ttl_ms: opts.ttl ? parseInt(opts.ttl, 10) : void 0,
|
|
34
|
+
team_id: opts.team
|
|
35
|
+
});
|
|
36
|
+
if (container.context.json) {
|
|
37
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
38
|
+
} else if (container.context.quiet) {
|
|
39
|
+
console.log(messages.map((m) => m.id).join("\n"));
|
|
40
|
+
} else {
|
|
41
|
+
printSuccess(`Broadcast sent to ${messages.length} agent(s)`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
msg.command("inbox <agent-id>").description("Show pending messages for an agent").action(async (agentId) => {
|
|
45
|
+
await container.paths.requireInit();
|
|
46
|
+
const pending = await container.messageService.listPendingForAgent(agentId);
|
|
47
|
+
if (container.context.json) {
|
|
48
|
+
console.log(JSON.stringify(pending, null, 2));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (pending.length === 0) {
|
|
52
|
+
console.log(dim("\n No pending messages.\n"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log();
|
|
56
|
+
for (const m of pending) {
|
|
57
|
+
console.log(` ${dim(m.id)} from ${m.from_agent_id}${m.subject ? ` \u2014 ${m.subject}` : ""}`);
|
|
58
|
+
console.log(` ${m.body}`);
|
|
59
|
+
console.log();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
msg.command("list").description("List all messages").option("--agent <agent-id>", "Filter by agent (sent or received)").action(async (opts) => {
|
|
63
|
+
await container.paths.requireInit();
|
|
64
|
+
let messages;
|
|
65
|
+
if (opts.agent) {
|
|
66
|
+
messages = await container.messageService.listForAgent(opts.agent);
|
|
67
|
+
} else {
|
|
68
|
+
messages = await container.messageService.listAll();
|
|
69
|
+
}
|
|
70
|
+
if (container.context.json) {
|
|
71
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (messages.length === 0) {
|
|
75
|
+
console.log(dim("\n No messages.\n"));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const headers = ["ID", "FROM", "TO", "CHANNEL", "STATUS", "SENT"];
|
|
79
|
+
const rows = messages.map((m) => [
|
|
80
|
+
m.id,
|
|
81
|
+
m.from_agent_id,
|
|
82
|
+
m.to_agent_id ?? "*",
|
|
83
|
+
m.channel,
|
|
84
|
+
m.status,
|
|
85
|
+
formatDurationSince(m.created_at)
|
|
86
|
+
]);
|
|
87
|
+
console.log();
|
|
88
|
+
printTable(headers, rows);
|
|
89
|
+
console.log(`
|
|
90
|
+
${messages.length} message(s)
|
|
91
|
+
`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { registerMsgCommand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-ADO66XZ3.js"}
|