@skrr-ai/cli 0.1.42 → 0.1.44
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 +2 -0
- package/dist/base-command.js +1 -0
- package/dist/commands/balance/index.js +1 -1
- package/dist/commands/balance/overage.js +4 -3
- package/dist/commands/balance/plan.js +10 -6
- package/dist/commands/balance/show.d.ts +32 -0
- package/dist/commands/balance/show.js +74 -3
- package/dist/commands/balance/usage/events.js +3 -2
- package/dist/commands/balance/usage.js +2 -1
- package/dist/commands/browser/install.js +3 -2
- package/dist/commands/browser/uninstall.js +3 -2
- package/dist/commands/code/handover.d.ts +1 -0
- package/dist/commands/code/handover.js +4 -0
- package/dist/commands/code/install.js +3 -2
- package/dist/commands/code/jobs/run.d.ts +1 -0
- package/dist/commands/code/jobs/run.js +4 -0
- package/dist/commands/daemon/install.js +7 -0
- package/dist/commands/harnesses/install.d.ts +11 -0
- package/dist/commands/harnesses/install.js +33 -14
- package/dist/commands/harnesses/installers.d.ts +10 -0
- package/dist/commands/harnesses/installers.js +31 -0
- package/dist/commands/harnesses/leases/show.js +14 -0
- package/dist/commands/harnesses/list.js +3 -2
- package/dist/commands/instructions/install.d.ts +22 -0
- package/dist/commands/instructions/install.js +83 -7
- package/dist/commands/instructions/list.js +5 -0
- package/dist/commands/instructions/show.d.ts +6 -0
- package/dist/commands/instructions/show.js +34 -1
- package/dist/commands/instructions/status.js +17 -1
- package/dist/commands/payments/wallet.js +2 -2
- package/dist/commands/tasks/attachments/set-role.d.ts +24 -0
- package/dist/commands/tasks/attachments/set-role.js +60 -0
- package/dist/commands/tasks/attachments/upload.d.ts +1 -0
- package/dist/commands/tasks/attachments/upload.js +18 -52
- package/dist/commands/tasks/comments/add.d.ts +1 -0
- package/dist/commands/tasks/comments/add.js +67 -2
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +56 -1
- package/dist/commands/tasks/create.d.ts +6 -0
- package/dist/commands/tasks/create.js +26 -3
- package/dist/commands/tasks/labels/attach.js +4 -0
- package/dist/commands/tasks/list.d.ts +1 -0
- package/dist/commands/tasks/list.js +9 -0
- package/dist/commands/tasks/result/submit.d.ts +3 -0
- package/dist/commands/tasks/result/submit.js +76 -8
- package/dist/commands/tasks/show.d.ts +23 -0
- package/dist/commands/tasks/show.js +61 -1
- package/dist/commands/tasks/update.js +16 -2
- package/dist/commands/tasks/updates/add.d.ts +1 -0
- package/dist/commands/tasks/updates/add.js +63 -0
- package/dist/commands/views/create.js +12 -2
- package/dist/commands/views/list.js +3 -2
- package/dist/commands/views/show.js +2 -0
- package/dist/lib/agentic-stream.d.ts +10 -4
- package/dist/lib/agentic-stream.js +25 -11
- package/dist/lib/api-fetch.js +7 -2
- package/dist/lib/cli-installers.d.ts +23 -4
- package/dist/lib/cli-installers.js +56 -8
- package/dist/lib/daemon-setup.d.ts +18 -1
- package/dist/lib/daemon-setup.js +33 -1
- package/dist/lib/dedicated-machines.js +4 -2
- package/dist/lib/file-mime.js +1 -1
- package/dist/lib/first-party-harness-agent.d.ts +16 -1
- package/dist/lib/first-party-harness-agent.js +47 -17
- package/dist/lib/first-party-harness-doctor.js +49 -48
- package/dist/lib/first-party-harness-managed.d.ts +9 -4
- package/dist/lib/first-party-harness-managed.js +13 -10
- package/dist/lib/first-party-harness.d.ts +32 -21
- package/dist/lib/first-party-harness.js +49 -31
- package/dist/lib/harness-provider-input.d.ts +18 -12
- package/dist/lib/harness-provider-input.js +18 -12
- package/dist/lib/harness-tiers.d.ts +4 -3
- package/dist/lib/harness-tiers.js +4 -3
- package/dist/lib/harnesses.d.ts +6 -0
- package/dist/lib/html-text.js +25 -0
- package/dist/lib/instruction-input.d.ts +21 -0
- package/dist/lib/instruction-input.js +30 -0
- package/dist/lib/instruction-provenance.d.ts +54 -0
- package/dist/lib/instruction-provenance.js +84 -0
- package/dist/lib/session-task-endpoints.d.ts +1 -1
- package/dist/lib/session-task-endpoints.js +3 -0
- package/dist/lib/task-asset-upload.d.ts +84 -0
- package/dist/lib/task-asset-upload.js +374 -0
- package/dist/lib/task-closure.d.ts +15 -0
- package/dist/lib/task-closure.js +20 -0
- package/dist/lib/task-view-render.d.ts +14 -0
- package/dist/lib/task-view-render.js +55 -0
- package/dist/lib/tasks.d.ts +26 -0
- package/dist/lib/tasks.js +38 -1
- package/dist/lib/views/vocabulary.d.ts +1 -1
- package/dist/lib/views/vocabulary.js +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +183 -58
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +286 -100
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +21 -33
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +24 -50
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.d.ts +19 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.js +26 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.d.ts +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +9 -5
- 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 +1 -13
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.d.ts +21 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.js +75 -19
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +183 -58
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +279 -99
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +21 -33
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +24 -49
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.d.ts +19 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.js +27 -11
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.d.ts +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +9 -5
- 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 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.d.ts +21 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.js +74 -19
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +4588 -4509
- package/dist/node_modules/@skrr-ai/data-provider/package.json +1 -1
- package/oclif.manifest.json +33980 -33832
- package/package.json +3 -3
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.conflictingTargetOf = conflictingTargetOf;
|
|
4
|
+
exports.describeTargetConflict = describeTargetConflict;
|
|
3
5
|
const core_1 = require("@oclif/core");
|
|
4
6
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
5
7
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -9,6 +11,41 @@ const harness_provider_input_1 = require("../../lib/harness-provider-input");
|
|
|
9
11
|
const prompt_1 = require("../../lib/prompt");
|
|
10
12
|
/** The providers a managed instruction can target, canonical spellings. */
|
|
11
13
|
const MANAGED_INSTRUCTION_PROVIDERS = ['claude', 'codex', auth_core_1.FIRST_PARTY_HARNESS.provider];
|
|
14
|
+
function conflictingTargetOf(body) {
|
|
15
|
+
const value = body?.conflictingTarget;
|
|
16
|
+
return value && typeof value.id === 'string' && value.id ? value : null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What to do about a placement that already has a target, as commands.
|
|
20
|
+
*
|
|
21
|
+
* Re-running an install whose first attempt had failed printed "An unexpected
|
|
22
|
+
* error occurred. Code: TARGET_CONFLICT" (OSK-4631): no target, no path, no next
|
|
23
|
+
* step, and no word on whether the re-run had partly applied. The API now names
|
|
24
|
+
* the target in the way; this turns that into the commands for its state. A live
|
|
25
|
+
* target is changed or removed, never installed twice; one being removed can be
|
|
26
|
+
* restored, or purged once its daemon confirms cleanup.
|
|
27
|
+
*/
|
|
28
|
+
function describeTargetConflict(target, { bin, placement, created }) {
|
|
29
|
+
const state = [target.desiredState, target.status].filter(Boolean).join(', ');
|
|
30
|
+
const lines = target.desiredState === 'removed'
|
|
31
|
+
? [
|
|
32
|
+
`Target ${target.id} already holds ${placement} on that machine and is being removed${state ? ` (${state})` : ''}.`,
|
|
33
|
+
`Bring it back with \`${bin} instructions restore-target ${target.id}\`, or install again ` +
|
|
34
|
+
`after its daemon confirms cleanup and \`${bin} instructions purge-target ${target.id}\`.`,
|
|
35
|
+
]
|
|
36
|
+
: [
|
|
37
|
+
`Target ${target.id} already manages ${placement} on that machine${state ? ` (${state})` : ''}.`,
|
|
38
|
+
...(target.status === 'error'
|
|
39
|
+
? [`Its last sync failed; \`${bin} instructions status\` shows why.`]
|
|
40
|
+
: []),
|
|
41
|
+
`Change what it applies with \`${bin} instructions update-target ${target.id} --bundle <id>\`, ` +
|
|
42
|
+
`or drop it with \`${bin} instructions remove ${target.id}\`.`,
|
|
43
|
+
];
|
|
44
|
+
lines.push(created.length
|
|
45
|
+
? `Created before this refusal: ${created.join(', ')}.`
|
|
46
|
+
: 'No target was created by this command.');
|
|
47
|
+
return lines.join(' ');
|
|
48
|
+
}
|
|
12
49
|
class InstructionsInstall extends base_command_1.BaseCommand {
|
|
13
50
|
static description = 'Opt in a daemon target to ongoing managed instruction reconciliation';
|
|
14
51
|
static flags = {
|
|
@@ -32,7 +69,13 @@ class InstructionsInstall extends base_command_1.BaseCommand {
|
|
|
32
69
|
default: MANAGED_INSTRUCTION_PROVIDERS,
|
|
33
70
|
}),
|
|
34
71
|
scope: core_1.Flags.string({ description: 'global or project', options: ['global', 'project'] }),
|
|
35
|
-
project: core_1.Flags.string({
|
|
72
|
+
project: core_1.Flags.string({
|
|
73
|
+
// The daemon writes a project target at the repository root, so a path
|
|
74
|
+
// outside any Git repository is accepted here and then fails on the
|
|
75
|
+
// machine. Saying so is the only warning this command can give: the path
|
|
76
|
+
// is checked where it lives, not here (OSK-4626).
|
|
77
|
+
description: "Absolute project path on the daemon's machine, inside a Git repository (the block is written at its root)",
|
|
78
|
+
}),
|
|
36
79
|
mode: core_1.Flags.string({
|
|
37
80
|
description: 'Project footprint',
|
|
38
81
|
options: ['local', 'team'],
|
|
@@ -87,12 +130,20 @@ class InstructionsInstall extends base_command_1.BaseCommand {
|
|
|
87
130
|
if (providers.includes('codex') && Buffer.byteLength(previewBody, 'utf8') > 30 * 1024) {
|
|
88
131
|
this.error('Codex managed instruction bodies are limited to 30 KiB; no targets were created', { exit: 2 });
|
|
89
132
|
}
|
|
90
|
-
|
|
133
|
+
// The body is shown so the confirmation below is informed. With `--yes`
|
|
134
|
+
// there is no confirmation to inform, and printing a ~9 KB body anyway put
|
|
135
|
+
// the command's actual outcome — often a refusal — a screen of scrollback
|
|
136
|
+
// away (OSK-4631). Say what was authorized, and where to read it.
|
|
137
|
+
if (!flags.json && !flags.yes) {
|
|
91
138
|
this.log('Exact managed instruction body:');
|
|
92
139
|
this.log('---');
|
|
93
140
|
this.log(previewBody);
|
|
94
141
|
this.log('---');
|
|
95
142
|
}
|
|
143
|
+
else if (!flags.json) {
|
|
144
|
+
this.log(`Authorizing ${Buffer.byteLength(previewBody, 'utf8').toLocaleString()} bytes of instruction ` +
|
|
145
|
+
`${flags.bundle}; \`${this.config.bin} instructions show ${flags.bundle}\` prints them.`);
|
|
146
|
+
}
|
|
96
147
|
const teamWarning = scope === 'project' && flags.mode === 'team'
|
|
97
148
|
? ' Team mode writes to repository files and may affect every contributor.'
|
|
98
149
|
: '';
|
|
@@ -101,8 +152,8 @@ class InstructionsInstall extends base_command_1.BaseCommand {
|
|
|
101
152
|
return this.log('Aborted.');
|
|
102
153
|
const daemonId = await this.resolveDaemon(flags.daemon);
|
|
103
154
|
const results = [];
|
|
104
|
-
|
|
105
|
-
|
|
155
|
+
for (const provider of providers) {
|
|
156
|
+
try {
|
|
106
157
|
results.push(await data_provider_1.dataService.createManagedInstructionTarget({
|
|
107
158
|
daemonId,
|
|
108
159
|
bundleId: flags.bundle,
|
|
@@ -115,15 +166,40 @@ class InstructionsInstall extends base_command_1.BaseCommand {
|
|
|
115
166
|
label: flags.label,
|
|
116
167
|
}));
|
|
117
168
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
169
|
+
catch (error) {
|
|
170
|
+
// One target per provider, created in turn, so a refusal part-way
|
|
171
|
+
// through leaves the earlier ones in place. Say which.
|
|
172
|
+
const created = results.map((result) => `${(0, harness_provider_input_1.canonicalHarnessInput)(result.target.provider)} (${result.target.id})`);
|
|
173
|
+
const refusal = (0, base_command_1.apiRefusal)(error);
|
|
174
|
+
const conflict = refusal.code === 'TARGET_CONFLICT' ? conflictingTargetOf(refusal.body) : null;
|
|
175
|
+
if (conflict) {
|
|
176
|
+
this.failWithCliError({
|
|
177
|
+
message: describeTargetConflict(conflict, {
|
|
178
|
+
bin: this.config.bin,
|
|
179
|
+
placement: `${(0, harness_provider_input_1.canonicalHarnessInput)(provider)} ${scope}${flags.project ? ` ${flags.project}` : ''}`,
|
|
180
|
+
created,
|
|
181
|
+
}),
|
|
182
|
+
code: 'TARGET_CONFLICT',
|
|
183
|
+
status: 409,
|
|
184
|
+
exit: 1,
|
|
185
|
+
retryable: false,
|
|
186
|
+
details: { ...refusal.body, created: results.map((result) => result.target) },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (created.length) {
|
|
190
|
+
this.warn(`Created before this failure: ${created.join(', ')}.`);
|
|
191
|
+
}
|
|
192
|
+
this.handleApiError(error);
|
|
193
|
+
}
|
|
121
194
|
}
|
|
122
195
|
if (flags.json)
|
|
123
196
|
return this.log(JSON.stringify(results, null, 2));
|
|
124
197
|
for (const result of results) {
|
|
125
198
|
this.log(`Install queued: ${(0, harness_provider_input_1.canonicalHarnessInput)(result.target.provider)} ${result.target.scope}${result.target.projectPath ? ` ${result.target.projectPath}` : ''} (${result.target.id})`);
|
|
126
199
|
}
|
|
200
|
+
// Queued is not applied: the daemon checks the placement when it writes, and
|
|
201
|
+
// a path it cannot use fails there, after this command has exited 0.
|
|
202
|
+
this.log(`The daemon applies these on its next sync; \`${this.config.bin} instructions status\` shows when, or why not.`);
|
|
127
203
|
}
|
|
128
204
|
/**
|
|
129
205
|
* The daemon the targets are created on, by the rule every daemon-picking
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
|
+
const instruction_provenance_1 = require("../../lib/instruction-provenance");
|
|
7
8
|
class InstructionsList extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'List version-controlled instruction prompts';
|
|
9
10
|
static flags = {
|
|
@@ -32,12 +33,16 @@ class InstructionsList extends base_command_1.BaseCommand {
|
|
|
32
33
|
id: bundle.id,
|
|
33
34
|
name: bundle.name,
|
|
34
35
|
version: String(bundle.currentVersionNumber),
|
|
36
|
+
// The built-in release the CURRENT body is, if any — a separate counter
|
|
37
|
+
// from VERSION, which is this prompt's own (OSK-4647).
|
|
38
|
+
template: (0, instruction_provenance_1.builtInLabel)(bundle.currentVersion),
|
|
35
39
|
status: bundle.deletedAt ? 'deleted' : bundle.status,
|
|
36
40
|
updated: bundle.updatedAt,
|
|
37
41
|
})), [
|
|
38
42
|
{ key: 'id', header: 'ID' },
|
|
39
43
|
{ key: 'name', header: 'NAME', maxWidth: 32 },
|
|
40
44
|
{ key: 'version', header: 'VERSION' },
|
|
45
|
+
{ key: 'template', header: 'TEMPLATE' },
|
|
41
46
|
{ key: 'status', header: 'STATUS' },
|
|
42
47
|
{ key: 'updated', header: 'UPDATED' },
|
|
43
48
|
], (line) => this.log(line));
|
|
@@ -9,4 +9,10 @@ export default class InstructionsShow extends BaseCommand {
|
|
|
9
9
|
versions: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
};
|
|
11
11
|
run(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* The built-in release this server would install today, or undefined. Read
|
|
14
|
+
* from the offer, which already reports it as `templateVersion`; a failure
|
|
15
|
+
* costs only the "is there a newer one" clause, never the command.
|
|
16
|
+
*/
|
|
17
|
+
private latestTemplateVersion;
|
|
12
18
|
}
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
|
+
const instruction_provenance_1 = require("../../lib/instruction-provenance");
|
|
7
8
|
class InstructionsShow extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'Show exact prompt content and version history';
|
|
9
10
|
static args = {
|
|
@@ -38,6 +39,9 @@ class InstructionsShow extends base_command_1.BaseCommand {
|
|
|
38
39
|
(0, format_1.renderTable)(response.versions.map((version) => ({
|
|
39
40
|
id: version.id,
|
|
40
41
|
version: String(version.versionNumber),
|
|
42
|
+
// Its own column, never folded into VERSION: the prompt's counter
|
|
43
|
+
// and the built-in release are different numbers (OSK-4647).
|
|
44
|
+
template: (0, instruction_provenance_1.builtInLabel)(version),
|
|
41
45
|
hash: version.hash.slice(0, 12),
|
|
42
46
|
status: version.archivedAt
|
|
43
47
|
? 'archived'
|
|
@@ -48,10 +52,20 @@ class InstructionsShow extends base_command_1.BaseCommand {
|
|
|
48
52
|
})), [
|
|
49
53
|
{ key: 'id', header: 'ID' },
|
|
50
54
|
{ key: 'version', header: 'VERSION' },
|
|
51
|
-
{ key: 'hash', header: 'HASH' },
|
|
55
|
+
{ key: 'hash', header: 'BODY HASH' },
|
|
52
56
|
{ key: 'status', header: 'STATUS' },
|
|
57
|
+
{ key: 'template', header: 'TEMPLATE' },
|
|
53
58
|
{ key: 'message', header: 'MESSAGE', maxWidth: 48 },
|
|
54
59
|
], (line) => this.log(line));
|
|
60
|
+
// Three hashes answer "is my file current?", and this table shows one.
|
|
61
|
+
// A file's `v=` is the body as rendered for its target, so beside an
|
|
62
|
+
// agent-identity section it matches none of these (OSK-4644).
|
|
63
|
+
this.log('');
|
|
64
|
+
this.log("BODY HASH is the version as written. A managed file's `v=` is the body as");
|
|
65
|
+
this.log('rendered for its target, which differs when it fills in an agent identity;');
|
|
66
|
+
this.log(`compare it with FILE HASH in \`${this.config.bin} instructions status\`.`);
|
|
67
|
+
this.log("VERSION counts this prompt's saved bodies; TEMPLATE is the built-in release a");
|
|
68
|
+
this.log('body was taken from, which is a separate number.');
|
|
55
69
|
return;
|
|
56
70
|
}
|
|
57
71
|
const response = await data_provider_1.dataService.getManagedInstructionBundle(args.id);
|
|
@@ -61,6 +75,9 @@ class InstructionsShow extends base_command_1.BaseCommand {
|
|
|
61
75
|
this.log(`${bundle.name} (${bundle.id}) — v${bundle.currentVersionNumber} — ${bundle.status}`);
|
|
62
76
|
if (bundle.description)
|
|
63
77
|
this.log(bundle.description);
|
|
78
|
+
const provenance = (0, instruction_provenance_1.describeTemplateProvenance)(bundle, await this.latestTemplateVersion(bundle.sourceTemplateKey));
|
|
79
|
+
if (provenance)
|
|
80
|
+
this.log(provenance);
|
|
64
81
|
this.log('');
|
|
65
82
|
this.log(bundle.currentVersion?.body || '(no active content)');
|
|
66
83
|
}
|
|
@@ -84,5 +101,21 @@ class InstructionsShow extends base_command_1.BaseCommand {
|
|
|
84
101
|
this.handleApiError(error);
|
|
85
102
|
}
|
|
86
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* The built-in release this server would install today, or undefined. Read
|
|
106
|
+
* from the offer, which already reports it as `templateVersion`; a failure
|
|
107
|
+
* costs only the "is there a newer one" clause, never the command.
|
|
108
|
+
*/
|
|
109
|
+
async latestTemplateVersion(templateKey) {
|
|
110
|
+
if (!templateKey)
|
|
111
|
+
return undefined;
|
|
112
|
+
try {
|
|
113
|
+
const offer = await data_provider_1.dataService.getManagedInstructionOffer(templateKey);
|
|
114
|
+
return offer?.preset?.templateVersion;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
87
120
|
}
|
|
88
121
|
exports.default = InstructionsShow;
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
7
|
const instruction_input_1 = require("../../lib/instruction-input");
|
|
8
|
+
const instruction_provenance_1 = require("../../lib/instruction-provenance");
|
|
8
9
|
class InstructionsStatus extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Show managed targets, applied versions, paths, and reconciliation errors';
|
|
10
11
|
static flags = {
|
|
@@ -42,12 +43,14 @@ class InstructionsStatus extends base_command_1.BaseCommand {
|
|
|
42
43
|
// Leave it empty.
|
|
43
44
|
}
|
|
44
45
|
let bundleNames = new Map();
|
|
46
|
+
let bundlesById = new Map();
|
|
45
47
|
try {
|
|
46
48
|
const bundleResponse = await data_provider_1.dataService.listManagedInstructionBundles({
|
|
47
49
|
includeArchived: true,
|
|
48
50
|
includeDeleted: true,
|
|
49
51
|
});
|
|
50
52
|
bundleNames = (0, instruction_input_1.buildBundleNameIndex)(bundleResponse.bundles);
|
|
53
|
+
bundlesById = new Map(bundleResponse.bundles.map((bundle) => [bundle.id, bundle]));
|
|
51
54
|
}
|
|
52
55
|
catch {
|
|
53
56
|
// Leave the index empty — rows show the full bundle id instead.
|
|
@@ -73,7 +76,17 @@ class InstructionsStatus extends base_command_1.BaseCommand {
|
|
|
73
76
|
target: target.appliedPath ||
|
|
74
77
|
(target.scope === 'global' ? 'global' : target.projectPath || 'project'),
|
|
75
78
|
desired: target.desiredState,
|
|
76
|
-
|
|
79
|
+
// `v3 (built-in v5)`: the prompt's version, and the built-in release
|
|
80
|
+
// it is when that is known. `APPLIED v3` alone read as two releases
|
|
81
|
+
// behind a preset announced as v5 (OSK-4647).
|
|
82
|
+
applied: (0, instruction_provenance_1.appliedVersionLabel)(target.appliedVersionNumber, bundlesById.get(target.bundleId)),
|
|
83
|
+
// The hash the managed block in the file starts with (`v=`), cut to the
|
|
84
|
+
// same 12 characters `show --versions` prints. It is the body as
|
|
85
|
+
// rendered for THIS target, so it matches a version's hash only when
|
|
86
|
+
// nothing was filled in — and was `--json` only, which made "is the
|
|
87
|
+
// block in my CLAUDE.md current?" read as "my machine is running a body
|
|
88
|
+
// the server never heard of" (OSK-4644).
|
|
89
|
+
fileHash: target.appliedHash ? target.appliedHash.slice(0, 12) : '-',
|
|
77
90
|
status: (0, instruction_input_1.describeTargetSync)(target, Date.now(), liveDaemonIds),
|
|
78
91
|
})), [
|
|
79
92
|
{ key: 'id', header: 'TARGET ID' },
|
|
@@ -88,6 +101,7 @@ class InstructionsStatus extends base_command_1.BaseCommand {
|
|
|
88
101
|
{ key: 'target', header: 'PATH', maxWidth: 36 },
|
|
89
102
|
{ key: 'desired', header: 'DESIRED' },
|
|
90
103
|
{ key: 'applied', header: 'APPLIED' },
|
|
104
|
+
{ key: 'fileHash', header: 'FILE HASH' },
|
|
91
105
|
// Wide enough for the stall note to keep its remedy. Truncating at 48
|
|
92
106
|
// cut `purge-target` off the end, which hid the one actionable half of
|
|
93
107
|
// the sentence.
|
|
@@ -106,6 +120,8 @@ class InstructionsStatus extends base_command_1.BaseCommand {
|
|
|
106
120
|
for (const command of rebinds)
|
|
107
121
|
this.log(` ${command}`);
|
|
108
122
|
}
|
|
123
|
+
for (const line of (0, instruction_input_1.failedTargetLines)(response.targets, this.config.bin))
|
|
124
|
+
this.log(line);
|
|
109
125
|
// Where the text went.
|
|
110
126
|
//
|
|
111
127
|
// The count in the STATUS column says skrr overwrote something you
|
|
@@ -52,8 +52,8 @@ class PaymentsWallet extends base_command_1.BaseCommand {
|
|
|
52
52
|
// CLI — so anyone looking for "my balance" found USDC and drew the wrong
|
|
53
53
|
// conclusion about their usage ceiling. Name the other one.
|
|
54
54
|
this.log('');
|
|
55
|
-
this.log('This is the x402 crypto wallet, in USDC. Your hosted USAGE balance
|
|
56
|
-
this.log('the
|
|
55
|
+
this.log('This is the x402 crypto wallet, in USDC. Your hosted USAGE balance and');
|
|
56
|
+
this.log('plan limits — the ceilings that refuse a turn — are `skrr balance show`.');
|
|
57
57
|
const payments = history.payments ?? [];
|
|
58
58
|
if (payments.length === 0) {
|
|
59
59
|
this.log('');
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr tasks attachments set-role <task> <attachment> --role …`
|
|
4
|
+
*
|
|
5
|
+
* The one way to change what an existing asset IS on a Task. Its real use is
|
|
6
|
+
* promotion: an agent may only upload `evidence` or `deliverable`, because an
|
|
7
|
+
* `input` is forwarded into every future Run of the Task — so when an agent's
|
|
8
|
+
* screenshot should become an input, a person promotes it here. The server
|
|
9
|
+
* refuses the call from an agent, whatever credential it holds, and moves the
|
|
10
|
+
* asset's ledger link with the role.
|
|
11
|
+
*/
|
|
12
|
+
export default class TasksAttachmentsSetRole extends BaseCommand {
|
|
13
|
+
static description: string;
|
|
14
|
+
static examples: string[];
|
|
15
|
+
static args: {
|
|
16
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
17
|
+
attachmentId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
18
|
+
};
|
|
19
|
+
static flags: {
|
|
20
|
+
role: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr tasks attachments set-role <task> <attachment> --role …`
|
|
8
|
+
*
|
|
9
|
+
* The one way to change what an existing asset IS on a Task. Its real use is
|
|
10
|
+
* promotion: an agent may only upload `evidence` or `deliverable`, because an
|
|
11
|
+
* `input` is forwarded into every future Run of the Task — so when an agent's
|
|
12
|
+
* screenshot should become an input, a person promotes it here. The server
|
|
13
|
+
* refuses the call from an agent, whatever credential it holds, and moves the
|
|
14
|
+
* asset's ledger link with the role.
|
|
15
|
+
*/
|
|
16
|
+
class TasksAttachmentsSetRole extends base_command_1.BaseCommand {
|
|
17
|
+
static description = "Change an attachment's role (input, evidence, or deliverable). Making an asset an input " +
|
|
18
|
+
'sends it into every future Run of the task, so only a person can change a role.';
|
|
19
|
+
static examples = [
|
|
20
|
+
'<%= config.bin %> tasks attachments set-role <task-id> <attachment-id> --role input',
|
|
21
|
+
'<%= config.bin %> tasks attachments set-role <task-id> <attachment-id> --role evidence --json',
|
|
22
|
+
];
|
|
23
|
+
static args = {
|
|
24
|
+
id: core_1.Args.string({ description: 'Task ID', required: true, ignoreStdin: true }),
|
|
25
|
+
attachmentId: core_1.Args.string({ description: 'Attachment ID', required: true, ignoreStdin: true }),
|
|
26
|
+
};
|
|
27
|
+
static flags = {
|
|
28
|
+
role: core_1.Flags.string({
|
|
29
|
+
required: true,
|
|
30
|
+
options: ['input', 'evidence', 'deliverable'],
|
|
31
|
+
description: 'input (forwarded into every future Run), evidence (supports an Update or Result), or deliverable (the media is the product)',
|
|
32
|
+
}),
|
|
33
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
34
|
+
};
|
|
35
|
+
async run() {
|
|
36
|
+
this.requireAuth();
|
|
37
|
+
const { args, flags } = await this.parse(TasksAttachmentsSetRole);
|
|
38
|
+
let attachment;
|
|
39
|
+
try {
|
|
40
|
+
attachment = await data_provider_1.dataService.setTaskAttachmentRole({
|
|
41
|
+
taskId: args.id,
|
|
42
|
+
attachmentId: args.attachmentId,
|
|
43
|
+
role: flags.role,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
this.handleApiError(err);
|
|
48
|
+
}
|
|
49
|
+
if (flags.json) {
|
|
50
|
+
this.log(JSON.stringify(attachment, null, 2));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const name = attachment.originalName || attachment.id;
|
|
54
|
+
const effect = attachment.role === 'input'
|
|
55
|
+
? ' It will be sent into every future Run of this task.'
|
|
56
|
+
: ' It is no longer sent into Runs.';
|
|
57
|
+
this.log(`${name} is now ${attachment.role}.${effect}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.default = TasksAttachmentsSetRole;
|
|
@@ -8,6 +8,7 @@ export default class TasksAttachmentsUpload extends BaseCommand {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
file: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
role: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -1,50 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const fs = __importStar(require("node:fs"));
|
|
37
|
-
const path = __importStar(require("node:path"));
|
|
38
|
-
const node_buffer_1 = require("node:buffer");
|
|
39
3
|
const core_1 = require("@oclif/core");
|
|
40
|
-
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
41
4
|
const base_command_1 = require("../../../base-command");
|
|
42
|
-
const
|
|
5
|
+
const task_asset_upload_1 = require("../../../lib/task-asset-upload");
|
|
43
6
|
class TasksAttachmentsUpload extends base_command_1.BaseCommand {
|
|
44
7
|
static description = 'Upload a file attachment to a task';
|
|
45
8
|
static examples = [
|
|
46
9
|
'<%= config.bin %> tasks attachments upload <task-id> --file ./report.pdf',
|
|
47
10
|
'<%= config.bin %> tasks attachments upload <task-id> --file ./screenshot.png --json',
|
|
11
|
+
'<%= config.bin %> tasks attachments upload <task-id> --file ./demo.mp4 --role deliverable',
|
|
48
12
|
];
|
|
49
13
|
static args = {
|
|
50
14
|
id: core_1.Args.string({ description: 'Task ID', required: true, ignoreStdin: true }),
|
|
@@ -52,32 +16,34 @@ class TasksAttachmentsUpload extends base_command_1.BaseCommand {
|
|
|
52
16
|
static flags = {
|
|
53
17
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
54
18
|
file: core_1.Flags.string({ description: 'Path to the file to upload', required: true }),
|
|
19
|
+
role: core_1.Flags.string({
|
|
20
|
+
description: 'Asset role: evidence (supports an Update/Result), deliverable (the media is the product), or input (forwarded into every future Run — only a person may add one; a person promotes an agent upload with `attachments set-role`). Defaults to evidence when an agent uploads, input when a person does.',
|
|
21
|
+
options: ['input', 'evidence', 'deliverable'],
|
|
22
|
+
}),
|
|
55
23
|
};
|
|
56
24
|
async run() {
|
|
57
25
|
this.requireAuth();
|
|
58
26
|
const { args, flags } = await this.parse(TasksAttachmentsUpload);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const buf = fs.readFileSync(filePath);
|
|
64
|
-
const filename = path.basename(filePath);
|
|
65
|
-
const fd = new FormData();
|
|
66
|
-
const mimeType = (0, file_mime_1.mimeTypeForFilename)(filename);
|
|
67
|
-
fd.append('file', new node_buffer_1.Blob([buf], { type: mimeType }), filename);
|
|
68
|
-
let result;
|
|
27
|
+
// The pipeline — buffered vs direct, session vs generic — lives in
|
|
28
|
+
// task-asset-upload.ts so `--attach` on updates/result/complete/comments
|
|
29
|
+
// makes the same routing decisions byte for byte (OSK-9863).
|
|
30
|
+
let asset;
|
|
69
31
|
try {
|
|
70
|
-
|
|
32
|
+
asset = await (0, task_asset_upload_1.uploadTaskAssetFile)({
|
|
33
|
+
taskId: args.id,
|
|
34
|
+
filePath: flags.file,
|
|
35
|
+
role: flags.role,
|
|
36
|
+
});
|
|
71
37
|
}
|
|
72
38
|
catch (err) {
|
|
73
39
|
this.handleApiError(err);
|
|
74
40
|
}
|
|
75
41
|
if (flags.json) {
|
|
76
|
-
this.log(JSON.stringify(
|
|
42
|
+
this.log(JSON.stringify(asset, null, 2));
|
|
77
43
|
return;
|
|
78
44
|
}
|
|
79
|
-
const
|
|
80
|
-
this.log(`Uploaded ${filename}
|
|
45
|
+
const dedup = asset.deduplicated ? ' (deduplicated — already on the task)' : '';
|
|
46
|
+
this.log(`Uploaded ${asset.filename} → attachment ${asset.id}${dedup}`);
|
|
81
47
|
}
|
|
82
48
|
}
|
|
83
49
|
exports.default = TasksAttachmentsUpload;
|
|
@@ -16,6 +16,7 @@ export default class TasksCommentsAdd extends BaseCommand {
|
|
|
16
16
|
'parent-comment': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
17
|
'anchor-mark-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
18
|
'anchor-quote': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
attach: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
20
|
};
|
|
20
21
|
run(): Promise<void>;
|
|
21
22
|
/**
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
const node_crypto_1 = require("node:crypto");
|
|
4
37
|
const core_1 = require("@oclif/core");
|
|
@@ -55,6 +88,11 @@ class TasksCommentsAdd extends base_command_1.BaseCommand {
|
|
|
55
88
|
'anchor-quote': core_1.Flags.string({
|
|
56
89
|
description: 'Captured quote for the anchor (≤1000 chars; truncated to 500 to match the editor). Enables inline-comment mode when used without --anchor-mark-id.',
|
|
57
90
|
}),
|
|
91
|
+
attach: core_1.Flags.string({
|
|
92
|
+
multiple: true,
|
|
93
|
+
description: 'Upload a file as a Task asset and reference it in the comment body ' +
|
|
94
|
+
'(``, resolved to a signed URL at read time). Repeatable.',
|
|
95
|
+
}),
|
|
58
96
|
};
|
|
59
97
|
async run() {
|
|
60
98
|
this.requireAuth();
|
|
@@ -107,9 +145,36 @@ class TasksCommentsAdd extends base_command_1.BaseCommand {
|
|
|
107
145
|
// mentionedAgentIds, reopen, and interrupt are preserved. Boolean flags
|
|
108
146
|
// default to false; only pass them through when actually set so they
|
|
109
147
|
// don't clobber a `true` value from the JSON file.
|
|
148
|
+
// --attach: upload first, then append `task-asset:` references to the
|
|
149
|
+
// body — comments store stable asset ids, not URLs (OSK-9856/9863).
|
|
150
|
+
let attachSuffix = '';
|
|
151
|
+
if (flags.attach?.length) {
|
|
152
|
+
const { uploadTaskAssetFile, taskAssetMarkdownRef } = await Promise.resolve().then(() => __importStar(require('../../../lib/task-asset-upload')));
|
|
153
|
+
const refs = [];
|
|
154
|
+
for (const filePath of flags.attach) {
|
|
155
|
+
try {
|
|
156
|
+
const asset = await uploadTaskAssetFile({
|
|
157
|
+
taskId: task.id,
|
|
158
|
+
filePath,
|
|
159
|
+
role: 'evidence',
|
|
160
|
+
});
|
|
161
|
+
refs.push(taskAssetMarkdownRef(asset));
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
this.error(`--attach failed: ${err.message}`, { exit: 1 });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (refs.length)
|
|
168
|
+
attachSuffix = `\n\n${refs.join('\n')}`;
|
|
169
|
+
}
|
|
110
170
|
const mentionedFromFlag = flags['mention-agent'];
|
|
171
|
+
const baseBody = flags.body ?? (typeof commentBody.body === 'string' ? commentBody.body : undefined);
|
|
111
172
|
const data = (0, prompt_1.mergeDefined)(commentBody, {
|
|
112
|
-
body:
|
|
173
|
+
body: baseBody
|
|
174
|
+
? `${baseBody}${attachSuffix}`
|
|
175
|
+
: attachSuffix
|
|
176
|
+
? attachSuffix.trimStart()
|
|
177
|
+
: undefined,
|
|
113
178
|
mentionedAgentIds: Array.isArray(mentionedFromFlag) && mentionedFromFlag.length > 0
|
|
114
179
|
? mentionedFromFlag
|
|
115
180
|
: undefined,
|
|
@@ -163,7 +228,7 @@ class TasksCommentsAdd extends base_command_1.BaseCommand {
|
|
|
163
228
|
? await (0, api_fetch_1.apiFetch)(sessionPath, {
|
|
164
229
|
method: 'POST',
|
|
165
230
|
body: {
|
|
166
|
-
body:
|
|
231
|
+
body: data.body,
|
|
167
232
|
...(mentioned ? { mentionedAgentIds: mentioned } : {}),
|
|
168
233
|
},
|
|
169
234
|
headers: { 'X-Idempotency-Key': idempotencyKey },
|
|
@@ -26,6 +26,7 @@ export default class TasksComplete extends BaseCommand {
|
|
|
26
26
|
'structured-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
27
|
deliverable: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
28
|
evidence: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
attach: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
30
|
remaining: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
31
|
'source-run': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
32
|
'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|