@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,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
|
|
@@ -71,6 +71,12 @@ export default class TasksCreate extends BaseCommand {
|
|
|
71
71
|
'lifecycle-pack': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
72
72
|
};
|
|
73
73
|
run(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* A create refusal, translated. `TASK_GOAL_NOT_FOUND` names the goal id this
|
|
76
|
+
* command sent and the flag that gets past it, where the server's sentence
|
|
77
|
+
* names API fields (OSK-10219); everything else is the uniform translation.
|
|
78
|
+
*/
|
|
79
|
+
private failTaskCreate;
|
|
74
80
|
private createTaskOrRecover;
|
|
75
81
|
/**
|
|
76
82
|
* Predict the create route's `ASSIGNEE_NOT_IN_SPACE` degradation for a
|
|
@@ -333,7 +333,7 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
333
333
|
instantiated = (await data_provider_1.dataService.createTask(payload));
|
|
334
334
|
}
|
|
335
335
|
catch (err) {
|
|
336
|
-
this.
|
|
336
|
+
this.failTaskCreate(err, payload, flags.goal !== undefined);
|
|
337
337
|
}
|
|
338
338
|
const root = instantiated.rootTask ||
|
|
339
339
|
(instantiated.rootTasks || [])[0];
|
|
@@ -475,7 +475,7 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
if (!(defaultAgentResolution.applied && failureCode === 'ASSIGNEE_NOT_IN_SPACE')) {
|
|
478
|
-
this.
|
|
478
|
+
this.failTaskCreate(err, payload, flags.goal !== undefined);
|
|
479
479
|
}
|
|
480
480
|
delete payload.assigneeAgentIds;
|
|
481
481
|
delete payload.assigneeUserIds;
|
|
@@ -502,7 +502,7 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
502
502
|
createRecovery = result.recovery;
|
|
503
503
|
}
|
|
504
504
|
catch (retryErr) {
|
|
505
|
-
this.
|
|
505
|
+
this.failTaskCreate(retryErr, payload, flags.goal !== undefined);
|
|
506
506
|
}
|
|
507
507
|
}
|
|
508
508
|
const url = (0, web_url_1.taskUrlFrom)(this.cliConfig.baseURL, created);
|
|
@@ -537,6 +537,29 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
537
537
|
this.log(`View it at ${url}`);
|
|
538
538
|
await (0, task_instruction_offer_1.maybeOfferTaskManagementInstructions)((message) => this.log(message));
|
|
539
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* A create refusal, translated. `TASK_GOAL_NOT_FOUND` names the goal id this
|
|
542
|
+
* command sent and the flag that gets past it, where the server's sentence
|
|
543
|
+
* names API fields (OSK-10219); everything else is the uniform translation.
|
|
544
|
+
*/
|
|
545
|
+
failTaskCreate(err, payload, goalFromFlag) {
|
|
546
|
+
const goalId = payload.goalId;
|
|
547
|
+
if ((0, base_command_1.apiRefusal)(err).code === tasks_1.TASK_GOAL_NOT_FOUND && typeof goalId === 'string' && goalId) {
|
|
548
|
+
this.failWithCliError({
|
|
549
|
+
message: (0, tasks_1.describeTaskGoalNotFound)({
|
|
550
|
+
goalId,
|
|
551
|
+
command: 'create',
|
|
552
|
+
bin: this.config.bin,
|
|
553
|
+
goalSource: goalFromFlag ? 'flag' : 'json',
|
|
554
|
+
}),
|
|
555
|
+
code: tasks_1.TASK_GOAL_NOT_FOUND,
|
|
556
|
+
status: 400,
|
|
557
|
+
exit: 1,
|
|
558
|
+
retryable: false,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
this.handleApiError(err);
|
|
562
|
+
}
|
|
540
563
|
async createTaskOrRecover(payload) {
|
|
541
564
|
try {
|
|
542
565
|
return {
|
|
@@ -28,6 +28,10 @@ class TasksLabelsAttach extends base_command_1.BaseCommand {
|
|
|
28
28
|
static flags = {
|
|
29
29
|
json: core_1.Flags.boolean({ description: 'Output the updated task as JSON' }),
|
|
30
30
|
'label-id': core_1.Flags.string({
|
|
31
|
+
// `--label` is what `spaces labels add` takes and what the managed
|
|
32
|
+
// task-management instructions tell every agent to type; without the
|
|
33
|
+
// alias that documented command died at parse.
|
|
34
|
+
aliases: ['label'],
|
|
31
35
|
description: 'Label to attach — id, or a name from `skrr labels list --applicable-to task`. An unknown name is refused, never created (repeatable).',
|
|
32
36
|
multiple: true,
|
|
33
37
|
required: true,
|
|
@@ -58,6 +58,7 @@ export default class TasksList extends BaseCommand {
|
|
|
58
58
|
tag: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
59
59
|
'label-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
60
60
|
q: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
61
|
+
view: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
61
62
|
limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
62
63
|
cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
63
64
|
calendar: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -48,6 +48,7 @@ const FILTER_FLAGS = new Set([
|
|
|
48
48
|
'tag',
|
|
49
49
|
'label-id',
|
|
50
50
|
'q',
|
|
51
|
+
'view',
|
|
51
52
|
]);
|
|
52
53
|
/**
|
|
53
54
|
* What the zero-row case is allowed to say. The bare `No tasks.` was step 3
|
|
@@ -182,6 +183,7 @@ function buildListParams(flags, assigneeUserId) {
|
|
|
182
183
|
? { labelIds: flag('label-id') }
|
|
183
184
|
: {}),
|
|
184
185
|
q: flag('q'),
|
|
186
|
+
...(flag('view') ? { taskViewId: flag('view') } : {}),
|
|
185
187
|
limit: flag('limit'),
|
|
186
188
|
cursor: flag('cursor'),
|
|
187
189
|
};
|
|
@@ -205,6 +207,7 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
205
207
|
'<%= config.bin %> tasks list --actionable-by agent --actionable-for-agent <agent-id>',
|
|
206
208
|
'<%= config.bin %> tasks list --needs-me',
|
|
207
209
|
'<%= config.bin %> tasks list --dri me',
|
|
210
|
+
'<%= config.bin %> tasks list --view <task-view-id>',
|
|
208
211
|
'<%= config.bin %> tasks list --calendar 2026-08-01..2026-08-31 --json',
|
|
209
212
|
];
|
|
210
213
|
static flags = {
|
|
@@ -314,6 +317,12 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
314
317
|
multiple: true,
|
|
315
318
|
}),
|
|
316
319
|
q: core_1.Flags.string({ description: 'Free-text search query' }),
|
|
320
|
+
// A saved Task View is a query; this is the one place outside the browser
|
|
321
|
+
// that runs it (OSK-4651). Resolved server-side by the same evaluator the
|
|
322
|
+
// view subscriptions use, over the tasks this caller may read.
|
|
323
|
+
view: core_1.Flags.string({
|
|
324
|
+
description: 'Only tasks a saved Task View selects (task_view_…; see `views list`). Combines with other filters',
|
|
325
|
+
}),
|
|
317
326
|
limit: core_1.Flags.integer({ description: 'Max results', default: 50 }),
|
|
318
327
|
cursor: core_1.Flags.string({ description: 'Pagination cursor from a previous page' }),
|
|
319
328
|
calendar: core_1.Flags.string({
|
|
@@ -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;
|
|
@@ -10,6 +10,29 @@ import { BaseCommand } from '../../base-command';
|
|
|
10
10
|
* exists for them to show.
|
|
11
11
|
*/
|
|
12
12
|
export declare function taskPointerLines(t: Record<string, unknown>, ref: string, bin?: string): string[];
|
|
13
|
+
/**
|
|
14
|
+
* The `Labels:` value.
|
|
15
|
+
*
|
|
16
|
+
* `labels attach` writes ids, and without this line the only way to see
|
|
17
|
+
* whether one landed was to attach it again and read "No change — labels
|
|
18
|
+
* already attached" (OSK-10313). Names, because an id is not something a
|
|
19
|
+
* person recognises — but an id beats nothing, so a vocabulary that could not
|
|
20
|
+
* be read (or a label missing from it) degrades per entry rather than failing
|
|
21
|
+
* the command or hiding the label.
|
|
22
|
+
*/
|
|
23
|
+
export declare function labelsLine(labelIds?: string[], nameById?: Map<string, string>): string;
|
|
24
|
+
/**
|
|
25
|
+
* The `Executor:` value — who does this task, and whether anyone said so.
|
|
26
|
+
*
|
|
27
|
+
* It printed `legacy / inferred` whenever `executionMode` was absent, which is
|
|
28
|
+
* the normal result of `tasks create` without `--execution-mode`. A task made
|
|
29
|
+
* ten seconds earlier by the most ordinary invocation there is read as old data
|
|
30
|
+
* made the deprecated way (OSK-4629). The executor is now the one the server
|
|
31
|
+
* acts on (`resolveTaskExecutor`, shared with `TaskActionability`), and the
|
|
32
|
+
* value says when it is implied by the assignees rather than declared, because
|
|
33
|
+
* reassigning the task changes only the implied kind.
|
|
34
|
+
*/
|
|
35
|
+
export declare function taskExecutorLabel(t: Record<string, unknown>, bin?: string): string;
|
|
13
36
|
/**
|
|
14
37
|
* The failure rows of `tasks show`, when there are any. (S3 dogfood finding)
|
|
15
38
|
*
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.taskPointerLines = taskPointerLines;
|
|
4
|
+
exports.labelsLine = labelsLine;
|
|
5
|
+
exports.taskExecutorLabel = taskExecutorLabel;
|
|
4
6
|
exports.taskFailureLines = taskFailureLines;
|
|
5
7
|
const core_1 = require("@oclif/core");
|
|
6
8
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -11,6 +13,7 @@ const task_closure_1 = require("../../lib/task-closure");
|
|
|
11
13
|
const task_resolver_1 = require("../../lib/task-resolver");
|
|
12
14
|
const web_url_1 = require("../../lib/web-url");
|
|
13
15
|
const html_text_1 = require("../../lib/html-text");
|
|
16
|
+
const label_ref_1 = require("../../lib/label-ref");
|
|
14
17
|
const format_1 = require("../../lib/format");
|
|
15
18
|
/**
|
|
16
19
|
* Where to look next — as COMMANDS, not as facts about the task.
|
|
@@ -39,6 +42,46 @@ function taskPointerLines(t, ref, bin = 'skrr') {
|
|
|
39
42
|
...pointers.map(([command, what]) => ` ${command.padEnd(width)} ${what}`),
|
|
40
43
|
];
|
|
41
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The `Labels:` value.
|
|
47
|
+
*
|
|
48
|
+
* `labels attach` writes ids, and without this line the only way to see
|
|
49
|
+
* whether one landed was to attach it again and read "No change — labels
|
|
50
|
+
* already attached" (OSK-10313). Names, because an id is not something a
|
|
51
|
+
* person recognises — but an id beats nothing, so a vocabulary that could not
|
|
52
|
+
* be read (or a label missing from it) degrades per entry rather than failing
|
|
53
|
+
* the command or hiding the label.
|
|
54
|
+
*/
|
|
55
|
+
function labelsLine(labelIds, nameById) {
|
|
56
|
+
const ids = (labelIds ?? []).filter((id) => typeof id === 'string' && id.length > 0);
|
|
57
|
+
if (ids.length === 0)
|
|
58
|
+
return '-';
|
|
59
|
+
return ids.map((id) => nameById?.get(id) ?? id).join(', ');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The `Executor:` value — who does this task, and whether anyone said so.
|
|
63
|
+
*
|
|
64
|
+
* It printed `legacy / inferred` whenever `executionMode` was absent, which is
|
|
65
|
+
* the normal result of `tasks create` without `--execution-mode`. A task made
|
|
66
|
+
* ten seconds earlier by the most ordinary invocation there is read as old data
|
|
67
|
+
* made the deprecated way (OSK-4629). The executor is now the one the server
|
|
68
|
+
* acts on (`resolveTaskExecutor`, shared with `TaskActionability`), and the
|
|
69
|
+
* value says when it is implied by the assignees rather than declared, because
|
|
70
|
+
* reassigning the task changes only the implied kind.
|
|
71
|
+
*/
|
|
72
|
+
function taskExecutorLabel(t, bin = 'skrr') {
|
|
73
|
+
const executor = (0, data_provider_1.resolveTaskExecutor)(t);
|
|
74
|
+
switch (executor.source) {
|
|
75
|
+
case 'declared':
|
|
76
|
+
return executor.mode;
|
|
77
|
+
case 'assignees':
|
|
78
|
+
return `${executor.mode} (not declared; implied by the ${executor.mode} assignees)`;
|
|
79
|
+
case 'mixed-assignees':
|
|
80
|
+
return `not chosen — Human and Agent assignees; pick one with \`${bin} tasks update --execution-mode\``;
|
|
81
|
+
case 'unassigned':
|
|
82
|
+
return '-';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
42
85
|
/**
|
|
43
86
|
* The failure rows of `tasks show`, when there are any. (S3 dogfood finding)
|
|
44
87
|
*
|
|
@@ -284,7 +327,7 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
284
327
|
}
|
|
285
328
|
this.log(`Result: ${priorLine}`);
|
|
286
329
|
}
|
|
287
|
-
this.log(`Executor: ${t.
|
|
330
|
+
this.log(`Executor: ${taskExecutorLabel(t, this.config.bin)}`);
|
|
288
331
|
this.log(`Priority: ${t.priority ?? '-'}`);
|
|
289
332
|
this.log(`Parent: ${t.parentId ?? '-'}`);
|
|
290
333
|
this.log(`Space: ${t.spaceId ?? '-'}`);
|
|
@@ -293,6 +336,23 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
293
336
|
// was no way to tell an ignored flag from an honoured one.
|
|
294
337
|
this.log(`Project: ${t.projectId ?? '-'}`);
|
|
295
338
|
this.log(`Goal: ${t.goalId ?? '-'}`);
|
|
339
|
+
// Printed for the same reason Project is: `labels attach` writes ids, and
|
|
340
|
+
// without this line the only way to see whether one landed was to attach
|
|
341
|
+
// it again and read "No change — labels already attached" (OSK-10313).
|
|
342
|
+
// Names, because an id is not something a person recognises; a vocabulary
|
|
343
|
+
// read that fails prints the ids rather than failing the whole command.
|
|
344
|
+
const labelIds = Array.isArray(t.labelIds) ? t.labelIds : [];
|
|
345
|
+
let labelNames;
|
|
346
|
+
if (labelIds.length > 0) {
|
|
347
|
+
try {
|
|
348
|
+
const vocabulary = await (0, label_ref_1.collectLabelVocabulary)({ applicableTo: 'task' });
|
|
349
|
+
labelNames = new Map(vocabulary.map((row) => [row.id, row.name]));
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
// A vocabulary that cannot be read prints ids; see labelsLine.
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
this.log(`Labels: ${labelsLine(labelIds, labelNames)}`);
|
|
296
356
|
this.log(`Author: ${t.author ?? '-'}`);
|
|
297
357
|
const dri = t.dri;
|
|
298
358
|
if (dri?.resolved) {
|
|
@@ -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'],
|
|
@@ -401,6 +403,18 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
401
403
|
});
|
|
402
404
|
}
|
|
403
405
|
catch (err) {
|
|
406
|
+
// The server's refusal says "detach the goal with goalId: null", which is
|
|
407
|
+
// not something a CLI user can type. Name the id sent and `--goal none`.
|
|
408
|
+
const goalId = payload.goalId;
|
|
409
|
+
if ((0, base_command_1.apiRefusal)(err).code === tasks_2.TASK_GOAL_NOT_FOUND && typeof goalId === 'string' && goalId) {
|
|
410
|
+
this.failWithCliError({
|
|
411
|
+
message: (0, tasks_2.describeTaskGoalNotFound)({ goalId, command: 'update', bin: this.config.bin }),
|
|
412
|
+
code: tasks_2.TASK_GOAL_NOT_FOUND,
|
|
413
|
+
status: 400,
|
|
414
|
+
exit: 1,
|
|
415
|
+
retryable: false,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
404
418
|
this.handleApiError(err);
|
|
405
419
|
}
|
|
406
420
|
// Postcondition, not a prediction — see `droppedEstimateWarning`. On stderr
|
|
@@ -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;
|
|
@@ -19,7 +19,10 @@ class ViewsCreate extends base_command_1.BaseCommand {
|
|
|
19
19
|
'from-json': core_1.Flags.string({ description: 'JSON Task View body' }),
|
|
20
20
|
name: core_1.Flags.string({ description: 'View name' }),
|
|
21
21
|
description: core_1.Flags.string({ description: 'Short explanation shown in the modal' }),
|
|
22
|
-
type: core_1.Flags.string({
|
|
22
|
+
type: core_1.Flags.string({
|
|
23
|
+
options: [...vocabulary_1.VIEW_TYPES],
|
|
24
|
+
description: `Layout (default: ${vocabulary_1.TASK_VIEW_DEFAULT_TYPE})`,
|
|
25
|
+
}),
|
|
23
26
|
'task-id': core_1.Flags.string({ multiple: true, description: 'Include this exact task ID' }),
|
|
24
27
|
space: core_1.Flags.string({ multiple: true, description: 'Limit to this Space ID' }),
|
|
25
28
|
// Status labels are per-Space. The API bounds and normalizes values but
|
|
@@ -41,7 +44,7 @@ class ViewsCreate extends base_command_1.BaseCommand {
|
|
|
41
44
|
}),
|
|
42
45
|
'group-by': core_1.Flags.string({
|
|
43
46
|
options: [...vocabulary_1.VIEW_GROUP_BY_VALUES],
|
|
44
|
-
description:
|
|
47
|
+
description: `Grouping dimension (default: ${vocabulary_1.TASK_VIEW_DEFAULT_GROUP_BY})`,
|
|
45
48
|
}),
|
|
46
49
|
sort: core_1.Flags.string({
|
|
47
50
|
options: [...vocabulary_1.VIEW_SORT_KEYS],
|
|
@@ -107,6 +110,13 @@ class ViewsCreate extends base_command_1.BaseCommand {
|
|
|
107
110
|
return void this.log(JSON.stringify(result, null, 2));
|
|
108
111
|
}
|
|
109
112
|
this.log(`Created Task View ${view.id}`);
|
|
113
|
+
// What the SERVER saved, read back from the response — not an echo of the
|
|
114
|
+
// flags. Creation is the one moment the caller still knows what they meant
|
|
115
|
+
// to type, so it is where a filter that silently did not take has to show
|
|
116
|
+
// (dogfood OSK-4646). Same renderer as `views show`.
|
|
117
|
+
for (const line of (0, task_view_render_1.describeTaskView)(view)) {
|
|
118
|
+
this.log(line);
|
|
119
|
+
}
|
|
110
120
|
this.log(result.url);
|
|
111
121
|
if (warning)
|
|
112
122
|
this.warn(warning);
|