@skrr-ai/cli 0.1.42 → 0.1.43
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/balance/overage.js +4 -3
- package/dist/commands/balance/plan.js +10 -6
- 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/install.js +3 -2
- 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/list.js +3 -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/result/submit.d.ts +3 -0
- package/dist/commands/tasks/result/submit.js +76 -8
- package/dist/commands/tasks/update.js +4 -2
- package/dist/commands/tasks/updates/add.d.ts +1 -0
- package/dist/commands/tasks/updates/add.js +63 -0
- package/dist/lib/api-fetch.js +7 -2
- package/dist/lib/cli-installers.d.ts +23 -4
- package/dist/lib/cli-installers.js +47 -7
- package/dist/lib/dedicated-machines.js +4 -2
- package/dist/lib/file-mime.js +1 -1
- package/dist/lib/first-party-harness-agent.js +6 -5
- package/dist/lib/first-party-harness-doctor.js +15 -32
- 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 +25 -21
- package/dist/lib/first-party-harness.js +40 -27
- 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/html-text.js +25 -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/tasks.d.ts +8 -0
- package/dist/lib/tasks.js +16 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +113 -39
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +148 -71
- 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/esm/firstPartyHarness.d.ts +113 -39
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +146 -70
- 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/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3855 -3779
- package/dist/node_modules/@skrr-ai/data-provider/package.json +1 -1
- package/oclif.manifest.json +26935 -26810
- package/package.json +2 -2
|
@@ -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
|
exports.describePendingReview = describePendingReview;
|
|
4
37
|
const core_1 = require("@oclif/core");
|
|
@@ -97,6 +130,11 @@ class TasksComplete extends base_command_1.BaseCommand {
|
|
|
97
130
|
description: 'Exact Task Resource link id produced by `tasks deliverable add`',
|
|
98
131
|
}),
|
|
99
132
|
evidence: core_1.Flags.string({ multiple: true, description: 'Evidence as <kind>:<id-or-uri>' }),
|
|
133
|
+
attach: core_1.Flags.string({
|
|
134
|
+
multiple: true,
|
|
135
|
+
description: 'Upload a file as a Task asset (role: evidence) and cite it in evidenceRefs. ' +
|
|
136
|
+
'Repeatable. Re-attaching identical bytes dedupes on the server.',
|
|
137
|
+
}),
|
|
100
138
|
remaining: core_1.Flags.string({ multiple: true, description: 'Remaining work item' }),
|
|
101
139
|
'source-run': core_1.Flags.string({ multiple: true, description: 'Contributing Task Run id' }),
|
|
102
140
|
'run-id': core_1.Flags.string({ description: 'Expected current Task Run id' }),
|
|
@@ -214,6 +252,23 @@ class TasksComplete extends base_command_1.BaseCommand {
|
|
|
214
252
|
retryable: false,
|
|
215
253
|
});
|
|
216
254
|
}
|
|
255
|
+
// --attach: upload once the input is known to be valid — a closeout the CLI
|
|
256
|
+
// is about to refuse must not leave stored bytes behind — and before the
|
|
257
|
+
// idempotency key is derived, so a retry sees the same refs.
|
|
258
|
+
const evidenceRefs = Array.isArray(input.evidenceRefs) ? [...input.evidenceRefs] : [];
|
|
259
|
+
if (flags.attach?.length) {
|
|
260
|
+
const { attachTaskAssetFiles } = await Promise.resolve().then(() => __importStar(require('../../lib/task-asset-upload')));
|
|
261
|
+
try {
|
|
262
|
+
evidenceRefs.push(...(await attachTaskAssetFiles({
|
|
263
|
+
taskId: identity.id,
|
|
264
|
+
files: flags.attach,
|
|
265
|
+
role: 'evidence',
|
|
266
|
+
})));
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
this.error(`--attach failed: ${err.message}`, { exit: 1 });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
217
272
|
const payload = {
|
|
218
273
|
status,
|
|
219
274
|
summary,
|
|
@@ -223,7 +278,7 @@ class TasksComplete extends base_command_1.BaseCommand {
|
|
|
223
278
|
resourceLinkIds: Array.isArray(input.resourceLinkIds)
|
|
224
279
|
? stringArray(input.resourceLinkIds)
|
|
225
280
|
: [],
|
|
226
|
-
evidenceRefs
|
|
281
|
+
evidenceRefs,
|
|
227
282
|
remainingWork: Array.isArray(input.remainingWork) ? input.remainingWork : [],
|
|
228
283
|
contributors: Array.isArray(input.contributors)
|
|
229
284
|
? input.contributors
|
|
@@ -15,6 +15,7 @@ export default class TasksResultSubmit extends BaseCommand {
|
|
|
15
15
|
'structured-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
16
|
deliverable: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
17
|
evidence: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
attach: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
19
|
remaining: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
20
|
'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
21
|
'source-run': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -23,4 +24,6 @@ export default class TasksResultSubmit extends BaseCommand {
|
|
|
23
24
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
24
25
|
};
|
|
25
26
|
run(): Promise<void>;
|
|
27
|
+
/** The two ways forward from a closed Task, named where the commands are known. */
|
|
28
|
+
private reopenRequired;
|
|
26
29
|
}
|
|
@@ -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 core_1 = require("@oclif/core");
|
|
4
37
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -43,6 +76,11 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
|
43
76
|
multiple: true,
|
|
44
77
|
description: 'Evidence reference as <kind>:<id-or-uri>',
|
|
45
78
|
}),
|
|
79
|
+
attach: core_1.Flags.string({
|
|
80
|
+
multiple: true,
|
|
81
|
+
description: 'Upload a file as a Task asset (role: evidence) and cite it in evidenceRefs. ' +
|
|
82
|
+
'Repeatable. Re-attaching identical bytes dedupes on the server.',
|
|
83
|
+
}),
|
|
46
84
|
remaining: core_1.Flags.string({ multiple: true, description: 'Remaining work item (repeatable)' }),
|
|
47
85
|
'run-id': core_1.Flags.string({ description: 'Canonical Task Run that produced this Result' }),
|
|
48
86
|
'source-run': core_1.Flags.string({ multiple: true, description: 'Contributing Run id (repeatable)' }),
|
|
@@ -85,6 +123,36 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
|
85
123
|
const value = raw.slice(split + 1);
|
|
86
124
|
return /^https?:|^file:/.test(value) ? { kind, uri: value } : { kind, id: value };
|
|
87
125
|
});
|
|
126
|
+
// --attach: upload first so the Result cites real asset ids. Uploads land
|
|
127
|
+
// before the idempotency key is derived, so a retry sees the same refs.
|
|
128
|
+
if (flags.attach?.length) {
|
|
129
|
+
const { attachTaskAssetFiles, readTaskForUpload } = await Promise.resolve().then(() => __importStar(require('../../../lib/task-asset-upload')));
|
|
130
|
+
// A closed Task refuses the Result, and the files would already be
|
|
131
|
+
// stored — indexed as unreferenced uploads nobody asked for. Ask first.
|
|
132
|
+
// The server's refusal below stays the authority; this only keeps a
|
|
133
|
+
// refusal we can already see from costing an upload.
|
|
134
|
+
let target;
|
|
135
|
+
try {
|
|
136
|
+
target = await readTaskForUpload(task.id);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
this.error(`--attach failed: ${err.message}`, { exit: 1 });
|
|
140
|
+
}
|
|
141
|
+
if ((0, task_closure_1.taskIsSettled)(target)) {
|
|
142
|
+
this.reopenRequired(task.id, 'This Task is closed, and a Result can only be submitted while it is open. ' +
|
|
143
|
+
'Nothing was uploaded.');
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
evidenceRefs.push(...(await attachTaskAssetFiles({
|
|
147
|
+
taskId: task.id,
|
|
148
|
+
files: flags.attach,
|
|
149
|
+
role: 'evidence',
|
|
150
|
+
})));
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
this.error(`--attach failed: ${err.message}`, { exit: 1 });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
88
156
|
const payload = {
|
|
89
157
|
summary: flags.summary,
|
|
90
158
|
body: flags.body,
|
|
@@ -127,14 +195,7 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
|
127
195
|
// (OSK-10031).
|
|
128
196
|
const refusal = (0, base_command_1.apiRefusal)(error);
|
|
129
197
|
if (refusal.code === 'TASK_REOPEN_REQUIRED') {
|
|
130
|
-
this.
|
|
131
|
-
refusal.message ?? 'This Task is closed.',
|
|
132
|
-
...(0, task_closure_1.reopenRequiredLines)({
|
|
133
|
-
bin: this.config.bin,
|
|
134
|
-
task: task.id,
|
|
135
|
-
command: 'result submit',
|
|
136
|
-
}),
|
|
137
|
-
].join('\n'), { exit: 1, code: 'TASK_REOPEN_REQUIRED' });
|
|
198
|
+
this.reopenRequired(task.id, refusal.message ?? 'This Task is closed.');
|
|
138
199
|
}
|
|
139
200
|
this.handleApiError(error);
|
|
140
201
|
}
|
|
@@ -154,5 +215,12 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
|
154
215
|
if (url)
|
|
155
216
|
this.log(`Task: ${url}`);
|
|
156
217
|
}
|
|
218
|
+
/** The two ways forward from a closed Task, named where the commands are known. */
|
|
219
|
+
reopenRequired(taskId, message) {
|
|
220
|
+
this.error([
|
|
221
|
+
message,
|
|
222
|
+
...(0, task_closure_1.reopenRequiredLines)({ bin: this.config.bin, task: taskId, command: 'result submit' }),
|
|
223
|
+
].join('\n'), { exit: 1, code: 'TASK_REOPEN_REQUIRED' });
|
|
224
|
+
}
|
|
157
225
|
}
|
|
158
226
|
exports.default = TasksResultSubmit;
|
|
@@ -97,7 +97,9 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
97
97
|
// set of "move this task somewhere" options — which is how a reader
|
|
98
98
|
// concludes the CLI cannot change a task's project at all (dogfood
|
|
99
99
|
// OSK-4652). It can: `tasks move <id> --project <id|none>`.
|
|
100
|
-
goal: core_1.Flags.string({
|
|
100
|
+
goal: core_1.Flags.string({
|
|
101
|
+
description: 'Move task to a different goal (goal id), or "none" to detach it from its goal',
|
|
102
|
+
}),
|
|
101
103
|
cycle: core_1.Flags.string({
|
|
102
104
|
description: 'Set planning cycle by ID, or "current" / "next" in the task Space',
|
|
103
105
|
}),
|
|
@@ -324,7 +326,7 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
324
326
|
// sees it and answers with the sentence that names `tasks move`.
|
|
325
327
|
status: flags.status,
|
|
326
328
|
duplicateOfId: flags['duplicate-of'],
|
|
327
|
-
goalId: flags.goal,
|
|
329
|
+
goalId: (0, tasks_2.resolveTaskGoalFlag)(flags.goal),
|
|
328
330
|
cycleId: flags.cycle,
|
|
329
331
|
spaceId: flags.space,
|
|
330
332
|
assigneeAgentIds: flags['assignee-agent'],
|
|
@@ -15,6 +15,7 @@ export default class TasksUpdatesAdd extends BaseCommand {
|
|
|
15
15
|
'spec-version': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
16
|
supersedes: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
17
|
reference: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
attach: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
19
|
'idempotency-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
20
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
21
|
};
|
|
@@ -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 core_1 = require("@oclif/core");
|
|
4
37
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -64,6 +97,12 @@ class TasksUpdatesAdd extends base_command_1.BaseCommand {
|
|
|
64
97
|
}),
|
|
65
98
|
supersedes: core_1.Flags.string({ description: 'Update id this correction supersedes' }),
|
|
66
99
|
reference: core_1.Flags.string({ multiple: true, description: 'Reference as <kind>:<id-or-uri>' }),
|
|
100
|
+
attach: core_1.Flags.string({
|
|
101
|
+
multiple: true,
|
|
102
|
+
description: 'Upload a file as a Task asset (role: evidence) and cite it in this Update — appended to ' +
|
|
103
|
+
'data.evidenceRefs for finding/verification payloads, to the Update references otherwise. ' +
|
|
104
|
+
'Repeatable. Re-attaching identical bytes dedupes on the server.',
|
|
105
|
+
}),
|
|
67
106
|
'idempotency-key': core_1.Flags.string({ description: 'Stable retry key for this exact Update' }),
|
|
68
107
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
69
108
|
};
|
|
@@ -88,6 +127,30 @@ class TasksUpdatesAdd extends base_command_1.BaseCommand {
|
|
|
88
127
|
const value = raw.slice(split + 1);
|
|
89
128
|
return /^https?:|^file:/.test(value) ? { kind, uri: value } : { kind, id: value };
|
|
90
129
|
});
|
|
130
|
+
// --attach: upload first so the Update can cite the asset ids. For
|
|
131
|
+
// finding/verification the citation lands in data.evidenceRefs where the
|
|
132
|
+
// evidence renderer reads it; for the other Update kinds it becomes a
|
|
133
|
+
// task_attachment reference on the Update itself.
|
|
134
|
+
if (flags.attach?.length) {
|
|
135
|
+
const { attachTaskAssetFiles } = await Promise.resolve().then(() => __importStar(require('../../../lib/task-asset-upload')));
|
|
136
|
+
let refs;
|
|
137
|
+
try {
|
|
138
|
+
refs = await attachTaskAssetFiles({
|
|
139
|
+
taskId: task.id,
|
|
140
|
+
files: flags.attach,
|
|
141
|
+
role: 'evidence',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
this.error(`--attach failed: ${err.message}`, { exit: 1 });
|
|
146
|
+
}
|
|
147
|
+
if (Array.isArray(data.evidenceRefs)) {
|
|
148
|
+
data = { ...data, evidenceRefs: [...data.evidenceRefs, ...refs] };
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
references.push(...refs);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
91
154
|
const idempotencyKey = flags['idempotency-key'] ||
|
|
92
155
|
(0, outbox_1.idempotencyKeyFor)('task-update', task.id, JSON.stringify({ type: flags.type, summary: flags.summary, data, resume }));
|
|
93
156
|
let result;
|
package/dist/lib/api-fetch.js
CHANGED
|
@@ -93,9 +93,14 @@ async function apiFetch(pathOrUrl, opts = {}) {
|
|
|
93
93
|
? assertTrustedAutonomousUrl(pathOrUrl, baseURL)
|
|
94
94
|
: pathOrUrl
|
|
95
95
|
: `${baseURL.replace(/\/+$/, '')}${pathOrUrl.startsWith('/') ? '' : '/'}${pathOrUrl}`;
|
|
96
|
+
// A FormData body passes through untouched — fetch sets the multipart
|
|
97
|
+
// boundary itself, and stringifying would destroy it. Upload commands
|
|
98
|
+
// (tasks attachments) need this on the session-scoped path, which is not
|
|
99
|
+
// in dataService.
|
|
100
|
+
const isFormData = typeof FormData !== 'undefined' && opts.body instanceof FormData;
|
|
96
101
|
let body;
|
|
97
102
|
if (opts.body !== undefined && method !== 'GET') {
|
|
98
|
-
body = JSON.stringify(opts.body);
|
|
103
|
+
body = isFormData ? opts.body : JSON.stringify(opts.body);
|
|
99
104
|
}
|
|
100
105
|
// Same rule as every `dataService` write (`@skrr-ai/data-provider`
|
|
101
106
|
// idempotency), chosen once so the 401 retries below resend the same key.
|
|
@@ -145,7 +150,7 @@ async function apiFetch(pathOrUrl, opts = {}) {
|
|
|
145
150
|
Accept: 'application/json',
|
|
146
151
|
'X-Oversky-Origin': (0, refresh_1.getCliOrigin)(),
|
|
147
152
|
};
|
|
148
|
-
if (opts.body !== undefined && method !== 'GET') {
|
|
153
|
+
if (opts.body !== undefined && method !== 'GET' && !isFormData) {
|
|
149
154
|
headers['Content-Type'] = 'application/json';
|
|
150
155
|
}
|
|
151
156
|
if (credential.token) {
|
|
@@ -34,10 +34,7 @@ export interface ManagedCliProviderState {
|
|
|
34
34
|
updateDisabledReason?: string | null;
|
|
35
35
|
platformSupported?: boolean;
|
|
36
36
|
authentication?: ManagedCliAuthentication | null;
|
|
37
|
-
job?:
|
|
38
|
-
id?: string;
|
|
39
|
-
status?: string;
|
|
40
|
-
} | null;
|
|
37
|
+
job?: ManagedCliInstallJob | null;
|
|
41
38
|
}
|
|
42
39
|
export interface CliInstallersResponse {
|
|
43
40
|
daemonId?: string;
|
|
@@ -155,6 +152,7 @@ export interface ManagedCliInstallJob {
|
|
|
155
152
|
status: 'queued' | 'running' | 'succeeded' | 'failed';
|
|
156
153
|
/** `update` for an in-place update; absent from an older daemon, meaning install. */
|
|
157
154
|
kind?: 'install' | 'update';
|
|
155
|
+
startedAt?: string;
|
|
158
156
|
previousVersion?: string | null;
|
|
159
157
|
installedVersion?: string | null;
|
|
160
158
|
error?: string;
|
|
@@ -184,6 +182,17 @@ export interface StartInstallResponse {
|
|
|
184
182
|
};
|
|
185
183
|
}
|
|
186
184
|
export declare function startManagedCliInstall(daemonId: string, provider: string, credential?: unknown): Promise<StartInstallResponse>;
|
|
185
|
+
/**
|
|
186
|
+
* How long after a start request times out a job for the same provider is taken
|
|
187
|
+
* to be the one that request began.
|
|
188
|
+
*
|
|
189
|
+
* The relay holds the request while the daemon answers, and a gateway can cut
|
|
190
|
+
* that off at its own deadline: an update returned HTTP 504 after 21.9s while
|
|
191
|
+
* the job it started ran to success, and the caller was told the outcome was
|
|
192
|
+
* unknown (OSK-10096 verifier). A job that started within this window of the
|
|
193
|
+
* request is that request's job.
|
|
194
|
+
*/
|
|
195
|
+
export declare const START_TIMEOUT_JOB_WINDOW_MS = 120000;
|
|
187
196
|
/** Ask the daemon to update an installed CLI in place (OSK-10096). */
|
|
188
197
|
export declare function startManagedCliUpdate(daemonId: string, provider: string, credential?: unknown): Promise<StartInstallResponse>;
|
|
189
198
|
/**
|
|
@@ -191,6 +200,16 @@ export declare function startManagedCliUpdate(daemonId: string, provider: string
|
|
|
191
200
|
* "Updated Claude Code 2.1.270 → 2.1.280." or "Claude Code is still 2.1.270:
|
|
192
201
|
* its updater found nothing newer." Null when the job does not carry both.
|
|
193
202
|
*/
|
|
203
|
+
/**
|
|
204
|
+
* The job a timed-out start request began, or null when none can be claimed.
|
|
205
|
+
*
|
|
206
|
+
* Read from the daemon's own inventory rather than assumed: it is the only
|
|
207
|
+
* party that knows whether the request reached it.
|
|
208
|
+
*/
|
|
209
|
+
export declare function jobStartedDespiteTimeout(daemonId: string, provider: string, credential?: unknown, opts?: {
|
|
210
|
+
now?: number;
|
|
211
|
+
windowMs?: number;
|
|
212
|
+
}): Promise<ManagedCliInstallJob | null>;
|
|
194
213
|
export declare function updateOutcomeLine(job: ManagedCliInstallJob): string | null;
|
|
195
214
|
export declare function readManagedCliInstallJob(daemonId: string, jobId: string, credential?: unknown): Promise<{
|
|
196
215
|
job?: ManagedCliInstallJob;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.INSTALL_POLL_INTERVAL_MS = exports.INSTALL_MAX_WAIT_MS = exports.ROW_READINESS_TIMEOUT_MS = exports.MANAGED_CLI_PROVIDER_SINCE = void 0;
|
|
3
|
+
exports.INSTALL_POLL_INTERVAL_MS = exports.INSTALL_MAX_WAIT_MS = exports.START_TIMEOUT_JOB_WINDOW_MS = exports.ROW_READINESS_TIMEOUT_MS = exports.MANAGED_CLI_PROVIDER_SINCE = void 0;
|
|
4
4
|
exports.describeProvidersNotOffered = describeProvidersNotOffered;
|
|
5
5
|
exports.providersNotOffered = providersNotOffered;
|
|
6
6
|
exports.listCliInstallers = listCliInstallers;
|
|
@@ -10,6 +10,7 @@ exports.readinessKey = readinessKey;
|
|
|
10
10
|
exports.readinessForRows = readinessForRows;
|
|
11
11
|
exports.startManagedCliInstall = startManagedCliInstall;
|
|
12
12
|
exports.startManagedCliUpdate = startManagedCliUpdate;
|
|
13
|
+
exports.jobStartedDespiteTimeout = jobStartedDespiteTimeout;
|
|
13
14
|
exports.updateOutcomeLine = updateOutcomeLine;
|
|
14
15
|
exports.readManagedCliInstallJob = readManagedCliInstallJob;
|
|
15
16
|
exports.unseenLogLines = unseenLogLines;
|
|
@@ -88,12 +89,14 @@ function describeProvidersNotOffered(missing) {
|
|
|
88
89
|
.join(', ');
|
|
89
90
|
}
|
|
90
91
|
function providersNotOffered(offered, known) {
|
|
91
|
-
// Canonicalize BOTH sides.
|
|
92
|
-
//
|
|
93
|
-
// older spelling, so a raw comparison against the current
|
|
94
|
-
// a machine where it
|
|
95
|
-
//
|
|
96
|
-
//
|
|
92
|
+
// Canonicalize BOTH sides. A daemon answers under the spelling it was built
|
|
93
|
+
// with — during the rename window the 0.8.35 build reported the first-party
|
|
94
|
+
// harness under its older spelling, so a raw comparison against the current
|
|
95
|
+
// one reported it missing on a machine where it was installed and working (the
|
|
96
|
+
// first version of this helper said "Not offered: devin, <first-party
|
|
97
|
+
// harness>" when only `devin` was true). This is INGRESS, so it canonicalizes
|
|
98
|
+
// accepted spellings only: since contract a retired spelling is not the
|
|
99
|
+
// harness, and a daemon still answering under one predates the wire release.
|
|
97
100
|
const seen = new Set((offered ?? []).map((provider) => canonical(provider.provider)).filter(Boolean));
|
|
98
101
|
return known.filter((provider) => !seen.has(canonical(provider)));
|
|
99
102
|
}
|
|
@@ -214,6 +217,17 @@ async function readinessForRows(rows, credential, opts = {}) {
|
|
|
214
217
|
async function startManagedCliInstall(daemonId, provider, credential) {
|
|
215
218
|
return (0, api_fetch_1.apiFetch)(`/api/daemons/${encodeURIComponent(daemonId)}/cli-installers/${encodeURIComponent(provider)}/install`, { method: 'POST', body: {}, credential: credential });
|
|
216
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* How long after a start request times out a job for the same provider is taken
|
|
222
|
+
* to be the one that request began.
|
|
223
|
+
*
|
|
224
|
+
* The relay holds the request while the daemon answers, and a gateway can cut
|
|
225
|
+
* that off at its own deadline: an update returned HTTP 504 after 21.9s while
|
|
226
|
+
* the job it started ran to success, and the caller was told the outcome was
|
|
227
|
+
* unknown (OSK-10096 verifier). A job that started within this window of the
|
|
228
|
+
* request is that request's job.
|
|
229
|
+
*/
|
|
230
|
+
exports.START_TIMEOUT_JOB_WINDOW_MS = 120_000;
|
|
217
231
|
/** Ask the daemon to update an installed CLI in place (OSK-10096). */
|
|
218
232
|
async function startManagedCliUpdate(daemonId, provider, credential) {
|
|
219
233
|
return (0, api_fetch_1.apiFetch)(`/api/daemons/${encodeURIComponent(daemonId)}/cli-installers/${encodeURIComponent(provider)}/update`, { method: 'POST', body: {}, credential: credential });
|
|
@@ -223,6 +237,32 @@ async function startManagedCliUpdate(daemonId, provider, credential) {
|
|
|
223
237
|
* "Updated Claude Code 2.1.270 → 2.1.280." or "Claude Code is still 2.1.270:
|
|
224
238
|
* its updater found nothing newer." Null when the job does not carry both.
|
|
225
239
|
*/
|
|
240
|
+
/**
|
|
241
|
+
* The job a timed-out start request began, or null when none can be claimed.
|
|
242
|
+
*
|
|
243
|
+
* Read from the daemon's own inventory rather than assumed: it is the only
|
|
244
|
+
* party that knows whether the request reached it.
|
|
245
|
+
*/
|
|
246
|
+
async function jobStartedDespiteTimeout(daemonId, provider, credential, opts = {}) {
|
|
247
|
+
let response;
|
|
248
|
+
try {
|
|
249
|
+
response = await listCliInstallers(daemonId, credential);
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const row = (response.providers ?? []).find((entry) => canonical(entry.provider) === canonical(provider));
|
|
255
|
+
const job = row?.job;
|
|
256
|
+
if (!job?.id)
|
|
257
|
+
return null;
|
|
258
|
+
if (job.status === 'queued' || job.status === 'running')
|
|
259
|
+
return job;
|
|
260
|
+
const startedAt = job.startedAt ? Date.parse(job.startedAt) : NaN;
|
|
261
|
+
if (!Number.isFinite(startedAt))
|
|
262
|
+
return null;
|
|
263
|
+
const now = opts.now ?? Date.now();
|
|
264
|
+
return now - startedAt <= (opts.windowMs ?? exports.START_TIMEOUT_JOB_WINDOW_MS) ? job : null;
|
|
265
|
+
}
|
|
226
266
|
function updateOutcomeLine(job) {
|
|
227
267
|
const before = job.previousVersion;
|
|
228
268
|
const after = job.installedVersion;
|
|
@@ -845,8 +845,10 @@ function selectDedicatedAttachHarness(lease, harnesses, engine) {
|
|
|
845
845
|
}
|
|
846
846
|
const providers = [...new Set(rows.map((row) => row.provider))];
|
|
847
847
|
if (engine) {
|
|
848
|
-
// Any
|
|
849
|
-
// harness's older name means the row stored
|
|
848
|
+
// Any ACCEPTED spelling of an engine names it — during a rename's alias window,
|
|
849
|
+
// a user who typed the first-party harness's older name means the row stored
|
|
850
|
+
// under its canonical one. A retired spelling is accepted nowhere, so it names
|
|
851
|
+
// no engine here either (`isSameHarnessProvider`).
|
|
850
852
|
const match = rows.find((row) => (0, auth_core_1.isSameHarnessProvider)(row.provider, engine));
|
|
851
853
|
if (!match) {
|
|
852
854
|
return {
|
package/dist/lib/file-mime.js
CHANGED
|
@@ -220,7 +220,7 @@ async function resolveFirstPartyHarnessAgent(explicit, deps = {}, options = {})
|
|
|
220
220
|
const created = options.createDefault === false
|
|
221
221
|
? null
|
|
222
222
|
: await (deps.ensureDefaultAgent ?? ensureDefaultAgent)(
|
|
223
|
-
// Canonical: what the server stores
|
|
223
|
+
// Canonical: what the server stores, and the one spelling every server accepts.
|
|
224
224
|
auth_core_1.FIRST_PARTY_HARNESS.provider, options.signal);
|
|
225
225
|
if (created?.id) {
|
|
226
226
|
return {
|
|
@@ -330,11 +330,12 @@ function readRawConfigKey() {
|
|
|
330
330
|
* first real session read. Returns whether the file now holds it under the
|
|
331
331
|
* neutral key.
|
|
332
332
|
*
|
|
333
|
-
* Reading alone used to leave it where it was
|
|
334
|
-
*
|
|
335
|
-
*
|
|
333
|
+
* Reading alone used to leave it where it was. `legacyAgentConfigKeys()` keeps
|
|
334
|
+
* naming an old key after its spelling is retired (it reads the identity's
|
|
335
|
+
* ARTIFACT spellings, since the file predates the rename), but a key that is only
|
|
336
|
+
* ever read is one the next pruning of `formerSpellings` would strand, and a user
|
|
336
337
|
* who never ran `--set`, `--clear` or logout would silently lose their setting.
|
|
337
|
-
* Moving it
|
|
338
|
+
* Moving it on the first session read retires the old key long before that.
|
|
338
339
|
*
|
|
339
340
|
* Only the session path calls this — `skrr code doctor` reports and never
|
|
340
341
|
* writes. Best-effort: an unwritable config is left alone and still read.
|