@opengeni/ogtool 1.2.1-canary.37222177070001 → 1.3.0
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/bin/ogtool.cjs +75 -3
- package/package.json +2 -2
- package/src/cli.ts +26 -0
package/dist/bin/ogtool.cjs
CHANGED
|
@@ -14619,6 +14619,7 @@ function requireCompleteSiteToolContext(value, context) {
|
|
|
14619
14619
|
}
|
|
14620
14620
|
var CodemodeOperationState = exports_external.enum([
|
|
14621
14621
|
"queued",
|
|
14622
|
+
"waiting_for_approval",
|
|
14622
14623
|
"running",
|
|
14623
14624
|
"completed",
|
|
14624
14625
|
"failed",
|
|
@@ -14642,6 +14643,8 @@ var CodemodeOperation = exports_external.object({
|
|
|
14642
14643
|
message: "Codemode operation caller must be codemode"
|
|
14643
14644
|
}),
|
|
14644
14645
|
state: CodemodeOperationState,
|
|
14646
|
+
durableApproval: exports_external.literal(true).optional(),
|
|
14647
|
+
approvalRequestId: exports_external.string().uuid().optional(),
|
|
14645
14648
|
result: AttemptToolResult.nullable(),
|
|
14646
14649
|
errorCode: exports_external.string().min(1).max(128).nullable(),
|
|
14647
14650
|
errorMessage: exports_external.string().min(1).max(4096).nullable(),
|
|
@@ -14652,6 +14655,7 @@ var CodemodeOperation = exports_external.object({
|
|
|
14652
14655
|
updatedAt: exports_external.string().datetime({ offset: true })
|
|
14653
14656
|
}).strict();
|
|
14654
14657
|
var CodemodeCallRequest = exports_external.object({
|
|
14658
|
+
durableApproval: exports_external.literal(true).optional(),
|
|
14655
14659
|
operationId: exports_external.string().uuid(),
|
|
14656
14660
|
catalogDigest: sha256,
|
|
14657
14661
|
identity: AttemptToolIdentity,
|
|
@@ -15089,6 +15093,20 @@ class CodemodeOperationError extends Error {
|
|
|
15089
15093
|
this.operation = operation;
|
|
15090
15094
|
this.code = code;
|
|
15091
15095
|
this.name = "CodemodeOperationError";
|
|
15096
|
+
Object.defineProperty(this, "operation", { value: operation, enumerable: false });
|
|
15097
|
+
}
|
|
15098
|
+
}
|
|
15099
|
+
|
|
15100
|
+
class CodemodeApprovalPendingError extends Error {
|
|
15101
|
+
operationId;
|
|
15102
|
+
approvalRequestId;
|
|
15103
|
+
code = "codemode_approval_pending";
|
|
15104
|
+
state = "waiting_for_approval";
|
|
15105
|
+
constructor(operationId, approvalRequestId) {
|
|
15106
|
+
super(`Operation ${operationId} is waiting for approval. After review, read or resume this handle; do not submit its arguments again.`);
|
|
15107
|
+
this.operationId = operationId;
|
|
15108
|
+
this.approvalRequestId = approvalRequestId;
|
|
15109
|
+
this.name = "CodemodeApprovalPendingError";
|
|
15092
15110
|
}
|
|
15093
15111
|
}
|
|
15094
15112
|
|
|
@@ -15212,6 +15230,9 @@ class CodemodeClient {
|
|
|
15212
15230
|
} else {
|
|
15213
15231
|
operation = await this.read(operationId, options.signal);
|
|
15214
15232
|
}
|
|
15233
|
+
if (operation.state === "waiting_for_approval") {
|
|
15234
|
+
throw new CodemodeApprovalPendingError(operation.operationId, operation.approvalRequestId);
|
|
15235
|
+
}
|
|
15215
15236
|
if (operation.state === "completed") {
|
|
15216
15237
|
return { result: AttemptToolResult.parse(operation.result), entry };
|
|
15217
15238
|
}
|
|
@@ -15258,11 +15279,39 @@ class CodemodeClient {
|
|
|
15258
15279
|
operationId,
|
|
15259
15280
|
catalogDigest,
|
|
15260
15281
|
identity,
|
|
15261
|
-
arguments: argumentsValue
|
|
15282
|
+
arguments: argumentsValue,
|
|
15283
|
+
durableApproval: true
|
|
15262
15284
|
})
|
|
15263
15285
|
});
|
|
15264
15286
|
return CodemodeCallSubmission.parse(await response.json()).operation;
|
|
15265
15287
|
}
|
|
15288
|
+
async status(operationId, signal) {
|
|
15289
|
+
const operation = await this.read(operationId, signal);
|
|
15290
|
+
return {
|
|
15291
|
+
operationId: operation.operationId,
|
|
15292
|
+
state: operation.state,
|
|
15293
|
+
approvalRequestId: operation.approvalRequestId,
|
|
15294
|
+
result: operation.result,
|
|
15295
|
+
errorCode: operation.errorCode,
|
|
15296
|
+
errorMessage: operation.errorMessage
|
|
15297
|
+
};
|
|
15298
|
+
}
|
|
15299
|
+
async resume(operationId, options = {}) {
|
|
15300
|
+
const deadline = Date.now() + boundedPositiveInteger(options.timeoutMs ?? this.timeoutMs, 1000, 60 * 60000);
|
|
15301
|
+
while (true) {
|
|
15302
|
+
throwIfAborted(options.signal);
|
|
15303
|
+
const operation = await this.read(operationId, options.signal);
|
|
15304
|
+
if (operation.state === "waiting_for_approval")
|
|
15305
|
+
throw new CodemodeApprovalPendingError(operation.operationId, operation.approvalRequestId);
|
|
15306
|
+
if (operation.state === "completed")
|
|
15307
|
+
return AttemptToolResult.parse(operation.result);
|
|
15308
|
+
if (["failed", "outcome_unknown", "cancelled"].includes(operation.state))
|
|
15309
|
+
throw new CodemodeOperationError(operation, operation.errorCode ?? `codemode_${operation.state}`);
|
|
15310
|
+
if (Date.now() >= deadline)
|
|
15311
|
+
throw new CodemodeTransportError(`Codemode operation ${operationId} did not settle before the client deadline`);
|
|
15312
|
+
await abortableDelay(this.pollIntervalMs, options.signal);
|
|
15313
|
+
}
|
|
15314
|
+
}
|
|
15266
15315
|
async read(operationId, signal) {
|
|
15267
15316
|
const response = await this.request(`/calls/${operationId}`, {
|
|
15268
15317
|
method: "GET",
|
|
@@ -15280,7 +15329,8 @@ class CodemodeClient {
|
|
|
15280
15329
|
...init,
|
|
15281
15330
|
headers: {
|
|
15282
15331
|
...Object.fromEntries(new Headers(init.headers).entries()),
|
|
15283
|
-
authorization: `Bearer ${token}
|
|
15332
|
+
authorization: `Bearer ${token}`,
|
|
15333
|
+
"x-opengeni-codemode-capabilities": "durable-approval-v1"
|
|
15284
15334
|
}
|
|
15285
15335
|
});
|
|
15286
15336
|
if (!response.ok && throwOnError) {
|
|
@@ -15419,7 +15469,7 @@ async function abortableDelay(delayMs, signal) {
|
|
|
15419
15469
|
// package.json
|
|
15420
15470
|
var package_default = {
|
|
15421
15471
|
name: "@opengeni/ogtool",
|
|
15422
|
-
version: "1.
|
|
15472
|
+
version: "1.3.0",
|
|
15423
15473
|
description: "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
|
|
15424
15474
|
license: "Apache-2.0",
|
|
15425
15475
|
repository: {
|
|
@@ -15549,6 +15599,8 @@ function usage(exitCode = 1) {
|
|
|
15549
15599
|
" [--query <substring>] [--limit <1..100>] [--offset <nonnegative integer>]",
|
|
15550
15600
|
" ogtool show <tool-path-or-model-name>",
|
|
15551
15601
|
" ogtool call <tool-path-or-model-name> [json-object]",
|
|
15602
|
+
" ogtool read <operation-id>",
|
|
15603
|
+
" ogtool resume <operation-id>",
|
|
15552
15604
|
" ogtool declarations [output-file]",
|
|
15553
15605
|
" ogtool doctor",
|
|
15554
15606
|
" ogtool --version",
|
|
@@ -15709,6 +15761,14 @@ async function main() {
|
|
|
15709
15761
|
throw new Error("usage: ogtool show <tool-path-or-model-name>");
|
|
15710
15762
|
}
|
|
15711
15763
|
const client = configuredClient();
|
|
15764
|
+
if (command === "read" || command === "resume") {
|
|
15765
|
+
if (args.length !== 1 || !/^[0-9a-f-]{36}$/iu.test(args[0]))
|
|
15766
|
+
throw new Error("A valid operation ID is required");
|
|
15767
|
+
const result = command === "read" ? await client.status(args[0]) : await client.resume(args[0]);
|
|
15768
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
15769
|
+
`);
|
|
15770
|
+
return;
|
|
15771
|
+
}
|
|
15712
15772
|
if (command === "list") {
|
|
15713
15773
|
const catalog = await client.catalog();
|
|
15714
15774
|
if (listOptions.full) {
|
|
@@ -15753,6 +15813,18 @@ async function main() {
|
|
|
15753
15813
|
return usage();
|
|
15754
15814
|
}
|
|
15755
15815
|
main().catch((error51) => {
|
|
15816
|
+
if (error51 instanceof CodemodeApprovalPendingError) {
|
|
15817
|
+
process.stdout.write(`${JSON.stringify({ operationId: error51.operationId, state: error51.state, code: error51.code, approvalRequestId: error51.approvalRequestId, message: error51.message })}
|
|
15818
|
+
`);
|
|
15819
|
+
process.exitCode = 2;
|
|
15820
|
+
return;
|
|
15821
|
+
}
|
|
15822
|
+
if (error51 instanceof CodemodeOperationError) {
|
|
15823
|
+
process.stdout.write(`${JSON.stringify({ operationId: error51.operation.operationId, state: error51.operation.state, code: error51.code, message: error51.message })}
|
|
15824
|
+
`);
|
|
15825
|
+
process.exitCode = error51.operation.state === "outcome_unknown" ? 3 : 1;
|
|
15826
|
+
return;
|
|
15827
|
+
}
|
|
15756
15828
|
const code = error51 && typeof error51 === "object" && "code" in error51 ? String(error51.code) : null;
|
|
15757
15829
|
process.stderr.write(`${error51 instanceof Error ? error51.message : String(error51)}
|
|
15758
15830
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/ogtool",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@opengeni/codemode": "1.
|
|
40
|
+
"@opengeni/codemode": "1.3.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18"
|
package/src/cli.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { readFileSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import {
|
|
4
4
|
CodemodeClient,
|
|
5
|
+
CodemodeApprovalPendingError,
|
|
6
|
+
CodemodeOperationError,
|
|
5
7
|
generateCodemodeDeclarations,
|
|
6
8
|
type AttemptToolCatalog,
|
|
7
9
|
type AttemptToolCatalogEntry,
|
|
@@ -19,6 +21,8 @@ function usage(exitCode = 1): void {
|
|
|
19
21
|
" [--query <substring>] [--limit <1..100>] [--offset <nonnegative integer>]",
|
|
20
22
|
" ogtool show <tool-path-or-model-name>",
|
|
21
23
|
" ogtool call <tool-path-or-model-name> [json-object]",
|
|
24
|
+
" ogtool read <operation-id>",
|
|
25
|
+
" ogtool resume <operation-id>",
|
|
22
26
|
" ogtool declarations [output-file]",
|
|
23
27
|
" ogtool doctor",
|
|
24
28
|
" ogtool --version",
|
|
@@ -197,6 +201,14 @@ async function main(): Promise<void> {
|
|
|
197
201
|
}
|
|
198
202
|
|
|
199
203
|
const client = configuredClient();
|
|
204
|
+
if (command === "read" || command === "resume") {
|
|
205
|
+
if (args.length !== 1 || !/^[0-9a-f-]{36}$/iu.test(args[0]!))
|
|
206
|
+
throw new Error("A valid operation ID is required");
|
|
207
|
+
const result =
|
|
208
|
+
command === "read" ? await client.status(args[0]!) : await client.resume(args[0]!);
|
|
209
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
200
212
|
if (command === "list") {
|
|
201
213
|
const catalog = await client.catalog();
|
|
202
214
|
if (listOptions!.full) {
|
|
@@ -240,6 +252,20 @@ async function main(): Promise<void> {
|
|
|
240
252
|
}
|
|
241
253
|
|
|
242
254
|
void main().catch((error: unknown) => {
|
|
255
|
+
if (error instanceof CodemodeApprovalPendingError) {
|
|
256
|
+
process.stdout.write(
|
|
257
|
+
`${JSON.stringify({ operationId: error.operationId, state: error.state, code: error.code, approvalRequestId: error.approvalRequestId, message: error.message })}\n`,
|
|
258
|
+
);
|
|
259
|
+
process.exitCode = 2;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (error instanceof CodemodeOperationError) {
|
|
263
|
+
process.stdout.write(
|
|
264
|
+
`${JSON.stringify({ operationId: error.operation.operationId, state: error.operation.state, code: error.code, message: error.message })}\n`,
|
|
265
|
+
);
|
|
266
|
+
process.exitCode = error.operation.state === "outcome_unknown" ? 3 : 1;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
243
269
|
const code =
|
|
244
270
|
error && typeof error === "object" && "code" in error
|
|
245
271
|
? String((error as { code: unknown }).code)
|