@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
|
@@ -1,2 +1,13 @@
|
|
|
1
|
+
export declare const COMMITMENT_RESPONSIBILITY_LEVELS: readonly ["reasoning_only", "full_ownership"];
|
|
2
|
+
export declare const REASONING_TOOL_ESCAPES: readonly ["bash", "browser"];
|
|
3
|
+
export declare const RELEASE_INSTALL_CHANNELS: readonly ["latest", "manual"];
|
|
4
|
+
/**
|
|
5
|
+
* `09:00-18:00` or `09:00-18:00@America/Los_Angeles`, or a JSON object.
|
|
6
|
+
*
|
|
7
|
+
* The stored shape is `{start, end, timezone}` with `start`/`end` REQUIRED, so
|
|
8
|
+
* the shorthand always supplies both and never a half-open window the schema
|
|
9
|
+
* would reject at write time with a message about a subdocument.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseWorkingHoursFlag(value: string): Record<string, unknown>;
|
|
1
12
|
/** Apply the structured agent fields exposed by the web config editor. */
|
|
2
13
|
export declare function mergeAgentConfigFlags(body: Record<string, unknown>, flags: Record<string, unknown>): Record<string, unknown>;
|
package/dist/lib/agent-config.js
CHANGED
|
@@ -1,7 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RELEASE_INSTALL_CHANNELS = exports.REASONING_TOOL_ESCAPES = exports.COMMITMENT_RESPONSIBILITY_LEVELS = void 0;
|
|
4
|
+
exports.parseWorkingHoursFlag = parseWorkingHoursFlag;
|
|
3
5
|
exports.mergeAgentConfigFlags = mergeAgentConfigFlags;
|
|
4
6
|
const prompt_1 = require("./prompt");
|
|
7
|
+
const agent_visual_refs_1 = require("./agent-visual-refs");
|
|
8
|
+
exports.COMMITMENT_RESPONSIBILITY_LEVELS = ['reasoning_only', 'full_ownership'];
|
|
9
|
+
exports.REASONING_TOOL_ESCAPES = ['bash', 'browser'];
|
|
10
|
+
exports.RELEASE_INSTALL_CHANNELS = ['latest', 'manual'];
|
|
11
|
+
/**
|
|
12
|
+
* `09:00-18:00` or `09:00-18:00@America/Los_Angeles`, or a JSON object.
|
|
13
|
+
*
|
|
14
|
+
* The stored shape is `{start, end, timezone}` with `start`/`end` REQUIRED, so
|
|
15
|
+
* the shorthand always supplies both and never a half-open window the schema
|
|
16
|
+
* would reject at write time with a message about a subdocument.
|
|
17
|
+
*/
|
|
18
|
+
function parseWorkingHoursFlag(value) {
|
|
19
|
+
const trimmed = value.trim();
|
|
20
|
+
if (trimmed.startsWith('{'))
|
|
21
|
+
return JSON.parse(trimmed);
|
|
22
|
+
const [window, timezone] = trimmed.split('@');
|
|
23
|
+
const match = /^([0-2]\d:[0-5]\d)-([0-2]\d:[0-5]\d)$/.exec(window ?? '');
|
|
24
|
+
if (!match) {
|
|
25
|
+
throw new Error(`--todo-working-hours: cannot read "${value}". ` +
|
|
26
|
+
'Write HH:MM-HH:MM, optionally @<IANA timezone> — for example ' +
|
|
27
|
+
'09:00-18:00@America/Los_Angeles. A JSON object is also accepted.');
|
|
28
|
+
}
|
|
29
|
+
return timezone
|
|
30
|
+
? { start: match[1], end: match[2], timezone }
|
|
31
|
+
: { start: match[1], end: match[2] };
|
|
32
|
+
}
|
|
5
33
|
/** Apply the structured agent fields exposed by the web config editor. */
|
|
6
34
|
function mergeAgentConfigFlags(body, flags) {
|
|
7
35
|
const json = {
|
|
@@ -22,10 +50,21 @@ function mergeAgentConfigFlags(body, flags) {
|
|
|
22
50
|
if (value !== undefined)
|
|
23
51
|
parsed[field] = JSON.parse(String(value));
|
|
24
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* `avatar` and `sceneBackground` are DISCRIMINATED UNIONS server-side, not
|
|
55
|
+
* strings — see `agent-visual-refs.ts`. `--scene-background` used to sit in
|
|
56
|
+
* the pass-through map below, which made it a flag with no value that could
|
|
57
|
+
* pass validation. Both go through the shared parser.
|
|
58
|
+
*/
|
|
59
|
+
if (flags['scene-background'] !== undefined) {
|
|
60
|
+
parsed.sceneBackground = (0, agent_visual_refs_1.parseSceneBackgroundFlag)(String(flags['scene-background']));
|
|
61
|
+
}
|
|
62
|
+
if (flags.avatar !== undefined) {
|
|
63
|
+
parsed.avatar = (0, agent_visual_refs_1.parseAvatarRefFlag)(String(flags.avatar));
|
|
64
|
+
}
|
|
25
65
|
const direct = {
|
|
26
66
|
'network-mode': 'network_mode',
|
|
27
67
|
'character-3d-id': 'character3DId',
|
|
28
|
-
'scene-background': 'sceneBackground',
|
|
29
68
|
'tone-mode': 'toneMode',
|
|
30
69
|
'tone-id': 'toneId',
|
|
31
70
|
'tone-notes': 'toneNotes',
|
|
@@ -46,8 +85,51 @@ function mergeAgentConfigFlags(body, flags) {
|
|
|
46
85
|
if (flags[flag] !== undefined)
|
|
47
86
|
parsed[field] = flags[flag];
|
|
48
87
|
}
|
|
49
|
-
|
|
50
|
-
|
|
88
|
+
const integers = {
|
|
89
|
+
'recursion-limit': 'recursion_limit',
|
|
90
|
+
'max-turns': 'maxTurns',
|
|
91
|
+
};
|
|
92
|
+
for (const [flag, field] of Object.entries(integers)) {
|
|
93
|
+
if (flags[flag] !== undefined)
|
|
94
|
+
parsed[field] = flags[flag];
|
|
95
|
+
}
|
|
96
|
+
/* Fields the web config editor has always written and no flag reached. */
|
|
97
|
+
if (flags['conversation-starter'] !== undefined) {
|
|
98
|
+
parsed.conversation_starters = flags['conversation-starter'];
|
|
99
|
+
}
|
|
100
|
+
if (flags['todo-working-hours'] !== undefined) {
|
|
101
|
+
parsed.todoWorkingHours = parseWorkingHoursFlag(String(flags['todo-working-hours']));
|
|
102
|
+
}
|
|
103
|
+
if (flags['reasoning-tool-escape'] !== undefined) {
|
|
104
|
+
parsed.reasoningToolEscapes = flags['reasoning-tool-escape'];
|
|
105
|
+
}
|
|
106
|
+
if (flags['commitment-responsibility'] !== undefined) {
|
|
107
|
+
parsed.commitmentResponsibilityDefault = flags['commitment-responsibility'];
|
|
108
|
+
}
|
|
109
|
+
if (flags['commitment-responsibility-ceiling'] !== undefined) {
|
|
110
|
+
parsed.commitmentResponsibilityCeiling = flags['commitment-responsibility-ceiling'];
|
|
111
|
+
}
|
|
112
|
+
if (flags['tool-resources'] !== undefined) {
|
|
113
|
+
parsed.tool_resources = JSON.parse(String(flags['tool-resources']));
|
|
114
|
+
}
|
|
115
|
+
if (flags['project-id'] !== undefined)
|
|
116
|
+
parsed.projectIds = flags['project-id'];
|
|
117
|
+
if (flags['remove-project-id'] !== undefined) {
|
|
118
|
+
parsed.removeProjectIds = flags['remove-project-id'];
|
|
119
|
+
}
|
|
120
|
+
// Two flags, one stored object. Sent whole so a caller who sets only the
|
|
121
|
+
// channel does not silently clear `allowAutoMinorUpdates` — the server
|
|
122
|
+
// replaces the subdocument rather than merging into it.
|
|
123
|
+
if (flags['install-channel'] !== undefined || flags['auto-minor-updates'] !== undefined) {
|
|
124
|
+
const releasePolicy = {};
|
|
125
|
+
if (flags['install-channel'] !== undefined) {
|
|
126
|
+
releasePolicy.defaultInstallChannel = flags['install-channel'];
|
|
127
|
+
}
|
|
128
|
+
if (flags['auto-minor-updates'] !== undefined) {
|
|
129
|
+
releasePolicy.allowAutoMinorUpdates = flags['auto-minor-updates'];
|
|
130
|
+
}
|
|
131
|
+
parsed.releasePolicy = releasePolicy;
|
|
132
|
+
}
|
|
51
133
|
// Cross-Space Task execution ceiling. `0` means unlimited, matching the
|
|
52
134
|
// Space limits' convention so a user learns one spelling of "no cap".
|
|
53
135
|
if (flags['max-concurrent-task-executions'] !== undefined) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pin` / `unpin` / `mute` / `unmute` on top of a TOGGLE endpoint.
|
|
3
|
+
*
|
|
4
|
+
* `PATCH /api/user/agent-preferences/:agentId/pin` flips the bit; it does not
|
|
5
|
+
* take a desired state. A CLI that exposed the flip directly would make
|
|
6
|
+
* `skrr agents pin X` mean "pin it, unless it already was, in which case unpin
|
|
7
|
+
* it" — fine for a button a human clicks while looking at the result, wrong for
|
|
8
|
+
* a command in a script, where the outcome would depend on state the script
|
|
9
|
+
* never read.
|
|
10
|
+
*
|
|
11
|
+
* So the desired state is sent, and the endpoint now takes one. It used to be
|
|
12
|
+
* read-then-flip-if-different, which made each command idempotent when run
|
|
13
|
+
* alone and inverted under concurrency: six `skrr agents pin` calls that each
|
|
14
|
+
* read "unpinned" sent six flips, and six flips from false is false — pinning an
|
|
15
|
+
* agent six times left it unpinned. That was never fixable from out here, as the
|
|
16
|
+
* previous version of this comment said; it needed the endpoint to accept a
|
|
17
|
+
* desired state, which is what `pinned`/`muted` in the body now is.
|
|
18
|
+
*
|
|
19
|
+
* `changed` comes from the server, which is the only place that can compare the
|
|
20
|
+
* old value with the new one without a second race.
|
|
21
|
+
*/
|
|
22
|
+
export type AgentFlag = 'pin' | 'mute';
|
|
23
|
+
export interface FlagChange {
|
|
24
|
+
/** The value the server reports AFTER this call. */
|
|
25
|
+
value: boolean;
|
|
26
|
+
/** False when the flag already held the desired value and nothing was sent. */
|
|
27
|
+
changed: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare function setAgentFlag(agentId: string, flag: AgentFlag, desired: boolean): Promise<FlagChange>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setAgentFlag = setAgentFlag;
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
async function setAgentFlag(agentId, flag, desired) {
|
|
6
|
+
const current = await data_provider_1.dataService.getAgentPreferences(agentId);
|
|
7
|
+
const held = flag === 'pin' ? current.preferences?.isPinned : current.preferences?.isMuted;
|
|
8
|
+
// Nothing to send. True on every server version, and the one case where a
|
|
9
|
+
// write would be pure risk.
|
|
10
|
+
if (Boolean(held) === desired) {
|
|
11
|
+
return { value: desired, changed: false };
|
|
12
|
+
}
|
|
13
|
+
// The read stays, and it is NOT what the race was. The race was read-then-
|
|
14
|
+
// FLIP: the write depended on what was read, so two readers of the same value
|
|
15
|
+
// sent two flips. The write now carries the desired state, so any number of
|
|
16
|
+
// them land on it — the read only decides whether to speak at all.
|
|
17
|
+
//
|
|
18
|
+
// It also keeps this honest against a server that has not been deployed yet.
|
|
19
|
+
// A build without the desired-state branch ignores the body and flips; from a
|
|
20
|
+
// state we have just confirmed differs, one flip still reaches `desired`, so
|
|
21
|
+
// the reported outcome is true either way. Reporting the server's `changed`
|
|
22
|
+
// alone was not: an old server omits it, `?? false` read that as "nothing to
|
|
23
|
+
// do", and `skrr agents pin` said so while flipping the bit.
|
|
24
|
+
if (flag === 'pin') {
|
|
25
|
+
const result = await data_provider_1.dataService.toggleAgentPin(agentId, desired);
|
|
26
|
+
return { value: result.isPinned, changed: result.changed ?? true };
|
|
27
|
+
}
|
|
28
|
+
const result = await data_provider_1.dataService.toggleAgentMute(agentId, desired);
|
|
29
|
+
return { value: result.isMuted, changed: result.changed ?? true };
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AgentAvatarRef, AgentSceneBackground } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* The `--scene-background` help, shared by `agents create` and `agents update`.
|
|
4
|
+
*
|
|
5
|
+
* It named three forms and no preset ids, while the refusal it led to named a
|
|
6
|
+
* fourth form (JSON) and listed all the ids — so the only way to learn the valid
|
|
7
|
+
* values was to type a wrong one on purpose. `--avatar`, one flag away, already
|
|
8
|
+
* did this right. Built from the shipped catalog so it cannot fall behind it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SCENE_BACKGROUND_FLAG_HELP: string;
|
|
11
|
+
export declare function imageUploadMimeType(filePath: string): string | undefined;
|
|
12
|
+
/** Preset ids this build ships, for an error message that can be acted on. */
|
|
13
|
+
export declare function avatarPresetIds(): string[];
|
|
14
|
+
export declare function sceneBackgroundPresetIds(): string[];
|
|
15
|
+
export declare function parseAvatarRefFlag(value: string): AgentAvatarRef;
|
|
16
|
+
export declare function parseSceneBackgroundFlag(value: string): AgentSceneBackground;
|
|
17
|
+
/**
|
|
18
|
+
* The avatar line for `agents show` text output.
|
|
19
|
+
*
|
|
20
|
+
* `agents show` printed no avatar at all, so its output was byte-identical before
|
|
21
|
+
* and after `agents update --avatar preset:studio-halo`: "has the Halo preset"
|
|
22
|
+
* and "has no face whatsoever" could not be told apart without `--json` and
|
|
23
|
+
* knowing which raw field to decode. The coercion `--avatar` performs is the one
|
|
24
|
+
* thing a reader would want confirmed, and it was the one thing hidden.
|
|
25
|
+
*
|
|
26
|
+
* Rendered in the same shorthand `--avatar` accepts, so what is printed is what
|
|
27
|
+
* can be typed back. An ABSENT avatar is kept apart from an explicit
|
|
28
|
+
* `{type:'default'}`: both show the platform logo, but only the absent one was
|
|
29
|
+
* never chosen, and that is exactly what `agents avatar default apply` rewrites.
|
|
30
|
+
*/
|
|
31
|
+
export declare function agentAvatarLine(raw: unknown): string;
|
|
32
|
+
/** The scene-background line, in the shorthand `--scene-background` accepts. */
|
|
33
|
+
export declare function agentSceneBackgroundLine(raw: unknown): string;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SCENE_BACKGROUND_FLAG_HELP = void 0;
|
|
4
|
+
exports.imageUploadMimeType = imageUploadMimeType;
|
|
5
|
+
exports.avatarPresetIds = avatarPresetIds;
|
|
6
|
+
exports.sceneBackgroundPresetIds = sceneBackgroundPresetIds;
|
|
7
|
+
exports.parseAvatarRefFlag = parseAvatarRefFlag;
|
|
8
|
+
exports.parseSceneBackgroundFlag = parseSceneBackgroundFlag;
|
|
9
|
+
exports.agentAvatarLine = agentAvatarLine;
|
|
10
|
+
exports.agentSceneBackgroundLine = agentSceneBackgroundLine;
|
|
11
|
+
/**
|
|
12
|
+
* The two "how does this agent look" fields, parsed from a flag.
|
|
13
|
+
*
|
|
14
|
+
* WHY A PARSER AND NOT A PLAIN STRING
|
|
15
|
+
* ───────────────────────────────────
|
|
16
|
+
* `agent.avatar` and `agent.sceneBackground` are DISCRIMINATED UNIONS on the
|
|
17
|
+
* wire (`packages/api/src/agents/validation.ts`), because a face and a backdrop
|
|
18
|
+
* each have several possible origins — a built-in preset, the caller's own
|
|
19
|
+
* uploaded asset, an explicit "the platform default", a raw storage path — and
|
|
20
|
+
* a bare string cannot say which. `agentUpdateSchema.parse(req.body)` runs with
|
|
21
|
+
* no coercion, so a string reaches the server and is rejected.
|
|
22
|
+
*
|
|
23
|
+
* `--scene-background` shipped as a pass-through string for exactly that
|
|
24
|
+
* reason, which made it a flag with NO value that could ever succeed: every
|
|
25
|
+
* invocation was a 400 naming a zod path rather than the flag. The fix is to
|
|
26
|
+
* own the shorthand here, once, so both fields read the same way and neither
|
|
27
|
+
* can regress into a raw string again.
|
|
28
|
+
*
|
|
29
|
+
* THE SHORTHAND
|
|
30
|
+
* ─────────────
|
|
31
|
+
* default → { type: 'default' }
|
|
32
|
+
* preset:<id> → { type: 'preset', id }
|
|
33
|
+
* asset:<id> → { type: 'asset', id } (avatar only)
|
|
34
|
+
* image:<filepath>@<source> → { type: 'image', filepath, source }
|
|
35
|
+
* {"type":"preset","id":"..."} → parsed verbatim, the escape hatch
|
|
36
|
+
*
|
|
37
|
+
* A bare id is deliberately NOT accepted. `preset:studio` and an asset id are
|
|
38
|
+
* different namespaces, and guessing between them would make the failure mode
|
|
39
|
+
* "your avatar silently became someone else's" rather than a parse error.
|
|
40
|
+
*/
|
|
41
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
42
|
+
/**
|
|
43
|
+
* The `--scene-background` help, shared by `agents create` and `agents update`.
|
|
44
|
+
*
|
|
45
|
+
* It named three forms and no preset ids, while the refusal it led to named a
|
|
46
|
+
* fourth form (JSON) and listed all the ids — so the only way to learn the valid
|
|
47
|
+
* values was to type a wrong one on purpose. `--avatar`, one flag away, already
|
|
48
|
+
* did this right. Built from the shipped catalog so it cannot fall behind it.
|
|
49
|
+
*/
|
|
50
|
+
exports.SCENE_BACKGROUND_FLAG_HELP = 'Backdrop for the 3D view: default, preset:<id>, image:<filepath>@<source>, or a JSON ' +
|
|
51
|
+
`object such as {"type":"preset","id":"midnight"}. Presets: ${data_provider_1.AGENT_SCENE_BACKGROUND_PRESETS.map((preset) => preset.id).join(', ')}. For your own photo use \`skrr agents scene-background upload\` — ` +
|
|
52
|
+
'<filepath> is the storage path that command produces, not a file on disk.';
|
|
53
|
+
/**
|
|
54
|
+
* The MIME type to send an image upload as, from its file extension.
|
|
55
|
+
*
|
|
56
|
+
* The upload routes gate on the multipart part's type, and a part built as
|
|
57
|
+
* `new Blob([bytes])` has none, so it arrives as `application/octet-stream` and
|
|
58
|
+
* is refused whatever its bytes are. `agents avatar upload` shipped that way and
|
|
59
|
+
* could not upload any file (OSK-9841). Returns undefined for anything that is
|
|
60
|
+
* not an image type the routes accept, so a caller can refuse locally.
|
|
61
|
+
*/
|
|
62
|
+
const UPLOAD_IMAGE_TYPES = {
|
|
63
|
+
'.png': 'image/png',
|
|
64
|
+
'.jpg': 'image/jpeg',
|
|
65
|
+
'.jpeg': 'image/jpeg',
|
|
66
|
+
'.webp': 'image/webp',
|
|
67
|
+
'.gif': 'image/gif',
|
|
68
|
+
};
|
|
69
|
+
function imageUploadMimeType(filePath) {
|
|
70
|
+
const dot = filePath.lastIndexOf('.');
|
|
71
|
+
return dot < 0 ? undefined : UPLOAD_IMAGE_TYPES[filePath.slice(dot).toLowerCase()];
|
|
72
|
+
}
|
|
73
|
+
/** `image:path/to.png@s3` — the `@` is the LAST one, so a path may contain `@`. */
|
|
74
|
+
function parseImage(rest, flag) {
|
|
75
|
+
const at = rest.lastIndexOf('@');
|
|
76
|
+
if (at <= 0 || at === rest.length - 1) {
|
|
77
|
+
throw new Error(`${flag}: "image:" needs a storage source — write image:<filepath>@<source>, ` +
|
|
78
|
+
'for example image:images/123/face.png@s3.');
|
|
79
|
+
}
|
|
80
|
+
return { filepath: rest.slice(0, at), source: rest.slice(at + 1) };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A JSON object escape hatch, so a shape this grammar has not learned yet is
|
|
84
|
+
* still expressible without falling back to `--from-json` for the whole agent.
|
|
85
|
+
* Returns `undefined` when the value is not JSON at all, so the caller can go on
|
|
86
|
+
* to the shorthand rather than reporting a JSON syntax error for `preset:foo`.
|
|
87
|
+
*/
|
|
88
|
+
function parseJsonObject(value) {
|
|
89
|
+
const trimmed = value.trim();
|
|
90
|
+
if (!trimmed.startsWith('{'))
|
|
91
|
+
return undefined;
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(trimmed);
|
|
94
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : undefined;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Hold a JSON value to the same rules as the shorthand, for the shapes the
|
|
102
|
+
* grammar knows.
|
|
103
|
+
*
|
|
104
|
+
* The JSON form used to be returned unchecked, so the one form with no worked
|
|
105
|
+
* example was also the one with no local validation: `{"type":"preset"}` went to
|
|
106
|
+
* the server and came back as a raw zod dump
|
|
107
|
+
* (`sceneBackground.id: Invalid input: expected string, received undefined`),
|
|
108
|
+
* while `preset:` with no id got a sentence. A KNOWN `type` is now validated here
|
|
109
|
+
* exactly as its shorthand is. An unknown `type` still passes through untouched,
|
|
110
|
+
* because letting a shape this grammar has not learned reach the server is the
|
|
111
|
+
* reason the escape hatch exists.
|
|
112
|
+
*/
|
|
113
|
+
function checkJsonRef(json, flag, shorthand) {
|
|
114
|
+
const type = json.type;
|
|
115
|
+
const str = (value) => (typeof value === 'string' ? value : '');
|
|
116
|
+
if (type === 'default')
|
|
117
|
+
return;
|
|
118
|
+
if (type === 'preset' || type === 'asset') {
|
|
119
|
+
if (!str(json.id)) {
|
|
120
|
+
throw new Error(`${flag}: a JSON value of type "${type}" needs a string "id" — for example ` +
|
|
121
|
+
`{"type":"${type}","id":"<id>"}, or the shorthand ${type}:<id>.`);
|
|
122
|
+
}
|
|
123
|
+
shorthand(`${type}:${str(json.id)}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (type === 'image') {
|
|
127
|
+
if (!str(json.filepath) || !str(json.source)) {
|
|
128
|
+
throw new Error(`${flag}: a JSON value of type "image" needs string "filepath" and "source" — ` +
|
|
129
|
+
'for example {"type":"image","filepath":"<storage path>","source":"s3"}.');
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (typeof type !== 'string' || !type) {
|
|
134
|
+
throw new Error(`${flag}: a JSON value needs a string "type" (default, preset, image, …).`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Preset ids this build ships, for an error message that can be acted on. */
|
|
138
|
+
function avatarPresetIds() {
|
|
139
|
+
return data_provider_1.AGENT_AVATAR_PRESETS.map((preset) => preset.id);
|
|
140
|
+
}
|
|
141
|
+
function sceneBackgroundPresetIds() {
|
|
142
|
+
return data_provider_1.AGENT_SCENE_BACKGROUND_PRESETS.map((preset) => preset.id);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Name a handful of valid ids rather than all of them.
|
|
146
|
+
*
|
|
147
|
+
* There are ~60 avatar presets. An error that prints every one buries the
|
|
148
|
+
* sentence that says what went wrong, so show a few and point at the command
|
|
149
|
+
* that lists the rest.
|
|
150
|
+
*/
|
|
151
|
+
function someOf(ids, limit = 6) {
|
|
152
|
+
const head = ids.slice(0, limit).join(', ');
|
|
153
|
+
return ids.length > limit ? `${head}, … (${ids.length} total)` : head;
|
|
154
|
+
}
|
|
155
|
+
function parseAvatarRefFlag(value) {
|
|
156
|
+
const json = parseJsonObject(value);
|
|
157
|
+
if (json) {
|
|
158
|
+
checkJsonRef(json, '--avatar', parseAvatarRefFlag);
|
|
159
|
+
return json;
|
|
160
|
+
}
|
|
161
|
+
const raw = value.trim();
|
|
162
|
+
if (raw === 'default')
|
|
163
|
+
return { type: 'default' };
|
|
164
|
+
const colon = raw.indexOf(':');
|
|
165
|
+
const kind = colon === -1 ? raw : raw.slice(0, colon);
|
|
166
|
+
const rest = colon === -1 ? '' : raw.slice(colon + 1);
|
|
167
|
+
if (kind === 'preset') {
|
|
168
|
+
if (!(0, data_provider_1.isAgentAvatarPresetId)(rest)) {
|
|
169
|
+
throw new Error(`--avatar: "${rest}" is not an avatar preset in this build. ` +
|
|
170
|
+
`Try one of: ${someOf(avatarPresetIds())}. ` +
|
|
171
|
+
'Run `skrr agents avatar presets` for the full catalog.');
|
|
172
|
+
}
|
|
173
|
+
return { type: 'preset', id: rest };
|
|
174
|
+
}
|
|
175
|
+
if (kind === 'asset') {
|
|
176
|
+
if (!rest) {
|
|
177
|
+
throw new Error('--avatar: "asset:" needs an id from your library — ' +
|
|
178
|
+
'run `skrr agents avatar library` to list them.');
|
|
179
|
+
}
|
|
180
|
+
return { type: 'asset', id: rest };
|
|
181
|
+
}
|
|
182
|
+
if (kind === 'image')
|
|
183
|
+
return { type: 'image', ...parseImage(rest, '--avatar') };
|
|
184
|
+
throw new Error(`--avatar: cannot read "${value}". Accepted: default, preset:<id>, asset:<id>, ` +
|
|
185
|
+
'image:<filepath>@<source>, or a JSON object. ' +
|
|
186
|
+
'To upload a new image file instead, use `skrr agents avatar upload --file <path>`.');
|
|
187
|
+
}
|
|
188
|
+
function parseSceneBackgroundFlag(value) {
|
|
189
|
+
const json = parseJsonObject(value);
|
|
190
|
+
if (json) {
|
|
191
|
+
checkJsonRef(json, '--scene-background', parseSceneBackgroundFlag);
|
|
192
|
+
return json;
|
|
193
|
+
}
|
|
194
|
+
const raw = value.trim();
|
|
195
|
+
if (raw === 'default')
|
|
196
|
+
return { type: 'default' };
|
|
197
|
+
const colon = raw.indexOf(':');
|
|
198
|
+
const kind = colon === -1 ? raw : raw.slice(0, colon);
|
|
199
|
+
const rest = colon === -1 ? '' : raw.slice(colon + 1);
|
|
200
|
+
if (kind === 'preset') {
|
|
201
|
+
if (!(0, data_provider_1.isAgentSceneBackgroundPresetId)(rest)) {
|
|
202
|
+
throw new Error(`--scene-background: "${rest}" is not a backdrop preset in this build. ` +
|
|
203
|
+
`Valid ids: ${sceneBackgroundPresetIds().join(', ')}.`);
|
|
204
|
+
}
|
|
205
|
+
return { type: 'preset', id: rest };
|
|
206
|
+
}
|
|
207
|
+
if (kind === 'image')
|
|
208
|
+
return { type: 'image', ...parseImage(rest, '--scene-background') };
|
|
209
|
+
// A bare preset id is the single most likely mistake here, because the
|
|
210
|
+
// backdrop catalog is short enough to remember. Say so instead of listing the
|
|
211
|
+
// grammar twice.
|
|
212
|
+
if ((0, data_provider_1.isAgentSceneBackgroundPresetId)(raw)) {
|
|
213
|
+
throw new Error(`--scene-background: "${raw}" is a preset id — write preset:${raw}. ` +
|
|
214
|
+
'A bare id is refused because preset and image live in different namespaces.');
|
|
215
|
+
}
|
|
216
|
+
throw new Error(`--scene-background: cannot read "${value}". Accepted: default, preset:<id>, ` +
|
|
217
|
+
`image:<filepath>@<source>, or a JSON object. Presets: ${sceneBackgroundPresetIds().join(', ')}.`);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The avatar line for `agents show` text output.
|
|
221
|
+
*
|
|
222
|
+
* `agents show` printed no avatar at all, so its output was byte-identical before
|
|
223
|
+
* and after `agents update --avatar preset:studio-halo`: "has the Halo preset"
|
|
224
|
+
* and "has no face whatsoever" could not be told apart without `--json` and
|
|
225
|
+
* knowing which raw field to decode. The coercion `--avatar` performs is the one
|
|
226
|
+
* thing a reader would want confirmed, and it was the one thing hidden.
|
|
227
|
+
*
|
|
228
|
+
* Rendered in the same shorthand `--avatar` accepts, so what is printed is what
|
|
229
|
+
* can be typed back. An ABSENT avatar is kept apart from an explicit
|
|
230
|
+
* `{type:'default'}`: both show the platform logo, but only the absent one was
|
|
231
|
+
* never chosen, and that is exactly what `agents avatar default apply` rewrites.
|
|
232
|
+
*/
|
|
233
|
+
function agentAvatarLine(raw) {
|
|
234
|
+
if (raw == null) {
|
|
235
|
+
return 'none chosen — shows the platform logo (`agents avatar default apply` would fill it)';
|
|
236
|
+
}
|
|
237
|
+
const ref = raw;
|
|
238
|
+
switch (ref.type) {
|
|
239
|
+
case 'default':
|
|
240
|
+
return 'default — the platform logo, chosen';
|
|
241
|
+
case 'preset': {
|
|
242
|
+
const id = typeof ref.id === 'string' ? ref.id : '';
|
|
243
|
+
const preset = (0, data_provider_1.getAgentAvatarPreset)(id);
|
|
244
|
+
return preset ? `preset:${id} (${preset.name})` : `preset:${id} (not in this build)`;
|
|
245
|
+
}
|
|
246
|
+
case 'asset':
|
|
247
|
+
return `asset:${typeof ref.id === 'string' ? ref.id : '?'} (from your avatar library)`;
|
|
248
|
+
case 'image':
|
|
249
|
+
return 'an uploaded image';
|
|
250
|
+
default:
|
|
251
|
+
return 'unrecognised value — see `--json`';
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** The scene-background line, in the shorthand `--scene-background` accepts. */
|
|
255
|
+
function agentSceneBackgroundLine(raw) {
|
|
256
|
+
const ref = (raw ?? { type: 'default' });
|
|
257
|
+
if (ref.type === 'default')
|
|
258
|
+
return 'default';
|
|
259
|
+
if (ref.type === 'preset') {
|
|
260
|
+
const id = typeof ref.id === 'string' ? ref.id : '';
|
|
261
|
+
const preset = data_provider_1.AGENT_SCENE_BACKGROUND_PRESETS.find((candidate) => candidate.id === id);
|
|
262
|
+
return preset ? `preset:${id} (${preset.name})` : `preset:${id} (not in this build)`;
|
|
263
|
+
}
|
|
264
|
+
if (ref.type === 'image')
|
|
265
|
+
return 'an uploaded image';
|
|
266
|
+
return 'unrecognised value — see `--json`';
|
|
267
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The answer a question gets when no terminal exists to ask it on. Written to the
|
|
3
|
+
* agent, so it says what happened and what to do rather than pretending a person
|
|
4
|
+
* replied.
|
|
5
|
+
*/
|
|
6
|
+
export declare const NON_INTERACTIVE_QUESTION_ANSWER: string;
|
|
1
7
|
export type AgenticStreamEvent = {
|
|
2
8
|
type: string;
|
|
3
9
|
sessionId?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgenticStreamClient = exports.USER_CONNECTION_CAP_CODE = void 0;
|
|
3
|
+
exports.AgenticStreamClient = exports.USER_CONNECTION_CAP_CODE = exports.NON_INTERACTIVE_QUESTION_ANSWER = void 0;
|
|
4
4
|
exports.writeJsonLine = writeJsonLine;
|
|
5
5
|
exports.envelopesText = envelopesText;
|
|
6
6
|
exports.envelopeKey = envelopeKey;
|
|
@@ -19,6 +19,13 @@ const socket_io_client_1 = require("socket.io-client");
|
|
|
19
19
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
20
20
|
const config_1 = require("./config");
|
|
21
21
|
const publicEndpoints_generated_1 = require("./publicEndpoints.generated");
|
|
22
|
+
/**
|
|
23
|
+
* The answer a question gets when no terminal exists to ask it on. Written to the
|
|
24
|
+
* agent, so it says what happened and what to do rather than pretending a person
|
|
25
|
+
* replied.
|
|
26
|
+
*/
|
|
27
|
+
exports.NON_INTERACTIVE_QUESTION_ANSWER = 'No answer: this turn was started non-interactively (no terminal), so nobody can reply to ' +
|
|
28
|
+
'questions. Proceed with your best judgement, or finish by stating exactly what you need.';
|
|
22
29
|
/**
|
|
23
30
|
* Write exactly one complete JSON value on one line.
|
|
24
31
|
*
|
|
@@ -667,10 +674,25 @@ class AgenticStreamClient {
|
|
|
667
674
|
async handleQuestion(event) {
|
|
668
675
|
if (this.closed)
|
|
669
676
|
return;
|
|
677
|
+
// The same question can arrive twice (both delivery paths carry it — a
|
|
678
|
+
// non-interactive run showed two `question.requested` for one questionId,
|
|
679
|
+
// each answered). Answer it once, as tool events are emitted once.
|
|
680
|
+
if (!this.firstTimeSeen('question', event.questionId))
|
|
681
|
+
return;
|
|
670
682
|
this.emit({ ...event, type: 'question.requested' });
|
|
683
|
+
// Nobody can answer a question in a run with no terminal. This used to
|
|
684
|
+
// prompt on stdin anyway: a scripted `agents chat --jsonl` printed the
|
|
685
|
+
// question and a `>` to stderr, read nothing, and the turn sat for the
|
|
686
|
+
// server's full 300-second question timeout — then ended with the agent told
|
|
687
|
+
// "Not answered … timed out", at the cost of the whole wait. Answer at once
|
|
688
|
+
// instead, saying why, so the agent proceeds or states what it needs. An
|
|
689
|
+
// explicit `input` (tests, an embedding caller) is treated as interactive.
|
|
690
|
+
const interactive = this.options.input !== undefined || Boolean(process.stdin.isTTY);
|
|
671
691
|
const answers = {};
|
|
672
692
|
for (const question of event.questions ?? []) {
|
|
673
|
-
const answer =
|
|
693
|
+
const answer = interactive
|
|
694
|
+
? await this.ask(`${question.header ?? 'Question'}: ${question.question}\n> `)
|
|
695
|
+
: exports.NON_INTERACTIVE_QUESTION_ANSWER;
|
|
674
696
|
answers[question.header ?? question.question] = answer;
|
|
675
697
|
}
|
|
676
698
|
if (event.questionId && this.socket) {
|
|
@@ -680,7 +702,12 @@ class AgenticStreamClient {
|
|
|
680
702
|
answers,
|
|
681
703
|
});
|
|
682
704
|
}
|
|
683
|
-
this.emit({
|
|
705
|
+
this.emit({
|
|
706
|
+
type: 'question.answered',
|
|
707
|
+
questionId: event.questionId,
|
|
708
|
+
answers,
|
|
709
|
+
...(interactive ? {} : { nonInteractive: true }),
|
|
710
|
+
});
|
|
684
711
|
}
|
|
685
712
|
ask(prompt) {
|
|
686
713
|
// A prompt raised after close has nobody to answer it, and re-creating the
|
|
@@ -773,6 +800,10 @@ class AgenticStreamClient {
|
|
|
773
800
|
output.write(`\n[${event.type}]\n`);
|
|
774
801
|
this.renderedText = this.accumulated;
|
|
775
802
|
}
|
|
803
|
+
else if (event.type === 'question.answered' && event.nonInteractive) {
|
|
804
|
+
output.write('\n[question] no terminal to answer on, so the agent was told to proceed without an answer\n');
|
|
805
|
+
this.renderedText = this.accumulated;
|
|
806
|
+
}
|
|
776
807
|
}
|
|
777
808
|
finish(status, event) {
|
|
778
809
|
if (this.settled)
|
|
@@ -33,7 +33,7 @@ export type ResolutionFailure = {
|
|
|
33
33
|
* NO_SPACE — the reference needs a membership list to match against, but
|
|
34
34
|
* the task/payload has no space, so only raw ids are possible.
|
|
35
35
|
*/
|
|
36
|
-
code: 'NOT_FOUND' | 'AMBIGUOUS' | 'NO_SPACE';
|
|
36
|
+
code: 'NOT_FOUND' | 'AMBIGUOUS' | 'NO_SPACE' | 'NOT_A_REFERENCE';
|
|
37
37
|
query: string;
|
|
38
38
|
kind: MemberKind;
|
|
39
39
|
/** For AMBIGUOUS: the tied matches. For NOT_FOUND: everything available. */
|
|
@@ -7,6 +7,7 @@ exports.describeMember = describeMember;
|
|
|
7
7
|
exports.describeCandidates = describeCandidates;
|
|
8
8
|
exports.resolveAssigneeReferences = resolveAssigneeReferences;
|
|
9
9
|
exports.formatResolutionFailure = formatResolutionFailure;
|
|
10
|
+
const failed_lookup_1 = require("./failed-lookup");
|
|
10
11
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
11
12
|
const OBJECT_ID_RE = /^[0-9a-fA-F]{24}$/;
|
|
12
13
|
const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
@@ -84,6 +85,11 @@ function resolveMember(query, members, kind) {
|
|
|
84
85
|
if (!q) {
|
|
85
86
|
return { ok: false, code: 'NOT_FOUND', query: raw, kind, candidates: pool };
|
|
86
87
|
}
|
|
88
|
+
// A failed lookup's output is refused before the name tiers can match it.
|
|
89
|
+
// See `failed-lookup.ts`.
|
|
90
|
+
if ((0, failed_lookup_1.isFailedLookupValue)(raw)) {
|
|
91
|
+
return { ok: false, code: 'NOT_A_REFERENCE', query: raw, kind, candidates: [] };
|
|
92
|
+
}
|
|
87
93
|
const tiers = [
|
|
88
94
|
// 1. Exact id. Case-sensitive on purpose — ids are opaque.
|
|
89
95
|
(m) => m.id === raw,
|
|
@@ -186,6 +192,8 @@ function formatResolutionFailure(failure, bin = 'skrr') {
|
|
|
186
192
|
const noun = failure.kind === 'user' ? 'person' : 'agent';
|
|
187
193
|
const plural = failure.kind === 'user' ? 'people' : 'agents';
|
|
188
194
|
switch (failure.code) {
|
|
195
|
+
case 'NOT_A_REFERENCE':
|
|
196
|
+
return (0, failed_lookup_1.describeFailedLookupValue)(failure.query, noun);
|
|
189
197
|
case 'AMBIGUOUS':
|
|
190
198
|
return (`"${failure.query}" matches ${failure.candidates.length} ${plural} in this space:\n` +
|
|
191
199
|
`${describeCandidates(failure.candidates)}\n` +
|
|
@@ -29,6 +29,18 @@ export type BulkApplyResult = {
|
|
|
29
29
|
* semantics match `skrr tasks bulk-update`). `apply` returns whether the task
|
|
30
30
|
* actually changed (already-satisfied tasks are reported as no-ops).
|
|
31
31
|
*/
|
|
32
|
+
/**
|
|
33
|
+
* The server's reason for a failed per-task write, not the transport's.
|
|
34
|
+
*
|
|
35
|
+
* A bulk run used to record `err.message`, which for a dataService call is the
|
|
36
|
+
* transport line — `HTTP 400 Bad Request — PATCH https://…/api/tasks/<id>` — so
|
|
37
|
+
* `tasks actions attach --all-in-space` printed that once per task and named
|
|
38
|
+
* neither the ref nor the rule that refused it (OSK-9652). The same call made
|
|
39
|
+
* for a single task goes through `handleApiError`, which reads the body. This
|
|
40
|
+
* reads it the same way: `message`, then `error`, plus the first validation
|
|
41
|
+
* detail when the server sent one.
|
|
42
|
+
*/
|
|
43
|
+
export declare function bulkFailureMessage(err: unknown): string;
|
|
32
44
|
export declare function applyToTaskTargets(targets: Array<{
|
|
33
45
|
id: string;
|
|
34
46
|
identifier?: string;
|