@sanctuary-framework/mcp-server 1.2.5 → 1.2.6
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 +864 -35
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +864 -35
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +847 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +239 -3
- package/dist/index.d.ts +239 -3
- package/dist/index.js +847 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -17218,6 +17218,27 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17218
17218
|
await handleStream2(deps, res);
|
|
17219
17219
|
return true;
|
|
17220
17220
|
}
|
|
17221
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/history`) {
|
|
17222
|
+
const limit = parseLimit2(
|
|
17223
|
+
url.searchParams.get("limit"),
|
|
17224
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17225
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17226
|
+
);
|
|
17227
|
+
const statusRaw = url.searchParams.get("status");
|
|
17228
|
+
const sinceTs = url.searchParams.get("since") ?? void 0;
|
|
17229
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17230
|
+
const filterStatus = statusRaw && isStatusFilter(statusRaw) && statusRaw !== "pending" ? statusRaw : void 0;
|
|
17231
|
+
const entries = await deps.aggregator.getHistory(
|
|
17232
|
+
{
|
|
17233
|
+
limit,
|
|
17234
|
+
...filterStatus !== void 0 ? { status: filterStatus } : {},
|
|
17235
|
+
...sinceTs !== void 0 ? { sinceTs } : {}
|
|
17236
|
+
},
|
|
17237
|
+
operatorId
|
|
17238
|
+
);
|
|
17239
|
+
writeJSON4(res, 200, { ok: true, data: { entries } });
|
|
17240
|
+
return true;
|
|
17241
|
+
}
|
|
17221
17242
|
if (method === "GET" && path === APPROVAL_INBOX_API_PREFIX) {
|
|
17222
17243
|
const limit = parseLimit2(
|
|
17223
17244
|
url.searchParams.get("limit"),
|
|
@@ -17240,11 +17261,39 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17240
17261
|
writeJSON4(res, 404, { ok: false, error: "not_found", path });
|
|
17241
17262
|
return true;
|
|
17242
17263
|
}
|
|
17243
|
-
if (method === "GET" && entryMatch.action ===
|
|
17244
|
-
const
|
|
17245
|
-
|
|
17246
|
-
(
|
|
17264
|
+
if (method === "GET" && entryMatch.action === "audit-trail") {
|
|
17265
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17266
|
+
if (!entry) {
|
|
17267
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17268
|
+
return true;
|
|
17269
|
+
}
|
|
17270
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17271
|
+
const trail = await deps.aggregator.getAuditTrail(
|
|
17272
|
+
entryMatch.aggregatorId,
|
|
17273
|
+
operatorId
|
|
17247
17274
|
);
|
|
17275
|
+
writeJSON4(res, 200, { ok: true, data: { entry, audit_trail: trail } });
|
|
17276
|
+
return true;
|
|
17277
|
+
}
|
|
17278
|
+
if (method === "GET" && entryMatch.action === "payload") {
|
|
17279
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17280
|
+
if (!entry) {
|
|
17281
|
+
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17282
|
+
return true;
|
|
17283
|
+
}
|
|
17284
|
+
const operatorId = deps.operatorId ?? APPROVAL_INBOX_OPERATOR_DEFAULT;
|
|
17285
|
+
const payload = await deps.aggregator.getFullPayloadWithAudit(
|
|
17286
|
+
entryMatch.aggregatorId,
|
|
17287
|
+
operatorId
|
|
17288
|
+
);
|
|
17289
|
+
writeJSON4(res, 200, {
|
|
17290
|
+
ok: true,
|
|
17291
|
+
data: { entry, request_payload: payload }
|
|
17292
|
+
});
|
|
17293
|
+
return true;
|
|
17294
|
+
}
|
|
17295
|
+
if (method === "GET" && entryMatch.action === null) {
|
|
17296
|
+
const entry = await deps.aggregator.getEntry(entryMatch.aggregatorId);
|
|
17248
17297
|
if (!entry) {
|
|
17249
17298
|
writeJSON4(res, 404, { ok: false, error: "not_found" });
|
|
17250
17299
|
return true;
|
|
@@ -20278,7 +20327,10 @@ var init_approval_aggregator = __esm({
|
|
|
20278
20327
|
APPROVAL_AGGREGATOR_AUDIT_OPS = {
|
|
20279
20328
|
AGGREGATED: "cross_harness_approval_aggregated",
|
|
20280
20329
|
RESOLVED: "cross_harness_approval_resolved",
|
|
20281
|
-
DEDUPED: "cross_harness_approval_deduped"
|
|
20330
|
+
DEDUPED: "cross_harness_approval_deduped",
|
|
20331
|
+
PAYLOAD_DECRYPTED: "cross_harness_approval_payload_decrypted",
|
|
20332
|
+
AUDIT_TRAIL_VIEWED: "cross_harness_approval_audit_trail_viewed",
|
|
20333
|
+
REPLAYED: "cross_harness_approval_replayed"
|
|
20282
20334
|
};
|
|
20283
20335
|
DEFAULT_PENDING_TTL_MS = 5 * 60 * 1e3;
|
|
20284
20336
|
DEFAULT_MAX_LIST_LIMIT = 200;
|
|
@@ -20294,6 +20346,8 @@ var init_approval_aggregator = __esm({
|
|
|
20294
20346
|
now;
|
|
20295
20347
|
resolveSourceContext;
|
|
20296
20348
|
resolveHubInboxItemId;
|
|
20349
|
+
payloadStore;
|
|
20350
|
+
resolveEnforcementChain;
|
|
20297
20351
|
/** Cached entries by `aggregator_id`. */
|
|
20298
20352
|
entries = /* @__PURE__ */ new Map();
|
|
20299
20353
|
/** Dedup index: `${harness}|${agent}|${audit_id}` -> aggregator_id. */
|
|
@@ -20323,6 +20377,14 @@ var init_approval_aggregator = __esm({
|
|
|
20323
20377
|
source_agent_id: this.fortressId
|
|
20324
20378
|
}));
|
|
20325
20379
|
this.resolveHubInboxItemId = deps.resolveHubInboxItemId ?? ((_event) => void 0);
|
|
20380
|
+
this.payloadStore = deps.payloadStore ?? null;
|
|
20381
|
+
this.resolveEnforcementChain = deps.resolveEnforcementChain ?? ((event) => [
|
|
20382
|
+
{
|
|
20383
|
+
layer: "l2",
|
|
20384
|
+
event: `approval_required:${event.operation}`,
|
|
20385
|
+
timestamp: event.request_timestamp
|
|
20386
|
+
}
|
|
20387
|
+
]);
|
|
20326
20388
|
}
|
|
20327
20389
|
/**
|
|
20328
20390
|
* Subscribe an event listener. Returns an unsubscribe fn. SSE handlers
|
|
@@ -20373,13 +20435,152 @@ var init_approval_aggregator = __esm({
|
|
|
20373
20435
|
}
|
|
20374
20436
|
/**
|
|
20375
20437
|
* Return the original (unhashed) request payload for the entry. Returns
|
|
20376
|
-
* `null` when the entry is unknown
|
|
20377
|
-
*
|
|
20438
|
+
* `null` when the entry is unknown. When the in-memory payload map has
|
|
20439
|
+
* been evicted (e.g. after a server restart) and a `payloadStore` was
|
|
20440
|
+
* provided, the at-rest bundle is decrypted and the in-memory map is
|
|
20441
|
+
* refilled. Audit emission lives on the `*WithAudit` variant; this base
|
|
20442
|
+
* accessor is silent so internal callers can read without polluting the
|
|
20443
|
+
* audit trail.
|
|
20378
20444
|
*/
|
|
20379
20445
|
async getFullPayload(aggregatorId) {
|
|
20380
20446
|
await this.hydrate();
|
|
20381
20447
|
if (!this.entries.has(aggregatorId)) return null;
|
|
20382
|
-
|
|
20448
|
+
const cached = this.fullPayloads.get(aggregatorId);
|
|
20449
|
+
if (cached !== void 0) return cached;
|
|
20450
|
+
if (this.payloadStore) {
|
|
20451
|
+
try {
|
|
20452
|
+
const restored = await this.payloadStore.loadPayload(aggregatorId);
|
|
20453
|
+
if (restored !== null) {
|
|
20454
|
+
this.fullPayloads.set(aggregatorId, restored);
|
|
20455
|
+
return restored;
|
|
20456
|
+
}
|
|
20457
|
+
} catch {
|
|
20458
|
+
}
|
|
20459
|
+
}
|
|
20460
|
+
return null;
|
|
20461
|
+
}
|
|
20462
|
+
/**
|
|
20463
|
+
* Return the entry record for the given id, or null when unknown.
|
|
20464
|
+
* Idempotent. v1.3 Upsilon-3.
|
|
20465
|
+
*/
|
|
20466
|
+
async getEntry(aggregatorId) {
|
|
20467
|
+
await this.hydrate();
|
|
20468
|
+
return this.entries.get(aggregatorId) ?? null;
|
|
20469
|
+
}
|
|
20470
|
+
/**
|
|
20471
|
+
* Audited variant of `getFullPayload`. Emits the
|
|
20472
|
+
* `cross_harness_approval_payload_decrypted` audit event before
|
|
20473
|
+
* returning. Used by the operator-facing /payload replay route.
|
|
20474
|
+
* v1.3 Upsilon-3.
|
|
20475
|
+
*/
|
|
20476
|
+
async getFullPayloadWithAudit(aggregatorId, operatorId) {
|
|
20477
|
+
const payload = await this.getFullPayload(aggregatorId);
|
|
20478
|
+
if (payload === null) return null;
|
|
20479
|
+
const entry = this.entries.get(aggregatorId);
|
|
20480
|
+
this.auditLog.append(
|
|
20481
|
+
"l2",
|
|
20482
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.PAYLOAD_DECRYPTED,
|
|
20483
|
+
operatorId,
|
|
20484
|
+
{
|
|
20485
|
+
aggregator_id: aggregatorId,
|
|
20486
|
+
...entry ? {
|
|
20487
|
+
source_harness: entry.source_harness,
|
|
20488
|
+
source_agent_id: entry.source_agent_id,
|
|
20489
|
+
entry_status: entry.status
|
|
20490
|
+
} : {}
|
|
20491
|
+
}
|
|
20492
|
+
);
|
|
20493
|
+
return payload;
|
|
20494
|
+
}
|
|
20495
|
+
/**
|
|
20496
|
+
* Return the audit-log entries that led to and surround this approval.
|
|
20497
|
+
* Best-effort matching: aggregator-side emissions (AGGREGATED, RESOLVED,
|
|
20498
|
+
* DEDUPED, replay events) all carry `details.aggregator_id` and link
|
|
20499
|
+
* directly. Gate-side emissions (`gate_*:operation`) do not carry the
|
|
20500
|
+
* aggregator id at v1.3, so they are matched via timestamp window
|
|
20501
|
+
* (entry.created_at to entry.resolved_at + 1s, or expires_at + 1s while
|
|
20502
|
+
* pending) and operation suffix. Emits AUDIT_TRAIL_VIEWED on call.
|
|
20503
|
+
* v1.3 Upsilon-3.
|
|
20504
|
+
*/
|
|
20505
|
+
async getAuditTrail(aggregatorId, operatorId) {
|
|
20506
|
+
await this.hydrate();
|
|
20507
|
+
const entry = this.entries.get(aggregatorId);
|
|
20508
|
+
if (!entry) {
|
|
20509
|
+
return [];
|
|
20510
|
+
}
|
|
20511
|
+
const sinceMs = Date.parse(entry.created_at) - 1e3;
|
|
20512
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
20513
|
+
const queried = await this.auditLog.query({ since: sinceIso, limit: 1e3 });
|
|
20514
|
+
const operationPart = entry.policy_rule_id.includes(":") ? entry.policy_rule_id.slice(entry.policy_rule_id.indexOf(":") + 1) : entry.policy_rule_id;
|
|
20515
|
+
const lifetimeStart = sinceMs;
|
|
20516
|
+
const lifetimeEnd = entry.resolved_at ? Date.parse(entry.resolved_at) + 1e3 : Date.parse(entry.expires_at) + 1e3;
|
|
20517
|
+
const matches = [];
|
|
20518
|
+
for (const audit of queried.entries) {
|
|
20519
|
+
const detailsId = audit.details !== void 0 ? audit.details["aggregator_id"] : void 0;
|
|
20520
|
+
if (detailsId === aggregatorId) {
|
|
20521
|
+
matches.push(audit);
|
|
20522
|
+
continue;
|
|
20523
|
+
}
|
|
20524
|
+
const auditMs = Date.parse(audit.timestamp);
|
|
20525
|
+
if (auditMs < lifetimeStart || auditMs > lifetimeEnd) continue;
|
|
20526
|
+
if (audit.operation.endsWith(`:${operationPart}`)) {
|
|
20527
|
+
matches.push(audit);
|
|
20528
|
+
}
|
|
20529
|
+
}
|
|
20530
|
+
matches.sort(
|
|
20531
|
+
(a, b) => a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0
|
|
20532
|
+
);
|
|
20533
|
+
this.auditLog.append(
|
|
20534
|
+
"l2",
|
|
20535
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.AUDIT_TRAIL_VIEWED,
|
|
20536
|
+
operatorId,
|
|
20537
|
+
{
|
|
20538
|
+
aggregator_id: aggregatorId,
|
|
20539
|
+
entry_status: entry.status,
|
|
20540
|
+
match_count: matches.length
|
|
20541
|
+
}
|
|
20542
|
+
);
|
|
20543
|
+
return matches;
|
|
20544
|
+
}
|
|
20545
|
+
/**
|
|
20546
|
+
* List historical (resolved) approvals. Excludes pending entries by
|
|
20547
|
+
* design: `list()` is the pending-inbox surface and `getHistory()` is
|
|
20548
|
+
* the resolved-replay surface. Emits REPLAYED on each call. v1.3
|
|
20549
|
+
* Upsilon-3.
|
|
20550
|
+
*/
|
|
20551
|
+
async getHistory(opts, operatorId) {
|
|
20552
|
+
await this.hydrate();
|
|
20553
|
+
await this.expireStale();
|
|
20554
|
+
const limit = Math.min(
|
|
20555
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20556
|
+
this.maxListLimit
|
|
20557
|
+
);
|
|
20558
|
+
const sinceMs = opts?.sinceTs ? Date.parse(opts.sinceTs) : Number.NEGATIVE_INFINITY;
|
|
20559
|
+
const matching = [];
|
|
20560
|
+
for (const entry of this.entries.values()) {
|
|
20561
|
+
if (entry.status === "pending") continue;
|
|
20562
|
+
if (opts?.status && entry.status !== opts.status) continue;
|
|
20563
|
+
const stamp = Date.parse(entry.resolved_at ?? entry.created_at);
|
|
20564
|
+
if (stamp < sinceMs) continue;
|
|
20565
|
+
matching.push(entry);
|
|
20566
|
+
}
|
|
20567
|
+
matching.sort((a, b) => {
|
|
20568
|
+
const aStamp = a.resolved_at ?? a.created_at;
|
|
20569
|
+
const bStamp = b.resolved_at ?? b.created_at;
|
|
20570
|
+
return bStamp.localeCompare(aStamp);
|
|
20571
|
+
});
|
|
20572
|
+
const sliced = matching.slice(0, limit);
|
|
20573
|
+
this.auditLog.append(
|
|
20574
|
+
"l2",
|
|
20575
|
+
APPROVAL_AGGREGATOR_AUDIT_OPS.REPLAYED,
|
|
20576
|
+
operatorId,
|
|
20577
|
+
{
|
|
20578
|
+
result_count: sliced.length,
|
|
20579
|
+
...opts?.status !== void 0 ? { status_filter: opts.status } : {},
|
|
20580
|
+
...opts?.sinceTs !== void 0 ? { since: opts.sinceTs } : {}
|
|
20581
|
+
}
|
|
20582
|
+
);
|
|
20583
|
+
return sliced;
|
|
20383
20584
|
}
|
|
20384
20585
|
/**
|
|
20385
20586
|
* Resolve an entry. Used by both:
|
|
@@ -20453,6 +20654,7 @@ var init_approval_aggregator = __esm({
|
|
|
20453
20654
|
const now = this.now();
|
|
20454
20655
|
const expires = new Date(now.getTime() + this.pendingTtlMs);
|
|
20455
20656
|
const hubInboxId = this.resolveHubInboxItemId(event);
|
|
20657
|
+
const enforcementChain = this.resolveEnforcementChain(event);
|
|
20456
20658
|
const entry = {
|
|
20457
20659
|
aggregator_id: id,
|
|
20458
20660
|
source_harness: ctx.source_harness,
|
|
@@ -20464,13 +20666,20 @@ var init_approval_aggregator = __esm({
|
|
|
20464
20666
|
status: "pending",
|
|
20465
20667
|
created_at: now.toISOString(),
|
|
20466
20668
|
expires_at: expires.toISOString(),
|
|
20467
|
-
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {}
|
|
20669
|
+
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {},
|
|
20670
|
+
...enforcementChain.length > 0 ? { enforcement_chain: enforcementChain } : {}
|
|
20468
20671
|
};
|
|
20469
20672
|
this.entries.set(id, entry);
|
|
20470
20673
|
this.dedupIndex.set(dedupKey, id);
|
|
20471
20674
|
this.correlationIndex.set(event.correlation_id, id);
|
|
20472
20675
|
this.fullPayloads.set(id, event.context);
|
|
20473
20676
|
await this.persist(entry);
|
|
20677
|
+
if (this.payloadStore) {
|
|
20678
|
+
try {
|
|
20679
|
+
await this.payloadStore.savePayload(id, event.context);
|
|
20680
|
+
} catch {
|
|
20681
|
+
}
|
|
20682
|
+
}
|
|
20474
20683
|
this.auditLog.append(
|
|
20475
20684
|
"l2",
|
|
20476
20685
|
APPROVAL_AGGREGATOR_AUDIT_OPS.AGGREGATED,
|
|
@@ -20786,6 +20995,149 @@ var init_aggregator_backed_channel = __esm({
|
|
|
20786
20995
|
}
|
|
20787
20996
|
});
|
|
20788
20997
|
|
|
20998
|
+
// src/principal-policy/aggregator-store.ts
|
|
20999
|
+
function payloadKey(aggregatorId) {
|
|
21000
|
+
return `${AGGREGATOR_PAYLOAD_KEY_PREFIX}${aggregatorId}`;
|
|
21001
|
+
}
|
|
21002
|
+
function stripKeyPrefix(key) {
|
|
21003
|
+
if (!key.startsWith(AGGREGATOR_PAYLOAD_KEY_PREFIX)) return null;
|
|
21004
|
+
return key.slice(AGGREGATOR_PAYLOAD_KEY_PREFIX.length);
|
|
21005
|
+
}
|
|
21006
|
+
var AGGREGATOR_PAYLOAD_NAMESPACE, AGGREGATOR_PAYLOAD_KEY_PREFIX, HKDF_INFO, DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS, MAX_BUNDLE_BYTES2, AggregatorPayloadStore;
|
|
21007
|
+
var init_aggregator_store = __esm({
|
|
21008
|
+
"src/principal-policy/aggregator-store.ts"() {
|
|
21009
|
+
init_encryption();
|
|
21010
|
+
init_key_derivation();
|
|
21011
|
+
init_encoding();
|
|
21012
|
+
AGGREGATOR_PAYLOAD_NAMESPACE = "_approval_aggregator_payloads";
|
|
21013
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX = "payload.";
|
|
21014
|
+
HKDF_INFO = "l2-approval-aggregator-payload-v1";
|
|
21015
|
+
DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS = 30;
|
|
21016
|
+
MAX_BUNDLE_BYTES2 = 4 * 1024 * 1024;
|
|
21017
|
+
AggregatorPayloadStore = class {
|
|
21018
|
+
storage;
|
|
21019
|
+
encryptionKey;
|
|
21020
|
+
fortressId;
|
|
21021
|
+
retentionDays;
|
|
21022
|
+
constructor(opts) {
|
|
21023
|
+
this.storage = opts.storage;
|
|
21024
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO);
|
|
21025
|
+
this.fortressId = opts.fortressId;
|
|
21026
|
+
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_AGGREGATOR_PAYLOAD_RETENTION_DAYS;
|
|
21027
|
+
}
|
|
21028
|
+
/**
|
|
21029
|
+
* Persist `payload` under the given aggregator_id. Idempotent; calling
|
|
21030
|
+
* twice with the same id rewrites the bundle (retention_until is
|
|
21031
|
+
* recomputed). Returns the bundle's retention_until ISO-8601 timestamp
|
|
21032
|
+
* so callers can log it.
|
|
21033
|
+
*/
|
|
21034
|
+
async savePayload(aggregatorId, payload) {
|
|
21035
|
+
const now = /* @__PURE__ */ new Date();
|
|
21036
|
+
const retentionMs = this.retentionDays * 24 * 60 * 60 * 1e3;
|
|
21037
|
+
const retentionUntil = new Date(now.getTime() + retentionMs);
|
|
21038
|
+
const bundle = {
|
|
21039
|
+
version: 1,
|
|
21040
|
+
aggregator_id: aggregatorId,
|
|
21041
|
+
fortress_id: this.fortressId,
|
|
21042
|
+
created_at: now.toISOString(),
|
|
21043
|
+
retention_until: retentionUntil.toISOString(),
|
|
21044
|
+
payload
|
|
21045
|
+
};
|
|
21046
|
+
const aad = stringToBytes(aggregatorId);
|
|
21047
|
+
const plaintext = stringToBytes(JSON.stringify(bundle));
|
|
21048
|
+
const envelope = encrypt(plaintext, this.encryptionKey, aad);
|
|
21049
|
+
await this.storage.write(
|
|
21050
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21051
|
+
payloadKey(aggregatorId),
|
|
21052
|
+
stringToBytes(JSON.stringify(envelope))
|
|
21053
|
+
);
|
|
21054
|
+
return bundle.retention_until;
|
|
21055
|
+
}
|
|
21056
|
+
/**
|
|
21057
|
+
* Read the persisted payload for the aggregator_id. Returns null if no
|
|
21058
|
+
* bundle exists, the bundle is corrupted, or AAD binding fails.
|
|
21059
|
+
*/
|
|
21060
|
+
async loadPayload(aggregatorId) {
|
|
21061
|
+
const key = payloadKey(aggregatorId);
|
|
21062
|
+
let raw;
|
|
21063
|
+
try {
|
|
21064
|
+
raw = await this.storage.read(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21065
|
+
} catch {
|
|
21066
|
+
return null;
|
|
21067
|
+
}
|
|
21068
|
+
if (!raw) return null;
|
|
21069
|
+
if (raw.length > MAX_BUNDLE_BYTES2) return null;
|
|
21070
|
+
try {
|
|
21071
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21072
|
+
const aad = stringToBytes(aggregatorId);
|
|
21073
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21074
|
+
const parsed = JSON.parse(
|
|
21075
|
+
bytesToString(plaintext)
|
|
21076
|
+
);
|
|
21077
|
+
if (parsed.version !== 1) return null;
|
|
21078
|
+
if (parsed.aggregator_id !== aggregatorId) return null;
|
|
21079
|
+
return parsed.payload;
|
|
21080
|
+
} catch {
|
|
21081
|
+
return null;
|
|
21082
|
+
}
|
|
21083
|
+
}
|
|
21084
|
+
/**
|
|
21085
|
+
* Delete the persisted payload. Returns true when a bundle was removed,
|
|
21086
|
+
* false when none existed.
|
|
21087
|
+
*/
|
|
21088
|
+
async deletePayload(aggregatorId) {
|
|
21089
|
+
const key = payloadKey(aggregatorId);
|
|
21090
|
+
const existed = await this.storage.exists(
|
|
21091
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21092
|
+
key
|
|
21093
|
+
);
|
|
21094
|
+
if (!existed) return false;
|
|
21095
|
+
try {
|
|
21096
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, key);
|
|
21097
|
+
} catch {
|
|
21098
|
+
return false;
|
|
21099
|
+
}
|
|
21100
|
+
return true;
|
|
21101
|
+
}
|
|
21102
|
+
/**
|
|
21103
|
+
* Drop expired payload bundles. Returns the count of bundles pruned.
|
|
21104
|
+
* Caller wires this into the cocoon-unlock initialization path.
|
|
21105
|
+
*/
|
|
21106
|
+
async pruneExpired(now) {
|
|
21107
|
+
const cutoff = (now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
21108
|
+
const entries = await this.storage.list(
|
|
21109
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21110
|
+
AGGREGATOR_PAYLOAD_KEY_PREFIX
|
|
21111
|
+
);
|
|
21112
|
+
let pruned = 0;
|
|
21113
|
+
for (const meta of entries) {
|
|
21114
|
+
const aggregatorId = stripKeyPrefix(meta.key);
|
|
21115
|
+
if (aggregatorId === null) continue;
|
|
21116
|
+
const raw = await this.storage.read(
|
|
21117
|
+
AGGREGATOR_PAYLOAD_NAMESPACE,
|
|
21118
|
+
meta.key
|
|
21119
|
+
);
|
|
21120
|
+
if (!raw) continue;
|
|
21121
|
+
try {
|
|
21122
|
+
const envelope = JSON.parse(bytesToString(raw));
|
|
21123
|
+
const aad = stringToBytes(aggregatorId);
|
|
21124
|
+
const plaintext = decrypt(envelope, this.encryptionKey, aad);
|
|
21125
|
+
const parsed = JSON.parse(
|
|
21126
|
+
bytesToString(plaintext)
|
|
21127
|
+
);
|
|
21128
|
+
if (parsed.retention_until <= cutoff) {
|
|
21129
|
+
await this.storage.delete(AGGREGATOR_PAYLOAD_NAMESPACE, meta.key);
|
|
21130
|
+
pruned += 1;
|
|
21131
|
+
}
|
|
21132
|
+
} catch {
|
|
21133
|
+
}
|
|
21134
|
+
}
|
|
21135
|
+
return { pruned };
|
|
21136
|
+
}
|
|
21137
|
+
};
|
|
21138
|
+
}
|
|
21139
|
+
});
|
|
21140
|
+
|
|
20789
21141
|
// src/principal-policy/tools.ts
|
|
20790
21142
|
function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
20791
21143
|
return [
|
|
@@ -33404,7 +33756,14 @@ var init_operator_chat_audit_events = __esm({
|
|
|
33404
33756
|
* turns; the concierge degrades to single-turn after emitting. Body
|
|
33405
33757
|
* carries thread_id + a stable failure_reason enum.
|
|
33406
33758
|
*/
|
|
33407
|
-
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed"
|
|
33759
|
+
CONCIERGE_MEMORY_READ_FAILED: "operator_concierge_memory_read_failed",
|
|
33760
|
+
/**
|
|
33761
|
+
* Concierge dynamic-context fetcher failed (WP-V1.3-9 Tau-3). Emitted
|
|
33762
|
+
* when a category fetcher throws while assembling the dynamic context
|
|
33763
|
+
* fold. The concierge omits that category and continues; the user-
|
|
33764
|
+
* facing query is never broken. Body carries category + failure_reason.
|
|
33765
|
+
*/
|
|
33766
|
+
CONCIERGE_CONTEXT_FETCHER_FAILED: "operator_concierge_context_fetcher_failed"
|
|
33408
33767
|
};
|
|
33409
33768
|
}
|
|
33410
33769
|
});
|
|
@@ -33417,12 +33776,291 @@ var init_operator_chat_types = __esm({
|
|
|
33417
33776
|
CONCIERGE_THREAD_KEY = "_fortress";
|
|
33418
33777
|
}
|
|
33419
33778
|
});
|
|
33779
|
+
|
|
33780
|
+
// src/chat/concierge-context-router.ts
|
|
33781
|
+
function phrasePattern(phrase) {
|
|
33782
|
+
const escaped = phrase.toLowerCase().split(/\s+/).map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
|
|
33783
|
+
return { source: `\\b${escaped}\\b`, phrase };
|
|
33784
|
+
}
|
|
33785
|
+
function extractAgentNameHint(query) {
|
|
33786
|
+
const agentPattern = /\bagent\s+["']?([A-Za-z][\w-]{0,40})["']?/i;
|
|
33787
|
+
const m = query.match(agentPattern);
|
|
33788
|
+
if (m && m[1]) return m[1];
|
|
33789
|
+
const quoted = query.match(/["']([A-Za-z][\w-]{0,40})["']/);
|
|
33790
|
+
if (quoted && quoted[1]) return quoted[1];
|
|
33791
|
+
return null;
|
|
33792
|
+
}
|
|
33793
|
+
function isTrivialQuery(query) {
|
|
33794
|
+
const norm = query.trim().toLowerCase();
|
|
33795
|
+
if (norm.length === 0) return true;
|
|
33796
|
+
if (norm.length < 8) return true;
|
|
33797
|
+
return TRIVIAL_GREETINGS.has(norm);
|
|
33798
|
+
}
|
|
33799
|
+
function classifyQuery(query) {
|
|
33800
|
+
const normalized = query.toLowerCase();
|
|
33801
|
+
const matches = [];
|
|
33802
|
+
for (const spec of CATEGORY_KEYWORDS) {
|
|
33803
|
+
const matchedPhrases = [];
|
|
33804
|
+
for (const pattern of spec.patterns) {
|
|
33805
|
+
if (matchedPhrases.includes(pattern.phrase)) continue;
|
|
33806
|
+
const re = new RegExp(pattern.source, "i");
|
|
33807
|
+
if (re.test(normalized)) {
|
|
33808
|
+
matchedPhrases.push(pattern.phrase);
|
|
33809
|
+
}
|
|
33810
|
+
}
|
|
33811
|
+
if (matchedPhrases.length === 0) continue;
|
|
33812
|
+
const confidence = Math.min(1, 0.4 + 0.3 * matchedPhrases.length);
|
|
33813
|
+
matches.push({
|
|
33814
|
+
category: spec.category,
|
|
33815
|
+
confidence,
|
|
33816
|
+
matched_keywords: matchedPhrases,
|
|
33817
|
+
agent_name_hint: spec.category === "agent_state" || spec.category === "agent_activity" ? extractAgentNameHint(query) : null
|
|
33818
|
+
});
|
|
33819
|
+
}
|
|
33820
|
+
matches.sort((a, b) => {
|
|
33821
|
+
if (b.confidence !== a.confidence) return b.confidence - a.confidence;
|
|
33822
|
+
return CONTEXT_CATEGORIES.indexOf(a.category) - CONTEXT_CATEGORIES.indexOf(b.category);
|
|
33823
|
+
});
|
|
33824
|
+
return matches;
|
|
33825
|
+
}
|
|
33420
33826
|
function approxTokenLen(text) {
|
|
33827
|
+
return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
33828
|
+
}
|
|
33829
|
+
async function runFetcher(match, fetchers) {
|
|
33830
|
+
switch (match.category) {
|
|
33831
|
+
case "templates":
|
|
33832
|
+
return fetchers.templates();
|
|
33833
|
+
case "agent_state":
|
|
33834
|
+
return fetchers.agent_state(match.agent_name_hint);
|
|
33835
|
+
case "agent_activity":
|
|
33836
|
+
return fetchers.agent_activity(match.agent_name_hint);
|
|
33837
|
+
case "audit_log":
|
|
33838
|
+
return fetchers.audit_log();
|
|
33839
|
+
case "sentinel_findings":
|
|
33840
|
+
return fetchers.sentinel_findings();
|
|
33841
|
+
case "anomaly_alerts":
|
|
33842
|
+
return fetchers.anomaly_alerts();
|
|
33843
|
+
case "recent_receipts":
|
|
33844
|
+
return fetchers.recent_receipts();
|
|
33845
|
+
case "verascore_deltas":
|
|
33846
|
+
return fetchers.verascore_deltas();
|
|
33847
|
+
}
|
|
33848
|
+
}
|
|
33849
|
+
function trivialMatch(category) {
|
|
33850
|
+
return {
|
|
33851
|
+
category,
|
|
33852
|
+
confidence: 0.5,
|
|
33853
|
+
matched_keywords: ["llm-assist"],
|
|
33854
|
+
agent_name_hint: null
|
|
33855
|
+
};
|
|
33856
|
+
}
|
|
33857
|
+
async function foldContext(query, fetchers, opts) {
|
|
33858
|
+
const budget = opts?.maxTokens ?? DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET;
|
|
33859
|
+
let matches = classifyQuery(query);
|
|
33860
|
+
if (matches.length === 0 && !isTrivialQuery(query) && opts?.llmAssistClassify) {
|
|
33861
|
+
try {
|
|
33862
|
+
const picked = await opts.llmAssistClassify(query, CONTEXT_CATEGORIES);
|
|
33863
|
+
if (picked !== "none" && CONTEXT_CATEGORIES.includes(picked)) {
|
|
33864
|
+
matches = [trivialMatch(picked)];
|
|
33865
|
+
}
|
|
33866
|
+
} catch {
|
|
33867
|
+
}
|
|
33868
|
+
}
|
|
33869
|
+
if (matches.length === 0) {
|
|
33870
|
+
return { section: "", categoriesIncluded: [] };
|
|
33871
|
+
}
|
|
33872
|
+
const attempts = [];
|
|
33873
|
+
for (const match of matches) {
|
|
33874
|
+
try {
|
|
33875
|
+
const text = await runFetcher(match, fetchers);
|
|
33876
|
+
const trimmed = text.trim();
|
|
33877
|
+
if (trimmed.length > 0) {
|
|
33878
|
+
attempts.push({ category: match.category, text: trimmed });
|
|
33879
|
+
}
|
|
33880
|
+
} catch (err) {
|
|
33881
|
+
opts?.onFetcherFailure?.(match.category, err);
|
|
33882
|
+
}
|
|
33883
|
+
}
|
|
33884
|
+
if (attempts.length === 0) {
|
|
33885
|
+
return { section: "", categoriesIncluded: [] };
|
|
33886
|
+
}
|
|
33887
|
+
const headerTokens = approxTokenLen(`${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
33888
|
+
`);
|
|
33889
|
+
const sepTokens = approxTokenLen("\n\n");
|
|
33890
|
+
let runningTokens = headerTokens;
|
|
33891
|
+
const kept = [];
|
|
33892
|
+
for (const attempt of attempts) {
|
|
33893
|
+
const block = `### ${CATEGORY_LABELS[attempt.category]}
|
|
33894
|
+
${attempt.text}`;
|
|
33895
|
+
const tokens = approxTokenLen(block) + (kept.length > 0 ? sepTokens : 0);
|
|
33896
|
+
if (kept.length === 0) {
|
|
33897
|
+
kept.push(attempt);
|
|
33898
|
+
runningTokens += tokens;
|
|
33899
|
+
continue;
|
|
33900
|
+
}
|
|
33901
|
+
if (runningTokens + tokens > budget) break;
|
|
33902
|
+
kept.push(attempt);
|
|
33903
|
+
runningTokens += tokens;
|
|
33904
|
+
}
|
|
33905
|
+
const blocks = kept.map(
|
|
33906
|
+
(k) => `### ${CATEGORY_LABELS[k.category]}
|
|
33907
|
+
${k.text}`
|
|
33908
|
+
);
|
|
33909
|
+
const section = `${DYNAMIC_CONTEXT_SECTION_HEADER}
|
|
33910
|
+
${blocks.join("\n\n")}`;
|
|
33911
|
+
return {
|
|
33912
|
+
section,
|
|
33913
|
+
categoriesIncluded: kept.map((k) => k.category)
|
|
33914
|
+
};
|
|
33915
|
+
}
|
|
33916
|
+
var APPROX_CHARS_PER_TOKEN, DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET, DYNAMIC_CONTEXT_SECTION_HEADER, CONTEXT_CATEGORIES, CATEGORY_KEYWORDS, TRIVIAL_GREETINGS, CATEGORY_LABELS;
|
|
33917
|
+
var init_concierge_context_router = __esm({
|
|
33918
|
+
"src/chat/concierge-context-router.ts"() {
|
|
33919
|
+
APPROX_CHARS_PER_TOKEN = 4;
|
|
33920
|
+
DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET = 2e3;
|
|
33921
|
+
DYNAMIC_CONTEXT_SECTION_HEADER = "## Live fortress context";
|
|
33922
|
+
CONTEXT_CATEGORIES = [
|
|
33923
|
+
"templates",
|
|
33924
|
+
"agent_state",
|
|
33925
|
+
"agent_activity",
|
|
33926
|
+
"audit_log",
|
|
33927
|
+
"sentinel_findings",
|
|
33928
|
+
"anomaly_alerts",
|
|
33929
|
+
"recent_receipts",
|
|
33930
|
+
"verascore_deltas"
|
|
33931
|
+
];
|
|
33932
|
+
CATEGORY_KEYWORDS = [
|
|
33933
|
+
{
|
|
33934
|
+
category: "templates",
|
|
33935
|
+
patterns: [
|
|
33936
|
+
"templates",
|
|
33937
|
+
"template",
|
|
33938
|
+
"channel templates",
|
|
33939
|
+
"channel template",
|
|
33940
|
+
"list templates",
|
|
33941
|
+
"available templates",
|
|
33942
|
+
"what templates"
|
|
33943
|
+
].map(phrasePattern)
|
|
33944
|
+
},
|
|
33945
|
+
{
|
|
33946
|
+
category: "agent_state",
|
|
33947
|
+
patterns: [
|
|
33948
|
+
"state",
|
|
33949
|
+
"status",
|
|
33950
|
+
"agent state",
|
|
33951
|
+
"agent status",
|
|
33952
|
+
"status of agent",
|
|
33953
|
+
"status of agents",
|
|
33954
|
+
"state of",
|
|
33955
|
+
"doing"
|
|
33956
|
+
].map(phrasePattern)
|
|
33957
|
+
},
|
|
33958
|
+
{
|
|
33959
|
+
category: "agent_activity",
|
|
33960
|
+
patterns: [
|
|
33961
|
+
"activity",
|
|
33962
|
+
"agent activity",
|
|
33963
|
+
"what did",
|
|
33964
|
+
"recent activity"
|
|
33965
|
+
].map(phrasePattern)
|
|
33966
|
+
},
|
|
33967
|
+
{
|
|
33968
|
+
category: "audit_log",
|
|
33969
|
+
patterns: [
|
|
33970
|
+
"audit log",
|
|
33971
|
+
"audit",
|
|
33972
|
+
"log entry",
|
|
33973
|
+
"log entries",
|
|
33974
|
+
"what happened",
|
|
33975
|
+
"show me events",
|
|
33976
|
+
"event class"
|
|
33977
|
+
].map(phrasePattern)
|
|
33978
|
+
},
|
|
33979
|
+
{
|
|
33980
|
+
category: "sentinel_findings",
|
|
33981
|
+
patterns: [
|
|
33982
|
+
"sentinel",
|
|
33983
|
+
"sentinels",
|
|
33984
|
+
"warning",
|
|
33985
|
+
"warnings",
|
|
33986
|
+
"alert",
|
|
33987
|
+
"alerts",
|
|
33988
|
+
"whats wrong",
|
|
33989
|
+
"what's wrong",
|
|
33990
|
+
"findings"
|
|
33991
|
+
].map(phrasePattern)
|
|
33992
|
+
},
|
|
33993
|
+
{
|
|
33994
|
+
category: "anomaly_alerts",
|
|
33995
|
+
patterns: [
|
|
33996
|
+
"anomaly",
|
|
33997
|
+
"anomalies",
|
|
33998
|
+
"spike",
|
|
33999
|
+
"unusual",
|
|
34000
|
+
"outlier"
|
|
34001
|
+
].map(phrasePattern)
|
|
34002
|
+
},
|
|
34003
|
+
{
|
|
34004
|
+
category: "recent_receipts",
|
|
34005
|
+
patterns: [
|
|
34006
|
+
"receipt",
|
|
34007
|
+
"receipts",
|
|
34008
|
+
"concordia",
|
|
34009
|
+
"commitment",
|
|
34010
|
+
"commitments",
|
|
34011
|
+
"chain",
|
|
34012
|
+
"chains"
|
|
34013
|
+
].map(phrasePattern)
|
|
34014
|
+
},
|
|
34015
|
+
{
|
|
34016
|
+
category: "verascore_deltas",
|
|
34017
|
+
patterns: [
|
|
34018
|
+
"verascore",
|
|
34019
|
+
"vera score",
|
|
34020
|
+
"trust score",
|
|
34021
|
+
"reputation"
|
|
34022
|
+
].map(phrasePattern)
|
|
34023
|
+
}
|
|
34024
|
+
];
|
|
34025
|
+
TRIVIAL_GREETINGS = /* @__PURE__ */ new Set([
|
|
34026
|
+
"hi",
|
|
34027
|
+
"hello",
|
|
34028
|
+
"hey",
|
|
34029
|
+
"yo",
|
|
34030
|
+
"ok",
|
|
34031
|
+
"thanks",
|
|
34032
|
+
"thx",
|
|
34033
|
+
"thank you"
|
|
34034
|
+
]);
|
|
34035
|
+
CATEGORY_LABELS = {
|
|
34036
|
+
templates: "Templates",
|
|
34037
|
+
agent_state: "Agent state",
|
|
34038
|
+
agent_activity: "Agent activity",
|
|
34039
|
+
audit_log: "Audit log",
|
|
34040
|
+
sentinel_findings: "Sentinel findings",
|
|
34041
|
+
anomaly_alerts: "Anomaly alerts",
|
|
34042
|
+
recent_receipts: "Recent receipts",
|
|
34043
|
+
verascore_deltas: "Verascore deltas"
|
|
34044
|
+
};
|
|
34045
|
+
}
|
|
34046
|
+
});
|
|
34047
|
+
function approxTokenLen2(text) {
|
|
33421
34048
|
return Math.ceil(text.length / 4);
|
|
33422
34049
|
}
|
|
33423
34050
|
function makeEventId(prefix) {
|
|
33424
34051
|
return `${prefix}-${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;
|
|
33425
34052
|
}
|
|
34053
|
+
function classifyFetcherError(error) {
|
|
34054
|
+
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
34055
|
+
if (msg.includes("timeout") || msg.includes("timed out")) return "timeout";
|
|
34056
|
+
if (msg.includes("schema") || msg.includes("invalid shape")) {
|
|
34057
|
+
return "schema_mismatch";
|
|
34058
|
+
}
|
|
34059
|
+
if (msg.includes("io") || msg.includes("read") || msg.includes("enoent") || msg.includes("eacces")) {
|
|
34060
|
+
return "io_failed";
|
|
34061
|
+
}
|
|
34062
|
+
return "unknown";
|
|
34063
|
+
}
|
|
33426
34064
|
function formatPriorTurnLine(turn) {
|
|
33427
34065
|
const label = turn.role === "user" ? "OPERATOR" : "CONCIERGE";
|
|
33428
34066
|
return `${label}: ${turn.content}`;
|
|
@@ -33430,18 +34068,20 @@ function formatPriorTurnLine(turn) {
|
|
|
33430
34068
|
function hashOf(input) {
|
|
33431
34069
|
return hashToString(sha256.sha256(stringToBytes(input)));
|
|
33432
34070
|
}
|
|
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;
|
|
34071
|
+
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
34072
|
var init_operator_chat_service = __esm({
|
|
33435
34073
|
"src/chat/operator-chat-service.ts"() {
|
|
33436
34074
|
init_hashing();
|
|
33437
34075
|
init_encoding();
|
|
33438
34076
|
init_operator_chat_audit_events();
|
|
33439
34077
|
init_operator_chat_types();
|
|
34078
|
+
init_concierge_context_router();
|
|
33440
34079
|
DEFAULT_CONCIERGE_MAX_TOKENS = 512;
|
|
33441
34080
|
DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS = 10;
|
|
33442
34081
|
DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS = 24 * 60 * 60 * 1e3;
|
|
33443
34082
|
DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET = 500;
|
|
33444
34083
|
DEFAULT_CONCIERGE_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
34084
|
+
DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET = 2e3;
|
|
33445
34085
|
SANCTUARY_DOMAIN_REFERENCE = `Castle Architecture (four enforcement layers):
|
|
33446
34086
|
1. Castle Wall: OS-boundary egress filter enforced at the kernel level. Blocks unauthorized outbound calls even from prompt-injected agents.
|
|
33447
34087
|
2. Sentinels: internal observation via process introspection. Surfaces anomalies to the operator; does not enforce.
|
|
@@ -33483,6 +34123,9 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33483
34123
|
historyTokenBudget;
|
|
33484
34124
|
sessionTtlMs;
|
|
33485
34125
|
clock;
|
|
34126
|
+
contextFetchers;
|
|
34127
|
+
contextLlmAssist;
|
|
34128
|
+
dynamicContextBudget;
|
|
33486
34129
|
/**
|
|
33487
34130
|
* In-memory thread_id assigned to the active concierge session.
|
|
33488
34131
|
* The first sendConcierge call after construction allocates a fresh
|
|
@@ -33514,6 +34157,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33514
34157
|
this.historyTokenBudget = deps.conciergeHistoryTokenBudget !== void 0 && deps.conciergeHistoryTokenBudget > 0 ? deps.conciergeHistoryTokenBudget : DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET;
|
|
33515
34158
|
this.sessionTtlMs = deps.conciergeSessionTtlMs !== void 0 && deps.conciergeSessionTtlMs > 0 ? deps.conciergeSessionTtlMs : DEFAULT_CONCIERGE_SESSION_TTL_MS;
|
|
33516
34159
|
this.clock = deps.conciergeClock ?? (() => Date.now());
|
|
34160
|
+
if (deps.conciergeContextFetchers) {
|
|
34161
|
+
this.contextFetchers = deps.conciergeContextFetchers;
|
|
34162
|
+
}
|
|
34163
|
+
if (deps.conciergeContextLlmAssist) {
|
|
34164
|
+
this.contextLlmAssist = deps.conciergeContextLlmAssist;
|
|
34165
|
+
}
|
|
34166
|
+
this.dynamicContextBudget = deps.conciergeDynamicContextBudget !== void 0 && deps.conciergeDynamicContextBudget > 0 ? deps.conciergeDynamicContextBudget : DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET;
|
|
33517
34167
|
}
|
|
33518
34168
|
// ── Concierge ─────────────────────────────────────────────────────────
|
|
33519
34169
|
/**
|
|
@@ -33577,6 +34227,7 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33577
34227
|
let servedBy = "disabled";
|
|
33578
34228
|
let displayLabel = "Concierge: substrate not configured";
|
|
33579
34229
|
let outcome = "substrate_disabled";
|
|
34230
|
+
let dynamicCategoriesIncluded = [];
|
|
33580
34231
|
if (!this.substrateSelector) {
|
|
33581
34232
|
conciergeBody = "Concierge unavailable. The substrate selector is not configured for this fortress. Pick a substrate in the Policy center to enable concierge replies.";
|
|
33582
34233
|
} else {
|
|
@@ -33588,7 +34239,14 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33588
34239
|
conciergeBody = "Concierge unavailable. The chosen substrate does not support summarization. Pick a different substrate in the Policy center.";
|
|
33589
34240
|
outcome = "substrate_disabled";
|
|
33590
34241
|
} else {
|
|
33591
|
-
const
|
|
34242
|
+
const dynamicResult = await this.runDynamicContextFold(
|
|
34243
|
+
filterResult.filtered
|
|
34244
|
+
);
|
|
34245
|
+
dynamicCategoriesIncluded = dynamicResult.categoriesIncluded;
|
|
34246
|
+
const context = await this.assembleConciergeContext(
|
|
34247
|
+
priorTurns,
|
|
34248
|
+
dynamicResult.section
|
|
34249
|
+
);
|
|
33592
34250
|
const response = await this.substrateSelector.invokeSummarize(
|
|
33593
34251
|
"concierge",
|
|
33594
34252
|
{
|
|
@@ -33652,7 +34310,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33652
34310
|
...assistantTurnId !== void 0 ? { turn_index: assistantTurnId } : {},
|
|
33653
34311
|
...this.memory ? {
|
|
33654
34312
|
prior_turns_folded: memoryReadFailureReason === null ? priorTurns.length : 0
|
|
33655
|
-
} : {}
|
|
34313
|
+
} : {},
|
|
34314
|
+
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {}
|
|
33656
34315
|
};
|
|
33657
34316
|
this.emit(OPERATOR_CHAT_OPS.CONCIERGE_CHAT, payload, outcome === "ok" ? "success" : "failure");
|
|
33658
34317
|
return {
|
|
@@ -33803,10 +34462,13 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33803
34462
|
* ## Sanctuary reference
|
|
33804
34463
|
* <static domain reference block>
|
|
33805
34464
|
*
|
|
34465
|
+
* ## Live fortress context ← WP-V1.3-9 Tau-3, when present
|
|
34466
|
+
* ### <Category>
|
|
34467
|
+
* <fetcher payload>
|
|
34468
|
+
*
|
|
33806
34469
|
* ## Prior conversation ← WP-V1.3-9 Tau-2, when present
|
|
33807
34470
|
* OPERATOR: ...
|
|
33808
34471
|
* CONCIERGE: ...
|
|
33809
|
-
* ---
|
|
33810
34472
|
*
|
|
33811
34473
|
* ## Recent activity
|
|
33812
34474
|
* <recentActivity output>
|
|
@@ -33825,13 +34487,14 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
33825
34487
|
* if available; the v1.2 selector does not expose one, so structured
|
|
33826
34488
|
* serialization is the canonical path for v1.3.
|
|
33827
34489
|
*/
|
|
33828
|
-
async assembleConciergeContext(priorTurns = []) {
|
|
34490
|
+
async assembleConciergeContext(priorTurns = [], dynamicSection = "") {
|
|
33829
34491
|
const ref = `## Sanctuary reference
|
|
33830
34492
|
${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
33831
34493
|
const priorSection = this.formatPriorTurnsSection(priorTurns);
|
|
33832
34494
|
if (!this.contextProviders) {
|
|
33833
34495
|
return [
|
|
33834
34496
|
ref,
|
|
34497
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33835
34498
|
...priorSection ? [priorSection] : [],
|
|
33836
34499
|
"## Recent activity\n(no providers wired)",
|
|
33837
34500
|
"## Wrapped agents\n(no providers wired)",
|
|
@@ -33845,6 +34508,7 @@ ${SANCTUARY_DOMAIN_REFERENCE}`;
|
|
|
33845
34508
|
]);
|
|
33846
34509
|
return [
|
|
33847
34510
|
ref,
|
|
34511
|
+
...dynamicSection ? [dynamicSection] : [],
|
|
33848
34512
|
...priorSection ? [priorSection] : [],
|
|
33849
34513
|
`## Recent activity
|
|
33850
34514
|
${activity}`,
|
|
@@ -33854,6 +34518,51 @@ ${agents}`,
|
|
|
33854
34518
|
${inbox}`
|
|
33855
34519
|
].join("\n\n");
|
|
33856
34520
|
}
|
|
34521
|
+
/**
|
|
34522
|
+
* Run the WP-V1.3-9 Tau-3 dynamic-context fold for a single round-
|
|
34523
|
+
* trip. Fail-soft on every axis: missing fetchers short-circuit to
|
|
34524
|
+
* an empty fold, fetcher failures emit a per-category audit event
|
|
34525
|
+
* and are omitted from the rendered section, an LLM-assist failure
|
|
34526
|
+
* proceeds with no fold. Returns the rendered section + the list of
|
|
34527
|
+
* categories whose data made it into the section (used for the
|
|
34528
|
+
* round-trip audit emission).
|
|
34529
|
+
*/
|
|
34530
|
+
async runDynamicContextFold(query) {
|
|
34531
|
+
if (!this.contextFetchers) {
|
|
34532
|
+
return { section: "", categoriesIncluded: [] };
|
|
34533
|
+
}
|
|
34534
|
+
const result = await foldContext(query, this.contextFetchers, {
|
|
34535
|
+
maxTokens: this.dynamicContextBudget,
|
|
34536
|
+
...this.contextLlmAssist ? { llmAssistClassify: this.contextLlmAssist } : {},
|
|
34537
|
+
onFetcherFailure: (category, error) => {
|
|
34538
|
+
this.emitContextFetcherFailed(category, classifyFetcherError(error));
|
|
34539
|
+
}
|
|
34540
|
+
});
|
|
34541
|
+
return result;
|
|
34542
|
+
}
|
|
34543
|
+
/**
|
|
34544
|
+
* Emit the WP-V1.3-9 Tau-3 fetcher-failure audit event. Pulled out
|
|
34545
|
+
* of the fold path so the dynamic-context handler stays readable.
|
|
34546
|
+
* Emits with `result: "failure"` since the named category dropped
|
|
34547
|
+
* from the rendered section for this round-trip.
|
|
34548
|
+
*/
|
|
34549
|
+
emitContextFetcherFailed(category, failureReason) {
|
|
34550
|
+
const payload = {
|
|
34551
|
+
version: "1.2",
|
|
34552
|
+
event_id: makeEventId("conc-ctxfail"),
|
|
34553
|
+
emitted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34554
|
+
identity_id: this.identityId,
|
|
34555
|
+
kind: "operator_concierge_context_fetcher_failed",
|
|
34556
|
+
surface: "concierge",
|
|
34557
|
+
category,
|
|
34558
|
+
failure_reason: failureReason
|
|
34559
|
+
};
|
|
34560
|
+
this.emit(
|
|
34561
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
34562
|
+
payload,
|
|
34563
|
+
"failure"
|
|
34564
|
+
);
|
|
34565
|
+
}
|
|
33857
34566
|
/**
|
|
33858
34567
|
* Render the prior-conversation section with token-budget enforcement
|
|
33859
34568
|
* (WP-V1.3-9 Tau-2). Drops oldest turns first when the rendered
|
|
@@ -33864,14 +34573,14 @@ ${inbox}`
|
|
|
33864
34573
|
if (turns.length === 0) return "";
|
|
33865
34574
|
const HEADER = "## Prior conversation";
|
|
33866
34575
|
const lines = turns.map(formatPriorTurnLine);
|
|
33867
|
-
const headerTokens =
|
|
34576
|
+
const headerTokens = approxTokenLen2(`${HEADER}
|
|
33868
34577
|
`);
|
|
33869
|
-
const sepTokens =
|
|
34578
|
+
const sepTokens = approxTokenLen2("\n");
|
|
33870
34579
|
let runningTokens = headerTokens;
|
|
33871
34580
|
let runningLines = [];
|
|
33872
34581
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
33873
34582
|
const line = lines[i];
|
|
33874
|
-
const tokens =
|
|
34583
|
+
const tokens = approxTokenLen2(line) + (runningLines.length > 0 ? sepTokens : 0);
|
|
33875
34584
|
if (runningTokens + tokens > this.historyTokenBudget) break;
|
|
33876
34585
|
runningTokens += tokens;
|
|
33877
34586
|
runningLines.push(line);
|
|
@@ -33899,7 +34608,7 @@ ${runningLines.join("\n")}`;
|
|
|
33899
34608
|
function chatStorageKey(surface, threadKey) {
|
|
33900
34609
|
return `${surface}.${threadKey}`;
|
|
33901
34610
|
}
|
|
33902
|
-
var OPERATOR_CHAT_NAMESPACE,
|
|
34611
|
+
var OPERATOR_CHAT_NAMESPACE, HKDF_INFO2, OperatorChatStore;
|
|
33903
34612
|
var init_operator_chat_store = __esm({
|
|
33904
34613
|
"src/chat/operator-chat-store.ts"() {
|
|
33905
34614
|
init_encryption();
|
|
@@ -33907,13 +34616,13 @@ var init_operator_chat_store = __esm({
|
|
|
33907
34616
|
init_encoding();
|
|
33908
34617
|
init_operator_chat_types();
|
|
33909
34618
|
OPERATOR_CHAT_NAMESPACE = "_chat";
|
|
33910
|
-
|
|
34619
|
+
HKDF_INFO2 = "operator-chat-store-v1";
|
|
33911
34620
|
OperatorChatStore = class {
|
|
33912
34621
|
storage;
|
|
33913
34622
|
encryptionKey;
|
|
33914
34623
|
constructor(storage, masterKey) {
|
|
33915
34624
|
this.storage = storage;
|
|
33916
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
34625
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO2);
|
|
33917
34626
|
}
|
|
33918
34627
|
/**
|
|
33919
34628
|
* Load a thread. Returns null if no record exists or if the on-disk
|
|
@@ -33998,7 +34707,7 @@ var init_operator_chat_store = __esm({
|
|
|
33998
34707
|
function bundleKey(threadId) {
|
|
33999
34708
|
return `${CONCIERGE_MEMORY_KEY_PREFIX}${threadId}`;
|
|
34000
34709
|
}
|
|
34001
|
-
function
|
|
34710
|
+
function stripKeyPrefix2(key) {
|
|
34002
34711
|
if (!key.startsWith(CONCIERGE_MEMORY_KEY_PREFIX)) return null;
|
|
34003
34712
|
return key.slice(CONCIERGE_MEMORY_KEY_PREFIX.length);
|
|
34004
34713
|
}
|
|
@@ -34009,7 +34718,7 @@ function lastTurnId(bundle) {
|
|
|
34009
34718
|
}
|
|
34010
34719
|
return max;
|
|
34011
34720
|
}
|
|
34012
|
-
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX,
|
|
34721
|
+
var CONCIERGE_MEMORY_NAMESPACE, CONCIERGE_MEMORY_KEY_PREFIX, HKDF_INFO3, DEFAULT_CONCIERGE_RETENTION_DAYS, MAX_BUNDLE_BYTES3, ConciergeMemoryStore;
|
|
34013
34722
|
var init_concierge_memory_store = __esm({
|
|
34014
34723
|
"src/chat/concierge-memory-store.ts"() {
|
|
34015
34724
|
init_encryption();
|
|
@@ -34017,9 +34726,9 @@ var init_concierge_memory_store = __esm({
|
|
|
34017
34726
|
init_encoding();
|
|
34018
34727
|
CONCIERGE_MEMORY_NAMESPACE = "_chat";
|
|
34019
34728
|
CONCIERGE_MEMORY_KEY_PREFIX = "concierge_memory.";
|
|
34020
|
-
|
|
34729
|
+
HKDF_INFO3 = "concierge-memory-store-v1";
|
|
34021
34730
|
DEFAULT_CONCIERGE_RETENTION_DAYS = 30;
|
|
34022
|
-
|
|
34731
|
+
MAX_BUNDLE_BYTES3 = 4 * 1024 * 1024;
|
|
34023
34732
|
ConciergeMemoryStore = class {
|
|
34024
34733
|
storage;
|
|
34025
34734
|
encryptionKey;
|
|
@@ -34028,7 +34737,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34028
34737
|
locks;
|
|
34029
34738
|
constructor(opts) {
|
|
34030
34739
|
this.storage = opts.storage;
|
|
34031
|
-
this.encryptionKey = derivePurposeKey(opts.masterKey,
|
|
34740
|
+
this.encryptionKey = derivePurposeKey(opts.masterKey, HKDF_INFO3);
|
|
34032
34741
|
this.fortressId = opts.fortressId;
|
|
34033
34742
|
this.retentionDays = opts.retentionDays !== void 0 && opts.retentionDays > 0 ? opts.retentionDays : DEFAULT_CONCIERGE_RETENTION_DAYS;
|
|
34034
34743
|
this.locks = /* @__PURE__ */ new Map();
|
|
@@ -34107,7 +34816,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34107
34816
|
return { ok: false, reason: "io_failed" };
|
|
34108
34817
|
}
|
|
34109
34818
|
if (!raw) return { ok: true, turns: [] };
|
|
34110
|
-
if (raw.length >
|
|
34819
|
+
if (raw.length > MAX_BUNDLE_BYTES3) {
|
|
34111
34820
|
return { ok: false, reason: "oversize_bundle" };
|
|
34112
34821
|
}
|
|
34113
34822
|
let envelope;
|
|
@@ -34154,7 +34863,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34154
34863
|
);
|
|
34155
34864
|
const summaries = [];
|
|
34156
34865
|
for (const meta of entries) {
|
|
34157
|
-
const threadId =
|
|
34866
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34158
34867
|
if (threadId === null) continue;
|
|
34159
34868
|
const bundle = await this.loadBundle(threadId);
|
|
34160
34869
|
if (!bundle || bundle.turns.length === 0) continue;
|
|
@@ -34207,7 +34916,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34207
34916
|
);
|
|
34208
34917
|
let pruned = 0;
|
|
34209
34918
|
for (const meta of entries) {
|
|
34210
|
-
const threadId =
|
|
34919
|
+
const threadId = stripKeyPrefix2(meta.key);
|
|
34211
34920
|
if (threadId === null) continue;
|
|
34212
34921
|
pruned += await this.withLock(threadId, async () => {
|
|
34213
34922
|
const bundle = await this.loadBundle(threadId);
|
|
@@ -34238,7 +34947,7 @@ var init_concierge_memory_store = __esm({
|
|
|
34238
34947
|
return null;
|
|
34239
34948
|
}
|
|
34240
34949
|
if (!raw) return null;
|
|
34241
|
-
if (raw.length >
|
|
34950
|
+
if (raw.length > MAX_BUNDLE_BYTES3) return null;
|
|
34242
34951
|
try {
|
|
34243
34952
|
const envelope = JSON.parse(bytesToString(raw));
|
|
34244
34953
|
const aad = stringToBytes(threadId);
|
|
@@ -34329,7 +35038,18 @@ function buildV11Bindings(inputs) {
|
|
|
34329
35038
|
registry
|
|
34330
35039
|
}),
|
|
34331
35040
|
conciergePiiFilter: buildConciergePiiFilter(),
|
|
34332
|
-
conciergeMemory
|
|
35041
|
+
conciergeMemory,
|
|
35042
|
+
conciergeContextFetchers: buildConciergeContextFetchers({
|
|
35043
|
+
auditLog: inputs.auditLog,
|
|
35044
|
+
identityId: inputs.identityId,
|
|
35045
|
+
registry
|
|
35046
|
+
}),
|
|
35047
|
+
...inputs.intelligenceSelector ? {
|
|
35048
|
+
conciergeContextLlmAssist: buildConciergeContextLlmAssist({
|
|
35049
|
+
selector: inputs.intelligenceSelector,
|
|
35050
|
+
identityId: inputs.identityId
|
|
35051
|
+
})
|
|
35052
|
+
} : {}
|
|
34333
35053
|
});
|
|
34334
35054
|
}
|
|
34335
35055
|
const hubService = new HubService({
|
|
@@ -34390,6 +35110,107 @@ function buildConciergeContextProviders(args) {
|
|
|
34390
35110
|
}
|
|
34391
35111
|
};
|
|
34392
35112
|
}
|
|
35113
|
+
function buildConciergeContextFetchers(args) {
|
|
35114
|
+
const empty = async () => "";
|
|
35115
|
+
return {
|
|
35116
|
+
templates: async () => {
|
|
35117
|
+
const entries = listTemplates();
|
|
35118
|
+
if (entries.length === 0) return "(no templates installed)";
|
|
35119
|
+
const lines = entries.map((e) => {
|
|
35120
|
+
const m = e.metadata;
|
|
35121
|
+
return `${m.name} (tier ${m.tier}, channel ${m.channel}, target ${m.target_archetype})`;
|
|
35122
|
+
});
|
|
35123
|
+
return lines.join("\n");
|
|
35124
|
+
},
|
|
35125
|
+
agent_state: async (agentNameHint) => {
|
|
35126
|
+
const records = args.registry.list({ identity_id: args.identityId });
|
|
35127
|
+
if (records.length === 0) return "(no wrapped agents)";
|
|
35128
|
+
const filtered = agentNameHint ? records.filter(
|
|
35129
|
+
(r) => r.agent_id.toLowerCase().includes(agentNameHint.toLowerCase()) || r.harness.toLowerCase().includes(agentNameHint.toLowerCase())
|
|
35130
|
+
) : records;
|
|
35131
|
+
const target = filtered.length > 0 ? filtered : records;
|
|
35132
|
+
const lines = target.slice(0, 20).map((r) => {
|
|
35133
|
+
const tmpl = typeof r.channel_template_id === "string" ? r.channel_template_id : "no_template";
|
|
35134
|
+
return `${r.agent_id} harness=${r.harness} status=${r.status} template=${tmpl}`;
|
|
35135
|
+
});
|
|
35136
|
+
return lines.join("\n");
|
|
35137
|
+
},
|
|
35138
|
+
agent_activity: async (agentNameHint) => {
|
|
35139
|
+
const result = await args.auditLog.query({ limit: 50 });
|
|
35140
|
+
const owned = result.entries.filter(
|
|
35141
|
+
(e) => e.identity_id === args.identityId
|
|
35142
|
+
);
|
|
35143
|
+
const filtered = agentNameHint ? owned.filter((e) => {
|
|
35144
|
+
const agentId = e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : "";
|
|
35145
|
+
return agentId.toLowerCase().includes(agentNameHint.toLowerCase());
|
|
35146
|
+
}) : owned;
|
|
35147
|
+
const tail = (filtered.length > 0 ? filtered : owned).slice(-20);
|
|
35148
|
+
if (tail.length === 0) return "(no activity)";
|
|
35149
|
+
return tail.map((e) => {
|
|
35150
|
+
const agentId = (e.details && typeof e.details["agent_id"] === "string" ? e.details["agent_id"] : null) ?? "_fortress";
|
|
35151
|
+
return `${e.timestamp} ${e.layer}.${e.operation} agent=${agentId} result=${e.result}`;
|
|
35152
|
+
}).join("\n");
|
|
35153
|
+
},
|
|
35154
|
+
audit_log: async () => {
|
|
35155
|
+
const result = await args.auditLog.query({ limit: 30 });
|
|
35156
|
+
const owned = result.entries.filter(
|
|
35157
|
+
(e) => e.identity_id === args.identityId
|
|
35158
|
+
);
|
|
35159
|
+
if (owned.length === 0) return "(no audit log entries)";
|
|
35160
|
+
return owned.slice(-30).map(
|
|
35161
|
+
(e) => `${e.timestamp} ${e.layer}.${e.operation} result=${e.result}`
|
|
35162
|
+
).join("\n");
|
|
35163
|
+
},
|
|
35164
|
+
sentinel_findings: empty,
|
|
35165
|
+
anomaly_alerts: empty,
|
|
35166
|
+
recent_receipts: async () => {
|
|
35167
|
+
const result = await args.auditLog.query({ limit: 100 });
|
|
35168
|
+
const owned = result.entries.filter(
|
|
35169
|
+
(e) => e.identity_id === args.identityId && e.operation.startsWith("composition_")
|
|
35170
|
+
);
|
|
35171
|
+
if (owned.length === 0) return "(no recent composition events)";
|
|
35172
|
+
return owned.slice(-15).map((e) => `${e.timestamp} ${e.operation} result=${e.result}`).join("\n");
|
|
35173
|
+
},
|
|
35174
|
+
verascore_deltas: empty
|
|
35175
|
+
};
|
|
35176
|
+
}
|
|
35177
|
+
function buildConciergeContextLlmAssist(args) {
|
|
35178
|
+
return async (query, categories) => {
|
|
35179
|
+
const labelList = categories.map((c) => `- ${c}`).join("\n");
|
|
35180
|
+
const prompt2 = `You are a router. Classify the operator's query into one of the categories below or "none".
|
|
35181
|
+
Reply with exactly one token: one category name or "none".
|
|
35182
|
+
|
|
35183
|
+
Categories:
|
|
35184
|
+
${labelList}
|
|
35185
|
+
|
|
35186
|
+
Query: ${query}
|
|
35187
|
+
|
|
35188
|
+
Category:`;
|
|
35189
|
+
try {
|
|
35190
|
+
const handle = await args.selector.getSubstrate("concierge");
|
|
35191
|
+
if (!handle.capability.summarize) return "none";
|
|
35192
|
+
const response = await args.selector.invokeSummarize("concierge", {
|
|
35193
|
+
kind: "summarize",
|
|
35194
|
+
context: prompt2,
|
|
35195
|
+
query: "Output the single category token.",
|
|
35196
|
+
maxTokens: 16
|
|
35197
|
+
});
|
|
35198
|
+
if (response.failureClass || response.body.kind !== "summarize") {
|
|
35199
|
+
return "none";
|
|
35200
|
+
}
|
|
35201
|
+
const raw = response.body.text.trim().toLowerCase();
|
|
35202
|
+
const head = raw.split(/\s|[.,!?:;]/)[0] ?? "";
|
|
35203
|
+
const normalized = head.replace(/[^a-z_]/g, "");
|
|
35204
|
+
const known = categories;
|
|
35205
|
+
if (known.includes(normalized)) {
|
|
35206
|
+
return normalized;
|
|
35207
|
+
}
|
|
35208
|
+
return "none";
|
|
35209
|
+
} catch {
|
|
35210
|
+
return "none";
|
|
35211
|
+
}
|
|
35212
|
+
};
|
|
35213
|
+
}
|
|
34393
35214
|
function buildConciergePiiFilter() {
|
|
34394
35215
|
return {
|
|
34395
35216
|
filter(input) {
|
|
@@ -34417,6 +35238,7 @@ var init_wiring = __esm({
|
|
|
34417
35238
|
init_agent_registry_persistence();
|
|
34418
35239
|
init_operator_chat_index();
|
|
34419
35240
|
init_privacy_filter();
|
|
35241
|
+
init_registry();
|
|
34420
35242
|
CapabilityErrorAgentController = class {
|
|
34421
35243
|
fail(action) {
|
|
34422
35244
|
throw new HubCapabilityError(
|
|
@@ -34564,7 +35386,7 @@ var init_defaults = __esm({
|
|
|
34564
35386
|
});
|
|
34565
35387
|
|
|
34566
35388
|
// src/intelligence/policy-store.ts
|
|
34567
|
-
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY,
|
|
35389
|
+
var INTELLIGENCE_NAMESPACE, SUBSTRATE_CONFIG_KEY, HKDF_INFO4, IntelligenceConfigStore;
|
|
34568
35390
|
var init_policy_store = __esm({
|
|
34569
35391
|
"src/intelligence/policy-store.ts"() {
|
|
34570
35392
|
init_encryption();
|
|
@@ -34573,13 +35395,13 @@ var init_policy_store = __esm({
|
|
|
34573
35395
|
init_defaults();
|
|
34574
35396
|
INTELLIGENCE_NAMESPACE = "_intelligence";
|
|
34575
35397
|
SUBSTRATE_CONFIG_KEY = "substrate-config";
|
|
34576
|
-
|
|
35398
|
+
HKDF_INFO4 = "intelligence-substrate-config";
|
|
34577
35399
|
IntelligenceConfigStore = class {
|
|
34578
35400
|
storage;
|
|
34579
35401
|
encryptionKey;
|
|
34580
35402
|
constructor(storage, masterKey) {
|
|
34581
35403
|
this.storage = storage;
|
|
34582
|
-
this.encryptionKey = derivePurposeKey(masterKey,
|
|
35404
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_INFO4);
|
|
34583
35405
|
}
|
|
34584
35406
|
/**
|
|
34585
35407
|
* Load the operator's substrate config from disk. Returns the config
|
|
@@ -38497,12 +39319,18 @@ ${err.message}
|
|
|
38497
39319
|
} : void 0;
|
|
38498
39320
|
const fortressIdForAggregator = fortressIdFromStoragePath(config.storage_path);
|
|
38499
39321
|
const aggregatorIdentityId = identityManager.getPrimaryIdentityId() ?? `fortress:${config.storage_path}`;
|
|
39322
|
+
const aggregatorPayloadStore = new AggregatorPayloadStore({
|
|
39323
|
+
storage,
|
|
39324
|
+
masterKey,
|
|
39325
|
+
fortressId: fortressIdForAggregator
|
|
39326
|
+
});
|
|
38500
39327
|
const approvalAggregator = new ApprovalAggregator({
|
|
38501
39328
|
storage,
|
|
38502
39329
|
masterKey,
|
|
38503
39330
|
auditLog,
|
|
38504
39331
|
identityId: aggregatorIdentityId,
|
|
38505
|
-
fortressId: fortressIdForAggregator
|
|
39332
|
+
fortressId: fortressIdForAggregator,
|
|
39333
|
+
payloadStore: aggregatorPayloadStore
|
|
38506
39334
|
});
|
|
38507
39335
|
const wrappedApprovalChannel = new AggregatorBackedChannel({
|
|
38508
39336
|
underlying: approvalChannel,
|
|
@@ -38716,6 +39544,7 @@ var init_src = __esm({
|
|
|
38716
39544
|
init_gate();
|
|
38717
39545
|
init_approval_aggregator();
|
|
38718
39546
|
init_aggregator_backed_channel();
|
|
39547
|
+
init_aggregator_store();
|
|
38719
39548
|
init_tools4();
|
|
38720
39549
|
init_router();
|
|
38721
39550
|
init_router();
|