@karowanorg/orc-ops 0.1.0 → 0.1.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/dist/guide.d.ts +1 -1
- package/dist/guide.js +2 -3
- package/dist/ops.d.ts +0 -10
- package/dist/ops.js +16 -28
- package/dist/registry.js +2 -2
- package/package.json +6 -6
package/dist/guide.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* - CLI: `orc guide`
|
|
4
4
|
* - MCP: the `orc_guide` tool
|
|
5
5
|
*/
|
|
6
|
-
export declare const GUIDE = "# orc \u2014 how to write and run a program\n\norc runs a \"program\": a script that fans out AI-agent subtasks (\"leaves\") and\nrecords each one, so a run is reproducible, resumable, and observable. You write\na program, launch it, then watch it and collect the result.\n\n## 1. Write a program\n\nA program is a `.orc.ts` file with a single default-exported async function.\nIt receives an api object and returns the run's result:\n\n import type { Program } from \"@karowanorg/orc-sdk/program\"; // optional, type-only\n\n const program: Program = async ({ agent, parallel, phase }) => {\n const inventory = await agent(\"List the modules in this repo.\", {\n schema: { type: \"object\",\n properties: { modules: { type: \"array\", items: { type: \"string\" } } },\n required: [\"modules\"] },\n });\n\n // Ordinary async/await controls the flow. Awaiting a result before the\n // next call makes it a dependency; independent calls run concurrently.\n const plans = await Promise.all((inventory.modules as string[]).map(async (m) => {\n const findings = await agent(`Audit module ${m}`, { id: `audit-${m}` });\n return agent(`Plan a fix for ${m}: ${JSON.stringify(findings)}`, { id: `plan-${m}` });\n }));\n\n return phase(\"synthesis\", () => agent(`Merge these plans: ${JSON.stringify(plans)}`, { id: \"merge\" }));\n };\n export default program;\n\n## The api\n\nIMPORTANT \u2014 leaves are isolated. Each agent() runs a FRESH subagent that shares\nNONE of your context: it cannot see this program, your conversation, other\nleaves' prompts or results, or anything you know that you haven't written into\nits prompt (plus the shared `--brief`).\n\n- agent(prompt, opts?) => Promise<result>\n Dispatch one agent. Returns its result (matching `schema` if you pass one).\n A failed leaf rejects the promise, so wrap it in try/catch if you want to\n handle failure. Options:\n id a label shown in the monitor\n schema JSON Schema; the result is structured output matching it\n harness \"claude\" | \"codex\" | a configured harness (default: auto)\n model e.g. \"claude-fable-5\", \"gpt-5.6-sol\"\n reasoningEffort \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\n readOnly default true; set false for a leaf that edits files\n cwd working directory for this leaf (defaults to the run's)\n
|
|
6
|
+
export declare const GUIDE = "# orc \u2014 how to write and run a program\n\norc runs a \"program\": a script that fans out AI-agent subtasks (\"leaves\") and\nrecords each one, so a run is reproducible, resumable, and observable. You write\na program, launch it, then watch it and collect the result.\n\n## 1. Write a program\n\nA program is a `.orc.ts` file with a single default-exported async function.\nIt receives an api object and returns the run's result:\n\n import type { Program } from \"@karowanorg/orc-sdk/program\"; // optional, type-only\n\n const program: Program = async ({ agent, parallel, phase }) => {\n const inventory = await agent(\"List the modules in this repo.\", {\n schema: { type: \"object\",\n properties: { modules: { type: \"array\", items: { type: \"string\" } } },\n required: [\"modules\"] },\n });\n\n // Ordinary async/await controls the flow. Awaiting a result before the\n // next call makes it a dependency; independent calls run concurrently.\n const plans = await Promise.all((inventory.modules as string[]).map(async (m) => {\n const findings = await agent(`Audit module ${m}`, { id: `audit-${m}` });\n return agent(`Plan a fix for ${m}: ${JSON.stringify(findings)}`, { id: `plan-${m}` });\n }));\n\n return phase(\"synthesis\", () => agent(`Merge these plans: ${JSON.stringify(plans)}`, { id: \"merge\" }));\n };\n export default program;\n\n## The api\n\nIMPORTANT \u2014 leaves are isolated. Each agent() runs a FRESH subagent that shares\nNONE of your context: it cannot see this program, your conversation, other\nleaves' prompts or results, or anything you know that you haven't written into\nits prompt (plus the shared `--brief`).\n\n- agent(prompt, opts?) => Promise<result>\n Dispatch one agent. Returns its result (matching `schema` if you pass one).\n A failed leaf rejects the promise, so wrap it in try/catch if you want to\n handle failure. Options:\n id a label shown in the monitor\n schema JSON Schema; the result is structured output matching it\n harness \"claude\" | \"codex\" | a configured harness (default: auto)\n model e.g. \"claude-fable-5\", \"gpt-5.6-sol\"\n reasoningEffort \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\n readOnly default true; set false for a leaf that edits files\n cwd working directory for this leaf (defaults to the run's)\n idleTimeout ms with no output before the leaf is killed (false = off)\n phase group this call under a phase label\n To see valid `harness`, `model`, and `reasoningEffort` values for your\n machine, run `orc capabilities` (or `orc capabilities --json`) \u2014 it lists\n each installed harness with its available models and reasoning levels.\n Omit any of them to use the default; an unknown value is rejected up front\n by `orc validate`.\n\n- parallel(specs[]) => Promise<outcomes[]>\n Run several agents at once from an array of option objects (each with a\n `prompt`). Every lane runs to completion INDEPENDENTLY \u2014 one lane failing\n never cancels the others. Outcomes come back in order as\n `{ status: \"ok\", value } | { status: \"error\", error }`, so you decide how to\n handle partial failure. (For fail-fast, use `Promise.all` over `agent()`,\n which rejects on the first failure.)\n\n- phase(name, fn) => Promise<result>\n Group every agent() call made inside `fn` under a phase, for a readable\n run timeline.\n\n- settle(promise) => { status: \"ok\", value } | { status: \"error\", error }\n Run a lane and capture its outcome instead of letting a failure stop the run\n \u2014 useful for \"do all of these, some may fail\" fan-outs.\n\n- log(message) \u2014 write a line to the run's live event feed.\n- ext.<name>(payload) \u2014 call a custom step you registered in orc.config.\n\nBecause leaves can't see each other, pass data between them as plain values:\nput a previous result into the next prompt with JSON.stringify so the receiving\nleaf actually has it. Use normal try/catch, Promise.all/allSettled, and bounded\nloops for control flow.\n\n## What a program may and may not do\n\n- No wall clock or randomness. `Date`, `Math.random`, timers, network, file\n access, and imports (beyond type-only) are unavailable \u2014 a program only\n decides which agents to run and how to combine their results.\n- Loops must be finite; an unbounded loop is stopped by a step limit.\n- These constraints let orc replay a program exactly when you resume it, so the\n same inputs always produce the same run.\n\n## Writing files\n\nBy default leaves are read-only. To let a leaf directly modify files or run\nmutating commands, set `readOnly: false` and launch the run with\n`--allow-writes`. Configured hooks and MCP tools are not disabled for read-only\nleaves; their side effects are outside this guarantee. A write leaf runs with\nwhatever permissions your own agent has; add `--sandbox` to confine its writes\nto the working directory. If a run stops on a write leaf, `orc resume` picks it\nback up (it re-checks the working-tree state first, never blindly redoing work).\n\n## 2. Validate and launch\n\n orc validate --program-path ./my.orc.ts # compile + preview, no run\n orc launch --program-path ./my.orc.ts --brief \"what this run is for\"\n\n`--brief` (required) is shared context added to every leaf. Common launch flags:\n`--allow-writes`, `--approval-mode manual|accept-edits|auto|bypass`,\n`--sandbox`, `--harness claude|codex`, `--budget <usd>` (fail the run after\nobserved estimated cost exceeds this; concurrent work may overshoot), `--wait`\n(block for the result instead of running in the background).\n\n## 3. Watch and collect\n\n orc status --run-id <id> # summary\n orc wait --run-id <id> # block until it finishes\n orc get-result --run-id <id> # the final result (or --seq N for one leaf)\n orc trace --run-id <id> # per-leaf and per-tool detail\n orc open --run-id <id> # open the live monitor, print its URL\n orc list # recent runs\n\n## 4. Approvals\n\nIn `manual` or `accept-edits` mode a leaf can pause to ask permission for a\ntool. Answer it from anywhere:\n\n orc approvals --run-id <id>\n orc respond --run-id <id> --approval-id <aid> --behavior allow|deny\n\n## Discover more\n\n orc --help # every command\n orc <command> --help # a command's flags\n orc commands # JSON catalog of all operations\n orc capabilities # available harnesses, models, and reasoning levels\n orc doctor # check this machine is ready\n\nEvery command supports `--json`. Run state lives in `$ORC_HOME` (default\n`~/.orc`). Real runs need `claude` and/or `codex` installed and logged in.\n";
|
package/dist/guide.js
CHANGED
|
@@ -52,7 +52,6 @@ its prompt (plus the shared \`--brief\`).
|
|
|
52
52
|
reasoningEffort "low" | "medium" | "high" | "xhigh" | "max"
|
|
53
53
|
readOnly default true; set false for a leaf that edits files
|
|
54
54
|
cwd working directory for this leaf (defaults to the run's)
|
|
55
|
-
host SSH destination to run this leaf on a remote machine
|
|
56
55
|
idleTimeout ms with no output before the leaf is killed (false = off)
|
|
57
56
|
phase group this call under a phase label
|
|
58
57
|
To see valid \`harness\`, \`model\`, and \`reasoningEffort\` values for your
|
|
@@ -110,7 +109,7 @@ back up (it re-checks the working-tree state first, never blindly redoing work).
|
|
|
110
109
|
orc launch --program-path ./my.orc.ts --brief "what this run is for"
|
|
111
110
|
|
|
112
111
|
\`--brief\` (required) is shared context added to every leaf. Common launch flags:
|
|
113
|
-
\`--allow-writes\`, \`--
|
|
112
|
+
\`--allow-writes\`, \`--approval-mode manual|accept-edits|auto|bypass\`,
|
|
114
113
|
\`--sandbox\`, \`--harness claude|codex\`, \`--budget <usd>\` (fail the run after
|
|
115
114
|
observed estimated cost exceeds this; concurrent work may overshoot), \`--wait\`
|
|
116
115
|
(block for the result instead of running in the background).
|
|
@@ -138,7 +137,7 @@ tool. Answer it from anywhere:
|
|
|
138
137
|
orc <command> --help # a command's flags
|
|
139
138
|
orc commands # JSON catalog of all operations
|
|
140
139
|
orc capabilities # available harnesses, models, and reasoning levels
|
|
141
|
-
orc doctor
|
|
140
|
+
orc doctor # check this machine is ready
|
|
142
141
|
|
|
143
142
|
Every command supports \`--json\`. Run state lives in \`$ORC_HOME\` (default
|
|
144
143
|
\`~/.orc\`). Real runs need \`claude\` and/or \`codex\` installed and logged in.
|
package/dist/ops.d.ts
CHANGED
|
@@ -18,7 +18,6 @@ interface FirstFrontierCall {
|
|
|
18
18
|
id?: string;
|
|
19
19
|
readOnly: boolean;
|
|
20
20
|
harness?: string;
|
|
21
|
-
host?: string;
|
|
22
21
|
model?: string;
|
|
23
22
|
reasoningEffort?: string;
|
|
24
23
|
schema?: Json;
|
|
@@ -27,7 +26,6 @@ interface FirstFrontierCall {
|
|
|
27
26
|
export declare const launch: OpDef<z.ZodObject<{
|
|
28
27
|
programPath: z.ZodString;
|
|
29
28
|
cwd: z.ZodOptional<z.ZodString>;
|
|
30
|
-
host: z.ZodOptional<z.ZodString>;
|
|
31
29
|
brief: z.ZodString;
|
|
32
30
|
allowWrites: z.ZodDefault<z.ZodBoolean>;
|
|
33
31
|
approvalMode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -79,7 +77,6 @@ export declare const validate: OpDef<z.ZodObject<{
|
|
|
79
77
|
bypass: "bypass";
|
|
80
78
|
}>>;
|
|
81
79
|
harness: z.ZodOptional<z.ZodString>;
|
|
82
|
-
host: z.ZodOptional<z.ZodString>;
|
|
83
80
|
checkCapabilities: z.ZodDefault<z.ZodBoolean>;
|
|
84
81
|
}, z.core.$strip>, {
|
|
85
82
|
ok: boolean;
|
|
@@ -137,7 +134,6 @@ export declare const getTrace: OpDef<z.ZodObject<{
|
|
|
137
134
|
harness?: string;
|
|
138
135
|
model?: string;
|
|
139
136
|
reasoningEffort?: string;
|
|
140
|
-
host?: string;
|
|
141
137
|
cwd?: string;
|
|
142
138
|
readOnly: boolean;
|
|
143
139
|
startMs: number;
|
|
@@ -159,7 +155,6 @@ export declare const list: OpDef<z.ZodObject<{
|
|
|
159
155
|
name: string | undefined;
|
|
160
156
|
state: string;
|
|
161
157
|
createdAtMs: number;
|
|
162
|
-
host: string | undefined;
|
|
163
158
|
cwd: string;
|
|
164
159
|
}[]>;
|
|
165
160
|
export declare const cancel: OpDef<z.ZodObject<{
|
|
@@ -194,10 +189,8 @@ export declare const respondApproval: OpDef<z.ZodObject<{
|
|
|
194
189
|
enqueued: boolean;
|
|
195
190
|
}>;
|
|
196
191
|
export declare const capabilities: OpDef<z.ZodObject<{
|
|
197
|
-
host: z.ZodOptional<z.ZodString>;
|
|
198
192
|
refresh: z.ZodDefault<z.ZodBoolean>;
|
|
199
193
|
}, z.core.$strip>, {
|
|
200
|
-
host: string;
|
|
201
194
|
defaultHarness: string;
|
|
202
195
|
harnesses: Record<string, unknown>;
|
|
203
196
|
extensions: string[];
|
|
@@ -214,16 +207,13 @@ export declare const report: OpDef<z.ZodObject<{
|
|
|
214
207
|
path: string;
|
|
215
208
|
}>;
|
|
216
209
|
export declare const guide: OpDef<z.ZodObject<{
|
|
217
|
-
host: z.ZodOptional<z.ZodString>;
|
|
218
210
|
probe: z.ZodDefault<z.ZodBoolean>;
|
|
219
211
|
}, z.core.$strip>, {
|
|
220
212
|
guide: string;
|
|
221
213
|
}>;
|
|
222
214
|
export declare const doctor: OpDef<z.ZodObject<{
|
|
223
|
-
host: z.ZodOptional<z.ZodString>;
|
|
224
215
|
cwd: z.ZodOptional<z.ZodString>;
|
|
225
216
|
}, z.core.$strip>, {
|
|
226
|
-
host: string;
|
|
227
217
|
checks: Record<string, unknown>;
|
|
228
218
|
}>;
|
|
229
219
|
export declare const ALL_OPS: OpDef[];
|
package/dist/ops.js
CHANGED
|
@@ -25,7 +25,6 @@ export const launch = defineOp({
|
|
|
25
25
|
input: z.object({
|
|
26
26
|
programPath: z.string().describe("path to the program (.orc.ts/.ts/.js)"),
|
|
27
27
|
cwd: z.string().optional().describe("working directory (plain path); defaults to the caller's cwd"),
|
|
28
|
-
host: z.string().optional().describe("SSH destination (separate field; e.g. 'build@ci-box' or an ssh-config alias)"),
|
|
29
28
|
brief: z.string().describe("shared context injected into every leaf"),
|
|
30
29
|
allowWrites: z.boolean().default(false).describe("grant write-declared leaves permission to mutate files"),
|
|
31
30
|
approvalMode: ApprovalMode.default("auto").describe("manual | accept-edits | auto | bypass"),
|
|
@@ -42,7 +41,6 @@ export const launch = defineOp({
|
|
|
42
41
|
const manifest = await prepareRun({
|
|
43
42
|
programPath: input.programPath,
|
|
44
43
|
cwd: input.cwd,
|
|
45
|
-
host: input.host,
|
|
46
44
|
brief: input.brief,
|
|
47
45
|
allowWrites: input.allowWrites,
|
|
48
46
|
approvalMode: input.approvalMode,
|
|
@@ -87,7 +85,6 @@ export const validate = defineOp({
|
|
|
87
85
|
allowWrites: z.boolean().default(false),
|
|
88
86
|
approvalMode: ApprovalMode.default("auto").describe("check the first-frontier harnesses can honor this mode"),
|
|
89
87
|
harness: z.string().optional().describe("default harness override (same precedence as launch)"),
|
|
90
|
-
host: z.string().optional().describe("check capabilities on this remote host"),
|
|
91
88
|
checkCapabilities: z.boolean().default(true).describe("probe referenced harnesses for model/effort/mode support (slower)"),
|
|
92
89
|
}),
|
|
93
90
|
async handler(input, ctx) {
|
|
@@ -105,7 +102,6 @@ export const validate = defineOp({
|
|
|
105
102
|
id: spec.id,
|
|
106
103
|
readOnly: spec.readOnly,
|
|
107
104
|
harness: spec.harness,
|
|
108
|
-
host: spec.host,
|
|
109
105
|
model: spec.model,
|
|
110
106
|
reasoningEffort: spec.reasoningEffort,
|
|
111
107
|
schema: spec.schema,
|
|
@@ -127,19 +123,16 @@ export const validate = defineOp({
|
|
|
127
123
|
finally {
|
|
128
124
|
vm?.dispose();
|
|
129
125
|
}
|
|
130
|
-
// Host can change per leaf, so only share probes with the same effective
|
|
131
|
-
// harness and executor destination.
|
|
132
126
|
const capsCache = new Map();
|
|
133
|
-
const capsFor = (harnessName
|
|
134
|
-
const
|
|
135
|
-
const cached = capsCache.get(key);
|
|
127
|
+
const capsFor = (harnessName) => {
|
|
128
|
+
const cached = capsCache.get(harnessName);
|
|
136
129
|
if (cached)
|
|
137
130
|
return cached;
|
|
138
131
|
const harness = ctx.registry.harnesses.get(harnessName);
|
|
139
132
|
if (!harness)
|
|
140
133
|
return Promise.reject(new Error(`unknown harness "${harnessName}"`));
|
|
141
|
-
const pending = Promise.resolve().then(() => harness.discover({ executor: ctx.registry.
|
|
142
|
-
capsCache.set(
|
|
134
|
+
const pending = Promise.resolve().then(() => harness.discover({ executor: ctx.registry.executor }));
|
|
135
|
+
capsCache.set(harnessName, pending);
|
|
143
136
|
return pending;
|
|
144
137
|
};
|
|
145
138
|
for (const call of firstCalls) {
|
|
@@ -159,7 +152,6 @@ export const validate = defineOp({
|
|
|
159
152
|
}
|
|
160
153
|
if (call.kind === "agent") {
|
|
161
154
|
const harnessName = call.harness ?? input.harness ?? ctx.registry.defaultHarness;
|
|
162
|
-
const host = call.host ?? input.host;
|
|
163
155
|
const harness = ctx.registry.harnesses.get(harnessName);
|
|
164
156
|
if (!harness) {
|
|
165
157
|
problems.push(`call ${call.seq} uses unknown harness "${harnessName}" (available: ${[...ctx.registry.harnesses.keys()].join(", ")})`);
|
|
@@ -177,10 +169,10 @@ export const validate = defineOp({
|
|
|
177
169
|
if (harness && input.checkCapabilities) {
|
|
178
170
|
let caps;
|
|
179
171
|
try {
|
|
180
|
-
caps = await capsFor(harnessName
|
|
172
|
+
caps = await capsFor(harnessName);
|
|
181
173
|
}
|
|
182
174
|
catch (err) {
|
|
183
|
-
problems.push(`call ${call.seq}: could not discover harness "${harnessName}"
|
|
175
|
+
problems.push(`call ${call.seq}: could not discover harness "${harnessName}" (${String(err instanceof Error ? err.message : err)})`);
|
|
184
176
|
continue;
|
|
185
177
|
}
|
|
186
178
|
if (!caps.available) {
|
|
@@ -218,7 +210,7 @@ export const validate = defineOp({
|
|
|
218
210
|
}
|
|
219
211
|
const approvalMode = input.approvalMode ?? "auto";
|
|
220
212
|
if (caps.approvalModes.length > 0 && !caps.approvalModes.includes(approvalMode)) {
|
|
221
|
-
problems.push(`call ${call.seq}: harness "${harnessName}" cannot honor approval mode "${approvalMode}"
|
|
213
|
+
problems.push(`call ${call.seq}: harness "${harnessName}" cannot honor approval mode "${approvalMode}" (supports: ${caps.approvalModes.join(", ")})`);
|
|
222
214
|
}
|
|
223
215
|
}
|
|
224
216
|
}
|
|
@@ -322,13 +314,13 @@ export const list = defineOp({
|
|
|
322
314
|
catch {
|
|
323
315
|
/* partial run dir */
|
|
324
316
|
}
|
|
325
|
-
return { runId: m.runId, name: m.name, state, createdAtMs: m.createdAtMs,
|
|
317
|
+
return { runId: m.runId, name: m.name, state, createdAtMs: m.createdAtMs, cwd: m.cwd };
|
|
326
318
|
});
|
|
327
319
|
},
|
|
328
320
|
});
|
|
329
321
|
export const cancel = defineOp({
|
|
330
322
|
name: "cancel",
|
|
331
|
-
doc: "Queue cancellation.
|
|
323
|
+
doc: "Queue cancellation. Leaves get TERM→KILL on their whole process group.",
|
|
332
324
|
readOnly: false,
|
|
333
325
|
input: z.object({ runId: RunId }),
|
|
334
326
|
async handler(input) {
|
|
@@ -401,11 +393,10 @@ export const capabilities = defineOp({
|
|
|
401
393
|
doc: "List harnesses, models, and reasoning levels — each discovered through the harness's native mechanism.",
|
|
402
394
|
readOnly: true,
|
|
403
395
|
input: z.object({
|
|
404
|
-
host: z.string().optional().describe("probe a remote host instead of local"),
|
|
405
396
|
refresh: z.boolean().default(false),
|
|
406
397
|
}),
|
|
407
398
|
async handler(input, ctx) {
|
|
408
|
-
const executor = ctx.registry.
|
|
399
|
+
const executor = ctx.registry.executor;
|
|
409
400
|
const out = {};
|
|
410
401
|
for (const [name, harness] of ctx.registry.harnesses) {
|
|
411
402
|
out[name] = await harness.discover({ executor }).catch((err) => ({
|
|
@@ -414,7 +405,6 @@ export const capabilities = defineOp({
|
|
|
414
405
|
}));
|
|
415
406
|
}
|
|
416
407
|
return {
|
|
417
|
-
host: input.host ?? "(local)",
|
|
418
408
|
defaultHarness: ctx.registry.defaultHarness,
|
|
419
409
|
harnesses: out,
|
|
420
410
|
extensions: [...ctx.registry.extensions.keys()],
|
|
@@ -450,7 +440,6 @@ export const guide = defineOp({
|
|
|
450
440
|
doc: "How to write and run an orc program — the authoring + usage guide, with this machine's live harness/model catalog appended.",
|
|
451
441
|
readOnly: true,
|
|
452
442
|
input: z.object({
|
|
453
|
-
host: z.string().optional().describe("probe this remote host's harnesses instead of local"),
|
|
454
443
|
probe: z.boolean().default(true).describe("append the live capability catalog (set false for the static doc only)"),
|
|
455
444
|
}),
|
|
456
445
|
async handler(input, ctx) {
|
|
@@ -461,7 +450,7 @@ export const guide = defineOp({
|
|
|
461
450
|
// values in hand instead of guessing. Never let a slow or missing harness
|
|
462
451
|
// break the guide — degrade to the static doc, which already points at
|
|
463
452
|
// `orc capabilities`.
|
|
464
|
-
const caps = await withDeadline(capabilities.handler({
|
|
453
|
+
const caps = await withDeadline(capabilities.handler({ refresh: false }, ctx), 15_000).catch(() => null);
|
|
465
454
|
return { guide: GUIDE + (caps ? renderCapabilitiesForGuide(caps) : "") };
|
|
466
455
|
},
|
|
467
456
|
});
|
|
@@ -483,7 +472,7 @@ function renderCapabilitiesForGuide(caps) {
|
|
|
483
472
|
"",
|
|
484
473
|
"## Available on this machine",
|
|
485
474
|
"",
|
|
486
|
-
|
|
475
|
+
"Discovered live — these are the valid \`harness\`, \`model\`, and",
|
|
487
476
|
`\`reasoningEffort\` values right now, so you don't have to guess. Default harness: **${c.defaultHarness}**.`,
|
|
488
477
|
"Omit any of them to take the default.",
|
|
489
478
|
];
|
|
@@ -502,19 +491,18 @@ function renderCapabilitiesForGuide(caps) {
|
|
|
502
491
|
if (h.approvalModes?.length)
|
|
503
492
|
lines.push(` - approval modes: ${h.approvalModes.join(", ")}`);
|
|
504
493
|
}
|
|
505
|
-
lines.push("", "Re-run `orc capabilities` any time
|
|
494
|
+
lines.push("", "Re-run `orc capabilities` any time.");
|
|
506
495
|
return lines.join("\n");
|
|
507
496
|
}
|
|
508
497
|
export const doctor = defineOp({
|
|
509
498
|
name: "doctor",
|
|
510
|
-
doc: "Preflight
|
|
499
|
+
doc: "Preflight this machine: harness binaries, versions, cwd existence.",
|
|
511
500
|
readOnly: true,
|
|
512
501
|
input: z.object({
|
|
513
|
-
host: z.string().optional(),
|
|
514
502
|
cwd: z.string().optional(),
|
|
515
503
|
}),
|
|
516
504
|
async handler(input, ctx) {
|
|
517
|
-
const executor = ctx.registry.
|
|
505
|
+
const executor = ctx.registry.executor;
|
|
518
506
|
const checks = {};
|
|
519
507
|
for (const [name, harness] of ctx.registry.harnesses) {
|
|
520
508
|
const caps = await harness.discover({ executor }).catch(() => null);
|
|
@@ -523,7 +511,7 @@ export const doctor = defineOp({
|
|
|
523
511
|
if (input.cwd) {
|
|
524
512
|
checks.cwd = { path: input.cwd, exists: await executor.exists(input.cwd) };
|
|
525
513
|
}
|
|
526
|
-
return {
|
|
514
|
+
return { checks };
|
|
527
515
|
},
|
|
528
516
|
});
|
|
529
517
|
// ---------------------------------------------------------------------------
|
package/dist/registry.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* come only from an explicit orc.config.(js|json).
|
|
6
6
|
*/
|
|
7
7
|
import { callerAffinity, loadConfig } from "@karowanorg/orc-core";
|
|
8
|
-
import {
|
|
8
|
+
import { LocalExecutor } from "@karowanorg/orc-executors";
|
|
9
9
|
import { claudeHarness } from "@karowanorg/orc-harness-claude";
|
|
10
10
|
import { codexHarness, createCodexHarness } from "@karowanorg/orc-harness-codex";
|
|
11
11
|
import { makeExecHarness } from "./exec-harness.js";
|
|
@@ -31,5 +31,5 @@ export async function buildRegistry(opts = {}) {
|
|
|
31
31
|
config.defaultHarness ??
|
|
32
32
|
callerAffinity(opts.mcpClientName) ??
|
|
33
33
|
"codex";
|
|
34
|
-
return { harnesses, extensions, defaultHarness,
|
|
34
|
+
return { harnesses, extensions, defaultHarness, executor: new LocalExecutor() };
|
|
35
35
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@karowanorg/orc-ops",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"license": "0BSD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@karowanorg/orc-core": "^0.1.
|
|
9
|
-
"@karowanorg/orc-executors": "^0.1.
|
|
10
|
-
"@karowanorg/orc-harness-claude": "^0.1.
|
|
11
|
-
"@karowanorg/orc-harness-codex": "^0.1.
|
|
12
|
-
"@karowanorg/orc-ui": "^0.1.
|
|
8
|
+
"@karowanorg/orc-core": "^0.1.1",
|
|
9
|
+
"@karowanorg/orc-executors": "^0.1.1",
|
|
10
|
+
"@karowanorg/orc-harness-claude": "^0.1.1",
|
|
11
|
+
"@karowanorg/orc-harness-codex": "^0.1.1",
|
|
12
|
+
"@karowanorg/orc-ui": "^0.1.1",
|
|
13
13
|
"zod": "^4.1.0"
|
|
14
14
|
},
|
|
15
15
|
"description": "The zod-first operation registry orc's CLI, MCP server, and SDK all interpret.",
|