@m8t-stack/cli 0.2.81 → 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/dist/cli.js +479 -54
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -229,10 +229,77 @@ var init_agent_roster = __esm({
|
|
|
229
229
|
});
|
|
230
230
|
|
|
231
231
|
// ../../packages/api-contract/dist/esm/ui-directive.js
|
|
232
|
-
|
|
232
|
+
function parseArgs(input) {
|
|
233
|
+
if (!isRecord(input) || !nonEmpty(input.title) || !Array.isArray(input.options))
|
|
234
|
+
return null;
|
|
235
|
+
const { options } = input;
|
|
236
|
+
if (options.length < MIN_OPTIONS || options.length > MAX_OPTIONS)
|
|
237
|
+
return null;
|
|
238
|
+
const parsed = [];
|
|
239
|
+
for (const option of options) {
|
|
240
|
+
if (!isRecord(option) || !nonEmpty(option.label) || !nonEmpty(option.detail))
|
|
241
|
+
return null;
|
|
242
|
+
parsed.push({ label: option.label, detail: option.detail });
|
|
243
|
+
}
|
|
244
|
+
return { title: input.title, options: parsed };
|
|
245
|
+
}
|
|
246
|
+
function parseState(input, optionCount) {
|
|
247
|
+
if (!isRecord(input))
|
|
248
|
+
return null;
|
|
249
|
+
switch (input.status) {
|
|
250
|
+
case "pending":
|
|
251
|
+
return { status: "pending" };
|
|
252
|
+
case "dismissed":
|
|
253
|
+
return { status: "dismissed" };
|
|
254
|
+
case "submitting":
|
|
255
|
+
return inRange(input.optionIndex, optionCount) ? { status: "submitting", optionIndex: input.optionIndex } : null;
|
|
256
|
+
case "selected":
|
|
257
|
+
if (!inRange(input.optionIndex, optionCount))
|
|
258
|
+
return null;
|
|
259
|
+
return input.acknowledgement === "pending" || input.acknowledgement === "complete" || input.acknowledgement === "error" ? { status: "selected", optionIndex: input.optionIndex, acknowledgement: input.acknowledgement } : null;
|
|
260
|
+
case "error":
|
|
261
|
+
return nonEmpty(input.message) ? { status: "error", message: input.message } : null;
|
|
262
|
+
default:
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function parseUiDirectiveFrame(input) {
|
|
267
|
+
if (!isRecord(input))
|
|
268
|
+
return null;
|
|
269
|
+
if (input.source !== "voice" && input.source !== "text")
|
|
270
|
+
return null;
|
|
271
|
+
const directive = input.directive;
|
|
272
|
+
if (!isRecord(directive))
|
|
273
|
+
return null;
|
|
274
|
+
if (directive.version !== 1 || directive.name !== "present_decision")
|
|
275
|
+
return null;
|
|
276
|
+
if (!nonEmpty(directive.callId))
|
|
277
|
+
return null;
|
|
278
|
+
const args = parseArgs(directive.args);
|
|
279
|
+
if (!args)
|
|
280
|
+
return null;
|
|
281
|
+
const state = parseState(directive.state, args.options.length);
|
|
282
|
+
if (!state)
|
|
283
|
+
return null;
|
|
284
|
+
return {
|
|
285
|
+
directive: { version: 1, name: "present_decision", callId: directive.callId, args, state },
|
|
286
|
+
source: input.source
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function isDecisionRefusalReason(value) {
|
|
290
|
+
return typeof value === "string" && decisionRefusalReasons.includes(value);
|
|
291
|
+
}
|
|
292
|
+
var UI_DIRECTIVE_PART_TYPE, MIN_OPTIONS, MAX_OPTIONS, isRecord, nonEmpty, inRange, UI_DIRECTIVE_RESULT_PART_TYPE, DECISION_REFUSAL_REASONS, decisionRefusalReasons;
|
|
233
293
|
var init_ui_directive = __esm({
|
|
234
294
|
"../../packages/api-contract/dist/esm/ui-directive.js"() {
|
|
235
295
|
"use strict";
|
|
296
|
+
UI_DIRECTIVE_PART_TYPE = "data-ui-directive";
|
|
297
|
+
MIN_OPTIONS = 2;
|
|
298
|
+
MAX_OPTIONS = 4;
|
|
299
|
+
isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
300
|
+
nonEmpty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
301
|
+
inRange = (value, count) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value < count;
|
|
302
|
+
UI_DIRECTIVE_RESULT_PART_TYPE = "data-ui-result";
|
|
236
303
|
DECISION_REFUSAL_REASONS = {
|
|
237
304
|
/** 409 — no live call with that `callId`. Answered twice, or talked past and dismissed. */
|
|
238
305
|
notPending: "decision_not_pending",
|
|
@@ -1400,7 +1467,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1400
1467
|
import { Builtins, Cli } from "clipanion";
|
|
1401
1468
|
|
|
1402
1469
|
// src/lib/package-version.ts
|
|
1403
|
-
var CLI_VERSION = "0.2.
|
|
1470
|
+
var CLI_VERSION = "0.2.82";
|
|
1404
1471
|
|
|
1405
1472
|
// src/lib/render-error.ts
|
|
1406
1473
|
init_errors();
|
|
@@ -12728,6 +12795,25 @@ function classifyFoundryError(err) {
|
|
|
12728
12795
|
return { category: "unknown", retryable: false, status, message };
|
|
12729
12796
|
}
|
|
12730
12797
|
|
|
12798
|
+
// ../../packages/foundry-invoke/dist/esm/artifacts.js
|
|
12799
|
+
var FENCE_RE = /```json m8t:artifacts\s*\n([\s\S]*?)\n```/;
|
|
12800
|
+
function parseArtifacts(raw) {
|
|
12801
|
+
const text = raw;
|
|
12802
|
+
const m = FENCE_RE.exec(text);
|
|
12803
|
+
if (!m)
|
|
12804
|
+
return { text: text.trimEnd(), artifacts: [] };
|
|
12805
|
+
let artifacts = [];
|
|
12806
|
+
try {
|
|
12807
|
+
const parsed = JSON.parse(m[1]);
|
|
12808
|
+
if (Array.isArray(parsed))
|
|
12809
|
+
artifacts = parsed;
|
|
12810
|
+
} catch {
|
|
12811
|
+
artifacts = [];
|
|
12812
|
+
}
|
|
12813
|
+
const clean2 = text.slice(0, m.index).trimEnd();
|
|
12814
|
+
return { text: clean2, artifacts };
|
|
12815
|
+
}
|
|
12816
|
+
|
|
12731
12817
|
// src/lib/render-error.ts
|
|
12732
12818
|
function renderHint(hint) {
|
|
12733
12819
|
return hint.split("\n").join("\n ");
|
|
@@ -26708,7 +26794,7 @@ var str3 = (v) => {
|
|
|
26708
26794
|
return "";
|
|
26709
26795
|
};
|
|
26710
26796
|
var req = (v, fallback = "") => str3(v) ?? fallback;
|
|
26711
|
-
function
|
|
26797
|
+
function parseArtifacts2(v) {
|
|
26712
26798
|
if (typeof v !== "string" || v === "")
|
|
26713
26799
|
return void 0;
|
|
26714
26800
|
try {
|
|
@@ -26742,7 +26828,7 @@ function mapEntity(e) {
|
|
|
26742
26828
|
delegationId: str3(e.delegationId),
|
|
26743
26829
|
parentEventId: str3(e.parentEventId),
|
|
26744
26830
|
depth: e.depth == null ? void 0 : Number(e.depth),
|
|
26745
|
-
artifacts:
|
|
26831
|
+
artifacts: parseArtifacts2(e.artifacts)
|
|
26746
26832
|
};
|
|
26747
26833
|
}
|
|
26748
26834
|
var rank = (o) => o === "ok" ? 0 : 1;
|
|
@@ -30728,7 +30814,7 @@ var ONBOARDING_BLOCK_KEYS = [
|
|
|
30728
30814
|
"advisor_name",
|
|
30729
30815
|
"advisor_email"
|
|
30730
30816
|
];
|
|
30731
|
-
function
|
|
30817
|
+
function isRecord2(value) {
|
|
30732
30818
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30733
30819
|
}
|
|
30734
30820
|
function hasValidUniqueJsonKeys(source) {
|
|
@@ -30836,7 +30922,7 @@ var V3_COMPANY_KEYS = ["name", "one_liner"];
|
|
|
30836
30922
|
var V3_ADDRESS_KEYS = ["address", "city", "postal_code", "country"];
|
|
30837
30923
|
var V3_REQUEST_KEYS = ["type", "model", "region", "consent", "company_address"];
|
|
30838
30924
|
function exactStringRecord(value, keys) {
|
|
30839
|
-
if (!
|
|
30925
|
+
if (!isRecord2(value)) return "non-string-value";
|
|
30840
30926
|
const present = new Set(Object.keys(value));
|
|
30841
30927
|
for (const key2 of keys) if (!present.has(key2)) return "missing-key";
|
|
30842
30928
|
if (present.size !== keys.length) return "unexpected-key";
|
|
@@ -30848,7 +30934,7 @@ function canonicalPendingRequests(value) {
|
|
|
30848
30934
|
if (value.length > 1) return { ok: false, reason: "too-many-pending-requests" };
|
|
30849
30935
|
const requests = [];
|
|
30850
30936
|
for (const entry of value) {
|
|
30851
|
-
if (!
|
|
30937
|
+
if (!isRecord2(entry)) return { ok: false, reason: "non-string-value" };
|
|
30852
30938
|
const present = new Set(Object.keys(entry));
|
|
30853
30939
|
for (const key2 of V3_REQUEST_KEYS) {
|
|
30854
30940
|
if (!present.has(key2)) return { ok: false, reason: "missing-key" };
|
|
@@ -30898,7 +30984,7 @@ function canonicalV3Block(value) {
|
|
|
30898
30984
|
};
|
|
30899
30985
|
}
|
|
30900
30986
|
function canonicalBlock(value) {
|
|
30901
|
-
if (!
|
|
30987
|
+
if (!isRecord2(value)) return { ok: false, reason: "non-string-value" };
|
|
30902
30988
|
if (value.schema_version === "3") return canonicalV3Block(value);
|
|
30903
30989
|
if (value.schema_version !== "2") return { ok: false, reason: "unknown-schema-version" };
|
|
30904
30990
|
const keys = new Set(Object.keys(value));
|
|
@@ -30943,7 +31029,7 @@ function parseOnboardingArtifactResult(machineText) {
|
|
|
30943
31029
|
if (json.includes("m8t_onboarding")) return { ok: false, reason: "malformed-json" };
|
|
30944
31030
|
continue;
|
|
30945
31031
|
}
|
|
30946
|
-
if (!
|
|
31032
|
+
if (!isRecord2(parsed) || !Object.hasOwn(parsed, "m8t_onboarding")) continue;
|
|
30947
31033
|
if (Object.keys(parsed).length !== 1) return { ok: false, reason: "unexpected-key" };
|
|
30948
31034
|
const outcome = canonicalBlock(parsed.m8t_onboarding);
|
|
30949
31035
|
if (!outcome.ok) return outcome;
|
|
@@ -30989,7 +31075,7 @@ async function readCursorPages(args) {
|
|
|
30989
31075
|
} catch {
|
|
30990
31076
|
return null;
|
|
30991
31077
|
}
|
|
30992
|
-
if (!
|
|
31078
|
+
if (!isRecord2(body) || !Array.isArray(body.data)) return null;
|
|
30993
31079
|
const page = body;
|
|
30994
31080
|
all.push(...page.data);
|
|
30995
31081
|
if (page.has_more !== true) {
|
|
@@ -31010,7 +31096,7 @@ function decodeFoundryUser(token) {
|
|
|
31010
31096
|
if (parts.length !== 3 || parts.some((part) => part.length === 0) || !/^[A-Za-z0-9_-]+$/.test(parts[1] ?? "")) return null;
|
|
31011
31097
|
try {
|
|
31012
31098
|
const payload = JSON.parse(Buffer.from(parts[1] ?? "", "base64url").toString("utf8"));
|
|
31013
|
-
if (!
|
|
31099
|
+
if (!isRecord2(payload)) return null;
|
|
31014
31100
|
const claim = payload.upn ?? payload.preferred_username ?? payload.email;
|
|
31015
31101
|
return typeof claim === "string" && claim.trim().length > 0 ? claim : null;
|
|
31016
31102
|
} catch {
|
|
@@ -31041,7 +31127,7 @@ async function findOnboardingProfile(args) {
|
|
|
31041
31127
|
});
|
|
31042
31128
|
if (!listed) return { ...EMPTY_PROFILE_RESULT };
|
|
31043
31129
|
const conversations = orderNewest(listed.flatMap((value, ordinal) => {
|
|
31044
|
-
if (!
|
|
31130
|
+
if (!isRecord2(value) || typeof value.id !== "string" || value.id.length === 0 || !isRecord2(value.metadata)) return [];
|
|
31045
31131
|
const metadata = value.metadata;
|
|
31046
31132
|
if (metadata.app !== "m8t-webapp" || metadata.agent !== INTAKE_AGENT_NAME) return [];
|
|
31047
31133
|
return [{
|
|
@@ -31059,7 +31145,7 @@ async function findOnboardingProfile(args) {
|
|
|
31059
31145
|
});
|
|
31060
31146
|
if (!items) return { hadIntake: true, block: null, machineText: null, speechText: null, rejection: null };
|
|
31061
31147
|
const assistantItems = orderNewest(items.flatMap((value, ordinal) => {
|
|
31062
|
-
if (!
|
|
31148
|
+
if (!isRecord2(value) || value.type !== "message" || value.role !== "assistant" || !Array.isArray(value.content)) return [];
|
|
31063
31149
|
const id = typeof value.id === "string" ? value.id : "";
|
|
31064
31150
|
return [{ value, id, createdAt: timestamp(value.created_at), ordinal }];
|
|
31065
31151
|
}));
|
|
@@ -31068,7 +31154,7 @@ async function findOnboardingProfile(args) {
|
|
|
31068
31154
|
for (const item of assistantItems) {
|
|
31069
31155
|
const content = item.value.content;
|
|
31070
31156
|
const machineText = content.flatMap((part) => {
|
|
31071
|
-
if (!
|
|
31157
|
+
if (!isRecord2(part)) return [];
|
|
31072
31158
|
if (typeof part.text === "string" && part.text.length > 0) return [part.text];
|
|
31073
31159
|
if (typeof part.transcript === "string") return [part.transcript];
|
|
31074
31160
|
return [];
|
|
@@ -34571,6 +34657,14 @@ var COMPANION_HISTORY_LIMIT_MAX = 40;
|
|
|
34571
34657
|
var COMPANION_TURN_TEXT_MAX_CODE_POINTS = 32768;
|
|
34572
34658
|
var COMPANION_REPLY_DELTA_MAX_CODE_POINTS = 4096;
|
|
34573
34659
|
var COMPANION_TURN_ID_MAX_LENGTH = 256;
|
|
34660
|
+
var COMPANION_DECISION_CALL_ID_MAX_LENGTH = 256;
|
|
34661
|
+
var COMPANION_DECISION_TITLE_MAX_LENGTH = 200;
|
|
34662
|
+
var COMPANION_DECISION_LABEL_MAX_LENGTH = 100;
|
|
34663
|
+
var COMPANION_DECISION_DETAIL_MAX_CODE_POINTS = 400;
|
|
34664
|
+
var COMPANION_DECISION_OPTIONS_MIN = 2;
|
|
34665
|
+
var COMPANION_DECISION_OPTIONS_MAX = 4;
|
|
34666
|
+
var COMPANION_ARTIFACT_NAME_MAX_LENGTH = 200;
|
|
34667
|
+
var COMPANION_ARTIFACTS_MAX = 16;
|
|
34574
34668
|
var PERSONAS = /* @__PURE__ */ new Set([
|
|
34575
34669
|
"startup-advisor",
|
|
34576
34670
|
"ezra"
|
|
@@ -34580,7 +34674,8 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
|
34580
34674
|
"not-authorized",
|
|
34581
34675
|
"mate-unavailable",
|
|
34582
34676
|
"busy",
|
|
34583
|
-
"bad-request"
|
|
34677
|
+
"bad-request",
|
|
34678
|
+
"decision-not-pending"
|
|
34584
34679
|
]);
|
|
34585
34680
|
var CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/u;
|
|
34586
34681
|
var URL_SAFE_OPAQUE_ID = /^[A-Za-z0-9_-]+$/u;
|
|
@@ -34589,7 +34684,7 @@ var VERSION3 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,63}$/u;
|
|
|
34589
34684
|
function isVersionOrNull(value) {
|
|
34590
34685
|
return value === null || typeof value === "string" && VERSION3.test(value);
|
|
34591
34686
|
}
|
|
34592
|
-
function
|
|
34687
|
+
function isRecord3(value) {
|
|
34593
34688
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34594
34689
|
}
|
|
34595
34690
|
function hasExactKeys(value, keys) {
|
|
@@ -34613,8 +34708,72 @@ var INSTANT_SHAPE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/;
|
|
|
34613
34708
|
function isInstantOrNull(value) {
|
|
34614
34709
|
return value === null || typeof value === "string" && INSTANT_SHAPE.test(value) && Number.isFinite(Date.parse(value));
|
|
34615
34710
|
}
|
|
34616
|
-
function
|
|
34617
|
-
|
|
34711
|
+
function parseDecision(value) {
|
|
34712
|
+
if (!isRecord3(value) || !isBoundedPlainString(value.callId, COMPANION_DECISION_CALL_ID_MAX_LENGTH) || !isBoundedPlainString(value.title, COMPANION_DECISION_TITLE_MAX_LENGTH) || !Array.isArray(value.options) || value.options.length < COMPANION_DECISION_OPTIONS_MIN || value.options.length > COMPANION_DECISION_OPTIONS_MAX) {
|
|
34713
|
+
return eventError();
|
|
34714
|
+
}
|
|
34715
|
+
const options = value.options.map((option) => {
|
|
34716
|
+
if (!isRecord3(option) || !hasExactKeys(option, ["label", "detail"]) || !isBoundedPlainString(option.label, COMPANION_DECISION_LABEL_MAX_LENGTH) || !isBoundedMessageText(option.detail, COMPANION_DECISION_DETAIL_MAX_CODE_POINTS)) {
|
|
34717
|
+
return eventError();
|
|
34718
|
+
}
|
|
34719
|
+
return { label: option.label, detail: option.detail };
|
|
34720
|
+
});
|
|
34721
|
+
const base = { callId: value.callId, title: value.title, options };
|
|
34722
|
+
if (value.status === "pending" || value.status === "dismissed") {
|
|
34723
|
+
if (!hasExactKeys(value, ["callId", "title", "options", "status"])) {
|
|
34724
|
+
return eventError();
|
|
34725
|
+
}
|
|
34726
|
+
return { ...base, status: value.status };
|
|
34727
|
+
}
|
|
34728
|
+
if (value.status !== "selected" || !hasExactKeys(value, ["callId", "title", "options", "status", "optionIndex"]) || !Number.isSafeInteger(value.optionIndex) || value.optionIndex < 0 || value.optionIndex >= options.length) {
|
|
34729
|
+
return eventError();
|
|
34730
|
+
}
|
|
34731
|
+
return { ...base, status: "selected", optionIndex: value.optionIndex };
|
|
34732
|
+
}
|
|
34733
|
+
function parseArtifact(value) {
|
|
34734
|
+
if (!isRecord3(value) || !isBoundedPlainString(value.name, COMPANION_ARTIFACT_NAME_MAX_LENGTH)) {
|
|
34735
|
+
return eventError();
|
|
34736
|
+
}
|
|
34737
|
+
if (value.sizeBytes === void 0) {
|
|
34738
|
+
if (!hasExactKeys(value, ["name"])) return eventError();
|
|
34739
|
+
return { name: value.name };
|
|
34740
|
+
}
|
|
34741
|
+
if (!hasExactKeys(value, ["name", "sizeBytes"]) || !Number.isSafeInteger(value.sizeBytes) || value.sizeBytes < 0) {
|
|
34742
|
+
return eventError();
|
|
34743
|
+
}
|
|
34744
|
+
return { name: value.name, sizeBytes: value.sizeBytes };
|
|
34745
|
+
}
|
|
34746
|
+
function parseTurnArtifacts(value) {
|
|
34747
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > COMPANION_ARTIFACTS_MAX) {
|
|
34748
|
+
return eventError();
|
|
34749
|
+
}
|
|
34750
|
+
return value.map(parseArtifact);
|
|
34751
|
+
}
|
|
34752
|
+
function parseTurn(value) {
|
|
34753
|
+
if (!isRecord3(value) || !isBoundedPlainString(value.id, COMPANION_TURN_ID_MAX_LENGTH) || value.role !== "user" && value.role !== "mate" || !isInstantOrNull(value.at)) {
|
|
34754
|
+
return eventError();
|
|
34755
|
+
}
|
|
34756
|
+
const keys = [
|
|
34757
|
+
"id",
|
|
34758
|
+
"role",
|
|
34759
|
+
"text",
|
|
34760
|
+
"at",
|
|
34761
|
+
...value.decision === void 0 ? [] : ["decision"],
|
|
34762
|
+
...value.artifacts === void 0 ? [] : ["artifacts"]
|
|
34763
|
+
];
|
|
34764
|
+
if (!hasExactKeys(value, keys)) return eventError();
|
|
34765
|
+
const allowEmptyText = value.decision !== void 0 || value.artifacts !== void 0;
|
|
34766
|
+
if (!(allowEmptyText && value.text === "" || isBoundedMessageText(value.text, COMPANION_TURN_TEXT_MAX_CODE_POINTS))) {
|
|
34767
|
+
return eventError();
|
|
34768
|
+
}
|
|
34769
|
+
return {
|
|
34770
|
+
id: value.id,
|
|
34771
|
+
role: value.role,
|
|
34772
|
+
text: value.text,
|
|
34773
|
+
at: value.at,
|
|
34774
|
+
...value.decision === void 0 ? {} : { decision: parseDecision(value.decision) },
|
|
34775
|
+
...value.artifacts === void 0 ? {} : { artifacts: parseTurnArtifacts(value.artifacts) }
|
|
34776
|
+
};
|
|
34618
34777
|
}
|
|
34619
34778
|
function isCanonicalInstant(value) {
|
|
34620
34779
|
if (typeof value !== "string") return false;
|
|
@@ -34670,7 +34829,7 @@ function isValidMateRoute(value) {
|
|
|
34670
34829
|
}
|
|
34671
34830
|
}
|
|
34672
34831
|
function parseRequest(value) {
|
|
34673
|
-
if (!
|
|
34832
|
+
if (!isRecord3(value)) return requestError();
|
|
34674
34833
|
if (value.type === "roster") {
|
|
34675
34834
|
if (!hasExactKeys(value, ["type"])) return requestError();
|
|
34676
34835
|
return { type: "roster" };
|
|
@@ -34679,18 +34838,36 @@ function parseRequest(value) {
|
|
|
34679
34838
|
if (!hasExactKeys(value, ["type"])) return requestError();
|
|
34680
34839
|
return { type: "update" };
|
|
34681
34840
|
}
|
|
34682
|
-
if (value.type === "history") {
|
|
34841
|
+
if (value.type === "history" || value.type === "recall") {
|
|
34683
34842
|
if (!hasExactKeys(value, ["type", "requestId", "personaKey", "limit"]) || !isRequestId(value.requestId) || !isPersonaKey(value.personaKey) || !Number.isSafeInteger(value.limit) || value.limit < 1 || value.limit > COMPANION_HISTORY_LIMIT_MAX) {
|
|
34684
34843
|
return requestError();
|
|
34685
34844
|
}
|
|
34686
34845
|
return {
|
|
34687
|
-
type:
|
|
34846
|
+
type: value.type,
|
|
34688
34847
|
requestId: value.requestId,
|
|
34689
34848
|
personaKey: value.personaKey,
|
|
34690
34849
|
limit: value.limit
|
|
34691
34850
|
};
|
|
34692
34851
|
}
|
|
34693
|
-
if (value.type
|
|
34852
|
+
if (value.type === "decide") {
|
|
34853
|
+
if (!hasExactKeys(value, [
|
|
34854
|
+
"type",
|
|
34855
|
+
"requestId",
|
|
34856
|
+
"personaKey",
|
|
34857
|
+
"callId",
|
|
34858
|
+
"optionIndex"
|
|
34859
|
+
]) || !isRequestId(value.requestId) || !isPersonaKey(value.personaKey) || !isBoundedPlainString(value.callId, COMPANION_DECISION_CALL_ID_MAX_LENGTH) || !Number.isSafeInteger(value.optionIndex) || value.optionIndex < 0 || value.optionIndex >= COMPANION_DECISION_OPTIONS_MAX) {
|
|
34860
|
+
return requestError();
|
|
34861
|
+
}
|
|
34862
|
+
return {
|
|
34863
|
+
type: "decide",
|
|
34864
|
+
requestId: value.requestId,
|
|
34865
|
+
personaKey: value.personaKey,
|
|
34866
|
+
callId: value.callId,
|
|
34867
|
+
optionIndex: value.optionIndex
|
|
34868
|
+
};
|
|
34869
|
+
}
|
|
34870
|
+
if (value.type !== "send" && value.type !== "converse" && value.type !== "chat" || !hasExactKeys(value, [
|
|
34694
34871
|
"type",
|
|
34695
34872
|
"requestId",
|
|
34696
34873
|
"personaKey",
|
|
@@ -34718,7 +34895,7 @@ function parseRequestLine(line2) {
|
|
|
34718
34895
|
}
|
|
34719
34896
|
}
|
|
34720
34897
|
function parseMate(value) {
|
|
34721
|
-
if (!
|
|
34898
|
+
if (!isRecord3(value) || !hasExactKeys(value, [
|
|
34722
34899
|
"personaKey",
|
|
34723
34900
|
"agentName",
|
|
34724
34901
|
"displayName",
|
|
@@ -34743,7 +34920,7 @@ function parseMate(value) {
|
|
|
34743
34920
|
};
|
|
34744
34921
|
}
|
|
34745
34922
|
function parseEvent(value) {
|
|
34746
|
-
if (!
|
|
34923
|
+
if (!isRecord3(value)) return eventError();
|
|
34747
34924
|
if (value.type === "update") {
|
|
34748
34925
|
if (!hasExactKeys(value, ["type", "installed", "available", "severity"]) || !isVersionOrNull(value.installed) || !isVersionOrNull(value.available) || !(value.severity === null || SEVERITIES2.has(value.severity))) {
|
|
34749
34926
|
return eventError();
|
|
@@ -34786,18 +34963,33 @@ function parseEvent(value) {
|
|
|
34786
34963
|
return { type: "completed", requestId: value.requestId };
|
|
34787
34964
|
}
|
|
34788
34965
|
if (value.type === "turn") {
|
|
34789
|
-
if (!hasExactKeys(value, ["type", "requestId", "turn"]) || !isRequestId(value.requestId)
|
|
34966
|
+
if (!hasExactKeys(value, ["type", "requestId", "turn"]) || !isRequestId(value.requestId)) {
|
|
34790
34967
|
return eventError();
|
|
34791
34968
|
}
|
|
34792
34969
|
return {
|
|
34793
34970
|
type: "turn",
|
|
34794
34971
|
requestId: value.requestId,
|
|
34795
|
-
turn:
|
|
34796
|
-
|
|
34797
|
-
|
|
34798
|
-
|
|
34799
|
-
|
|
34800
|
-
|
|
34972
|
+
turn: parseTurn(value.turn)
|
|
34973
|
+
};
|
|
34974
|
+
}
|
|
34975
|
+
if (value.type === "reply-decision") {
|
|
34976
|
+
if (!hasExactKeys(value, ["type", "requestId", "decision"]) || !isRequestId(value.requestId)) {
|
|
34977
|
+
return eventError();
|
|
34978
|
+
}
|
|
34979
|
+
return {
|
|
34980
|
+
type: "reply-decision",
|
|
34981
|
+
requestId: value.requestId,
|
|
34982
|
+
decision: parseDecision(value.decision)
|
|
34983
|
+
};
|
|
34984
|
+
}
|
|
34985
|
+
if (value.type === "reply-artifacts") {
|
|
34986
|
+
if (!hasExactKeys(value, ["type", "requestId", "artifacts"]) || !isRequestId(value.requestId) || !Array.isArray(value.artifacts) || value.artifacts.length === 0 || value.artifacts.length > COMPANION_ARTIFACTS_MAX) {
|
|
34987
|
+
return eventError();
|
|
34988
|
+
}
|
|
34989
|
+
return {
|
|
34990
|
+
type: "reply-artifacts",
|
|
34991
|
+
requestId: value.requestId,
|
|
34992
|
+
artifacts: value.artifacts.map(parseArtifact)
|
|
34801
34993
|
};
|
|
34802
34994
|
}
|
|
34803
34995
|
if (value.type === "history-end") {
|
|
@@ -34854,6 +35046,7 @@ function serializeEvent(value) {
|
|
|
34854
35046
|
}
|
|
34855
35047
|
|
|
34856
35048
|
// src/lib/companion-chat-client.ts
|
|
35049
|
+
init_esm();
|
|
34857
35050
|
import { stat as stat4 } from "fs/promises";
|
|
34858
35051
|
var RESPONSE_MAX_BYTES = 1e6;
|
|
34859
35052
|
var REQUEST_DEADLINE_MS = 12e4;
|
|
@@ -34866,7 +35059,7 @@ var PredispatchFailure = class extends Error {
|
|
|
34866
35059
|
}
|
|
34867
35060
|
reason;
|
|
34868
35061
|
};
|
|
34869
|
-
function
|
|
35062
|
+
function isRecord4(value) {
|
|
34870
35063
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34871
35064
|
}
|
|
34872
35065
|
function hasControlCharacter(value) {
|
|
@@ -34936,16 +35129,16 @@ async function readJsonEnvelope(response) {
|
|
|
34936
35129
|
if (error instanceof PredispatchFailure) throw error;
|
|
34937
35130
|
throw new PredispatchFailure("not-connected");
|
|
34938
35131
|
}
|
|
34939
|
-
if (!
|
|
35132
|
+
if (!isRecord4(envelope) || envelope.ok !== true || !("data" in envelope)) {
|
|
34940
35133
|
throw new PredispatchFailure("not-connected");
|
|
34941
35134
|
}
|
|
34942
35135
|
return envelope.data;
|
|
34943
35136
|
}
|
|
34944
35137
|
function decodeAgents(data) {
|
|
34945
|
-
if (!
|
|
35138
|
+
if (!isRecord4(data) || !Array.isArray(data.agents)) {
|
|
34946
35139
|
throw new PredispatchFailure("mate-unavailable");
|
|
34947
35140
|
}
|
|
34948
|
-
return data.agents.filter(
|
|
35141
|
+
return data.agents.filter(isRecord4);
|
|
34949
35142
|
}
|
|
34950
35143
|
function resolveAgentName(agents, personaKey) {
|
|
34951
35144
|
const matches = agents.filter(
|
|
@@ -34967,18 +35160,18 @@ function requireAgentName(agents, personaKey) {
|
|
|
34967
35160
|
return name;
|
|
34968
35161
|
}
|
|
34969
35162
|
function decodeConversationId(data) {
|
|
34970
|
-
if (!
|
|
35163
|
+
if (!isRecord4(data) || typeof data.id !== "string" || !OPAQUE_ID.test(data.id)) {
|
|
34971
35164
|
throw new PredispatchFailure("not-connected");
|
|
34972
35165
|
}
|
|
34973
35166
|
return data.id;
|
|
34974
35167
|
}
|
|
34975
35168
|
function decodeLastMessageId(data) {
|
|
34976
|
-
if (!
|
|
35169
|
+
if (!isRecord4(data) || !Array.isArray(data.messages)) {
|
|
34977
35170
|
throw new PredispatchFailure("not-connected");
|
|
34978
35171
|
}
|
|
34979
35172
|
const messages = data.messages;
|
|
34980
35173
|
const last = messages.at(-1);
|
|
34981
|
-
if (!
|
|
35174
|
+
if (!isRecord4(last) || typeof last.id !== "string" || !OPAQUE_ID.test(last.id)) {
|
|
34982
35175
|
return void 0;
|
|
34983
35176
|
}
|
|
34984
35177
|
return last.id;
|
|
@@ -35029,13 +35222,61 @@ function boundCodePoints(value, maxCodePoints) {
|
|
|
35029
35222
|
}
|
|
35030
35223
|
return value;
|
|
35031
35224
|
}
|
|
35225
|
+
function boundPlainLine(value, maxLength) {
|
|
35226
|
+
return value.replace(/[\u0000-\u001f\u007f]/gu, " ").trim().slice(0, maxLength);
|
|
35227
|
+
}
|
|
35228
|
+
var ARTIFACTS_PART_TYPE = "data-artifacts";
|
|
35229
|
+
function toCompanionDecision(directive) {
|
|
35230
|
+
const state = directive.state;
|
|
35231
|
+
if (state.status !== "pending" && state.status !== "selected" && state.status !== "dismissed") {
|
|
35232
|
+
return null;
|
|
35233
|
+
}
|
|
35234
|
+
const callId = boundPlainLine(
|
|
35235
|
+
directive.callId,
|
|
35236
|
+
COMPANION_DECISION_CALL_ID_MAX_LENGTH
|
|
35237
|
+
);
|
|
35238
|
+
const title = boundPlainLine(
|
|
35239
|
+
directive.args.title,
|
|
35240
|
+
COMPANION_DECISION_TITLE_MAX_LENGTH
|
|
35241
|
+
);
|
|
35242
|
+
if (callId.length === 0 || title.length === 0) return null;
|
|
35243
|
+
const options = [];
|
|
35244
|
+
for (const option of directive.args.options) {
|
|
35245
|
+
const label = boundPlainLine(option.label, COMPANION_DECISION_LABEL_MAX_LENGTH);
|
|
35246
|
+
const detail = boundCodePoints(
|
|
35247
|
+
sanitizeMessageText(option.detail).trim(),
|
|
35248
|
+
COMPANION_DECISION_DETAIL_MAX_CODE_POINTS
|
|
35249
|
+
);
|
|
35250
|
+
if (label.length === 0 || detail.length === 0) return null;
|
|
35251
|
+
options.push({ label, detail });
|
|
35252
|
+
}
|
|
35253
|
+
const base = { callId, title, options };
|
|
35254
|
+
return state.status === "selected" ? { ...base, status: "selected", optionIndex: state.optionIndex } : { ...base, status: state.status };
|
|
35255
|
+
}
|
|
35256
|
+
function toCompanionArtifacts(data) {
|
|
35257
|
+
const artifacts = [];
|
|
35258
|
+
for (const entry of data) {
|
|
35259
|
+
if (artifacts.length >= COMPANION_ARTIFACTS_MAX) break;
|
|
35260
|
+
if (!isRecord4(entry) || typeof entry.name !== "string") continue;
|
|
35261
|
+
const name = boundPlainLine(entry.name, COMPANION_ARTIFACT_NAME_MAX_LENGTH);
|
|
35262
|
+
if (name.length === 0) continue;
|
|
35263
|
+
const size = entry.size_bytes;
|
|
35264
|
+
artifacts.push(
|
|
35265
|
+
typeof size === "number" && Number.isSafeInteger(size) && size >= 0 ? { name, sizeBytes: size } : { name }
|
|
35266
|
+
);
|
|
35267
|
+
}
|
|
35268
|
+
return artifacts;
|
|
35269
|
+
}
|
|
35270
|
+
function decodeMessageInstant(value) {
|
|
35271
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 && value < EPOCH_SECONDS_LIMIT ? new Date(Math.round(value) * 1e3).toISOString() : null;
|
|
35272
|
+
}
|
|
35032
35273
|
function decodeTurns(data, limit2) {
|
|
35033
|
-
if (!
|
|
35274
|
+
if (!isRecord4(data) || !Array.isArray(data.messages)) {
|
|
35034
35275
|
throw new PredispatchFailure("not-connected");
|
|
35035
35276
|
}
|
|
35036
35277
|
const turns = [];
|
|
35037
35278
|
for (const entry of data.messages) {
|
|
35038
|
-
if (!
|
|
35279
|
+
if (!isRecord4(entry)) continue;
|
|
35039
35280
|
if (entry.role !== "user" && entry.role !== "assistant") continue;
|
|
35040
35281
|
if (typeof entry.id !== "string" || !OPAQUE_ID.test(entry.id)) continue;
|
|
35041
35282
|
if (typeof entry.content !== "string") continue;
|
|
@@ -35044,12 +35285,52 @@ function decodeTurns(data, limit2) {
|
|
|
35044
35285
|
COMPANION_TURN_TEXT_MAX_CODE_POINTS
|
|
35045
35286
|
);
|
|
35046
35287
|
if (text.length === 0) continue;
|
|
35047
|
-
const at = typeof entry.createdAt === "number" && Number.isFinite(entry.createdAt) && entry.createdAt > 0 && entry.createdAt < EPOCH_SECONDS_LIMIT ? new Date(Math.round(entry.createdAt) * 1e3).toISOString() : null;
|
|
35048
35288
|
turns.push({
|
|
35049
35289
|
id: entry.id,
|
|
35050
35290
|
role: entry.role === "user" ? "user" : "mate",
|
|
35051
35291
|
text,
|
|
35052
|
-
at
|
|
35292
|
+
at: decodeMessageInstant(entry.createdAt)
|
|
35293
|
+
});
|
|
35294
|
+
}
|
|
35295
|
+
return turns.slice(-limit2);
|
|
35296
|
+
}
|
|
35297
|
+
function decodeDurableDecision(entry) {
|
|
35298
|
+
const frame = parseUiDirectiveFrame({
|
|
35299
|
+
directive: entry.uiDirective,
|
|
35300
|
+
source: entry.uiDirectiveSource === "voice" ? "voice" : "text"
|
|
35301
|
+
});
|
|
35302
|
+
if (!frame) return null;
|
|
35303
|
+
return toCompanionDecision(frame.directive);
|
|
35304
|
+
}
|
|
35305
|
+
function decodeRichTurns(data, limit2) {
|
|
35306
|
+
if (!isRecord4(data) || !Array.isArray(data.messages)) {
|
|
35307
|
+
throw new PredispatchFailure("not-connected");
|
|
35308
|
+
}
|
|
35309
|
+
const turns = [];
|
|
35310
|
+
for (const entry of data.messages) {
|
|
35311
|
+
if (!isRecord4(entry)) continue;
|
|
35312
|
+
if (entry.role !== "user" && entry.role !== "assistant") continue;
|
|
35313
|
+
if (typeof entry.id !== "string" || !OPAQUE_ID.test(entry.id)) continue;
|
|
35314
|
+
if (typeof entry.content !== "string") continue;
|
|
35315
|
+
const parsed = parseArtifacts(entry.content);
|
|
35316
|
+
const artifacts = toCompanionArtifacts(parsed.artifacts);
|
|
35317
|
+
const text = boundCodePoints(
|
|
35318
|
+
sanitizeMessageText(parsed.text),
|
|
35319
|
+
COMPANION_TURN_TEXT_MAX_CODE_POINTS
|
|
35320
|
+
);
|
|
35321
|
+
const at = decodeMessageInstant(entry.createdAt);
|
|
35322
|
+
const decision = entry.uiDirective === void 0 ? null : decodeDurableDecision(entry);
|
|
35323
|
+
if (decision !== null) {
|
|
35324
|
+
turns.push({ id: entry.id, role: "mate", text, at, decision });
|
|
35325
|
+
continue;
|
|
35326
|
+
}
|
|
35327
|
+
if (text.length === 0 && artifacts.length === 0) continue;
|
|
35328
|
+
turns.push({
|
|
35329
|
+
id: entry.id,
|
|
35330
|
+
role: entry.role === "user" ? "user" : "mate",
|
|
35331
|
+
text,
|
|
35332
|
+
at,
|
|
35333
|
+
...artifacts.length > 0 ? { artifacts } : {}
|
|
35053
35334
|
});
|
|
35054
35335
|
}
|
|
35055
35336
|
return turns.slice(-limit2);
|
|
@@ -35163,7 +35444,7 @@ async function drainAcceptedSse(response) {
|
|
|
35163
35444
|
continue;
|
|
35164
35445
|
}
|
|
35165
35446
|
const parsed = JSON.parse(data);
|
|
35166
|
-
if (!
|
|
35447
|
+
if (!isRecord4(parsed) || typeof parsed.type !== "string" || parsed.type === "error") {
|
|
35167
35448
|
throw new Error("invalid stream event");
|
|
35168
35449
|
}
|
|
35169
35450
|
}
|
|
@@ -35185,7 +35466,7 @@ function emitBoundedText(text, emit) {
|
|
|
35185
35466
|
}
|
|
35186
35467
|
if (slice.length > 0) emit(slice);
|
|
35187
35468
|
}
|
|
35188
|
-
async function streamAcceptedSse(response, now, onText) {
|
|
35469
|
+
async function streamAcceptedSse(response, now, onText, onData) {
|
|
35189
35470
|
if (!response.body) throw new Error("response body unavailable");
|
|
35190
35471
|
const reader = response.body.getReader();
|
|
35191
35472
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
@@ -35211,7 +35492,7 @@ async function streamAcceptedSse(response, now, onText) {
|
|
|
35211
35492
|
return;
|
|
35212
35493
|
}
|
|
35213
35494
|
const parsed = JSON.parse(data);
|
|
35214
|
-
if (!
|
|
35495
|
+
if (!isRecord4(parsed) || typeof parsed.type !== "string" || parsed.type === "error") {
|
|
35215
35496
|
throw new Error("invalid stream event");
|
|
35216
35497
|
}
|
|
35217
35498
|
if (parsed.type === "text-delta" && typeof parsed.delta === "string" && parsed.delta.length > 0) {
|
|
@@ -35220,6 +35501,10 @@ async function streamAcceptedSse(response, now, onText) {
|
|
|
35220
35501
|
flush();
|
|
35221
35502
|
}
|
|
35222
35503
|
}
|
|
35504
|
+
if (onData && parsed.type.startsWith("data-")) {
|
|
35505
|
+
flush();
|
|
35506
|
+
onData(parsed);
|
|
35507
|
+
}
|
|
35223
35508
|
};
|
|
35224
35509
|
const drainFrames = () => {
|
|
35225
35510
|
for (; ; ) {
|
|
@@ -35255,7 +35540,7 @@ async function streamAcceptedSse(response, now, onText) {
|
|
|
35255
35540
|
throw new Error("stream ended without terminal marker");
|
|
35256
35541
|
}
|
|
35257
35542
|
}
|
|
35258
|
-
async function dispatchConversation(request, sink, deps, consume, readDesktopMarker) {
|
|
35543
|
+
async function dispatchConversation(request, sink, deps, consume, readDesktopMarker, chatBody, classifyRefusal) {
|
|
35259
35544
|
const { controller, timer } = createDeadline(deps);
|
|
35260
35545
|
const fetchImpl = deps.fetch ?? fetch;
|
|
35261
35546
|
let route;
|
|
@@ -35301,17 +35586,19 @@ async function dispatchConversation(request, sink, deps, consume, readDesktopMar
|
|
|
35301
35586
|
chatResponse = await fetchImpl(`${origin}/api/chat`, {
|
|
35302
35587
|
method: "POST",
|
|
35303
35588
|
headers: { ...headers, "content-type": "application/json" },
|
|
35304
|
-
body: JSON.stringify(
|
|
35305
|
-
messages: [{ role: "user", content: request.text }],
|
|
35306
|
-
agentName,
|
|
35307
|
-
conversationId
|
|
35308
|
-
}),
|
|
35589
|
+
body: JSON.stringify(chatBody(agentName, conversationId)),
|
|
35309
35590
|
signal: controller.signal
|
|
35310
35591
|
});
|
|
35311
35592
|
} catch {
|
|
35312
35593
|
throw new Error("chat dispatch outcome unavailable");
|
|
35313
35594
|
}
|
|
35314
35595
|
if (!chatResponse.ok || !chatResponse.body || !(chatResponse.headers.get("content-type") ?? "").toLowerCase().includes("text/event-stream")) {
|
|
35596
|
+
if (!chatResponse.ok && classifyRefusal) {
|
|
35597
|
+
const reason = await classifyRefusal(chatResponse);
|
|
35598
|
+
if (reason !== null) {
|
|
35599
|
+
return emitFailure(sink, reason, request.requestId);
|
|
35600
|
+
}
|
|
35601
|
+
}
|
|
35315
35602
|
throw new Error("chat response not accepted");
|
|
35316
35603
|
}
|
|
35317
35604
|
const acceptedEvent = parseEvent({
|
|
@@ -35349,8 +35636,40 @@ async function dispatchConversation(request, sink, deps, consume, readDesktopMar
|
|
|
35349
35636
|
clearTimeout(timer);
|
|
35350
35637
|
}
|
|
35351
35638
|
}
|
|
35639
|
+
function textTurnBody(text) {
|
|
35640
|
+
return (agentName, conversationId) => ({
|
|
35641
|
+
messages: [{ role: "user", content: text }],
|
|
35642
|
+
agentName,
|
|
35643
|
+
conversationId
|
|
35644
|
+
});
|
|
35645
|
+
}
|
|
35646
|
+
function replyDataForwarder(requestId, sink) {
|
|
35647
|
+
return (part) => {
|
|
35648
|
+
if (part.type === UI_DIRECTIVE_PART_TYPE) {
|
|
35649
|
+
const frame = parseUiDirectiveFrame(part.data);
|
|
35650
|
+
if (!frame) return;
|
|
35651
|
+
const decision = toCompanionDecision(frame.directive);
|
|
35652
|
+
if (decision === null) return;
|
|
35653
|
+
sink(parseEvent({ type: "reply-decision", requestId, decision }));
|
|
35654
|
+
return;
|
|
35655
|
+
}
|
|
35656
|
+
if (part.type === ARTIFACTS_PART_TYPE && Array.isArray(part.data)) {
|
|
35657
|
+
const artifacts = toCompanionArtifacts(part.data);
|
|
35658
|
+
if (artifacts.length > 0) {
|
|
35659
|
+
sink(parseEvent({ type: "reply-artifacts", requestId, artifacts }));
|
|
35660
|
+
}
|
|
35661
|
+
}
|
|
35662
|
+
};
|
|
35663
|
+
}
|
|
35352
35664
|
async function sendCompanionMessage(request, sink, deps = {}) {
|
|
35353
|
-
return dispatchConversation(
|
|
35665
|
+
return dispatchConversation(
|
|
35666
|
+
request,
|
|
35667
|
+
sink,
|
|
35668
|
+
deps,
|
|
35669
|
+
drainAcceptedSse,
|
|
35670
|
+
true,
|
|
35671
|
+
textTurnBody(request.text)
|
|
35672
|
+
);
|
|
35354
35673
|
}
|
|
35355
35674
|
async function converseCompanionMessage(request, sink, deps = {}) {
|
|
35356
35675
|
return dispatchConversation(
|
|
@@ -35366,10 +35685,101 @@ async function converseCompanionMessage(request, sink, deps = {}) {
|
|
|
35366
35685
|
})
|
|
35367
35686
|
);
|
|
35368
35687
|
}),
|
|
35369
|
-
false
|
|
35688
|
+
false,
|
|
35689
|
+
textTurnBody(request.text)
|
|
35690
|
+
);
|
|
35691
|
+
}
|
|
35692
|
+
async function chatCompanionMessage(request, sink, deps = {}) {
|
|
35693
|
+
return dispatchConversation(
|
|
35694
|
+
request,
|
|
35695
|
+
sink,
|
|
35696
|
+
deps,
|
|
35697
|
+
(response) => streamAcceptedSse(
|
|
35698
|
+
response,
|
|
35699
|
+
deps.now ?? Date.now,
|
|
35700
|
+
(text) => {
|
|
35701
|
+
sink(
|
|
35702
|
+
parseEvent({
|
|
35703
|
+
type: "reply-delta",
|
|
35704
|
+
requestId: request.requestId,
|
|
35705
|
+
text
|
|
35706
|
+
})
|
|
35707
|
+
);
|
|
35708
|
+
},
|
|
35709
|
+
replyDataForwarder(request.requestId, sink)
|
|
35710
|
+
),
|
|
35711
|
+
false,
|
|
35712
|
+
textTurnBody(request.text)
|
|
35713
|
+
);
|
|
35714
|
+
}
|
|
35715
|
+
async function classifyDecideRefusal(response) {
|
|
35716
|
+
let reason;
|
|
35717
|
+
try {
|
|
35718
|
+
const envelope = JSON.parse(await readBoundedText(response));
|
|
35719
|
+
if (isRecord4(envelope) && isRecord4(envelope.error) && isRecord4(envelope.error.details)) {
|
|
35720
|
+
reason = envelope.error.details.reason;
|
|
35721
|
+
}
|
|
35722
|
+
} catch {
|
|
35723
|
+
}
|
|
35724
|
+
if (isDecisionRefusalReason(reason)) {
|
|
35725
|
+
return reason === DECISION_REFUSAL_REASONS.notPending ? "decision-not-pending" : "bad-request";
|
|
35726
|
+
}
|
|
35727
|
+
if (response.status === 401 || response.status === 403) {
|
|
35728
|
+
return "not-authorized";
|
|
35729
|
+
}
|
|
35730
|
+
if (response.status === 400) return "bad-request";
|
|
35731
|
+
if (response.status === 409) return "busy";
|
|
35732
|
+
return null;
|
|
35733
|
+
}
|
|
35734
|
+
async function decideCompanionMessage(request, sink, deps = {}) {
|
|
35735
|
+
const message = {
|
|
35736
|
+
role: "user",
|
|
35737
|
+
parts: [
|
|
35738
|
+
{
|
|
35739
|
+
type: UI_DIRECTIVE_RESULT_PART_TYPE,
|
|
35740
|
+
data: {
|
|
35741
|
+
version: 1,
|
|
35742
|
+
name: "present_decision",
|
|
35743
|
+
callId: request.callId,
|
|
35744
|
+
result: { status: "selected", optionIndex: request.optionIndex }
|
|
35745
|
+
}
|
|
35746
|
+
}
|
|
35747
|
+
]
|
|
35748
|
+
};
|
|
35749
|
+
return dispatchConversation(
|
|
35750
|
+
request,
|
|
35751
|
+
sink,
|
|
35752
|
+
deps,
|
|
35753
|
+
(response) => streamAcceptedSse(
|
|
35754
|
+
response,
|
|
35755
|
+
deps.now ?? Date.now,
|
|
35756
|
+
(text) => {
|
|
35757
|
+
sink(
|
|
35758
|
+
parseEvent({
|
|
35759
|
+
type: "reply-delta",
|
|
35760
|
+
requestId: request.requestId,
|
|
35761
|
+
text
|
|
35762
|
+
})
|
|
35763
|
+
);
|
|
35764
|
+
},
|
|
35765
|
+
replyDataForwarder(request.requestId, sink)
|
|
35766
|
+
),
|
|
35767
|
+
false,
|
|
35768
|
+
(agentName, conversationId) => ({
|
|
35769
|
+
messages: [message],
|
|
35770
|
+
agentName,
|
|
35771
|
+
conversationId
|
|
35772
|
+
}),
|
|
35773
|
+
classifyDecideRefusal
|
|
35370
35774
|
);
|
|
35371
35775
|
}
|
|
35372
35776
|
async function historyCompanionMessages(request, sink, deps = {}) {
|
|
35777
|
+
return fetchConversationTurns(request, sink, deps, decodeTurns);
|
|
35778
|
+
}
|
|
35779
|
+
async function recallCompanionMessages(request, sink, deps = {}) {
|
|
35780
|
+
return fetchConversationTurns(request, sink, deps, decodeRichTurns);
|
|
35781
|
+
}
|
|
35782
|
+
async function fetchConversationTurns(request, sink, deps, decode) {
|
|
35373
35783
|
const { controller, timer } = createDeadline(deps);
|
|
35374
35784
|
const fetchImpl = deps.fetch ?? fetch;
|
|
35375
35785
|
try {
|
|
@@ -35389,7 +35799,7 @@ async function historyCompanionMessages(request, sink, deps = {}) {
|
|
|
35389
35799
|
agentName,
|
|
35390
35800
|
controller.signal
|
|
35391
35801
|
);
|
|
35392
|
-
const turns =
|
|
35802
|
+
const turns = decode(
|
|
35393
35803
|
await fetchConversationMessages(
|
|
35394
35804
|
fetchImpl,
|
|
35395
35805
|
origin,
|
|
@@ -35545,7 +35955,10 @@ async function dispatchRequest(request, sink, handlers) {
|
|
|
35545
35955
|
return terminal;
|
|
35546
35956
|
}
|
|
35547
35957
|
if (request.type === "history") return handlers.history(request, sink);
|
|
35958
|
+
if (request.type === "recall") return handlers.recall(request, sink);
|
|
35548
35959
|
if (request.type === "converse") return handlers.converse(request, sink);
|
|
35960
|
+
if (request.type === "chat") return handlers.chat(request, sink);
|
|
35961
|
+
if (request.type === "decide") return handlers.decide(request, sink);
|
|
35549
35962
|
return handlers.send(request, sink);
|
|
35550
35963
|
}
|
|
35551
35964
|
async function handleWithContext(request, sink, handlers, context) {
|
|
@@ -35581,7 +35994,10 @@ async function runCompanionBridgeServe(stdin, stdout, stderr, deps = {}) {
|
|
|
35581
35994
|
roster: (sink2) => rosterCompanions(sink2, chat),
|
|
35582
35995
|
send: (request, sink2) => sendCompanionMessage(request, sink2, chat),
|
|
35583
35996
|
converse: (request, sink2) => converseCompanionMessage(request, sink2, chat),
|
|
35997
|
+
chat: (request, sink2) => chatCompanionMessage(request, sink2, chat),
|
|
35998
|
+
decide: (request, sink2) => decideCompanionMessage(request, sink2, chat),
|
|
35584
35999
|
history: (request, sink2) => historyCompanionMessages(request, sink2, chat),
|
|
36000
|
+
recall: (request, sink2) => recallCompanionMessages(request, sink2, chat),
|
|
35585
36001
|
update: deps.update ?? (() => checkCompanionUpdate(defaultLocalCompanionInstallOptions()))
|
|
35586
36002
|
};
|
|
35587
36003
|
const sink = (event) => {
|
|
@@ -35616,7 +36032,10 @@ var defaultDeps4 = {
|
|
|
35616
36032
|
roster: rosterCompanions,
|
|
35617
36033
|
send: sendCompanionMessage,
|
|
35618
36034
|
converse: converseCompanionMessage,
|
|
36035
|
+
chat: chatCompanionMessage,
|
|
36036
|
+
decide: decideCompanionMessage,
|
|
35619
36037
|
history: historyCompanionMessages,
|
|
36038
|
+
recall: recallCompanionMessages,
|
|
35620
36039
|
update: () => checkCompanionUpdate(defaultLocalCompanionInstallOptions())
|
|
35621
36040
|
};
|
|
35622
36041
|
async function readSingleRequest(stdin) {
|
|
@@ -35667,8 +36086,14 @@ async function runCompanionBridge(stdin, stdout, stderr, deps = defaultDeps4) {
|
|
|
35667
36086
|
sink(terminal);
|
|
35668
36087
|
} else if (request.type === "history") {
|
|
35669
36088
|
terminal = await deps.history(request, sink);
|
|
36089
|
+
} else if (request.type === "recall") {
|
|
36090
|
+
terminal = await deps.recall(request, sink);
|
|
35670
36091
|
} else if (request.type === "converse") {
|
|
35671
36092
|
terminal = await deps.converse(request, sink);
|
|
36093
|
+
} else if (request.type === "chat") {
|
|
36094
|
+
terminal = await deps.chat(request, sink);
|
|
36095
|
+
} else if (request.type === "decide") {
|
|
36096
|
+
terminal = await deps.decide(request, sink);
|
|
35672
36097
|
} else terminal = await deps.send(request, sink);
|
|
35673
36098
|
return exitFor(terminal);
|
|
35674
36099
|
} catch {
|