@skrr-ai/cli 0.1.114 → 0.1.115
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.js +10 -1
- package/dist/commands/computer-use/audio.d.ts +6 -0
- package/dist/commands/computer-use/audio.js +9 -0
- package/dist/commands/computer-use/browser.d.ts +7 -0
- package/dist/commands/computer-use/browser.js +16 -0
- package/dist/commands/computer-use/disable.d.ts +6 -0
- package/dist/commands/computer-use/disable.js +9 -0
- package/dist/commands/computer-use/enable.d.ts +6 -0
- package/dist/commands/computer-use/enable.js +9 -0
- package/dist/commands/computer-use/index.d.ts +6 -0
- package/dist/commands/computer-use/index.js +9 -0
- package/dist/commands/computer-use/install.d.ts +6 -0
- package/dist/commands/computer-use/install.js +9 -0
- package/dist/commands/computer-use/recover.d.ts +6 -0
- package/dist/commands/computer-use/recover.js +9 -0
- package/dist/commands/computer-use/status.d.ts +6 -0
- package/dist/commands/computer-use/status.js +9 -0
- package/dist/commands/computer-use/stop.d.ts +6 -0
- package/dist/commands/computer-use/stop.js +9 -0
- package/dist/commands/daemon/login.js +1 -1
- package/dist/commands/followups/plans/cancel.js +10 -3
- package/dist/commands/followups/plans/capacity.d.ts +9 -0
- package/dist/commands/followups/plans/capacity.js +42 -0
- package/dist/commands/followups/plans/create.js +3 -0
- package/dist/commands/followups/plans/revise.js +13 -6
- package/dist/lib/agentic-stream.d.ts +5 -1
- package/dist/lib/agentic-stream.js +25 -9
- package/dist/lib/computer-use.d.ts +9 -0
- package/dist/lib/computer-use.js +41 -0
- package/dist/lib/lookbackPlans.d.ts +20 -6
- package/dist/lib/lookbackPlans.js +19 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerUse.d.ts +228 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerUse.js +375 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +4 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +6 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +40 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/desktopWire.d.ts +140 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/desktopWire.js +46 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +1 -1
- 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 +8 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerUse.d.ts +228 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerUse.js +358 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +4 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +5 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +40 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/desktopWire.d.ts +140 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/desktopWire.js +42 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +1 -1
- 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 +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +21 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +23687 -23456
- package/oclif.manifest.json +284 -4
- package/package.json +2 -2
|
@@ -105,10 +105,14 @@ function reconcileTerminalFromMessages(messages, responseMessageId) {
|
|
|
105
105
|
[...messages].reverse().find((m) => m && m.isCreatedByUser === false);
|
|
106
106
|
if (!row)
|
|
107
107
|
return null;
|
|
108
|
+
const projection = row.metadata && typeof row.metadata === 'object'
|
|
109
|
+
? row.metadata.publicProjection : undefined;
|
|
110
|
+
const publicProjection = (0, data_provider_1.isDecodedPublicProjection)(projection) ? { publicProjection: projection } : {};
|
|
108
111
|
const failure = (0, data_provider_1.resolveMessageFailure)(row);
|
|
109
112
|
if (failure) {
|
|
110
113
|
return {
|
|
111
114
|
status: 'failed',
|
|
115
|
+
...publicProjection,
|
|
112
116
|
...(failure.answer ? { text: failure.answer } : {}),
|
|
113
117
|
// The reason exists on the row; it simply never reached the surface. Say
|
|
114
118
|
// it, rather than the transport error that masked it (OSK-7595).
|
|
@@ -123,7 +127,7 @@ function reconcileTerminalFromMessages(messages, responseMessageId) {
|
|
|
123
127
|
// it set is a turn that ended having produced nothing, which is still
|
|
124
128
|
// terminal and still better reported than waited on.
|
|
125
129
|
if (row.unfinished === false)
|
|
126
|
-
return { status: 'completed', text };
|
|
130
|
+
return { status: 'completed', text, ...publicProjection };
|
|
127
131
|
return null;
|
|
128
132
|
}
|
|
129
133
|
function agenticRecord(row) {
|
|
@@ -161,12 +165,16 @@ function handoverStateFromMessages(messages, responseMessageId) {
|
|
|
161
165
|
(!responseMessageId && [...messages].reverse().find((m) => m && m.isCreatedByUser === false));
|
|
162
166
|
if (!row)
|
|
163
167
|
return { state: 'pending' };
|
|
168
|
+
const projection = row.metadata && typeof row.metadata === 'object'
|
|
169
|
+
? row.metadata.publicProjection : undefined;
|
|
170
|
+
const publicProjection = (0, data_provider_1.isDecodedPublicProjection)(projection) ? { publicProjection: projection } : {};
|
|
164
171
|
const failure = (0, data_provider_1.resolveMessageFailure)(row);
|
|
165
172
|
if (failure) {
|
|
166
173
|
if (agenticErrorSubtype(row) === agentic_stream_1.DAEMON_HANDOVER_REASON)
|
|
167
174
|
return { state: 'pending' };
|
|
168
175
|
return {
|
|
169
176
|
state: 'failed',
|
|
177
|
+
...publicProjection,
|
|
170
178
|
error: failure.reason ?? 'The run failed. No reason was recorded on the message.',
|
|
171
179
|
...(failure.answer ? { text: failure.answer } : {}),
|
|
172
180
|
};
|
|
@@ -178,6 +186,7 @@ function handoverStateFromMessages(messages, responseMessageId) {
|
|
|
178
186
|
const repairedAt = typeof repair.repairedAt === 'string' ? repair.repairedAt : undefined;
|
|
179
187
|
return {
|
|
180
188
|
state: 'repaired',
|
|
189
|
+
...publicProjection,
|
|
181
190
|
text: typeof row.text === 'string' ? row.text : '',
|
|
182
191
|
...(repairedAt ? { repairedAt } : {}),
|
|
183
192
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseAudio extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Configure optional computer audio with status, enable or disable';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use audio --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'audio';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseAudio;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseBrowser extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Configure original Chrome, inspect its extension, and manage its native host';
|
|
6
|
+
static description = 'Actions: status, enable, disable, setup, update, verify. Setup uses the original LCU installer: private relay files belong to the selected skrr profile, while native-host registration is shared by the desktop account and supported Chromium browsers. Verify initializes the original MCP schema without browser actions. Flags are forwarded unchanged; run `skrrd computer-use browser --help` for all options.';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> computer-use browser enable',
|
|
9
|
+
'<%= config.bin %> computer-use browser setup --profile work',
|
|
10
|
+
'<%= config.bin %> computer-use browser status --profile work --json',
|
|
11
|
+
'<%= config.bin %> computer-use browser update --profile work',
|
|
12
|
+
'<%= config.bin %> computer-use browser verify --profile work --json',
|
|
13
|
+
];
|
|
14
|
+
action = 'browser';
|
|
15
|
+
}
|
|
16
|
+
exports.default = ComputerUseBrowser;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseDisable extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Revoke Computer Use consent and stop the active controller';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use disable --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'disable';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseDisable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseEnable extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Enable Computer Use locally; --cloud-agents separately grants cloud Agent access';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use enable --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'enable';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseEnable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUse extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Install and control optional Computer Use on this machine';
|
|
6
|
+
static description = 'Computer Use uses your installed official app runtime. Run `skrr computer-use status`; use `skrrd computer-use --help` for all options, including --profile and --json.';
|
|
7
|
+
action = undefined;
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUse;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseInstall extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Install a pinned thin release from an explicit local archive and trusted SHA-256';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use install --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'install';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseInstall;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseRecover extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Retry runtime recovery only after confirmed execution cleanup';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use recover --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'recover';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseRecover;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseStatus extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Show configuration and live Computer Use availability without desktop interaction';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use status --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'status';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseStatus;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const computer_use_1 = require("../../lib/computer-use");
|
|
4
|
+
class ComputerUseStop extends computer_use_1.ComputerUseCommand {
|
|
5
|
+
static summary = 'Stop the running Computer Use controller and confirm cleanup';
|
|
6
|
+
static description = 'Flags are forwarded unchanged. Run `skrrd computer-use stop --help` for options; --profile selects the local daemon profile and --json emits one stable document.';
|
|
7
|
+
action = 'stop';
|
|
8
|
+
}
|
|
9
|
+
exports.default = ComputerUseStop;
|
|
@@ -32,7 +32,7 @@ const daemon_machine_identity_copy_1 = require("../../lib/daemon-machine-identit
|
|
|
32
32
|
class DaemonLogin extends core_1.Command {
|
|
33
33
|
static aliases = ['daemons:login'];
|
|
34
34
|
static summary = 'Authenticate the skrr background service on this computer (separate from `skrr login`)';
|
|
35
|
-
static description = (0, exec_runtime_binary_1.forwardedFlagsNote)('login', { binds: true });
|
|
35
|
+
static description = (0, exec_runtime_binary_1.forwardedFlagsNote)('login', { binds: true }) + '\nUse --computer-use to request explicit Computer Use permission in browser consent. This does not enable the runtime or grant machine access.';
|
|
36
36
|
static strict = false; // forward all args verbatim — see run()
|
|
37
37
|
async run() {
|
|
38
38
|
// `this.argv`, NOT `this.parse()` — `strict = false` relaxes POSITIONAL
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const lookbackPlans_1 = require("../../../lib/lookbackPlans");
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../../base-command");
|
|
5
|
-
const
|
|
6
|
+
const lookbackPlans_2 = require("../../../lib/lookbackPlans");
|
|
6
7
|
class LookbackPlansCancel extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Cancel the remaining lookbacks of a plan';
|
|
8
|
-
static args = { id:
|
|
9
|
+
static args = { id: lookbackPlans_2.lookbackPlanIdArg };
|
|
9
10
|
static flags = {
|
|
10
11
|
revision: core_1.Flags.integer({ description: 'Expected current revision; stale edits are refused', min: 1 }),
|
|
11
12
|
reason: core_1.Flags.string({ description: 'Why the remaining lookbacks are no longer needed' }),
|
|
@@ -15,10 +16,16 @@ class LookbackPlansCancel extends base_command_1.BaseCommand {
|
|
|
15
16
|
this.requireAuth();
|
|
16
17
|
const { args, flags } = await this.parse(LookbackPlansCancel);
|
|
17
18
|
try {
|
|
18
|
-
const result = await
|
|
19
|
+
const result = await lookbackPlans_2.lookbackPlansApi.cancel(args.id, { expectedRevision: flags.revision, reason: flags.reason });
|
|
19
20
|
this.log(flags.json ? JSON.stringify(result, null, 2) : `Lookback plan ${result.plan.id}: ${result.plan.state} (r${result.plan.revision}).`);
|
|
20
21
|
}
|
|
21
22
|
catch (err) {
|
|
23
|
+
if ((0, lookbackPlans_1.isLookbackMutationOutcomeUnknown)(err)) {
|
|
24
|
+
const readback = await lookbackPlans_2.lookbackPlansApi.show(args.id).catch(() => null);
|
|
25
|
+
this.failWithCliError((0, lookbackPlans_1.lookbackUnconfirmedFailure)({ operation: 'cancel', planId: args.id,
|
|
26
|
+
...(readback?.plan ? { currentPlan: readback.plan } : {}),
|
|
27
|
+
readback: readback?.plan ? 'observed' : 'unavailable' }));
|
|
28
|
+
}
|
|
22
29
|
this.handleApiError(err);
|
|
23
30
|
}
|
|
24
31
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export default class LookbackPlansCapacity extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../../base-command");
|
|
5
|
+
const lookbackPlans_1 = require("../../../lib/lookbackPlans");
|
|
6
|
+
const followups_1 = require("../../../lib/followups");
|
|
7
|
+
class LookbackPlansCapacity extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'Read one agent’s actual UTC-day lookback plan allowance; reserves nothing';
|
|
9
|
+
static flags = {
|
|
10
|
+
agent: core_1.Flags.string({ description: 'Agent ID (default: bound session agent)' }),
|
|
11
|
+
json: core_1.Flags.boolean({ description: 'Output authoritative capacity facts as JSON' }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
this.requireAuth();
|
|
15
|
+
const { flags } = await this.parse(LookbackPlansCapacity);
|
|
16
|
+
let agentId;
|
|
17
|
+
try {
|
|
18
|
+
agentId = (0, followups_1.resolveFollowUpAgent)(flags.agent).id;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
this.failWithCliError({ message: err instanceof Error ? err.message : String(err),
|
|
22
|
+
code: 'AGENT_CONTEXT_AMBIGUOUS', exit: 2, retryable: false });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const result = await lookbackPlans_1.lookbackPlansApi.capacity({ agentId });
|
|
27
|
+
if (flags.json) {
|
|
28
|
+
this.log(JSON.stringify(result, null, 2));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.log(`${result.scope.agentId}: ${result.remaining}/${result.limit} plans remaining (${result.used} admitted this UTC day).`);
|
|
32
|
+
this.log(result.admission === 'policy_blocked'
|
|
33
|
+
? 'New plans are blocked by a zero agent allowance. The daily reset does not change that policy.'
|
|
34
|
+
: `UTC-day reset: ${new Date(result.period.resetAt).toLocaleString()} (${result.period.resetAt}). Recheck capacity then.`);
|
|
35
|
+
this.log(`Observed: ${result.observedAt}. This read reserves nothing; source, execution and delivery are checked separately.`);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.handleApiError(err);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.default = LookbackPlansCapacity;
|
|
@@ -30,6 +30,9 @@ class LookbackPlansCreate extends base_command_1.BaseCommand {
|
|
|
30
30
|
this.log(flags.json ? JSON.stringify(result, null, 2) : (0, lookbackPlans_1.lookbackArmingLine)(result));
|
|
31
31
|
}
|
|
32
32
|
catch (err) {
|
|
33
|
+
if ((0, lookbackPlans_1.isLookbackMutationOutcomeUnknown)(err)) {
|
|
34
|
+
this.failWithCliError((0, lookbackPlans_1.lookbackUnconfirmedFailure)({ operation: 'create', source: body.plan.source, agentId: body.agentId }));
|
|
35
|
+
}
|
|
33
36
|
this.handleApiError(err);
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const lookbackPlans_1 = require("../../../lib/lookbackPlans");
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../../base-command");
|
|
5
6
|
const prompt_1 = require("../../../lib/prompt");
|
|
6
|
-
const
|
|
7
|
+
const lookbackPlans_2 = require("../../../lib/lookbackPlans");
|
|
7
8
|
const lookbackPlanHelp_1 = require("../../../lib/lookbackPlanHelp");
|
|
8
9
|
class LookbackPlansRevise extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Revise pending lookbacks using the original source and step IDs\n\n' + lookbackPlanHelp_1.LOOKBACK_PLAN_INPUT_HELP +
|
|
10
11
|
'\n\nRevise accepts the plan itself, not a create envelope. Use the current --revision from show; a stale revision returns LOOKBACK_CONFLICT (409).';
|
|
11
12
|
static examples = ['<%= config.bin %> followups plans revise PLAN_ID --revision 1 --from-json revised-plan.json --json'];
|
|
12
|
-
static args = { id:
|
|
13
|
+
static args = { id: lookbackPlans_2.lookbackPlanIdArg };
|
|
13
14
|
static flags = {
|
|
14
15
|
revision: core_1.Flags.integer({ description: 'Expected current revision; stale edits are refused', min: 1, required: true }),
|
|
15
16
|
'from-json': core_1.Flags.string({ description: 'Full PlanInput JSON file; - reads stdin', required: true }),
|
|
@@ -20,17 +21,23 @@ class LookbackPlansRevise extends base_command_1.BaseCommand {
|
|
|
20
21
|
const { args, flags } = await this.parse(LookbackPlansRevise);
|
|
21
22
|
let plan;
|
|
22
23
|
try {
|
|
23
|
-
plan = (0,
|
|
24
|
+
plan = (0, lookbackPlans_2.lookbackInput)(await (0, prompt_1.readJsonBody)(flags['from-json']), true);
|
|
24
25
|
}
|
|
25
26
|
catch (err) {
|
|
26
|
-
this.failWithCliError((0,
|
|
27
|
+
this.failWithCliError((0, lookbackPlans_2.lookbackInputFailure)(err));
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
29
30
|
try {
|
|
30
|
-
const result = await
|
|
31
|
-
this.log(flags.json ? JSON.stringify(result, null, 2) : (0,
|
|
31
|
+
const result = await lookbackPlans_2.lookbackPlansApi.revise(args.id, { expectedRevision: flags.revision, plan });
|
|
32
|
+
this.log(flags.json ? JSON.stringify(result, null, 2) : (0, lookbackPlans_2.lookbackArmingLine)(result));
|
|
32
33
|
}
|
|
33
34
|
catch (err) {
|
|
35
|
+
if ((0, lookbackPlans_1.isLookbackMutationOutcomeUnknown)(err)) {
|
|
36
|
+
const readback = await lookbackPlans_2.lookbackPlansApi.show(args.id).catch(() => null);
|
|
37
|
+
this.failWithCliError((0, lookbackPlans_1.lookbackUnconfirmedFailure)({ operation: 'revise', planId: args.id,
|
|
38
|
+
...(readback?.plan ? { currentPlan: readback.plan } : {}),
|
|
39
|
+
readback: readback?.plan ? 'observed' : 'unavailable' }));
|
|
40
|
+
}
|
|
34
41
|
this.handleApiError(err);
|
|
35
42
|
}
|
|
36
43
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AssistantTextJoiner } from '@skrr-ai/data-provider';
|
|
1
|
+
import { type PublicProjection, type AssistantTextJoiner } from '@skrr-ai/data-provider';
|
|
2
2
|
/**
|
|
3
3
|
* Why a question was dismissed when no terminal exists to ask it on. It is the
|
|
4
4
|
* REASON for a dismissal, never an answer: it travels as the value of the
|
|
@@ -48,6 +48,7 @@ export type AgenticStreamResult = {
|
|
|
48
48
|
*/
|
|
49
49
|
export type ReconciledTerminal = {
|
|
50
50
|
status: 'completed' | 'failed';
|
|
51
|
+
publicProjection?: PublicProjection;
|
|
51
52
|
/** The answer as persisted, when there is one. */
|
|
52
53
|
text?: string;
|
|
53
54
|
/** The recorded failure reason — `metadata.agentic.error` on the message. */
|
|
@@ -100,6 +101,7 @@ export type HandoverReading =
|
|
|
100
101
|
| {
|
|
101
102
|
state: 'repaired';
|
|
102
103
|
text: string;
|
|
104
|
+
publicProjection?: PublicProjection;
|
|
103
105
|
repairedAt?: string;
|
|
104
106
|
}
|
|
105
107
|
/** The machine's turn ended without finishing, and the server settled it so. */
|
|
@@ -107,6 +109,7 @@ export type HandoverReading =
|
|
|
107
109
|
state: 'failed';
|
|
108
110
|
error: string;
|
|
109
111
|
text?: string;
|
|
112
|
+
publicProjection?: PublicProjection;
|
|
110
113
|
};
|
|
111
114
|
export type HandoverWaitOptions = {
|
|
112
115
|
/** Read the persisted response message. A throw or null is "no evidence". */
|
|
@@ -512,6 +515,7 @@ export declare class AgenticStreamClient {
|
|
|
512
515
|
private readonly textJoiner;
|
|
513
516
|
/** Highest envelope `__seq` folded into `accumulated`, for gap detection. */
|
|
514
517
|
private highestSeq;
|
|
518
|
+
private publicProjection;
|
|
515
519
|
private readonly pendingEnvelopes;
|
|
516
520
|
private replayTimer;
|
|
517
521
|
private replayFlight;
|
|
@@ -740,6 +740,7 @@ class AgenticStreamClient {
|
|
|
740
740
|
textJoiner = (0, data_provider_1.createAssistantTextJoiner)();
|
|
741
741
|
/** Highest envelope `__seq` folded into `accumulated`, for gap detection. */
|
|
742
742
|
highestSeq = 0;
|
|
743
|
+
publicProjection;
|
|
743
744
|
pendingEnvelopes = new Map();
|
|
744
745
|
replayTimer = null;
|
|
745
746
|
replayFlight = null;
|
|
@@ -972,6 +973,7 @@ class AgenticStreamClient {
|
|
|
972
973
|
reason,
|
|
973
974
|
...(terminal.error ? { message: terminal.error, error: terminal.error } : {}),
|
|
974
975
|
...(typeof terminal.text === 'string' ? { result: terminal.text } : {}),
|
|
976
|
+
...(terminal.publicProjection ? { publicProjection: terminal.publicProjection } : {}),
|
|
975
977
|
});
|
|
976
978
|
return true;
|
|
977
979
|
}
|
|
@@ -1129,6 +1131,7 @@ class AgenticStreamClient {
|
|
|
1129
1131
|
type: 'execution:complete',
|
|
1130
1132
|
sessionId: this.options.sessionId,
|
|
1131
1133
|
result: reading.text,
|
|
1134
|
+
...(reading.publicProjection ? { publicProjection: reading.publicProjection } : {}),
|
|
1132
1135
|
repaired: true,
|
|
1133
1136
|
repairedFrom: 'durable_record',
|
|
1134
1137
|
overturned: { code: exports.WORKER_REPLACED_CODE, reason: exports.DAEMON_HANDOVER_REASON },
|
|
@@ -1146,6 +1149,7 @@ class AgenticStreamClient {
|
|
|
1146
1149
|
message: reading.error,
|
|
1147
1150
|
errors: [reading.error],
|
|
1148
1151
|
...(typeof reading.text === 'string' && reading.text ? { result: reading.text } : {}),
|
|
1152
|
+
...(reading.publicProjection ? { publicProjection: reading.publicProjection } : {}),
|
|
1149
1153
|
handover: { outcome: 'machine_failed', waitedMs },
|
|
1150
1154
|
});
|
|
1151
1155
|
return true;
|
|
@@ -1454,6 +1458,9 @@ class AgenticStreamClient {
|
|
|
1454
1458
|
if (fresh.length === 0)
|
|
1455
1459
|
return; // a pure re-delivery — drop it whole
|
|
1456
1460
|
const scoped = { ...event, envelopes: fresh };
|
|
1461
|
+
if (fresh.some((env) => env?.ev?.t === 'text' &&
|
|
1462
|
+
env.ev?.publicProjection === 'lookback_answer_v1'))
|
|
1463
|
+
this.publicProjection = 'lookback_answer_v1';
|
|
1457
1464
|
// Note what never arrived before folding this batch in (OSK-7631,
|
|
1458
1465
|
// OSK-13518). Checked against the FRESH set: a re-delivery carries old
|
|
1459
1466
|
// seqs and would read as a gap that never happened.
|
|
@@ -1539,6 +1546,8 @@ class AgenticStreamClient {
|
|
|
1539
1546
|
socket.on('message:stream', (event) => {
|
|
1540
1547
|
if (!match(event))
|
|
1541
1548
|
return;
|
|
1549
|
+
if (event.publicProjection === 'lookback_answer_v1')
|
|
1550
|
+
this.publicProjection = event.publicProjection;
|
|
1542
1551
|
const text = typeof event.text === 'string' ? event.text : '';
|
|
1543
1552
|
const delta = typeof event.delta === 'string' ? event.delta : '';
|
|
1544
1553
|
if (text && text.length >= this.accumulated.length)
|
|
@@ -1574,6 +1583,7 @@ class AgenticStreamClient {
|
|
|
1574
1583
|
if (!match(event))
|
|
1575
1584
|
return;
|
|
1576
1585
|
this.accumulated = '';
|
|
1586
|
+
this.publicProjection = undefined;
|
|
1577
1587
|
this.textJoiner.reset();
|
|
1578
1588
|
this.renderedText = '';
|
|
1579
1589
|
// Seqs restart with the stream, so a fresh low seq is not a gap.
|
|
@@ -2099,7 +2109,7 @@ class AgenticStreamClient {
|
|
|
2099
2109
|
const streamedText = (0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true });
|
|
2100
2110
|
void this.readRecordedText().then((recorded) => {
|
|
2101
2111
|
this.settleGapVerdict(streamedText, recorded);
|
|
2102
|
-
this.settle(status, event, recorded
|
|
2112
|
+
this.settle(status, event, recorded);
|
|
2103
2113
|
});
|
|
2104
2114
|
return;
|
|
2105
2115
|
}
|
|
@@ -2124,10 +2134,10 @@ class AgenticStreamClient {
|
|
|
2124
2134
|
try {
|
|
2125
2135
|
const terminal = await reconcile();
|
|
2126
2136
|
if (terminal && typeof terminal.text === 'string' && terminal.text) {
|
|
2127
|
-
return { text: terminal.text };
|
|
2137
|
+
return { text: terminal.text, ...(terminal.publicProjection ? { publicProjection: terminal.publicProjection } : {}) };
|
|
2128
2138
|
}
|
|
2129
2139
|
if (terminal)
|
|
2130
|
-
empty = { text: '' };
|
|
2140
|
+
empty = { text: '', ...(terminal.publicProjection ? { publicProjection: terminal.publicProjection } : {}) };
|
|
2131
2141
|
}
|
|
2132
2142
|
catch {
|
|
2133
2143
|
// No evidence either way; try again, then settle on the stream.
|
|
@@ -2135,7 +2145,7 @@ class AgenticStreamClient {
|
|
|
2135
2145
|
}
|
|
2136
2146
|
return empty;
|
|
2137
2147
|
}
|
|
2138
|
-
settle(status, event,
|
|
2148
|
+
settle(status, event, recorded) {
|
|
2139
2149
|
// `execution:complete` carries the final answer as `result`, and it is
|
|
2140
2150
|
// AUTHORITATIVE — preferred over whatever the deltas added up to, not just
|
|
2141
2151
|
// used when they added up to nothing.
|
|
@@ -2146,6 +2156,8 @@ class AgenticStreamClient {
|
|
|
2146
2156
|
// `result` whenever the server sends one makes the returned text the
|
|
2147
2157
|
// agent's actual final message rather than however much of it arrived in
|
|
2148
2158
|
// time.
|
|
2159
|
+
if (event.publicProjection === 'lookback_answer_v1')
|
|
2160
|
+
this.publicProjection = event.publicProjection;
|
|
2149
2161
|
const finalText = typeof event.result === 'string' ? event.result : '';
|
|
2150
2162
|
// …EXCEPT when it is a strict suffix of what we accumulated.
|
|
2151
2163
|
//
|
|
@@ -2168,7 +2180,10 @@ class AgenticStreamClient {
|
|
|
2168
2180
|
this.accumulated.length > finalText.length &&
|
|
2169
2181
|
(this.accumulated.endsWith(finalText) ||
|
|
2170
2182
|
endsWithIgnoringWhitespace(this.accumulated, finalText));
|
|
2171
|
-
if (
|
|
2183
|
+
if (event.publicProjection === 'lookback_answer_v1' && typeof event.result === 'string') {
|
|
2184
|
+
this.accumulated = event.result;
|
|
2185
|
+
}
|
|
2186
|
+
else if (finalText && finalText !== this.accumulated && !accumulationIsSuperset) {
|
|
2172
2187
|
this.accumulated = finalText;
|
|
2173
2188
|
}
|
|
2174
2189
|
// The record wins over a stream known to have lost chunks, unless what
|
|
@@ -2176,9 +2191,10 @@ class AgenticStreamClient {
|
|
|
2176
2191
|
// other way round).
|
|
2177
2192
|
// (Compared as the reader sees it: the record holds a widget as its fallback sentence,
|
|
2178
2193
|
// which is shorter than the block the stream carried, and the raw length would never lose.)
|
|
2179
|
-
if (
|
|
2180
|
-
|
|
2181
|
-
this.accumulated =
|
|
2194
|
+
if (recorded && (recorded.publicProjection === 'lookback_answer_v1' ||
|
|
2195
|
+
recorded.text.length > (0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true }).length)) {
|
|
2196
|
+
this.accumulated = recorded.text;
|
|
2197
|
+
this.publicProjection = recorded.publicProjection;
|
|
2182
2198
|
}
|
|
2183
2199
|
// The finished answer, as every other surface shows it: the web applies
|
|
2184
2200
|
// this same sanitizer, so a scheduling JSON block or leaked function-call
|
|
@@ -2186,7 +2202,7 @@ class AgenticStreamClient {
|
|
|
2186
2202
|
// printed as part of the agent's answer.
|
|
2187
2203
|
// A widget is its fallback sentence in a terminal, first: the sanitizer must read
|
|
2188
2204
|
// prose and never a widget's script (the server projects before it sanitizes, too).
|
|
2189
|
-
this.accumulated = (0, data_provider_1.sanitizeFinalText)((0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true }));
|
|
2205
|
+
this.accumulated = (0, data_provider_1.sanitizeFinalText)((0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true }), this.publicProjection);
|
|
2190
2206
|
if (!this.options.quiet && !this.options.jsonl && this.accumulated) {
|
|
2191
2207
|
const output = this.options.output ?? process.stdout;
|
|
2192
2208
|
const { append, shown } = renderableDelta(this.renderedText, this.accumulated);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export declare function buildComputerUseArgs(action: string | undefined, argv: readonly string[]): string[];
|
|
3
|
+
/** The runtime owns local consent, installation and lifecycle; the REST CLI only dispatches. */
|
|
4
|
+
export declare function forwardComputerUseCommand(command: Command, action: string | undefined, argv: readonly string[]): Promise<void>;
|
|
5
|
+
export declare abstract class ComputerUseCommand extends Command {
|
|
6
|
+
static strict: boolean;
|
|
7
|
+
protected abstract action: string | undefined;
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ComputerUseCommand = void 0;
|
|
4
|
+
exports.buildComputerUseArgs = buildComputerUseArgs;
|
|
5
|
+
exports.forwardComputerUseCommand = forwardComputerUseCommand;
|
|
6
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const exec_runtime_binary_1 = require("./exec-runtime-binary");
|
|
8
|
+
function buildComputerUseArgs(action, argv) {
|
|
9
|
+
return ['computer-use', ...(action ? [action] : []), ...argv];
|
|
10
|
+
}
|
|
11
|
+
/** The runtime owns local consent, installation and lifecycle; the REST CLI only dispatches. */
|
|
12
|
+
async function forwardComputerUseCommand(command, action, argv) {
|
|
13
|
+
const fail = (message, code, exit) => {
|
|
14
|
+
if (argv.includes('--json')) {
|
|
15
|
+
command.log(JSON.stringify({ object: 'computer_use_control', schemaVersion: 1, action: action ?? argv[0] ?? 'help', ok: false, error: { code, message } }));
|
|
16
|
+
return command.exit(exit);
|
|
17
|
+
}
|
|
18
|
+
command.log(message);
|
|
19
|
+
return command.exit(exit);
|
|
20
|
+
};
|
|
21
|
+
try {
|
|
22
|
+
if ((await (0, exec_runtime_binary_1.runtimeBinarySupportsSubcommand)('computer-use')) === false) {
|
|
23
|
+
return fail('This local daemon does not support Computer Use. Update skrrd, then retry.', 'runtime_unsupported', 2);
|
|
24
|
+
}
|
|
25
|
+
command.exit(await (0, exec_runtime_binary_1.execRuntimeBinary)(buildComputerUseArgs(action, argv)));
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error.message === 'runtime-binary-not-installed') {
|
|
29
|
+
return fail((0, exec_runtime_binary_1.notInstalledMessage)(), 'runtime_not_installed', 127);
|
|
30
|
+
}
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
class ComputerUseCommand extends core_1.Command {
|
|
35
|
+
static strict = false;
|
|
36
|
+
async run() {
|
|
37
|
+
// Never call parse(): unknown runtime flags must reach the authoritative parser unchanged.
|
|
38
|
+
await forwardComputerUseCommand(this, this.action, this.argv);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.ComputerUseCommand = ComputerUseCommand;
|