@krapht/ork 0.4.0 → 1.0.0-alpha.1
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/README.md +16 -12
- package/dist/{__build_info__-CtSVVuZE.mjs → __build_info__-D9lSlMFy.mjs} +36 -112
- package/dist/bin.mjs +688 -306
- package/dist/{clean-Dcr807be.mjs → clean-CA_Oi2Wl.mjs} +1 -1
- package/dist/completion-DBGfL-gN.mjs +405 -0
- package/dist/{context-C_bksb0C.mjs → context-6x3kXREO.mjs} +11 -88
- package/dist/decide-CoIJh34e.mjs +113 -0
- package/dist/{find-DptmbhGd.mjs → find-rBBk7Jui.mjs} +1 -1
- package/dist/{format-J-a21Yvn.mjs → format-zMmhqyLE.mjs} +71 -37
- package/dist/help-groups-BwYoAWsh.mjs +354 -0
- package/dist/{in-a-run-D1Qc5Mit.mjs → in-a-run-DdAakpRR.mjs} +1 -1
- package/dist/{limits-BDZCmGEu.mjs → limits-BPM9wUlV.mjs} +1 -1
- package/dist/{list-ZvY2OcLq.mjs → list-Bv5Lxu7z.mjs} +1 -1
- package/dist/{mcp-CHVKKg3B.mjs → mcp-DM30MFBw.mjs} +7 -7
- package/dist/{output-CXSJO00X.mjs → output-TV_j7Ni0.mjs} +67 -17
- package/dist/{pause-BPSmg4yz.mjs → pause-C7lJkSma.mjs} +4 -4
- package/dist/{relay-Do-aNbSD.mjs → relay-BipJYszF.mjs} +2 -2
- package/dist/{remove-AwaMMaHf.mjs → remove-BDs9isB6.mjs} +3 -3
- package/dist/{send-DhGBkowy.mjs → send-nbkjf3sc.mjs} +3 -3
- package/dist/{src-CpDKIulI.mjs → src-B0TT7DBi.mjs} +28 -15
- package/dist/{src-BHnxpJyH.mjs → src-B9v0lDc6.mjs} +58 -10
- package/dist/{src-UWkk1sl9.mjs → src-BxUJPGa5.mjs} +252 -18
- package/dist/{src-CGqMati3.mjs → src-hrj2h0IZ.mjs} +640 -220
- package/dist/ui/THIRD_PARTY_LICENSES.txt +2 -2
- package/dist/ui/assets/app-BNT0SuIz.css +1 -0
- package/dist/ui/assets/app-CmkynZyW.js +67 -0
- package/dist/ui/assets/{index-BiO54L90.css → index-BPIbqRRb.css} +1 -1
- package/dist/ui/assets/{index-MQNNgsyT.js → index-CPx74lFf.js} +2 -2
- package/dist/ui/index.html +2 -3
- package/dist/{ui-DhutUMgQ.mjs → ui-B98FSboa.mjs} +5 -5
- package/dist/{usage-CT7Z-yjr.mjs → usage-EW7DI6Z7.mjs} +6 -6
- package/dist/{watch-0Qr2UfCQ.mjs → watch-BAkSGaOp.mjs} +7 -7
- package/dist/workflows-vsEohqa7.mjs +88 -0
- package/dist/{worktrees-DHl80k96.mjs → worktrees-Ahj9rdWK.mjs} +5 -5
- package/package.json +3 -3
- package/dist/ui/assets/app-BgVDC_5l.js +0 -67
- package/dist/ui/assets/app-DVf68fj5.css +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createInterface } from "node:readline/promises";
|
|
1
|
+
import { $ as text, Bt as FEEDBACK_TARGETS, Q as inTransaction, Rt as FEEDBACK_KINDS, X as usageQueries, Xt as maskReplacer, Y as backfillUsage, Z as eventOf, Zt as maskSecrets, gn as PROJECT_MODES, yt as ownProcessStart, zt as FEEDBACK_SEVERITIES } from "./src-hrj2h0IZ.mjs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { mkdirSync } from "node:fs";
|
|
5
4
|
import { homedir } from "node:os";
|
|
6
5
|
import { DatabaseSync } from "node:sqlite";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import { stripVTControlCharacters, styleText } from "node:util";
|
|
8
8
|
// ../core/src/store/drafts.ts
|
|
9
9
|
const rowOf = (row) => {
|
|
@@ -49,6 +49,11 @@ const choicesOf = (json) => {
|
|
|
49
49
|
return [choice];
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
|
+
/** A note as stored: masked, or null when blank. */
|
|
53
|
+
const noteOf = (note) => {
|
|
54
|
+
const trimmed = note?.trim() ?? "";
|
|
55
|
+
return trimmed === "" ? null : maskSecrets(trimmed);
|
|
56
|
+
};
|
|
52
57
|
const kindOf = (value) => value === "permission" ? "permission" : "question";
|
|
53
58
|
const statusOf$1 = (value) => value === "answered" || value === "withdrawn" ? value : "open";
|
|
54
59
|
const decisionOf = (row) => {
|
|
@@ -66,17 +71,19 @@ const decisionOf = (row) => {
|
|
|
66
71
|
recommended: text(row, "recommended"),
|
|
67
72
|
context: text(row, "context"),
|
|
68
73
|
answer: text(row, "answer"),
|
|
69
|
-
answeredAt: text(row, "answered_at")
|
|
74
|
+
answeredAt: text(row, "answered_at"),
|
|
75
|
+
note: text(row, "note"),
|
|
76
|
+
owner: text(row, "owner")
|
|
70
77
|
};
|
|
71
78
|
for (const [key, value] of Object.entries(optional)) if (value !== "") Object.assign(record, { [key]: value });
|
|
72
79
|
const by = text(row, "answered_by");
|
|
73
|
-
if (by === "terminal" || by === "decide" || by === "ui") record.answeredBy = by;
|
|
80
|
+
if (by === "terminal" || by === "decide" || by === "ui" || by === "owner") record.answeredBy = by;
|
|
74
81
|
return record;
|
|
75
82
|
};
|
|
76
83
|
const decisionQueries = (db) => {
|
|
77
|
-
const insert = db.prepare(`INSERT INTO decisions (id, run_id, node, kind, question, options, recommended, context, opened_at, status)
|
|
78
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'open')`);
|
|
79
|
-
const answer = db.prepare(`UPDATE decisions SET status = 'answered', answer = ?, answered_by = ?, answered_at = ?
|
|
84
|
+
const insert = db.prepare(`INSERT INTO decisions (id, run_id, node, kind, question, options, recommended, context, owner, opened_at, status)
|
|
85
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'open')`);
|
|
86
|
+
const answer = db.prepare(`UPDATE decisions SET status = 'answered', answer = ?, answered_by = ?, answered_at = ?, note = ?
|
|
80
87
|
WHERE id = ? AND status = 'open'`);
|
|
81
88
|
const withdraw = db.prepare("UPDATE decisions SET status = 'withdrawn', answered_at = ? WHERE id = ? AND status = 'open'");
|
|
82
89
|
const byId = db.prepare("SELECT * FROM decisions WHERE id = ?");
|
|
@@ -97,14 +104,14 @@ const decisionQueries = (db) => {
|
|
|
97
104
|
question: maskSecrets(decision.question),
|
|
98
105
|
...decision.context === void 0 ? {} : { context: maskSecrets(decision.context) }
|
|
99
106
|
};
|
|
100
|
-
insert.run(masked.id, masked.runId, masked.node, masked.kind, masked.question, JSON.stringify(masked.options), masked.recommended ?? null, masked.context ?? null, openedAt);
|
|
107
|
+
insert.run(masked.id, masked.runId, masked.node, masked.kind, masked.question, JSON.stringify(masked.options), masked.recommended ?? null, masked.context ?? null, masked.owner ?? null, openedAt);
|
|
101
108
|
return {
|
|
102
109
|
...masked,
|
|
103
110
|
openedAt,
|
|
104
111
|
status: "open"
|
|
105
112
|
};
|
|
106
113
|
},
|
|
107
|
-
answerDecision: (id, choice, by) => Number(answer.run(choice, by, (/* @__PURE__ */ new Date()).toISOString(), id).changes) === 1,
|
|
114
|
+
answerDecision: (id, choice, by, note) => Number(answer.run(choice, by, (/* @__PURE__ */ new Date()).toISOString(), noteOf(note), id).changes) === 1,
|
|
108
115
|
withdrawDecision: (id) => {
|
|
109
116
|
withdraw.run((/* @__PURE__ */ new Date()).toISOString(), id);
|
|
110
117
|
},
|
|
@@ -720,9 +727,21 @@ const MIGRATIONS = [
|
|
|
720
727
|
);`,
|
|
721
728
|
`ALTER TABLE feedback_items ADD COLUMN merged_into TEXT;
|
|
722
729
|
CREATE INDEX feedback_items_merged ON feedback_items (merged_into);`,
|
|
723
|
-
`ALTER TABLE runs ADD COLUMN process_start TEXT
|
|
730
|
+
`ALTER TABLE runs ADD COLUMN process_start TEXT;`,
|
|
731
|
+
`ALTER TABLE runs ADD COLUMN skipped INTEGER;
|
|
732
|
+
ALTER TABLE runs ADD COLUMN failures_handled INTEGER;`,
|
|
733
|
+
`ALTER TABLE decisions ADD COLUMN note TEXT;`,
|
|
734
|
+
`ALTER TABLE decisions ADD COLUMN owner TEXT;`
|
|
724
735
|
];
|
|
725
736
|
const versionOf = (db) => Number(db.prepare("PRAGMA user_version").get()?.["user_version"] ?? 0);
|
|
737
|
+
/**
|
|
738
|
+
* Refuses a database that is not at this Ork's schema version, newer or older,
|
|
739
|
+
* for a reader that may not migrate it (a read-only open).
|
|
740
|
+
*/
|
|
741
|
+
const requireCurrent = (db, migrations = MIGRATIONS) => {
|
|
742
|
+
const version = versionOf(db);
|
|
743
|
+
if (version !== migrations.length) throw new Error(`The store is at schema version ${String(version)}; this Ork reads ${String(migrations.length)}.`);
|
|
744
|
+
};
|
|
726
745
|
/** Applies the migrations the database has not had yet. */
|
|
727
746
|
const migrate = (db, migrations = MIGRATIONS) => {
|
|
728
747
|
for (const [index, step] of migrations.entries()) {
|
|
@@ -741,7 +760,9 @@ const migrate = (db, migrations = MIGRATIONS) => {
|
|
|
741
760
|
* project, `~/.ork/state.db`, in WAL mode so other `ork` processes read while
|
|
742
761
|
* a run writes. Events are stored with secrets masked, feedback records
|
|
743
762
|
* beside them, and the registered projects; the schema is versioned with
|
|
744
|
-
* `user_version`.
|
|
763
|
+
* `user_version`. Tab completion opens it read-only: no store created, no
|
|
764
|
+
* migration, a store at another version refused, and the database never
|
|
765
|
+
* changed (SQLite may still add the `-wal` and `-shm` files beside it).
|
|
745
766
|
*/
|
|
746
767
|
/** `~/.ork/state.db`; `home` is `~` (tests pass a folder). */
|
|
747
768
|
const storePath = (home = homedir()) => path.join(home, ".ork", "state.db");
|
|
@@ -773,6 +794,10 @@ const recordOf = (row) => {
|
|
|
773
794
|
if (parent !== "") record.parent = parent;
|
|
774
795
|
const finished = text(row, "finished_at");
|
|
775
796
|
if (finished !== "") record.finishedAt = finished;
|
|
797
|
+
const skipped = row?.["skipped"];
|
|
798
|
+
if (typeof skipped === "number") record.skipped = skipped;
|
|
799
|
+
const handled = row?.["failures_handled"];
|
|
800
|
+
if (typeof handled === "number") record.failuresHandled = handled;
|
|
776
801
|
return record;
|
|
777
802
|
};
|
|
778
803
|
/** The node an event is about, for filtering. */
|
|
@@ -781,9 +806,20 @@ const nodeOf = (event) => {
|
|
|
781
806
|
if ("node" in event && typeof event.node === "string") return event.node;
|
|
782
807
|
return null;
|
|
783
808
|
};
|
|
784
|
-
/**
|
|
785
|
-
const
|
|
786
|
-
const
|
|
809
|
+
/** A database opened for reading only, refused unless it is current. */
|
|
810
|
+
const openReadOnly = (file) => {
|
|
811
|
+
const db = new DatabaseSync(file, { readOnly: true });
|
|
812
|
+
try {
|
|
813
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
814
|
+
requireCurrent(db);
|
|
815
|
+
return db;
|
|
816
|
+
} catch (error) {
|
|
817
|
+
db.close();
|
|
818
|
+
throw error;
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
/** A database opened for writing: created, in WAL mode, migrated. */
|
|
822
|
+
const openWritable = (file) => {
|
|
787
823
|
if (file !== ":memory:") mkdirSync(path.dirname(file), { recursive: true });
|
|
788
824
|
const db = new DatabaseSync(file);
|
|
789
825
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
@@ -791,18 +827,28 @@ const openStore = (file = storePath(), options = {}) => {
|
|
|
791
827
|
db.exec("PRAGMA synchronous = NORMAL");
|
|
792
828
|
db.exec("PRAGMA foreign_keys = ON");
|
|
793
829
|
migrate(db);
|
|
830
|
+
return db;
|
|
831
|
+
};
|
|
832
|
+
/**
|
|
833
|
+
* Opens (and creates) the store at `file`; `:memory:` for tests. With
|
|
834
|
+
* `readOnly`, it neither creates nor migrates, and throws when it can't read.
|
|
835
|
+
*/
|
|
836
|
+
const openStore = (file = storePath(), options = {}) => {
|
|
837
|
+
const ownStart = options.processStart ?? ownProcessStart;
|
|
838
|
+
const db = options.readOnly === true ? openReadOnly(file) : openWritable(file);
|
|
794
839
|
const insertRun = db.prepare(`INSERT INTO runs (id, workflow, file, project, status, pid, process_start, started_at, parent, depth)
|
|
795
840
|
VALUES (?, ?, ?, ?, 'running', ?, ?, ?, ?, ?)`);
|
|
796
841
|
const lastSeq = db.prepare("SELECT COALESCE(MAX(seq), 0) AS seq FROM events WHERE run_id = ?");
|
|
797
842
|
const insertEvent = db.prepare("INSERT INTO events (run_id, seq, at, type, node, data) VALUES (?, ?, ?, ?, ?, ?)");
|
|
798
|
-
const finishRun = db.prepare("UPDATE runs SET status = ?, finished_at = ?, cost_usd = ? WHERE id = ?");
|
|
799
|
-
const reopenRun = db.prepare("UPDATE runs SET status = 'running', pid = ?, process_start = ?, finished_at = NULL WHERE id = ?");
|
|
843
|
+
const finishRun = db.prepare("UPDATE runs SET status = ?, finished_at = ?, cost_usd = ?, skipped = ?, failures_handled = ? WHERE id = ?");
|
|
844
|
+
const reopenRun = db.prepare("UPDATE runs SET status = 'running', pid = ?, process_start = ?, finished_at = NULL, skipped = NULL, failures_handled = NULL WHERE id = ?");
|
|
800
845
|
const addCost = db.prepare("UPDATE runs SET cost_usd = cost_usd + ? WHERE id = ?");
|
|
801
846
|
const byId = db.prepare("SELECT * FROM runs WHERE id = ?");
|
|
802
847
|
const byPrefix = db.prepare("SELECT * FROM runs WHERE substr(id, 1, ?) = ? ORDER BY started_at DESC, rowid DESC");
|
|
803
848
|
const allRuns = db.prepare("SELECT * FROM runs ORDER BY started_at DESC, rowid DESC LIMIT ?");
|
|
804
849
|
const projectRuns = db.prepare("SELECT * FROM runs WHERE project = ? ORDER BY started_at DESC, rowid DESC LIMIT ?");
|
|
805
850
|
const eventsAfter = db.prepare("SELECT seq, at, data FROM events WHERE run_id = ? AND seq > ? ORDER BY seq");
|
|
851
|
+
const runNodes = db.prepare("SELECT node FROM events WHERE run_id = ? AND node IS NOT NULL GROUP BY node ORDER BY MIN(seq)");
|
|
806
852
|
const { insertFeedback, recordUsage, recordPlanLimit, ...queries } = storeQueries(db);
|
|
807
853
|
return {
|
|
808
854
|
...queries,
|
|
@@ -832,7 +878,10 @@ const openStore = (file = storePath(), options = {}) => {
|
|
|
832
878
|
if (event.type === "node.event" && event.event.type === "session.finished") recordUsage(runId);
|
|
833
879
|
if (event.type === "node.event" && event.event.type === "plan.limit") recordPlanLimit(event.event, at);
|
|
834
880
|
if (event.type === "feedback.recorded") insertFeedback(runId, seq, at, event.node, event.feedback);
|
|
835
|
-
if (event.type === "run.finished")
|
|
881
|
+
if (event.type === "run.finished") {
|
|
882
|
+
const { status, costUsd, skipped, failuresHandled } = event.result;
|
|
883
|
+
finishRun.run(status, at, costUsd, skipped ?? null, failuresHandled ?? null, runId);
|
|
884
|
+
}
|
|
836
885
|
return {
|
|
837
886
|
runId,
|
|
838
887
|
seq,
|
|
@@ -855,6 +904,7 @@ const openStore = (file = storePath(), options = {}) => {
|
|
|
855
904
|
at: text(r, "at"),
|
|
856
905
|
event: eventOf(text(r, "data"))
|
|
857
906
|
})),
|
|
907
|
+
nodes: (runId) => runNodes.all(runId).map((r) => text(r, "node")),
|
|
858
908
|
close: () => {
|
|
859
909
|
db.close();
|
|
860
910
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as findRun } from "./find-
|
|
3
|
-
import { a as write, c as openStore, i as style, o as writeErr } from "./output-
|
|
4
|
-
import { r as continueRefusal } from "./in-a-run-
|
|
1
|
+
import { G as requestContinue, K as requestPause } from "./src-hrj2h0IZ.mjs";
|
|
2
|
+
import { t as findRun } from "./find-rBBk7Jui.mjs";
|
|
3
|
+
import { a as write, c as openStore, i as style, o as writeErr } from "./output-TV_j7Ni0.mjs";
|
|
4
|
+
import { r as continueRefusal } from "./in-a-run-DdAakpRR.mjs";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
// src/commands/pause.ts
|
|
7
7
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as
|
|
2
|
-
import { a as write, c as openStore, i as style, o as writeErr } from "./output-
|
|
1
|
+
import { B as linkNodes, L as addressOf, U as unlinkNodes } from "./src-hrj2h0IZ.mjs";
|
|
2
|
+
import { a as write, c as openStore, i as style, o as writeErr } from "./output-TV_j7Ni0.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
// src/commands/relay.ts
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as listOrkWorktrees, t as createdWorktrees } from "./list-
|
|
3
|
-
import { i as keyOf, n as applyStep, r as cleanStep, s as stepPrunes } from "./clean-
|
|
1
|
+
import { ht as liveStatus, j as lines, k as git } from "./src-hrj2h0IZ.mjs";
|
|
2
|
+
import { n as listOrkWorktrees, t as createdWorktrees } from "./list-Bv5Lxu7z.mjs";
|
|
3
|
+
import { i as keyOf, n as applyStep, r as cleanStep, s as stepPrunes } from "./clean-CA_Oi2Wl.mjs";
|
|
4
4
|
// ../core/src/worktree/words.ts
|
|
5
5
|
/**
|
|
6
6
|
* @file The plain words for what `ork worktrees` shows, in one place, so the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as openStore, o as writeErr } from "./output-
|
|
3
|
-
import { u as inheritedScrubber } from "./src-
|
|
1
|
+
import { an as wakeRun, ht as liveStatus, kt as scriptContactsOf, rn as socketPath } from "./src-hrj2h0IZ.mjs";
|
|
2
|
+
import { c as openStore, o as writeErr } from "./output-TV_j7Ni0.mjs";
|
|
3
|
+
import { u as inheritedScrubber } from "./src-BxUJPGa5.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
// ../core/src/remote/send.ts
|
|
6
6
|
/**
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
1
|
+
import { B as linkNodes, Cn as runDirOf, Ct as walkChecks, En as inside, Fn as applyEdits, G as requestContinue, Gn as expandEdge, Hn as EdgeInputSchema, Ht as planPost, In as newWorkflowText, J as tellLiveRun, K as requestPause, Ln as readDocument, Nn as skillsIn, Nt as nodeSays, On as LESSON_CAP_TOKENS, Pn as WorkflowEditSchema, Rn as renderJsonSchema, St as checkWorkflowText, Tn as workflowDirOf, U as unlinkNodes, Ut as runGh, Vt as DISCUSSIONS, Wt as sendPost, _t as runStatus, bn as placeFiles, bt as processAlive, ct as explainWorkflowText, d as runningRunIds, f as runningScript, gt as pausedOf, hn as loadAgents, ht as liveStatus, l as planUpgrade, nt as resumable, o as limitsReport, ot as detachRun, p as detectInstaller, q as requestStop, qn as NodeSchema, r as capsHere, st as followEvents, tn as readCondition, tt as detachResume, u as releaseNotes, v as triggersReport, vt as runTree, wt as walkSummary, xn as placeFor, zn as parseWorkflow } from "./src-hrj2h0IZ.mjs";
|
|
2
|
+
import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-D9lSlMFy.mjs";
|
|
3
|
+
import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-CoIJh34e.mjs";
|
|
4
|
+
import { n as newRunId, t as findRun } from "./find-rBBk7Jui.mjs";
|
|
5
|
+
import { c as openStore, l as storePath, s as nodeOf } from "./output-TV_j7Ni0.mjs";
|
|
5
6
|
import { n as usageReport } from "./report-DK4LGqwF.mjs";
|
|
6
|
-
import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-
|
|
7
|
-
import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-
|
|
7
|
+
import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-CA_Oi2Wl.mjs";
|
|
8
|
+
import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-BDs9isB6.mjs";
|
|
8
9
|
import path from "node:path";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -350,7 +351,11 @@ const DecisionsQuerySchema = z.strictObject({
|
|
|
350
351
|
run: z.string().min(1).optional(),
|
|
351
352
|
project: z.string().min(1).optional()
|
|
352
353
|
});
|
|
353
|
-
|
|
354
|
+
/** An answer: the option, and what the person said with it, if anything. */
|
|
355
|
+
const AnswerSchema = z.strictObject({
|
|
356
|
+
choose: z.string().min(1),
|
|
357
|
+
note: z.string().optional()
|
|
358
|
+
});
|
|
354
359
|
const RunFlags = {
|
|
355
360
|
inputs: z.record(z.string(), z.string()).optional(),
|
|
356
361
|
driver: Driver.optional(),
|
|
@@ -362,7 +367,9 @@ const StartRunSchema = z.strictObject({
|
|
|
362
367
|
project: z.string().min(1),
|
|
363
368
|
/** A workflow's name in the project, or a path inside the project. */
|
|
364
369
|
workflow: z.string().min(1),
|
|
365
|
-
...RunFlags
|
|
370
|
+
...RunFlags,
|
|
371
|
+
/** Its sessions load the machine's Claude setup (`--machine-claude`). */
|
|
372
|
+
machineClaude: z.boolean().optional()
|
|
366
373
|
});
|
|
367
374
|
const ResumeRunSchema = z.strictObject(RunFlags);
|
|
368
375
|
const MessageSchema = z.strictObject({
|
|
@@ -936,7 +943,8 @@ const flagsOf = (options) => [
|
|
|
936
943
|
...Object.entries(options.inputs ?? {}).flatMap(([name, value]) => ["--input", `${name}=${value}`]),
|
|
937
944
|
...options.driver === void 0 ? [] : ["--driver", options.driver],
|
|
938
945
|
...options.inPlace === void 0 ? [] : [options.inPlace ? "--in-place" : "--no-in-place"],
|
|
939
|
-
...options.allowDirty === true ? ["--allow-dirty"] : []
|
|
946
|
+
...options.allowDirty === true ? ["--allow-dirty"] : [],
|
|
947
|
+
...options.machineClaude === true ? ["--machine-claude"] : []
|
|
940
948
|
];
|
|
941
949
|
const WORKFLOW_SUFFIX = ".ork.yaml";
|
|
942
950
|
/**
|
|
@@ -955,7 +963,7 @@ const writeRoutes = (context) => {
|
|
|
955
963
|
const script = context.script === void 0 ? {} : { script: context.script };
|
|
956
964
|
return {
|
|
957
965
|
answer: async ({ params, body }) => {
|
|
958
|
-
const answered = await answerDecision(context.store, params.id, body.choose, context.home, "ui");
|
|
966
|
+
const answered = await answerDecision(context.store, params.id, body.choose, context.home, "ui", body.note);
|
|
959
967
|
return answered.ok ? ok({
|
|
960
968
|
decision: params.id,
|
|
961
969
|
answer: body.choose
|
|
@@ -1710,8 +1718,11 @@ const mcpTools = (context) => {
|
|
|
1710
1718
|
];
|
|
1711
1719
|
};
|
|
1712
1720
|
const NOT_HERE = "This server was not started by `ork ui`.";
|
|
1713
|
-
/**
|
|
1714
|
-
|
|
1721
|
+
/**
|
|
1722
|
+
* Asks the registry when the daily check is due; never throws. `current` is the
|
|
1723
|
+
* running version, which says whether the `canary` tag counts.
|
|
1724
|
+
*/
|
|
1725
|
+
const checkIfDue = async (file, options, current) => {
|
|
1715
1726
|
try {
|
|
1716
1727
|
const now = /* @__PURE__ */ new Date();
|
|
1717
1728
|
const cache = readUpdateCache(file);
|
|
@@ -1723,7 +1734,8 @@ const checkIfDue = async (file, options) => {
|
|
|
1723
1734
|
const registry = registryOf(options.env ?? process.env);
|
|
1724
1735
|
await refreshUpdateCache(file, options.name, now, {
|
|
1725
1736
|
...registry === void 0 ? {} : { registry },
|
|
1726
|
-
...options.fetch === void 0 ? {} : { fetch: options.fetch }
|
|
1737
|
+
...options.fetch === void 0 ? {} : { fetch: options.fetch },
|
|
1738
|
+
current
|
|
1727
1739
|
});
|
|
1728
1740
|
return true;
|
|
1729
1741
|
} catch {
|
|
@@ -1750,7 +1762,7 @@ const createUpdates = (input) => {
|
|
|
1750
1762
|
let timer;
|
|
1751
1763
|
if (options !== void 0 && reason === null) {
|
|
1752
1764
|
const due = () => {
|
|
1753
|
-
checkIfDue(file, options).then((asked) => {
|
|
1765
|
+
checkIfDue(file, options, version).then((asked) => {
|
|
1754
1766
|
if (asked) record = null;
|
|
1755
1767
|
return asked;
|
|
1756
1768
|
});
|
|
@@ -2276,7 +2288,8 @@ const askPlan = async (context) => {
|
|
|
2276
2288
|
const latest = await fetchLatest(options.name, {
|
|
2277
2289
|
...registry === void 0 ? {} : { registry },
|
|
2278
2290
|
...options.fetch === void 0 ? {} : { fetch: options.fetch },
|
|
2279
|
-
timeoutMs: ASK_TIMEOUT_MS
|
|
2291
|
+
timeoutMs: ASK_TIMEOUT_MS,
|
|
2292
|
+
current
|
|
2280
2293
|
});
|
|
2281
2294
|
const script = options.script ?? runningScript();
|
|
2282
2295
|
const plan = planUpgrade({
|
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bt as FEEDBACK_TARGETS, Rt as FEEDBACK_KINDS, pt as parseReport, zt as FEEDBACK_SEVERITIES } from "./src-hrj2h0IZ.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
4
|
import { createInterface } from "node:readline";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { createServer } from "node:http";
|
|
7
7
|
import { createSdkMcpServer, query, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
8
|
+
// ../runtime-claude/src/cache-env.ts
|
|
9
|
+
/** Claude Code's switch for the one-hour prompt cache. */
|
|
10
|
+
const PROMPT_CACHE_1H = "ENABLE_PROMPT_CACHING_1H";
|
|
11
|
+
/** The variables a session adds to its driver's environment. */
|
|
12
|
+
const cacheEnv = (spec) => spec.promptCache === "1h" ? { [PROMPT_CACHE_1H]: "1" } : {};
|
|
13
|
+
// ../runtime-claude/src/clean.ts
|
|
14
|
+
/** Claude Code's switch that turns its auto-memory off. */
|
|
15
|
+
const NO_AUTO_MEMORY = "CLAUDE_CODE_DISABLE_AUTO_MEMORY";
|
|
16
|
+
/**
|
|
17
|
+
* The CLI flag that moves the per-machine sections (working directory, memory
|
|
18
|
+
* path, git status) out of the system prompt; the SDK's
|
|
19
|
+
* `excludeDynamicSections`.
|
|
20
|
+
*/
|
|
21
|
+
const EXCLUDE_DYNAMIC_SECTIONS = "--exclude-dynamic-system-prompt-sections";
|
|
22
|
+
/** Whether the session loads no MCP server but Ork's. */
|
|
23
|
+
const strictMcpOf = (spec) => spec.tools.strictMcp === true || spec.machineClaude !== true;
|
|
24
|
+
/** The variables that keep the machine's auto-memory out of a session. */
|
|
25
|
+
const memoryEnv = (spec) => spec.machineClaude === true ? {} : { [NO_AUTO_MEMORY]: "1" };
|
|
26
|
+
/** Everything a session adds to its driver's environment. */
|
|
27
|
+
const driverEnv = (spec) => ({
|
|
28
|
+
...cacheEnv(spec),
|
|
29
|
+
...memoryEnv(spec)
|
|
30
|
+
});
|
|
8
31
|
// ../runtime-claude/src/normalize.ts
|
|
9
32
|
/**
|
|
10
33
|
* @file Both drivers emit the same message JSON (the Agent SDK's messages are
|
|
@@ -520,8 +543,16 @@ const askUserTool = defineTool({
|
|
|
520
543
|
context: z.string().optional().describe("What the user needs to know to decide, in a few sentences.")
|
|
521
544
|
},
|
|
522
545
|
run: async ({ nodeId, ports }, args) => {
|
|
546
|
+
let note;
|
|
547
|
+
let owner;
|
|
523
548
|
const question = {
|
|
524
549
|
nodeId,
|
|
550
|
+
onNote: (given) => {
|
|
551
|
+
note = given;
|
|
552
|
+
},
|
|
553
|
+
onOwner: (given) => {
|
|
554
|
+
owner = given;
|
|
555
|
+
},
|
|
525
556
|
question: args.question,
|
|
526
557
|
options: args.options.map((o) => {
|
|
527
558
|
const choice = { id: o.id };
|
|
@@ -533,7 +564,8 @@ const askUserTool = defineTool({
|
|
|
533
564
|
if (args.recommended !== void 0) question.recommended = args.recommended;
|
|
534
565
|
if (args.context !== void 0) question.context = args.context;
|
|
535
566
|
const answer = await ports.human.ask(question);
|
|
536
|
-
|
|
567
|
+
const who = owner === void 0 ? "The user" : `Your owner, \`${owner}\`,`;
|
|
568
|
+
return text(note === void 0 ? `${who} chose: ${answer}` : `${who} chose: ${answer}\nThey said: ${note}`);
|
|
537
569
|
}
|
|
538
570
|
});
|
|
539
571
|
// ../runtime-claude/src/tools/claims.ts
|
|
@@ -707,11 +739,12 @@ const answerTool = defineTool({
|
|
|
707
739
|
description: "Answer a question Ork asked you as the owner of a node, such as a loop of yours that ran out of rounds. The question's id and options are in Ork's message.",
|
|
708
740
|
shape: {
|
|
709
741
|
question: z.string().describe("The question's id, e.g. 'q1'."),
|
|
710
|
-
choice: z.string().describe("One of its options.")
|
|
742
|
+
choice: z.string().describe("One of its options."),
|
|
743
|
+
note: z.string().optional().describe("Why, in a sentence or two; it is recorded with your answer.")
|
|
711
744
|
},
|
|
712
745
|
available: ({ ports }) => ports.mailbox !== void 0 && ports.ownership !== void 0,
|
|
713
746
|
run: ({ ports }, args) => {
|
|
714
|
-
const answered = ports.mailbox?.answer(args.question, args.choice);
|
|
747
|
+
const answered = ports.mailbox?.answer(args.question, args.choice, args.note);
|
|
715
748
|
if (answered === void 0) return Promise.resolve(text("No questions."));
|
|
716
749
|
return Promise.resolve(text(answered.ok ? `Answered ${args.question}: ${args.choice}.` : `Not answered: ${answered.error}.`));
|
|
717
750
|
}
|
|
@@ -802,6 +835,7 @@ const buildCliArgs = (spec, mcp, allowed) => {
|
|
|
802
835
|
spec.settingSources.join(","),
|
|
803
836
|
"--append-system-prompt",
|
|
804
837
|
spec.systemAppend,
|
|
838
|
+
EXCLUDE_DYNAMIC_SECTIONS,
|
|
805
839
|
"--permission-mode",
|
|
806
840
|
spec.permissionMode,
|
|
807
841
|
"--json-schema",
|
|
@@ -814,6 +848,7 @@ const buildCliArgs = (spec, mcp, allowed) => {
|
|
|
814
848
|
[...spec.tools.allow, ...allowed].join(",")
|
|
815
849
|
];
|
|
816
850
|
if (spec.tools.only !== void 0) args.push("--tools", spec.tools.only.join(","));
|
|
851
|
+
if (strictMcpOf(spec)) args.push("--strict-mcp-config");
|
|
817
852
|
if (spec.agents !== void 0) args.push("--agents", JSON.stringify(spec.agents));
|
|
818
853
|
if (spec.tools.deny.length > 0) args.push("--disallowedTools", spec.tools.deny.join(","));
|
|
819
854
|
if (spec.model !== void 0) args.push("--model", spec.model);
|
|
@@ -821,6 +856,7 @@ const buildCliArgs = (spec, mcp, allowed) => {
|
|
|
821
856
|
if (spec.maxTurns !== void 0) args.push("--max-turns", String(spec.maxTurns));
|
|
822
857
|
if (spec.budgetUsd !== void 0) args.push("--max-budget-usd", String(spec.budgetUsd));
|
|
823
858
|
if (spec.resume !== void 0) args.push("--resume", spec.resume);
|
|
859
|
+
if (spec.resume !== void 0 && spec.fork === true) args.push("--fork-session");
|
|
824
860
|
for (const dir of spec.plugins ?? []) args.push("--plugin-dir", dir);
|
|
825
861
|
const settings = mcp.holdUrl === void 0 ? spec.settings : withHoldHook(spec.settings, mcp.holdUrl, mcp.token);
|
|
826
862
|
if (settings !== void 0) args.push("--settings", JSON.stringify(settings));
|
|
@@ -857,7 +893,10 @@ const createCliRuntime = (options = {}) => ({
|
|
|
857
893
|
} : mcp;
|
|
858
894
|
const legOf = (args, carried) => runLeg({
|
|
859
895
|
bin: options.bin ?? "claude",
|
|
860
|
-
env:
|
|
896
|
+
env: {
|
|
897
|
+
...options.env ?? process.env,
|
|
898
|
+
...driverEnv(spec)
|
|
899
|
+
},
|
|
861
900
|
cwd: spec.cwd,
|
|
862
901
|
args,
|
|
863
902
|
carried,
|
|
@@ -886,7 +925,8 @@ const createCliRuntime = (options = {}) => ({
|
|
|
886
925
|
}
|
|
887
926
|
args = buildCliArgs({
|
|
888
927
|
...spec,
|
|
889
|
-
resume: leg.sessionId
|
|
928
|
+
resume: leg.sessionId,
|
|
929
|
+
fork: false
|
|
890
930
|
}, endpoint, allowed);
|
|
891
931
|
}
|
|
892
932
|
} finally {
|
|
@@ -955,7 +995,8 @@ const createQueue = () => {
|
|
|
955
995
|
// ../runtime-claude/src/sdk.ts
|
|
956
996
|
/**
|
|
957
997
|
* @file The SDK driver: runs a session in-process with the Claude Agent SDK,
|
|
958
|
-
* only with an API key or a cloud provider, never a claude.ai login
|
|
998
|
+
* only with an API key or a cloud provider, never a claude.ai login, clean of
|
|
999
|
+
* the machine's Claude setup unless the run asks for it (ADR-065). A node
|
|
959
1000
|
* that can be paused gets a `PreToolUse` callback hook: a short pause holds
|
|
960
1001
|
* the call, a long one defers it and resumes the session when the node
|
|
961
1002
|
* continues (ADR-041).
|
|
@@ -1015,12 +1056,16 @@ const buildSdkOptions = (spec, ports, env, held) => {
|
|
|
1015
1056
|
});
|
|
1016
1057
|
const options = {
|
|
1017
1058
|
cwd: spec.cwd,
|
|
1018
|
-
env: definedEnv(
|
|
1059
|
+
env: definedEnv({
|
|
1060
|
+
...env,
|
|
1061
|
+
...driverEnv(spec)
|
|
1062
|
+
}),
|
|
1019
1063
|
settingSources: spec.settingSources,
|
|
1020
1064
|
systemPrompt: {
|
|
1021
1065
|
type: "preset",
|
|
1022
1066
|
preset: "claude_code",
|
|
1023
|
-
append: spec.systemAppend
|
|
1067
|
+
append: spec.systemAppend,
|
|
1068
|
+
excludeDynamicSections: true
|
|
1024
1069
|
},
|
|
1025
1070
|
permissionMode: spec.permissionMode,
|
|
1026
1071
|
allowedTools: [...spec.tools.allow, ...preapprovedTools(tools)],
|
|
@@ -1046,12 +1091,14 @@ const buildSdkOptions = (spec, ports, env, held) => {
|
|
|
1046
1091
|
}
|
|
1047
1092
|
};
|
|
1048
1093
|
if (spec.tools.only !== void 0) options.tools = spec.tools.only;
|
|
1094
|
+
if (strictMcpOf(spec)) options.strictMcpConfig = true;
|
|
1049
1095
|
if (spec.agents !== void 0) options.agents = spec.agents;
|
|
1050
1096
|
if (spec.model !== void 0) options.model = spec.model;
|
|
1051
1097
|
if (spec.effort !== void 0) options.effort = spec.effort;
|
|
1052
1098
|
if (spec.maxTurns !== void 0) options.maxTurns = spec.maxTurns;
|
|
1053
1099
|
if (spec.budgetUsd !== void 0) options.maxBudgetUsd = spec.budgetUsd;
|
|
1054
1100
|
if (spec.resume !== void 0) options.resume = spec.resume;
|
|
1101
|
+
if (spec.resume !== void 0 && spec.fork === true) options.forkSession = true;
|
|
1055
1102
|
if (spec.plugins !== void 0) options.plugins = spec.plugins.map((dir) => ({
|
|
1056
1103
|
type: "local",
|
|
1057
1104
|
path: dir
|
|
@@ -1081,7 +1128,8 @@ const createSdkRuntime = (env = process.env, holdWindowMs) => ({
|
|
|
1081
1128
|
deferring = false;
|
|
1082
1129
|
const legSpec = resume === void 0 ? spec : {
|
|
1083
1130
|
...spec,
|
|
1084
|
-
resume
|
|
1131
|
+
resume,
|
|
1132
|
+
fork: false
|
|
1085
1133
|
};
|
|
1086
1134
|
current = query({
|
|
1087
1135
|
prompt: input,
|