@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.
Files changed (108) hide show
  1. package/dist/App-RKAPZNZO.js +6682 -0
  2. package/dist/agent-KBTLGGCT.js +183 -0
  3. package/dist/agent-shop-YN2BSLHM.js +2 -0
  4. package/dist/chunk-2C2TFQ7K.js +136 -0
  5. package/dist/chunk-45K2XID7.js +29 -0
  6. package/dist/chunk-52BFUGDD.js +220 -0
  7. package/dist/chunk-7X2GI5OV.js +181 -0
  8. package/dist/{chunk-HSBYJ5C5.js → chunk-A36WAF2S.js} +89 -2
  9. package/dist/chunk-CHIP7O6V.js +83 -0
  10. package/dist/chunk-D6RFF3KN.js +85 -0
  11. package/dist/{chunk-BCPUTULS.js → chunk-DAVHOWGD.js} +188 -16
  12. package/dist/chunk-FRTKB575.js +87 -0
  13. package/dist/chunk-HXYAZGLP.js +15 -0
  14. package/dist/chunk-I3SMISEF.js +29 -0
  15. package/dist/chunk-K6DMQERQ.js +89 -0
  16. package/dist/chunk-LV6GDBBI.js +297 -0
  17. package/dist/chunk-P6ATSXGL.js +107 -0
  18. package/dist/chunk-PNE6LQRF.js +5 -0
  19. package/dist/chunk-U2VDNUZL.js +52 -0
  20. package/dist/{chunk-BGHCY7WY.js → chunk-VMDQVRBR.js} +18 -8
  21. package/dist/chunk-VMDQVRBR.js.map +1 -0
  22. package/dist/chunk-W6RSVMXR.js +66 -0
  23. package/dist/claude-NHUNA5RZ.js +5 -0
  24. package/dist/cli.js +199 -1
  25. package/dist/clipboard-service-RTDUUQQU.js +200 -0
  26. package/dist/codex-DIXT44JR.js +123 -0
  27. package/dist/config-OTAVSMOD.js +75 -0
  28. package/dist/container-LJU4QNDH.js +1594 -0
  29. package/dist/context-OL4BVUV5.js +83 -0
  30. package/dist/cursor-C3TR2IJC.js +97 -0
  31. package/dist/doctor-V2FPS236.js +67 -0
  32. package/dist/doctor-service-TPOMFAIG.js +2 -0
  33. package/dist/goal-FMYYN2FR.js +138 -0
  34. package/dist/index.d.ts +12 -1
  35. package/dist/index.js +14 -7
  36. package/dist/index.js.map +1 -1
  37. package/dist/init-U7MCIOB2.js +165 -0
  38. package/dist/logs-PHPYWQ6I.js +207 -0
  39. package/dist/msg-FUWWLEKM.js +95 -0
  40. package/dist/orchestrator-ADO66XZ3.js +5 -0
  41. package/dist/{orchestrator-KF4UY5GD.js.map → orchestrator-ADO66XZ3.js.map} +1 -1
  42. package/dist/orchestrator-E3FQ4SOE.js +1424 -0
  43. package/dist/process-manager-HUVNAPQV.js +2 -0
  44. package/dist/registry-PQWRVNF2.js +2 -0
  45. package/dist/run-N72G5V2H.js +95 -0
  46. package/dist/shell-3S4VLYEG.js +4 -0
  47. package/dist/{shell-UXJNTNBC.js → shell-JXOPKDXH.js} +3 -3
  48. package/dist/shell-JXOPKDXH.js.map +1 -0
  49. package/dist/shop-picker-2HY67UWP.js +79 -0
  50. package/dist/status-RZWN2C6C.js +56 -0
  51. package/dist/task-2TJW6Z7O.js +221 -0
  52. package/dist/team-PFLP4PPL.js +97 -0
  53. package/dist/template-engine-4IZKRRHG.js +3 -0
  54. package/dist/tui-IM3YUUVD.js +245 -0
  55. package/dist/update-YLP7FPNY.js +64 -0
  56. package/dist/update-check-4YKLGBFB.js +2 -0
  57. package/dist/workspace-manager-JM6U7JOH.js +215 -0
  58. package/package.json +1 -1
  59. package/readme.md +9 -2
  60. package/scripts/postinstall.js +44 -2
  61. package/dist/App-NN7HR7UE.js +0 -20
  62. package/dist/agent-S4DKSX63.js +0 -9
  63. package/dist/agent-shop-D2RS4BZK.js +0 -2
  64. package/dist/chunk-3MQNQ7QW.js +0 -2
  65. package/dist/chunk-5AJ4LYO5.js +0 -8
  66. package/dist/chunk-6MJ7V6VY.js +0 -2
  67. package/dist/chunk-BGHCY7WY.js.map +0 -1
  68. package/dist/chunk-CDFA4IIQ.js +0 -2
  69. package/dist/chunk-CHRW4CLD.js +0 -2
  70. package/dist/chunk-HMMPM7MF.js +0 -3
  71. package/dist/chunk-HXOMNULD.js +0 -2
  72. package/dist/chunk-IS3YBE2B.js +0 -3
  73. package/dist/chunk-KPCT44WU.js +0 -2
  74. package/dist/chunk-L26TK7Y5.js +0 -2
  75. package/dist/chunk-LXNRCJ22.js +0 -2
  76. package/dist/chunk-OQKREZUF.js +0 -11
  77. package/dist/chunk-PJ5DKXGR.js +0 -2
  78. package/dist/chunk-QFKVCNKL.js +0 -2
  79. package/dist/chunk-UMZEA3JT.js +0 -5
  80. package/dist/claude-GQZNDJ6L.js +0 -2
  81. package/dist/clipboard-service-MYLSWM5E.js +0 -25
  82. package/dist/codex-SJV7ZZBY.js +0 -2
  83. package/dist/config-CCSS2P7R.js +0 -2
  84. package/dist/container-NEKK5W2B.js +0 -6
  85. package/dist/context-GSMQHQES.js +0 -7
  86. package/dist/cursor-4JQOCP5X.js +0 -2
  87. package/dist/doctor-UAII4VWN.js +0 -2
  88. package/dist/doctor-service-PB7YBH3F.js +0 -2
  89. package/dist/goal-RFKFPR7M.js +0 -8
  90. package/dist/init-2D4RAN7B.js +0 -53
  91. package/dist/logs-UXFXVYCP.js +0 -12
  92. package/dist/msg-4SCLBO4K.js +0 -9
  93. package/dist/orchestrator-KF4UY5GD.js +0 -5
  94. package/dist/orchestrator-MFL3XK5L.js +0 -13
  95. package/dist/process-manager-33H27MQF.js +0 -2
  96. package/dist/registry-BO2PPRNG.js +0 -2
  97. package/dist/run-HSHRELOP.js +0 -3
  98. package/dist/shell-F42UUF3U.js +0 -2
  99. package/dist/shell-UXJNTNBC.js.map +0 -1
  100. package/dist/shop-picker-LE3SKFOX.js +0 -5
  101. package/dist/status-DLBNWSWM.js +0 -2
  102. package/dist/task-AP2TIOOF.js +0 -20
  103. package/dist/team-MSIBKOQC.js +0 -4
  104. package/dist/template-engine-ONIDVD4F.js +0 -2
  105. package/dist/tui-PIQT4ZZ2.js +0 -2
  106. package/dist/update-PC2ENCKU.js +0 -2
  107. package/dist/update-check-HGMBDYHL.js +0 -2
  108. package/dist/workspace-manager-DYN3XJ7X.js +0 -3
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env node
2
+ import { NotInitializedError } from './chunk-2C2TFQ7K.js';
3
+ import { randomBytes } from 'crypto';
4
+ import fs from 'fs/promises';
5
+ import path2 from 'path';
6
+ import yaml from 'js-yaml';
7
+ import { accessSync } from 'fs';
8
+
9
+ async function atomicWrite(filePath, content) {
10
+ const dir = path2.dirname(filePath);
11
+ await ensureDir(dir);
12
+ const tmpPath = path2.join(dir, `.${path2.basename(filePath)}.${randomBytes(4).toString("hex")}.tmp`);
13
+ try {
14
+ await fs.writeFile(tmpPath, content, "utf-8");
15
+ await fs.rename(tmpPath, filePath);
16
+ } catch (err) {
17
+ await fs.unlink(tmpPath).catch(() => {
18
+ });
19
+ throw err;
20
+ }
21
+ }
22
+ async function readYaml(filePath) {
23
+ try {
24
+ const content = await fs.readFile(filePath, "utf-8");
25
+ return yaml.load(content);
26
+ } catch (err) {
27
+ if (isENOENT(err)) return null;
28
+ throw err;
29
+ }
30
+ }
31
+ async function writeYaml(filePath, data) {
32
+ const content = yaml.dump(data, {
33
+ indent: 2,
34
+ lineWidth: 120,
35
+ noRefs: true,
36
+ sortKeys: false
37
+ });
38
+ await atomicWrite(filePath, content);
39
+ }
40
+ async function readJson(filePath) {
41
+ try {
42
+ const content = await fs.readFile(filePath, "utf-8");
43
+ return JSON.parse(content);
44
+ } catch (err) {
45
+ if (isENOENT(err)) return null;
46
+ throw err;
47
+ }
48
+ }
49
+ async function writeJson(filePath, data) {
50
+ const content = JSON.stringify(data, null, 2) + "\n";
51
+ await atomicWrite(filePath, content);
52
+ }
53
+ var PIPE_BUF = 4096;
54
+ async function appendJsonl(filePath, record) {
55
+ const dir = path2.dirname(filePath);
56
+ await ensureDir(dir);
57
+ let line = JSON.stringify(record) + "\n";
58
+ const byteLen = Buffer.byteLength(line, "utf-8");
59
+ if (byteLen > PIPE_BUF && record !== null && typeof record === "object") {
60
+ const obj = record;
61
+ if (typeof obj.data === "string" && obj.data.length > 0) {
62
+ const shell = JSON.stringify({ ...obj, data: "" }) + "\n";
63
+ const overhead = Buffer.byteLength(shell, "utf-8");
64
+ const budget = PIPE_BUF - overhead - 3;
65
+ if (budget > 0) {
66
+ const truncated = obj.data.slice(0, budget);
67
+ line = JSON.stringify({ ...obj, data: truncated + "\u2026" }) + "\n";
68
+ }
69
+ }
70
+ }
71
+ const fd = await fs.open(filePath, "a");
72
+ try {
73
+ await fd.write(line, null, "utf-8");
74
+ } finally {
75
+ await fd.close();
76
+ }
77
+ }
78
+ var MAX_JSONL_READ_SIZE = 50 * 1024 * 1024;
79
+ async function readJsonl(filePath) {
80
+ try {
81
+ const stat = await fs.stat(filePath);
82
+ if (stat.size > MAX_JSONL_READ_SIZE) {
83
+ process.stderr.write(
84
+ `[readJsonl] file too large (${(stat.size / 1024 / 1024).toFixed(1)} MB), reading tail only: ${filePath}
85
+ `
86
+ );
87
+ return readJsonlTail(filePath, 200);
88
+ }
89
+ return readAndParseJsonl(filePath);
90
+ } catch (err) {
91
+ if (isENOENT(err)) return [];
92
+ throw err;
93
+ }
94
+ }
95
+ async function readJsonlTail(filePath, count) {
96
+ try {
97
+ const stat = await fs.stat(filePath);
98
+ if (stat.size < 32768) {
99
+ return (await readAndParseJsonl(filePath)).slice(-count);
100
+ }
101
+ const fd = await fs.open(filePath, "r");
102
+ try {
103
+ const chunkSize = Math.min(stat.size, stat.size > 1048576 ? 131072 : 65536);
104
+ let position = Math.max(0, stat.size - chunkSize);
105
+ let earliestReadPosition = position;
106
+ let tail = "";
107
+ for (let attempt = 0; attempt < 4 && position >= 0; attempt++) {
108
+ earliestReadPosition = position;
109
+ const readSize = Math.min(chunkSize, stat.size - position);
110
+ const buf = Buffer.alloc(readSize);
111
+ await fd.read(buf, 0, readSize, position);
112
+ tail = buf.toString("utf-8") + tail;
113
+ const lines2 = tail.split("\n").filter((l) => l.trim().length > 0);
114
+ if (lines2.length >= count + 1) {
115
+ return parseJsonlLines(lines2.slice(-count));
116
+ }
117
+ if (position === 0) break;
118
+ position = Math.max(0, position - chunkSize);
119
+ }
120
+ const lines = tail.split("\n").filter((l) => l.trim().length > 0);
121
+ const safeLines = earliestReadPosition > 0 ? lines.slice(1) : lines;
122
+ return parseJsonlLines(safeLines.slice(-count));
123
+ } finally {
124
+ await fd.close();
125
+ }
126
+ } catch (err) {
127
+ if (isENOENT(err)) return [];
128
+ throw err;
129
+ }
130
+ }
131
+ async function readAndParseJsonl(filePath) {
132
+ const content = await fs.readFile(filePath, "utf-8");
133
+ const lines = content.split("\n").filter((l) => l.trim().length > 0);
134
+ return parseJsonlLines(lines);
135
+ }
136
+ function parseJsonlLines(lines) {
137
+ const results = [];
138
+ for (const raw of lines) {
139
+ const line = raw.trim();
140
+ if (!line) continue;
141
+ try {
142
+ results.push(JSON.parse(line));
143
+ } catch {
144
+ process.stderr.write(`[readJsonl] skipping corrupt line: ${line.slice(0, 200)}
145
+ `);
146
+ }
147
+ }
148
+ return results;
149
+ }
150
+ async function ensureDir(dirPath) {
151
+ await fs.mkdir(dirPath, { recursive: true });
152
+ }
153
+ async function pathExists(filePath) {
154
+ try {
155
+ await fs.access(filePath);
156
+ return true;
157
+ } catch {
158
+ return false;
159
+ }
160
+ }
161
+ async function listFiles(dirPath, ext) {
162
+ try {
163
+ const entries = await fs.readdir(dirPath);
164
+ if (ext) {
165
+ return entries.filter((e) => e.endsWith(ext));
166
+ }
167
+ return entries;
168
+ } catch (err) {
169
+ if (isENOENT(err)) return [];
170
+ throw err;
171
+ }
172
+ }
173
+ function isENOENT(err) {
174
+ return err instanceof Error && "code" in err && err.code === "ENOENT";
175
+ }
176
+ var ORCHESTRY_DIR = ".orchestry";
177
+ var ID_PATTERN = /^[A-Za-z0-9._-]+$/;
178
+ var Paths = class {
179
+ constructor(projectRoot) {
180
+ this.projectRoot = projectRoot;
181
+ }
182
+ /** Root .orchestry/ directory */
183
+ get root() {
184
+ return path2.join(this.projectRoot, ORCHESTRY_DIR);
185
+ }
186
+ get configPath() {
187
+ return path2.join(this.root, "config.yml");
188
+ }
189
+ get statePath() {
190
+ return path2.join(this.root, "state.json");
191
+ }
192
+ get lockPath() {
193
+ return path2.join(this.root, "orchestry.lock");
194
+ }
195
+ get tasksDir() {
196
+ return path2.join(this.root, "tasks");
197
+ }
198
+ get agentsDir() {
199
+ return path2.join(this.root, "agents");
200
+ }
201
+ get runsDir() {
202
+ return path2.join(this.root, "runs");
203
+ }
204
+ get templatesDir() {
205
+ return path2.join(this.root, "templates");
206
+ }
207
+ get logsDir() {
208
+ return path2.join(this.root, "logs");
209
+ }
210
+ get contextDir() {
211
+ return path2.join(this.root, "context");
212
+ }
213
+ contextPath(key) {
214
+ return path2.join(this.contextDir, `${sanitizeId(key)}.json`);
215
+ }
216
+ get messagesDir() {
217
+ return path2.join(this.root, "messages");
218
+ }
219
+ messagePath(id) {
220
+ return path2.join(this.messagesDir, `${sanitizeId(id)}.json`);
221
+ }
222
+ get goalsDir() {
223
+ return path2.join(this.root, "goals");
224
+ }
225
+ goalPath(id) {
226
+ return path2.join(this.goalsDir, `${sanitizeId(id)}.yml`);
227
+ }
228
+ get teamsDir() {
229
+ return path2.join(this.root, "teams");
230
+ }
231
+ get attachmentsDir() {
232
+ return path2.join(this.root, "attachments");
233
+ }
234
+ taskAttachmentsDir(taskId) {
235
+ return path2.join(this.attachmentsDir, sanitizeId(taskId));
236
+ }
237
+ teamPath(id) {
238
+ return path2.join(this.teamsDir, `${sanitizeId(id)}.yml`);
239
+ }
240
+ get gitignorePath() {
241
+ return path2.join(this.root, ".gitignore");
242
+ }
243
+ get workspaceExcludePath() {
244
+ return path2.join(this.root, "workspace-exclude");
245
+ }
246
+ taskPath(id) {
247
+ return path2.join(this.tasksDir, `${sanitizeId(id)}.yml`);
248
+ }
249
+ agentPath(id) {
250
+ return path2.join(this.agentsDir, `${sanitizeId(id)}.yml`);
251
+ }
252
+ runPath(id) {
253
+ return path2.join(this.runsDir, `${sanitizeId(id)}.json`);
254
+ }
255
+ runEventsPath(id) {
256
+ return path2.join(this.runsDir, `${sanitizeId(id)}.jsonl`);
257
+ }
258
+ defaultTemplatePath() {
259
+ return path2.join(this.templatesDir, "default.md");
260
+ }
261
+ async isInitialized() {
262
+ return pathExists(this.root);
263
+ }
264
+ async requireInit() {
265
+ if (!await this.isInitialized()) {
266
+ throw new NotInitializedError();
267
+ }
268
+ }
269
+ };
270
+ function sanitizeId(id) {
271
+ if (!ID_PATTERN.test(id)) {
272
+ throw new Error(`Invalid identifier: "${id}"`);
273
+ }
274
+ return id;
275
+ }
276
+ function validateWorkspacePath(workspacePath, projectRoot) {
277
+ const resolved = path2.resolve(workspacePath);
278
+ const root = path2.resolve(projectRoot);
279
+ if (!resolved.startsWith(root + path2.sep) && resolved !== root) {
280
+ throw new Error(`Workspace path "${workspacePath}" is outside project root`);
281
+ }
282
+ }
283
+ function findProjectRoot(startDir = process.cwd()) {
284
+ let dir = path2.resolve(startDir);
285
+ const root = path2.parse(dir).root;
286
+ while (dir !== root) {
287
+ try {
288
+ accessSync(path2.join(dir, ".orchestry"));
289
+ return dir;
290
+ } catch {
291
+ }
292
+ dir = path2.dirname(dir);
293
+ }
294
+ return startDir;
295
+ }
296
+
297
+ export { Paths, appendJsonl, atomicWrite, ensureDir, findProjectRoot, listFiles, pathExists, readJson, readJsonl, readJsonlTail, readYaml, sanitizeId, validateWorkspacePath, writeJson, writeYaml };
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ import { mkdtemp, writeFile, readFile, unlink, rm } from 'fs/promises';
3
+ import { tmpdir } from 'os';
4
+ import { join } from 'path';
5
+ import { spawn } from 'child_process';
6
+
7
+ async function openInEditor(initialContent, opts = {}) {
8
+ const { extension = ".yml", prefix = "orch-" } = opts;
9
+ const editor = process.env["EDITOR"] || process.env["VISUAL"] || "vi";
10
+ const dir = await mkdtemp(join(tmpdir(), prefix));
11
+ const filePath = join(dir, `edit${extension}`);
12
+ await writeFile(filePath, initialContent, "utf8");
13
+ try {
14
+ const parts = editor.split(/\s+/);
15
+ const child = spawn(parts[0], [...parts.slice(1), filePath], { stdio: "inherit" });
16
+ await new Promise((resolve, reject) => {
17
+ child.on("close", (code) => {
18
+ if (code === 0) resolve();
19
+ else reject(new Error(`Editor exited with code ${code}`));
20
+ });
21
+ child.on("error", reject);
22
+ });
23
+ return await readFile(filePath, "utf8");
24
+ } finally {
25
+ await unlink(filePath).catch(() => {
26
+ });
27
+ await rm(dir, { recursive: true }).catch(() => {
28
+ });
29
+ }
30
+ }
31
+ function toEditorContent(fields) {
32
+ const lines = [
33
+ "---",
34
+ `title: ${fields.title}`,
35
+ `priority: ${fields.priority}`,
36
+ "---",
37
+ "",
38
+ fields.description ?? ""
39
+ ];
40
+ return lines.join("\n");
41
+ }
42
+ function fromEditorContent(content) {
43
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
44
+ if (!match) {
45
+ return { description: content.trim() || void 0 };
46
+ }
47
+ const frontmatter = match[1] ?? "";
48
+ const body = match[2] ?? "";
49
+ const result = {};
50
+ for (const line of frontmatter.split("\n")) {
51
+ const kv = line.match(/^([\w]+):\s*(.*)$/);
52
+ if (!kv) continue;
53
+ const key = kv[1];
54
+ const value = kv[2] ?? "";
55
+ if (key === "title" && value.trim()) {
56
+ result.title = value.trim();
57
+ } else if (key === "priority") {
58
+ const n = parseInt(value.trim(), 10);
59
+ if (n >= 1 && n <= 4) result.priority = n;
60
+ }
61
+ }
62
+ const desc = body.trim();
63
+ if (desc) result.description = desc;
64
+ return result;
65
+ }
66
+ function agentToEditorContent(fields) {
67
+ const lines = [
68
+ "# Edit agent configuration.",
69
+ "# Lines starting with # are ignored.",
70
+ "# Role description goes below the second --- separator.",
71
+ "---",
72
+ `name: ${fields.name}`,
73
+ `model: ${fields.model ?? ""}`,
74
+ "---",
75
+ "",
76
+ fields.role ?? ""
77
+ ];
78
+ return lines.join("\n");
79
+ }
80
+ function agentFromEditorContent(content) {
81
+ const lines = content.split("\n");
82
+ const firstFence = lines.findIndex((l) => l.trimEnd() === "---");
83
+ const stripped = (firstFence >= 0 ? [...lines.slice(0, firstFence).filter((l) => !l.startsWith("#")), ...lines.slice(firstFence)] : lines.filter((l) => !l.startsWith("#"))).join("\n");
84
+ const match = stripped.trimStart().match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
85
+ if (!match) {
86
+ const role = stripped.trim();
87
+ return { role: role || void 0 };
88
+ }
89
+ const frontmatter = match[1] ?? "";
90
+ const body = match[2] ?? "";
91
+ const result = {};
92
+ for (const line of frontmatter.split("\n")) {
93
+ const kv = line.match(/^([\w]+):\s*(.*)$/);
94
+ if (!kv) continue;
95
+ const key = kv[1];
96
+ const value = kv[2] ?? "";
97
+ if (key === "name") {
98
+ result.name = value.trim();
99
+ } else if (key === "model") {
100
+ result.model = value.trim();
101
+ }
102
+ }
103
+ result.role = body.trim();
104
+ return result;
105
+ }
106
+
107
+ export { agentFromEditorContent, agentToEditorContent, fromEditorContent, openInEditor, toEditorContent };
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ // src/domain/task.ts
3
+ var AUTONOMOUS_LABEL = "autonomous";
4
+
5
+ export { AUTONOMOUS_LABEL };
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ // src/domain/transitions.ts
3
+ var VALID_TRANSITIONS = {
4
+ todo: ["in_progress", "cancelled"],
5
+ in_progress: ["review", "retrying", "failed", "cancelled"],
6
+ retrying: ["in_progress", "failed", "cancelled"],
7
+ review: ["done", "todo", "cancelled"],
8
+ done: [],
9
+ failed: ["todo", "retrying"],
10
+ cancelled: ["todo"]
11
+ };
12
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["done", "failed", "cancelled"]);
13
+ function canTransition(from, to) {
14
+ return VALID_TRANSITIONS[from].includes(to);
15
+ }
16
+ function isTerminal(status) {
17
+ return TERMINAL_STATUSES.has(status);
18
+ }
19
+ function isDispatchable(status) {
20
+ return status === "todo" || status === "retrying";
21
+ }
22
+ function isBlocked(task, allTasks) {
23
+ if (task.depends_on.length === 0) return false;
24
+ if (allTasks instanceof Map) {
25
+ return task.depends_on.some((depId) => {
26
+ const dep = allTasks.get(depId);
27
+ return !dep || dep.status !== "done";
28
+ });
29
+ }
30
+ return task.depends_on.some((depId) => {
31
+ const dep = allTasks.find((t) => t.id === depId);
32
+ return !dep || dep.status !== "done";
33
+ });
34
+ }
35
+ function resolveFailureStatus(task) {
36
+ if (task.attempts < task.max_attempts) {
37
+ return "retrying";
38
+ }
39
+ return "failed";
40
+ }
41
+ function resolveCompletionStatus(task, success, _autoApprove) {
42
+ if (success) {
43
+ return "review";
44
+ }
45
+ return resolveFailureStatus(task);
46
+ }
47
+ function calculateRetryDelay(attempt, baseDelayMs, maxDelayMs) {
48
+ const delay = baseDelayMs * Math.pow(2, attempt);
49
+ return Math.min(delay, maxDelayMs);
50
+ }
51
+
52
+ export { calculateRetryDelay, canTransition, isBlocked, isDispatchable, isTerminal, resolveCompletionStatus, resolveFailureStatus };
@@ -1,5 +1,5 @@
1
1
  import { AUTONOMOUS_LABEL, DEFAULT_PROMPT_TEMPLATE, buildPromptContext } from './chunk-B4JQM4NU.js';
