blun-king-cli 9.1.612 → 9.1.613
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/CHANGELOG.md +8 -1
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/agent-spine-plugin/src/hook.js +4 -0
- package/agent-spine-plugin/src/lib/preflight.js +27 -9
- package/blun.mjs +1547 -330
- package/bundled-agent-sources.json +2 -2
- package/package.json +1 -1
- package/worker-host.mjs +194 -25
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:5c7277a864ffcc0a6909494ad5ada6956f900fe23735200c5aca26b1e7d78834
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -1211,7 +1211,7 @@ function normalizeBlunToolSchema(schema) {
|
|
|
1211
1211
|
}
|
|
1212
1212
|
function ensureBlunPropertyTypes(schema) {
|
|
1213
1213
|
const normalized = cloneJsonValue(schema);
|
|
1214
|
-
if (!isRecord$
|
|
1214
|
+
if (!isRecord$33(normalized)) throw new Error("JSON Schema root must normalize to an object.");
|
|
1215
1215
|
recurseSchema(normalized);
|
|
1216
1216
|
return normalized;
|
|
1217
1217
|
}
|
|
@@ -1272,7 +1272,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
1272
1272
|
let current = root;
|
|
1273
1273
|
for (const rawPart of ref.slice(2).split("/")) {
|
|
1274
1274
|
const part = unescapeJsonPointerPart(rawPart);
|
|
1275
|
-
if (isRecord$
|
|
1275
|
+
if (isRecord$33(current)) {
|
|
1276
1276
|
if (!hasOwn(current, part)) return { found: false };
|
|
1277
1277
|
current = current[part];
|
|
1278
1278
|
} else if (Array.isArray(current)) {
|
|
@@ -1294,20 +1294,20 @@ function parseJsonPointerArrayIndex(part) {
|
|
|
1294
1294
|
return Number(part);
|
|
1295
1295
|
}
|
|
1296
1296
|
function recurseSchema(node) {
|
|
1297
|
-
if (!isRecord$
|
|
1297
|
+
if (!isRecord$33(node)) return;
|
|
1298
1298
|
visitChildSchemas(node, normalizeProperty);
|
|
1299
1299
|
}
|
|
1300
1300
|
function visitChildSchemas(node, visit) {
|
|
1301
1301
|
for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
|
|
1302
1302
|
const value = node[key];
|
|
1303
1303
|
if (kind === "single") {
|
|
1304
|
-
if (isRecord$
|
|
1304
|
+
if (isRecord$33(value)) visit(value);
|
|
1305
1305
|
} else if (kind === "array") {
|
|
1306
1306
|
if (Array.isArray(value)) for (const item of value) visit(item);
|
|
1307
1307
|
} else if (kind === "map") {
|
|
1308
|
-
if (isRecord$
|
|
1308
|
+
if (isRecord$33(value)) for (const item of Object.values(value)) visit(item);
|
|
1309
1309
|
} else if (kind === "schema-or-array") {
|
|
1310
|
-
if (isRecord$
|
|
1310
|
+
if (isRecord$33(value)) visit(value);
|
|
1311
1311
|
else if (Array.isArray(value)) for (const item of value) visit(item);
|
|
1312
1312
|
}
|
|
1313
1313
|
}
|
|
@@ -1319,7 +1319,7 @@ function childSchemaKeysForParentType(parentType) {
|
|
|
1319
1319
|
});
|
|
1320
1320
|
}
|
|
1321
1321
|
function normalizeProperty(node) {
|
|
1322
|
-
if (!isRecord$
|
|
1322
|
+
if (!isRecord$33(node)) return;
|
|
1323
1323
|
if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
|
|
1324
1324
|
const enumValues = node["enum"];
|
|
1325
1325
|
if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
|
|
@@ -1403,14 +1403,14 @@ function hasAnyKey(obj, keys) {
|
|
|
1403
1403
|
}
|
|
1404
1404
|
function cloneJsonValue(value) {
|
|
1405
1405
|
if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
|
|
1406
|
-
if (isRecord$
|
|
1406
|
+
if (isRecord$33(value)) {
|
|
1407
1407
|
const cloned = {};
|
|
1408
1408
|
for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
|
|
1409
1409
|
return cloned;
|
|
1410
1410
|
}
|
|
1411
1411
|
return value;
|
|
1412
1412
|
}
|
|
1413
|
-
function isRecord$
|
|
1413
|
+
function isRecord$33(value) {
|
|
1414
1414
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1415
1415
|
}
|
|
1416
1416
|
function hasOwn(obj, key) {
|
|
@@ -1819,16 +1819,6 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1819
1819
|
const payload = parsed;
|
|
1820
1820
|
const messages = Array.isArray(payload["messages"]) ? payload["messages"] : [];
|
|
1821
1821
|
const tools = Array.isArray(payload["tools"]) ? payload["tools"] : void 0;
|
|
1822
|
-
let systemMessageBytes = 0;
|
|
1823
|
-
let conversationMessageBytes = 0;
|
|
1824
|
-
let toolResultMessageBytes = 0;
|
|
1825
|
-
for (const message of messages) {
|
|
1826
|
-
const size = Buffer.byteLength(JSON.stringify(message), "utf8");
|
|
1827
|
-
const role = message !== null && typeof message === "object" ? message["role"] : void 0;
|
|
1828
|
-
if (role === "system" || role === "developer") systemMessageBytes += size;
|
|
1829
|
-
else if (role === "tool") toolResultMessageBytes += size;
|
|
1830
|
-
else conversationMessageBytes += size;
|
|
1831
|
-
}
|
|
1832
1822
|
const toolDefinitions = Object.freeze((tools ?? []).map((tool, index) => {
|
|
1833
1823
|
const entry = tool !== null && typeof tool === "object" ? tool : void 0;
|
|
1834
1824
|
const fn = entry?.["function"];
|
|
@@ -1839,6 +1829,44 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1839
1829
|
...typeof name === "string" && name.length > 0 && name.length <= 128 ? { name } : {}
|
|
1840
1830
|
});
|
|
1841
1831
|
}));
|
|
1832
|
+
const declaredNames = new Set(toolDefinitions.flatMap((tool) => tool.name === void 0 ? [] : [tool.name]));
|
|
1833
|
+
const callNames = /* @__PURE__ */ new Map();
|
|
1834
|
+
for (const message of messages) {
|
|
1835
|
+
if (message === null || typeof message !== "object" || message["role"] !== "assistant") continue;
|
|
1836
|
+
const calls = message["tool_calls"];
|
|
1837
|
+
if (!Array.isArray(calls)) continue;
|
|
1838
|
+
for (const call of calls) {
|
|
1839
|
+
if (call === null || typeof call !== "object") continue;
|
|
1840
|
+
const entry = call;
|
|
1841
|
+
const fn = entry["function"];
|
|
1842
|
+
const name = fn !== null && typeof fn === "object" ? fn["name"] : void 0;
|
|
1843
|
+
const id = entry["id"];
|
|
1844
|
+
if (typeof id !== "string" || id.length === 0) continue;
|
|
1845
|
+
callNames.set(id, callNames.has(id) ? void 0 : typeof name === "string" && declaredNames.has(name) ? name : void 0);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
let systemMessageBytes = 0;
|
|
1849
|
+
let conversationMessageBytes = 0;
|
|
1850
|
+
let toolResultMessageBytes = 0;
|
|
1851
|
+
const results = /* @__PURE__ */ new Map();
|
|
1852
|
+
for (const message of messages) {
|
|
1853
|
+
const size = Buffer.byteLength(JSON.stringify(message), "utf8");
|
|
1854
|
+
const role = message !== null && typeof message === "object" ? message["role"] : void 0;
|
|
1855
|
+
if (role === "system" || role === "developer") systemMessageBytes += size;
|
|
1856
|
+
else if (role === "tool") {
|
|
1857
|
+
toolResultMessageBytes += size;
|
|
1858
|
+
const id = message["tool_call_id"];
|
|
1859
|
+
const name = typeof id === "string" ? callNames.get(id) : void 0;
|
|
1860
|
+
const key = name ?? "";
|
|
1861
|
+
const previous = results.get(key);
|
|
1862
|
+
results.set(key, {
|
|
1863
|
+
...name === void 0 ? {} : { name },
|
|
1864
|
+
count: (previous?.count ?? 0) + 1,
|
|
1865
|
+
bytes: (previous?.bytes ?? 0) + size
|
|
1866
|
+
});
|
|
1867
|
+
} else conversationMessageBytes += size;
|
|
1868
|
+
}
|
|
1869
|
+
const toolResultByTool = Object.freeze(Array.from(results.values(), (entry) => Object.freeze(entry)));
|
|
1842
1870
|
const toolArrayOverheadBytes = tools === void 0 ? 0 : 2 + Math.max(0, tools.length - 1);
|
|
1843
1871
|
const toolSchemaBytes = toolDefinitions.reduce((sum, tool) => sum + tool.bytes, toolArrayOverheadBytes);
|
|
1844
1872
|
return Object.freeze({
|
|
@@ -1848,6 +1876,7 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1848
1876
|
systemMessageBytes,
|
|
1849
1877
|
conversationMessageBytes,
|
|
1850
1878
|
toolResultMessageBytes,
|
|
1879
|
+
...toolResultByTool.length === 0 ? {} : { toolResultByTool },
|
|
1851
1880
|
toolSchemaBytes,
|
|
1852
1881
|
toolDefinitions,
|
|
1853
1882
|
toolArrayOverheadBytes,
|
|
@@ -2350,6 +2379,9 @@ function extractChatCompletionUsage(usage) {
|
|
|
2350
2379
|
const value = usage;
|
|
2351
2380
|
const promptTokens = typeof value["prompt_tokens"] === "number" ? value["prompt_tokens"] : 0;
|
|
2352
2381
|
const completionTokens = typeof value["completion_tokens"] === "number" ? value["completion_tokens"] : 0;
|
|
2382
|
+
const completionDetails = value["completion_tokens_details"];
|
|
2383
|
+
const reportedReasoning = completionDetails !== null && typeof completionDetails === "object" ? completionDetails["reasoning_tokens"] : void 0;
|
|
2384
|
+
const outputReasoning = typeof reportedReasoning === "number" && Number.isSafeInteger(reportedReasoning) && reportedReasoning >= 0 && reportedReasoning <= completionTokens ? reportedReasoning : void 0;
|
|
2353
2385
|
let cachedTokens = 0;
|
|
2354
2386
|
if (typeof value["cached_tokens"] === "number") cachedTokens = value["cached_tokens"];
|
|
2355
2387
|
else if (value["prompt_tokens_details"] !== null && typeof value["prompt_tokens_details"] === "object") {
|
|
@@ -2359,6 +2391,7 @@ function extractChatCompletionUsage(usage) {
|
|
|
2359
2391
|
return {
|
|
2360
2392
|
inputOther: promptTokens - cachedTokens,
|
|
2361
2393
|
output: completionTokens,
|
|
2394
|
+
...outputReasoning === void 0 ? {} : { outputReasoning },
|
|
2362
2395
|
inputCacheRead: cachedTokens,
|
|
2363
2396
|
inputCacheCreation: 0
|
|
2364
2397
|
};
|
|
@@ -3373,9 +3406,11 @@ function emptyUsage() {
|
|
|
3373
3406
|
* Sum two TokenUsage values.
|
|
3374
3407
|
*/
|
|
3375
3408
|
function addUsage$1(a, b) {
|
|
3409
|
+
const outputReasoning = a.outputReasoning !== void 0 && b.outputReasoning !== void 0 ? a.outputReasoning + b.outputReasoning : a.output === 0 ? b.outputReasoning : b.output === 0 ? a.outputReasoning : void 0;
|
|
3376
3410
|
return {
|
|
3377
3411
|
inputOther: a.inputOther + b.inputOther,
|
|
3378
3412
|
output: a.output + b.output,
|
|
3413
|
+
...outputReasoning === void 0 ? {} : { outputReasoning },
|
|
3379
3414
|
inputCacheRead: a.inputCacheRead + b.inputCacheRead,
|
|
3380
3415
|
inputCacheCreation: a.inputCacheCreation + b.inputCacheCreation
|
|
3381
3416
|
};
|
|
@@ -10153,6 +10188,8 @@ var init_schema = __esmMin((() => {
|
|
|
10153
10188
|
ProviderConfigSchema = object$1({
|
|
10154
10189
|
type: ProviderTypeSchema,
|
|
10155
10190
|
apiKey: string().optional(),
|
|
10191
|
+
memoryWorkspaceId: string().regex(/^blun-[0-9a-f]{64}$/u).optional(),
|
|
10192
|
+
memoryApiKeyHash: string().regex(/^[0-9a-f]{64}$/u).optional(),
|
|
10156
10193
|
baseUrl: string().optional(),
|
|
10157
10194
|
defaultModel: string().optional(),
|
|
10158
10195
|
oauth: OAuthRefSchema.optional(),
|
|
@@ -10643,7 +10680,8 @@ function tokenToWire(token) {
|
|
|
10643
10680
|
expires_at: token.expiresAt,
|
|
10644
10681
|
scope: token.scope,
|
|
10645
10682
|
token_type: token.tokenType,
|
|
10646
|
-
expires_in: token.expiresIn
|
|
10683
|
+
expires_in: token.expiresIn,
|
|
10684
|
+
...token.memoryWorkspaceId === void 0 ? {} : { memory_workspace_id: token.memoryWorkspaceId }
|
|
10647
10685
|
};
|
|
10648
10686
|
}
|
|
10649
10687
|
function tokenFromWire(wire) {
|
|
@@ -10653,13 +10691,14 @@ function tokenFromWire(wire) {
|
|
|
10653
10691
|
expiresAt: typeof wire.expires_at === "number" ? wire.expires_at : 0,
|
|
10654
10692
|
scope: wire.scope ?? "",
|
|
10655
10693
|
tokenType: wire.token_type ?? "",
|
|
10656
|
-
expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0
|
|
10694
|
+
expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0,
|
|
10695
|
+
...typeof wire.memory_workspace_id === "string" && wire.memory_workspace_id.length > 0 ? { memoryWorkspaceId: wire.memory_workspace_id } : {}
|
|
10657
10696
|
};
|
|
10658
10697
|
}
|
|
10659
10698
|
var init_types$17 = __esmMin((() => {}));
|
|
10660
10699
|
//#endregion
|
|
10661
10700
|
//#region ../../packages/oauth/src/utils.ts
|
|
10662
|
-
function isRecord$
|
|
10701
|
+
function isRecord$32(value) {
|
|
10663
10702
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10664
10703
|
}
|
|
10665
10704
|
var init_utils$1 = __esmMin((() => {}));
|
|
@@ -11242,7 +11281,7 @@ var init_storage = __esmMin((() => {
|
|
|
11242
11281
|
} catch {
|
|
11243
11282
|
return;
|
|
11244
11283
|
}
|
|
11245
|
-
if (!isRecord$
|
|
11284
|
+
if (!isRecord$32(parsed)) return void 0;
|
|
11246
11285
|
return tokenFromWire(parsed);
|
|
11247
11286
|
}
|
|
11248
11287
|
async save(name, token) {
|
|
@@ -11336,7 +11375,7 @@ function extractApiErrorMessage(value) {
|
|
|
11336
11375
|
}
|
|
11337
11376
|
return;
|
|
11338
11377
|
}
|
|
11339
|
-
if (!isRecord$
|
|
11378
|
+
if (!isRecord$32(value)) return void 0;
|
|
11340
11379
|
for (const key of DIRECT_ERROR_KEYS) {
|
|
11341
11380
|
const message = stringField$4(value, key);
|
|
11342
11381
|
if (message !== void 0) return message;
|
|
@@ -11344,7 +11383,7 @@ function extractApiErrorMessage(value) {
|
|
|
11344
11383
|
const error = value["error"];
|
|
11345
11384
|
const errorString = nonEmptyString$7(error);
|
|
11346
11385
|
if (errorString !== void 0) return errorString;
|
|
11347
|
-
if (isRecord$
|
|
11386
|
+
if (isRecord$32(error)) for (const key of NESTED_ERROR_KEYS) {
|
|
11348
11387
|
const message = stringField$4(error, key);
|
|
11349
11388
|
if (message !== void 0) return message;
|
|
11350
11389
|
}
|
|
@@ -11434,7 +11473,7 @@ async function postForm(url, params, deviceHeaders, options) {
|
|
|
11434
11473
|
let data = {};
|
|
11435
11474
|
try {
|
|
11436
11475
|
const parsed = await response.json();
|
|
11437
|
-
if (isRecord$
|
|
11476
|
+
if (isRecord$32(parsed)) data = parsed;
|
|
11438
11477
|
} catch {}
|
|
11439
11478
|
return {
|
|
11440
11479
|
status,
|
|
@@ -13064,6 +13103,27 @@ var init_oauth_manager = __esmMin((() => {
|
|
|
13064
13103
|
const state = await this.loadState();
|
|
13065
13104
|
return state.kind === "valid" ? state.token.accessToken : void 0;
|
|
13066
13105
|
}
|
|
13106
|
+
async getCachedMemoryWorkspaceId() {
|
|
13107
|
+
const state = await this.loadState();
|
|
13108
|
+
return state.kind === "valid" && state.token.expiresAt > this.now() ? state.token.memoryWorkspaceId : void 0;
|
|
13109
|
+
}
|
|
13110
|
+
async cacheMemoryWorkspaceId(workspaceId) {
|
|
13111
|
+
if (workspaceId.length === 0) return false;
|
|
13112
|
+
const release = await this.acquireRefreshLock();
|
|
13113
|
+
try {
|
|
13114
|
+
const state = await this.loadState();
|
|
13115
|
+
if (state.kind !== "valid" || state.token.expiresAt <= this.now()) return false;
|
|
13116
|
+
if (state.token.memoryWorkspaceId === workspaceId) return true;
|
|
13117
|
+
if (state.token.memoryWorkspaceId !== void 0) return false;
|
|
13118
|
+
await this.storage.save(this.config.name, {
|
|
13119
|
+
...state.token,
|
|
13120
|
+
memoryWorkspaceId: workspaceId
|
|
13121
|
+
});
|
|
13122
|
+
return true;
|
|
13123
|
+
} finally {
|
|
13124
|
+
await release();
|
|
13125
|
+
}
|
|
13126
|
+
}
|
|
13067
13127
|
async logout() {
|
|
13068
13128
|
await this.inFlightRefresh?.promise.catch(() => void 0);
|
|
13069
13129
|
const release = await this.acquireRefreshLock();
|
|
@@ -13131,7 +13191,10 @@ var init_oauth_manager = __esmMin((() => {
|
|
|
13131
13191
|
if (activeToken.refreshToken.length === 0) throw new OAuthUnauthorizedError(`Token for "${this.config.name}" has no refresh_token; re-login required.`);
|
|
13132
13192
|
try {
|
|
13133
13193
|
const refreshed = await this.refreshImpl(this.config, activeToken.refreshToken);
|
|
13134
|
-
await this.storage.save(this.config.name,
|
|
13194
|
+
await this.storage.save(this.config.name, {
|
|
13195
|
+
...refreshed,
|
|
13196
|
+
memoryWorkspaceId: activeToken.memoryWorkspaceId
|
|
13197
|
+
});
|
|
13135
13198
|
this.notifyRefresh({ success: true });
|
|
13136
13199
|
return refreshed.accessToken;
|
|
13137
13200
|
} catch (error) {
|
|
@@ -13346,9 +13409,9 @@ function blunContextWindowsUrl(oauthHost) {
|
|
|
13346
13409
|
return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
|
|
13347
13410
|
}
|
|
13348
13411
|
function parseManagedContextWindow(payload, plan) {
|
|
13349
|
-
if (!isRecord$
|
|
13412
|
+
if (!isRecord$32(payload)) return void 0;
|
|
13350
13413
|
const contextWindows = payload["kontext"];
|
|
13351
|
-
if (!isRecord$
|
|
13414
|
+
if (!isRecord$32(contextWindows)) return void 0;
|
|
13352
13415
|
const value = contextWindows[plan];
|
|
13353
13416
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
13354
13417
|
}
|
|
@@ -13383,7 +13446,7 @@ function parseManagedUsagePayload(payload) {
|
|
|
13383
13446
|
const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
|
|
13384
13447
|
const contextWindowTokens = managedContextWindowFrom(rec);
|
|
13385
13448
|
const unlimited = rec["unlimited"] === true;
|
|
13386
|
-
const stand = isRecord$
|
|
13449
|
+
const stand = isRecord$32(rec["stand"]) ? rec["stand"] : void 0;
|
|
13387
13450
|
if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
|
|
13388
13451
|
const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
|
|
13389
13452
|
if (row !== null) limits.push(row);
|
|
@@ -13393,9 +13456,9 @@ function parseManagedUsagePayload(payload) {
|
|
|
13393
13456
|
const item = rawLimits[idx];
|
|
13394
13457
|
if (!item || typeof item !== "object") continue;
|
|
13395
13458
|
const detailRaw = item["detail"];
|
|
13396
|
-
const detail = isRecord$
|
|
13459
|
+
const detail = isRecord$32(detailRaw) ? detailRaw : item;
|
|
13397
13460
|
const windowRaw = item["window"];
|
|
13398
|
-
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$
|
|
13461
|
+
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$32(windowRaw) ? windowRaw : {}, idx));
|
|
13399
13462
|
if (row !== null) limits.push(row);
|
|
13400
13463
|
}
|
|
13401
13464
|
return {
|
|
@@ -13419,7 +13482,7 @@ function managedContextWindowFrom(payload) {
|
|
|
13419
13482
|
return values.every((value) => value === first) ? first : void 0;
|
|
13420
13483
|
}
|
|
13421
13484
|
function toAccountUsageRow(raw, id, label, accountUnlimited) {
|
|
13422
|
-
if (!isRecord$
|
|
13485
|
+
if (!isRecord$32(raw)) return null;
|
|
13423
13486
|
const used = toInt(raw["verbraucht"]);
|
|
13424
13487
|
const unlimited = accountUnlimited || raw["unlimited"] === true;
|
|
13425
13488
|
const fraction = raw["anteil"];
|
|
@@ -13452,7 +13515,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
|
|
|
13452
13515
|
};
|
|
13453
13516
|
}
|
|
13454
13517
|
function toUsageRow(raw, defaultLabel) {
|
|
13455
|
-
if (!isRecord$
|
|
13518
|
+
if (!isRecord$32(raw)) return null;
|
|
13456
13519
|
const unlimited = raw["unlimited"] === true;
|
|
13457
13520
|
const limit = toInt(raw["limit"]);
|
|
13458
13521
|
let used = toInt(raw["used"]);
|
|
@@ -13573,7 +13636,7 @@ function isManagedQuotaErrorMessage(message) {
|
|
|
13573
13636
|
return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
|
|
13574
13637
|
}
|
|
13575
13638
|
function hasManagedUsageShape(payload) {
|
|
13576
|
-
if (!isRecord$
|
|
13639
|
+
if (!isRecord$32(payload)) return false;
|
|
13577
13640
|
let recognized = false;
|
|
13578
13641
|
if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
|
|
13579
13642
|
recognized = true;
|
|
@@ -13589,15 +13652,15 @@ function hasManagedUsageShape(payload) {
|
|
|
13589
13652
|
if (!Array.isArray(limits)) return false;
|
|
13590
13653
|
for (let index = 0; index < limits.length; index++) {
|
|
13591
13654
|
const item = limits[index];
|
|
13592
|
-
if (!isRecord$
|
|
13593
|
-
const detail = isRecord$
|
|
13594
|
-
if (toUsageRow(detail, limitLabel(item, detail, isRecord$
|
|
13655
|
+
if (!isRecord$32(item)) return false;
|
|
13656
|
+
const detail = isRecord$32(item["detail"]) ? item["detail"] : item;
|
|
13657
|
+
if (toUsageRow(detail, limitLabel(item, detail, isRecord$32(item["window"]) ? item["window"] : {}, index)) === null) return false;
|
|
13595
13658
|
}
|
|
13596
13659
|
}
|
|
13597
13660
|
if ("stand" in payload) {
|
|
13598
13661
|
recognized = true;
|
|
13599
13662
|
const stand = payload["stand"];
|
|
13600
|
-
if (!isRecord$
|
|
13663
|
+
if (!isRecord$32(stand)) return false;
|
|
13601
13664
|
const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
|
|
13602
13665
|
if (windows.length === 0) return false;
|
|
13603
13666
|
const unlimited = payload["unlimited"] === true;
|
|
@@ -13693,8 +13756,8 @@ function userExtras(existing, remoteOwnedFields) {
|
|
|
13693
13756
|
return out;
|
|
13694
13757
|
}
|
|
13695
13758
|
function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
|
|
13696
|
-
const current = isRecord$
|
|
13697
|
-
const overrides = cloneOverrides(isRecord$
|
|
13759
|
+
const current = isRecord$32(existing) ? existing : {};
|
|
13760
|
+
const overrides = cloneOverrides(isRecord$32(current["overrides"]) ? current["overrides"] : void 0);
|
|
13698
13761
|
return {
|
|
13699
13762
|
...userExtras(current, remoteOwnedFields),
|
|
13700
13763
|
...remote,
|
|
@@ -13883,7 +13946,7 @@ function parseModelContextLength(item, modelId) {
|
|
|
13883
13946
|
return values[0];
|
|
13884
13947
|
}
|
|
13885
13948
|
function toModelInfo(item) {
|
|
13886
|
-
if (!isRecord$
|
|
13949
|
+
if (!isRecord$32(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
|
|
13887
13950
|
const contextLength = parseModelContextLength(item, item["id"]);
|
|
13888
13951
|
const displayName = item["display_name"];
|
|
13889
13952
|
const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
|
|
@@ -13970,7 +14033,7 @@ async function fetchManagedBlunCodeModels(options) {
|
|
|
13970
14033
|
throw new Error(message);
|
|
13971
14034
|
}
|
|
13972
14035
|
const payload = await response.json();
|
|
13973
|
-
if (!isRecord$
|
|
14036
|
+
if (!isRecord$32(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
|
|
13974
14037
|
return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
|
|
13975
14038
|
}
|
|
13976
14039
|
throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
|
|
@@ -14013,11 +14076,11 @@ function applyManagedBlunCodeConfig(config, options) {
|
|
|
14013
14076
|
apiKey
|
|
14014
14077
|
};
|
|
14015
14078
|
const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
|
|
14016
|
-
for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$
|
|
14079
|
+
for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$32(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
|
|
14017
14080
|
for (const model of options.models) {
|
|
14018
14081
|
const capabilities = capabilitiesForModel(model);
|
|
14019
14082
|
const key = managedModelKey(model.id);
|
|
14020
|
-
const existing = isRecord$
|
|
14083
|
+
const existing = isRecord$32(existingModels[key]) ? existingModels[key] : {};
|
|
14021
14084
|
const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
|
|
14022
14085
|
existingModels[key] = mergeRefreshedModelAlias(existing, {
|
|
14023
14086
|
provider: BLUN_PROVIDER_NAME$1,
|
|
@@ -14065,7 +14128,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
|
|
|
14065
14128
|
let removedDefaultModel = false;
|
|
14066
14129
|
const existingModels = config.models ?? {};
|
|
14067
14130
|
for (const [key, model] of Object.entries(existingModels)) {
|
|
14068
|
-
if (!isRecord$
|
|
14131
|
+
if (!isRecord$32(model) || model["provider"] !== "managed:blun") continue;
|
|
14069
14132
|
delete existingModels[key];
|
|
14070
14133
|
if (config.defaultModel === key) removedDefaultModel = true;
|
|
14071
14134
|
}
|
|
@@ -14105,7 +14168,7 @@ function selectDefaultModel(config, models, options) {
|
|
|
14105
14168
|
function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
|
|
14106
14169
|
if (managedModels.has(defaultModel)) return true;
|
|
14107
14170
|
const existing = existingModels[defaultModel];
|
|
14108
|
-
return isRecord$
|
|
14171
|
+
return isRecord$32(existing) && existing["provider"] !== "managed:blun";
|
|
14109
14172
|
}
|
|
14110
14173
|
function assertPositiveContextLength(model) {
|
|
14111
14174
|
if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
|
|
@@ -14181,13 +14244,13 @@ function blunManagedQuotaUrl(oauthHost) {
|
|
|
14181
14244
|
return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
|
|
14182
14245
|
}
|
|
14183
14246
|
function parseManagedQuotaPayload(payload) {
|
|
14184
|
-
if (!isRecord$
|
|
14247
|
+
if (!isRecord$32(payload)) return void 0;
|
|
14185
14248
|
const plan = nonEmptyString$6(payload["plan"]);
|
|
14186
14249
|
const paid = payload["bezahlt"];
|
|
14187
14250
|
const creditCents = payload["guthaben_cent"];
|
|
14188
14251
|
const billingKind = nonEmptyString$6(payload["art"]);
|
|
14189
14252
|
const globalUnlimited = payload["unlimited"];
|
|
14190
|
-
if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$
|
|
14253
|
+
if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$32(payload["stand"])) return;
|
|
14191
14254
|
if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
|
|
14192
14255
|
const limits = parseManagedUsagePayload(payload).limits;
|
|
14193
14256
|
if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
|
|
@@ -14257,7 +14320,7 @@ function nonEmptyString$6(value) {
|
|
|
14257
14320
|
function hasStrictQuotaStand(stand, globalUnlimited) {
|
|
14258
14321
|
return REQUIRED_WINDOWS.every(([sourceKey]) => {
|
|
14259
14322
|
const row = stand[sourceKey];
|
|
14260
|
-
if (!isRecord$
|
|
14323
|
+
if (!isRecord$32(row)) return false;
|
|
14261
14324
|
const used = row["verbraucht"];
|
|
14262
14325
|
const rowUnlimited = row["unlimited"];
|
|
14263
14326
|
if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
|
|
@@ -14547,6 +14610,16 @@ var init_toolkit = __esmMin((() => {
|
|
|
14547
14610
|
hasToken: await this.managerFor(name, oauthKey, oauthHost).hasToken()
|
|
14548
14611
|
}] };
|
|
14549
14612
|
}
|
|
14613
|
+
async getCachedMemoryWorkspaceId(oauthRef) {
|
|
14614
|
+
const oauthHost = this.oauthHostFor(oauthRef);
|
|
14615
|
+
const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
|
|
14616
|
+
return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).getCachedMemoryWorkspaceId();
|
|
14617
|
+
}
|
|
14618
|
+
async cacheMemoryWorkspaceId(workspaceId, oauthRef) {
|
|
14619
|
+
const oauthHost = this.oauthHostFor(oauthRef);
|
|
14620
|
+
const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
|
|
14621
|
+
return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).cacheMemoryWorkspaceId(workspaceId);
|
|
14622
|
+
}
|
|
14550
14623
|
async login(providerName, options = {}) {
|
|
14551
14624
|
const name = providerName ?? "managed:blun";
|
|
14552
14625
|
const oauthHost = this.oauthHostFor(options.oauthRef, options.oauthHost);
|
|
@@ -16687,6 +16760,8 @@ function providerToToml(provider, rawProvider) {
|
|
|
16687
16760
|
for (const key of [
|
|
16688
16761
|
"type",
|
|
16689
16762
|
"apiKey",
|
|
16763
|
+
"memoryWorkspaceId",
|
|
16764
|
+
"memoryApiKeyHash",
|
|
16690
16765
|
"baseUrl",
|
|
16691
16766
|
"defaultModel",
|
|
16692
16767
|
"oauth",
|
|
@@ -21772,7 +21847,7 @@ function parseSkillText(options) {
|
|
|
21772
21847
|
throw error;
|
|
21773
21848
|
}
|
|
21774
21849
|
const frontmatter = parsed.data ?? {};
|
|
21775
|
-
if (!isRecord$
|
|
21850
|
+
if (!isRecord$31(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
|
|
21776
21851
|
const metadata = normalizeMetadata(frontmatter);
|
|
21777
21852
|
if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
|
|
21778
21853
|
const name = nonEmptyString$4(metadata.name);
|
|
@@ -21885,7 +21960,7 @@ function tokenizeArgs(raw) {
|
|
|
21885
21960
|
function nonEmptyString$4(value) {
|
|
21886
21961
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
21887
21962
|
}
|
|
21888
|
-
function isRecord$
|
|
21963
|
+
function isRecord$31(value) {
|
|
21889
21964
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21890
21965
|
}
|
|
21891
21966
|
var import_regexp_escape, FrontmatterError, SkillParseError, UnsupportedSkillTypeError, FENCE, METADATA_ALIASES;
|
|
@@ -21934,7 +22009,7 @@ var init_parser$1 = __esmMin((() => {
|
|
|
21934
22009
|
function parseCommandText(input) {
|
|
21935
22010
|
const { text, commandPath, pluginId } = input;
|
|
21936
22011
|
const parsed = parseFrontmatter(text);
|
|
21937
|
-
const frontmatter = isRecord$
|
|
22012
|
+
const frontmatter = isRecord$30(parsed.data) ? parsed.data : {};
|
|
21938
22013
|
const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
|
|
21939
22014
|
const name = nonEmptyString$3(frontmatter["name"]) ?? baseName;
|
|
21940
22015
|
const body = parsed.body.trim();
|
|
@@ -21976,7 +22051,7 @@ function descriptionFromBody(body) {
|
|
|
21976
22051
|
if (firstLine === void 0) return "No description provided.";
|
|
21977
22052
|
return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
|
|
21978
22053
|
}
|
|
21979
|
-
function isRecord$
|
|
22054
|
+
function isRecord$30(value) {
|
|
21980
22055
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21981
22056
|
}
|
|
21982
22057
|
var init_commands = __esmMin((() => {
|
|
@@ -29835,7 +29910,7 @@ var init_per_id_json_store = __esmMin((() => {
|
|
|
29835
29910
|
}));
|
|
29836
29911
|
//#endregion
|
|
29837
29912
|
//#region ../../packages/agent-core/src/agent/background/resume-store.ts
|
|
29838
|
-
var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$
|
|
29913
|
+
var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$29, TaskResumeStore;
|
|
29839
29914
|
var init_resume_store = __esmMin((() => {
|
|
29840
29915
|
init_zod$1();
|
|
29841
29916
|
BACKGROUND_TASK_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*-[0-9a-z]{8}$/;
|
|
@@ -29860,7 +29935,7 @@ var init_resume_store = __esmMin((() => {
|
|
|
29860
29935
|
startedAt: timestamp$2.nullable()
|
|
29861
29936
|
}).strict();
|
|
29862
29937
|
hash$3 = (value) => createHash("sha256").update(value).digest("hex");
|
|
29863
|
-
isRecord$
|
|
29938
|
+
isRecord$29 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
29864
29939
|
TaskResumeStore = class {
|
|
29865
29940
|
home;
|
|
29866
29941
|
constructor(home) {
|
|
@@ -29915,9 +29990,9 @@ var init_resume_store = __esmMin((() => {
|
|
|
29915
29990
|
}
|
|
29916
29991
|
async readOwnedTask(taskId) {
|
|
29917
29992
|
const task = await this.read("tasks", taskId);
|
|
29918
|
-
if (!isRecord$
|
|
29993
|
+
if (!isRecord$29(task)) throw new Error("Task has no persisted local record.");
|
|
29919
29994
|
const owner = task["resumeOwnership"];
|
|
29920
|
-
if (!isRecord$
|
|
29995
|
+
if (!isRecord$29(owner) || owner["version"] !== 1 || owner["scope"] !== hash$3(await this.root()) || owner["taskId"] !== taskId || task["taskId"] !== taskId || task["kind"] !== "agent" || owner["agentId"] !== task["agentId"] || owner["startedAt"] !== task["startedAt"]) throw new Error("Task ownership is unverified; historical or foreign records cannot be resumed automatically.");
|
|
29921
29996
|
const { resumeOwnership: _ownership, ...info } = task;
|
|
29922
29997
|
return info;
|
|
29923
29998
|
}
|
|
@@ -30038,12 +30113,12 @@ function legacyStatusToCurrent$1(task) {
|
|
|
30038
30113
|
return task.status;
|
|
30039
30114
|
}
|
|
30040
30115
|
function isReadablePersistedTask$1(obj) {
|
|
30041
|
-
return isRecord$
|
|
30116
|
+
return isRecord$28(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
|
|
30042
30117
|
}
|
|
30043
30118
|
function isLegacyPersistedTask$1(task) {
|
|
30044
30119
|
return "task_id" in task;
|
|
30045
30120
|
}
|
|
30046
|
-
function isRecord$
|
|
30121
|
+
function isRecord$28(value) {
|
|
30047
30122
|
return typeof value === "object" && value !== null;
|
|
30048
30123
|
}
|
|
30049
30124
|
function optionalNonEmptyString$2(value) {
|
|
@@ -229641,7 +229716,7 @@ function escapeXml(value) {
|
|
|
229641
229716
|
function locationKey(messageIndex, partIndex) {
|
|
229642
229717
|
return `${String(messageIndex)}:${String(partIndex)}`;
|
|
229643
229718
|
}
|
|
229644
|
-
function isRecord$
|
|
229719
|
+
function isRecord$27(value) {
|
|
229645
229720
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
229646
229721
|
}
|
|
229647
229722
|
function isNonNegativeInteger$1(value) {
|
|
@@ -229842,7 +229917,7 @@ var init_vision_reader = __esmMin((() => {
|
|
|
229842
229917
|
reason: "malformed"
|
|
229843
229918
|
};
|
|
229844
229919
|
}
|
|
229845
|
-
if (!isRecord$
|
|
229920
|
+
if (!isRecord$27(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
|
|
229846
229921
|
ok: false,
|
|
229847
229922
|
reason: "malformed"
|
|
229848
229923
|
};
|
|
@@ -231074,7 +231149,7 @@ var init_full = __esmMin((() => {
|
|
|
231074
231149
|
}
|
|
231075
231150
|
requestBodyByteBudget(messages, context) {
|
|
231076
231151
|
const limit = this.agent.blunConfig?.loopControl?.maxRequestHistoryBytes;
|
|
231077
|
-
if (!this.agent.config.hasProvider || this.strategy.compactionBudgetTokens === void 0 || limit
|
|
231152
|
+
if (!this.agent.config.hasProvider || this.strategy.compactionBudgetTokens === void 0 || limit !== void 0 && (!Number.isSafeInteger(limit) || limit <= 0)) return void 0;
|
|
231078
231153
|
const model = this.agent.activeResponderModel ?? this.agent.config.modelAlias;
|
|
231079
231154
|
if (model === void 0 || this.agent.config.runtimeModel(model).provider.name !== "blun") return void 0;
|
|
231080
231155
|
const systemPrompt = context.systemPrompt ?? this.agent.effectiveSystemPrompt;
|
|
@@ -231092,7 +231167,7 @@ var init_full = __esmMin((() => {
|
|
|
231092
231167
|
if (Buffer.byteLength(JSON.stringify({
|
|
231093
231168
|
systemPrompt,
|
|
231094
231169
|
messages: []
|
|
231095
|
-
}), "utf8")
|
|
231170
|
+
}), "utf8") >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
|
|
231096
231171
|
return {
|
|
231097
231172
|
usedRequestBytesEstimate: Buffer.byteLength(JSON.stringify({
|
|
231098
231173
|
systemPrompt,
|
|
@@ -231452,7 +231527,10 @@ var init_full = __esmMin((() => {
|
|
|
231452
231527
|
dropOrphanResults: true
|
|
231453
231528
|
}), createUserMessage(requestInstruction)], capability));
|
|
231454
231529
|
};
|
|
231455
|
-
const estimateRequestBytes = (messages) => Buffer.byteLength(JSON.stringify(
|
|
231530
|
+
const estimateRequestBytes = (messages) => Buffer.byteLength(JSON.stringify({
|
|
231531
|
+
systemPrompt: this.agent.effectiveSystemPrompt,
|
|
231532
|
+
messages
|
|
231533
|
+
}), "utf8");
|
|
231456
231534
|
while (true) {
|
|
231457
231535
|
signal.throwIfAborted();
|
|
231458
231536
|
if (hierarchicalPassCount >= MAX_HIERARCHICAL_COMPACTION_PASSES) throw new BlunError(ErrorCodes.COMPACTION_FAILED, `Compaction stopped after ${String(MAX_HIERARCHICAL_COMPACTION_PASSES)} staged requests without reaching a final summary. The conversation history was not changed.`, { details: {
|
|
@@ -236173,7 +236251,7 @@ function structuredOutput(stdout, input) {
|
|
|
236173
236251
|
return {
|
|
236174
236252
|
...result,
|
|
236175
236253
|
additionalContext: input["hook_event_name"] === "UserPromptSubmit" && hookSpecificOutput?.hookEventName === "UserPromptSubmit" ? hookSpecificOutput.additionalContext : void 0,
|
|
236176
|
-
updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$
|
|
236254
|
+
updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$26(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
|
|
236177
236255
|
};
|
|
236178
236256
|
}
|
|
236179
236257
|
return {
|
|
@@ -236242,7 +236320,7 @@ function killProcessTreeWindows(child, force) {
|
|
|
236242
236320
|
} catch {}
|
|
236243
236321
|
}
|
|
236244
236322
|
}
|
|
236245
|
-
function isRecord$
|
|
236323
|
+
function isRecord$26(value) {
|
|
236246
236324
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
236247
236325
|
}
|
|
236248
236326
|
function errorMessage$12(error) {
|
|
@@ -236259,7 +236337,7 @@ var init_runner = __esmMin((() => {
|
|
|
236259
236337
|
if (typeof value === "string") return value;
|
|
236260
236338
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
236261
236339
|
}, string().optional());
|
|
236262
|
-
HookSpecificOutputSchema = preprocess((value) => isRecord$
|
|
236340
|
+
HookSpecificOutputSchema = preprocess((value) => isRecord$26(value) ? value : void 0, looseObject({
|
|
236263
236341
|
message: OptionalStringSchema,
|
|
236264
236342
|
additionalContext: OptionalStringSchema,
|
|
236265
236343
|
permissionDecision: unknown().optional(),
|
|
@@ -237547,7 +237625,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
237547
237625
|
} catch {
|
|
237548
237626
|
return { kind: "invalid" };
|
|
237549
237627
|
}
|
|
237550
|
-
if (!isRecord$
|
|
237628
|
+
if (!isRecord$25(parsed) || !isRecord$25(parsed["personal_memory"])) return { kind: "invalid" };
|
|
237551
237629
|
const memory = parsed["personal_memory"];
|
|
237552
237630
|
const savedRaw = memory["saved"];
|
|
237553
237631
|
const threadsRaw = memory["threads"];
|
|
@@ -237556,7 +237634,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
237556
237634
|
if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
|
|
237557
237635
|
const saved = [];
|
|
237558
237636
|
for (const value of savedRaw) {
|
|
237559
|
-
if (!isRecord$
|
|
237637
|
+
if (!isRecord$25(value)) return { kind: "invalid" };
|
|
237560
237638
|
const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
|
|
237561
237639
|
const confidence = value["confidence"];
|
|
237562
237640
|
if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
|
|
@@ -237567,7 +237645,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
237567
237645
|
}
|
|
237568
237646
|
const threads = [];
|
|
237569
237647
|
for (const value of threadsRaw) {
|
|
237570
|
-
if (!isRecord$
|
|
237648
|
+
if (!isRecord$25(value)) return { kind: "invalid" };
|
|
237571
237649
|
const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
|
|
237572
237650
|
const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
|
|
237573
237651
|
if (title === void 0 || summary === void 0) return { kind: "invalid" };
|
|
@@ -237621,7 +237699,7 @@ function boundedTrimmedString(value, maxChars) {
|
|
|
237621
237699
|
const trimmed = value.trim();
|
|
237622
237700
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
237623
237701
|
}
|
|
237624
|
-
function isRecord$
|
|
237702
|
+
function isRecord$25(value) {
|
|
237625
237703
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
237626
237704
|
}
|
|
237627
237705
|
var PERSONAL_MEMORY_HOST_RECALL_HANDLER$1, RECALL_LIMIT, RECALL_TIMEOUT_MS, MAX_QUERY_CHARS, MAX_WIRE_CHARS, MAX_SAVED_MEMORIES, MAX_THREADS, MAX_MEMORY_TEXT_CHARS, MAX_THREAD_TITLE_CHARS, MAX_THREAD_SUMMARY_CHARS, CONFIDENCE_VALUES, TELEGRAM_GROUP_MARKER_RE, TELEGRAM_MARKER_RE, TELEGRAM_CHANNEL_RE, TELEGRAM_SOURCE_RE, TELEGRAM_CHAT_ID_RE, TELEGRAM_SENDER_LINE_RE, TELEGRAM_ATTACHMENT_BLOCK_RE, TELEGRAM_ATTACHMENT_NOTICE_RE, TELEGRAM_IMAGE_ATTACHMENT_RE, GENERIC_IMAGE_QUERY, GENERIC_FILE_QUERY, GENERIC_EMPTY_QUERY, PERSONAL_MEMORY_RECALL_VARIANT, PersonalMemoryRecallInjector;
|
|
@@ -240076,10 +240154,27 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240076
240154
|
function relatedSearchTerms(token) {
|
|
240077
240155
|
return TOOL_SEARCH_RELATED_TERM_GROUPS.find((terms) => terms.includes(token)) || [token];
|
|
240078
240156
|
}
|
|
240157
|
+
function withoutFencedCode(value) {
|
|
240158
|
+
const visibleLines = [];
|
|
240159
|
+
let fence = null;
|
|
240160
|
+
for (const line of String(value || "").split(/\r?\n/)) {
|
|
240161
|
+
const marker = line.match(/^ {0,3}(`{3,}|~{3,})/u)?.[1];
|
|
240162
|
+
if (fence) {
|
|
240163
|
+
if (marker?.[0] === fence[0] && marker.length >= fence.length && /^ {0,3}(?:`{3,}|~{3,})[ \t]*$/u.test(line)) fence = null;
|
|
240164
|
+
continue;
|
|
240165
|
+
}
|
|
240166
|
+
if (marker) {
|
|
240167
|
+
fence = marker;
|
|
240168
|
+
continue;
|
|
240169
|
+
}
|
|
240170
|
+
visibleLines.push(line);
|
|
240171
|
+
}
|
|
240172
|
+
return visibleLines.join("\n");
|
|
240173
|
+
}
|
|
240079
240174
|
function rankingIntentTexts(value) {
|
|
240080
240175
|
const text = String(value || "");
|
|
240081
240176
|
const channelBodies = [...text.matchAll(/(?:^|\r?\n)<channel\b[^>]*>\r?\n([\s\S]*?)\r?\n<\/channel>(?=\r?\n|$)/giu)].map((match) => match[1]);
|
|
240082
|
-
return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " ")));
|
|
240177
|
+
return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(withoutFencedCode(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " "))));
|
|
240083
240178
|
}
|
|
240084
240179
|
function rankingTokens(value) {
|
|
240085
240180
|
return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
|
|
@@ -251175,7 +251270,8 @@ function logStepTiming(log, turnId, step, response) {
|
|
|
251175
251270
|
inputOtherTokens: response.usage.inputOther,
|
|
251176
251271
|
cacheReadTokens: response.usage.inputCacheRead,
|
|
251177
251272
|
cacheCreationTokens: response.usage.inputCacheCreation,
|
|
251178
|
-
outputTokens: response.usage.output
|
|
251273
|
+
outputTokens: response.usage.output,
|
|
251274
|
+
...response.usage.outputReasoning === void 0 ? {} : { outputReasoningTokens: response.usage.outputReasoning }
|
|
251179
251275
|
});
|
|
251180
251276
|
}
|
|
251181
251277
|
function deriveStepStopReason(response) {
|
|
@@ -252249,6 +252345,7 @@ var init_events$1 = __esmMin((() => {
|
|
|
252249
252345
|
tokenUsageSchema = object$1({
|
|
252250
252346
|
inputOther: number$1(),
|
|
252251
252347
|
output: number$1(),
|
|
252348
|
+
outputReasoning: number$1().optional(),
|
|
252252
252349
|
inputCacheRead: number$1(),
|
|
252253
252350
|
inputCacheCreation: number$1()
|
|
252254
252351
|
});
|
|
@@ -253429,7 +253526,7 @@ function createAsyncApiDocument(options = {}) {
|
|
|
253429
253526
|
function buildMessages() {
|
|
253430
253527
|
const messages = {};
|
|
253431
253528
|
for (const operation of ASYNCAPI_OPERATIONS) {
|
|
253432
|
-
const id = messageId$
|
|
253529
|
+
const id = messageId$2(operation.type);
|
|
253433
253530
|
messages[id] = asyncApiMessage(operation.type, operation.description, operation.messageSchema);
|
|
253434
253531
|
if (operation.ackSchema !== void 0) {
|
|
253435
253532
|
const ackId = `${id}_ack`;
|
|
@@ -253439,10 +253536,10 @@ function buildMessages() {
|
|
|
253439
253536
|
return messages;
|
|
253440
253537
|
}
|
|
253441
253538
|
function operationMessageRefs(direction) {
|
|
253442
|
-
return ASYNCAPI_OPERATIONS.filter((operation) => operation.direction === direction).map((operation) => ({ $ref: `#/components/messages/${messageId$
|
|
253539
|
+
return ASYNCAPI_OPERATIONS.filter((operation) => operation.direction === direction).map((operation) => ({ $ref: `#/components/messages/${messageId$2(operation.type)}` }));
|
|
253443
253540
|
}
|
|
253444
253541
|
function ackMessageRefs() {
|
|
253445
|
-
return ASYNCAPI_OPERATIONS.filter((operation) => operation.ackSchema !== void 0).map((operation) => ({ $ref: `#/components/messages/${messageId$
|
|
253542
|
+
return ASYNCAPI_OPERATIONS.filter((operation) => operation.ackSchema !== void 0).map((operation) => ({ $ref: `#/components/messages/${messageId$2(operation.type)}_ack` }));
|
|
253446
253543
|
}
|
|
253447
253544
|
function asyncApiMessage(name, summary, schema) {
|
|
253448
253545
|
return {
|
|
@@ -253462,7 +253559,7 @@ function jsonSchema$1(schema) {
|
|
|
253462
253559
|
delete converted["$schema"];
|
|
253463
253560
|
return converted;
|
|
253464
253561
|
}
|
|
253465
|
-
function messageId$
|
|
253562
|
+
function messageId$2(type) {
|
|
253466
253563
|
return type.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
253467
253564
|
}
|
|
253468
253565
|
function titleFromName(name) {
|
|
@@ -269056,6 +269153,10 @@ var init_turn = __esmMin((() => {
|
|
|
269056
269153
|
signal.throwIfAborted();
|
|
269057
269154
|
const blockResult = renderUserPromptHookBlockResult(promptHookResults);
|
|
269058
269155
|
if (blockResult !== void 0) {
|
|
269156
|
+
this.agent.log.warn("turn blocked by UserPromptSubmit hook", {
|
|
269157
|
+
turnId,
|
|
269158
|
+
reason: blockResult.message
|
|
269159
|
+
});
|
|
269059
269160
|
this.agent.context.appendMessage({
|
|
269060
269161
|
role: "assistant",
|
|
269061
269162
|
content: [{
|
|
@@ -269273,6 +269374,17 @@ var init_turn = __esmMin((() => {
|
|
|
269273
269374
|
signal.throwIfAborted();
|
|
269274
269375
|
if (stopBlock !== void 0) {
|
|
269275
269376
|
stopHookContinuationUsed = true;
|
|
269377
|
+
this.agent.log.warn("turn continuation blocked by Stop hook", {
|
|
269378
|
+
turnId,
|
|
269379
|
+
reason: stopBlock.reason
|
|
269380
|
+
});
|
|
269381
|
+
this.agent.emitEvent({
|
|
269382
|
+
type: "hook.result",
|
|
269383
|
+
turnId,
|
|
269384
|
+
hookEvent: "Stop",
|
|
269385
|
+
content: stopBlock.reason,
|
|
269386
|
+
blocked: true
|
|
269387
|
+
});
|
|
269276
269388
|
this.agent.context.appendUserMessage([{
|
|
269277
269389
|
type: "text",
|
|
269278
269390
|
text: stopBlock.reason
|
|
@@ -272739,6 +272851,7 @@ var init_fallback_llm = __esmMin((() => {
|
|
|
272739
272851
|
throw new Error("Fallback request preparation requires a fresh request boundary.");
|
|
272740
272852
|
}
|
|
272741
272853
|
let requestParams = params;
|
|
272854
|
+
let messagesReady = false;
|
|
272742
272855
|
const rebuildRequestMessages = async () => {
|
|
272743
272856
|
const messages = await rebuildMessages();
|
|
272744
272857
|
const suffix = requestParams.boundaryMessageSuffix;
|
|
@@ -272747,7 +272860,14 @@ var init_fallback_llm = __esmMin((() => {
|
|
|
272747
272860
|
while (true) {
|
|
272748
272861
|
const candidate = this.current;
|
|
272749
272862
|
try {
|
|
272750
|
-
|
|
272863
|
+
const prepared = await this.prepareRequest?.(candidate, requestParams, rebuildRequestMessages);
|
|
272864
|
+
if (prepared !== void 0) if ("messagesReady" in prepared) {
|
|
272865
|
+
requestParams = prepared.params;
|
|
272866
|
+
messagesReady = true;
|
|
272867
|
+
} else {
|
|
272868
|
+
requestParams = prepared;
|
|
272869
|
+
messagesReady = false;
|
|
272870
|
+
}
|
|
272751
272871
|
} catch (error) {
|
|
272752
272872
|
if (!isFallbackCandidateError(error) && !isUnavailableFallbackCandidate(error)) throw error;
|
|
272753
272873
|
const nextIndex = this.findNextCandidateIndex();
|
|
@@ -272757,13 +272877,14 @@ var init_fallback_llm = __esmMin((() => {
|
|
|
272757
272877
|
...requestParams,
|
|
272758
272878
|
messages: await rebuildRequestMessages()
|
|
272759
272879
|
};
|
|
272880
|
+
messagesReady = false;
|
|
272760
272881
|
requestParams.signal.throwIfAborted();
|
|
272761
272882
|
this.currentIndex = nextIndex;
|
|
272762
272883
|
this.onModelChanged(this.current.alias);
|
|
272763
272884
|
continue;
|
|
272764
272885
|
}
|
|
272765
272886
|
requestParams.signal.throwIfAborted();
|
|
272766
|
-
const messages = await rebuildRequestMessages();
|
|
272887
|
+
const messages = messagesReady ? requestParams.messages : await rebuildRequestMessages();
|
|
272767
272888
|
requestParams.signal.throwIfAborted();
|
|
272768
272889
|
return {
|
|
272769
272890
|
...requestParams,
|
|
@@ -273088,6 +273209,11 @@ var init_llm_request_logger = __esmMin((() => {
|
|
|
273088
273209
|
systemMessageBytes: breakdown.systemMessageBytes,
|
|
273089
273210
|
conversationMessageBytes: breakdown.conversationMessageBytes,
|
|
273090
273211
|
toolResultMessageBytes: breakdown.toolResultMessageBytes,
|
|
273212
|
+
...breakdown.toolResultByTool === void 0 ? {} : { toolResultByTool: breakdown.toolResultByTool.map((tool) => ({
|
|
273213
|
+
count: tool.count,
|
|
273214
|
+
bytes: tool.bytes,
|
|
273215
|
+
...tool.name === void 0 ? {} : { name: tool.name }
|
|
273216
|
+
})) },
|
|
273091
273217
|
toolSchemaBytes: breakdown.toolSchemaBytes,
|
|
273092
273218
|
otherBytes: breakdown.otherBytes,
|
|
273093
273219
|
...breakdown.toolArrayOverheadBytes === void 0 ? {} : { toolArrayOverheadBytes: breakdown.toolArrayOverheadBytes },
|
|
@@ -273393,11 +273519,18 @@ var init_agent = __esmMin((() => {
|
|
|
273393
273519
|
systemPrompt,
|
|
273394
273520
|
tools: params.tools
|
|
273395
273521
|
}).eligible ? params.tools.filter((tool) => tool.name !== "CompactConversation") : params.tools;
|
|
273396
|
-
this.turn.commitPendingSteers(steers);
|
|
273397
|
-
|
|
273522
|
+
const steersCommitted = this.turn.commitPendingSteers(steers);
|
|
273523
|
+
if (compacted || steersCommitted) params = {
|
|
273398
273524
|
...params,
|
|
273399
|
-
|
|
273400
|
-
|
|
273525
|
+
messages: await rebuildMessages()
|
|
273526
|
+
};
|
|
273527
|
+
return {
|
|
273528
|
+
params: {
|
|
273529
|
+
...params,
|
|
273530
|
+
systemPrompt,
|
|
273531
|
+
tools
|
|
273532
|
+
},
|
|
273533
|
+
messagesReady: true
|
|
273401
273534
|
};
|
|
273402
273535
|
}, (candidate, _params, error) => {
|
|
273403
273536
|
this.fullCompaction.observeContextOverflow(error, candidate.alias);
|
|
@@ -304778,9 +304911,9 @@ function projectAgentSpinePrompt(input) {
|
|
|
304778
304911
|
if (typeof input["hook_event_name"] !== "string" || !PROMPT_EVENTS.has(input["hook_event_name"]) || !Array.isArray(input["prompt"])) return input;
|
|
304779
304912
|
let changed = false;
|
|
304780
304913
|
const prompt = input["prompt"].map((part) => {
|
|
304781
|
-
if (!isRecord$
|
|
304914
|
+
if (!isRecord$24(part)) return part;
|
|
304782
304915
|
const field = part["type"] === "image_url" ? "imageUrl" : part["type"] === "audio_url" ? "audioUrl" : part["type"] === "video_url" ? "videoUrl" : void 0;
|
|
304783
|
-
if (field === void 0 || !isRecord$
|
|
304916
|
+
if (field === void 0 || !isRecord$24(part[field]) || typeof part[field]["url"] !== "string") return part;
|
|
304784
304917
|
const serialized = JSON.stringify(part);
|
|
304785
304918
|
changed = true;
|
|
304786
304919
|
return {
|
|
@@ -304795,7 +304928,7 @@ function projectAgentSpinePrompt(input) {
|
|
|
304795
304928
|
prompt
|
|
304796
304929
|
} : input;
|
|
304797
304930
|
}
|
|
304798
|
-
function isRecord$
|
|
304931
|
+
function isRecord$24(value) {
|
|
304799
304932
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
304800
304933
|
}
|
|
304801
304934
|
var PROMPT_EVENTS, EMPTY_RUNTIME, AgentSpineSessionRuntime;
|
|
@@ -339213,10 +339346,10 @@ async function appendForkedMarkers(state) {
|
|
|
339213
339346
|
time: Date.now()
|
|
339214
339347
|
};
|
|
339215
339348
|
const agents = state["agents"];
|
|
339216
|
-
if (!isRecord$
|
|
339349
|
+
if (!isRecord$23(agents)) return;
|
|
339217
339350
|
const paths = /* @__PURE__ */ new Set();
|
|
339218
339351
|
for (const agentMeta of Object.values(agents)) {
|
|
339219
|
-
if (!isRecord$
|
|
339352
|
+
if (!isRecord$23(agentMeta)) continue;
|
|
339220
339353
|
const homedir = agentMeta["homedir"];
|
|
339221
339354
|
if (typeof homedir !== "string") continue;
|
|
339222
339355
|
paths.add(join$4(homedir, "wire.jsonl"));
|
|
@@ -339228,7 +339361,7 @@ async function appendForkedMarkers(state) {
|
|
|
339228
339361
|
}));
|
|
339229
339362
|
}
|
|
339230
339363
|
function customMetadataForFork(value) {
|
|
339231
|
-
if (!isRecord$
|
|
339364
|
+
if (!isRecord$23(value)) return {};
|
|
339232
339365
|
const custom = {};
|
|
339233
339366
|
for (const [key, entry] of Object.entries(value)) {
|
|
339234
339367
|
if (key === "goal" || key === "managedQuotaWarningThreshold") continue;
|
|
@@ -339283,10 +339416,10 @@ function normalizeForkTitle(title, fallback) {
|
|
|
339283
339416
|
return typeof fallback === "string" && fallback.trim().length > 0 ? fallback : "New Session";
|
|
339284
339417
|
}
|
|
339285
339418
|
function rewriteAgentHomedirs(value, sourceDir, targetDir) {
|
|
339286
|
-
if (!isRecord$
|
|
339419
|
+
if (!isRecord$23(value)) return {};
|
|
339287
339420
|
const agents = {};
|
|
339288
339421
|
for (const [agentId, agentMeta] of Object.entries(value)) {
|
|
339289
|
-
if (!isRecord$
|
|
339422
|
+
if (!isRecord$23(agentMeta)) {
|
|
339290
339423
|
agents[agentId] = agentMeta;
|
|
339291
339424
|
continue;
|
|
339292
339425
|
}
|
|
@@ -339304,7 +339437,7 @@ function remapSessionPath(value, sourceDir, targetDir) {
|
|
|
339304
339437
|
if (rel.startsWith("..") || isAbsolute$2(rel)) return value;
|
|
339305
339438
|
return join$4(targetDir, rel);
|
|
339306
339439
|
}
|
|
339307
|
-
function isRecord$
|
|
339440
|
+
function isRecord$23(value) {
|
|
339308
339441
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
339309
339442
|
}
|
|
339310
339443
|
async function statIfExists(path) {
|
|
@@ -339568,7 +339701,7 @@ var init_session_store$1 = __esmMin((() => {
|
|
|
339568
339701
|
} catch (error) {
|
|
339569
339702
|
throw new BlunError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${input.sourceId}" state.json was not found`, { cause: error });
|
|
339570
339703
|
}
|
|
339571
|
-
if (!isRecord$
|
|
339704
|
+
if (!isRecord$23(parsed)) throw new BlunError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
|
|
339572
339705
|
const title = normalizeForkTitle(input.title, parsed["title"]);
|
|
339573
339706
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
339574
339707
|
const next = {
|
|
@@ -350893,6 +351026,39 @@ var BlunAuthFacade = class {
|
|
|
350893
351026
|
}
|
|
350894
351027
|
return this.toolkit.status(providerName, this.resolveRuntimeManagedAuth(providerName).oauthRef);
|
|
350895
351028
|
}
|
|
351029
|
+
async getCachedMemoryWorkspaceId() {
|
|
351030
|
+
const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
|
|
351031
|
+
if (apiKey !== void 0) {
|
|
351032
|
+
const provider = readConfigFileForUpdate(this.options.configPath).providers[BLUN_PROVIDER_NAME$1];
|
|
351033
|
+
if (provider?.apiKey !== apiKey || provider.memoryApiKeyHash !== memoryApiKeyHash(apiKey)) return;
|
|
351034
|
+
return provider.memoryWorkspaceId;
|
|
351035
|
+
}
|
|
351036
|
+
return this.toolkit.getCachedMemoryWorkspaceId(this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
|
|
351037
|
+
}
|
|
351038
|
+
async cacheMemoryWorkspaceId(workspaceId) {
|
|
351039
|
+
const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
|
|
351040
|
+
if (apiKey !== void 0) {
|
|
351041
|
+
const hash = memoryApiKeyHash(apiKey);
|
|
351042
|
+
return mutateConfigFile(this.options.configPath, (config) => {
|
|
351043
|
+
const provider = config.providers[BLUN_PROVIDER_NAME$1];
|
|
351044
|
+
if (provider?.apiKey !== apiKey) return {
|
|
351045
|
+
config,
|
|
351046
|
+
result: false
|
|
351047
|
+
};
|
|
351048
|
+
if (provider.memoryApiKeyHash === hash && provider.memoryWorkspaceId !== void 0 && provider.memoryWorkspaceId !== workspaceId) return {
|
|
351049
|
+
config,
|
|
351050
|
+
result: false
|
|
351051
|
+
};
|
|
351052
|
+
provider.memoryApiKeyHash = hash;
|
|
351053
|
+
provider.memoryWorkspaceId = workspaceId;
|
|
351054
|
+
return {
|
|
351055
|
+
config,
|
|
351056
|
+
result: true
|
|
351057
|
+
};
|
|
351058
|
+
});
|
|
351059
|
+
}
|
|
351060
|
+
return this.toolkit.cacheMemoryWorkspaceId(workspaceId, this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
|
|
351061
|
+
}
|
|
350896
351062
|
async login(providerName = BLUN_PROVIDER_NAME$1, options = {}) {
|
|
350897
351063
|
const auth = this.resolveManagedAuth(providerName);
|
|
350898
351064
|
const loginAuth = resolveBlunCodeLoginAuth({
|
|
@@ -351198,6 +351364,9 @@ function nonEmpty(value) {
|
|
|
351198
351364
|
const normalized = value?.trim();
|
|
351199
351365
|
return normalized === void 0 || normalized.length === 0 ? void 0 : normalized;
|
|
351200
351366
|
}
|
|
351367
|
+
function memoryApiKeyHash(apiKey) {
|
|
351368
|
+
return createHash("sha256").update(apiKey).digest("hex");
|
|
351369
|
+
}
|
|
351201
351370
|
function transitionAggregateError(message, primary, secondary) {
|
|
351202
351371
|
return new AggregateError([primary, secondary], message, { cause: primary });
|
|
351203
351372
|
}
|
|
@@ -361563,6 +361732,30 @@ var AcpSession = class {
|
|
|
361563
361732
|
}, event.message));
|
|
361564
361733
|
return;
|
|
361565
361734
|
}
|
|
361735
|
+
if (event.type === "hook.result") {
|
|
361736
|
+
if (!isFromMainAgent(event) || event.content.trim().length === 0) return;
|
|
361737
|
+
if (event.blocked === true) log.warn("acp: turn blocked by hook", {
|
|
361738
|
+
sessionId,
|
|
361739
|
+
hookEvent: event.hookEvent,
|
|
361740
|
+
reason: event.content
|
|
361741
|
+
});
|
|
361742
|
+
conn.sessionUpdate({
|
|
361743
|
+
sessionId,
|
|
361744
|
+
update: {
|
|
361745
|
+
sessionUpdate: "agent_message_chunk",
|
|
361746
|
+
content: {
|
|
361747
|
+
type: "text",
|
|
361748
|
+
text: `${event.content}\n`
|
|
361749
|
+
}
|
|
361750
|
+
}
|
|
361751
|
+
}).catch((err) => {
|
|
361752
|
+
log.warn("acp: failed to push hook result", {
|
|
361753
|
+
sessionId,
|
|
361754
|
+
error: err instanceof Error ? err.message : String(err)
|
|
361755
|
+
});
|
|
361756
|
+
});
|
|
361757
|
+
return;
|
|
361758
|
+
}
|
|
361566
361759
|
if (event.type === "assistant.delta") {
|
|
361567
361760
|
if (!isFromMainAgent(event)) return;
|
|
361568
361761
|
conn.sessionUpdate(assistantDeltaToSessionUpdate(sessionId, event)).catch((err) => {
|
|
@@ -364331,8 +364524,8 @@ function createAccountMemoryClient(auth, options = {}) {
|
|
|
364331
364524
|
}
|
|
364332
364525
|
function readAccountMemoryConsentStatus(payload) {
|
|
364333
364526
|
const settings = unwrapPayload(payload)?.["settings"];
|
|
364334
|
-
const dataControls = isRecord$
|
|
364335
|
-
if (!isRecord$
|
|
364527
|
+
const dataControls = isRecord$22(settings) ? settings["data_controls"] : void 0;
|
|
364528
|
+
if (!isRecord$22(dataControls)) throw new Error("Account memory returned an invalid response.");
|
|
364336
364529
|
if (dataControls["memory_consent_asked"] !== true) return "never_asked";
|
|
364337
364530
|
if (dataControls["allow_memory"] === true) return "enabled";
|
|
364338
364531
|
if (dataControls["allow_memory"] === false) return "disabled";
|
|
@@ -364455,8 +364648,8 @@ function memoryContextSummary(facts, included) {
|
|
|
364455
364648
|
})}`;
|
|
364456
364649
|
}
|
|
364457
364650
|
function unwrapPayload(value) {
|
|
364458
|
-
if (!isRecord$
|
|
364459
|
-
return isRecord$
|
|
364651
|
+
if (!isRecord$22(value)) return void 0;
|
|
364652
|
+
return isRecord$22(value["data"]) ? value["data"] : value;
|
|
364460
364653
|
}
|
|
364461
364654
|
function readFacts(root) {
|
|
364462
364655
|
let rawFacts = [];
|
|
@@ -364464,7 +364657,7 @@ function readFacts(root) {
|
|
|
364464
364657
|
else {
|
|
364465
364658
|
const factsJson = parseFactsJson(root["facts_json"]);
|
|
364466
364659
|
if (Array.isArray(factsJson)) rawFacts = factsJson;
|
|
364467
|
-
else if (isRecord$
|
|
364660
|
+
else if (isRecord$22(factsJson) && Array.isArray(factsJson["facts"])) rawFacts = factsJson["facts"];
|
|
364468
364661
|
}
|
|
364469
364662
|
const facts = [];
|
|
364470
364663
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -364493,7 +364686,7 @@ function parseFactsJson(value) {
|
|
|
364493
364686
|
}
|
|
364494
364687
|
}
|
|
364495
364688
|
function normalizeFact(value) {
|
|
364496
|
-
const raw = typeof value === "string" ? value : isRecord$
|
|
364689
|
+
const raw = typeof value === "string" ? value : isRecord$22(value) && typeof value["text"] === "string" ? value["text"] : void 0;
|
|
364497
364690
|
if (raw === void 0) return void 0;
|
|
364498
364691
|
const normalized = raw.replaceAll(/\s+/gu, " ").trim();
|
|
364499
364692
|
if (normalized.length === 0) return void 0;
|
|
@@ -364504,7 +364697,7 @@ function normalizeFact(value) {
|
|
|
364504
364697
|
truncated: normalized.length > ACCOUNT_MEMORY_MAX_FACT_CHARS
|
|
364505
364698
|
};
|
|
364506
364699
|
}
|
|
364507
|
-
function isRecord$
|
|
364700
|
+
function isRecord$22(value) {
|
|
364508
364701
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
364509
364702
|
}
|
|
364510
364703
|
//#endregion
|
|
@@ -364731,6 +364924,8 @@ registerUiCatalogFragment({
|
|
|
364731
364924
|
"auth.logout.selectTitle": "Select a provider to log out",
|
|
364732
364925
|
"auth.logout.none": "Nothing to log out.",
|
|
364733
364926
|
"auth.logout.complete": "Logged out from {provider}.",
|
|
364927
|
+
"auth.warning.memoryRetractionOAuthPending": "Deletion has not been sent yet. It will be sent at your next sign-in.",
|
|
364928
|
+
"auth.warning.memoryRetractionApiKeyPending": "Deletion has not been sent yet. It will be sent once you reconnect.",
|
|
364734
364929
|
"auth.warning.remoteRevokeFailed": "The local OAuth credentials were removed, but remote revocation could not be confirmed.",
|
|
364735
364930
|
"auth.warning.oauthCleanupFailed": "The API key is active, but the previous OAuth credentials could not be fully removed."
|
|
364736
364931
|
},
|
|
@@ -364763,6 +364958,8 @@ registerUiCatalogFragment({
|
|
|
364763
364958
|
"auth.logout.selectTitle": "Anbieter zum Abmelden auswählen",
|
|
364764
364959
|
"auth.logout.none": "Es gibt keine aktive Anmeldung.",
|
|
364765
364960
|
"auth.logout.complete": "Von {provider} abgemeldet.",
|
|
364961
|
+
"auth.warning.memoryRetractionOAuthPending": "Löschen noch nicht übertragen – folgt bei deiner nächsten Anmeldung.",
|
|
364962
|
+
"auth.warning.memoryRetractionApiKeyPending": "Löschen noch nicht übertragen – folgt, sobald du wieder verbunden bist.",
|
|
364766
364963
|
"auth.warning.remoteRevokeFailed": "Die lokalen OAuth-Zugangsdaten wurden entfernt, aber der Widerruf auf dem Server konnte nicht bestätigt werden.",
|
|
364767
364964
|
"auth.warning.oauthCleanupFailed": "Der API-Schlüssel ist aktiv, aber die vorherigen OAuth-Zugangsdaten konnten nicht vollständig entfernt werden."
|
|
364768
364965
|
},
|
|
@@ -364795,6 +364992,8 @@ registerUiCatalogFragment({
|
|
|
364795
364992
|
"auth.logout.selectTitle": "Selecciona el proveedor cuya sesión quieres cerrar",
|
|
364796
364993
|
"auth.logout.none": "No hay ninguna sesión que cerrar.",
|
|
364797
364994
|
"auth.logout.complete": "Sesión cerrada en {provider}.",
|
|
364995
|
+
"auth.warning.memoryRetractionOAuthPending": "La eliminación aún no se ha enviado: se enviará en tu próximo inicio de sesión.",
|
|
364996
|
+
"auth.warning.memoryRetractionApiKeyPending": "La eliminación aún no se ha enviado: se enviará cuando se restablezca la conexión.",
|
|
364798
364997
|
"auth.warning.remoteRevokeFailed": "Las credenciales OAuth locales se han eliminado, pero no se pudo confirmar su revocación en el servidor.",
|
|
364799
364998
|
"auth.warning.oauthCleanupFailed": "La clave de API está activa, pero no se pudieron eliminar por completo las credenciales OAuth anteriores."
|
|
364800
364999
|
},
|
|
@@ -364827,6 +365026,8 @@ registerUiCatalogFragment({
|
|
|
364827
365026
|
"auth.logout.selectTitle": "Sélectionnez le fournisseur dont vous souhaitez vous déconnecter",
|
|
364828
365027
|
"auth.logout.none": "Aucune session à fermer.",
|
|
364829
365028
|
"auth.logout.complete": "Déconnexion de {provider} effectuée.",
|
|
365029
|
+
"auth.warning.memoryRetractionOAuthPending": "Suppression pas encore transmise – elle le sera à ta prochaine connexion.",
|
|
365030
|
+
"auth.warning.memoryRetractionApiKeyPending": "Suppression pas encore transmise – elle le sera dès que la connexion sera rétablie.",
|
|
364830
365031
|
"auth.warning.remoteRevokeFailed": "Les identifiants OAuth locaux ont été supprimés, mais leur révocation sur le serveur n’a pas pu être confirmée.",
|
|
364831
365032
|
"auth.warning.oauthCleanupFailed": "La clé API est active, mais les identifiants OAuth précédents n’ont pas pu être entièrement supprimés."
|
|
364832
365033
|
},
|
|
@@ -364859,6 +365060,8 @@ registerUiCatalogFragment({
|
|
|
364859
365060
|
"auth.logout.selectTitle": "Välj en leverantör att logga ut från",
|
|
364860
365061
|
"auth.logout.none": "Det finns inget att logga ut från.",
|
|
364861
365062
|
"auth.logout.complete": "Utloggad från {provider}.",
|
|
365063
|
+
"auth.warning.memoryRetractionOAuthPending": "Raderingen har inte överförts än – sker vid din nästa inloggning.",
|
|
365064
|
+
"auth.warning.memoryRetractionApiKeyPending": "Raderingen har inte överförts än – sker så snart du är ansluten igen.",
|
|
364862
365065
|
"auth.warning.remoteRevokeFailed": "De lokala OAuth-uppgifterna har tagits bort, men det gick inte att bekräfta återkallelsen på servern.",
|
|
364863
365066
|
"auth.warning.oauthCleanupFailed": "API-nyckeln är aktiv, men de tidigare OAuth-uppgifterna kunde inte tas bort helt."
|
|
364864
365067
|
},
|
|
@@ -364891,6 +365094,8 @@ registerUiCatalogFragment({
|
|
|
364891
365094
|
"auth.logout.selectTitle": "Vyberte poskytovatele, od kterého se chcete odhlásit",
|
|
364892
365095
|
"auth.logout.none": "Nic k odhlášení.",
|
|
364893
365096
|
"auth.logout.complete": "Odhlášeno od {provider}.",
|
|
365097
|
+
"auth.warning.memoryRetractionOAuthPending": "Smazání zatím nebylo přeneseno – proběhne při tvém příštím přihlášení.",
|
|
365098
|
+
"auth.warning.memoryRetractionApiKeyPending": "Smazání zatím nebylo přeneseno – proběhne, jakmile se obnoví připojení.",
|
|
364894
365099
|
"auth.warning.remoteRevokeFailed": "Místní přihlašovací údaje OAuth byly odstraněny, ale jejich zneplatnění na serveru se nepodařilo potvrdit.",
|
|
364895
365100
|
"auth.warning.oauthCleanupFailed": "Klíč API je aktivní, ale předchozí přihlašovací údaje OAuth nebyly zcela odstraněny."
|
|
364896
365101
|
}
|
|
@@ -366022,7 +366227,7 @@ function formatErrorMessage$4(error, filePath) {
|
|
|
366022
366227
|
function findValidationIssues(error) {
|
|
366023
366228
|
if (!(error instanceof Error)) return void 0;
|
|
366024
366229
|
const details = "details" in error ? error.details : void 0;
|
|
366025
|
-
if (!isRecord$
|
|
366230
|
+
if (!isRecord$21(details)) return void 0;
|
|
366026
366231
|
const validationIssues = details["validationIssues"];
|
|
366027
366232
|
return isValidationIssueArray(validationIssues) ? validationIssues : void 0;
|
|
366028
366233
|
}
|
|
@@ -366030,11 +366235,11 @@ function isValidationIssueArray(value) {
|
|
|
366030
366235
|
return Array.isArray(value) && value.every(isValidationIssue);
|
|
366031
366236
|
}
|
|
366032
366237
|
function isValidationIssue(value) {
|
|
366033
|
-
if (!isRecord$
|
|
366238
|
+
if (!isRecord$21(value) || typeof value["message"] !== "string") return false;
|
|
366034
366239
|
const path = value["path"];
|
|
366035
366240
|
return Array.isArray(path) && path.every((segment) => typeof segment === "string" || typeof segment === "number");
|
|
366036
366241
|
}
|
|
366037
|
-
function isRecord$
|
|
366242
|
+
function isRecord$21(value) {
|
|
366038
366243
|
return typeof value === "object" && value !== null;
|
|
366039
366244
|
}
|
|
366040
366245
|
function findZodError(error) {
|
|
@@ -366529,7 +366734,7 @@ function assertEntryCount(value) {
|
|
|
366529
366734
|
return value;
|
|
366530
366735
|
}
|
|
366531
366736
|
function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
|
|
366532
|
-
if (!isRecord$
|
|
366737
|
+
if (!isRecord$20(value) || !hasOnlyKeys(value, [
|
|
366533
366738
|
"version",
|
|
366534
366739
|
"records",
|
|
366535
366740
|
"relations"
|
|
@@ -366542,7 +366747,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
|
|
|
366542
366747
|
return {
|
|
366543
366748
|
version: 1,
|
|
366544
366749
|
records: value["records"].map((candidate, index) => {
|
|
366545
|
-
if (!isRecord$
|
|
366750
|
+
if (!isRecord$20(candidate) || !hasOnlyKeys(candidate, [
|
|
366546
366751
|
"source_record_id",
|
|
366547
366752
|
"type",
|
|
366548
366753
|
"raw_locator"
|
|
@@ -366562,7 +366767,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
|
|
|
366562
366767
|
};
|
|
366563
366768
|
}),
|
|
366564
366769
|
relations: value["relations"].map((candidate, index) => {
|
|
366565
|
-
if (!isRecord$
|
|
366770
|
+
if (!isRecord$20(candidate) || !hasOnlyKeys(candidate, [
|
|
366566
366771
|
"from_source_record_id",
|
|
366567
366772
|
"type",
|
|
366568
366773
|
"to"
|
|
@@ -366572,7 +366777,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
|
|
|
366572
366777
|
const target = candidate["to"];
|
|
366573
366778
|
if (typeof fromRecordId !== "string" || !isValidRecordId(fromRecordId) || !recordIds.has(fromRecordId)) throw new Error(`record relation ${index} must start at a declared local record`);
|
|
366574
366779
|
if (typeof type !== "string" || !MISTAKE_RELATION_TYPES.includes(type)) throw new Error(`record relation ${index} has an invalid relation type`);
|
|
366575
|
-
if (!isRecord$
|
|
366780
|
+
if (!isRecord$20(target) || !hasOnlyKeys(target, ["source_id", "source_record_id"])) throw new Error(`record relation ${index} has an invalid target`);
|
|
366576
366781
|
const targetSourceId = target["source_id"];
|
|
366577
366782
|
const targetRecordId = target["source_record_id"];
|
|
366578
366783
|
if (typeof targetSourceId !== "string" || !isNormalizedSourceId(targetSourceId)) throw new Error(`record relation ${index} has an invalid target source id`);
|
|
@@ -366842,7 +367047,7 @@ function receiptsEqual(left, right) {
|
|
|
366842
367047
|
return left.version === right.version && left.accepted === right.accepted && left.event_id === right.event_id && left.client_event_id === right.client_event_id && left.source_id === right.source_id && left.canonical_agent_id === right.canonical_agent_id && left.received_at === right.received_at && left.raw_count === right.raw_count && left.accepted_count === right.accepted_count && left.rejected_count === right.rejected_count && left.raw_bytes === right.raw_bytes && left.raw_sha256 === right.raw_sha256 && left.declared_entry_count === right.declared_entry_count;
|
|
366843
367048
|
}
|
|
366844
367049
|
function isStateActionReceipt(value) {
|
|
366845
|
-
if (!isRecord$
|
|
367050
|
+
if (!isRecord$20(value) || !hasOnlyKeys(value, STATE_ACTION_KEYS)) return false;
|
|
366846
367051
|
const reason = value["reason"];
|
|
366847
367052
|
return value["version"] === 1 && typeof value["action_id"] === "string" && UUID_RE$1.test(value["action_id"]) && (value["action"] === "remove" || value["action"] === "restore") && typeof value["target_event_id"] === "string" && UUID_RE$1.test(value["target_event_id"]) && typeof value["acted_at"] === "string" && isIsoTimestamp(value["acted_at"]) && Number.isSafeInteger(value["server_sequence"]) && value["server_sequence"] >= 1 && typeof value["principal_id"] === "string" && isNormalizedSourceId(value["principal_id"]) && typeof reason === "string" && reason.trim() === reason && reason.length >= 3 && reason.length <= 500;
|
|
366848
367053
|
}
|
|
@@ -366945,7 +367150,7 @@ function assertInventoryInvariants(bestandsstatus, aktualitaetsstatus, declaredE
|
|
|
366945
367150
|
if (aktualitaetsstatus === "fresh" && lastRawObservedAt === null) throw new Error("fresh inventory requires a last raw observed timestamp");
|
|
366946
367151
|
if (capturedAt !== void 0 && lastRawObservedAt !== null && Date.parse(lastRawObservedAt) > Date.parse(capturedAt)) throw new Error("last raw observed timestamp must not be later than captured at");
|
|
366947
367152
|
}
|
|
366948
|
-
function isRecord$
|
|
367153
|
+
function isRecord$20(value) {
|
|
366949
367154
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
366950
367155
|
}
|
|
366951
367156
|
function hasOnlyKeys(value, allowedKeys) {
|
|
@@ -367889,12 +368094,14 @@ const PERSONAL_MEMORY_EXPLICIT_CATEGORY = "user_explicit";
|
|
|
367889
368094
|
const SAFE_BROKER_ERROR_CODES = new Set([
|
|
367890
368095
|
"AUTHENTICATION_REQUIRED",
|
|
367891
368096
|
"EXPLICIT_CONSENT_REQUIRED",
|
|
368097
|
+
"FORGET_GENERATION_CHANGED",
|
|
367892
368098
|
"INTERNAL_ERROR",
|
|
367893
368099
|
"INTERACTIVE_CONFIRMATION_REQUIRED",
|
|
367894
368100
|
"INSUFFICIENT_SCOPE",
|
|
367895
368101
|
"INVALID_PAYLOAD",
|
|
367896
368102
|
"MEMORY_NOT_FOUND",
|
|
367897
368103
|
"MEMORY_WRITE_DISABLED",
|
|
368104
|
+
"PAYLOAD_TOO_LARGE",
|
|
367898
368105
|
"SECRET_REJECTED",
|
|
367899
368106
|
"UNAVAILABLE"
|
|
367900
368107
|
]);
|
|
@@ -367909,7 +368116,7 @@ var PersonalMemoryBrokerError = class extends Error {
|
|
|
367909
368116
|
}
|
|
367910
368117
|
};
|
|
367911
368118
|
function parsePersonalMemorySettings(payload) {
|
|
367912
|
-
if (!isRecord$
|
|
368119
|
+
if (!isRecord$19(payload)) return void 0;
|
|
367913
368120
|
const status = payload["status"];
|
|
367914
368121
|
if (status !== "configured" && status !== "never_asked") return void 0;
|
|
367915
368122
|
const memoryEnabled = payload["memory_enabled"];
|
|
@@ -368018,21 +368225,23 @@ async function brokerHttpError(response) {
|
|
|
368018
368225
|
const responseCode = await safeBrokerResponseCode(response);
|
|
368019
368226
|
if (responseCode !== void 0) return new PersonalMemoryBrokerError(responseCode, status);
|
|
368020
368227
|
if (status === 401) return new PersonalMemoryBrokerError("AUTHENTICATION_REQUIRED", status);
|
|
368228
|
+
if (status === 409) return new PersonalMemoryBrokerError("FORGET_GENERATION_CHANGED", status);
|
|
368229
|
+
if (status === 413) return new PersonalMemoryBrokerError("PAYLOAD_TOO_LARGE", status);
|
|
368021
368230
|
if (status === 403) return new PersonalMemoryBrokerError("INSUFFICIENT_SCOPE", status);
|
|
368022
368231
|
return new PersonalMemoryBrokerError("UNAVAILABLE", status);
|
|
368023
368232
|
}
|
|
368024
368233
|
async function safeBrokerResponseCode(response) {
|
|
368025
368234
|
try {
|
|
368026
368235
|
const payload = await response.json();
|
|
368027
|
-
if (!isRecord$
|
|
368028
|
-
const nested = isRecord$
|
|
368236
|
+
if (!isRecord$19(payload)) return void 0;
|
|
368237
|
+
const nested = isRecord$19(payload["error"]) ? payload["error"]["code"] : void 0;
|
|
368029
368238
|
const candidate = payload["code"] ?? payload["error_code"] ?? nested;
|
|
368030
368239
|
return typeof candidate === "string" && SAFE_BROKER_ERROR_CODES.has(candidate) ? candidate : void 0;
|
|
368031
368240
|
} catch {
|
|
368032
368241
|
return;
|
|
368033
368242
|
}
|
|
368034
368243
|
}
|
|
368035
|
-
function isRecord$
|
|
368244
|
+
function isRecord$19(value) {
|
|
368036
368245
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
368037
368246
|
}
|
|
368038
368247
|
function isAllowedBrokerRequest(method, path) {
|
|
@@ -368043,13 +368252,17 @@ function isAllowedBrokerRequest(method, path) {
|
|
|
368043
368252
|
return false;
|
|
368044
368253
|
}
|
|
368045
368254
|
if (url.origin !== "https://personal-memory.invalid") return false;
|
|
368046
|
-
if (url.
|
|
368255
|
+
if (url.hash.length > 0) return false;
|
|
368256
|
+
if (url.pathname === "/api/memory/workspace" && url.search.length > 0) return method === "GET" && url.searchParams.size === 2 && url.searchParams.get("source") === "tui" && url.searchParams.has("sessionId") && (url.searchParams.get("sessionId")?.length ?? 0) > 0 && (url.searchParams.get("sessionId")?.length ?? 0) <= 200;
|
|
368257
|
+
if (url.search.length > 0) return false;
|
|
368047
368258
|
const pathname = url.pathname;
|
|
368048
368259
|
if (pathname === PERSONAL_MEMORY_SETTINGS_PATH) return method === "GET" || method === "PUT";
|
|
368049
368260
|
if (pathname === "/api/account/consent") return method === "POST";
|
|
368050
368261
|
if (pathname === PERSONAL_MEMORY_MEMORIES_PATH) return method === "GET" || method === "POST";
|
|
368051
368262
|
if (/^\/v1\/me\/memories\/[0-9a-f-]{36}$/i.test(pathname)) return false;
|
|
368052
368263
|
if (pathname === PERSONAL_MEMORY_RECALL_PATH) return method === PERSONAL_MEMORY_RECALL_METHOD;
|
|
368264
|
+
if (pathname === "/api/memory/workspace") return method === "GET";
|
|
368265
|
+
if (pathname === "/api/memory/capture" || pathname === "/api/memory/recall" || pathname === "/api/memory/search" || pathname === "/api/memory/retract") return method === "POST";
|
|
368053
368266
|
return false;
|
|
368054
368267
|
}
|
|
368055
368268
|
//#endregion
|
|
@@ -368739,7 +368952,7 @@ function createAttestation(value, createdAt) {
|
|
|
368739
368952
|
};
|
|
368740
368953
|
}
|
|
368741
368954
|
function parseProof(value) {
|
|
368742
|
-
if (!isRecord$
|
|
368955
|
+
if (!isRecord$18(value) || value["schema"] !== "blun.proof" || value["schemaVersion"] !== 1) throw new Error("Unsupported proof document.");
|
|
368743
368956
|
assertObjectKeys(value, [
|
|
368744
368957
|
"schema",
|
|
368745
368958
|
"schemaVersion",
|
|
@@ -368759,12 +368972,12 @@ function parseProof(value) {
|
|
|
368759
368972
|
"incomplete",
|
|
368760
368973
|
"failed"
|
|
368761
368974
|
].includes(proof.outcome)) throw new Error("Invalid proof outcome.");
|
|
368762
|
-
if (!isRecord$
|
|
368975
|
+
if (!isRecord$18(proof.source) || proof.source.kind !== "workspace") throw new Error("Invalid proof source.");
|
|
368763
368976
|
assertObjectKeys(proof.source, ["kind"], ["git"], "proof source");
|
|
368764
368977
|
if (proof.source.git !== void 0) validateGitSnapshot(proof.source.git);
|
|
368765
368978
|
if (!Array.isArray(proof.checks) || !Array.isArray(proof.artifacts)) throw new TypeError("Invalid proof collections.");
|
|
368766
368979
|
if (proof.checks.length > MAX_COMMANDS || proof.artifacts.length > MAX_ARTIFACTS) throw new Error("Proof collections exceed their limits.");
|
|
368767
|
-
if (!isRecord$
|
|
368980
|
+
if (!isRecord$18(proof.attestation) || proof.attestation.algorithm !== "SHA-256" || proof.attestation.scope !== "content-integrity-only" || !SHA256_PATTERN.test(proof.attestation.hash)) throw new Error("Invalid proof attestation.");
|
|
368768
368981
|
assertObjectKeys(proof.attestation, [
|
|
368769
368982
|
"algorithm",
|
|
368770
368983
|
"scope",
|
|
@@ -368779,7 +368992,7 @@ function parseProof(value) {
|
|
|
368779
368992
|
screenshot: 0
|
|
368780
368993
|
};
|
|
368781
368994
|
for (const artifact of proof.artifacts) {
|
|
368782
|
-
if (!isRecord$
|
|
368995
|
+
if (!isRecord$18(artifact) || artifact.kind !== "file" && artifact.kind !== "screenshot" || typeof artifact.id !== "string" || typeof artifact.size !== "number" || !Number.isSafeInteger(artifact.size) || artifact.size < 0 || typeof artifact.sha256 !== "string" || !SHA256_PATTERN.test(artifact.sha256)) throw new Error("Invalid proof artifact.");
|
|
368783
368996
|
assertObjectKeys(artifact, [
|
|
368784
368997
|
"id",
|
|
368785
368998
|
"kind",
|
|
@@ -368796,14 +369009,14 @@ function parseProof(value) {
|
|
|
368796
369009
|
return proof;
|
|
368797
369010
|
}
|
|
368798
369011
|
function validateGitSnapshot(value) {
|
|
368799
|
-
if (!isRecord$
|
|
369012
|
+
if (!isRecord$18(value)) throw new Error("Invalid proof git snapshot.");
|
|
368800
369013
|
assertObjectKeys(value, ["dirty", "changedCount"], [], "proof git snapshot");
|
|
368801
369014
|
if (typeof value["dirty"] !== "boolean") throw new TypeError("Invalid proof git dirty flag.");
|
|
368802
369015
|
if (typeof value["changedCount"] !== "number" || !Number.isSafeInteger(value["changedCount"]) || value["changedCount"] < 0) throw new Error("Invalid proof git changed count.");
|
|
368803
369016
|
if (value["dirty"] !== value["changedCount"] > 0) throw new Error("Inconsistent proof git state.");
|
|
368804
369017
|
}
|
|
368805
369018
|
function validateProofCheck(value, index) {
|
|
368806
|
-
if (!isRecord$
|
|
369019
|
+
if (!isRecord$18(value)) throw new Error("Invalid proof check.");
|
|
368807
369020
|
assertObjectKeys(value, [
|
|
368808
369021
|
"id",
|
|
368809
369022
|
"outcome",
|
|
@@ -368815,13 +369028,13 @@ function validateProofCheck(value, index) {
|
|
|
368815
369028
|
if (value["outcome"] !== expectedOutcome) throw new Error("Invalid proof check outcome.");
|
|
368816
369029
|
}
|
|
368817
369030
|
function attestedContent(value) {
|
|
368818
|
-
if (!isRecord$
|
|
369031
|
+
if (!isRecord$18(value)) return value;
|
|
368819
369032
|
const { attestation: _attestation, createdAt: _createdAt, ...content } = value;
|
|
368820
369033
|
return content;
|
|
368821
369034
|
}
|
|
368822
369035
|
function canonicalize(value) {
|
|
368823
369036
|
if (Array.isArray(value)) return value.map(canonicalize);
|
|
368824
|
-
if (!isRecord$
|
|
369037
|
+
if (!isRecord$18(value)) return value;
|
|
368825
369038
|
return Object.keys(value).toSorted().reduce((result, key) => {
|
|
368826
369039
|
result[key] = canonicalize(value[key]);
|
|
368827
369040
|
return result;
|
|
@@ -368898,7 +369111,7 @@ function sameFileIdentity$1(left, right) {
|
|
|
368898
369111
|
function sameFileSnapshot(left, right) {
|
|
368899
369112
|
return sameFileIdentity$1(left, right) && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
|
|
368900
369113
|
}
|
|
368901
|
-
function isRecord$
|
|
369114
|
+
function isRecord$18(value) {
|
|
368902
369115
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
368903
369116
|
}
|
|
368904
369117
|
//#endregion
|
|
@@ -423773,12 +423986,12 @@ function legacyStatusToCurrent(task) {
|
|
|
423773
423986
|
return task.status;
|
|
423774
423987
|
}
|
|
423775
423988
|
function isReadablePersistedTask(obj) {
|
|
423776
|
-
return isRecord$
|
|
423989
|
+
return isRecord$17(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
|
|
423777
423990
|
}
|
|
423778
423991
|
function isLegacyPersistedTask(task) {
|
|
423779
423992
|
return "task_id" in task;
|
|
423780
423993
|
}
|
|
423781
|
-
function isRecord$
|
|
423994
|
+
function isRecord$17(value) {
|
|
423782
423995
|
return typeof value === "object" && value !== null;
|
|
423783
423996
|
}
|
|
423784
423997
|
function optionalNonEmptyString(value) {
|
|
@@ -424187,11 +424400,11 @@ const WINDOWS_RESERVED_NAMES = new Set([
|
|
|
424187
424400
|
...Array.from({ length: 9 }, (_value, index) => `COM${String(index + 1)}`),
|
|
424188
424401
|
...Array.from({ length: 9 }, (_value, index) => `LPT${String(index + 1)}`)
|
|
424189
424402
|
]);
|
|
424190
|
-
function isRecord$
|
|
424403
|
+
function isRecord$16(value) {
|
|
424191
424404
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
424192
424405
|
}
|
|
424193
424406
|
function assertRecord(value, label) {
|
|
424194
|
-
if (!isRecord$
|
|
424407
|
+
if (!isRecord$16(value)) throw new Error(`${label} must be an object.`);
|
|
424195
424408
|
}
|
|
424196
424409
|
function assertExactKeys(value, required, optional, label) {
|
|
424197
424410
|
const allowed = new Set([...required, ...optional]);
|
|
@@ -424482,7 +424695,7 @@ function currentArtifactRecord(artifacts) {
|
|
|
424482
424695
|
return result;
|
|
424483
424696
|
}
|
|
424484
424697
|
function readAttestationHash(value) {
|
|
424485
|
-
if (!isRecord$
|
|
424698
|
+
if (!isRecord$16(value) || !isRecord$16(value["attestation"])) return null;
|
|
424486
424699
|
const hash = value["attestation"]["hash"];
|
|
424487
424700
|
return typeof hash === "string" && /^[a-f0-9]{64}$/.test(hash) ? hash : null;
|
|
424488
424701
|
}
|
|
@@ -425254,21 +425467,21 @@ async function ensureSafeDirectory(path, create, recursive) {
|
|
|
425254
425467
|
return true;
|
|
425255
425468
|
}
|
|
425256
425469
|
function validateRegistry(value, context) {
|
|
425257
|
-
if (!isRecord$
|
|
425470
|
+
if (!isRecord$15(value) || value["version"] !== 1) throw new WorkspaceError("registry_invalid", "Unsupported workspace registry version.");
|
|
425258
425471
|
if (!hasExactKeys(value, REGISTRY_KEYS)) throw new WorkspaceError("registry_invalid", "Workspace registry contains unknown fields.");
|
|
425259
|
-
if (value["repoFingerprint"] !== context.repoFingerprint || value["primaryRoot"] !== context.primaryRoot || !isRecord$
|
|
425472
|
+
if (value["repoFingerprint"] !== context.repoFingerprint || value["primaryRoot"] !== context.primaryRoot || !isRecord$15(value["workspaces"])) throw new WorkspaceError("registry_invalid", "Workspace registry does not match this repository.");
|
|
425260
425473
|
for (const [name, record] of Object.entries(value["workspaces"])) if (!isWorkspaceRecord(record) || record.name !== name) throw new WorkspaceError("registry_invalid", "Workspace registry contains an invalid entry.");
|
|
425261
425474
|
return value;
|
|
425262
425475
|
}
|
|
425263
425476
|
function isWorkspaceRecord(value) {
|
|
425264
|
-
if (!isRecord$
|
|
425477
|
+
if (!isRecord$15(value) || !hasExactKeys(value, WORKSPACE_RECORD_KEYS)) return false;
|
|
425265
425478
|
return typeof value["name"] === "string" && typeof value["path"] === "string" && typeof value["branch"] === "string" && typeof value["baseCommit"] === "string" && typeof value["repoFingerprint"] === "string" && isCanonicalIsoTimestamp(value["createdAt"]);
|
|
425266
425479
|
}
|
|
425267
425480
|
function isCanonicalIsoTimestamp(value) {
|
|
425268
425481
|
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)) return false;
|
|
425269
425482
|
return new Date(value).toISOString() === value;
|
|
425270
425483
|
}
|
|
425271
|
-
function isRecord$
|
|
425484
|
+
function isRecord$15(value) {
|
|
425272
425485
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
425273
425486
|
const prototype = Object.getPrototypeOf(value);
|
|
425274
425487
|
return prototype === Object.prototype || prototype === null;
|
|
@@ -425359,7 +425572,7 @@ async function readRegistryLockMetadata(lockPath) {
|
|
|
425359
425572
|
if (error.code !== void 0) throw error;
|
|
425360
425573
|
return;
|
|
425361
425574
|
}
|
|
425362
|
-
if (!isRecord$
|
|
425575
|
+
if (!isRecord$15(value) || !hasExactKeys(value, [
|
|
425363
425576
|
"version",
|
|
425364
425577
|
"pid",
|
|
425365
425578
|
"createdAt",
|
|
@@ -426068,7 +426281,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
|
|
|
426068
426281
|
let skippedRecords = 0;
|
|
426069
426282
|
for (const session of sessions) {
|
|
426070
426283
|
const sessionDir = await realpath(session.sessionDir).catch(() => void 0);
|
|
426071
|
-
if (sessionDir === void 0 || path.basename(sessionDir) !== session.id || !isInside(sessionsRoot, sessionDir)) {
|
|
426284
|
+
if (sessionDir === void 0 || path.basename(sessionDir) !== session.id || !isInside$1(sessionsRoot, sessionDir)) {
|
|
426072
426285
|
skippedSessions++;
|
|
426073
426286
|
continue;
|
|
426074
426287
|
}
|
|
@@ -426090,7 +426303,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
|
|
|
426090
426303
|
continue;
|
|
426091
426304
|
}
|
|
426092
426305
|
const canonicalWire = await realpath(wirePath).catch(() => void 0);
|
|
426093
|
-
if (canonicalWire === void 0 || !isInside(sessionDir, canonicalWire)) {
|
|
426306
|
+
if (canonicalWire === void 0 || !isInside$1(sessionDir, canonicalWire)) {
|
|
426094
426307
|
skippedSessions++;
|
|
426095
426308
|
continue;
|
|
426096
426309
|
}
|
|
@@ -426108,7 +426321,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
|
|
|
426108
426321
|
skippedRecords++;
|
|
426109
426322
|
continue;
|
|
426110
426323
|
}
|
|
426111
|
-
const event = isRecord$
|
|
426324
|
+
const event = isRecord$14(record) && record["type"] === "context.append_loop_event" && isRecord$14(record["event"]) ? record["event"] : void 0;
|
|
426112
426325
|
if (event?.["type"] === "step.end" && typeof event["uuid"] === "string") assistantSteps.delete(event["uuid"]);
|
|
426113
426326
|
else if (event?.["type"] === "content.part" && typeof event["stepUuid"] === "string" && isTextPart(event["part"])) {
|
|
426114
426327
|
const stepId = event["stepUuid"];
|
|
@@ -426185,11 +426398,11 @@ async function* boundedWireLines(wirePath, size) {
|
|
|
426185
426398
|
}
|
|
426186
426399
|
}
|
|
426187
426400
|
function searchableText(record) {
|
|
426188
|
-
if (!isRecord$
|
|
426189
|
-
if (record["type"] === "context.append_message" && isRecord$
|
|
426401
|
+
if (!isRecord$14(record)) return void 0;
|
|
426402
|
+
if (record["type"] === "context.append_message" && isRecord$14(record["message"])) {
|
|
426190
426403
|
const message = record["message"];
|
|
426191
426404
|
const origin = message["origin"];
|
|
426192
|
-
if (message["role"] !== "user" && message["role"] !== "assistant" || message["role"] === "assistant" && origin !== void 0 || message["role"] === "user" && origin !== void 0 && (!isRecord$
|
|
426405
|
+
if (message["role"] !== "user" && message["role"] !== "assistant" || message["role"] === "assistant" && origin !== void 0 || message["role"] === "user" && origin !== void 0 && (!isRecord$14(origin) || origin["kind"] !== "user")) return;
|
|
426193
426406
|
const content = message["content"];
|
|
426194
426407
|
if (!Array.isArray(content)) return void 0;
|
|
426195
426408
|
const text = content.filter(isTextPart).map((part) => part.text).join(" ");
|
|
@@ -426211,12 +426424,12 @@ function snippet(text, firstTerm) {
|
|
|
426211
426424
|
return `${start > 0 ? "..." : ""}${flattened.slice(start, end)}${end < flattened.length ? "..." : ""}`;
|
|
426212
426425
|
}
|
|
426213
426426
|
function isTextPart(value) {
|
|
426214
|
-
return isRecord$
|
|
426427
|
+
return isRecord$14(value) && value["type"] === "text" && typeof value["text"] === "string";
|
|
426215
426428
|
}
|
|
426216
|
-
function isRecord$
|
|
426429
|
+
function isRecord$14(value) {
|
|
426217
426430
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
426218
426431
|
}
|
|
426219
|
-
function isInside(parent, child) {
|
|
426432
|
+
function isInside$1(parent, child) {
|
|
426220
426433
|
const relative = path.relative(parent, child);
|
|
426221
426434
|
return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
426222
426435
|
}
|
|
@@ -426309,7 +426522,7 @@ async function searchLocalToolEvents(homeDir, sessions, query, limit = 8) {
|
|
|
426309
426522
|
};
|
|
426310
426523
|
}
|
|
426311
426524
|
function parseSavedEvent(value, sessionId) {
|
|
426312
|
-
if (!isRecord$
|
|
426525
|
+
if (!isRecord$13(value) || value["version"] !== 1 || value["sessionId"] !== sessionId || typeof value["agentId"] !== "string" || !TOOL_NAME.test(value["agentId"]) || typeof value["tool"] !== "string" || !TOOL_NAME.test(value["tool"]) || typeof value["at"] !== "number" || !Number.isSafeInteger(value["at"]) || value["at"] < 0 || value["status"] !== "ok" && value["status"] !== "error" && value["status"] !== "synthetic") return;
|
|
426313
426526
|
const filePath = value["filePath"];
|
|
426314
426527
|
if (filePath !== void 0 && (typeof filePath !== "string" || filePath.length > 1024 || /[\u0000-\u001F\u007F]/u.test(filePath))) return void 0;
|
|
426315
426528
|
return {
|
|
@@ -426341,7 +426554,7 @@ function localToolEventRecordingEnabled(homeDir) {
|
|
|
426341
426554
|
}
|
|
426342
426555
|
if (!info.isFile() || info.isSymbolicLink() || info.size > 1024) return false;
|
|
426343
426556
|
const parsed = JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
426344
|
-
return isRecord$
|
|
426557
|
+
return isRecord$13(parsed) && parsed["version"] === 1 && parsed["enabled"] === true;
|
|
426345
426558
|
} catch {
|
|
426346
426559
|
return false;
|
|
426347
426560
|
}
|
|
@@ -426452,7 +426665,7 @@ function createLocalToolEventRecorder(homeDir, sessionId, enabled = localToolEve
|
|
|
426452
426665
|
};
|
|
426453
426666
|
}
|
|
426454
426667
|
function filePathFor(tool, args) {
|
|
426455
|
-
if (!FILE_TOOLS.has(tool) || !isRecord$
|
|
426668
|
+
if (!FILE_TOOLS.has(tool) || !isRecord$13(args)) return {};
|
|
426456
426669
|
const value = args["path"];
|
|
426457
426670
|
if (typeof value !== "string" || value.length === 0 || value.length > 1024 || /[\u0000-\u001F\u007F]/u.test(value)) return {};
|
|
426458
426671
|
return { filePath: value };
|
|
@@ -426495,11 +426708,11 @@ async function assertPlainDirectory(directory) {
|
|
|
426495
426708
|
function samePath(a, b) {
|
|
426496
426709
|
return process.platform === "win32" ? path.resolve(a).toLocaleLowerCase() === path.resolve(b).toLocaleLowerCase() : path.resolve(a) === path.resolve(b);
|
|
426497
426710
|
}
|
|
426498
|
-
function isRecord$
|
|
426711
|
+
function isRecord$13(value) {
|
|
426499
426712
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
426500
426713
|
}
|
|
426501
426714
|
function isErrno$1(error, code) {
|
|
426502
|
-
return isRecord$
|
|
426715
|
+
return isRecord$13(error) && error["code"] === code;
|
|
426503
426716
|
}
|
|
426504
426717
|
//#endregion
|
|
426505
426718
|
//#region src/personal-memory/session-mcp.ts
|
|
@@ -426681,12 +426894,12 @@ function isPersonalMemoryToolName(name) {
|
|
|
426681
426894
|
return PERSONAL_MEMORY_TOOL_NAMES.includes(name);
|
|
426682
426895
|
}
|
|
426683
426896
|
function normalizePhaseOneRecall(payload, limit) {
|
|
426684
|
-
if (!isRecord$
|
|
426897
|
+
if (!isRecord$12(payload) || !Array.isArray(payload["ergebnis"])) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
426685
426898
|
const results = payload["ergebnis"];
|
|
426686
426899
|
if (results.length > 100) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
426687
426900
|
return { personal_memory: {
|
|
426688
426901
|
saved: results.map((entry) => {
|
|
426689
|
-
if (!isRecord$
|
|
426902
|
+
if (!isRecord$12(entry)) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
426690
426903
|
const text = entry["inhalt"];
|
|
426691
426904
|
if (typeof text !== "string" || text.trim().length === 0 || text.length > 4e3) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
426692
426905
|
return {
|
|
@@ -426698,7 +426911,46 @@ function normalizePhaseOneRecall(payload, limit) {
|
|
|
426698
426911
|
chat_history_context: []
|
|
426699
426912
|
} };
|
|
426700
426913
|
}
|
|
426701
|
-
function isRecord$
|
|
426914
|
+
function isRecord$12(value) {
|
|
426915
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
426916
|
+
}
|
|
426917
|
+
//#endregion
|
|
426918
|
+
//#region src/personal-memory/account-memory-recall.ts
|
|
426919
|
+
function mergeAccountMemoryRecall(phaseOne, account) {
|
|
426920
|
+
const existing = parsePhaseOne(phaseOne);
|
|
426921
|
+
if (existing === void 0 && account === void 0) throw new PersonalMemoryBrokerError("UNAVAILABLE");
|
|
426922
|
+
const saved = [...(existing?.personal_memory.saved ?? []).slice(0, 4), ...(account?.profile.card ?? []).slice(0, 4).map((text) => ({
|
|
426923
|
+
text: text.slice(0, 1e3),
|
|
426924
|
+
confidence: "medium"
|
|
426925
|
+
}))];
|
|
426926
|
+
const threads = (existing?.personal_memory.threads ?? []).slice(0, 4);
|
|
426927
|
+
if (account?.profile.representation.trim()) threads.push({
|
|
426928
|
+
title: "Account memory profile",
|
|
426929
|
+
summary: account.profile.representation.slice(0, 1e3)
|
|
426930
|
+
});
|
|
426931
|
+
for (const item of account?.items ?? []) {
|
|
426932
|
+
if (threads.length >= 8) break;
|
|
426933
|
+
threads.push({
|
|
426934
|
+
title: `${item.source} / ${item.sessionId}`.slice(0, 200),
|
|
426935
|
+
summary: item.text.slice(0, 1e3)
|
|
426936
|
+
});
|
|
426937
|
+
}
|
|
426938
|
+
return { personal_memory: {
|
|
426939
|
+
saved,
|
|
426940
|
+
threads,
|
|
426941
|
+
chat_history_context: []
|
|
426942
|
+
} };
|
|
426943
|
+
}
|
|
426944
|
+
function parsePhaseOne(value) {
|
|
426945
|
+
if (!isRecord$11(value) || !isRecord$11(value["personal_memory"])) return void 0;
|
|
426946
|
+
const memory = value["personal_memory"];
|
|
426947
|
+
if (!Array.isArray(memory["saved"]) || !Array.isArray(memory["threads"]) || !Array.isArray(memory["chat_history_context"]) || memory["chat_history_context"].length > 0) return void 0;
|
|
426948
|
+
const saved = memory["saved"];
|
|
426949
|
+
const threads = memory["threads"];
|
|
426950
|
+
if (saved.length > 8 || threads.length > 8 || !saved.every((item) => isRecord$11(item) && typeof item["text"] === "string" && item["text"].length <= 1e3 && item["confidence"] === "medium") || !threads.every((item) => isRecord$11(item) && typeof item["title"] === "string" && item["title"].length <= 200 && typeof item["summary"] === "string" && item["summary"].length <= 1e3)) return void 0;
|
|
426951
|
+
return value;
|
|
426952
|
+
}
|
|
426953
|
+
function isRecord$11(value) {
|
|
426702
426954
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
426703
426955
|
}
|
|
426704
426956
|
//#endregion
|
|
@@ -426817,7 +427069,7 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
|
|
|
426817
427069
|
if (localHistory === void 0 || !savedSearchEnabled && !localOnlyEnabled) return;
|
|
426818
427070
|
const searchClient = savedSearchEnabled ? options.client ?? createPersonalMemoryBrokerClient(harness) : void 0;
|
|
426819
427071
|
try {
|
|
426820
|
-
await registerPersonalMemorySearchTool(session, localHistory, searchClient, binding, savedSearchEnabled, localOnlyEnabled);
|
|
427072
|
+
await registerPersonalMemorySearchTool(session, localHistory, searchClient, binding, savedSearchEnabled, localOnlyEnabled, savedSearchEnabled ? options.accountMemory : void 0);
|
|
426821
427073
|
} catch (error) {
|
|
426822
427074
|
await session.unregisterToolAndWait(PERSONAL_MEMORY_SEARCH_TOOL).catch(() => {});
|
|
426823
427075
|
throw error;
|
|
@@ -426835,10 +427087,10 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
|
|
|
426835
427087
|
for (const name of binding === void 0 ? [] : personalMemoryToolNames(binding.mode, binding.capabilities)) {
|
|
426836
427088
|
if (name === "memory_recall") continue;
|
|
426837
427089
|
const definition = personalMemoryToolDefinition(name);
|
|
426838
|
-
await session.registerToolAndWait(qualifiedPersonalMemoryToolName(name), definition.description, definition.parameters, createHostHandler(client, name, context, name === "memory_settings_update" ? () => refreshPersonalMemoryBinding(session, harness, client, localHistory) : void 0));
|
|
427090
|
+
await session.registerToolAndWait(qualifiedPersonalMemoryToolName(name), definition.description, definition.parameters, createHostHandler(client, name, context, name === "memory_settings_update" ? () => refreshPersonalMemoryBinding(session, harness, client, localHistory, options.accountMemory) : void 0));
|
|
426839
427091
|
}
|
|
426840
|
-
if (savedSearchEnabled) session.setHostToolCallHandler(PERSONAL_MEMORY_HOST_RECALL_HANDLER, createHostHandler(client, "memory_recall", context));
|
|
426841
|
-
if (localHistory !== void 0 && (savedSearchEnabled || localOnlyEnabled)) await registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled);
|
|
427092
|
+
if (savedSearchEnabled) session.setHostToolCallHandler(PERSONAL_MEMORY_HOST_RECALL_HANDLER, createHostHandler(client, "memory_recall", context, void 0, options.accountMemory));
|
|
427093
|
+
if (localHistory !== void 0 && (savedSearchEnabled || localOnlyEnabled)) await registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled, savedSearchEnabled ? options.accountMemory : void 0);
|
|
426842
427094
|
if (binding !== void 0) await session.setPersonalMemoryHostCapability(true);
|
|
426843
427095
|
} catch (error) {
|
|
426844
427096
|
resetPersonalMemorySession();
|
|
@@ -426846,7 +427098,7 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
|
|
|
426846
427098
|
throw error;
|
|
426847
427099
|
}
|
|
426848
427100
|
}
|
|
426849
|
-
async function registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled) {
|
|
427101
|
+
async function registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled, accountMemory) {
|
|
426850
427102
|
const context = binding === void 0 ? void 0 : {
|
|
426851
427103
|
mode: binding.mode,
|
|
426852
427104
|
capabilities: binding.capabilities
|
|
@@ -426859,14 +427111,15 @@ async function registerPersonalMemorySearchTool(session, localHistory, client, b
|
|
|
426859
427111
|
};
|
|
426860
427112
|
try {
|
|
426861
427113
|
const sessions = localHistory.listSessions({ includeArchive: true });
|
|
426862
|
-
const [savedResult, workHistoryResult, toolEventsResult] = await Promise.allSettled([
|
|
427114
|
+
const [savedResult, workHistoryResult, toolEventsResult, accountResult] = await Promise.allSettled([
|
|
426863
427115
|
savedSearchEnabled ? invokePersonalMemoryTool(client, "memory_recall", parsed.data, context) : Promise.resolve(void 0),
|
|
426864
427116
|
sessions.then((list) => searchLocalWorkHistory(localHistory.homeDir, list, parsed.data.query, parsed.data.limit)),
|
|
426865
|
-
sessions.then((list) => searchLocalToolEvents(localHistory.homeDir, list, parsed.data.query, parsed.data.limit))
|
|
427117
|
+
sessions.then((list) => searchLocalToolEvents(localHistory.homeDir, list, parsed.data.query, parsed.data.limit)),
|
|
427118
|
+
accountMemory?.search(parsed.data.query, Math.min(20, parsed.data.limit)) ?? Promise.resolve(void 0)
|
|
426866
427119
|
]);
|
|
426867
427120
|
const saved = savedSearchEnabled && savedResult.status === "fulfilled" ? savedSearchResultSchema.safeParse(savedResult.value) : void 0;
|
|
426868
427121
|
const savedAvailable = saved?.success === true;
|
|
426869
|
-
if (!savedAvailable && workHistoryResult.status === "rejected" && toolEventsResult.status === "rejected") return {
|
|
427122
|
+
if (!savedAvailable && workHistoryResult.status === "rejected" && toolEventsResult.status === "rejected" && (accountResult.status === "rejected" || accountResult.value === void 0)) return {
|
|
426870
427123
|
output: "MEMORY_SEARCH_UNAVAILABLE",
|
|
426871
427124
|
isError: true
|
|
426872
427125
|
};
|
|
@@ -426877,6 +427130,13 @@ async function registerPersonalMemorySearchTool(session, localHistory, client, b
|
|
|
426877
427130
|
workHistoryAvailable: workHistoryResult.status === "fulfilled",
|
|
426878
427131
|
toolEvents: toolEventsResult.status === "fulfilled" ? toolEventsResult.value : null,
|
|
426879
427132
|
toolEventsAvailable: toolEventsResult.status === "fulfilled",
|
|
427133
|
+
accountHistory: accountResult.status === "fulfilled" ? accountResult.value?.items.slice(0, 8).map((item) => ({
|
|
427134
|
+
source: item.source,
|
|
427135
|
+
sessionId: item.sessionId,
|
|
427136
|
+
at: item.at,
|
|
427137
|
+
text: item.text.slice(0, 600)
|
|
427138
|
+
})) ?? null : null,
|
|
427139
|
+
accountHistoryAvailable: accountResult.status === "fulfilled" && accountResult.value !== void 0,
|
|
426880
427140
|
toolEventRecordingEnabled: localOnlyEnabled
|
|
426881
427141
|
}) };
|
|
426882
427142
|
} catch {
|
|
@@ -426946,13 +427206,20 @@ function supportsPersonalMemoryHostTools(session) {
|
|
|
426946
427206
|
function qualifiedPersonalMemoryToolName(name) {
|
|
426947
427207
|
return `${PERSONAL_MEMORY_QUALIFIED_PREFIX}${name}`;
|
|
426948
427208
|
}
|
|
426949
|
-
function createHostHandler(client, name, context, afterSettingsUpdate) {
|
|
427209
|
+
function createHostHandler(client, name, context, afterSettingsUpdate, accountMemory) {
|
|
426950
427210
|
return async (request) => {
|
|
426951
427211
|
try {
|
|
426952
|
-
const
|
|
427212
|
+
const original = () => invokePersonalMemoryTool(client, name, request.args, {
|
|
426953
427213
|
...context,
|
|
426954
427214
|
explicitRememberAttested: name === "memory_remember" ? consumePersonalMemoryRememberIntent(request) : void 0
|
|
426955
427215
|
});
|
|
427216
|
+
let result;
|
|
427217
|
+
if (name === "memory_recall" && accountMemory !== void 0) {
|
|
427218
|
+
const parsed = searchInputSchema.safeParse(request.args);
|
|
427219
|
+
if (!parsed.success) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
427220
|
+
const [phaseOne, account] = await Promise.all([original().catch(() => void 0), accountMemory.recall(parsed.data.query)]);
|
|
427221
|
+
result = mergeAccountMemoryRecall(phaseOne, account);
|
|
427222
|
+
} else result = await original();
|
|
426956
427223
|
if (name === "memory_settings_update") await afterSettingsUpdate?.();
|
|
426957
427224
|
return { output: JSON.stringify(result ?? null) };
|
|
426958
427225
|
} catch (error) {
|
|
@@ -426963,7 +427230,7 @@ function createHostHandler(client, name, context, afterSettingsUpdate) {
|
|
|
426963
427230
|
}
|
|
426964
427231
|
};
|
|
426965
427232
|
}
|
|
426966
|
-
async function refreshPersonalMemoryBinding(session, harness, client, localHistory) {
|
|
427233
|
+
async function refreshPersonalMemoryBinding(session, harness, client, localHistory, accountMemory) {
|
|
426967
427234
|
resetPersonalMemorySession();
|
|
426968
427235
|
await clearPersonalMemoryHostTools(session);
|
|
426969
427236
|
try {
|
|
@@ -426975,7 +427242,8 @@ async function refreshPersonalMemoryBinding(session, harness, client, localHisto
|
|
|
426975
427242
|
await bindPersonalMemoryHostTools(session, harness, {
|
|
426976
427243
|
binding,
|
|
426977
427244
|
client,
|
|
426978
|
-
localHistory
|
|
427245
|
+
localHistory,
|
|
427246
|
+
accountMemory
|
|
426979
427247
|
});
|
|
426980
427248
|
} catch (error) {
|
|
426981
427249
|
resetPersonalMemorySession();
|
|
@@ -438706,6 +438974,148 @@ function sanitizeTerminalText(value) {
|
|
|
438706
438974
|
return value.replaceAll(OSC_SEQUENCE$1, "").replaceAll(CSI_SEQUENCE$1, "").replaceAll(ESC_SEQUENCE$1, "").replaceAll(CONTROL_CHARACTERS$1, " ");
|
|
438707
438975
|
}
|
|
438708
438976
|
//#endregion
|
|
438977
|
+
//#region src/tui/utils/export-markdown.copy.ts
|
|
438978
|
+
registerUiCatalogFragment({
|
|
438979
|
+
en: {
|
|
438980
|
+
"export.thinking": "Thinking",
|
|
438981
|
+
"export.image": "image",
|
|
438982
|
+
"export.audio": "audio",
|
|
438983
|
+
"export.video": "video",
|
|
438984
|
+
"export.toolCall": "Tool Call: {name}",
|
|
438985
|
+
"export.toolResult": "Tool Result: {name}",
|
|
438986
|
+
"export.turn": "Turn {number}",
|
|
438987
|
+
"export.user": "User",
|
|
438988
|
+
"export.assistant": "Assistant",
|
|
438989
|
+
"export.system": "System",
|
|
438990
|
+
"export.unknownTool": "unknown",
|
|
438991
|
+
"export.overview": "Overview",
|
|
438992
|
+
"export.topic": "Topic",
|
|
438993
|
+
"export.labelSeparator": ":",
|
|
438994
|
+
"export.empty": "empty",
|
|
438995
|
+
"export.conversation": "Conversation",
|
|
438996
|
+
"export.turnCount.one": "{count} turn",
|
|
438997
|
+
"export.turnCount.other": "{count} turns",
|
|
438998
|
+
"export.toolCallCount.one": "{count} tool call",
|
|
438999
|
+
"export.toolCallCount.other": "{count} tool calls",
|
|
439000
|
+
"export.title": "King Session Export"
|
|
439001
|
+
},
|
|
439002
|
+
de: {
|
|
439003
|
+
"export.thinking": "Denken",
|
|
439004
|
+
"export.image": "Bild",
|
|
439005
|
+
"export.audio": "Audio",
|
|
439006
|
+
"export.video": "Video",
|
|
439007
|
+
"export.toolCall": "Werkzeugaufruf: {name}",
|
|
439008
|
+
"export.toolResult": "Werkzeugergebnis: {name}",
|
|
439009
|
+
"export.turn": "Durchlauf {number}",
|
|
439010
|
+
"export.user": "Benutzer",
|
|
439011
|
+
"export.assistant": "Assistent",
|
|
439012
|
+
"export.system": "System",
|
|
439013
|
+
"export.unknownTool": "unbekannt",
|
|
439014
|
+
"export.overview": "Übersicht",
|
|
439015
|
+
"export.topic": "Thema",
|
|
439016
|
+
"export.labelSeparator": ":",
|
|
439017
|
+
"export.empty": "leer",
|
|
439018
|
+
"export.conversation": "Gespräch",
|
|
439019
|
+
"export.turnCount.one": "{count} Durchlauf",
|
|
439020
|
+
"export.turnCount.other": "{count} Durchläufe",
|
|
439021
|
+
"export.toolCallCount.one": "{count} Werkzeugaufruf",
|
|
439022
|
+
"export.toolCallCount.other": "{count} Werkzeugaufrufe",
|
|
439023
|
+
"export.title": "King-Sitzungsexport"
|
|
439024
|
+
},
|
|
439025
|
+
es: {
|
|
439026
|
+
"export.thinking": "Razonamiento",
|
|
439027
|
+
"export.image": "imagen",
|
|
439028
|
+
"export.audio": "audio",
|
|
439029
|
+
"export.video": "vídeo",
|
|
439030
|
+
"export.toolCall": "Llamada a herramienta: {name}",
|
|
439031
|
+
"export.toolResult": "Resultado de la herramienta: {name}",
|
|
439032
|
+
"export.turn": "Turno {number}",
|
|
439033
|
+
"export.user": "Usuario",
|
|
439034
|
+
"export.assistant": "Asistente",
|
|
439035
|
+
"export.system": "Sistema",
|
|
439036
|
+
"export.unknownTool": "desconocida",
|
|
439037
|
+
"export.overview": "Resumen",
|
|
439038
|
+
"export.topic": "Tema",
|
|
439039
|
+
"export.labelSeparator": ":",
|
|
439040
|
+
"export.empty": "vacío",
|
|
439041
|
+
"export.conversation": "Conversación",
|
|
439042
|
+
"export.turnCount.one": "{count} turno",
|
|
439043
|
+
"export.turnCount.other": "{count} turnos",
|
|
439044
|
+
"export.toolCallCount.one": "{count} llamada a herramienta",
|
|
439045
|
+
"export.toolCallCount.other": "{count} llamadas a herramientas",
|
|
439046
|
+
"export.title": "Exportación de la sesión de King"
|
|
439047
|
+
},
|
|
439048
|
+
fr: {
|
|
439049
|
+
"export.thinking": "Réflexion",
|
|
439050
|
+
"export.image": "image",
|
|
439051
|
+
"export.audio": "audio",
|
|
439052
|
+
"export.video": "vidéo",
|
|
439053
|
+
"export.toolCall": "Appel d’outil\xA0: {name}",
|
|
439054
|
+
"export.toolResult": "Résultat de l’outil\xA0: {name}",
|
|
439055
|
+
"export.turn": "Tour {number}",
|
|
439056
|
+
"export.user": "Utilisateur",
|
|
439057
|
+
"export.assistant": "Assistant",
|
|
439058
|
+
"export.system": "Système",
|
|
439059
|
+
"export.unknownTool": "inconnu",
|
|
439060
|
+
"export.overview": "Vue d’ensemble",
|
|
439061
|
+
"export.topic": "Sujet",
|
|
439062
|
+
"export.labelSeparator": "\xA0:",
|
|
439063
|
+
"export.empty": "vide",
|
|
439064
|
+
"export.conversation": "Conversation",
|
|
439065
|
+
"export.turnCount.one": "{count} tour",
|
|
439066
|
+
"export.turnCount.other": "{count} tours",
|
|
439067
|
+
"export.toolCallCount.one": "{count} appel d’outil",
|
|
439068
|
+
"export.toolCallCount.other": "{count} appels d’outil",
|
|
439069
|
+
"export.title": "Export de la session King"
|
|
439070
|
+
},
|
|
439071
|
+
sv: {
|
|
439072
|
+
"export.thinking": "Resonemang",
|
|
439073
|
+
"export.image": "bild",
|
|
439074
|
+
"export.audio": "ljud",
|
|
439075
|
+
"export.video": "video",
|
|
439076
|
+
"export.toolCall": "Verktygsanrop: {name}",
|
|
439077
|
+
"export.toolResult": "Verktygsresultat: {name}",
|
|
439078
|
+
"export.turn": "Omgång {number}",
|
|
439079
|
+
"export.user": "Användare",
|
|
439080
|
+
"export.assistant": "Assistent",
|
|
439081
|
+
"export.system": "System",
|
|
439082
|
+
"export.unknownTool": "okänt",
|
|
439083
|
+
"export.overview": "Översikt",
|
|
439084
|
+
"export.topic": "Ämne",
|
|
439085
|
+
"export.labelSeparator": ":",
|
|
439086
|
+
"export.empty": "tomt",
|
|
439087
|
+
"export.conversation": "Konversation",
|
|
439088
|
+
"export.turnCount.one": "{count} omgång",
|
|
439089
|
+
"export.turnCount.other": "{count} omgångar",
|
|
439090
|
+
"export.toolCallCount.one": "{count} verktygsanrop",
|
|
439091
|
+
"export.toolCallCount.other": "{count} verktygsanrop",
|
|
439092
|
+
"export.title": "Export av King-session"
|
|
439093
|
+
},
|
|
439094
|
+
cs: {
|
|
439095
|
+
"export.thinking": "Uvažování",
|
|
439096
|
+
"export.image": "obrázek",
|
|
439097
|
+
"export.audio": "zvuk",
|
|
439098
|
+
"export.video": "video",
|
|
439099
|
+
"export.toolCall": "Volání nástroje: {name}",
|
|
439100
|
+
"export.toolResult": "Výsledek nástroje: {name}",
|
|
439101
|
+
"export.turn": "Kolo {number}",
|
|
439102
|
+
"export.user": "Uživatel",
|
|
439103
|
+
"export.assistant": "Asistent",
|
|
439104
|
+
"export.system": "Systém",
|
|
439105
|
+
"export.unknownTool": "neznámý",
|
|
439106
|
+
"export.overview": "Přehled",
|
|
439107
|
+
"export.topic": "Téma",
|
|
439108
|
+
"export.labelSeparator": ":",
|
|
439109
|
+
"export.empty": "prázdné",
|
|
439110
|
+
"export.conversation": "Konverzace",
|
|
439111
|
+
"export.turnCount.one": "Kola: {count}",
|
|
439112
|
+
"export.turnCount.other": "Kola: {count}",
|
|
439113
|
+
"export.toolCallCount.one": "{count} volání nástroje",
|
|
439114
|
+
"export.toolCallCount.other": "{count} volání nástrojů",
|
|
439115
|
+
"export.title": "Export relace King"
|
|
439116
|
+
}
|
|
439117
|
+
});
|
|
439118
|
+
//#endregion
|
|
438709
439119
|
//#region src/tui/components/messages/usage-panel.ts
|
|
438710
439120
|
registerUiCatalogFragment({
|
|
438711
439121
|
en: {
|
|
@@ -438874,6 +439284,11 @@ function usageNumber(value) {
|
|
|
438874
439284
|
function usageInputTotal$2(usage) {
|
|
438875
439285
|
return usageNumber(usage.inputOther) + usageNumber(usage.inputCacheRead) + usageNumber(usage.inputCacheCreation);
|
|
438876
439286
|
}
|
|
439287
|
+
function knownReasoningTokens(usage) {
|
|
439288
|
+
const value = usage.outputReasoning;
|
|
439289
|
+
const output = usageNumber(usage.output);
|
|
439290
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= output ? value : void 0;
|
|
439291
|
+
}
|
|
438877
439292
|
function managedUsageLabel(row) {
|
|
438878
439293
|
switch (row.id) {
|
|
438879
439294
|
case "five_hours": return uiText("usage.plan.window.fiveHours");
|
|
@@ -438922,14 +439337,23 @@ function buildSessionUsageSection(usage, error, value, muted, errorStyle) {
|
|
|
438922
439337
|
const locale = getCurrentUiLocale();
|
|
438923
439338
|
let totalInput = 0;
|
|
438924
439339
|
let totalOutput = 0;
|
|
439340
|
+
let totalReasoning = 0;
|
|
439341
|
+
let reasoningComplete = true;
|
|
438925
439342
|
for (const [model, row] of entries) {
|
|
438926
439343
|
const input = usageInputTotal$2(row);
|
|
438927
439344
|
const output = usageNumber(row.output);
|
|
439345
|
+
const reasoning = knownReasoningTokens(row);
|
|
438928
439346
|
totalInput += input;
|
|
438929
439347
|
totalOutput += output;
|
|
438930
|
-
|
|
439348
|
+
if (reasoning !== void 0) totalReasoning += reasoning;
|
|
439349
|
+
else if (output > 0) reasoningComplete = false;
|
|
439350
|
+
const reasoningPart = reasoning === void 0 ? "" : ` ${uiText("export.thinking")} ${value(formatExactTokenCount(reasoning, locale))}`;
|
|
439351
|
+
lines.push(` ${muted(sanitizeTerminalText(model))} ${uiText("usage.input")} ${value(formatExactTokenCount(input, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(output, locale))}${reasoningPart} ${uiText("usage.total")} ${value(formatExactTokenCount(input + output, locale))}`);
|
|
439352
|
+
}
|
|
439353
|
+
if (entries.length > 1) {
|
|
439354
|
+
const reasoningPart = reasoningComplete && totalOutput > 0 ? ` ${uiText("export.thinking")} ${value(formatExactTokenCount(totalReasoning, locale))}` : "";
|
|
439355
|
+
lines.push(` ${muted(uiText("usage.total"))} ${uiText("usage.input")} ${value(formatExactTokenCount(totalInput, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(totalOutput, locale))}${reasoningPart} ${uiText("usage.total")} ${value(formatExactTokenCount(totalInput + totalOutput, locale))}`);
|
|
438931
439356
|
}
|
|
438932
|
-
if (entries.length > 1) lines.push(` ${muted(uiText("usage.total"))} ${uiText("usage.input")} ${value(formatExactTokenCount(totalInput, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(totalOutput, locale))} ${uiText("usage.total")} ${value(formatExactTokenCount(totalInput + totalOutput, locale))}`);
|
|
438933
439357
|
return lines;
|
|
438934
439358
|
}
|
|
438935
439359
|
function buildManagedUsageSection(usage, error, accent, value, muted, errorStyle) {
|
|
@@ -502978,7 +503402,7 @@ function parsePluginMarketplace(raw, location) {
|
|
|
502978
503402
|
} catch (error) {
|
|
502979
503403
|
throw new Error(`Plugin marketplace is not valid JSON: ${formatParseError(error)}`, { cause: error });
|
|
502980
503404
|
}
|
|
502981
|
-
if (!isRecord$
|
|
503405
|
+
if (!isRecord$10(parsed)) throw new TypeError("Plugin marketplace must be an object.");
|
|
502982
503406
|
const rawPlugins = parsed["plugins"];
|
|
502983
503407
|
if (!Array.isArray(rawPlugins)) throw new TypeError("Plugin marketplace must contain a \"plugins\" array.");
|
|
502984
503408
|
return {
|
|
@@ -503022,7 +503446,7 @@ async function readMarketplaceText(location, fetchImpl) {
|
|
|
503022
503446
|
return response.text();
|
|
503023
503447
|
}
|
|
503024
503448
|
function parseMarketplaceEntry(value, index, location) {
|
|
503025
|
-
if (!isRecord$
|
|
503449
|
+
if (!isRecord$10(value)) throw new TypeError(`Plugin marketplace entry ${index + 1} must be an object.`);
|
|
503026
503450
|
const id = requiredString(value, "id", index);
|
|
503027
503451
|
validateMarketplaceEntryType(value, id);
|
|
503028
503452
|
const source = stringField$2(value, "source") ?? stringField$2(value, "url") ?? stringField$2(value, "downloadUrl");
|
|
@@ -503158,7 +503582,7 @@ function stringArrayField(value, field) {
|
|
|
503158
503582
|
const out = raw.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
503159
503583
|
return out.length > 0 ? out : void 0;
|
|
503160
503584
|
}
|
|
503161
|
-
function isRecord$
|
|
503585
|
+
function isRecord$10(value) {
|
|
503162
503586
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
503163
503587
|
}
|
|
503164
503588
|
function formatParseError(error) {
|
|
@@ -505260,6 +505684,7 @@ async function handleBlunApiKeyLogin(host, options, promptOptions) {
|
|
|
505260
505684
|
provider: DEFAULT_OAUTH_PROVIDER_NAME,
|
|
505261
505685
|
method: "api_key"
|
|
505262
505686
|
});
|
|
505687
|
+
host.accountMemoryRuntime?.retryPending().catch(() => {});
|
|
505263
505688
|
host.showStatus(uiText("auth.login.success"));
|
|
505264
505689
|
return "authenticated";
|
|
505265
505690
|
}
|
|
@@ -505302,6 +505727,7 @@ async function handleBlunCodeOAuthLogin(host, options = {}) {
|
|
|
505302
505727
|
method: "oauth",
|
|
505303
505728
|
already_logged_in: alreadyLoggedIn
|
|
505304
505729
|
});
|
|
505730
|
+
host.accountMemoryRuntime?.retryPending().catch(() => {});
|
|
505305
505731
|
if (alreadyLoggedIn) host.showStatus(uiText("auth.login.already"));
|
|
505306
505732
|
return "authenticated";
|
|
505307
505733
|
} catch (error) {
|
|
@@ -505346,11 +505772,16 @@ async function handleLogoutCommand(host) {
|
|
|
505346
505772
|
const currentProvider = host.state.appState.availableModels[currentModel]?.provider;
|
|
505347
505773
|
const target = await promptLogoutProviderSelection(host, options, currentProvider);
|
|
505348
505774
|
if (target === void 0) return;
|
|
505775
|
+
const memoryRetractionPending = await host.accountMemoryRuntime?.flushRetractionsBeforeLogout() ?? false;
|
|
505349
505776
|
showAuthWarnings(host, (await host.harness.auth.logout(DEFAULT_OAUTH_PROVIDER_NAME)).warnings);
|
|
505350
505777
|
await host.authFlow.refreshConfigAfterLogout({ clearCustomerAccount: true });
|
|
505351
505778
|
await host.authFlow.clearActiveSessionAfterLogout({ clearCustomerAccount: true });
|
|
505352
505779
|
host.track("logout", { provider: target });
|
|
505353
505780
|
host.showStatus(uiText("auth.logout.complete", { provider: PRODUCT_NAME }));
|
|
505781
|
+
if (memoryRetractionPending) {
|
|
505782
|
+
const key = hasManagedApiKey ? "auth.warning.memoryRetractionApiKeyPending" : "auth.warning.memoryRetractionOAuthPending";
|
|
505783
|
+
host.showStatus(uiText(key), "warning");
|
|
505784
|
+
}
|
|
505354
505785
|
}
|
|
505355
505786
|
function showAuthWarnings(host, warnings) {
|
|
505356
505787
|
if (warnings?.some((warning) => warning.code === "remote_revoke_failed") === true) host.showStatus(uiText("auth.warning.remoteRevokeFailed"), "warning");
|
|
@@ -505782,6 +506213,11 @@ async function showContextReport(host, detailed) {
|
|
|
505782
506213
|
name: tool.name === void 0 ? void 0 : diagnosticLabel(tool.name),
|
|
505783
506214
|
bytes: validTextSize(tool.bytes)
|
|
505784
506215
|
})) : void 0,
|
|
506216
|
+
toolResults: detailed === true ? breakdown?.toolResultByTool?.map((tool) => ({
|
|
506217
|
+
name: tool.name === void 0 ? void 0 : diagnosticLabel(tool.name),
|
|
506218
|
+
count: validTextSize(tool.count),
|
|
506219
|
+
bytes: validTextSize(tool.bytes)
|
|
506220
|
+
})) : void 0,
|
|
505785
506221
|
toolArrayOverheadBytes: validTextSize(breakdown?.toolArrayOverheadBytes),
|
|
505786
506222
|
historyOrigins: origins === void 0 ? void 0 : {
|
|
505787
506223
|
totalBytes: validTextSize(origins.totalBytes),
|
|
@@ -505849,6 +506285,15 @@ async function showContextReport(host, detailed) {
|
|
|
505849
506285
|
if (lastRequest.tools.length > 20) lines.push(`... (+${String(lastRequest.tools.length - 20)})`);
|
|
505850
506286
|
lines.push(row("context.otherPart", lastRequest.toolArrayOverheadBytes));
|
|
505851
506287
|
}
|
|
506288
|
+
if (lastRequest.toolResults !== void 0) {
|
|
506289
|
+
lines.push("", currentTheme.boldFg("primary", uiText("context.toolResultsPart")));
|
|
506290
|
+
for (const tool of lastRequest.toolResults.toSorted((a, b) => (b.bytes ?? -1) - (a.bytes ?? -1)).slice(0, 20)) {
|
|
506291
|
+
const count = tool.count === void 0 ? "?" : formatExactTokenCount(tool.count, getCurrentUiLocale());
|
|
506292
|
+
const size = tool.bytes === void 0 ? uiText("context.unavailable") : formatExactTokenCount(tool.bytes, getCurrentUiLocale());
|
|
506293
|
+
lines.push(`${tool.name ?? "?"} (${count}): ${size}`);
|
|
506294
|
+
}
|
|
506295
|
+
if (lastRequest.toolResults.length > 20) lines.push(`... (+${String(lastRequest.toolResults.length - 20)})`);
|
|
506296
|
+
}
|
|
505852
506297
|
lines.push("", currentTheme.boldFg("primary", uiText("context.promptTextBytes")), currentTheme.fg("textDim", uiText("context.sourceNote")), row("context.instructionPart", lastRequest.sources[0]), row("context.skillListingPart", lastRequest.sources[1]), row("context.runtimeMemoryPart", lastRequest.sources[2]), row("context.templatePart", lastRequest.sources[3]), row("context.totalPart", lastRequest.sources[4]), "", currentTheme.boldFg("primary", uiText("context.sourceFilesPart")), row("context.generatedPart", lastRequest.sources[5]));
|
|
505853
506298
|
if (lastRequest.files === void 0) lines.push(uiText("context.unavailable"));
|
|
505854
506299
|
else {
|
|
@@ -506235,7 +506680,7 @@ var ChannelCommandController = class {
|
|
|
506235
506680
|
function requireValid(condition) {
|
|
506236
506681
|
if (!condition) throw new Error("Invalid Telegram session queue state or transition");
|
|
506237
506682
|
}
|
|
506238
|
-
function isRecord$
|
|
506683
|
+
function isRecord$9(value) {
|
|
506239
506684
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
506240
506685
|
}
|
|
506241
506686
|
function isId(value) {
|
|
@@ -506245,7 +506690,7 @@ function isOffset(value) {
|
|
|
506245
506690
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
506246
506691
|
}
|
|
506247
506692
|
function readSpan(value) {
|
|
506248
|
-
requireValid(isRecord$
|
|
506693
|
+
requireValid(isRecord$9(value));
|
|
506249
506694
|
const { start, end } = value;
|
|
506250
506695
|
requireValid(isOffset(start) && isOffset(end) && start < end);
|
|
506251
506696
|
return {
|
|
@@ -506258,7 +506703,7 @@ function ownsRange(state, sessionId, span) {
|
|
|
506258
506703
|
}
|
|
506259
506704
|
/** Reject incompatible or corrupt state; never silently fall back to the profile cursor. */
|
|
506260
506705
|
function parseSessionQueue(value) {
|
|
506261
|
-
requireValid(isRecord$
|
|
506706
|
+
requireValid(isRecord$9(value));
|
|
506262
506707
|
const { version, fileId, frontier, activeSessionId, sessions, spans, acknowledged } = value;
|
|
506263
506708
|
requireValid(version === 1 && isId(fileId) && isOffset(frontier) && isId(activeSessionId));
|
|
506264
506709
|
requireValid(Array.isArray(sessions) && sessions.every(isId));
|
|
@@ -506267,7 +506712,7 @@ function parseSessionQueue(value) {
|
|
|
506267
506712
|
requireValid(Array.isArray(spans) && Array.isArray(acknowledged));
|
|
506268
506713
|
const owned = spans.map((raw) => {
|
|
506269
506714
|
const span = readSpan(raw);
|
|
506270
|
-
requireValid(isRecord$
|
|
506715
|
+
requireValid(isRecord$9(raw));
|
|
506271
506716
|
const sessionId = raw["sessionId"];
|
|
506272
506717
|
requireValid(sessionId === null || isId(sessionId) && known.has(sessionId));
|
|
506273
506718
|
return {
|
|
@@ -508758,14 +509203,14 @@ function findGoalIndex(file, goalId) {
|
|
|
508758
509203
|
return index;
|
|
508759
509204
|
}
|
|
508760
509205
|
function isGoalQueueFile(value) {
|
|
508761
|
-
if (!isRecord$
|
|
509206
|
+
if (!isRecord$8(value)) return false;
|
|
508762
509207
|
return value["version"] === GOAL_QUEUE_VERSION && Array.isArray(value["goals"]) && value["goals"].every(isUpcomingGoal);
|
|
508763
509208
|
}
|
|
508764
509209
|
function isUpcomingGoal(value) {
|
|
508765
|
-
if (!isRecord$
|
|
509210
|
+
if (!isRecord$8(value)) return false;
|
|
508766
509211
|
return isNonEmptyString(value["id"]) && isNonEmptyString(value["objective"]) && isNonEmptyString(value["createdAt"]) && isNonEmptyString(value["updatedAt"]);
|
|
508767
509212
|
}
|
|
508768
|
-
function isRecord$
|
|
509213
|
+
function isRecord$8(value) {
|
|
508769
509214
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
508770
509215
|
}
|
|
508771
509216
|
function isNonEmptyString(value) {
|
|
@@ -508778,7 +509223,7 @@ function timestampAfter(previous) {
|
|
|
508778
509223
|
return now.toISOString();
|
|
508779
509224
|
}
|
|
508780
509225
|
function isErrno(error, code) {
|
|
508781
|
-
return isRecord$
|
|
509226
|
+
return isRecord$8(error) && error["code"] === code;
|
|
508782
509227
|
}
|
|
508783
509228
|
function describeError(error) {
|
|
508784
509229
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -513549,148 +513994,6 @@ function isAbortError$1(error) {
|
|
|
513549
513994
|
return isAbortMessage(String(error));
|
|
513550
513995
|
}
|
|
513551
513996
|
//#endregion
|
|
513552
|
-
//#region src/tui/utils/export-markdown.copy.ts
|
|
513553
|
-
registerUiCatalogFragment({
|
|
513554
|
-
en: {
|
|
513555
|
-
"export.thinking": "Thinking",
|
|
513556
|
-
"export.image": "image",
|
|
513557
|
-
"export.audio": "audio",
|
|
513558
|
-
"export.video": "video",
|
|
513559
|
-
"export.toolCall": "Tool Call: {name}",
|
|
513560
|
-
"export.toolResult": "Tool Result: {name}",
|
|
513561
|
-
"export.turn": "Turn {number}",
|
|
513562
|
-
"export.user": "User",
|
|
513563
|
-
"export.assistant": "Assistant",
|
|
513564
|
-
"export.system": "System",
|
|
513565
|
-
"export.unknownTool": "unknown",
|
|
513566
|
-
"export.overview": "Overview",
|
|
513567
|
-
"export.topic": "Topic",
|
|
513568
|
-
"export.labelSeparator": ":",
|
|
513569
|
-
"export.empty": "empty",
|
|
513570
|
-
"export.conversation": "Conversation",
|
|
513571
|
-
"export.turnCount.one": "{count} turn",
|
|
513572
|
-
"export.turnCount.other": "{count} turns",
|
|
513573
|
-
"export.toolCallCount.one": "{count} tool call",
|
|
513574
|
-
"export.toolCallCount.other": "{count} tool calls",
|
|
513575
|
-
"export.title": "King Session Export"
|
|
513576
|
-
},
|
|
513577
|
-
de: {
|
|
513578
|
-
"export.thinking": "Denken",
|
|
513579
|
-
"export.image": "Bild",
|
|
513580
|
-
"export.audio": "Audio",
|
|
513581
|
-
"export.video": "Video",
|
|
513582
|
-
"export.toolCall": "Werkzeugaufruf: {name}",
|
|
513583
|
-
"export.toolResult": "Werkzeugergebnis: {name}",
|
|
513584
|
-
"export.turn": "Durchlauf {number}",
|
|
513585
|
-
"export.user": "Benutzer",
|
|
513586
|
-
"export.assistant": "Assistent",
|
|
513587
|
-
"export.system": "System",
|
|
513588
|
-
"export.unknownTool": "unbekannt",
|
|
513589
|
-
"export.overview": "Übersicht",
|
|
513590
|
-
"export.topic": "Thema",
|
|
513591
|
-
"export.labelSeparator": ":",
|
|
513592
|
-
"export.empty": "leer",
|
|
513593
|
-
"export.conversation": "Gespräch",
|
|
513594
|
-
"export.turnCount.one": "{count} Durchlauf",
|
|
513595
|
-
"export.turnCount.other": "{count} Durchläufe",
|
|
513596
|
-
"export.toolCallCount.one": "{count} Werkzeugaufruf",
|
|
513597
|
-
"export.toolCallCount.other": "{count} Werkzeugaufrufe",
|
|
513598
|
-
"export.title": "King-Sitzungsexport"
|
|
513599
|
-
},
|
|
513600
|
-
es: {
|
|
513601
|
-
"export.thinking": "Razonamiento",
|
|
513602
|
-
"export.image": "imagen",
|
|
513603
|
-
"export.audio": "audio",
|
|
513604
|
-
"export.video": "vídeo",
|
|
513605
|
-
"export.toolCall": "Llamada a herramienta: {name}",
|
|
513606
|
-
"export.toolResult": "Resultado de la herramienta: {name}",
|
|
513607
|
-
"export.turn": "Turno {number}",
|
|
513608
|
-
"export.user": "Usuario",
|
|
513609
|
-
"export.assistant": "Asistente",
|
|
513610
|
-
"export.system": "Sistema",
|
|
513611
|
-
"export.unknownTool": "desconocida",
|
|
513612
|
-
"export.overview": "Resumen",
|
|
513613
|
-
"export.topic": "Tema",
|
|
513614
|
-
"export.labelSeparator": ":",
|
|
513615
|
-
"export.empty": "vacío",
|
|
513616
|
-
"export.conversation": "Conversación",
|
|
513617
|
-
"export.turnCount.one": "{count} turno",
|
|
513618
|
-
"export.turnCount.other": "{count} turnos",
|
|
513619
|
-
"export.toolCallCount.one": "{count} llamada a herramienta",
|
|
513620
|
-
"export.toolCallCount.other": "{count} llamadas a herramientas",
|
|
513621
|
-
"export.title": "Exportación de la sesión de King"
|
|
513622
|
-
},
|
|
513623
|
-
fr: {
|
|
513624
|
-
"export.thinking": "Réflexion",
|
|
513625
|
-
"export.image": "image",
|
|
513626
|
-
"export.audio": "audio",
|
|
513627
|
-
"export.video": "vidéo",
|
|
513628
|
-
"export.toolCall": "Appel d’outil\xA0: {name}",
|
|
513629
|
-
"export.toolResult": "Résultat de l’outil\xA0: {name}",
|
|
513630
|
-
"export.turn": "Tour {number}",
|
|
513631
|
-
"export.user": "Utilisateur",
|
|
513632
|
-
"export.assistant": "Assistant",
|
|
513633
|
-
"export.system": "Système",
|
|
513634
|
-
"export.unknownTool": "inconnu",
|
|
513635
|
-
"export.overview": "Vue d’ensemble",
|
|
513636
|
-
"export.topic": "Sujet",
|
|
513637
|
-
"export.labelSeparator": "\xA0:",
|
|
513638
|
-
"export.empty": "vide",
|
|
513639
|
-
"export.conversation": "Conversation",
|
|
513640
|
-
"export.turnCount.one": "{count} tour",
|
|
513641
|
-
"export.turnCount.other": "{count} tours",
|
|
513642
|
-
"export.toolCallCount.one": "{count} appel d’outil",
|
|
513643
|
-
"export.toolCallCount.other": "{count} appels d’outil",
|
|
513644
|
-
"export.title": "Export de la session King"
|
|
513645
|
-
},
|
|
513646
|
-
sv: {
|
|
513647
|
-
"export.thinking": "Resonemang",
|
|
513648
|
-
"export.image": "bild",
|
|
513649
|
-
"export.audio": "ljud",
|
|
513650
|
-
"export.video": "video",
|
|
513651
|
-
"export.toolCall": "Verktygsanrop: {name}",
|
|
513652
|
-
"export.toolResult": "Verktygsresultat: {name}",
|
|
513653
|
-
"export.turn": "Omgång {number}",
|
|
513654
|
-
"export.user": "Användare",
|
|
513655
|
-
"export.assistant": "Assistent",
|
|
513656
|
-
"export.system": "System",
|
|
513657
|
-
"export.unknownTool": "okänt",
|
|
513658
|
-
"export.overview": "Översikt",
|
|
513659
|
-
"export.topic": "Ämne",
|
|
513660
|
-
"export.labelSeparator": ":",
|
|
513661
|
-
"export.empty": "tomt",
|
|
513662
|
-
"export.conversation": "Konversation",
|
|
513663
|
-
"export.turnCount.one": "{count} omgång",
|
|
513664
|
-
"export.turnCount.other": "{count} omgångar",
|
|
513665
|
-
"export.toolCallCount.one": "{count} verktygsanrop",
|
|
513666
|
-
"export.toolCallCount.other": "{count} verktygsanrop",
|
|
513667
|
-
"export.title": "Export av King-session"
|
|
513668
|
-
},
|
|
513669
|
-
cs: {
|
|
513670
|
-
"export.thinking": "Uvažování",
|
|
513671
|
-
"export.image": "obrázek",
|
|
513672
|
-
"export.audio": "zvuk",
|
|
513673
|
-
"export.video": "video",
|
|
513674
|
-
"export.toolCall": "Volání nástroje: {name}",
|
|
513675
|
-
"export.toolResult": "Výsledek nástroje: {name}",
|
|
513676
|
-
"export.turn": "Kolo {number}",
|
|
513677
|
-
"export.user": "Uživatel",
|
|
513678
|
-
"export.assistant": "Asistent",
|
|
513679
|
-
"export.system": "Systém",
|
|
513680
|
-
"export.unknownTool": "neznámý",
|
|
513681
|
-
"export.overview": "Přehled",
|
|
513682
|
-
"export.topic": "Téma",
|
|
513683
|
-
"export.labelSeparator": ":",
|
|
513684
|
-
"export.empty": "prázdné",
|
|
513685
|
-
"export.conversation": "Konverzace",
|
|
513686
|
-
"export.turnCount.one": "Kola: {count}",
|
|
513687
|
-
"export.turnCount.other": "Kola: {count}",
|
|
513688
|
-
"export.toolCallCount.one": "{count} volání nástroje",
|
|
513689
|
-
"export.toolCallCount.other": "{count} volání nástrojů",
|
|
513690
|
-
"export.title": "Export relace King"
|
|
513691
|
-
}
|
|
513692
|
-
});
|
|
513693
|
-
//#endregion
|
|
513694
513997
|
//#region src/tui/utils/export-markdown.ts
|
|
513695
513998
|
const HINT_KEYS = [
|
|
513696
513999
|
"path",
|
|
@@ -520695,10 +520998,10 @@ function parseGoalValue(output) {
|
|
|
520695
520998
|
} catch {
|
|
520696
520999
|
return;
|
|
520697
521000
|
}
|
|
520698
|
-
if (!isRecord$
|
|
521001
|
+
if (!isRecord$7(parsed) || !("goal" in parsed)) return void 0;
|
|
520699
521002
|
const goal = parsed["goal"];
|
|
520700
521003
|
if (goal === null) return null;
|
|
520701
|
-
if (!isRecord$
|
|
521004
|
+
if (!isRecord$7(goal)) return void 0;
|
|
520702
521005
|
return goal;
|
|
520703
521006
|
}
|
|
520704
521007
|
function formatGoalStats(goal) {
|
|
@@ -520720,7 +521023,7 @@ function stringArg(args, key) {
|
|
|
520720
521023
|
const value = args[key];
|
|
520721
521024
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
520722
521025
|
}
|
|
520723
|
-
function isRecord$
|
|
521026
|
+
function isRecord$7(value) {
|
|
520724
521027
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
520725
521028
|
}
|
|
520726
521029
|
function stringField$1(record, key) {
|
|
@@ -524772,10 +525075,10 @@ var CustomerMistakeBrokerError = class extends Error {
|
|
|
524772
525075
|
}
|
|
524773
525076
|
};
|
|
524774
525077
|
function parseMistakeConsent(payload) {
|
|
524775
|
-
if (!isRecord$
|
|
524776
|
-
const settings = (isRecord$
|
|
524777
|
-
const dataControls = isRecord$
|
|
524778
|
-
if (!isRecord$
|
|
525078
|
+
if (!isRecord$6(payload)) return void 0;
|
|
525079
|
+
const settings = (isRecord$6(payload["data"]) ? payload["data"] : payload)["settings"];
|
|
525080
|
+
const dataControls = isRecord$6(settings) ? settings["data_controls"] : void 0;
|
|
525081
|
+
if (!isRecord$6(dataControls)) return void 0;
|
|
524779
525082
|
const asked = dataControls["mistake_consent_asked"];
|
|
524780
525083
|
const allowed = dataControls["allow_mistake"];
|
|
524781
525084
|
if (typeof asked !== "boolean" || typeof allowed !== "boolean") return void 0;
|
|
@@ -524889,7 +525192,7 @@ function normalizeBaseUrl(value) {
|
|
|
524889
525192
|
if (url.protocol !== "https:" || url.username.length > 0 || url.password.length > 0 || url.search.length > 0 || url.hash.length > 0 || url.pathname !== "/" && url.pathname !== "") throw new CustomerMistakeBrokerError("INVALID_PAYLOAD");
|
|
524890
525193
|
return url.origin;
|
|
524891
525194
|
}
|
|
524892
|
-
function isRecord$
|
|
525195
|
+
function isRecord$6(value) {
|
|
524893
525196
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
524894
525197
|
}
|
|
524895
525198
|
//#endregion
|
|
@@ -524981,6 +525284,902 @@ var CustomerMistakeHostController = class {
|
|
|
524981
525284
|
}
|
|
524982
525285
|
};
|
|
524983
525286
|
//#endregion
|
|
525287
|
+
//#region src/personal-memory/account-memory-broker.ts
|
|
525288
|
+
const MAX_CAPTURE_BYTES = 1e6;
|
|
525289
|
+
const UUID_V4$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
525290
|
+
var AccountMemoryBroker = class {
|
|
525291
|
+
client;
|
|
525292
|
+
constructor(client) {
|
|
525293
|
+
this.client = client;
|
|
525294
|
+
}
|
|
525295
|
+
async workspace(sessionId) {
|
|
525296
|
+
if (sessionId !== void 0 && (!sessionId.trim() || sessionId.length > 200)) invalid();
|
|
525297
|
+
const path = sessionId === void 0 ? "/api/memory/workspace" : `/api/memory/workspace?source=tui&sessionId=${encodeURIComponent(sessionId)}`;
|
|
525298
|
+
const value = await this.client.request("GET", path);
|
|
525299
|
+
if (!isRecord$5(value) || typeof value["workspaceId"] !== "string" || !/^blun-[0-9a-f]{64}$/iu.test(value["workspaceId"]) || !generation(value["forgetGeneration"]) || sessionId !== void 0 && !generation(value["sessionEpoch"]) || value["forgetCutoff"] !== null && !isoTime$1(value["forgetCutoff"])) invalid();
|
|
525300
|
+
return {
|
|
525301
|
+
workspaceId: value["workspaceId"],
|
|
525302
|
+
forgetGeneration: value["forgetGeneration"],
|
|
525303
|
+
forgetCutoff: value["forgetCutoff"],
|
|
525304
|
+
sessionEpoch: sessionId === void 0 ? null : value["sessionEpoch"]
|
|
525305
|
+
};
|
|
525306
|
+
}
|
|
525307
|
+
async capture(input) {
|
|
525308
|
+
if (!UUID_V4$1.test(input.captureId) || !input.sessionId.trim() || !generation(input.forgetGeneration) || input.sessionEpoch !== null && !generation(input.sessionEpoch) || input.messages.length === 0 || input.messages.length > 200 || input.messages.some((message) => !messageId$1(message.id) || !["user", "assistant"].includes(message.role) || !message.content.trim() || !isoTime$1(message.at))) invalid();
|
|
525309
|
+
if (new Set(input.messages.map((message) => message.id)).size !== input.messages.length) invalid();
|
|
525310
|
+
const body = {
|
|
525311
|
+
captureId: input.captureId,
|
|
525312
|
+
source: "tui",
|
|
525313
|
+
sessionId: input.sessionId,
|
|
525314
|
+
forgetGeneration: input.forgetGeneration,
|
|
525315
|
+
sessionEpoch: input.sessionEpoch,
|
|
525316
|
+
messages: input.messages.map((message) => ({
|
|
525317
|
+
id: message.id,
|
|
525318
|
+
role: message.role,
|
|
525319
|
+
content: message.content,
|
|
525320
|
+
at: message.at
|
|
525321
|
+
}))
|
|
525322
|
+
};
|
|
525323
|
+
if (Buffer.byteLength(JSON.stringify(body), "utf8") > MAX_CAPTURE_BYTES) invalid();
|
|
525324
|
+
const value = await this.client.request("POST", "/api/memory/capture", body);
|
|
525325
|
+
if (isRecord$5(value) && value["accepted"] === 0 && value["reason"] === "memory_disabled") return {
|
|
525326
|
+
accepted: 0,
|
|
525327
|
+
reason: "memory_disabled"
|
|
525328
|
+
};
|
|
525329
|
+
if (isRecord$5(value) && value["accepted"] === 0 && value["reason"] === "session_retracted" && generation(value["skipped"]) && generation(value["sessionEpoch"])) return {
|
|
525330
|
+
accepted: 0,
|
|
525331
|
+
skipped: value["skipped"],
|
|
525332
|
+
reason: "session_retracted",
|
|
525333
|
+
sessionEpoch: value["sessionEpoch"]
|
|
525334
|
+
};
|
|
525335
|
+
if (!isRecord$5(value) || !generation(value["accepted"]) || !generation(value["skipped"]) || typeof value["duplicate"] !== "boolean" || !generation(value["forgetGeneration"]) || !generation(value["sessionEpoch"])) invalid();
|
|
525336
|
+
return {
|
|
525337
|
+
accepted: value["accepted"],
|
|
525338
|
+
skipped: value["skipped"],
|
|
525339
|
+
duplicate: value["duplicate"],
|
|
525340
|
+
forgetGeneration: value["forgetGeneration"],
|
|
525341
|
+
sessionEpoch: value["sessionEpoch"]
|
|
525342
|
+
};
|
|
525343
|
+
}
|
|
525344
|
+
async retract(input) {
|
|
525345
|
+
if (!UUID_V4$1.test(input.retractId) || !input.sessionId.trim() || input.sessionId.length > 200 || "wholeSession" in input && input.expectedEpoch !== null && !generation(input.expectedEpoch)) invalid();
|
|
525346
|
+
const body = "wholeSession" in input ? {
|
|
525347
|
+
retractId: input.retractId,
|
|
525348
|
+
source: "tui",
|
|
525349
|
+
sessionId: input.sessionId,
|
|
525350
|
+
wholeSession: true,
|
|
525351
|
+
expectedEpoch: input.expectedEpoch
|
|
525352
|
+
} : {
|
|
525353
|
+
retractId: input.retractId,
|
|
525354
|
+
source: "tui",
|
|
525355
|
+
sessionId: input.sessionId,
|
|
525356
|
+
messageIds: input.messageIds
|
|
525357
|
+
};
|
|
525358
|
+
if (!("wholeSession" in input) && (input.messageIds.length === 0 || input.messageIds.length > 200 || input.messageIds.some((id) => !messageId$1(id)) || new Set(input.messageIds).size !== input.messageIds.length)) invalid();
|
|
525359
|
+
const value = await this.client.request("POST", "/api/memory/retract", body);
|
|
525360
|
+
if ("wholeSession" in input && isRecord$5(value) && value["retracted"] === 0 && value["rederive"] === false && value["reason"] === "already_retracted" && generation(value["sessionEpoch"]) && input.expectedEpoch !== null && value["sessionEpoch"] >= input.expectedEpoch) return {
|
|
525361
|
+
retracted: 0,
|
|
525362
|
+
rederive: false,
|
|
525363
|
+
reason: "already_retracted",
|
|
525364
|
+
sessionEpoch: value["sessionEpoch"]
|
|
525365
|
+
};
|
|
525366
|
+
if (!isRecord$5(value) || !generation(value["retracted"]) || value["rederive"] !== "queued" || "wholeSession" in input && !generation(value["sessionEpoch"]) || value["sessionEpoch"] !== void 0 && !generation(value["sessionEpoch"])) invalid();
|
|
525367
|
+
return {
|
|
525368
|
+
retracted: value["retracted"],
|
|
525369
|
+
rederive: "queued",
|
|
525370
|
+
...value["sessionEpoch"] === void 0 ? {} : { sessionEpoch: value["sessionEpoch"] }
|
|
525371
|
+
};
|
|
525372
|
+
}
|
|
525373
|
+
async recall(query, limit = 8, sources) {
|
|
525374
|
+
const body = queryBody(query, limit, sources);
|
|
525375
|
+
const value = await this.client.request("POST", "/api/memory/recall", body);
|
|
525376
|
+
if (!isRecord$5(value) || !isRecord$5(value["profile"]) || !Array.isArray(value["items"]) || !generation(value["forgetGeneration"])) invalid();
|
|
525377
|
+
const profile = value["profile"];
|
|
525378
|
+
if (!Array.isArray(profile["card"]) || profile["card"].length > 20 || !profile["card"].every((item) => typeof item === "string" && item.length <= 1e3) || typeof profile["representation"] !== "string" || profile["representation"].length > 4e3) invalid();
|
|
525379
|
+
return {
|
|
525380
|
+
profile: {
|
|
525381
|
+
card: profile["card"],
|
|
525382
|
+
representation: profile["representation"]
|
|
525383
|
+
},
|
|
525384
|
+
items: parseItems(value["items"]),
|
|
525385
|
+
forgetGeneration: value["forgetGeneration"]
|
|
525386
|
+
};
|
|
525387
|
+
}
|
|
525388
|
+
async search(query, options = {}) {
|
|
525389
|
+
const body = queryBody(query, options.limit ?? 20, options.sources);
|
|
525390
|
+
if (options.after !== void 0 && !isoTime$1(options.after) || options.before !== void 0 && !isoTime$1(options.before)) invalid();
|
|
525391
|
+
const value = await this.client.request("POST", "/api/memory/search", {
|
|
525392
|
+
...body,
|
|
525393
|
+
...options.after === void 0 ? {} : { after: options.after },
|
|
525394
|
+
...options.before === void 0 ? {} : { before: options.before }
|
|
525395
|
+
});
|
|
525396
|
+
if (!isRecord$5(value) || !Array.isArray(value["items"]) || !generation(value["forgetGeneration"])) invalid();
|
|
525397
|
+
return {
|
|
525398
|
+
items: parseItems(value["items"]),
|
|
525399
|
+
forgetGeneration: value["forgetGeneration"]
|
|
525400
|
+
};
|
|
525401
|
+
}
|
|
525402
|
+
};
|
|
525403
|
+
function queryBody(query, limit, sources) {
|
|
525404
|
+
if (!query.trim() || query.length > 1e3 || !Number.isInteger(limit) || limit < 1 || limit > 20 || sources !== void 0 && (!Array.isArray(sources) || sources.some((source) => !/^(?:chat|tui|plugin:[a-z0-9_-]+)$/iu.test(source)))) invalid();
|
|
525405
|
+
return {
|
|
525406
|
+
query,
|
|
525407
|
+
limit,
|
|
525408
|
+
...sources === void 0 ? {} : { sources }
|
|
525409
|
+
};
|
|
525410
|
+
}
|
|
525411
|
+
function parseItems(value) {
|
|
525412
|
+
if (value.length > 20) invalid();
|
|
525413
|
+
return value.map((item) => {
|
|
525414
|
+
if (!isRecord$5(item) || typeof item["id"] !== "string" || item["id"].length > 200 || typeof item["text"] !== "string" || item["text"].length > 2e3 || typeof item["source"] !== "string" || !/^(?:chat|tui|plugin:[a-z0-9_-]+)$/iu.test(item["source"]) || typeof item["sessionId"] !== "string" || item["sessionId"].length > 200 || !isoTime$1(item["at"]) || typeof item["score"] !== "number" || !Number.isFinite(item["score"]) || item["role"] !== void 0 && item["role"] !== "user" && item["role"] !== "assistant") invalid();
|
|
525415
|
+
return item;
|
|
525416
|
+
});
|
|
525417
|
+
}
|
|
525418
|
+
function generation(value) {
|
|
525419
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
525420
|
+
}
|
|
525421
|
+
function messageId$1(value) {
|
|
525422
|
+
return typeof value === "string" && value.length > 0 && value.length <= 200 && /^[a-z0-9][a-z0-9._:-]*$/iu.test(value);
|
|
525423
|
+
}
|
|
525424
|
+
function isoTime$1(value) {
|
|
525425
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value)) && /(?:Z|[+-]\d\d:\d\d)$/u.test(value);
|
|
525426
|
+
}
|
|
525427
|
+
function isRecord$5(value) {
|
|
525428
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
525429
|
+
}
|
|
525430
|
+
function invalid() {
|
|
525431
|
+
throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
|
|
525432
|
+
}
|
|
525433
|
+
//#endregion
|
|
525434
|
+
//#region src/personal-memory/honcho-capture-source.ts
|
|
525435
|
+
const SECRET_PATTERN = /\b(?:password|passwort|api[-_ ]?key|secret|bearer|credential|cvv|cvc|iban)\b|sk-[a-z0-9_-]{20,}|ghp_[a-z0-9]{20,}|\b(?:\d[ -]?){13,19}\b/iu;
|
|
525436
|
+
const GROUP_MARKER = /^\[tg\s+(?:group|supergroup)\b/im;
|
|
525437
|
+
const MAX_WIRE_RECORD_CHARS = 4 * 1024 * 1024;
|
|
525438
|
+
async function readCompletedHonchoTurn(homeDir, session, turnId) {
|
|
525439
|
+
const sessionsRoot = await realpath(path.join(homeDir, "sessions"));
|
|
525440
|
+
const sessionDir = await realpath(session.sessionDir);
|
|
525441
|
+
if (path.basename(sessionDir) !== session.id || !isInside(sessionsRoot, sessionDir)) throw new Error("Honcho session path is outside this profile.");
|
|
525442
|
+
const canonicalWire = await realpath(path.join(sessionDir, "agents", "main", "wire.jsonl"));
|
|
525443
|
+
if (!isInside(sessionDir, canonicalWire)) throw new Error("Honcho Wire path escapes the session.");
|
|
525444
|
+
const wireStat = await stat(canonicalWire);
|
|
525445
|
+
if (!wireStat.isFile() || wireStat.size === 0) return void 0;
|
|
525446
|
+
const scanner = createTurnScanner(turnId);
|
|
525447
|
+
for await (const line of boundedLines(canonicalWire, wireStat.size)) scanner.accept(JSON.parse(line));
|
|
525448
|
+
return scanner.finish();
|
|
525449
|
+
}
|
|
525450
|
+
function createTurnScanner(completedTurnId) {
|
|
525451
|
+
let latestUserText;
|
|
525452
|
+
let latestUserTime;
|
|
525453
|
+
let userText;
|
|
525454
|
+
let occurredAt;
|
|
525455
|
+
let assistantText = "";
|
|
525456
|
+
let finalStepEnded = false;
|
|
525457
|
+
const targetTurnId = String(completedTurnId);
|
|
525458
|
+
const accept = (raw) => {
|
|
525459
|
+
if (!isRecord$4(raw)) return;
|
|
525460
|
+
if (raw["type"] === "turn.prompt") {
|
|
525461
|
+
const origin = raw["origin"];
|
|
525462
|
+
const input = raw["input"];
|
|
525463
|
+
const text = isRecord$4(origin) && origin["kind"] === "user" && Array.isArray(input) && input.every((part) => isRecord$4(part) && part["type"] === "text") ? textParts(input) : void 0;
|
|
525464
|
+
latestUserText = text && !GROUP_MARKER.test(text) && !SECRET_PATTERN.test(text) ? text : void 0;
|
|
525465
|
+
latestUserTime = latestUserText === void 0 ? void 0 : isoTime(raw["time"]);
|
|
525466
|
+
return;
|
|
525467
|
+
}
|
|
525468
|
+
if (raw["type"] !== "context.append_loop_event" || !isRecord$4(raw["event"])) return;
|
|
525469
|
+
const event = raw["event"];
|
|
525470
|
+
if (event["type"] === "step.begin" && event["turnId"] === targetTurnId) {
|
|
525471
|
+
userText ??= latestUserText;
|
|
525472
|
+
occurredAt ??= latestUserTime;
|
|
525473
|
+
assistantText = "";
|
|
525474
|
+
finalStepEnded = false;
|
|
525475
|
+
return;
|
|
525476
|
+
}
|
|
525477
|
+
if (event["type"] === "content.part" && event["turnId"] === targetTurnId && userText !== void 0 && isRecord$4(event["part"]) && event["part"]["type"] === "text" && typeof event["part"]["text"] === "string") {
|
|
525478
|
+
assistantText += event["part"]["text"];
|
|
525479
|
+
return;
|
|
525480
|
+
}
|
|
525481
|
+
if (event["type"] === "step.end" && event["turnId"] === targetTurnId) finalStepEnded = event["finishReason"] === "end_turn";
|
|
525482
|
+
};
|
|
525483
|
+
return {
|
|
525484
|
+
accept,
|
|
525485
|
+
finish: () => {
|
|
525486
|
+
const answer = assistantText.trim();
|
|
525487
|
+
return finalStepEnded && userText !== void 0 && occurredAt !== void 0 && answer.length > 0 && !SECRET_PATTERN.test(answer) ? {
|
|
525488
|
+
userText,
|
|
525489
|
+
assistantText: answer,
|
|
525490
|
+
occurredAt
|
|
525491
|
+
} : void 0;
|
|
525492
|
+
}
|
|
525493
|
+
};
|
|
525494
|
+
}
|
|
525495
|
+
function isoTime(value) {
|
|
525496
|
+
if (typeof value !== "string") return void 0;
|
|
525497
|
+
const timestamp = Date.parse(value);
|
|
525498
|
+
return Number.isFinite(timestamp) && new Date(timestamp).toISOString() === value ? value : void 0;
|
|
525499
|
+
}
|
|
525500
|
+
function textParts(parts) {
|
|
525501
|
+
return parts.filter((part) => isRecord$4(part) && part["type"] === "text" && typeof part["text"] === "string").map((part) => part.text).join("\n").trim() || void 0;
|
|
525502
|
+
}
|
|
525503
|
+
function isRecord$4(value) {
|
|
525504
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
525505
|
+
}
|
|
525506
|
+
function isInside(root, candidate) {
|
|
525507
|
+
const relative = path.relative(root, candidate);
|
|
525508
|
+
return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
525509
|
+
}
|
|
525510
|
+
async function* boundedLines(wirePath, size) {
|
|
525511
|
+
const stream = createReadStream(wirePath, {
|
|
525512
|
+
encoding: "utf8",
|
|
525513
|
+
end: size - 1
|
|
525514
|
+
});
|
|
525515
|
+
let pending = "";
|
|
525516
|
+
try {
|
|
525517
|
+
for await (const chunk of stream) {
|
|
525518
|
+
let offset = 0;
|
|
525519
|
+
while (offset < chunk.length) {
|
|
525520
|
+
const newline = chunk.indexOf("\n", offset);
|
|
525521
|
+
const end = newline < 0 ? chunk.length : newline;
|
|
525522
|
+
pending += chunk.slice(offset, end);
|
|
525523
|
+
if (pending.length > MAX_WIRE_RECORD_CHARS) throw new Error("Honcho Wire record is too large.");
|
|
525524
|
+
if (newline < 0) break;
|
|
525525
|
+
if (pending.length > 0) yield pending.replace(/\r$/u, "");
|
|
525526
|
+
pending = "";
|
|
525527
|
+
offset = newline + 1;
|
|
525528
|
+
}
|
|
525529
|
+
}
|
|
525530
|
+
} finally {
|
|
525531
|
+
stream.destroy();
|
|
525532
|
+
}
|
|
525533
|
+
}
|
|
525534
|
+
//#endregion
|
|
525535
|
+
//#region src/personal-memory/account-memory-capture.ts
|
|
525536
|
+
const MAX_PENDING = 2e3;
|
|
525537
|
+
const MAX_COMPLETED = 1e4;
|
|
525538
|
+
const MAX_RETRACTIONS = 2e3;
|
|
525539
|
+
const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
525540
|
+
var AccountMemoryCaptureQueue = class {
|
|
525541
|
+
homeDir;
|
|
525542
|
+
broker;
|
|
525543
|
+
readTurn;
|
|
525544
|
+
workspaceCache;
|
|
525545
|
+
work = Promise.resolve();
|
|
525546
|
+
constructor(homeDir, broker, readTurn = readCompletedHonchoTurn, workspaceCache) {
|
|
525547
|
+
this.homeDir = homeDir;
|
|
525548
|
+
this.broker = broker;
|
|
525549
|
+
this.readTurn = readTurn;
|
|
525550
|
+
this.workspaceCache = workspaceCache;
|
|
525551
|
+
}
|
|
525552
|
+
captureCompletedTurn(session, turnId) {
|
|
525553
|
+
return this.serial(async () => {
|
|
525554
|
+
if (!Number.isSafeInteger(turnId) || turnId < 0) return "unavailable";
|
|
525555
|
+
let state;
|
|
525556
|
+
try {
|
|
525557
|
+
state = await this.readSessionState(session.id);
|
|
525558
|
+
if (turnId <= state.blockedThroughTurnId) return "skipped";
|
|
525559
|
+
if (turnId > state.highestObservedTurnId) {
|
|
525560
|
+
state = {
|
|
525561
|
+
...state,
|
|
525562
|
+
highestObservedTurnId: turnId
|
|
525563
|
+
};
|
|
525564
|
+
await this.writeSessionState(state);
|
|
525565
|
+
}
|
|
525566
|
+
} catch {
|
|
525567
|
+
return "unavailable";
|
|
525568
|
+
}
|
|
525569
|
+
let workspace;
|
|
525570
|
+
let turn;
|
|
525571
|
+
try {
|
|
525572
|
+
workspace = await this.broker.workspace(session.id);
|
|
525573
|
+
turn = await this.readTurn(this.homeDir, session, turnId);
|
|
525574
|
+
} catch {
|
|
525575
|
+
return "unavailable";
|
|
525576
|
+
}
|
|
525577
|
+
if (state.workspaceId !== null && state.workspaceId !== workspace.workspaceId) return "unavailable";
|
|
525578
|
+
if (state.workspaceId === null || state.sessionEpoch !== workspace.sessionEpoch) try {
|
|
525579
|
+
await this.writeSessionState({
|
|
525580
|
+
...state,
|
|
525581
|
+
workspaceId: workspace.workspaceId,
|
|
525582
|
+
sessionEpoch: workspace.sessionEpoch
|
|
525583
|
+
});
|
|
525584
|
+
} catch {
|
|
525585
|
+
return "unavailable";
|
|
525586
|
+
}
|
|
525587
|
+
if (this.workspaceCache !== void 0) try {
|
|
525588
|
+
if (!await this.workspaceCache.set(workspace.workspaceId)) return "unavailable";
|
|
525589
|
+
} catch {
|
|
525590
|
+
return "unavailable";
|
|
525591
|
+
}
|
|
525592
|
+
if (turn === void 0 || beforeCutoff(turn.occurredAt, workspace.forgetCutoff)) return "skipped";
|
|
525593
|
+
const journalPath = this.journalPath(workspace.workspaceId);
|
|
525594
|
+
let journal;
|
|
525595
|
+
try {
|
|
525596
|
+
journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525597
|
+
} catch {
|
|
525598
|
+
return "unavailable";
|
|
525599
|
+
}
|
|
525600
|
+
if (journal.suppressedTurns.includes(turnKey(session.id, turnId))) return "skipped";
|
|
525601
|
+
if (journal.known.some((entry) => entry.sessionId === session.id && entry.turnId === turnId)) return "skipped";
|
|
525602
|
+
const revision = journal.revisions[turnKey(session.id, turnId)] ?? 0;
|
|
525603
|
+
const messageIds = turnMessageIds(session.id, turnId, turn, revision);
|
|
525604
|
+
const key = captureKey(session.id, turnId, turn.occurredAt, messageIds);
|
|
525605
|
+
if (journal.completed.includes(key)) return "skipped";
|
|
525606
|
+
const old = journal.pending.find((entry) => entry.sessionId === session.id && entry.turnId === turnId);
|
|
525607
|
+
if (old !== void 0 && (old.occurredAt !== turn.occurredAt || old.messageIds.some((id, index) => id !== messageIds[index]))) return "skipped";
|
|
525608
|
+
if (old === void 0) {
|
|
525609
|
+
if (journal.pending.length >= MAX_PENDING) return "unavailable";
|
|
525610
|
+
journal = {
|
|
525611
|
+
...journal,
|
|
525612
|
+
pending: [...journal.pending, {
|
|
525613
|
+
captureId: randomUUID(),
|
|
525614
|
+
sessionId: session.id,
|
|
525615
|
+
sessionDir: session.sessionDir,
|
|
525616
|
+
turnId,
|
|
525617
|
+
occurredAt: turn.occurredAt,
|
|
525618
|
+
messageIds,
|
|
525619
|
+
sessionEpoch: workspace.sessionEpoch,
|
|
525620
|
+
awaitingSessionRetract: journal.retractions.some((entry) => entry.sessionId === session.id && "wholeSession" in entry)
|
|
525621
|
+
}]
|
|
525622
|
+
};
|
|
525623
|
+
try {
|
|
525624
|
+
await this.writeJournal(journalPath, journal);
|
|
525625
|
+
} catch {
|
|
525626
|
+
return "unavailable";
|
|
525627
|
+
}
|
|
525628
|
+
}
|
|
525629
|
+
if (!await this.flushRetractions(journalPath, journal)) return "queued";
|
|
525630
|
+
journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525631
|
+
return this.flushJournal(journalPath, journal, workspace, {
|
|
525632
|
+
sessionId: session.id,
|
|
525633
|
+
turnId,
|
|
525634
|
+
turn
|
|
525635
|
+
});
|
|
525636
|
+
});
|
|
525637
|
+
}
|
|
525638
|
+
retryPending() {
|
|
525639
|
+
return this.serial(async () => {
|
|
525640
|
+
try {
|
|
525641
|
+
const workspace = await this.broker.workspace();
|
|
525642
|
+
const journalPath = this.journalPath(workspace.workspaceId);
|
|
525643
|
+
let journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525644
|
+
if (!await this.flushRetractions(journalPath, journal)) return "queued";
|
|
525645
|
+
journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525646
|
+
return await this.flushJournal(journalPath, journal, workspace);
|
|
525647
|
+
} catch {
|
|
525648
|
+
return "unavailable";
|
|
525649
|
+
}
|
|
525650
|
+
});
|
|
525651
|
+
}
|
|
525652
|
+
retryRetractions() {
|
|
525653
|
+
return this.serial(async () => {
|
|
525654
|
+
try {
|
|
525655
|
+
const workspace = await this.broker.workspace();
|
|
525656
|
+
const journalPath = this.journalPath(workspace.workspaceId);
|
|
525657
|
+
const journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525658
|
+
if (journal.retractions.length === 0) return "skipped";
|
|
525659
|
+
return await this.flushRetractions(journalPath, journal) ? "retracted" : "queued";
|
|
525660
|
+
} catch {
|
|
525661
|
+
return "unavailable";
|
|
525662
|
+
}
|
|
525663
|
+
});
|
|
525664
|
+
}
|
|
525665
|
+
flushRetractionsBeforeLogout() {
|
|
525666
|
+
return this.serial(async () => {
|
|
525667
|
+
try {
|
|
525668
|
+
const cachedWorkspaceId = await this.workspaceCache?.get();
|
|
525669
|
+
if (cachedWorkspaceId === void 0) return false;
|
|
525670
|
+
const journalPath = this.journalPath(cachedWorkspaceId);
|
|
525671
|
+
const journal = await this.readJournal(journalPath, cachedWorkspaceId);
|
|
525672
|
+
if (journal.retractions.length === 0) return false;
|
|
525673
|
+
if ((await this.broker.workspace()).workspaceId !== cachedWorkspaceId) return true;
|
|
525674
|
+
return !await this.flushRetractions(journalPath, journal);
|
|
525675
|
+
} catch {
|
|
525676
|
+
return true;
|
|
525677
|
+
}
|
|
525678
|
+
});
|
|
525679
|
+
}
|
|
525680
|
+
retractTurn(sessionId, turnId) {
|
|
525681
|
+
return this.serial(async () => {
|
|
525682
|
+
try {
|
|
525683
|
+
const workspace = await this.broker.workspace();
|
|
525684
|
+
const journalPath = this.journalPath(workspace.workspaceId);
|
|
525685
|
+
const journal = await this.readJournal(journalPath, workspace.workspaceId);
|
|
525686
|
+
const matching = [...journal.pending, ...journal.known].filter((entry) => entry.sessionId === sessionId && entry.turnId === turnId);
|
|
525687
|
+
const messageIds = [...new Set(matching.flatMap((entry) => entry.messageIds))];
|
|
525688
|
+
if (messageIds.length === 0) return "skipped";
|
|
525689
|
+
if (journal.retractions.length >= MAX_RETRACTIONS) return "unavailable";
|
|
525690
|
+
const next = {
|
|
525691
|
+
...journal,
|
|
525692
|
+
pending: journal.pending.filter((entry) => entry.sessionId !== sessionId || entry.turnId !== turnId),
|
|
525693
|
+
known: journal.known.filter((entry) => entry.sessionId !== sessionId || entry.turnId !== turnId),
|
|
525694
|
+
retractions: [...journal.retractions, {
|
|
525695
|
+
retractId: randomUUID(),
|
|
525696
|
+
sessionId,
|
|
525697
|
+
messageIds
|
|
525698
|
+
}],
|
|
525699
|
+
revisions: {
|
|
525700
|
+
...journal.revisions,
|
|
525701
|
+
[turnKey(sessionId, turnId)]: (journal.revisions[turnKey(sessionId, turnId)] ?? 0) + 1
|
|
525702
|
+
}
|
|
525703
|
+
};
|
|
525704
|
+
await this.writeJournal(journalPath, next);
|
|
525705
|
+
return await this.flushRetractions(journalPath, next) ? "retracted" : "queued";
|
|
525706
|
+
} catch {
|
|
525707
|
+
return "unavailable";
|
|
525708
|
+
}
|
|
525709
|
+
});
|
|
525710
|
+
}
|
|
525711
|
+
retractSession(sessionId, throughTurnId) {
|
|
525712
|
+
return this.serial(async () => {
|
|
525713
|
+
if (throughTurnId !== void 0 && (!Number.isSafeInteger(throughTurnId) || throughTurnId < 0)) return "unavailable";
|
|
525714
|
+
let state;
|
|
525715
|
+
try {
|
|
525716
|
+
state = await this.readSessionState(sessionId);
|
|
525717
|
+
} catch {
|
|
525718
|
+
return "unavailable";
|
|
525719
|
+
}
|
|
525720
|
+
let workspace;
|
|
525721
|
+
try {
|
|
525722
|
+
workspace = await this.broker.workspace(sessionId);
|
|
525723
|
+
} catch {
|
|
525724
|
+
if (state.workspaceId !== null) {
|
|
525725
|
+
let cachedWorkspaceId;
|
|
525726
|
+
try {
|
|
525727
|
+
cachedWorkspaceId = await this.workspaceCache?.get();
|
|
525728
|
+
} catch {
|
|
525729
|
+
return "unavailable";
|
|
525730
|
+
}
|
|
525731
|
+
if (cachedWorkspaceId !== state.workspaceId) {
|
|
525732
|
+
try {
|
|
525733
|
+
await this.writeSessionState({
|
|
525734
|
+
...state,
|
|
525735
|
+
highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
|
|
525736
|
+
blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1)
|
|
525737
|
+
});
|
|
525738
|
+
} catch {
|
|
525739
|
+
return "unavailable";
|
|
525740
|
+
}
|
|
525741
|
+
return "unavailable";
|
|
525742
|
+
}
|
|
525743
|
+
return this.queueSessionRetraction(sessionId, state, cachedWorkspaceId, state.sessionEpoch, throughTurnId, false);
|
|
525744
|
+
}
|
|
525745
|
+
try {
|
|
525746
|
+
await this.writeSessionState({
|
|
525747
|
+
...state,
|
|
525748
|
+
highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
|
|
525749
|
+
blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1)
|
|
525750
|
+
});
|
|
525751
|
+
return "retracted";
|
|
525752
|
+
} catch {
|
|
525753
|
+
return "unavailable";
|
|
525754
|
+
}
|
|
525755
|
+
}
|
|
525756
|
+
if (workspace.sessionEpoch === null) return "unavailable";
|
|
525757
|
+
if (state.workspaceId !== null && state.workspaceId !== workspace.workspaceId) return "unavailable";
|
|
525758
|
+
if (this.workspaceCache !== void 0) try {
|
|
525759
|
+
if (!await this.workspaceCache.set(workspace.workspaceId)) return "unavailable";
|
|
525760
|
+
} catch {
|
|
525761
|
+
return "unavailable";
|
|
525762
|
+
}
|
|
525763
|
+
return this.queueSessionRetraction(sessionId, state, workspace.workspaceId, workspace.sessionEpoch, throughTurnId, true);
|
|
525764
|
+
});
|
|
525765
|
+
}
|
|
525766
|
+
async queueSessionRetraction(sessionId, state, workspaceId, expectedEpoch, throughTurnId, sendNow) {
|
|
525767
|
+
try {
|
|
525768
|
+
const journalPath = this.journalPath(workspaceId);
|
|
525769
|
+
const journal = await this.readJournal(journalPath, workspaceId);
|
|
525770
|
+
if (journal.retractions.length >= MAX_RETRACTIONS) return "unavailable";
|
|
525771
|
+
const next = {
|
|
525772
|
+
...journal,
|
|
525773
|
+
pending: journal.pending.filter((entry) => entry.sessionId !== sessionId),
|
|
525774
|
+
known: journal.known.filter((entry) => entry.sessionId !== sessionId),
|
|
525775
|
+
retractions: [...journal.retractions, {
|
|
525776
|
+
retractId: randomUUID(),
|
|
525777
|
+
sessionId,
|
|
525778
|
+
wholeSession: true,
|
|
525779
|
+
expectedEpoch
|
|
525780
|
+
}],
|
|
525781
|
+
suppressedTurns: [...new Set([...journal.suppressedTurns, ...[...journal.pending, ...journal.known].filter((entry) => entry.sessionId === sessionId).map((entry) => turnKey(entry.sessionId, entry.turnId))])].slice(-MAX_COMPLETED)
|
|
525782
|
+
};
|
|
525783
|
+
await this.writeJournal(journalPath, next);
|
|
525784
|
+
await this.writeSessionState({
|
|
525785
|
+
...state,
|
|
525786
|
+
highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
|
|
525787
|
+
blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1),
|
|
525788
|
+
workspaceId,
|
|
525789
|
+
sessionEpoch: expectedEpoch
|
|
525790
|
+
});
|
|
525791
|
+
return sendNow && await this.flushRetractions(journalPath, next) ? "retracted" : "queued";
|
|
525792
|
+
} catch {
|
|
525793
|
+
return "unavailable";
|
|
525794
|
+
}
|
|
525795
|
+
}
|
|
525796
|
+
async flushRetractions(journalPath, journal) {
|
|
525797
|
+
if (this.broker.retract === void 0) return journal.retractions.length === 0;
|
|
525798
|
+
let current = journal;
|
|
525799
|
+
for (const entry of journal.retractions) {
|
|
525800
|
+
let response;
|
|
525801
|
+
try {
|
|
525802
|
+
response = await this.broker.retract(entry);
|
|
525803
|
+
} catch {
|
|
525804
|
+
return false;
|
|
525805
|
+
}
|
|
525806
|
+
if ("wholeSession" in entry && response.sessionEpoch !== void 0) try {
|
|
525807
|
+
const state = await this.readSessionState(entry.sessionId);
|
|
525808
|
+
await this.writeSessionState({
|
|
525809
|
+
...state,
|
|
525810
|
+
sessionEpoch: response.sessionEpoch
|
|
525811
|
+
});
|
|
525812
|
+
} catch {
|
|
525813
|
+
return false;
|
|
525814
|
+
}
|
|
525815
|
+
current = {
|
|
525816
|
+
...current,
|
|
525817
|
+
retractions: current.retractions.filter((item) => item !== entry),
|
|
525818
|
+
pending: "wholeSession" in entry && response.sessionEpoch !== void 0 ? response.rederive === false ? current.pending.filter((item) => item.sessionId !== entry.sessionId || !item.awaitingSessionRetract) : current.pending.map((item) => item.sessionId === entry.sessionId && item.awaitingSessionRetract ? {
|
|
525819
|
+
...item,
|
|
525820
|
+
sessionEpoch: response.sessionEpoch,
|
|
525821
|
+
awaitingSessionRetract: false
|
|
525822
|
+
} : item) : current.pending
|
|
525823
|
+
};
|
|
525824
|
+
await this.writeJournal(journalPath, current);
|
|
525825
|
+
}
|
|
525826
|
+
return true;
|
|
525827
|
+
}
|
|
525828
|
+
discardPending() {
|
|
525829
|
+
return this.serial(async () => {
|
|
525830
|
+
const directory = path.join(this.homeDir, "memory");
|
|
525831
|
+
let names;
|
|
525832
|
+
try {
|
|
525833
|
+
names = await readdir(directory);
|
|
525834
|
+
} catch (error) {
|
|
525835
|
+
if (isMissing(error)) return;
|
|
525836
|
+
throw error;
|
|
525837
|
+
}
|
|
525838
|
+
for (const name of names) {
|
|
525839
|
+
if (!/^honcho-pending-[0-9a-f]{64}\.json$/u.test(name)) continue;
|
|
525840
|
+
const journalPath = path.join(directory, name);
|
|
525841
|
+
if (!(await lstat(journalPath)).isFile()) continue;
|
|
525842
|
+
const value = JSON.parse(await readFile(journalPath, "utf8"));
|
|
525843
|
+
if (!isRecord$3(value) || typeof value["workspaceId"] !== "string") continue;
|
|
525844
|
+
const journal = await this.readJournal(journalPath, value["workspaceId"]);
|
|
525845
|
+
if (journal.pending.length > 0) await this.writeJournal(journalPath, {
|
|
525846
|
+
...journal,
|
|
525847
|
+
pending: []
|
|
525848
|
+
});
|
|
525849
|
+
}
|
|
525850
|
+
});
|
|
525851
|
+
}
|
|
525852
|
+
async flushJournal(journalPath, journal, workspace, fresh) {
|
|
525853
|
+
if (journal.pending.length === 0) return "skipped";
|
|
525854
|
+
let pending = [...journal.pending];
|
|
525855
|
+
let completed = [...journal.completed];
|
|
525856
|
+
let known = [...journal.known];
|
|
525857
|
+
let result = "skipped";
|
|
525858
|
+
for (const entry of journal.pending) {
|
|
525859
|
+
if (entry.awaitingSessionRetract) return "queued";
|
|
525860
|
+
const session = {
|
|
525861
|
+
id: entry.sessionId,
|
|
525862
|
+
sessionDir: entry.sessionDir
|
|
525863
|
+
};
|
|
525864
|
+
let turn;
|
|
525865
|
+
try {
|
|
525866
|
+
turn = fresh?.sessionId === entry.sessionId && fresh.turnId === entry.turnId ? fresh.turn : await this.readTurn(this.homeDir, session, entry.turnId);
|
|
525867
|
+
} catch {
|
|
525868
|
+
return "queued";
|
|
525869
|
+
}
|
|
525870
|
+
if (turn === void 0 || turn.occurredAt !== entry.occurredAt || beforeCutoff(entry.occurredAt, workspace.forgetCutoff)) {
|
|
525871
|
+
pending = pending.filter((item) => item.captureId !== entry.captureId);
|
|
525872
|
+
await this.writeJournal(journalPath, {
|
|
525873
|
+
...journal,
|
|
525874
|
+
pending,
|
|
525875
|
+
completed,
|
|
525876
|
+
known
|
|
525877
|
+
});
|
|
525878
|
+
continue;
|
|
525879
|
+
}
|
|
525880
|
+
const revision = journal.revisions[turnKey(entry.sessionId, entry.turnId)] ?? 0;
|
|
525881
|
+
if (turnMessageIds(entry.sessionId, entry.turnId, turn, revision).some((id, index) => id !== entry.messageIds[index])) {
|
|
525882
|
+
pending = pending.filter((item) => item.captureId !== entry.captureId);
|
|
525883
|
+
await this.writeJournal(journalPath, {
|
|
525884
|
+
...journal,
|
|
525885
|
+
pending,
|
|
525886
|
+
completed,
|
|
525887
|
+
known
|
|
525888
|
+
});
|
|
525889
|
+
continue;
|
|
525890
|
+
}
|
|
525891
|
+
try {
|
|
525892
|
+
const response = await this.broker.capture({
|
|
525893
|
+
captureId: entry.captureId,
|
|
525894
|
+
sessionId: entry.sessionId,
|
|
525895
|
+
forgetGeneration: workspace.forgetGeneration,
|
|
525896
|
+
sessionEpoch: entry.sessionEpoch,
|
|
525897
|
+
messages: [{
|
|
525898
|
+
id: entry.messageIds[0],
|
|
525899
|
+
role: "user",
|
|
525900
|
+
content: turn.userText,
|
|
525901
|
+
at: turn.occurredAt
|
|
525902
|
+
}, {
|
|
525903
|
+
id: entry.messageIds[1],
|
|
525904
|
+
role: "assistant",
|
|
525905
|
+
content: turn.assistantText,
|
|
525906
|
+
at: turn.occurredAt
|
|
525907
|
+
}]
|
|
525908
|
+
});
|
|
525909
|
+
const key = captureKey(entry.sessionId, entry.turnId, entry.occurredAt, entry.messageIds);
|
|
525910
|
+
if ("reason" in response && response.reason === "memory_disabled") {
|
|
525911
|
+
completed = [...completed, key].slice(-MAX_COMPLETED);
|
|
525912
|
+
await this.writeJournal(journalPath, {
|
|
525913
|
+
...journal,
|
|
525914
|
+
pending: [],
|
|
525915
|
+
completed
|
|
525916
|
+
});
|
|
525917
|
+
return "skipped";
|
|
525918
|
+
}
|
|
525919
|
+
if ("reason" in response && response.reason === "session_retracted") {
|
|
525920
|
+
pending = pending.filter((item) => item.sessionId !== entry.sessionId || item.sessionEpoch !== entry.sessionEpoch);
|
|
525921
|
+
await this.writeJournal(journalPath, {
|
|
525922
|
+
...journal,
|
|
525923
|
+
pending,
|
|
525924
|
+
completed,
|
|
525925
|
+
known
|
|
525926
|
+
});
|
|
525927
|
+
return "skipped";
|
|
525928
|
+
}
|
|
525929
|
+
pending = pending.filter((item) => item.captureId !== entry.captureId);
|
|
525930
|
+
completed = [...completed, key].slice(-MAX_COMPLETED);
|
|
525931
|
+
known = [...known, {
|
|
525932
|
+
key,
|
|
525933
|
+
sessionId: entry.sessionId,
|
|
525934
|
+
turnId: entry.turnId,
|
|
525935
|
+
occurredAt: entry.occurredAt,
|
|
525936
|
+
messageIds: entry.messageIds
|
|
525937
|
+
}].slice(-MAX_COMPLETED);
|
|
525938
|
+
await this.writeJournal(journalPath, {
|
|
525939
|
+
...journal,
|
|
525940
|
+
pending,
|
|
525941
|
+
completed,
|
|
525942
|
+
known
|
|
525943
|
+
});
|
|
525944
|
+
result = "captured";
|
|
525945
|
+
} catch (error) {
|
|
525946
|
+
if (error instanceof PersonalMemoryBrokerError && error.status === 403) {
|
|
525947
|
+
const suppressedTurns = [...new Set([...journal.suppressedTurns, ...pending.map((item) => turnKey(item.sessionId, item.turnId))])].slice(-MAX_COMPLETED);
|
|
525948
|
+
try {
|
|
525949
|
+
await this.writeJournal(journalPath, {
|
|
525950
|
+
...journal,
|
|
525951
|
+
pending: [],
|
|
525952
|
+
completed,
|
|
525953
|
+
known,
|
|
525954
|
+
suppressedTurns
|
|
525955
|
+
});
|
|
525956
|
+
} catch {
|
|
525957
|
+
return "unavailable";
|
|
525958
|
+
}
|
|
525959
|
+
return "skipped";
|
|
525960
|
+
}
|
|
525961
|
+
if (error instanceof PersonalMemoryBrokerError && (error.code === "INVALID_PAYLOAD" || error.code === "PAYLOAD_TOO_LARGE" || error.code === "SECRET_REJECTED")) {
|
|
525962
|
+
pending = pending.filter((item) => item.captureId !== entry.captureId);
|
|
525963
|
+
await this.writeJournal(journalPath, {
|
|
525964
|
+
...journal,
|
|
525965
|
+
pending,
|
|
525966
|
+
completed,
|
|
525967
|
+
known
|
|
525968
|
+
});
|
|
525969
|
+
continue;
|
|
525970
|
+
}
|
|
525971
|
+
if (error instanceof PersonalMemoryBrokerError && error.code === "FORGET_GENERATION_CHANGED") return "queued";
|
|
525972
|
+
return "queued";
|
|
525973
|
+
}
|
|
525974
|
+
}
|
|
525975
|
+
return result;
|
|
525976
|
+
}
|
|
525977
|
+
journalPath(workspaceId) {
|
|
525978
|
+
const name = createHash("sha256").update(workspaceId).digest("hex");
|
|
525979
|
+
return path.join(this.homeDir, "memory", `honcho-pending-${name}.json`);
|
|
525980
|
+
}
|
|
525981
|
+
sessionStatePath(sessionId) {
|
|
525982
|
+
const name = createHash("sha256").update(sessionId).digest("hex");
|
|
525983
|
+
return path.join(this.homeDir, "memory", `honcho-session-${name}.json`);
|
|
525984
|
+
}
|
|
525985
|
+
async readSessionState(sessionId) {
|
|
525986
|
+
let value;
|
|
525987
|
+
try {
|
|
525988
|
+
value = JSON.parse(await readFile(this.sessionStatePath(sessionId), "utf8"));
|
|
525989
|
+
} catch (error) {
|
|
525990
|
+
if (isMissing(error)) return {
|
|
525991
|
+
version: 1,
|
|
525992
|
+
sessionId,
|
|
525993
|
+
highestObservedTurnId: -1,
|
|
525994
|
+
blockedThroughTurnId: -1,
|
|
525995
|
+
workspaceId: null,
|
|
525996
|
+
sessionEpoch: null
|
|
525997
|
+
};
|
|
525998
|
+
throw error;
|
|
525999
|
+
}
|
|
526000
|
+
if (!isRecord$3(value) || value["version"] !== 1 || value["sessionId"] !== sessionId || !Number.isSafeInteger(value["highestObservedTurnId"]) || value["highestObservedTurnId"] < -1 || !Number.isSafeInteger(value["blockedThroughTurnId"]) || value["blockedThroughTurnId"] < -1 || value["blockedThroughTurnId"] > value["highestObservedTurnId"] || value["workspaceId"] !== null && (typeof value["workspaceId"] !== "string" || value["workspaceId"].length === 0) || value["sessionEpoch"] !== null && (!Number.isSafeInteger(value["sessionEpoch"]) || value["sessionEpoch"] < 0)) throw new Error("Invalid account memory session state.");
|
|
526001
|
+
return value;
|
|
526002
|
+
}
|
|
526003
|
+
async writeSessionState(state) {
|
|
526004
|
+
const statePath = this.sessionStatePath(state.sessionId);
|
|
526005
|
+
const directory = path.dirname(statePath);
|
|
526006
|
+
await mkdir(directory, {
|
|
526007
|
+
recursive: true,
|
|
526008
|
+
mode: 448
|
|
526009
|
+
});
|
|
526010
|
+
const root = await realpath(this.homeDir);
|
|
526011
|
+
if (path.dirname(await realpath(directory)) !== root) throw new Error("Account memory session state escapes the BLUN profile.");
|
|
526012
|
+
const temporary = `${statePath}.${randomUUID()}.tmp`;
|
|
526013
|
+
try {
|
|
526014
|
+
await writeFile(temporary, JSON.stringify(state), {
|
|
526015
|
+
encoding: "utf8",
|
|
526016
|
+
mode: 384,
|
|
526017
|
+
flag: "wx"
|
|
526018
|
+
});
|
|
526019
|
+
await rename(temporary, statePath);
|
|
526020
|
+
} finally {
|
|
526021
|
+
await unlink(temporary).catch(() => {});
|
|
526022
|
+
}
|
|
526023
|
+
}
|
|
526024
|
+
async readJournal(journalPath, workspaceId) {
|
|
526025
|
+
let text;
|
|
526026
|
+
try {
|
|
526027
|
+
text = await readFile(journalPath, "utf8");
|
|
526028
|
+
} catch (error) {
|
|
526029
|
+
if (isMissing(error)) return {
|
|
526030
|
+
version: 2,
|
|
526031
|
+
workspaceId,
|
|
526032
|
+
pending: [],
|
|
526033
|
+
completed: [],
|
|
526034
|
+
known: [],
|
|
526035
|
+
retractions: [],
|
|
526036
|
+
suppressedTurns: [],
|
|
526037
|
+
revisions: {}
|
|
526038
|
+
};
|
|
526039
|
+
throw error;
|
|
526040
|
+
}
|
|
526041
|
+
const value = JSON.parse(text);
|
|
526042
|
+
if (!isRecord$3(value) || value["version"] !== 2 || value["workspaceId"] !== workspaceId || !Array.isArray(value["pending"]) || value["pending"].length > MAX_PENDING || !value["pending"].every(validPending) || !Array.isArray(value["completed"]) || value["completed"].length > MAX_COMPLETED || !value["completed"].every((item) => typeof item === "string" && /^[0-9a-f]{64}$/u.test(item)) || !Array.isArray(value["known"]) || value["known"].length > MAX_COMPLETED || !value["known"].every(validKnown) || !Array.isArray(value["retractions"]) || value["retractions"].length > MAX_RETRACTIONS || !value["retractions"].every(validRetraction) || !Array.isArray(value["suppressedTurns"]) || value["suppressedTurns"].length > MAX_COMPLETED || !value["suppressedTurns"].every((item) => typeof item === "string" && /^[0-9a-f]{64}$/u.test(item)) || !isRecord$3(value["revisions"]) || Object.keys(value["revisions"]).length > MAX_COMPLETED || !Object.entries(value["revisions"]).every(([key, revision]) => /^[0-9a-f]{64}$/u.test(key) && Number.isSafeInteger(revision) && revision >= 0)) throw new Error("Invalid account memory journal.");
|
|
526043
|
+
return value;
|
|
526044
|
+
}
|
|
526045
|
+
async writeJournal(journalPath, journal) {
|
|
526046
|
+
const directory = path.dirname(journalPath);
|
|
526047
|
+
await mkdir(directory, {
|
|
526048
|
+
recursive: true,
|
|
526049
|
+
mode: 448
|
|
526050
|
+
});
|
|
526051
|
+
const root = await realpath(this.homeDir);
|
|
526052
|
+
if (path.dirname(await realpath(directory)) !== root) throw new Error("Account memory journal escapes the BLUN profile.");
|
|
526053
|
+
const temporary = `${journalPath}.${randomUUID()}.tmp`;
|
|
526054
|
+
try {
|
|
526055
|
+
await writeFile(temporary, JSON.stringify(journal), {
|
|
526056
|
+
encoding: "utf8",
|
|
526057
|
+
mode: 384,
|
|
526058
|
+
flag: "wx"
|
|
526059
|
+
});
|
|
526060
|
+
await rename(temporary, journalPath);
|
|
526061
|
+
} finally {
|
|
526062
|
+
await unlink(temporary).catch(() => {});
|
|
526063
|
+
}
|
|
526064
|
+
}
|
|
526065
|
+
serial(run) {
|
|
526066
|
+
const task = this.work.then(run, run);
|
|
526067
|
+
this.work = task.then(() => void 0, () => void 0);
|
|
526068
|
+
return task;
|
|
526069
|
+
}
|
|
526070
|
+
};
|
|
526071
|
+
function beforeCutoff(occurredAt, cutoff) {
|
|
526072
|
+
return cutoff !== null && Date.parse(occurredAt) <= Date.parse(cutoff);
|
|
526073
|
+
}
|
|
526074
|
+
function captureKey(sessionId, turnId, occurredAt, messageIds) {
|
|
526075
|
+
return createHash("sha256").update(`${sessionId}\0${turnId}\0${occurredAt}\0${messageIds.join("\0")}`).digest("hex");
|
|
526076
|
+
}
|
|
526077
|
+
function turnKey(sessionId, turnId) {
|
|
526078
|
+
return createHash("sha256").update(`${sessionId}\0${turnId}`).digest("hex");
|
|
526079
|
+
}
|
|
526080
|
+
function turnMessageIds(sessionId, turnId, turn, revision) {
|
|
526081
|
+
return [stableMessageId(sessionId, turnId, revision, "user", turn.userText), stableMessageId(sessionId, turnId, revision, "assistant", turn.assistantText)];
|
|
526082
|
+
}
|
|
526083
|
+
function stableMessageId(sessionId, turnId, revision, role, content) {
|
|
526084
|
+
return `tui-${createHash("sha256").update(`${sessionId}\0${turnId}\0${revision}\0${role}\0${content}`).digest("hex")}`;
|
|
526085
|
+
}
|
|
526086
|
+
function validPending(value) {
|
|
526087
|
+
return isRecord$3(value) && typeof value["captureId"] === "string" && UUID_V4.test(value["captureId"]) && typeof value["sessionId"] === "string" && typeof value["sessionDir"] === "string" && Number.isSafeInteger(value["turnId"]) && value["turnId"] >= 0 && typeof value["occurredAt"] === "string" && Number.isFinite(Date.parse(value["occurredAt"])) && validMessageIds(value["messageIds"]) && typeof value["awaitingSessionRetract"] === "boolean" && (value["sessionEpoch"] === null || Number.isSafeInteger(value["sessionEpoch"]) && value["sessionEpoch"] >= 0);
|
|
526088
|
+
}
|
|
526089
|
+
function validKnown(value) {
|
|
526090
|
+
return isRecord$3(value) && typeof value["key"] === "string" && /^[0-9a-f]{64}$/u.test(value["key"]) && typeof value["sessionId"] === "string" && Number.isSafeInteger(value["turnId"]) && typeof value["occurredAt"] === "string" && Number.isFinite(Date.parse(value["occurredAt"])) && validMessageIds(value["messageIds"]);
|
|
526091
|
+
}
|
|
526092
|
+
function validRetraction(value) {
|
|
526093
|
+
return isRecord$3(value) && typeof value["retractId"] === "string" && UUID_V4.test(value["retractId"]) && typeof value["sessionId"] === "string" && value["sessionId"].length > 0 && (value["wholeSession"] === true && (value["expectedEpoch"] === null || Number.isSafeInteger(value["expectedEpoch"]) && value["expectedEpoch"] >= 0) || Array.isArray(value["messageIds"]) && value["messageIds"].length > 0 && value["messageIds"].length <= 200 && value["messageIds"].every(validMessageId));
|
|
526094
|
+
}
|
|
526095
|
+
function validMessageIds(value) {
|
|
526096
|
+
return Array.isArray(value) && value.length === 2 && value.every(validMessageId);
|
|
526097
|
+
}
|
|
526098
|
+
function validMessageId(value) {
|
|
526099
|
+
return typeof value === "string" && /^tui-[0-9a-f]{64}$/u.test(value);
|
|
526100
|
+
}
|
|
526101
|
+
function isRecord$3(value) {
|
|
526102
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
526103
|
+
}
|
|
526104
|
+
function isMissing(error) {
|
|
526105
|
+
return isRecord$3(error) && error["code"] === "ENOENT";
|
|
526106
|
+
}
|
|
526107
|
+
//#endregion
|
|
526108
|
+
//#region src/personal-memory/account-memory-runtime.ts
|
|
526109
|
+
var TuiAccountMemoryRuntime = class {
|
|
526110
|
+
client;
|
|
526111
|
+
broker;
|
|
526112
|
+
queue;
|
|
526113
|
+
getManagedQuota;
|
|
526114
|
+
constructor(client, broker, queue, getManagedQuota) {
|
|
526115
|
+
this.client = client;
|
|
526116
|
+
this.broker = broker;
|
|
526117
|
+
this.queue = queue;
|
|
526118
|
+
this.getManagedQuota = getManagedQuota;
|
|
526119
|
+
}
|
|
526120
|
+
async captureCompletedTurn(session, turnId) {
|
|
526121
|
+
const permission = await this.permission("write");
|
|
526122
|
+
if (permission === "unavailable") return "unavailable";
|
|
526123
|
+
if (permission === "denied") {
|
|
526124
|
+
await this.queue.discardPending().catch(() => {});
|
|
526125
|
+
return "skipped";
|
|
526126
|
+
}
|
|
526127
|
+
return this.queue.captureCompletedTurn(session, turnId).catch(() => "unavailable");
|
|
526128
|
+
}
|
|
526129
|
+
async retryPending() {
|
|
526130
|
+
const permission = await this.permission("write");
|
|
526131
|
+
if (permission === "denied") await this.queue.discardPending().catch(() => {});
|
|
526132
|
+
const retractions = await this.queue.retryRetractions().catch(() => "unavailable");
|
|
526133
|
+
if (retractions === "queued") return "queued";
|
|
526134
|
+
if (permission === "denied") return "skipped";
|
|
526135
|
+
if (permission === "unavailable" || retractions === "unavailable") return "unavailable";
|
|
526136
|
+
return this.queue.retryPending().catch(() => "unavailable");
|
|
526137
|
+
}
|
|
526138
|
+
retractTurn(sessionId, turnId) {
|
|
526139
|
+
return this.queue.retractTurn(sessionId, turnId).catch(() => "unavailable");
|
|
526140
|
+
}
|
|
526141
|
+
retractSession(sessionId, throughTurnId) {
|
|
526142
|
+
return (throughTurnId === void 0 ? this.queue.retractSession(sessionId) : this.queue.retractSession(sessionId, throughTurnId)).catch(() => "unavailable");
|
|
526143
|
+
}
|
|
526144
|
+
flushRetractionsBeforeLogout() {
|
|
526145
|
+
return this.queue.flushRetractionsBeforeLogout().catch(() => true);
|
|
526146
|
+
}
|
|
526147
|
+
async recall(query) {
|
|
526148
|
+
if (await this.permission("read") !== "allowed") return void 0;
|
|
526149
|
+
return this.broker.recall(query, 8).catch(() => void 0);
|
|
526150
|
+
}
|
|
526151
|
+
async search(query, limit = 20) {
|
|
526152
|
+
if (await this.permission("read") !== "allowed") return void 0;
|
|
526153
|
+
return this.broker.search(query, { limit }).catch(() => void 0);
|
|
526154
|
+
}
|
|
526155
|
+
async permission(operation) {
|
|
526156
|
+
let settings;
|
|
526157
|
+
try {
|
|
526158
|
+
const quota = await this.getManagedQuota();
|
|
526159
|
+
if (quota.kind !== "ok") return "unavailable";
|
|
526160
|
+
if (quota.paid !== true) return "denied";
|
|
526161
|
+
settings = await this.client.getSettings();
|
|
526162
|
+
} catch {
|
|
526163
|
+
return "unavailable";
|
|
526164
|
+
}
|
|
526165
|
+
if (settings.consentStatus !== "enabled" || !settings.memoryEnabled || !settings.useChatHistory) return "denied";
|
|
526166
|
+
return operation === "write" ? settings.allowNewMemories ? "allowed" : "denied" : settings.useSavedMemories ? "allowed" : "denied";
|
|
526167
|
+
}
|
|
526168
|
+
};
|
|
526169
|
+
function createTuiAccountMemoryRuntime(harness, env = process.env) {
|
|
526170
|
+
if (env["BLUN_ACCOUNT_MEMORY_BROKER_ENABLED"] !== "1") return void 0;
|
|
526171
|
+
try {
|
|
526172
|
+
const client = createPersonalMemoryBrokerClient(harness);
|
|
526173
|
+
const broker = new AccountMemoryBroker(client);
|
|
526174
|
+
return new TuiAccountMemoryRuntime(client, broker, new AccountMemoryCaptureQueue(harness.homeDir, broker, void 0, {
|
|
526175
|
+
get: () => harness.auth.getCachedMemoryWorkspaceId(),
|
|
526176
|
+
set: (workspaceId) => harness.auth.cacheMemoryWorkspaceId(workspaceId)
|
|
526177
|
+
}), () => harness.auth.getManagedQuota(DEFAULT_OAUTH_PROVIDER_NAME));
|
|
526178
|
+
} catch {
|
|
526179
|
+
return;
|
|
526180
|
+
}
|
|
526181
|
+
}
|
|
526182
|
+
//#endregion
|
|
524984
526183
|
//#region src/utils/persistence.ts
|
|
524985
526184
|
/**
|
|
524986
526185
|
* Small persistence helpers for CLI-owned data files.
|
|
@@ -532899,7 +534098,8 @@ var PersonalMemoryController = class {
|
|
|
532899
534098
|
await this.dependencies.bindTools(session, this.host.harness, {
|
|
532900
534099
|
binding: personalMemoryHostBinding(),
|
|
532901
534100
|
localHistory: this.host.harness,
|
|
532902
|
-
searchOnly: true
|
|
534101
|
+
searchOnly: true,
|
|
534102
|
+
accountMemory: this.host.accountMemoryRuntime
|
|
532903
534103
|
});
|
|
532904
534104
|
return this.isCurrent(generation, session) ? "ready" : "stale";
|
|
532905
534105
|
} catch {
|
|
@@ -532981,7 +534181,8 @@ var PersonalMemoryController = class {
|
|
|
532981
534181
|
await this.dependencies.bindTools(session, this.host.harness, {
|
|
532982
534182
|
binding,
|
|
532983
534183
|
client,
|
|
532984
|
-
localHistory: this.host.harness
|
|
534184
|
+
localHistory: this.host.harness,
|
|
534185
|
+
accountMemory: this.host.accountMemoryRuntime
|
|
532985
534186
|
});
|
|
532986
534187
|
return "ready";
|
|
532987
534188
|
} catch {
|
|
@@ -535804,7 +537005,10 @@ var SessionEventHandler = class {
|
|
|
535804
537005
|
this.showPendingCompactionRetry();
|
|
535805
537006
|
this.goalCompletionTurnEnded = true;
|
|
535806
537007
|
this.scheduleQueuedGoalPromotion();
|
|
535807
|
-
if (event.reason === "completed")
|
|
537008
|
+
if (event.reason === "completed") {
|
|
537009
|
+
this.host.refreshManagedQuotaWindows();
|
|
537010
|
+
this.host.recordAccountMemoryTurn?.(event);
|
|
537011
|
+
}
|
|
535808
537012
|
}
|
|
535809
537013
|
handleStepBegin(event) {
|
|
535810
537014
|
this.host.commitQueuedSteerAtStepStart(event.turnId);
|
|
@@ -543069,6 +544273,7 @@ var BlunTUI = class {
|
|
|
543069
544273
|
editorKeyboard;
|
|
543070
544274
|
scrollbackController;
|
|
543071
544275
|
personalMemoryController;
|
|
544276
|
+
accountMemoryRuntime;
|
|
543072
544277
|
customerMistakeController;
|
|
543073
544278
|
managedQuotaWarningController;
|
|
543074
544279
|
managedQuotaWarningPersistence = Promise.resolve();
|
|
@@ -543153,6 +544358,7 @@ var BlunTUI = class {
|
|
|
543153
544358
|
this.loopCountdown = new LoopCountdownController(() => this.state.ui.requestRender());
|
|
543154
544359
|
this.authFlow = new AuthFlowController(this);
|
|
543155
544360
|
this.personalMemoryController = new PersonalMemoryController(this);
|
|
544361
|
+
this.accountMemoryRuntime = createTuiAccountMemoryRuntime(harness);
|
|
543156
544362
|
this.customerMistakeController = new CustomerMistakeHostController();
|
|
543157
544363
|
this.btwPanelController = new BtwPanelController(this);
|
|
543158
544364
|
this.sessionEventHandler = new SessionEventHandler(this);
|
|
@@ -544846,6 +546052,15 @@ var BlunTUI = class {
|
|
|
544846
546052
|
refreshManagedQuotaWindows() {
|
|
544847
546053
|
this.authFlow.refreshManagedQuotaWindows();
|
|
544848
546054
|
}
|
|
546055
|
+
recordAccountMemoryTurn(event) {
|
|
546056
|
+
const session = this.session;
|
|
546057
|
+
const sessionDir = session?.summary?.sessionDir;
|
|
546058
|
+
if (session === void 0 || sessionDir === void 0) return;
|
|
546059
|
+
this.accountMemoryRuntime?.captureCompletedTurn({
|
|
546060
|
+
id: session.id,
|
|
546061
|
+
sessionDir
|
|
546062
|
+
}, event.turnId).catch(() => {});
|
|
546063
|
+
}
|
|
544849
546064
|
async refreshPersonalMemory(promptIfNeverAsked = false) {
|
|
544850
546065
|
await this.personalMemoryController.refresh({ promptIfNeverAsked });
|
|
544851
546066
|
}
|
|
@@ -544987,6 +546202,7 @@ var BlunTUI = class {
|
|
|
544987
546202
|
await this.refreshManagedImageReaderAvailability(session);
|
|
544988
546203
|
await this.authFlow.applyManagedAccountContextToSession();
|
|
544989
546204
|
await this.personalMemoryController.refresh();
|
|
546205
|
+
this.accountMemoryRuntime?.retryPending().catch(() => {});
|
|
544990
546206
|
this.telegramSessionScope = queueScope;
|
|
544991
546207
|
this.telegramChannel?.bindSessionQueue(queueScope);
|
|
544992
546208
|
if (selectionScope !== void 0 && this.session === session) {
|
|
@@ -545270,6 +546486,7 @@ var BlunTUI = class {
|
|
|
545270
546486
|
this.registerSessionHandlers(session);
|
|
545271
546487
|
await this.refreshManagedImageReaderAvailability(session);
|
|
545272
546488
|
await this.personalMemoryController.refresh();
|
|
546489
|
+
this.accountMemoryRuntime?.retryPending().catch(() => {});
|
|
545273
546490
|
await this.syncRuntimeState(session);
|
|
545274
546491
|
this.updateTerminalTitle();
|
|
545275
546492
|
try {
|