@skrr-ai/cli 0.1.122 → 0.1.124
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/commands/agents/chat.d.ts +7 -0
- package/dist/commands/agents/chat.js +32 -6
- package/dist/commands/agents/delete.d.ts +8 -0
- package/dist/commands/agents/delete.js +16 -0
- package/dist/commands/context.js +7 -0
- package/dist/commands/followups/act.js +3 -0
- package/dist/commands/followups/checkin.js +3 -0
- package/dist/commands/followups/remind.js +3 -0
- package/dist/commands/followups/show.js +1 -1
- package/dist/commands/followups/watch.js +3 -0
- package/dist/commands/search/workspace.js +1 -1
- package/dist/commands/store/gallery-admissions/approve.js +1 -1
- package/dist/commands/store/gallery-admissions/preview.js +1 -1
- package/dist/commands/store/gallery-admissions/refuse.js +1 -1
- package/dist/commands/store/gallery-admissions/show.js +1 -1
- package/dist/lib/agentic-stream.d.ts +46 -0
- package/dist/lib/agentic-stream.js +135 -14
- package/dist/lib/auth-core-init.d.ts +15 -2
- package/dist/lib/auth-core-init.js +47 -6
- package/dist/lib/auth-failure.js +12 -0
- package/dist/lib/command-hygiene.js +30 -1
- package/dist/lib/daemonBrokerRefusal.js +5 -1
- package/dist/lib/exec-runtime-binary.d.ts +9 -0
- package/dist/lib/exec-runtime-binary.js +15 -1
- package/dist/lib/followups.d.ts +13 -0
- package/dist/lib/followups.js +8 -0
- package/dist/lib/keychain.js +41 -4
- package/dist/lib/profile-machine-identity-guard.js +2 -1
- package/dist/lib/runtime-start-verification.js +6 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +5 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +69 -27
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +135 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +440 -83
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKey.d.ts +106 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKey.js +77 -19
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyHandle.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyHandle.js +77 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyHardware.d.ts +68 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyHardware.js +264 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyServerSupport.d.ts +31 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceKeyServerSupport.js +90 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/dpop.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/independentMachineReservation.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +7 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +110 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/index.js +13 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.d.ts +18 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +11 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/macos.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/macos.js +14 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/masterKekService.d.ts +69 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/masterKekService.js +67 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/liveState.d.ts +154 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/liveState.js +281 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.js +6 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +8 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/profileStateDir.js +7 -27
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +24 -16
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/stateFiles.d.ts +31 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/stateFiles.js +89 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +3 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +41 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.d.ts +7 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +5 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +4 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +122 -38
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +135 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +603 -90
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKey.d.ts +106 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKey.js +131 -27
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyHandle.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyHandle.js +81 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyHardware.d.ts +68 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyHardware.js +317 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyServerSupport.d.ts +31 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceKeyServerSupport.js +86 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/dpop.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/independentMachineReservation.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +7 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +14 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/index.js +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.d.ts +18 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.js +18 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/macos.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/macos.js +23 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/masterKekService.d.ts +69 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/masterKekService.js +134 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/liveState.d.ts +154 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/liveState.js +386 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.js +6 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +11 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/profileStateDir.js +6 -35
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +45 -16
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/stateFiles.d.ts +31 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/stateFiles.js +73 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +3 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +40 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.d.ts +7 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +21 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7349 -7325
- package/oclif.manifest.json +11 -2
- package/package.json +4 -1
|
@@ -155,6 +155,12 @@ export declare function noOutputFailureMessage(input: {
|
|
|
155
155
|
text?: string;
|
|
156
156
|
conversationId?: string | null;
|
|
157
157
|
}): string | null;
|
|
158
|
+
/**
|
|
159
|
+
* What a failed run says for itself. The reason is whatever the terminal event
|
|
160
|
+
* carries (see `terminalFailureMessage`); only a failure that carries none gets
|
|
161
|
+
* the generic sentence.
|
|
162
|
+
*/
|
|
163
|
+
export declare function agentRunFailureMessage(result: Pick<AgenticStreamResult, 'lastEvent'>): string;
|
|
158
164
|
export declare function noStreamJsonPayload(input: {
|
|
159
165
|
result: AgenticStreamResult;
|
|
160
166
|
conversationId?: string;
|
|
@@ -222,6 +228,7 @@ export default class AgentsChat extends BaseCommand {
|
|
|
222
228
|
'thread-root': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
223
229
|
'no-stream': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
224
230
|
quick: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
231
|
+
incremental: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
225
232
|
jsonl: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
226
233
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
227
234
|
'repair-wait': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -9,6 +9,7 @@ exports.handoverInterruptMessage = handoverInterruptMessage;
|
|
|
9
9
|
exports.interruptAction = interruptAction;
|
|
10
10
|
exports.inspectTurnCommand = inspectTurnCommand;
|
|
11
11
|
exports.noOutputFailureMessage = noOutputFailureMessage;
|
|
12
|
+
exports.agentRunFailureMessage = agentRunFailureMessage;
|
|
12
13
|
exports.noStreamJsonPayload = noStreamJsonPayload;
|
|
13
14
|
exports.chatStreamHeaderLines = chatStreamHeaderLines;
|
|
14
15
|
exports.daemonPinFields = daemonPinFields;
|
|
@@ -259,6 +260,14 @@ function noOutputFailureMessage(input) {
|
|
|
259
260
|
return (`The turn ended with no output (status: ${input.status}). ` +
|
|
260
261
|
`It may have failed on the runtime. Inspect it with: ${inspectTurnCommand(input.conversationId)}`);
|
|
261
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* What a failed run says for itself. The reason is whatever the terminal event
|
|
265
|
+
* carries (see `terminalFailureMessage`); only a failure that carries none gets
|
|
266
|
+
* the generic sentence.
|
|
267
|
+
*/
|
|
268
|
+
function agentRunFailureMessage(result) {
|
|
269
|
+
return (0, agentic_stream_1.terminalFailureMessage)(result.lastEvent) ?? 'Agent run failed';
|
|
270
|
+
}
|
|
262
271
|
function noStreamJsonPayload(input) {
|
|
263
272
|
const { result, conversationId, agentId, baseURL, threadRootMessageId } = input;
|
|
264
273
|
return {
|
|
@@ -281,9 +290,9 @@ function noStreamJsonPayload(input) {
|
|
|
281
290
|
? {
|
|
282
291
|
failureReason: result.lastEvent?.reason ??
|
|
283
292
|
result.lastEvent?.code ??
|
|
284
|
-
result.lastEvent
|
|
293
|
+
(0, agentic_stream_1.terminalFailureMessage)(result.lastEvent) ??
|
|
285
294
|
'agent_run_failed',
|
|
286
|
-
error: result
|
|
295
|
+
error: agentRunFailureMessage(result),
|
|
287
296
|
terminalEvent: result.lastEvent,
|
|
288
297
|
}
|
|
289
298
|
: {}),
|
|
@@ -370,10 +379,20 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
370
379
|
'agent’s runtime, tools, session, or working directory and cannot perform work — ' +
|
|
371
380
|
'it is for inline text assistance. Use --no-stream for a real turn.',
|
|
372
381
|
}),
|
|
382
|
+
incremental: core_1.Flags.boolean({
|
|
383
|
+
description: 'With --jsonl, make `text.delta` a real delta: it carries only `delta`, the characters ' +
|
|
384
|
+
'it adds, instead of the whole answer so far, and leaves out the envelopes that ' +
|
|
385
|
+
'`session.output` already carries. A rewrite that is not an append arrives as ' +
|
|
386
|
+
'`replace`, the new full text. `run.result` still holds the whole answer. Without it ' +
|
|
387
|
+
'a long answer written as JSON lines grows with the square of its length.',
|
|
388
|
+
dependsOn: ['jsonl'],
|
|
389
|
+
}),
|
|
373
390
|
jsonl: core_1.Flags.boolean({
|
|
374
391
|
description: 'Emit one JSON event per line while streaming. Every line is a complete JSON value. ' +
|
|
375
392
|
'Assistant text arrives as `text.delta` whose `text` is the CUMULATIVE answer so far, ' +
|
|
376
|
-
'not a delta — take the last one, or `run.result` at the end.
|
|
393
|
+
'not a delta — take the last one, or `run.result` at the end. Each `text.delta` also ' +
|
|
394
|
+
'carries `delta`, the characters it adds, when it only appends to the one before; ' +
|
|
395
|
+
'with --incremental it carries nothing else of the text (see that flag). The same text is ' +
|
|
377
396
|
'mirrored inside `session.output` envelopes for consumers that want the raw stream, ' +
|
|
378
397
|
'so folding both doubles the answer: pick ONE lane. A widget the agent wrote ' +
|
|
379
398
|
'(a block of CSS, HTML and JavaScript the apps draw) is its text description in ' +
|
|
@@ -392,7 +411,11 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
392
411
|
'and local-harness runs alike. A `session.notice` with `notice: ' +
|
|
393
412
|
'"harness-session-reset"` means the local harness could not resume its previous ' +
|
|
394
413
|
'session and started a new one, which does not see earlier turns of the ' +
|
|
395
|
-
'conversation; `message` says why.
|
|
414
|
+
'conversation; `message` says why. `notice: "model-request-retrying"` means the ' +
|
|
415
|
+
'model rejected or could not answer a request and the harness is retrying it: ' +
|
|
416
|
+
'`message` names the cause (for example the model rejecting the credentials on ' +
|
|
417
|
+
'this machine, HTTP 403) and the attempt, a few times per retry episode, so a ' +
|
|
418
|
+
'run that looks quiet is not. A `permission.resolved` says ' +
|
|
396
419
|
'how a local harness permission request was decided: `decidedBy` in words, and ' +
|
|
397
420
|
'`basis` — `person` (with `surface`), `mode` (with `mode`), `policy` or ' +
|
|
398
421
|
'`session-grant` — beside the wire `by`. When a platform update restarts the server ' +
|
|
@@ -404,7 +427,9 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
404
427
|
'the machine finished; `run.failed` with `handover.outcome: "machine_failed"` and the ' +
|
|
405
428
|
'machine\'s reason when it did not; or `run.failed` with `handover.outcome: "expired"` ' +
|
|
406
429
|
'and the original failure when --repair-wait ran out (exit 1 for both). Ctrl-C during ' +
|
|
407
|
-
'the wait emits `run.detached` with `handedOver: true` and exits 130.'
|
|
430
|
+
'the wait emits `run.detached` with `handedOver: true` and exits 130. Whenever a run ' +
|
|
431
|
+
'fails, `run.failed` carries `message`, the reason in words as the platform gave it (the ' +
|
|
432
|
+
'same sentence a terminal prints after `Error:`), beside the short `reason`.',
|
|
408
433
|
}),
|
|
409
434
|
json: core_1.Flags.boolean({
|
|
410
435
|
description: 'Emit the final one-shot response as JSON (use with --no-stream)',
|
|
@@ -788,6 +813,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
788
813
|
sessionId: started.sessionId,
|
|
789
814
|
conversationId,
|
|
790
815
|
jsonl: flags.jsonl,
|
|
816
|
+
incrementalText: flags.incremental,
|
|
791
817
|
quiet,
|
|
792
818
|
approveTools: flags['approve-tools'],
|
|
793
819
|
reconcileTerminal,
|
|
@@ -966,7 +992,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
966
992
|
process.exitCode = 1;
|
|
967
993
|
}
|
|
968
994
|
else if (result.status === 'failed') {
|
|
969
|
-
this.error(
|
|
995
|
+
this.error(agentRunFailureMessage(result), { exit: 1 });
|
|
970
996
|
}
|
|
971
997
|
else if (quiet) {
|
|
972
998
|
// Non-streaming human output: the answer the turn produced.
|
|
@@ -8,6 +8,14 @@ import { BaseCommand } from '../../base-command';
|
|
|
8
8
|
export declare function agentRemovalQuestion(agentId: string, kind: AgentRemovalKind | null): string;
|
|
9
9
|
/** What happened, read from the server's response rather than predicted. */
|
|
10
10
|
export declare function agentRemovalReport(agentId: string, response: DeleteAgentResponse | undefined): string;
|
|
11
|
+
/**
|
|
12
|
+
* What became of the agent's Personal Context data, read from the same response
|
|
13
|
+
* (OSK-20112). The agent row is gone as soon as the delete returns, but data
|
|
14
|
+
* derived from its connected sources is erased separately: `Deleted agent` must
|
|
15
|
+
* never stand in for "erased". Nothing is printed when the server reported
|
|
16
|
+
* nothing (an older server, or an uninstall, which erases nothing).
|
|
17
|
+
*/
|
|
18
|
+
export declare function agentErasureReport(response: DeleteAgentResponse | undefined): string[];
|
|
11
19
|
export default class AgentsDelete extends BaseCommand {
|
|
12
20
|
static description: string;
|
|
13
21
|
static examples: string[];
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.agentRemovalQuestion = agentRemovalQuestion;
|
|
4
4
|
exports.agentRemovalReport = agentRemovalReport;
|
|
5
|
+
exports.agentErasureReport = agentErasureReport;
|
|
5
6
|
const core_1 = require("@oclif/core");
|
|
6
7
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
7
8
|
const base_command_1 = require("../../base-command");
|
|
@@ -38,6 +39,19 @@ function agentRemovalReport(agentId, response) {
|
|
|
38
39
|
return `Deleted agent ${agentId}`;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* What became of the agent's Personal Context data, read from the same response
|
|
44
|
+
* (OSK-20112). The agent row is gone as soon as the delete returns, but data
|
|
45
|
+
* derived from its connected sources is erased separately: `Deleted agent` must
|
|
46
|
+
* never stand in for "erased". Nothing is printed when the server reported
|
|
47
|
+
* nothing (an older server, or an uninstall, which erases nothing).
|
|
48
|
+
*/
|
|
49
|
+
function agentErasureReport(response) {
|
|
50
|
+
if ((0, data_provider_1.agentRemovalKind)(response) !== 'deleted')
|
|
51
|
+
return [];
|
|
52
|
+
const erasure = response && 'erasure' in response ? response.erasure : undefined;
|
|
53
|
+
return (0, data_provider_1.describePersonalContextErasure)(erasure)?.lines ?? [];
|
|
54
|
+
}
|
|
41
55
|
class AgentsDelete extends base_command_1.BaseCommand {
|
|
42
56
|
static description = 'Delete an agent you created (irreversible), or uninstall one installed from the store (reinstalling restores it)';
|
|
43
57
|
static examples = [
|
|
@@ -89,6 +103,8 @@ class AgentsDelete extends base_command_1.BaseCommand {
|
|
|
89
103
|
this.handleApiError(err);
|
|
90
104
|
}
|
|
91
105
|
this.log(agentRemovalReport(args.id, response));
|
|
106
|
+
for (const line of agentErasureReport(response))
|
|
107
|
+
this.log(line);
|
|
92
108
|
}
|
|
93
109
|
}
|
|
94
110
|
exports.default = AgentsDelete;
|
package/dist/commands/context.js
CHANGED
|
@@ -64,6 +64,13 @@ class Context extends base_command_1.BaseCommand {
|
|
|
64
64
|
path: (0, config_1.getConfigPath)(),
|
|
65
65
|
cliId: (0, cli_id_1.resolveCliId)(this.cliConfig) ?? null,
|
|
66
66
|
},
|
|
67
|
+
// Silent about the DAEMON's device key on purpose (OSK-20507). This is the CLI's
|
|
68
|
+
// own sign-in, and the CLI never requires a device key (OSK-12063), so an
|
|
69
|
+
// unreadable one changes nothing an agent reading this can do. The daemon's
|
|
70
|
+
// account of its key is `skrr daemon status` (`problems`, from `/health`
|
|
71
|
+
// `deviceIdentity`), and the one line a `skrr` process prints about it is the
|
|
72
|
+
// notice in `lib/auth-core-init.ts`. Adding it here would put a machine fact
|
|
73
|
+
// beside a per-process one and read as this credential's state.
|
|
67
74
|
auth: {
|
|
68
75
|
signedIn: Boolean(this.resolvedCredential?.token),
|
|
69
76
|
tokenSource: this.credentialSourceLabel(),
|
|
@@ -100,6 +100,9 @@ class FollowupsAct extends base_command_1.BaseCommand {
|
|
|
100
100
|
this.log(JSON.stringify(response, null, 2));
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
|
+
const producerNotice = (0, followups_1.producerDowngradeNotice)(response);
|
|
104
|
+
if (producerNotice)
|
|
105
|
+
this.log(producerNotice);
|
|
103
106
|
const row = response.followup;
|
|
104
107
|
if (response.reused) {
|
|
105
108
|
this.log(`Already armed: ${row?.id} — the same act exists and was not duplicated.`);
|
|
@@ -126,6 +126,9 @@ class FollowupsCheckin extends base_command_1.BaseCommand {
|
|
|
126
126
|
this.log(JSON.stringify(response, null, 2));
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
|
+
const producerNotice = (0, followups_1.producerDowngradeNotice)(response);
|
|
130
|
+
if (producerNotice)
|
|
131
|
+
this.log(producerNotice);
|
|
129
132
|
const row = response.followup;
|
|
130
133
|
if (response.reused) {
|
|
131
134
|
this.log(reusedMessage(row, subject, flags.why));
|
|
@@ -102,6 +102,9 @@ class FollowupsRemind extends base_command_1.BaseCommand {
|
|
|
102
102
|
this.log(JSON.stringify(response, null, 2));
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
+
const producerNotice = (0, followups_1.producerDowngradeNotice)(response);
|
|
106
|
+
if (producerNotice)
|
|
107
|
+
this.log(producerNotice);
|
|
105
108
|
const row = response.followup;
|
|
106
109
|
if (response.reused && response.rescheduled) {
|
|
107
110
|
this.log(`Moved: ${row?.id} now fires at ${row?.nextRunAt ?? at} — the same reminder already existed, so it was rescheduled rather than duplicated.`);
|
|
@@ -42,7 +42,7 @@ class FollowupsShow extends base_command_1.BaseCommand {
|
|
|
42
42
|
['says', row.content],
|
|
43
43
|
['why', row.why],
|
|
44
44
|
['intent', row.intentKey],
|
|
45
|
-
['producer', row.producer],
|
|
45
|
+
['producer', row.producerLabel ? `${row.producer} (${row.producerLabel})` : row.producer],
|
|
46
46
|
['gate', row.gate ? (GATE_LABEL[row.gate] ?? row.gate) : undefined],
|
|
47
47
|
['terminal', row.terminal ? `${row.terminal} (${row.terminalReason ?? '—'})` : undefined],
|
|
48
48
|
[
|
|
@@ -237,6 +237,9 @@ class FollowupsWatch extends base_command_1.BaseCommand {
|
|
|
237
237
|
this.log(JSON.stringify(response, null, 2));
|
|
238
238
|
return;
|
|
239
239
|
}
|
|
240
|
+
const producerNotice = (0, followups_1.producerDowngradeNotice)(response);
|
|
241
|
+
if (producerNotice)
|
|
242
|
+
this.log(producerNotice);
|
|
240
243
|
const row = response.followup;
|
|
241
244
|
if (response.reused) {
|
|
242
245
|
this.log(`Already armed: ${row?.id} — an identical watch exists and was not duplicated.`);
|
|
@@ -104,7 +104,7 @@ class SearchWorkspace extends base_command_1.BaseCommand {
|
|
|
104
104
|
url: `${(0, web_url_1.webOrigin)(this.cliConfig.baseURL)}${item.href}`,
|
|
105
105
|
}));
|
|
106
106
|
if (flags.json) {
|
|
107
|
-
this.
|
|
107
|
+
this.printJsonResult({ ...response, results });
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
110
|
for (const diagnostic of new Set(response.diagnostics || []))
|
|
@@ -24,7 +24,7 @@ class StoreGalleryAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
24
24
|
revision: flags.revision, digest: flags.digest, imagesReviewed: true, ...(flags.note ? { note: flags.note } : {}),
|
|
25
25
|
});
|
|
26
26
|
if (flags.json)
|
|
27
|
-
this.
|
|
27
|
+
this.printJsonResult(result);
|
|
28
28
|
else
|
|
29
29
|
this.log(`Approved gallery revision ${flags.revision}.`);
|
|
30
30
|
}
|
|
@@ -36,7 +36,7 @@ class StoreGalleryAdmissionsPreview extends base_command_1.BaseCommand {
|
|
|
36
36
|
await (0, promises_1.writeFile)(flags.output, bytes, { flag: 'wx', mode: 0o600 });
|
|
37
37
|
const receipt = { requestId: args.id, kind, revision: review.revision, digest: review.digest, imageId: args.imageId, sha256: digest, path: flags.output, bytes: bytes.length };
|
|
38
38
|
if (flags.json)
|
|
39
|
-
this.
|
|
39
|
+
this.printJsonResult(receipt);
|
|
40
40
|
else
|
|
41
41
|
this.log(`Wrote ${bytes.length} bytes to ${flags.output} (sha256:${digest}). Review revision ${review.revision}, digest ${review.digest}.`);
|
|
42
42
|
}
|
|
@@ -23,7 +23,7 @@ class StoreGalleryAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
23
23
|
revision: flags.revision, digest: flags.digest, note: flags.note.trim(),
|
|
24
24
|
});
|
|
25
25
|
if (flags.json)
|
|
26
|
-
this.
|
|
26
|
+
this.printJsonResult(result);
|
|
27
27
|
else
|
|
28
28
|
this.log(`Refused gallery revision ${flags.revision}.`);
|
|
29
29
|
}
|
|
@@ -16,7 +16,7 @@ class StoreGalleryAdmissionsShow extends base_command_1.BaseCommand {
|
|
|
16
16
|
try {
|
|
17
17
|
const result = await data_provider_1.dataService.getStoreGalleryAdmission(flags.kind, args.id);
|
|
18
18
|
if (flags.json) {
|
|
19
|
-
this.
|
|
19
|
+
this.printJsonResult(result);
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
const r = result.review;
|
|
@@ -11,11 +11,31 @@ import { type PublicProjection, type AssistantTextJoiner } from '@skrr-ai/data-p
|
|
|
11
11
|
* — consent nobody gave, on a form nobody saw (OSK-10274).
|
|
12
12
|
*/
|
|
13
13
|
export declare const NON_INTERACTIVE_QUESTION_DISMISSAL: string;
|
|
14
|
+
/**
|
|
15
|
+
* A terminal that has printed the header and nothing else for several seconds looks hung. The
|
|
16
|
+
* first line comes after this long with no output at all, and then again at this interval
|
|
17
|
+
* (OSK-20427). Typical waits are 4 to 6 seconds before the first words, so a quick reply
|
|
18
|
+
* prints nothing extra.
|
|
19
|
+
*/
|
|
20
|
+
export declare const WAITING_NOTICE_AFTER_MS = 2500;
|
|
21
|
+
export declare const WAITING_NOTICE_EVERY_MS = 10000;
|
|
14
22
|
export type AgenticStreamEvent = {
|
|
15
23
|
type: string;
|
|
16
24
|
sessionId?: string;
|
|
17
25
|
[key: string]: unknown;
|
|
18
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* The sentence a failed run's terminal event gives for why it failed.
|
|
29
|
+
*
|
|
30
|
+
* The server's failure funnel (`handleSessionFailure`) sends `errors: [<sentence>]`
|
|
31
|
+
* and a short `reason`, never a `message`; other terminal events carry `message`,
|
|
32
|
+
* and a few an `error` string. Every reader used to look at `message` alone, so a
|
|
33
|
+
* run the platform refused ("no valid release package", "insufficient balance", a
|
|
34
|
+
* runtime that was not there) ended as `Error: Agent run failed` with the reason
|
|
35
|
+
* sitting unread in the same event (OSK-20410). One reader, in one order: the
|
|
36
|
+
* explicit `message`, then `error`, then the first entry of `errors`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function terminalFailureMessage(event: Record<string, unknown> | null | undefined): string | undefined;
|
|
19
39
|
export type AgenticStreamResult = {
|
|
20
40
|
sessionId: string;
|
|
21
41
|
responseMessageId?: string;
|
|
@@ -161,6 +181,12 @@ export type AgenticStreamOptions = {
|
|
|
161
181
|
/** Action-required notices when stdout is reserved for a final result. */
|
|
162
182
|
statusOutput?: NodeJS.WritableStream;
|
|
163
183
|
jsonl?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* With `jsonl`, a `text.delta` carries only the characters it adds (`delta`), not the whole
|
|
186
|
+
* answer so far, and not the envelopes `session.output` already carries. A rewrite that is not
|
|
187
|
+
* an append arrives as `replace`, the new full text. `run.result` still holds the whole answer.
|
|
188
|
+
*/
|
|
189
|
+
incrementalText?: boolean;
|
|
164
190
|
approveTools?: boolean;
|
|
165
191
|
input?: NodeJS.ReadableStream;
|
|
166
192
|
output?: NodeJS.WritableStream;
|
|
@@ -579,6 +605,12 @@ export declare class AgenticStreamClient {
|
|
|
579
605
|
private readonly openQuestionPrompts;
|
|
580
606
|
/** Text already written to the terminal, for suffix-only rendering. */
|
|
581
607
|
private renderedText;
|
|
608
|
+
/** The "still waiting" line for a terminal run with no output yet (OSK-20427). */
|
|
609
|
+
private waitingTimer;
|
|
610
|
+
private waitingStartedAt;
|
|
611
|
+
private outputSeen;
|
|
612
|
+
/** The cumulative text of the last `text.delta` written as JSON, for `delta`/`replace`. */
|
|
613
|
+
private lastJsonlText;
|
|
582
614
|
private idleTimer;
|
|
583
615
|
/** Releases a connect wait still in flight; `close()` calls it. */
|
|
584
616
|
private abandonConnectWait;
|
|
@@ -777,6 +809,20 @@ export declare class AgenticStreamClient {
|
|
|
777
809
|
* passed through, preserving prior behaviour.
|
|
778
810
|
*/
|
|
779
811
|
private emitToolEvent;
|
|
812
|
+
/**
|
|
813
|
+
* Say so when a terminal run has been quiet since it started. Human output only: a script
|
|
814
|
+
* reading --jsonl has the events, and --quiet asked for nothing but the answer.
|
|
815
|
+
*/
|
|
816
|
+
private trackWaiting;
|
|
817
|
+
private stopWaiting;
|
|
818
|
+
/**
|
|
819
|
+
* A `text.delta` is named for a delta and carries the whole answer so far (`text`), so a long
|
|
820
|
+
* answer written as JSON lines grows with the square of its length: 207 events for a 2.4 KB
|
|
821
|
+
* answer came to about 250 KB (OSK-20428). The contract stays, since scripts take the last one;
|
|
822
|
+
* `delta` is added to it, and `incrementalText` turns the cumulative text and the duplicated
|
|
823
|
+
* envelopes off for a consumer that wants only what is new.
|
|
824
|
+
*/
|
|
825
|
+
private jsonlView;
|
|
780
826
|
private emit;
|
|
781
827
|
/**
|
|
782
828
|
* Human-mode lines for the hand-over wait. Returns true when the event is
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgenticStreamClient = exports.USER_CONNECTION_CAP_CODE = exports.CODEX_DECLINED_TOOL_OUTPUTS = exports.TYPE_AHEAD_DISCARD_MS = exports.HANDOVER_POLL_INTERVAL_MS = exports.DAEMON_HANDOVER_REASON = exports.WORKER_REPLACED_CODE = exports.NON_INTERACTIVE_QUESTION_DISMISSAL = void 0;
|
|
3
|
+
exports.AgenticStreamClient = exports.USER_CONNECTION_CAP_CODE = exports.CODEX_DECLINED_TOOL_OUTPUTS = exports.TYPE_AHEAD_DISCARD_MS = exports.HANDOVER_POLL_INTERVAL_MS = exports.DAEMON_HANDOVER_REASON = exports.WORKER_REPLACED_CODE = exports.WAITING_NOTICE_EVERY_MS = exports.WAITING_NOTICE_AFTER_MS = exports.NON_INTERACTIVE_QUESTION_DISMISSAL = void 0;
|
|
4
|
+
exports.terminalFailureMessage = terminalFailureMessage;
|
|
4
5
|
exports.isDaemonHandoverFailure = isDaemonHandoverFailure;
|
|
5
6
|
exports.formatWaitDuration = formatWaitDuration;
|
|
6
7
|
exports.writeJsonLine = writeJsonLine;
|
|
@@ -46,6 +47,47 @@ const dpop_auth_1 = require("./dpop-auth");
|
|
|
46
47
|
*/
|
|
47
48
|
exports.NON_INTERACTIVE_QUESTION_DISMISSAL = 'No answer: this turn was started non-interactively (no terminal), so nobody can reply to ' +
|
|
48
49
|
'questions. Proceed with your best judgement, or finish by stating exactly what you need.';
|
|
50
|
+
/**
|
|
51
|
+
* A terminal that has printed the header and nothing else for several seconds looks hung. The
|
|
52
|
+
* first line comes after this long with no output at all, and then again at this interval
|
|
53
|
+
* (OSK-20427). Typical waits are 4 to 6 seconds before the first words, so a quick reply
|
|
54
|
+
* prints nothing extra.
|
|
55
|
+
*/
|
|
56
|
+
exports.WAITING_NOTICE_AFTER_MS = 2500;
|
|
57
|
+
exports.WAITING_NOTICE_EVERY_MS = 10_000;
|
|
58
|
+
/** What counts as the run having said something, so the waiting line stops. */
|
|
59
|
+
const OUTPUT_EVENT_TYPES = new Set([
|
|
60
|
+
'text.delta',
|
|
61
|
+
'tool.started',
|
|
62
|
+
'tool.completed',
|
|
63
|
+
'session.notice',
|
|
64
|
+
'permission.requested',
|
|
65
|
+
'run.completed',
|
|
66
|
+
'run.failed',
|
|
67
|
+
'run.aborted',
|
|
68
|
+
'run.handed_over',
|
|
69
|
+
]);
|
|
70
|
+
/**
|
|
71
|
+
* The sentence a failed run's terminal event gives for why it failed.
|
|
72
|
+
*
|
|
73
|
+
* The server's failure funnel (`handleSessionFailure`) sends `errors: [<sentence>]`
|
|
74
|
+
* and a short `reason`, never a `message`; other terminal events carry `message`,
|
|
75
|
+
* and a few an `error` string. Every reader used to look at `message` alone, so a
|
|
76
|
+
* run the platform refused ("no valid release package", "insufficient balance", a
|
|
77
|
+
* runtime that was not there) ended as `Error: Agent run failed` with the reason
|
|
78
|
+
* sitting unread in the same event (OSK-20410). One reader, in one order: the
|
|
79
|
+
* explicit `message`, then `error`, then the first entry of `errors`.
|
|
80
|
+
*/
|
|
81
|
+
function terminalFailureMessage(event) {
|
|
82
|
+
if (!event)
|
|
83
|
+
return undefined;
|
|
84
|
+
const sentence = (value) => typeof value === 'string' && value.trim() ? value : undefined;
|
|
85
|
+
const entryText = (entry) => sentence(entry) ?? sentence(entry?.message);
|
|
86
|
+
const fromList = Array.isArray(event.errors)
|
|
87
|
+
? event.errors.map(entryText).find((entry) => entry !== undefined)
|
|
88
|
+
: undefined;
|
|
89
|
+
return sentence(event.message) ?? sentence(event.error) ?? fromList;
|
|
90
|
+
}
|
|
49
91
|
/**
|
|
50
92
|
* OSK-13517 / OSK-13543 — the one failure that is not an ending.
|
|
51
93
|
*
|
|
@@ -807,6 +849,12 @@ class AgenticStreamClient {
|
|
|
807
849
|
openQuestionPrompts = new Map();
|
|
808
850
|
/** Text already written to the terminal, for suffix-only rendering. */
|
|
809
851
|
renderedText = '';
|
|
852
|
+
/** The "still waiting" line for a terminal run with no output yet (OSK-20427). */
|
|
853
|
+
waitingTimer = null;
|
|
854
|
+
waitingStartedAt = 0;
|
|
855
|
+
outputSeen = false;
|
|
856
|
+
/** The cumulative text of the last `text.delta` written as JSON, for `delta`/`replace`. */
|
|
857
|
+
lastJsonlText = '';
|
|
810
858
|
idleTimer = null;
|
|
811
859
|
/** Releases a connect wait still in flight; `close()` calls it. */
|
|
812
860
|
abandonConnectWait = null;
|
|
@@ -1012,6 +1060,7 @@ class AgenticStreamClient {
|
|
|
1012
1060
|
if (this.replayTimer)
|
|
1013
1061
|
clearTimeout(this.replayTimer);
|
|
1014
1062
|
this.replayTimer = null;
|
|
1063
|
+
this.stopWaiting();
|
|
1015
1064
|
this.stopHandoverTimers();
|
|
1016
1065
|
this.pendingEnvelopes.clear();
|
|
1017
1066
|
this.browserPermissionRequests.clear();
|
|
@@ -1079,10 +1128,7 @@ class AgenticStreamClient {
|
|
|
1079
1128
|
const deadlineTimer = setTimeout(() => void this.expireHandover(), opts.maxWaitMs);
|
|
1080
1129
|
const pollTimer = setInterval(() => this.requestHandoverRead(), opts.pollIntervalMs ?? exports.HANDOVER_POLL_INTERVAL_MS);
|
|
1081
1130
|
this.handover = { event, startedAt, deadlineTimer, pollTimer, reading: null, readAgain: false };
|
|
1082
|
-
const
|
|
1083
|
-
? event.errors[0]
|
|
1084
|
-
: undefined;
|
|
1085
|
-
const message = typeof event.message === 'string' && event.message ? event.message : firstError;
|
|
1131
|
+
const message = terminalFailureMessage(event);
|
|
1086
1132
|
this.emit({
|
|
1087
1133
|
type: 'run.handed_over',
|
|
1088
1134
|
sessionId: this.options.sessionId,
|
|
@@ -1745,6 +1791,10 @@ class AgenticStreamClient {
|
|
|
1745
1791
|
return;
|
|
1746
1792
|
}
|
|
1747
1793
|
if (!this.options.approveTools || !this.socket) {
|
|
1794
|
+
// This CLI makes the decision and nobody is asked, so it says so FIRST. The bound path used
|
|
1795
|
+
// to return before any event, and the only lines a person saw were the server's "The
|
|
1796
|
+
// response was admitted. Tool execution is not confirmed.", which read like an approval.
|
|
1797
|
+
this.emit({ ...event, type: 'permission.denied', reason: 'noninteractive_or_not_enabled' });
|
|
1748
1798
|
if (event.toolUseId) {
|
|
1749
1799
|
if (await this.sendBoundPermissionDecision(event, false, { reason: 'CLI was not started with --approve-tools', automatic: true }))
|
|
1750
1800
|
return;
|
|
@@ -1759,7 +1809,6 @@ class AgenticStreamClient {
|
|
|
1759
1809
|
automatic: true,
|
|
1760
1810
|
});
|
|
1761
1811
|
}
|
|
1762
|
-
this.emit({ ...event, type: 'permission.denied', reason: 'noninteractive_or_not_enabled' });
|
|
1763
1812
|
return;
|
|
1764
1813
|
}
|
|
1765
1814
|
/**
|
|
@@ -1782,6 +1831,14 @@ class AgenticStreamClient {
|
|
|
1782
1831
|
*/
|
|
1783
1832
|
const interactive = this.options.input !== undefined || Boolean(process.stdin.isTTY);
|
|
1784
1833
|
if (!interactive) {
|
|
1834
|
+
// Announced before it is sent, as the denial is: the bound path used to return first, so
|
|
1835
|
+
// "allowed by --approve-tools" never reached a person who used the flag.
|
|
1836
|
+
this.emit({
|
|
1837
|
+
...event,
|
|
1838
|
+
type: 'permission.approved',
|
|
1839
|
+
auto: true,
|
|
1840
|
+
reason: 'approved by --approve-tools, which was given with no terminal to ask at',
|
|
1841
|
+
});
|
|
1785
1842
|
if (await this.sendBoundPermissionDecision(event, true))
|
|
1786
1843
|
return;
|
|
1787
1844
|
this.socket.emit('permission:approve', {
|
|
@@ -1789,12 +1846,6 @@ class AgenticStreamClient {
|
|
|
1789
1846
|
toolUseId: event.toolUseId,
|
|
1790
1847
|
toolName: event.toolName,
|
|
1791
1848
|
});
|
|
1792
|
-
this.emit({
|
|
1793
|
-
...event,
|
|
1794
|
-
type: 'permission.approved',
|
|
1795
|
-
auto: true,
|
|
1796
|
-
reason: 'approved by --approve-tools, which was given with no terminal to ask at',
|
|
1797
|
-
});
|
|
1798
1849
|
return;
|
|
1799
1850
|
}
|
|
1800
1851
|
const prompt = new AbortController();
|
|
@@ -2084,6 +2135,60 @@ class AgenticStreamClient {
|
|
|
2084
2135
|
return;
|
|
2085
2136
|
this.emit(event);
|
|
2086
2137
|
}
|
|
2138
|
+
/**
|
|
2139
|
+
* Say so when a terminal run has been quiet since it started. Human output only: a script
|
|
2140
|
+
* reading --jsonl has the events, and --quiet asked for nothing but the answer.
|
|
2141
|
+
*/
|
|
2142
|
+
trackWaiting(event, output) {
|
|
2143
|
+
if (OUTPUT_EVENT_TYPES.has(event.type)) {
|
|
2144
|
+
this.outputSeen = true;
|
|
2145
|
+
this.stopWaiting();
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
if (event.type !== 'run.started' || this.outputSeen || this.waitingTimer)
|
|
2149
|
+
return;
|
|
2150
|
+
this.waitingStartedAt = Date.now();
|
|
2151
|
+
const schedule = (first) => {
|
|
2152
|
+
this.waitingTimer = setTimeout(() => {
|
|
2153
|
+
this.waitingTimer = null;
|
|
2154
|
+
if (this.outputSeen || this.closed)
|
|
2155
|
+
return;
|
|
2156
|
+
const seconds = Math.floor((Date.now() - this.waitingStartedAt) / 1000);
|
|
2157
|
+
output.write(first
|
|
2158
|
+
? '[run] waiting for the agent to start answering…\n'
|
|
2159
|
+
: `[run] still waiting for the agent (${seconds} s)…\n`);
|
|
2160
|
+
schedule(false);
|
|
2161
|
+
}, first ? exports.WAITING_NOTICE_AFTER_MS : exports.WAITING_NOTICE_EVERY_MS);
|
|
2162
|
+
// A reminder must never be the reason the process stays alive.
|
|
2163
|
+
this.waitingTimer.unref?.();
|
|
2164
|
+
};
|
|
2165
|
+
schedule(true);
|
|
2166
|
+
}
|
|
2167
|
+
stopWaiting() {
|
|
2168
|
+
if (this.waitingTimer)
|
|
2169
|
+
clearTimeout(this.waitingTimer);
|
|
2170
|
+
this.waitingTimer = null;
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* A `text.delta` is named for a delta and carries the whole answer so far (`text`), so a long
|
|
2174
|
+
* answer written as JSON lines grows with the square of its length: 207 events for a 2.4 KB
|
|
2175
|
+
* answer came to about 250 KB (OSK-20428). The contract stays, since scripts take the last one;
|
|
2176
|
+
* `delta` is added to it, and `incrementalText` turns the cumulative text and the duplicated
|
|
2177
|
+
* envelopes off for a consumer that wants only what is new.
|
|
2178
|
+
*/
|
|
2179
|
+
jsonlView(event) {
|
|
2180
|
+
if (event.type !== 'text.delta' || typeof event.text !== 'string')
|
|
2181
|
+
return event;
|
|
2182
|
+
const previous = this.lastJsonlText;
|
|
2183
|
+
const text = event.text;
|
|
2184
|
+
this.lastJsonlText = text;
|
|
2185
|
+
const appended = text.startsWith(previous) ? text.slice(previous.length) : undefined;
|
|
2186
|
+
if (!this.options.incrementalText) {
|
|
2187
|
+
return appended === undefined ? event : { ...event, delta: appended };
|
|
2188
|
+
}
|
|
2189
|
+
const { text: _text, envelopes: _envelopes, ...rest } = event;
|
|
2190
|
+
return appended === undefined ? { ...rest, replace: text } : { ...rest, delta: appended };
|
|
2191
|
+
}
|
|
2087
2192
|
emit(event) {
|
|
2088
2193
|
this.lastEvent = event;
|
|
2089
2194
|
this.options.onEvent?.(event);
|
|
@@ -2108,9 +2213,10 @@ class AgenticStreamClient {
|
|
|
2108
2213
|
return;
|
|
2109
2214
|
const output = this.options.output ?? process.stdout;
|
|
2110
2215
|
if (this.options.jsonl) {
|
|
2111
|
-
writeJsonLine(output, event);
|
|
2216
|
+
writeJsonLine(output, this.jsonlView(event));
|
|
2112
2217
|
return;
|
|
2113
2218
|
}
|
|
2219
|
+
this.trackWaiting(event, output);
|
|
2114
2220
|
if (event.type === 'run.started') {
|
|
2115
2221
|
const permission = describeRunPermission(event);
|
|
2116
2222
|
if (permission)
|
|
@@ -2192,6 +2298,12 @@ class AgenticStreamClient {
|
|
|
2192
2298
|
output.write(`\n[question] ${why}\n`);
|
|
2193
2299
|
this.renderedText = this.answerText();
|
|
2194
2300
|
}
|
|
2301
|
+
else if (event.type === 'permission.denied' && event.reason === 'noninteractive_or_not_enabled') {
|
|
2302
|
+
// Said out loud, because nobody was asked and the agent will not say it plainly: this run
|
|
2303
|
+
// had no terminal to ask at and was not given --approve-tools, so the call was refused.
|
|
2304
|
+
output.write(`\n[permission] ${describePermission(event)} denied: nobody could be asked, and this run was not started with --approve-tools\n`);
|
|
2305
|
+
this.renderedText = this.answerText();
|
|
2306
|
+
}
|
|
2195
2307
|
else if (event.type === 'permission.approved' && event.auto === true) {
|
|
2196
2308
|
// Said out loud, because nobody was asked: the flag approved it, and a
|
|
2197
2309
|
// reader of this log should see which tools that covered (OSK-10323).
|
|
@@ -2379,7 +2491,16 @@ class AgenticStreamClient {
|
|
|
2379
2491
|
output.write(append);
|
|
2380
2492
|
output.write('\n');
|
|
2381
2493
|
}
|
|
2382
|
-
|
|
2494
|
+
// A failed run states why under the one key a script reads (`message`), whichever
|
|
2495
|
+
// shape the terminal event used. `lastEvent` below stays the event as received.
|
|
2496
|
+
const failureMessage = status === 'failed' && !(typeof event.message === 'string' && event.message.trim())
|
|
2497
|
+
? terminalFailureMessage(event)
|
|
2498
|
+
: undefined;
|
|
2499
|
+
this.emit({
|
|
2500
|
+
...event,
|
|
2501
|
+
...(failureMessage ? { message: failureMessage } : {}),
|
|
2502
|
+
type: `run.${status}`,
|
|
2503
|
+
});
|
|
2383
2504
|
this.close();
|
|
2384
2505
|
this.terminalResult = {
|
|
2385
2506
|
sessionId: this.options.sessionId,
|
|
@@ -38,9 +38,22 @@ export declare function plainCredentialEnvelopeWarning(args: readonly unknown[])
|
|
|
38
38
|
export declare const CREDENTIAL_KEY_CHANGED_NOTICE: string;
|
|
39
39
|
/**
|
|
40
40
|
* The one line an unreadable device key prints when no credential-key change
|
|
41
|
-
* explains it
|
|
42
|
-
*
|
|
41
|
+
* explains it (OSK-20506).
|
|
42
|
+
*
|
|
43
|
+
* The CLI never enrolls or requires a device key (OSK-12063), so this degrades a
|
|
44
|
+
* proof, not a sign-in: say exactly that. What it must not do is point at
|
|
45
|
+
* `skrr login`. That signs this CLI in on its own and never creates or replaces a
|
|
46
|
+
* device key, so a person who followed it would be told the same thing on the next
|
|
47
|
+
* command. Only an interactive daemon sign-in mints a key and re-pins it, and which
|
|
48
|
+
* one depends on who runs the daemon, so this uses the sentence the hand-off
|
|
49
|
+
* refusals use for the same repair (`daemonSignInRemedy`) rather than a second
|
|
50
|
+
* spelling.
|
|
51
|
+
*
|
|
52
|
+
* `profile` names the command for a non-default profile: a bare `skrr daemon login`
|
|
53
|
+
* signs the default daemon in and leaves this one as it was (OSK-16435).
|
|
43
54
|
*/
|
|
55
|
+
export declare function deviceKeyRecoveryRequiredNotice(profile?: string): string;
|
|
56
|
+
/** The notice for the default profile. */
|
|
44
57
|
export declare const DEVICE_KEY_RECOVERY_REQUIRED_NOTICE: string;
|
|
45
58
|
export declare function createCredentialEnvelopeWarningPresenter(): (args: readonly unknown[]) => string | null;
|
|
46
59
|
type DedicatedGenerationPreparationOptions = {
|