@skrr-ai/cli 0.1.21 → 0.1.23
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 +83 -73
- package/bin/dev-fallback.js +221 -0
- package/bin/run.js +43 -0
- package/dist/base-command.d.ts +15 -0
- package/dist/base-command.js +71 -10
- package/dist/commands/agents/attach-harness.d.ts +37 -0
- package/dist/commands/agents/attach-harness.js +102 -3
- package/dist/commands/agents/chat.d.ts +69 -1
- package/dist/commands/agents/chat.js +202 -22
- package/dist/commands/agents/create.d.ts +38 -0
- package/dist/commands/agents/create.js +95 -2
- package/dist/commands/agents/schedule-trace.js +11 -0
- package/dist/commands/agents/show.js +29 -1
- package/dist/commands/api-keys/create.d.ts +24 -0
- package/dist/commands/api-keys/create.js +80 -0
- package/dist/commands/api-keys/list.d.ts +11 -0
- package/dist/commands/api-keys/list.js +42 -0
- package/dist/commands/api-keys/revoke.d.ts +14 -0
- package/dist/commands/api-keys/revoke.js +33 -0
- package/dist/commands/api-keys/rotate.d.ts +19 -0
- package/dist/commands/api-keys/rotate.js +42 -0
- package/dist/commands/balance/index.d.ts +18 -0
- package/dist/commands/balance/index.js +29 -0
- package/dist/commands/balance/show.d.ts +25 -0
- package/dist/commands/balance/show.js +60 -0
- package/dist/commands/balance/statement.d.ts +19 -0
- package/dist/commands/balance/statement.js +52 -0
- package/dist/commands/browser/doctor.d.ts +11 -0
- package/dist/commands/browser/doctor.js +11 -0
- package/dist/commands/code/jobs/approve.d.ts +25 -0
- package/dist/commands/code/jobs/approve.js +52 -0
- package/dist/commands/code/jobs/cancel.d.ts +12 -0
- package/dist/commands/code/jobs/cancel.js +39 -0
- package/dist/commands/code/jobs/index.d.ts +19 -0
- package/dist/commands/code/jobs/index.js +38 -0
- package/dist/commands/code/jobs/list.d.ts +12 -0
- package/dist/commands/code/jobs/list.js +87 -0
- package/dist/commands/code/jobs/run.d.ts +32 -0
- package/dist/commands/code/jobs/run.js +151 -0
- package/dist/commands/code/jobs/show.d.ts +12 -0
- package/dist/commands/code/jobs/show.js +86 -0
- package/dist/commands/commitments/create.d.ts +1 -0
- package/dist/commands/commitments/create.js +19 -5
- package/dist/commands/commitments/preflight.js +18 -4
- package/dist/commands/commitments/receipt-metrics.d.ts +39 -0
- package/dist/commands/commitments/receipt-metrics.js +78 -0
- package/dist/commands/convos/search.js +5 -5
- package/dist/commands/harnesses/leases/list.d.ts +3 -0
- package/dist/commands/harnesses/leases/list.js +59 -12
- package/dist/commands/harnesses/leases/show.js +36 -0
- package/dist/commands/harnesses/list.d.ts +18 -0
- package/dist/commands/harnesses/list.js +30 -0
- package/dist/commands/harnesses/products.js +48 -3
- package/dist/commands/harnesses/quota.d.ts +16 -0
- package/dist/commands/harnesses/quota.js +26 -1
- package/dist/commands/harnesses/usage.js +17 -0
- package/dist/commands/inbox/index.d.ts +2 -1
- package/dist/commands/inbox/index.js +27 -4
- package/dist/commands/login.js +4 -1
- package/dist/commands/machines/list.d.ts +1 -0
- package/dist/commands/machines/list.js +33 -5
- package/dist/commands/memory/approvals/issue.d.ts +18 -0
- package/dist/commands/memory/approvals/issue.js +63 -0
- package/dist/commands/memory/commit.js +5 -2
- package/dist/commands/memory/context.d.ts +3 -2
- package/dist/commands/memory/context.js +9 -11
- package/dist/commands/memory/delete.d.ts +1 -1
- package/dist/commands/memory/list.d.ts +1 -1
- package/dist/commands/memory/list.js +1 -1
- package/dist/commands/memory/mounts/resolve.d.ts +10 -0
- package/dist/commands/memory/mounts/resolve.js +27 -0
- package/dist/commands/memory/proposals/commit.d.ts +18 -0
- package/dist/commands/memory/proposals/commit.js +32 -0
- package/dist/commands/memory/proposals/create.d.ts +18 -0
- package/dist/commands/memory/proposals/create.js +56 -0
- package/dist/commands/memory/proposals/list.d.ts +13 -0
- package/dist/commands/memory/proposals/list.js +31 -0
- package/dist/commands/memory/proposals/promote.d.ts +22 -0
- package/dist/commands/memory/proposals/promote.js +33 -0
- package/dist/commands/memory/proposals/reject.d.ts +16 -0
- package/dist/commands/memory/proposals/reject.js +28 -0
- package/dist/commands/memory/rebuild-index.d.ts +20 -0
- package/dist/commands/memory/rebuild-index.js +25 -0
- package/dist/commands/memory/save.d.ts +1 -1
- package/dist/commands/memory/save.js +1 -1
- package/dist/commands/memory/search.d.ts +6 -3
- package/dist/commands/memory/search.js +27 -3
- package/dist/commands/memory/show.d.ts +1 -1
- package/dist/commands/memory/stores/archive.d.ts +14 -0
- package/dist/commands/memory/stores/archive.js +31 -0
- package/dist/commands/memory/stores/create.d.ts +12 -0
- package/dist/commands/memory/stores/create.js +30 -0
- package/dist/commands/memory/stores/delete.d.ts +15 -0
- package/dist/commands/memory/stores/delete.js +38 -0
- package/dist/commands/memory/stores/list.d.ts +10 -0
- package/dist/commands/memory/stores/list.js +29 -0
- package/dist/commands/memory/stores/show.d.ts +12 -0
- package/dist/commands/memory/stores/show.js +14 -0
- package/dist/commands/memory/stores/update.d.ts +15 -0
- package/dist/commands/memory/stores/update.js +39 -0
- package/dist/commands/memory/sync/delete.d.ts +13 -0
- package/dist/commands/memory/sync/delete.js +35 -0
- package/dist/commands/memory/sync/pull.d.ts +19 -0
- package/dist/commands/memory/sync/pull.js +52 -0
- package/dist/commands/memory/sync/push.d.ts +18 -0
- package/dist/commands/memory/sync/push.js +115 -0
- package/dist/commands/memory/sync/resolve.d.ts +23 -0
- package/dist/commands/memory/sync/resolve.js +27 -0
- package/dist/commands/memory/sync/status.d.ts +9 -0
- package/dist/commands/memory/sync/status.js +22 -0
- package/dist/commands/memory/topics/archive.d.ts +20 -0
- package/dist/commands/memory/topics/archive.js +29 -0
- package/dist/commands/memory/topics/create.d.ts +23 -0
- package/dist/commands/memory/topics/create.js +46 -0
- package/dist/commands/memory/topics/delete.d.ts +22 -0
- package/dist/commands/memory/topics/delete.js +30 -0
- package/dist/commands/memory/topics/forget.d.ts +22 -0
- package/dist/commands/memory/topics/forget.js +29 -0
- package/dist/commands/memory/topics/list.d.ts +13 -0
- package/dist/commands/memory/topics/list.js +22 -0
- package/dist/commands/memory/topics/move.d.ts +22 -0
- package/dist/commands/memory/topics/move.js +26 -0
- package/dist/commands/memory/topics/show.d.ts +17 -0
- package/dist/commands/memory/topics/show.js +21 -0
- package/dist/commands/memory/topics/update.d.ts +23 -0
- package/dist/commands/memory/topics/update.js +27 -0
- package/dist/commands/memory/tree.d.ts +5 -2
- package/dist/commands/memory/tree.js +20 -2
- package/dist/commands/memory/update.d.ts +1 -1
- package/dist/commands/memory/versions/list.d.ts +16 -0
- package/dist/commands/memory/versions/list.js +22 -0
- package/dist/commands/memory/versions/redact.d.ts +21 -0
- package/dist/commands/memory/versions/redact.js +22 -0
- package/dist/commands/memory/versions/restore.d.ts +20 -0
- package/dist/commands/memory/versions/restore.js +16 -0
- package/dist/commands/memory/versions/show.d.ts +15 -0
- package/dist/commands/memory/versions/show.js +17 -0
- package/dist/commands/messages/list.js +25 -8
- package/dist/commands/messages/show.js +10 -0
- package/dist/commands/store/install.js +5 -1
- package/dist/commands/store/releases.js +1 -1
- package/dist/commands/store/update.js +5 -1
- package/dist/commands/subscriptions/cancel.js +5 -1
- package/dist/commands/subscriptions/health.js +5 -1
- package/dist/commands/subscriptions/status.js +5 -1
- package/dist/commands/subscriptions/subscribe.js +5 -1
- package/dist/commands/tasks/activity.d.ts +2 -3
- package/dist/commands/tasks/activity.js +15 -5
- package/dist/commands/tasks/complete.d.ts +18 -150
- package/dist/commands/tasks/complete.js +161 -600
- package/dist/commands/tasks/create.d.ts +5 -0
- package/dist/commands/tasks/create.js +107 -4
- package/dist/commands/tasks/deliverable/add.d.ts +8 -0
- package/dist/commands/tasks/deliverable/add.js +41 -8
- package/dist/commands/tasks/deliverable/confirm.d.ts +5 -5
- package/dist/commands/tasks/deliverable/confirm.js +9 -18
- package/dist/commands/tasks/deliverable/list.d.ts +12 -0
- package/dist/commands/tasks/deliverable/list.js +37 -0
- package/dist/commands/tasks/events/append.d.ts +2 -0
- package/dist/commands/tasks/events/append.js +11 -4
- package/dist/commands/tasks/events/list.d.ts +1 -0
- package/dist/commands/tasks/events/list.js +1 -0
- package/dist/commands/tasks/events/tail.d.ts +1 -0
- package/dist/commands/tasks/events/tail.js +1 -0
- package/dist/commands/tasks/expectations/assess.d.ts +21 -0
- package/dist/commands/tasks/expectations/assess.js +77 -0
- package/dist/commands/tasks/expectations.js +14 -18
- package/dist/commands/tasks/judge.d.ts +1 -0
- package/dist/commands/tasks/judge.js +2 -1
- package/dist/commands/tasks/output.d.ts +2 -11
- package/dist/commands/tasks/output.js +64 -145
- package/dist/commands/tasks/report.d.ts +3 -3
- package/dist/commands/tasks/report.js +64 -41
- package/dist/commands/tasks/resource/add.d.ts +23 -0
- package/dist/commands/tasks/resource/add.js +76 -0
- package/dist/commands/tasks/resource/list.d.ts +13 -0
- package/dist/commands/tasks/resource/list.js +41 -0
- package/dist/commands/tasks/result/show.d.ts +13 -0
- package/dist/commands/tasks/result/show.js +46 -0
- package/dist/commands/tasks/result/submit.d.ts +26 -0
- package/dist/commands/tasks/result/submit.js +134 -0
- package/dist/commands/tasks/resume/save.d.ts +16 -0
- package/dist/commands/tasks/resume/save.js +59 -0
- package/dist/commands/tasks/resume/show.d.ts +13 -0
- package/dist/commands/tasks/resume/show.js +35 -0
- package/dist/commands/tasks/review.d.ts +17 -0
- package/dist/commands/tasks/review.js +54 -0
- package/dist/commands/tasks/runs.js +5 -0
- package/dist/commands/tasks/timeline.d.ts +2 -2
- package/dist/commands/tasks/timeline.js +10 -23
- package/dist/commands/tasks/updates/add.d.ts +22 -0
- package/dist/commands/tasks/updates/add.js +101 -0
- package/dist/commands/tasks/updates/list.d.ts +15 -0
- package/dist/commands/tasks/updates/list.js +57 -0
- package/dist/commands/tasks/waive.d.ts +1 -0
- package/dist/commands/tasks/waive.js +2 -1
- package/dist/lib/agentic-stream.d.ts +257 -0
- package/dist/lib/agentic-stream.js +490 -33
- package/dist/lib/balance.d.ts +8 -0
- package/dist/lib/commitment-product.d.ts +10 -1
- package/dist/lib/commitment-product.js +66 -2
- package/dist/lib/commitments.d.ts +4 -1
- package/dist/lib/commitments.js +32 -1
- package/dist/lib/conversation-search.d.ts +3 -0
- package/dist/lib/conversation-search.js +75 -0
- package/dist/lib/execution-target.d.ts +21 -0
- package/dist/lib/execution-target.js +22 -6
- package/dist/lib/harnesses.d.ts +82 -6
- package/dist/lib/harnesses.js +30 -2
- package/dist/lib/hosted-machines.js +9 -0
- package/dist/lib/inbox.d.ts +2 -1
- package/dist/lib/machines.d.ts +17 -0
- package/dist/lib/machines.js +29 -0
- package/dist/lib/managed-agent-keys.d.ts +104 -0
- package/dist/lib/managed-agent-keys.js +50 -0
- package/dist/lib/memory-scope.d.ts +4 -3
- package/dist/lib/memory-scope.js +9 -9
- package/dist/lib/memory-sync.d.ts +114 -0
- package/dist/lib/memory-sync.js +730 -0
- package/dist/lib/message-provenance.d.ts +42 -0
- package/dist/lib/message-provenance.js +89 -0
- package/dist/lib/scoped-memory-command.d.ts +68 -0
- package/dist/lib/scoped-memory-command.js +183 -0
- package/dist/lib/session-task-endpoints.d.ts +1 -1
- package/dist/lib/session-task-endpoints.js +7 -0
- package/dist/lib/sky-code-broker.d.ts +47 -0
- package/dist/lib/sky-code-broker.js +50 -0
- package/dist/lib/sky-code-doctor.js +10 -1
- package/dist/lib/task-artifact-flags.d.ts +2 -0
- package/dist/lib/task-artifact-flags.js +7 -0
- package/dist/lib/task-execution.d.ts +4 -5
- package/dist/lib/task-execution.js +4 -5
- package/dist/lib/task-extras.d.ts +1 -5
- package/dist/lib/task-extras.js +1 -5
- package/dist/lib/task-transcript.d.ts +5 -7
- package/dist/lib/task-transcript.js +8 -16
- package/dist/lib/tasks.d.ts +7 -21
- package/dist/lib/tasks.js +17 -20
- package/dist/lib/triggers.d.ts +39 -1
- package/dist/lib/triggers.js +70 -2
- package/dist/lib/usage-discovery.d.ts +17 -1
- package/dist/lib/usage-discovery.js +17 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3733 -3618
- package/oclif.manifest.json +25726 -19886
- package/package.json +26 -5
package/dist/base-command.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.describeAssigneeNotInSpace = describeAssigneeNotInSpace;
|
|
|
10
10
|
exports.describeForbidden = describeForbidden;
|
|
11
11
|
exports.isDaemonScopedCredential = isDaemonScopedCredential;
|
|
12
12
|
exports.describeDaemonScopedCredential = describeDaemonScopedCredential;
|
|
13
|
+
exports.isTypedServerRefusal = isTypedServerRefusal;
|
|
13
14
|
exports.isRetryableFailure = isRetryableFailure;
|
|
14
15
|
const core_1 = require("@oclif/core");
|
|
15
16
|
Object.defineProperty(exports, "Flags", { enumerable: true, get: function () { return core_1.Flags; } });
|
|
@@ -936,6 +937,29 @@ class BaseCommand extends core_1.Command {
|
|
|
936
937
|
retryable: true,
|
|
937
938
|
});
|
|
938
939
|
}
|
|
940
|
+
else if (isTypedServerRefusal(body)) {
|
|
941
|
+
// A 5xx the server DELIBERATELY produced and described in its own
|
|
942
|
+
// words. Reaching the outage branch below made the CLI announce a
|
|
943
|
+
// platform outage for a per-conversation condition: "https://skrr.ai is
|
|
944
|
+
// not serving requests right now. This is a service outage, not a
|
|
945
|
+
// problem with your account or this command" — for
|
|
946
|
+
// `CONVERSATION_ADMISSION_OUTCOME_UNCONFIRMED`, while skrr.ai served
|
|
947
|
+
// every other command in the same minute, with the outer `retryable`
|
|
948
|
+
// reading true over an inner `false` (retrying was futile for ~35
|
|
949
|
+
// minutes). The reader is sent to a status page instead of learning
|
|
950
|
+
// that one conversation is parked (OSK-7719).
|
|
951
|
+
//
|
|
952
|
+
// So: the server's code, the server's words, and the server's verdict
|
|
953
|
+
// on whether retrying can help.
|
|
954
|
+
this.failWithCliError({
|
|
955
|
+
message: say(bodyMessage || e.message),
|
|
956
|
+
code: bodyCode || `HTTP_${e.status}`,
|
|
957
|
+
status: e.status,
|
|
958
|
+
exit: 1,
|
|
959
|
+
retryable: isRetryableFailure(e.status, body),
|
|
960
|
+
details: body ?? undefined,
|
|
961
|
+
});
|
|
962
|
+
}
|
|
939
963
|
else if ((0, outbox_1.isOutageFailure)(e)) {
|
|
940
964
|
// A gateway/unavailable status is an OUTAGE, and saying so is the whole
|
|
941
965
|
// point. During the OSK-2806 incident these surfaced as bare
|
|
@@ -955,11 +979,17 @@ class BaseCommand extends core_1.Command {
|
|
|
955
979
|
// predicate is what made a single route's 500 read as a platform
|
|
956
980
|
// outage.
|
|
957
981
|
this.noteControlPlaneOutage(e.status);
|
|
982
|
+
const method = e.method?.toUpperCase();
|
|
983
|
+
const readOnlyRequest = method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
|
|
984
|
+
const outcome = readOnlyRequest
|
|
985
|
+
? 'No write was attempted by this request; retry once the service recovers.'
|
|
986
|
+
: 'For a write, the gateway may have timed out after the server committed it. ' +
|
|
987
|
+
'The outcome is unknown — check the target or reconcile by idempotency key before retrying.';
|
|
958
988
|
this.failWithCliError({
|
|
959
989
|
message: say(`${this.cliConfig.baseURL} is not serving requests right now` +
|
|
960
990
|
`${e.status ? ` (HTTP ${e.status})` : ''}. ` +
|
|
961
991
|
'This is a service outage, not a problem with your account or this command. ' +
|
|
962
|
-
|
|
992
|
+
outcome),
|
|
963
993
|
code: 'CONTROL_PLANE_UNAVAILABLE',
|
|
964
994
|
status: e.status,
|
|
965
995
|
exit: 5,
|
|
@@ -1093,15 +1123,16 @@ class BaseCommand extends core_1.Command {
|
|
|
1093
1123
|
});
|
|
1094
1124
|
}
|
|
1095
1125
|
// Same discipline as `handleApiError`: only a real outage gets outage
|
|
1096
|
-
// wording
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1126
|
+
// wording. Even an edge 504 can arrive AFTER the application committed a
|
|
1127
|
+
// write, so neither branch claims nothing landed. A replay is safe because
|
|
1128
|
+
// the queued record carries an idempotency key, not because the first
|
|
1129
|
+
// attempt is assumed absent.
|
|
1100
1130
|
const outage = (0, outbox_1.isOutageFailure)(err);
|
|
1101
1131
|
const statusSuffix = e.status ? ` (HTTP ${e.status})` : '';
|
|
1102
1132
|
const lead = outage
|
|
1103
1133
|
? `${this.cliConfig.baseURL} is not serving requests right now${statusSuffix}. ` +
|
|
1104
|
-
`Your ${write.summary} was queued locally as ${queuedId}
|
|
1134
|
+
`Your ${write.summary} was queued locally as ${queuedId}; whether the server already ` +
|
|
1135
|
+
'applied the timed-out attempt is unknown, so verify before replaying.'
|
|
1105
1136
|
: `${this.cliConfig.baseURL} did not accept this write${statusSuffix}. ` +
|
|
1106
1137
|
`Your ${write.summary} was queued locally as ${queuedId}; whether the server applied ` +
|
|
1107
1138
|
'any of it is not reported, so verify before replaying.';
|
|
@@ -1341,15 +1372,23 @@ function describeAssigneeNotInSpace(serverMessage, bin = 'skrr') {
|
|
|
1341
1372
|
* Server-declared TERMINAL refusals: a state conflict the caller must resolve
|
|
1342
1373
|
* by doing something DIFFERENT, never by repeating the identical request.
|
|
1343
1374
|
*
|
|
1344
|
-
* `skrr tasks move --status done`
|
|
1345
|
-
*
|
|
1375
|
+
* `skrr tasks move --status done` with no current Result or independent Review
|
|
1376
|
+
* returns a typed 409. 409 used to be in the
|
|
1346
1377
|
* transient set below, so the JSON envelope said `retryable: true` — and
|
|
1347
1378
|
* `daemon/CLAUDE.md` tells daemon-hosted agents to retry retryable errors, so
|
|
1348
1379
|
* they looped on a refusal that can never succeed on retry. The refusal names
|
|
1349
|
-
* the supported path (`
|
|
1380
|
+
* the supported path (`skrr tasks complete`, Result, then Review); the
|
|
1350
1381
|
* envelope has to agree that the ONLY way forward is that path.
|
|
1351
1382
|
*/
|
|
1352
|
-
const TERMINAL_ERROR_CODES = new Set([
|
|
1383
|
+
const TERMINAL_ERROR_CODES = new Set([
|
|
1384
|
+
'TASK_RESULT_REQUIRED',
|
|
1385
|
+
'TASK_CURRENT_RESULT_MISSING',
|
|
1386
|
+
'TASK_RESULT_SPEC_VERSION_MISMATCH',
|
|
1387
|
+
'TASK_EXPECTATIONS_NOT_MET',
|
|
1388
|
+
'TASK_RESULT_CHANGES_REQUESTED',
|
|
1389
|
+
'TASK_RESULT_REVIEW_REQUIRED',
|
|
1390
|
+
'TASK_DELIVERY_NOT_INTEGRATED',
|
|
1391
|
+
]);
|
|
1353
1392
|
/**
|
|
1354
1393
|
* Whether an automated retry of the IDENTICAL request could plausibly succeed.
|
|
1355
1394
|
*
|
|
@@ -1451,6 +1490,28 @@ function describeDaemonScopedCredential(bin, scope = 'daemon', source) {
|
|
|
1451
1490
|
return (`${subject}, which cannot access user API commands. ` +
|
|
1452
1491
|
`Run \`${bin} login\` to create a CLI credential. For the local runtime itself, use \`${bin} daemon login\`.`);
|
|
1453
1492
|
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Did the server MEAN this 5xx, or did it fall over?
|
|
1495
|
+
*
|
|
1496
|
+
* An outage and a designed refusal arrive with the same status and want
|
|
1497
|
+
* opposite reactions — wait for recovery, versus act on a condition. The
|
|
1498
|
+
* discriminator is whether the server authored an answer: a typed `code` plus
|
|
1499
|
+
* either an explanation it wrote (`cause` / `remedy`, both of which the 5xx
|
|
1500
|
+
* redaction boundary deliberately lets through) or an explicit verdict that
|
|
1501
|
+
* retrying will not help.
|
|
1502
|
+
*
|
|
1503
|
+
* Deliberately NOT folded into `isOutageFailure`: that predicate also gates the
|
|
1504
|
+
* outbox queue decision and `noteControlPlaneOutage`, and those ask a different
|
|
1505
|
+
* question. Merging the two is the mistake its own comment warns about.
|
|
1506
|
+
*/
|
|
1507
|
+
function isTypedServerRefusal(body) {
|
|
1508
|
+
if (!body || typeof body !== 'object')
|
|
1509
|
+
return false;
|
|
1510
|
+
const code = stringProp(body, 'code') || stringProp(body, 'errorType');
|
|
1511
|
+
if (!code)
|
|
1512
|
+
return false;
|
|
1513
|
+
return (typeof body.cause === 'string' || typeof body.remedy === 'string' || body.retryable === false);
|
|
1514
|
+
}
|
|
1454
1515
|
function isRetryableFailure(status, body) {
|
|
1455
1516
|
const declared = body?.retryable;
|
|
1456
1517
|
if (typeof declared === 'boolean')
|
|
@@ -1,15 +1,52 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Sort two positionals into (harness, agent), whichever order they were typed.
|
|
4
|
+
*
|
|
5
|
+
* The discriminator is the id SHAPE, not the position: an agent id is
|
|
6
|
+
* `agent_…`, and nothing else this command accepts is. That covers the reported
|
|
7
|
+
* mistake exactly — `attach-harness <agent> <harness>` — without guessing when
|
|
8
|
+
* neither value looks like an agent.
|
|
9
|
+
*
|
|
10
|
+
* Returns `{ error }` rather than picking, when the two sources disagree.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveAttachPositionals(first: string, second: string | undefined, agentFlag: string | undefined): {
|
|
13
|
+
harness: string;
|
|
14
|
+
agent?: string;
|
|
15
|
+
error?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
error: string;
|
|
18
|
+
harness?: undefined;
|
|
19
|
+
};
|
|
2
20
|
export default class AgentsAttachHarness extends BaseCommand {
|
|
3
21
|
static description: string;
|
|
4
22
|
static examples: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Which positional is which, when a caller gave two.
|
|
25
|
+
*
|
|
26
|
+
* This is the ONLY command in the `agents` topic whose positional is not the
|
|
27
|
+
* agent — every neighbour is `agents <verb> <agent-id> [args]`, and the
|
|
28
|
+
* space's own Execution Map documents `attach-harness <agent> <harness>`. A
|
|
29
|
+
* caller writing that shape had their agent id silently accepted AS THE
|
|
30
|
+
* HARNESS and the real harness rejected with `Unexpected argument:
|
|
31
|
+
* 6a985ed2…` — an error that names the argument it does not want, never says
|
|
32
|
+
* what it does want, and does not notice that the value it accepted is
|
|
33
|
+
* obviously an `agent_…` id (OSK-7686).
|
|
34
|
+
*
|
|
35
|
+
* So both orders work, decided by the shape of the ids rather than by
|
|
36
|
+
* position. An explicit `--agent` still wins, and a conflict is refused
|
|
37
|
+
* rather than silently resolved — being attached to the wrong machine is the
|
|
38
|
+
* wrong way to find out which one was meant.
|
|
39
|
+
*/
|
|
5
40
|
static args: {
|
|
6
41
|
harness: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
42
|
+
agent: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
43
|
};
|
|
8
44
|
static flags: {
|
|
9
45
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
46
|
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
47
|
'next-target': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
48
|
'advance-on': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
49
|
+
'strict-order': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
50
|
'rebind-tasks': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
14
51
|
};
|
|
15
52
|
run(): Promise<void>;
|
|
@@ -1,10 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAttachPositionals = resolveAttachPositionals;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../base-command");
|
|
6
7
|
const execution_target_1 = require("../../lib/execution-target");
|
|
7
8
|
const agent_resolver_1 = require("../../lib/agent-resolver");
|
|
9
|
+
/**
|
|
10
|
+
* Sort two positionals into (harness, agent), whichever order they were typed.
|
|
11
|
+
*
|
|
12
|
+
* The discriminator is the id SHAPE, not the position: an agent id is
|
|
13
|
+
* `agent_…`, and nothing else this command accepts is. That covers the reported
|
|
14
|
+
* mistake exactly — `attach-harness <agent> <harness>` — without guessing when
|
|
15
|
+
* neither value looks like an agent.
|
|
16
|
+
*
|
|
17
|
+
* Returns `{ error }` rather than picking, when the two sources disagree.
|
|
18
|
+
*/
|
|
19
|
+
function resolveAttachPositionals(first, second, agentFlag) {
|
|
20
|
+
const isAgentId = (value) => !!value && value.startsWith('agent_');
|
|
21
|
+
let harness = first;
|
|
22
|
+
let agent = second;
|
|
23
|
+
if (second && isAgentId(first) && !isAgentId(second)) {
|
|
24
|
+
harness = second;
|
|
25
|
+
agent = first;
|
|
26
|
+
}
|
|
27
|
+
else if (second && isAgentId(first) && isAgentId(second)) {
|
|
28
|
+
return {
|
|
29
|
+
error: `Both positionals look like agent ids ("${first}", "${second}"). ` +
|
|
30
|
+
'Pass one agent and one harness: `agents attach-harness <harness> --agent <agent>`.',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (agent && agentFlag && agent !== agentFlag) {
|
|
34
|
+
return {
|
|
35
|
+
error: `Conflicting agents: "${agent}" (positional) and "${agentFlag}" (--agent). Pass one. ` +
|
|
36
|
+
'Attaching to the wrong machine is the wrong way to find out which was meant.',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (isAgentId(harness)) {
|
|
40
|
+
return {
|
|
41
|
+
error: `"${harness}" is an agent id, not a harness. This command takes the harness first: ` +
|
|
42
|
+
'`agents attach-harness <harness> --agent <agent>`. ' +
|
|
43
|
+
'List harnesses with `skrr harnesses list --all`.',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { harness, ...(agent ? { agent } : {}) };
|
|
47
|
+
}
|
|
8
48
|
class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
9
49
|
static description = 'Attach a harness to an agent';
|
|
10
50
|
static examples = [
|
|
@@ -18,6 +58,23 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
18
58
|
// local-daemon user — a dead end at the exact moment the id is needed.
|
|
19
59
|
// `harnesses list` is the command that surfaces daemon-registered harness
|
|
20
60
|
// _ids (see cli/src/commands/harnesses/list.ts).
|
|
61
|
+
/**
|
|
62
|
+
* Which positional is which, when a caller gave two.
|
|
63
|
+
*
|
|
64
|
+
* This is the ONLY command in the `agents` topic whose positional is not the
|
|
65
|
+
* agent — every neighbour is `agents <verb> <agent-id> [args]`, and the
|
|
66
|
+
* space's own Execution Map documents `attach-harness <agent> <harness>`. A
|
|
67
|
+
* caller writing that shape had their agent id silently accepted AS THE
|
|
68
|
+
* HARNESS and the real harness rejected with `Unexpected argument:
|
|
69
|
+
* 6a985ed2…` — an error that names the argument it does not want, never says
|
|
70
|
+
* what it does want, and does not notice that the value it accepted is
|
|
71
|
+
* obviously an `agent_…` id (OSK-7686).
|
|
72
|
+
*
|
|
73
|
+
* So both orders work, decided by the shape of the ids rather than by
|
|
74
|
+
* position. An explicit `--agent` still wins, and a conflict is refused
|
|
75
|
+
* rather than silently resolved — being attached to the wrong machine is the
|
|
76
|
+
* wrong way to find out which one was meant.
|
|
77
|
+
*/
|
|
21
78
|
static args = {
|
|
22
79
|
harness: core_1.Args.string({
|
|
23
80
|
description: 'Harness id. Use sbs_... for a Hosted Machine session, hosted-machine for the default Hosted Machine product, agent-worker for the cloud worker, or a harness id. ' +
|
|
@@ -25,6 +82,12 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
25
82
|
required: true,
|
|
26
83
|
ignoreStdin: true,
|
|
27
84
|
}),
|
|
85
|
+
agent: core_1.Args.string({
|
|
86
|
+
description: 'Optional second positional, so `agents attach-harness <agent> <harness>` — the shape ' +
|
|
87
|
+
'every other agents command uses — works. Equivalent to --agent.',
|
|
88
|
+
required: false,
|
|
89
|
+
ignoreStdin: true,
|
|
90
|
+
}),
|
|
28
91
|
};
|
|
29
92
|
static flags = {
|
|
30
93
|
json: core_1.Flags.boolean({ description: 'Output the attachment result as JSON' }),
|
|
@@ -36,10 +99,23 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
36
99
|
multiple: true,
|
|
37
100
|
}),
|
|
38
101
|
'advance-on': core_1.Flags.string({
|
|
39
|
-
description: 'Failure category that permits
|
|
102
|
+
description: 'Failure category that permits EACH non-final target to advance to the next one. ' +
|
|
103
|
+
// The flag read as an explicit opt-in, so omitting it looked like
|
|
104
|
+
// opting into nothing — and the server was writing
|
|
105
|
+
// `["offline","unavailable"]` on a target the caller had explicitly
|
|
106
|
+
// pinned, with nothing in --help or in either command's output saying
|
|
107
|
+
// so (OSK-7669).
|
|
108
|
+
'Defaults to `offline unavailable` when omitted and a next target exists; ' +
|
|
109
|
+
'pass --strict-order for a chain no failure may advance. ' +
|
|
110
|
+
'Applies to every non-final target, not only the one named here.',
|
|
40
111
|
multiple: true,
|
|
41
112
|
options: [...execution_target_1.EXECUTION_TARGET_ADVANCE_REASONS],
|
|
42
113
|
}),
|
|
114
|
+
'strict-order': core_1.Flags.boolean({
|
|
115
|
+
description: 'No failure category permits an advance. The declared next targets stay recorded but ' +
|
|
116
|
+
'the chain never moves — previously only expressible by hand-writing executionPolicy ' +
|
|
117
|
+
'through --from-json.',
|
|
118
|
+
}),
|
|
43
119
|
'rebind-tasks': core_1.Flags.boolean({
|
|
44
120
|
description: 'Publish the updated agent release and migrate dormant assigned task pins to it. Running, review, and completed tasks are never changed.',
|
|
45
121
|
}),
|
|
@@ -47,9 +123,20 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
47
123
|
async run() {
|
|
48
124
|
this.requireAuth();
|
|
49
125
|
const { args, flags } = await this.parse(AgentsAttachHarness);
|
|
126
|
+
const positional = resolveAttachPositionals(args.harness, args.agent, flags.agent);
|
|
127
|
+
if (positional.error) {
|
|
128
|
+
this.failWithCliError({
|
|
129
|
+
message: positional.error,
|
|
130
|
+
code: 'ATTACH_HARNESS_ARGUMENTS',
|
|
131
|
+
exit: 2,
|
|
132
|
+
retryable: false,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
const harnessArg = positional.harness;
|
|
136
|
+
const agentArg = positional.agent;
|
|
50
137
|
let agentIdentity;
|
|
51
138
|
try {
|
|
52
|
-
agentIdentity = await (0, agent_resolver_1.resolveAgentIdentity)(flags.agent);
|
|
139
|
+
agentIdentity = await (0, agent_resolver_1.resolveAgentIdentity)(flags.agent || agentArg);
|
|
53
140
|
}
|
|
54
141
|
catch (err) {
|
|
55
142
|
const failure = (0, agent_resolver_1.agentResolutionFailure)(err);
|
|
@@ -66,8 +153,9 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
66
153
|
let patch;
|
|
67
154
|
try {
|
|
68
155
|
patch = (0, execution_target_1.buildExecutionOrderPatch)({
|
|
69
|
-
selectors: [
|
|
156
|
+
selectors: [harnessArg, ...(flags['next-target'] || [])],
|
|
70
157
|
advanceOn: flags['advance-on'],
|
|
158
|
+
strict: flags['strict-order'],
|
|
71
159
|
});
|
|
72
160
|
}
|
|
73
161
|
catch (err) {
|
|
@@ -110,6 +198,17 @@ class AgentsAttachHarness extends base_command_1.BaseCommand {
|
|
|
110
198
|
this.log(`Agent resolved from ${agentIdentity.source}.`);
|
|
111
199
|
}
|
|
112
200
|
this.log(`Execution order: ${targets.map(executionTargetSelector).join(' → ')}`);
|
|
201
|
+
// Print the policy that was actually written. A default the operator did
|
|
202
|
+
// not ask for and cannot see is one they will not know they have — the
|
|
203
|
+
// only way to find it was to diff the returned JSON against what was typed
|
|
204
|
+
// (OSK-7669).
|
|
205
|
+
for (const [index, target] of targets.entries()) {
|
|
206
|
+
const advance = Array.isArray(target.advanceOn) ? target.advanceOn : [];
|
|
207
|
+
this.log(` ${index + 1}. ${executionTargetSelector(target)} — ` +
|
|
208
|
+
(advance.length > 0
|
|
209
|
+
? `may advance on: ${advance.join(', ')}`
|
|
210
|
+
: 'strict: no failure permits an advance'));
|
|
211
|
+
}
|
|
113
212
|
const migration = updated?.harnessAttachment;
|
|
114
213
|
if (migration) {
|
|
115
214
|
this.log(`Published release ${migration.releaseId || 'unknown'} and rebound ` +
|
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
-
import { type AgenticStreamResult } from '../../lib/agentic-stream';
|
|
2
|
+
import { type AgenticStreamResult, type ReconciledTerminal } from '../../lib/agentic-stream';
|
|
3
|
+
/**
|
|
4
|
+
* Exit code for a run the USER stopped watching, by pressing Ctrl-C.
|
|
5
|
+
*
|
|
6
|
+
* OSK-2944 established that exiting 1 on a lost stream made "the run failed"
|
|
7
|
+
* and "we lost the view of a live run" indistinguishable, and invited duplicate
|
|
8
|
+
* execution. So a detach gets its own non-zero code.
|
|
9
|
+
*
|
|
10
|
+
* It must be non-zero on EVERY output mode. The `--jsonl` branch used to
|
|
11
|
+
* `return` here, which leaves the exit code at 0, so a script driving the CLI
|
|
12
|
+
* read a detached — possibly already-failed — run as a success. That is the
|
|
13
|
+
* mode automation actually uses.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DETACH_EXIT_CODE = 130;
|
|
16
|
+
/**
|
|
17
|
+
* Exit code for a detach nobody asked for — the stream was lost, or could not
|
|
18
|
+
* be attached at all.
|
|
19
|
+
*
|
|
20
|
+
* 130 is the conventional "killed by SIGINT" code, and it was returned for a
|
|
21
|
+
* detach that no signal caused: a script reading it concludes the user pressed
|
|
22
|
+
* Ctrl-C, which is the opposite of what happened (OSK-7660). Reserving 130 for
|
|
23
|
+
* an actual interrupt and giving the unattended case its own code keeps both
|
|
24
|
+
* answers true.
|
|
25
|
+
*/
|
|
26
|
+
export declare const STREAM_LOST_EXIT_CODE = 75;
|
|
27
|
+
/**
|
|
28
|
+
* What to say when the user pressed Ctrl-C and the run did not stop.
|
|
29
|
+
*
|
|
30
|
+
* A cancel is REQUESTED over the session; whether the harness honours it is not
|
|
31
|
+
* something this process can guarantee. Measured on a local harness, where the
|
|
32
|
+
* answer is checkable with `ps`: the CLI exited, and the shell and the `sleep
|
|
33
|
+
* 200` it had spawned were still alive at +10s, +26s and +53s — while the CLI
|
|
34
|
+
* said nothing about it at all (OSK-7733). Three things compound there: work
|
|
35
|
+
* the user asked to stop keeps consuming their machine and their vendor tokens;
|
|
36
|
+
* they are not told, so they will not go and kill it; and the record is left
|
|
37
|
+
* `unfinished: true` with no error, so the cancellation is invisible in history
|
|
38
|
+
* too.
|
|
39
|
+
*
|
|
40
|
+
* Silence is the one unacceptable option, because the user will believe they
|
|
41
|
+
* cancelled. This says what was asked, what is not guaranteed, and how to look.
|
|
42
|
+
*/
|
|
43
|
+
export declare function interruptedDetachMessage(input: {
|
|
44
|
+
sessionId: string;
|
|
45
|
+
conversationId?: string | null;
|
|
46
|
+
}): string;
|
|
47
|
+
/**
|
|
48
|
+
* What the durable record says about a turn, read from its messages.
|
|
49
|
+
*
|
|
50
|
+
* The stream is not the only witness and must not be the only one consulted: a
|
|
51
|
+
* run refused during admission writes `error: true` plus the reason on the
|
|
52
|
+
* response message and never closes the session stream, so a joined subscriber
|
|
53
|
+
* waits forever for an event that will not come (OSK-7624, OSK-7635, OSK-7720,
|
|
54
|
+
* OSK-7735). Exported as a pure function so the mapping from a message row to a
|
|
55
|
+
* terminal verdict is testable without a socket.
|
|
56
|
+
*
|
|
57
|
+
* Returns null while the row is still in flight — the caller keeps waiting,
|
|
58
|
+
* because a long tool call is silence, not a failure.
|
|
59
|
+
*/
|
|
60
|
+
export declare function reconcileTerminalFromMessages(messages: ReadonlyArray<Record<string, unknown>>, responseMessageId?: string): ReconciledTerminal | null;
|
|
61
|
+
/**
|
|
62
|
+
* How to look at a turn the CLI is no longer watching.
|
|
63
|
+
*
|
|
64
|
+
* NOT `skrr agents chat --conversation <id>`, which is what this used to print:
|
|
65
|
+
* that command requires the `agentId` argument and `--prompt`, so it exits with
|
|
66
|
+
* `Missing 1 required arg: agentId` and never reattaches. A recovery
|
|
67
|
+
* instruction that cannot be run is worse than none — it costs the reader a
|
|
68
|
+
* round trip to discover the product was wrong.
|
|
69
|
+
*/
|
|
70
|
+
export declare function inspectTurnCommand(conversationId?: string | null): string;
|
|
3
71
|
/**
|
|
4
72
|
* A terminal run that produced no text is NOT a success to report silently.
|
|
5
73
|
*
|