@openscout/protocol 0.2.63 → 0.2.82
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/LICENSE +202 -0
- package/README.md +103 -52
- package/dist/a2a.d.ts +224 -0
- package/dist/a2a.d.ts.map +1 -0
- package/dist/a2a.js +225 -0
- package/dist/activity.d.ts +70 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +1 -0
- package/dist/actors.d.ts +7 -3
- package/dist/actors.d.ts.map +1 -0
- package/dist/actors.js +15 -1
- package/dist/agent-broker-feed.d.ts +84 -0
- package/dist/agent-broker-feed.d.ts.map +1 -0
- package/dist/agent-broker-feed.js +1 -0
- package/dist/agent-identity.d.ts +23 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +122 -8
- package/dist/agent-runs.d.ts +191 -0
- package/dist/agent-runs.d.ts.map +1 -0
- package/dist/agent-runs.js +365 -0
- package/dist/assigned-roles.d.ts +205 -0
- package/dist/assigned-roles.d.ts.map +1 -0
- package/dist/assigned-roles.js +228 -0
- package/dist/broker-routes.d.ts +40 -0
- package/dist/broker-routes.d.ts.map +1 -0
- package/dist/broker-routes.js +56 -0
- package/dist/budget.d.ts +65 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +19 -0
- package/dist/capability-matrix.d.ts +230 -0
- package/dist/capability-matrix.d.ts.map +1 -0
- package/dist/capability-matrix.js +304 -0
- package/dist/channel-identity.d.ts +40 -0
- package/dist/channel-identity.d.ts.map +1 -0
- package/dist/channel-identity.js +108 -0
- package/dist/collaboration.d.ts +45 -16
- package/dist/collaboration.d.ts.map +1 -0
- package/dist/collaboration.js +39 -23
- package/dist/common.d.ts +4 -3
- package/dist/common.d.ts.map +1 -0
- package/dist/conversations.d.ts +1 -0
- package/dist/conversations.d.ts.map +1 -0
- package/dist/cursor-transport.d.ts +22 -0
- package/dist/cursor-transport.d.ts.map +1 -0
- package/dist/cursor-transport.js +10 -0
- package/dist/debug-attach.d.ts +29 -0
- package/dist/debug-attach.d.ts.map +1 -0
- package/dist/debug-attach.js +6 -0
- package/dist/deliveries.d.ts +16 -2
- package/dist/deliveries.d.ts.map +1 -0
- package/dist/durable-actions.d.ts +94 -0
- package/dist/durable-actions.d.ts.map +1 -0
- package/dist/durable-actions.js +1 -0
- package/dist/events.d.ts +27 -1
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +14 -1
- package/dist/harness-feature-support.d.ts +76 -0
- package/dist/harness-feature-support.d.ts.map +1 -0
- package/dist/harness-feature-support.js +29 -0
- package/dist/host-integrations.d.ts +22 -0
- package/dist/host-integrations.d.ts.map +1 -0
- package/dist/host-integrations.js +64 -0
- package/dist/inbox.d.ts +50 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +9 -0
- package/dist/index.d.ts +36 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -2
- package/dist/invocations.d.ts +121 -0
- package/dist/invocations.d.ts.map +1 -0
- package/dist/invocations.js +201 -1
- package/dist/mesh.d.ts +98 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +18 -1
- package/dist/messages.d.ts +3 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/native-interactions.d.ts +30 -0
- package/dist/native-interactions.d.ts.map +1 -0
- package/dist/native-interactions.js +51 -0
- package/dist/observed-status.d.ts +33 -0
- package/dist/observed-status.d.ts.map +1 -0
- package/dist/observed-status.js +6 -0
- package/dist/orchestrator-prompt.d.ts +10 -0
- package/dist/orchestrator-prompt.d.ts.map +1 -0
- package/dist/orchestrator-prompt.js +36 -0
- package/dist/permission-policy.d.ts +5 -0
- package/dist/permission-policy.d.ts.map +1 -0
- package/dist/permission-policy.js +15 -0
- package/dist/provisional-agent-names.d.ts +30 -0
- package/dist/provisional-agent-names.d.ts.map +1 -0
- package/dist/provisional-agent-names.js +224 -0
- package/dist/read-receipts.d.ts +12 -0
- package/dist/read-receipts.d.ts.map +1 -0
- package/dist/read-receipts.js +1 -0
- package/dist/relay-agent-card.d.ts +10 -0
- package/dist/relay-agent-card.d.ts.map +1 -0
- package/dist/rendezvous.d.ts +97 -0
- package/dist/rendezvous.d.ts.map +1 -0
- package/dist/rendezvous.js +35 -0
- package/dist/reserved-vocabulary.d.ts +21 -0
- package/dist/reserved-vocabulary.d.ts.map +1 -0
- package/dist/reserved-vocabulary.js +101 -0
- package/dist/route-aliases.d.ts +112 -0
- package/dist/route-aliases.d.ts.map +1 -0
- package/dist/route-aliases.js +1 -0
- package/dist/runtime-catalog-contract.d.ts +39 -0
- package/dist/runtime-catalog-contract.d.ts.map +1 -0
- package/dist/runtime-catalog-contract.js +17 -0
- package/dist/runtime-catalog.d.ts +11 -0
- package/dist/runtime-catalog.d.ts.map +1 -0
- package/dist/runtime-catalog.generated.d.ts +230 -0
- package/dist/runtime-catalog.generated.d.ts.map +1 -0
- package/dist/runtime-catalog.generated.js +299 -0
- package/dist/runtime-catalog.js +192 -0
- package/dist/runtime-execution.d.ts +161 -0
- package/dist/runtime-execution.d.ts.map +1 -0
- package/dist/runtime-execution.js +327 -0
- package/dist/runtime-profiles.d.ts +12 -0
- package/dist/runtime-profiles.d.ts.map +1 -0
- package/dist/runtime-profiles.js +20 -0
- package/dist/scout-agent-card.d.ts +10 -0
- package/dist/scout-agent-card.d.ts.map +1 -0
- package/dist/scout-composer.d.ts +27 -0
- package/dist/scout-composer.d.ts.map +1 -0
- package/dist/scout-composer.js +192 -0
- package/dist/scout-delivery.d.ts +101 -4
- package/dist/scout-delivery.d.ts.map +1 -0
- package/dist/scout-dispatch.d.ts +44 -3
- package/dist/scout-dispatch.d.ts.map +1 -0
- package/dist/scout-reply-context.d.ts +14 -0
- package/dist/scout-reply-context.d.ts.map +1 -0
- package/dist/scout-reply-context.js +1 -0
- package/dist/session-display-state.d.ts +132 -0
- package/dist/session-display-state.d.ts.map +1 -0
- package/dist/session-display-state.js +94 -0
- package/dist/terminal-host-topology.d.ts +119 -0
- package/dist/terminal-host-topology.d.ts.map +1 -0
- package/dist/terminal-host-topology.js +21 -0
- package/dist/terminal-sessions.d.ts +142 -0
- package/dist/terminal-sessions.d.ts.map +1 -0
- package/dist/terminal-sessions.js +81 -0
- package/dist/terminal-surface-id.d.ts +73 -0
- package/dist/terminal-surface-id.d.ts.map +1 -0
- package/dist/terminal-surface-id.js +162 -0
- package/dist/terminal-workspaces.d.ts +199 -0
- package/dist/terminal-workspaces.d.ts.map +1 -0
- package/dist/terminal-workspaces.js +287 -0
- package/dist/thread-events.d.ts +1 -0
- package/dist/thread-events.d.ts.map +1 -0
- package/dist/time.d.ts +16 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +33 -0
- package/dist/transports.d.ts +1 -0
- package/dist/transports.d.ts.map +1 -0
- package/package.json +37 -9
- package/src/a2a.ts +471 -0
- package/src/activity.ts +113 -0
- package/src/actors.ts +42 -8
- package/src/agent-broker-feed.ts +102 -0
- package/src/agent-identity.ts +143 -8
- package/src/agent-runs.ts +675 -0
- package/src/assigned-roles.ts +437 -0
- package/src/broker-routes.ts +62 -0
- package/src/budget.ts +88 -0
- package/src/capability-matrix.ts +648 -0
- package/src/channel-identity.ts +147 -0
- package/src/collaboration.ts +78 -48
- package/src/common.ts +24 -5
- package/src/cursor-transport.ts +34 -0
- package/src/debug-attach.ts +38 -0
- package/src/deliveries.ts +16 -1
- package/src/durable-actions.ts +125 -0
- package/src/events.ts +31 -0
- package/src/harness-feature-support.ts +116 -0
- package/src/host-integrations.ts +104 -0
- package/src/inbox.ts +68 -0
- package/src/index.ts +35 -2
- package/src/invocations.ts +353 -0
- package/src/mesh.ts +130 -0
- package/src/messages.ts +2 -0
- package/src/native-interactions.ts +100 -0
- package/src/observed-status.ts +90 -0
- package/src/orchestrator-prompt.ts +47 -0
- package/src/permission-policy.ts +21 -0
- package/src/provisional-agent-names.ts +272 -0
- package/src/read-receipts.ts +12 -0
- package/src/relay-agent-card.ts +73 -63
- package/src/rendezvous.ts +154 -0
- package/src/reserved-vocabulary.ts +135 -0
- package/src/route-aliases.ts +130 -0
- package/src/runtime-catalog-contract.ts +60 -0
- package/src/runtime-catalog.generated.ts +300 -0
- package/src/runtime-catalog.md +21 -0
- package/src/runtime-catalog.ts +193 -0
- package/src/runtime-catalog.v1.json +81 -0
- package/src/runtime-execution.ts +545 -0
- package/src/runtime-profiles.ts +37 -0
- package/src/scout-agent-card.ts +10 -0
- package/src/scout-composer.ts +249 -0
- package/src/scout-delivery.ts +117 -4
- package/src/scout-dispatch.ts +34 -2
- package/src/scout-reply-context.ts +15 -0
- package/src/session-display-state.ts +202 -0
- package/src/terminal-host-topology.ts +132 -0
- package/src/terminal-sessions.ts +187 -0
- package/src/terminal-surface-id.ts +189 -0
- package/src/terminal-workspaces.ts +455 -0
- package/src/time.ts +49 -0
- package/dist/agent-address.d.ts +0 -1
- package/dist/agent-address.js +0 -1
- package/dist/agent-selectors.d.ts +0 -1
- package/dist/agent-selectors.js +0 -1
- package/src/agent-address.ts +0 -1
- package/src/agent-identity.test.ts +0 -435
- package/src/agent-selectors.ts +0 -1
- package/src/scout-agent-card.test.ts +0 -54
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { SCOUT_RUNTIME_CATALOG_DATA } from "./runtime-catalog.generated.js";
|
|
2
|
+
import { SCOUT_LAUNCHABLE_HARNESSES, SCOUT_REASONING_EFFORT_LABELS, SCOUT_REASONING_EFFORTS, } from "./runtime-catalog-contract.js";
|
|
3
|
+
export * from "./runtime-catalog-contract.js";
|
|
4
|
+
/**
|
|
5
|
+
* Scout's versioned product catalog. Harness vendors are execution adapters,
|
|
6
|
+
* not catalog authorities: availability, ordering, labels, defaults, and the
|
|
7
|
+
* per-model effort ladder come from runtime-catalog.v1.json. Running brokers
|
|
8
|
+
* may replace this bundled last-known-good seed with a newer valid revision.
|
|
9
|
+
*/
|
|
10
|
+
export const SCOUT_RUNTIME_CATALOG = SCOUT_RUNTIME_CATALOG_DATA;
|
|
11
|
+
export function scoutRuntimeHarness(harness, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
12
|
+
return catalog.harnesses.find((entry) => entry.id === harness);
|
|
13
|
+
}
|
|
14
|
+
export function isScoutRuntimeHarnessEnabled(harness, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
15
|
+
return scoutRuntimeHarness(harness, catalog)?.enabled === true;
|
|
16
|
+
}
|
|
17
|
+
/** Enabled and offered as its own picker row. Hidden transports remain legal. */
|
|
18
|
+
export function isScoutRuntimeHarnessListed(harness, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
19
|
+
const entry = scoutRuntimeHarness(harness, catalog);
|
|
20
|
+
return entry?.enabled === true && entry.listed !== false;
|
|
21
|
+
}
|
|
22
|
+
export function scoutRuntimeDefaultHarness(catalog = SCOUT_RUNTIME_CATALOG) {
|
|
23
|
+
return catalog.harnesses.find((entry) => entry.enabled && entry.default)?.id
|
|
24
|
+
?? catalog.harnesses.find((entry) => entry.enabled)?.id
|
|
25
|
+
?? null;
|
|
26
|
+
}
|
|
27
|
+
export function scoutRuntimeDefaultModel(harness, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
28
|
+
const entry = scoutRuntimeHarness(harness, catalog);
|
|
29
|
+
return entry?.models.find((model) => model.enabled && model.default)?.id
|
|
30
|
+
?? entry?.models.find((model) => model.enabled)?.id
|
|
31
|
+
?? null;
|
|
32
|
+
}
|
|
33
|
+
export function scoutRuntimeReasoningEfforts(harness, model, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
34
|
+
const entry = scoutRuntimeHarness(harness, catalog);
|
|
35
|
+
if (!entry || !entry.enabled)
|
|
36
|
+
return null;
|
|
37
|
+
const selected = model
|
|
38
|
+
? entry.models.find((candidate) => candidate.enabled && candidate.id === model)
|
|
39
|
+
: undefined;
|
|
40
|
+
return selected?.reasoningEfforts === null
|
|
41
|
+
? null
|
|
42
|
+
: selected?.reasoningEfforts ?? entry.reasoningEfforts;
|
|
43
|
+
}
|
|
44
|
+
export function scoutRuntimeDefaultReasoningEffort(harness, model, catalog = SCOUT_RUNTIME_CATALOG) {
|
|
45
|
+
const entry = scoutRuntimeHarness(harness, catalog);
|
|
46
|
+
const selected = model
|
|
47
|
+
? entry?.models.find((candidate) => candidate.enabled && candidate.id === model)
|
|
48
|
+
: undefined;
|
|
49
|
+
const efforts = scoutRuntimeReasoningEfforts(harness, model, catalog);
|
|
50
|
+
const preferred = selected?.defaultReasoningEffort ?? entry?.defaultReasoningEffort ?? null;
|
|
51
|
+
return preferred && efforts?.includes(preferred) ? preferred : efforts?.[0] ?? null;
|
|
52
|
+
}
|
|
53
|
+
export function scoutRuntimeDefaultsByHarness(catalog = SCOUT_RUNTIME_CATALOG) {
|
|
54
|
+
return Object.fromEntries(catalog.harnesses
|
|
55
|
+
.filter((entry) => entry.enabled)
|
|
56
|
+
.map((entry) => {
|
|
57
|
+
const model = scoutRuntimeDefaultModel(entry.id, catalog);
|
|
58
|
+
return [entry.id, {
|
|
59
|
+
model,
|
|
60
|
+
reasoningEffort: scoutRuntimeDefaultReasoningEffort(entry.id, model, catalog),
|
|
61
|
+
}];
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
export const SCOUT_RUNTIME_DEFAULTS_BY_HARNESS = scoutRuntimeDefaultsByHarness();
|
|
65
|
+
export const SCOUT_REASONING_EFFORTS_BY_HARNESS = Object.fromEntries(SCOUT_RUNTIME_CATALOG.harnesses
|
|
66
|
+
.filter((entry) => entry.enabled)
|
|
67
|
+
.map((entry) => {
|
|
68
|
+
const supported = SCOUT_REASONING_EFFORTS.filter((effort) => entry.reasoningEfforts?.includes(effort)
|
|
69
|
+
|| entry.models.some((model) => model.enabled && model.reasoningEfforts?.includes(effort)));
|
|
70
|
+
return [entry.id, supported];
|
|
71
|
+
}));
|
|
72
|
+
/** Project one nested catalog into the flat API model list. */
|
|
73
|
+
export function scoutRuntimeModelCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
|
|
74
|
+
const models = new Map();
|
|
75
|
+
for (const harness of catalog.harnesses) {
|
|
76
|
+
if (!harness.enabled)
|
|
77
|
+
continue;
|
|
78
|
+
for (const model of harness.models) {
|
|
79
|
+
if (!model.enabled)
|
|
80
|
+
continue;
|
|
81
|
+
const existing = models.get(model.id);
|
|
82
|
+
if (existing) {
|
|
83
|
+
if (!existing.harnesses.includes(harness.id))
|
|
84
|
+
existing.harnesses.push(harness.id);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
models.set(model.id, {
|
|
88
|
+
id: model.id,
|
|
89
|
+
label: model.label,
|
|
90
|
+
...(model.description ? { description: model.description } : {}),
|
|
91
|
+
harnesses: [harness.id],
|
|
92
|
+
source: "default",
|
|
93
|
+
...(model.family ? { family: model.family } : {}),
|
|
94
|
+
...(model.version ? { version: model.version } : {}),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return Array.from(models.values());
|
|
99
|
+
}
|
|
100
|
+
/** Projections retained for API compatibility; SCOUT_RUNTIME_CATALOG owns them. */
|
|
101
|
+
export const SCOUT_RUNTIME_MODEL_CATALOG = scoutRuntimeModelCatalog();
|
|
102
|
+
const SCOUT_RUNTIME_EFFORT_DESCRIPTIONS = {
|
|
103
|
+
none: "No extra thinking",
|
|
104
|
+
minimal: "Smallest reasoning budget",
|
|
105
|
+
low: "Fast responses with lighter reasoning",
|
|
106
|
+
medium: "Balanced speed and reasoning depth",
|
|
107
|
+
high: "Greater reasoning depth for complex work",
|
|
108
|
+
xhigh: "Extra high reasoning depth",
|
|
109
|
+
max: "Maximum reasoning depth",
|
|
110
|
+
ultra: "Maximum reasoning with delegation",
|
|
111
|
+
};
|
|
112
|
+
export function scoutRuntimeEffortCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
|
|
113
|
+
return SCOUT_REASONING_EFFORTS.flatMap((id) => {
|
|
114
|
+
const harnesses = [];
|
|
115
|
+
const restrictedModels = [];
|
|
116
|
+
for (const harness of catalog.harnesses) {
|
|
117
|
+
if (!harness.enabled)
|
|
118
|
+
continue;
|
|
119
|
+
const enabledModels = harness.models.filter((model) => model.enabled);
|
|
120
|
+
const supportingModels = enabledModels.filter((model) => (model.reasoningEfforts ?? harness.reasoningEfforts)?.includes(id));
|
|
121
|
+
const supportedWithoutModel = enabledModels.length === 0 && harness.reasoningEfforts?.includes(id);
|
|
122
|
+
if (supportingModels.length === 0 && !supportedWithoutModel)
|
|
123
|
+
continue;
|
|
124
|
+
harnesses.push(harness.id);
|
|
125
|
+
if (enabledModels.length > 0 && supportingModels.length < enabledModels.length) {
|
|
126
|
+
restrictedModels.push(...supportingModels.map((model) => model.id));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (harnesses.length === 0)
|
|
130
|
+
return [];
|
|
131
|
+
return [{
|
|
132
|
+
id,
|
|
133
|
+
label: SCOUT_REASONING_EFFORT_LABELS[id],
|
|
134
|
+
description: SCOUT_RUNTIME_EFFORT_DESCRIPTIONS[id],
|
|
135
|
+
harnesses,
|
|
136
|
+
...(restrictedModels.length > 0 ? { models: restrictedModels } : {}),
|
|
137
|
+
}];
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
export const SCOUT_RUNTIME_EFFORT_CATALOG = scoutRuntimeEffortCatalog();
|
|
141
|
+
/** Canonical model aliases shared by every request boundary and spawn path. */
|
|
142
|
+
export function normalizeScoutRuntimeModel(harness, input) {
|
|
143
|
+
const requested = input.trim();
|
|
144
|
+
if (!requested) {
|
|
145
|
+
return { ok: false, requested, error: "model cannot be empty" };
|
|
146
|
+
}
|
|
147
|
+
const normalizedHarness = harness.trim().toLowerCase();
|
|
148
|
+
const lower = requested.toLowerCase();
|
|
149
|
+
if (normalizedHarness === "codex") {
|
|
150
|
+
if (lower === "5.6" || lower === "gpt-5.6") {
|
|
151
|
+
return { ok: true, requested, resolved: "gpt-5.6-sol" };
|
|
152
|
+
}
|
|
153
|
+
if (/^\d+(?:\.\d+)*(?:-[a-z0-9][a-z0-9._-]*)?$/u.test(lower)) {
|
|
154
|
+
return { ok: true, requested, resolved: `gpt-${lower}` };
|
|
155
|
+
}
|
|
156
|
+
return { ok: true, requested, resolved: requested };
|
|
157
|
+
}
|
|
158
|
+
if (normalizedHarness === "claude") {
|
|
159
|
+
const aliases = {
|
|
160
|
+
fable: "claude-fable-5",
|
|
161
|
+
opus: "claude-opus-5",
|
|
162
|
+
sonnet: "claude-sonnet-4-6",
|
|
163
|
+
haiku: "claude-haiku-4-5",
|
|
164
|
+
};
|
|
165
|
+
return { ok: true, requested, resolved: aliases[lower] ?? requested };
|
|
166
|
+
}
|
|
167
|
+
return { ok: true, requested, resolved: requested };
|
|
168
|
+
}
|
|
169
|
+
/** Parse the shell-safe `<harness>[/<model>[/<effort>]]` production. */
|
|
170
|
+
export function parseScoutRuntimeSpec(input) {
|
|
171
|
+
const raw = input.trim();
|
|
172
|
+
const parts = raw.split("/");
|
|
173
|
+
if (!raw || parts.length > 3 || parts.some((part) => !part.trim())) {
|
|
174
|
+
return {
|
|
175
|
+
ok: false,
|
|
176
|
+
error: "runtime must be <harness>[/<model>[/<effort>]]",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const harness = parts[0].trim().toLowerCase();
|
|
180
|
+
if (!isScoutLaunchableHarness(harness)) {
|
|
181
|
+
return {
|
|
182
|
+
ok: false,
|
|
183
|
+
error: `unsupported runtime harness "${parts[0]}"; expected one of: ${SCOUT_LAUNCHABLE_HARNESSES.join(", ")}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const model = parts[1]?.trim();
|
|
187
|
+
const effortRaw = parts[2]?.trim();
|
|
188
|
+
const reasoningEffort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
|
|
189
|
+
if (effortRaw && !reasoningEffort) {
|
|
190
|
+
return {
|
|
191
|
+
ok: false,
|
|
192
|
+
error: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const issues = validateScoutRuntimeTuple({ harness, model, reasoningEffort });
|
|
196
|
+
if (issues.length > 0) {
|
|
197
|
+
return { ok: false, error: issues.map((issue) => issue.message).join("; ") };
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
ok: true,
|
|
201
|
+
value: {
|
|
202
|
+
harness,
|
|
203
|
+
...(model ? { model } : {}),
|
|
204
|
+
...(reasoningEffort ? { reasoningEffort } : {}),
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
export function formatScoutRuntimeSpec(spec) {
|
|
209
|
+
if (spec.reasoningEffort && !spec.model) {
|
|
210
|
+
throw new Error("runtime literal cannot encode effort without a model; use --harness and --effort");
|
|
211
|
+
}
|
|
212
|
+
return [spec.harness, spec.model, spec.reasoningEffort]
|
|
213
|
+
.filter((part) => Boolean(part))
|
|
214
|
+
.join("/");
|
|
215
|
+
}
|
|
216
|
+
export function isScoutLaunchableHarness(value) {
|
|
217
|
+
return Boolean(value)
|
|
218
|
+
&& SCOUT_LAUNCHABLE_HARNESSES.includes(value.trim().toLowerCase());
|
|
219
|
+
}
|
|
220
|
+
export function normalizeScoutReasoningEffort(value) {
|
|
221
|
+
const normalized = value?.trim().toLowerCase();
|
|
222
|
+
return normalized && SCOUT_REASONING_EFFORTS.includes(normalized)
|
|
223
|
+
? normalized
|
|
224
|
+
: null;
|
|
225
|
+
}
|
|
226
|
+
export function runtimeDimensionResolution(input) {
|
|
227
|
+
const requested = input.requested?.trim() || undefined;
|
|
228
|
+
const resolved = input.resolved?.trim() || undefined;
|
|
229
|
+
const observed = input.observed?.trim() || undefined;
|
|
230
|
+
const drift = !observed || !resolved
|
|
231
|
+
? "unknown"
|
|
232
|
+
: observed.toLowerCase() === resolved.toLowerCase()
|
|
233
|
+
? "match"
|
|
234
|
+
: "mismatch";
|
|
235
|
+
return {
|
|
236
|
+
...(requested ? { requested } : {}),
|
|
237
|
+
...(resolved ? { resolved } : {}),
|
|
238
|
+
...(input.source && resolved ? { source: input.source } : {}),
|
|
239
|
+
...(observed ? { observed } : {}),
|
|
240
|
+
...(observed && input.observedAt !== undefined ? { observedAt: input.observedAt } : {}),
|
|
241
|
+
drift,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
export function createScoutExecutionResolution(input) {
|
|
245
|
+
const dimension = (key) => runtimeDimensionResolution({
|
|
246
|
+
requested: input.requested?.[key],
|
|
247
|
+
resolved: input.resolved?.[key],
|
|
248
|
+
source: input.source?.[key],
|
|
249
|
+
observed: input.observed?.[key],
|
|
250
|
+
observedAt: input.observedAt,
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
schemaVersion: "openscout.execution-resolution.v1",
|
|
254
|
+
harness: dimension("harness"),
|
|
255
|
+
model: dimension("model"),
|
|
256
|
+
reasoningEffort: dimension("reasoningEffort"),
|
|
257
|
+
...(input.sessionId?.trim() ? { sessionId: input.sessionId.trim() } : {}),
|
|
258
|
+
...(input.resolvedAt !== undefined ? { resolvedAt: input.resolvedAt } : {}),
|
|
259
|
+
...(input.observedAt !== undefined ? { observedAt: input.observedAt } : {}),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
export function validateScoutRuntimeTuple(input, catalog) {
|
|
263
|
+
const harness = input.harness?.trim().toLowerCase();
|
|
264
|
+
const model = input.model?.trim();
|
|
265
|
+
const effortRaw = input.reasoningEffort?.trim();
|
|
266
|
+
const issues = [];
|
|
267
|
+
if (harness && !isScoutLaunchableHarness(harness)) {
|
|
268
|
+
issues.push({
|
|
269
|
+
code: "unsupported_harness",
|
|
270
|
+
dimension: "harness",
|
|
271
|
+
message: `unsupported harness "${input.harness}"; expected one of: ${SCOUT_LAUNCHABLE_HARNESSES.join(", ")}`,
|
|
272
|
+
});
|
|
273
|
+
return issues;
|
|
274
|
+
}
|
|
275
|
+
const effort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
|
|
276
|
+
if (effortRaw && !effort) {
|
|
277
|
+
issues.push({
|
|
278
|
+
code: "unsupported_reasoning_effort",
|
|
279
|
+
dimension: "reasoningEffort",
|
|
280
|
+
message: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else if (effort && harness) {
|
|
284
|
+
const catalogEffort = catalog?.efforts.find((candidate) => candidate.id === effort);
|
|
285
|
+
let supported = catalogEffort
|
|
286
|
+
? catalogEffort.harnesses.includes(harness)
|
|
287
|
+
: (scoutRuntimeReasoningEfforts(harness, model) ?? []).includes(effort);
|
|
288
|
+
if (supported && catalogEffort?.models?.length && model) {
|
|
289
|
+
const harnessModels = new Set(catalog?.models
|
|
290
|
+
.filter((candidate) => candidate.harnesses.includes(harness))
|
|
291
|
+
.map((candidate) => candidate.id.toLowerCase()) ?? []);
|
|
292
|
+
const scopedModels = catalogEffort.models.filter((candidate) => (harnessModels.has(candidate.toLowerCase())));
|
|
293
|
+
if (harnessModels.has(model.toLowerCase()) && scopedModels.length > 0) {
|
|
294
|
+
supported = scopedModels.some((candidate) => candidate.toLowerCase() === model.toLowerCase());
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (!supported) {
|
|
298
|
+
issues.push({
|
|
299
|
+
code: "reasoning_effort_harness_mismatch",
|
|
300
|
+
dimension: "reasoningEffort",
|
|
301
|
+
message: `reasoning effort "${effort}" is not supported by harness "${harness}"`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const modelSelectableHarness = harness === "claude"
|
|
306
|
+
|| harness === "codex"
|
|
307
|
+
|| harness === "grok"
|
|
308
|
+
|| harness === "grok-acp";
|
|
309
|
+
if (model && harness && !modelSelectableHarness) {
|
|
310
|
+
issues.push({
|
|
311
|
+
code: "unsupported_model_dimension",
|
|
312
|
+
dimension: "model",
|
|
313
|
+
message: `model selection is not supported by harness "${harness}"`,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else if (model && harness && catalog) {
|
|
317
|
+
const known = catalog.models.find((candidate) => candidate.id.toLowerCase() === model.toLowerCase());
|
|
318
|
+
if (known && !known.harnesses.includes(harness)) {
|
|
319
|
+
issues.push({
|
|
320
|
+
code: "model_harness_mismatch",
|
|
321
|
+
dimension: "model",
|
|
322
|
+
message: `model "${model}" is not supported by harness "${harness}"`,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return issues;
|
|
327
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ScoutReasoningEffort } from "./runtime-execution.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reserved natural-language profile names. Their execution definitions stay
|
|
4
|
+
* broker-owned; clients use this list only to recognize unambiguous syntax.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SCOUT_RESERVED_RUNTIME_PROFILE_IDS: readonly ["fable", "kimi", "grok", "opus"];
|
|
7
|
+
export type ScoutReservedRuntimeProfileId = (typeof SCOUT_RESERVED_RUNTIME_PROFILE_IDS)[number];
|
|
8
|
+
export declare const SCOUT_RUNTIME_PROFILE_REASONING_EFFORTS: readonly ["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"];
|
|
9
|
+
export type ScoutRuntimeProfileReasoningEffort = ScoutReasoningEffort;
|
|
10
|
+
export declare function normalizeReservedRuntimeProfileId(value: string): ScoutReservedRuntimeProfileId | null;
|
|
11
|
+
export declare function normalizeRuntimeProfileReasoningEffort(value: string): ScoutRuntimeProfileReasoningEffort | null;
|
|
12
|
+
//# sourceMappingURL=runtime-profiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-profiles.d.ts","sourceRoot":"","sources":["../src/runtime-profiles.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,kCAAkC,4CAKrC,CAAC;AAEX,MAAM,MAAM,6BAA6B,GACvC,CAAC,OAAO,kCAAkC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,eAAO,MAAM,uCAAuC,gFAA0B,CAAC;AAE/E,MAAM,MAAM,kCAAkC,GAAG,oBAAoB,CAAC;AAEtE,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,MAAM,GACZ,6BAA6B,GAAG,IAAI,CAGtC;AAED,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,MAAM,GACZ,kCAAkC,GAAG,IAAI,CAE3C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { normalizeAgentSelectorSegment } from "./agent-identity.js";
|
|
2
|
+
import { normalizeScoutReasoningEffort, SCOUT_REASONING_EFFORTS, } from "./runtime-execution.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reserved natural-language profile names. Their execution definitions stay
|
|
5
|
+
* broker-owned; clients use this list only to recognize unambiguous syntax.
|
|
6
|
+
*/
|
|
7
|
+
export const SCOUT_RESERVED_RUNTIME_PROFILE_IDS = [
|
|
8
|
+
"fable",
|
|
9
|
+
"kimi",
|
|
10
|
+
"grok",
|
|
11
|
+
"opus",
|
|
12
|
+
];
|
|
13
|
+
export const SCOUT_RUNTIME_PROFILE_REASONING_EFFORTS = SCOUT_REASONING_EFFORTS;
|
|
14
|
+
export function normalizeReservedRuntimeProfileId(value) {
|
|
15
|
+
const normalized = normalizeAgentSelectorSegment(value);
|
|
16
|
+
return SCOUT_RESERVED_RUNTIME_PROFILE_IDS.find((id) => id === normalized) ?? null;
|
|
17
|
+
}
|
|
18
|
+
export function normalizeRuntimeProfileReasoningEffort(value) {
|
|
19
|
+
return normalizeScoutReasoningEffort(normalizeAgentSelectorSegment(value));
|
|
20
|
+
}
|
|
@@ -39,6 +39,14 @@ export interface ScoutReturnAddress {
|
|
|
39
39
|
sessionId?: string;
|
|
40
40
|
metadata?: MetadataMap;
|
|
41
41
|
}
|
|
42
|
+
export interface ScoutAgentCardLifecycle {
|
|
43
|
+
kind: "persistent" | "one_time";
|
|
44
|
+
createdAt?: number;
|
|
45
|
+
createdById?: ScoutId;
|
|
46
|
+
expiresAt?: number;
|
|
47
|
+
maxUses?: number;
|
|
48
|
+
inboxConversationId?: ScoutId;
|
|
49
|
+
}
|
|
42
50
|
/**
|
|
43
51
|
* Scout's local discovery and routing card for one addressable agent target.
|
|
44
52
|
*
|
|
@@ -75,7 +83,9 @@ export interface ScoutAgentCard {
|
|
|
75
83
|
createdById?: ScoutId;
|
|
76
84
|
brokerRegistered: boolean;
|
|
77
85
|
inboxConversationId?: ScoutId;
|
|
86
|
+
lifecycle?: ScoutAgentCardLifecycle;
|
|
78
87
|
returnAddress: ScoutReturnAddress;
|
|
79
88
|
metadata?: MetadataMap;
|
|
80
89
|
}
|
|
81
90
|
export declare function buildScoutReturnAddress(input: ScoutReturnAddress): ScoutReturnAddress;
|
|
91
|
+
//# sourceMappingURL=scout-agent-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scout-agent-card.d.ts","sourceRoot":"","sources":["../src/scout-agent-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ScoutRouteTarget } from "./scout-dispatch.js";
|
|
2
|
+
export declare const SCOUT_COMPOSER_ROUTE_OPERATOR: ">>";
|
|
3
|
+
export declare const SCOUT_TARGET_HANDLE_SHORTHAND: "\u2316";
|
|
4
|
+
export type ScoutComposerRouteDiagnosticCode = "missing_target" | "invalid_target";
|
|
5
|
+
export interface ScoutComposerRouteDiagnostic {
|
|
6
|
+
code: ScoutComposerRouteDiagnosticCode;
|
|
7
|
+
message: string;
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ScoutComposerRoute {
|
|
12
|
+
operator: typeof SCOUT_COMPOSER_ROUTE_OPERATOR;
|
|
13
|
+
token: string;
|
|
14
|
+
target: ScoutRouteTarget;
|
|
15
|
+
operatorStart: number;
|
|
16
|
+
operatorEnd: number;
|
|
17
|
+
targetStart: number;
|
|
18
|
+
targetEnd: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ScoutComposerRouteParseResult {
|
|
21
|
+
route: ScoutComposerRoute | null;
|
|
22
|
+
body: string;
|
|
23
|
+
diagnostics: ScoutComposerRouteDiagnostic[];
|
|
24
|
+
}
|
|
25
|
+
export declare function parseScoutComposerRouteTarget(value: string): ScoutRouteTarget | null;
|
|
26
|
+
export declare function parseScoutComposerRoute(input: string): ScoutComposerRouteParseResult;
|
|
27
|
+
//# sourceMappingURL=scout-composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scout-composer.d.ts","sourceRoot":"","sources":["../src/scout-composer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,eAAO,MAAM,6BAA6B,EAAG,IAAa,CAAC;AAC3D,eAAO,MAAM,6BAA6B,EAAG,QAAY,CAAC;AAE1D,MAAM,MAAM,gCAAgC,GACxC,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,6BAA6B,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,4BAA4B,EAAE,CAAC;CAC7C;AA+HD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAyBpF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,6BAA6B,CA8DpF"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { parseAgentIdentity } from "./agent-identity.js";
|
|
2
|
+
import { AGENT_HARNESSES } from "./actors.js";
|
|
3
|
+
export const SCOUT_COMPOSER_ROUTE_OPERATOR = ">>";
|
|
4
|
+
export const SCOUT_TARGET_HANDLE_SHORTHAND = "⌖";
|
|
5
|
+
const WHITESPACE_PATTERN = /\s/;
|
|
6
|
+
const TRAILING_TARGET_PUNCTUATION_PATTERN = /[.,!?;)\]}]+$/;
|
|
7
|
+
const ROUTE_VALUE_PATTERN = /^\S+$/;
|
|
8
|
+
const AGENT_LABEL_START_PATTERN = /^[A-Za-z0-9]/;
|
|
9
|
+
const SESSION_ROUTE_HARNESSES = new Set(AGENT_HARNESSES);
|
|
10
|
+
function findRouteOperator(input) {
|
|
11
|
+
let searchFrom = 0;
|
|
12
|
+
while (searchFrom < input.length) {
|
|
13
|
+
const index = input.indexOf(SCOUT_COMPOSER_ROUTE_OPERATOR, searchFrom);
|
|
14
|
+
if (index === -1) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const previous = index > 0 ? input[index - 1] : "";
|
|
18
|
+
if (index === 0 || WHITESPACE_PATTERN.test(previous)) {
|
|
19
|
+
return {
|
|
20
|
+
start: index,
|
|
21
|
+
end: index + SCOUT_COMPOSER_ROUTE_OPERATOR.length,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
searchFrom = index + SCOUT_COMPOSER_ROUTE_OPERATOR.length;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function routeBodyWithoutTarget(input, start, end) {
|
|
29
|
+
return `${input.slice(0, start)} ${input.slice(end)}`.replace(/\s+/g, " ").trim();
|
|
30
|
+
}
|
|
31
|
+
function trimRouteTargetToken(value) {
|
|
32
|
+
return value
|
|
33
|
+
.trim()
|
|
34
|
+
.replace(TRAILING_TARGET_PUNCTUATION_PATTERN, "");
|
|
35
|
+
}
|
|
36
|
+
function isRouteValue(value) {
|
|
37
|
+
return value.length > 0 && ROUTE_VALUE_PATTERN.test(value);
|
|
38
|
+
}
|
|
39
|
+
function parseAgentLabelTarget(value) {
|
|
40
|
+
const label = value.replace(/^@+/, "");
|
|
41
|
+
if (!AGENT_LABEL_START_PATTERN.test(label)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
if (!parseAgentIdentity(label)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return { kind: "agent_label", label, value };
|
|
48
|
+
}
|
|
49
|
+
function parseTargetHandleTarget(rawValue) {
|
|
50
|
+
const handle = rawValue.replace(/^[@⌖]+/, "");
|
|
51
|
+
if (!isRouteValue(handle)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return { kind: "target_handle", handle, value: `target:${handle}` };
|
|
55
|
+
}
|
|
56
|
+
function parseRouteAliasTarget(rawValue) {
|
|
57
|
+
const alias = rawValue.replace(/^@+/, "").trim().toLowerCase();
|
|
58
|
+
if (!isRouteValue(alias))
|
|
59
|
+
return null;
|
|
60
|
+
return { kind: "route_alias", alias, value: `alias:${alias}` };
|
|
61
|
+
}
|
|
62
|
+
function parseSessionRouteTarget(rawValue) {
|
|
63
|
+
const value = rawValue.replace(/^@+/, "");
|
|
64
|
+
if (!isRouteValue(value)) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const harnessSeparator = value.indexOf(":");
|
|
68
|
+
if (harnessSeparator > 0) {
|
|
69
|
+
const maybeHarness = value.slice(0, harnessSeparator);
|
|
70
|
+
const sessionId = value.slice(harnessSeparator + 1);
|
|
71
|
+
if (SESSION_ROUTE_HARNESSES.has(maybeHarness) && isRouteValue(sessionId)) {
|
|
72
|
+
return {
|
|
73
|
+
kind: "session_id",
|
|
74
|
+
sessionId,
|
|
75
|
+
harness: maybeHarness,
|
|
76
|
+
value: `session:${maybeHarness}:${sessionId}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { kind: "session_id", sessionId: value, value: `session:${value}` };
|
|
81
|
+
}
|
|
82
|
+
function parsePrefixedRouteTarget(prefix, rawValue) {
|
|
83
|
+
const value = rawValue.replace(/^@+/, "");
|
|
84
|
+
if (!isRouteValue(value)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (prefix === "agent" || prefix === "a") {
|
|
88
|
+
return parseAgentLabelTarget(value);
|
|
89
|
+
}
|
|
90
|
+
if (prefix === "alias" || prefix === "route-alias" || prefix === "route_alias") {
|
|
91
|
+
return parseRouteAliasTarget(rawValue);
|
|
92
|
+
}
|
|
93
|
+
if (prefix === "target" || prefix === "target-handle" || prefix === "target_handle") {
|
|
94
|
+
return parseTargetHandleTarget(rawValue);
|
|
95
|
+
}
|
|
96
|
+
if (prefix === "ref" || prefix === "binding" || prefix === "binding-ref") {
|
|
97
|
+
return { kind: "binding_ref", ref: value, value: `ref:${value}` };
|
|
98
|
+
}
|
|
99
|
+
if (prefix === "project" || prefix === "project-path" || prefix === "project_path") {
|
|
100
|
+
return { kind: "project_path", projectPath: value, value: `project:${value}` };
|
|
101
|
+
}
|
|
102
|
+
if (prefix === "id" || prefix === "agent-id" || prefix === "agent_id") {
|
|
103
|
+
return { kind: "agent_id", agentId: value, value: `id:${value}` };
|
|
104
|
+
}
|
|
105
|
+
if (prefix === "session" || prefix === "session-id" || prefix === "session_id" || prefix === "sid" || prefix === "s") {
|
|
106
|
+
return parseSessionRouteTarget(rawValue);
|
|
107
|
+
}
|
|
108
|
+
if (prefix === "channel" || prefix === "chan" || prefix === "ch") {
|
|
109
|
+
return { kind: "channel", channel: value, value: `channel:${value}` };
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
export function parseScoutComposerRouteTarget(value) {
|
|
114
|
+
const token = trimRouteTargetToken(value);
|
|
115
|
+
if (!isRouteValue(token)) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (token === "broadcast") {
|
|
119
|
+
return { kind: "broadcast", value: token };
|
|
120
|
+
}
|
|
121
|
+
if (token.startsWith(SCOUT_TARGET_HANDLE_SHORTHAND)) {
|
|
122
|
+
return parseTargetHandleTarget(token);
|
|
123
|
+
}
|
|
124
|
+
const separatorIndex = token.indexOf(":");
|
|
125
|
+
if (separatorIndex > 0) {
|
|
126
|
+
const prefix = token.slice(0, separatorIndex).toLowerCase();
|
|
127
|
+
const rawValue = token.slice(separatorIndex + 1);
|
|
128
|
+
const prefixed = parsePrefixedRouteTarget(prefix, rawValue);
|
|
129
|
+
if (prefixed) {
|
|
130
|
+
return prefixed;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return parseAgentLabelTarget(token);
|
|
134
|
+
}
|
|
135
|
+
export function parseScoutComposerRoute(input) {
|
|
136
|
+
const operator = findRouteOperator(input);
|
|
137
|
+
if (!operator) {
|
|
138
|
+
return {
|
|
139
|
+
route: null,
|
|
140
|
+
body: input.trim(),
|
|
141
|
+
diagnostics: [],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
let targetStart = operator.end;
|
|
145
|
+
while (targetStart < input.length && WHITESPACE_PATTERN.test(input[targetStart] ?? "")) {
|
|
146
|
+
targetStart += 1;
|
|
147
|
+
}
|
|
148
|
+
if (targetStart >= input.length) {
|
|
149
|
+
return {
|
|
150
|
+
route: null,
|
|
151
|
+
body: routeBodyWithoutTarget(input, operator.start, operator.end),
|
|
152
|
+
diagnostics: [{
|
|
153
|
+
code: "missing_target",
|
|
154
|
+
message: "route operator requires a target after >>",
|
|
155
|
+
start: operator.start,
|
|
156
|
+
end: operator.end,
|
|
157
|
+
}],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
let targetEnd = targetStart;
|
|
161
|
+
while (targetEnd < input.length && !WHITESPACE_PATTERN.test(input[targetEnd] ?? "")) {
|
|
162
|
+
targetEnd += 1;
|
|
163
|
+
}
|
|
164
|
+
const rawToken = input.slice(targetStart, targetEnd);
|
|
165
|
+
const token = trimRouteTargetToken(rawToken);
|
|
166
|
+
const target = parseScoutComposerRouteTarget(token);
|
|
167
|
+
if (!target) {
|
|
168
|
+
return {
|
|
169
|
+
route: null,
|
|
170
|
+
body: routeBodyWithoutTarget(input, operator.start, targetEnd),
|
|
171
|
+
diagnostics: [{
|
|
172
|
+
code: "invalid_target",
|
|
173
|
+
message: `invalid route target: ${rawToken}`,
|
|
174
|
+
start: targetStart,
|
|
175
|
+
end: targetEnd,
|
|
176
|
+
}],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
route: {
|
|
181
|
+
operator: SCOUT_COMPOSER_ROUTE_OPERATOR,
|
|
182
|
+
token,
|
|
183
|
+
target,
|
|
184
|
+
operatorStart: operator.start,
|
|
185
|
+
operatorEnd: operator.end,
|
|
186
|
+
targetStart,
|
|
187
|
+
targetEnd,
|
|
188
|
+
},
|
|
189
|
+
body: routeBodyWithoutTarget(input, operator.start, targetEnd),
|
|
190
|
+
diagnostics: [],
|
|
191
|
+
};
|
|
192
|
+
}
|