@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.cjs
CHANGED
|
@@ -5044,7 +5044,8 @@ var init_constants = __esm({
|
|
|
5044
5044
|
RESERVED_EVENT_TYPE_PREFIXES = [
|
|
5045
5045
|
"EXTENSION_",
|
|
5046
5046
|
"cross_fortress_",
|
|
5047
|
-
"multi_master_"
|
|
5047
|
+
"multi_master_",
|
|
5048
|
+
"cross_harness_approval_"
|
|
5048
5049
|
];
|
|
5049
5050
|
RESERVED_EXTENSION_ENVELOPE_KEYS = [
|
|
5050
5051
|
"cross_fortress_read_grant",
|
|
@@ -9236,9 +9237,9 @@ function fingerprintDID(did) {
|
|
|
9236
9237
|
return `${raw.slice(0, 6)}\u2026${raw.slice(-6)}`;
|
|
9237
9238
|
}
|
|
9238
9239
|
function countInjectionsToday(audit) {
|
|
9239
|
-
const
|
|
9240
|
-
|
|
9241
|
-
const cutoff =
|
|
9240
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9241
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9242
|
+
const cutoff = startOfDay2.getTime();
|
|
9242
9243
|
return audit.filter((e) => {
|
|
9243
9244
|
const ts = new Date(e.timestamp).getTime();
|
|
9244
9245
|
if (isNaN(ts) || ts < cutoff) return false;
|
|
@@ -9247,9 +9248,9 @@ function countInjectionsToday(audit) {
|
|
|
9247
9248
|
}).length;
|
|
9248
9249
|
}
|
|
9249
9250
|
function countProofsToday(audit) {
|
|
9250
|
-
const
|
|
9251
|
-
|
|
9252
|
-
const cutoff =
|
|
9251
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9252
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9253
|
+
const cutoff = startOfDay2.getTime();
|
|
9253
9254
|
return audit.filter((e) => {
|
|
9254
9255
|
if (e.layer !== "l3") return false;
|
|
9255
9256
|
if (!PROOF_CREATION_OPS.has(e.operation)) return false;
|
|
@@ -17218,6 +17219,45 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17218
17219
|
await handleStream2(deps, res);
|
|
17219
17220
|
return true;
|
|
17220
17221
|
}
|
|
17222
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/revision`) {
|
|
17223
|
+
const revision = await deps.aggregator.getRevision();
|
|
17224
|
+
writeJSON4(res, 200, { ok: true, data: { revision } });
|
|
17225
|
+
return true;
|
|
17226
|
+
}
|
|
17227
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/sync`) {
|
|
17228
|
+
const sinceRaw = url.searchParams.get("since_revision");
|
|
17229
|
+
const sinceParsed = sinceRaw === null ? 0 : Number.parseInt(sinceRaw, 10);
|
|
17230
|
+
const sinceRevision = Number.isFinite(sinceParsed) && sinceParsed >= 0 ? sinceParsed : 0;
|
|
17231
|
+
const limit = parseLimit2(
|
|
17232
|
+
url.searchParams.get("limit"),
|
|
17233
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17234
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17235
|
+
);
|
|
17236
|
+
const delta = await deps.aggregator.getSync({ sinceRevision, limit });
|
|
17237
|
+
writeJSON4(res, 200, { ok: true, data: delta });
|
|
17238
|
+
return true;
|
|
17239
|
+
}
|
|
17240
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/history`) {
|
|
17241
|
+
const limit = parseLimit2(
|
|
17242
|
+
url.searchParams.get("limit"),
|
|
17243
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17244
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17245
|
+
);
|
|
17246
|
+
const statusRaw = url.searchParams.get("status");
|
|
17247
|
+
const sinceTs = url.searchParams.get("since") ?? void 0;
|
|
17248
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17249
|
+
const filterStatus = statusRaw && isStatusFilter(statusRaw) && statusRaw !== "pending" ? statusRaw : void 0;
|
|
17250
|
+
const entries = await deps.aggregator.getHistory(
|
|
17251
|
+
{
|
|
17252
|
+
limit,
|
|
17253
|
+
...filterStatus !== void 0 ? { status: filterStatus } : {},
|
|
17254
|
+
...sinceTs !== void 0 ? { sinceTs } : {}
|
|
17255
|
+
},
|
|
17256
|
+
operatorId
|
|
17257
|
+
);
|
|
17258
|
+
writeJSON4(res, 200, { ok: true, data: { entries } });
|
|
17259
|
+
return true;
|
|
17260
|
+
}
|
|
17221
17261
|
if (method === "GET" && path === APPROVAL_INBOX_API_PREFIX) {
|
|
17222
17262
|
const limit = parseLimit2(
|
|
17223
17263
|
url.searchParams.get("limit"),
|
|
@@ -17240,11 +17280,39 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17240
17280
|
writeJSON4(res, 404, { ok: false, error: "not_found", path });
|
|
17241
17281
|
return true;
|
|
17242
17282
|
}
|
|
17243
|
-
if (method === "GET" && entryMatch.action ===
|
|
17244
|
-
const
|
|
17245
|
-
|
|
17246
|
-
(
|
|
17283
|
+
if (method === "GET" && entryMatch.action === "audit-trail") {
|
|
17284
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17285
|
+
if (!entry) {
|
|
17286
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17287
|
+
return true;
|
|
17288
|
+
}
|
|
17289
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17290
|
+
const trail = await deps.aggregator.getAuditTrail(
|
|
17291
|
+
entryMatch.aggregatorId,
|
|
17292
|
+
operatorId
|
|
17247
17293
|
);
|
|
17294
|
+
writeJSON4(res, 200, { ok: true, data: { entry, audit_trail: trail } });
|
|
17295
|
+
return true;
|
|
17296
|
+
}
|
|
17297
|
+
if (method === "GET" && entryMatch.action === "payload") {
|
|
17298
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17299
|
+
if (!entry) {
|
|
17300
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17301
|
+
return true;
|
|
17302
|
+
}
|
|
17303
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17304
|
+
const payload = await deps.aggregator.getFullPayloadWithAudit(
|
|
17305
|
+
entryMatch.aggregatorId,
|
|
17306
|
+
operatorId
|
|
17307
|
+
);
|
|
17308
|
+
writeJSON4(res, 200, {
|
|
17309
|
+
ok: true,
|
|
17310
|
+
data: { entry, request_payload: payload }
|
|
17311
|
+
});
|
|
17312
|
+
return true;
|
|
17313
|
+
}
|
|
17314
|
+
if (method === "GET" && entryMatch.action === null) {
|
|
17315
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17248
17316
|
if (!entry) {
|
|
17249
17317
|
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17250
17318
|
return true;
|
|
@@ -20278,7 +20346,10 @@ var init_approval_aggregator = __esm({
|
|
|
20278
20346
|
APPROVAL_AGGREGATOR_AUDIT_OPS = {
|
|
20279
20347
|
AGGREGATED: "cross_harness_approval_aggregated",
|
|
20280
20348
|
RESOLVED: "cross_harness_approval_resolved",
|
|
20281
|
-
DEDUPED: "cross_harness_approval_deduped"
|
|
20349
|
+
DEDUPED: "cross_harness_approval_deduped",
|
|
20350
|
+
PAYLOAD_DECRYPTED: "cross_harness_approval_payload_decrypted",
|
|
20351
|
+
AUDIT_TRAIL_VIEWED: "cross_harness_approval_audit_trail_viewed",
|
|
20352
|
+
REPLAYED: "cross_harness_approval_replayed"
|
|
20282
20353
|
};
|
|
20283
20354
|
DEFAULT_PENDING_TTL_MS = 5 * 60 * 1e3;
|
|
20284
20355
|
DEFAULT_MAX_LIST_LIMIT = 200;
|
|
@@ -20294,6 +20365,8 @@ var init_approval_aggregator = __esm({
|
|
|
20294
20365
|
now;
|
|
20295
20366
|
resolveSourceContext;
|
|
20296
20367
|
resolveHubInboxItemId;
|
|
20368
|
+
payloadStore;
|
|
20369
|
+
resolveEnforcementChain;
|
|
20297
20370
|
/** Cached entries by `aggregator_id`. */
|
|
20298
20371
|
entries = /* @__PURE__ */ new Map();
|
|
20299
20372
|
/** Dedup index: `${harness}|${agent}|${audit_id}` -> aggregator_id. */
|
|
@@ -20306,6 +20379,20 @@ var init_approval_aggregator = __esm({
|
|
|
20306
20379
|
hydrated = false;
|
|
20307
20380
|
/** Active SSE listeners. */
|
|
20308
20381
|
listeners = /* @__PURE__ */ new Set();
|
|
20382
|
+
/**
|
|
20383
|
+
* Monotonic revision counter, bumped on every mutation (ingest of new
|
|
20384
|
+
* entry, resolve, expire, delete). Hydrated from max(last_modified_revision)
|
|
20385
|
+
* across persisted entries on first read; in-memory after that. v1.3
|
|
20386
|
+
* Upsilon-4.
|
|
20387
|
+
*/
|
|
20388
|
+
currentRevision = 0;
|
|
20389
|
+
/**
|
|
20390
|
+
* Removal tombstones: aggregator_id -> revision at removal. Used by the
|
|
20391
|
+
* sync API to surface "removed" entries to mobile consumers between
|
|
20392
|
+
* polls. In-memory only; server restart clears tombstones (mobile
|
|
20393
|
+
* bootstraps via `list()` on reconnect). v1.3 Upsilon-4.
|
|
20394
|
+
*/
|
|
20395
|
+
removedTombstones = /* @__PURE__ */ new Map();
|
|
20309
20396
|
constructor(deps) {
|
|
20310
20397
|
this.storage = deps.storage;
|
|
20311
20398
|
this.encryptionKey = derivePurposeKey(
|
|
@@ -20323,6 +20410,14 @@ var init_approval_aggregator = __esm({
|
|
|
20323
20410
|
source_agent_id: this.fortressId
|
|
20324
20411
|
}));
|
|
20325
20412
|
this.resolveHubInboxItemId = deps.resolveHubInboxItemId ?? ((_event) => void 0);
|
|
20413
|
+
this.payloadStore = deps.payloadStore ?? null;
|
|
20414
|
+
this.resolveEnforcementChain = deps.resolveEnforcementChain ?? ((event) => [
|
|
20415
|
+
{
|
|
20416
|
+
layer: "l2",
|
|
20417
|
+
event: `approval_required:${event.operation}`,
|
|
20418
|
+
timestamp: event.request_timestamp
|
|
20419
|
+
}
|
|
20420
|
+
]);
|
|
20326
20421
|
}
|
|
20327
20422
|
/**
|
|
20328
20423
|
* Subscribe an event listener. Returns an unsubscribe fn. SSE handlers
|
|
@@ -20332,6 +20427,113 @@ var init_approval_aggregator = __esm({
|
|
|
20332
20427
|
this.listeners.add(listener);
|
|
20333
20428
|
return () => this.listeners.delete(listener);
|
|
20334
20429
|
}
|
|
20430
|
+
/**
|
|
20431
|
+
* Current aggregator revision. v1.3 Upsilon-4. Mobile companions
|
|
20432
|
+
* poll the lightweight `/revision` route to detect that something
|
|
20433
|
+
* changed before fetching a full sync delta.
|
|
20434
|
+
*/
|
|
20435
|
+
async getRevision() {
|
|
20436
|
+
await this.hydrate();
|
|
20437
|
+
return this.currentRevision;
|
|
20438
|
+
}
|
|
20439
|
+
/**
|
|
20440
|
+
* Compute a delta since `sinceRevision`. v1.3 Upsilon-4. Mobile
|
|
20441
|
+
* clients poll this for cheap state-sync. Behavior:
|
|
20442
|
+
* - `added`: entries whose `created_at_revision > sinceRevision`.
|
|
20443
|
+
* - `changed`: entries that existed at `sinceRevision` but had a
|
|
20444
|
+
* status transition (resolve, expire) since.
|
|
20445
|
+
* - `removed`: aggregator_ids deleted after `sinceRevision`.
|
|
20446
|
+
* - `revision`: current aggregator revision; pass this back as
|
|
20447
|
+
* `sinceRevision` on the next call.
|
|
20448
|
+
*
|
|
20449
|
+
* `limit` caps the total count returned across all three lists,
|
|
20450
|
+
* prioritized as added -> changed -> removed (newer-state first).
|
|
20451
|
+
* When more changes exist than fit, the next call with the returned
|
|
20452
|
+
* revision will pick up the rest because each entry's
|
|
20453
|
+
* last_modified_revision is unchanged by truncation.
|
|
20454
|
+
*/
|
|
20455
|
+
async getSync(opts) {
|
|
20456
|
+
await this.hydrate();
|
|
20457
|
+
await this.expireStale();
|
|
20458
|
+
const sinceRevision = opts?.sinceRevision ?? 0;
|
|
20459
|
+
const cap = Math.min(
|
|
20460
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20461
|
+
this.maxListLimit
|
|
20462
|
+
);
|
|
20463
|
+
const added = [];
|
|
20464
|
+
const changed = [];
|
|
20465
|
+
for (const entry of this.entries.values()) {
|
|
20466
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20467
|
+
if (lastMod <= sinceRevision) continue;
|
|
20468
|
+
const createdRev = entry.created_at_revision ?? 0;
|
|
20469
|
+
if (createdRev > sinceRevision) {
|
|
20470
|
+
added.push(entry);
|
|
20471
|
+
} else {
|
|
20472
|
+
changed.push(entry);
|
|
20473
|
+
}
|
|
20474
|
+
}
|
|
20475
|
+
const removed = [];
|
|
20476
|
+
for (const [id, rev] of this.removedTombstones) {
|
|
20477
|
+
if (rev > sinceRevision) removed.push(id);
|
|
20478
|
+
}
|
|
20479
|
+
added.sort(
|
|
20480
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20481
|
+
);
|
|
20482
|
+
changed.sort(
|
|
20483
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20484
|
+
);
|
|
20485
|
+
let remaining = cap;
|
|
20486
|
+
const addedOut = added.slice(0, Math.max(0, remaining));
|
|
20487
|
+
remaining -= addedOut.length;
|
|
20488
|
+
const changedOut = changed.slice(0, Math.max(0, remaining));
|
|
20489
|
+
remaining -= changedOut.length;
|
|
20490
|
+
const removedOut = removed.slice(0, Math.max(0, remaining));
|
|
20491
|
+
return {
|
|
20492
|
+
revision: this.currentRevision,
|
|
20493
|
+
added: addedOut,
|
|
20494
|
+
changed: changedOut,
|
|
20495
|
+
removed: removedOut
|
|
20496
|
+
};
|
|
20497
|
+
}
|
|
20498
|
+
/**
|
|
20499
|
+
* Delete an entry. Drops the in-memory record, the persisted bundle,
|
|
20500
|
+
* and the at-rest payload (if a payload store is wired). Records a
|
|
20501
|
+
* tombstone with the new revision so sync-API consumers see a
|
|
20502
|
+
* `removed` delta. Returns true when an entry was deleted, false on
|
|
20503
|
+
* unknown id. v1.3 Upsilon-4. Reserved for v1.4+ retention housekeeping;
|
|
20504
|
+
* Upsilon-4 ships the surface so mobile sync-API tests can exercise the
|
|
20505
|
+
* removal path.
|
|
20506
|
+
*/
|
|
20507
|
+
async deleteEntry(aggregatorId) {
|
|
20508
|
+
await this.hydrate();
|
|
20509
|
+
const entry = this.entries.get(aggregatorId);
|
|
20510
|
+
if (!entry) return false;
|
|
20511
|
+
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20512
|
+
this.entries.delete(aggregatorId);
|
|
20513
|
+
this.dedupIndex.delete(dedupKey);
|
|
20514
|
+
this.fullPayloads.delete(aggregatorId);
|
|
20515
|
+
for (const [corr, id] of this.correlationIndex) {
|
|
20516
|
+
if (id === aggregatorId) this.correlationIndex.delete(corr);
|
|
20517
|
+
}
|
|
20518
|
+
try {
|
|
20519
|
+
await this.storage.delete(APPROVAL_AGGREGATOR_NAMESPACE, aggregatorId);
|
|
20520
|
+
} catch {
|
|
20521
|
+
}
|
|
20522
|
+
if (this.payloadStore) {
|
|
20523
|
+
try {
|
|
20524
|
+
await this.payloadStore.deletePayload(aggregatorId);
|
|
20525
|
+
} catch {
|
|
20526
|
+
}
|
|
20527
|
+
}
|
|
20528
|
+
const revision = this.nextRevision();
|
|
20529
|
+
this.removedTombstones.set(aggregatorId, revision);
|
|
20530
|
+
this.emit({ type: "removed", entry: { ...entry } });
|
|
20531
|
+
return true;
|
|
20532
|
+
}
|
|
20533
|
+
nextRevision() {
|
|
20534
|
+
this.currentRevision += 1;
|
|
20535
|
+
return this.currentRevision;
|
|
20536
|
+
}
|
|
20335
20537
|
/**
|
|
20336
20538
|
* Ingest a gate event. Returns the aggregator entry on first sight,
|
|
20337
20539
|
* `null` when deduped. Resolution events update the existing record;
|
|
@@ -20373,13 +20575,152 @@ var init_approval_aggregator = __esm({
|
|
|
20373
20575
|
}
|
|
20374
20576
|
/**
|
|
20375
20577
|
* Return the original (unhashed) request payload for the entry. Returns
|
|
20376
|
-
* `null` when the entry is unknown
|
|
20377
|
-
*
|
|
20578
|
+
* `null` when the entry is unknown. When the in-memory payload map has
|
|
20579
|
+
* been evicted (e.g. after a server restart) and a `payloadStore` was
|
|
20580
|
+
* provided, the at-rest bundle is decrypted and the in-memory map is
|
|
20581
|
+
* refilled. Audit emission lives on the `*WithAudit` variant; this base
|
|
20582
|
+
* accessor is silent so internal callers can read without polluting the
|
|
20583
|
+
* audit trail.
|
|
20378
20584
|
*/
|
|
20379
20585
|
async getFullPayload(aggregatorId) {
|
|
20380
20586
|
await this.hydrate();
|
|
20381
20587
|
if (!this.entries.has(aggregatorId)) return null;
|
|
20382
|
-
|
|
20588
|
+
const cached = this.fullPayloads.get(aggregatorId);
|
|
20589
|
+
if (cached !== void 0) return cached;
|
|
20590
|
+
if (this.payloadStore) {
|
|
20591
|
+
try {
|
|
20592
|
+
const restored = await this.payloadStore.loadPayload(aggregatorId);
|
|
20593
|
+
if (restored !== null) {
|
|
20594
|
+
this.fullPayloads.set(aggregatorId, restored);
|
|
20595
|
+
return restored;
|
|
20596
|
+
}
|
|
20597
|
+
} catch {
|
|
20598
|
+
}
|
|
20599
|
+
}
|
|
20600
|
+
return null;
|
|
20601
|
+
}
|
|
20602
|
+
/**
|
|
20603
|
+
* Return the entry record for the given id, or null when unknown.
|
|
20604
|
+
* Idempotent. v1.3 Upsilon-3.
|
|
20605
|
+
*/
|
|
20606
|
+
async getEntry(aggregatorId) {
|
|
20607
|
+
await this.hydrate();
|
|
20608
|
+
return this.entries.get(aggregatorId) ?? null;
|
|
20609
|
+
}
|
|
20610
|
+
/**
|
|
20611
|
+
* Audited variant of `getFullPayload`. Emits the
|
|
20612
|
+
* `cross_harness_approval_payload_decrypted` audit event before
|
|
20613
|
+
* returning. Used by the operator-facing /payload replay route.
|
|
20614
|
+
* v1.3 Upsilon-3.
|
|
20615
|
+
*/
|
|
20616
|
+
async getFullPayloadWithAudit(aggregatorId, operatorId) {
|
|
20617
|
+
const payload = await this.getFullPayload(aggregatorId);
|
|
20618
|
+
if (payload === null) return null;
|
|
20619
|
+
const entry = this.entries.get(aggregatorId);
|
|
20620
|
+
this.auditLog.append(
|
|
20621
|
+
"l2",
|
|
20622
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.PAYLOAD_DECRYPTED,
|
|
20623
|
+
operatorId,
|
|
20624
|
+
{
|
|
20625
|
+
aggregator_id: aggregatorId,
|
|
20626
|
+
...entry ? {
|
|
20627
|
+
source_harness: entry.source_harness,
|
|
20628
|
+
source_agent_id: entry.source_agent_id,
|
|
20629
|
+
entry_status: entry.status
|
|
20630
|
+
} : {}
|
|
20631
|
+
}
|
|
20632
|
+
);
|
|
20633
|
+
return payload;
|
|
20634
|
+
}
|
|
20635
|
+
/**
|
|
20636
|
+
* Return the audit-log entries that led to and surround this approval.
|
|
20637
|
+
* Best-effort matching: aggregator-side emissions (AGGREGATED, RESOLVED,
|
|
20638
|
+
* DEDUPED, replay events) all carry `details.aggregator_id` and link
|
|
20639
|
+
* directly. Gate-side emissions (`gate_*:operation`) do not carry the
|
|
20640
|
+
* aggregator id at v1.3, so they are matched via timestamp window
|
|
20641
|
+
* (entry.created_at to entry.resolved_at + 1s, or expires_at + 1s while
|
|
20642
|
+
* pending) and operation suffix. Emits AUDIT_TRAIL_VIEWED on call.
|
|
20643
|
+
* v1.3 Upsilon-3.
|
|
20644
|
+
*/
|
|
20645
|
+
async getAuditTrail(aggregatorId, operatorId) {
|
|
20646
|
+
await this.hydrate();
|
|
20647
|
+
const entry = this.entries.get(aggregatorId);
|
|
20648
|
+
if (!entry) {
|
|
20649
|
+
return [];
|
|
20650
|
+
}
|
|
20651
|
+
const sinceMs = Date.parse(entry.created_at) - 1e3;
|
|
20652
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
20653
|
+
const queried = await this.auditLog.query({ since: sinceIso, limit: 1e3 });
|
|
20654
|
+
const operationPart = entry.policy_rule_id.includes(":") ? entry.policy_rule_id.slice(entry.policy_rule_id.indexOf(":") + 1) : entry.policy_rule_id;
|
|
20655
|
+
const lifetimeStart = sinceMs;
|
|
20656
|
+
const lifetimeEnd = entry.resolved_at ? Date.parse(entry.resolved_at) + 1e3 : Date.parse(entry.expires_at) + 1e3;
|
|
20657
|
+
const matches = [];
|
|
20658
|
+
for (const audit of queried.entries) {
|
|
20659
|
+
const detailsId = audit.details !== void 0 ? audit.details["aggregator_id"] : void 0;
|
|
20660
|
+
if (detailsId === aggregatorId) {
|
|
20661
|
+
matches.push(audit);
|
|
20662
|
+
continue;
|
|
20663
|
+
}
|
|
20664
|
+
const auditMs = Date.parse(audit.timestamp);
|
|
20665
|
+
if (auditMs < lifetimeStart || auditMs > lifetimeEnd) continue;
|
|
20666
|
+
if (audit.operation.endsWith(`:${operationPart}`)) {
|
|
20667
|
+
matches.push(audit);
|
|
20668
|
+
}
|
|
20669
|
+
}
|
|
20670
|
+
matches.sort(
|
|
20671
|
+
(a, b) => a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0
|
|
20672
|
+
);
|
|
20673
|
+
this.auditLog.append(
|
|
20674
|
+
"l2",
|
|
20675
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.AUDIT_TRAIL_VIEWED,
|
|
20676
|
+
operatorId,
|
|
20677
|
+
{
|
|
20678
|
+
aggregator_id: aggregatorId,
|
|
20679
|
+
entry_status: entry.status,
|
|
20680
|
+
match_count: matches.length
|
|
20681
|
+
}
|
|
20682
|
+
);
|
|
20683
|
+
return matches;
|
|
20684
|
+
}
|
|
20685
|
+
/**
|
|
20686
|
+
* List historical (resolved) approvals. Excludes pending entries by
|
|
20687
|
+
* design: `list()` is the pending-inbox surface and `getHistory()` is
|
|
20688
|
+
* the resolved-replay surface. Emits REPLAYED on each call. v1.3
|
|
20689
|
+
* Upsilon-3.
|
|
20690
|
+
*/
|
|
20691
|
+
async getHistory(opts, operatorId) {
|
|
20692
|
+
await this.hydrate();
|
|
20693
|
+
await this.expireStale();
|
|
20694
|
+
const limit = Math.min(
|
|
20695
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20696
|
+
this.maxListLimit
|
|
20697
|
+
);
|
|
20698
|
+
const sinceMs = opts?.sinceTs ? Date.parse(opts.sinceTs) : Number.NEGATIVE_INFINITY;
|
|
20699
|
+
const matching = [];
|
|
20700
|
+
for (const entry of this.entries.values()) {
|
|
20701
|
+
if (entry.status === "pending") continue;
|
|
20702
|
+
if (opts?.status && entry.status !== opts.status) continue;
|
|
20703
|
+
const stamp = Date.parse(entry.resolved_at ?? entry.created_at);
|
|
20704
|
+
if (stamp < sinceMs) continue;
|
|
20705
|
+
matching.push(entry);
|
|
20706
|
+
}
|
|
20707
|
+
matching.sort((a, b) => {
|
|
20708
|
+
const aStamp = a.resolved_at ?? a.created_at;
|
|
20709
|
+
const bStamp = b.resolved_at ?? b.created_at;
|
|
20710
|
+
return bStamp.localeCompare(aStamp);
|
|
20711
|
+
});
|
|
20712
|
+
const sliced = matching.slice(0, limit);
|
|
20713
|
+
this.auditLog.append(
|
|
20714
|
+
"l2",
|
|
20715
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.REPLAYED,
|
|
20716
|
+
operatorId,
|
|
20717
|
+
{
|
|
20718
|
+
result_count: sliced.length,
|
|
20719
|
+
...opts?.status !== void 0 ? { status_filter: opts.status } : {},
|
|
20720
|
+
...opts?.sinceTs !== void 0 ? { since: opts.sinceTs } : {}
|
|
20721
|
+
}
|
|
20722
|
+
);
|
|
20723
|
+
return sliced;
|
|
20383
20724
|
}
|
|
20384
20725
|
/**
|
|
20385
20726
|
* Resolve an entry. Used by both:
|
|
@@ -20403,6 +20744,7 @@ var init_approval_aggregator = __esm({
|
|
|
20403
20744
|
entry.status = decision;
|
|
20404
20745
|
entry.resolved_at = this.now().toISOString();
|
|
20405
20746
|
entry.resolved_by = operatorId;
|
|
20747
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20406
20748
|
await this.persist(entry);
|
|
20407
20749
|
this.auditLog.append(
|
|
20408
20750
|
"l2",
|
|
@@ -20453,6 +20795,8 @@ var init_approval_aggregator = __esm({
|
|
|
20453
20795
|
const now = this.now();
|
|
20454
20796
|
const expires = new Date(now.getTime() + this.pendingTtlMs);
|
|
20455
20797
|
const hubInboxId = this.resolveHubInboxItemId(event);
|
|
20798
|
+
const enforcementChain = this.resolveEnforcementChain(event);
|
|
20799
|
+
const revision = this.nextRevision();
|
|
20456
20800
|
const entry = {
|
|
20457
20801
|
aggregator_id: id,
|
|
20458
20802
|
source_harness: ctx.source_harness,
|
|
@@ -20464,13 +20808,22 @@ var init_approval_aggregator = __esm({
|
|
|
20464
20808
|
status: "pending",
|
|
20465
20809
|
created_at: now.toISOString(),
|
|
20466
20810
|
expires_at: expires.toISOString(),
|
|
20467
|
-
|
|
20811
|
+
created_at_revision: revision,
|
|
20812
|
+
last_modified_revision: revision,
|
|
20813
|
+
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {},
|
|
20814
|
+
...enforcementChain.length > 0 ? { enforcement_chain: enforcementChain } : {}
|
|
20468
20815
|
};
|
|
20469
20816
|
this.entries.set(id, entry);
|
|
20470
20817
|
this.dedupIndex.set(dedupKey, id);
|
|
20471
20818
|
this.correlationIndex.set(event.correlation_id, id);
|
|
20472
20819
|
this.fullPayloads.set(id, event.context);
|
|
20473
20820
|
await this.persist(entry);
|
|
20821
|
+
if (this.payloadStore) {
|
|
20822
|
+
try {
|
|
20823
|
+
await this.payloadStore.savePayload(id, event.context);
|
|
20824
|
+
} catch {
|
|
20825
|
+
}
|
|
20826
|
+
}
|
|
20474
20827
|
this.auditLog.append(
|
|
20475
20828
|
"l2",
|
|
20476
20829
|
APPROVAL_AGGREGATOR_AUDIT_OPS.AGGREGATED,
|
|
@@ -20499,6 +20852,7 @@ var init_approval_aggregator = __esm({
|
|
|
20499
20852
|
entry.status = status;
|
|
20500
20853
|
entry.resolved_at = event.resolution.decided_at;
|
|
20501
20854
|
entry.resolved_by = event.resolution.decided_by;
|
|
20855
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20502
20856
|
await this.persist(entry);
|
|
20503
20857
|
this.auditLog.append(
|
|
20504
20858
|
"l2",
|
|
@@ -20561,6 +20915,7 @@ var init_approval_aggregator = __esm({
|
|
|
20561
20915
|
entry.status = "expired";
|
|
20562
20916
|
entry.resolved_at = this.now().toISOString();
|
|
20563
20917
|
entry.resolved_by = "system_ttl";
|
|
20918
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20564
20919
|
await this.persist(entry);
|
|
20565
20920
|
this.auditLog.append(
|
|
20566
20921
|
"l2",
|
|
@@ -20607,6 +20962,10 @@ var init_approval_aggregator = __esm({
|
|
|
20607
20962
|
this.entries.set(entry.aggregator_id, entry);
|
|
20608
20963
|
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20609
20964
|
this.dedupIndex.set(dedupKey, entry.aggregator_id);
|
|
20965
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20966
|
+
if (lastMod > this.currentRevision) {
|
|
20967
|
+
this.currentRevision = lastMod;
|
|
20968
|
+
}
|
|
20610
20969
|
} catch {
|
|
20611
20970
|
}
|
|
20612
20971
|
}
|
|
@@ -20786,6 +21145,149 @@ var init_aggregator_backed_channel = __esm({
|
|
|
20786
21145
|
}
|
|
20787
21146
|
});
|
|
20788
21147
|
|
|
21148
|
+
// src/principal-policy/aggregator-store.ts
|
|
21149
|
+
function payloadKey(aggregatorId) {
|
|
21150
|
+
return `${AGGREGATOR_PAYLOAD_KEY_PREFIX}${aggregatorId}`;
|
|
21151
|
+
}
|
|
21152
|
+
function stripKeyPrefix(key) {
|
|
21153
|
+
if (!key.startsWith(AGGREGATOR_PAYLOAD_KEY_PREFIX)) return null;
|
|
21154
|
+
return key.slice(AGGREGATOR_PAYLOAD_KEY_PREFIX.length);
|
|
21155
|
+
}
|
|
21156
|
+
var AGGREGATOR_PAYLOAD_NAMESPACE, AGGREGATOR_PAYLOAD_KEY_PREFIX, HKDF_INFO, DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS, MAX_BUNDLE_BYTES2, AggregatorPayloadStore;
|
|
21157
|
+
var init_aggregator_store = __esm({
|
|
21158
|
+
"src/principal-policy/aggregator-store.ts"() {
|
|
21159
|
+
init_encryption();
|
|
21160
|
+
init_key_derivation();
|
|
21161
|
+
init_encoding();
|
|
21162
|
+
AGGREGATOR_PAYLOAD_NAMESPACE = "_approval_aggregator_payloads";
|
|
21163
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX = "payload.";
|
|
21164
|
+
HKDF_INFO = "l2-approval-aggregator-payload-v1";
|
|
21165
|
+
DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS = 30;
|
|
21166
|
+
MAX_BUNDLE_BYTES2 = 4 * 1024 * 1024;
|
|
21167
|
+
AggregatorPayloadStore = class {
|
|
21168
|
+
storage;
|
|
21169
|
+
encryptionKey;
|
|
21170
|
+
fortressId;
|
|
21171
|
+
retentionDays;
|
|
21172
|
+
constructor(opts) {
|
|
21173
|
+
this.storage = opts.storage;
|
|
21174
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO);
|
|
21175
|
+
this.fortressId = opts.fortressId;
|
|
21176
|
+
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS;
|
|
21177
|
+
}
|
|
21178
|
+
/**
|
|
21179
|
+
* Persist `payload` under the given aggregator_id. Idempotent; calling
|
|
21180
|
+
* twice with the same id rewrites the bundle (retention_until is
|
|
21181
|
+
* recomputed). Returns the bundle's retention_until ISO-8601 timestamp
|
|
21182
|
+
* so callers can log it.
|
|
21183
|
+
*/
|
|
21184
|
+
async savePayload(aggregatorId, payload) {
|
|
21185
|
+
const now = /* @__PURE__ */ new Date();
|
|
21186
|
+
const retentionMs = this.retentionDays * 24 * 60 * 60 * 1e3;
|
|
21187
|
+
const retentionUntil = new Date(now.getTime() + retentionMs);
|
|
21188
|
+
const bundle = {
|
|
21189
|
+
version: 1,
|
|
21190
|
+
aggregator_id: aggregatorId,
|
|
21191
|
+
fortress_id: this.fortressId,
|
|
21192
|
+
created_at: now.toISOString(),
|
|
21193
|
+
retention_until: retentionUntil.toISOString(),
|
|
21194
|
+
payload
|
|
21195
|
+
};
|
|
21196
|
+
const aad = stringToBytes(aggregatorId);
|
|
21197
|
+
const plaintext = stringToBytes(JSON.stringify(bundle));
|
|
21198
|
+
const envelope = encrypt(plaintext, this.encryptionKey, aad);
|
|
21199
|
+
await this.storage.write(
|
|
21200
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21201
|
+
payloadKey(aggregatorId),
|
|
21202
|
+
stringToBytes(JSON.stringify(envelope))
|
|
21203
|
+
);
|
|
21204
|
+
return bundle.retention_until;
|
|
21205
|
+
}
|
|
21206
|
+
/**
|
|
21207
|
+
* Read the persisted payload for the aggregator_id. Returns null if no
|
|
21208
|
+
* bundle exists, the bundle is corrupted, or AAD binding fails.
|
|
21209
|
+
*/
|
|
21210
|
+
async loadPayload(aggregatorId) {
|
|
21211
|
+
const key = payloadKey(aggregatorId);
|
|
21212
|
+
let raw;
|
|
21213
|
+
try {
|
|
21214
|
+
raw = await this.storage.read(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21215
|
+
} catch {
|
|
21216
|
+
return null;
|
|
21217
|
+
}
|
|
21218
|
+
if (!raw) return null;
|
|
21219
|
+
if (raw.length > MAX_BUNDLE_BYTES2) return null;
|
|
21220
|
+
try {
|
|
21221
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21222
|
+
const aad = stringToBytes(aggregatorId);
|
|
21223
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21224
|
+
const parsed = JSON.parse(
|
|
21225
|
+
bytesToString(plaintext)
|
|
21226
|
+
);
|
|
21227
|
+
if (parsed.version !== 1) return null;
|
|
21228
|
+
if (parsed.aggregator_id !== aggregatorId) return null;
|
|
21229
|
+
return parsed.payload;
|
|
21230
|
+
} catch {
|
|
21231
|
+
return null;
|
|
21232
|
+
}
|
|
21233
|
+
}
|
|
21234
|
+
/**
|
|
21235
|
+
* Delete the persisted payload. Returns true when a bundle was removed,
|
|
21236
|
+
* false when none existed.
|
|
21237
|
+
*/
|
|
21238
|
+
async deletePayload(aggregatorId) {
|
|
21239
|
+
const key = payloadKey(aggregatorId);
|
|
21240
|
+
const existed = await this.storage.exists(
|
|
21241
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21242
|
+
key
|
|
21243
|
+
);
|
|
21244
|
+
if (!existed) return false;
|
|
21245
|
+
try {
|
|
21246
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21247
|
+
} catch {
|
|
21248
|
+
return false;
|
|
21249
|
+
}
|
|
21250
|
+
return true;
|
|
21251
|
+
}
|
|
21252
|
+
/**
|
|
21253
|
+
* Drop expired payload bundles. Returns the count of bundles pruned.
|
|
21254
|
+
* Caller wires this into the cocoon-unlock initialization path.
|
|
21255
|
+
*/
|
|
21256
|
+
async pruneExpired(now) {
|
|
21257
|
+
const cutoff = (now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
21258
|
+
const entries = await this.storage.list(
|
|
21259
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21260
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX
|
|
21261
|
+
);
|
|
21262
|
+
let pruned = 0;
|
|
21263
|
+
for (const meta of entries) {
|
|
21264
|
+
const aggregatorId = stripKeyPrefix(meta.key);
|
|
21265
|
+
if (aggregatorId === null) continue;
|
|
21266
|
+
const raw = await this.storage.read(
|
|
21267
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21268
|
+
meta.key
|
|
21269
|
+
);
|
|
21270
|
+
if (!raw) continue;
|
|
21271
|
+
try {
|
|
21272
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21273
|
+
const aad = stringToBytes(aggregatorId);
|
|
21274
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21275
|
+
const parsed = JSON.parse(
|
|
21276
|
+
bytesToString(plaintext)
|
|
21277
|
+
);
|
|
21278
|
+
if (parsed.retention_until <= cutoff) {
|
|
21279
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, meta.key);
|
|
21280
|
+
pruned += 1;
|
|
21281
|
+
}
|
|
21282
|
+
} catch {
|
|
21283
|
+
}
|
|
21284
|
+
}
|
|
21285
|
+
return { pruned };
|
|
21286
|
+
}
|
|
21287
|
+
};
|
|
21288
|
+
}
|
|
21289
|
+
});
|
|
21290
|
+
|
|
20789
21291
|
// src/principal-policy/tools.ts
|
|
20790
21292
|
function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
20791
21293
|
return [
|
|
@@ -33404,7 +33906,14 @@ var init_operator_chat_audit_events = __esm({
|
|
|
33404
33906
|
* turns; the concierge degrades to single-turn after emitting. Body
|
|
33405
33907
|
* carries thread_id + a stable failure_reason enum.
|
|
33406
33908
|
*/
|
|
33407
|
-
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed"
|
|
33909
|
+
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed",
|
|
33910
|
+
/**
|
|
33911
|
+
* Concierge dynamic-context fetcher failed (WP-V1.3-9 Tau-3). Emitted
|
|
33912
|
+
* when a category fetcher throws while assembling the dynamic context
|
|
33913
|
+
* fold. The concierge omits that category and continues; the user-
|
|
33914
|
+
* facing query is never broken. Body carries category + failure_reason.
|
|
33915
|
+
*/
|
|
33916
|
+
CONCIERGE_CONTEXT_FETCHER_FAILED: "operator_concierge_context_fetcher_failed"
|
|
33408
33917
|
};
|
|
33409
33918
|
}
|
|
33410
33919
|
});
|
|
@@ -33417,12 +33926,844 @@ var init_operator_chat_types = __esm({
|
|
|
33417
33926
|
CONCIERGE_THREAD_KEY = "_fortress";
|
|
33418
33927
|
}
|
|
33419
33928
|
});
|
|
33929
|
+
|
|
33930
|
+
// src/chat/concierge-context-router.ts
|
|
33931
|
+
function phrasePattern(phrase) {
|
|
33932
|
+
const escaped = phrase.toLowerCase().split(/\s+/).map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
|
|
33933
|
+
return { source: `\\b${escaped}\\b`, phrase };
|
|
33934
|
+
}
|
|
33935
|
+
function extractAgentNameHint(query) {
|
|
33936
|
+
const agentPattern = /\bagent\s+["']?([A-Za-z][\w-]{0,40})["']?/i;
|
|
33937
|
+
const m = query.match(agentPattern);
|
|
33938
|
+
if (m && m[1]) return m[1];
|
|
33939
|
+
const quoted = query.match(/["']([A-Za-z][\w-]{0,40})["']/);
|
|
33940
|
+
if (quoted && quoted[1]) return quoted[1];
|
|
33941
|
+
return null;
|
|
33942
|
+
}
|
|
33943
|
+
function isTrivialQuery(query) {
|
|
33944
|
+
const norm = query.trim().toLowerCase();
|
|
33945
|
+
if (norm.length === 0) return true;
|
|
33946
|
+
if (norm.length < 8) return true;
|
|
33947
|
+
return TRIVIAL_GREETINGS.has(norm);
|
|
33948
|
+
}
|
|
33949
|
+
function classifyQuery(query, parsedGrammar) {
|
|
33950
|
+
const normalized = query.toLowerCase();
|
|
33951
|
+
const matches = [];
|
|
33952
|
+
const grammarAgent = parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null;
|
|
33953
|
+
for (const spec of CATEGORY_KEYWORDS) {
|
|
33954
|
+
const matchedPhrases = [];
|
|
33955
|
+
for (const pattern of spec.patterns) {
|
|
33956
|
+
if (matchedPhrases.includes(pattern.phrase)) continue;
|
|
33957
|
+
const re = new RegExp(pattern.source, "i");
|
|
33958
|
+
if (re.test(normalized)) {
|
|
33959
|
+
matchedPhrases.push(pattern.phrase);
|
|
33960
|
+
}
|
|
33961
|
+
}
|
|
33962
|
+
if (matchedPhrases.length === 0) continue;
|
|
33963
|
+
const confidence = Math.min(1, 0.4 + 0.3 * matchedPhrases.length);
|
|
33964
|
+
const wantsAgentHint = spec.category === "agent_state" || spec.category === "agent_activity";
|
|
33965
|
+
const agent_name_hint = wantsAgentHint ? grammarAgent ?? extractAgentNameHint(query) : null;
|
|
33966
|
+
matches.push({
|
|
33967
|
+
category: spec.category,
|
|
33968
|
+
confidence,
|
|
33969
|
+
matched_keywords: matchedPhrases,
|
|
33970
|
+
agent_name_hint,
|
|
33971
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33972
|
+
});
|
|
33973
|
+
}
|
|
33974
|
+
matches.sort((a, b) => {
|
|
33975
|
+
if (b.confidence !== a.confidence) return b.confidence - a.confidence;
|
|
33976
|
+
return CONTEXT_CATEGORIES.indexOf(a.category) - CONTEXT_CATEGORIES.indexOf(b.category);
|
|
33977
|
+
});
|
|
33978
|
+
return matches;
|
|
33979
|
+
}
|
|
33980
|
+
function fetcherHintsFromGrammar(parsed) {
|
|
33981
|
+
if (!parsed) return void 0;
|
|
33982
|
+
const hasTime = parsed.time_range !== null;
|
|
33983
|
+
const hasAgents = parsed.agent_names.length > 0;
|
|
33984
|
+
const hasEvents = parsed.event_types.length > 0;
|
|
33985
|
+
if (!hasTime && !hasAgents && !hasEvents) return void 0;
|
|
33986
|
+
const hints = {};
|
|
33987
|
+
if (parsed.time_range) {
|
|
33988
|
+
const range = parsed.time_range;
|
|
33989
|
+
hints.time_range = {
|
|
33990
|
+
start: range.start,
|
|
33991
|
+
end: range.end,
|
|
33992
|
+
...range.relative_label !== void 0 ? { relative_label: range.relative_label } : {}
|
|
33993
|
+
};
|
|
33994
|
+
}
|
|
33995
|
+
if (hasAgents) hints.agent_names = parsed.agent_names;
|
|
33996
|
+
if (hasEvents) hints.event_types = parsed.event_types;
|
|
33997
|
+
return hints;
|
|
33998
|
+
}
|
|
33420
33999
|
function approxTokenLen(text) {
|
|
34000
|
+
return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
34001
|
+
}
|
|
34002
|
+
async function runFetcher(match, fetchers, hints) {
|
|
34003
|
+
switch (match.category) {
|
|
34004
|
+
case "templates":
|
|
34005
|
+
return fetchers.templates(hints);
|
|
34006
|
+
case "agent_state":
|
|
34007
|
+
return fetchers.agent_state(match.agent_name_hint, hints);
|
|
34008
|
+
case "agent_activity":
|
|
34009
|
+
return fetchers.agent_activity(match.agent_name_hint, hints);
|
|
34010
|
+
case "audit_log":
|
|
34011
|
+
return fetchers.audit_log(hints);
|
|
34012
|
+
case "sentinel_findings":
|
|
34013
|
+
return fetchers.sentinel_findings(hints);
|
|
34014
|
+
case "anomaly_alerts":
|
|
34015
|
+
return fetchers.anomaly_alerts(hints);
|
|
34016
|
+
case "recent_receipts":
|
|
34017
|
+
return fetchers.recent_receipts(hints);
|
|
34018
|
+
case "verascore_deltas":
|
|
34019
|
+
return fetchers.verascore_deltas(hints);
|
|
34020
|
+
}
|
|
34021
|
+
}
|
|
34022
|
+
function trivialMatch(category, parsedGrammar) {
|
|
34023
|
+
return {
|
|
34024
|
+
category,
|
|
34025
|
+
confidence: 0.5,
|
|
34026
|
+
matched_keywords: ["llm-assist"],
|
|
34027
|
+
agent_name_hint: parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null,
|
|
34028
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
34029
|
+
};
|
|
34030
|
+
}
|
|
34031
|
+
async function foldContext(query, fetchers, opts) {
|
|
34032
|
+
const budget = opts?.maxTokens ?? DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET;
|
|
34033
|
+
const parsed = opts?.parsed ?? null;
|
|
34034
|
+
const hints = fetcherHintsFromGrammar(parsed);
|
|
34035
|
+
let matches = classifyQuery(query, parsed);
|
|
34036
|
+
if (matches.length === 0 && !isTrivialQuery(query) && opts?.llmAssistClassify) {
|
|
34037
|
+
try {
|
|
34038
|
+
const picked = await opts.llmAssistClassify(query, CONTEXT_CATEGORIES);
|
|
34039
|
+
if (picked !== "none" && CONTEXT_CATEGORIES.includes(picked)) {
|
|
34040
|
+
matches = [trivialMatch(picked, parsed)];
|
|
34041
|
+
}
|
|
34042
|
+
} catch {
|
|
34043
|
+
}
|
|
34044
|
+
}
|
|
34045
|
+
if (matches.length === 0) {
|
|
34046
|
+
return { section: "", categoriesIncluded: [] };
|
|
34047
|
+
}
|
|
34048
|
+
const attempts = [];
|
|
34049
|
+
for (const match of matches) {
|
|
34050
|
+
try {
|
|
34051
|
+
const text = await runFetcher(match, fetchers, hints);
|
|
34052
|
+
const trimmed = text.trim();
|
|
34053
|
+
if (trimmed.length > 0) {
|
|
34054
|
+
attempts.push({ category: match.category, text: trimmed });
|
|
34055
|
+
}
|
|
34056
|
+
} catch (err) {
|
|
34057
|
+
opts?.onFetcherFailure?.(match.category, err);
|
|
34058
|
+
}
|
|
34059
|
+
}
|
|
34060
|
+
if (attempts.length === 0) {
|
|
34061
|
+
return { section: "", categoriesIncluded: [] };
|
|
34062
|
+
}
|
|
34063
|
+
const headerTokens = approxTokenLen(`${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
34064
|
+
`);
|
|
34065
|
+
const sepTokens = approxTokenLen("\n\n");
|
|
34066
|
+
let runningTokens = headerTokens;
|
|
34067
|
+
const kept = [];
|
|
34068
|
+
for (const attempt of attempts) {
|
|
34069
|
+
const block = `### ${CATEGORY_LABELS[attempt.category]}
|
|
34070
|
+
${attempt.text}`;
|
|
34071
|
+
const tokens = approxTokenLen(block) + (kept.length > 0 ? sepTokens : 0);
|
|
34072
|
+
if (kept.length === 0) {
|
|
34073
|
+
kept.push(attempt);
|
|
34074
|
+
runningTokens += tokens;
|
|
34075
|
+
continue;
|
|
34076
|
+
}
|
|
34077
|
+
if (runningTokens + tokens > budget) break;
|
|
34078
|
+
kept.push(attempt);
|
|
34079
|
+
runningTokens += tokens;
|
|
34080
|
+
}
|
|
34081
|
+
const blocks = kept.map(
|
|
34082
|
+
(k) => `### ${CATEGORY_LABELS[k.category]}
|
|
34083
|
+
${k.text}`
|
|
34084
|
+
);
|
|
34085
|
+
const section = `${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
34086
|
+
${blocks.join("\n\n")}`;
|
|
34087
|
+
return {
|
|
34088
|
+
section,
|
|
34089
|
+
categoriesIncluded: kept.map((k) => k.category)
|
|
34090
|
+
};
|
|
34091
|
+
}
|
|
34092
|
+
var APPROX_CHARS_PER_TOKEN, DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET, DYNAMIC_CONTEXT_SECTION_HEADER, CONTEXT_CATEGORIES, CATEGORY_KEYWORDS, TRIVIAL_GREETINGS, CATEGORY_LABELS;
|
|
34093
|
+
var init_concierge_context_router = __esm({
|
|
34094
|
+
"src/chat/concierge-context-router.ts"() {
|
|
34095
|
+
APPROX_CHARS_PER_TOKEN = 4;
|
|
34096
|
+
DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET = 2e3;
|
|
34097
|
+
DYNAMIC_CONTEXT_SECTION_HEADER = "## Live fortress context";
|
|
34098
|
+
CONTEXT_CATEGORIES = [
|
|
34099
|
+
"templates",
|
|
34100
|
+
"agent_state",
|
|
34101
|
+
"agent_activity",
|
|
34102
|
+
"audit_log",
|
|
34103
|
+
"sentinel_findings",
|
|
34104
|
+
"anomaly_alerts",
|
|
34105
|
+
"recent_receipts",
|
|
34106
|
+
"verascore_deltas"
|
|
34107
|
+
];
|
|
34108
|
+
CATEGORY_KEYWORDS = [
|
|
34109
|
+
{
|
|
34110
|
+
category: "templates",
|
|
34111
|
+
patterns: [
|
|
34112
|
+
"templates",
|
|
34113
|
+
"template",
|
|
34114
|
+
"channel templates",
|
|
34115
|
+
"channel template",
|
|
34116
|
+
"list templates",
|
|
34117
|
+
"available templates",
|
|
34118
|
+
"what templates"
|
|
34119
|
+
].map(phrasePattern)
|
|
34120
|
+
},
|
|
34121
|
+
{
|
|
34122
|
+
category: "agent_state",
|
|
34123
|
+
patterns: [
|
|
34124
|
+
"state",
|
|
34125
|
+
"status",
|
|
34126
|
+
"agent state",
|
|
34127
|
+
"agent status",
|
|
34128
|
+
"status of agent",
|
|
34129
|
+
"status of agents",
|
|
34130
|
+
"state of",
|
|
34131
|
+
"doing"
|
|
34132
|
+
].map(phrasePattern)
|
|
34133
|
+
},
|
|
34134
|
+
{
|
|
34135
|
+
category: "agent_activity",
|
|
34136
|
+
patterns: [
|
|
34137
|
+
"activity",
|
|
34138
|
+
"agent activity",
|
|
34139
|
+
"what did",
|
|
34140
|
+
"recent activity"
|
|
34141
|
+
].map(phrasePattern)
|
|
34142
|
+
},
|
|
34143
|
+
{
|
|
34144
|
+
category: "audit_log",
|
|
34145
|
+
patterns: [
|
|
34146
|
+
"audit log",
|
|
34147
|
+
"audit",
|
|
34148
|
+
"log entry",
|
|
34149
|
+
"log entries",
|
|
34150
|
+
"what happened",
|
|
34151
|
+
"show me events",
|
|
34152
|
+
"event class"
|
|
34153
|
+
].map(phrasePattern)
|
|
34154
|
+
},
|
|
34155
|
+
{
|
|
34156
|
+
category: "sentinel_findings",
|
|
34157
|
+
patterns: [
|
|
34158
|
+
"sentinel",
|
|
34159
|
+
"sentinels",
|
|
34160
|
+
"warning",
|
|
34161
|
+
"warnings",
|
|
34162
|
+
"alert",
|
|
34163
|
+
"alerts",
|
|
34164
|
+
"whats wrong",
|
|
34165
|
+
"what's wrong",
|
|
34166
|
+
"findings"
|
|
34167
|
+
].map(phrasePattern)
|
|
34168
|
+
},
|
|
34169
|
+
{
|
|
34170
|
+
category: "anomaly_alerts",
|
|
34171
|
+
patterns: [
|
|
34172
|
+
"anomaly",
|
|
34173
|
+
"anomalies",
|
|
34174
|
+
"spike",
|
|
34175
|
+
"unusual",
|
|
34176
|
+
"outlier"
|
|
34177
|
+
].map(phrasePattern)
|
|
34178
|
+
},
|
|
34179
|
+
{
|
|
34180
|
+
category: "recent_receipts",
|
|
34181
|
+
patterns: [
|
|
34182
|
+
"receipt",
|
|
34183
|
+
"receipts",
|
|
34184
|
+
"concordia",
|
|
34185
|
+
"commitment",
|
|
34186
|
+
"commitments",
|
|
34187
|
+
"chain",
|
|
34188
|
+
"chains"
|
|
34189
|
+
].map(phrasePattern)
|
|
34190
|
+
},
|
|
34191
|
+
{
|
|
34192
|
+
category: "verascore_deltas",
|
|
34193
|
+
patterns: [
|
|
34194
|
+
"verascore",
|
|
34195
|
+
"vera score",
|
|
34196
|
+
"trust score",
|
|
34197
|
+
"reputation"
|
|
34198
|
+
].map(phrasePattern)
|
|
34199
|
+
}
|
|
34200
|
+
];
|
|
34201
|
+
TRIVIAL_GREETINGS = /* @__PURE__ */ new Set([
|
|
34202
|
+
"hi",
|
|
34203
|
+
"hello",
|
|
34204
|
+
"hey",
|
|
34205
|
+
"yo",
|
|
34206
|
+
"ok",
|
|
34207
|
+
"thanks",
|
|
34208
|
+
"thx",
|
|
34209
|
+
"thank you"
|
|
34210
|
+
]);
|
|
34211
|
+
CATEGORY_LABELS = {
|
|
34212
|
+
templates: "Templates",
|
|
34213
|
+
agent_state: "Agent state",
|
|
34214
|
+
agent_activity: "Agent activity",
|
|
34215
|
+
audit_log: "Audit log",
|
|
34216
|
+
sentinel_findings: "Sentinel findings",
|
|
34217
|
+
anomaly_alerts: "Anomaly alerts",
|
|
34218
|
+
recent_receipts: "Recent receipts",
|
|
34219
|
+
verascore_deltas: "Verascore deltas"
|
|
34220
|
+
};
|
|
34221
|
+
}
|
|
34222
|
+
});
|
|
34223
|
+
|
|
34224
|
+
// src/composition/constants.ts
|
|
34225
|
+
var COMPOSITION_EVENT_TYPES;
|
|
34226
|
+
var init_constants4 = __esm({
|
|
34227
|
+
"src/composition/constants.ts"() {
|
|
34228
|
+
init_constants();
|
|
34229
|
+
COMPOSITION_EVENT_TYPES = [
|
|
34230
|
+
"composition_receipt_packed",
|
|
34231
|
+
"composition_receipt_verified",
|
|
34232
|
+
"composition_mandate_verified",
|
|
34233
|
+
"composition_verascore_published",
|
|
34234
|
+
"composition_sidecar_spawned",
|
|
34235
|
+
"composition_sidecar_crashed",
|
|
34236
|
+
"composition_sidecar_recovered",
|
|
34237
|
+
"composition_degraded",
|
|
34238
|
+
"composition_recovered"
|
|
34239
|
+
];
|
|
34240
|
+
}
|
|
34241
|
+
});
|
|
34242
|
+
|
|
34243
|
+
// src/chat/concierge-query-grammar.ts
|
|
34244
|
+
function resolveTimeRange(query, now) {
|
|
34245
|
+
const normalized = query.trim();
|
|
34246
|
+
const lower = normalized.toLowerCase();
|
|
34247
|
+
const fromTo = lower.match(
|
|
34248
|
+
/\b(?:from|between)\s+(.+?)\s+(?:to|and|-|until)\s+([\w:.\-+t /]+)/i
|
|
34249
|
+
);
|
|
34250
|
+
if (fromTo) {
|
|
34251
|
+
const aSlice = fromTo[1];
|
|
34252
|
+
const bSlice = fromTo[2];
|
|
34253
|
+
if (aSlice !== void 0 && bSlice !== void 0) {
|
|
34254
|
+
const a = parseInstant(aSlice, now);
|
|
34255
|
+
const b = parseInstant(bSlice, now);
|
|
34256
|
+
if (a && b) {
|
|
34257
|
+
const start = a.getTime() <= b.getTime() ? a : b;
|
|
34258
|
+
const end = a.getTime() <= b.getTime() ? b : a;
|
|
34259
|
+
return {
|
|
34260
|
+
range: { start, end },
|
|
34261
|
+
matchedSubstring: fromTo[0]
|
|
34262
|
+
};
|
|
34263
|
+
}
|
|
34264
|
+
}
|
|
34265
|
+
}
|
|
34266
|
+
const sinceMatch = lower.match(/\bsince\s+([\w:.\-+t /]+)/i);
|
|
34267
|
+
if (sinceMatch) {
|
|
34268
|
+
const slice = sinceMatch[1];
|
|
34269
|
+
if (slice !== void 0) {
|
|
34270
|
+
const start = parseInstant(slice, now);
|
|
34271
|
+
if (start) {
|
|
34272
|
+
return {
|
|
34273
|
+
range: { start, end: now },
|
|
34274
|
+
matchedSubstring: sinceMatch[0]
|
|
34275
|
+
};
|
|
34276
|
+
}
|
|
34277
|
+
}
|
|
34278
|
+
}
|
|
34279
|
+
if (/\byesterday\b/.test(lower)) {
|
|
34280
|
+
const startOfToday = startOfDay(now);
|
|
34281
|
+
const start = new Date(startOfToday.getTime() - MS_PER_DAY);
|
|
34282
|
+
const end = new Date(startOfToday.getTime() - 1);
|
|
34283
|
+
return {
|
|
34284
|
+
range: { start, end, relative_label: "yesterday" },
|
|
34285
|
+
matchedSubstring: "yesterday"
|
|
34286
|
+
};
|
|
34287
|
+
}
|
|
34288
|
+
if (/\btoday\b/.test(lower)) {
|
|
34289
|
+
return {
|
|
34290
|
+
range: {
|
|
34291
|
+
start: startOfDay(now),
|
|
34292
|
+
end: now,
|
|
34293
|
+
relative_label: "today"
|
|
34294
|
+
},
|
|
34295
|
+
matchedSubstring: "today"
|
|
34296
|
+
};
|
|
34297
|
+
}
|
|
34298
|
+
const compactHours = lower.match(/\blast\s+(\d+)\s*h\b/i);
|
|
34299
|
+
if (compactHours) {
|
|
34300
|
+
const tok = compactHours[1];
|
|
34301
|
+
if (tok !== void 0) {
|
|
34302
|
+
const n = Number.parseInt(tok, 10);
|
|
34303
|
+
if (Number.isFinite(n) && n > 0) {
|
|
34304
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34305
|
+
return {
|
|
34306
|
+
range: { start, end: now, relative_label: `last ${n}h` },
|
|
34307
|
+
matchedSubstring: compactHours[0]
|
|
34308
|
+
};
|
|
34309
|
+
}
|
|
34310
|
+
}
|
|
34311
|
+
}
|
|
34312
|
+
const hoursMatch = lower.match(
|
|
34313
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:hr\b|hrs\b|hour|hours)/i
|
|
34314
|
+
);
|
|
34315
|
+
if (hoursMatch) {
|
|
34316
|
+
const tok = hoursMatch[1];
|
|
34317
|
+
if (tok !== void 0) {
|
|
34318
|
+
const n = parseCount(tok);
|
|
34319
|
+
if (n !== null && n > 0) {
|
|
34320
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34321
|
+
return {
|
|
34322
|
+
range: { start, end: now, relative_label: `past ${n} hour${n === 1 ? "" : "s"}` },
|
|
34323
|
+
matchedSubstring: hoursMatch[0]
|
|
34324
|
+
};
|
|
34325
|
+
}
|
|
34326
|
+
}
|
|
34327
|
+
}
|
|
34328
|
+
if (/\b(?:past|last)\s+hour\b/.test(lower)) {
|
|
34329
|
+
const start = new Date(now.getTime() - MS_PER_HOUR);
|
|
34330
|
+
return {
|
|
34331
|
+
range: { start, end: now, relative_label: "past hour" },
|
|
34332
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+hour\b/i)[0]
|
|
34333
|
+
};
|
|
34334
|
+
}
|
|
34335
|
+
const daysMatch = lower.match(
|
|
34336
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:d\b|day|days)/i
|
|
34337
|
+
);
|
|
34338
|
+
if (daysMatch) {
|
|
34339
|
+
const tok = daysMatch[1];
|
|
34340
|
+
if (tok !== void 0) {
|
|
34341
|
+
const n = parseCount(tok);
|
|
34342
|
+
if (n !== null && n > 0) {
|
|
34343
|
+
const start = new Date(now.getTime() - n * MS_PER_DAY);
|
|
34344
|
+
return {
|
|
34345
|
+
range: { start, end: now, relative_label: `past ${n} day${n === 1 ? "" : "s"}` },
|
|
34346
|
+
matchedSubstring: daysMatch[0]
|
|
34347
|
+
};
|
|
34348
|
+
}
|
|
34349
|
+
}
|
|
34350
|
+
}
|
|
34351
|
+
if (/\b(?:past|last)\s+day\b/.test(lower)) {
|
|
34352
|
+
const start = new Date(now.getTime() - MS_PER_DAY);
|
|
34353
|
+
return {
|
|
34354
|
+
range: { start, end: now, relative_label: "past day" },
|
|
34355
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+day\b/i)[0]
|
|
34356
|
+
};
|
|
34357
|
+
}
|
|
34358
|
+
if (/\bthis\s+week\b/.test(lower)) {
|
|
34359
|
+
const start = startOfWeek(now);
|
|
34360
|
+
return {
|
|
34361
|
+
range: { start, end: now, relative_label: "this week" },
|
|
34362
|
+
matchedSubstring: lower.match(/\bthis\s+week\b/i)[0]
|
|
34363
|
+
};
|
|
34364
|
+
}
|
|
34365
|
+
if (/\b(?:past|last)\s+week\b/.test(lower)) {
|
|
34366
|
+
const start = new Date(now.getTime() - 7 * MS_PER_DAY);
|
|
34367
|
+
return {
|
|
34368
|
+
range: { start, end: now, relative_label: "past week" },
|
|
34369
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+week\b/i)[0]
|
|
34370
|
+
};
|
|
34371
|
+
}
|
|
34372
|
+
const isoMatch = normalized.match(
|
|
34373
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?)?)\b/
|
|
34374
|
+
);
|
|
34375
|
+
if (isoMatch) {
|
|
34376
|
+
const tok = isoMatch[1];
|
|
34377
|
+
if (tok !== void 0) {
|
|
34378
|
+
const parsed = parseInstant(tok, now);
|
|
34379
|
+
if (parsed) {
|
|
34380
|
+
const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(tok);
|
|
34381
|
+
if (isDateOnly) {
|
|
34382
|
+
return {
|
|
34383
|
+
range: {
|
|
34384
|
+
start: parsed,
|
|
34385
|
+
end: new Date(parsed.getTime() + MS_PER_DAY - 1)
|
|
34386
|
+
},
|
|
34387
|
+
matchedSubstring: tok
|
|
34388
|
+
};
|
|
34389
|
+
}
|
|
34390
|
+
return {
|
|
34391
|
+
range: {
|
|
34392
|
+
start: new Date(parsed.getTime() - 30 * 60 * 1e3),
|
|
34393
|
+
end: new Date(parsed.getTime() + 30 * 60 * 1e3)
|
|
34394
|
+
},
|
|
34395
|
+
matchedSubstring: tok
|
|
34396
|
+
};
|
|
34397
|
+
}
|
|
34398
|
+
}
|
|
34399
|
+
}
|
|
34400
|
+
return null;
|
|
34401
|
+
}
|
|
34402
|
+
function parseInstant(token, now) {
|
|
34403
|
+
const trimmed = token.trim().replace(/[,.!?;]+$/g, "");
|
|
34404
|
+
if (!trimmed) return null;
|
|
34405
|
+
const lower = trimmed.toLowerCase();
|
|
34406
|
+
if (lower === "now") return now;
|
|
34407
|
+
if (lower === "today") return startOfDay(now);
|
|
34408
|
+
if (lower === "yesterday") {
|
|
34409
|
+
return new Date(startOfDay(now).getTime() - MS_PER_DAY);
|
|
34410
|
+
}
|
|
34411
|
+
const isoLike = trimmed.replace(" ", "T");
|
|
34412
|
+
const parsed = new Date(isoLike);
|
|
34413
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
34414
|
+
return null;
|
|
34415
|
+
}
|
|
34416
|
+
function parseCount(token) {
|
|
34417
|
+
const lower = token.toLowerCase();
|
|
34418
|
+
if (/^\d+$/.test(lower)) {
|
|
34419
|
+
const n = Number.parseInt(lower, 10);
|
|
34420
|
+
return Number.isFinite(n) ? n : null;
|
|
34421
|
+
}
|
|
34422
|
+
return NUMBER_WORDS[lower] ?? null;
|
|
34423
|
+
}
|
|
34424
|
+
function startOfDay(d) {
|
|
34425
|
+
const out = new Date(d);
|
|
34426
|
+
out.setHours(0, 0, 0, 0);
|
|
34427
|
+
return out;
|
|
34428
|
+
}
|
|
34429
|
+
function startOfWeek(d) {
|
|
34430
|
+
const out = startOfDay(d);
|
|
34431
|
+
const dayOfWeek = out.getDay();
|
|
34432
|
+
const offsetToMonday = (dayOfWeek + 6) % 7;
|
|
34433
|
+
out.setDate(out.getDate() - offsetToMonday);
|
|
34434
|
+
return out;
|
|
34435
|
+
}
|
|
34436
|
+
function listFromRegistry(registry) {
|
|
34437
|
+
if (!registry) return [];
|
|
34438
|
+
if (Array.isArray(registry)) return registry;
|
|
34439
|
+
if (typeof registry.list === "function") {
|
|
34440
|
+
return registry.list();
|
|
34441
|
+
}
|
|
34442
|
+
return [];
|
|
34443
|
+
}
|
|
34444
|
+
function extractAgentNames(query, registry) {
|
|
34445
|
+
const records = listFromRegistry(registry);
|
|
34446
|
+
if (records.length === 0) return { matched: [], flagged: false };
|
|
34447
|
+
const lowerQuery = query.toLowerCase();
|
|
34448
|
+
const compactQuery = lowerQuery.replace(/[\s_-]+/g, "");
|
|
34449
|
+
const matched = [];
|
|
34450
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34451
|
+
for (const rec of records) {
|
|
34452
|
+
const id = rec.agent_id;
|
|
34453
|
+
if (!id || seen.has(id)) continue;
|
|
34454
|
+
const idLower = id.toLowerCase();
|
|
34455
|
+
if (idLower.length < 3) continue;
|
|
34456
|
+
const idCompact = idLower.replace(/[\s_-]+/g, "");
|
|
34457
|
+
const wordRe = new RegExp(
|
|
34458
|
+
`\\b${idLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
|
|
34459
|
+
"i"
|
|
34460
|
+
);
|
|
34461
|
+
if (wordRe.test(query)) {
|
|
34462
|
+
matched.push(id);
|
|
34463
|
+
seen.add(id);
|
|
34464
|
+
continue;
|
|
34465
|
+
}
|
|
34466
|
+
if (idCompact.length >= 4 && compactQuery.includes(idCompact)) {
|
|
34467
|
+
matched.push(id);
|
|
34468
|
+
seen.add(id);
|
|
34469
|
+
}
|
|
34470
|
+
}
|
|
34471
|
+
const agentMention = lowerQuery.match(/\bagent\s+([a-z0-9_-]{3,40})/i);
|
|
34472
|
+
const flagged = matched.length === 0 && agentMention !== null && agentMention[1] !== void 0 && !records.some((r) => r.agent_id.toLowerCase() === agentMention[1]?.toLowerCase());
|
|
34473
|
+
return { matched, flagged };
|
|
34474
|
+
}
|
|
34475
|
+
function escapeRegex(s) {
|
|
34476
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34477
|
+
}
|
|
34478
|
+
function extractEventTypes(query, enumValues) {
|
|
34479
|
+
const lower = query.toLowerCase();
|
|
34480
|
+
const matched = [];
|
|
34481
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34482
|
+
for (const ev of enumValues) {
|
|
34483
|
+
if (seen.has(ev)) continue;
|
|
34484
|
+
const re = new RegExp(`\\b${escapeRegex(ev)}\\b`, "i");
|
|
34485
|
+
if (re.test(query)) {
|
|
34486
|
+
matched.push(ev);
|
|
34487
|
+
seen.add(ev);
|
|
34488
|
+
}
|
|
34489
|
+
}
|
|
34490
|
+
for (const syn of EVENT_SYNONYMS) {
|
|
34491
|
+
const re = new RegExp(
|
|
34492
|
+
`\\b${syn.phrase.split(/\s+/).map(escapeRegex).join("\\s+")}\\b`,
|
|
34493
|
+
"i"
|
|
34494
|
+
);
|
|
34495
|
+
if (re.test(query)) {
|
|
34496
|
+
for (const c of syn.canonical) {
|
|
34497
|
+
if (seen.has(c)) continue;
|
|
34498
|
+
if (!enumValues.includes(c)) continue;
|
|
34499
|
+
matched.push(c);
|
|
34500
|
+
seen.add(c);
|
|
34501
|
+
}
|
|
34502
|
+
}
|
|
34503
|
+
}
|
|
34504
|
+
const globMatches = lower.match(/\b([a-z_]+)_\*/g) ?? [];
|
|
34505
|
+
for (const glob of globMatches) {
|
|
34506
|
+
const prefix = glob.slice(0, -2);
|
|
34507
|
+
for (const ev of enumValues) {
|
|
34508
|
+
if (seen.has(ev)) continue;
|
|
34509
|
+
if (ev.startsWith(prefix)) {
|
|
34510
|
+
matched.push(ev);
|
|
34511
|
+
seen.add(ev);
|
|
34512
|
+
}
|
|
34513
|
+
}
|
|
34514
|
+
}
|
|
34515
|
+
const eventNounMention = /\b(?:event|events|class|classes)\b/i.test(query) && matched.length === 0;
|
|
34516
|
+
return { matched, flagged: eventNounMention };
|
|
34517
|
+
}
|
|
34518
|
+
function deriveIntentPhrase(query, stripTokens) {
|
|
34519
|
+
let out = query;
|
|
34520
|
+
for (const tok of stripTokens) {
|
|
34521
|
+
if (!tok) continue;
|
|
34522
|
+
const re = new RegExp(escapeRegex(tok), "gi");
|
|
34523
|
+
out = out.replace(re, " ");
|
|
34524
|
+
}
|
|
34525
|
+
return out.replace(/\s+/g, " ").trim();
|
|
34526
|
+
}
|
|
34527
|
+
function computeConfidence(parsed) {
|
|
34528
|
+
const dims = [
|
|
34529
|
+
{ present: parsed.hasTimeMention, resolved: parsed.timeResolved },
|
|
34530
|
+
{ present: parsed.hasAgentMention, resolved: parsed.agentResolved },
|
|
34531
|
+
{ present: parsed.hasEventMention, resolved: parsed.eventResolved }
|
|
34532
|
+
];
|
|
34533
|
+
const present = dims.filter((d) => d.present);
|
|
34534
|
+
let base;
|
|
34535
|
+
if (present.length === 0) {
|
|
34536
|
+
base = parsed.intentEmpty ? 0 : 0.3;
|
|
34537
|
+
} else {
|
|
34538
|
+
const resolved = present.filter((d) => d.resolved).length;
|
|
34539
|
+
base = resolved / present.length;
|
|
34540
|
+
}
|
|
34541
|
+
const adjusted = base - 0.15 * parsed.ambiguityCount;
|
|
34542
|
+
if (adjusted < 0) return 0;
|
|
34543
|
+
if (adjusted > 1) return 1;
|
|
34544
|
+
return adjusted;
|
|
34545
|
+
}
|
|
34546
|
+
function parseQuery(query, opts) {
|
|
34547
|
+
const now = opts?.now ?? /* @__PURE__ */ new Date();
|
|
34548
|
+
const enumValues = opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES;
|
|
34549
|
+
const original = query ?? "";
|
|
34550
|
+
const trimmed = original.trim();
|
|
34551
|
+
if (trimmed.length === 0) {
|
|
34552
|
+
return {
|
|
34553
|
+
time_range: null,
|
|
34554
|
+
agent_names: [],
|
|
34555
|
+
event_types: [],
|
|
34556
|
+
intent_phrase: "",
|
|
34557
|
+
ambiguity_flags: ["no_signal_extracted"],
|
|
34558
|
+
parse_confidence: 0
|
|
34559
|
+
};
|
|
34560
|
+
}
|
|
34561
|
+
const ambiguity_flags = /* @__PURE__ */ new Set();
|
|
34562
|
+
const timeMatch = resolveTimeRange(trimmed, now);
|
|
34563
|
+
const hasTimeMention = TIME_MENTION_PROBE.test(trimmed);
|
|
34564
|
+
if (hasTimeMention && !timeMatch) {
|
|
34565
|
+
ambiguity_flags.add("unknown_time_token");
|
|
34566
|
+
}
|
|
34567
|
+
const agentResult = extractAgentNames(trimmed, opts?.registry);
|
|
34568
|
+
if (agentResult.flagged) {
|
|
34569
|
+
ambiguity_flags.add("unknown_agent_token");
|
|
34570
|
+
}
|
|
34571
|
+
const hasAgentMention = AGENT_MENTION_PROBE.test(trimmed);
|
|
34572
|
+
const eventResult = extractEventTypes(trimmed, enumValues);
|
|
34573
|
+
const hasEventMention = EVENT_MENTION_PROBE.test(trimmed);
|
|
34574
|
+
if (eventResult.flagged) {
|
|
34575
|
+
ambiguity_flags.add("unknown_event_token");
|
|
34576
|
+
}
|
|
34577
|
+
const stripTokens = [];
|
|
34578
|
+
if (timeMatch) stripTokens.push(timeMatch.matchedSubstring);
|
|
34579
|
+
for (const name of agentResult.matched) stripTokens.push(name);
|
|
34580
|
+
for (const ev of eventResult.matched) {
|
|
34581
|
+
if (trimmed.toLowerCase().includes(ev.toLowerCase())) {
|
|
34582
|
+
stripTokens.push(ev);
|
|
34583
|
+
}
|
|
34584
|
+
}
|
|
34585
|
+
const intent_phrase = deriveIntentPhrase(trimmed, stripTokens);
|
|
34586
|
+
const parse_confidence = computeConfidence({
|
|
34587
|
+
hasTimeMention,
|
|
34588
|
+
timeResolved: timeMatch !== null,
|
|
34589
|
+
hasAgentMention,
|
|
34590
|
+
agentResolved: agentResult.matched.length > 0,
|
|
34591
|
+
hasEventMention,
|
|
34592
|
+
eventResolved: eventResult.matched.length > 0,
|
|
34593
|
+
intentEmpty: intent_phrase.length === 0,
|
|
34594
|
+
ambiguityCount: ambiguity_flags.size
|
|
34595
|
+
});
|
|
34596
|
+
if (timeMatch === null && agentResult.matched.length === 0 && eventResult.matched.length === 0 && intent_phrase.length === 0) {
|
|
34597
|
+
ambiguity_flags.add("no_signal_extracted");
|
|
34598
|
+
}
|
|
34599
|
+
return {
|
|
34600
|
+
time_range: timeMatch ? timeMatch.range : null,
|
|
34601
|
+
agent_names: agentResult.matched,
|
|
34602
|
+
event_types: eventResult.matched,
|
|
34603
|
+
intent_phrase,
|
|
34604
|
+
ambiguity_flags: Array.from(ambiguity_flags),
|
|
34605
|
+
parse_confidence
|
|
34606
|
+
};
|
|
34607
|
+
}
|
|
34608
|
+
function isLowConfidence(parsed) {
|
|
34609
|
+
return parsed.parse_confidence < LLM_ASSIST_THRESHOLD;
|
|
34610
|
+
}
|
|
34611
|
+
async function parseQueryWithLlmAssist(query, llmAssist, opts) {
|
|
34612
|
+
const parsed = parseQuery(query, opts);
|
|
34613
|
+
if (!llmAssist || !isLowConfidence(parsed)) return parsed;
|
|
34614
|
+
let completion;
|
|
34615
|
+
try {
|
|
34616
|
+
completion = await llmAssist(query, parsed);
|
|
34617
|
+
} catch {
|
|
34618
|
+
return parsed;
|
|
34619
|
+
}
|
|
34620
|
+
if (!completion || typeof completion !== "object") return parsed;
|
|
34621
|
+
const merged = { ...parsed };
|
|
34622
|
+
if (parsed.time_range === null && completion.time_range) {
|
|
34623
|
+
merged.time_range = completion.time_range;
|
|
34624
|
+
}
|
|
34625
|
+
if (parsed.agent_names.length === 0 && Array.isArray(completion.agent_names)) {
|
|
34626
|
+
merged.agent_names = completion.agent_names.filter(
|
|
34627
|
+
(s) => typeof s === "string" && s.length > 0
|
|
34628
|
+
);
|
|
34629
|
+
}
|
|
34630
|
+
if (parsed.event_types.length === 0 && Array.isArray(completion.event_types)) {
|
|
34631
|
+
const allowed = new Set(opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES);
|
|
34632
|
+
merged.event_types = completion.event_types.filter(
|
|
34633
|
+
(s) => typeof s === "string" && allowed.has(s)
|
|
34634
|
+
);
|
|
34635
|
+
}
|
|
34636
|
+
merged.parse_confidence = Math.max(
|
|
34637
|
+
parsed.parse_confidence,
|
|
34638
|
+
computeConfidence({
|
|
34639
|
+
hasTimeMention: TIME_MENTION_PROBE.test(query),
|
|
34640
|
+
timeResolved: merged.time_range !== null,
|
|
34641
|
+
hasAgentMention: AGENT_MENTION_PROBE.test(query),
|
|
34642
|
+
agentResolved: merged.agent_names.length > 0,
|
|
34643
|
+
hasEventMention: EVENT_MENTION_PROBE.test(query),
|
|
34644
|
+
eventResolved: merged.event_types.length > 0,
|
|
34645
|
+
intentEmpty: merged.intent_phrase.length === 0,
|
|
34646
|
+
ambiguityCount: merged.ambiguity_flags.length
|
|
34647
|
+
})
|
|
34648
|
+
);
|
|
34649
|
+
return merged;
|
|
34650
|
+
}
|
|
34651
|
+
function auditSafeSummary(parsed) {
|
|
34652
|
+
return {
|
|
34653
|
+
time_range: parsed.time_range ? {
|
|
34654
|
+
start_iso: parsed.time_range.start.toISOString(),
|
|
34655
|
+
end_iso: parsed.time_range.end.toISOString(),
|
|
34656
|
+
...parsed.time_range.relative_label !== void 0 ? { relative_label: parsed.time_range.relative_label } : {}
|
|
34657
|
+
} : null,
|
|
34658
|
+
agent_names: [...parsed.agent_names],
|
|
34659
|
+
event_types: [...parsed.event_types],
|
|
34660
|
+
ambiguity_flags: [...parsed.ambiguity_flags],
|
|
34661
|
+
parse_confidence: parsed.parse_confidence
|
|
34662
|
+
};
|
|
34663
|
+
}
|
|
34664
|
+
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;
|
|
34665
|
+
var init_concierge_query_grammar = __esm({
|
|
34666
|
+
"src/chat/concierge-query-grammar.ts"() {
|
|
34667
|
+
init_constants4();
|
|
34668
|
+
init_operator_chat_audit_events();
|
|
34669
|
+
CANONICAL_AUDIT_EVENT_CLASSES = [
|
|
34670
|
+
// Lifecycle / policy
|
|
34671
|
+
"policy_change",
|
|
34672
|
+
"approval_request",
|
|
34673
|
+
"audit_truncate",
|
|
34674
|
+
"lockdown",
|
|
34675
|
+
"unwrap",
|
|
34676
|
+
// Exit bundle (Tier 1)
|
|
34677
|
+
"exit_bundle_export",
|
|
34678
|
+
"exit_bundle_import_activate",
|
|
34679
|
+
"exit_bundle_rekey",
|
|
34680
|
+
// Cross-harness approval aggregator
|
|
34681
|
+
"cross_harness_approval_aggregated",
|
|
34682
|
+
"cross_harness_approval_resolved",
|
|
34683
|
+
"cross_harness_approval_deduped",
|
|
34684
|
+
"cross_harness_approval_payload_decrypted",
|
|
34685
|
+
"cross_harness_approval_audit_trail_viewed",
|
|
34686
|
+
"cross_harness_approval_replayed",
|
|
34687
|
+
// Composition (full set from constants.ts)
|
|
34688
|
+
...COMPOSITION_EVENT_TYPES,
|
|
34689
|
+
// Operator chat / concierge (full set from OPERATOR_CHAT_OPS)
|
|
34690
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CHAT,
|
|
34691
|
+
OPERATOR_CHAT_OPS.AGENT_INSPECT_PANEL_OPENED,
|
|
34692
|
+
OPERATOR_CHAT_OPS.CONCIERGE_HISTORY_READ,
|
|
34693
|
+
OPERATOR_CHAT_OPS.CONCIERGE_THREAD_DELETED,
|
|
34694
|
+
OPERATOR_CHAT_OPS.CONCIERGE_MEMORY_READ_FAILED,
|
|
34695
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
34696
|
+
// Bridge / commitment
|
|
34697
|
+
"bridge_commit",
|
|
34698
|
+
"bridge_verify",
|
|
34699
|
+
"bridge_attest",
|
|
34700
|
+
"proof_commitment",
|
|
34701
|
+
"proof_reveal",
|
|
34702
|
+
// Reputation
|
|
34703
|
+
"reputation_export",
|
|
34704
|
+
"reputation_import",
|
|
34705
|
+
"reputation_publish",
|
|
34706
|
+
"reputation_record",
|
|
34707
|
+
"reputation_query"
|
|
34708
|
+
];
|
|
34709
|
+
EVENT_SYNONYMS = [
|
|
34710
|
+
{ phrase: "approvals", canonical: ["approval_request", "cross_harness_approval_aggregated", "cross_harness_approval_resolved"] },
|
|
34711
|
+
{ phrase: "approval", canonical: ["approval_request"] },
|
|
34712
|
+
{ phrase: "policy changes", canonical: ["policy_change"] },
|
|
34713
|
+
{ phrase: "policy change", canonical: ["policy_change"] },
|
|
34714
|
+
{ phrase: "policy edits", canonical: ["policy_change"] },
|
|
34715
|
+
{ phrase: "lockdowns", canonical: ["lockdown"] },
|
|
34716
|
+
{ phrase: "exit bundles", canonical: ["exit_bundle_export", "exit_bundle_import_activate"] },
|
|
34717
|
+
{ phrase: "exit bundle", canonical: ["exit_bundle_export"] },
|
|
34718
|
+
{ phrase: "audit truncations", canonical: ["audit_truncate"] },
|
|
34719
|
+
{ phrase: "audit truncation", canonical: ["audit_truncate"] },
|
|
34720
|
+
{ phrase: "compositions", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34721
|
+
{ phrase: "receipts", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34722
|
+
{ phrase: "receipt verifications", canonical: ["composition_receipt_verified"] },
|
|
34723
|
+
{ phrase: "concierge chats", canonical: [OPERATOR_CHAT_OPS.CONCIERGE_CHAT] },
|
|
34724
|
+
{ phrase: "cross harness approvals", canonical: ["cross_harness_approval_aggregated", "cross_harness_approval_resolved"] }
|
|
34725
|
+
];
|
|
34726
|
+
MS_PER_HOUR = 60 * 60 * 1e3;
|
|
34727
|
+
MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
34728
|
+
NUMBER_WORDS = {
|
|
34729
|
+
a: 1,
|
|
34730
|
+
an: 1,
|
|
34731
|
+
one: 1,
|
|
34732
|
+
two: 2,
|
|
34733
|
+
three: 3,
|
|
34734
|
+
four: 4,
|
|
34735
|
+
five: 5,
|
|
34736
|
+
six: 6,
|
|
34737
|
+
seven: 7,
|
|
34738
|
+
eight: 8,
|
|
34739
|
+
nine: 9,
|
|
34740
|
+
ten: 10,
|
|
34741
|
+
twelve: 12,
|
|
34742
|
+
twentyfour: 24
|
|
34743
|
+
};
|
|
34744
|
+
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;
|
|
34745
|
+
AGENT_MENTION_PROBE = /\bagent[s]?\b/i;
|
|
34746
|
+
EVENT_MENTION_PROBE = /\b(event|events|class|classes|approvals?|policy)\b/i;
|
|
34747
|
+
LLM_ASSIST_THRESHOLD = 0.5;
|
|
34748
|
+
}
|
|
34749
|
+
});
|
|
34750
|
+
function approxTokenLen2(text) {
|
|
33421
34751
|
return Math.ceil(text.length / 4);
|
|
33422
34752
|
}
|
|
33423
34753
|
function makeEventId(prefix) {
|
|
33424
34754
|
return `${prefix}-${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;
|
|
33425
34755
|
}
|
|
34756
|
+
function classifyFetcherError(error) {
|
|
34757
|
+
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
34758
|
+
if (msg.includes("timeout") || msg.includes("timed out")) return "timeout";
|
|
34759
|
+
if (msg.includes("schema") || msg.includes("invalid shape")) {
|
|
34760
|
+
return "schema_mismatch";
|
|
34761
|
+
}
|
|
34762
|
+
if (msg.includes("io") || msg.includes("read") || msg.includes("enoent") || msg.includes("eacces")) {
|
|
34763
|
+
return "io_failed";
|
|
34764
|
+
}
|
|
34765
|
+
return "unknown";
|
|
34766
|
+
}
|
|
33426
34767
|
function formatPriorTurnLine(turn) {
|
|
33427
34768
|
const label = turn.role === "user" ? "OPERATOR" : "CONCIERGE";
|
|
33428
34769
|
return `${label}: ${turn.content}`;
|
|
@@ -33430,18 +34771,21 @@ function formatPriorTurnLine(turn) {
|
|
|
33430
34771
|
function hashOf(input) {
|
|
33431
34772
|
return hashToString(sha256.sha256(stringToBytes(input)));
|
|
33432
34773
|
}
|
|
33433
|
-
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;
|
|
34774
|
+
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;
|
|
33434
34775
|
var init_operator_chat_service = __esm({
|
|
33435
34776
|
"src/chat/operator-chat-service.ts"() {
|
|
33436
34777
|
init_hashing();
|
|
33437
34778
|
init_encoding();
|
|
33438
34779
|
init_operator_chat_audit_events();
|
|
33439
34780
|
init_operator_chat_types();
|
|
34781
|
+
init_concierge_context_router();
|
|
34782
|
+
init_concierge_query_grammar();
|
|
33440
34783
|
DEFAULT_CONCIERGE_MAX_TOKENS = 512;
|
|
33441
34784
|
DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS = 10;
|
|
33442
34785
|
DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS = 24 * 60 * 60 * 1e3;
|
|
33443
34786
|
DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET = 500;
|
|
33444
34787
|
DEFAULT_CONCIERGE_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
34788
|
+
DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET = 2e3;
|
|
33445
34789
|
SANCTUARY_DOMAIN_REFERENCE = `Castle Architecture (four enforcement layers):
|
|
33446
34790
|
1. Castle Wall: OS-boundary egress filter enforced at the kernel level. Blocks unauthorized outbound calls even from prompt-injected agents.
|
|
33447
34791
|
2. Sentinels: internal observation via process introspection. Surfaces anomalies to the operator; does not enforce.
|
|
@@ -33483,6 +34827,11 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33483
34827
|
historyTokenBudget;
|
|
33484
34828
|
sessionTtlMs;
|
|
33485
34829
|
clock;
|
|
34830
|
+
contextFetchers;
|
|
34831
|
+
contextLlmAssist;
|
|
34832
|
+
dynamicContextBudget;
|
|
34833
|
+
agentRegistry;
|
|
34834
|
+
grammarLlmAssist;
|
|
33486
34835
|
/**
|
|
33487
34836
|
* In-memory thread_id assigned to the active concierge session.
|
|
33488
34837
|
* The first sendConcierge call after construction allocates a fresh
|
|
@@ -33514,6 +34863,19 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33514
34863
|
this.historyTokenBudget = deps.conciergeHistoryTokenBudget !== void 0 && deps.conciergeHistoryTokenBudget > 0 ? deps.conciergeHistoryTokenBudget : DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET;
|
|
33515
34864
|
this.sessionTtlMs = deps.conciergeSessionTtlMs !== void 0 && deps.conciergeSessionTtlMs > 0 ? deps.conciergeSessionTtlMs : DEFAULT_CONCIERGE_SESSION_TTL_MS;
|
|
33516
34865
|
this.clock = deps.conciergeClock ?? (() => Date.now());
|
|
34866
|
+
if (deps.conciergeContextFetchers) {
|
|
34867
|
+
this.contextFetchers = deps.conciergeContextFetchers;
|
|
34868
|
+
}
|
|
34869
|
+
if (deps.conciergeContextLlmAssist) {
|
|
34870
|
+
this.contextLlmAssist = deps.conciergeContextLlmAssist;
|
|
34871
|
+
}
|
|
34872
|
+
this.dynamicContextBudget = deps.conciergeDynamicContextBudget !== void 0 && deps.conciergeDynamicContextBudget > 0 ? deps.conciergeDynamicContextBudget : DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET;
|
|
34873
|
+
if (deps.conciergeAgentRegistry) {
|
|
34874
|
+
this.agentRegistry = deps.conciergeAgentRegistry;
|
|
34875
|
+
}
|
|
34876
|
+
if (deps.conciergeGrammarLlmAssist) {
|
|
34877
|
+
this.grammarLlmAssist = deps.conciergeGrammarLlmAssist;
|
|
34878
|
+
}
|
|
33517
34879
|
}
|
|
33518
34880
|
// ── Concierge ─────────────────────────────────────────────────────────
|
|
33519
34881
|
/**
|
|
@@ -33572,11 +34934,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33572
34934
|
await this.memory.appendTurn(threadId, "user", trimmed).catch(() => {
|
|
33573
34935
|
});
|
|
33574
34936
|
}
|
|
34937
|
+
const parsedGrammar = await this.runGrammarParse(filterResult.filtered);
|
|
33575
34938
|
const start = Date.now();
|
|
33576
34939
|
let conciergeBody;
|
|
33577
34940
|
let servedBy = "disabled";
|
|
33578
34941
|
let displayLabel = "Concierge: substrate not configured";
|
|
33579
34942
|
let outcome = "substrate_disabled";
|
|
34943
|
+
let dynamicCategoriesIncluded = [];
|
|
33580
34944
|
if (!this.substrateSelector) {
|
|
33581
34945
|
conciergeBody = "Concierge unavailable. The substrate selector is not configured for this fortress. Pick a substrate in the Policy center to enable concierge replies.";
|
|
33582
34946
|
} else {
|
|
@@ -33588,7 +34952,15 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33588
34952
|
conciergeBody = "Concierge unavailable. The chosen substrate does not support summarization. Pick a different substrate in the Policy center.";
|
|
33589
34953
|
outcome = "substrate_disabled";
|
|
33590
34954
|
} else {
|
|
33591
|
-
const
|
|
34955
|
+
const dynamicResult = await this.runDynamicContextFold(
|
|
34956
|
+
filterResult.filtered,
|
|
34957
|
+
parsedGrammar
|
|
34958
|
+
);
|
|
34959
|
+
dynamicCategoriesIncluded = dynamicResult.categoriesIncluded;
|
|
34960
|
+
const context = await this.assembleConciergeContext(
|
|
34961
|
+
priorTurns,
|
|
34962
|
+
dynamicResult.section
|
|
34963
|
+
);
|
|
33592
34964
|
const response = await this.substrateSelector.invokeSummarize(
|
|
33593
34965
|
"concierge",
|
|
33594
34966
|
{
|
|
@@ -33652,7 +35024,9 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33652
35024
|
...assistantTurnId !== void 0 ? { turn_index: assistantTurnId } : {},
|
|
33653
35025
|
...this.memory ? {
|
|
33654
35026
|
prior_turns_folded: memoryReadFailureReason === null ? priorTurns.length : 0
|
|
33655
|
-
} : {}
|
|
35027
|
+
} : {},
|
|
35028
|
+
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {},
|
|
35029
|
+
parsed_grammar: auditSafeSummary(parsedGrammar)
|
|
33656
35030
|
};
|
|
33657
35031
|
this.emit(OPERATOR_CHAT_OPS.CONCIERGE_CHAT, payload, outcome === "ok" ? "success" : "failure");
|
|
33658
35032
|
return {
|
|
@@ -33803,10 +35177,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33803
35177
|
* ## Sanctuary reference
|
|
33804
35178
|
* <static domain reference block>
|
|
33805
35179
|
*
|
|
35180
|
+
* ## Live fortress context ← WP-V1.3-9 Tau-3, when present
|
|
35181
|
+
* ### <Category>
|
|
35182
|
+
* <fetcher payload>
|
|
35183
|
+
*
|
|
33806
35184
|
* ## Prior conversation ← WP-V1.3-9 Tau-2, when present
|
|
33807
35185
|
* OPERATOR: ...
|
|
33808
35186
|
* CONCIERGE: ...
|
|
33809
|
-
* ---
|
|
33810
35187
|
*
|
|
33811
35188
|
* ## Recent activity
|
|
33812
35189
|
* <recentActivity output>
|
|
@@ -33825,13 +35202,14 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33825
35202
|
* if available; the v1.2 selector does not expose one, so structured
|
|
33826
35203
|
* serialization is the canonical path for v1.3.
|
|
33827
35204
|
*/
|
|
33828
|
-
async assembleConciergeContext(priorTurns = []) {
|
|
35205
|
+
async assembleConciergeContext(priorTurns = [], dynamicSection = "") {
|
|
33829
35206
|
const ref = `## Sanctuary reference
|
|
33830
35207
|
${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
33831
35208
|
const priorSection = this.formatPriorTurnsSection(priorTurns);
|
|
33832
35209
|
if (!this.contextProviders) {
|
|
33833
35210
|
return [
|
|
33834
35211
|
ref,
|
|
35212
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33835
35213
|
...priorSection ? [priorSection] : [],
|
|
33836
35214
|
"## Recent activity\n(no providers wired)",
|
|
33837
35215
|
"## Wrapped agents\n(no providers wired)",
|
|
@@ -33845,6 +35223,7 @@ ${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
|
33845
35223
|
]);
|
|
33846
35224
|
return [
|
|
33847
35225
|
ref,
|
|
35226
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33848
35227
|
...priorSection ? [priorSection] : [],
|
|
33849
35228
|
`## Recent activity
|
|
33850
35229
|
${activity}`,
|
|
@@ -33854,6 +35233,69 @@ ${agents}`,
|
|
|
33854
35233
|
${inbox}`
|
|
33855
35234
|
].join("\n\n");
|
|
33856
35235
|
}
|
|
35236
|
+
/**
|
|
35237
|
+
* Run the WP-V1.3-9 Tau-3 dynamic-context fold for a single round-
|
|
35238
|
+
* trip. Fail-soft on every axis: missing fetchers short-circuit to
|
|
35239
|
+
* an empty fold, fetcher failures emit a per-category audit event
|
|
35240
|
+
* and are omitted from the rendered section, an LLM-assist failure
|
|
35241
|
+
* proceeds with no fold. Returns the rendered section + the list of
|
|
35242
|
+
* categories whose data made it into the section (used for the
|
|
35243
|
+
* round-trip audit emission).
|
|
35244
|
+
*
|
|
35245
|
+
* Tau-4: receives the pre-parsed `ParsedQuery` and forwards it as the
|
|
35246
|
+
* `parsed` opt to `foldContext`, so fetchers see the structured
|
|
35247
|
+
* `FetcherHints` derived from it.
|
|
35248
|
+
*/
|
|
35249
|
+
async runDynamicContextFold(query, parsedGrammar) {
|
|
35250
|
+
if (!this.contextFetchers) {
|
|
35251
|
+
return { section: "", categoriesIncluded: [] };
|
|
35252
|
+
}
|
|
35253
|
+
const result = await foldContext(query, this.contextFetchers, {
|
|
35254
|
+
maxTokens: this.dynamicContextBudget,
|
|
35255
|
+
...this.contextLlmAssist ? { llmAssistClassify: this.contextLlmAssist } : {},
|
|
35256
|
+
onFetcherFailure: (category, error) => {
|
|
35257
|
+
this.emitContextFetcherFailed(category, classifyFetcherError(error));
|
|
35258
|
+
},
|
|
35259
|
+
parsed: parsedGrammar
|
|
35260
|
+
});
|
|
35261
|
+
return result;
|
|
35262
|
+
}
|
|
35263
|
+
/**
|
|
35264
|
+
* WP-V1.3-9 Tau-4: parse the (PII-filtered) operator query into a
|
|
35265
|
+
* `ParsedQuery`. Routes through the LLM-assist completion hook when
|
|
35266
|
+
* configured and the rule-based parse is below
|
|
35267
|
+
* `LLM_ASSIST_THRESHOLD`. Always returns a parse object (never
|
|
35268
|
+
* throws) so the audit emission can carry the result unconditionally.
|
|
35269
|
+
*/
|
|
35270
|
+
async runGrammarParse(query) {
|
|
35271
|
+
return parseQueryWithLlmAssist(query, this.grammarLlmAssist, {
|
|
35272
|
+
...this.agentRegistry !== void 0 ? { registry: this.agentRegistry } : {},
|
|
35273
|
+
eventClassEnum: CANONICAL_AUDIT_EVENT_CLASSES
|
|
35274
|
+
});
|
|
35275
|
+
}
|
|
35276
|
+
/**
|
|
35277
|
+
* Emit the WP-V1.3-9 Tau-3 fetcher-failure audit event. Pulled out
|
|
35278
|
+
* of the fold path so the dynamic-context handler stays readable.
|
|
35279
|
+
* Emits with `result: "failure"` since the named category dropped
|
|
35280
|
+
* from the rendered section for this round-trip.
|
|
35281
|
+
*/
|
|
35282
|
+
emitContextFetcherFailed(category, failureReason) {
|
|
35283
|
+
const payload = {
|
|
35284
|
+
version: "1.2",
|
|
35285
|
+
event_id: makeEventId("conc-ctxfail"),
|
|
35286
|
+
emitted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35287
|
+
identity_id: this.identityId,
|
|
35288
|
+
kind: "operator_concierge_context_fetcher_failed",
|
|
35289
|
+
surface: "concierge",
|
|
35290
|
+
category,
|
|
35291
|
+
failure_reason: failureReason
|
|
35292
|
+
};
|
|
35293
|
+
this.emit(
|
|
35294
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
35295
|
+
payload,
|
|
35296
|
+
"failure"
|
|
35297
|
+
);
|
|
35298
|
+
}
|
|
33857
35299
|
/**
|
|
33858
35300
|
* Render the prior-conversation section with token-budget enforcement
|
|
33859
35301
|
* (WP-V1.3-9 Tau-2). Drops oldest turns first when the rendered
|
|
@@ -33864,14 +35306,14 @@ ${inbox}`
|
|
|
33864
35306
|
if (turns.length === 0) return "";
|
|
33865
35307
|
const HEADER = "## Prior conversation";
|
|
33866
35308
|
const lines = turns.map(formatPriorTurnLine);
|
|
33867
|
-
const headerTokens =
|
|
35309
|
+
const headerTokens = approxTokenLen2(`${HEADER}
|
|
33868
35310
|
`);
|
|
33869
|
-
const sepTokens =
|
|
35311
|
+
const sepTokens = approxTokenLen2("\n");
|
|
33870
35312
|
let runningTokens = headerTokens;
|
|
33871
35313
|
let runningLines = [];
|
|
33872
35314
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
33873
35315
|
const line = lines[i];
|
|
33874
|
-
const tokens =
|
|
35316
|
+
const tokens = approxTokenLen2(line) + (runningLines.length > 0 ? sepTokens : 0);
|
|
33875
35317
|
if (runningTokens + tokens > this.historyTokenBudget) break;
|
|
33876
35318
|
runningTokens += tokens;
|
|
33877
35319
|
runningLines.push(line);
|
|
@@ -33899,7 +35341,7 @@ ${runningLines.join("\n")}`;
|
|
|
33899
35341
|
function chatStorageKey(surface, threadKey) {
|
|
33900
35342
|
return `${surface}.${threadKey}`;
|
|
33901
35343
|
}
|
|
33902
|
-
var OPERATOR_CHAT_NAMESPACE,
|
|
35344
|
+
var OPERATOR_CHAT_NAMESPACE, HKDF_INFO2, OperatorChatStore;
|
|
33903
35345
|
var init_operator_chat_store = __esm({
|
|
33904
35346
|
"src/chat/operator-chat-store.ts"() {
|
|
33905
35347
|
init_encryption();
|
|
@@ -33907,13 +35349,13 @@ var init_operator_chat_store = __esm({
|
|
|
33907
35349
|
init_encoding();
|
|
33908
35350
|
init_operator_chat_types();
|
|
33909
35351
|
OPERATOR_CHAT_NAMESPACE = "_chat";
|
|
33910
|
-
|
|
35352
|
+
HKDF_INFO2 = "operator-chat-store-v1";
|
|
33911
35353
|
OperatorChatStore = class {
|
|
33912
35354
|
storage;
|
|
33913
35355
|
encryptionKey;
|
|
33914
35356
|
constructor(storage, masterKey) {
|
|
33915
35357
|
this.storage = storage;
|
|
33916
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
35358
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO2);
|
|
33917
35359
|
}
|
|
33918
35360
|
/**
|
|
33919
35361
|
* Load a thread. Returns null if no record exists or if the on-disk
|
|
@@ -33998,7 +35440,7 @@ var init_operator_chat_store = __esm({
|
|
|
33998
35440
|
function bundleKey(threadId) {
|
|
33999
35441
|
return `${CONCIERGE_MEMORY_KEY_PREFIX}${threadId}`;
|
|
34000
35442
|
}
|
|
34001
|
-
function
|
|
35443
|
+
function stripKeyPrefix2(key) {
|
|
34002
35444
|
if (!key.startsWith(CONCIERGE_MEMORY_KEY_PREFIX)) return null;
|
|
34003
35445
|
return key.slice(CONCIERGE_MEMORY_KEY_PREFIX.length);
|
|
34004
35446
|
}
|
|
@@ -34009,7 +35451,7 @@ function lastTurnId(bundle) {
|
|
|
34009
35451
|
}
|
|
34010
35452
|
return max;
|
|
34011
35453
|
}
|
|
34012
|
-
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX,
|
|
35454
|
+
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX, HKDF_INFO3, DEFAULT_CONCIERGE_RETENTION_DAYS, MAX_BUNDLE_BYTES3, ConciergeMemoryStore;
|
|
34013
35455
|
var init_concierge_memory_store = __esm({
|
|
34014
35456
|
"src/chat/concierge-memory-store.ts"() {
|
|
34015
35457
|
init_encryption();
|
|
@@ -34017,9 +35459,9 @@ var init_concierge_memory_store = __esm({
|
|
|
34017
35459
|
init_encoding();
|
|
34018
35460
|
CONCIERGE_MEMORY_NAMESPACE = "_chat";
|
|
34019
35461
|
CONCIERGE_MEMORY_KEY_PREFIX = "concierge_memory.";
|
|
34020
|
-
|
|
35462
|
+
HKDF_INFO3 = "concierge-memory-store-v1";
|
|
34021
35463
|
DEFAULT_CONCIERGE_RETENTION_DAYS = 30;
|
|
34022
|
-
|
|
35464
|
+
MAX_BUNDLE_BYTES3 = 4 * 1024 * 1024;
|
|
34023
35465
|
ConciergeMemoryStore = class {
|
|
34024
35466
|
storage;
|
|
34025
35467
|
encryptionKey;
|
|
@@ -34028,7 +35470,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34028
35470
|
locks;
|
|
34029
35471
|
constructor(opts) {
|
|
34030
35472
|
this.storage = opts.storage;
|
|
34031
|
-
this.encryptionKey = derivePurposeKey(opts.masterKey,
|
|
35473
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO3);
|
|
34032
35474
|
this.fortressId = opts.fortressId;
|
|
34033
35475
|
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_CONCIERGE_RETENTION_DAYS;
|
|
34034
35476
|
this.locks = /* @__PURE__ */ new Map();
|
|
@@ -34107,7 +35549,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34107
35549
|
return { ok: false, reason: "io_failed" };
|
|
34108
35550
|
}
|
|
34109
35551
|
if (!raw) return { ok: true, turns: [] };
|
|
34110
|
-
if (raw.length >
|
|
35552
|
+
if (raw.length > MAX_BUNDLE_BYTES3) {
|
|
34111
35553
|
return { ok: false, reason: "oversize_bundle" };
|
|
34112
35554
|
}
|
|
34113
35555
|
let envelope;
|
|
@@ -34154,7 +35596,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34154
35596
|
);
|
|
34155
35597
|
const summaries = [];
|
|
34156
35598
|
for (const meta of entries) {
|
|
34157
|
-
const threadId =
|
|
35599
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34158
35600
|
if (threadId === null) continue;
|
|
34159
35601
|
const bundle = await this.loadBundle(threadId);
|
|
34160
35602
|
if (!bundle || bundle.turns.length === 0) continue;
|
|
@@ -34207,7 +35649,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34207
35649
|
);
|
|
34208
35650
|
let pruned = 0;
|
|
34209
35651
|
for (const meta of entries) {
|
|
34210
|
-
const threadId =
|
|
35652
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34211
35653
|
if (threadId === null) continue;
|
|
34212
35654
|
pruned += await this.withLock(threadId, async () => {
|
|
34213
35655
|
const bundle = await this.loadBundle(threadId);
|
|
@@ -34238,7 +35680,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34238
35680
|
return null;
|
|
34239
35681
|
}
|
|
34240
35682
|
if (!raw) return null;
|
|
34241
|
-
if (raw.length >
|
|
35683
|
+
if (raw.length > MAX_BUNDLE_BYTES3) return null;
|
|
34242
35684
|
try {
|
|
34243
35685
|
const envelope = JSON.parse(bytesToString(raw));
|
|
34244
35686
|
const aad = stringToBytes(threadId);
|
|
@@ -34329,7 +35771,18 @@ function buildV11Bindings(inputs) {
|
|
|
34329
35771
|
registry
|
|
34330
35772
|
}),
|
|
34331
35773
|
conciergePiiFilter: buildConciergePiiFilter(),
|
|
34332
|
-
conciergeMemory
|
|
35774
|
+
conciergeMemory,
|
|
35775
|
+
conciergeContextFetchers: buildConciergeContextFetchers({
|
|
35776
|
+
auditLog: inputs.auditLog,
|
|
35777
|
+
identityId: inputs.identityId,
|
|
35778
|
+
registry
|
|
35779
|
+
}),
|
|
35780
|
+
...inputs.intelligenceSelector ? {
|
|
35781
|
+
conciergeContextLlmAssist: buildConciergeContextLlmAssist({
|
|
35782
|
+
selector: inputs.intelligenceSelector,
|
|
35783
|
+
identityId: inputs.identityId
|
|
35784
|
+
})
|
|
35785
|
+
} : {}
|
|
34333
35786
|
});
|
|
34334
35787
|
}
|
|
34335
35788
|
const hubService = new HubService({
|
|
@@ -34390,6 +35843,107 @@ function buildConciergeContextProviders(args) {
|
|
|
34390
35843
|
}
|
|
34391
35844
|
};
|
|
34392
35845
|
}
|
|
35846
|
+
function buildConciergeContextFetchers(args) {
|
|
35847
|
+
const empty = async () => "";
|
|
35848
|
+
return {
|
|
35849
|
+
templates: async () => {
|
|
35850
|
+
const entries = listTemplates();
|
|
35851
|
+
if (entries.length === 0) return "(no templates installed)";
|
|
35852
|
+
const lines = entries.map((e) => {
|
|
35853
|
+
const m = e.metadata;
|
|
35854
|
+
return `${m.name} (tier ${m.tier}, channel ${m.channel}, target ${m.target_archetype})`;
|
|
35855
|
+
});
|
|
35856
|
+
return lines.join("\n");
|
|
35857
|
+
},
|
|
35858
|
+
agent_state: async (agentNameHint) => {
|
|
35859
|
+
const records = args.registry.list({ identity_id: args.identityId });
|
|
35860
|
+
if (records.length === 0) return "(no wrapped agents)";
|
|
35861
|
+
const filtered = agentNameHint ? records.filter(
|
|
35862
|
+
(r) => r.agent_id.toLowerCase().includes(agentNameHint.toLowerCase()) || r.harness.toLowerCase().includes(agentNameHint.toLowerCase())
|
|
35863
|
+
) : records;
|
|
35864
|
+
const target = filtered.length > 0 ? filtered : records;
|
|
35865
|
+
const lines = target.slice(0, 20).map((r) => {
|
|
35866
|
+
const tmpl = typeof r.channel_template_id === "string" ? r.channel_template_id : "no_template";
|
|
35867
|
+
return `${r.agent_id} harness=${r.harness} status=${r.status} template=${tmpl}`;
|
|
35868
|
+
});
|
|
35869
|
+
return lines.join("\n");
|
|
35870
|
+
},
|
|
35871
|
+
agent_activity: async (agentNameHint) => {
|
|
35872
|
+
const result = await args.auditLog.query({ limit: 50 });
|
|
35873
|
+
const owned = result.entries.filter(
|
|
35874
|
+
(e) => e.identity_id === args.identityId
|
|
35875
|
+
);
|
|
35876
|
+
const filtered = agentNameHint ? owned.filter((e) => {
|
|
35877
|
+
const agentId = e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : "";
|
|
35878
|
+
return agentId.toLowerCase().includes(agentNameHint.toLowerCase());
|
|
35879
|
+
}) : owned;
|
|
35880
|
+
const tail = (filtered.length > 0 ? filtered : owned).slice(-20);
|
|
35881
|
+
if (tail.length === 0) return "(no activity)";
|
|
35882
|
+
return tail.map((e) => {
|
|
35883
|
+
const agentId = (e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : null) ?? "_fortress";
|
|
35884
|
+
return `${e.timestamp} ${e.layer}.${e.operation} agent=${agentId} result=${e.result}`;
|
|
35885
|
+
}).join("\n");
|
|
35886
|
+
},
|
|
35887
|
+
audit_log: async () => {
|
|
35888
|
+
const result = await args.auditLog.query({ limit: 30 });
|
|
35889
|
+
const owned = result.entries.filter(
|
|
35890
|
+
(e) => e.identity_id === args.identityId
|
|
35891
|
+
);
|
|
35892
|
+
if (owned.length === 0) return "(no audit log entries)";
|
|
35893
|
+
return owned.slice(-30).map(
|
|
35894
|
+
(e) => `${e.timestamp} ${e.layer}.${e.operation} result=${e.result}`
|
|
35895
|
+
).join("\n");
|
|
35896
|
+
},
|
|
35897
|
+
sentinel_findings: empty,
|
|
35898
|
+
anomaly_alerts: empty,
|
|
35899
|
+
recent_receipts: async () => {
|
|
35900
|
+
const result = await args.auditLog.query({ limit: 100 });
|
|
35901
|
+
const owned = result.entries.filter(
|
|
35902
|
+
(e) => e.identity_id === args.identityId && e.operation.startsWith("composition_")
|
|
35903
|
+
);
|
|
35904
|
+
if (owned.length === 0) return "(no recent composition events)";
|
|
35905
|
+
return owned.slice(-15).map((e) => `${e.timestamp} ${e.operation} result=${e.result}`).join("\n");
|
|
35906
|
+
},
|
|
35907
|
+
verascore_deltas: empty
|
|
35908
|
+
};
|
|
35909
|
+
}
|
|
35910
|
+
function buildConciergeContextLlmAssist(args) {
|
|
35911
|
+
return async (query, categories) => {
|
|
35912
|
+
const labelList = categories.map((c) => `- ${c}`).join("\n");
|
|
35913
|
+
const prompt2 = `You are a router. Classify the operator's query into one of the categories below or "none".
|
|
35914
|
+
Reply with exactly one token: one category name or "none".
|
|
35915
|
+
|
|
35916
|
+
Categories:
|
|
35917
|
+
${labelList}
|
|
35918
|
+
|
|
35919
|
+
Query: ${query}
|
|
35920
|
+
|
|
35921
|
+
Category:`;
|
|
35922
|
+
try {
|
|
35923
|
+
const handle = await args.selector.getSubstrate("concierge");
|
|
35924
|
+
if (!handle.capability.summarize) return "none";
|
|
35925
|
+
const response = await args.selector.invokeSummarize("concierge", {
|
|
35926
|
+
kind: "summarize",
|
|
35927
|
+
context: prompt2,
|
|
35928
|
+
query: "Output the single category token.",
|
|
35929
|
+
maxTokens: 16
|
|
35930
|
+
});
|
|
35931
|
+
if (response.failureClass || response.body.kind !== "summarize") {
|
|
35932
|
+
return "none";
|
|
35933
|
+
}
|
|
35934
|
+
const raw = response.body.text.trim().toLowerCase();
|
|
35935
|
+
const head = raw.split(/\s|[.,!?:;]/)[0] ?? "";
|
|
35936
|
+
const normalized = head.replace(/[^a-z_]/g, "");
|
|
35937
|
+
const known = categories;
|
|
35938
|
+
if (known.includes(normalized)) {
|
|
35939
|
+
return normalized;
|
|
35940
|
+
}
|
|
35941
|
+
return "none";
|
|
35942
|
+
} catch {
|
|
35943
|
+
return "none";
|
|
35944
|
+
}
|
|
35945
|
+
};
|
|
35946
|
+
}
|
|
34393
35947
|
function buildConciergePiiFilter() {
|
|
34394
35948
|
return {
|
|
34395
35949
|
filter(input) {
|
|
@@ -34417,6 +35971,7 @@ var init_wiring = __esm({
|
|
|
34417
35971
|
init_agent_registry_persistence();
|
|
34418
35972
|
init_operator_chat_index();
|
|
34419
35973
|
init_privacy_filter();
|
|
35974
|
+
init_registry();
|
|
34420
35975
|
CapabilityErrorAgentController = class {
|
|
34421
35976
|
fail(action) {
|
|
34422
35977
|
throw new HubCapabilityError(
|
|
@@ -34564,7 +36119,7 @@ var init_defaults = __esm({
|
|
|
34564
36119
|
});
|
|
34565
36120
|
|
|
34566
36121
|
// src/intelligence/policy-store.ts
|
|
34567
|
-
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY,
|
|
36122
|
+
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY, HKDF_INFO4, IntelligenceConfigStore;
|
|
34568
36123
|
var init_policy_store = __esm({
|
|
34569
36124
|
"src/intelligence/policy-store.ts"() {
|
|
34570
36125
|
init_encryption();
|
|
@@ -34573,13 +36128,13 @@ var init_policy_store = __esm({
|
|
|
34573
36128
|
init_defaults();
|
|
34574
36129
|
INTELLIGENCE_NAMESPACE = "_intelligence";
|
|
34575
36130
|
SUBSTRATE_CONFIG_KEY = "substrate-config";
|
|
34576
|
-
|
|
36131
|
+
HKDF_INFO4 = "intelligence-substrate-config";
|
|
34577
36132
|
IntelligenceConfigStore = class {
|
|
34578
36133
|
storage;
|
|
34579
36134
|
encryptionKey;
|
|
34580
36135
|
constructor(storage, masterKey) {
|
|
34581
36136
|
this.storage = storage;
|
|
34582
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
36137
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO4);
|
|
34583
36138
|
}
|
|
34584
36139
|
/**
|
|
34585
36140
|
* Load the operator's substrate config from disk. Returns the config
|
|
@@ -36229,7 +37784,7 @@ var init_memory = __esm({
|
|
|
36229
37784
|
|
|
36230
37785
|
// src/contracts/v1.1/constants.ts
|
|
36231
37786
|
var SIGNATURE_SCHEME_V12, EXIT_BUNDLE_MANIFEST_VERSION, EXIT_BUNDLE_ARTIFACT_KINDS;
|
|
36232
|
-
var
|
|
37787
|
+
var init_constants5 = __esm({
|
|
36233
37788
|
"src/contracts/v1.1/constants.ts"() {
|
|
36234
37789
|
SIGNATURE_SCHEME_V12 = "ed25519-v1";
|
|
36235
37790
|
EXIT_BUNDLE_MANIFEST_VERSION = "SANCTUARY_EXIT_BUNDLE_V1";
|
|
@@ -36647,7 +38202,7 @@ async function verifyExitBundle(bundleDir, options = {}) {
|
|
|
36647
38202
|
var InvalidExitBundleError, PRIVATE_MATERIAL_KEYS;
|
|
36648
38203
|
var init_verifier2 = __esm({
|
|
36649
38204
|
"src/exit/verifier.ts"() {
|
|
36650
|
-
|
|
38205
|
+
init_constants5();
|
|
36651
38206
|
init_exit_bundle_manifest();
|
|
36652
38207
|
init_encoding();
|
|
36653
38208
|
init_hashing();
|
|
@@ -37459,7 +39014,7 @@ var init_bundle = __esm({
|
|
|
37459
39014
|
"src/exit/bundle.ts"() {
|
|
37460
39015
|
init_state_store();
|
|
37461
39016
|
init_config();
|
|
37462
|
-
|
|
39017
|
+
init_constants5();
|
|
37463
39018
|
init_canonical_json();
|
|
37464
39019
|
init_hashing();
|
|
37465
39020
|
init_encoding();
|
|
@@ -38497,12 +40052,18 @@ ${err.message}
|
|
|
38497
40052
|
} : void 0;
|
|
38498
40053
|
const fortressIdForAggregator = fortressIdFromStoragePath(config.storage_path);
|
|
38499
40054
|
const aggregatorIdentityId = identityManager.getPrimaryIdentityId() ?? `fortress:${config.storage_path}`;
|
|
40055
|
+
const aggregatorPayloadStore = new AggregatorPayloadStore({
|
|
40056
|
+
storage,
|
|
40057
|
+
masterKey,
|
|
40058
|
+
fortressId: fortressIdForAggregator
|
|
40059
|
+
});
|
|
38500
40060
|
const approvalAggregator = new ApprovalAggregator({
|
|
38501
40061
|
storage,
|
|
38502
40062
|
masterKey,
|
|
38503
40063
|
auditLog,
|
|
38504
40064
|
identityId: aggregatorIdentityId,
|
|
38505
|
-
fortressId: fortressIdForAggregator
|
|
40065
|
+
fortressId: fortressIdForAggregator,
|
|
40066
|
+
payloadStore: aggregatorPayloadStore
|
|
38506
40067
|
});
|
|
38507
40068
|
const wrappedApprovalChannel = new AggregatorBackedChannel({
|
|
38508
40069
|
underlying: approvalChannel,
|
|
@@ -38716,6 +40277,7 @@ var init_src = __esm({
|
|
|
38716
40277
|
init_gate();
|
|
38717
40278
|
init_approval_aggregator();
|
|
38718
40279
|
init_aggregator_backed_channel();
|
|
40280
|
+
init_aggregator_store();
|
|
38719
40281
|
init_tools4();
|
|
38720
40282
|
init_router();
|
|
38721
40283
|
init_router();
|