@sanctuary-framework/mcp-server 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1607 -45
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1607 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1580 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +543 -5
- package/dist/index.d.ts +543 -5
- package/dist/index.js +1580 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5037,7 +5037,8 @@ var init_constants = __esm({
|
|
|
5037
5037
|
RESERVED_EVENT_TYPE_PREFIXES = [
|
|
5038
5038
|
"EXTENSION_",
|
|
5039
5039
|
"cross_fortress_",
|
|
5040
|
-
"multi_master_"
|
|
5040
|
+
"multi_master_",
|
|
5041
|
+
"cross_harness_approval_"
|
|
5041
5042
|
];
|
|
5042
5043
|
RESERVED_EXTENSION_ENVELOPE_KEYS = [
|
|
5043
5044
|
"cross_fortress_read_grant",
|
|
@@ -9229,9 +9230,9 @@ function fingerprintDID(did) {
|
|
|
9229
9230
|
return `${raw.slice(0, 6)}\u2026${raw.slice(-6)}`;
|
|
9230
9231
|
}
|
|
9231
9232
|
function countInjectionsToday(audit) {
|
|
9232
|
-
const
|
|
9233
|
-
|
|
9234
|
-
const cutoff =
|
|
9233
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9234
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9235
|
+
const cutoff = startOfDay2.getTime();
|
|
9235
9236
|
return audit.filter((e) => {
|
|
9236
9237
|
const ts = new Date(e.timestamp).getTime();
|
|
9237
9238
|
if (isNaN(ts) || ts < cutoff) return false;
|
|
@@ -9240,9 +9241,9 @@ function countInjectionsToday(audit) {
|
|
|
9240
9241
|
}).length;
|
|
9241
9242
|
}
|
|
9242
9243
|
function countProofsToday(audit) {
|
|
9243
|
-
const
|
|
9244
|
-
|
|
9245
|
-
const cutoff =
|
|
9244
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9245
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9246
|
+
const cutoff = startOfDay2.getTime();
|
|
9246
9247
|
return audit.filter((e) => {
|
|
9247
9248
|
if (e.layer !== "l3") return false;
|
|
9248
9249
|
if (!PROOF_CREATION_OPS.has(e.operation)) return false;
|
|
@@ -17211,6 +17212,45 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17211
17212
|
await handleStream2(deps, res);
|
|
17212
17213
|
return true;
|
|
17213
17214
|
}
|
|
17215
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/revision`) {
|
|
17216
|
+
const revision = await deps.aggregator.getRevision();
|
|
17217
|
+
writeJSON4(res, 200, { ok: true, data: { revision } });
|
|
17218
|
+
return true;
|
|
17219
|
+
}
|
|
17220
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/sync`) {
|
|
17221
|
+
const sinceRaw = url.searchParams.get("since_revision");
|
|
17222
|
+
const sinceParsed = sinceRaw === null ? 0 : Number.parseInt(sinceRaw, 10);
|
|
17223
|
+
const sinceRevision = Number.isFinite(sinceParsed) && sinceParsed >= 0 ? sinceParsed : 0;
|
|
17224
|
+
const limit = parseLimit2(
|
|
17225
|
+
url.searchParams.get("limit"),
|
|
17226
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17227
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17228
|
+
);
|
|
17229
|
+
const delta = await deps.aggregator.getSync({ sinceRevision, limit });
|
|
17230
|
+
writeJSON4(res, 200, { ok: true, data: delta });
|
|
17231
|
+
return true;
|
|
17232
|
+
}
|
|
17233
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/history`) {
|
|
17234
|
+
const limit = parseLimit2(
|
|
17235
|
+
url.searchParams.get("limit"),
|
|
17236
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17237
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17238
|
+
);
|
|
17239
|
+
const statusRaw = url.searchParams.get("status");
|
|
17240
|
+
const sinceTs = url.searchParams.get("since") ?? void 0;
|
|
17241
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17242
|
+
const filterStatus = statusRaw && isStatusFilter(statusRaw) && statusRaw !== "pending" ? statusRaw : void 0;
|
|
17243
|
+
const entries = await deps.aggregator.getHistory(
|
|
17244
|
+
{
|
|
17245
|
+
limit,
|
|
17246
|
+
...filterStatus !== void 0 ? { status: filterStatus } : {},
|
|
17247
|
+
...sinceTs !== void 0 ? { sinceTs } : {}
|
|
17248
|
+
},
|
|
17249
|
+
operatorId
|
|
17250
|
+
);
|
|
17251
|
+
writeJSON4(res, 200, { ok: true, data: { entries } });
|
|
17252
|
+
return true;
|
|
17253
|
+
}
|
|
17214
17254
|
if (method === "GET" && path === APPROVAL_INBOX_API_PREFIX) {
|
|
17215
17255
|
const limit = parseLimit2(
|
|
17216
17256
|
url.searchParams.get("limit"),
|
|
@@ -17233,11 +17273,39 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17233
17273
|
writeJSON4(res, 404, { ok: false, error: "not_found", path });
|
|
17234
17274
|
return true;
|
|
17235
17275
|
}
|
|
17236
|
-
if (method === "GET" && entryMatch.action ===
|
|
17237
|
-
const
|
|
17238
|
-
|
|
17239
|
-
(
|
|
17276
|
+
if (method === "GET" && entryMatch.action === "audit-trail") {
|
|
17277
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17278
|
+
if (!entry) {
|
|
17279
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17280
|
+
return true;
|
|
17281
|
+
}
|
|
17282
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17283
|
+
const trail = await deps.aggregator.getAuditTrail(
|
|
17284
|
+
entryMatch.aggregatorId,
|
|
17285
|
+
operatorId
|
|
17240
17286
|
);
|
|
17287
|
+
writeJSON4(res, 200, { ok: true, data: { entry, audit_trail: trail } });
|
|
17288
|
+
return true;
|
|
17289
|
+
}
|
|
17290
|
+
if (method === "GET" && entryMatch.action === "payload") {
|
|
17291
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17292
|
+
if (!entry) {
|
|
17293
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17294
|
+
return true;
|
|
17295
|
+
}
|
|
17296
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17297
|
+
const payload = await deps.aggregator.getFullPayloadWithAudit(
|
|
17298
|
+
entryMatch.aggregatorId,
|
|
17299
|
+
operatorId
|
|
17300
|
+
);
|
|
17301
|
+
writeJSON4(res, 200, {
|
|
17302
|
+
ok: true,
|
|
17303
|
+
data: { entry, request_payload: payload }
|
|
17304
|
+
});
|
|
17305
|
+
return true;
|
|
17306
|
+
}
|
|
17307
|
+
if (method === "GET" && entryMatch.action === null) {
|
|
17308
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17241
17309
|
if (!entry) {
|
|
17242
17310
|
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17243
17311
|
return true;
|
|
@@ -20271,7 +20339,10 @@ var init_approval_aggregator = __esm({
|
|
|
20271
20339
|
APPROVAL_AGGREGATOR_AUDIT_OPS = {
|
|
20272
20340
|
AGGREGATED: "cross_harness_approval_aggregated",
|
|
20273
20341
|
RESOLVED: "cross_harness_approval_resolved",
|
|
20274
|
-
DEDUPED: "cross_harness_approval_deduped"
|
|
20342
|
+
DEDUPED: "cross_harness_approval_deduped",
|
|
20343
|
+
PAYLOAD_DECRYPTED: "cross_harness_approval_payload_decrypted",
|
|
20344
|
+
AUDIT_TRAIL_VIEWED: "cross_harness_approval_audit_trail_viewed",
|
|
20345
|
+
REPLAYED: "cross_harness_approval_replayed"
|
|
20275
20346
|
};
|
|
20276
20347
|
DEFAULT_PENDING_TTL_MS = 5 * 60 * 1e3;
|
|
20277
20348
|
DEFAULT_MAX_LIST_LIMIT = 200;
|
|
@@ -20287,6 +20358,8 @@ var init_approval_aggregator = __esm({
|
|
|
20287
20358
|
now;
|
|
20288
20359
|
resolveSourceContext;
|
|
20289
20360
|
resolveHubInboxItemId;
|
|
20361
|
+
payloadStore;
|
|
20362
|
+
resolveEnforcementChain;
|
|
20290
20363
|
/** Cached entries by `aggregator_id`. */
|
|
20291
20364
|
entries = /* @__PURE__ */ new Map();
|
|
20292
20365
|
/** Dedup index: `${harness}|${agent}|${audit_id}` -> aggregator_id. */
|
|
@@ -20299,6 +20372,20 @@ var init_approval_aggregator = __esm({
|
|
|
20299
20372
|
hydrated = false;
|
|
20300
20373
|
/** Active SSE listeners. */
|
|
20301
20374
|
listeners = /* @__PURE__ */ new Set();
|
|
20375
|
+
/**
|
|
20376
|
+
* Monotonic revision counter, bumped on every mutation (ingest of new
|
|
20377
|
+
* entry, resolve, expire, delete). Hydrated from max(last_modified_revision)
|
|
20378
|
+
* across persisted entries on first read; in-memory after that. v1.3
|
|
20379
|
+
* Upsilon-4.
|
|
20380
|
+
*/
|
|
20381
|
+
currentRevision = 0;
|
|
20382
|
+
/**
|
|
20383
|
+
* Removal tombstones: aggregator_id -> revision at removal. Used by the
|
|
20384
|
+
* sync API to surface "removed" entries to mobile consumers between
|
|
20385
|
+
* polls. In-memory only; server restart clears tombstones (mobile
|
|
20386
|
+
* bootstraps via `list()` on reconnect). v1.3 Upsilon-4.
|
|
20387
|
+
*/
|
|
20388
|
+
removedTombstones = /* @__PURE__ */ new Map();
|
|
20302
20389
|
constructor(deps) {
|
|
20303
20390
|
this.storage = deps.storage;
|
|
20304
20391
|
this.encryptionKey = derivePurposeKey(
|
|
@@ -20316,6 +20403,14 @@ var init_approval_aggregator = __esm({
|
|
|
20316
20403
|
source_agent_id: this.fortressId
|
|
20317
20404
|
}));
|
|
20318
20405
|
this.resolveHubInboxItemId = deps.resolveHubInboxItemId ?? ((_event) => void 0);
|
|
20406
|
+
this.payloadStore = deps.payloadStore ?? null;
|
|
20407
|
+
this.resolveEnforcementChain = deps.resolveEnforcementChain ?? ((event) => [
|
|
20408
|
+
{
|
|
20409
|
+
layer: "l2",
|
|
20410
|
+
event: `approval_required:${event.operation}`,
|
|
20411
|
+
timestamp: event.request_timestamp
|
|
20412
|
+
}
|
|
20413
|
+
]);
|
|
20319
20414
|
}
|
|
20320
20415
|
/**
|
|
20321
20416
|
* Subscribe an event listener. Returns an unsubscribe fn. SSE handlers
|
|
@@ -20325,6 +20420,113 @@ var init_approval_aggregator = __esm({
|
|
|
20325
20420
|
this.listeners.add(listener);
|
|
20326
20421
|
return () => this.listeners.delete(listener);
|
|
20327
20422
|
}
|
|
20423
|
+
/**
|
|
20424
|
+
* Current aggregator revision. v1.3 Upsilon-4. Mobile companions
|
|
20425
|
+
* poll the lightweight `/revision` route to detect that something
|
|
20426
|
+
* changed before fetching a full sync delta.
|
|
20427
|
+
*/
|
|
20428
|
+
async getRevision() {
|
|
20429
|
+
await this.hydrate();
|
|
20430
|
+
return this.currentRevision;
|
|
20431
|
+
}
|
|
20432
|
+
/**
|
|
20433
|
+
* Compute a delta since `sinceRevision`. v1.3 Upsilon-4. Mobile
|
|
20434
|
+
* clients poll this for cheap state-sync. Behavior:
|
|
20435
|
+
* - `added`: entries whose `created_at_revision > sinceRevision`.
|
|
20436
|
+
* - `changed`: entries that existed at `sinceRevision` but had a
|
|
20437
|
+
* status transition (resolve, expire) since.
|
|
20438
|
+
* - `removed`: aggregator_ids deleted after `sinceRevision`.
|
|
20439
|
+
* - `revision`: current aggregator revision; pass this back as
|
|
20440
|
+
* `sinceRevision` on the next call.
|
|
20441
|
+
*
|
|
20442
|
+
* `limit` caps the total count returned across all three lists,
|
|
20443
|
+
* prioritized as added -> changed -> removed (newer-state first).
|
|
20444
|
+
* When more changes exist than fit, the next call with the returned
|
|
20445
|
+
* revision will pick up the rest because each entry's
|
|
20446
|
+
* last_modified_revision is unchanged by truncation.
|
|
20447
|
+
*/
|
|
20448
|
+
async getSync(opts) {
|
|
20449
|
+
await this.hydrate();
|
|
20450
|
+
await this.expireStale();
|
|
20451
|
+
const sinceRevision = opts?.sinceRevision ?? 0;
|
|
20452
|
+
const cap = Math.min(
|
|
20453
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20454
|
+
this.maxListLimit
|
|
20455
|
+
);
|
|
20456
|
+
const added = [];
|
|
20457
|
+
const changed = [];
|
|
20458
|
+
for (const entry of this.entries.values()) {
|
|
20459
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20460
|
+
if (lastMod <= sinceRevision) continue;
|
|
20461
|
+
const createdRev = entry.created_at_revision ?? 0;
|
|
20462
|
+
if (createdRev > sinceRevision) {
|
|
20463
|
+
added.push(entry);
|
|
20464
|
+
} else {
|
|
20465
|
+
changed.push(entry);
|
|
20466
|
+
}
|
|
20467
|
+
}
|
|
20468
|
+
const removed = [];
|
|
20469
|
+
for (const [id, rev] of this.removedTombstones) {
|
|
20470
|
+
if (rev > sinceRevision) removed.push(id);
|
|
20471
|
+
}
|
|
20472
|
+
added.sort(
|
|
20473
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20474
|
+
);
|
|
20475
|
+
changed.sort(
|
|
20476
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20477
|
+
);
|
|
20478
|
+
let remaining = cap;
|
|
20479
|
+
const addedOut = added.slice(0, Math.max(0, remaining));
|
|
20480
|
+
remaining -= addedOut.length;
|
|
20481
|
+
const changedOut = changed.slice(0, Math.max(0, remaining));
|
|
20482
|
+
remaining -= changedOut.length;
|
|
20483
|
+
const removedOut = removed.slice(0, Math.max(0, remaining));
|
|
20484
|
+
return {
|
|
20485
|
+
revision: this.currentRevision,
|
|
20486
|
+
added: addedOut,
|
|
20487
|
+
changed: changedOut,
|
|
20488
|
+
removed: removedOut
|
|
20489
|
+
};
|
|
20490
|
+
}
|
|
20491
|
+
/**
|
|
20492
|
+
* Delete an entry. Drops the in-memory record, the persisted bundle,
|
|
20493
|
+
* and the at-rest payload (if a payload store is wired). Records a
|
|
20494
|
+
* tombstone with the new revision so sync-API consumers see a
|
|
20495
|
+
* `removed` delta. Returns true when an entry was deleted, false on
|
|
20496
|
+
* unknown id. v1.3 Upsilon-4. Reserved for v1.4+ retention housekeeping;
|
|
20497
|
+
* Upsilon-4 ships the surface so mobile sync-API tests can exercise the
|
|
20498
|
+
* removal path.
|
|
20499
|
+
*/
|
|
20500
|
+
async deleteEntry(aggregatorId) {
|
|
20501
|
+
await this.hydrate();
|
|
20502
|
+
const entry = this.entries.get(aggregatorId);
|
|
20503
|
+
if (!entry) return false;
|
|
20504
|
+
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20505
|
+
this.entries.delete(aggregatorId);
|
|
20506
|
+
this.dedupIndex.delete(dedupKey);
|
|
20507
|
+
this.fullPayloads.delete(aggregatorId);
|
|
20508
|
+
for (const [corr, id] of this.correlationIndex) {
|
|
20509
|
+
if (id === aggregatorId) this.correlationIndex.delete(corr);
|
|
20510
|
+
}
|
|
20511
|
+
try {
|
|
20512
|
+
await this.storage.delete(APPROVAL_AGGREGATOR_NAMESPACE, aggregatorId);
|
|
20513
|
+
} catch {
|
|
20514
|
+
}
|
|
20515
|
+
if (this.payloadStore) {
|
|
20516
|
+
try {
|
|
20517
|
+
await this.payloadStore.deletePayload(aggregatorId);
|
|
20518
|
+
} catch {
|
|
20519
|
+
}
|
|
20520
|
+
}
|
|
20521
|
+
const revision = this.nextRevision();
|
|
20522
|
+
this.removedTombstones.set(aggregatorId, revision);
|
|
20523
|
+
this.emit({ type: "removed", entry: { ...entry } });
|
|
20524
|
+
return true;
|
|
20525
|
+
}
|
|
20526
|
+
nextRevision() {
|
|
20527
|
+
this.currentRevision += 1;
|
|
20528
|
+
return this.currentRevision;
|
|
20529
|
+
}
|
|
20328
20530
|
/**
|
|
20329
20531
|
* Ingest a gate event. Returns the aggregator entry on first sight,
|
|
20330
20532
|
* `null` when deduped. Resolution events update the existing record;
|
|
@@ -20366,13 +20568,152 @@ var init_approval_aggregator = __esm({
|
|
|
20366
20568
|
}
|
|
20367
20569
|
/**
|
|
20368
20570
|
* Return the original (unhashed) request payload for the entry. Returns
|
|
20369
|
-
* `null` when the entry is unknown
|
|
20370
|
-
*
|
|
20571
|
+
* `null` when the entry is unknown. When the in-memory payload map has
|
|
20572
|
+
* been evicted (e.g. after a server restart) and a `payloadStore` was
|
|
20573
|
+
* provided, the at-rest bundle is decrypted and the in-memory map is
|
|
20574
|
+
* refilled. Audit emission lives on the `*WithAudit` variant; this base
|
|
20575
|
+
* accessor is silent so internal callers can read without polluting the
|
|
20576
|
+
* audit trail.
|
|
20371
20577
|
*/
|
|
20372
20578
|
async getFullPayload(aggregatorId) {
|
|
20373
20579
|
await this.hydrate();
|
|
20374
20580
|
if (!this.entries.has(aggregatorId)) return null;
|
|
20375
|
-
|
|
20581
|
+
const cached = this.fullPayloads.get(aggregatorId);
|
|
20582
|
+
if (cached !== void 0) return cached;
|
|
20583
|
+
if (this.payloadStore) {
|
|
20584
|
+
try {
|
|
20585
|
+
const restored = await this.payloadStore.loadPayload(aggregatorId);
|
|
20586
|
+
if (restored !== null) {
|
|
20587
|
+
this.fullPayloads.set(aggregatorId, restored);
|
|
20588
|
+
return restored;
|
|
20589
|
+
}
|
|
20590
|
+
} catch {
|
|
20591
|
+
}
|
|
20592
|
+
}
|
|
20593
|
+
return null;
|
|
20594
|
+
}
|
|
20595
|
+
/**
|
|
20596
|
+
* Return the entry record for the given id, or null when unknown.
|
|
20597
|
+
* Idempotent. v1.3 Upsilon-3.
|
|
20598
|
+
*/
|
|
20599
|
+
async getEntry(aggregatorId) {
|
|
20600
|
+
await this.hydrate();
|
|
20601
|
+
return this.entries.get(aggregatorId) ?? null;
|
|
20602
|
+
}
|
|
20603
|
+
/**
|
|
20604
|
+
* Audited variant of `getFullPayload`. Emits the
|
|
20605
|
+
* `cross_harness_approval_payload_decrypted` audit event before
|
|
20606
|
+
* returning. Used by the operator-facing /payload replay route.
|
|
20607
|
+
* v1.3 Upsilon-3.
|
|
20608
|
+
*/
|
|
20609
|
+
async getFullPayloadWithAudit(aggregatorId, operatorId) {
|
|
20610
|
+
const payload = await this.getFullPayload(aggregatorId);
|
|
20611
|
+
if (payload === null) return null;
|
|
20612
|
+
const entry = this.entries.get(aggregatorId);
|
|
20613
|
+
this.auditLog.append(
|
|
20614
|
+
"l2",
|
|
20615
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.PAYLOAD_DECRYPTED,
|
|
20616
|
+
operatorId,
|
|
20617
|
+
{
|
|
20618
|
+
aggregator_id: aggregatorId,
|
|
20619
|
+
...entry ? {
|
|
20620
|
+
source_harness: entry.source_harness,
|
|
20621
|
+
source_agent_id: entry.source_agent_id,
|
|
20622
|
+
entry_status: entry.status
|
|
20623
|
+
} : {}
|
|
20624
|
+
}
|
|
20625
|
+
);
|
|
20626
|
+
return payload;
|
|
20627
|
+
}
|
|
20628
|
+
/**
|
|
20629
|
+
* Return the audit-log entries that led to and surround this approval.
|
|
20630
|
+
* Best-effort matching: aggregator-side emissions (AGGREGATED, RESOLVED,
|
|
20631
|
+
* DEDUPED, replay events) all carry `details.aggregator_id` and link
|
|
20632
|
+
* directly. Gate-side emissions (`gate_*:operation`) do not carry the
|
|
20633
|
+
* aggregator id at v1.3, so they are matched via timestamp window
|
|
20634
|
+
* (entry.created_at to entry.resolved_at + 1s, or expires_at + 1s while
|
|
20635
|
+
* pending) and operation suffix. Emits AUDIT_TRAIL_VIEWED on call.
|
|
20636
|
+
* v1.3 Upsilon-3.
|
|
20637
|
+
*/
|
|
20638
|
+
async getAuditTrail(aggregatorId, operatorId) {
|
|
20639
|
+
await this.hydrate();
|
|
20640
|
+
const entry = this.entries.get(aggregatorId);
|
|
20641
|
+
if (!entry) {
|
|
20642
|
+
return [];
|
|
20643
|
+
}
|
|
20644
|
+
const sinceMs = Date.parse(entry.created_at) - 1e3;
|
|
20645
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
20646
|
+
const queried = await this.auditLog.query({ since: sinceIso, limit: 1e3 });
|
|
20647
|
+
const operationPart = entry.policy_rule_id.includes(":") ? entry.policy_rule_id.slice(entry.policy_rule_id.indexOf(":") + 1) : entry.policy_rule_id;
|
|
20648
|
+
const lifetimeStart = sinceMs;
|
|
20649
|
+
const lifetimeEnd = entry.resolved_at ? Date.parse(entry.resolved_at) + 1e3 : Date.parse(entry.expires_at) + 1e3;
|
|
20650
|
+
const matches = [];
|
|
20651
|
+
for (const audit of queried.entries) {
|
|
20652
|
+
const detailsId = audit.details !== void 0 ? audit.details["aggregator_id"] : void 0;
|
|
20653
|
+
if (detailsId === aggregatorId) {
|
|
20654
|
+
matches.push(audit);
|
|
20655
|
+
continue;
|
|
20656
|
+
}
|
|
20657
|
+
const auditMs = Date.parse(audit.timestamp);
|
|
20658
|
+
if (auditMs < lifetimeStart || auditMs > lifetimeEnd) continue;
|
|
20659
|
+
if (audit.operation.endsWith(`:${operationPart}`)) {
|
|
20660
|
+
matches.push(audit);
|
|
20661
|
+
}
|
|
20662
|
+
}
|
|
20663
|
+
matches.sort(
|
|
20664
|
+
(a, b) => a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0
|
|
20665
|
+
);
|
|
20666
|
+
this.auditLog.append(
|
|
20667
|
+
"l2",
|
|
20668
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.AUDIT_TRAIL_VIEWED,
|
|
20669
|
+
operatorId,
|
|
20670
|
+
{
|
|
20671
|
+
aggregator_id: aggregatorId,
|
|
20672
|
+
entry_status: entry.status,
|
|
20673
|
+
match_count: matches.length
|
|
20674
|
+
}
|
|
20675
|
+
);
|
|
20676
|
+
return matches;
|
|
20677
|
+
}
|
|
20678
|
+
/**
|
|
20679
|
+
* List historical (resolved) approvals. Excludes pending entries by
|
|
20680
|
+
* design: `list()` is the pending-inbox surface and `getHistory()` is
|
|
20681
|
+
* the resolved-replay surface. Emits REPLAYED on each call. v1.3
|
|
20682
|
+
* Upsilon-3.
|
|
20683
|
+
*/
|
|
20684
|
+
async getHistory(opts, operatorId) {
|
|
20685
|
+
await this.hydrate();
|
|
20686
|
+
await this.expireStale();
|
|
20687
|
+
const limit = Math.min(
|
|
20688
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20689
|
+
this.maxListLimit
|
|
20690
|
+
);
|
|
20691
|
+
const sinceMs = opts?.sinceTs ? Date.parse(opts.sinceTs) : Number.NEGATIVE_INFINITY;
|
|
20692
|
+
const matching = [];
|
|
20693
|
+
for (const entry of this.entries.values()) {
|
|
20694
|
+
if (entry.status === "pending") continue;
|
|
20695
|
+
if (opts?.status && entry.status !== opts.status) continue;
|
|
20696
|
+
const stamp = Date.parse(entry.resolved_at ?? entry.created_at);
|
|
20697
|
+
if (stamp < sinceMs) continue;
|
|
20698
|
+
matching.push(entry);
|
|
20699
|
+
}
|
|
20700
|
+
matching.sort((a, b) => {
|
|
20701
|
+
const aStamp = a.resolved_at ?? a.created_at;
|
|
20702
|
+
const bStamp = b.resolved_at ?? b.created_at;
|
|
20703
|
+
return bStamp.localeCompare(aStamp);
|
|
20704
|
+
});
|
|
20705
|
+
const sliced = matching.slice(0, limit);
|
|
20706
|
+
this.auditLog.append(
|
|
20707
|
+
"l2",
|
|
20708
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.REPLAYED,
|
|
20709
|
+
operatorId,
|
|
20710
|
+
{
|
|
20711
|
+
result_count: sliced.length,
|
|
20712
|
+
...opts?.status !== void 0 ? { status_filter: opts.status } : {},
|
|
20713
|
+
...opts?.sinceTs !== void 0 ? { since: opts.sinceTs } : {}
|
|
20714
|
+
}
|
|
20715
|
+
);
|
|
20716
|
+
return sliced;
|
|
20376
20717
|
}
|
|
20377
20718
|
/**
|
|
20378
20719
|
* Resolve an entry. Used by both:
|
|
@@ -20396,6 +20737,7 @@ var init_approval_aggregator = __esm({
|
|
|
20396
20737
|
entry.status = decision;
|
|
20397
20738
|
entry.resolved_at = this.now().toISOString();
|
|
20398
20739
|
entry.resolved_by = operatorId;
|
|
20740
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20399
20741
|
await this.persist(entry);
|
|
20400
20742
|
this.auditLog.append(
|
|
20401
20743
|
"l2",
|
|
@@ -20446,6 +20788,8 @@ var init_approval_aggregator = __esm({
|
|
|
20446
20788
|
const now = this.now();
|
|
20447
20789
|
const expires = new Date(now.getTime() + this.pendingTtlMs);
|
|
20448
20790
|
const hubInboxId = this.resolveHubInboxItemId(event);
|
|
20791
|
+
const enforcementChain = this.resolveEnforcementChain(event);
|
|
20792
|
+
const revision = this.nextRevision();
|
|
20449
20793
|
const entry = {
|
|
20450
20794
|
aggregator_id: id,
|
|
20451
20795
|
source_harness: ctx.source_harness,
|
|
@@ -20457,13 +20801,22 @@ var init_approval_aggregator = __esm({
|
|
|
20457
20801
|
status: "pending",
|
|
20458
20802
|
created_at: now.toISOString(),
|
|
20459
20803
|
expires_at: expires.toISOString(),
|
|
20460
|
-
|
|
20804
|
+
created_at_revision: revision,
|
|
20805
|
+
last_modified_revision: revision,
|
|
20806
|
+
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {},
|
|
20807
|
+
...enforcementChain.length > 0 ? { enforcement_chain: enforcementChain } : {}
|
|
20461
20808
|
};
|
|
20462
20809
|
this.entries.set(id, entry);
|
|
20463
20810
|
this.dedupIndex.set(dedupKey, id);
|
|
20464
20811
|
this.correlationIndex.set(event.correlation_id, id);
|
|
20465
20812
|
this.fullPayloads.set(id, event.context);
|
|
20466
20813
|
await this.persist(entry);
|
|
20814
|
+
if (this.payloadStore) {
|
|
20815
|
+
try {
|
|
20816
|
+
await this.payloadStore.savePayload(id, event.context);
|
|
20817
|
+
} catch {
|
|
20818
|
+
}
|
|
20819
|
+
}
|
|
20467
20820
|
this.auditLog.append(
|
|
20468
20821
|
"l2",
|
|
20469
20822
|
APPROVAL_AGGREGATOR_AUDIT_OPS.AGGREGATED,
|
|
@@ -20492,6 +20845,7 @@ var init_approval_aggregator = __esm({
|
|
|
20492
20845
|
entry.status = status;
|
|
20493
20846
|
entry.resolved_at = event.resolution.decided_at;
|
|
20494
20847
|
entry.resolved_by = event.resolution.decided_by;
|
|
20848
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20495
20849
|
await this.persist(entry);
|
|
20496
20850
|
this.auditLog.append(
|
|
20497
20851
|
"l2",
|
|
@@ -20554,6 +20908,7 @@ var init_approval_aggregator = __esm({
|
|
|
20554
20908
|
entry.status = "expired";
|
|
20555
20909
|
entry.resolved_at = this.now().toISOString();
|
|
20556
20910
|
entry.resolved_by = "system_ttl";
|
|
20911
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20557
20912
|
await this.persist(entry);
|
|
20558
20913
|
this.auditLog.append(
|
|
20559
20914
|
"l2",
|
|
@@ -20600,6 +20955,10 @@ var init_approval_aggregator = __esm({
|
|
|
20600
20955
|
this.entries.set(entry.aggregator_id, entry);
|
|
20601
20956
|
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20602
20957
|
this.dedupIndex.set(dedupKey, entry.aggregator_id);
|
|
20958
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20959
|
+
if (lastMod > this.currentRevision) {
|
|
20960
|
+
this.currentRevision = lastMod;
|
|
20961
|
+
}
|
|
20603
20962
|
} catch {
|
|
20604
20963
|
}
|
|
20605
20964
|
}
|
|
@@ -20779,6 +21138,149 @@ var init_aggregator_backed_channel = __esm({
|
|
|
20779
21138
|
}
|
|
20780
21139
|
});
|
|
20781
21140
|
|
|
21141
|
+
// src/principal-policy/aggregator-store.ts
|
|
21142
|
+
function payloadKey(aggregatorId) {
|
|
21143
|
+
return `${AGGREGATOR_PAYLOAD_KEY_PREFIX}${aggregatorId}`;
|
|
21144
|
+
}
|
|
21145
|
+
function stripKeyPrefix(key) {
|
|
21146
|
+
if (!key.startsWith(AGGREGATOR_PAYLOAD_KEY_PREFIX)) return null;
|
|
21147
|
+
return key.slice(AGGREGATOR_PAYLOAD_KEY_PREFIX.length);
|
|
21148
|
+
}
|
|
21149
|
+
var AGGREGATOR_PAYLOAD_NAMESPACE, AGGREGATOR_PAYLOAD_KEY_PREFIX, HKDF_INFO, DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS, MAX_BUNDLE_BYTES2, AggregatorPayloadStore;
|
|
21150
|
+
var init_aggregator_store = __esm({
|
|
21151
|
+
"src/principal-policy/aggregator-store.ts"() {
|
|
21152
|
+
init_encryption();
|
|
21153
|
+
init_key_derivation();
|
|
21154
|
+
init_encoding();
|
|
21155
|
+
AGGREGATOR_PAYLOAD_NAMESPACE = "_approval_aggregator_payloads";
|
|
21156
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX = "payload.";
|
|
21157
|
+
HKDF_INFO = "l2-approval-aggregator-payload-v1";
|
|
21158
|
+
DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS = 30;
|
|
21159
|
+
MAX_BUNDLE_BYTES2 = 4 * 1024 * 1024;
|
|
21160
|
+
AggregatorPayloadStore = class {
|
|
21161
|
+
storage;
|
|
21162
|
+
encryptionKey;
|
|
21163
|
+
fortressId;
|
|
21164
|
+
retentionDays;
|
|
21165
|
+
constructor(opts) {
|
|
21166
|
+
this.storage = opts.storage;
|
|
21167
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO);
|
|
21168
|
+
this.fortressId = opts.fortressId;
|
|
21169
|
+
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS;
|
|
21170
|
+
}
|
|
21171
|
+
/**
|
|
21172
|
+
* Persist `payload` under the given aggregator_id. Idempotent; calling
|
|
21173
|
+
* twice with the same id rewrites the bundle (retention_until is
|
|
21174
|
+
* recomputed). Returns the bundle's retention_until ISO-8601 timestamp
|
|
21175
|
+
* so callers can log it.
|
|
21176
|
+
*/
|
|
21177
|
+
async savePayload(aggregatorId, payload) {
|
|
21178
|
+
const now = /* @__PURE__ */ new Date();
|
|
21179
|
+
const retentionMs = this.retentionDays * 24 * 60 * 60 * 1e3;
|
|
21180
|
+
const retentionUntil = new Date(now.getTime() + retentionMs);
|
|
21181
|
+
const bundle = {
|
|
21182
|
+
version: 1,
|
|
21183
|
+
aggregator_id: aggregatorId,
|
|
21184
|
+
fortress_id: this.fortressId,
|
|
21185
|
+
created_at: now.toISOString(),
|
|
21186
|
+
retention_until: retentionUntil.toISOString(),
|
|
21187
|
+
payload
|
|
21188
|
+
};
|
|
21189
|
+
const aad = stringToBytes(aggregatorId);
|
|
21190
|
+
const plaintext = stringToBytes(JSON.stringify(bundle));
|
|
21191
|
+
const envelope = encrypt(plaintext, this.encryptionKey, aad);
|
|
21192
|
+
await this.storage.write(
|
|
21193
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21194
|
+
payloadKey(aggregatorId),
|
|
21195
|
+
stringToBytes(JSON.stringify(envelope))
|
|
21196
|
+
);
|
|
21197
|
+
return bundle.retention_until;
|
|
21198
|
+
}
|
|
21199
|
+
/**
|
|
21200
|
+
* Read the persisted payload for the aggregator_id. Returns null if no
|
|
21201
|
+
* bundle exists, the bundle is corrupted, or AAD binding fails.
|
|
21202
|
+
*/
|
|
21203
|
+
async loadPayload(aggregatorId) {
|
|
21204
|
+
const key = payloadKey(aggregatorId);
|
|
21205
|
+
let raw;
|
|
21206
|
+
try {
|
|
21207
|
+
raw = await this.storage.read(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21208
|
+
} catch {
|
|
21209
|
+
return null;
|
|
21210
|
+
}
|
|
21211
|
+
if (!raw) return null;
|
|
21212
|
+
if (raw.length > MAX_BUNDLE_BYTES2) return null;
|
|
21213
|
+
try {
|
|
21214
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21215
|
+
const aad = stringToBytes(aggregatorId);
|
|
21216
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21217
|
+
const parsed = JSON.parse(
|
|
21218
|
+
bytesToString(plaintext)
|
|
21219
|
+
);
|
|
21220
|
+
if (parsed.version !== 1) return null;
|
|
21221
|
+
if (parsed.aggregator_id !== aggregatorId) return null;
|
|
21222
|
+
return parsed.payload;
|
|
21223
|
+
} catch {
|
|
21224
|
+
return null;
|
|
21225
|
+
}
|
|
21226
|
+
}
|
|
21227
|
+
/**
|
|
21228
|
+
* Delete the persisted payload. Returns true when a bundle was removed,
|
|
21229
|
+
* false when none existed.
|
|
21230
|
+
*/
|
|
21231
|
+
async deletePayload(aggregatorId) {
|
|
21232
|
+
const key = payloadKey(aggregatorId);
|
|
21233
|
+
const existed = await this.storage.exists(
|
|
21234
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21235
|
+
key
|
|
21236
|
+
);
|
|
21237
|
+
if (!existed) return false;
|
|
21238
|
+
try {
|
|
21239
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21240
|
+
} catch {
|
|
21241
|
+
return false;
|
|
21242
|
+
}
|
|
21243
|
+
return true;
|
|
21244
|
+
}
|
|
21245
|
+
/**
|
|
21246
|
+
* Drop expired payload bundles. Returns the count of bundles pruned.
|
|
21247
|
+
* Caller wires this into the cocoon-unlock initialization path.
|
|
21248
|
+
*/
|
|
21249
|
+
async pruneExpired(now) {
|
|
21250
|
+
const cutoff = (now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
21251
|
+
const entries = await this.storage.list(
|
|
21252
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21253
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX
|
|
21254
|
+
);
|
|
21255
|
+
let pruned = 0;
|
|
21256
|
+
for (const meta of entries) {
|
|
21257
|
+
const aggregatorId = stripKeyPrefix(meta.key);
|
|
21258
|
+
if (aggregatorId === null) continue;
|
|
21259
|
+
const raw = await this.storage.read(
|
|
21260
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21261
|
+
meta.key
|
|
21262
|
+
);
|
|
21263
|
+
if (!raw) continue;
|
|
21264
|
+
try {
|
|
21265
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21266
|
+
const aad = stringToBytes(aggregatorId);
|
|
21267
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21268
|
+
const parsed = JSON.parse(
|
|
21269
|
+
bytesToString(plaintext)
|
|
21270
|
+
);
|
|
21271
|
+
if (parsed.retention_until <= cutoff) {
|
|
21272
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, meta.key);
|
|
21273
|
+
pruned += 1;
|
|
21274
|
+
}
|
|
21275
|
+
} catch {
|
|
21276
|
+
}
|
|
21277
|
+
}
|
|
21278
|
+
return { pruned };
|
|
21279
|
+
}
|
|
21280
|
+
};
|
|
21281
|
+
}
|
|
21282
|
+
});
|
|
21283
|
+
|
|
20782
21284
|
// src/principal-policy/tools.ts
|
|
20783
21285
|
function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
20784
21286
|
return [
|
|
@@ -33397,7 +33899,14 @@ var init_operator_chat_audit_events = __esm({
|
|
|
33397
33899
|
* turns; the concierge degrades to single-turn after emitting. Body
|
|
33398
33900
|
* carries thread_id + a stable failure_reason enum.
|
|
33399
33901
|
*/
|
|
33400
|
-
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed"
|
|
33902
|
+
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed",
|
|
33903
|
+
/**
|
|
33904
|
+
* Concierge dynamic-context fetcher failed (WP-V1.3-9 Tau-3). Emitted
|
|
33905
|
+
* when a category fetcher throws while assembling the dynamic context
|
|
33906
|
+
* fold. The concierge omits that category and continues; the user-
|
|
33907
|
+
* facing query is never broken. Body carries category + failure_reason.
|
|
33908
|
+
*/
|
|
33909
|
+
CONCIERGE_CONTEXT_FETCHER_FAILED: "operator_concierge_context_fetcher_failed"
|
|
33401
33910
|
};
|
|
33402
33911
|
}
|
|
33403
33912
|
});
|
|
@@ -33410,12 +33919,844 @@ var init_operator_chat_types = __esm({
|
|
|
33410
33919
|
CONCIERGE_THREAD_KEY = "_fortress";
|
|
33411
33920
|
}
|
|
33412
33921
|
});
|
|
33922
|
+
|
|
33923
|
+
// src/chat/concierge-context-router.ts
|
|
33924
|
+
function phrasePattern(phrase) {
|
|
33925
|
+
const escaped = phrase.toLowerCase().split(/\s+/).map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
|
|
33926
|
+
return { source: `\\b${escaped}\\b`, phrase };
|
|
33927
|
+
}
|
|
33928
|
+
function extractAgentNameHint(query) {
|
|
33929
|
+
const agentPattern = /\bagent\s+["']?([A-Za-z][\w-]{0,40})["']?/i;
|
|
33930
|
+
const m = query.match(agentPattern);
|
|
33931
|
+
if (m && m[1]) return m[1];
|
|
33932
|
+
const quoted = query.match(/["']([A-Za-z][\w-]{0,40})["']/);
|
|
33933
|
+
if (quoted && quoted[1]) return quoted[1];
|
|
33934
|
+
return null;
|
|
33935
|
+
}
|
|
33936
|
+
function isTrivialQuery(query) {
|
|
33937
|
+
const norm = query.trim().toLowerCase();
|
|
33938
|
+
if (norm.length === 0) return true;
|
|
33939
|
+
if (norm.length < 8) return true;
|
|
33940
|
+
return TRIVIAL_GREETINGS.has(norm);
|
|
33941
|
+
}
|
|
33942
|
+
function classifyQuery(query, parsedGrammar) {
|
|
33943
|
+
const normalized = query.toLowerCase();
|
|
33944
|
+
const matches = [];
|
|
33945
|
+
const grammarAgent = parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null;
|
|
33946
|
+
for (const spec of CATEGORY_KEYWORDS) {
|
|
33947
|
+
const matchedPhrases = [];
|
|
33948
|
+
for (const pattern of spec.patterns) {
|
|
33949
|
+
if (matchedPhrases.includes(pattern.phrase)) continue;
|
|
33950
|
+
const re = new RegExp(pattern.source, "i");
|
|
33951
|
+
if (re.test(normalized)) {
|
|
33952
|
+
matchedPhrases.push(pattern.phrase);
|
|
33953
|
+
}
|
|
33954
|
+
}
|
|
33955
|
+
if (matchedPhrases.length === 0) continue;
|
|
33956
|
+
const confidence = Math.min(1, 0.4 + 0.3 * matchedPhrases.length);
|
|
33957
|
+
const wantsAgentHint = spec.category === "agent_state" || spec.category === "agent_activity";
|
|
33958
|
+
const agent_name_hint = wantsAgentHint ? grammarAgent ?? extractAgentNameHint(query) : null;
|
|
33959
|
+
matches.push({
|
|
33960
|
+
category: spec.category,
|
|
33961
|
+
confidence,
|
|
33962
|
+
matched_keywords: matchedPhrases,
|
|
33963
|
+
agent_name_hint,
|
|
33964
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33965
|
+
});
|
|
33966
|
+
}
|
|
33967
|
+
matches.sort((a, b) => {
|
|
33968
|
+
if (b.confidence !== a.confidence) return b.confidence - a.confidence;
|
|
33969
|
+
return CONTEXT_CATEGORIES.indexOf(a.category) - CONTEXT_CATEGORIES.indexOf(b.category);
|
|
33970
|
+
});
|
|
33971
|
+
return matches;
|
|
33972
|
+
}
|
|
33973
|
+
function fetcherHintsFromGrammar(parsed) {
|
|
33974
|
+
if (!parsed) return void 0;
|
|
33975
|
+
const hasTime = parsed.time_range !== null;
|
|
33976
|
+
const hasAgents = parsed.agent_names.length > 0;
|
|
33977
|
+
const hasEvents = parsed.event_types.length > 0;
|
|
33978
|
+
if (!hasTime && !hasAgents && !hasEvents) return void 0;
|
|
33979
|
+
const hints = {};
|
|
33980
|
+
if (parsed.time_range) {
|
|
33981
|
+
const range = parsed.time_range;
|
|
33982
|
+
hints.time_range = {
|
|
33983
|
+
start: range.start,
|
|
33984
|
+
end: range.end,
|
|
33985
|
+
...range.relative_label !== void 0 ? { relative_label: range.relative_label } : {}
|
|
33986
|
+
};
|
|
33987
|
+
}
|
|
33988
|
+
if (hasAgents) hints.agent_names = parsed.agent_names;
|
|
33989
|
+
if (hasEvents) hints.event_types = parsed.event_types;
|
|
33990
|
+
return hints;
|
|
33991
|
+
}
|
|
33413
33992
|
function approxTokenLen(text) {
|
|
33993
|
+
return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
33994
|
+
}
|
|
33995
|
+
async function runFetcher(match, fetchers, hints) {
|
|
33996
|
+
switch (match.category) {
|
|
33997
|
+
case "templates":
|
|
33998
|
+
return fetchers.templates(hints);
|
|
33999
|
+
case "agent_state":
|
|
34000
|
+
return fetchers.agent_state(match.agent_name_hint, hints);
|
|
34001
|
+
case "agent_activity":
|
|
34002
|
+
return fetchers.agent_activity(match.agent_name_hint, hints);
|
|
34003
|
+
case "audit_log":
|
|
34004
|
+
return fetchers.audit_log(hints);
|
|
34005
|
+
case "sentinel_findings":
|
|
34006
|
+
return fetchers.sentinel_findings(hints);
|
|
34007
|
+
case "anomaly_alerts":
|
|
34008
|
+
return fetchers.anomaly_alerts(hints);
|
|
34009
|
+
case "recent_receipts":
|
|
34010
|
+
return fetchers.recent_receipts(hints);
|
|
34011
|
+
case "verascore_deltas":
|
|
34012
|
+
return fetchers.verascore_deltas(hints);
|
|
34013
|
+
}
|
|
34014
|
+
}
|
|
34015
|
+
function trivialMatch(category, parsedGrammar) {
|
|
34016
|
+
return {
|
|
34017
|
+
category,
|
|
34018
|
+
confidence: 0.5,
|
|
34019
|
+
matched_keywords: ["llm-assist"],
|
|
34020
|
+
agent_name_hint: parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null,
|
|
34021
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
34022
|
+
};
|
|
34023
|
+
}
|
|
34024
|
+
async function foldContext(query, fetchers, opts) {
|
|
34025
|
+
const budget = opts?.maxTokens ?? DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET;
|
|
34026
|
+
const parsed = opts?.parsed ?? null;
|
|
34027
|
+
const hints = fetcherHintsFromGrammar(parsed);
|
|
34028
|
+
let matches = classifyQuery(query, parsed);
|
|
34029
|
+
if (matches.length === 0 && !isTrivialQuery(query) && opts?.llmAssistClassify) {
|
|
34030
|
+
try {
|
|
34031
|
+
const picked = await opts.llmAssistClassify(query, CONTEXT_CATEGORIES);
|
|
34032
|
+
if (picked !== "none" && CONTEXT_CATEGORIES.includes(picked)) {
|
|
34033
|
+
matches = [trivialMatch(picked, parsed)];
|
|
34034
|
+
}
|
|
34035
|
+
} catch {
|
|
34036
|
+
}
|
|
34037
|
+
}
|
|
34038
|
+
if (matches.length === 0) {
|
|
34039
|
+
return { section: "", categoriesIncluded: [] };
|
|
34040
|
+
}
|
|
34041
|
+
const attempts = [];
|
|
34042
|
+
for (const match of matches) {
|
|
34043
|
+
try {
|
|
34044
|
+
const text = await runFetcher(match, fetchers, hints);
|
|
34045
|
+
const trimmed = text.trim();
|
|
34046
|
+
if (trimmed.length > 0) {
|
|
34047
|
+
attempts.push({ category: match.category, text: trimmed });
|
|
34048
|
+
}
|
|
34049
|
+
} catch (err) {
|
|
34050
|
+
opts?.onFetcherFailure?.(match.category, err);
|
|
34051
|
+
}
|
|
34052
|
+
}
|
|
34053
|
+
if (attempts.length === 0) {
|
|
34054
|
+
return { section: "", categoriesIncluded: [] };
|
|
34055
|
+
}
|
|
34056
|
+
const headerTokens = approxTokenLen(`${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
34057
|
+
`);
|
|
34058
|
+
const sepTokens = approxTokenLen("\n\n");
|
|
34059
|
+
let runningTokens = headerTokens;
|
|
34060
|
+
const kept = [];
|
|
34061
|
+
for (const attempt of attempts) {
|
|
34062
|
+
const block = `### ${CATEGORY_LABELS[attempt.category]}
|
|
34063
|
+
${attempt.text}`;
|
|
34064
|
+
const tokens = approxTokenLen(block) + (kept.length > 0 ? sepTokens : 0);
|
|
34065
|
+
if (kept.length === 0) {
|
|
34066
|
+
kept.push(attempt);
|
|
34067
|
+
runningTokens += tokens;
|
|
34068
|
+
continue;
|
|
34069
|
+
}
|
|
34070
|
+
if (runningTokens + tokens > budget) break;
|
|
34071
|
+
kept.push(attempt);
|
|
34072
|
+
runningTokens += tokens;
|
|
34073
|
+
}
|
|
34074
|
+
const blocks = kept.map(
|
|
34075
|
+
(k) => `### ${CATEGORY_LABELS[k.category]}
|
|
34076
|
+
${k.text}`
|
|
34077
|
+
);
|
|
34078
|
+
const section = `${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
34079
|
+
${blocks.join("\n\n")}`;
|
|
34080
|
+
return {
|
|
34081
|
+
section,
|
|
34082
|
+
categoriesIncluded: kept.map((k) => k.category)
|
|
34083
|
+
};
|
|
34084
|
+
}
|
|
34085
|
+
var APPROX_CHARS_PER_TOKEN, DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET, DYNAMIC_CONTEXT_SECTION_HEADER, CONTEXT_CATEGORIES, CATEGORY_KEYWORDS, TRIVIAL_GREETINGS, CATEGORY_LABELS;
|
|
34086
|
+
var init_concierge_context_router = __esm({
|
|
34087
|
+
"src/chat/concierge-context-router.ts"() {
|
|
34088
|
+
APPROX_CHARS_PER_TOKEN = 4;
|
|
34089
|
+
DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET = 2e3;
|
|
34090
|
+
DYNAMIC_CONTEXT_SECTION_HEADER = "## Live fortress context";
|
|
34091
|
+
CONTEXT_CATEGORIES = [
|
|
34092
|
+
"templates",
|
|
34093
|
+
"agent_state",
|
|
34094
|
+
"agent_activity",
|
|
34095
|
+
"audit_log",
|
|
34096
|
+
"sentinel_findings",
|
|
34097
|
+
"anomaly_alerts",
|
|
34098
|
+
"recent_receipts",
|
|
34099
|
+
"verascore_deltas"
|
|
34100
|
+
];
|
|
34101
|
+
CATEGORY_KEYWORDS = [
|
|
34102
|
+
{
|
|
34103
|
+
category: "templates",
|
|
34104
|
+
patterns: [
|
|
34105
|
+
"templates",
|
|
34106
|
+
"template",
|
|
34107
|
+
"channel templates",
|
|
34108
|
+
"channel template",
|
|
34109
|
+
"list templates",
|
|
34110
|
+
"available templates",
|
|
34111
|
+
"what templates"
|
|
34112
|
+
].map(phrasePattern)
|
|
34113
|
+
},
|
|
34114
|
+
{
|
|
34115
|
+
category: "agent_state",
|
|
34116
|
+
patterns: [
|
|
34117
|
+
"state",
|
|
34118
|
+
"status",
|
|
34119
|
+
"agent state",
|
|
34120
|
+
"agent status",
|
|
34121
|
+
"status of agent",
|
|
34122
|
+
"status of agents",
|
|
34123
|
+
"state of",
|
|
34124
|
+
"doing"
|
|
34125
|
+
].map(phrasePattern)
|
|
34126
|
+
},
|
|
34127
|
+
{
|
|
34128
|
+
category: "agent_activity",
|
|
34129
|
+
patterns: [
|
|
34130
|
+
"activity",
|
|
34131
|
+
"agent activity",
|
|
34132
|
+
"what did",
|
|
34133
|
+
"recent activity"
|
|
34134
|
+
].map(phrasePattern)
|
|
34135
|
+
},
|
|
34136
|
+
{
|
|
34137
|
+
category: "audit_log",
|
|
34138
|
+
patterns: [
|
|
34139
|
+
"audit log",
|
|
34140
|
+
"audit",
|
|
34141
|
+
"log entry",
|
|
34142
|
+
"log entries",
|
|
34143
|
+
"what happened",
|
|
34144
|
+
"show me events",
|
|
34145
|
+
"event class"
|
|
34146
|
+
].map(phrasePattern)
|
|
34147
|
+
},
|
|
34148
|
+
{
|
|
34149
|
+
category: "sentinel_findings",
|
|
34150
|
+
patterns: [
|
|
34151
|
+
"sentinel",
|
|
34152
|
+
"sentinels",
|
|
34153
|
+
"warning",
|
|
34154
|
+
"warnings",
|
|
34155
|
+
"alert",
|
|
34156
|
+
"alerts",
|
|
34157
|
+
"whats wrong",
|
|
34158
|
+
"what's wrong",
|
|
34159
|
+
"findings"
|
|
34160
|
+
].map(phrasePattern)
|
|
34161
|
+
},
|
|
34162
|
+
{
|
|
34163
|
+
category: "anomaly_alerts",
|
|
34164
|
+
patterns: [
|
|
34165
|
+
"anomaly",
|
|
34166
|
+
"anomalies",
|
|
34167
|
+
"spike",
|
|
34168
|
+
"unusual",
|
|
34169
|
+
"outlier"
|
|
34170
|
+
].map(phrasePattern)
|
|
34171
|
+
},
|
|
34172
|
+
{
|
|
34173
|
+
category: "recent_receipts",
|
|
34174
|
+
patterns: [
|
|
34175
|
+
"receipt",
|
|
34176
|
+
"receipts",
|
|
34177
|
+
"concordia",
|
|
34178
|
+
"commitment",
|
|
34179
|
+
"commitments",
|
|
34180
|
+
"chain",
|
|
34181
|
+
"chains"
|
|
34182
|
+
].map(phrasePattern)
|
|
34183
|
+
},
|
|
34184
|
+
{
|
|
34185
|
+
category: "verascore_deltas",
|
|
34186
|
+
patterns: [
|
|
34187
|
+
"verascore",
|
|
34188
|
+
"vera score",
|
|
34189
|
+
"trust score",
|
|
34190
|
+
"reputation"
|
|
34191
|
+
].map(phrasePattern)
|
|
34192
|
+
}
|
|
34193
|
+
];
|
|
34194
|
+
TRIVIAL_GREETINGS = /* @__PURE__ */ new Set([
|
|
34195
|
+
"hi",
|
|
34196
|
+
"hello",
|
|
34197
|
+
"hey",
|
|
34198
|
+
"yo",
|
|
34199
|
+
"ok",
|
|
34200
|
+
"thanks",
|
|
34201
|
+
"thx",
|
|
34202
|
+
"thank you"
|
|
34203
|
+
]);
|
|
34204
|
+
CATEGORY_LABELS = {
|
|
34205
|
+
templates: "Templates",
|
|
34206
|
+
agent_state: "Agent state",
|
|
34207
|
+
agent_activity: "Agent activity",
|
|
34208
|
+
audit_log: "Audit log",
|
|
34209
|
+
sentinel_findings: "Sentinel findings",
|
|
34210
|
+
anomaly_alerts: "Anomaly alerts",
|
|
34211
|
+
recent_receipts: "Recent receipts",
|
|
34212
|
+
verascore_deltas: "Verascore deltas"
|
|
34213
|
+
};
|
|
34214
|
+
}
|
|
34215
|
+
});
|
|
34216
|
+
|
|
34217
|
+
// src/composition/constants.ts
|
|
34218
|
+
var COMPOSITION_EVENT_TYPES;
|
|
34219
|
+
var init_constants4 = __esm({
|
|
34220
|
+
"src/composition/constants.ts"() {
|
|
34221
|
+
init_constants();
|
|
34222
|
+
COMPOSITION_EVENT_TYPES = [
|
|
34223
|
+
"composition_receipt_packed",
|
|
34224
|
+
"composition_receipt_verified",
|
|
34225
|
+
"composition_mandate_verified",
|
|
34226
|
+
"composition_verascore_published",
|
|
34227
|
+
"composition_sidecar_spawned",
|
|
34228
|
+
"composition_sidecar_crashed",
|
|
34229
|
+
"composition_sidecar_recovered",
|
|
34230
|
+
"composition_degraded",
|
|
34231
|
+
"composition_recovered"
|
|
34232
|
+
];
|
|
34233
|
+
}
|
|
34234
|
+
});
|
|
34235
|
+
|
|
34236
|
+
// src/chat/concierge-query-grammar.ts
|
|
34237
|
+
function resolveTimeRange(query, now) {
|
|
34238
|
+
const normalized = query.trim();
|
|
34239
|
+
const lower = normalized.toLowerCase();
|
|
34240
|
+
const fromTo = lower.match(
|
|
34241
|
+
/\b(?:from|between)\s+(.+?)\s+(?:to|and|-|until)\s+([\w:.\-+t /]+)/i
|
|
34242
|
+
);
|
|
34243
|
+
if (fromTo) {
|
|
34244
|
+
const aSlice = fromTo[1];
|
|
34245
|
+
const bSlice = fromTo[2];
|
|
34246
|
+
if (aSlice !== void 0 && bSlice !== void 0) {
|
|
34247
|
+
const a = parseInstant(aSlice, now);
|
|
34248
|
+
const b = parseInstant(bSlice, now);
|
|
34249
|
+
if (a && b) {
|
|
34250
|
+
const start = a.getTime() <= b.getTime() ? a : b;
|
|
34251
|
+
const end = a.getTime() <= b.getTime() ? b : a;
|
|
34252
|
+
return {
|
|
34253
|
+
range: { start, end },
|
|
34254
|
+
matchedSubstring: fromTo[0]
|
|
34255
|
+
};
|
|
34256
|
+
}
|
|
34257
|
+
}
|
|
34258
|
+
}
|
|
34259
|
+
const sinceMatch = lower.match(/\bsince\s+([\w:.\-+t /]+)/i);
|
|
34260
|
+
if (sinceMatch) {
|
|
34261
|
+
const slice = sinceMatch[1];
|
|
34262
|
+
if (slice !== void 0) {
|
|
34263
|
+
const start = parseInstant(slice, now);
|
|
34264
|
+
if (start) {
|
|
34265
|
+
return {
|
|
34266
|
+
range: { start, end: now },
|
|
34267
|
+
matchedSubstring: sinceMatch[0]
|
|
34268
|
+
};
|
|
34269
|
+
}
|
|
34270
|
+
}
|
|
34271
|
+
}
|
|
34272
|
+
if (/\byesterday\b/.test(lower)) {
|
|
34273
|
+
const startOfToday = startOfDay(now);
|
|
34274
|
+
const start = new Date(startOfToday.getTime() - MS_PER_DAY);
|
|
34275
|
+
const end = new Date(startOfToday.getTime() - 1);
|
|
34276
|
+
return {
|
|
34277
|
+
range: { start, end, relative_label: "yesterday" },
|
|
34278
|
+
matchedSubstring: "yesterday"
|
|
34279
|
+
};
|
|
34280
|
+
}
|
|
34281
|
+
if (/\btoday\b/.test(lower)) {
|
|
34282
|
+
return {
|
|
34283
|
+
range: {
|
|
34284
|
+
start: startOfDay(now),
|
|
34285
|
+
end: now,
|
|
34286
|
+
relative_label: "today"
|
|
34287
|
+
},
|
|
34288
|
+
matchedSubstring: "today"
|
|
34289
|
+
};
|
|
34290
|
+
}
|
|
34291
|
+
const compactHours = lower.match(/\blast\s+(\d+)\s*h\b/i);
|
|
34292
|
+
if (compactHours) {
|
|
34293
|
+
const tok = compactHours[1];
|
|
34294
|
+
if (tok !== void 0) {
|
|
34295
|
+
const n = Number.parseInt(tok, 10);
|
|
34296
|
+
if (Number.isFinite(n) && n > 0) {
|
|
34297
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34298
|
+
return {
|
|
34299
|
+
range: { start, end: now, relative_label: `last ${n}h` },
|
|
34300
|
+
matchedSubstring: compactHours[0]
|
|
34301
|
+
};
|
|
34302
|
+
}
|
|
34303
|
+
}
|
|
34304
|
+
}
|
|
34305
|
+
const hoursMatch = lower.match(
|
|
34306
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:hr\b|hrs\b|hour|hours)/i
|
|
34307
|
+
);
|
|
34308
|
+
if (hoursMatch) {
|
|
34309
|
+
const tok = hoursMatch[1];
|
|
34310
|
+
if (tok !== void 0) {
|
|
34311
|
+
const n = parseCount(tok);
|
|
34312
|
+
if (n !== null && n > 0) {
|
|
34313
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34314
|
+
return {
|
|
34315
|
+
range: { start, end: now, relative_label: `past ${n} hour${n === 1 ? "" : "s"}` },
|
|
34316
|
+
matchedSubstring: hoursMatch[0]
|
|
34317
|
+
};
|
|
34318
|
+
}
|
|
34319
|
+
}
|
|
34320
|
+
}
|
|
34321
|
+
if (/\b(?:past|last)\s+hour\b/.test(lower)) {
|
|
34322
|
+
const start = new Date(now.getTime() - MS_PER_HOUR);
|
|
34323
|
+
return {
|
|
34324
|
+
range: { start, end: now, relative_label: "past hour" },
|
|
34325
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+hour\b/i)[0]
|
|
34326
|
+
};
|
|
34327
|
+
}
|
|
34328
|
+
const daysMatch = lower.match(
|
|
34329
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:d\b|day|days)/i
|
|
34330
|
+
);
|
|
34331
|
+
if (daysMatch) {
|
|
34332
|
+
const tok = daysMatch[1];
|
|
34333
|
+
if (tok !== void 0) {
|
|
34334
|
+
const n = parseCount(tok);
|
|
34335
|
+
if (n !== null && n > 0) {
|
|
34336
|
+
const start = new Date(now.getTime() - n * MS_PER_DAY);
|
|
34337
|
+
return {
|
|
34338
|
+
range: { start, end: now, relative_label: `past ${n} day${n === 1 ? "" : "s"}` },
|
|
34339
|
+
matchedSubstring: daysMatch[0]
|
|
34340
|
+
};
|
|
34341
|
+
}
|
|
34342
|
+
}
|
|
34343
|
+
}
|
|
34344
|
+
if (/\b(?:past|last)\s+day\b/.test(lower)) {
|
|
34345
|
+
const start = new Date(now.getTime() - MS_PER_DAY);
|
|
34346
|
+
return {
|
|
34347
|
+
range: { start, end: now, relative_label: "past day" },
|
|
34348
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+day\b/i)[0]
|
|
34349
|
+
};
|
|
34350
|
+
}
|
|
34351
|
+
if (/\bthis\s+week\b/.test(lower)) {
|
|
34352
|
+
const start = startOfWeek(now);
|
|
34353
|
+
return {
|
|
34354
|
+
range: { start, end: now, relative_label: "this week" },
|
|
34355
|
+
matchedSubstring: lower.match(/\bthis\s+week\b/i)[0]
|
|
34356
|
+
};
|
|
34357
|
+
}
|
|
34358
|
+
if (/\b(?:past|last)\s+week\b/.test(lower)) {
|
|
34359
|
+
const start = new Date(now.getTime() - 7 * MS_PER_DAY);
|
|
34360
|
+
return {
|
|
34361
|
+
range: { start, end: now, relative_label: "past week" },
|
|
34362
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+week\b/i)[0]
|
|
34363
|
+
};
|
|
34364
|
+
}
|
|
34365
|
+
const isoMatch = normalized.match(
|
|
34366
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?)?)\b/
|
|
34367
|
+
);
|
|
34368
|
+
if (isoMatch) {
|
|
34369
|
+
const tok = isoMatch[1];
|
|
34370
|
+
if (tok !== void 0) {
|
|
34371
|
+
const parsed = parseInstant(tok, now);
|
|
34372
|
+
if (parsed) {
|
|
34373
|
+
const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(tok);
|
|
34374
|
+
if (isDateOnly) {
|
|
34375
|
+
return {
|
|
34376
|
+
range: {
|
|
34377
|
+
start: parsed,
|
|
34378
|
+
end: new Date(parsed.getTime() + MS_PER_DAY - 1)
|
|
34379
|
+
},
|
|
34380
|
+
matchedSubstring: tok
|
|
34381
|
+
};
|
|
34382
|
+
}
|
|
34383
|
+
return {
|
|
34384
|
+
range: {
|
|
34385
|
+
start: new Date(parsed.getTime() - 30 * 60 * 1e3),
|
|
34386
|
+
end: new Date(parsed.getTime() + 30 * 60 * 1e3)
|
|
34387
|
+
},
|
|
34388
|
+
matchedSubstring: tok
|
|
34389
|
+
};
|
|
34390
|
+
}
|
|
34391
|
+
}
|
|
34392
|
+
}
|
|
34393
|
+
return null;
|
|
34394
|
+
}
|
|
34395
|
+
function parseInstant(token, now) {
|
|
34396
|
+
const trimmed = token.trim().replace(/[,.!?;]+$/g, "");
|
|
34397
|
+
if (!trimmed) return null;
|
|
34398
|
+
const lower = trimmed.toLowerCase();
|
|
34399
|
+
if (lower === "now") return now;
|
|
34400
|
+
if (lower === "today") return startOfDay(now);
|
|
34401
|
+
if (lower === "yesterday") {
|
|
34402
|
+
return new Date(startOfDay(now).getTime() - MS_PER_DAY);
|
|
34403
|
+
}
|
|
34404
|
+
const isoLike = trimmed.replace(" ", "T");
|
|
34405
|
+
const parsed = new Date(isoLike);
|
|
34406
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
34407
|
+
return null;
|
|
34408
|
+
}
|
|
34409
|
+
function parseCount(token) {
|
|
34410
|
+
const lower = token.toLowerCase();
|
|
34411
|
+
if (/^\d+$/.test(lower)) {
|
|
34412
|
+
const n = Number.parseInt(lower, 10);
|
|
34413
|
+
return Number.isFinite(n) ? n : null;
|
|
34414
|
+
}
|
|
34415
|
+
return NUMBER_WORDS[lower] ?? null;
|
|
34416
|
+
}
|
|
34417
|
+
function startOfDay(d) {
|
|
34418
|
+
const out = new Date(d);
|
|
34419
|
+
out.setHours(0, 0, 0, 0);
|
|
34420
|
+
return out;
|
|
34421
|
+
}
|
|
34422
|
+
function startOfWeek(d) {
|
|
34423
|
+
const out = startOfDay(d);
|
|
34424
|
+
const dayOfWeek = out.getDay();
|
|
34425
|
+
const offsetToMonday = (dayOfWeek + 6) % 7;
|
|
34426
|
+
out.setDate(out.getDate() - offsetToMonday);
|
|
34427
|
+
return out;
|
|
34428
|
+
}
|
|
34429
|
+
function listFromRegistry(registry) {
|
|
34430
|
+
if (!registry) return [];
|
|
34431
|
+
if (Array.isArray(registry)) return registry;
|
|
34432
|
+
if (typeof registry.list === "function") {
|
|
34433
|
+
return registry.list();
|
|
34434
|
+
}
|
|
34435
|
+
return [];
|
|
34436
|
+
}
|
|
34437
|
+
function extractAgentNames(query, registry) {
|
|
34438
|
+
const records = listFromRegistry(registry);
|
|
34439
|
+
if (records.length === 0) return { matched: [], flagged: false };
|
|
34440
|
+
const lowerQuery = query.toLowerCase();
|
|
34441
|
+
const compactQuery = lowerQuery.replace(/[\s_-]+/g, "");
|
|
34442
|
+
const matched = [];
|
|
34443
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34444
|
+
for (const rec of records) {
|
|
34445
|
+
const id = rec.agent_id;
|
|
34446
|
+
if (!id || seen.has(id)) continue;
|
|
34447
|
+
const idLower = id.toLowerCase();
|
|
34448
|
+
if (idLower.length < 3) continue;
|
|
34449
|
+
const idCompact = idLower.replace(/[\s_-]+/g, "");
|
|
34450
|
+
const wordRe = new RegExp(
|
|
34451
|
+
`\\b${idLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
|
|
34452
|
+
"i"
|
|
34453
|
+
);
|
|
34454
|
+
if (wordRe.test(query)) {
|
|
34455
|
+
matched.push(id);
|
|
34456
|
+
seen.add(id);
|
|
34457
|
+
continue;
|
|
34458
|
+
}
|
|
34459
|
+
if (idCompact.length >= 4 && compactQuery.includes(idCompact)) {
|
|
34460
|
+
matched.push(id);
|
|
34461
|
+
seen.add(id);
|
|
34462
|
+
}
|
|
34463
|
+
}
|
|
34464
|
+
const agentMention = lowerQuery.match(/\bagent\s+([a-z0-9_-]{3,40})/i);
|
|
34465
|
+
const flagged = matched.length === 0 && agentMention !== null && agentMention[1] !== void 0 && !records.some((r) => r.agent_id.toLowerCase() === agentMention[1]?.toLowerCase());
|
|
34466
|
+
return { matched, flagged };
|
|
34467
|
+
}
|
|
34468
|
+
function escapeRegex(s) {
|
|
34469
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34470
|
+
}
|
|
34471
|
+
function extractEventTypes(query, enumValues) {
|
|
34472
|
+
const lower = query.toLowerCase();
|
|
34473
|
+
const matched = [];
|
|
34474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34475
|
+
for (const ev of enumValues) {
|
|
34476
|
+
if (seen.has(ev)) continue;
|
|
34477
|
+
const re = new RegExp(`\\b${escapeRegex(ev)}\\b`, "i");
|
|
34478
|
+
if (re.test(query)) {
|
|
34479
|
+
matched.push(ev);
|
|
34480
|
+
seen.add(ev);
|
|
34481
|
+
}
|
|
34482
|
+
}
|
|
34483
|
+
for (const syn of EVENT_SYNONYMS) {
|
|
34484
|
+
const re = new RegExp(
|
|
34485
|
+
`\\b${syn.phrase.split(/\s+/).map(escapeRegex).join("\\s+")}\\b`,
|
|
34486
|
+
"i"
|
|
34487
|
+
);
|
|
34488
|
+
if (re.test(query)) {
|
|
34489
|
+
for (const c of syn.canonical) {
|
|
34490
|
+
if (seen.has(c)) continue;
|
|
34491
|
+
if (!enumValues.includes(c)) continue;
|
|
34492
|
+
matched.push(c);
|
|
34493
|
+
seen.add(c);
|
|
34494
|
+
}
|
|
34495
|
+
}
|
|
34496
|
+
}
|
|
34497
|
+
const globMatches = lower.match(/\b([a-z_]+)_\*/g) ?? [];
|
|
34498
|
+
for (const glob of globMatches) {
|
|
34499
|
+
const prefix = glob.slice(0, -2);
|
|
34500
|
+
for (const ev of enumValues) {
|
|
34501
|
+
if (seen.has(ev)) continue;
|
|
34502
|
+
if (ev.startsWith(prefix)) {
|
|
34503
|
+
matched.push(ev);
|
|
34504
|
+
seen.add(ev);
|
|
34505
|
+
}
|
|
34506
|
+
}
|
|
34507
|
+
}
|
|
34508
|
+
const eventNounMention = /\b(?:event|events|class|classes)\b/i.test(query) && matched.length === 0;
|
|
34509
|
+
return { matched, flagged: eventNounMention };
|
|
34510
|
+
}
|
|
34511
|
+
function deriveIntentPhrase(query, stripTokens) {
|
|
34512
|
+
let out = query;
|
|
34513
|
+
for (const tok of stripTokens) {
|
|
34514
|
+
if (!tok) continue;
|
|
34515
|
+
const re = new RegExp(escapeRegex(tok), "gi");
|
|
34516
|
+
out = out.replace(re, " ");
|
|
34517
|
+
}
|
|
34518
|
+
return out.replace(/\s+/g, " ").trim();
|
|
34519
|
+
}
|
|
34520
|
+
function computeConfidence(parsed) {
|
|
34521
|
+
const dims = [
|
|
34522
|
+
{ present: parsed.hasTimeMention, resolved: parsed.timeResolved },
|
|
34523
|
+
{ present: parsed.hasAgentMention, resolved: parsed.agentResolved },
|
|
34524
|
+
{ present: parsed.hasEventMention, resolved: parsed.eventResolved }
|
|
34525
|
+
];
|
|
34526
|
+
const present = dims.filter((d) => d.present);
|
|
34527
|
+
let base;
|
|
34528
|
+
if (present.length === 0) {
|
|
34529
|
+
base = parsed.intentEmpty ? 0 : 0.3;
|
|
34530
|
+
} else {
|
|
34531
|
+
const resolved = present.filter((d) => d.resolved).length;
|
|
34532
|
+
base = resolved / present.length;
|
|
34533
|
+
}
|
|
34534
|
+
const adjusted = base - 0.15 * parsed.ambiguityCount;
|
|
34535
|
+
if (adjusted < 0) return 0;
|
|
34536
|
+
if (adjusted > 1) return 1;
|
|
34537
|
+
return adjusted;
|
|
34538
|
+
}
|
|
34539
|
+
function parseQuery(query, opts) {
|
|
34540
|
+
const now = opts?.now ?? /* @__PURE__ */ new Date();
|
|
34541
|
+
const enumValues = opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES;
|
|
34542
|
+
const original = query ?? "";
|
|
34543
|
+
const trimmed = original.trim();
|
|
34544
|
+
if (trimmed.length === 0) {
|
|
34545
|
+
return {
|
|
34546
|
+
time_range: null,
|
|
34547
|
+
agent_names: [],
|
|
34548
|
+
event_types: [],
|
|
34549
|
+
intent_phrase: "",
|
|
34550
|
+
ambiguity_flags: ["no_signal_extracted"],
|
|
34551
|
+
parse_confidence: 0
|
|
34552
|
+
};
|
|
34553
|
+
}
|
|
34554
|
+
const ambiguity_flags = /* @__PURE__ */ new Set();
|
|
34555
|
+
const timeMatch = resolveTimeRange(trimmed, now);
|
|
34556
|
+
const hasTimeMention = TIME_MENTION_PROBE.test(trimmed);
|
|
34557
|
+
if (hasTimeMention && !timeMatch) {
|
|
34558
|
+
ambiguity_flags.add("unknown_time_token");
|
|
34559
|
+
}
|
|
34560
|
+
const agentResult = extractAgentNames(trimmed, opts?.registry);
|
|
34561
|
+
if (agentResult.flagged) {
|
|
34562
|
+
ambiguity_flags.add("unknown_agent_token");
|
|
34563
|
+
}
|
|
34564
|
+
const hasAgentMention = AGENT_MENTION_PROBE.test(trimmed);
|
|
34565
|
+
const eventResult = extractEventTypes(trimmed, enumValues);
|
|
34566
|
+
const hasEventMention = EVENT_MENTION_PROBE.test(trimmed);
|
|
34567
|
+
if (eventResult.flagged) {
|
|
34568
|
+
ambiguity_flags.add("unknown_event_token");
|
|
34569
|
+
}
|
|
34570
|
+
const stripTokens = [];
|
|
34571
|
+
if (timeMatch) stripTokens.push(timeMatch.matchedSubstring);
|
|
34572
|
+
for (const name of agentResult.matched) stripTokens.push(name);
|
|
34573
|
+
for (const ev of eventResult.matched) {
|
|
34574
|
+
if (trimmed.toLowerCase().includes(ev.toLowerCase())) {
|
|
34575
|
+
stripTokens.push(ev);
|
|
34576
|
+
}
|
|
34577
|
+
}
|
|
34578
|
+
const intent_phrase = deriveIntentPhrase(trimmed, stripTokens);
|
|
34579
|
+
const parse_confidence = computeConfidence({
|
|
34580
|
+
hasTimeMention,
|
|
34581
|
+
timeResolved: timeMatch !== null,
|
|
34582
|
+
hasAgentMention,
|
|
34583
|
+
agentResolved: agentResult.matched.length > 0,
|
|
34584
|
+
hasEventMention,
|
|
34585
|
+
eventResolved: eventResult.matched.length > 0,
|
|
34586
|
+
intentEmpty: intent_phrase.length === 0,
|
|
34587
|
+
ambiguityCount: ambiguity_flags.size
|
|
34588
|
+
});
|
|
34589
|
+
if (timeMatch === null && agentResult.matched.length === 0 && eventResult.matched.length === 0 && intent_phrase.length === 0) {
|
|
34590
|
+
ambiguity_flags.add("no_signal_extracted");
|
|
34591
|
+
}
|
|
34592
|
+
return {
|
|
34593
|
+
time_range: timeMatch ? timeMatch.range : null,
|
|
34594
|
+
agent_names: agentResult.matched,
|
|
34595
|
+
event_types: eventResult.matched,
|
|
34596
|
+
intent_phrase,
|
|
34597
|
+
ambiguity_flags: Array.from(ambiguity_flags),
|
|
34598
|
+
parse_confidence
|
|
34599
|
+
};
|
|
34600
|
+
}
|
|
34601
|
+
function isLowConfidence(parsed) {
|
|
34602
|
+
return parsed.parse_confidence < LLM_ASSIST_THRESHOLD;
|
|
34603
|
+
}
|
|
34604
|
+
async function parseQueryWithLlmAssist(query, llmAssist, opts) {
|
|
34605
|
+
const parsed = parseQuery(query, opts);
|
|
34606
|
+
if (!llmAssist || !isLowConfidence(parsed)) return parsed;
|
|
34607
|
+
let completion;
|
|
34608
|
+
try {
|
|
34609
|
+
completion = await llmAssist(query, parsed);
|
|
34610
|
+
} catch {
|
|
34611
|
+
return parsed;
|
|
34612
|
+
}
|
|
34613
|
+
if (!completion || typeof completion !== "object") return parsed;
|
|
34614
|
+
const merged = { ...parsed };
|
|
34615
|
+
if (parsed.time_range === null && completion.time_range) {
|
|
34616
|
+
merged.time_range = completion.time_range;
|
|
34617
|
+
}
|
|
34618
|
+
if (parsed.agent_names.length === 0 && Array.isArray(completion.agent_names)) {
|
|
34619
|
+
merged.agent_names = completion.agent_names.filter(
|
|
34620
|
+
(s) => typeof s === "string" && s.length > 0
|
|
34621
|
+
);
|
|
34622
|
+
}
|
|
34623
|
+
if (parsed.event_types.length === 0 && Array.isArray(completion.event_types)) {
|
|
34624
|
+
const allowed = new Set(opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES);
|
|
34625
|
+
merged.event_types = completion.event_types.filter(
|
|
34626
|
+
(s) => typeof s === "string" && allowed.has(s)
|
|
34627
|
+
);
|
|
34628
|
+
}
|
|
34629
|
+
merged.parse_confidence = Math.max(
|
|
34630
|
+
parsed.parse_confidence,
|
|
34631
|
+
computeConfidence({
|
|
34632
|
+
hasTimeMention: TIME_MENTION_PROBE.test(query),
|
|
34633
|
+
timeResolved: merged.time_range !== null,
|
|
34634
|
+
hasAgentMention: AGENT_MENTION_PROBE.test(query),
|
|
34635
|
+
agentResolved: merged.agent_names.length > 0,
|
|
34636
|
+
hasEventMention: EVENT_MENTION_PROBE.test(query),
|
|
34637
|
+
eventResolved: merged.event_types.length > 0,
|
|
34638
|
+
intentEmpty: merged.intent_phrase.length === 0,
|
|
34639
|
+
ambiguityCount: merged.ambiguity_flags.length
|
|
34640
|
+
})
|
|
34641
|
+
);
|
|
34642
|
+
return merged;
|
|
34643
|
+
}
|
|
34644
|
+
function auditSafeSummary(parsed) {
|
|
34645
|
+
return {
|
|
34646
|
+
time_range: parsed.time_range ? {
|
|
34647
|
+
start_iso: parsed.time_range.start.toISOString(),
|
|
34648
|
+
end_iso: parsed.time_range.end.toISOString(),
|
|
34649
|
+
...parsed.time_range.relative_label !== void 0 ? { relative_label: parsed.time_range.relative_label } : {}
|
|
34650
|
+
} : null,
|
|
34651
|
+
agent_names: [...parsed.agent_names],
|
|
34652
|
+
event_types: [...parsed.event_types],
|
|
34653
|
+
ambiguity_flags: [...parsed.ambiguity_flags],
|
|
34654
|
+
parse_confidence: parsed.parse_confidence
|
|
34655
|
+
};
|
|
34656
|
+
}
|
|
34657
|
+
var CANONICAL_AUDIT_EVENT_CLASSES, EVENT_SYNONYMS, MS_PER_HOUR, MS_PER_DAY, NUMBER_WORDS, TIME_MENTION_PROBE, AGENT_MENTION_PROBE, EVENT_MENTION_PROBE, LLM_ASSIST_THRESHOLD;
|
|
34658
|
+
var init_concierge_query_grammar = __esm({
|
|
34659
|
+
"src/chat/concierge-query-grammar.ts"() {
|
|
34660
|
+
init_constants4();
|
|
34661
|
+
init_operator_chat_audit_events();
|
|
34662
|
+
CANONICAL_AUDIT_EVENT_CLASSES = [
|
|
34663
|
+
// Lifecycle / policy
|
|
34664
|
+
"policy_change",
|
|
34665
|
+
"approval_request",
|
|
34666
|
+
"audit_truncate",
|
|
34667
|
+
"lockdown",
|
|
34668
|
+
"unwrap",
|
|
34669
|
+
// Exit bundle (Tier 1)
|
|
34670
|
+
"exit_bundle_export",
|
|
34671
|
+
"exit_bundle_import_activate",
|
|
34672
|
+
"exit_bundle_rekey",
|
|
34673
|
+
// Cross-harness approval aggregator
|
|
34674
|
+
"cross_harness_approval_aggregated",
|
|
34675
|
+
"cross_harness_approval_resolved",
|
|
34676
|
+
"cross_harness_approval_deduped",
|
|
34677
|
+
"cross_harness_approval_payload_decrypted",
|
|
34678
|
+
"cross_harness_approval_audit_trail_viewed",
|
|
34679
|
+
"cross_harness_approval_replayed",
|
|
34680
|
+
// Composition (full set from constants.ts)
|
|
34681
|
+
...COMPOSITION_EVENT_TYPES,
|
|
34682
|
+
// Operator chat / concierge (full set from OPERATOR_CHAT_OPS)
|
|
34683
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CHAT,
|
|
34684
|
+
OPERATOR_CHAT_OPS.AGENT_INSPECT_PANEL_OPENED,
|
|
34685
|
+
OPERATOR_CHAT_OPS.CONCIERGE_HISTORY_READ,
|
|
34686
|
+
OPERATOR_CHAT_OPS.CONCIERGE_THREAD_DELETED,
|
|
34687
|
+
OPERATOR_CHAT_OPS.CONCIERGE_MEMORY_READ_FAILED,
|
|
34688
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
34689
|
+
// Bridge / commitment
|
|
34690
|
+
"bridge_commit",
|
|
34691
|
+
"bridge_verify",
|
|
34692
|
+
"bridge_attest",
|
|
34693
|
+
"proof_commitment",
|
|
34694
|
+
"proof_reveal",
|
|
34695
|
+
// Reputation
|
|
34696
|
+
"reputation_export",
|
|
34697
|
+
"reputation_import",
|
|
34698
|
+
"reputation_publish",
|
|
34699
|
+
"reputation_record",
|
|
34700
|
+
"reputation_query"
|
|
34701
|
+
];
|
|
34702
|
+
EVENT_SYNONYMS = [
|
|
34703
|
+
{ phrase: "approvals", canonical: ["approval_request", "cross_harness_approval_aggregated", "cross_harness_approval_resolved"] },
|
|
34704
|
+
{ phrase: "approval", canonical: ["approval_request"] },
|
|
34705
|
+
{ phrase: "policy changes", canonical: ["policy_change"] },
|
|
34706
|
+
{ phrase: "policy change", canonical: ["policy_change"] },
|
|
34707
|
+
{ phrase: "policy edits", canonical: ["policy_change"] },
|
|
34708
|
+
{ phrase: "lockdowns", canonical: ["lockdown"] },
|
|
34709
|
+
{ phrase: "exit bundles", canonical: ["exit_bundle_export", "exit_bundle_import_activate"] },
|
|
34710
|
+
{ phrase: "exit bundle", canonical: ["exit_bundle_export"] },
|
|
34711
|
+
{ phrase: "audit truncations", canonical: ["audit_truncate"] },
|
|
34712
|
+
{ phrase: "audit truncation", canonical: ["audit_truncate"] },
|
|
34713
|
+
{ phrase: "compositions", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34714
|
+
{ phrase: "receipts", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34715
|
+
{ phrase: "receipt verifications", canonical: ["composition_receipt_verified"] },
|
|
34716
|
+
{ phrase: "concierge chats", canonical: [OPERATOR_CHAT_OPS.CONCIERGE_CHAT] },
|
|
34717
|
+
{ phrase: "cross harness approvals", canonical: ["cross_harness_approval_aggregated", "cross_harness_approval_resolved"] }
|
|
34718
|
+
];
|
|
34719
|
+
MS_PER_HOUR = 60 * 60 * 1e3;
|
|
34720
|
+
MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
34721
|
+
NUMBER_WORDS = {
|
|
34722
|
+
a: 1,
|
|
34723
|
+
an: 1,
|
|
34724
|
+
one: 1,
|
|
34725
|
+
two: 2,
|
|
34726
|
+
three: 3,
|
|
34727
|
+
four: 4,
|
|
34728
|
+
five: 5,
|
|
34729
|
+
six: 6,
|
|
34730
|
+
seven: 7,
|
|
34731
|
+
eight: 8,
|
|
34732
|
+
nine: 9,
|
|
34733
|
+
ten: 10,
|
|
34734
|
+
twelve: 12,
|
|
34735
|
+
twentyfour: 24
|
|
34736
|
+
};
|
|
34737
|
+
TIME_MENTION_PROBE = /\b(yesterday|today|now|past|last|this\s+week|this\s+month|since|from|between|\d{4}-\d{2}-\d{2})\b/i;
|
|
34738
|
+
AGENT_MENTION_PROBE = /\bagent[s]?\b/i;
|
|
34739
|
+
EVENT_MENTION_PROBE = /\b(event|events|class|classes|approvals?|policy)\b/i;
|
|
34740
|
+
LLM_ASSIST_THRESHOLD = 0.5;
|
|
34741
|
+
}
|
|
34742
|
+
});
|
|
34743
|
+
function approxTokenLen2(text) {
|
|
33414
34744
|
return Math.ceil(text.length / 4);
|
|
33415
34745
|
}
|
|
33416
34746
|
function makeEventId(prefix) {
|
|
33417
34747
|
return `${prefix}-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
33418
34748
|
}
|
|
34749
|
+
function classifyFetcherError(error) {
|
|
34750
|
+
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
34751
|
+
if (msg.includes("timeout") || msg.includes("timed out")) return "timeout";
|
|
34752
|
+
if (msg.includes("schema") || msg.includes("invalid shape")) {
|
|
34753
|
+
return "schema_mismatch";
|
|
34754
|
+
}
|
|
34755
|
+
if (msg.includes("io") || msg.includes("read") || msg.includes("enoent") || msg.includes("eacces")) {
|
|
34756
|
+
return "io_failed";
|
|
34757
|
+
}
|
|
34758
|
+
return "unknown";
|
|
34759
|
+
}
|
|
33419
34760
|
function formatPriorTurnLine(turn) {
|
|
33420
34761
|
const label = turn.role === "user" ? "OPERATOR" : "CONCIERGE";
|
|
33421
34762
|
return `${label}: ${turn.content}`;
|
|
@@ -33423,18 +34764,21 @@ function formatPriorTurnLine(turn) {
|
|
|
33423
34764
|
function hashOf(input) {
|
|
33424
34765
|
return hashToString(sha256(stringToBytes(input)));
|
|
33425
34766
|
}
|
|
33426
|
-
var DEFAULT_CONCIERGE_MAX_TOKENS, DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS, DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS, DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET, DEFAULT_CONCIERGE_SESSION_TTL_MS, SANCTUARY_DOMAIN_REFERENCE, OperatorChatService;
|
|
34767
|
+
var DEFAULT_CONCIERGE_MAX_TOKENS, DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS, DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS, DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET, DEFAULT_CONCIERGE_SESSION_TTL_MS, DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET, SANCTUARY_DOMAIN_REFERENCE, OperatorChatService;
|
|
33427
34768
|
var init_operator_chat_service = __esm({
|
|
33428
34769
|
"src/chat/operator-chat-service.ts"() {
|
|
33429
34770
|
init_hashing();
|
|
33430
34771
|
init_encoding();
|
|
33431
34772
|
init_operator_chat_audit_events();
|
|
33432
34773
|
init_operator_chat_types();
|
|
34774
|
+
init_concierge_context_router();
|
|
34775
|
+
init_concierge_query_grammar();
|
|
33433
34776
|
DEFAULT_CONCIERGE_MAX_TOKENS = 512;
|
|
33434
34777
|
DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS = 10;
|
|
33435
34778
|
DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS = 24 * 60 * 60 * 1e3;
|
|
33436
34779
|
DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET = 500;
|
|
33437
34780
|
DEFAULT_CONCIERGE_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
34781
|
+
DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET = 2e3;
|
|
33438
34782
|
SANCTUARY_DOMAIN_REFERENCE = `Castle Architecture (four enforcement layers):
|
|
33439
34783
|
1. Castle Wall: OS-boundary egress filter enforced at the kernel level. Blocks unauthorized outbound calls even from prompt-injected agents.
|
|
33440
34784
|
2. Sentinels: internal observation via process introspection. Surfaces anomalies to the operator; does not enforce.
|
|
@@ -33476,6 +34820,11 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33476
34820
|
historyTokenBudget;
|
|
33477
34821
|
sessionTtlMs;
|
|
33478
34822
|
clock;
|
|
34823
|
+
contextFetchers;
|
|
34824
|
+
contextLlmAssist;
|
|
34825
|
+
dynamicContextBudget;
|
|
34826
|
+
agentRegistry;
|
|
34827
|
+
grammarLlmAssist;
|
|
33479
34828
|
/**
|
|
33480
34829
|
* In-memory thread_id assigned to the active concierge session.
|
|
33481
34830
|
* The first sendConcierge call after construction allocates a fresh
|
|
@@ -33507,6 +34856,19 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33507
34856
|
this.historyTokenBudget = deps.conciergeHistoryTokenBudget !== void 0 && deps.conciergeHistoryTokenBudget > 0 ? deps.conciergeHistoryTokenBudget : DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET;
|
|
33508
34857
|
this.sessionTtlMs = deps.conciergeSessionTtlMs !== void 0 && deps.conciergeSessionTtlMs > 0 ? deps.conciergeSessionTtlMs : DEFAULT_CONCIERGE_SESSION_TTL_MS;
|
|
33509
34858
|
this.clock = deps.conciergeClock ?? (() => Date.now());
|
|
34859
|
+
if (deps.conciergeContextFetchers) {
|
|
34860
|
+
this.contextFetchers = deps.conciergeContextFetchers;
|
|
34861
|
+
}
|
|
34862
|
+
if (deps.conciergeContextLlmAssist) {
|
|
34863
|
+
this.contextLlmAssist = deps.conciergeContextLlmAssist;
|
|
34864
|
+
}
|
|
34865
|
+
this.dynamicContextBudget = deps.conciergeDynamicContextBudget !== void 0 && deps.conciergeDynamicContextBudget > 0 ? deps.conciergeDynamicContextBudget : DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET;
|
|
34866
|
+
if (deps.conciergeAgentRegistry) {
|
|
34867
|
+
this.agentRegistry = deps.conciergeAgentRegistry;
|
|
34868
|
+
}
|
|
34869
|
+
if (deps.conciergeGrammarLlmAssist) {
|
|
34870
|
+
this.grammarLlmAssist = deps.conciergeGrammarLlmAssist;
|
|
34871
|
+
}
|
|
33510
34872
|
}
|
|
33511
34873
|
// ── Concierge ─────────────────────────────────────────────────────────
|
|
33512
34874
|
/**
|
|
@@ -33565,11 +34927,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33565
34927
|
await this.memory.appendTurn(threadId, "user", trimmed).catch(() => {
|
|
33566
34928
|
});
|
|
33567
34929
|
}
|
|
34930
|
+
const parsedGrammar = await this.runGrammarParse(filterResult.filtered);
|
|
33568
34931
|
const start = Date.now();
|
|
33569
34932
|
let conciergeBody;
|
|
33570
34933
|
let servedBy = "disabled";
|
|
33571
34934
|
let displayLabel = "Concierge: substrate not configured";
|
|
33572
34935
|
let outcome = "substrate_disabled";
|
|
34936
|
+
let dynamicCategoriesIncluded = [];
|
|
33573
34937
|
if (!this.substrateSelector) {
|
|
33574
34938
|
conciergeBody = "Concierge unavailable. The substrate selector is not configured for this fortress. Pick a substrate in the Policy center to enable concierge replies.";
|
|
33575
34939
|
} else {
|
|
@@ -33581,7 +34945,15 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33581
34945
|
conciergeBody = "Concierge unavailable. The chosen substrate does not support summarization. Pick a different substrate in the Policy center.";
|
|
33582
34946
|
outcome = "substrate_disabled";
|
|
33583
34947
|
} else {
|
|
33584
|
-
const
|
|
34948
|
+
const dynamicResult = await this.runDynamicContextFold(
|
|
34949
|
+
filterResult.filtered,
|
|
34950
|
+
parsedGrammar
|
|
34951
|
+
);
|
|
34952
|
+
dynamicCategoriesIncluded = dynamicResult.categoriesIncluded;
|
|
34953
|
+
const context = await this.assembleConciergeContext(
|
|
34954
|
+
priorTurns,
|
|
34955
|
+
dynamicResult.section
|
|
34956
|
+
);
|
|
33585
34957
|
const response = await this.substrateSelector.invokeSummarize(
|
|
33586
34958
|
"concierge",
|
|
33587
34959
|
{
|
|
@@ -33645,7 +35017,9 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33645
35017
|
...assistantTurnId !== void 0 ? { turn_index: assistantTurnId } : {},
|
|
33646
35018
|
...this.memory ? {
|
|
33647
35019
|
prior_turns_folded: memoryReadFailureReason === null ? priorTurns.length : 0
|
|
33648
|
-
} : {}
|
|
35020
|
+
} : {},
|
|
35021
|
+
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {},
|
|
35022
|
+
parsed_grammar: auditSafeSummary(parsedGrammar)
|
|
33649
35023
|
};
|
|
33650
35024
|
this.emit(OPERATOR_CHAT_OPS.CONCIERGE_CHAT, payload, outcome === "ok" ? "success" : "failure");
|
|
33651
35025
|
return {
|
|
@@ -33796,10 +35170,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33796
35170
|
* ## Sanctuary reference
|
|
33797
35171
|
* <static domain reference block>
|
|
33798
35172
|
*
|
|
35173
|
+
* ## Live fortress context ← WP-V1.3-9 Tau-3, when present
|
|
35174
|
+
* ### <Category>
|
|
35175
|
+
* <fetcher payload>
|
|
35176
|
+
*
|
|
33799
35177
|
* ## Prior conversation ← WP-V1.3-9 Tau-2, when present
|
|
33800
35178
|
* OPERATOR: ...
|
|
33801
35179
|
* CONCIERGE: ...
|
|
33802
|
-
* ---
|
|
33803
35180
|
*
|
|
33804
35181
|
* ## Recent activity
|
|
33805
35182
|
* <recentActivity output>
|
|
@@ -33818,13 +35195,14 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33818
35195
|
* if available; the v1.2 selector does not expose one, so structured
|
|
33819
35196
|
* serialization is the canonical path for v1.3.
|
|
33820
35197
|
*/
|
|
33821
|
-
async assembleConciergeContext(priorTurns = []) {
|
|
35198
|
+
async assembleConciergeContext(priorTurns = [], dynamicSection = "") {
|
|
33822
35199
|
const ref = `## Sanctuary reference
|
|
33823
35200
|
${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
33824
35201
|
const priorSection = this.formatPriorTurnsSection(priorTurns);
|
|
33825
35202
|
if (!this.contextProviders) {
|
|
33826
35203
|
return [
|
|
33827
35204
|
ref,
|
|
35205
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33828
35206
|
...priorSection ? [priorSection] : [],
|
|
33829
35207
|
"## Recent activity\n(no providers wired)",
|
|
33830
35208
|
"## Wrapped agents\n(no providers wired)",
|
|
@@ -33838,6 +35216,7 @@ ${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
|
33838
35216
|
]);
|
|
33839
35217
|
return [
|
|
33840
35218
|
ref,
|
|
35219
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33841
35220
|
...priorSection ? [priorSection] : [],
|
|
33842
35221
|
`## Recent activity
|
|
33843
35222
|
${activity}`,
|
|
@@ -33847,6 +35226,69 @@ ${agents}`,
|
|
|
33847
35226
|
${inbox}`
|
|
33848
35227
|
].join("\n\n");
|
|
33849
35228
|
}
|
|
35229
|
+
/**
|
|
35230
|
+
* Run the WP-V1.3-9 Tau-3 dynamic-context fold for a single round-
|
|
35231
|
+
* trip. Fail-soft on every axis: missing fetchers short-circuit to
|
|
35232
|
+
* an empty fold, fetcher failures emit a per-category audit event
|
|
35233
|
+
* and are omitted from the rendered section, an LLM-assist failure
|
|
35234
|
+
* proceeds with no fold. Returns the rendered section + the list of
|
|
35235
|
+
* categories whose data made it into the section (used for the
|
|
35236
|
+
* round-trip audit emission).
|
|
35237
|
+
*
|
|
35238
|
+
* Tau-4: receives the pre-parsed `ParsedQuery` and forwards it as the
|
|
35239
|
+
* `parsed` opt to `foldContext`, so fetchers see the structured
|
|
35240
|
+
* `FetcherHints` derived from it.
|
|
35241
|
+
*/
|
|
35242
|
+
async runDynamicContextFold(query, parsedGrammar) {
|
|
35243
|
+
if (!this.contextFetchers) {
|
|
35244
|
+
return { section: "", categoriesIncluded: [] };
|
|
35245
|
+
}
|
|
35246
|
+
const result = await foldContext(query, this.contextFetchers, {
|
|
35247
|
+
maxTokens: this.dynamicContextBudget,
|
|
35248
|
+
...this.contextLlmAssist ? { llmAssistClassify: this.contextLlmAssist } : {},
|
|
35249
|
+
onFetcherFailure: (category, error) => {
|
|
35250
|
+
this.emitContextFetcherFailed(category, classifyFetcherError(error));
|
|
35251
|
+
},
|
|
35252
|
+
parsed: parsedGrammar
|
|
35253
|
+
});
|
|
35254
|
+
return result;
|
|
35255
|
+
}
|
|
35256
|
+
/**
|
|
35257
|
+
* WP-V1.3-9 Tau-4: parse the (PII-filtered) operator query into a
|
|
35258
|
+
* `ParsedQuery`. Routes through the LLM-assist completion hook when
|
|
35259
|
+
* configured and the rule-based parse is below
|
|
35260
|
+
* `LLM_ASSIST_THRESHOLD`. Always returns a parse object (never
|
|
35261
|
+
* throws) so the audit emission can carry the result unconditionally.
|
|
35262
|
+
*/
|
|
35263
|
+
async runGrammarParse(query) {
|
|
35264
|
+
return parseQueryWithLlmAssist(query, this.grammarLlmAssist, {
|
|
35265
|
+
...this.agentRegistry !== void 0 ? { registry: this.agentRegistry } : {},
|
|
35266
|
+
eventClassEnum: CANONICAL_AUDIT_EVENT_CLASSES
|
|
35267
|
+
});
|
|
35268
|
+
}
|
|
35269
|
+
/**
|
|
35270
|
+
* Emit the WP-V1.3-9 Tau-3 fetcher-failure audit event. Pulled out
|
|
35271
|
+
* of the fold path so the dynamic-context handler stays readable.
|
|
35272
|
+
* Emits with `result: "failure"` since the named category dropped
|
|
35273
|
+
* from the rendered section for this round-trip.
|
|
35274
|
+
*/
|
|
35275
|
+
emitContextFetcherFailed(category, failureReason) {
|
|
35276
|
+
const payload = {
|
|
35277
|
+
version: "1.2",
|
|
35278
|
+
event_id: makeEventId("conc-ctxfail"),
|
|
35279
|
+
emitted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35280
|
+
identity_id: this.identityId,
|
|
35281
|
+
kind: "operator_concierge_context_fetcher_failed",
|
|
35282
|
+
surface: "concierge",
|
|
35283
|
+
category,
|
|
35284
|
+
failure_reason: failureReason
|
|
35285
|
+
};
|
|
35286
|
+
this.emit(
|
|
35287
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
35288
|
+
payload,
|
|
35289
|
+
"failure"
|
|
35290
|
+
);
|
|
35291
|
+
}
|
|
33850
35292
|
/**
|
|
33851
35293
|
* Render the prior-conversation section with token-budget enforcement
|
|
33852
35294
|
* (WP-V1.3-9 Tau-2). Drops oldest turns first when the rendered
|
|
@@ -33857,14 +35299,14 @@ ${inbox}`
|
|
|
33857
35299
|
if (turns.length === 0) return "";
|
|
33858
35300
|
const HEADER = "## Prior conversation";
|
|
33859
35301
|
const lines = turns.map(formatPriorTurnLine);
|
|
33860
|
-
const headerTokens =
|
|
35302
|
+
const headerTokens = approxTokenLen2(`${HEADER}
|
|
33861
35303
|
`);
|
|
33862
|
-
const sepTokens =
|
|
35304
|
+
const sepTokens = approxTokenLen2("\n");
|
|
33863
35305
|
let runningTokens = headerTokens;
|
|
33864
35306
|
let runningLines = [];
|
|
33865
35307
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
33866
35308
|
const line = lines[i];
|
|
33867
|
-
const tokens =
|
|
35309
|
+
const tokens = approxTokenLen2(line) + (runningLines.length > 0 ? sepTokens : 0);
|
|
33868
35310
|
if (runningTokens + tokens > this.historyTokenBudget) break;
|
|
33869
35311
|
runningTokens += tokens;
|
|
33870
35312
|
runningLines.push(line);
|
|
@@ -33892,7 +35334,7 @@ ${runningLines.join("\n")}`;
|
|
|
33892
35334
|
function chatStorageKey(surface, threadKey) {
|
|
33893
35335
|
return `${surface}.${threadKey}`;
|
|
33894
35336
|
}
|
|
33895
|
-
var OPERATOR_CHAT_NAMESPACE,
|
|
35337
|
+
var OPERATOR_CHAT_NAMESPACE, HKDF_INFO2, OperatorChatStore;
|
|
33896
35338
|
var init_operator_chat_store = __esm({
|
|
33897
35339
|
"src/chat/operator-chat-store.ts"() {
|
|
33898
35340
|
init_encryption();
|
|
@@ -33900,13 +35342,13 @@ var init_operator_chat_store = __esm({
|
|
|
33900
35342
|
init_encoding();
|
|
33901
35343
|
init_operator_chat_types();
|
|
33902
35344
|
OPERATOR_CHAT_NAMESPACE = "_chat";
|
|
33903
|
-
|
|
35345
|
+
HKDF_INFO2 = "operator-chat-store-v1";
|
|
33904
35346
|
OperatorChatStore = class {
|
|
33905
35347
|
storage;
|
|
33906
35348
|
encryptionKey;
|
|
33907
35349
|
constructor(storage, masterKey) {
|
|
33908
35350
|
this.storage = storage;
|
|
33909
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
35351
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO2);
|
|
33910
35352
|
}
|
|
33911
35353
|
/**
|
|
33912
35354
|
* Load a thread. Returns null if no record exists or if the on-disk
|
|
@@ -33991,7 +35433,7 @@ var init_operator_chat_store = __esm({
|
|
|
33991
35433
|
function bundleKey(threadId) {
|
|
33992
35434
|
return `${CONCIERGE_MEMORY_KEY_PREFIX}${threadId}`;
|
|
33993
35435
|
}
|
|
33994
|
-
function
|
|
35436
|
+
function stripKeyPrefix2(key) {
|
|
33995
35437
|
if (!key.startsWith(CONCIERGE_MEMORY_KEY_PREFIX)) return null;
|
|
33996
35438
|
return key.slice(CONCIERGE_MEMORY_KEY_PREFIX.length);
|
|
33997
35439
|
}
|
|
@@ -34002,7 +35444,7 @@ function lastTurnId(bundle) {
|
|
|
34002
35444
|
}
|
|
34003
35445
|
return max;
|
|
34004
35446
|
}
|
|
34005
|
-
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX,
|
|
35447
|
+
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX, HKDF_INFO3, DEFAULT_CONCIERGE_RETENTION_DAYS, MAX_BUNDLE_BYTES3, ConciergeMemoryStore;
|
|
34006
35448
|
var init_concierge_memory_store = __esm({
|
|
34007
35449
|
"src/chat/concierge-memory-store.ts"() {
|
|
34008
35450
|
init_encryption();
|
|
@@ -34010,9 +35452,9 @@ var init_concierge_memory_store = __esm({
|
|
|
34010
35452
|
init_encoding();
|
|
34011
35453
|
CONCIERGE_MEMORY_NAMESPACE = "_chat";
|
|
34012
35454
|
CONCIERGE_MEMORY_KEY_PREFIX = "concierge_memory.";
|
|
34013
|
-
|
|
35455
|
+
HKDF_INFO3 = "concierge-memory-store-v1";
|
|
34014
35456
|
DEFAULT_CONCIERGE_RETENTION_DAYS = 30;
|
|
34015
|
-
|
|
35457
|
+
MAX_BUNDLE_BYTES3 = 4 * 1024 * 1024;
|
|
34016
35458
|
ConciergeMemoryStore = class {
|
|
34017
35459
|
storage;
|
|
34018
35460
|
encryptionKey;
|
|
@@ -34021,7 +35463,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34021
35463
|
locks;
|
|
34022
35464
|
constructor(opts) {
|
|
34023
35465
|
this.storage = opts.storage;
|
|
34024
|
-
this.encryptionKey = derivePurposeKey(opts.masterKey,
|
|
35466
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO3);
|
|
34025
35467
|
this.fortressId = opts.fortressId;
|
|
34026
35468
|
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_CONCIERGE_RETENTION_DAYS;
|
|
34027
35469
|
this.locks = /* @__PURE__ */ new Map();
|
|
@@ -34100,7 +35542,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34100
35542
|
return { ok: false, reason: "io_failed" };
|
|
34101
35543
|
}
|
|
34102
35544
|
if (!raw) return { ok: true, turns: [] };
|
|
34103
|
-
if (raw.length >
|
|
35545
|
+
if (raw.length > MAX_BUNDLE_BYTES3) {
|
|
34104
35546
|
return { ok: false, reason: "oversize_bundle" };
|
|
34105
35547
|
}
|
|
34106
35548
|
let envelope;
|
|
@@ -34147,7 +35589,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34147
35589
|
);
|
|
34148
35590
|
const summaries = [];
|
|
34149
35591
|
for (const meta of entries) {
|
|
34150
|
-
const threadId =
|
|
35592
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34151
35593
|
if (threadId === null) continue;
|
|
34152
35594
|
const bundle = await this.loadBundle(threadId);
|
|
34153
35595
|
if (!bundle || bundle.turns.length === 0) continue;
|
|
@@ -34200,7 +35642,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34200
35642
|
);
|
|
34201
35643
|
let pruned = 0;
|
|
34202
35644
|
for (const meta of entries) {
|
|
34203
|
-
const threadId =
|
|
35645
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34204
35646
|
if (threadId === null) continue;
|
|
34205
35647
|
pruned += await this.withLock(threadId, async () => {
|
|
34206
35648
|
const bundle = await this.loadBundle(threadId);
|
|
@@ -34231,7 +35673,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34231
35673
|
return null;
|
|
34232
35674
|
}
|
|
34233
35675
|
if (!raw) return null;
|
|
34234
|
-
if (raw.length >
|
|
35676
|
+
if (raw.length > MAX_BUNDLE_BYTES3) return null;
|
|
34235
35677
|
try {
|
|
34236
35678
|
const envelope = JSON.parse(bytesToString(raw));
|
|
34237
35679
|
const aad = stringToBytes(threadId);
|
|
@@ -34322,7 +35764,18 @@ function buildV11Bindings(inputs) {
|
|
|
34322
35764
|
registry
|
|
34323
35765
|
}),
|
|
34324
35766
|
conciergePiiFilter: buildConciergePiiFilter(),
|
|
34325
|
-
conciergeMemory
|
|
35767
|
+
conciergeMemory,
|
|
35768
|
+
conciergeContextFetchers: buildConciergeContextFetchers({
|
|
35769
|
+
auditLog: inputs.auditLog,
|
|
35770
|
+
identityId: inputs.identityId,
|
|
35771
|
+
registry
|
|
35772
|
+
}),
|
|
35773
|
+
...inputs.intelligenceSelector ? {
|
|
35774
|
+
conciergeContextLlmAssist: buildConciergeContextLlmAssist({
|
|
35775
|
+
selector: inputs.intelligenceSelector,
|
|
35776
|
+
identityId: inputs.identityId
|
|
35777
|
+
})
|
|
35778
|
+
} : {}
|
|
34326
35779
|
});
|
|
34327
35780
|
}
|
|
34328
35781
|
const hubService = new HubService({
|
|
@@ -34383,6 +35836,107 @@ function buildConciergeContextProviders(args) {
|
|
|
34383
35836
|
}
|
|
34384
35837
|
};
|
|
34385
35838
|
}
|
|
35839
|
+
function buildConciergeContextFetchers(args) {
|
|
35840
|
+
const empty = async () => "";
|
|
35841
|
+
return {
|
|
35842
|
+
templates: async () => {
|
|
35843
|
+
const entries = listTemplates();
|
|
35844
|
+
if (entries.length === 0) return "(no templates installed)";
|
|
35845
|
+
const lines = entries.map((e) => {
|
|
35846
|
+
const m = e.metadata;
|
|
35847
|
+
return `${m.name} (tier ${m.tier}, channel ${m.channel}, target ${m.target_archetype})`;
|
|
35848
|
+
});
|
|
35849
|
+
return lines.join("\n");
|
|
35850
|
+
},
|
|
35851
|
+
agent_state: async (agentNameHint) => {
|
|
35852
|
+
const records = args.registry.list({ identity_id: args.identityId });
|
|
35853
|
+
if (records.length === 0) return "(no wrapped agents)";
|
|
35854
|
+
const filtered = agentNameHint ? records.filter(
|
|
35855
|
+
(r) => r.agent_id.toLowerCase().includes(agentNameHint.toLowerCase()) || r.harness.toLowerCase().includes(agentNameHint.toLowerCase())
|
|
35856
|
+
) : records;
|
|
35857
|
+
const target = filtered.length > 0 ? filtered : records;
|
|
35858
|
+
const lines = target.slice(0, 20).map((r) => {
|
|
35859
|
+
const tmpl = typeof r.channel_template_id === "string" ? r.channel_template_id : "no_template";
|
|
35860
|
+
return `${r.agent_id} harness=${r.harness} status=${r.status} template=${tmpl}`;
|
|
35861
|
+
});
|
|
35862
|
+
return lines.join("\n");
|
|
35863
|
+
},
|
|
35864
|
+
agent_activity: async (agentNameHint) => {
|
|
35865
|
+
const result = await args.auditLog.query({ limit: 50 });
|
|
35866
|
+
const owned = result.entries.filter(
|
|
35867
|
+
(e) => e.identity_id === args.identityId
|
|
35868
|
+
);
|
|
35869
|
+
const filtered = agentNameHint ? owned.filter((e) => {
|
|
35870
|
+
const agentId = e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : "";
|
|
35871
|
+
return agentId.toLowerCase().includes(agentNameHint.toLowerCase());
|
|
35872
|
+
}) : owned;
|
|
35873
|
+
const tail = (filtered.length > 0 ? filtered : owned).slice(-20);
|
|
35874
|
+
if (tail.length === 0) return "(no activity)";
|
|
35875
|
+
return tail.map((e) => {
|
|
35876
|
+
const agentId = (e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : null) ?? "_fortress";
|
|
35877
|
+
return `${e.timestamp} ${e.layer}.${e.operation} agent=${agentId} result=${e.result}`;
|
|
35878
|
+
}).join("\n");
|
|
35879
|
+
},
|
|
35880
|
+
audit_log: async () => {
|
|
35881
|
+
const result = await args.auditLog.query({ limit: 30 });
|
|
35882
|
+
const owned = result.entries.filter(
|
|
35883
|
+
(e) => e.identity_id === args.identityId
|
|
35884
|
+
);
|
|
35885
|
+
if (owned.length === 0) return "(no audit log entries)";
|
|
35886
|
+
return owned.slice(-30).map(
|
|
35887
|
+
(e) => `${e.timestamp} ${e.layer}.${e.operation} result=${e.result}`
|
|
35888
|
+
).join("\n");
|
|
35889
|
+
},
|
|
35890
|
+
sentinel_findings: empty,
|
|
35891
|
+
anomaly_alerts: empty,
|
|
35892
|
+
recent_receipts: async () => {
|
|
35893
|
+
const result = await args.auditLog.query({ limit: 100 });
|
|
35894
|
+
const owned = result.entries.filter(
|
|
35895
|
+
(e) => e.identity_id === args.identityId && e.operation.startsWith("composition_")
|
|
35896
|
+
);
|
|
35897
|
+
if (owned.length === 0) return "(no recent composition events)";
|
|
35898
|
+
return owned.slice(-15).map((e) => `${e.timestamp} ${e.operation} result=${e.result}`).join("\n");
|
|
35899
|
+
},
|
|
35900
|
+
verascore_deltas: empty
|
|
35901
|
+
};
|
|
35902
|
+
}
|
|
35903
|
+
function buildConciergeContextLlmAssist(args) {
|
|
35904
|
+
return async (query, categories) => {
|
|
35905
|
+
const labelList = categories.map((c) => `- ${c}`).join("\n");
|
|
35906
|
+
const prompt2 = `You are a router. Classify the operator's query into one of the categories below or "none".
|
|
35907
|
+
Reply with exactly one token: one category name or "none".
|
|
35908
|
+
|
|
35909
|
+
Categories:
|
|
35910
|
+
${labelList}
|
|
35911
|
+
|
|
35912
|
+
Query: ${query}
|
|
35913
|
+
|
|
35914
|
+
Category:`;
|
|
35915
|
+
try {
|
|
35916
|
+
const handle = await args.selector.getSubstrate("concierge");
|
|
35917
|
+
if (!handle.capability.summarize) return "none";
|
|
35918
|
+
const response = await args.selector.invokeSummarize("concierge", {
|
|
35919
|
+
kind: "summarize",
|
|
35920
|
+
context: prompt2,
|
|
35921
|
+
query: "Output the single category token.",
|
|
35922
|
+
maxTokens: 16
|
|
35923
|
+
});
|
|
35924
|
+
if (response.failureClass || response.body.kind !== "summarize") {
|
|
35925
|
+
return "none";
|
|
35926
|
+
}
|
|
35927
|
+
const raw = response.body.text.trim().toLowerCase();
|
|
35928
|
+
const head = raw.split(/\s|[.,!?:;]/)[0] ?? "";
|
|
35929
|
+
const normalized = head.replace(/[^a-z_]/g, "");
|
|
35930
|
+
const known = categories;
|
|
35931
|
+
if (known.includes(normalized)) {
|
|
35932
|
+
return normalized;
|
|
35933
|
+
}
|
|
35934
|
+
return "none";
|
|
35935
|
+
} catch {
|
|
35936
|
+
return "none";
|
|
35937
|
+
}
|
|
35938
|
+
};
|
|
35939
|
+
}
|
|
34386
35940
|
function buildConciergePiiFilter() {
|
|
34387
35941
|
return {
|
|
34388
35942
|
filter(input) {
|
|
@@ -34410,6 +35964,7 @@ var init_wiring = __esm({
|
|
|
34410
35964
|
init_agent_registry_persistence();
|
|
34411
35965
|
init_operator_chat_index();
|
|
34412
35966
|
init_privacy_filter();
|
|
35967
|
+
init_registry();
|
|
34413
35968
|
CapabilityErrorAgentController = class {
|
|
34414
35969
|
fail(action) {
|
|
34415
35970
|
throw new HubCapabilityError(
|
|
@@ -34557,7 +36112,7 @@ var init_defaults = __esm({
|
|
|
34557
36112
|
});
|
|
34558
36113
|
|
|
34559
36114
|
// src/intelligence/policy-store.ts
|
|
34560
|
-
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY,
|
|
36115
|
+
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY, HKDF_INFO4, IntelligenceConfigStore;
|
|
34561
36116
|
var init_policy_store = __esm({
|
|
34562
36117
|
"src/intelligence/policy-store.ts"() {
|
|
34563
36118
|
init_encryption();
|
|
@@ -34566,13 +36121,13 @@ var init_policy_store = __esm({
|
|
|
34566
36121
|
init_defaults();
|
|
34567
36122
|
INTELLIGENCE_NAMESPACE = "_intelligence";
|
|
34568
36123
|
SUBSTRATE_CONFIG_KEY = "substrate-config";
|
|
34569
|
-
|
|
36124
|
+
HKDF_INFO4 = "intelligence-substrate-config";
|
|
34570
36125
|
IntelligenceConfigStore = class {
|
|
34571
36126
|
storage;
|
|
34572
36127
|
encryptionKey;
|
|
34573
36128
|
constructor(storage, masterKey) {
|
|
34574
36129
|
this.storage = storage;
|
|
34575
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
36130
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO4);
|
|
34576
36131
|
}
|
|
34577
36132
|
/**
|
|
34578
36133
|
* Load the operator's substrate config from disk. Returns the config
|
|
@@ -36222,7 +37777,7 @@ var init_memory = __esm({
|
|
|
36222
37777
|
|
|
36223
37778
|
// src/contracts/v1.1/constants.ts
|
|
36224
37779
|
var SIGNATURE_SCHEME_V12, EXIT_BUNDLE_MANIFEST_VERSION, EXIT_BUNDLE_ARTIFACT_KINDS;
|
|
36225
|
-
var
|
|
37780
|
+
var init_constants5 = __esm({
|
|
36226
37781
|
"src/contracts/v1.1/constants.ts"() {
|
|
36227
37782
|
SIGNATURE_SCHEME_V12 = "ed25519-v1";
|
|
36228
37783
|
EXIT_BUNDLE_MANIFEST_VERSION = "SANCTUARY_EXIT_BUNDLE_V1";
|
|
@@ -36640,7 +38195,7 @@ async function verifyExitBundle(bundleDir, options = {}) {
|
|
|
36640
38195
|
var InvalidExitBundleError, PRIVATE_MATERIAL_KEYS;
|
|
36641
38196
|
var init_verifier2 = __esm({
|
|
36642
38197
|
"src/exit/verifier.ts"() {
|
|
36643
|
-
|
|
38198
|
+
init_constants5();
|
|
36644
38199
|
init_exit_bundle_manifest();
|
|
36645
38200
|
init_encoding();
|
|
36646
38201
|
init_hashing();
|
|
@@ -37452,7 +39007,7 @@ var init_bundle = __esm({
|
|
|
37452
39007
|
"src/exit/bundle.ts"() {
|
|
37453
39008
|
init_state_store();
|
|
37454
39009
|
init_config();
|
|
37455
|
-
|
|
39010
|
+
init_constants5();
|
|
37456
39011
|
init_canonical_json();
|
|
37457
39012
|
init_hashing();
|
|
37458
39013
|
init_encoding();
|
|
@@ -38490,12 +40045,18 @@ ${err.message}
|
|
|
38490
40045
|
} : void 0;
|
|
38491
40046
|
const fortressIdForAggregator = fortressIdFromStoragePath(config.storage_path);
|
|
38492
40047
|
const aggregatorIdentityId = identityManager.getPrimaryIdentityId() ?? `fortress:${config.storage_path}`;
|
|
40048
|
+
const aggregatorPayloadStore = new AggregatorPayloadStore({
|
|
40049
|
+
storage,
|
|
40050
|
+
masterKey,
|
|
40051
|
+
fortressId: fortressIdForAggregator
|
|
40052
|
+
});
|
|
38493
40053
|
const approvalAggregator = new ApprovalAggregator({
|
|
38494
40054
|
storage,
|
|
38495
40055
|
masterKey,
|
|
38496
40056
|
auditLog,
|
|
38497
40057
|
identityId: aggregatorIdentityId,
|
|
38498
|
-
fortressId: fortressIdForAggregator
|
|
40058
|
+
fortressId: fortressIdForAggregator,
|
|
40059
|
+
payloadStore: aggregatorPayloadStore
|
|
38499
40060
|
});
|
|
38500
40061
|
const wrappedApprovalChannel = new AggregatorBackedChannel({
|
|
38501
40062
|
underlying: approvalChannel,
|
|
@@ -38709,6 +40270,7 @@ var init_src = __esm({
|
|
|
38709
40270
|
init_gate();
|
|
38710
40271
|
init_approval_aggregator();
|
|
38711
40272
|
init_aggregator_backed_channel();
|
|
40273
|
+
init_aggregator_store();
|
|
38712
40274
|
init_tools4();
|
|
38713
40275
|
init_router();
|
|
38714
40276
|
init_router();
|