2
- import { LockConflictError, WorkspaceError, TaskAlreadyRunningError, NoAgentsError } from './chunk-NLQAJ7TW.js';
2
+ import { LockConflictError, WorkspaceError, TaskAlreadyRunningError, NoAgentsError, classifyAdapterError } from './chunk-NLQAJ7TW.js';
3
3
  import { dirname } from 'path';
4
4
  import fs from 'fs/promises';
5
5
  import { execFile } from 'child_process';
@@ -1007,6 +1007,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1007
1007
  await this.deps.agentService.setStatus(agent.id, "running");
1008
1008
  const agentData = await this.deps.agentService.get(agent.id);
1009
1009
  agentData.current_task = taskId;
1010
+ agentData.last_error = void 0;
1010
1011
  await this.deps.agentStore.save(agentData);
1011
1012
  const adapter = this.deps.adapterRegistry.require(agent.adapter);
1012
1013
  const abortController = new AbortController();
@@ -1062,6 +1063,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1062
1063
  let collectedTokens;
1063
1064
  let resultText;
1064
1065
  let lastAgentMessage;
1066
+ let lastErrorKind;
1065
1067
  const filesChangedSet = /* @__PURE__ */ new Set();
1066
1068
  try {
1067
1069
  for await (const event of generator) {
@@ -1120,11 +1122,13 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1120
1122
  path: typeof event.data === "string" ? event.data : String(event.data)
1121
1123
  });
