open-research-protocol 0.4.8 → 0.4.10
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 +10 -0
- package/bin/orp-compute.mjs +341 -0
- package/bin/orp.js +58 -15
- package/cli/orp.py +490 -0
- package/docs/AGENT_LOOP.md +3 -0
- package/docs/ORP_YOUTUBE_INSPECT.md +97 -0
- package/llms.txt +3 -0
- package/package.json +1 -1
- package/scripts/orp-kernel-benchmark.py +8 -8
- package/spec/v1/youtube-source.schema.json +151 -0
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ verification remains independent of framing. See `modules/instruments/README.md`
|
|
|
33
33
|
- `docs/ORP_REASONING_KERNEL_CANONICAL_CONTINUATION_PILOT.md` — harder live downstream benchmark where the agent must produce the next canonical task artifact
|
|
34
34
|
- `docs/ORP_REASONING_KERNEL_EVIDENCE_MATRIX.md` — honest map of what the kernel proves, only suggests, or still leaves unproven
|
|
35
35
|
- `docs/ORP_REASONING_KERNEL_EVALUATION_PLAN.md` — comparative experiment plan for upgrading kernel evidence beyond implementation validity
|
|
36
|
+
- `docs/ORP_YOUTUBE_INSPECT.md` — first-class YouTube metadata/transcript ingestion surface for agent-readable external source context
|
|
36
37
|
- `docs/EXTERNAL_CONTRIBUTION_GOVERNANCE.md` — canonical local-first workflow for external OSS PR work
|
|
37
38
|
- `docs/OSS_CONTRIBUTION_AGENT_LOOP.md` — agent operating rhythm for external contribution workflows
|
|
38
39
|
- `templates/` — claim, verification, failure, and issue templates
|
|
@@ -51,11 +52,13 @@ verification remains independent of framing. See `modules/instruments/README.md`
|
|
|
51
52
|
ORP should feel like one CLI with built-in abilities:
|
|
52
53
|
|
|
53
54
|
- `workspace` for hosted auth, idea, feature, world, checkpoint, and worker operations
|
|
55
|
+
- `youtube` for public video metadata and transcript ingestion
|
|
54
56
|
- `governance` for local-first repo initialization, branch safety, checkpoint commits, backup refs, readiness, repair, and cleanup
|
|
55
57
|
- `discover` for profile-based GitHub scanning and opportunity selection
|
|
56
58
|
- `collaborate` for repository collaboration setup and workflow execution
|
|
57
59
|
- `erdos` for Erdos-specific data and workflow support
|
|
58
60
|
- `report` and `packet` for ORP artifacts
|
|
61
|
+
- `compute` for targeted compute admission, local execution, and paid approval gating
|
|
59
62
|
|
|
60
63
|
The `pack` layer still exists, but it is now an advanced/internal surface rather
|
|
61
64
|
than the main product story.
|
|
@@ -118,6 +121,8 @@ orp home --json
|
|
|
118
121
|
orp about --json
|
|
119
122
|
orp auth login
|
|
120
123
|
orp whoami --json
|
|
124
|
+
orp youtube inspect https://www.youtube.com/watch?v=<video_id> --json
|
|
125
|
+
orp youtube inspect https://www.youtube.com/watch?v=<video_id> --save --json
|
|
121
126
|
orp ideas list --json
|
|
122
127
|
orp world bind --idea-id <idea-id> --project-root /abs/path --codex-session-id <session-id> --json
|
|
123
128
|
orp checkpoint queue --idea-id <idea-id> --json
|
|
@@ -141,6 +146,8 @@ orp pack install --pack-id erdos-open-problems --json
|
|
|
141
146
|
orp pack fetch --source <git-url> --pack-id <pack-id> --install-target . --json
|
|
142
147
|
orp gate run --profile default --json
|
|
143
148
|
orp packet emit --profile default --json
|
|
149
|
+
orp compute decide --input orp.compute.json --json
|
|
150
|
+
orp compute run-local --input orp.compute.json --task orp.compute.task.json --json
|
|
144
151
|
orp report summary --json
|
|
145
152
|
```
|
|
146
153
|
|
|
@@ -149,6 +156,8 @@ These surfaces are meant to help automated systems discover ORP quickly:
|
|
|
149
156
|
- bare `orp` opens a home screen with repo/runtime status, available packs, and next commands
|
|
150
157
|
- `orp home --json` returns the same landing context in machine-readable form
|
|
151
158
|
- `orp auth ...`, `orp ideas ...`, `orp world ...`, `orp checkpoint ...`, `orp runner ...`, and `orp agent ...` expose the hosted workspace surface directly through ORP
|
|
159
|
+
- `orp compute ...` exposes targeted-compute admission, local execution, and paid-approval gating through a stable ORP wrapper surface
|
|
160
|
+
- `orp youtube inspect ...` exposes public YouTube metadata plus full transcript ingestion through a stable ORP artifact shape for agent use when caption tracks are available
|
|
152
161
|
- `orp init`, `orp status`, `orp branch start`, `orp checkpoint create`, `orp backup`, `orp ready`, `orp doctor`, and `orp cleanup` expose the local-first repo governance surface directly through ORP
|
|
153
162
|
- `orp discover ...` exposes profile-based GitHub scanning as a built-in ORP ability
|
|
154
163
|
- `orp collaborate ...` exposes built-in collaboration setup and workflow execution without asking users to think in terms of separate governance packs
|
|
@@ -212,6 +221,7 @@ Minimal CLI skeleton:
|
|
|
212
221
|
|
|
213
222
|
```bash
|
|
214
223
|
orp auth login
|
|
224
|
+
orp youtube inspect https://www.youtube.com/watch?v=<video_id> --json
|
|
215
225
|
orp ideas list --json
|
|
216
226
|
orp world bind --idea-id <idea-id> --project-root /abs/path --codex-session-id <session-id> --json
|
|
217
227
|
orp checkpoint queue --idea-id <idea-id> --json
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import {
|
|
7
|
+
buildOrpComputeGateResult,
|
|
8
|
+
buildOrpComputePacket,
|
|
9
|
+
defineComputePacket,
|
|
10
|
+
defineDecision,
|
|
11
|
+
defineImpactRead,
|
|
12
|
+
definePolicy,
|
|
13
|
+
defineResultBundle,
|
|
14
|
+
defineRung,
|
|
15
|
+
evaluateDispatch,
|
|
16
|
+
runLocalShellPacket,
|
|
17
|
+
} from "breakthroughs";
|
|
18
|
+
|
|
19
|
+
function printHelp() {
|
|
20
|
+
console.log(`ORP compute
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
orp compute decide --input <path> [--packet-out <path>] [--json]
|
|
24
|
+
orp compute run-local --input <path> --task <path> [--receipt-out <path>] [--packet-out <path>] [--json]
|
|
25
|
+
|
|
26
|
+
Input JSON shape:
|
|
27
|
+
{
|
|
28
|
+
"decision": { ... },
|
|
29
|
+
"rung": { ... },
|
|
30
|
+
"policy": { ... },
|
|
31
|
+
"packet": { ... },
|
|
32
|
+
"repo": {
|
|
33
|
+
"rootPath": "/abs/path",
|
|
34
|
+
"git": { "branch": "main", "commit": "abc123" }
|
|
35
|
+
},
|
|
36
|
+
"orp": {
|
|
37
|
+
"boardId": "targeted_compute",
|
|
38
|
+
"problemId": "adult-vs-developmental-rgc",
|
|
39
|
+
"artifactRoot": "orp/artifacts"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Task JSON shape for run-local:
|
|
44
|
+
{
|
|
45
|
+
"command": "node",
|
|
46
|
+
"args": ["-e", "console.log('hello')"],
|
|
47
|
+
"cwd": "/abs/path",
|
|
48
|
+
"timeoutMs": 30000,
|
|
49
|
+
"env": {}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Policy semantics:
|
|
53
|
+
- local admitted rungs can resolve to run_local
|
|
54
|
+
- paid admitted rungs resolve to request_paid_approval unless the rung is explicitly approved in policy.paid.approvedRungs
|
|
55
|
+
`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseArgs(argv) {
|
|
59
|
+
const options = {
|
|
60
|
+
json: false,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
64
|
+
const arg = argv[i];
|
|
65
|
+
|
|
66
|
+
if (arg === "--json") {
|
|
67
|
+
options.json = true;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (arg === "-h" || arg === "--help") {
|
|
71
|
+
options.help = true;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (arg.startsWith("--")) {
|
|
75
|
+
const key = arg.slice(2).replace(/-([a-z])/g, (_, ch) => ch.toUpperCase());
|
|
76
|
+
const value = argv[i + 1];
|
|
77
|
+
if (value == null || value.startsWith("--")) {
|
|
78
|
+
throw new Error(`missing value for ${arg}`);
|
|
79
|
+
}
|
|
80
|
+
options[key] = value;
|
|
81
|
+
i += 1;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!options.command) {
|
|
86
|
+
options.command = arg;
|
|
87
|
+
} else {
|
|
88
|
+
throw new Error(`unexpected argument: ${arg}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return options;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function readJson(filePath) {
|
|
96
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
97
|
+
return JSON.parse(raw);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function writeJson(filePath, payload) {
|
|
101
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
102
|
+
await fs.writeFile(filePath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function buildContext(raw) {
|
|
106
|
+
if (!raw || typeof raw !== "object") {
|
|
107
|
+
throw new Error("input must be a JSON object");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
raw,
|
|
112
|
+
decision: defineDecision(raw.decision),
|
|
113
|
+
rung: defineRung(raw.rung),
|
|
114
|
+
policy: definePolicy(raw.policy),
|
|
115
|
+
packet: defineComputePacket(raw.packet),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function commandLabel(subcommand, options) {
|
|
120
|
+
const parts = ["orp", "compute", subcommand];
|
|
121
|
+
if (options.input) {
|
|
122
|
+
parts.push("--input", options.input);
|
|
123
|
+
}
|
|
124
|
+
if (options.task) {
|
|
125
|
+
parts.push("--task", options.task);
|
|
126
|
+
}
|
|
127
|
+
return parts.join(" ");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function gateStatusForDispatch(action) {
|
|
131
|
+
if (action === "hold_packet") {
|
|
132
|
+
return "fail";
|
|
133
|
+
}
|
|
134
|
+
if (action === "request_paid_approval") {
|
|
135
|
+
return "hold";
|
|
136
|
+
}
|
|
137
|
+
return "pass";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function summarizeDispatch(dispatchResult) {
|
|
141
|
+
if (dispatchResult.action === "request_paid_approval") {
|
|
142
|
+
return `compute packet requires explicit paid approval for rung ${dispatchResult.rungId}`;
|
|
143
|
+
}
|
|
144
|
+
if (dispatchResult.action === "hold_packet") {
|
|
145
|
+
return `compute packet is being held because ${dispatchResult.reason}`;
|
|
146
|
+
}
|
|
147
|
+
return `compute packet admitted with action ${dispatchResult.action}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function runDecide(options) {
|
|
151
|
+
if (!options.input) {
|
|
152
|
+
throw new Error("compute decide requires --input <path>");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const context = buildContext(await readJson(options.input));
|
|
156
|
+
const dispatchResult = evaluateDispatch(context);
|
|
157
|
+
const gateResult = buildOrpComputeGateResult({
|
|
158
|
+
gateId: context.packet.rungId,
|
|
159
|
+
command: commandLabel("decide", options),
|
|
160
|
+
status: gateStatusForDispatch(dispatchResult.action),
|
|
161
|
+
evidenceNote: summarizeDispatch(dispatchResult),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const payload = {
|
|
165
|
+
ok: dispatchResult.action !== "hold_packet",
|
|
166
|
+
command: "compute decide",
|
|
167
|
+
dispatch_result: dispatchResult,
|
|
168
|
+
gate_result: gateResult,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
if (options.packetOut) {
|
|
172
|
+
const orpPacket = buildOrpComputePacket({
|
|
173
|
+
repoRoot: context.raw.repo?.rootPath || process.cwd(),
|
|
174
|
+
repoGit: context.raw.repo?.git,
|
|
175
|
+
decision: context.decision,
|
|
176
|
+
packet: context.packet,
|
|
177
|
+
dispatchResult,
|
|
178
|
+
gateResults: [gateResult],
|
|
179
|
+
artifactRoot: context.raw.orp?.artifactRoot,
|
|
180
|
+
boardId: context.raw.orp?.boardId,
|
|
181
|
+
problemId: context.raw.orp?.problemId,
|
|
182
|
+
stateNote: summarizeDispatch(dispatchResult),
|
|
183
|
+
});
|
|
184
|
+
await writeJson(options.packetOut, orpPacket);
|
|
185
|
+
payload.orp_packet_path = path.resolve(options.packetOut);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (options.json) {
|
|
189
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
190
|
+
} else {
|
|
191
|
+
console.log(`${dispatchResult.action}: ${summarizeDispatch(dispatchResult)}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return dispatchResult.action === "hold_packet" ? 1 : 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function runLocal(options) {
|
|
198
|
+
if (!options.input) {
|
|
199
|
+
throw new Error("compute run-local requires --input <path>");
|
|
200
|
+
}
|
|
201
|
+
if (!options.task) {
|
|
202
|
+
throw new Error("compute run-local requires --task <path>");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const context = buildContext(await readJson(options.input));
|
|
206
|
+
const task = await readJson(options.task);
|
|
207
|
+
const dispatchResult = evaluateDispatch(context);
|
|
208
|
+
|
|
209
|
+
if (dispatchResult.action !== "run_local") {
|
|
210
|
+
const message = `compute packet is not locally runnable; dispatch action is ${dispatchResult.action}`;
|
|
211
|
+
if (options.json) {
|
|
212
|
+
console.log(JSON.stringify({ ok: false, error: message, dispatch_result: dispatchResult }, null, 2));
|
|
213
|
+
} else {
|
|
214
|
+
console.error(message);
|
|
215
|
+
}
|
|
216
|
+
return 1;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const executionReceipt = await runLocalShellPacket({
|
|
220
|
+
decision: context.decision,
|
|
221
|
+
rung: context.rung,
|
|
222
|
+
packet: context.packet,
|
|
223
|
+
dispatchResult,
|
|
224
|
+
task,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const gateResult = buildOrpComputeGateResult({
|
|
228
|
+
gateId: context.packet.rungId,
|
|
229
|
+
command: `${executionReceipt.command} ${executionReceipt.args.join(" ")}`.trim(),
|
|
230
|
+
status: executionReceipt.status === "pass" ? "pass" : "fail",
|
|
231
|
+
exitCode: executionReceipt.exitCode == null ? 1 : executionReceipt.exitCode,
|
|
232
|
+
durationMs: executionReceipt.durationMs,
|
|
233
|
+
evidenceNote: `local shell execution completed with status ${executionReceipt.status}`,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const resultBundle = defineResultBundle({
|
|
237
|
+
id: `${context.packet.id}-result`,
|
|
238
|
+
packetId: context.packet.id,
|
|
239
|
+
outputs: context.packet.requiredOutputs,
|
|
240
|
+
status: executionReceipt.status,
|
|
241
|
+
metrics: {
|
|
242
|
+
exitCode: executionReceipt.exitCode,
|
|
243
|
+
durationMs: executionReceipt.durationMs,
|
|
244
|
+
timedOut: executionReceipt.timedOut,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const impactRead = defineImpactRead({
|
|
249
|
+
id: `${context.packet.id}-impact`,
|
|
250
|
+
bundleId: resultBundle.id,
|
|
251
|
+
nextAction: executionReceipt.status === "pass" ? "review_result_bundle" : "reroute_or_debug",
|
|
252
|
+
summary:
|
|
253
|
+
executionReceipt.status === "pass"
|
|
254
|
+
? `local compute packet ${context.packet.id} completed successfully`
|
|
255
|
+
: `local compute packet ${context.packet.id} failed and needs follow-up`,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const payload = {
|
|
259
|
+
ok: executionReceipt.status === "pass",
|
|
260
|
+
command: "compute run-local",
|
|
261
|
+
dispatch_result: dispatchResult,
|
|
262
|
+
execution_receipt: executionReceipt,
|
|
263
|
+
gate_result: gateResult,
|
|
264
|
+
result_bundle: resultBundle,
|
|
265
|
+
impact_read: impactRead,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
if (options.receiptOut) {
|
|
269
|
+
await writeJson(options.receiptOut, executionReceipt);
|
|
270
|
+
payload.execution_receipt_path = path.resolve(options.receiptOut);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (options.packetOut) {
|
|
274
|
+
const orpPacket = buildOrpComputePacket({
|
|
275
|
+
repoRoot: context.raw.repo?.rootPath || process.cwd(),
|
|
276
|
+
repoGit: context.raw.repo?.git,
|
|
277
|
+
decision: context.decision,
|
|
278
|
+
packet: context.packet,
|
|
279
|
+
dispatchResult,
|
|
280
|
+
resultBundle,
|
|
281
|
+
impactRead,
|
|
282
|
+
gateResults: [gateResult],
|
|
283
|
+
artifactRoot: context.raw.orp?.artifactRoot,
|
|
284
|
+
boardId: context.raw.orp?.boardId,
|
|
285
|
+
problemId: context.raw.orp?.problemId,
|
|
286
|
+
extraPaths: options.receiptOut ? [path.resolve(options.receiptOut)] : [],
|
|
287
|
+
stateNote: impactRead.summary,
|
|
288
|
+
});
|
|
289
|
+
await writeJson(options.packetOut, orpPacket);
|
|
290
|
+
payload.orp_packet_path = path.resolve(options.packetOut);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (options.json) {
|
|
294
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
295
|
+
} else {
|
|
296
|
+
console.log(`${executionReceipt.status}: ${impactRead.summary}`);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (executionReceipt.exitCode == null) {
|
|
300
|
+
return 1;
|
|
301
|
+
}
|
|
302
|
+
return executionReceipt.exitCode;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export async function runComputeCli(argv = process.argv.slice(2)) {
|
|
306
|
+
let options;
|
|
307
|
+
try {
|
|
308
|
+
options = parseArgs(argv);
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.error(String(error.message || error));
|
|
311
|
+
printHelp();
|
|
312
|
+
return 1;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (options.help || !options.command) {
|
|
316
|
+
printHelp();
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
if (options.command === "decide") {
|
|
322
|
+
return await runDecide(options);
|
|
323
|
+
}
|
|
324
|
+
if (options.command === "run-local") {
|
|
325
|
+
return await runLocal(options);
|
|
326
|
+
}
|
|
327
|
+
throw new Error(`unknown compute command: ${options.command}`);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
if (options.json) {
|
|
330
|
+
console.log(JSON.stringify({ ok: false, error: String(error.message || error) }, null, 2));
|
|
331
|
+
} else {
|
|
332
|
+
console.error(String(error.message || error));
|
|
333
|
+
}
|
|
334
|
+
return 1;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
339
|
+
const code = await runComputeCli(process.argv.slice(2));
|
|
340
|
+
process.exit(code == null ? 0 : code);
|
|
341
|
+
}
|
package/bin/orp.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const path = require("path");
|
|
4
|
+
const { pathToFileURL } = require("url");
|
|
4
5
|
const { spawnSync } = require("child_process");
|
|
5
6
|
|
|
6
7
|
const cliPath = path.resolve(__dirname, "..", "cli", "orp.py");
|
|
8
|
+
const computeCliUrl = pathToFileURL(path.resolve(__dirname, "orp-compute.mjs")).href;
|
|
7
9
|
const argv = process.argv.slice(2);
|
|
8
10
|
|
|
9
11
|
const candidates = [];
|
|
@@ -15,24 +17,65 @@ if (process.platform === "win32") {
|
|
|
15
17
|
}
|
|
16
18
|
candidates.push("python3", "python");
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
function isTopLevelHelp(args) {
|
|
21
|
+
return args.length === 0 || args.includes("-h") || args.includes("--help");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function runCompute(args) {
|
|
25
|
+
const mod = await import(computeCliUrl);
|
|
26
|
+
const code = await mod.runComputeCli(args);
|
|
27
|
+
process.exit(code == null ? 0 : code);
|
|
28
|
+
}
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
process.exit(result.status == null ? 1 : result.status);
|
|
30
|
+
async function main() {
|
|
31
|
+
if (argv[0] === "compute") {
|
|
32
|
+
await runCompute(argv.slice(1));
|
|
33
|
+
return;
|
|
25
34
|
}
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
|
|
36
|
+
const captureOutput = isTopLevelHelp(argv);
|
|
37
|
+
let lastErr = null;
|
|
38
|
+
|
|
39
|
+
for (const py of candidates) {
|
|
40
|
+
const args = py === "py" ? ["-3", cliPath, ...argv] : [cliPath, ...argv];
|
|
41
|
+
const result = spawnSync(
|
|
42
|
+
py,
|
|
43
|
+
args,
|
|
44
|
+
captureOutput
|
|
45
|
+
? { encoding: "utf8" }
|
|
46
|
+
: { stdio: "inherit" },
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (!result.error) {
|
|
50
|
+
if (captureOutput) {
|
|
51
|
+
if (result.stdout) {
|
|
52
|
+
process.stdout.write(result.stdout);
|
|
53
|
+
}
|
|
54
|
+
if (result.stderr) {
|
|
55
|
+
process.stderr.write(result.stderr);
|
|
56
|
+
}
|
|
57
|
+
if (result.status === 0) {
|
|
58
|
+
process.stdout.write("\nAdditional wrapper surface:\n orp compute -h\n");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
process.exit(result.status == null ? 1 : result.status);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (result.error && result.error.code === "ENOENT") {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
lastErr = result.error;
|
|
28
68
|
}
|
|
29
|
-
lastErr = result.error;
|
|
30
|
-
}
|
|
31
69
|
|
|
32
|
-
console.error("ORP CLI requires Python 3 on PATH.");
|
|
33
|
-
console.error("Tried: " + candidates.join(", "));
|
|
34
|
-
if (lastErr) {
|
|
35
|
-
|
|
70
|
+
console.error("ORP CLI requires Python 3 on PATH.");
|
|
71
|
+
console.error("Tried: " + candidates.join(", "));
|
|
72
|
+
if (lastErr) {
|
|
73
|
+
console.error(String(lastErr));
|
|
74
|
+
}
|
|
75
|
+
process.exit(1);
|
|
36
76
|
}
|
|
37
|
-
process.exit(1);
|
|
38
77
|
|
|
78
|
+
main().catch((error) => {
|
|
79
|
+
console.error(String(error && error.stack ? error.stack : error));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|