@usabledev/usable-chat 1.209.2 → 1.211.0
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/cli.js +462 -168
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -57298,15 +57298,15 @@ var require_image_q = __commonJS({
|
|
|
57298
57298
|
const match2 = -1;
|
|
57299
57299
|
let bestMatch = match2;
|
|
57300
57300
|
let bestDistance = Number.MAX_VALUE;
|
|
57301
|
-
for (let
|
|
57302
|
-
const foundRed = lookupRed[
|
|
57303
|
-
const foundGreen = lookupGreen[
|
|
57304
|
-
const foundBlue = lookupBlue[
|
|
57305
|
-
const foundAlpha = lookupAlpha[
|
|
57301
|
+
for (let lookup3 = 0; lookup3 < this._colors; lookup3++) {
|
|
57302
|
+
const foundRed = lookupRed[lookup3];
|
|
57303
|
+
const foundGreen = lookupGreen[lookup3];
|
|
57304
|
+
const foundBlue = lookupBlue[lookup3];
|
|
57305
|
+
const foundAlpha = lookupAlpha[lookup3];
|
|
57306
57306
|
const distance3 = this._distance.calculateRaw(foundRed, foundGreen, foundBlue, foundAlpha, color.r, color.g, color.b, color.a);
|
|
57307
57307
|
if (distance3 < bestDistance) {
|
|
57308
57308
|
bestDistance = distance3;
|
|
57309
|
-
bestMatch =
|
|
57309
|
+
bestMatch = lookup3;
|
|
57310
57310
|
}
|
|
57311
57311
|
}
|
|
57312
57312
|
this._reds[bestMatch] += color.r;
|
|
@@ -83959,15 +83959,15 @@ var init_image_q = __esm({
|
|
|
83959
83959
|
const match2 = -1;
|
|
83960
83960
|
let bestMatch = match2;
|
|
83961
83961
|
let bestDistance = Number.MAX_VALUE;
|
|
83962
|
-
for (let
|
|
83963
|
-
const foundRed = lookupRed[
|
|
83964
|
-
const foundGreen = lookupGreen[
|
|
83965
|
-
const foundBlue = lookupBlue[
|
|
83966
|
-
const foundAlpha = lookupAlpha[
|
|
83962
|
+
for (let lookup3 = 0; lookup3 < this._colors; lookup3++) {
|
|
83963
|
+
const foundRed = lookupRed[lookup3];
|
|
83964
|
+
const foundGreen = lookupGreen[lookup3];
|
|
83965
|
+
const foundBlue = lookupBlue[lookup3];
|
|
83966
|
+
const foundAlpha = lookupAlpha[lookup3];
|
|
83967
83967
|
const distance3 = this._distance.calculateRaw(foundRed, foundGreen, foundBlue, foundAlpha, color.r, color.g, color.b, color.a);
|
|
83968
83968
|
if (distance3 < bestDistance) {
|
|
83969
83969
|
bestDistance = distance3;
|
|
83970
|
-
bestMatch =
|
|
83970
|
+
bestMatch = lookup3;
|
|
83971
83971
|
}
|
|
83972
83972
|
}
|
|
83973
83973
|
this._reds[bestMatch] += color.r;
|
|
@@ -94237,11 +94237,12 @@ var init_env2 = __esm({
|
|
|
94237
94237
|
// (/api/oauth/register). Pre-configured in Keycloak (memory-mesh) with PKCE +
|
|
94238
94238
|
// whitelisted redirect URIs — clients never hit Keycloak's DCR endpoint.
|
|
94239
94239
|
MCP_OAUTH_CLIENT_ID: external_exports.string().min(1).default("mcp_oauth_client"),
|
|
94240
|
-
// Optional
|
|
94241
|
-
//
|
|
94242
|
-
//
|
|
94243
|
-
//
|
|
94244
|
-
//
|
|
94240
|
+
// Optional override for Bearer JWT client trust. Bearer tokens are accepted
|
|
94241
|
+
// when Usable trusts their azp (first-party SSO, mcp_oauth_client, any
|
|
94242
|
+
// marketplace app — looked up via /api/oauth/client-trust). Client IDs listed
|
|
94243
|
+
// here (comma-separated) are always trusted without a lookup: use it only for
|
|
94244
|
+
// clients Usable does not know, or as break-glass during a Usable outage.
|
|
94245
|
+
// See docs/chat-v2-contract.md#authentication.
|
|
94245
94246
|
CHAT_TRUSTED_CLIENT_IDS: external_exports.string().optional(),
|
|
94246
94247
|
USABLE_MOBILE_CHAT_HOST_ENABLED: external_exports.enum(["true", "false"]).default("false"),
|
|
94247
94248
|
USABLE_MOBILE_CHAT_HOST_ORIGIN: external_exports.string().url().optional(),
|
|
@@ -94547,8 +94548,8 @@ var init_config = __esm({
|
|
|
94547
94548
|
/** Static public client_id returned by the MCP OAuth registration endpoint. */
|
|
94548
94549
|
mcpOAuthClientId: env.MCP_OAUTH_CLIENT_ID || DEFAULT_MCP_OAUTH_CLIENT_ID2,
|
|
94549
94550
|
/**
|
|
94550
|
-
* Optional
|
|
94551
|
-
*
|
|
94551
|
+
* Optional override list of Bearer JWT client IDs trusted without asking
|
|
94552
|
+
* Usable (comma-separated). See oauth-client-trust.service.ts.
|
|
94552
94553
|
*/
|
|
94553
94554
|
trustedClientIdsRaw: env.CHAT_TRUSTED_CLIENT_IDS
|
|
94554
94555
|
},
|
|
@@ -95133,6 +95134,12 @@ var init_beta_features = __esm({
|
|
|
95133
95134
|
name: "Research mode",
|
|
95134
95135
|
description: "Run structured, sourced research with specialist workers and an HTML report."
|
|
95135
95136
|
},
|
|
95137
|
+
"auto-model": {
|
|
95138
|
+
key: "auto-model",
|
|
95139
|
+
name: "Auto model",
|
|
95140
|
+
description: "Use Jev to choose a curated model for each text request.",
|
|
95141
|
+
failureMessage: "Could not save Auto model. Try again."
|
|
95142
|
+
},
|
|
95136
95143
|
"configurable-hooks": {
|
|
95137
95144
|
key: "configurable-hooks",
|
|
95138
95145
|
name: "Configurable hooks",
|
|
@@ -95159,7 +95166,8 @@ var init_beta_features = __esm({
|
|
|
95159
95166
|
betaFeatureGrantSchema = external_exports.object({
|
|
95160
95167
|
enabled: external_exports.boolean(),
|
|
95161
95168
|
enabledAt: external_exports.string().datetime(),
|
|
95162
|
-
enabledBy: external_exports.string()
|
|
95169
|
+
enabledBy: external_exports.string(),
|
|
95170
|
+
autoModelChoices: external_exports.object({ simple: external_exports.string(), advanced: external_exports.string() }).optional()
|
|
95163
95171
|
});
|
|
95164
95172
|
userBetaFeaturesSchema = external_exports.record(external_exports.string(), betaFeatureGrantSchema);
|
|
95165
95173
|
}
|
|
@@ -106895,11 +106903,11 @@ var require_randomUUID = __commonJS({
|
|
|
106895
106903
|
var require_dist_cjs31 = __commonJS({
|
|
106896
106904
|
"node_modules/.pnpm/@smithy+uuid@1.1.2/node_modules/@smithy/uuid/dist-cjs/index.js"(exports2) {
|
|
106897
106905
|
"use strict";
|
|
106898
|
-
var
|
|
106906
|
+
var randomUUID16 = require_randomUUID();
|
|
106899
106907
|
var decimalToHex = Array.from({ length: 256 }, (_16, i19) => i19.toString(16).padStart(2, "0"));
|
|
106900
106908
|
var v43 = () => {
|
|
106901
|
-
if (
|
|
106902
|
-
return
|
|
106909
|
+
if (randomUUID16.randomUUID) {
|
|
106910
|
+
return randomUUID16.randomUUID();
|
|
106903
106911
|
}
|
|
106904
106912
|
const rnds = new Uint8Array(16);
|
|
106905
106913
|
crypto.getRandomValues(rnds);
|
|
@@ -144783,8 +144791,8 @@ var require_utils = __commonJS({
|
|
|
144783
144791
|
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
144784
144792
|
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
144785
144793
|
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
144786
|
-
function reescapeHostDelimiters(host,
|
|
144787
|
-
const re10 =
|
|
144794
|
+
function reescapeHostDelimiters(host, isIP4) {
|
|
144795
|
+
const re10 = isIP4 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
144788
144796
|
re10.lastIndex = 0;
|
|
144789
144797
|
return host.replace(re10, (ch) => HOST_DELIMS[ch]);
|
|
144790
144798
|
}
|
|
@@ -145266,7 +145274,7 @@ var require_fast_uri = __commonJS({
|
|
|
145266
145274
|
fragment: void 0
|
|
145267
145275
|
};
|
|
145268
145276
|
let malformedAuthorityOrPort = false;
|
|
145269
|
-
let
|
|
145277
|
+
let isIP4 = false;
|
|
145270
145278
|
if (options2.reference === "suffix") {
|
|
145271
145279
|
if (options2.scheme) {
|
|
145272
145280
|
uri = options2.scheme + ":" + uri;
|
|
@@ -145296,9 +145304,9 @@ var require_fast_uri = __commonJS({
|
|
|
145296
145304
|
if (ipv4result === false) {
|
|
145297
145305
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
145298
145306
|
parsed.host = ipv6result.host.toLowerCase();
|
|
145299
|
-
|
|
145307
|
+
isIP4 = ipv6result.isIPV6;
|
|
145300
145308
|
} else {
|
|
145301
|
-
|
|
145309
|
+
isIP4 = true;
|
|
145302
145310
|
}
|
|
145303
145311
|
}
|
|
145304
145312
|
if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) {
|
|
@@ -145315,7 +145323,7 @@ var require_fast_uri = __commonJS({
|
|
|
145315
145323
|
}
|
|
145316
145324
|
const schemeHandler = getSchemeHandler(options2.scheme || parsed.scheme);
|
|
145317
145325
|
if (!options2.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
|
|
145318
|
-
if (parsed.host && (options2.domainHost || schemeHandler && schemeHandler.domainHost) &&
|
|
145326
|
+
if (parsed.host && (options2.domainHost || schemeHandler && schemeHandler.domainHost) && isIP4 === false && nonSimpleDomain(parsed.host)) {
|
|
145319
145327
|
try {
|
|
145320
145328
|
parsed.host = URL.domainToASCII(parsed.host.toLowerCase());
|
|
145321
145329
|
} catch (e15) {
|
|
@@ -145329,7 +145337,7 @@ var require_fast_uri = __commonJS({
|
|
|
145329
145337
|
parsed.scheme = unescape(parsed.scheme);
|
|
145330
145338
|
}
|
|
145331
145339
|
if (parsed.host !== void 0) {
|
|
145332
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host),
|
|
145340
|
+
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP4);
|
|
145333
145341
|
}
|
|
145334
145342
|
}
|
|
145335
145343
|
if (parsed.path) {
|
|
@@ -162763,6 +162771,12 @@ var init_schema_mcp = __esm({
|
|
|
162763
162771
|
lastError: text2("last_error"),
|
|
162764
162772
|
deletedAt: timestamp("deleted_at", { withTimezone: true }),
|
|
162765
162773
|
sourceEventId: varchar("source_event_id", { length: 255 }),
|
|
162774
|
+
// User approval for credential-bearing profiles (see services/mcp-approval.ts).
|
|
162775
|
+
// Existing rows are grandfathered with approved_via='legacy' and no fingerprint.
|
|
162776
|
+
origin: varchar("origin", { length: 16 }).notNull().default("legacy").$type(),
|
|
162777
|
+
approvedFingerprint: varchar("approved_fingerprint", { length: 80 }),
|
|
162778
|
+
approvedAt: timestamp("approved_at", { withTimezone: true }),
|
|
162779
|
+
approvedVia: varchar("approved_via", { length: 32 }),
|
|
162766
162780
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
162767
162781
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
162768
162782
|
},
|
|
@@ -163434,6 +163448,41 @@ var init_tool = __esm({
|
|
|
163434
163448
|
}
|
|
163435
163449
|
});
|
|
163436
163450
|
|
|
163451
|
+
// src/core/pause/envelope.ts
|
|
163452
|
+
function isMcpApprovalPause(output) {
|
|
163453
|
+
if (!output || typeof output !== "object") return false;
|
|
163454
|
+
const pause = output.__pause;
|
|
163455
|
+
return pause !== void 0 && pause.kind === MCP_APPROVAL_PAUSE_KIND && typeof pause.resumeToken === "string" && typeof pause.mcpApproval?.profileId === "string" && typeof pause.mcpApproval.fingerprint === "string";
|
|
163456
|
+
}
|
|
163457
|
+
function detectPause(toolResult, toolCallId) {
|
|
163458
|
+
if (isAskQuestionPause(toolResult)) {
|
|
163459
|
+
return {
|
|
163460
|
+
resumeToken: toolResult.__pause.resumeToken,
|
|
163461
|
+
questions: toolResult.__pause.questions,
|
|
163462
|
+
context: toolResult.__pause.context,
|
|
163463
|
+
toolCallId
|
|
163464
|
+
};
|
|
163465
|
+
}
|
|
163466
|
+
if (isMcpApprovalPause(toolResult)) {
|
|
163467
|
+
return {
|
|
163468
|
+
kind: MCP_APPROVAL_PAUSE_KIND,
|
|
163469
|
+
resumeToken: toolResult.__pause.resumeToken,
|
|
163470
|
+
mcpApproval: toolResult.__pause.mcpApproval,
|
|
163471
|
+
action: toolResult.__pause.action,
|
|
163472
|
+
toolCallId
|
|
163473
|
+
};
|
|
163474
|
+
}
|
|
163475
|
+
return null;
|
|
163476
|
+
}
|
|
163477
|
+
var MCP_APPROVAL_PAUSE_KIND;
|
|
163478
|
+
var init_envelope = __esm({
|
|
163479
|
+
"src/core/pause/envelope.ts"() {
|
|
163480
|
+
"use strict";
|
|
163481
|
+
init_tool();
|
|
163482
|
+
MCP_APPROVAL_PAUSE_KIND = "mcp-approval";
|
|
163483
|
+
}
|
|
163484
|
+
});
|
|
163485
|
+
|
|
163437
163486
|
// src/core/ai/provider-attempt.ts
|
|
163438
163487
|
function providerAttemptAbortError(attempt) {
|
|
163439
163488
|
const reason = attempt.signal.reason;
|
|
@@ -164099,15 +164148,10 @@ async function adaptClaudeStream(stream, options2) {
|
|
|
164099
164148
|
});
|
|
164100
164149
|
multiplexer.send(cardEvent);
|
|
164101
164150
|
}
|
|
164102
|
-
|
|
164151
|
+
const pause = detectPause(toolResult, id);
|
|
164152
|
+
if (pause) {
|
|
164103
164153
|
pauseDetected = true;
|
|
164104
|
-
if (onPauseDetected)
|
|
164105
|
-
await onPauseDetected({
|
|
164106
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
164107
|
-
questions: toolResult.__pause.questions,
|
|
164108
|
-
context: toolResult.__pause.context
|
|
164109
|
-
});
|
|
164110
|
-
}
|
|
164154
|
+
if (onPauseDetected) await onPauseDetected(pause);
|
|
164111
164155
|
return { toolResult };
|
|
164112
164156
|
}
|
|
164113
164157
|
if (toolResult?.__parentToolCall === true) {
|
|
@@ -164380,15 +164424,10 @@ async function adaptClaudeStream(stream, options2) {
|
|
|
164380
164424
|
});
|
|
164381
164425
|
multiplexer.send(cardEvent);
|
|
164382
164426
|
}
|
|
164383
|
-
|
|
164427
|
+
const pause = detectPause(toolResult, id);
|
|
164428
|
+
if (pause) {
|
|
164384
164429
|
pauseDetected = true;
|
|
164385
|
-
if (onPauseDetected)
|
|
164386
|
-
await onPauseDetected({
|
|
164387
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
164388
|
-
questions: toolResult.__pause.questions,
|
|
164389
|
-
context: toolResult.__pause.context
|
|
164390
|
-
});
|
|
164391
|
-
}
|
|
164430
|
+
if (onPauseDetected) await onPauseDetected(pause);
|
|
164392
164431
|
return { toolResult };
|
|
164393
164432
|
}
|
|
164394
164433
|
if (toolResult?.__parentToolCall === true) {
|
|
@@ -164608,7 +164647,7 @@ var init_claude_stream_adapter = __esm({
|
|
|
164608
164647
|
"use strict";
|
|
164609
164648
|
init_logger();
|
|
164610
164649
|
init_store();
|
|
164611
|
-
|
|
164650
|
+
init_envelope();
|
|
164612
164651
|
init_provider_attempt();
|
|
164613
164652
|
}
|
|
164614
164653
|
});
|
|
@@ -164724,15 +164763,10 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
164724
164763
|
});
|
|
164725
164764
|
multiplexer.send(cardEvent);
|
|
164726
164765
|
}
|
|
164727
|
-
|
|
164766
|
+
const pause = detectPause(toolResult, id);
|
|
164767
|
+
if (pause) {
|
|
164728
164768
|
pauseDetected = true;
|
|
164729
|
-
if (onPauseDetected)
|
|
164730
|
-
await onPauseDetected({
|
|
164731
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
164732
|
-
questions: toolResult.__pause.questions,
|
|
164733
|
-
context: toolResult.__pause.context
|
|
164734
|
-
});
|
|
164735
|
-
}
|
|
164769
|
+
if (onPauseDetected) await onPauseDetected(pause);
|
|
164736
164770
|
return;
|
|
164737
164771
|
}
|
|
164738
164772
|
if (toolResult?.__parentToolCall === true) {
|
|
@@ -165309,7 +165343,7 @@ var init_openrouter_stream_adapter = __esm({
|
|
|
165309
165343
|
"use strict";
|
|
165310
165344
|
init_logger();
|
|
165311
165345
|
init_store();
|
|
165312
|
-
|
|
165346
|
+
init_envelope();
|
|
165313
165347
|
init_provider_attempt();
|
|
165314
165348
|
}
|
|
165315
165349
|
});
|
|
@@ -167172,7 +167206,7 @@ function buildBlock(artifact) {
|
|
|
167172
167206
|
${body2}
|
|
167173
167207
|
</referenced-artifact>`;
|
|
167174
167208
|
}
|
|
167175
|
-
async function resolveArtifactMentions(text5,
|
|
167209
|
+
async function resolveArtifactMentions(text5, lookup3) {
|
|
167176
167210
|
if (!text5 || typeof text5 !== "string") return text5;
|
|
167177
167211
|
const ids = /* @__PURE__ */ new Set();
|
|
167178
167212
|
const matches = text5.matchAll(ARTIFACT_MENTION_RE);
|
|
@@ -167180,7 +167214,7 @@ async function resolveArtifactMentions(text5, lookup2) {
|
|
|
167180
167214
|
ids.add(match2[1].toLowerCase());
|
|
167181
167215
|
}
|
|
167182
167216
|
if (ids.size === 0) return text5;
|
|
167183
|
-
const resolved = await
|
|
167217
|
+
const resolved = await lookup3(Array.from(ids));
|
|
167184
167218
|
const byId = /* @__PURE__ */ new Map();
|
|
167185
167219
|
for (const artifact of resolved) {
|
|
167186
167220
|
byId.set(artifact.id.toLowerCase(), artifact);
|
|
@@ -167211,14 +167245,14 @@ function buildElement(user) {
|
|
|
167211
167245
|
const handle = escapeXml2(`@${handleSource}`);
|
|
167212
167246
|
return `<slack-user id="${user.id}" handle="${handle}" name="${name18}" />`;
|
|
167213
167247
|
}
|
|
167214
|
-
async function resolveSlackMentions(text5,
|
|
167248
|
+
async function resolveSlackMentions(text5, lookup3) {
|
|
167215
167249
|
if (!text5 || typeof text5 !== "string") return text5;
|
|
167216
167250
|
const ids = /* @__PURE__ */ new Set();
|
|
167217
167251
|
for (const match2 of text5.matchAll(SLACK_MENTION_RE)) {
|
|
167218
167252
|
ids.add(match2[1].toUpperCase());
|
|
167219
167253
|
}
|
|
167220
167254
|
if (ids.size === 0) return text5;
|
|
167221
|
-
const resolved = await
|
|
167255
|
+
const resolved = await lookup3(Array.from(ids));
|
|
167222
167256
|
const byId = /* @__PURE__ */ new Map();
|
|
167223
167257
|
for (const user of resolved) {
|
|
167224
167258
|
byId.set(user.id.toUpperCase(), user);
|
|
@@ -175113,7 +175147,7 @@ var require_gaxios = __commonJS({
|
|
|
175113
175147
|
var retry_js_1 = require_retry();
|
|
175114
175148
|
var stream_1 = __require("stream");
|
|
175115
175149
|
var interceptor_js_1 = require_interceptor();
|
|
175116
|
-
var
|
|
175150
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
175117
175151
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
175118
175152
|
var Gaxios = class {
|
|
175119
175153
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -175386,7 +175420,7 @@ var require_gaxios = __commonJS({
|
|
|
175386
175420
|
*/
|
|
175387
175421
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
175388
175422
|
if (opts.multipart?.length) {
|
|
175389
|
-
const boundary = await
|
|
175423
|
+
const boundary = await randomUUID16();
|
|
175390
175424
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
175391
175425
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
175392
175426
|
} else if (shouldDirectlyPassData) {
|
|
@@ -178067,12 +178101,12 @@ var require_base64_js = __commonJS({
|
|
|
178067
178101
|
exports2.byteLength = byteLength;
|
|
178068
178102
|
exports2.toByteArray = toByteArray;
|
|
178069
178103
|
exports2.fromByteArray = fromByteArray;
|
|
178070
|
-
var
|
|
178104
|
+
var lookup3 = [];
|
|
178071
178105
|
var revLookup = [];
|
|
178072
178106
|
var Arr = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
|
|
178073
178107
|
var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
178074
178108
|
for (i19 = 0, len = code.length; i19 < len; ++i19) {
|
|
178075
|
-
|
|
178109
|
+
lookup3[i19] = code[i19];
|
|
178076
178110
|
revLookup[code.charCodeAt(i19)] = i19;
|
|
178077
178111
|
}
|
|
178078
178112
|
var i19;
|
|
@@ -178125,7 +178159,7 @@ var require_base64_js = __commonJS({
|
|
|
178125
178159
|
return arr;
|
|
178126
178160
|
}
|
|
178127
178161
|
function tripletToBase64(num) {
|
|
178128
|
-
return
|
|
178162
|
+
return lookup3[num >> 18 & 63] + lookup3[num >> 12 & 63] + lookup3[num >> 6 & 63] + lookup3[num & 63];
|
|
178129
178163
|
}
|
|
178130
178164
|
function encodeChunk(uint8, start, end) {
|
|
178131
178165
|
var tmp;
|
|
@@ -178148,12 +178182,12 @@ var require_base64_js = __commonJS({
|
|
|
178148
178182
|
if (extraBytes === 1) {
|
|
178149
178183
|
tmp = uint8[len2 - 1];
|
|
178150
178184
|
parts.push(
|
|
178151
|
-
|
|
178185
|
+
lookup3[tmp >> 2] + lookup3[tmp << 4 & 63] + "=="
|
|
178152
178186
|
);
|
|
178153
178187
|
} else if (extraBytes === 2) {
|
|
178154
178188
|
tmp = (uint8[len2 - 2] << 8) + uint8[len2 - 1];
|
|
178155
178189
|
parts.push(
|
|
178156
|
-
|
|
178190
|
+
lookup3[tmp >> 10] + lookup3[tmp >> 4 & 63] + lookup3[tmp << 2 & 63] + "="
|
|
178157
178191
|
);
|
|
178158
178192
|
}
|
|
178159
178193
|
return parts.join("");
|
|
@@ -205822,15 +205856,10 @@ async function callGeminiDirect({
|
|
|
205822
205856
|
try {
|
|
205823
205857
|
if (abortSignal?.aborted) break;
|
|
205824
205858
|
let toolResult = await executeToolByName(toolName, toolArgs, { ...context3, toolCallId });
|
|
205825
|
-
|
|
205859
|
+
const pause = detectPause(toolResult, toolCallId);
|
|
205860
|
+
if (pause) {
|
|
205826
205861
|
pauseDetected = true;
|
|
205827
|
-
if (onPauseDetected)
|
|
205828
|
-
await onPauseDetected({
|
|
205829
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
205830
|
-
questions: toolResult.__pause.questions,
|
|
205831
|
-
context: toolResult.__pause.context
|
|
205832
|
-
});
|
|
205833
|
-
}
|
|
205862
|
+
if (onPauseDetected) await onPauseDetected(pause);
|
|
205834
205863
|
completedToolCalls.push({ id: toolCallId, name: toolName, arguments: toolArgs });
|
|
205835
205864
|
break;
|
|
205836
205865
|
}
|
|
@@ -205995,15 +206024,10 @@ async function callGeminiDirect({
|
|
|
205995
206024
|
try {
|
|
205996
206025
|
if (abortSignal?.aborted) break;
|
|
205997
206026
|
let toolResult = await executeToolByName(toolName, toolArgs, { ...context3, toolCallId });
|
|
205998
|
-
|
|
206027
|
+
const pause = detectPause(toolResult, toolCallId);
|
|
206028
|
+
if (pause) {
|
|
205999
206029
|
pauseDetected = true;
|
|
206000
|
-
if (onPauseDetected)
|
|
206001
|
-
await onPauseDetected({
|
|
206002
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
206003
|
-
questions: toolResult.__pause.questions,
|
|
206004
|
-
context: toolResult.__pause.context
|
|
206005
|
-
});
|
|
206006
|
-
}
|
|
206030
|
+
if (onPauseDetected) await onPauseDetected(pause);
|
|
206007
206031
|
completedToolCalls.push({ id: toolCallId, name: toolName, arguments: toolArgs });
|
|
206008
206032
|
break;
|
|
206009
206033
|
}
|
|
@@ -206260,7 +206284,7 @@ var init_gemini_direct_stream_adapter = __esm({
|
|
|
206260
206284
|
init_node2();
|
|
206261
206285
|
init_esm2();
|
|
206262
206286
|
init_store();
|
|
206263
|
-
|
|
206287
|
+
init_envelope();
|
|
206264
206288
|
init_provider_attempt();
|
|
206265
206289
|
}
|
|
206266
206290
|
});
|
|
@@ -207714,6 +207738,7 @@ var init_tool_categories = __esm({
|
|
|
207714
207738
|
"update-project",
|
|
207715
207739
|
"mcp_config_apply",
|
|
207716
207740
|
"mcp_config_request_secret",
|
|
207741
|
+
"mcp_server_request_approval",
|
|
207717
207742
|
"mcp_call_tool",
|
|
207718
207743
|
"mcp_server_create",
|
|
207719
207744
|
"mcp_server_update",
|
|
@@ -212213,7 +212238,7 @@ var require_redis_errors = __commonJS({
|
|
|
212213
212238
|
var require_lib3 = __commonJS({
|
|
212214
212239
|
"node_modules/.pnpm/cluster-key-slot@1.1.2/node_modules/cluster-key-slot/lib/index.js"(exports2, module) {
|
|
212215
212240
|
"use strict";
|
|
212216
|
-
var
|
|
212241
|
+
var lookup3 = [
|
|
212217
212242
|
0,
|
|
212218
212243
|
4129,
|
|
212219
212244
|
8258,
|
|
@@ -212513,11 +212538,11 @@ var require_lib3 = __commonJS({
|
|
|
212513
212538
|
start = i19;
|
|
212514
212539
|
}
|
|
212515
212540
|
} else if (char2 !== 125) {
|
|
212516
|
-
resultHash =
|
|
212541
|
+
resultHash = lookup3[(char2 ^ resultHash >> 8) & 255] ^ resultHash << 8;
|
|
212517
212542
|
} else if (i19 - 1 !== start) {
|
|
212518
212543
|
return resultHash & 16383;
|
|
212519
212544
|
}
|
|
212520
|
-
result =
|
|
212545
|
+
result = lookup3[(char2 ^ result >> 8) & 255] ^ result << 8;
|
|
212521
212546
|
}
|
|
212522
212547
|
return result & 16383;
|
|
212523
212548
|
};
|
|
@@ -220243,6 +220268,7 @@ function buildMcpServerToolsPromptSection({
|
|
|
220243
220268
|
"- Prefer user-wide profile tools: `mcp_server_list`, `mcp_server_create`, `mcp_server_update`, `mcp_server_delete`, and `mcp_server_test`.",
|
|
220244
220269
|
"- Use legacy sandbox config tools `mcp_config_list`, `mcp_config_propose`, `mcp_config_test`, and `mcp_config_apply` only when the user explicitly asks for legacy per-sandbox MCP config.",
|
|
220245
220270
|
"- Never ask the user to reveal secret values. Use `vault_secret_list` to find full secret IDs, or exact Vault secret names when the create/update tool allows them.",
|
|
220271
|
+
"- A server that would receive Vault secrets stays inactive until the user approves it in the app. You cannot approve it: when a tool result says `approvalRequired`, share the `approvalUrl` and wait. Changing its URL, command, or secret bindings requires approval again.",
|
|
220246
220272
|
"- For npx/uvx API-key MCP servers, put command/header flags in `args` and bind secret values through `envSecretRefs`, not `headersSecretRefs`.",
|
|
220247
220273
|
'- Groundcover API-key setup uses `runner: "npx"`, `package: "mcp-remote"`, args including `https://mcp.groundcover.com/api/mcp`, `--header`, `Authorization:${GROUNDCOVER_API_KEY}`, and `envSecretRefs: { "GROUNDCOVER_API_KEY": "<secret-id-or-name>" }`.',
|
|
220248
220274
|
"- After command-based MCP config changes, use `sandbox_list` then `sandbox_restart` if a running execution environment needs a fresh start."
|
|
@@ -220521,6 +220547,43 @@ var init_store2 = __esm({
|
|
|
220521
220547
|
}
|
|
220522
220548
|
});
|
|
220523
220549
|
|
|
220550
|
+
// src/core/pause/mcp-approval.ts
|
|
220551
|
+
var mcp_approval_exports = {};
|
|
220552
|
+
__export2(mcp_approval_exports, {
|
|
220553
|
+
buildMcpApprovalPause: () => buildMcpApprovalPause,
|
|
220554
|
+
buildMcpApprovalPlaceholder: () => buildMcpApprovalPlaceholder,
|
|
220555
|
+
formatMcpApprovalDecision: () => formatMcpApprovalDecision
|
|
220556
|
+
});
|
|
220557
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
220558
|
+
function buildMcpApprovalPause(approval, action5) {
|
|
220559
|
+
return {
|
|
220560
|
+
__pause: {
|
|
220561
|
+
kind: MCP_APPROVAL_PAUSE_KIND,
|
|
220562
|
+
resumeToken: randomUUID5(),
|
|
220563
|
+
mcpApproval: approval,
|
|
220564
|
+
action: action5
|
|
220565
|
+
}
|
|
220566
|
+
};
|
|
220567
|
+
}
|
|
220568
|
+
function buildMcpApprovalPlaceholder(approval) {
|
|
220569
|
+
return `[Awaiting user approval for MCP server "${approval.name}" \u2014 approval card is open]`;
|
|
220570
|
+
}
|
|
220571
|
+
function formatMcpApprovalDecision(params) {
|
|
220572
|
+
const { approval, action: action5, decision } = params;
|
|
220573
|
+
const subject = `MCP server "${approval.name}" (id ${approval.profileId}, ${approval.target})`;
|
|
220574
|
+
const done = action5 === "requested" ? "" : ` It was ${action5}.`;
|
|
220575
|
+
if (decision === "approved") {
|
|
220576
|
+
return `User approved ${subject} to use its Vault secrets.${done} It is now active: test it with mcp_server_test before using its tools.`;
|
|
220577
|
+
}
|
|
220578
|
+
return `User rejected ${subject}; it stays disabled and receives no secrets.${done} Do not retry or re-create it unless the user asks.`;
|
|
220579
|
+
}
|
|
220580
|
+
var init_mcp_approval = __esm({
|
|
220581
|
+
"src/core/pause/mcp-approval.ts"() {
|
|
220582
|
+
"use strict";
|
|
220583
|
+
init_envelope();
|
|
220584
|
+
}
|
|
220585
|
+
});
|
|
220586
|
+
|
|
220524
220587
|
// src/lib/services/user.service.ts
|
|
220525
220588
|
var user_service_exports = {};
|
|
220526
220589
|
__export2(user_service_exports, {
|
|
@@ -223153,32 +223216,15 @@ var init_hook_definition = __esm({
|
|
|
223153
223216
|
}
|
|
223154
223217
|
});
|
|
223155
223218
|
|
|
223156
|
-
// src/lib/
|
|
223157
|
-
import { lookup } from "node:dns/promises";
|
|
223158
|
-
import { request as httpRequest } from "node:http";
|
|
223159
|
-
import { request as httpsRequest } from "node:https";
|
|
223219
|
+
// src/lib/net/guarded-fetch.ts
|
|
223160
223220
|
import { isIP as isIP2 } from "node:net";
|
|
223161
|
-
function boundedJson(value, maxBytes, code = "HOOK_RUNTIME_LIMIT") {
|
|
223162
|
-
const json3 = JSON.stringify(value ?? null);
|
|
223163
|
-
if (Buffer.byteLength(json3, "utf8") > maxBytes) throw new Error(code);
|
|
223164
|
-
return json3;
|
|
223165
|
-
}
|
|
223166
|
-
function usableOrigin() {
|
|
223167
|
-
try {
|
|
223168
|
-
return config2.mcp.url ? new URL(config2.mcp.url).origin : null;
|
|
223169
|
-
} catch {
|
|
223170
|
-
return null;
|
|
223171
|
-
}
|
|
223172
|
-
}
|
|
223173
|
-
function sanitizedUrl(url3) {
|
|
223174
|
-
return `${url3.origin}${url3.pathname}`;
|
|
223175
|
-
}
|
|
223176
223221
|
function normalizeIpLiteral(address) {
|
|
223177
223222
|
return address.toLowerCase().replace(/^\[|\]$/g, "");
|
|
223178
223223
|
}
|
|
223179
223224
|
function embeddedIpv4Address(address) {
|
|
223180
|
-
const
|
|
223181
|
-
if (!
|
|
223225
|
+
const prefix2 = ["::ffff:", "64:ff9b::", "::"].find((candidate) => address.startsWith(candidate));
|
|
223226
|
+
if (!prefix2) return null;
|
|
223227
|
+
const suffix = address.slice(prefix2.length);
|
|
223182
223228
|
if (isIP2(suffix) === 4) return suffix;
|
|
223183
223229
|
const match2 = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(suffix);
|
|
223184
223230
|
if (!match2) return null;
|
|
@@ -223195,7 +223241,40 @@ function isForbiddenAddress(address) {
|
|
|
223195
223241
|
const [a22 = 0, b32 = 0] = normalized.split(".").map(Number);
|
|
223196
223242
|
return a22 === 0 || a22 === 10 || a22 === 127 || a22 === 100 && b32 >= 64 && b32 <= 127 || a22 === 169 && b32 === 254 || a22 === 172 && b32 >= 16 && b32 <= 31 || a22 === 192 && b32 === 0 || a22 === 192 && b32 === 168 || a22 === 198 && (b32 === 18 || b32 === 19) || a22 === 198 && b32 === 51 || a22 === 203 && b32 === 0 || a22 >= 224;
|
|
223197
223243
|
}
|
|
223198
|
-
return normalized.startsWith("fc") || normalized.startsWith("fd") ||
|
|
223244
|
+
return normalized.startsWith("fc") || normalized.startsWith("fd") || /^fe[89a-f]/.test(normalized) || normalized.startsWith("ff") || normalized.startsWith("2001:db8");
|
|
223245
|
+
}
|
|
223246
|
+
var MCP_FETCH_POLICY;
|
|
223247
|
+
var init_guarded_fetch = __esm({
|
|
223248
|
+
"src/lib/net/guarded-fetch.ts"() {
|
|
223249
|
+
"use strict";
|
|
223250
|
+
MCP_FETCH_POLICY = {
|
|
223251
|
+
allowHttp: true,
|
|
223252
|
+
maxResponseBytes: 5 * 1024 * 1024,
|
|
223253
|
+
timeoutMs: 3e4,
|
|
223254
|
+
maxRedirects: 5
|
|
223255
|
+
};
|
|
223256
|
+
}
|
|
223257
|
+
});
|
|
223258
|
+
|
|
223259
|
+
// src/lib/hooks/hook-runtime.ts
|
|
223260
|
+
import { lookup } from "node:dns/promises";
|
|
223261
|
+
import { request as httpRequest } from "node:http";
|
|
223262
|
+
import { request as httpsRequest } from "node:https";
|
|
223263
|
+
import { isIP as isIP3 } from "node:net";
|
|
223264
|
+
function boundedJson(value, maxBytes, code = "HOOK_RUNTIME_LIMIT") {
|
|
223265
|
+
const json3 = JSON.stringify(value ?? null);
|
|
223266
|
+
if (Buffer.byteLength(json3, "utf8") > maxBytes) throw new Error(code);
|
|
223267
|
+
return json3;
|
|
223268
|
+
}
|
|
223269
|
+
function usableOrigin() {
|
|
223270
|
+
try {
|
|
223271
|
+
return config2.mcp.url ? new URL(config2.mcp.url).origin : null;
|
|
223272
|
+
} catch {
|
|
223273
|
+
return null;
|
|
223274
|
+
}
|
|
223275
|
+
}
|
|
223276
|
+
function sanitizedUrl(url3) {
|
|
223277
|
+
return `${url3.origin}${url3.pathname}`;
|
|
223199
223278
|
}
|
|
223200
223279
|
async function validateDestination(url3) {
|
|
223201
223280
|
if (Buffer.byteLength(url3.toString()) > LIMITS.urlBytes || url3.username || url3.password) {
|
|
@@ -223212,8 +223291,8 @@ async function validateDestination(url3) {
|
|
|
223212
223291
|
if (url3.hostname === "localhost" || url3.hostname.endsWith(".local")) {
|
|
223213
223292
|
throw new Error("HOOK_FETCH_DESTINATION_BLOCKED");
|
|
223214
223293
|
}
|
|
223215
|
-
const hostname2 =
|
|
223216
|
-
const addresses =
|
|
223294
|
+
const hostname2 = url3.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
223295
|
+
const addresses = isIP3(hostname2) ? [{ address: hostname2 }] : await lookup(hostname2, { all: true, verbatim: true });
|
|
223217
223296
|
if (addresses.length === 0 || addresses.some(({ address }) => isForbiddenAddress(address))) {
|
|
223218
223297
|
throw new Error("HOOK_FETCH_DESTINATION_BLOCKED");
|
|
223219
223298
|
}
|
|
@@ -223611,6 +223690,7 @@ var init_hook_runtime = __esm({
|
|
|
223611
223690
|
"use strict";
|
|
223612
223691
|
init_config();
|
|
223613
223692
|
init_dist15();
|
|
223693
|
+
init_guarded_fetch();
|
|
223614
223694
|
LIMITS = {
|
|
223615
223695
|
memoryBytes: 16 * 1024 * 1024,
|
|
223616
223696
|
stackBytes: 256 * 1024,
|
|
@@ -225375,12 +225455,12 @@ var init_hook_runtime_token = __esm({
|
|
|
225375
225455
|
});
|
|
225376
225456
|
|
|
225377
225457
|
// src/lib/hooks/hook-test-confirmation.ts
|
|
225378
|
-
import { randomUUID as
|
|
225458
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
225379
225459
|
async function issueHookTestConfirmation(userId, conversationId, turnId) {
|
|
225380
225460
|
if (!await isRedisAvailable()) return null;
|
|
225381
225461
|
const redis = getRedis();
|
|
225382
225462
|
if (!redis) return null;
|
|
225383
|
-
const token =
|
|
225463
|
+
const token = randomUUID6();
|
|
225384
225464
|
await redis.set(
|
|
225385
225465
|
`hook-test-confirmation:${token}`,
|
|
225386
225466
|
JSON.stringify({ userId, conversationId, turnId }),
|
|
@@ -230846,7 +230926,7 @@ var init_conversation_resource_authorization = __esm({
|
|
|
230846
230926
|
});
|
|
230847
230927
|
|
|
230848
230928
|
// src/lib/services/hook-definition.service.ts
|
|
230849
|
-
import { createHash as createHash10, randomUUID as
|
|
230929
|
+
import { createHash as createHash10, randomUUID as randomUUID7 } from "node:crypto";
|
|
230850
230930
|
function deterministicUuid(namespace, value) {
|
|
230851
230931
|
const bytes = Buffer.from(
|
|
230852
230932
|
createHash10("sha256").update(`${namespace}\0${value}`).digest().subarray(0, 16)
|
|
@@ -230857,8 +230937,8 @@ function deterministicUuid(namespace, value) {
|
|
|
230857
230937
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
230858
230938
|
}
|
|
230859
230939
|
async function createHookDefinition(pathway, userId, input, idempotencyKey) {
|
|
230860
|
-
const hookId = idempotencyKey ? deterministicUuid("usable-chat:hook-definition", `${userId}:${idempotencyKey}`) :
|
|
230861
|
-
const revisionId = idempotencyKey ? deterministicUuid("usable-chat:hook-revision", hookId) :
|
|
230940
|
+
const hookId = idempotencyKey ? deterministicUuid("usable-chat:hook-definition", `${userId}:${idempotencyKey}`) : randomUUID7();
|
|
230941
|
+
const revisionId = idempotencyKey ? deterministicUuid("usable-chat:hook-revision", hookId) : randomUUID7();
|
|
230862
230942
|
const existingHook = await getHookDefinition(userId, hookId);
|
|
230863
230943
|
if (existingHook) return existingHook;
|
|
230864
230944
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -230872,7 +230952,7 @@ async function createHookDefinition(pathway, userId, input, idempotencyKey) {
|
|
|
230872
230952
|
const order = (existing.at(-1)?.order ?? -1) + 1;
|
|
230873
230953
|
await pathway.write("hook-definition.0/hook-definition.created.0", {
|
|
230874
230954
|
data: {
|
|
230875
|
-
id:
|
|
230955
|
+
id: randomUUID7(),
|
|
230876
230956
|
timestamp: timestamp2,
|
|
230877
230957
|
hookId,
|
|
230878
230958
|
revisionId,
|
|
@@ -230921,11 +231001,11 @@ async function reviseHookDefinition(pathway, userId, hookId, baseRevision, input
|
|
|
230921
231001
|
).orderBy(asc(hookDefinitions.order));
|
|
230922
231002
|
order = (rows.at(-1)?.order ?? -1) + 1;
|
|
230923
231003
|
}
|
|
230924
|
-
const revisionId =
|
|
231004
|
+
const revisionId = randomUUID7();
|
|
230925
231005
|
try {
|
|
230926
231006
|
await pathway.write("hook-definition.0/hook-definition.revised.0", {
|
|
230927
231007
|
data: {
|
|
230928
|
-
id:
|
|
231008
|
+
id: randomUUID7(),
|
|
230929
231009
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
230930
231010
|
hookId,
|
|
230931
231011
|
revisionId,
|
|
@@ -230953,7 +231033,7 @@ async function setHookActivation(pathway, userId, hookId, enabled2) {
|
|
|
230953
231033
|
if (!await getHookDefinition(userId, hookId)) return null;
|
|
230954
231034
|
await pathway.write("hook-definition.0/hook-definition.activation-changed.0", {
|
|
230955
231035
|
data: {
|
|
230956
|
-
id:
|
|
231036
|
+
id: randomUUID7(),
|
|
230957
231037
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
230958
231038
|
hookId,
|
|
230959
231039
|
userId,
|
|
@@ -230965,7 +231045,7 @@ async function setHookActivation(pathway, userId, hookId, enabled2) {
|
|
|
230965
231045
|
async function reorderHookDefinitions(pathway, userId, input) {
|
|
230966
231046
|
await pathway.write("hook-definition.0/hook-definition.reordered.0", {
|
|
230967
231047
|
data: {
|
|
230968
|
-
id:
|
|
231048
|
+
id: randomUUID7(),
|
|
230969
231049
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
230970
231050
|
userId,
|
|
230971
231051
|
...input
|
|
@@ -301776,7 +301856,7 @@ var init_httpHeaders = __esm({
|
|
|
301776
301856
|
});
|
|
301777
301857
|
|
|
301778
301858
|
// node_modules/.pnpm/@typespec+ts-http-runtime@0.3.4/node_modules/@typespec/ts-http-runtime/dist/esm/util/uuidUtils.js
|
|
301779
|
-
function
|
|
301859
|
+
function randomUUID8() {
|
|
301780
301860
|
return crypto.randomUUID();
|
|
301781
301861
|
}
|
|
301782
301862
|
var init_uuidUtils = __esm({
|
|
@@ -301830,7 +301910,7 @@ var init_pipelineRequest = __esm({
|
|
|
301830
301910
|
this.abortSignal = options2.abortSignal;
|
|
301831
301911
|
this.onUploadProgress = options2.onUploadProgress;
|
|
301832
301912
|
this.onDownloadProgress = options2.onDownloadProgress;
|
|
301833
|
-
this.requestId = options2.requestId ||
|
|
301913
|
+
this.requestId = options2.requestId || randomUUID8();
|
|
301834
301914
|
this.allowInsecureConnection = options2.allowInsecureConnection ?? false;
|
|
301835
301915
|
this.enableBrowserStreams = options2.enableBrowserStreams ?? false;
|
|
301836
301916
|
this.requestOverrides = options2.requestOverrides;
|
|
@@ -303534,7 +303614,7 @@ var init_concat = __esm({
|
|
|
303534
303614
|
|
|
303535
303615
|
// node_modules/.pnpm/@typespec+ts-http-runtime@0.3.4/node_modules/@typespec/ts-http-runtime/dist/esm/policies/multipartPolicy.js
|
|
303536
303616
|
function generateBoundary() {
|
|
303537
|
-
return `----AzSDKFormBoundary${
|
|
303617
|
+
return `----AzSDKFormBoundary${randomUUID8()}`;
|
|
303538
303618
|
}
|
|
303539
303619
|
function encodeHeaders(headers) {
|
|
303540
303620
|
let result = "";
|
|
@@ -304163,8 +304243,8 @@ var init_typeGuards2 = __esm({
|
|
|
304163
304243
|
function isError2(e15) {
|
|
304164
304244
|
return isError(e15);
|
|
304165
304245
|
}
|
|
304166
|
-
function
|
|
304167
|
-
return
|
|
304246
|
+
function randomUUID9() {
|
|
304247
|
+
return randomUUID8();
|
|
304168
304248
|
}
|
|
304169
304249
|
var isNodeLike2;
|
|
304170
304250
|
var init_esm40 = __esm({
|
|
@@ -333526,7 +333606,7 @@ var init_BlobLeaseClient = __esm({
|
|
|
333526
333606
|
this._containerOrBlobOperation = clientContext.blob;
|
|
333527
333607
|
}
|
|
333528
333608
|
if (!leaseId2) {
|
|
333529
|
-
leaseId2 =
|
|
333609
|
+
leaseId2 = randomUUID9();
|
|
333530
333610
|
}
|
|
333531
333611
|
this._leaseId = leaseId2;
|
|
333532
333612
|
}
|
|
@@ -337933,7 +338013,7 @@ var init_Clients = __esm({
|
|
|
337933
338013
|
throw new RangeError(`The buffer's size is too big or the BlockSize is too small;the number of blocks must be <= ${BLOCK_BLOB_MAX_BLOCKS}`);
|
|
337934
338014
|
}
|
|
337935
338015
|
const blockList = [];
|
|
337936
|
-
const blockIDPrefix =
|
|
338016
|
+
const blockIDPrefix = randomUUID9();
|
|
337937
338017
|
let transferProgress = 0;
|
|
337938
338018
|
const batch = new Batch(options2.concurrency);
|
|
337939
338019
|
for (let i19 = 0; i19 < numBlocks; i19++) {
|
|
@@ -338014,7 +338094,7 @@ var init_Clients = __esm({
|
|
|
338014
338094
|
}
|
|
338015
338095
|
return tracingClient.withSpan("BlockBlobClient-uploadStream", options2, async (updatedOptions) => {
|
|
338016
338096
|
let blockNum = 0;
|
|
338017
|
-
const blockIDPrefix =
|
|
338097
|
+
const blockIDPrefix = randomUUID9();
|
|
338018
338098
|
let transferProgress = 0;
|
|
338019
338099
|
const blockList = [];
|
|
338020
338100
|
const scheduler = new BufferScheduler(
|
|
@@ -339139,7 +339219,7 @@ var init_BlobBatch = __esm({
|
|
|
339139
339219
|
constructor() {
|
|
339140
339220
|
this.operationCount = 0;
|
|
339141
339221
|
this.body = "";
|
|
339142
|
-
const tempGuid =
|
|
339222
|
+
const tempGuid = randomUUID9();
|
|
339143
339223
|
this.boundary = `batch_${tempGuid}`;
|
|
339144
339224
|
this.subRequestPrefix = `--${this.boundary}${HTTP_LINE_ENDING}${HeaderConstants.CONTENT_TYPE}: application/http${HTTP_LINE_ENDING}${HeaderConstants.CONTENT_TRANSFER_ENCODING}: binary`;
|
|
339145
339225
|
this.multipartContentType = `multipart/mixed; boundary=${this.boundary}`;
|
|
@@ -350204,7 +350284,7 @@ var require_issuer = __commonJS({
|
|
|
350204
350284
|
var { keystores } = require_weak_cache();
|
|
350205
350285
|
var processResponse = require_process_response();
|
|
350206
350286
|
var request = require_request2();
|
|
350207
|
-
var
|
|
350287
|
+
var inFlight2 = /* @__PURE__ */ new WeakMap();
|
|
350208
350288
|
var caches = /* @__PURE__ */ new WeakMap();
|
|
350209
350289
|
var lrus = (ctx) => {
|
|
350210
350290
|
if (!caches.has(ctx)) {
|
|
@@ -350217,11 +350297,11 @@ var require_issuer = __commonJS({
|
|
|
350217
350297
|
const keystore = keystores.get(this);
|
|
350218
350298
|
const cache10 = lrus(this);
|
|
350219
350299
|
if (reload || !keystore) {
|
|
350220
|
-
if (
|
|
350221
|
-
return
|
|
350300
|
+
if (inFlight2.has(this)) {
|
|
350301
|
+
return inFlight2.get(this);
|
|
350222
350302
|
}
|
|
350223
350303
|
cache10.reset();
|
|
350224
|
-
|
|
350304
|
+
inFlight2.set(
|
|
350225
350305
|
this,
|
|
350226
350306
|
(async () => {
|
|
350227
350307
|
const response = await request.call(this, {
|
|
@@ -350232,7 +350312,7 @@ var require_issuer = __commonJS({
|
|
|
350232
350312
|
Accept: "application/json, application/jwk-set+json"
|
|
350233
350313
|
}
|
|
350234
350314
|
}).finally(() => {
|
|
350235
|
-
|
|
350315
|
+
inFlight2.delete(this);
|
|
350236
350316
|
});
|
|
350237
350317
|
const jwks2 = processResponse(response);
|
|
350238
350318
|
const joseKeyStore = KeyStore.fromJWKS(jwks2, { onlyPublic: true });
|
|
@@ -350241,7 +350321,7 @@ var require_issuer = __commonJS({
|
|
|
350241
350321
|
return joseKeyStore;
|
|
350242
350322
|
})()
|
|
350243
350323
|
);
|
|
350244
|
-
return
|
|
350324
|
+
return inFlight2.get(this);
|
|
350245
350325
|
}
|
|
350246
350326
|
return keystore;
|
|
350247
350327
|
}
|
|
@@ -359211,7 +359291,7 @@ __export2(auth_refresh_coordination_exports, {
|
|
|
359211
359291
|
compressAccessTokenRotation: () => compressAccessTokenRotation,
|
|
359212
359292
|
coordinateAccessTokenRefresh: () => coordinateAccessTokenRefresh
|
|
359213
359293
|
});
|
|
359214
|
-
import { createHash as createHash12, randomUUID as
|
|
359294
|
+
import { createHash as createHash12, randomUUID as randomUUID10 } from "node:crypto";
|
|
359215
359295
|
async function coordinateAccessTokenRefresh(token, refresh2) {
|
|
359216
359296
|
const redis = getRedis();
|
|
359217
359297
|
const secret = process.env.NEXTAUTH_SECRET;
|
|
@@ -359263,7 +359343,7 @@ async function coordinateAccessTokenRefresh(token, refresh2) {
|
|
|
359263
359343
|
}
|
|
359264
359344
|
throw new Error("refresh_rotation_chain_limit");
|
|
359265
359345
|
}
|
|
359266
|
-
const owner =
|
|
359346
|
+
const owner = randomUUID10();
|
|
359267
359347
|
if (!await redis.set(key2, owner, "EX", TTL, "NX")) {
|
|
359268
359348
|
for (let attempt = 0; attempt < 20; attempt++) {
|
|
359269
359349
|
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
@@ -360154,15 +360234,126 @@ var init_embed_auth = __esm({
|
|
|
360154
360234
|
}
|
|
360155
360235
|
});
|
|
360156
360236
|
|
|
360237
|
+
// src/lib/services/oauth-client-trust.service.ts
|
|
360238
|
+
function overrideClientIds() {
|
|
360239
|
+
return (config2.auth.trustedClientIdsRaw ?? "").split(",").map((id) => id.trim()).filter(Boolean);
|
|
360240
|
+
}
|
|
360241
|
+
function getClientTrustUrl() {
|
|
360242
|
+
const mcpUrl = config2.mcp.url;
|
|
360243
|
+
if (!mcpUrl || !MCP_PATH.test(mcpUrl)) return null;
|
|
360244
|
+
return `${mcpUrl.replace(MCP_PATH, "")}/api/oauth/client-trust`;
|
|
360245
|
+
}
|
|
360246
|
+
function remember(azp, verdict) {
|
|
360247
|
+
if (!verdictCache.has(azp) && verdictCache.size >= CACHE_MAX_ENTRIES) {
|
|
360248
|
+
const oldest = verdictCache.keys().next().value;
|
|
360249
|
+
if (typeof oldest === "string") verdictCache.delete(oldest);
|
|
360250
|
+
}
|
|
360251
|
+
const now2 = Date.now();
|
|
360252
|
+
verdictCache.set(
|
|
360253
|
+
azp,
|
|
360254
|
+
verdict === "trusted" ? {
|
|
360255
|
+
verdict,
|
|
360256
|
+
expiresAt: now2 + TRUSTED_TTL_MS,
|
|
360257
|
+
staleUntil: now2 + TRUSTED_TTL_MS + STALE_IF_ERROR_MS
|
|
360258
|
+
} : { verdict, expiresAt: now2 + UNTRUSTED_TTL_MS }
|
|
360259
|
+
);
|
|
360260
|
+
}
|
|
360261
|
+
async function lookup2(azp, accessToken, fetchImpl) {
|
|
360262
|
+
const url3 = getClientTrustUrl();
|
|
360263
|
+
if (!url3) {
|
|
360264
|
+
logger.error("oauth-client-trust", "USABLE_MCP_URL is missing or does not end in /api/mcp");
|
|
360265
|
+
return null;
|
|
360266
|
+
}
|
|
360267
|
+
try {
|
|
360268
|
+
const response = await fetchImpl(url3, {
|
|
360269
|
+
method: "GET",
|
|
360270
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
360271
|
+
cache: "no-store",
|
|
360272
|
+
signal: AbortSignal.timeout(LOOKUP_TIMEOUT_MS)
|
|
360273
|
+
});
|
|
360274
|
+
if (!response.ok) {
|
|
360275
|
+
logger.warn("oauth-client-trust", "Client trust lookup failed", {
|
|
360276
|
+
azp,
|
|
360277
|
+
status: response.status
|
|
360278
|
+
});
|
|
360279
|
+
return null;
|
|
360280
|
+
}
|
|
360281
|
+
const parsed = trustResponseSchema.safeParse(await response.json());
|
|
360282
|
+
if (!parsed.success || parsed.data.clientId !== azp) {
|
|
360283
|
+
logger.warn("oauth-client-trust", "Client trust lookup returned an unexpected body", { azp });
|
|
360284
|
+
return null;
|
|
360285
|
+
}
|
|
360286
|
+
const verdict = parsed.data.trusted ? "trusted" : "untrusted";
|
|
360287
|
+
remember(azp, verdict);
|
|
360288
|
+
return verdict;
|
|
360289
|
+
} catch (error41) {
|
|
360290
|
+
logger.warn("oauth-client-trust", "Client trust lookup errored", {
|
|
360291
|
+
azp,
|
|
360292
|
+
error: error41 instanceof Error ? error41.message : String(error41)
|
|
360293
|
+
});
|
|
360294
|
+
return null;
|
|
360295
|
+
}
|
|
360296
|
+
}
|
|
360297
|
+
async function resolveOAuthClientTrust(azp, accessToken, options2 = {}) {
|
|
360298
|
+
if (!azp) return "untrusted";
|
|
360299
|
+
if (azp === config2.auth.mcpOAuthClientId || overrideClientIds().includes(azp)) return "trusted";
|
|
360300
|
+
const cached2 = verdictCache.get(azp);
|
|
360301
|
+
if (!options2.bypassCache && cached2 && cached2.expiresAt > Date.now()) {
|
|
360302
|
+
return cached2.verdict;
|
|
360303
|
+
}
|
|
360304
|
+
let pending = inFlight.get(azp);
|
|
360305
|
+
if (!pending) {
|
|
360306
|
+
pending = lookup2(azp, accessToken, options2.fetchImpl ?? fetch).finally(() => {
|
|
360307
|
+
inFlight.delete(azp);
|
|
360308
|
+
});
|
|
360309
|
+
inFlight.set(azp, pending);
|
|
360310
|
+
}
|
|
360311
|
+
const verdict = await pending;
|
|
360312
|
+
if (verdict) return verdict;
|
|
360313
|
+
const stale = verdictCache.get(azp);
|
|
360314
|
+
if (!options2.bypassCache && stale?.verdict === "trusted" && stale.staleUntil !== void 0 && stale.staleUntil > Date.now()) {
|
|
360315
|
+
logger.warn("oauth-client-trust", "Serving stale trusted verdict while Usable is unavailable", {
|
|
360316
|
+
azp
|
|
360317
|
+
});
|
|
360318
|
+
return "trusted";
|
|
360319
|
+
}
|
|
360320
|
+
return "unavailable";
|
|
360321
|
+
}
|
|
360322
|
+
var TRUSTED_TTL_MS, UNTRUSTED_TTL_MS, STALE_IF_ERROR_MS, LOOKUP_TIMEOUT_MS, CACHE_MAX_ENTRIES, trustResponseSchema, verdictCache, inFlight, MCP_PATH;
|
|
360323
|
+
var init_oauth_client_trust_service = __esm({
|
|
360324
|
+
"src/lib/services/oauth-client-trust.service.ts"() {
|
|
360325
|
+
"use strict";
|
|
360326
|
+
init_zod();
|
|
360327
|
+
init_config();
|
|
360328
|
+
init_logger();
|
|
360329
|
+
TRUSTED_TTL_MS = 5 * 6e4;
|
|
360330
|
+
UNTRUSTED_TTL_MS = 3e4;
|
|
360331
|
+
STALE_IF_ERROR_MS = 60 * 6e4;
|
|
360332
|
+
LOOKUP_TIMEOUT_MS = 5e3;
|
|
360333
|
+
CACHE_MAX_ENTRIES = 500;
|
|
360334
|
+
trustResponseSchema = external_exports.union([
|
|
360335
|
+
external_exports.object({
|
|
360336
|
+
clientId: external_exports.string().min(1),
|
|
360337
|
+
trusted: external_exports.literal(true),
|
|
360338
|
+
kind: external_exports.enum(["first-party-sso", "mcp-oauth", "marketplace-app"]),
|
|
360339
|
+
appId: external_exports.string().optional()
|
|
360340
|
+
}),
|
|
360341
|
+
external_exports.object({
|
|
360342
|
+
clientId: external_exports.string().min(1).nullable(),
|
|
360343
|
+
trusted: external_exports.literal(false)
|
|
360344
|
+
})
|
|
360345
|
+
]);
|
|
360346
|
+
verdictCache = /* @__PURE__ */ new Map();
|
|
360347
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
360348
|
+
MCP_PATH = /\/api\/mcp\/?$/;
|
|
360349
|
+
}
|
|
360350
|
+
});
|
|
360351
|
+
|
|
360157
360352
|
// src/lib/auth-helper.ts
|
|
360158
360353
|
function parseTrustedClientIds(raw) {
|
|
360159
360354
|
if (!raw) return [];
|
|
360160
360355
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
360161
360356
|
}
|
|
360162
|
-
function isTrustedAzp(azp, trustedClientIds) {
|
|
360163
|
-
if (trustedClientIds.length === 0) return true;
|
|
360164
|
-
return azp !== void 0 && trustedClientIds.includes(azp);
|
|
360165
|
-
}
|
|
360166
360357
|
function hasConfiguredSessionCookie(cookieHeader, sessionCookieName) {
|
|
360167
360358
|
if (!cookieHeader || !sessionCookieName) return false;
|
|
360168
360359
|
return cookieHeader.split(";").some((cookie) => {
|
|
@@ -360227,15 +360418,23 @@ async function getAuthFromRequest(request, options2) {
|
|
|
360227
360418
|
const token = authHeader.slice(7);
|
|
360228
360419
|
const result = await verifyJWT(token);
|
|
360229
360420
|
if (result.success) {
|
|
360230
|
-
const
|
|
360231
|
-
if (
|
|
360421
|
+
const clientTrust = await resolveOAuthClientTrust(result.payload.azp, token);
|
|
360422
|
+
if (clientTrust === "untrusted") {
|
|
360232
360423
|
console.warn(
|
|
360233
|
-
`[AuthHelper] Bearer JWT azp rejected: ${result.payload.azp ?? "<missing>"} not
|
|
360424
|
+
`[AuthHelper] Bearer JWT azp rejected: ${result.payload.azp ?? "<missing>"} is not a client trusted by Usable`
|
|
360234
360425
|
);
|
|
360235
360426
|
lastRejection = {
|
|
360236
360427
|
code: "JWT_AZP_REJECTED",
|
|
360237
360428
|
message: "JWT authorized party (azp) is not a trusted client for this service"
|
|
360238
360429
|
};
|
|
360430
|
+
} else if (clientTrust === "unavailable") {
|
|
360431
|
+
console.warn(
|
|
360432
|
+
`[AuthHelper] Bearer JWT azp ${result.payload.azp} could not be checked: Usable client trust lookup unavailable`
|
|
360433
|
+
);
|
|
360434
|
+
lastRejection = {
|
|
360435
|
+
code: "CLIENT_TRUST_UNAVAILABLE",
|
|
360436
|
+
message: "Client authorization is temporarily unavailable. Please try again."
|
|
360437
|
+
};
|
|
360239
360438
|
} else {
|
|
360240
360439
|
const userId = result.payload.usable_user_id || result.payload.sub;
|
|
360241
360440
|
if (!userId) {
|
|
@@ -360313,6 +360512,7 @@ var init_auth_helper = __esm({
|
|
|
360313
360512
|
init_config();
|
|
360314
360513
|
import_server2 = __toESM(require_server());
|
|
360315
360514
|
init_embed_auth();
|
|
360515
|
+
init_oauth_client_trust_service();
|
|
360316
360516
|
jwks = null;
|
|
360317
360517
|
}
|
|
360318
360518
|
});
|
|
@@ -361534,7 +361734,7 @@ var init_host_jwt = __esm({
|
|
|
361534
361734
|
});
|
|
361535
361735
|
|
|
361536
361736
|
// src/lib/work-runtime/resume-proof.ts
|
|
361537
|
-
import { createHash as createHash14, createHmac as createHmac4, randomUUID as
|
|
361737
|
+
import { createHash as createHash14, createHmac as createHmac4, randomUUID as randomUUID11, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
361538
361738
|
function encoded(value) {
|
|
361539
361739
|
return Buffer.from(value).toString("base64url");
|
|
361540
361740
|
}
|
|
@@ -362379,7 +362579,7 @@ __export2(file_storage_service_exports, {
|
|
|
362379
362579
|
FileStorageService: () => FileStorageService,
|
|
362380
362580
|
fileStorageService: () => fileStorageService
|
|
362381
362581
|
});
|
|
362382
|
-
import { randomUUID as
|
|
362582
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
362383
362583
|
function estimateBase64Bytes2(base643) {
|
|
362384
362584
|
const content = base643.includes(",") ? base643.split(",")[1] : base643;
|
|
362385
362585
|
const len = content.length;
|
|
@@ -362462,7 +362662,7 @@ var init_file_storage_service = __esm({
|
|
|
362462
362662
|
mimeType: stored2.mimeType ?? params.mimeType
|
|
362463
362663
|
};
|
|
362464
362664
|
}
|
|
362465
|
-
const id =
|
|
362665
|
+
const id = randomUUID12();
|
|
362466
362666
|
const preview = params.previewBytes ?? params.bytes;
|
|
362467
362667
|
const llm = params.llmBytes ?? preview;
|
|
362468
362668
|
const estimatedTokens = Math.ceil(Math.ceil(llm.byteLength * 4 / 3) / 100);
|
|
@@ -362629,7 +362829,7 @@ var init_file_storage_service = __esm({
|
|
|
362629
362829
|
* For documents: keeps extractedContent as text and optional originalContent as base64 bytes.
|
|
362630
362830
|
*/
|
|
362631
362831
|
async storeFile(params) {
|
|
362632
|
-
const fileId =
|
|
362832
|
+
const fileId = randomUUID12();
|
|
362633
362833
|
let extractedContent = params.extractedContent;
|
|
362634
362834
|
let originalContent = params.originalContent ?? null;
|
|
362635
362835
|
if (params.fileType === "image" && params.contentType === "base64") {
|
|
@@ -362918,7 +363118,7 @@ var init_file_storage_service = __esm({
|
|
|
362918
363118
|
paths = await storage.uploadVariants({
|
|
362919
363119
|
fileId,
|
|
362920
363120
|
userId,
|
|
362921
|
-
namespace: `migration-${
|
|
363121
|
+
namespace: `migration-${randomUUID12()}`,
|
|
362922
363122
|
variants: {
|
|
362923
363123
|
original: { bytes: original2, mimeType },
|
|
362924
363124
|
preview: { bytes: preview, mimeType: "image/webp" },
|
|
@@ -363183,7 +363383,7 @@ var init_file_storage_service = __esm({
|
|
|
363183
363383
|
});
|
|
363184
363384
|
|
|
363185
363385
|
// src/core/orchestrator/index.ts
|
|
363186
|
-
import { createHash as createHash17, randomUUID as
|
|
363386
|
+
import { createHash as createHash17, randomUUID as randomUUID13 } from "node:crypto";
|
|
363187
363387
|
function shouldRecoverSilentStop({
|
|
363188
363388
|
text: text5,
|
|
363189
363389
|
lastStepHadToolErrors,
|
|
@@ -363738,21 +363938,24 @@ function createPauseCallback({
|
|
|
363738
363938
|
pauseSignaled
|
|
363739
363939
|
}) {
|
|
363740
363940
|
return async (data2) => {
|
|
363741
|
-
orchestrationLogger.info(
|
|
363742
|
-
|
|
363743
|
-
|
|
363744
|
-
|
|
363941
|
+
orchestrationLogger.info(
|
|
363942
|
+
data2.kind === "mcp-approval" ? "Pause detected \u2014 MCP approval (deferred persist)" : "Pause detected \u2014 askUserQuestion (deferred persist)",
|
|
363943
|
+
{
|
|
363944
|
+
resumeToken: data2.resumeToken,
|
|
363945
|
+
...data2.kind === "mcp-approval" ? { profileId: data2.mcpApproval.profileId } : { questionCount: data2.questions.length }
|
|
363946
|
+
}
|
|
363947
|
+
);
|
|
363745
363948
|
pendingPauseRef.current = { data: data2 };
|
|
363746
363949
|
pauseSignaled.current = true;
|
|
363747
363950
|
};
|
|
363748
363951
|
}
|
|
363749
|
-
function replacePauseToolResultPlaceholder(messages4, toolUseId) {
|
|
363952
|
+
function replacePauseToolResultPlaceholder(messages4, toolUseId, placeholder2 = ASK_QUESTION_PLACEHOLDER) {
|
|
363750
363953
|
for (const msg of messages4) {
|
|
363751
363954
|
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
363752
363955
|
const parts = msg.content;
|
|
363753
363956
|
for (const part of parts) {
|
|
363754
363957
|
if (part.type === "tool_result" && part.tool_use_id === toolUseId) {
|
|
363755
|
-
part.content =
|
|
363958
|
+
part.content = placeholder2;
|
|
363756
363959
|
return true;
|
|
363757
363960
|
}
|
|
363758
363961
|
}
|
|
@@ -363760,7 +363963,7 @@ function replacePauseToolResultPlaceholder(messages4, toolUseId) {
|
|
|
363760
363963
|
const oaiMsg = msg;
|
|
363761
363964
|
if (oaiMsg.role === "tool" && oaiMsg.tool_call_id === toolUseId) {
|
|
363762
363965
|
;
|
|
363763
|
-
msg.content =
|
|
363966
|
+
msg.content = placeholder2;
|
|
363764
363967
|
return true;
|
|
363765
363968
|
}
|
|
363766
363969
|
}
|
|
@@ -363782,6 +363985,22 @@ async function drainPendingPause({
|
|
|
363782
363985
|
resolveStreamComplete
|
|
363783
363986
|
}) {
|
|
363784
363987
|
const { data: data2 } = pending;
|
|
363988
|
+
if (data2.kind === "mcp-approval") {
|
|
363989
|
+
return drainMcpApprovalPause({
|
|
363990
|
+
data: data2,
|
|
363991
|
+
toolCalls,
|
|
363992
|
+
emitter,
|
|
363993
|
+
multiplexer,
|
|
363994
|
+
context: context3,
|
|
363995
|
+
messageId,
|
|
363996
|
+
correlationId,
|
|
363997
|
+
conversationMessages,
|
|
363998
|
+
persona,
|
|
363999
|
+
config: config3,
|
|
364000
|
+
embedSnapshot,
|
|
364001
|
+
resolveStreamComplete
|
|
364002
|
+
});
|
|
364003
|
+
}
|
|
363785
364004
|
const askToolCall = toolCalls.find((tc) => tc.name === "ask-user-question");
|
|
363786
364005
|
const pausedToolUseId = askToolCall?.id;
|
|
363787
364006
|
if (pausedToolUseId) {
|
|
@@ -363822,7 +364041,7 @@ async function drainPendingPause({
|
|
|
363822
364041
|
if (durable && conversationId && pausedToolUseId) {
|
|
363823
364042
|
await context3.sessionPathway.write("chat-interaction.0/chat-interaction.updated.0", {
|
|
363824
364043
|
data: {
|
|
363825
|
-
id:
|
|
364044
|
+
id: randomUUID13(),
|
|
363826
364045
|
interactionId: data2.resumeToken,
|
|
363827
364046
|
conversationId,
|
|
363828
364047
|
assistantMessageId: messageId,
|
|
@@ -363906,6 +364125,81 @@ async function drainPendingPause({
|
|
|
363906
364125
|
multiplexer.close();
|
|
363907
364126
|
resolveStreamComplete();
|
|
363908
364127
|
}
|
|
364128
|
+
async function drainMcpApprovalPause({
|
|
364129
|
+
data: data2,
|
|
364130
|
+
toolCalls,
|
|
364131
|
+
emitter,
|
|
364132
|
+
multiplexer,
|
|
364133
|
+
context: context3,
|
|
364134
|
+
messageId,
|
|
364135
|
+
correlationId,
|
|
364136
|
+
conversationMessages,
|
|
364137
|
+
persona,
|
|
364138
|
+
config: config3,
|
|
364139
|
+
embedSnapshot,
|
|
364140
|
+
resolveStreamComplete
|
|
364141
|
+
}) {
|
|
364142
|
+
const { buildMcpApprovalPlaceholder: buildMcpApprovalPlaceholder2 } = await Promise.resolve().then(() => (init_mcp_approval(), mcp_approval_exports));
|
|
364143
|
+
const pausedToolUseId = toolCalls.find((tc) => tc.id === data2.toolCallId)?.id ?? [...toolCalls].reverse().find((tc) => tc.name.startsWith("mcp_server_"))?.id;
|
|
364144
|
+
if (pausedToolUseId) {
|
|
364145
|
+
replacePauseToolResultPlaceholder(
|
|
364146
|
+
conversationMessages,
|
|
364147
|
+
pausedToolUseId,
|
|
364148
|
+
buildMcpApprovalPlaceholder2(data2.mcpApproval)
|
|
364149
|
+
);
|
|
364150
|
+
} else {
|
|
364151
|
+
orchestrationLogger.warn("MCP approval pause signaled but its tool_call was not found");
|
|
364152
|
+
}
|
|
364153
|
+
const snapshot2 = ensureToolCallIntegrity([...conversationMessages]);
|
|
364154
|
+
const lastSequence = emitter.getSequence();
|
|
364155
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
364156
|
+
try {
|
|
364157
|
+
const { storePauseState: storePauseState2 } = await Promise.resolve().then(() => (init_store2(), store_exports));
|
|
364158
|
+
await storePauseState2({
|
|
364159
|
+
kind: "mcp-approval",
|
|
364160
|
+
mcpApproval: data2.mcpApproval,
|
|
364161
|
+
mcpAction: data2.action,
|
|
364162
|
+
resumeToken: data2.resumeToken,
|
|
364163
|
+
userId: context3.session?.user?.id || "",
|
|
364164
|
+
conversationId: context3.metadata?.conversationId,
|
|
364165
|
+
messageId,
|
|
364166
|
+
correlationId,
|
|
364167
|
+
lastSequence,
|
|
364168
|
+
conversationMessages: snapshot2,
|
|
364169
|
+
pausedToolUseId,
|
|
364170
|
+
persona,
|
|
364171
|
+
config: config3,
|
|
364172
|
+
questions: [],
|
|
364173
|
+
temporary: context3.metadata?.temporary === true,
|
|
364174
|
+
embedSnapshot,
|
|
364175
|
+
pausedAt: now2.toISOString(),
|
|
364176
|
+
expiresAt: new Date(now2.getTime() + 60 * 60 * 1e3).toISOString()
|
|
364177
|
+
});
|
|
364178
|
+
} catch (error41) {
|
|
364179
|
+
orchestrationLogger.warn("MCP approval pause cache unavailable; approval still works", {
|
|
364180
|
+
resumeToken: data2.resumeToken,
|
|
364181
|
+
error: error41 instanceof Error ? error41.message : String(error41)
|
|
364182
|
+
});
|
|
364183
|
+
}
|
|
364184
|
+
const approvalEvent = emitter.emit(
|
|
364185
|
+
"mcp-approval-request",
|
|
364186
|
+
{
|
|
364187
|
+
interactionId: data2.resumeToken,
|
|
364188
|
+
resumeToken: data2.resumeToken,
|
|
364189
|
+
approval: data2.mcpApproval,
|
|
364190
|
+
action: data2.action
|
|
364191
|
+
}
|
|
364192
|
+
);
|
|
364193
|
+
multiplexer.send(approvalEvent);
|
|
364194
|
+
orchestrationLogger.info("MCP approval requested, closing stream", {
|
|
364195
|
+
resumeToken: data2.resumeToken,
|
|
364196
|
+
profileId: data2.mcpApproval.profileId,
|
|
364197
|
+
pausedToolUseId,
|
|
364198
|
+
lastSequence
|
|
364199
|
+
});
|
|
364200
|
+
multiplexer.close();
|
|
364201
|
+
resolveStreamComplete();
|
|
364202
|
+
}
|
|
363909
364203
|
function safeProviderErrorCategory(value) {
|
|
363910
364204
|
return typeof value === "string" && providerErrorCategories.has(value) ? value : void 0;
|
|
363911
364205
|
}
|
|
@@ -363917,7 +364211,7 @@ function beginNumberedProviderAttempt(budget, route) {
|
|
|
363917
364211
|
const attempt = budget.begin(route);
|
|
363918
364212
|
const number4 = (providerAttemptNumbers.get(budget) ?? 0) + 1;
|
|
363919
364213
|
providerAttemptNumbers.set(budget, number4);
|
|
363920
|
-
return { attempt, id:
|
|
364214
|
+
return { attempt, id: randomUUID13(), number: number4, startedAt: Date.now() };
|
|
363921
364215
|
}
|
|
363922
364216
|
function hasProviderAttemptCapacity(budget) {
|
|
363923
364217
|
return (providerAttemptNumbers.get(budget) ?? 0) < budget.maxAttempts;
|
|
@@ -364016,7 +364310,7 @@ async function callLLM({
|
|
|
364016
364310
|
}
|
|
364017
364311
|
const effectiveZdr2 = openRouterPolicy.effectiveZdr;
|
|
364018
364312
|
const resolveDirectPolicy = (route) => resolveProviderPolicy({ modelId: selectedModelId, route, ...providerPrivacy });
|
|
364019
|
-
const safeCorrelationId = safeProviderIdentifier(context3.correlationId) ?? safeProviderIdentifier(context3.messageId) ??
|
|
364313
|
+
const safeCorrelationId = safeProviderIdentifier(context3.correlationId) ?? safeProviderIdentifier(context3.messageId) ?? randomUUID13();
|
|
364020
364314
|
const safeModel = getModelById(selectedModelId) || getModelEntry(selectedModelId) ? selectedModelId : void 0;
|
|
364021
364315
|
const endpointIdentity = (endpoint) => createHash17("sha256").update(endpoint).digest("hex").slice(0, 16);
|
|
364022
364316
|
const circuitPolicy = (endpoint) => `zdr:${effectiveZdr2 ? "required" : "disabled"}:endpoint:${endpointIdentity(endpoint)}`;
|
|
@@ -366181,7 +366475,7 @@ Folder behavior:
|
|
|
366181
366475
|
}
|
|
366182
366476
|
};
|
|
366183
366477
|
}
|
|
366184
|
-
const planMessage = config3.enableTools ? "\u{1F527} Engaging model with tools..." : "\u{1F4AC} Responding with selected model...";
|
|
366478
|
+
const planMessage = config3.autoModelNotice ?? (config3.enableTools ? "\u{1F527} Engaging model with tools..." : "\u{1F4AC} Responding with selected model...");
|
|
366185
366479
|
const planEvent = emitter.emit("plan", {
|
|
366186
366480
|
plan: planMessage,
|
|
366187
366481
|
steps: config3.maxSteps
|
|
@@ -368347,7 +368641,7 @@ Continue once without hiding or replacing your prior response.`
|
|
|
368347
368641
|
};
|
|
368348
368642
|
}
|
|
368349
368643
|
function createOrchestratorRequest(messages4, context3, config3, persona, apiKey, mcpTools, anthropicApiKey, providerBaseUrl, providerAuthToken, codexAuth) {
|
|
368350
|
-
const messageId = context3.messageId ||
|
|
368644
|
+
const messageId = context3.messageId || randomUUID13();
|
|
368351
368645
|
if (!context3.sessionPathway) {
|
|
368352
368646
|
throw new Error(
|
|
368353
368647
|
"sessionPathway is required but not provided. Ensure createSessionPathwaysForAPI() is called in the API route and sessionPathway is passed to createOrchestratorRequest."
|
|
@@ -370245,7 +370539,7 @@ var init_skills3 = __esm({
|
|
|
370245
370539
|
// src/adapters/cli/subagent.ts
|
|
370246
370540
|
import { spawn as spawn5 } from "node:child_process";
|
|
370247
370541
|
import { basename as basename8 } from "node:path";
|
|
370248
|
-
import { randomUUID as
|
|
370542
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
370249
370543
|
function currentSubagentDepth() {
|
|
370250
370544
|
const d21 = Number(process.env.USABLE_SUBAGENT_DEPTH ?? 0);
|
|
370251
370545
|
return Number.isFinite(d21) && d21 > 0 ? Math.floor(d21) : 0;
|
|
@@ -370344,7 +370638,7 @@ function publicTask(task) {
|
|
|
370344
370638
|
};
|
|
370345
370639
|
}
|
|
370346
370640
|
function startCliSubagentTask(input) {
|
|
370347
|
-
const taskId = input.taskId ??
|
|
370641
|
+
const taskId = input.taskId ?? randomUUID14();
|
|
370348
370642
|
const abortController = new AbortController();
|
|
370349
370643
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
370350
370644
|
const run2 = input._run ?? runCliSubagent;
|
|
@@ -385819,7 +386113,7 @@ var init_todo_checklist = __esm({
|
|
|
385819
386113
|
// src/cli/warp-agent.ts
|
|
385820
386114
|
import { openSync, writeSync } from "node:fs";
|
|
385821
386115
|
import { basename as basename9 } from "node:path";
|
|
385822
|
-
import { randomUUID as
|
|
386116
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
385823
386117
|
function isWarpAgentHost() {
|
|
385824
386118
|
return !!process.env.WARP_CLI_AGENT_PROTOCOL_VERSION && process.platform !== "win32";
|
|
385825
386119
|
}
|
|
@@ -385872,7 +386166,7 @@ var init_warp_agent = __esm({
|
|
|
385872
386166
|
"use strict";
|
|
385873
386167
|
WARP_AGENT_SLUG = "usable-chat";
|
|
385874
386168
|
APP_NAME = "usable-chat";
|
|
385875
|
-
sessionId =
|
|
386169
|
+
sessionId = randomUUID15();
|
|
385876
386170
|
}
|
|
385877
386171
|
});
|
|
385878
386172
|
|
|
@@ -391814,7 +392108,7 @@ init_tui_select();
|
|
|
391814
392108
|
init_model_registry();
|
|
391815
392109
|
|
|
391816
392110
|
// package.json
|
|
391817
|
-
var version2 = "1.
|
|
392111
|
+
var version2 = "1.211.0";
|
|
391818
392112
|
|
|
391819
392113
|
// src/adapters/cli/model-catalog.ts
|
|
391820
392114
|
init_codex_auth();
|