@skrr-ai/cli 0.1.22 → 0.1.24
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 +96 -0
- package/dist/base-command.d.ts +15 -0
- package/dist/base-command.js +145 -11
- 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/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 +49 -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/dedicated/create.d.ts +18 -0
- package/dist/commands/machines/dedicated/create.js +90 -0
- package/dist/commands/machines/dedicated/destroy.d.ts +14 -0
- package/dist/commands/machines/dedicated/destroy.js +56 -0
- package/dist/commands/machines/dedicated/grow.d.ts +13 -0
- package/dist/commands/machines/dedicated/grow.js +46 -0
- package/dist/commands/machines/dedicated/health-check.d.ts +12 -0
- package/dist/commands/machines/dedicated/health-check.js +42 -0
- package/dist/commands/machines/dedicated/incident-close.d.ts +12 -0
- package/dist/commands/machines/dedicated/incident-close.js +42 -0
- package/dist/commands/machines/dedicated/index.d.ts +6 -0
- package/dist/commands/machines/dedicated/index.js +39 -0
- package/dist/commands/machines/dedicated/list.d.ts +11 -0
- package/dist/commands/machines/dedicated/list.js +58 -0
- package/dist/commands/machines/dedicated/restart.d.ts +12 -0
- package/dist/commands/machines/dedicated/restart.js +42 -0
- package/dist/commands/machines/dedicated/show.d.ts +12 -0
- package/dist/commands/machines/dedicated/show.js +58 -0
- package/dist/commands/machines/dedicated/snapshot.d.ts +12 -0
- package/dist/commands/machines/dedicated/snapshot.js +42 -0
- package/dist/commands/machines/dedicated/start.d.ts +12 -0
- package/dist/commands/machines/dedicated/start.js +42 -0
- package/dist/commands/machines/dedicated/stop.d.ts +12 -0
- package/dist/commands/machines/dedicated/stop.js +42 -0
- package/dist/commands/machines/hosted/index.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/spaces/update.js +16 -12
- package/dist/commands/spaces/work-sync/reconcile.d.ts +38 -0
- package/dist/commands/spaces/work-sync/reconcile.js +90 -0
- package/dist/commands/spaces/work-sync/telemetry.d.ts +29 -0
- package/dist/commands/spaces/work-sync/telemetry.js +96 -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 +20 -6
- package/dist/commands/tasks/complete.d.ts +22 -150
- package/dist/commands/tasks/complete.js +174 -599
- package/dist/commands/tasks/create.d.ts +6 -0
- package/dist/commands/tasks/create.js +114 -4
- package/dist/commands/tasks/deliverable/add.d.ts +8 -0
- package/dist/commands/tasks/deliverable/add.js +62 -11
- 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 +58 -0
- package/dist/commands/tasks/events/append.d.ts +2 -0
- package/dist/commands/tasks/events/append.js +41 -6
- 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 +103 -0
- package/dist/commands/tasks/expectations.js +121 -25
- package/dist/commands/tasks/judge.d.ts +1 -0
- package/dist/commands/tasks/judge.js +2 -1
- package/dist/commands/tasks/output.d.ts +1 -11
- package/dist/commands/tasks/output.js +80 -141
- package/dist/commands/tasks/report.d.ts +3 -3
- package/dist/commands/tasks/report.js +66 -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 +64 -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 +69 -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/self-schedule.js +7 -4
- package/dist/commands/tasks/show.js +19 -0
- package/dist/commands/tasks/timeline.d.ts +2 -2
- package/dist/commands/tasks/timeline.js +19 -24
- package/dist/commands/tasks/updates/add.d.ts +22 -0
- package/dist/commands/tasks/updates/add.js +122 -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 +2 -1
- package/dist/lib/commitments.js +1 -0
- package/dist/lib/conversation-search.d.ts +3 -0
- package/dist/lib/conversation-search.js +75 -0
- package/dist/lib/dedicated-machines.d.ts +66 -0
- package/dist/lib/dedicated-machines.js +161 -0
- package/dist/lib/execution-target.d.ts +21 -0
- package/dist/lib/execution-target.js +22 -6
- package/dist/lib/harnesses.d.ts +87 -6
- package/dist/lib/harnesses.js +32 -1
- 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-legacy.d.ts +24 -0
- package/dist/lib/task-legacy.js +48 -0
- package/dist/lib/task-transcript.d.ts +5 -7
- package/dist/lib/task-transcript.js +8 -16
- package/dist/lib/tasks.d.ts +39 -21
- package/dist/lib/tasks.js +64 -21
- 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/lib/work-sync.d.ts +70 -0
- package/dist/lib/work-sync.js +29 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3760 -3621
- package/oclif.manifest.json +14653 -7813
- package/package.json +26 -5
package/dist/base-command.d.ts
CHANGED
|
@@ -387,5 +387,20 @@ type IncompatibleCliCredentialScope = 'daemon' | 'daemon-install';
|
|
|
387
387
|
export declare function isDaemonScopedCredential(token?: string | null): boolean;
|
|
388
388
|
/** The one repair for a machine-only token passed to a human CLI command. */
|
|
389
389
|
export declare function describeDaemonScopedCredential(bin: string, scope?: IncompatibleCliCredentialScope, source?: ResolvedCredential['source']): string;
|
|
390
|
+
/**
|
|
391
|
+
* Did the server MEAN this 5xx, or did it fall over?
|
|
392
|
+
*
|
|
393
|
+
* An outage and a designed refusal arrive with the same status and want
|
|
394
|
+
* opposite reactions — wait for recovery, versus act on a condition. The
|
|
395
|
+
* discriminator is whether the server authored an answer: a typed `code` plus
|
|
396
|
+
* either an explanation it wrote (`cause` / `remedy`, both of which the 5xx
|
|
397
|
+
* redaction boundary deliberately lets through) or an explicit verdict that
|
|
398
|
+
* retrying will not help.
|
|
399
|
+
*
|
|
400
|
+
* Deliberately NOT folded into `isOutageFailure`: that predicate also gates the
|
|
401
|
+
* outbox queue decision and `noteControlPlaneOutage`, and those ask a different
|
|
402
|
+
* question. Merging the two is the mistake its own comment warns about.
|
|
403
|
+
*/
|
|
404
|
+
export declare function isTypedServerRefusal(body: Record<string, unknown> | null): boolean;
|
|
390
405
|
export declare function isRetryableFailure(status: number | undefined, body: Record<string, unknown> | null): boolean;
|
|
391
406
|
export { Flags };
|
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; } });
|
|
@@ -751,6 +752,14 @@ class BaseCommand extends core_1.Command {
|
|
|
751
752
|
if (isOclifExitError(err)) {
|
|
752
753
|
return super.catch(err);
|
|
753
754
|
}
|
|
755
|
+
// Canonical Task Model v1 removed several `tasks complete` flags outright,
|
|
756
|
+
// so a caller following older instructions — including the managed block the
|
|
757
|
+
// platform itself installed — got a bare `Nonexistent flags:` with no hint
|
|
758
|
+
// that the capability moved rather than vanished. Name where each went.
|
|
759
|
+
const retiredHint = retiredFlagHint(err.message || '');
|
|
760
|
+
if (retiredHint) {
|
|
761
|
+
err.message = `${err.message}\n\n${retiredHint}`;
|
|
762
|
+
}
|
|
754
763
|
if (this.wantsJsonOutput()) {
|
|
755
764
|
const exit = err.exitCode ?? err.oclif?.exit ?? 1;
|
|
756
765
|
process.exitCode = exit;
|
|
@@ -936,6 +945,29 @@ class BaseCommand extends core_1.Command {
|
|
|
936
945
|
retryable: true,
|
|
937
946
|
});
|
|
938
947
|
}
|
|
948
|
+
else if (isTypedServerRefusal(body)) {
|
|
949
|
+
// A 5xx the server DELIBERATELY produced and described in its own
|
|
950
|
+
// words. Reaching the outage branch below made the CLI announce a
|
|
951
|
+
// platform outage for a per-conversation condition: "https://skrr.ai is
|
|
952
|
+
// not serving requests right now. This is a service outage, not a
|
|
953
|
+
// problem with your account or this command" — for
|
|
954
|
+
// `CONVERSATION_ADMISSION_OUTCOME_UNCONFIRMED`, while skrr.ai served
|
|
955
|
+
// every other command in the same minute, with the outer `retryable`
|
|
956
|
+
// reading true over an inner `false` (retrying was futile for ~35
|
|
957
|
+
// minutes). The reader is sent to a status page instead of learning
|
|
958
|
+
// that one conversation is parked (OSK-7719).
|
|
959
|
+
//
|
|
960
|
+
// So: the server's code, the server's words, and the server's verdict
|
|
961
|
+
// on whether retrying can help.
|
|
962
|
+
this.failWithCliError({
|
|
963
|
+
message: say(bodyMessage || e.message),
|
|
964
|
+
code: bodyCode || `HTTP_${e.status}`,
|
|
965
|
+
status: e.status,
|
|
966
|
+
exit: 1,
|
|
967
|
+
retryable: isRetryableFailure(e.status, body),
|
|
968
|
+
details: body ?? undefined,
|
|
969
|
+
});
|
|
970
|
+
}
|
|
939
971
|
else if ((0, outbox_1.isOutageFailure)(e)) {
|
|
940
972
|
// A gateway/unavailable status is an OUTAGE, and saying so is the whole
|
|
941
973
|
// point. During the OSK-2806 incident these surfaced as bare
|
|
@@ -955,11 +987,17 @@ class BaseCommand extends core_1.Command {
|
|
|
955
987
|
// predicate is what made a single route's 500 read as a platform
|
|
956
988
|
// outage.
|
|
957
989
|
this.noteControlPlaneOutage(e.status);
|
|
990
|
+
const method = e.method?.toUpperCase();
|
|
991
|
+
const readOnlyRequest = method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
|
|
992
|
+
const outcome = readOnlyRequest
|
|
993
|
+
? 'No write was attempted by this request; retry once the service recovers.'
|
|
994
|
+
: 'For a write, the gateway may have timed out after the server committed it. ' +
|
|
995
|
+
'The outcome is unknown — check the target or reconcile by idempotency key before retrying.';
|
|
958
996
|
this.failWithCliError({
|
|
959
997
|
message: say(`${this.cliConfig.baseURL} is not serving requests right now` +
|
|
960
998
|
`${e.status ? ` (HTTP ${e.status})` : ''}. ` +
|
|
961
999
|
'This is a service outage, not a problem with your account or this command. ' +
|
|
962
|
-
|
|
1000
|
+
outcome),
|
|
963
1001
|
code: 'CONTROL_PLANE_UNAVAILABLE',
|
|
964
1002
|
status: e.status,
|
|
965
1003
|
exit: 5,
|
|
@@ -1093,15 +1131,16 @@ class BaseCommand extends core_1.Command {
|
|
|
1093
1131
|
});
|
|
1094
1132
|
}
|
|
1095
1133
|
// Same discipline as `handleApiError`: only a real outage gets outage
|
|
1096
|
-
// wording
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1134
|
+
// wording. Even an edge 504 can arrive AFTER the application committed a
|
|
1135
|
+
// write, so neither branch claims nothing landed. A replay is safe because
|
|
1136
|
+
// the queued record carries an idempotency key, not because the first
|
|
1137
|
+
// attempt is assumed absent.
|
|
1100
1138
|
const outage = (0, outbox_1.isOutageFailure)(err);
|
|
1101
1139
|
const statusSuffix = e.status ? ` (HTTP ${e.status})` : '';
|
|
1102
1140
|
const lead = outage
|
|
1103
1141
|
? `${this.cliConfig.baseURL} is not serving requests right now${statusSuffix}. ` +
|
|
1104
|
-
`Your ${write.summary} was queued locally as ${queuedId}
|
|
1142
|
+
`Your ${write.summary} was queued locally as ${queuedId}; whether the server already ` +
|
|
1143
|
+
'applied the timed-out attempt is unknown, so verify before replaying.'
|
|
1105
1144
|
: `${this.cliConfig.baseURL} did not accept this write${statusSuffix}. ` +
|
|
1106
1145
|
`Your ${write.summary} was queued locally as ${queuedId}; whether the server applied ` +
|
|
1107
1146
|
'any of it is not reported, so verify before replaying.';
|
|
@@ -1132,7 +1171,10 @@ class BaseCommand extends core_1.Command {
|
|
|
1132
1171
|
// terminal refusal or a 500. oclif's pretty-printer renders a `code` on a
|
|
1133
1172
|
// CLIError as its own `Code: <code>` line, so passing it through gives
|
|
1134
1173
|
// every skrr command a greppable failure line at no other cost.
|
|
1135
|
-
|
|
1174
|
+
//
|
|
1175
|
+
// Field-level validation is appended for the same reason: the server names
|
|
1176
|
+
// the offending field and only `--json` callers could read it.
|
|
1177
|
+
this.error(`${message}${formatValidationIssues(details)}`, { exit, code });
|
|
1136
1178
|
}
|
|
1137
1179
|
writeJsonCliError({ message, code, status, exit, retryable, details, }) {
|
|
1138
1180
|
this.log(JSON.stringify({
|
|
@@ -1341,15 +1383,23 @@ function describeAssigneeNotInSpace(serverMessage, bin = 'skrr') {
|
|
|
1341
1383
|
* Server-declared TERMINAL refusals: a state conflict the caller must resolve
|
|
1342
1384
|
* by doing something DIFFERENT, never by repeating the identical request.
|
|
1343
1385
|
*
|
|
1344
|
-
* `skrr tasks move --status done`
|
|
1345
|
-
*
|
|
1386
|
+
* `skrr tasks move --status done` with no current Result or independent Review
|
|
1387
|
+
* returns a typed 409. 409 used to be in the
|
|
1346
1388
|
* transient set below, so the JSON envelope said `retryable: true` — and
|
|
1347
1389
|
* `daemon/CLAUDE.md` tells daemon-hosted agents to retry retryable errors, so
|
|
1348
1390
|
* they looped on a refusal that can never succeed on retry. The refusal names
|
|
1349
|
-
* the supported path (`
|
|
1391
|
+
* the supported path (`skrr tasks complete`, Result, then Review); the
|
|
1350
1392
|
* envelope has to agree that the ONLY way forward is that path.
|
|
1351
1393
|
*/
|
|
1352
|
-
const TERMINAL_ERROR_CODES = new Set([
|
|
1394
|
+
const TERMINAL_ERROR_CODES = new Set([
|
|
1395
|
+
'TASK_RESULT_REQUIRED',
|
|
1396
|
+
'TASK_CURRENT_RESULT_MISSING',
|
|
1397
|
+
'TASK_RESULT_SPEC_VERSION_MISMATCH',
|
|
1398
|
+
'TASK_EXPECTATIONS_NOT_MET',
|
|
1399
|
+
'TASK_RESULT_CHANGES_REQUESTED',
|
|
1400
|
+
'TASK_RESULT_REVIEW_REQUIRED',
|
|
1401
|
+
'TASK_DELIVERY_NOT_INTEGRATED',
|
|
1402
|
+
]);
|
|
1353
1403
|
/**
|
|
1354
1404
|
* Whether an automated retry of the IDENTICAL request could plausibly succeed.
|
|
1355
1405
|
*
|
|
@@ -1451,6 +1501,28 @@ function describeDaemonScopedCredential(bin, scope = 'daemon', source) {
|
|
|
1451
1501
|
return (`${subject}, which cannot access user API commands. ` +
|
|
1452
1502
|
`Run \`${bin} login\` to create a CLI credential. For the local runtime itself, use \`${bin} daemon login\`.`);
|
|
1453
1503
|
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Did the server MEAN this 5xx, or did it fall over?
|
|
1506
|
+
*
|
|
1507
|
+
* An outage and a designed refusal arrive with the same status and want
|
|
1508
|
+
* opposite reactions — wait for recovery, versus act on a condition. The
|
|
1509
|
+
* discriminator is whether the server authored an answer: a typed `code` plus
|
|
1510
|
+
* either an explanation it wrote (`cause` / `remedy`, both of which the 5xx
|
|
1511
|
+
* redaction boundary deliberately lets through) or an explicit verdict that
|
|
1512
|
+
* retrying will not help.
|
|
1513
|
+
*
|
|
1514
|
+
* Deliberately NOT folded into `isOutageFailure`: that predicate also gates the
|
|
1515
|
+
* outbox queue decision and `noteControlPlaneOutage`, and those ask a different
|
|
1516
|
+
* question. Merging the two is the mistake its own comment warns about.
|
|
1517
|
+
*/
|
|
1518
|
+
function isTypedServerRefusal(body) {
|
|
1519
|
+
if (!body || typeof body !== 'object')
|
|
1520
|
+
return false;
|
|
1521
|
+
const code = stringProp(body, 'code') || stringProp(body, 'errorType');
|
|
1522
|
+
if (!code)
|
|
1523
|
+
return false;
|
|
1524
|
+
return (typeof body.cause === 'string' || typeof body.remedy === 'string' || body.retryable === false);
|
|
1525
|
+
}
|
|
1454
1526
|
function isRetryableFailure(status, body) {
|
|
1455
1527
|
const declared = body?.retryable;
|
|
1456
1528
|
if (typeof declared === 'boolean')
|
|
@@ -1460,6 +1532,42 @@ function isRetryableFailure(status, body) {
|
|
|
1460
1532
|
return false;
|
|
1461
1533
|
return status === 408 || status === 425 || status === 429 || !!(status && status >= 500);
|
|
1462
1534
|
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Render server-supplied field validation into the human error.
|
|
1537
|
+
*
|
|
1538
|
+
* The canonical Task routes answer a schema rejection with
|
|
1539
|
+
* `{error: 'Invalid request data', details: <zod issues>}` — which names the
|
|
1540
|
+
* exact field — but the human path used to print only the generic sentence, so
|
|
1541
|
+
* `tasks updates add --type finding` failed with `Invalid request data` and the
|
|
1542
|
+
* operator had to re-run the identical command with `--json` to learn that
|
|
1543
|
+
* `data.evidenceRefs` was missing. The answer was already on the wire; only the
|
|
1544
|
+
* renderer threw it away.
|
|
1545
|
+
*
|
|
1546
|
+
* Shape-sniffed rather than typed against zod: `details` also carries unrelated
|
|
1547
|
+
* payloads (outbox ids, oclif suggestions), and those must pass through
|
|
1548
|
+
* untouched rather than render as pseudo-fields.
|
|
1549
|
+
*/
|
|
1550
|
+
function formatValidationIssues(details) {
|
|
1551
|
+
const issues = Array.isArray(details)
|
|
1552
|
+
? details
|
|
1553
|
+
: Array.isArray(details?.details)
|
|
1554
|
+
? details.details
|
|
1555
|
+
: Array.isArray(details?.issues)
|
|
1556
|
+
? details.issues
|
|
1557
|
+
: [];
|
|
1558
|
+
const lines = [];
|
|
1559
|
+
for (const issue of issues) {
|
|
1560
|
+
const row = issue;
|
|
1561
|
+
const message = typeof row?.message === 'string' ? row.message : '';
|
|
1562
|
+
if (!message)
|
|
1563
|
+
continue;
|
|
1564
|
+
const path = Array.isArray(row.path) ? row.path.join('.') : '';
|
|
1565
|
+
lines.push(path ? ` ${path}: ${message}` : ` ${message}`);
|
|
1566
|
+
if (lines.length === 10)
|
|
1567
|
+
break;
|
|
1568
|
+
}
|
|
1569
|
+
return lines.length > 0 ? `\n${lines.join('\n')}` : '';
|
|
1570
|
+
}
|
|
1463
1571
|
function detailsFromPrettyError(options) {
|
|
1464
1572
|
const details = {};
|
|
1465
1573
|
for (const key of ['suggestions', 'ref', 'showHelp']) {
|
|
@@ -1476,6 +1584,32 @@ function detailsFromCaughtError(err) {
|
|
|
1476
1584
|
details.exit = err.oclif.exit;
|
|
1477
1585
|
return Object.keys(details).length > 0 ? details : undefined;
|
|
1478
1586
|
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Where a removed flag's capability went. Keyed by flag name so it fires on
|
|
1589
|
+
* oclif's own `Nonexistent flags:` message without parsing its grammar.
|
|
1590
|
+
*/
|
|
1591
|
+
const RETIRED_FLAG_REPLACEMENTS = {
|
|
1592
|
+
'--verdict': '--verdict is gone: a review decision and a domain conclusion are different facts. ' +
|
|
1593
|
+
'Use `tasks review --decision accepted|changes_requested` for acceptance, and ' +
|
|
1594
|
+
'--conclusion-type/--conclusion-json for a conclusion such as NO-SHIP.',
|
|
1595
|
+
'--outcome': '--outcome is now --summary.',
|
|
1596
|
+
'--finding': '--finding is gone: record findings as `tasks updates add --type finding`.',
|
|
1597
|
+
'--evidence': '--evidence is now --evidence-ref on the Result, or an evidenceRefs entry.',
|
|
1598
|
+
'--next': '--next is now --remaining.',
|
|
1599
|
+
'--deliverables': '--deliverables is now --deliverable <task-resource-link-id>, recorded first with ' +
|
|
1600
|
+
'`tasks deliverable add`.',
|
|
1601
|
+
'--artifact': '--artifact is now --deliverable <task-resource-link-id>, recorded first with ' +
|
|
1602
|
+
'`tasks deliverable add`.',
|
|
1603
|
+
'--supersede': '--supersede is implicit: submitting again creates a new Result version.',
|
|
1604
|
+
};
|
|
1605
|
+
function retiredFlagHint(message) {
|
|
1606
|
+
if (!/nonexistent flag/i.test(message))
|
|
1607
|
+
return null;
|
|
1608
|
+
const hits = Object.keys(RETIRED_FLAG_REPLACEMENTS).filter((flag) => new RegExp(`${flag}(?![\\w-])`).test(message));
|
|
1609
|
+
if (hits.length === 0)
|
|
1610
|
+
return null;
|
|
1611
|
+
return hits.map((flag) => ` ${RETIRED_FLAG_REPLACEMENTS[flag]}`).join('\n');
|
|
1612
|
+
}
|
|
1479
1613
|
function parseCliErrorCode(err) {
|
|
1480
1614
|
if (err.name && err.name !== 'Error') {
|
|
1481
1615
|
return err.name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
@@ -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
|
*
|