1122
1124
  } else if (event.type === "error") {
1125
+ if (event.errorKind) lastErrorKind = event.errorKind;
1123
1126
  this.deps.eventBus.emit({
1124
1127
  type: "agent:error",
1125
1128
  runId,
1126
1129
  agentId,
1127
- error: busData
1130
+ error: busData,
1131
+ ...event.errorKind ? { errorKind: event.errorKind } : {}
1128
1132
  });
1129
1133
  }
1130
1134
  }
@@ -1132,9 +1136,10 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1132
1136
  await this.handleRunSuccess(taskId, runId, agentId, collectedTokens, finalResult, [...filesChangedSet]);
1133
1137
  } catch (err) {
1134
1138
  const error = err instanceof Error ? err.message : String(err);
1139
+ const errorKind = lastErrorKind ?? (err instanceof Error ? err.errorKind : void 0);
1135
1140
  const entry = this.state?.running[taskId];
1136
1141
  if (entry) {
1137
- await this.handleRunFailure(taskId, entry, error);
1142
+ await this.handleRunFailure(taskId, entry, error, errorKind);
1138
1143
  }
1139
1144
  }
1140
1145
  }
@@ -1259,10 +1264,10 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1259
1264
  await this.saveState();
1260
1265
  this.scheduleImmediateDispatch();
