@skrr-ai/cli 0.1.36 → 0.1.38
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 +17 -4
- package/bin/dev-fallback.js +167 -4
- package/dist/base-command.js +46 -2
- package/dist/commands/agents/actions/create.d.ts +5 -0
- package/dist/commands/agents/actions/create.js +42 -5
- package/dist/commands/agents/actions/delete.d.ts +1 -0
- package/dist/commands/agents/actions/delete.js +7 -0
- package/dist/commands/agents/actions/update.d.ts +5 -0
- package/dist/commands/agents/actions/update.js +27 -1
- package/dist/commands/agents/api-actions/add.d.ts +41 -0
- package/dist/commands/agents/api-actions/add.js +205 -0
- package/dist/commands/agents/api-actions/index.d.ts +39 -0
- package/dist/commands/agents/api-actions/index.js +103 -0
- package/dist/commands/agents/api-actions/remove.d.ts +14 -0
- package/dist/commands/agents/api-actions/remove.js +36 -0
- package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
- package/dist/commands/agents/avatar/default/apply.js +56 -0
- package/dist/commands/agents/avatar/default/index.d.ts +29 -0
- package/dist/commands/agents/avatar/default/index.js +61 -0
- package/dist/commands/agents/avatar/default/set.d.ts +24 -0
- package/dist/commands/agents/avatar/default/set.js +120 -0
- package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
- package/dist/commands/agents/avatar/library/delete.js +47 -0
- package/dist/commands/agents/avatar/library/index.d.ts +16 -0
- package/dist/commands/agents/avatar/library/index.js +56 -0
- package/dist/commands/agents/avatar/presets.d.ts +19 -0
- package/dist/commands/agents/avatar/presets.js +56 -0
- package/dist/commands/agents/avatar/upload.js +7 -1
- package/dist/commands/agents/categories/create.d.ts +14 -0
- package/dist/commands/agents/categories/create.js +46 -0
- package/dist/commands/agents/categories/delete.d.ts +13 -0
- package/dist/commands/agents/categories/delete.js +41 -0
- package/dist/commands/agents/categories/index.d.ts +36 -0
- package/dist/commands/agents/categories/index.js +135 -0
- package/dist/commands/agents/categories/update.d.ts +22 -0
- package/dist/commands/agents/categories/update.js +59 -0
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +94 -7
- package/dist/commands/agents/create.d.ts +10 -0
- package/dist/commands/agents/create.js +64 -3
- package/dist/commands/agents/ensure-default.d.ts +27 -0
- package/dist/commands/agents/ensure-default.js +65 -0
- package/dist/commands/agents/list.d.ts +15 -0
- package/dist/commands/agents/list.js +31 -1
- package/dist/commands/agents/mute.d.ts +16 -0
- package/dist/commands/agents/mute.js +38 -0
- package/dist/commands/agents/pin.d.ts +16 -0
- package/dist/commands/agents/pin.js +38 -0
- package/dist/commands/agents/scene-background/upload.d.ts +30 -0
- package/dist/commands/agents/scene-background/upload.js +97 -0
- package/dist/commands/agents/show.js +13 -0
- package/dist/commands/agents/tools/auth.d.ts +19 -0
- package/dist/commands/agents/tools/auth.js +41 -0
- package/dist/commands/agents/tools/calls.d.ts +36 -0
- package/dist/commands/agents/tools/calls.js +117 -0
- package/dist/commands/agents/tools/index.d.ts +20 -0
- package/dist/commands/agents/tools/index.js +77 -0
- package/dist/commands/agents/unmute.d.ts +16 -0
- package/dist/commands/agents/unmute.js +38 -0
- package/dist/commands/agents/unpin.d.ts +16 -0
- package/dist/commands/agents/unpin.js +38 -0
- package/dist/commands/agents/update.d.ts +12 -0
- package/dist/commands/agents/update.js +74 -3
- package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
- package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
- package/dist/commands/convos/messages.d.ts +13 -0
- package/dist/commands/convos/messages.js +40 -16
- package/dist/commands/daemon/index.js +8 -1
- package/dist/commands/daemon/logs.d.ts +26 -0
- package/dist/commands/daemon/logs.js +56 -0
- package/dist/commands/daemon/uninstall.js +1 -1
- package/dist/commands/followups/act.d.ts +22 -0
- package/dist/commands/followups/act.js +103 -0
- package/dist/commands/followups/cancel.d.ts +20 -0
- package/dist/commands/followups/cancel.js +50 -0
- package/dist/commands/followups/checkin.d.ts +27 -0
- package/dist/commands/followups/checkin.js +107 -0
- package/dist/commands/followups/list.d.ts +24 -0
- package/dist/commands/followups/list.js +90 -0
- package/dist/commands/followups/observability.d.ts +23 -0
- package/dist/commands/followups/observability.js +114 -0
- package/dist/commands/followups/remind.d.ts +26 -0
- package/dist/commands/followups/remind.js +106 -0
- package/dist/commands/followups/reschedule.d.ts +15 -0
- package/dist/commands/followups/reschedule.js +48 -0
- package/dist/commands/followups/resolve.d.ts +23 -0
- package/dist/commands/followups/resolve.js +54 -0
- package/dist/commands/followups/show.d.ts +12 -0
- package/dist/commands/followups/show.js +46 -0
- package/dist/commands/followups/watch.d.ts +51 -0
- package/dist/commands/followups/watch.js +211 -0
- package/dist/commands/goals/labels/add.js +19 -2
- package/dist/commands/goals/labels/remove.js +22 -2
- package/dist/commands/harnesses/forget.js +28 -0
- package/dist/commands/harnesses/install.d.ts +41 -0
- package/dist/commands/harnesses/install.js +165 -0
- package/dist/commands/harnesses/installers.d.ts +45 -0
- package/dist/commands/harnesses/installers.js +155 -0
- package/dist/commands/harnesses/list.d.ts +82 -1
- package/dist/commands/harnesses/list.js +104 -12
- package/dist/commands/harnesses/models.js +10 -1
- package/dist/commands/harnesses/show.d.ts +15 -0
- package/dist/commands/harnesses/show.js +44 -3
- package/dist/commands/harnesses/update.js +1 -1
- package/dist/commands/harnesses/usage.d.ts +25 -0
- package/dist/commands/harnesses/usage.js +24 -2
- package/dist/commands/instructions/status.js +13 -1
- package/dist/commands/labels/list.d.ts +24 -1
- package/dist/commands/labels/list.js +62 -19
- package/dist/commands/machines/dedicated/catalog.js +4 -15
- package/dist/commands/machines/dedicated/create.d.ts +8 -0
- package/dist/commands/machines/dedicated/create.js +58 -1
- package/dist/commands/machines/dedicated/destroy.js +18 -4
- package/dist/commands/machines/dedicated/list.js +9 -6
- package/dist/commands/machines/hosted/list.js +12 -0
- package/dist/commands/machines/list.js +11 -0
- package/dist/commands/machines/show.d.ts +1 -0
- package/dist/commands/machines/show.js +40 -11
- package/dist/commands/memory/governance/index.d.ts +21 -0
- package/dist/commands/memory/governance/index.js +64 -0
- package/dist/commands/memory/governance/set.d.ts +24 -0
- package/dist/commands/memory/governance/set.js +95 -0
- package/dist/commands/memory/provenance.d.ts +18 -0
- package/dist/commands/memory/provenance.js +66 -0
- package/dist/commands/profiles/list.d.ts +23 -0
- package/dist/commands/profiles/list.js +96 -0
- package/dist/commands/search/skills.d.ts +11 -1
- package/dist/commands/search/skills.js +26 -8
- package/dist/commands/skills/details.d.ts +2 -0
- package/dist/commands/skills/details.js +24 -1
- package/dist/commands/skills/import-as-actions.d.ts +32 -0
- package/dist/commands/skills/import-as-actions.js +175 -0
- package/dist/commands/skills/install.d.ts +2 -0
- package/dist/commands/skills/install.js +24 -1
- package/dist/commands/skills/invocable.js +6 -2
- package/dist/commands/skills/local.d.ts +40 -0
- package/dist/commands/skills/local.js +160 -0
- package/dist/commands/skills/search.d.ts +11 -1
- package/dist/commands/skills/search.js +29 -8
- package/dist/commands/spaces/actions/add.js +23 -5
- package/dist/commands/spaces/actions/available.js +3 -0
- package/dist/commands/spaces/actions/list.d.ts +5 -0
- package/dist/commands/spaces/actions/list.js +49 -3
- package/dist/commands/spaces/actions/run.d.ts +28 -0
- package/dist/commands/spaces/actions/run.js +146 -0
- package/dist/commands/spaces/actions/update.js +27 -5
- package/dist/commands/spaces/create.d.ts +3 -0
- package/dist/commands/spaces/create.js +32 -2
- package/dist/commands/spaces/label-summaries.d.ts +27 -0
- package/dist/commands/spaces/label-summaries.js +64 -0
- package/dist/commands/spaces/labels/add.js +19 -2
- package/dist/commands/spaces/labels/remove.js +22 -2
- package/dist/commands/spaces/show.js +2 -0
- package/dist/commands/spaces/task-rollups.d.ts +5 -0
- package/dist/commands/spaces/task-rollups.js +15 -4
- package/dist/commands/spaces/update.d.ts +5 -0
- package/dist/commands/spaces/update.js +41 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +105 -0
- package/dist/commands/tasks/actions/attach.js +32 -7
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +21 -1
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.js +34 -2
- package/dist/commands/tasks/events/append.js +29 -6
- package/dist/commands/tasks/expectations/assess.d.ts +12 -0
- package/dist/commands/tasks/expectations/assess.js +123 -14
- package/dist/commands/tasks/expectations.js +95 -17
- package/dist/commands/tasks/follow-up.js +2 -2
- package/dist/commands/tasks/labels/attach.js +20 -3
- package/dist/commands/tasks/labels/detach.js +21 -3
- package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/attach.js +47 -0
- package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/definitions.js +59 -0
- package/dist/commands/tasks/lifecycle/detach.d.ts +19 -0
- package/dist/commands/tasks/lifecycle/detach.js +72 -0
- package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
- package/dist/commands/tasks/lifecycle/history.js +38 -0
- package/dist/commands/tasks/lifecycle/migrate.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/migrate.js +68 -0
- package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
- package/dist/commands/tasks/lifecycle/reopen.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/reopen.js +71 -0
- package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/show.js +27 -0
- package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/start.js +30 -0
- package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/transition.js +109 -0
- package/dist/commands/tasks/list.js +16 -9
- package/dist/commands/tasks/move.d.ts +1 -0
- package/dist/commands/tasks/move.js +29 -0
- package/dist/commands/tasks/result/submit.js +11 -1
- package/dist/commands/tasks/review-queue.d.ts +44 -0
- package/dist/commands/tasks/review-queue.js +314 -0
- package/dist/commands/tasks/show.d.ts +11 -0
- package/dist/commands/tasks/show.js +139 -4
- package/dist/commands/tasks/trust.js +7 -2
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +83 -0
- package/dist/commands/tasks/updates/add.js +1 -1
- package/dist/commands/token/list.d.ts +22 -0
- package/dist/commands/token/list.js +68 -0
- package/dist/commands/token/revoke.d.ts +23 -0
- package/dist/commands/token/revoke.js +53 -0
- package/dist/lib/agent-actions.d.ts +92 -11
- package/dist/lib/agent-actions.js +171 -25
- package/dist/lib/agent-config.d.ts +11 -0
- package/dist/lib/agent-config.js +85 -3
- package/dist/lib/agent-pin-mute.d.ts +29 -0
- package/dist/lib/agent-pin-mute.js +30 -0
- package/dist/lib/agent-visual-refs.d.ts +33 -0
- package/dist/lib/agent-visual-refs.js +267 -0
- package/dist/lib/agentic-stream.d.ts +6 -0
- package/dist/lib/agentic-stream.js +34 -3
- package/dist/lib/assignee-resolver.d.ts +1 -1
- package/dist/lib/assignee-resolver.js +8 -0
- package/dist/lib/bulk-task-targets.d.ts +12 -0
- package/dist/lib/bulk-task-targets.js +34 -1
- package/dist/lib/cli-installers.d.ts +130 -0
- package/dist/lib/cli-installers.js +145 -0
- package/dist/lib/command-miss.js +55 -7
- package/dist/lib/dedicated-lease-command.d.ts +13 -0
- package/dist/lib/dedicated-lease-command.js +22 -1
- package/dist/lib/dedicated-machines.d.ts +95 -1
- package/dist/lib/dedicated-machines.js +236 -2
- package/dist/lib/failed-lookup.d.ts +3 -0
- package/dist/lib/failed-lookup.js +40 -0
- package/dist/lib/first-party-harness-agent.js +16 -2
- package/dist/lib/first-party-harness-doctor.d.ts +15 -0
- package/dist/lib/first-party-harness-doctor.js +126 -27
- package/dist/lib/followups.d.ts +115 -0
- package/dist/lib/followups.js +127 -0
- package/dist/lib/harnesses.d.ts +8 -0
- package/dist/lib/instruction-input.d.ts +19 -1
- package/dist/lib/instruction-input.js +52 -1
- package/dist/lib/label-ref.d.ts +95 -0
- package/dist/lib/label-ref.js +163 -0
- package/dist/lib/label-scope.d.ts +17 -2
- package/dist/lib/label-scope.js +27 -7
- package/dist/lib/local-skills.d.ts +98 -0
- package/dist/lib/local-skills.js +195 -0
- package/dist/lib/machines.d.ts +10 -10
- package/dist/lib/machines.js +23 -1
- package/dist/lib/search-query.d.ts +19 -0
- package/dist/lib/search-query.js +35 -0
- package/dist/lib/space-custom-actions.d.ts +72 -0
- package/dist/lib/space-custom-actions.js +117 -0
- package/dist/lib/space-resolver.d.ts +1 -21
- package/dist/lib/space-resolver.js +19 -10
- package/dist/lib/task-closure.d.ts +33 -0
- package/dist/lib/task-closure.js +104 -0
- package/dist/lib/task-lifecycle-output.d.ts +14 -0
- package/dist/lib/task-lifecycle-output.js +209 -0
- package/dist/lib/task-ref-resolver.d.ts +1 -17
- package/dist/lib/task-ref-resolver.js +18 -8
- package/dist/lib/tasks.d.ts +3 -0
- package/dist/lib/tasks.js +40 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5559 -4897
- package/oclif.manifest.json +33890 -28690
- package/package.json +24 -6
package/README.md
CHANGED
|
@@ -839,8 +839,10 @@ cat space.json | sky spaces create --from-json -
|
|
|
839
839
|
sky spaces create --from-json template.json --title "Override title"
|
|
840
840
|
```
|
|
841
841
|
|
|
842
|
-
Flags: `--title`, `--description`, `--status`, `--color`, `--
|
|
843
|
-
`--
|
|
842
|
+
Flags: `--title`, `--description`, `--status`, `--color`, `--icon`,
|
|
843
|
+
`--icon-color`, `--lead-agent`, `--team`, `--target-date`, `--goal`,
|
|
844
|
+
`--label`, `--group-chat`, `--parent`, `--no-inherit-access`,
|
|
845
|
+
`--from-json <file|->`, `--json`.
|
|
844
846
|
|
|
845
847
|
### `sky spaces update <id>`
|
|
846
848
|
|
|
@@ -852,8 +854,19 @@ sky spaces update <space-id> --status active --color "#4f46e5"
|
|
|
852
854
|
sky spaces update <space-id> --from-json patch.json
|
|
853
855
|
```
|
|
854
856
|
|
|
855
|
-
Flags: `--title`, `--description`, `--status`, `--color`, `--
|
|
856
|
-
`--
|
|
857
|
+
Flags: `--title`, `--description`, `--status`, `--color`, `--icon`,
|
|
858
|
+
`--icon-color`, `--lead-agent`, `--target-date`, `--goal`,
|
|
859
|
+
`--no-inherit-access`, `--estimate-scale`, `--estimate-migration`,
|
|
860
|
+
`--default-estimate`, `--no-use-default-estimate`, `--default-expect`,
|
|
861
|
+
`--delivery-mode`, `--integration-branch`, `--auto-merge-tier`,
|
|
862
|
+
`--worktree-isolation`, `--no-auto-start-on-backlog-exit`,
|
|
863
|
+
`--triage-external-intake`, `--default-task-template`,
|
|
864
|
+
`--from-json <file|->`, `--json`.
|
|
865
|
+
|
|
866
|
+
Nullable fields accept `none` (or `null`) to clear: `--icon none` restores
|
|
867
|
+
the default folder, `--icon-color none` the neutral icon color,
|
|
868
|
+
`--lead-agent none` removes the Leader, `--target-date none` clears the
|
|
869
|
+
date, and `--default-task-template none` removes the default template.
|
|
857
870
|
|
|
858
871
|
### `sky spaces delete <id>`
|
|
859
872
|
|
package/bin/dev-fallback.js
CHANGED
|
@@ -48,6 +48,116 @@ function sourceTreeDigest(fileSystem, sourceRoot) {
|
|
|
48
48
|
return hash.digest('hex');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Every relative specifier a source imports, re-exports, or dynamically loads.
|
|
53
|
+
*
|
|
54
|
+
* Deliberately a scan rather than a parse: this runs before the CLI starts, so
|
|
55
|
+
* it may not cost a TypeScript program, and over-collecting is harmless — an
|
|
56
|
+
* extra file in the closure can only make the guard more conservative, never
|
|
57
|
+
* less.
|
|
58
|
+
*/
|
|
59
|
+
function relativeSpecifiers(text) {
|
|
60
|
+
const found = [];
|
|
61
|
+
const patterns = [
|
|
62
|
+
/(?:^|[\s;}])(?:import|export)[\s\S]{0,400}?from\s*['"](\.[^'"]*)['"]/g,
|
|
63
|
+
/\bimport\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g,
|
|
64
|
+
/\brequire\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g,
|
|
65
|
+
/(?:^|[\s;}])import\s+['"](\.[^'"]*)['"]/g,
|
|
66
|
+
];
|
|
67
|
+
for (const pattern of patterns) {
|
|
68
|
+
let match;
|
|
69
|
+
while ((match = pattern.exec(text)) !== null) found.push(match[1]);
|
|
70
|
+
}
|
|
71
|
+
return found;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Resolve a relative specifier the way tsc does, extensionless first. */
|
|
75
|
+
function resolveSourceSpecifier(fileSystem, fromDirectory, specifier) {
|
|
76
|
+
const base = path.resolve(fromDirectory, specifier);
|
|
77
|
+
const candidates = [
|
|
78
|
+
base,
|
|
79
|
+
`${base}.ts`,
|
|
80
|
+
`${base}.tsx`,
|
|
81
|
+
`${base}.json`,
|
|
82
|
+
path.join(base, 'index.ts'),
|
|
83
|
+
path.join(base, 'index.tsx'),
|
|
84
|
+
];
|
|
85
|
+
for (const candidate of candidates) {
|
|
86
|
+
try {
|
|
87
|
+
if (fileSystem.statSync(candidate).isFile()) return candidate;
|
|
88
|
+
} catch {
|
|
89
|
+
// try the next shape
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The digest of everything a single command is compiled FROM: its own source
|
|
97
|
+
* plus the transitive closure of the relative imports it reaches.
|
|
98
|
+
*
|
|
99
|
+
* This replaces a digest over the whole of `src` as the freshness test for one
|
|
100
|
+
* command, and the difference is not an optimisation — it is the difference
|
|
101
|
+
* between a true statement and a false one. The whole-tree digest answers "has
|
|
102
|
+
* anything in the CLI changed", and that was used to answer "is THIS command's
|
|
103
|
+
* build current". In a checkout where another session is editing a different
|
|
104
|
+
* command — routine here, see root CLAUDE.md on ~35 worktrees sharing one
|
|
105
|
+
* checkout — those answers disagree constantly, and the launcher then refuses a
|
|
106
|
+
* command whose own build it can prove is byte-current, or silently delegates it
|
|
107
|
+
* to whatever older CLI is on PATH. A dogfood run spent its first twenty minutes
|
|
108
|
+
* concluding that a shipped feature had not shipped, because the commands under
|
|
109
|
+
* test were being answered by a build that predated them.
|
|
110
|
+
*
|
|
111
|
+
* Commands do import other commands (`tasks update` imports `tasks create`), so
|
|
112
|
+
* the closure is walked rather than assuming command sources are independent —
|
|
113
|
+
* that assumption is false here, and a guard built on it would call a genuinely
|
|
114
|
+
* stale command fresh, which is the failure worth avoiding.
|
|
115
|
+
*
|
|
116
|
+
* An unresolvable specifier is hashed as its own text. The build script and this
|
|
117
|
+
* launcher run this same function, so they agree on that value; and a specifier
|
|
118
|
+
* that starts resolving later changes the digest, which is the correct verdict.
|
|
119
|
+
*/
|
|
120
|
+
function commandClosureDigest(fileSystem, sourceRoot, entrySource) {
|
|
121
|
+
const seen = new Set();
|
|
122
|
+
const unresolved = [];
|
|
123
|
+
const pending = [path.resolve(entrySource)];
|
|
124
|
+
while (pending.length) {
|
|
125
|
+
const current = pending.pop();
|
|
126
|
+
if (seen.has(current)) continue;
|
|
127
|
+
seen.add(current);
|
|
128
|
+
let text;
|
|
129
|
+
try {
|
|
130
|
+
text = fileSystem.readFileSync(current, 'utf8');
|
|
131
|
+
} catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
for (const specifier of relativeSpecifiers(text)) {
|
|
135
|
+
const resolved = resolveSourceSpecifier(fileSystem, path.dirname(current), specifier);
|
|
136
|
+
if (resolved) {
|
|
137
|
+
if (!seen.has(resolved)) pending.push(resolved);
|
|
138
|
+
} else {
|
|
139
|
+
unresolved.push(`${path.relative(sourceRoot, current)}:${specifier}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const hash = crypto.createHash('sha256');
|
|
144
|
+
for (const file of [...seen].sort()) {
|
|
145
|
+
hash.update(path.relative(sourceRoot, file).split(path.sep).join('/'));
|
|
146
|
+
hash.update('\0');
|
|
147
|
+
try {
|
|
148
|
+
hash.update(fileSystem.readFileSync(file));
|
|
149
|
+
} catch {
|
|
150
|
+
hash.update('<unreadable>');
|
|
151
|
+
}
|
|
152
|
+
hash.update('\0');
|
|
153
|
+
}
|
|
154
|
+
for (const miss of unresolved.sort()) {
|
|
155
|
+
hash.update(miss.split(path.sep).join('/'));
|
|
156
|
+
hash.update('\0');
|
|
157
|
+
}
|
|
158
|
+
return hash.digest('hex');
|
|
159
|
+
}
|
|
160
|
+
|
|
51
161
|
function findAlternateCli({
|
|
52
162
|
commandName,
|
|
53
163
|
currentEntry,
|
|
@@ -143,9 +253,17 @@ function missingLocalCommandBuild({ cliRoot, argv, fileSystem = fs, verifySource
|
|
|
143
253
|
} catch {
|
|
144
254
|
commandBuildManifest = null;
|
|
145
255
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
256
|
+
// Lazily, because the closure test below almost always settles the question
|
|
257
|
+
// first and this one reads every `.ts` under `src` — 1,300 files here, on a
|
|
258
|
+
// path that runs before any command starts.
|
|
259
|
+
let sourceTreeDigestCache;
|
|
260
|
+
const currentSourceTreeDigest = () => {
|
|
261
|
+
if (!commandBuildManifest) return null;
|
|
262
|
+
if (sourceTreeDigestCache === undefined) {
|
|
263
|
+
sourceTreeDigestCache = sourceTreeDigest(fileSystem, path.join(cliRoot, 'src'));
|
|
264
|
+
}
|
|
265
|
+
return sourceTreeDigestCache;
|
|
266
|
+
};
|
|
149
267
|
const commandParts = [];
|
|
150
268
|
for (const value of argv) {
|
|
151
269
|
if (String(value).startsWith('-')) break;
|
|
@@ -165,11 +283,26 @@ function missingLocalCommandBuild({ cliRoot, argv, fileSystem = fs, verifySource
|
|
|
165
283
|
if (!verifySourceIdentity) return null;
|
|
166
284
|
try {
|
|
167
285
|
const relative = path.relative(sourceCommandsDirectory, source).split(path.sep).join('/');
|
|
286
|
+
// What this command is actually compiled from: its own source plus the
|
|
287
|
+
// transitive closure of its relative imports. Scoped to the command
|
|
288
|
+
// because a change to an unrelated one cannot reach it, and walked rather
|
|
289
|
+
// than assumed because commands here do import each other.
|
|
290
|
+
const builtClosure = commandBuildManifest?.closures?.[relative];
|
|
291
|
+
if (typeof builtClosure === 'string') {
|
|
292
|
+
return builtClosure === commandClosureDigest(fileSystem, path.join(cliRoot, 'src'), source)
|
|
293
|
+
? null
|
|
294
|
+
: compiled;
|
|
295
|
+
}
|
|
168
296
|
const builtDigest = commandBuildManifest?.commands?.[relative];
|
|
297
|
+
// A manifest written before closures existed. Fall back to the old, wider
|
|
298
|
+
// test rather than trusting a per-file digest that cannot see an edited
|
|
299
|
+
// import — an over-cautious verdict is recoverable, a wrong "fresh" is
|
|
300
|
+
// what this launcher exists to prevent.
|
|
301
|
+
//
|
|
169
302
|
// Git checkouts and partial builds can make old JS newer than its source.
|
|
170
303
|
// Content identity is authoritative; no digest means the development
|
|
171
304
|
// build is unproved and the installed CLI is safer.
|
|
172
|
-
return commandBuildManifest?.sourceTreeDigest === currentSourceTreeDigest &&
|
|
305
|
+
return commandBuildManifest?.sourceTreeDigest === currentSourceTreeDigest() &&
|
|
173
306
|
typeof builtDigest === 'string' &&
|
|
174
307
|
builtDigest === sourceDigest(fileSystem, source)
|
|
175
308
|
? null
|
|
@@ -188,6 +321,35 @@ function missingLocalCommandBuild({ cliRoot, argv, fileSystem = fs, verifySource
|
|
|
188
321
|
if (incomplete) return incomplete;
|
|
189
322
|
break;
|
|
190
323
|
}
|
|
324
|
+
/*
|
|
325
|
+
* `--version` must report the binary that will actually RUN.
|
|
326
|
+
*
|
|
327
|
+
* It names no command, so the loop above never ran and this returned null —
|
|
328
|
+
* meaning `skrr --version` answered from the local checkout while every real
|
|
329
|
+
* command silently delegated to a different build. Someone verifying a change
|
|
330
|
+
* saw the version they expected and tested code they had not written, which is
|
|
331
|
+
* the precise failure this launcher exists to prevent, wearing a reassuring
|
|
332
|
+
* number.
|
|
333
|
+
*
|
|
334
|
+
* The whole-tree digest is the right test here: a stale tree means SOME
|
|
335
|
+
* command would fall back, so the version the user is about to rely on is not
|
|
336
|
+
* this one.
|
|
337
|
+
*/
|
|
338
|
+
if (argv.some((value) => value === '--version' || value === '-v')) {
|
|
339
|
+
// A STALE tree and a MISSING build are the same answer to the user's
|
|
340
|
+
// question. The digest comparison covers the first and skipped the second,
|
|
341
|
+
// because a wiped or half-written `dist` has no manifest to compare — so
|
|
342
|
+
// `--version` still answered from the checkout while every command fell
|
|
343
|
+
// back. Observed twice in one dogfood session, both times right after a
|
|
344
|
+
// rebuild left `dist` incomplete.
|
|
345
|
+
if (verifySourceIdentity && !commandBuildManifest) return commandsDirectory;
|
|
346
|
+
if (
|
|
347
|
+
verifySourceIdentity &&
|
|
348
|
+
commandBuildManifest.sourceTreeDigest !== currentSourceTreeDigest()
|
|
349
|
+
) {
|
|
350
|
+
return commandsDirectory;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
191
353
|
if (argv.some((value) => value === '--help' || value === '-h')) {
|
|
192
354
|
const sourceDirectory = path.join(sourceCommandsDirectory, ...commandParts);
|
|
193
355
|
const pending = [sourceDirectory];
|
|
@@ -215,6 +377,7 @@ function missingLocalCommandBuild({ cliRoot, argv, fileSystem = fs, verifySource
|
|
|
215
377
|
|
|
216
378
|
module.exports = {
|
|
217
379
|
COMMAND_BUILD_MANIFEST,
|
|
380
|
+
commandClosureDigest,
|
|
218
381
|
findAlternateCli,
|
|
219
382
|
missingLocalCommandBuild,
|
|
220
383
|
sourceTreeDigest,
|
package/dist/base-command.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.isTypedServerRefusal = isTypedServerRefusal;
|
|
|
16
16
|
exports.isRetryableFailure = isRetryableFailure;
|
|
17
17
|
const core_1 = require("@oclif/core");
|
|
18
18
|
Object.defineProperty(exports, "Flags", { enumerable: true, get: function () { return core_1.Flags; } });
|
|
19
|
+
const failed_lookup_1 = require("./lib/failed-lookup");
|
|
19
20
|
// Re-exported from its home in `lib/keychain`, beside the other profile
|
|
20
21
|
// functions. It lived here while `init()` was its only caller; a lib module
|
|
21
22
|
// needing it would otherwise have to import the command base class, and with
|
|
@@ -112,7 +113,8 @@ class BaseCommand extends core_1.Command {
|
|
|
112
113
|
}),
|
|
113
114
|
profile: core_1.Flags.string({
|
|
114
115
|
description: 'Which stored session to use. Each profile keeps its own credential and deployment, ' +
|
|
115
|
-
'so signing into one does not sign you out of another. Also OVERSKY_PROFILE.'
|
|
116
|
+
'so signing into one does not sign you out of another. Also OVERSKY_PROFILE. ' +
|
|
117
|
+
'List them with `profiles list`.',
|
|
116
118
|
}),
|
|
117
119
|
};
|
|
118
120
|
cliConfig;
|
|
@@ -391,6 +393,14 @@ class BaseCommand extends core_1.Command {
|
|
|
391
393
|
// UUID, so refs go through the same exact-match resolution as titles.
|
|
392
394
|
if (!query || (0, space_resolver_1.looksLikeCanonicalSpaceId)(query))
|
|
393
395
|
return query;
|
|
396
|
+
if ((0, failed_lookup_1.isFailedLookupValue)(query)) {
|
|
397
|
+
this.failWithCliError({
|
|
398
|
+
message: (0, failed_lookup_1.describeFailedLookupValue)(query, 'Space'),
|
|
399
|
+
code: space_resolver_1.SPACE_CLI_ERROR_CODE.NOT_A_REFERENCE,
|
|
400
|
+
exit: 2,
|
|
401
|
+
retryable: false,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
394
404
|
const normalizedQuery = (0, space_resolver_1.normalizeSpaceRef)(query);
|
|
395
405
|
const load = async (includeArchived) => {
|
|
396
406
|
let response;
|
|
@@ -489,6 +499,16 @@ class BaseCommand extends core_1.Command {
|
|
|
489
499
|
const query = value.trim();
|
|
490
500
|
if (!query)
|
|
491
501
|
return query;
|
|
502
|
+
// Before the search, not after it: `null` from a failed `jq -r` must never
|
|
503
|
+
// reach the title tiers, and it should not cost a request to say so.
|
|
504
|
+
if ((0, failed_lookup_1.isFailedLookupValue)(query)) {
|
|
505
|
+
this.failWithCliError({
|
|
506
|
+
message: (0, failed_lookup_1.describeFailedLookupValue)(query, 'task'),
|
|
507
|
+
code: task_ref_resolver_1.TASK_REF_CLI_ERROR_CODE.NOT_A_REFERENCE,
|
|
508
|
+
exit: 2,
|
|
509
|
+
retryable: false,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
492
512
|
let response;
|
|
493
513
|
try {
|
|
494
514
|
response = await data_provider_1.dataService.listTasks({ q: query, limit: 50 });
|
|
@@ -690,6 +710,7 @@ class BaseCommand extends core_1.Command {
|
|
|
690
710
|
AMBIGUOUS: 'ASSIGNEE_AMBIGUOUS',
|
|
691
711
|
NO_SPACE: 'ASSIGNEE_NO_SPACE_CONTEXT',
|
|
692
712
|
NOT_FOUND: 'ASSIGNEE_NOT_FOUND',
|
|
713
|
+
NOT_A_REFERENCE: 'ASSIGNEE_NOT_A_REFERENCE',
|
|
693
714
|
};
|
|
694
715
|
this.failWithCliError({
|
|
695
716
|
message: outcome.failures
|
|
@@ -1231,7 +1252,21 @@ class BaseCommand extends core_1.Command {
|
|
|
1231
1252
|
//
|
|
1232
1253
|
// Field-level validation is appended for the same reason: the server names
|
|
1233
1254
|
// the offending field and only `--json` callers could read it.
|
|
1234
|
-
|
|
1255
|
+
//
|
|
1256
|
+
// And the REMEDY, when the message does not already carry one. This CLI's
|
|
1257
|
+
// convention is a `→` remedy line inside the message (103 sites), with
|
|
1258
|
+
// `details.suggestion` as its machine-readable twin for `--json`. Where a
|
|
1259
|
+
// call site wrote the remedy ONLY into `details.suggestion`, it reached
|
|
1260
|
+
// `--json` alone, and a person at a terminal was told what was wrong and
|
|
1261
|
+
// never what to do — `followups list` without an agent, OSK-9670. oclif
|
|
1262
|
+
// renders `suggestions` as its own "Try this:" block. Skipped when the
|
|
1263
|
+
// message opens a `→` line, so those do not print the remedy twice.
|
|
1264
|
+
const suggestion = hasRemedyLine(message) ? undefined : authoredSuggestion(details);
|
|
1265
|
+
this.error(`${message}${formatValidationIssues(details)}`, {
|
|
1266
|
+
exit,
|
|
1267
|
+
code,
|
|
1268
|
+
...(suggestion ? { suggestions: [suggestion] } : {}),
|
|
1269
|
+
});
|
|
1235
1270
|
}
|
|
1236
1271
|
writeJsonCliError({ message, code, status, exit, retryable, details, }) {
|
|
1237
1272
|
this.log(JSON.stringify({
|
|
@@ -1612,6 +1647,15 @@ function isRetryableFailure(status, body) {
|
|
|
1612
1647
|
return false;
|
|
1613
1648
|
return status === 408 || status === 425 || status === 429 || !!(status && status >= 500);
|
|
1614
1649
|
}
|
|
1650
|
+
/** True when a message already carries this CLI's `→` remedy line. */
|
|
1651
|
+
function hasRemedyLine(message) {
|
|
1652
|
+
return /^\s*→/m.test(message);
|
|
1653
|
+
}
|
|
1654
|
+
/** The remedy a call site wrote into `details.suggestion`, if it wrote one. */
|
|
1655
|
+
function authoredSuggestion(details) {
|
|
1656
|
+
const suggestion = details?.suggestion;
|
|
1657
|
+
return typeof suggestion === 'string' && suggestion.trim() ? suggestion.trim() : undefined;
|
|
1658
|
+
}
|
|
1615
1659
|
/**
|
|
1616
1660
|
* Render server-supplied field validation into the human error.
|
|
1617
1661
|
*
|
|
@@ -18,6 +18,11 @@ export default class AgentsActionsCreate extends BaseCommand {
|
|
|
18
18
|
embeds: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
19
|
order: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
20
|
enabled: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
scope: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
|
+
space: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
'space-title': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
label: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
outcome: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
26
|
};
|
|
22
27
|
run(): Promise<void>;
|
|
23
28
|
}
|
|
@@ -39,6 +39,20 @@ class AgentsActionsCreate extends base_command_1.BaseCommand {
|
|
|
39
39
|
embeds: core_1.Flags.string({ description: 'Embedded built-in actions JSON array' }),
|
|
40
40
|
order: core_1.Flags.integer({ description: 'Display order (defaults to end of list)' }),
|
|
41
41
|
enabled: core_1.Flags.boolean({ description: 'Create enabled or disabled', allowNo: true }),
|
|
42
|
+
scope: core_1.Flags.string({
|
|
43
|
+
description: 'Where the action is offered. Implied by --space / --label; pass "general" to offer it everywhere.',
|
|
44
|
+
options: [...agent_actions_1.AGENT_ACTION_SCOPE_CHOICES],
|
|
45
|
+
}),
|
|
46
|
+
space: core_1.Flags.string({ description: 'Offer only in this space (implies --scope space)' }),
|
|
47
|
+
'space-title': core_1.Flags.string({ description: 'Denormalized space title for the scope chip' }),
|
|
48
|
+
label: core_1.Flags.string({
|
|
49
|
+
description: 'Offer in every space carrying this Label — a Label id or name from `labels list` (repeatable, any-of; implies --scope label). Not button text: that is `spaces actions add --label`.',
|
|
50
|
+
multiple: true,
|
|
51
|
+
}),
|
|
52
|
+
outcome: core_1.Flags.string({
|
|
53
|
+
description: "What a run leaves behind: 'ephemeral' hides the run's task once it answers, 'durable' keeps it on the board. Default ephemeral.",
|
|
54
|
+
options: [...agent_actions_1.AGENT_ACTION_OUTCOME_CHOICES],
|
|
55
|
+
}),
|
|
42
56
|
};
|
|
43
57
|
async run() {
|
|
44
58
|
this.requireAuth();
|
|
@@ -54,27 +68,40 @@ class AgentsActionsCreate extends base_command_1.BaseCommand {
|
|
|
54
68
|
config: (0, agent_actions_1.parseJsonObjectFlag)(flags.config, '--config'),
|
|
55
69
|
order: flags.order,
|
|
56
70
|
enabled: flags.enabled,
|
|
71
|
+
// Flags win over --from-json, and a JSON body may still carry these
|
|
72
|
+
// directly. Both paths land on the same two fields below.
|
|
73
|
+
scope: await (0, agent_actions_1.resolveAgentActionScopeFlags)(flags),
|
|
74
|
+
outcome: flags.outcome,
|
|
57
75
|
});
|
|
58
76
|
}
|
|
59
77
|
catch (err) {
|
|
60
78
|
this.error(err.message, { exit: 1 });
|
|
61
79
|
}
|
|
62
80
|
let created;
|
|
81
|
+
let replayed = false;
|
|
63
82
|
try {
|
|
64
|
-
const agent = await (0, agent_actions_1.fetchAgentForActionEdit)(args.agentId);
|
|
65
|
-
const actions = (0, agent_actions_1.getAgentActions)(agent);
|
|
66
83
|
const title = typeof body.title === 'string' ? body.title.trim() : '';
|
|
67
84
|
if (!title)
|
|
68
85
|
this.error('Action title is required. Pass --title or include title.', { exit: 1 });
|
|
69
86
|
const kind = body.kind === 'builtin' ? 'builtin' : 'prompt';
|
|
70
|
-
|
|
87
|
+
// No read of the library: position is assigned by the server at the
|
|
88
|
+
// moment of the append, so it cannot be computed from a stale copy. An
|
|
89
|
+
// explicit --order is still honoured.
|
|
90
|
+
const explicitOrder = typeof body.order === 'number' ? body.order : undefined;
|
|
91
|
+
const order = explicitOrder ?? 0;
|
|
71
92
|
const enabled = typeof body.enabled === 'boolean' ? body.enabled : true;
|
|
93
|
+
const scope = body.scope;
|
|
94
|
+
const outcome = body.outcome === 'durable' || body.outcome === 'ephemeral'
|
|
95
|
+
? body.outcome
|
|
96
|
+
: undefined;
|
|
72
97
|
if (kind === 'builtin') {
|
|
73
98
|
const builtinType = body.builtinType;
|
|
74
99
|
if (!agent_actions_1.BUILTIN_ACTION_TYPES.includes(builtinType)) {
|
|
75
100
|
this.error(`--builtin-type is required for built-in actions.`, { exit: 1 });
|
|
76
101
|
}
|
|
77
102
|
created = (0, agent_actions_1.makeBuiltinAction)({
|
|
103
|
+
scope,
|
|
104
|
+
outcome,
|
|
78
105
|
title,
|
|
79
106
|
description: typeof body.description === 'string' ? body.description : undefined,
|
|
80
107
|
builtinType: builtinType,
|
|
@@ -104,6 +131,8 @@ class AgentsActionsCreate extends base_command_1.BaseCommand {
|
|
|
104
131
|
this.error(err.message, { exit: 1 });
|
|
105
132
|
}
|
|
106
133
|
created = (0, agent_actions_1.makePromptAction)({
|
|
134
|
+
scope,
|
|
135
|
+
outcome,
|
|
107
136
|
title,
|
|
108
137
|
description: typeof body.description === 'string' ? body.description : undefined,
|
|
109
138
|
prompt,
|
|
@@ -114,7 +143,13 @@ class AgentsActionsCreate extends base_command_1.BaseCommand {
|
|
|
114
143
|
sourceListingId: typeof body.sourceListingId === 'string' ? body.sourceListingId : undefined,
|
|
115
144
|
});
|
|
116
145
|
}
|
|
117
|
-
|
|
146
|
+
if (explicitOrder === undefined) {
|
|
147
|
+
delete created.order;
|
|
148
|
+
}
|
|
149
|
+
const appended = await (0, agent_actions_1.appendAgentAction)(args.agentId, created);
|
|
150
|
+
// Report what the server stored, not what we sent.
|
|
151
|
+
created = appended.action;
|
|
152
|
+
replayed = !appended.created;
|
|
118
153
|
}
|
|
119
154
|
catch (err) {
|
|
120
155
|
this.handleApiError(err);
|
|
@@ -123,7 +158,9 @@ class AgentsActionsCreate extends base_command_1.BaseCommand {
|
|
|
123
158
|
this.log(JSON.stringify(created, null, 2));
|
|
124
159
|
return;
|
|
125
160
|
}
|
|
126
|
-
this.log(
|
|
161
|
+
this.log(replayed
|
|
162
|
+
? `Action ${created.id} was already on agent ${args.agentId} (nothing added):`
|
|
163
|
+
: `Created action on agent ${args.agentId}:`);
|
|
127
164
|
(0, agent_actions_1.renderAction)(created, (line) => this.log(line));
|
|
128
165
|
}
|
|
129
166
|
}
|
|
@@ -16,6 +16,9 @@ class AgentsActionsDelete extends base_command_1.BaseCommand {
|
|
|
16
16
|
};
|
|
17
17
|
static flags = {
|
|
18
18
|
yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation prompt' }),
|
|
19
|
+
// The only sibling (create, update, list, show) without --json, so a script
|
|
20
|
+
// driving the five broke on the fifth.
|
|
21
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
19
22
|
};
|
|
20
23
|
async run() {
|
|
21
24
|
this.requireAuth();
|
|
@@ -37,6 +40,10 @@ class AgentsActionsDelete extends base_command_1.BaseCommand {
|
|
|
37
40
|
catch (err) {
|
|
38
41
|
this.handleApiError(err);
|
|
39
42
|
}
|
|
43
|
+
if (flags.json) {
|
|
44
|
+
this.log(JSON.stringify({ deleted: true, agentId: args.agentId, actionId: args.actionId }, null, 2));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
40
47
|
this.log(`Deleted action ${args.actionId} from agent ${args.agentId}.`);
|
|
41
48
|
}
|
|
42
49
|
}
|
|
@@ -17,6 +17,11 @@ export default class AgentsActionsUpdate extends BaseCommand {
|
|
|
17
17
|
'replace-config': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
18
18
|
order: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
19
|
enabled: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
scope: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
space: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
|
+
'space-title': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
label: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
outcome: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
25
|
};
|
|
21
26
|
run(): Promise<void>;
|
|
22
27
|
}
|
|
@@ -35,6 +35,20 @@ class AgentsActionsUpdate extends base_command_1.BaseCommand {
|
|
|
35
35
|
}),
|
|
36
36
|
order: core_1.Flags.integer({ description: 'Display order' }),
|
|
37
37
|
enabled: core_1.Flags.boolean({ description: 'Enable or disable the action', allowNo: true }),
|
|
38
|
+
scope: core_1.Flags.string({
|
|
39
|
+
description: 'Where the action is offered. Implied by --space / --label; pass "general" to offer it everywhere.',
|
|
40
|
+
options: [...agent_actions_1.AGENT_ACTION_SCOPE_CHOICES],
|
|
41
|
+
}),
|
|
42
|
+
space: core_1.Flags.string({ description: 'Offer only in this space (implies --scope space)' }),
|
|
43
|
+
'space-title': core_1.Flags.string({ description: 'Denormalized space title for the scope chip' }),
|
|
44
|
+
label: core_1.Flags.string({
|
|
45
|
+
description: 'Offer in every space carrying this Label — a Label id or name from `labels list` (repeatable, any-of; implies --scope label). Not button text: that is `spaces actions add --label`.',
|
|
46
|
+
multiple: true,
|
|
47
|
+
}),
|
|
48
|
+
outcome: core_1.Flags.string({
|
|
49
|
+
description: "What a run leaves behind: 'ephemeral' hides the run's task once it answers, 'durable' keeps it on the board.",
|
|
50
|
+
options: [...agent_actions_1.AGENT_ACTION_OUTCOME_CHOICES],
|
|
51
|
+
}),
|
|
38
52
|
};
|
|
39
53
|
async run() {
|
|
40
54
|
this.requireAuth();
|
|
@@ -49,6 +63,8 @@ class AgentsActionsUpdate extends base_command_1.BaseCommand {
|
|
|
49
63
|
config: (0, agent_actions_1.parseJsonObjectFlag)(flags.config, '--config'),
|
|
50
64
|
order: flags.order,
|
|
51
65
|
enabled: flags.enabled,
|
|
66
|
+
scope: await (0, agent_actions_1.resolveAgentActionScopeFlags)(flags),
|
|
67
|
+
outcome: flags.outcome,
|
|
52
68
|
});
|
|
53
69
|
}
|
|
54
70
|
catch (err) {
|
|
@@ -76,6 +92,14 @@ class AgentsActionsUpdate extends base_command_1.BaseCommand {
|
|
|
76
92
|
next.order = patch.order;
|
|
77
93
|
if (typeof patch.enabled === 'boolean')
|
|
78
94
|
next.enabled = patch.enabled;
|
|
95
|
+
// A scope is replaced wholesale, never merged: `{kind:'space'}` and
|
|
96
|
+
// `{kind:'label'}` carry disjoint fields, so a shallow merge would leave
|
|
97
|
+
// a `labelIds` behind on a space scope and produce a shape the write gate
|
|
98
|
+
// rejects. Absent means "leave the existing scope alone".
|
|
99
|
+
if (patch.scope !== undefined)
|
|
100
|
+
next.scope = patch.scope;
|
|
101
|
+
if (patch.outcome !== undefined)
|
|
102
|
+
next.outcome = patch.outcome;
|
|
79
103
|
if (current.kind === 'builtin') {
|
|
80
104
|
const builtin = next;
|
|
81
105
|
if (patch.builtinType !== undefined) {
|
|
@@ -101,7 +125,9 @@ class AgentsActionsUpdate extends base_command_1.BaseCommand {
|
|
|
101
125
|
}
|
|
102
126
|
actions[index] = next;
|
|
103
127
|
updated = next;
|
|
104
|
-
await (0, agent_actions_1.updateAgentActions)(args.agentId, actions);
|
|
128
|
+
const savedAgent = await (0, agent_actions_1.updateAgentActions)(args.agentId, actions);
|
|
129
|
+
// Report what the server stored, not what we sent — see storedActionOrLocal.
|
|
130
|
+
updated = (0, agent_actions_1.storedActionOrLocal)(savedAgent, updated);
|
|
105
131
|
}
|
|
106
132
|
catch (err) {
|
|
107
133
|
this.handleApiError(err);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Attach (or re-attach) an OpenAPI document to an agent as a tool surface.
|
|
4
|
+
*
|
|
5
|
+
* The derivation is the SAME code the web builder runs —
|
|
6
|
+
* `validateAndParseOpenAPISpec` then `openapiToFunction`, both from
|
|
7
|
+
* `@skrr-ai/data-provider`. That matters more than it looks: the server stores
|
|
8
|
+
* `functions` verbatim and never re-reads the spec, so a CLI that derived them
|
|
9
|
+
* its own way would produce actions subtly unlike the ones the web produces from
|
|
10
|
+
* the same document, and the difference would only show up at call time.
|
|
11
|
+
*
|
|
12
|
+
* The spec is validated LOCALLY before anything is sent, because the endpoint's
|
|
13
|
+
* failure for a malformed document is `400 No functions provided` — true, and
|
|
14
|
+
* useless for finding the line that is wrong.
|
|
15
|
+
*/
|
|
16
|
+
export default class AgentsApiActionsAdd extends BaseCommand {
|
|
17
|
+
static description: string;
|
|
18
|
+
static examples: string[];
|
|
19
|
+
static args: {
|
|
20
|
+
agentId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
21
|
+
};
|
|
22
|
+
static flags: {
|
|
23
|
+
spec: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
'action-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
auth: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
'api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
|
+
'authorization-type': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
|
+
'custom-auth-header': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
'oauth-client-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
|
+
'oauth-client-secret': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
|
+
'oauth-authorization-url': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
32
|
+
'oauth-client-url': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
33
|
+
'oauth-scope': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
34
|
+
'oauth-token-exchange-method': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
36
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
37
|
+
};
|
|
38
|
+
private readSpec;
|
|
39
|
+
private buildAuth;
|
|
40
|
+
run(): Promise<void>;
|
|
41
|
+
}
|