@skrr-ai/cli 0.1.49 → 0.1.51
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 +5 -4
- package/dist/base-command.js +75 -6
- package/dist/commands/agents/chat.d.ts +14 -0
- package/dist/commands/agents/chat.js +37 -1
- package/dist/commands/agents/create.js +14 -7
- package/dist/commands/agents/show.d.ts +9 -0
- package/dist/commands/agents/show.js +53 -0
- package/dist/commands/agents/update.d.ts +9 -0
- package/dist/commands/agents/update.js +38 -5
- package/dist/commands/balance/show.d.ts +34 -0
- package/dist/commands/balance/show.js +92 -2
- package/dist/commands/code/index.d.ts +1 -0
- package/dist/commands/code/index.js +49 -5
- package/dist/commands/code/run.js +5 -1
- package/dist/commands/commitments/cycles.d.ts +19 -0
- package/dist/commands/commitments/cycles.js +46 -0
- package/dist/commands/commitments/doctor.d.ts +1 -0
- package/dist/commands/commitments/doctor.js +19 -4
- package/dist/commands/commitments/effective-policy.js +40 -1
- package/dist/commands/commitments/explain.d.ts +17 -0
- package/dist/commands/commitments/explain.js +40 -0
- package/dist/commands/commitments/next-tick.js +3 -1
- package/dist/commands/commitments/preflight.js +10 -0
- package/dist/commands/commitments/show.js +11 -1
- package/dist/commands/daemon/config.d.ts +15 -0
- package/dist/commands/daemon/config.js +38 -0
- package/dist/commands/daemon/index.js +1 -0
- package/dist/commands/daemon/status.js +15 -1
- package/dist/commands/goals/create.d.ts +1 -0
- package/dist/commands/goals/create.js +22 -0
- package/dist/commands/harnesses/models.d.ts +54 -0
- package/dist/commands/harnesses/models.js +100 -7
- package/dist/commands/harnesses/show.d.ts +11 -0
- package/dist/commands/harnesses/show.js +35 -0
- package/dist/commands/harnesses/update.d.ts +28 -1
- package/dist/commands/harnesses/update.js +73 -10
- package/dist/commands/logout.js +12 -1
- package/dist/commands/machines/dedicated/index.js +1 -1
- package/dist/commands/machines/dedicated/sign-in.js +4 -1
- package/dist/commands/machines/dedicated/terminal/kill.d.ts +21 -0
- package/dist/commands/machines/dedicated/terminal/kill.js +55 -0
- package/dist/commands/machines/dedicated/terminal/ls.d.ts +22 -0
- package/dist/commands/machines/dedicated/terminal/ls.js +70 -0
- package/dist/commands/machines/dedicated/terminal/rename.d.ts +23 -0
- package/dist/commands/machines/dedicated/terminal/rename.js +64 -0
- package/dist/commands/machines/dedicated/terminal.d.ts +9 -0
- package/dist/commands/machines/dedicated/terminal.js +27 -2
- package/dist/commands/machines/hosted/connect.js +2 -2
- package/dist/commands/machines/hosted/destroy.js +1 -1
- package/dist/commands/machines/hosted/exec.js +1 -1
- package/dist/commands/machines/hosted/list.js +1 -1
- package/dist/commands/machines/hosted/pause.js +1 -1
- package/dist/commands/machines/hosted/pull.js +1 -1
- package/dist/commands/machines/hosted/resume.js +1 -1
- package/dist/commands/machines/hosted/start.js +2 -2
- package/dist/commands/machines/hosted/status.js +2 -1
- package/dist/commands/outbox/list.d.ts +12 -1
- package/dist/commands/outbox/list.js +31 -2
- package/dist/commands/revoke-daemon.js +9 -0
- package/dist/commands/spaces/create.d.ts +1 -0
- package/dist/commands/spaces/create.js +17 -0
- package/dist/commands/spaces/show.js +5 -0
- package/dist/commands/spaces/update.d.ts +1 -0
- package/dist/commands/spaces/update.js +16 -0
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +6 -0
- package/dist/commands/tasks/list.js +1 -0
- package/dist/commands/tasks/show.js +45 -0
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +22 -0
- package/dist/commands/tasks/upsert.d.ts +1 -0
- package/dist/commands/tasks/upsert.js +16 -0
- package/dist/lib/agent-config.d.ts +2 -0
- package/dist/lib/agent-config.js +3 -1
- package/dist/lib/agentic-stream.d.ts +68 -1
- package/dist/lib/agentic-stream.js +294 -7
- package/dist/lib/api-fetch.js +19 -0
- package/dist/lib/auth-core-init.d.ts +2 -10
- package/dist/lib/auth-core-init.js +20 -67
- package/dist/lib/auth-failure.d.ts +33 -0
- package/dist/lib/auth-failure.js +65 -0
- package/dist/lib/auth-storage.d.ts +14 -0
- package/dist/lib/auth-storage.js +14 -0
- package/dist/lib/commitments.d.ts +37 -2
- package/dist/lib/commitments.js +148 -0
- package/dist/lib/daemonBroker.d.ts +134 -31
- package/dist/lib/daemonBroker.js +376 -31
- package/dist/lib/dedicated-lease-command.d.ts +14 -0
- package/dist/lib/dedicated-lease-command.js +30 -1
- package/dist/lib/dedicated-machines.js +8 -25
- package/dist/lib/dedicated-service-command.d.ts +11 -3
- package/dist/lib/dedicated-service-command.js +20 -3
- package/dist/lib/dedicated-service.d.ts +46 -0
- package/dist/lib/dedicated-service.js +85 -7
- package/dist/lib/dedicated-terminal.d.ts +21 -0
- package/dist/lib/dedicated-terminal.js +104 -9
- package/dist/lib/delegated-cli.js +4 -1
- package/dist/lib/exec-runtime-binary.d.ts +3 -1
- package/dist/lib/exec-runtime-binary.js +4 -2
- package/dist/lib/first-party-harness-broker.d.ts +10 -0
- package/dist/lib/first-party-harness-broker.js +13 -1
- package/dist/lib/first-party-harness-doctor.js +41 -1
- package/dist/lib/first-party-harness-managed.d.ts +4 -3
- package/dist/lib/first-party-harness-project-trust.d.ts +125 -0
- package/dist/lib/first-party-harness-project-trust.js +364 -0
- package/dist/lib/first-party-harness.d.ts +9 -2
- package/dist/lib/first-party-harness.js +6 -5
- package/dist/lib/harnesses.d.ts +10 -0
- package/dist/lib/hosted-machines.d.ts +10 -1
- package/dist/lib/hosted-machines.js +36 -2
- package/dist/lib/live-runtime-binary.d.ts +40 -0
- package/dist/lib/live-runtime-binary.js +193 -0
- package/dist/lib/login.d.ts +23 -0
- package/dist/lib/login.js +60 -10
- package/dist/lib/machine-spend-cap.d.ts +23 -0
- package/dist/lib/machine-spend-cap.js +68 -0
- package/dist/lib/message-intent.js +3 -1
- package/dist/lib/node-adapter.js +15 -3
- package/dist/lib/tasks.d.ts +20 -0
- package/dist/lib/tasks.js +54 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +90 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +113 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +26 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialSession.d.ts +47 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialSession.js +69 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.d.ts +133 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +189 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +41 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +25 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.js +268 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.js +11 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +36 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +156 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +8 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +9 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +8 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +16 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.d.ts +6 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.js +32 -9
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionPermissionAuthority.d.ts +81 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionPermissionAuthority.js +87 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +61 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.d.ts +6 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +90 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +105 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +25 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialSession.d.ts +47 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialSession.js +66 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.d.ts +133 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +182 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +41 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +10 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.js +257 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.js +11 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +36 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +147 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +8 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +9 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +8 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +16 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.d.ts +6 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.js +31 -9
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionPermissionAuthority.d.ts +81 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionPermissionAuthority.js +80 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +58 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.d.ts +6 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +61 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3418 -3344
- package/oclif.manifest.json +24813 -24242
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1247,11 +1247,12 @@ Create a new goal. `--title` is required unless supplied via `--from-json`.
|
|
|
1247
1247
|
```bash
|
|
1248
1248
|
sky goals create --title "Ship Q2 roadmap"
|
|
1249
1249
|
sky goals create --title "Milestone 1" --level milestone --parent <parent-id>
|
|
1250
|
+
sky goals create --title "Launch" --label <existing-label-id>
|
|
1250
1251
|
sky goals create --from-json goal.json
|
|
1251
1252
|
```
|
|
1252
1253
|
|
|
1253
1254
|
Flags: `--title`, `--description`, `--level`, `--parent`, `--owner-agent`,
|
|
1254
|
-
`--dri-agent`, `--dri-user`, `--from-json <file|->`, `--json`.
|
|
1255
|
+
`--dri-agent`, `--dri-user`, `--label` (repeatable), `--from-json <file|->`, `--json`.
|
|
1255
1256
|
|
|
1256
1257
|
### `sky goals update <id>`
|
|
1257
1258
|
|
|
@@ -1351,7 +1352,7 @@ sky tasks create --title "QA pass" \
|
|
|
1351
1352
|
--assignee-agent <agent-id> \
|
|
1352
1353
|
--assignee-agent <other-agent-id> \
|
|
1353
1354
|
--tag release --tag urgent \
|
|
1354
|
-
--label
|
|
1355
|
+
--label <existing-label-id>
|
|
1355
1356
|
sky tasks create --title "Follow up" --source-conversation <conversation-id>
|
|
1356
1357
|
sky tasks create --title "Spec task" --external-key ws0/spec --dry-run --json
|
|
1357
1358
|
sky tasks create --from-json task.json
|
|
@@ -1379,14 +1380,14 @@ are globally resolvable.
|
|
|
1379
1380
|
|
|
1380
1381
|
Tags are lightweight free-form keywords. Labels are shared workspace taxonomy
|
|
1381
1382
|
and are attached by opaque ID; discover existing IDs with
|
|
1382
|
-
`sky
|
|
1383
|
+
`sky labels list --applicable-to task`. Both are optional and repeatable at creation.
|
|
1383
1384
|
|
|
1384
1385
|
Flags: `--title`, `--description`, `--description-format`, `--external-key`,
|
|
1385
1386
|
`--default-agent`,
|
|
1386
1387
|
`--priority`, `--parent`, `--space`, `--goal`,
|
|
1387
1388
|
`--source-conversation`, `--source-message`, `--assignee-agent`
|
|
1388
1389
|
(repeatable), `--assignee-user` (repeatable), `--due-date`, `--tag`
|
|
1389
|
-
(repeatable), `--label-id`
|
|
1390
|
+
(repeatable), `--label` (repeatable; `--label-id` is a compatibility alias), `--from-json <file|->`, `--dry-run`,
|
|
1390
1391
|
`--json`.
|
|
1391
1392
|
|
|
1392
1393
|
### `sky tasks upsert`
|
package/dist/base-command.js
CHANGED
|
@@ -29,6 +29,7 @@ var keychain_1 = require("./lib/keychain");
|
|
|
29
29
|
Object.defineProperty(exports, "resolveProfileFromArgv", { enumerable: true, get: function () { return keychain_1.resolveProfileFromArgv; } });
|
|
30
30
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
31
31
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
32
|
+
const auth_failure_1 = require("./lib/auth-failure");
|
|
32
33
|
const assignee_resolver_1 = require("./lib/assignee-resolver");
|
|
33
34
|
const task_ref_resolver_1 = require("./lib/task-ref-resolver");
|
|
34
35
|
const space_resolver_1 = require("./lib/space-resolver");
|
|
@@ -298,10 +299,22 @@ class BaseCommand extends core_1.Command {
|
|
|
298
299
|
const accessToken = autoResult.outcome.accessToken;
|
|
299
300
|
this.resolvedCredential = {
|
|
300
301
|
token: accessToken,
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
|
|
302
|
+
// A `brokered` outcome is a daemon-owned access token held for
|
|
303
|
+
// THIS process only — nothing was persisted, so no stored-backend
|
|
304
|
+
// label applies. 'env-token' is the honest slot the shared
|
|
305
|
+
// CredentialSource union has for "a token this process holds in
|
|
306
|
+
// memory": `ensureFreshCliCredential` skips non-stored sources,
|
|
307
|
+
// which is correct — renewal happens by re-redeeming the
|
|
308
|
+
// descriptor (see api-fetch's 401 path), not by rotating a
|
|
309
|
+
// family that was never ours.
|
|
310
|
+
source: autoResult.outcome.brokered
|
|
311
|
+
? 'env-token'
|
|
312
|
+
: // The backend the broker actually wrote to. Hard-coding
|
|
313
|
+
// 'keychain' labelled a Linux credential (always the file)
|
|
314
|
+
// "macOS Keychain" in the same process that minted it.
|
|
315
|
+
autoResult.outcome.storedIn === 'keychain'
|
|
316
|
+
? 'keychain'
|
|
317
|
+
: 'file',
|
|
305
318
|
kind: (0, auth_core_1.classifyTokenKind)(accessToken),
|
|
306
319
|
};
|
|
307
320
|
}
|
|
@@ -990,16 +1003,29 @@ class BaseCommand extends core_1.Command {
|
|
|
990
1003
|
// `login` sends a CI job to do the one thing it cannot, and hides the
|
|
991
1004
|
// real mistake (dogfood OSK-4693). Name the credential instead.
|
|
992
1005
|
const presentedCiToken = Boolean(this.resolvedCredential?.token?.startsWith('osk_ci_'));
|
|
1006
|
+
// OSK-12116 — the 401 is usually the SECOND failure: the token expired
|
|
1007
|
+
// (routine) and renewing it was refused (the fault). The server's code
|
|
1008
|
+
// for the retry is `TOKEN_EXPIRED`, which names the routine half; the
|
|
1009
|
+
// latched refresh refusal names the half the reader can act on.
|
|
1010
|
+
const refreshRefusal = presentedCiToken
|
|
1011
|
+
? null
|
|
1012
|
+
: (0, auth_failure_1.describeRefreshRefusal)(readRefreshRefusal(), {
|
|
1013
|
+
bin: this.config.bin,
|
|
1014
|
+
cliId: this.cliConfig?.cliId,
|
|
1015
|
+
});
|
|
993
1016
|
this.failWithCliError({
|
|
994
1017
|
message: say(presentedCiToken
|
|
995
1018
|
? `Authentication failed: this is an \`osk_ci_*\` token, which only bootstraps a ` +
|
|
996
1019
|
`daemon (\`OVERSKY_TOKEN=<token> skrrd start\`). ${this.config.bin} commands do ` +
|
|
997
1020
|
`not accept it — sign in with \`${this.config.bin} login\` instead.`
|
|
998
|
-
:
|
|
999
|
-
|
|
1021
|
+
: refreshRefusal
|
|
1022
|
+
? `Authentication failed. ${refreshRefusal.message}`
|
|
1023
|
+
: `Authentication failed. Run \`${this.config.bin} login\` to sign in again.`),
|
|
1024
|
+
code: refreshRefusal?.code || bodyCode || 'AUTHENTICATION_FAILED',
|
|
1000
1025
|
status: e.status,
|
|
1001
1026
|
exit: exitCode,
|
|
1002
1027
|
retryable: true,
|
|
1028
|
+
...(refreshRefusal && bodyCode ? { details: { accessTokenCode: bodyCode } } : {}),
|
|
1003
1029
|
});
|
|
1004
1030
|
}
|
|
1005
1031
|
else if ((e.status === 403 || e.status === 504) &&
|
|
@@ -1275,6 +1301,36 @@ class BaseCommand extends core_1.Command {
|
|
|
1275
1301
|
// attempt is assumed absent.
|
|
1276
1302
|
const outage = (0, outbox_1.isOutageFailure)(err);
|
|
1277
1303
|
const statusSuffix = e.status ? ` (HTTP ${e.status})` : '';
|
|
1304
|
+
// OSK-12121 — a 401 is queued (the payload is authored, and it is worth
|
|
1305
|
+
// keeping until someone signs in again), but it is an AUTHENTICATION
|
|
1306
|
+
// failure, and saying "did not accept this write" left the reader to guess
|
|
1307
|
+
// that. Lead with the sign-in, name the refused refresh when one is latched,
|
|
1308
|
+
// and give the order the fix has to happen in: sign in, THEN replay.
|
|
1309
|
+
if (e.status === 401) {
|
|
1310
|
+
const refusal = (0, auth_failure_1.describeRefreshRefusal)(readRefreshRefusal(), {
|
|
1311
|
+
bin: this.config.bin,
|
|
1312
|
+
cliId: this.cliConfig?.cliId,
|
|
1313
|
+
});
|
|
1314
|
+
const why = refusal
|
|
1315
|
+
? refusal.message.replace(/\s*Run `[^`]+` to sign in again\.$/, '')
|
|
1316
|
+
: 'The server did not accept this sign-in.';
|
|
1317
|
+
this.failWithCliError({
|
|
1318
|
+
message: `Authentication failed${statusSuffix}. ${why} Your ${write.summary} was not applied; it ` +
|
|
1319
|
+
`was saved locally as ${queuedId} so it is not lost. Sign in with ` +
|
|
1320
|
+
`\`${this.config.bin} login\`, then replay it with \`${this.config.bin} outbox retry\` ` +
|
|
1321
|
+
`(or discard it with \`${this.config.bin} outbox drop ${queuedId}\`).`,
|
|
1322
|
+
code: refusal?.code || 'AUTHENTICATION_FAILED',
|
|
1323
|
+
status: e.status,
|
|
1324
|
+
exit: this.bareMode ? 75 : 2,
|
|
1325
|
+
retryable: true,
|
|
1326
|
+
details: {
|
|
1327
|
+
queued: true,
|
|
1328
|
+
outboxId: queuedId,
|
|
1329
|
+
idempotencyKey: write.idempotencyKey,
|
|
1330
|
+
...(e.code ? { accessTokenCode: e.code } : {}),
|
|
1331
|
+
},
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1278
1334
|
const lead = outage
|
|
1279
1335
|
? `${this.cliConfig.baseURL} is not serving requests right now${statusSuffix}. ` +
|
|
1280
1336
|
`Your ${write.summary} was queued locally as ${queuedId}; whether the server already ` +
|
|
@@ -1407,6 +1463,19 @@ function parseGlobalFlags(argv) {
|
|
|
1407
1463
|
}
|
|
1408
1464
|
return { bare, token, workspace };
|
|
1409
1465
|
}
|
|
1466
|
+
/**
|
|
1467
|
+
* The latched permanent refresh refusal, if any. Never throws: a surface that
|
|
1468
|
+
* cannot read the latch falls back to its generic wording (OSK-12116).
|
|
1469
|
+
*/
|
|
1470
|
+
function readRefreshRefusal() {
|
|
1471
|
+
try {
|
|
1472
|
+
const state = (0, auth_core_1.needsReauthState)();
|
|
1473
|
+
return state.needed ? { reason: state.reason, message: state.message } : null;
|
|
1474
|
+
}
|
|
1475
|
+
catch {
|
|
1476
|
+
return null;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1410
1479
|
function parseErrorBody(body) {
|
|
1411
1480
|
if (!body)
|
|
1412
1481
|
return null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { dataService } from '@skrr-ai/data-provider';
|
|
1
2
|
import { BaseCommand } from '../../base-command';
|
|
2
3
|
import { type AgenticStreamResult, type ReconciledTerminal } from '../../lib/agentic-stream';
|
|
3
4
|
/**
|
|
@@ -141,6 +142,17 @@ export declare function daemonPinFields(localSkills: {
|
|
|
141
142
|
pathHash: string;
|
|
142
143
|
}>;
|
|
143
144
|
} | Record<string, never>;
|
|
145
|
+
type ChatPermissionMode = NonNullable<Parameters<typeof dataService.startAgenticChat>[0]['permissionMode']>;
|
|
146
|
+
/**
|
|
147
|
+
* The per-turn permission-mode fragment of the chat-start payload (OSK-12124).
|
|
148
|
+
* It rides the same request layer the web composer's picker sends, which the
|
|
149
|
+
* server already honours above the agent's and the harness's stored defaults —
|
|
150
|
+
* so switching one conversation no longer means changing the agent for every
|
|
151
|
+
* conversation it has.
|
|
152
|
+
*/
|
|
153
|
+
export declare function permissionModeFields(mode: string | undefined): {
|
|
154
|
+
permissionMode: ChatPermissionMode;
|
|
155
|
+
} | Record<string, never>;
|
|
144
156
|
export default class AgentsChat extends BaseCommand {
|
|
145
157
|
static description: string;
|
|
146
158
|
static examples: string[];
|
|
@@ -157,6 +169,7 @@ export default class AgentsChat extends BaseCommand {
|
|
|
157
169
|
jsonl: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
158
170
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
159
171
|
'approve-tools': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
172
|
+
'permission-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
160
173
|
'local-skill': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
161
174
|
daemon: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
162
175
|
task: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -182,3 +195,4 @@ export default class AgentsChat extends BaseCommand {
|
|
|
182
195
|
private resolveLocalSkills;
|
|
183
196
|
run(): Promise<void>;
|
|
184
197
|
}
|
|
198
|
+
export {};
|
|
@@ -9,6 +9,7 @@ exports.noOutputFailureMessage = noOutputFailureMessage;
|
|
|
9
9
|
exports.noStreamJsonPayload = noStreamJsonPayload;
|
|
10
10
|
exports.chatStreamHeaderLines = chatStreamHeaderLines;
|
|
11
11
|
exports.daemonPinFields = daemonPinFields;
|
|
12
|
+
exports.permissionModeFields = permissionModeFields;
|
|
12
13
|
const node_fs_1 = require("node:fs");
|
|
13
14
|
const core_1 = require("@oclif/core");
|
|
14
15
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -157,6 +158,11 @@ function noStreamJsonPayload(input) {
|
|
|
157
158
|
responseMessageId: result.responseMessageId,
|
|
158
159
|
status: result.status,
|
|
159
160
|
response: result.text,
|
|
161
|
+
// The model a local harness reported running (OSK-12111). Absent on a
|
|
162
|
+
// cloud turn and on a harness that reports none.
|
|
163
|
+
...(typeof result.lastEvent?.harnessModel === 'string' && result.lastEvent.harnessModel
|
|
164
|
+
? { harnessModel: result.lastEvent.harnessModel }
|
|
165
|
+
: {}),
|
|
160
166
|
...(result.status === 'failed'
|
|
161
167
|
? {
|
|
162
168
|
failureReason: result.lastEvent?.reason ??
|
|
@@ -211,11 +217,22 @@ function daemonPinFields(localSkills, daemonFlag) {
|
|
|
211
217
|
}
|
|
212
218
|
return {};
|
|
213
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* The per-turn permission-mode fragment of the chat-start payload (OSK-12124).
|
|
222
|
+
* It rides the same request layer the web composer's picker sends, which the
|
|
223
|
+
* server already honours above the agent's and the harness's stored defaults —
|
|
224
|
+
* so switching one conversation no longer means changing the agent for every
|
|
225
|
+
* conversation it has.
|
|
226
|
+
*/
|
|
227
|
+
function permissionModeFields(mode) {
|
|
228
|
+
return mode ? { permissionMode: mode } : {};
|
|
229
|
+
}
|
|
214
230
|
class AgentsChat extends base_command_1.BaseCommand {
|
|
215
231
|
static description = 'Run an agent turn with live streaming, tool events, cancellation, and reconnects';
|
|
216
232
|
static examples = [
|
|
217
233
|
'<%= config.bin %> agents chat <agent-id> --prompt "Review the open tasks"',
|
|
218
234
|
'<%= config.bin %> agents chat <agent-id> --prompt "Deploy the fix" --approve-tools',
|
|
235
|
+
'<%= config.bin %> agents chat <agent-id> --conversation <id> --prompt "Now apply it" --permission-mode acceptEdits',
|
|
219
236
|
'<%= config.bin %> agents chat <agent-id> --prompt "Summarize" --jsonl',
|
|
220
237
|
'<%= config.bin %> agents chat <agent-id> --prompt "Summarize" --no-stream --json',
|
|
221
238
|
'<%= config.bin %> agents chat <agent-id> --prompt "Review this diff" --local-skill code-review',
|
|
@@ -250,7 +267,12 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
250
267
|
'`stream.gap` event means envelopes in that seq range never arrived and the streamed ' +
|
|
251
268
|
'text is short; `run.result` and the persisted message remain authoritative. Tool ' +
|
|
252
269
|
'calls arrive as `tool.started` / `tool.completed`, once per `toolUseId`, on cloud ' +
|
|
253
|
-
'and local-harness runs alike.'
|
|
270
|
+
'and local-harness runs alike. A `session.notice` with `notice: ' +
|
|
271
|
+
'"harness-session-reset"` means the local harness could not resume its previous ' +
|
|
272
|
+
'session and started a new one; `message` says why. A `permission.resolved` says ' +
|
|
273
|
+
'how a local harness permission request was decided: `decidedBy` in words, and ' +
|
|
274
|
+
'`basis` — `person` (with `surface`), `mode` (with `mode`), `policy` or ' +
|
|
275
|
+
'`session-grant` — beside the wire `by`.',
|
|
254
276
|
}),
|
|
255
277
|
json: core_1.Flags.boolean({
|
|
256
278
|
description: 'Emit the final one-shot response as JSON (use with --no-stream)',
|
|
@@ -260,6 +282,15 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
260
282
|
'with no terminal the flag itself is the approval for this turn, and each one is ' +
|
|
261
283
|
'reported on the stream. Without it every such call is denied.',
|
|
262
284
|
}),
|
|
285
|
+
'permission-mode': core_1.Flags.string({
|
|
286
|
+
description: 'Permission mode for THIS turn only, on a local-harness agent. It beats the agent’s and ' +
|
|
287
|
+
'the harness’s stored defaults for this turn and changes nothing else — pass it again ' +
|
|
288
|
+
'on each turn that needs it (`agents update --default-permission-mode` changes every ' +
|
|
289
|
+
'conversation of the agent). A mode the harness cannot honour runs as the one it can, ' +
|
|
290
|
+
'and run.started says which. --approve-tools is separate: it answers the approval ' +
|
|
291
|
+
'prompts a mode asks for.',
|
|
292
|
+
options: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
293
|
+
}),
|
|
263
294
|
'local-skill': core_1.Flags.string({
|
|
264
295
|
description: 'Invoke a skill on your machine on this turn, as `skrr skills local` lists it: its ' +
|
|
265
296
|
'name, or <root>/<name> when two roots share one. The turn runs on that machine. ' +
|
|
@@ -354,6 +385,10 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
354
385
|
'response and streams no events. Use --quick --json for a machine-readable ' +
|
|
355
386
|
'one-shot, or drop --quick for a real streamed turn.', { exit: 2 });
|
|
356
387
|
}
|
|
388
|
+
if (flags.quick && flags['permission-mode']) {
|
|
389
|
+
this.error('--permission-mode has no meaning with --quick: the persona-only summarizer runs no ' +
|
|
390
|
+
'tools, so there is nothing for a mode to govern. Drop --quick for a real turn.', { exit: 2 });
|
|
391
|
+
}
|
|
357
392
|
if (flags.quick && flags['local-skill']?.length) {
|
|
358
393
|
this.error('--local-skill has no meaning with --quick: the persona-only summarizer runs no ' +
|
|
359
394
|
'runtime, so no skill on your machine can load. Drop --quick for a real turn.', { exit: 2 });
|
|
@@ -485,6 +520,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
485
520
|
// execution policy places it elsewhere keeps that placement, and the
|
|
486
521
|
// run fails saying why rather than running without the skill.
|
|
487
522
|
...daemonPinFields(localSkills, flags.daemon),
|
|
523
|
+
...permissionModeFields(flags['permission-mode']),
|
|
488
524
|
});
|
|
489
525
|
}
|
|
490
526
|
catch (err) {
|
|
@@ -163,10 +163,11 @@ class AgentsCreate extends base_command_1.BaseCommand {
|
|
|
163
163
|
}),
|
|
164
164
|
description: core_1.Flags.string({ description: 'Agent description' }),
|
|
165
165
|
provider: core_1.Flags.string({
|
|
166
|
-
description: 'Model provider (
|
|
166
|
+
description: 'Model provider (default: agentic when --name is given)',
|
|
167
167
|
}),
|
|
168
168
|
model: core_1.Flags.string({
|
|
169
|
-
description: 'Model identifier (
|
|
169
|
+
description: 'Model identifier (default: `default`, auto-routing). On a local harness, any id the harness ' +
|
|
170
|
+
'accepts — `skrr harnesses models <harness>` lists the known ones.',
|
|
170
171
|
}),
|
|
171
172
|
instructions: core_1.Flags.string({
|
|
172
173
|
description: 'Initial raw custom instructions (creates one inline block; use `agents instructions` to compose reusable blocks later)',
|
|
@@ -199,7 +200,9 @@ class AgentsCreate extends base_command_1.BaseCommand {
|
|
|
199
200
|
description: 'Single-purpose agent: skip the system-managed relationship portfolio (conversation continuity, relationship pulse, commitment incubator, open-loop closer). Self-reflection is still seeded.',
|
|
200
201
|
}),
|
|
201
202
|
'default-permission-mode': core_1.Flags.string({
|
|
202
|
-
description:
|
|
203
|
+
description: "Permission mode for this agent's local-harness sessions (every harness, not only Claude Code). " +
|
|
204
|
+
'One-shot harnesses (gemini, opencode, cursor, copilot, goose, pi, openclaw) can only run as ' +
|
|
205
|
+
'bypassPermissions; any other mode is refused for them.',
|
|
203
206
|
options: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
204
207
|
}),
|
|
205
208
|
tools: core_1.Flags.string({
|
|
@@ -242,19 +245,23 @@ class AgentsCreate extends base_command_1.BaseCommand {
|
|
|
242
245
|
description: 'When this agent schedules its own work: HH:MM-HH:MM[@<IANA timezone>], e.g. ' +
|
|
243
246
|
'09:00-18:00@America/Los_Angeles',
|
|
244
247
|
}),
|
|
248
|
+
// Retired (OSK-11975): a Commitment turn works under the Agent's own
|
|
249
|
+
// permissions, so these three are stored but no longer read at runtime.
|
|
245
250
|
'reasoning-tool-escape': core_1.Flags.string({
|
|
246
|
-
description:
|
|
247
|
-
'These are ESCAPES, not a fenced tool surface.',
|
|
251
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
248
252
|
options: [...agent_config_1.REASONING_TOOL_ESCAPES],
|
|
249
253
|
multiple: true,
|
|
254
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
250
255
|
}),
|
|
251
256
|
'commitment-responsibility': core_1.Flags.string({
|
|
252
|
-
description: "
|
|
257
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
253
258
|
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
259
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
254
260
|
}),
|
|
255
261
|
'commitment-responsibility-ceiling': core_1.Flags.string({
|
|
256
|
-
description:
|
|
262
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
257
263
|
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
264
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
258
265
|
}),
|
|
259
266
|
'max-turns': core_1.Flags.integer({ description: 'Maximum turns in one agent run (1-500)' }),
|
|
260
267
|
'tool-resources': core_1.Flags.string({
|
|
@@ -13,6 +13,15 @@ export declare function agentToneLine(agent: {
|
|
|
13
13
|
toneMode?: unknown;
|
|
14
14
|
toneId?: unknown;
|
|
15
15
|
}): string;
|
|
16
|
+
/**
|
|
17
|
+
* The permission mode this agent runs with on its harness, and the layer that
|
|
18
|
+
* decided it (OSK-12069). The server resolves it (`effectivePermissionMode`) the
|
|
19
|
+
* way the dispatch does; the stored agent field alone is one of four layers, so
|
|
20
|
+
* printing it read "not set" for an agent whose harness default governed.
|
|
21
|
+
* Falls back to the stored field against a server that does not send the
|
|
22
|
+
* resolution, and says that is all it knows.
|
|
23
|
+
*/
|
|
24
|
+
export declare function agentPermissionLines(agent: Record<string, unknown>, harness: string): string[];
|
|
16
25
|
/** Text rendering is deliberately based on the server projection, with a
|
|
17
26
|
* storage-shape fallback while all stored policies are migrated. */
|
|
18
27
|
export declare function agentExecutionOrderLines(agent: Record<string, unknown>): string[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.agentToneLine = agentToneLine;
|
|
4
|
+
exports.agentPermissionLines = agentPermissionLines;
|
|
4
5
|
exports.agentExecutionOrderLines = agentExecutionOrderLines;
|
|
5
6
|
const core_1 = require("@oclif/core");
|
|
6
7
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -31,6 +32,46 @@ function agentToneLine(agent) {
|
|
|
31
32
|
return 'inherit — see `skrr agents tone show`';
|
|
32
33
|
return '-';
|
|
33
34
|
}
|
|
35
|
+
const PERMISSION_SOURCE_LABELS = {
|
|
36
|
+
agent: "this agent's default",
|
|
37
|
+
harness: "the harness's default",
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The permission mode this agent runs with on its harness, and the layer that
|
|
41
|
+
* decided it (OSK-12069). The server resolves it (`effectivePermissionMode`) the
|
|
42
|
+
* way the dispatch does; the stored agent field alone is one of four layers, so
|
|
43
|
+
* printing it read "not set" for an agent whose harness default governed.
|
|
44
|
+
* Falls back to the stored field against a server that does not send the
|
|
45
|
+
* resolution, and says that is all it knows.
|
|
46
|
+
*/
|
|
47
|
+
function agentPermissionLines(agent, harness) {
|
|
48
|
+
const effective = agent.effectivePermissionMode;
|
|
49
|
+
const pad = ' ';
|
|
50
|
+
if (!effective || typeof effective.source !== 'string') {
|
|
51
|
+
const stored = typeof agent.defaultPermissionMode === 'string' && agent.defaultPermissionMode
|
|
52
|
+
? agent.defaultPermissionMode
|
|
53
|
+
: "not set on the agent (the harness's or the daemon's default applies)";
|
|
54
|
+
return [`Permission: ${stored} — enforced by the ${harness} harness`];
|
|
55
|
+
}
|
|
56
|
+
const lines = [];
|
|
57
|
+
if (typeof effective.mode === 'string' && effective.mode) {
|
|
58
|
+
const from = PERMISSION_SOURCE_LABELS[effective.source] ?? effective.source;
|
|
59
|
+
lines.push(`Permission: ${effective.mode} (from ${from}) — enforced by the ${harness} harness`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
lines.push(`Permission: set by the daemon's own config on that machine — no agent or harness mode is set`);
|
|
63
|
+
}
|
|
64
|
+
if (typeof effective.coercedFrom === 'string' && effective.coercedFrom) {
|
|
65
|
+
lines.push(`${pad}${effective.coercedFrom} is configured, but ${harness} cannot honour it, so it runs as ${String(effective.mode)}.`);
|
|
66
|
+
}
|
|
67
|
+
const supported = Array.isArray(effective.supportedModes)
|
|
68
|
+
? effective.supportedModes.filter((m) => typeof m === 'string')
|
|
69
|
+
: [];
|
|
70
|
+
if (supported.length > 0)
|
|
71
|
+
lines.push(`${pad}${harness} accepts: ${supported.join(', ')}`);
|
|
72
|
+
lines.push(`${pad}A turn's own mode (\`agents chat --permission-mode\`) overrides this for that turn.`);
|
|
73
|
+
return lines;
|
|
74
|
+
}
|
|
34
75
|
/** Text rendering is deliberately based on the server projection, with a
|
|
35
76
|
* storage-shape fallback while all stored policies are migrated. */
|
|
36
77
|
function agentExecutionOrderLines(agent) {
|
|
@@ -163,6 +204,18 @@ class AgentsShow extends base_command_1.BaseCommand {
|
|
|
163
204
|
this.log(line);
|
|
164
205
|
if (a.harnessName || a.harnessProvider || a.harnessStatus) {
|
|
165
206
|
this.log(`Harness: ${a.harnessName ?? (typeof a.harnessProvider === 'string' ? (0, harness_provider_input_1.canonicalHarnessInput)(a.harnessProvider) : a.harnessProvider) ?? '-'}${a.harnessStatus ? ` (${a.harnessStatus})` : ''}`);
|
|
207
|
+
// On a harness, the HARNESS decides what runs and which permission modes
|
|
208
|
+
// exist — `Provider` is only the cloud model contract, so an agent read
|
|
209
|
+
// as "anthropic" while running Codex (OSK-12071). And the mode itself was
|
|
210
|
+
// visible only in --json (OSK-12069).
|
|
211
|
+
if (typeof a.harnessProvider === 'string' && a.harnessProvider) {
|
|
212
|
+
const harness = (0, harness_provider_input_1.canonicalHarnessInput)(a.harnessProvider);
|
|
213
|
+
for (const line of agentPermissionLines(a, harness))
|
|
214
|
+
this.log(line);
|
|
215
|
+
if (typeof a.provider === 'string' && a.provider && a.provider !== harness) {
|
|
216
|
+
this.log(` Runs on ${harness}; Provider "${a.provider}" is only the cloud model contract.`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
166
219
|
// An offline engine is the difference between "this agent works" and
|
|
167
220
|
// "this agent silently does nothing", and the display name alone cannot
|
|
168
221
|
// carry it: two runtimes for the same machine share an identical name,
|
|
@@ -55,3 +55,12 @@ export default class AgentsUpdate extends BaseCommand {
|
|
|
55
55
|
};
|
|
56
56
|
run(): Promise<void>;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* What changing the agent's default permission mode actually changed
|
|
60
|
+
* (OSK-12124). It is the AGENT's default, so it governs every conversation,
|
|
61
|
+
* task run and Commitment Run of the agent from its next turn — which the bare
|
|
62
|
+
* "Updated agent" line never said, and the only way to learn that a live
|
|
63
|
+
* conversation picked it up was to spend another turn. Names the per-turn
|
|
64
|
+
* alternative for the case that wanted one conversation changed.
|
|
65
|
+
*/
|
|
66
|
+
export declare function defaultPermissionModeNote(requested: string | undefined, updated: Record<string, unknown>): string | null;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultPermissionModeNote = defaultPermissionModeNote;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const agent_visual_refs_1 = require("../../lib/agent-visual-refs");
|
|
@@ -49,7 +50,11 @@ class AgentsUpdate extends base_command_1.BaseCommand {
|
|
|
49
50
|
description: 'Default working directory for local Harness sessions',
|
|
50
51
|
}),
|
|
51
52
|
'default-permission-mode': core_1.Flags.string({
|
|
52
|
-
description:
|
|
53
|
+
description: "Permission mode for this agent's local-harness sessions (every harness, not only Claude Code). " +
|
|
54
|
+
'It is the default for EVERY conversation, task run and Commitment Run of the agent; for one ' +
|
|
55
|
+
'turn only use `agents chat --permission-mode`. ' +
|
|
56
|
+
'One-shot harnesses (gemini, opencode, cursor, copilot, goose, pi, openclaw) can only run as ' +
|
|
57
|
+
'bypassPermissions; any other mode is refused for them.',
|
|
53
58
|
options: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
54
59
|
}),
|
|
55
60
|
tools: core_1.Flags.string({
|
|
@@ -93,19 +98,23 @@ class AgentsUpdate extends base_command_1.BaseCommand {
|
|
|
93
98
|
description: 'When this agent schedules its own work: HH:MM-HH:MM[@<IANA timezone>], e.g. ' +
|
|
94
99
|
'09:00-18:00@America/Los_Angeles',
|
|
95
100
|
}),
|
|
101
|
+
// Retired (OSK-11975): a Commitment turn works under the Agent's own
|
|
102
|
+
// permissions, so these three are stored but no longer read at runtime.
|
|
96
103
|
'reasoning-tool-escape': core_1.Flags.string({
|
|
97
|
-
description:
|
|
98
|
-
'These are ESCAPES, not a fenced tool surface.',
|
|
104
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
99
105
|
options: [...agent_config_1.REASONING_TOOL_ESCAPES],
|
|
100
106
|
multiple: true,
|
|
107
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
101
108
|
}),
|
|
102
109
|
'commitment-responsibility': core_1.Flags.string({
|
|
103
|
-
description: "
|
|
110
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
104
111
|
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
112
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
105
113
|
}),
|
|
106
114
|
'commitment-responsibility-ceiling': core_1.Flags.string({
|
|
107
|
-
description:
|
|
115
|
+
description: "Deprecated — no longer has any effect. Commitment runs use the agent's own permissions.",
|
|
108
116
|
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
117
|
+
deprecated: { message: agent_config_1.COMMITMENT_PERMISSION_FLAG_RETIRED },
|
|
109
118
|
}),
|
|
110
119
|
'max-turns': core_1.Flags.integer({ description: 'Maximum turns in one agent run (1-500)' }),
|
|
111
120
|
'tool-resources': core_1.Flags.string({
|
|
@@ -207,6 +216,30 @@ class AgentsUpdate extends base_command_1.BaseCommand {
|
|
|
207
216
|
const a = updated;
|
|
208
217
|
this.log(`Updated agent ${a.id ?? a._id ?? args.id} — ${a.name ?? '(no name)'}`);
|
|
209
218
|
this.log(`URL: ${(0, web_url_1.withAgentUrl)(this.cliConfig.baseURL, { ...a, id: a.id ?? a._id ?? args.id }).url ?? '-'}`);
|
|
219
|
+
const modeNote = defaultPermissionModeNote(flags['default-permission-mode'], a);
|
|
220
|
+
if (modeNote)
|
|
221
|
+
this.log(modeNote);
|
|
210
222
|
}
|
|
211
223
|
}
|
|
212
224
|
exports.default = AgentsUpdate;
|
|
225
|
+
/**
|
|
226
|
+
* What changing the agent's default permission mode actually changed
|
|
227
|
+
* (OSK-12124). It is the AGENT's default, so it governs every conversation,
|
|
228
|
+
* task run and Commitment Run of the agent from its next turn — which the bare
|
|
229
|
+
* "Updated agent" line never said, and the only way to learn that a live
|
|
230
|
+
* conversation picked it up was to spend another turn. Names the per-turn
|
|
231
|
+
* alternative for the case that wanted one conversation changed.
|
|
232
|
+
*/
|
|
233
|
+
function defaultPermissionModeNote(requested, updated) {
|
|
234
|
+
if (!requested)
|
|
235
|
+
return null;
|
|
236
|
+
const stored = typeof updated.defaultPermissionMode === 'string' && updated.defaultPermissionMode
|
|
237
|
+
? updated.defaultPermissionMode
|
|
238
|
+
: requested;
|
|
239
|
+
return [
|
|
240
|
+
`Permission: ${stored} is now this agent's default for EVERY conversation, task run and`,
|
|
241
|
+
' Commitment Run, starting with each one’s next turn. A turn that names its own',
|
|
242
|
+
' mode still wins. To change one turn only, leave the default alone and pass',
|
|
243
|
+
` \`skrr agents chat <agent> --conversation <id> --permission-mode ${requested}\`.`,
|
|
244
|
+
].join('\n');
|
|
245
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TSkyCodeUsageSnapshot } from '@skrr-ai/data-provider';
|
|
2
2
|
import { BaseCommand } from '../../base-command';
|
|
3
|
+
import type { WorkspaceBalance } from '../../lib/balance';
|
|
3
4
|
import { type RuntimeMonthlySpend } from '../../lib/harnesses';
|
|
4
5
|
/**
|
|
5
6
|
* The hosted-runtime monthly cap rows, as lines.
|
|
@@ -8,6 +9,32 @@ import { type RuntimeMonthlySpend } from '../../lib/harnesses';
|
|
|
8
9
|
* the wording is part of the observable contract and is pinned directly.
|
|
9
10
|
*/
|
|
10
11
|
export declare function renderRuntimeSpend(spend: RuntimeMonthlySpend[], log: (line: string) => void): void;
|
|
12
|
+
/**
|
|
13
|
+
* The workspace the next session on this machine is billed to, and why that one.
|
|
14
|
+
*
|
|
15
|
+
* `selected`: `workspaces use` / `--workspace` / a daemon handoff put it in
|
|
16
|
+
* `OVERSKY_WORKSPACE_ID`. `default`: nothing is selected, so the session carries
|
|
17
|
+
* the caller's server-side default workspace — the same resolution `whoami` and
|
|
18
|
+
* `workspaces list` describe ("resolves to your default workspace").
|
|
19
|
+
*/
|
|
20
|
+
export interface SessionBillingTarget {
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
source: 'selected' | 'default';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The account the NEXT session bills against, as lines — printed FIRST (OSK-12122).
|
|
27
|
+
*
|
|
28
|
+
* `skrr balance` opened on the personal account, so a user whose sessions bill
|
|
29
|
+
* the default workspace read `Credits: 999,503,672,326 ($999,503.67)` while every
|
|
30
|
+
* session was refused against that workspace's $0. The screen that exists to
|
|
31
|
+
* answer "why was I refused for credit" answered for the one account the
|
|
32
|
+
* refusal was not about, and nothing on it said which account that was.
|
|
33
|
+
*
|
|
34
|
+
* `balance` absent means the read failed: say so, never print a figure.
|
|
35
|
+
* Pure so the wording is pinned directly, like `renderRuntimeSpend`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderSessionBillingAccount(target: SessionBillingTarget, balance: WorkspaceBalance | null, log: (line: string) => void, bin?: string): void;
|
|
11
38
|
/**
|
|
12
39
|
* Your plan's ceilings, as lines.
|
|
13
40
|
*
|
|
@@ -66,6 +93,13 @@ export default class BalanceShow extends BaseCommand {
|
|
|
66
93
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
67
94
|
};
|
|
68
95
|
run(): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Which workspace the next session carries: the selected one, else the
|
|
98
|
+
* caller's default. Fail-open — an unreadable listing with nothing selected
|
|
99
|
+
* returns null and the screen falls back to the personal view it always had,
|
|
100
|
+
* rather than guessing an account.
|
|
101
|
+
*/
|
|
102
|
+
private resolveSessionBillingTarget;
|
|
69
103
|
/**
|
|
70
104
|
* Your plan's ceilings, beside the balance they are spent before.
|
|
71
105
|
*
|