@skrr-ai/cli 0.1.14 → 0.1.17
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/README.md +3 -0
- package/dist/base-command.d.ts +14 -0
- package/dist/base-command.js +60 -1
- package/dist/commands/agents/create.d.ts +1 -0
- package/dist/commands/agents/create.js +6 -1
- package/dist/commands/agents/instructions/add.d.ts +21 -0
- package/dist/commands/agents/instructions/add.js +115 -0
- package/dist/commands/agents/instructions/disable.d.ts +13 -0
- package/dist/commands/agents/instructions/disable.js +50 -0
- package/dist/commands/agents/instructions/edit.d.ts +16 -0
- package/dist/commands/agents/instructions/edit.js +79 -0
- package/dist/commands/agents/instructions/enable.d.ts +13 -0
- package/dist/commands/agents/instructions/enable.js +50 -0
- package/dist/commands/agents/instructions/move.d.ts +15 -0
- package/dist/commands/agents/instructions/move.js +61 -0
- package/dist/commands/agents/instructions/preview.d.ts +13 -0
- package/dist/commands/agents/instructions/preview.js +59 -0
- package/dist/commands/agents/instructions/remove.d.ts +13 -0
- package/dist/commands/agents/instructions/remove.js +49 -0
- package/dist/commands/agents/instructions/set.d.ts +17 -0
- package/dist/commands/agents/instructions/set.js +79 -0
- package/dist/commands/agents/instructions/show.d.ts +15 -0
- package/dist/commands/agents/instructions/show.js +76 -0
- package/dist/commands/agents/instructions/upgrade.d.ts +16 -0
- package/dist/commands/agents/instructions/upgrade.js +77 -0
- package/dist/commands/agents/show.js +5 -0
- package/dist/commands/agents/triggers/policy.js +8 -2
- package/dist/commands/agents/update.d.ts +1 -0
- package/dist/commands/agents/update.js +8 -2
- package/dist/commands/commitments/autonomy.js +9 -1
- package/dist/commands/commitments/create.d.ts +8 -5
- package/dist/commands/commitments/create.js +38 -8
- package/dist/commands/commitments/doctor.d.ts +19 -0
- package/dist/commands/commitments/doctor.js +72 -0
- package/dist/commands/commitments/preflight.d.ts +3 -1
- package/dist/commands/commitments/preflight.js +25 -3
- package/dist/commands/commitments/reports.js +15 -2
- package/dist/commands/commitments/update.d.ts +9 -2
- package/dist/commands/commitments/update.js +36 -2
- package/dist/commands/daemon/index.js +2 -0
- package/dist/commands/daemon/recover-offline-queue.d.ts +9 -0
- package/dist/commands/daemon/recover-offline-queue.js +24 -0
- package/dist/commands/daemon/start.js +29 -1
- package/dist/commands/instruction-blocks/create.d.ts +19 -0
- package/dist/commands/instruction-blocks/create.js +94 -0
- package/dist/commands/instruction-blocks/delete.d.ts +13 -0
- package/dist/commands/instruction-blocks/delete.js +35 -0
- package/dist/commands/instruction-blocks/list.d.ts +13 -0
- package/dist/commands/instruction-blocks/list.js +71 -0
- package/dist/commands/instruction-blocks/show.d.ts +12 -0
- package/dist/commands/instruction-blocks/show.js +35 -0
- package/dist/commands/instruction-blocks/update.d.ts +23 -0
- package/dist/commands/instruction-blocks/update.js +94 -0
- package/dist/commands/spaces/auto-executor/preview.d.ts +1 -0
- package/dist/commands/spaces/auto-executor/preview.js +62 -3
- package/dist/commands/spaces/auto-executor/update.d.ts +4 -0
- package/dist/commands/spaces/auto-executor/update.js +78 -7
- package/dist/commands/spaces/capacity.js +14 -2
- package/dist/commands/spaces/update.d.ts +4 -0
- package/dist/commands/spaces/update.js +49 -2
- package/dist/commands/tasks/complete.d.ts +12 -5
- package/dist/commands/tasks/complete.js +107 -28
- package/dist/commands/tasks/continue-ready.js +9 -1
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +27 -2
- package/dist/commands/tasks/deliverable/add.d.ts +23 -0
- package/dist/commands/tasks/deliverable/add.js +70 -0
- package/dist/commands/tasks/deliverable/confirm.d.ts +35 -0
- package/dist/commands/tasks/deliverable/confirm.js +77 -0
- package/dist/commands/tasks/events/append.d.ts +1 -1
- package/dist/commands/tasks/events/append.js +4 -4
- package/dist/commands/tasks/expectations.d.ts +12 -0
- package/dist/commands/tasks/expectations.js +111 -0
- package/dist/commands/tasks/judge.d.ts +29 -0
- package/dist/commands/tasks/judge.js +68 -0
- package/dist/commands/tasks/report.d.ts +1 -1
- package/dist/commands/tasks/report.js +27 -3
- package/dist/commands/tasks/trust.d.ts +35 -0
- package/dist/commands/tasks/trust.js +75 -0
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +34 -4
- package/dist/commands/tasks/waive.d.ts +25 -0
- package/dist/commands/tasks/waive.js +58 -0
- package/dist/lib/agent-config.js +5 -0
- package/dist/lib/agent-instructions.d.ts +15 -0
- package/dist/lib/agent-instructions.js +55 -0
- package/dist/lib/command-hygiene.d.ts +6 -1
- package/dist/lib/command-hygiene.js +49 -29
- package/dist/lib/commitments.d.ts +28 -3
- package/dist/lib/commitments.js +20 -11
- package/dist/lib/exec-runtime-binary.d.ts +13 -0
- package/dist/lib/exec-runtime-binary.js +45 -0
- package/dist/lib/git-task.d.ts +37 -0
- package/dist/lib/git-task.js +151 -0
- package/dist/lib/instruction-blocks.d.ts +29 -0
- package/dist/lib/instruction-blocks.js +159 -0
- package/dist/lib/runtime-start-verification.d.ts +49 -0
- package/dist/lib/runtime-start-verification.js +108 -0
- package/dist/lib/task-execution.d.ts +18 -2
- package/dist/lib/task-execution.js +19 -14
- package/dist/lib/task-transcript.js +1 -1
- package/dist/lib/tasks.d.ts +50 -0
- package/dist/lib/tasks.js +93 -2
- package/dist/node_modules/@skrr-ai/data-provider/index.js +2393 -2197
- package/dist/node_modules/@skrr-ai/inference-broker/package.json +1 -1
- package/oclif.manifest.json +17725 -15563
- package/package.json +4 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class InstructionBlocksDelete extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
const prompt_1 = require("../../lib/prompt");
|
|
7
|
+
class InstructionBlocksDelete extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'Archive a block you authored (existing Agent compositions keep their pinned snapshot)';
|
|
9
|
+
static examples = ['<%= config.bin %> instruction-blocks delete block_… --yes'];
|
|
10
|
+
static args = {
|
|
11
|
+
id: core_1.Args.string({ description: 'Instruction block ID', required: true, ignoreStdin: true }),
|
|
12
|
+
};
|
|
13
|
+
static flags = {
|
|
14
|
+
yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation' }),
|
|
15
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
this.requireAuth();
|
|
19
|
+
const { args, flags } = await this.parse(InstructionBlocksDelete);
|
|
20
|
+
const confirmed = await (0, prompt_1.confirmDestructive)(`Archive ${args.id}? Existing Agents keep their version-pinned snapshot, but it can no longer be newly attached.`, flags.yes);
|
|
21
|
+
if (!confirmed)
|
|
22
|
+
return this.log('Aborted.');
|
|
23
|
+
let result;
|
|
24
|
+
try {
|
|
25
|
+
result = await data_provider_1.dataService.archiveInstructionBlock(args.id);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
this.handleApiError(error);
|
|
29
|
+
}
|
|
30
|
+
if (flags.json)
|
|
31
|
+
return this.log(JSON.stringify(result, null, 2));
|
|
32
|
+
this.log(`Archived ${result.id}. Existing Agents retain their pinned snapshots.`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.default = InstructionBlocksDelete;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/** List the picker catalog in a form an Agent can act on without a browser. */
|
|
3
|
+
export default class InstructionBlocksList extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
official: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
library: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
category: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
const format_1 = require("../../lib/format");
|
|
7
|
+
const CATEGORIES = [
|
|
8
|
+
'github',
|
|
9
|
+
'communication',
|
|
10
|
+
'research',
|
|
11
|
+
'output',
|
|
12
|
+
'planning',
|
|
13
|
+
'other',
|
|
14
|
+
];
|
|
15
|
+
/** List the picker catalog in a form an Agent can act on without a browser. */
|
|
16
|
+
class InstructionBlocksList extends base_command_1.BaseCommand {
|
|
17
|
+
static description = 'List reusable Agent instruction blocks (official blocks and your visible library)';
|
|
18
|
+
static examples = [
|
|
19
|
+
'<%= config.bin %> instruction-blocks list',
|
|
20
|
+
'<%= config.bin %> instruction-blocks list --library',
|
|
21
|
+
'<%= config.bin %> instruction-blocks list --category github --json',
|
|
22
|
+
];
|
|
23
|
+
static flags = {
|
|
24
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
25
|
+
official: core_1.Flags.boolean({ description: 'Only code-owned official blocks' }),
|
|
26
|
+
library: core_1.Flags.boolean({ description: 'Only blocks visible from your library' }),
|
|
27
|
+
category: core_1.Flags.string({ description: 'Only blocks in this category', options: CATEGORIES }),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
this.requireAuth();
|
|
31
|
+
const { flags } = await this.parse(InstructionBlocksList);
|
|
32
|
+
if (flags.official && flags.library) {
|
|
33
|
+
this.error('Use either --official or --library, not both.', { exit: 2 });
|
|
34
|
+
}
|
|
35
|
+
let catalog;
|
|
36
|
+
try {
|
|
37
|
+
catalog = await data_provider_1.dataService.listInstructionBlocks();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.handleApiError(error);
|
|
41
|
+
}
|
|
42
|
+
const all = [
|
|
43
|
+
...(flags.library ? [] : catalog.official),
|
|
44
|
+
...(flags.official ? [] : catalog.library),
|
|
45
|
+
].filter((block) => !flags.category || block.category === flags.category);
|
|
46
|
+
if (flags.json) {
|
|
47
|
+
this.log(JSON.stringify({ blocks: all }, null, 2));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!all.length) {
|
|
51
|
+
this.log('No instruction blocks match. Create one with `skrr instruction-blocks create`.');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
(0, format_1.renderTable)(all.map((block) => ({
|
|
55
|
+
id: block.id,
|
|
56
|
+
name: block.name,
|
|
57
|
+
source: block.source,
|
|
58
|
+
version: `v${block.currentVersion}`,
|
|
59
|
+
category: block.category,
|
|
60
|
+
summary: block.summary,
|
|
61
|
+
})), [
|
|
62
|
+
{ key: 'id', header: 'ID', verbatim: true },
|
|
63
|
+
{ key: 'name', header: 'NAME', maxWidth: 30 },
|
|
64
|
+
{ key: 'source', header: 'SOURCE' },
|
|
65
|
+
{ key: 'version', header: 'VERSION' },
|
|
66
|
+
{ key: 'category', header: 'CATEGORY' },
|
|
67
|
+
{ key: 'summary', header: 'SUMMARY', maxWidth: 52 },
|
|
68
|
+
], (line) => this.log(line));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.default = InstructionBlocksList;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class InstructionBlocksShow extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
const instruction_blocks_1 = require("../../lib/instruction-blocks");
|
|
7
|
+
class InstructionBlocksShow extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'Show a reusable block, including its pinned source and requirements';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> instruction-blocks show block_official_decision_memo',
|
|
11
|
+
'<%= config.bin %> instruction-blocks show block_… --json',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Instruction block ID', required: true, ignoreStdin: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
|
|
17
|
+
async run() {
|
|
18
|
+
this.requireAuth();
|
|
19
|
+
const { args, flags } = await this.parse(InstructionBlocksShow);
|
|
20
|
+
let block;
|
|
21
|
+
try {
|
|
22
|
+
block = await data_provider_1.dataService.getInstructionBlock(args.id);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
this.handleApiError(error);
|
|
26
|
+
}
|
|
27
|
+
if (flags.json) {
|
|
28
|
+
this.log(JSON.stringify(block, null, 2));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const line of (0, instruction_blocks_1.renderInstructionBlockDetail)(block))
|
|
32
|
+
this.log(line);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.default = InstructionBlocksShow;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/** Any edit produces a new immutable source version; attached Agents stay pinned. */
|
|
3
|
+
export default class InstructionBlocksUpdate extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static args: {
|
|
7
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
summary: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
body: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
category: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
tag: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
+
visibility: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
'parameter-schema': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
requirements: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
changelog: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
const instruction_blocks_1 = require("../../lib/instruction-blocks");
|
|
7
|
+
const instruction_input_1 = require("../../lib/instruction-input");
|
|
8
|
+
const CATEGORIES = [
|
|
9
|
+
'github',
|
|
10
|
+
'communication',
|
|
11
|
+
'research',
|
|
12
|
+
'output',
|
|
13
|
+
'planning',
|
|
14
|
+
'other',
|
|
15
|
+
];
|
|
16
|
+
/** Any edit produces a new immutable source version; attached Agents stay pinned. */
|
|
17
|
+
class InstructionBlocksUpdate extends base_command_1.BaseCommand {
|
|
18
|
+
static description = 'Update a block you authored (creates a new immutable version; attached Agents stay pinned)';
|
|
19
|
+
static examples = [
|
|
20
|
+
'<%= config.bin %> instruction-blocks update block_… --body "Lead with evidence." --changelog "Clarify order"',
|
|
21
|
+
'<%= config.bin %> instruction-blocks update block_… --file ./review.md',
|
|
22
|
+
'<%= config.bin %> instruction-blocks update block_… --visibility workspace',
|
|
23
|
+
];
|
|
24
|
+
static args = {
|
|
25
|
+
id: core_1.Args.string({ description: 'Instruction block ID', required: true, ignoreStdin: true }),
|
|
26
|
+
};
|
|
27
|
+
static flags = {
|
|
28
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
29
|
+
name: core_1.Flags.string({ description: 'New block name' }),
|
|
30
|
+
summary: core_1.Flags.string({ description: 'New one-line description' }),
|
|
31
|
+
body: core_1.Flags.string({ description: 'New instruction template text' }),
|
|
32
|
+
file: core_1.Flags.string({ description: 'Read new template text from a file, or - for stdin' }),
|
|
33
|
+
category: core_1.Flags.string({ description: 'New library category', options: CATEGORIES }),
|
|
34
|
+
tag: core_1.Flags.string({
|
|
35
|
+
description: 'Replace tags with these values (repeatable)',
|
|
36
|
+
multiple: true,
|
|
37
|
+
}),
|
|
38
|
+
visibility: core_1.Flags.string({ options: ['private', 'workspace', 'public'] }),
|
|
39
|
+
'parameter-schema': core_1.Flags.string({ description: 'Replace parameters with this JSON array' }),
|
|
40
|
+
requirements: core_1.Flags.string({ description: 'Replace requirements with this JSON array' }),
|
|
41
|
+
changelog: core_1.Flags.string({ description: 'Reason for this version' }),
|
|
42
|
+
};
|
|
43
|
+
async run() {
|
|
44
|
+
this.requireAuth();
|
|
45
|
+
const { args, flags } = await this.parse(InstructionBlocksUpdate);
|
|
46
|
+
let bodyTemplate;
|
|
47
|
+
let parameterSchema;
|
|
48
|
+
let requirements;
|
|
49
|
+
try {
|
|
50
|
+
bodyTemplate = await (0, instruction_input_1.readInstructionBody)({ body: flags.body, file: flags.file });
|
|
51
|
+
parameterSchema = (0, instruction_blocks_1.parseJsonFlag)(flags['parameter-schema'], '--parameter-schema');
|
|
52
|
+
requirements = (0, instruction_blocks_1.parseJsonFlag)(flags.requirements, '--requirements');
|
|
53
|
+
if (parameterSchema && !Array.isArray(parameterSchema)) {
|
|
54
|
+
throw new Error('--parameter-schema must be a JSON array');
|
|
55
|
+
}
|
|
56
|
+
if (requirements && !Array.isArray(requirements)) {
|
|
57
|
+
throw new Error('--requirements must be a JSON array');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.error(error.message, { exit: 2 });
|
|
62
|
+
}
|
|
63
|
+
const patch = {
|
|
64
|
+
...(flags.name !== undefined ? { name: flags.name } : {}),
|
|
65
|
+
...(flags.summary !== undefined ? { summary: flags.summary } : {}),
|
|
66
|
+
...(bodyTemplate !== undefined ? { bodyTemplate } : {}),
|
|
67
|
+
...(flags.category !== undefined
|
|
68
|
+
? { category: flags.category }
|
|
69
|
+
: {}),
|
|
70
|
+
...(flags.tag !== undefined ? { tags: flags.tag } : {}),
|
|
71
|
+
...(flags.visibility !== undefined
|
|
72
|
+
? { visibility: flags.visibility }
|
|
73
|
+
: {}),
|
|
74
|
+
...(parameterSchema !== undefined ? { parameterSchema } : {}),
|
|
75
|
+
...(requirements !== undefined ? { requirements } : {}),
|
|
76
|
+
...(flags.changelog !== undefined ? { changelog: flags.changelog } : {}),
|
|
77
|
+
};
|
|
78
|
+
if (!Object.keys(patch).length) {
|
|
79
|
+
this.error('Nothing to update. Pass at least one field to change.', { exit: 2 });
|
|
80
|
+
}
|
|
81
|
+
let block;
|
|
82
|
+
try {
|
|
83
|
+
block = await data_provider_1.dataService.updateInstructionBlock(args.id, patch);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
this.handleApiError(error);
|
|
87
|
+
}
|
|
88
|
+
if (flags.json)
|
|
89
|
+
return this.log(JSON.stringify(block, null, 2));
|
|
90
|
+
this.log(`Updated ${block.name} (${block.id}) to v${block.currentVersion}.`);
|
|
91
|
+
this.log('Existing Agent compositions remain pinned; upgrade them explicitly when ready.');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.default = InstructionBlocksUpdate;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
2
|
export default class SpacesAutoExecutorPreview extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static examples: string[];
|
|
4
5
|
static args: {
|
|
5
6
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
7
|
};
|
|
@@ -6,21 +6,80 @@ const base_command_1 = require("../../../base-command");
|
|
|
6
6
|
const space_output_1 = require("../../../lib/space-output");
|
|
7
7
|
class SpacesAutoExecutorPreview extends base_command_1.BaseCommand {
|
|
8
8
|
static description = 'Preview what a space auto-executor run would do';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> spaces auto-executor preview <space-id>',
|
|
11
|
+
'<%= config.bin %> spaces auto-executor preview <space-id> --json',
|
|
12
|
+
];
|
|
9
13
|
static args = {
|
|
10
14
|
id: core_1.Args.string({ description: 'Space ID', required: true, ignoreStdin: true }),
|
|
11
15
|
};
|
|
12
16
|
static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
|
|
13
17
|
async run() {
|
|
14
18
|
this.requireAuth();
|
|
15
|
-
|
|
19
|
+
// `flags` was previously not destructured at all: --json was declared,
|
|
20
|
+
// ignored, and raw JSON printed unconditionally. There was no readable
|
|
21
|
+
// rendering of a preview anywhere in the CLI.
|
|
22
|
+
const { args, flags } = await this.parse(SpacesAutoExecutorPreview);
|
|
16
23
|
let result;
|
|
17
24
|
try {
|
|
18
|
-
result = await data_provider_1.dataService.previewSpaceAutoExecutor(args.id);
|
|
25
|
+
result = (await data_provider_1.dataService.previewSpaceAutoExecutor(args.id));
|
|
19
26
|
}
|
|
20
27
|
catch (err) {
|
|
21
28
|
this.handleApiError(err);
|
|
22
29
|
}
|
|
23
|
-
|
|
30
|
+
if (flags.json) {
|
|
31
|
+
this.log(JSON.stringify((0, space_output_1.withSpacePerspectiveUrl)(this.cliConfig.baseURL, args.id, 'execution', { result }), null, 2));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const { space, plan } = result;
|
|
35
|
+
if (!plan) {
|
|
36
|
+
this.log('No plan was returned for this space.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.log(`Space: ${space.title ?? args.id}`);
|
|
40
|
+
this.log(`Autopilot: ${space.autoExecuteEnabled ? 'enabled' : 'disabled'}` +
|
|
41
|
+
(space.autoExecuteLifecycleState === 'sleeping'
|
|
42
|
+
? ` (sleeping${space.autoExecuteSuspensionReason ? `: ${String(space.autoExecuteSuspensionReason).replace(/_/g, ' ')}` : ''})`
|
|
43
|
+
: '') +
|
|
44
|
+
` · ${plan.policy.mode}`);
|
|
45
|
+
const { capacity } = plan;
|
|
46
|
+
this.log(`Running: ${(0, data_provider_1.formatRunningCapacity)(capacity.activeCount, capacity.maxActiveTasks)}` +
|
|
47
|
+
(capacity.maxActiveTasks === null ? ' (no concurrency cap)' : ''));
|
|
48
|
+
this.log(`Can start: ${(0, data_provider_1.formatLimit)(capacity.startsAvailable)} now`);
|
|
49
|
+
if (capacity.budget && !capacity.budget.unlimited) {
|
|
50
|
+
this.log(`Budget: ${capacity.budget.consumedStarts}/${capacity.budget.maxStarts} starts used this round`);
|
|
51
|
+
}
|
|
52
|
+
const { actions, summary } = plan;
|
|
53
|
+
this.log('');
|
|
54
|
+
this.log(`Board: ${summary.readyCount} ready · ${summary.unassignedCount} unassigned · ` +
|
|
55
|
+
`${summary.runningCount} running · ${summary.failedCount} failed · ${summary.scheduledCount} scheduled`);
|
|
56
|
+
section(this.log.bind(this), 'Would start now', actions.startNow, (a) => taskLine(a.task));
|
|
57
|
+
section(this.log.bind(this), 'Would assign', actions.assignments, (a) => `${taskLine(a.task)} → ${a.suggestedAgentName ?? a.suggestedAgentId ?? 'no eligible agent'}`);
|
|
58
|
+
section(this.log.bind(this), 'Would schedule later', actions.scheduleLater, (a) => `${taskLine(a.task)} @ ${a.scheduledFor}`);
|
|
59
|
+
section(this.log.bind(this), 'Failures to review', actions.failureReviews, (a) => taskLine(a.task));
|
|
60
|
+
// The single most useful diagnostic in the payload: a ready task that is
|
|
61
|
+
// not starting because ITS agent is saturated elsewhere, not because this
|
|
62
|
+
// space is full. Without it the board just looks stuck.
|
|
63
|
+
section(this.log.bind(this), 'Waiting on agent capacity', actions.capacityWaits, (a) => `${taskLine(a.task)} (agent ${a.agentId ?? 'unknown'} is at its cross-space cap)`);
|
|
64
|
+
if (plan.risks?.length) {
|
|
65
|
+
this.log('');
|
|
66
|
+
this.log('Risks:');
|
|
67
|
+
for (const risk of plan.risks)
|
|
68
|
+
this.log(` ! ${risk}`);
|
|
69
|
+
}
|
|
24
70
|
}
|
|
25
71
|
}
|
|
26
72
|
exports.default = SpacesAutoExecutorPreview;
|
|
73
|
+
function taskLine(task) {
|
|
74
|
+
return `${task.identifier ? `${task.identifier} ` : ''}${task.title}`;
|
|
75
|
+
}
|
|
76
|
+
function section(log, heading, items, render, limit = 10) {
|
|
77
|
+
if (!items?.length)
|
|
78
|
+
return;
|
|
79
|
+
log('');
|
|
80
|
+
log(`${heading} (${items.length}):`);
|
|
81
|
+
for (const item of items.slice(0, limit))
|
|
82
|
+
log(` - ${render(item)}`);
|
|
83
|
+
if (items.length > limit)
|
|
84
|
+
log(` … ${items.length - limit} more (use --json for all)`);
|
|
85
|
+
}
|
|
@@ -9,7 +9,11 @@ export default class SpacesAutoExecutorUpdate extends BaseCommand {
|
|
|
9
9
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
11
|
enabled: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
mode: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
13
|
'interval-ms': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
cron: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
'daily-time': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
timezone: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
17
|
'max-starts-per-run': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
18
|
'max-active-tasks': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
19
|
};
|
|
@@ -5,11 +5,21 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
const prompt_1 = require("../../../lib/prompt");
|
|
7
7
|
const space_output_1 = require("../../../lib/space-output");
|
|
8
|
+
/**
|
|
9
|
+
* `0 = unlimited` is the persisted convention for both task limits. A flag
|
|
10
|
+
* description that omits it leaves the most useful setting undiscoverable —
|
|
11
|
+
* a user who wants "no cap" has no reason to guess that zero means it.
|
|
12
|
+
*/
|
|
13
|
+
const UNLIMITED_HINT = '0 = unlimited';
|
|
8
14
|
class SpacesAutoExecutorUpdate extends base_command_1.BaseCommand {
|
|
9
15
|
static description = 'Update a space auto-executor configuration';
|
|
10
16
|
static examples = [
|
|
11
17
|
'<%= config.bin %> spaces auto-executor update <space-id> --max-active-tasks 6',
|
|
12
18
|
'<%= config.bin %> spaces auto-executor update <space-id> --enabled --interval-ms 600000',
|
|
19
|
+
'<%= config.bin %> spaces auto-executor update <space-id> --mode cadenced',
|
|
20
|
+
'<%= config.bin %> spaces auto-executor update <space-id> --daily-time 09:00 --daily-time 17:00 --timezone America/Vancouver',
|
|
21
|
+
'<%= config.bin %> spaces auto-executor update <space-id> --cron "0 */2 * * *"',
|
|
22
|
+
'<%= config.bin %> spaces auto-executor update <space-id> --max-starts-per-run 0 # unlimited',
|
|
13
23
|
'<%= config.bin %> spaces auto-executor update <space-id> --no-enabled --json',
|
|
14
24
|
];
|
|
15
25
|
static args = {
|
|
@@ -21,9 +31,28 @@ class SpacesAutoExecutorUpdate extends base_command_1.BaseCommand {
|
|
|
21
31
|
description: 'Path to a JSON file (or "-" for stdin) to use as the patch body',
|
|
22
32
|
}),
|
|
23
33
|
enabled: core_1.Flags.boolean({ description: 'Enable or disable auto-execution', allowNo: true }),
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
mode: core_1.Flags.string({
|
|
35
|
+
description: 'continuous = a finished task promptly wakes the Leader to refill capacity; ' +
|
|
36
|
+
'cadenced = only run on the schedule, leaving a review window between batches',
|
|
37
|
+
options: [...data_provider_1.SPACE_AUTO_EXECUTION_MODES],
|
|
38
|
+
}),
|
|
39
|
+
'interval-ms': core_1.Flags.integer({
|
|
40
|
+
description: `Run every N milliseconds (min ${data_provider_1.SPACE_AUTO_EXECUTION_LIMITS.intervalMs.min}, max ${data_provider_1.SPACE_AUTO_EXECUTION_LIMITS.intervalMs.max})`,
|
|
41
|
+
}),
|
|
42
|
+
cron: core_1.Flags.string({ description: 'Run on a cron expression, e.g. "0 */2 * * *"' }),
|
|
43
|
+
'daily-time': core_1.Flags.string({
|
|
44
|
+
description: 'Run daily at HH:MM (24h). Repeatable for several times a day.',
|
|
45
|
+
multiple: true,
|
|
46
|
+
}),
|
|
47
|
+
timezone: core_1.Flags.string({
|
|
48
|
+
description: 'IANA timezone for --cron / --daily-time (default UTC)',
|
|
49
|
+
}),
|
|
50
|
+
'max-starts-per-run': core_1.Flags.integer({
|
|
51
|
+
description: `Max tasks to start per auto run (${UNLIMITED_HINT}, max ${data_provider_1.SPACE_AUTO_EXECUTION_LIMITS.maxStartsPerRun.max})`,
|
|
52
|
+
}),
|
|
53
|
+
'max-active-tasks': core_1.Flags.integer({
|
|
54
|
+
description: `Max concurrently active task executions in this space (${UNLIMITED_HINT}, max ${data_provider_1.SPACE_AUTO_EXECUTION_LIMITS.maxActiveTasks.max})`,
|
|
55
|
+
}),
|
|
27
56
|
};
|
|
28
57
|
async run() {
|
|
29
58
|
this.requireAuth();
|
|
@@ -35,9 +64,37 @@ class SpacesAutoExecutorUpdate extends base_command_1.BaseCommand {
|
|
|
35
64
|
catch (err) {
|
|
36
65
|
this.error(err.message, { exit: 1 });
|
|
37
66
|
}
|
|
67
|
+
// The API accepts exactly one recurrence shape. Rejecting here — by name,
|
|
68
|
+
// with the alternatives listed — beats a 400 that echoes the Zod refine.
|
|
69
|
+
const scheduleFlags = [
|
|
70
|
+
flags.cron !== undefined ? '--cron' : null,
|
|
71
|
+
flags['daily-time']?.length ? '--daily-time' : null,
|
|
72
|
+
flags['interval-ms'] !== undefined ? '--interval-ms' : null,
|
|
73
|
+
].filter(Boolean);
|
|
74
|
+
if (scheduleFlags.length > 1) {
|
|
75
|
+
this.error(`Pick one schedule shape: ${scheduleFlags.join(', ')} cannot be combined.`, {
|
|
76
|
+
exit: 1,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const timezone = flags.timezone ? { timezone: flags.timezone } : {};
|
|
80
|
+
let schedule;
|
|
81
|
+
if (flags.cron !== undefined) {
|
|
82
|
+
schedule = { cronExpression: flags.cron, ...timezone };
|
|
83
|
+
}
|
|
84
|
+
else if (flags['daily-time']?.length) {
|
|
85
|
+
schedule = { times: flags['daily-time'], ...timezone };
|
|
86
|
+
}
|
|
87
|
+
if (flags.timezone && !schedule) {
|
|
88
|
+
this.error('--timezone applies to --cron or --daily-time; pass one of them too.', {
|
|
89
|
+
exit: 1,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
38
92
|
const payload = (0, prompt_1.mergeDefined)(body, {
|
|
39
93
|
enabled: flags.enabled,
|
|
40
|
-
|
|
94
|
+
mode: flags.mode,
|
|
95
|
+
// `intervalMs` and `schedule` are mutually exclusive at the API.
|
|
96
|
+
intervalMs: schedule ? undefined : flags['interval-ms'],
|
|
97
|
+
schedule,
|
|
41
98
|
maxStartsPerRun: flags['max-starts-per-run'],
|
|
42
99
|
maxActiveTasks: flags['max-active-tasks'],
|
|
43
100
|
});
|
|
@@ -59,11 +116,25 @@ class SpacesAutoExecutorUpdate extends base_command_1.BaseCommand {
|
|
|
59
116
|
return;
|
|
60
117
|
}
|
|
61
118
|
const space = response?.space ?? {};
|
|
119
|
+
// A stored `0` means unlimited. Printing the raw number told the user the
|
|
120
|
+
// opposite of what the setting does.
|
|
121
|
+
const limit = (value) => typeof value === 'number' ? (0, data_provider_1.formatLimit)(value === 0 ? null : value) : '-';
|
|
62
122
|
this.log(`Updated auto-executor for ${space.id ?? args.id}`);
|
|
63
123
|
this.log(`Enabled: ${space.autoExecuteEnabled ? 'yes' : 'no'}`);
|
|
64
|
-
this.log(`
|
|
65
|
-
this.log(`
|
|
66
|
-
this.log(`Max
|
|
124
|
+
this.log(`Mode: ${space.autoExecuteMode ?? '-'}`);
|
|
125
|
+
this.log(`Interval: ${formatIntervalMs(space.autoExecuteIntervalMs)}`);
|
|
126
|
+
this.log(`Max starts/run: ${limit(space.autoExecuteMaxStartsPerRun)}`);
|
|
127
|
+
this.log(`Max active tasks: ${limit(space.autoExecuteMaxActiveTasks)}`);
|
|
67
128
|
}
|
|
68
129
|
}
|
|
69
130
|
exports.default = SpacesAutoExecutorUpdate;
|
|
131
|
+
/** Milliseconds are how the field is stored, not how anyone reads a cadence. */
|
|
132
|
+
function formatIntervalMs(value) {
|
|
133
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
134
|
+
return '-';
|
|
135
|
+
const minutes = value / 60_000;
|
|
136
|
+
if (minutes < 60)
|
|
137
|
+
return `${minutes % 1 === 0 ? minutes : minutes.toFixed(1)}m (${value}ms)`;
|
|
138
|
+
const hours = minutes / 60;
|
|
139
|
+
return `${hours % 1 === 0 ? hours : hours.toFixed(1)}h (${value}ms)`;
|
|
140
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const format_1 = require("../../lib/format");
|
|
6
7
|
const task_execution_1 = require("../../lib/task-execution");
|
|
@@ -33,11 +34,22 @@ class SpacesCapacity extends base_command_1.BaseCommand {
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
const space = capacity.space;
|
|
37
|
+
// `maxActiveTasks` / `availableSlots` are null when the space has no cap.
|
|
38
|
+
// Interpolating them directly is what produced `0/null active` (OSK-7087);
|
|
39
|
+
// the shared formatters in @skrr-ai/data-provider are the one place that
|
|
40
|
+
// decides how an absent ceiling reads, for the web and the CLI alike.
|
|
36
41
|
this.log(`Space: ${space.title ?? args.id}`);
|
|
37
42
|
this.log(`ID: ${space.id ?? args.id}`);
|
|
38
43
|
this.log(`Auto exec: ${space.autoExecuteEnabled ? 'enabled' : 'disabled'}`);
|
|
39
|
-
this.log(`Capacity: ${capacity.activeCount
|
|
40
|
-
|
|
44
|
+
this.log(`Capacity: ${(0, data_provider_1.formatRunningCapacity)(capacity.activeCount, capacity.maxActiveTasks)} active` +
|
|
45
|
+
(capacity.maxActiveTasks === null ? ' (no concurrency cap)' : ''));
|
|
46
|
+
this.log(`Available: ${(0, data_provider_1.formatLimit)(capacity.availableSlots)}`);
|
|
47
|
+
if (capacity.budget) {
|
|
48
|
+
const { consumedStarts, maxStarts, remaining, unlimited } = capacity.budget;
|
|
49
|
+
this.log(unlimited
|
|
50
|
+
? `Starts: ${consumedStarts} used this round (no per-run budget)`
|
|
51
|
+
: `Starts: ${consumedStarts}/${maxStarts} used this round, ${remaining} left`);
|
|
52
|
+
}
|
|
41
53
|
this.log(`Sampled: ${capacity.sampledTaskCount} tasks`);
|
|
42
54
|
if (capacity.activeTasks.length > 0) {
|
|
43
55
|
this.log('');
|
|
@@ -20,6 +20,10 @@ export default class SpacesUpdate extends BaseCommand {
|
|
|
20
20
|
'estimate-migration': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
21
|
'default-estimate': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
22
|
'use-default-estimate': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
23
|
+
'default-expect': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
'delivery-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
'integration-branch': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
'auto-merge-tier': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
27
|
'worktree-isolation': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
28
|
};
|
|
25
29
|
run(): Promise<void>;
|