@constraint/cli 0.3.4 → 0.3.6
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/package.json +1 -1
- package/skills/constraint-skills/references/commands.md +6 -1
- package/src/cli.js +36 -8
- package/src/config.js +3 -0
- package/src/setup.js +10 -2
package/package.json
CHANGED
|
@@ -49,11 +49,16 @@ constraint skills run complete <run-id> <actual-transcript-path>
|
|
|
49
49
|
constraint skills run list
|
|
50
50
|
constraint skills run list --team <domain> --user <workos-user-id> --skill <skill>
|
|
51
51
|
constraint skills run get <run-id>
|
|
52
|
-
constraint skills run get <run-id> --raw
|
|
52
|
+
constraint skills run get <run-id> --raw
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
Repeat `--team`, `--user`, or `--skill` to request subsets. Review visibility is permission-controlled.
|
|
56
56
|
|
|
57
|
+
`run get` never prints a transcript to stdout: it writes the run JSON (or the
|
|
58
|
+
original transcript file with `--raw`) under the system temp directory and
|
|
59
|
+
prints a one-object summary containing the file `path`. Read the file from
|
|
60
|
+
that path. Pass `--output <path>` to choose the destination (single run only).
|
|
61
|
+
|
|
57
62
|
## Automation and recovery
|
|
58
63
|
|
|
59
64
|
Global flags: `--json`, `--quiet`, `--no-color`, `--help`, and `--version`. Installer workflows also accept `--yes`.
|
package/src/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import readline from 'node:readline/promises';
|
|
4
5
|
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
uploadSkill,
|
|
36
37
|
} from './skills.js';
|
|
37
38
|
|
|
38
|
-
const VERSION = '0.3.
|
|
39
|
+
const VERSION = '0.3.6';
|
|
39
40
|
|
|
40
41
|
const HELP = `Constraint Skills CLI
|
|
41
42
|
|
|
@@ -56,7 +57,7 @@ Usage:
|
|
|
56
57
|
constraint skills run start <skill> --client <client> --session <session-id>
|
|
57
58
|
constraint skills run complete <run-id> <transcript-path>
|
|
58
59
|
constraint skills run list [--team <team>]... [--user <user>]... [--skill <skill>]...
|
|
59
|
-
constraint skills run get <run-id>... [--raw] [--output <path>]
|
|
60
|
+
constraint skills run get <run-id>... [--raw] [--output <path>] (always writes a file, prints summary + path)
|
|
60
61
|
|
|
61
62
|
Global options: --json --quiet --no-color --help --version`;
|
|
62
63
|
|
|
@@ -511,23 +512,50 @@ async function runList(args, config, out) {
|
|
|
511
512
|
out.data(await apiRequest(config, `/skill-runs?${query.toString()}`));
|
|
512
513
|
}
|
|
513
514
|
|
|
515
|
+
// Run payloads are whole session transcripts — megabytes of JSON that would
|
|
516
|
+
// flood a terminal or an agent's context. runGet therefore always writes to a
|
|
517
|
+
// file and prints only a summary with the path; there is no stdout mode.
|
|
518
|
+
async function runGetDestination(output, runId, extension) {
|
|
519
|
+
if (output) return path.resolve(output);
|
|
520
|
+
const directory = path.join(os.tmpdir(), 'constraint', 'runs');
|
|
521
|
+
await fs.mkdir(directory, { recursive: true });
|
|
522
|
+
return path.join(directory, `${runId}${extension}`);
|
|
523
|
+
}
|
|
524
|
+
|
|
514
525
|
async function runGet(args, config, out) {
|
|
515
526
|
const raw = takeFlag(args, '--raw');
|
|
516
527
|
const output = takeOption(args, '--output');
|
|
517
528
|
rejectUnknown(args);
|
|
518
529
|
if (!args.length) throw new Error('Usage: constraint skills run get <run-id>...');
|
|
530
|
+
if (output && args.length !== 1) throw new Error('--output accepts exactly one run ID');
|
|
519
531
|
if (raw && args.length !== 1) throw new Error('--raw accepts exactly one run ID');
|
|
520
532
|
if (raw) {
|
|
521
533
|
const response = await apiRequest(config, `/skill-runs/${encodeURIComponent(args[0])}/transcript`, { rawResponse: true });
|
|
522
534
|
const content = Buffer.from(await response.arrayBuffer());
|
|
523
|
-
|
|
524
|
-
|
|
535
|
+
const destination = await runGetDestination(output, args[0], '.transcript');
|
|
536
|
+
await fs.writeFile(destination, content);
|
|
537
|
+
out.data({ run_id: args[0], bytes: content.length, path: destination });
|
|
525
538
|
return;
|
|
526
539
|
}
|
|
527
|
-
const
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
540
|
+
const summaries = [];
|
|
541
|
+
for (const runId of args) {
|
|
542
|
+
const run = await apiRequest(config, `/skill-runs/${encodeURIComponent(runId)}`);
|
|
543
|
+
const destination = await runGetDestination(output, runId, '.json');
|
|
544
|
+
await fs.writeFile(destination, `${JSON.stringify(run, null, 2)}\n`);
|
|
545
|
+
const events = Array.isArray(run.normalized_events) ? run.normalized_events : [];
|
|
546
|
+
summaries.push({
|
|
547
|
+
run_id: run.run_id,
|
|
548
|
+
skill: run.skill_slug,
|
|
549
|
+
version: run.skill_version,
|
|
550
|
+
state: run.state,
|
|
551
|
+
client: run.client,
|
|
552
|
+
completed_at: run.completed_at,
|
|
553
|
+
events: events.length,
|
|
554
|
+
events_with_text: events.filter((event) => event.content).length,
|
|
555
|
+
path: destination,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
out.data(summaries.length === 1 ? summaries[0] : summaries);
|
|
531
559
|
}
|
|
532
560
|
|
|
533
561
|
async function runCommand(args, config, out) {
|
package/src/config.js
CHANGED
|
@@ -28,6 +28,9 @@ export async function loadConfig() {
|
|
|
28
28
|
return {
|
|
29
29
|
apiUrl: (process.env.CONSTRAINT_API_URL || saved.apiUrl || DEFAULT_API_URL).replace(/\/$/, ''),
|
|
30
30
|
agents: Array.isArray(saved.agents) ? saved.agents : Array.isArray(saved.clients) ? saved.clients : [],
|
|
31
|
+
companion_hashes: saved.companion_hashes && typeof saved.companion_hashes === 'object'
|
|
32
|
+
? saved.companion_hashes
|
|
33
|
+
: {},
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
|
package/src/setup.js
CHANGED
|
@@ -42,6 +42,13 @@ async function companionFiles() {
|
|
|
42
42
|
return readSkillDirectory(path.resolve(here, '..', 'skills', 'constraint-skills'));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export function expectedCompanionHash(config, selected, currentHash) {
|
|
46
|
+
const direct = config.companion_hashes?.[selected] || null;
|
|
47
|
+
if (direct) return direct;
|
|
48
|
+
const recorded = Object.values(config.companion_hashes || {});
|
|
49
|
+
return currentHash && recorded.includes(currentHash) ? currentHash : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
async function instructionPlan(selected, paths) {
|
|
46
53
|
let existing = '';
|
|
47
54
|
let mode = 0o644;
|
|
@@ -59,7 +66,6 @@ async function skillPlan(selected, paths) {
|
|
|
59
66
|
const files = await companionFiles();
|
|
60
67
|
const bundledHash = packageDigest(files);
|
|
61
68
|
const config = await loadConfig();
|
|
62
|
-
const expectedHash = config.companion_hashes?.[selected] || null;
|
|
63
69
|
const target = path.join(paths.skills, 'constraint-skills');
|
|
64
70
|
let currentHash = null;
|
|
65
71
|
try {
|
|
@@ -67,6 +73,7 @@ async function skillPlan(selected, paths) {
|
|
|
67
73
|
} catch (error) {
|
|
68
74
|
if (error && error.code !== 'ENOENT') throw error;
|
|
69
75
|
}
|
|
76
|
+
const expectedHash = expectedCompanionHash(config, selected, currentHash);
|
|
70
77
|
const action = currentHash === bundledHash
|
|
71
78
|
? 'current'
|
|
72
79
|
: currentHash === null
|
|
@@ -109,8 +116,9 @@ export async function installCompanionSkill(agent) {
|
|
|
109
116
|
const config = await loadConfig();
|
|
110
117
|
config.companion_hashes ||= {};
|
|
111
118
|
const target = path.join(paths.skills, 'constraint-skills');
|
|
119
|
+
const plan = await skillPlan(selected, paths);
|
|
112
120
|
const result = await writeSkillDirectory(target, files, {
|
|
113
|
-
expectedHash:
|
|
121
|
+
expectedHash: plan.expectedHash,
|
|
114
122
|
});
|
|
115
123
|
config.companion_hashes[selected] = result.hash;
|
|
116
124
|
await recordConfiguredAgent(selected, config);
|