1261
1266
  }
1262
- async handleRunFailure(taskId, entry, error) {
1263
- return this.withStateLock(() => this._handleRunFailure(taskId, entry, error));
1267
+ async handleRunFailure(taskId, entry, error, errorKind) {
1268
+ return this.withStateLock(() => this._handleRunFailure(taskId, entry, error, errorKind));
1264
1269
  }
1265
- async _handleRunFailure(taskId, entry, error) {
1270
+ async _handleRunFailure(taskId, entry, error, errorKind) {
1266
1271
  await this.flushStateLazy();
1267
1272
  this.abortControllers.delete(taskId);
1268
1273
  const state = this.state;
@@ -1273,6 +1278,11 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1273
1278
  const agentAfterIdle = await this.deps.agentStore.get(entry.agent_id);
1274
1279
  if (agentAfterIdle) {
1275
1280
  agentAfterIdle.current_task = void 0;
1281
+ agentAfterIdle.last_error = {
1282
+ message: error.slice(0, 500),
1283
+ kind: errorKind ?? classifyAdapterError(error),
1284
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1285
+ };
1276
1286
  await this.deps.agentStore.save(agentAfterIdle);
1277
1287
  }
1278
1288
  const agent = await this.deps.agentStore.get(entry.agent_id);
@@ -1457,5 +1467,5 @@ function serializeEventData(data, maxLen) {
1457
1467
  }
1458
1468
 
1459
1469
  export { Orchestrator, canTransition, isBlocked, isDispatchable, isTerminal, resolveFailureStatus };
1460
- //# sourceMappingURL=chunk-BGHCY7WY.js.map
1461
- //# sourceMappingURL=chunk-BGHCY7WY.js.map
1470
+ //# sourceMappingURL=chunk-VMDQVRBR.js.map
1471
+ //# sourceMappingURL=chunk-VMDQVRBR.js.map