@skrr-ai/cli 0.1.51 → 0.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.d.ts +7 -0
- package/dist/base-command.js +38 -8
- package/dist/commands/agents/chat.js +2 -1
- package/dist/commands/agents/create.js +21 -8
- package/dist/commands/agents/update.d.ts +55 -0
- package/dist/commands/agents/update.js +119 -23
- package/dist/commands/commitments/next-tick.js +9 -1
- package/dist/commands/context.js +2 -1
- package/dist/commands/daemon/config.js +16 -1
- package/dist/commands/doctor.js +8 -1
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.js +26 -7
- package/dist/commands/logout.js +3 -0
- package/dist/commands/machines/dedicated/show.js +25 -2
- package/dist/commands/tasks/approvals/list.d.ts +22 -0
- package/dist/commands/tasks/approvals/list.js +80 -3
- package/dist/commands/tasks/create.d.ts +5 -0
- package/dist/commands/tasks/create.js +28 -7
- package/dist/commands/tasks/start.d.ts +14 -0
- package/dist/commands/tasks/start.js +31 -1
- package/dist/commands/tasks/update.js +30 -3
- package/dist/commands/whoami.js +5 -3
- package/dist/lib/agent-config.d.ts +15 -0
- package/dist/lib/agent-config.js +46 -10
- package/dist/lib/agentic-stream.d.ts +21 -1
- package/dist/lib/agentic-stream.js +40 -6
- package/dist/lib/auth-failure.js +4 -1
- package/dist/lib/auth-storage.d.ts +24 -0
- package/dist/lib/auth-storage.js +348 -13
- package/dist/lib/cli-id.d.ts +22 -0
- package/dist/lib/cli-id.js +56 -0
- package/dist/lib/cli-identity.d.ts +49 -0
- package/dist/lib/cli-identity.js +159 -0
- package/dist/lib/commitments.d.ts +4 -0
- package/dist/lib/commitments.js +12 -1
- package/dist/lib/config.d.ts +17 -0
- package/dist/lib/config.js +15 -3
- package/dist/lib/cred-envelope.d.ts +12 -1
- package/dist/lib/cred-envelope.js +20 -3
- package/dist/lib/daemonBroker.d.ts +26 -4
- package/dist/lib/daemonBroker.js +82 -10
- package/dist/lib/daemonBrokerRefusal.d.ts +51 -0
- package/dist/lib/daemonBrokerRefusal.js +127 -0
- package/dist/lib/dedicated-machines.d.ts +53 -4
- package/dist/lib/dedicated-machines.js +95 -5
- package/dist/lib/delegated-cli.js +16 -0
- package/dist/lib/first-party-harness-broker.js +6 -4
- package/dist/lib/keychain.d.ts +39 -0
- package/dist/lib/keychain.js +254 -40
- package/dist/lib/label-ref.d.ts +34 -0
- package/dist/lib/label-ref.js +72 -1
- package/dist/lib/login.js +24 -12
- package/dist/lib/oauthLogin.js +2 -8
- package/dist/lib/refresh.js +6 -2
- package/dist/lib/tasks.js +33 -8
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.d.ts +13 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +9 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +4 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.d.ts +13 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +8 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3138 -3100
- package/oclif.manifest.json +26470 -26449
- package/package.json +1 -1
package/dist/lib/agent-config.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RELEASE_INSTALL_CHANNELS = exports.COMMITMENT_PERMISSION_FLAG_RETIRED = exports.REASONING_TOOL_ESCAPES = exports.COMMITMENT_RESPONSIBILITY_LEVELS = void 0;
|
|
3
|
+
exports.RELEASE_INSTALL_CHANNELS = exports.RETIRED_COMMITMENT_PERMISSION_FLAGS = exports.COMMITMENT_PERMISSION_FLAG_RETIRED = exports.REASONING_TOOL_ESCAPES = exports.COMMITMENT_RESPONSIBILITY_LEVELS = void 0;
|
|
4
|
+
exports.retiredCommitmentPermissionFlagMessage = retiredCommitmentPermissionFlagMessage;
|
|
5
|
+
exports.deprecatedFieldsWarnings = deprecatedFieldsWarnings;
|
|
6
|
+
exports.deprecatedFieldNames = deprecatedFieldNames;
|
|
4
7
|
exports.parseWorkingHoursFlag = parseWorkingHoursFlag;
|
|
5
8
|
exports.mergeAgentConfigFlags = mergeAgentConfigFlags;
|
|
6
9
|
const prompt_1 = require("./prompt");
|
|
@@ -9,6 +12,41 @@ exports.COMMITMENT_RESPONSIBILITY_LEVELS = ['reasoning_only', 'full_ownership'];
|
|
|
9
12
|
exports.REASONING_TOOL_ESCAPES = ['bash', 'browser'];
|
|
10
13
|
/** Warning printed by the three retired Commitment permission flags (OSK-11975). */
|
|
11
14
|
exports.COMMITMENT_PERMISSION_FLAG_RETIRED = "This setting no longer has any effect: Commitment runs use the agent's own permissions.";
|
|
15
|
+
/** The three retired flags themselves: accepted at parse, warned on, never sent. */
|
|
16
|
+
exports.RETIRED_COMMITMENT_PERMISSION_FLAGS = [
|
|
17
|
+
'reasoning-tool-escape',
|
|
18
|
+
'commitment-responsibility',
|
|
19
|
+
'commitment-responsibility-ceiling',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* The deprecation warning ONE retired flag prints. oclif prints a
|
|
23
|
+
* `deprecated.message` verbatim, so a shared message printed the same line
|
|
24
|
+
* once per flag with nothing saying which flag each one was about (OSK-12068).
|
|
25
|
+
*/
|
|
26
|
+
function retiredCommitmentPermissionFlagMessage(flag) {
|
|
27
|
+
return `--${flag} is retired and was not sent. ${exports.COMMITMENT_PERMISSION_FLAG_RETIRED}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The fields the server ignored and why, from a write's `deprecatedFields`
|
|
31
|
+
* notice, one line each. Empty when the response carries none.
|
|
32
|
+
*/
|
|
33
|
+
function deprecatedFieldsWarnings(response) {
|
|
34
|
+
const entries = response?.deprecatedFields;
|
|
35
|
+
if (!Array.isArray(entries))
|
|
36
|
+
return [];
|
|
37
|
+
return entries
|
|
38
|
+
.filter((entry) => Boolean(entry) && typeof entry.field === 'string')
|
|
39
|
+
.map((entry) => `${entry.field}: ${entry.reason || 'ignored by the server'}`);
|
|
40
|
+
}
|
|
41
|
+
/** The payload keys the server reported as ignored, so they are not also called "not kept". */
|
|
42
|
+
function deprecatedFieldNames(response) {
|
|
43
|
+
const entries = response?.deprecatedFields;
|
|
44
|
+
return Array.isArray(entries)
|
|
45
|
+
? entries
|
|
46
|
+
.map((entry) => entry?.field)
|
|
47
|
+
.filter((field) => typeof field === 'string')
|
|
48
|
+
: [];
|
|
49
|
+
}
|
|
12
50
|
exports.RELEASE_INSTALL_CHANNELS = ['latest', 'manual'];
|
|
13
51
|
/**
|
|
14
52
|
* `09:00-18:00` or `09:00-18:00@America/Los_Angeles`, or a JSON object.
|
|
@@ -102,15 +140,13 @@ function mergeAgentConfigFlags(body, flags) {
|
|
|
102
140
|
if (flags['todo-working-hours'] !== undefined) {
|
|
103
141
|
parsed.todoWorkingHours = parseWorkingHoursFlag(String(flags['todo-working-hours']));
|
|
104
142
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
parsed.commitmentResponsibilityCeiling = flags['commitment-responsibility-ceiling'];
|
|
113
|
-
}
|
|
143
|
+
// `--reasoning-tool-escape`, `--commitment-responsibility` and
|
|
144
|
+
// `--commitment-responsibility-ceiling` are retired (OSK-11975) and are
|
|
145
|
+
// deliberately NOT forwarded. The server still accepts and echoes the stored
|
|
146
|
+
// fields, so sending them wrote a value nothing reads and handed it back as
|
|
147
|
+
// if it were live — and "a ceiling a commitment may not exceed" is a safety
|
|
148
|
+
// claim a person then believes (OSK-12068). The flags stay parseable so old
|
|
149
|
+
// scripts do not break; oclif prints COMMITMENT_PERMISSION_FLAG_RETIRED.
|
|
114
150
|
if (flags['tool-resources'] !== undefined) {
|
|
115
151
|
parsed.tool_resources = JSON.parse(String(flags['tool-resources']));
|
|
116
152
|
}
|
|
@@ -299,7 +299,7 @@ export type SeqGap = {
|
|
|
299
299
|
* `service` envelopes that carry a `notice` — words for the person, not
|
|
300
300
|
* diagnostics — projected as `session.notice` events. Today the only notice is
|
|
301
301
|
* `harness-session-reset`: the local harness could not resume its previous
|
|
302
|
-
* session and began a new one,
|
|
302
|
+
* session and began a new one, which does not see earlier turns (OSK-12155).
|
|
303
303
|
*/
|
|
304
304
|
export declare function projectSessionNotices(envelopes: unknown[]): AgenticStreamEvent[];
|
|
305
305
|
export declare function detectSeqGap(highestApplied: number, incoming: number): SeqGap | null;
|
|
@@ -346,6 +346,11 @@ export declare class AgenticStreamClient {
|
|
|
346
346
|
* repeat count varies run to run and cannot be inferred by a consumer.
|
|
347
347
|
*/
|
|
348
348
|
private readonly seenLifecycle;
|
|
349
|
+
/**
|
|
350
|
+
* Whether this client's transport has dropped since it first connected. Until
|
|
351
|
+
* it has, every `session:join` it sends declares a FIRST join (OSK-12124).
|
|
352
|
+
*/
|
|
353
|
+
private transportDropped;
|
|
349
354
|
/** `call` → tool name, so a daemon `tool-call-end` can be named (OSK-7730). */
|
|
350
355
|
private readonly toolNamesByCall;
|
|
351
356
|
/** `permission-ask` requestId → tool name, to name its resolution (OSK-12113). */
|
|
@@ -373,6 +378,21 @@ export declare class AgenticStreamClient {
|
|
|
373
378
|
settledResult(): AgenticStreamResult | null;
|
|
374
379
|
constructor(options: AgenticStreamOptions);
|
|
375
380
|
run(): Promise<AgenticStreamResult>;
|
|
381
|
+
/**
|
|
382
|
+
* The `session:join` payload.
|
|
383
|
+
*
|
|
384
|
+
* This client learns its session id from the HTTP acceptance and only then
|
|
385
|
+
* connects, while a daemon turn publishes its `session:init` at once. The
|
|
386
|
+
* server drops buffered frames older than the socket's connect time — right
|
|
387
|
+
* for a RE-connect, which already rendered them, and wrong here, where they
|
|
388
|
+
* were never seen: `run.started` (the dispatched mode and its source) never
|
|
389
|
+
* reached a daemon turn's stream (OSK-12124). `firstJoin` says so, and the
|
|
390
|
+
* server then replays the pre-connect lifecycle frames. Both joins of the
|
|
391
|
+
* first connection carry it, because the server's replay drains the shared
|
|
392
|
+
* buffer and either join may be the one that reaches it first; the stream's
|
|
393
|
+
* own lifecycle dedupe absorbs the overlap. After a drop it is not sent.
|
|
394
|
+
*/
|
|
395
|
+
private sessionJoinPayload;
|
|
376
396
|
/**
|
|
377
397
|
* (Re)start the silence watchdog that asks the durable record what happened.
|
|
378
398
|
*
|
|
@@ -280,9 +280,14 @@ function describePermissionDecider(ev) {
|
|
|
280
280
|
? `the ${mode} permission mode (nobody was asked)`
|
|
281
281
|
: "the session's permission mode (nobody was asked)";
|
|
282
282
|
case 'policy':
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
if (ev.by === 'server')
|
|
284
|
+
return 'the unattended-run policy (nobody could be asked)';
|
|
285
|
+
// A client that denied on its own because it could not ask anyone — the
|
|
286
|
+
// skrr CLI without --approve-tools, say (OSK-12113).
|
|
287
|
+
if (typeof ev.surface === 'string' && SURFACE_LABELS[ev.surface]) {
|
|
288
|
+
return `${SURFACE_LABELS[ev.surface]}, which had nobody to ask (nobody was asked)`;
|
|
289
|
+
}
|
|
290
|
+
return 'a runtime policy (nobody was asked)';
|
|
286
291
|
case 'session-grant':
|
|
287
292
|
return 'an earlier "allow for this session"';
|
|
288
293
|
case 'person': {
|
|
@@ -421,7 +426,7 @@ function jitteredRetryDelay(retryAfterMs, random = Math.random) {
|
|
|
421
426
|
* `service` envelopes that carry a `notice` — words for the person, not
|
|
422
427
|
* diagnostics — projected as `session.notice` events. Today the only notice is
|
|
423
428
|
* `harness-session-reset`: the local harness could not resume its previous
|
|
424
|
-
* session and began a new one,
|
|
429
|
+
* session and began a new one, which does not see earlier turns (OSK-12155).
|
|
425
430
|
*/
|
|
426
431
|
function projectSessionNotices(envelopes) {
|
|
427
432
|
const out = [];
|
|
@@ -520,6 +525,11 @@ class AgenticStreamClient {
|
|
|
520
525
|
* repeat count varies run to run and cannot be inferred by a consumer.
|
|
521
526
|
*/
|
|
522
527
|
seenLifecycle = new Set();
|
|
528
|
+
/**
|
|
529
|
+
* Whether this client's transport has dropped since it first connected. Until
|
|
530
|
+
* it has, every `session:join` it sends declares a FIRST join (OSK-12124).
|
|
531
|
+
*/
|
|
532
|
+
transportDropped = false;
|
|
523
533
|
/** `call` → tool name, so a daemon `tool-call-end` can be named (OSK-7730). */
|
|
524
534
|
toolNamesByCall = new Map();
|
|
525
535
|
/** `permission-ask` requestId → tool name, to name its resolution (OSK-12113). */
|
|
@@ -581,11 +591,30 @@ class AgenticStreamClient {
|
|
|
581
591
|
// the result instead of awaiting an attach nobody is still attempting.
|
|
582
592
|
if (this.settled || this.closed || !this.socket)
|
|
583
593
|
return result;
|
|
584
|
-
this.socket.emit('session:join',
|
|
594
|
+
this.socket.emit('session:join', this.sessionJoinPayload());
|
|
585
595
|
this.emit({ type: 'session.joined', sessionId: this.options.sessionId });
|
|
586
596
|
this.armIdleProbe();
|
|
587
597
|
return result;
|
|
588
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* The `session:join` payload.
|
|
601
|
+
*
|
|
602
|
+
* This client learns its session id from the HTTP acceptance and only then
|
|
603
|
+
* connects, while a daemon turn publishes its `session:init` at once. The
|
|
604
|
+
* server drops buffered frames older than the socket's connect time — right
|
|
605
|
+
* for a RE-connect, which already rendered them, and wrong here, where they
|
|
606
|
+
* were never seen: `run.started` (the dispatched mode and its source) never
|
|
607
|
+
* reached a daemon turn's stream (OSK-12124). `firstJoin` says so, and the
|
|
608
|
+
* server then replays the pre-connect lifecycle frames. Both joins of the
|
|
609
|
+
* first connection carry it, because the server's replay drains the shared
|
|
610
|
+
* buffer and either join may be the one that reaches it first; the stream's
|
|
611
|
+
* own lifecycle dedupe absorbs the overlap. After a drop it is not sent.
|
|
612
|
+
*/
|
|
613
|
+
sessionJoinPayload() {
|
|
614
|
+
return this.transportDropped
|
|
615
|
+
? { sessionId: this.options.sessionId }
|
|
616
|
+
: { sessionId: this.options.sessionId, firstJoin: true };
|
|
617
|
+
}
|
|
589
618
|
/**
|
|
590
619
|
* (Re)start the silence watchdog that asks the durable record what happened.
|
|
591
620
|
*
|
|
@@ -726,10 +755,11 @@ class AgenticStreamClient {
|
|
|
726
755
|
const socket = this.socket;
|
|
727
756
|
const match = (event) => !event.sessionId || event.sessionId === this.options.sessionId;
|
|
728
757
|
socket.on('connect', () => {
|
|
729
|
-
socket.emit('session:join',
|
|
758
|
+
socket.emit('session:join', this.sessionJoinPayload());
|
|
730
759
|
this.emit({ type: 'transport.connected', sessionId: this.options.sessionId });
|
|
731
760
|
});
|
|
732
761
|
socket.on('disconnect', (reason) => {
|
|
762
|
+
this.transportDropped = true;
|
|
733
763
|
if (this.settled)
|
|
734
764
|
return;
|
|
735
765
|
this.emit({ type: 'transport.disconnected', sessionId: this.options.sessionId, reason });
|
|
@@ -913,6 +943,10 @@ class AgenticStreamClient {
|
|
|
913
943
|
toolUseId: event.toolUseId,
|
|
914
944
|
toolName: event.toolName,
|
|
915
945
|
reason: 'CLI was not started with --approve-tools',
|
|
946
|
+
// Nobody was asked: this client could not put the prompt to anyone.
|
|
947
|
+
// The server records it as a policy decision, not a person's
|
|
948
|
+
// (OSK-12113) — it used to read "a person on the skrr CLI".
|
|
949
|
+
automatic: true,
|
|
916
950
|
});
|
|
917
951
|
}
|
|
918
952
|
this.emit({ ...event, type: 'permission.denied', reason: 'noninteractive_or_not_enabled' });
|
package/dist/lib/auth-failure.js
CHANGED
|
@@ -33,7 +33,10 @@ function describeRefreshRefusal(refusal, opts) {
|
|
|
33
33
|
// configuration on this machine (a different HOME or config dir sharing the
|
|
34
34
|
// same login Keychain) can write this profile's credential under its own ID.
|
|
35
35
|
// Observed: a token minted for `cli_devin_dogfood` sitting in the default
|
|
36
|
-
// profile's slot.
|
|
36
|
+
// profile's slot. Since OSK-12135 the slot is namespaced by config root and a
|
|
37
|
+
// read refuses a bundle bound to another cliId before presenting it, so this
|
|
38
|
+
// is now reached only when the server's binding disagrees with a token that
|
|
39
|
+
// carries no readable `did`.
|
|
37
40
|
if (/bound to a different daemon/i.test(message)) {
|
|
38
41
|
return {
|
|
39
42
|
code,
|
|
@@ -6,14 +6,33 @@ export interface AuthBundle {
|
|
|
6
6
|
refreshExpiresAt?: number;
|
|
7
7
|
/** Normalized API origin that issued this access/refresh pair. */
|
|
8
8
|
serverOrigin?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The config that wrote this bundle, as stored. Filled on write from the
|
|
11
|
+
* current config; callers never need to set it.
|
|
12
|
+
*/
|
|
13
|
+
owner?: CredentialOwner;
|
|
14
|
+
}
|
|
15
|
+
/** Which skrr config a credential belongs to. */
|
|
16
|
+
export interface CredentialOwner {
|
|
17
|
+
/** Resolved config root (`~/.skrr`, or the `SKRR_CONFIG_DIR` override). */
|
|
18
|
+
configRoot?: string;
|
|
19
|
+
/** The CLI identity the server bound the refresh family to. */
|
|
20
|
+
cliId?: string;
|
|
9
21
|
}
|
|
10
22
|
export type CredentialOriginStatus = 'none' | 'unchecked' | 'matched' | 'unbound' | 'mismatch';
|
|
23
|
+
/** `foreign`: the stored bundle belongs to another skrr config and was not used. */
|
|
24
|
+
export type CredentialOwnerStatus = 'foreign';
|
|
11
25
|
export interface ReadResult {
|
|
12
26
|
bundle: AuthBundle | null;
|
|
13
27
|
backend: AuthBackend;
|
|
14
28
|
originStatus?: CredentialOriginStatus;
|
|
15
29
|
storedServerOrigin?: string;
|
|
16
30
|
expectedServerOrigin?: string;
|
|
31
|
+
ownerStatus?: CredentialOwnerStatus;
|
|
32
|
+
/** For `foreign`: who the stored bundle belongs to. */
|
|
33
|
+
storedOwner?: CredentialOwner;
|
|
34
|
+
/** For `foreign`: who this process is. */
|
|
35
|
+
expectedOwner?: CredentialOwner;
|
|
17
36
|
}
|
|
18
37
|
export interface WriteOptions {
|
|
19
38
|
/** Bind/overwrite the bundle's issuing origin. Invalid origins are rejected. */
|
|
@@ -47,6 +66,11 @@ export declare function deleteFileBackend(): void;
|
|
|
47
66
|
* function returns whatever is persisted.
|
|
48
67
|
*/
|
|
49
68
|
export declare function readFromBackend(expectedServerOrigin?: string): ReadResult;
|
|
69
|
+
/**
|
|
70
|
+
* One sentence naming whose credential was refused and why, for the surfaces
|
|
71
|
+
* that explain an absent sign-in (BaseCommand, `skrr doctor`).
|
|
72
|
+
*/
|
|
73
|
+
export declare function describeForeignCredential(result: ReadResult): string | null;
|
|
50
74
|
export declare function writeToBackend(bundle: AuthBundle, options?: WriteOptions): AuthBackend;
|
|
51
75
|
/**
|
|
52
76
|
* Clear both backends. Called on `skrr logout` (and internally during
|