@sanctuary-framework/mcp-server 1.2.6 → 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 +763 -30
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +763 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +753 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +312 -10
- package/dist/index.d.ts +312 -10
- package/dist/index.js +753 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5037,7 +5037,8 @@ var init_constants = __esm({
|
|
|
5037
5037
|
RESERVED_EVENT_TYPE_PREFIXES = [
|
|
5038
5038
|
"EXTENSION_",
|
|
5039
5039
|
"cross_fortress_",
|
|
5040
|
-
"multi_master_"
|
|
5040
|
+
"multi_master_",
|
|
5041
|
+
"cross_harness_approval_"
|
|
5041
5042
|
];
|
|
5042
5043
|
RESERVED_EXTENSION_ENVELOPE_KEYS = [
|
|
5043
5044
|
"cross_fortress_read_grant",
|
|
@@ -9229,9 +9230,9 @@ function fingerprintDID(did) {
|
|
|
9229
9230
|
return `${raw.slice(0, 6)}\u2026${raw.slice(-6)}`;
|
|
9230
9231
|
}
|
|
9231
9232
|
function countInjectionsToday(audit) {
|
|
9232
|
-
const
|
|
9233
|
-
|
|
9234
|
-
const cutoff =
|
|
9233
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9234
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9235
|
+
const cutoff = startOfDay2.getTime();
|
|
9235
9236
|
return audit.filter((e) => {
|
|
9236
9237
|
const ts = new Date(e.timestamp).getTime();
|
|
9237
9238
|
if (isNaN(ts) || ts < cutoff) return false;
|
|
@@ -9240,9 +9241,9 @@ function countInjectionsToday(audit) {
|
|
|
9240
9241
|
}).length;
|
|
9241
9242
|
}
|
|
9242
9243
|
function countProofsToday(audit) {
|
|
9243
|
-
const
|
|
9244
|
-
|
|
9245
|
-
const cutoff =
|
|
9244
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9245
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9246
|
+
const cutoff = startOfDay2.getTime();
|
|
9246
9247
|
return audit.filter((e) => {
|
|
9247
9248
|
if (e.layer !== "l3") return false;
|
|
9248
9249
|
if (!PROOF_CREATION_OPS.has(e.operation)) return false;
|
|
@@ -17211,6 +17212,24 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17211
17212
|
await handleStream2(deps, res);
|
|
17212
17213
|
return true;
|
|
17213
17214
|
}
|
|
17215
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/revision`) {
|
|
17216
|
+
const revision = await deps.aggregator.getRevision();
|
|
17217
|
+
writeJSON4(res, 200, { ok: true, data: { revision } });
|
|
17218
|
+
return true;
|
|
17219
|
+
}
|
|
17220
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/sync`) {
|
|
17221
|
+
const sinceRaw = url.searchParams.get("since_revision");
|
|
17222
|
+
const sinceParsed = sinceRaw === null ? 0 : Number.parseInt(sinceRaw, 10);
|
|
17223
|
+
const sinceRevision = Number.isFinite(sinceParsed) && sinceParsed >= 0 ? sinceParsed : 0;
|
|
17224
|
+
const limit = parseLimit2(
|
|
17225
|
+
url.searchParams.get("limit"),
|
|
17226
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17227
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17228
|
+
);
|
|
17229
|
+
const delta = await deps.aggregator.getSync({ sinceRevision, limit });
|
|
17230
|
+
writeJSON4(res, 200, { ok: true, data: delta });
|
|
17231
|
+
return true;
|
|
17232
|
+
}
|
|
17214
17233
|
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/history`) {
|
|
17215
17234
|
const limit = parseLimit2(
|
|
17216
17235
|
url.searchParams.get("limit"),
|
|
@@ -20353,6 +20372,20 @@ var init_approval_aggregator = __esm({
|
|
|
20353
20372
|
hydrated = false;
|
|
20354
20373
|
/** Active SSE listeners. */
|
|
20355
20374
|
listeners = /* @__PURE__ */ new Set();
|
|
20375
|
+
/**
|
|
20376
|
+
* Monotonic revision counter, bumped on every mutation (ingest of new
|
|
20377
|
+
* entry, resolve, expire, delete). Hydrated from max(last_modified_revision)
|
|
20378
|
+
* across persisted entries on first read; in-memory after that. v1.3
|
|
20379
|
+
* Upsilon-4.
|
|
20380
|
+
*/
|
|
20381
|
+
currentRevision = 0;
|
|
20382
|
+
/**
|
|
20383
|
+
* Removal tombstones: aggregator_id -> revision at removal. Used by the
|
|
20384
|
+
* sync API to surface "removed" entries to mobile consumers between
|
|
20385
|
+
* polls. In-memory only; server restart clears tombstones (mobile
|
|
20386
|
+
* bootstraps via `list()` on reconnect). v1.3 Upsilon-4.
|
|
20387
|
+
*/
|
|
20388
|
+
removedTombstones = /* @__PURE__ */ new Map();
|
|
20356
20389
|
constructor(deps) {
|
|
20357
20390
|
this.storage = deps.storage;
|
|
20358
20391
|
this.encryptionKey = derivePurposeKey(
|
|
@@ -20387,6 +20420,113 @@ var init_approval_aggregator = __esm({
|
|
|
20387
20420
|
this.listeners.add(listener);
|
|
20388
20421
|
return () => this.listeners.delete(listener);
|
|
20389
20422
|
}
|
|
20423
|
+
/**
|
|
20424
|
+
* Current aggregator revision. v1.3 Upsilon-4. Mobile companions
|
|
20425
|
+
* poll the lightweight `/revision` route to detect that something
|
|
20426
|
+
* changed before fetching a full sync delta.
|
|
20427
|
+
*/
|
|
20428
|
+
async getRevision() {
|
|
20429
|
+
await this.hydrate();
|
|
20430
|
+
return this.currentRevision;
|
|
20431
|
+
}
|
|
20432
|
+
/**
|
|
20433
|
+
* Compute a delta since `sinceRevision`. v1.3 Upsilon-4. Mobile
|
|
20434
|
+
* clients poll this for cheap state-sync. Behavior:
|
|
20435
|
+
* - `added`: entries whose `created_at_revision > sinceRevision`.
|
|
20436
|
+
* - `changed`: entries that existed at `sinceRevision` but had a
|
|
20437
|
+
* status transition (resolve, expire) since.
|
|
20438
|
+
* - `removed`: aggregator_ids deleted after `sinceRevision`.
|
|
20439
|
+
* - `revision`: current aggregator revision; pass this back as
|
|
20440
|
+
* `sinceRevision` on the next call.
|
|
20441
|
+
*
|
|
20442
|
+
* `limit` caps the total count returned across all three lists,
|
|
20443
|
+
* prioritized as added -> changed -> removed (newer-state first).
|
|
20444
|
+
* When more changes exist than fit, the next call with the returned
|
|
20445
|
+
* revision will pick up the rest because each entry's
|
|
20446
|
+
* last_modified_revision is unchanged by truncation.
|
|
20447
|
+
*/
|
|
20448
|
+
async getSync(opts) {
|
|
20449
|
+
await this.hydrate();
|
|
20450
|
+
await this.expireStale();
|
|
20451
|
+
const sinceRevision = opts?.sinceRevision ?? 0;
|
|
20452
|
+
const cap = Math.min(
|
|
20453
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20454
|
+
this.maxListLimit
|
|
20455
|
+
);
|
|
20456
|
+
const added = [];
|
|
20457
|
+
const changed = [];
|
|
20458
|
+
for (const entry of this.entries.values()) {
|
|
20459
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20460
|
+
if (lastMod <= sinceRevision) continue;
|
|
20461
|
+
const createdRev = entry.created_at_revision ?? 0;
|
|
20462
|
+
if (createdRev > sinceRevision) {
|
|
20463
|
+
added.push(entry);
|
|
20464
|
+
} else {
|
|
20465
|
+
changed.push(entry);
|
|
20466
|
+
}
|
|
20467
|
+
}
|
|
20468
|
+
const removed = [];
|
|
20469
|
+
for (const [id, rev] of this.removedTombstones) {
|
|
20470
|
+
if (rev > sinceRevision) removed.push(id);
|
|
20471
|
+
}
|
|
20472
|
+
added.sort(
|
|
20473
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20474
|
+
);
|
|
20475
|
+
changed.sort(
|
|
20476
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20477
|
+
);
|
|
20478
|
+
let remaining = cap;
|
|
20479
|
+
const addedOut = added.slice(0, Math.max(0, remaining));
|
|
20480
|
+
remaining -= addedOut.length;
|
|
20481
|
+
const changedOut = changed.slice(0, Math.max(0, remaining));
|
|
20482
|
+
remaining -= changedOut.length;
|
|
20483
|
+
const removedOut = removed.slice(0, Math.max(0, remaining));
|
|
20484
|
+
return {
|
|
20485
|
+
revision: this.currentRevision,
|
|
20486
|
+
added: addedOut,
|
|
20487
|
+
changed: changedOut,
|
|
20488
|
+
removed: removedOut
|
|
20489
|
+
};
|
|
20490
|
+
}
|
|
20491
|
+
/**
|
|
20492
|
+
* Delete an entry. Drops the in-memory record, the persisted bundle,
|
|
20493
|
+
* and the at-rest payload (if a payload store is wired). Records a
|
|
20494
|
+
* tombstone with the new revision so sync-API consumers see a
|
|
20495
|
+
* `removed` delta. Returns true when an entry was deleted, false on
|
|
20496
|
+
* unknown id. v1.3 Upsilon-4. Reserved for v1.4+ retention housekeeping;
|
|
20497
|
+
* Upsilon-4 ships the surface so mobile sync-API tests can exercise the
|
|
20498
|
+
* removal path.
|
|
20499
|
+
*/
|
|
20500
|
+
async deleteEntry(aggregatorId) {
|
|
20501
|
+
await this.hydrate();
|
|
20502
|
+
const entry = this.entries.get(aggregatorId);
|
|
20503
|
+
if (!entry) return false;
|
|
20504
|
+
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20505
|
+
this.entries.delete(aggregatorId);
|
|
20506
|
+
this.dedupIndex.delete(dedupKey);
|
|
20507
|
+
this.fullPayloads.delete(aggregatorId);
|
|
20508
|
+
for (const [corr, id] of this.correlationIndex) {
|
|
20509
|
+
if (id === aggregatorId) this.correlationIndex.delete(corr);
|
|
20510
|
+
}
|
|
20511
|
+
try {
|
|
20512
|
+
await this.storage.delete(APPROVAL_AGGREGATOR_NAMESPACE, aggregatorId);
|
|
20513
|
+
} catch {
|
|
20514
|
+
}
|
|
20515
|
+
if (this.payloadStore) {
|
|
20516
|
+
try {
|
|
20517
|
+
await this.payloadStore.deletePayload(aggregatorId);
|
|
20518
|
+
} catch {
|
|
20519
|
+
}
|
|
20520
|
+
}
|
|
20521
|
+
const revision = this.nextRevision();
|
|
20522
|
+
this.removedTombstones.set(aggregatorId, revision);
|
|
20523
|
+
this.emit({ type: "removed", entry: { ...entry } });
|
|
20524
|
+
return true;
|
|
20525
|
+
}
|
|
20526
|
+
nextRevision() {
|
|
20527
|
+
this.currentRevision += 1;
|
|
20528
|
+
return this.currentRevision;
|
|
20529
|
+
}
|
|
20390
20530
|
/**
|
|
20391
20531
|
* Ingest a gate event. Returns the aggregator entry on first sight,
|
|
20392
20532
|
* `null` when deduped. Resolution events update the existing record;
|
|
@@ -20597,6 +20737,7 @@ var init_approval_aggregator = __esm({
|
|
|
20597
20737
|
entry.status = decision;
|
|
20598
20738
|
entry.resolved_at = this.now().toISOString();
|
|
20599
20739
|
entry.resolved_by = operatorId;
|
|
20740
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20600
20741
|
await this.persist(entry);
|
|
20601
20742
|
this.auditLog.append(
|
|
20602
20743
|
"l2",
|
|
@@ -20648,6 +20789,7 @@ var init_approval_aggregator = __esm({
|
|
|
20648
20789
|
const expires = new Date(now.getTime() + this.pendingTtlMs);
|
|
20649
20790
|
const hubInboxId = this.resolveHubInboxItemId(event);
|
|
20650
20791
|
const enforcementChain = this.resolveEnforcementChain(event);
|
|
20792
|
+
const revision = this.nextRevision();
|
|
20651
20793
|
const entry = {
|
|
20652
20794
|
aggregator_id: id,
|
|
20653
20795
|
source_harness: ctx.source_harness,
|
|
@@ -20659,6 +20801,8 @@ var init_approval_aggregator = __esm({
|
|
|
20659
20801
|
status: "pending",
|
|
20660
20802
|
created_at: now.toISOString(),
|
|
20661
20803
|
expires_at: expires.toISOString(),
|
|
20804
|
+
created_at_revision: revision,
|
|
20805
|
+
last_modified_revision: revision,
|
|
20662
20806
|
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {},
|
|
20663
20807
|
...enforcementChain.length > 0 ? { enforcement_chain: enforcementChain } : {}
|
|
20664
20808
|
};
|
|
@@ -20701,6 +20845,7 @@ var init_approval_aggregator = __esm({
|
|
|
20701
20845
|
entry.status = status;
|
|
20702
20846
|
entry.resolved_at = event.resolution.decided_at;
|
|
20703
20847
|
entry.resolved_by = event.resolution.decided_by;
|
|
20848
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20704
20849
|
await this.persist(entry);
|
|
20705
20850
|
this.auditLog.append(
|
|
20706
20851
|
"l2",
|
|
@@ -20763,6 +20908,7 @@ var init_approval_aggregator = __esm({
|
|
|
20763
20908
|
entry.status = "expired";
|
|
20764
20909
|
entry.resolved_at = this.now().toISOString();
|
|
20765
20910
|
entry.resolved_by = "system_ttl";
|
|
20911
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20766
20912
|
await this.persist(entry);
|
|
20767
20913
|
this.auditLog.append(
|
|
20768
20914
|
"l2",
|
|
@@ -20809,6 +20955,10 @@ var init_approval_aggregator = __esm({
|
|
|
20809
20955
|
this.entries.set(entry.aggregator_id, entry);
|
|
20810
20956
|
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20811
20957
|
this.dedupIndex.set(dedupKey, entry.aggregator_id);
|
|
20958
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20959
|
+
if (lastMod > this.currentRevision) {
|
|
20960
|
+
this.currentRevision = lastMod;
|
|
20961
|
+
}
|
|
20812
20962
|
} catch {
|
|
20813
20963
|
}
|
|
20814
20964
|
}
|
|
@@ -33789,9 +33939,10 @@ function isTrivialQuery(query) {
|
|
|
33789
33939
|
if (norm.length < 8) return true;
|
|
33790
33940
|
return TRIVIAL_GREETINGS.has(norm);
|
|
33791
33941
|
}
|
|
33792
|
-
function classifyQuery(query) {
|
|
33942
|
+
function classifyQuery(query, parsedGrammar) {
|
|
33793
33943
|
const normalized = query.toLowerCase();
|
|
33794
33944
|
const matches = [];
|
|
33945
|
+
const grammarAgent = parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null;
|
|
33795
33946
|
for (const spec of CATEGORY_KEYWORDS) {
|
|
33796
33947
|
const matchedPhrases = [];
|
|
33797
33948
|
for (const pattern of spec.patterns) {
|
|
@@ -33803,11 +33954,14 @@ function classifyQuery(query) {
|
|
|
33803
33954
|
}
|
|
33804
33955
|
if (matchedPhrases.length === 0) continue;
|
|
33805
33956
|
const confidence = Math.min(1, 0.4 + 0.3 * matchedPhrases.length);
|
|
33957
|
+
const wantsAgentHint = spec.category === "agent_state" || spec.category === "agent_activity";
|
|
33958
|
+
const agent_name_hint = wantsAgentHint ? grammarAgent ?? extractAgentNameHint(query) : null;
|
|
33806
33959
|
matches.push({
|
|
33807
33960
|
category: spec.category,
|
|
33808
33961
|
confidence,
|
|
33809
33962
|
matched_keywords: matchedPhrases,
|
|
33810
|
-
agent_name_hint
|
|
33963
|
+
agent_name_hint,
|
|
33964
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33811
33965
|
});
|
|
33812
33966
|
}
|
|
33813
33967
|
matches.sort((a, b) => {
|
|
@@ -33816,45 +33970,67 @@ function classifyQuery(query) {
|
|
|
33816
33970
|
});
|
|
33817
33971
|
return matches;
|
|
33818
33972
|
}
|
|
33973
|
+
function fetcherHintsFromGrammar(parsed) {
|
|
33974
|
+
if (!parsed) return void 0;
|
|
33975
|
+
const hasTime = parsed.time_range !== null;
|
|
33976
|
+
const hasAgents = parsed.agent_names.length > 0;
|
|
33977
|
+
const hasEvents = parsed.event_types.length > 0;
|
|
33978
|
+
if (!hasTime && !hasAgents && !hasEvents) return void 0;
|
|
33979
|
+
const hints = {};
|
|
33980
|
+
if (parsed.time_range) {
|
|
33981
|
+
const range = parsed.time_range;
|
|
33982
|
+
hints.time_range = {
|
|
33983
|
+
start: range.start,
|
|
33984
|
+
end: range.end,
|
|
33985
|
+
...range.relative_label !== void 0 ? { relative_label: range.relative_label } : {}
|
|
33986
|
+
};
|
|
33987
|
+
}
|
|
33988
|
+
if (hasAgents) hints.agent_names = parsed.agent_names;
|
|
33989
|
+
if (hasEvents) hints.event_types = parsed.event_types;
|
|
33990
|
+
return hints;
|
|
33991
|
+
}
|
|
33819
33992
|
function approxTokenLen(text) {
|
|
33820
33993
|
return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
33821
33994
|
}
|
|
33822
|
-
async function runFetcher(match, fetchers) {
|
|
33995
|
+
async function runFetcher(match, fetchers, hints) {
|
|
33823
33996
|
switch (match.category) {
|
|
33824
33997
|
case "templates":
|
|
33825
|
-
return fetchers.templates();
|
|
33998
|
+
return fetchers.templates(hints);
|
|
33826
33999
|
case "agent_state":
|
|
33827
|
-
return fetchers.agent_state(match.agent_name_hint);
|
|
34000
|
+
return fetchers.agent_state(match.agent_name_hint, hints);
|
|
33828
34001
|
case "agent_activity":
|
|
33829
|
-
return fetchers.agent_activity(match.agent_name_hint);
|
|
34002
|
+
return fetchers.agent_activity(match.agent_name_hint, hints);
|
|
33830
34003
|
case "audit_log":
|
|
33831
|
-
return fetchers.audit_log();
|
|
34004
|
+
return fetchers.audit_log(hints);
|
|
33832
34005
|
case "sentinel_findings":
|
|
33833
|
-
return fetchers.sentinel_findings();
|
|
34006
|
+
return fetchers.sentinel_findings(hints);
|
|
33834
34007
|
case "anomaly_alerts":
|
|
33835
|
-
return fetchers.anomaly_alerts();
|
|
34008
|
+
return fetchers.anomaly_alerts(hints);
|
|
33836
34009
|
case "recent_receipts":
|
|
33837
|
-
return fetchers.recent_receipts();
|
|
34010
|
+
return fetchers.recent_receipts(hints);
|
|
33838
34011
|
case "verascore_deltas":
|
|
33839
|
-
return fetchers.verascore_deltas();
|
|
34012
|
+
return fetchers.verascore_deltas(hints);
|
|
33840
34013
|
}
|
|
33841
34014
|
}
|
|
33842
|
-
function trivialMatch(category) {
|
|
34015
|
+
function trivialMatch(category, parsedGrammar) {
|
|
33843
34016
|
return {
|
|
33844
34017
|
category,
|
|
33845
34018
|
confidence: 0.5,
|
|
33846
34019
|
matched_keywords: ["llm-assist"],
|
|
33847
|
-
agent_name_hint: null
|
|
34020
|
+
agent_name_hint: parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null,
|
|
34021
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33848
34022
|
};
|
|
33849
34023
|
}
|
|
33850
34024
|
async function foldContext(query, fetchers, opts) {
|
|
33851
34025
|
const budget = opts?.maxTokens ?? DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET;
|
|
33852
|
-
|
|
34026
|
+
const parsed = opts?.parsed ?? null;
|
|
34027
|
+
const hints = fetcherHintsFromGrammar(parsed);
|
|
34028
|
+
let matches = classifyQuery(query, parsed);
|
|
33853
34029
|
if (matches.length === 0 && !isTrivialQuery(query) && opts?.llmAssistClassify) {
|
|
33854
34030
|
try {
|
|
33855
34031
|
const picked = await opts.llmAssistClassify(query, CONTEXT_CATEGORIES);
|
|
33856
34032
|
if (picked !== "none" && CONTEXT_CATEGORIES.includes(picked)) {
|
|
33857
|
-
matches = [trivialMatch(picked)];
|
|
34033
|
+
matches = [trivialMatch(picked, parsed)];
|
|
33858
34034
|
}
|
|
33859
34035
|
} catch {
|
|
33860
34036
|
}
|
|
@@ -33865,7 +34041,7 @@ async function foldContext(query, fetchers, opts) {
|
|
|
33865
34041
|
const attempts = [];
|
|
33866
34042
|
for (const match of matches) {
|
|
33867
34043
|
try {
|
|
33868
|
-
const text = await runFetcher(match, fetchers);
|
|
34044
|
+
const text = await runFetcher(match, fetchers, hints);
|
|
33869
34045
|
const trimmed = text.trim();
|
|
33870
34046
|
if (trimmed.length > 0) {
|
|
33871
34047
|
attempts.push({ category: match.category, text: trimmed });
|
|
@@ -34037,6 +34213,533 @@ var init_concierge_context_router = __esm({
|
|
|
34037
34213
|
};
|
|
34038
34214
|
}
|
|
34039
34215
|
});
|
|
34216
|
+
|
|
34217
|
+
// src/composition/constants.ts
|
|
34218
|
+
var COMPOSITION_EVENT_TYPES;
|
|
34219
|
+
var init_constants4 = __esm({
|
|
34220
|
+
"src/composition/constants.ts"() {
|
|
34221
|
+
init_constants();
|
|
34222
|
+
COMPOSITION_EVENT_TYPES = [
|
|
34223
|
+
"composition_receipt_packed",
|
|
34224
|
+
"composition_receipt_verified",
|
|
34225
|
+
"composition_mandate_verified",
|
|
34226
|
+
"composition_verascore_published",
|
|
34227
|
+
"composition_sidecar_spawned",
|
|
34228
|
+
"composition_sidecar_crashed",
|
|
34229
|
+
"composition_sidecar_recovered",
|
|
34230
|
+
"composition_degraded",
|
|
34231
|
+
"composition_recovered"
|
|
34232
|
+
];
|
|
34233
|
+
}
|
|
34234
|
+
});
|
|
34235
|
+
|
|
34236
|
+
// src/chat/concierge-query-grammar.ts
|
|
34237
|
+
function resolveTimeRange(query, now) {
|
|
34238
|
+
const normalized = query.trim();
|
|
34239
|
+
const lower = normalized.toLowerCase();
|
|
34240
|
+
const fromTo = lower.match(
|
|
34241
|
+
/\b(?:from|between)\s+(.+?)\s+(?:to|and|-|until)\s+([\w:.\-+t /]+)/i
|
|
34242
|
+
);
|
|
34243
|
+
if (fromTo) {
|
|
34244
|
+
const aSlice = fromTo[1];
|
|
34245
|
+
const bSlice = fromTo[2];
|
|
34246
|
+
if (aSlice !== void 0 && bSlice !== void 0) {
|
|
34247
|
+
const a = parseInstant(aSlice, now);
|
|
34248
|
+
const b = parseInstant(bSlice, now);
|
|
34249
|
+
if (a && b) {
|
|
34250
|
+
const start = a.getTime() <= b.getTime() ? a : b;
|
|
34251
|
+
const end = a.getTime() <= b.getTime() ? b : a;
|
|
34252
|
+
return {
|
|
34253
|
+
range: { start, end },
|
|
34254
|
+
matchedSubstring: fromTo[0]
|
|
34255
|
+
};
|
|
34256
|
+
}
|
|
34257
|
+
}
|
|
34258
|
+
}
|
|
34259
|
+
const sinceMatch = lower.match(/\bsince\s+([\w:.\-+t /]+)/i);
|
|
34260
|
+
if (sinceMatch) {
|
|
34261
|
+
const slice = sinceMatch[1];
|
|
34262
|
+
if (slice !== void 0) {
|
|
34263
|
+
const start = parseInstant(slice, now);
|
|
34264
|
+
if (start) {
|
|
34265
|
+
return {
|
|
34266
|
+
range: { start, end: now },
|
|
34267
|
+
matchedSubstring: sinceMatch[0]
|
|
34268
|
+
};
|
|
34269
|
+
}
|
|
34270
|
+
}
|
|
34271
|
+
}
|
|
34272
|
+
if (/\byesterday\b/.test(lower)) {
|
|
34273
|
+
const startOfToday = startOfDay(now);
|
|
34274
|
+
const start = new Date(startOfToday.getTime() - MS_PER_DAY);
|
|
34275
|
+
const end = new Date(startOfToday.getTime() - 1);
|
|
34276
|
+
return {
|
|
34277
|
+
range: { start, end, relative_label: "yesterday" },
|
|
34278
|
+
matchedSubstring: "yesterday"
|
|
34279
|
+
};
|
|
34280
|
+
}
|
|
34281
|
+
if (/\btoday\b/.test(lower)) {
|
|
34282
|
+
return {
|
|
34283
|
+
range: {
|
|
34284
|
+
start: startOfDay(now),
|
|
34285
|
+
end: now,
|
|
34286
|
+
relative_label: "today"
|
|
34287
|
+
},
|
|
34288
|
+
matchedSubstring: "today"
|
|
34289
|
+
};
|
|
34290
|
+
}
|
|
34291
|
+
const compactHours = lower.match(/\blast\s+(\d+)\s*h\b/i);
|
|
34292
|
+
if (compactHours) {
|
|
34293
|
+
const tok = compactHours[1];
|
|
34294
|
+
if (tok !== void 0) {
|
|
34295
|
+
const n = Number.parseInt(tok, 10);
|
|
34296
|
+
if (Number.isFinite(n) && n > 0) {
|
|
34297
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34298
|
+
return {
|
|
34299
|
+
range: { start, end: now, relative_label: `last ${n}h` },
|
|
34300
|
+
matchedSubstring: compactHours[0]
|
|
34301
|
+
};
|
|
34302
|
+
}
|
|
34303
|
+
}
|
|
34304
|
+
}
|
|
34305
|
+
const hoursMatch = lower.match(
|
|
34306
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:hr\b|hrs\b|hour|hours)/i
|
|
34307
|
+
);
|
|
34308
|
+
if (hoursMatch) {
|
|
34309
|
+
const tok = hoursMatch[1];
|
|
34310
|
+
if (tok !== void 0) {
|
|
34311
|
+
const n = parseCount(tok);
|
|
34312
|
+
if (n !== null && n > 0) {
|
|
34313
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34314
|
+
return {
|
|
34315
|
+
range: { start, end: now, relative_label: `past ${n} hour${n === 1 ? "" : "s"}` },
|
|
34316
|
+
matchedSubstring: hoursMatch[0]
|
|
34317
|
+
};
|
|
34318
|
+
}
|
|
34319
|
+
}
|
|
34320
|
+
}
|
|
34321
|
+
if (/\b(?:past|last)\s+hour\b/.test(lower)) {
|
|
34322
|
+
const start = new Date(now.getTime() - MS_PER_HOUR);
|
|
34323
|
+
return {
|
|
34324
|
+
range: { start, end: now, relative_label: "past hour" },
|
|
34325
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+hour\b/i)[0]
|
|
34326
|
+
};
|
|
34327
|
+
}
|
|
34328
|
+
const daysMatch = lower.match(
|
|
34329
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:d\b|day|days)/i
|
|
34330
|
+
);
|
|
34331
|
+
if (daysMatch) {
|
|
34332
|
+
const tok = daysMatch[1];
|
|
34333
|
+
if (tok !== void 0) {
|
|
34334
|
+
const n = parseCount(tok);
|
|
34335
|
+
if (n !== null && n > 0) {
|
|
34336
|
+
const start = new Date(now.getTime() - n * MS_PER_DAY);
|
|
34337
|
+
return {
|
|
34338
|
+
range: { start, end: now, relative_label: `past ${n} day${n === 1 ? "" : "s"}` },
|
|
34339
|
+
matchedSubstring: daysMatch[0]
|
|
34340
|
+
};
|
|
34341
|
+
}
|
|
34342
|
+
}
|
|
34343
|
+
}
|
|
34344
|
+
if (/\b(?:past|last)\s+day\b/.test(lower)) {
|
|
34345
|
+
const start = new Date(now.getTime() - MS_PER_DAY);
|
|
34346
|
+
return {
|
|
34347
|
+
range: { start, end: now, relative_label: "past day" },
|
|
34348
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+day\b/i)[0]
|
|
34349
|
+
};
|
|
34350
|
+
}
|
|
34351
|
+
if (/\bthis\s+week\b/.test(lower)) {
|
|
34352
|
+
const start = startOfWeek(now);
|
|
34353
|
+
return {
|
|
34354
|
+
range: { start, end: now, relative_label: "this week" },
|
|
34355
|
+
matchedSubstring: lower.match(/\bthis\s+week\b/i)[0]
|
|
34356
|
+
};
|
|
34357
|
+
}
|
|
34358
|
+
if (/\b(?:past|last)\s+week\b/.test(lower)) {
|
|
34359
|
+
const start = new Date(now.getTime() - 7 * MS_PER_DAY);
|
|
34360
|
+
return {
|
|
34361
|
+
range: { start, end: now, relative_label: "past week" },
|
|
34362
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+week\b/i)[0]
|
|
34363
|
+
};
|
|
34364
|
+
}
|
|
34365
|
+
const isoMatch = normalized.match(
|
|
34366
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?)?)\b/
|
|
34367
|
+
);
|
|
34368
|
+
if (isoMatch) {
|
|
34369
|
+
const tok = isoMatch[1];
|
|
34370
|
+
if (tok !== void 0) {
|
|
34371
|
+
const parsed = parseInstant(tok, now);
|
|
34372
|
+
if (parsed) {
|
|
34373
|
+
const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(tok);
|
|
34374
|
+
if (isDateOnly) {
|
|
34375
|
+
return {
|
|
34376
|
+
range: {
|
|
34377
|
+
start: parsed,
|
|
34378
|
+
end: new Date(parsed.getTime() + MS_PER_DAY - 1)
|
|
34379
|
+
},
|
|
34380
|
+
matchedSubstring: tok
|
|
34381
|
+
};
|
|
34382
|
+
}
|
|
34383
|
+
return {
|
|
34384
|
+
range: {
|
|
34385
|
+
start: new Date(parsed.getTime() - 30 * 60 * 1e3),
|
|
34386
|
+
end: new Date(parsed.getTime() + 30 * 60 * 1e3)
|
|
34387
|
+
},
|
|
34388
|
+
matchedSubstring: tok
|
|
34389
|
+
};
|
|
34390
|
+
}
|
|
34391
|
+
}
|
|
34392
|
+
}
|
|
34393
|
+
return null;
|
|
34394
|
+
}
|
|
34395
|
+
function parseInstant(token, now) {
|
|
34396
|
+
const trimmed = token.trim().replace(/[,.!?;]+$/g, "");
|
|
34397
|
+
if (!trimmed) return null;
|
|
34398
|
+
const lower = trimmed.toLowerCase();
|
|
34399
|
+
if (lower === "now") return now;
|
|
34400
|
+
if (lower === "today") return startOfDay(now);
|
|
34401
|
+
if (lower === "yesterday") {
|
|
34402
|
+
return new Date(startOfDay(now).getTime() - MS_PER_DAY);
|
|
34403
|
+
}
|
|
34404
|
+
const isoLike = trimmed.replace(" ", "T");
|
|
34405
|
+
const parsed = new Date(isoLike);
|
|
34406
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
34407
|
+
return null;
|
|
34408
|
+
}
|
|
34409
|
+
function parseCount(token) {
|
|
34410
|
+
const lower = token.toLowerCase();
|
|
34411
|
+
if (/^\d+$/.test(lower)) {
|
|
34412
|
+
const n = Number.parseInt(lower, 10);
|
|
34413
|
+
return Number.isFinite(n) ? n : null;
|
|
34414
|
+
}
|
|
34415
|
+
return NUMBER_WORDS[lower] ?? null;
|
|
34416
|
+
}
|
|
34417
|
+
function startOfDay(d) {
|
|
34418
|
+
const out = new Date(d);
|
|
34419
|
+
out.setHours(0, 0, 0, 0);
|
|
34420
|
+
return out;
|
|
34421
|
+
}
|
|
34422
|
+
function startOfWeek(d) {
|
|
34423
|
+
const out = startOfDay(d);
|
|
34424
|
+
const dayOfWeek = out.getDay();
|
|
34425
|
+
const offsetToMonday = (dayOfWeek + 6) % 7;
|
|
34426
|
+
out.setDate(out.getDate() - offsetToMonday);
|
|
34427
|
+
return out;
|
|
34428
|
+
}
|
|
34429
|
+
function listFromRegistry(registry) {
|
|
34430
|
+
if (!registry) return [];
|
|
34431
|
+
if (Array.isArray(registry)) return registry;
|
|
34432
|
+
if (typeof registry.list === "function") {
|
|
34433
|
+
return registry.list();
|
|
34434
|
+
}
|
|
34435
|
+
return [];
|
|
34436
|
+
}
|
|
34437
|
+
function extractAgentNames(query, registry) {
|
|
34438
|
+
const records = listFromRegistry(registry);
|
|
34439
|
+
if (records.length === 0) return { matched: [], flagged: false };
|
|
34440
|
+
const lowerQuery = query.toLowerCase();
|
|
34441
|
+
const compactQuery = lowerQuery.replace(/[\s_-]+/g, "");
|
|
34442
|
+
const matched = [];
|
|
34443
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34444
|
+
for (const rec of records) {
|
|
34445
|
+
const id = rec.agent_id;
|
|
34446
|
+
if (!id || seen.has(id)) continue;
|
|
34447
|
+
const idLower = id.toLowerCase();
|
|
34448
|
+
if (idLower.length < 3) continue;
|
|
34449
|
+
const idCompact = idLower.replace(/[\s_-]+/g, "");
|
|
34450
|
+
const wordRe = new RegExp(
|
|
34451
|
+
`\\b${idLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
|
|
34452
|
+
"i"
|
|
34453
|
+
);
|
|
34454
|
+
if (wordRe.test(query)) {
|
|
34455
|
+
matched.push(id);
|
|
34456
|
+
seen.add(id);
|
|
34457
|
+
continue;
|
|
34458
|
+
}
|
|
34459
|
+
if (idCompact.length >= 4 && compactQuery.includes(idCompact)) {
|
|
34460
|
+
matched.push(id);
|
|
34461
|
+
seen.add(id);
|
|
34462
|
+
}
|
|
34463
|
+
}
|
|
34464
|
+
const agentMention = lowerQuery.match(/\bagent\s+([a-z0-9_-]{3,40})/i);
|
|
34465
|
+
const flagged = matched.length === 0 && agentMention !== null && agentMention[1] !== void 0 && !records.some((r) => r.agent_id.toLowerCase() === agentMention[1]?.toLowerCase());
|
|
34466
|
+
return { matched, flagged };
|
|
34467
|
+
}
|
|
34468
|
+
function escapeRegex(s) {
|
|
34469
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34470
|
+
}
|
|
34471
|
+
function extractEventTypes(query, enumValues) {
|
|
34472
|
+
const lower = query.toLowerCase();
|
|
34473
|
+
const matched = [];
|
|
34474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34475
|
+
for (const ev of enumValues) {
|
|
34476
|
+
if (seen.has(ev)) continue;
|
|
34477
|
+
const re = new RegExp(`\\b${escapeRegex(ev)}\\b`, "i");
|
|
34478
|
+
if (re.test(query)) {
|
|
34479
|
+
matched.push(ev);
|
|
34480
|
+
seen.add(ev);
|
|
34481
|
+
}
|
|
34482
|
+
}
|
|
34483
|
+
for (const syn of EVENT_SYNONYMS) {
|
|
34484
|
+
const re = new RegExp(
|
|
34485
|
+
`\\b${syn.phrase.split(/\s+/).map(escapeRegex).join("\\s+")}\\b`,
|
|
34486
|
+
"i"
|
|
34487
|
+
);
|
|
34488
|
+
if (re.test(query)) {
|
|
34489
|
+
for (const c of syn.canonical) {
|
|
34490
|
+
if (seen.has(c)) continue;
|
|
34491
|
+
if (!enumValues.includes(c)) continue;
|
|
34492
|
+
matched.push(c);
|
|
34493
|
+
seen.add(c);
|
|
34494
|
+
}
|
|
34495
|
+
}
|
|
34496
|
+
}
|
|
34497
|
+
const globMatches = lower.match(/\b([a-z_]+)_\*/g) ?? [];
|
|
34498
|
+
for (const glob of globMatches) {
|
|
34499
|
+
const prefix = glob.slice(0, -2);
|
|
34500
|
+
for (const ev of enumValues) {
|
|
34501
|
+
if (seen.has(ev)) continue;
|
|
34502
|
+
if (ev.startsWith(prefix)) {
|
|
34503
|
+
matched.push(ev);
|
|
34504
|
+
seen.add(ev);
|
|
34505
|
+
}
|
|
34506
|
+
}
|
|
34507
|
+
}
|
|
34508
|
+
const eventNounMention = /\b(?:event|events|class|classes)\b/i.test(query) && matched.length === 0;
|
|
34509
|
+
return { matched, flagged: eventNounMention };
|
|
34510
|
+
}
|
|
34511
|
+
function deriveIntentPhrase(query, stripTokens) {
|
|
34512
|
+
let out = query;
|
|
34513
|
+
for (const tok of stripTokens) {
|
|
34514
|
+
if (!tok) continue;
|
|
34515
|
+
const re = new RegExp(escapeRegex(tok), "gi");
|
|
34516
|
+
out = out.replace(re, " ");
|
|
34517
|
+
}
|
|
34518
|
+
return out.replace(/\s+/g, " ").trim();
|
|
34519
|
+
}
|
|
34520
|
+
function computeConfidence(parsed) {
|
|
34521
|
+
const dims = [
|
|
34522
|
+
{ present: parsed.hasTimeMention, resolved: parsed.timeResolved },
|
|
34523
|
+
{ present: parsed.hasAgentMention, resolved: parsed.agentResolved },
|
|
34524
|
+
{ present: parsed.hasEventMention, resolved: parsed.eventResolved }
|
|
34525
|
+
];
|
|
34526
|
+
const present = dims.filter((d) => d.present);
|
|
34527
|
+
let base;
|
|
34528
|
+
if (present.length === 0) {
|
|
34529
|
+
base = parsed.intentEmpty ? 0 : 0.3;
|
|
34530
|
+
} else {
|
|
34531
|
+
const resolved = present.filter((d) => d.resolved).length;
|
|
34532
|
+
base = resolved / present.length;
|
|
34533
|
+
}
|
|
34534
|
+
const adjusted = base - 0.15 * parsed.ambiguityCount;
|
|
34535
|
+
if (adjusted < 0) return 0;
|
|
34536
|
+
if (adjusted > 1) return 1;
|
|
34537
|
+
return adjusted;
|
|
34538
|
+
}
|
|
34539
|
+
function parseQuery(query, opts) {
|
|
34540
|
+
const now = opts?.now ?? /* @__PURE__ */ new Date();
|
|
34541
|
+
const enumValues = opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES;
|
|
34542
|
+
const original = query ?? "";
|
|
34543
|
+
const trimmed = original.trim();
|
|
34544
|
+
if (trimmed.length === 0) {
|
|
34545
|
+
return {
|
|
34546
|
+
time_range: null,
|
|
34547
|
+
agent_names: [],
|
|
34548
|
+
event_types: [],
|
|
34549
|
+
intent_phrase: "",
|
|
34550
|
+
ambiguity_flags: ["no_signal_extracted"],
|
|
34551
|
+
parse_confidence: 0
|
|
34552
|
+
};
|
|
34553
|
+
}
|
|
34554
|
+
const ambiguity_flags = /* @__PURE__ */ new Set();
|
|
34555
|
+
const timeMatch = resolveTimeRange(trimmed, now);
|
|
34556
|
+
const hasTimeMention = TIME_MENTION_PROBE.test(trimmed);
|
|
34557
|
+
if (hasTimeMention && !timeMatch) {
|
|
34558
|
+
ambiguity_flags.add("unknown_time_token");
|
|
34559
|
+
}
|
|
34560
|
+
const agentResult = extractAgentNames(trimmed, opts?.registry);
|
|
34561
|
+
if (agentResult.flagged) {
|
|
34562
|
+
ambiguity_flags.add("unknown_agent_token");
|
|
34563
|
+
}
|
|
34564
|
+
const hasAgentMention = AGENT_MENTION_PROBE.test(trimmed);
|
|
34565
|
+
const eventResult = extractEventTypes(trimmed, enumValues);
|
|
34566
|
+
const hasEventMention = EVENT_MENTION_PROBE.test(trimmed);
|
|
34567
|
+
if (eventResult.flagged) {
|
|
34568
|
+
ambiguity_flags.add("unknown_event_token");
|
|
34569
|
+
}
|
|
34570
|
+
const stripTokens = [];
|
|
34571
|
+
if (timeMatch) stripTokens.push(timeMatch.matchedSubstring);
|
|
34572
|
+
for (const name of agentResult.matched) stripTokens.push(name);
|
|
34573
|
+
for (const ev of eventResult.matched) {
|
|
34574
|
+
if (trimmed.toLowerCase().includes(ev.toLowerCase())) {
|
|
34575
|
+
stripTokens.push(ev);
|
|
34576
|
+
}
|
|
34577
|
+
}
|
|
34578
|
+
const intent_phrase = deriveIntentPhrase(trimmed, stripTokens);
|
|
34579
|
+
const parse_confidence = computeConfidence({
|
|
34580
|
+
hasTimeMention,
|
|
34581
|
+
timeResolved: timeMatch !== null,
|
|
34582
|
+
hasAgentMention,
|
|
34583
|
+
agentResolved: agentResult.matched.length > 0,
|
|
34584
|
+
hasEventMention,
|
|
34585
|
+
eventResolved: eventResult.matched.length > 0,
|
|
34586
|
+
intentEmpty: intent_phrase.length === 0,
|
|
34587
|
+
ambiguityCount: ambiguity_flags.size
|
|
34588
|
+
});
|
|
34589
|
+
if (timeMatch === null && agentResult.matched.length === 0 && eventResult.matched.length === 0 && intent_phrase.length === 0) {
|
|
34590
|
+
ambiguity_flags.add("no_signal_extracted");
|
|
34591
|
+
}
|
|
34592
|
+
return {
|
|
34593
|
+
time_range: timeMatch ? timeMatch.range : null,
|
|
34594
|
+
agent_names: agentResult.matched,
|
|
34595
|
+
event_types: eventResult.matched,
|
|
34596
|
+
intent_phrase,
|
|
34597
|
+
ambiguity_flags: Array.from(ambiguity_flags),
|
|
34598
|
+
parse_confidence
|
|
34599
|
+
};
|
|
34600
|
+
}
|
|
34601
|
+
function isLowConfidence(parsed) {
|
|
34602
|
+
return parsed.parse_confidence < LLM_ASSIST_THRESHOLD;
|
|
34603
|
+
}
|
|
34604
|
+
async function parseQueryWithLlmAssist(query, llmAssist, opts) {
|
|
34605
|
+
const parsed = parseQuery(query, opts);
|
|
34606
|
+
if (!llmAssist || !isLowConfidence(parsed)) return parsed;
|
|
34607
|
+
let completion;
|
|
34608
|
+
try {
|
|
34609
|
+
completion = await llmAssist(query, parsed);
|
|
34610
|
+
} catch {
|
|
34611
|
+
return parsed;
|
|
34612
|
+
}
|
|
34613
|
+
if (!completion || typeof completion !== "object") return parsed;
|
|
34614
|
+
const merged = { ...parsed };
|
|
34615
|
+
if (parsed.time_range === null && completion.time_range) {
|
|
34616
|
+
merged.time_range = completion.time_range;
|
|
34617
|
+
}
|
|
34618
|
+
if (parsed.agent_names.length === 0 && Array.isArray(completion.agent_names)) {
|
|
34619
|
+
merged.agent_names = completion.agent_names.filter(
|
|
34620
|
+
(s) => typeof s === "string" && s.length > 0
|
|
34621
|
+
);
|
|
34622
|
+
}
|
|
34623
|
+
if (parsed.event_types.length === 0 && Array.isArray(completion.event_types)) {
|
|
34624
|
+
const allowed = new Set(opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES);
|
|
34625
|
+
merged.event_types = completion.event_types.filter(
|
|
34626
|
+
(s) => typeof s === "string" && allowed.has(s)
|
|
34627
|
+
);
|
|
34628
|
+
}
|
|
34629
|
+
merged.parse_confidence = Math.max(
|
|
34630
|
+
parsed.parse_confidence,
|
|
34631
|
+
computeConfidence({
|
|
34632
|
+
hasTimeMention: TIME_MENTION_PROBE.test(query),
|
|
34633
|
+
timeResolved: merged.time_range !== null,
|
|
34634
|
+
hasAgentMention: AGENT_MENTION_PROBE.test(query),
|
|
34635
|
+
agentResolved: merged.agent_names.length > 0,
|
|
34636
|
+
hasEventMention: EVENT_MENTION_PROBE.test(query),
|
|
34637
|
+
eventResolved: merged.event_types.length > 0,
|
|
34638
|
+
intentEmpty: merged.intent_phrase.length === 0,
|
|
34639
|
+
ambiguityCount: merged.ambiguity_flags.length
|
|
34640
|
+
})
|
|
34641
|
+
);
|
|
34642
|
+
return merged;
|
|
34643
|
+
}
|
|
34644
|
+
function auditSafeSummary(parsed) {
|
|
34645
|
+
return {
|
|
34646
|
+
time_range: parsed.time_range ? {
|
|
34647
|
+
start_iso: parsed.time_range.start.toISOString(),
|
|
34648
|
+
end_iso: parsed.time_range.end.toISOString(),
|
|
34649
|
+
...parsed.time_range.relative_label !== void 0 ? { relative_label: parsed.time_range.relative_label } : {}
|
|
34650
|
+
} : null,
|
|
34651
|
+
agent_names: [...parsed.agent_names],
|
|
34652
|
+
event_types: [...parsed.event_types],
|
|
34653
|
+
ambiguity_flags: [...parsed.ambiguity_flags],
|
|
34654
|
+
parse_confidence: parsed.parse_confidence
|
|
34655
|
+
};
|
|
34656
|
+
}
|
|
34657
|
+
var CANONICAL_AUDIT_EVENT_CLASSES, EVENT_SYNONYMS, MS_PER_HOUR, MS_PER_DAY, NUMBER_WORDS, TIME_MENTION_PROBE, AGENT_MENTION_PROBE, EVENT_MENTION_PROBE, LLM_ASSIST_THRESHOLD;
|
|
34658
|
+
var init_concierge_query_grammar = __esm({
|
|
34659
|
+
"src/chat/concierge-query-grammar.ts"() {
|
|
34660
|
+
init_constants4();
|
|
34661
|
+
init_operator_chat_audit_events();
|
|
34662
|
+
CANONICAL_AUDIT_EVENT_CLASSES = [
|
|
34663
|
+
// Lifecycle / policy
|
|
34664
|
+
"policy_change",
|
|
34665
|
+
"approval_request",
|
|
34666
|
+
"audit_truncate",
|
|
34667
|
+
"lockdown",
|
|
34668
|
+
"unwrap",
|
|
34669
|
+
// Exit bundle (Tier 1)
|
|
34670
|
+
"exit_bundle_export",
|
|
34671
|
+
"exit_bundle_import_activate",
|
|
34672
|
+
"exit_bundle_rekey",
|
|
34673
|
+
// Cross-harness approval aggregator
|
|
34674
|
+
"cross_harness_approval_aggregated",
|
|
34675
|
+
"cross_harness_approval_resolved",
|
|
34676
|
+
"cross_harness_approval_deduped",
|
|
34677
|
+
"cross_harness_approval_payload_decrypted",
|
|
34678
|
+
"cross_harness_approval_audit_trail_viewed",
|
|
34679
|
+
"cross_harness_approval_replayed",
|
|
34680
|
+
// Composition (full set from constants.ts)
|
|
34681
|
+
...COMPOSITION_EVENT_TYPES,
|
|
34682
|
+
// Operator chat / concierge (full set from OPERATOR_CHAT_OPS)
|
|
34683
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CHAT,
|
|
34684
|
+
OPERATOR_CHAT_OPS.AGENT_INSPECT_PANEL_OPENED,
|
|
34685
|
+
OPERATOR_CHAT_OPS.CONCIERGE_HISTORY_READ,
|
|
34686
|
+
OPERATOR_CHAT_OPS.CONCIERGE_THREAD_DELETED,
|
|
34687
|
+
OPERATOR_CHAT_OPS.CONCIERGE_MEMORY_READ_FAILED,
|
|
34688
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
34689
|
+
// Bridge / commitment
|
|
34690
|
+
"bridge_commit",
|
|
34691
|
+
"bridge_verify",
|
|
34692
|
+
"bridge_attest",
|
|
34693
|
+
"proof_commitment",
|
|
34694
|
+
"proof_reveal",
|
|
34695
|
+
// Reputation
|
|
34696
|
+
"reputation_export",
|
|
34697
|
+
"reputation_import",
|
|
34698
|
+
"reputation_publish",
|
|
34699
|
+
"reputation_record",
|
|
34700
|
+
"reputation_query"
|
|
34701
|
+
];
|
|
34702
|
+
EVENT_SYNONYMS = [
|
|
34703
|
+
{ phrase: "approvals", canonical: ["approval_request", "cross_harness_approval_aggregated", "cross_harness_approval_resolved"] },
|
|
34704
|
+
{ phrase: "approval", canonical: ["approval_request"] },
|
|
34705
|
+
{ phrase: "policy changes", canonical: ["policy_change"] },
|
|
34706
|
+
{ phrase: "policy change", canonical: ["policy_change"] },
|
|
34707
|
+
{ phrase: "policy edits", canonical: ["policy_change"] },
|
|
34708
|
+
{ phrase: "lockdowns", canonical: ["lockdown"] },
|
|
34709
|
+
{ phrase: "exit bundles", canonical: ["exit_bundle_export", "exit_bundle_import_activate"] },
|
|
34710
|
+
{ phrase: "exit bundle", canonical: ["exit_bundle_export"] },
|
|
34711
|
+
{ phrase: "audit truncations", canonical: ["audit_truncate"] },
|
|
34712
|
+
{ phrase: "audit truncation", canonical: ["audit_truncate"] },
|
|
34713
|
+
{ phrase: "compositions", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34714
|
+
{ phrase: "receipts", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34715
|
+
{ phrase: "receipt verifications", canonical: ["composition_receipt_verified"] },
|
|
34716
|
+
{ phrase: "concierge chats", canonical: [OPERATOR_CHAT_OPS.CONCIERGE_CHAT] },
|
|
34717
|
+
{ phrase: "cross harness approvals", canonical: ["cross_harness_approval_aggregated", "cross_harness_approval_resolved"] }
|
|
34718
|
+
];
|
|
34719
|
+
MS_PER_HOUR = 60 * 60 * 1e3;
|
|
34720
|
+
MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
34721
|
+
NUMBER_WORDS = {
|
|
34722
|
+
a: 1,
|
|
34723
|
+
an: 1,
|
|
34724
|
+
one: 1,
|
|
34725
|
+
two: 2,
|
|
34726
|
+
three: 3,
|
|
34727
|
+
four: 4,
|
|
34728
|
+
five: 5,
|
|
34729
|
+
six: 6,
|
|
34730
|
+
seven: 7,
|
|
34731
|
+
eight: 8,
|
|
34732
|
+
nine: 9,
|
|
34733
|
+
ten: 10,
|
|
34734
|
+
twelve: 12,
|
|
34735
|
+
twentyfour: 24
|
|
34736
|
+
};
|
|
34737
|
+
TIME_MENTION_PROBE = /\b(yesterday|today|now|past|last|this\s+week|this\s+month|since|from|between|\d{4}-\d{2}-\d{2})\b/i;
|
|
34738
|
+
AGENT_MENTION_PROBE = /\bagent[s]?\b/i;
|
|
34739
|
+
EVENT_MENTION_PROBE = /\b(event|events|class|classes|approvals?|policy)\b/i;
|
|
34740
|
+
LLM_ASSIST_THRESHOLD = 0.5;
|
|
34741
|
+
}
|
|
34742
|
+
});
|
|
34040
34743
|
function approxTokenLen2(text) {
|
|
34041
34744
|
return Math.ceil(text.length / 4);
|
|
34042
34745
|
}
|
|
@@ -34069,6 +34772,7 @@ var init_operator_chat_service = __esm({
|
|
|
34069
34772
|
init_operator_chat_audit_events();
|
|
34070
34773
|
init_operator_chat_types();
|
|
34071
34774
|
init_concierge_context_router();
|
|
34775
|
+
init_concierge_query_grammar();
|
|
34072
34776
|
DEFAULT_CONCIERGE_MAX_TOKENS = 512;
|
|
34073
34777
|
DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS = 10;
|
|
34074
34778
|
DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -34119,6 +34823,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34119
34823
|
contextFetchers;
|
|
34120
34824
|
contextLlmAssist;
|
|
34121
34825
|
dynamicContextBudget;
|
|
34826
|
+
agentRegistry;
|
|
34827
|
+
grammarLlmAssist;
|
|
34122
34828
|
/**
|
|
34123
34829
|
* In-memory thread_id assigned to the active concierge session.
|
|
34124
34830
|
* The first sendConcierge call after construction allocates a fresh
|
|
@@ -34157,6 +34863,12 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34157
34863
|
this.contextLlmAssist = deps.conciergeContextLlmAssist;
|
|
34158
34864
|
}
|
|
34159
34865
|
this.dynamicContextBudget = deps.conciergeDynamicContextBudget !== void 0 && deps.conciergeDynamicContextBudget > 0 ? deps.conciergeDynamicContextBudget : DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET;
|
|
34866
|
+
if (deps.conciergeAgentRegistry) {
|
|
34867
|
+
this.agentRegistry = deps.conciergeAgentRegistry;
|
|
34868
|
+
}
|
|
34869
|
+
if (deps.conciergeGrammarLlmAssist) {
|
|
34870
|
+
this.grammarLlmAssist = deps.conciergeGrammarLlmAssist;
|
|
34871
|
+
}
|
|
34160
34872
|
}
|
|
34161
34873
|
// ── Concierge ─────────────────────────────────────────────────────────
|
|
34162
34874
|
/**
|
|
@@ -34215,6 +34927,7 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34215
34927
|
await this.memory.appendTurn(threadId, "user", trimmed).catch(() => {
|
|
34216
34928
|
});
|
|
34217
34929
|
}
|
|
34930
|
+
const parsedGrammar = await this.runGrammarParse(filterResult.filtered);
|
|
34218
34931
|
const start = Date.now();
|
|
34219
34932
|
let conciergeBody;
|
|
34220
34933
|
let servedBy = "disabled";
|
|
@@ -34233,7 +34946,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34233
34946
|
outcome = "substrate_disabled";
|
|
34234
34947
|
} else {
|
|
34235
34948
|
const dynamicResult = await this.runDynamicContextFold(
|
|
34236
|
-
filterResult.filtered
|
|
34949
|
+
filterResult.filtered,
|
|
34950
|
+
parsedGrammar
|
|
34237
34951
|
);
|
|
34238
34952
|
dynamicCategoriesIncluded = dynamicResult.categoriesIncluded;
|
|
34239
34953
|
const context = await this.assembleConciergeContext(
|
|
@@ -34304,7 +35018,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34304
35018
|
...this.memory ? {
|
|
34305
35019
|
prior_turns_folded: memoryReadFailureReason === null ? priorTurns.length : 0
|
|
34306
35020
|
} : {},
|
|
34307
|
-
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {}
|
|
35021
|
+
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {},
|
|
35022
|
+
parsed_grammar: auditSafeSummary(parsedGrammar)
|
|
34308
35023
|
};
|
|
34309
35024
|
this.emit(OPERATOR_CHAT_OPS.CONCIERGE_CHAT, payload, outcome === "ok" ? "success" : "failure");
|
|
34310
35025
|
return {
|
|
@@ -34519,8 +35234,12 @@ ${inbox}`
|
|
|
34519
35234
|
* proceeds with no fold. Returns the rendered section + the list of
|
|
34520
35235
|
* categories whose data made it into the section (used for the
|
|
34521
35236
|
* round-trip audit emission).
|
|
35237
|
+
*
|
|
35238
|
+
* Tau-4: receives the pre-parsed `ParsedQuery` and forwards it as the
|
|
35239
|
+
* `parsed` opt to `foldContext`, so fetchers see the structured
|
|
35240
|
+
* `FetcherHints` derived from it.
|
|
34522
35241
|
*/
|
|
34523
|
-
async runDynamicContextFold(query) {
|
|
35242
|
+
async runDynamicContextFold(query, parsedGrammar) {
|
|
34524
35243
|
if (!this.contextFetchers) {
|
|
34525
35244
|
return { section: "", categoriesIncluded: [] };
|
|
34526
35245
|
}
|
|
@@ -34529,10 +35248,24 @@ ${inbox}`
|
|
|
34529
35248
|
...this.contextLlmAssist ? { llmAssistClassify: this.contextLlmAssist } : {},
|
|
34530
35249
|
onFetcherFailure: (category, error) => {
|
|
34531
35250
|
this.emitContextFetcherFailed(category, classifyFetcherError(error));
|
|
34532
|
-
}
|
|
35251
|
+
},
|
|
35252
|
+
parsed: parsedGrammar
|
|
34533
35253
|
});
|
|
34534
35254
|
return result;
|
|
34535
35255
|
}
|
|
35256
|
+
/**
|
|
35257
|
+
* WP-V1.3-9 Tau-4: parse the (PII-filtered) operator query into a
|
|
35258
|
+
* `ParsedQuery`. Routes through the LLM-assist completion hook when
|
|
35259
|
+
* configured and the rule-based parse is below
|
|
35260
|
+
* `LLM_ASSIST_THRESHOLD`. Always returns a parse object (never
|
|
35261
|
+
* throws) so the audit emission can carry the result unconditionally.
|
|
35262
|
+
*/
|
|
35263
|
+
async runGrammarParse(query) {
|
|
35264
|
+
return parseQueryWithLlmAssist(query, this.grammarLlmAssist, {
|
|
35265
|
+
...this.agentRegistry !== void 0 ? { registry: this.agentRegistry } : {},
|
|
35266
|
+
eventClassEnum: CANONICAL_AUDIT_EVENT_CLASSES
|
|
35267
|
+
});
|
|
35268
|
+
}
|
|
34536
35269
|
/**
|
|
34537
35270
|
* Emit the WP-V1.3-9 Tau-3 fetcher-failure audit event. Pulled out
|
|
34538
35271
|
* of the fold path so the dynamic-context handler stays readable.
|
|
@@ -37044,7 +37777,7 @@ var init_memory = __esm({
|
|
|
37044
37777
|
|
|
37045
37778
|
// src/contracts/v1.1/constants.ts
|
|
37046
37779
|
var SIGNATURE_SCHEME_V12, EXIT_BUNDLE_MANIFEST_VERSION, EXIT_BUNDLE_ARTIFACT_KINDS;
|
|
37047
|
-
var
|
|
37780
|
+
var init_constants5 = __esm({
|
|
37048
37781
|
"src/contracts/v1.1/constants.ts"() {
|
|
37049
37782
|
SIGNATURE_SCHEME_V12 = "ed25519-v1";
|
|
37050
37783
|
EXIT_BUNDLE_MANIFEST_VERSION = "SANCTUARY_EXIT_BUNDLE_V1";
|
|
@@ -37462,7 +38195,7 @@ async function verifyExitBundle(bundleDir, options = {}) {
|
|
|
37462
38195
|
var InvalidExitBundleError, PRIVATE_MATERIAL_KEYS;
|
|
37463
38196
|
var init_verifier2 = __esm({
|
|
37464
38197
|
"src/exit/verifier.ts"() {
|
|
37465
|
-
|
|
38198
|
+
init_constants5();
|
|
37466
38199
|
init_exit_bundle_manifest();
|
|
37467
38200
|
init_encoding();
|
|
37468
38201
|
init_hashing();
|
|
@@ -38274,7 +39007,7 @@ var init_bundle = __esm({
|
|
|
38274
39007
|
"src/exit/bundle.ts"() {
|
|
38275
39008
|
init_state_store();
|
|
38276
39009
|
init_config();
|
|
38277
|
-
|
|
39010
|
+
init_constants5();
|
|
38278
39011
|
init_canonical_json();
|
|
38279
39012
|
init_hashing();
|
|
38280
39013
|
init_encoding();
|