@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.cjs
CHANGED
|
@@ -5044,7 +5044,8 @@ var init_constants = __esm({
|
|
|
5044
5044
|
RESERVED_EVENT_TYPE_PREFIXES = [
|
|
5045
5045
|
"EXTENSION_",
|
|
5046
5046
|
"cross_fortress_",
|
|
5047
|
-
"multi_master_"
|
|
5047
|
+
"multi_master_",
|
|
5048
|
+
"cross_harness_approval_"
|
|
5048
5049
|
];
|
|
5049
5050
|
RESERVED_EXTENSION_ENVELOPE_KEYS = [
|
|
5050
5051
|
"cross_fortress_read_grant",
|
|
@@ -9236,9 +9237,9 @@ function fingerprintDID(did) {
|
|
|
9236
9237
|
return `${raw.slice(0, 6)}\u2026${raw.slice(-6)}`;
|
|
9237
9238
|
}
|
|
9238
9239
|
function countInjectionsToday(audit) {
|
|
9239
|
-
const
|
|
9240
|
-
|
|
9241
|
-
const cutoff =
|
|
9240
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9241
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9242
|
+
const cutoff = startOfDay2.getTime();
|
|
9242
9243
|
return audit.filter((e) => {
|
|
9243
9244
|
const ts = new Date(e.timestamp).getTime();
|
|
9244
9245
|
if (isNaN(ts) || ts < cutoff) return false;
|
|
@@ -9247,9 +9248,9 @@ function countInjectionsToday(audit) {
|
|
|
9247
9248
|
}).length;
|
|
9248
9249
|
}
|
|
9249
9250
|
function countProofsToday(audit) {
|
|
9250
|
-
const
|
|
9251
|
-
|
|
9252
|
-
const cutoff =
|
|
9251
|
+
const startOfDay2 = /* @__PURE__ */ new Date();
|
|
9252
|
+
startOfDay2.setHours(0, 0, 0, 0);
|
|
9253
|
+
const cutoff = startOfDay2.getTime();
|
|
9253
9254
|
return audit.filter((e) => {
|
|
9254
9255
|
if (e.layer !== "l3") return false;
|
|
9255
9256
|
if (!PROOF_CREATION_OPS.has(e.operation)) return false;
|
|
@@ -17218,6 +17219,24 @@ async function handleApprovalInboxRoute(deps, req, res) {
|
|
|
17218
17219
|
await handleStream2(deps, res);
|
|
17219
17220
|
return true;
|
|
17220
17221
|
}
|
|
17222
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/revision`) {
|
|
17223
|
+
const revision = await deps.aggregator.getRevision();
|
|
17224
|
+
writeJSON4(res, 200, { ok: true, data: { revision } });
|
|
17225
|
+
return true;
|
|
17226
|
+
}
|
|
17227
|
+
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/sync`) {
|
|
17228
|
+
const sinceRaw = url.searchParams.get("since_revision");
|
|
17229
|
+
const sinceParsed = sinceRaw === null ? 0 : Number.parseInt(sinceRaw, 10);
|
|
17230
|
+
const sinceRevision = Number.isFinite(sinceParsed) && sinceParsed >= 0 ? sinceParsed : 0;
|
|
17231
|
+
const limit = parseLimit2(
|
|
17232
|
+
url.searchParams.get("limit"),
|
|
17233
|
+
APPROVAL_INBOX_DEFAULT_LIMIT,
|
|
17234
|
+
APPROVAL_INBOX_MAX_LIMIT
|
|
17235
|
+
);
|
|
17236
|
+
const delta = await deps.aggregator.getSync({ sinceRevision, limit });
|
|
17237
|
+
writeJSON4(res, 200, { ok: true, data: delta });
|
|
17238
|
+
return true;
|
|
17239
|
+
}
|
|
17221
17240
|
if (method === "GET" && path === `${APPROVAL_INBOX_API_PREFIX}/history`) {
|
|
17222
17241
|
const limit = parseLimit2(
|
|
17223
17242
|
url.searchParams.get("limit"),
|
|
@@ -20360,6 +20379,20 @@ var init_approval_aggregator = __esm({
|
|
|
20360
20379
|
hydrated = false;
|
|
20361
20380
|
/** Active SSE listeners. */
|
|
20362
20381
|
listeners = /* @__PURE__ */ new Set();
|
|
20382
|
+
/**
|
|
20383
|
+
* Monotonic revision counter, bumped on every mutation (ingest of new
|
|
20384
|
+
* entry, resolve, expire, delete). Hydrated from max(last_modified_revision)
|
|
20385
|
+
* across persisted entries on first read; in-memory after that. v1.3
|
|
20386
|
+
* Upsilon-4.
|
|
20387
|
+
*/
|
|
20388
|
+
currentRevision = 0;
|
|
20389
|
+
/**
|
|
20390
|
+
* Removal tombstones: aggregator_id -> revision at removal. Used by the
|
|
20391
|
+
* sync API to surface "removed" entries to mobile consumers between
|
|
20392
|
+
* polls. In-memory only; server restart clears tombstones (mobile
|
|
20393
|
+
* bootstraps via `list()` on reconnect). v1.3 Upsilon-4.
|
|
20394
|
+
*/
|
|
20395
|
+
removedTombstones = /* @__PURE__ */ new Map();
|
|
20363
20396
|
constructor(deps) {
|
|
20364
20397
|
this.storage = deps.storage;
|
|
20365
20398
|
this.encryptionKey = derivePurposeKey(
|
|
@@ -20394,6 +20427,113 @@ var init_approval_aggregator = __esm({
|
|
|
20394
20427
|
this.listeners.add(listener);
|
|
20395
20428
|
return () => this.listeners.delete(listener);
|
|
20396
20429
|
}
|
|
20430
|
+
/**
|
|
20431
|
+
* Current aggregator revision. v1.3 Upsilon-4. Mobile companions
|
|
20432
|
+
* poll the lightweight `/revision` route to detect that something
|
|
20433
|
+
* changed before fetching a full sync delta.
|
|
20434
|
+
*/
|
|
20435
|
+
async getRevision() {
|
|
20436
|
+
await this.hydrate();
|
|
20437
|
+
return this.currentRevision;
|
|
20438
|
+
}
|
|
20439
|
+
/**
|
|
20440
|
+
* Compute a delta since `sinceRevision`. v1.3 Upsilon-4. Mobile
|
|
20441
|
+
* clients poll this for cheap state-sync. Behavior:
|
|
20442
|
+
* - `added`: entries whose `created_at_revision > sinceRevision`.
|
|
20443
|
+
* - `changed`: entries that existed at `sinceRevision` but had a
|
|
20444
|
+
* status transition (resolve, expire) since.
|
|
20445
|
+
* - `removed`: aggregator_ids deleted after `sinceRevision`.
|
|
20446
|
+
* - `revision`: current aggregator revision; pass this back as
|
|
20447
|
+
* `sinceRevision` on the next call.
|
|
20448
|
+
*
|
|
20449
|
+
* `limit` caps the total count returned across all three lists,
|
|
20450
|
+
* prioritized as added -> changed -> removed (newer-state first).
|
|
20451
|
+
* When more changes exist than fit, the next call with the returned
|
|
20452
|
+
* revision will pick up the rest because each entry's
|
|
20453
|
+
* last_modified_revision is unchanged by truncation.
|
|
20454
|
+
*/
|
|
20455
|
+
async getSync(opts) {
|
|
20456
|
+
await this.hydrate();
|
|
20457
|
+
await this.expireStale();
|
|
20458
|
+
const sinceRevision = opts?.sinceRevision ?? 0;
|
|
20459
|
+
const cap = Math.min(
|
|
20460
|
+
opts?.limit ?? DEFAULT_LIST_PAGE_SIZE,
|
|
20461
|
+
this.maxListLimit
|
|
20462
|
+
);
|
|
20463
|
+
const added = [];
|
|
20464
|
+
const changed = [];
|
|
20465
|
+
for (const entry of this.entries.values()) {
|
|
20466
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20467
|
+
if (lastMod <= sinceRevision) continue;
|
|
20468
|
+
const createdRev = entry.created_at_revision ?? 0;
|
|
20469
|
+
if (createdRev > sinceRevision) {
|
|
20470
|
+
added.push(entry);
|
|
20471
|
+
} else {
|
|
20472
|
+
changed.push(entry);
|
|
20473
|
+
}
|
|
20474
|
+
}
|
|
20475
|
+
const removed = [];
|
|
20476
|
+
for (const [id, rev] of this.removedTombstones) {
|
|
20477
|
+
if (rev > sinceRevision) removed.push(id);
|
|
20478
|
+
}
|
|
20479
|
+
added.sort(
|
|
20480
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20481
|
+
);
|
|
20482
|
+
changed.sort(
|
|
20483
|
+
(a, b) => (a.last_modified_revision ?? 0) - (b.last_modified_revision ?? 0)
|
|
20484
|
+
);
|
|
20485
|
+
let remaining = cap;
|
|
20486
|
+
const addedOut = added.slice(0, Math.max(0, remaining));
|
|
20487
|
+
remaining -= addedOut.length;
|
|
20488
|
+
const changedOut = changed.slice(0, Math.max(0, remaining));
|
|
20489
|
+
remaining -= changedOut.length;
|
|
20490
|
+
const removedOut = removed.slice(0, Math.max(0, remaining));
|
|
20491
|
+
return {
|
|
20492
|
+
revision: this.currentRevision,
|
|
20493
|
+
added: addedOut,
|
|
20494
|
+
changed: changedOut,
|
|
20495
|
+
removed: removedOut
|
|
20496
|
+
};
|
|
20497
|
+
}
|
|
20498
|
+
/**
|
|
20499
|
+
* Delete an entry. Drops the in-memory record, the persisted bundle,
|
|
20500
|
+
* and the at-rest payload (if a payload store is wired). Records a
|
|
20501
|
+
* tombstone with the new revision so sync-API consumers see a
|
|
20502
|
+
* `removed` delta. Returns true when an entry was deleted, false on
|
|
20503
|
+
* unknown id. v1.3 Upsilon-4. Reserved for v1.4+ retention housekeeping;
|
|
20504
|
+
* Upsilon-4 ships the surface so mobile sync-API tests can exercise the
|
|
20505
|
+
* removal path.
|
|
20506
|
+
*/
|
|
20507
|
+
async deleteEntry(aggregatorId) {
|
|
20508
|
+
await this.hydrate();
|
|
20509
|
+
const entry = this.entries.get(aggregatorId);
|
|
20510
|
+
if (!entry) return false;
|
|
20511
|
+
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20512
|
+
this.entries.delete(aggregatorId);
|
|
20513
|
+
this.dedupIndex.delete(dedupKey);
|
|
20514
|
+
this.fullPayloads.delete(aggregatorId);
|
|
20515
|
+
for (const [corr, id] of this.correlationIndex) {
|
|
20516
|
+
if (id === aggregatorId) this.correlationIndex.delete(corr);
|
|
20517
|
+
}
|
|
20518
|
+
try {
|
|
20519
|
+
await this.storage.delete(APPROVAL_AGGREGATOR_NAMESPACE, aggregatorId);
|
|
20520
|
+
} catch {
|
|
20521
|
+
}
|
|
20522
|
+
if (this.payloadStore) {
|
|
20523
|
+
try {
|
|
20524
|
+
await this.payloadStore.deletePayload(aggregatorId);
|
|
20525
|
+
} catch {
|
|
20526
|
+
}
|
|
20527
|
+
}
|
|
20528
|
+
const revision = this.nextRevision();
|
|
20529
|
+
this.removedTombstones.set(aggregatorId, revision);
|
|
20530
|
+
this.emit({ type: "removed", entry: { ...entry } });
|
|
20531
|
+
return true;
|
|
20532
|
+
}
|
|
20533
|
+
nextRevision() {
|
|
20534
|
+
this.currentRevision += 1;
|
|
20535
|
+
return this.currentRevision;
|
|
20536
|
+
}
|
|
20397
20537
|
/**
|
|
20398
20538
|
* Ingest a gate event. Returns the aggregator entry on first sight,
|
|
20399
20539
|
* `null` when deduped. Resolution events update the existing record;
|
|
@@ -20604,6 +20744,7 @@ var init_approval_aggregator = __esm({
|
|
|
20604
20744
|
entry.status = decision;
|
|
20605
20745
|
entry.resolved_at = this.now().toISOString();
|
|
20606
20746
|
entry.resolved_by = operatorId;
|
|
20747
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20607
20748
|
await this.persist(entry);
|
|
20608
20749
|
this.auditLog.append(
|
|
20609
20750
|
"l2",
|
|
@@ -20655,6 +20796,7 @@ var init_approval_aggregator = __esm({
|
|
|
20655
20796
|
const expires = new Date(now.getTime() + this.pendingTtlMs);
|
|
20656
20797
|
const hubInboxId = this.resolveHubInboxItemId(event);
|
|
20657
20798
|
const enforcementChain = this.resolveEnforcementChain(event);
|
|
20799
|
+
const revision = this.nextRevision();
|
|
20658
20800
|
const entry = {
|
|
20659
20801
|
aggregator_id: id,
|
|
20660
20802
|
source_harness: ctx.source_harness,
|
|
@@ -20666,6 +20808,8 @@ var init_approval_aggregator = __esm({
|
|
|
20666
20808
|
status: "pending",
|
|
20667
20809
|
created_at: now.toISOString(),
|
|
20668
20810
|
expires_at: expires.toISOString(),
|
|
20811
|
+
created_at_revision: revision,
|
|
20812
|
+
last_modified_revision: revision,
|
|
20669
20813
|
...hubInboxId !== void 0 ? { hub_inbox_item_id: hubInboxId } : {},
|
|
20670
20814
|
...enforcementChain.length > 0 ? { enforcement_chain: enforcementChain } : {}
|
|
20671
20815
|
};
|
|
@@ -20708,6 +20852,7 @@ var init_approval_aggregator = __esm({
|
|
|
20708
20852
|
entry.status = status;
|
|
20709
20853
|
entry.resolved_at = event.resolution.decided_at;
|
|
20710
20854
|
entry.resolved_by = event.resolution.decided_by;
|
|
20855
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20711
20856
|
await this.persist(entry);
|
|
20712
20857
|
this.auditLog.append(
|
|
20713
20858
|
"l2",
|
|
@@ -20770,6 +20915,7 @@ var init_approval_aggregator = __esm({
|
|
|
20770
20915
|
entry.status = "expired";
|
|
20771
20916
|
entry.resolved_at = this.now().toISOString();
|
|
20772
20917
|
entry.resolved_by = "system_ttl";
|
|
20918
|
+
entry.last_modified_revision = this.nextRevision();
|
|
20773
20919
|
await this.persist(entry);
|
|
20774
20920
|
this.auditLog.append(
|
|
20775
20921
|
"l2",
|
|
@@ -20816,6 +20962,10 @@ var init_approval_aggregator = __esm({
|
|
|
20816
20962
|
this.entries.set(entry.aggregator_id, entry);
|
|
20817
20963
|
const dedupKey = `${entry.source_harness}|${entry.source_agent_id}|${entry.audit_log_entry_id}`;
|
|
20818
20964
|
this.dedupIndex.set(dedupKey, entry.aggregator_id);
|
|
20965
|
+
const lastMod = entry.last_modified_revision ?? 0;
|
|
20966
|
+
if (lastMod > this.currentRevision) {
|
|
20967
|
+
this.currentRevision = lastMod;
|
|
20968
|
+
}
|
|
20819
20969
|
} catch {
|
|
20820
20970
|
}
|
|
20821
20971
|
}
|
|
@@ -33796,9 +33946,10 @@ function isTrivialQuery(query) {
|
|
|
33796
33946
|
if (norm.length < 8) return true;
|
|
33797
33947
|
return TRIVIAL_GREETINGS.has(norm);
|
|
33798
33948
|
}
|
|
33799
|
-
function classifyQuery(query) {
|
|
33949
|
+
function classifyQuery(query, parsedGrammar) {
|
|
33800
33950
|
const normalized = query.toLowerCase();
|
|
33801
33951
|
const matches = [];
|
|
33952
|
+
const grammarAgent = parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null;
|
|
33802
33953
|
for (const spec of CATEGORY_KEYWORDS) {
|
|
33803
33954
|
const matchedPhrases = [];
|
|
33804
33955
|
for (const pattern of spec.patterns) {
|
|
@@ -33810,11 +33961,14 @@ function classifyQuery(query) {
|
|
|
33810
33961
|
}
|
|
33811
33962
|
if (matchedPhrases.length === 0) continue;
|
|
33812
33963
|
const confidence = Math.min(1, 0.4 + 0.3 * matchedPhrases.length);
|
|
33964
|
+
const wantsAgentHint = spec.category === "agent_state" || spec.category === "agent_activity";
|
|
33965
|
+
const agent_name_hint = wantsAgentHint ? grammarAgent ?? extractAgentNameHint(query) : null;
|
|
33813
33966
|
matches.push({
|
|
33814
33967
|
category: spec.category,
|
|
33815
33968
|
confidence,
|
|
33816
33969
|
matched_keywords: matchedPhrases,
|
|
33817
|
-
agent_name_hint
|
|
33970
|
+
agent_name_hint,
|
|
33971
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33818
33972
|
});
|
|
33819
33973
|
}
|
|
33820
33974
|
matches.sort((a, b) => {
|
|
@@ -33823,45 +33977,67 @@ function classifyQuery(query) {
|
|
|
33823
33977
|
});
|
|
33824
33978
|
return matches;
|
|
33825
33979
|
}
|
|
33980
|
+
function fetcherHintsFromGrammar(parsed) {
|
|
33981
|
+
if (!parsed) return void 0;
|
|
33982
|
+
const hasTime = parsed.time_range !== null;
|
|
33983
|
+
const hasAgents = parsed.agent_names.length > 0;
|
|
33984
|
+
const hasEvents = parsed.event_types.length > 0;
|
|
33985
|
+
if (!hasTime && !hasAgents && !hasEvents) return void 0;
|
|
33986
|
+
const hints = {};
|
|
33987
|
+
if (parsed.time_range) {
|
|
33988
|
+
const range = parsed.time_range;
|
|
33989
|
+
hints.time_range = {
|
|
33990
|
+
start: range.start,
|
|
33991
|
+
end: range.end,
|
|
33992
|
+
...range.relative_label !== void 0 ? { relative_label: range.relative_label } : {}
|
|
33993
|
+
};
|
|
33994
|
+
}
|
|
33995
|
+
if (hasAgents) hints.agent_names = parsed.agent_names;
|
|
33996
|
+
if (hasEvents) hints.event_types = parsed.event_types;
|
|
33997
|
+
return hints;
|
|
33998
|
+
}
|
|
33826
33999
|
function approxTokenLen(text) {
|
|
33827
34000
|
return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
33828
34001
|
}
|
|
33829
|
-
async function runFetcher(match, fetchers) {
|
|
34002
|
+
async function runFetcher(match, fetchers, hints) {
|
|
33830
34003
|
switch (match.category) {
|
|
33831
34004
|
case "templates":
|
|
33832
|
-
return fetchers.templates();
|
|
34005
|
+
return fetchers.templates(hints);
|
|
33833
34006
|
case "agent_state":
|
|
33834
|
-
return fetchers.agent_state(match.agent_name_hint);
|
|
34007
|
+
return fetchers.agent_state(match.agent_name_hint, hints);
|
|
33835
34008
|
case "agent_activity":
|
|
33836
|
-
return fetchers.agent_activity(match.agent_name_hint);
|
|
34009
|
+
return fetchers.agent_activity(match.agent_name_hint, hints);
|
|
33837
34010
|
case "audit_log":
|
|
33838
|
-
return fetchers.audit_log();
|
|
34011
|
+
return fetchers.audit_log(hints);
|
|
33839
34012
|
case "sentinel_findings":
|
|
33840
|
-
return fetchers.sentinel_findings();
|
|
34013
|
+
return fetchers.sentinel_findings(hints);
|
|
33841
34014
|
case "anomaly_alerts":
|
|
33842
|
-
return fetchers.anomaly_alerts();
|
|
34015
|
+
return fetchers.anomaly_alerts(hints);
|
|
33843
34016
|
case "recent_receipts":
|
|
33844
|
-
return fetchers.recent_receipts();
|
|
34017
|
+
return fetchers.recent_receipts(hints);
|
|
33845
34018
|
case "verascore_deltas":
|
|
33846
|
-
return fetchers.verascore_deltas();
|
|
34019
|
+
return fetchers.verascore_deltas(hints);
|
|
33847
34020
|
}
|
|
33848
34021
|
}
|
|
33849
|
-
function trivialMatch(category) {
|
|
34022
|
+
function trivialMatch(category, parsedGrammar) {
|
|
33850
34023
|
return {
|
|
33851
34024
|
category,
|
|
33852
34025
|
confidence: 0.5,
|
|
33853
34026
|
matched_keywords: ["llm-assist"],
|
|
33854
|
-
agent_name_hint: null
|
|
34027
|
+
agent_name_hint: parsedGrammar && parsedGrammar.agent_names.length > 0 ? parsedGrammar.agent_names[0] ?? null : null,
|
|
34028
|
+
...parsedGrammar !== void 0 ? { query_grammar: parsedGrammar } : {}
|
|
33855
34029
|
};
|
|
33856
34030
|
}
|
|
33857
34031
|
async function foldContext(query, fetchers, opts) {
|
|
33858
34032
|
const budget = opts?.maxTokens ?? DEFAULT_DYNAMIC_CONTEXT_TOKEN_BUDGET;
|
|
33859
|
-
|
|
34033
|
+
const parsed = opts?.parsed ?? null;
|
|
34034
|
+
const hints = fetcherHintsFromGrammar(parsed);
|
|
34035
|
+
let matches = classifyQuery(query, parsed);
|
|
33860
34036
|
if (matches.length === 0 && !isTrivialQuery(query) && opts?.llmAssistClassify) {
|
|
33861
34037
|
try {
|
|
33862
34038
|
const picked = await opts.llmAssistClassify(query, CONTEXT_CATEGORIES);
|
|
33863
34039
|
if (picked !== "none" && CONTEXT_CATEGORIES.includes(picked)) {
|
|
33864
|
-
matches = [trivialMatch(picked)];
|
|
34040
|
+
matches = [trivialMatch(picked, parsed)];
|
|
33865
34041
|
}
|
|
33866
34042
|
} catch {
|
|
33867
34043
|
}
|
|
@@ -33872,7 +34048,7 @@ async function foldContext(query, fetchers, opts) {
|
|
|
33872
34048
|
const attempts = [];
|
|
33873
34049
|
for (const match of matches) {
|
|
33874
34050
|
try {
|
|
33875
|
-
const text = await runFetcher(match, fetchers);
|
|
34051
|
+
const text = await runFetcher(match, fetchers, hints);
|
|
33876
34052
|
const trimmed = text.trim();
|
|
33877
34053
|
if (trimmed.length > 0) {
|
|
33878
34054
|
attempts.push({ category: match.category, text: trimmed });
|
|
@@ -34044,6 +34220,533 @@ var init_concierge_context_router = __esm({
|
|
|
34044
34220
|
};
|
|
34045
34221
|
}
|
|
34046
34222
|
});
|
|
34223
|
+
|
|
34224
|
+
// src/composition/constants.ts
|
|
34225
|
+
var COMPOSITION_EVENT_TYPES;
|
|
34226
|
+
var init_constants4 = __esm({
|
|
34227
|
+
"src/composition/constants.ts"() {
|
|
34228
|
+
init_constants();
|
|
34229
|
+
COMPOSITION_EVENT_TYPES = [
|
|
34230
|
+
"composition_receipt_packed",
|
|
34231
|
+
"composition_receipt_verified",
|
|
34232
|
+
"composition_mandate_verified",
|
|
34233
|
+
"composition_verascore_published",
|
|
34234
|
+
"composition_sidecar_spawned",
|
|
34235
|
+
"composition_sidecar_crashed",
|
|
34236
|
+
"composition_sidecar_recovered",
|
|
34237
|
+
"composition_degraded",
|
|
34238
|
+
"composition_recovered"
|
|
34239
|
+
];
|
|
34240
|
+
}
|
|
34241
|
+
});
|
|
34242
|
+
|
|
34243
|
+
// src/chat/concierge-query-grammar.ts
|
|
34244
|
+
function resolveTimeRange(query, now) {
|
|
34245
|
+
const normalized = query.trim();
|
|
34246
|
+
const lower = normalized.toLowerCase();
|
|
34247
|
+
const fromTo = lower.match(
|
|
34248
|
+
/\b(?:from|between)\s+(.+?)\s+(?:to|and|-|until)\s+([\w:.\-+t /]+)/i
|
|
34249
|
+
);
|
|
34250
|
+
if (fromTo) {
|
|
34251
|
+
const aSlice = fromTo[1];
|
|
34252
|
+
const bSlice = fromTo[2];
|
|
34253
|
+
if (aSlice !== void 0 && bSlice !== void 0) {
|
|
34254
|
+
const a = parseInstant(aSlice, now);
|
|
34255
|
+
const b = parseInstant(bSlice, now);
|
|
34256
|
+
if (a && b) {
|
|
34257
|
+
const start = a.getTime() <= b.getTime() ? a : b;
|
|
34258
|
+
const end = a.getTime() <= b.getTime() ? b : a;
|
|
34259
|
+
return {
|
|
34260
|
+
range: { start, end },
|
|
34261
|
+
matchedSubstring: fromTo[0]
|
|
34262
|
+
};
|
|
34263
|
+
}
|
|
34264
|
+
}
|
|
34265
|
+
}
|
|
34266
|
+
const sinceMatch = lower.match(/\bsince\s+([\w:.\-+t /]+)/i);
|
|
34267
|
+
if (sinceMatch) {
|
|
34268
|
+
const slice = sinceMatch[1];
|
|
34269
|
+
if (slice !== void 0) {
|
|
34270
|
+
const start = parseInstant(slice, now);
|
|
34271
|
+
if (start) {
|
|
34272
|
+
return {
|
|
34273
|
+
range: { start, end: now },
|
|
34274
|
+
matchedSubstring: sinceMatch[0]
|
|
34275
|
+
};
|
|
34276
|
+
}
|
|
34277
|
+
}
|
|
34278
|
+
}
|
|
34279
|
+
if (/\byesterday\b/.test(lower)) {
|
|
34280
|
+
const startOfToday = startOfDay(now);
|
|
34281
|
+
const start = new Date(startOfToday.getTime() - MS_PER_DAY);
|
|
34282
|
+
const end = new Date(startOfToday.getTime() - 1);
|
|
34283
|
+
return {
|
|
34284
|
+
range: { start, end, relative_label: "yesterday" },
|
|
34285
|
+
matchedSubstring: "yesterday"
|
|
34286
|
+
};
|
|
34287
|
+
}
|
|
34288
|
+
if (/\btoday\b/.test(lower)) {
|
|
34289
|
+
return {
|
|
34290
|
+
range: {
|
|
34291
|
+
start: startOfDay(now),
|
|
34292
|
+
end: now,
|
|
34293
|
+
relative_label: "today"
|
|
34294
|
+
},
|
|
34295
|
+
matchedSubstring: "today"
|
|
34296
|
+
};
|
|
34297
|
+
}
|
|
34298
|
+
const compactHours = lower.match(/\blast\s+(\d+)\s*h\b/i);
|
|
34299
|
+
if (compactHours) {
|
|
34300
|
+
const tok = compactHours[1];
|
|
34301
|
+
if (tok !== void 0) {
|
|
34302
|
+
const n = Number.parseInt(tok, 10);
|
|
34303
|
+
if (Number.isFinite(n) && n > 0) {
|
|
34304
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34305
|
+
return {
|
|
34306
|
+
range: { start, end: now, relative_label: `last ${n}h` },
|
|
34307
|
+
matchedSubstring: compactHours[0]
|
|
34308
|
+
};
|
|
34309
|
+
}
|
|
34310
|
+
}
|
|
34311
|
+
}
|
|
34312
|
+
const hoursMatch = lower.match(
|
|
34313
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:hr\b|hrs\b|hour|hours)/i
|
|
34314
|
+
);
|
|
34315
|
+
if (hoursMatch) {
|
|
34316
|
+
const tok = hoursMatch[1];
|
|
34317
|
+
if (tok !== void 0) {
|
|
34318
|
+
const n = parseCount(tok);
|
|
34319
|
+
if (n !== null && n > 0) {
|
|
34320
|
+
const start = new Date(now.getTime() - n * MS_PER_HOUR);
|
|
34321
|
+
return {
|
|
34322
|
+
range: { start, end: now, relative_label: `past ${n} hour${n === 1 ? "" : "s"}` },
|
|
34323
|
+
matchedSubstring: hoursMatch[0]
|
|
34324
|
+
};
|
|
34325
|
+
}
|
|
34326
|
+
}
|
|
34327
|
+
}
|
|
34328
|
+
if (/\b(?:past|last)\s+hour\b/.test(lower)) {
|
|
34329
|
+
const start = new Date(now.getTime() - MS_PER_HOUR);
|
|
34330
|
+
return {
|
|
34331
|
+
range: { start, end: now, relative_label: "past hour" },
|
|
34332
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+hour\b/i)[0]
|
|
34333
|
+
};
|
|
34334
|
+
}
|
|
34335
|
+
const daysMatch = lower.match(
|
|
34336
|
+
/\b(?:past|last)\s+([\w]+|\d+)\s*(?:d\b|day|days)/i
|
|
34337
|
+
);
|
|
34338
|
+
if (daysMatch) {
|
|
34339
|
+
const tok = daysMatch[1];
|
|
34340
|
+
if (tok !== void 0) {
|
|
34341
|
+
const n = parseCount(tok);
|
|
34342
|
+
if (n !== null && n > 0) {
|
|
34343
|
+
const start = new Date(now.getTime() - n * MS_PER_DAY);
|
|
34344
|
+
return {
|
|
34345
|
+
range: { start, end: now, relative_label: `past ${n} day${n === 1 ? "" : "s"}` },
|
|
34346
|
+
matchedSubstring: daysMatch[0]
|
|
34347
|
+
};
|
|
34348
|
+
}
|
|
34349
|
+
}
|
|
34350
|
+
}
|
|
34351
|
+
if (/\b(?:past|last)\s+day\b/.test(lower)) {
|
|
34352
|
+
const start = new Date(now.getTime() - MS_PER_DAY);
|
|
34353
|
+
return {
|
|
34354
|
+
range: { start, end: now, relative_label: "past day" },
|
|
34355
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+day\b/i)[0]
|
|
34356
|
+
};
|
|
34357
|
+
}
|
|
34358
|
+
if (/\bthis\s+week\b/.test(lower)) {
|
|
34359
|
+
const start = startOfWeek(now);
|
|
34360
|
+
return {
|
|
34361
|
+
range: { start, end: now, relative_label: "this week" },
|
|
34362
|
+
matchedSubstring: lower.match(/\bthis\s+week\b/i)[0]
|
|
34363
|
+
};
|
|
34364
|
+
}
|
|
34365
|
+
if (/\b(?:past|last)\s+week\b/.test(lower)) {
|
|
34366
|
+
const start = new Date(now.getTime() - 7 * MS_PER_DAY);
|
|
34367
|
+
return {
|
|
34368
|
+
range: { start, end: now, relative_label: "past week" },
|
|
34369
|
+
matchedSubstring: lower.match(/\b(?:past|last)\s+week\b/i)[0]
|
|
34370
|
+
};
|
|
34371
|
+
}
|
|
34372
|
+
const isoMatch = normalized.match(
|
|
34373
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?)?)\b/
|
|
34374
|
+
);
|
|
34375
|
+
if (isoMatch) {
|
|
34376
|
+
const tok = isoMatch[1];
|
|
34377
|
+
if (tok !== void 0) {
|
|
34378
|
+
const parsed = parseInstant(tok, now);
|
|
34379
|
+
if (parsed) {
|
|
34380
|
+
const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(tok);
|
|
34381
|
+
if (isDateOnly) {
|
|
34382
|
+
return {
|
|
34383
|
+
range: {
|
|
34384
|
+
start: parsed,
|
|
34385
|
+
end: new Date(parsed.getTime() + MS_PER_DAY - 1)
|
|
34386
|
+
},
|
|
34387
|
+
matchedSubstring: tok
|
|
34388
|
+
};
|
|
34389
|
+
}
|
|
34390
|
+
return {
|
|
34391
|
+
range: {
|
|
34392
|
+
start: new Date(parsed.getTime() - 30 * 60 * 1e3),
|
|
34393
|
+
end: new Date(parsed.getTime() + 30 * 60 * 1e3)
|
|
34394
|
+
},
|
|
34395
|
+
matchedSubstring: tok
|
|
34396
|
+
};
|
|
34397
|
+
}
|
|
34398
|
+
}
|
|
34399
|
+
}
|
|
34400
|
+
return null;
|
|
34401
|
+
}
|
|
34402
|
+
function parseInstant(token, now) {
|
|
34403
|
+
const trimmed = token.trim().replace(/[,.!?;]+$/g, "");
|
|
34404
|
+
if (!trimmed) return null;
|
|
34405
|
+
const lower = trimmed.toLowerCase();
|
|
34406
|
+
if (lower === "now") return now;
|
|
34407
|
+
if (lower === "today") return startOfDay(now);
|
|
34408
|
+
if (lower === "yesterday") {
|
|
34409
|
+
return new Date(startOfDay(now).getTime() - MS_PER_DAY);
|
|
34410
|
+
}
|
|
34411
|
+
const isoLike = trimmed.replace(" ", "T");
|
|
34412
|
+
const parsed = new Date(isoLike);
|
|
34413
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
34414
|
+
return null;
|
|
34415
|
+
}
|
|
34416
|
+
function parseCount(token) {
|
|
34417
|
+
const lower = token.toLowerCase();
|
|
34418
|
+
if (/^\d+$/.test(lower)) {
|
|
34419
|
+
const n = Number.parseInt(lower, 10);
|
|
34420
|
+
return Number.isFinite(n) ? n : null;
|
|
34421
|
+
}
|
|
34422
|
+
return NUMBER_WORDS[lower] ?? null;
|
|
34423
|
+
}
|
|
34424
|
+
function startOfDay(d) {
|
|
34425
|
+
const out = new Date(d);
|
|
34426
|
+
out.setHours(0, 0, 0, 0);
|
|
34427
|
+
return out;
|
|
34428
|
+
}
|
|
34429
|
+
function startOfWeek(d) {
|
|
34430
|
+
const out = startOfDay(d);
|
|
34431
|
+
const dayOfWeek = out.getDay();
|
|
34432
|
+
const offsetToMonday = (dayOfWeek + 6) % 7;
|
|
34433
|
+
out.setDate(out.getDate() - offsetToMonday);
|
|
34434
|
+
return out;
|
|
34435
|
+
}
|
|
34436
|
+
function listFromRegistry(registry) {
|
|
34437
|
+
if (!registry) return [];
|
|
34438
|
+
if (Array.isArray(registry)) return registry;
|
|
34439
|
+
if (typeof registry.list === "function") {
|
|
34440
|
+
return registry.list();
|
|
34441
|
+
}
|
|
34442
|
+
return [];
|
|
34443
|
+
}
|
|
34444
|
+
function extractAgentNames(query, registry) {
|
|
34445
|
+
const records = listFromRegistry(registry);
|
|
34446
|
+
if (records.length === 0) return { matched: [], flagged: false };
|
|
34447
|
+
const lowerQuery = query.toLowerCase();
|
|
34448
|
+
const compactQuery = lowerQuery.replace(/[\s_-]+/g, "");
|
|
34449
|
+
const matched = [];
|
|
34450
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34451
|
+
for (const rec of records) {
|
|
34452
|
+
const id = rec.agent_id;
|
|
34453
|
+
if (!id || seen.has(id)) continue;
|
|
34454
|
+
const idLower = id.toLowerCase();
|
|
34455
|
+
if (idLower.length < 3) continue;
|
|
34456
|
+
const idCompact = idLower.replace(/[\s_-]+/g, "");
|
|
34457
|
+
const wordRe = new RegExp(
|
|
34458
|
+
`\\b${idLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
|
|
34459
|
+
"i"
|
|
34460
|
+
);
|
|
34461
|
+
if (wordRe.test(query)) {
|
|
34462
|
+
matched.push(id);
|
|
34463
|
+
seen.add(id);
|
|
34464
|
+
continue;
|
|
34465
|
+
}
|
|
34466
|
+
if (idCompact.length >= 4 && compactQuery.includes(idCompact)) {
|
|
34467
|
+
matched.push(id);
|
|
34468
|
+
seen.add(id);
|
|
34469
|
+
}
|
|
34470
|
+
}
|
|
34471
|
+
const agentMention = lowerQuery.match(/\bagent\s+([a-z0-9_-]{3,40})/i);
|
|
34472
|
+
const flagged = matched.length === 0 && agentMention !== null && agentMention[1] !== void 0 && !records.some((r) => r.agent_id.toLowerCase() === agentMention[1]?.toLowerCase());
|
|
34473
|
+
return { matched, flagged };
|
|
34474
|
+
}
|
|
34475
|
+
function escapeRegex(s) {
|
|
34476
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34477
|
+
}
|
|
34478
|
+
function extractEventTypes(query, enumValues) {
|
|
34479
|
+
const lower = query.toLowerCase();
|
|
34480
|
+
const matched = [];
|
|
34481
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34482
|
+
for (const ev of enumValues) {
|
|
34483
|
+
if (seen.has(ev)) continue;
|
|
34484
|
+
const re = new RegExp(`\\b${escapeRegex(ev)}\\b`, "i");
|
|
34485
|
+
if (re.test(query)) {
|
|
34486
|
+
matched.push(ev);
|
|
34487
|
+
seen.add(ev);
|
|
34488
|
+
}
|
|
34489
|
+
}
|
|
34490
|
+
for (const syn of EVENT_SYNONYMS) {
|
|
34491
|
+
const re = new RegExp(
|
|
34492
|
+
`\\b${syn.phrase.split(/\s+/).map(escapeRegex).join("\\s+")}\\b`,
|
|
34493
|
+
"i"
|
|
34494
|
+
);
|
|
34495
|
+
if (re.test(query)) {
|
|
34496
|
+
for (const c of syn.canonical) {
|
|
34497
|
+
if (seen.has(c)) continue;
|
|
34498
|
+
if (!enumValues.includes(c)) continue;
|
|
34499
|
+
matched.push(c);
|
|
34500
|
+
seen.add(c);
|
|
34501
|
+
}
|
|
34502
|
+
}
|
|
34503
|
+
}
|
|
34504
|
+
const globMatches = lower.match(/\b([a-z_]+)_\*/g) ?? [];
|
|
34505
|
+
for (const glob of globMatches) {
|
|
34506
|
+
const prefix = glob.slice(0, -2);
|
|
34507
|
+
for (const ev of enumValues) {
|
|
34508
|
+
if (seen.has(ev)) continue;
|
|
34509
|
+
if (ev.startsWith(prefix)) {
|
|
34510
|
+
matched.push(ev);
|
|
34511
|
+
seen.add(ev);
|
|
34512
|
+
}
|
|
34513
|
+
}
|
|
34514
|
+
}
|
|
34515
|
+
const eventNounMention = /\b(?:event|events|class|classes)\b/i.test(query) && matched.length === 0;
|
|
34516
|
+
return { matched, flagged: eventNounMention };
|
|
34517
|
+
}
|
|
34518
|
+
function deriveIntentPhrase(query, stripTokens) {
|
|
34519
|
+
let out = query;
|
|
34520
|
+
for (const tok of stripTokens) {
|
|
34521
|
+
if (!tok) continue;
|
|
34522
|
+
const re = new RegExp(escapeRegex(tok), "gi");
|
|
34523
|
+
out = out.replace(re, " ");
|
|
34524
|
+
}
|
|
34525
|
+
return out.replace(/\s+/g, " ").trim();
|
|
34526
|
+
}
|
|
34527
|
+
function computeConfidence(parsed) {
|
|
34528
|
+
const dims = [
|
|
34529
|
+
{ present: parsed.hasTimeMention, resolved: parsed.timeResolved },
|
|
34530
|
+
{ present: parsed.hasAgentMention, resolved: parsed.agentResolved },
|
|
34531
|
+
{ present: parsed.hasEventMention, resolved: parsed.eventResolved }
|
|
34532
|
+
];
|
|
34533
|
+
const present = dims.filter((d) => d.present);
|
|
34534
|
+
let base;
|
|
34535
|
+
if (present.length === 0) {
|
|
34536
|
+
base = parsed.intentEmpty ? 0 : 0.3;
|
|
34537
|
+
} else {
|
|
34538
|
+
const resolved = present.filter((d) => d.resolved).length;
|
|
34539
|
+
base = resolved / present.length;
|
|
34540
|
+
}
|
|
34541
|
+
const adjusted = base - 0.15 * parsed.ambiguityCount;
|
|
34542
|
+
if (adjusted < 0) return 0;
|
|
34543
|
+
if (adjusted > 1) return 1;
|
|
34544
|
+
return adjusted;
|
|
34545
|
+
}
|
|
34546
|
+
function parseQuery(query, opts) {
|
|
34547
|
+
const now = opts?.now ?? /* @__PURE__ */ new Date();
|
|
34548
|
+
const enumValues = opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES;
|
|
34549
|
+
const original = query ?? "";
|
|
34550
|
+
const trimmed = original.trim();
|
|
34551
|
+
if (trimmed.length === 0) {
|
|
34552
|
+
return {
|
|
34553
|
+
time_range: null,
|
|
34554
|
+
agent_names: [],
|
|
34555
|
+
event_types: [],
|
|
34556
|
+
intent_phrase: "",
|
|
34557
|
+
ambiguity_flags: ["no_signal_extracted"],
|
|
34558
|
+
parse_confidence: 0
|
|
34559
|
+
};
|
|
34560
|
+
}
|
|
34561
|
+
const ambiguity_flags = /* @__PURE__ */ new Set();
|
|
34562
|
+
const timeMatch = resolveTimeRange(trimmed, now);
|
|
34563
|
+
const hasTimeMention = TIME_MENTION_PROBE.test(trimmed);
|
|
34564
|
+
if (hasTimeMention && !timeMatch) {
|
|
34565
|
+
ambiguity_flags.add("unknown_time_token");
|
|
34566
|
+
}
|
|
34567
|
+
const agentResult = extractAgentNames(trimmed, opts?.registry);
|
|
34568
|
+
if (agentResult.flagged) {
|
|
34569
|
+
ambiguity_flags.add("unknown_agent_token");
|
|
34570
|
+
}
|
|
34571
|
+
const hasAgentMention = AGENT_MENTION_PROBE.test(trimmed);
|
|
34572
|
+
const eventResult = extractEventTypes(trimmed, enumValues);
|
|
34573
|
+
const hasEventMention = EVENT_MENTION_PROBE.test(trimmed);
|
|
34574
|
+
if (eventResult.flagged) {
|
|
34575
|
+
ambiguity_flags.add("unknown_event_token");
|
|
34576
|
+
}
|
|
34577
|
+
const stripTokens = [];
|
|
34578
|
+
if (timeMatch) stripTokens.push(timeMatch.matchedSubstring);
|
|
34579
|
+
for (const name of agentResult.matched) stripTokens.push(name);
|
|
34580
|
+
for (const ev of eventResult.matched) {
|
|
34581
|
+
if (trimmed.toLowerCase().includes(ev.toLowerCase())) {
|
|
34582
|
+
stripTokens.push(ev);
|
|
34583
|
+
}
|
|
34584
|
+
}
|
|
34585
|
+
const intent_phrase = deriveIntentPhrase(trimmed, stripTokens);
|
|
34586
|
+
const parse_confidence = computeConfidence({
|
|
34587
|
+
hasTimeMention,
|
|
34588
|
+
timeResolved: timeMatch !== null,
|
|
34589
|
+
hasAgentMention,
|
|
34590
|
+
agentResolved: agentResult.matched.length > 0,
|
|
34591
|
+
hasEventMention,
|
|
34592
|
+
eventResolved: eventResult.matched.length > 0,
|
|
34593
|
+
intentEmpty: intent_phrase.length === 0,
|
|
34594
|
+
ambiguityCount: ambiguity_flags.size
|
|
34595
|
+
});
|
|
34596
|
+
if (timeMatch === null && agentResult.matched.length === 0 && eventResult.matched.length === 0 && intent_phrase.length === 0) {
|
|
34597
|
+
ambiguity_flags.add("no_signal_extracted");
|
|
34598
|
+
}
|
|
34599
|
+
return {
|
|
34600
|
+
time_range: timeMatch ? timeMatch.range : null,
|
|
34601
|
+
agent_names: agentResult.matched,
|
|
34602
|
+
event_types: eventResult.matched,
|
|
34603
|
+
intent_phrase,
|
|
34604
|
+
ambiguity_flags: Array.from(ambiguity_flags),
|
|
34605
|
+
parse_confidence
|
|
34606
|
+
};
|
|
34607
|
+
}
|
|
34608
|
+
function isLowConfidence(parsed) {
|
|
34609
|
+
return parsed.parse_confidence < LLM_ASSIST_THRESHOLD;
|
|
34610
|
+
}
|
|
34611
|
+
async function parseQueryWithLlmAssist(query, llmAssist, opts) {
|
|
34612
|
+
const parsed = parseQuery(query, opts);
|
|
34613
|
+
if (!llmAssist || !isLowConfidence(parsed)) return parsed;
|
|
34614
|
+
let completion;
|
|
34615
|
+
try {
|
|
34616
|
+
completion = await llmAssist(query, parsed);
|
|
34617
|
+
} catch {
|
|
34618
|
+
return parsed;
|
|
34619
|
+
}
|
|
34620
|
+
if (!completion || typeof completion !== "object") return parsed;
|
|
34621
|
+
const merged = { ...parsed };
|
|
34622
|
+
if (parsed.time_range === null && completion.time_range) {
|
|
34623
|
+
merged.time_range = completion.time_range;
|
|
34624
|
+
}
|
|
34625
|
+
if (parsed.agent_names.length === 0 && Array.isArray(completion.agent_names)) {
|
|
34626
|
+
merged.agent_names = completion.agent_names.filter(
|
|
34627
|
+
(s) => typeof s === "string" && s.length > 0
|
|
34628
|
+
);
|
|
34629
|
+
}
|
|
34630
|
+
if (parsed.event_types.length === 0 && Array.isArray(completion.event_types)) {
|
|
34631
|
+
const allowed = new Set(opts?.eventClassEnum ?? CANONICAL_AUDIT_EVENT_CLASSES);
|
|
34632
|
+
merged.event_types = completion.event_types.filter(
|
|
34633
|
+
(s) => typeof s === "string" && allowed.has(s)
|
|
34634
|
+
);
|
|
34635
|
+
}
|
|
34636
|
+
merged.parse_confidence = Math.max(
|
|
34637
|
+
parsed.parse_confidence,
|
|
34638
|
+
computeConfidence({
|
|
34639
|
+
hasTimeMention: TIME_MENTION_PROBE.test(query),
|
|
34640
|
+
timeResolved: merged.time_range !== null,
|
|
34641
|
+
hasAgentMention: AGENT_MENTION_PROBE.test(query),
|
|
34642
|
+
agentResolved: merged.agent_names.length > 0,
|
|
34643
|
+
hasEventMention: EVENT_MENTION_PROBE.test(query),
|
|
34644
|
+
eventResolved: merged.event_types.length > 0,
|
|
34645
|
+
intentEmpty: merged.intent_phrase.length === 0,
|
|
34646
|
+
ambiguityCount: merged.ambiguity_flags.length
|
|
34647
|
+
})
|
|
34648
|
+
);
|
|
34649
|
+
return merged;
|
|
34650
|
+
}
|
|
34651
|
+
function auditSafeSummary(parsed) {
|
|
34652
|
+
return {
|
|
34653
|
+
time_range: parsed.time_range ? {
|
|
34654
|
+
start_iso: parsed.time_range.start.toISOString(),
|
|
34655
|
+
end_iso: parsed.time_range.end.toISOString(),
|
|
34656
|
+
...parsed.time_range.relative_label !== void 0 ? { relative_label: parsed.time_range.relative_label } : {}
|
|
34657
|
+
} : null,
|
|
34658
|
+
agent_names: [...parsed.agent_names],
|
|
34659
|
+
event_types: [...parsed.event_types],
|
|
34660
|
+
ambiguity_flags: [...parsed.ambiguity_flags],
|
|
34661
|
+
parse_confidence: parsed.parse_confidence
|
|
34662
|
+
};
|
|
34663
|
+
}
|
|
34664
|
+
var CANONICAL_AUDIT_EVENT_CLASSES, EVENT_SYNONYMS, MS_PER_HOUR, MS_PER_DAY, NUMBER_WORDS, TIME_MENTION_PROBE, AGENT_MENTION_PROBE, EVENT_MENTION_PROBE, LLM_ASSIST_THRESHOLD;
|
|
34665
|
+
var init_concierge_query_grammar = __esm({
|
|
34666
|
+
"src/chat/concierge-query-grammar.ts"() {
|
|
34667
|
+
init_constants4();
|
|
34668
|
+
init_operator_chat_audit_events();
|
|
34669
|
+
CANONICAL_AUDIT_EVENT_CLASSES = [
|
|
34670
|
+
// Lifecycle / policy
|
|
34671
|
+
"policy_change",
|
|
34672
|
+
"approval_request",
|
|
34673
|
+
"audit_truncate",
|
|
34674
|
+
"lockdown",
|
|
34675
|
+
"unwrap",
|
|
34676
|
+
// Exit bundle (Tier 1)
|
|
34677
|
+
"exit_bundle_export",
|
|
34678
|
+
"exit_bundle_import_activate",
|
|
34679
|
+
"exit_bundle_rekey",
|
|
34680
|
+
// Cross-harness approval aggregator
|
|
34681
|
+
"cross_harness_approval_aggregated",
|
|
34682
|
+
"cross_harness_approval_resolved",
|
|
34683
|
+
"cross_harness_approval_deduped",
|
|
34684
|
+
"cross_harness_approval_payload_decrypted",
|
|
34685
|
+
"cross_harness_approval_audit_trail_viewed",
|
|
34686
|
+
"cross_harness_approval_replayed",
|
|
34687
|
+
// Composition (full set from constants.ts)
|
|
34688
|
+
...COMPOSITION_EVENT_TYPES,
|
|
34689
|
+
// Operator chat / concierge (full set from OPERATOR_CHAT_OPS)
|
|
34690
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CHAT,
|
|
34691
|
+
OPERATOR_CHAT_OPS.AGENT_INSPECT_PANEL_OPENED,
|
|
34692
|
+
OPERATOR_CHAT_OPS.CONCIERGE_HISTORY_READ,
|
|
34693
|
+
OPERATOR_CHAT_OPS.CONCIERGE_THREAD_DELETED,
|
|
34694
|
+
OPERATOR_CHAT_OPS.CONCIERGE_MEMORY_READ_FAILED,
|
|
34695
|
+
OPERATOR_CHAT_OPS.CONCIERGE_CONTEXT_FETCHER_FAILED,
|
|
34696
|
+
// Bridge / commitment
|
|
34697
|
+
"bridge_commit",
|
|
34698
|
+
"bridge_verify",
|
|
34699
|
+
"bridge_attest",
|
|
34700
|
+
"proof_commitment",
|
|
34701
|
+
"proof_reveal",
|
|
34702
|
+
// Reputation
|
|
34703
|
+
"reputation_export",
|
|
34704
|
+
"reputation_import",
|
|
34705
|
+
"reputation_publish",
|
|
34706
|
+
"reputation_record",
|
|
34707
|
+
"reputation_query"
|
|
34708
|
+
];
|
|
34709
|
+
EVENT_SYNONYMS = [
|
|
34710
|
+
{ phrase: "approvals", canonical: ["approval_request", "cross_harness_approval_aggregated", "cross_harness_approval_resolved"] },
|
|
34711
|
+
{ phrase: "approval", canonical: ["approval_request"] },
|
|
34712
|
+
{ phrase: "policy changes", canonical: ["policy_change"] },
|
|
34713
|
+
{ phrase: "policy change", canonical: ["policy_change"] },
|
|
34714
|
+
{ phrase: "policy edits", canonical: ["policy_change"] },
|
|
34715
|
+
{ phrase: "lockdowns", canonical: ["lockdown"] },
|
|
34716
|
+
{ phrase: "exit bundles", canonical: ["exit_bundle_export", "exit_bundle_import_activate"] },
|
|
34717
|
+
{ phrase: "exit bundle", canonical: ["exit_bundle_export"] },
|
|
34718
|
+
{ phrase: "audit truncations", canonical: ["audit_truncate"] },
|
|
34719
|
+
{ phrase: "audit truncation", canonical: ["audit_truncate"] },
|
|
34720
|
+
{ phrase: "compositions", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34721
|
+
{ phrase: "receipts", canonical: ["composition_receipt_packed", "composition_receipt_verified"] },
|
|
34722
|
+
{ phrase: "receipt verifications", canonical: ["composition_receipt_verified"] },
|
|
34723
|
+
{ phrase: "concierge chats", canonical: [OPERATOR_CHAT_OPS.CONCIERGE_CHAT] },
|
|
34724
|
+
{ phrase: "cross harness approvals", canonical: ["cross_harness_approval_aggregated", "cross_harness_approval_resolved"] }
|
|
34725
|
+
];
|
|
34726
|
+
MS_PER_HOUR = 60 * 60 * 1e3;
|
|
34727
|
+
MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
34728
|
+
NUMBER_WORDS = {
|
|
34729
|
+
a: 1,
|
|
34730
|
+
an: 1,
|
|
34731
|
+
one: 1,
|
|
34732
|
+
two: 2,
|
|
34733
|
+
three: 3,
|
|
34734
|
+
four: 4,
|
|
34735
|
+
five: 5,
|
|
34736
|
+
six: 6,
|
|
34737
|
+
seven: 7,
|
|
34738
|
+
eight: 8,
|
|
34739
|
+
nine: 9,
|
|
34740
|
+
ten: 10,
|
|
34741
|
+
twelve: 12,
|
|
34742
|
+
twentyfour: 24
|
|
34743
|
+
};
|
|
34744
|
+
TIME_MENTION_PROBE = /\b(yesterday|today|now|past|last|this\s+week|this\s+month|since|from|between|\d{4}-\d{2}-\d{2})\b/i;
|
|
34745
|
+
AGENT_MENTION_PROBE = /\bagent[s]?\b/i;
|
|
34746
|
+
EVENT_MENTION_PROBE = /\b(event|events|class|classes|approvals?|policy)\b/i;
|
|
34747
|
+
LLM_ASSIST_THRESHOLD = 0.5;
|
|
34748
|
+
}
|
|
34749
|
+
});
|
|
34047
34750
|
function approxTokenLen2(text) {
|
|
34048
34751
|
return Math.ceil(text.length / 4);
|
|
34049
34752
|
}
|
|
@@ -34076,6 +34779,7 @@ var init_operator_chat_service = __esm({
|
|
|
34076
34779
|
init_operator_chat_audit_events();
|
|
34077
34780
|
init_operator_chat_types();
|
|
34078
34781
|
init_concierge_context_router();
|
|
34782
|
+
init_concierge_query_grammar();
|
|
34079
34783
|
DEFAULT_CONCIERGE_MAX_TOKENS = 512;
|
|
34080
34784
|
DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS = 10;
|
|
34081
34785
|
DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -34126,6 +34830,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34126
34830
|
contextFetchers;
|
|
34127
34831
|
contextLlmAssist;
|
|
34128
34832
|
dynamicContextBudget;
|
|
34833
|
+
agentRegistry;
|
|
34834
|
+
grammarLlmAssist;
|
|
34129
34835
|
/**
|
|
34130
34836
|
* In-memory thread_id assigned to the active concierge session.
|
|
34131
34837
|
* The first sendConcierge call after construction allocates a fresh
|
|
@@ -34164,6 +34870,12 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34164
34870
|
this.contextLlmAssist = deps.conciergeContextLlmAssist;
|
|
34165
34871
|
}
|
|
34166
34872
|
this.dynamicContextBudget = deps.conciergeDynamicContextBudget !== void 0 && deps.conciergeDynamicContextBudget > 0 ? deps.conciergeDynamicContextBudget : DEFAULT_CONCIERGE_DYNAMIC_CONTEXT_BUDGET;
|
|
34873
|
+
if (deps.conciergeAgentRegistry) {
|
|
34874
|
+
this.agentRegistry = deps.conciergeAgentRegistry;
|
|
34875
|
+
}
|
|
34876
|
+
if (deps.conciergeGrammarLlmAssist) {
|
|
34877
|
+
this.grammarLlmAssist = deps.conciergeGrammarLlmAssist;
|
|
34878
|
+
}
|
|
34167
34879
|
}
|
|
34168
34880
|
// ── Concierge ─────────────────────────────────────────────────────────
|
|
34169
34881
|
/**
|
|
@@ -34222,6 +34934,7 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34222
34934
|
await this.memory.appendTurn(threadId, "user", trimmed).catch(() => {
|
|
34223
34935
|
});
|
|
34224
34936
|
}
|
|
34937
|
+
const parsedGrammar = await this.runGrammarParse(filterResult.filtered);
|
|
34225
34938
|
const start = Date.now();
|
|
34226
34939
|
let conciergeBody;
|
|
34227
34940
|
let servedBy = "disabled";
|
|
@@ -34240,7 +34953,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34240
34953
|
outcome = "substrate_disabled";
|
|
34241
34954
|
} else {
|
|
34242
34955
|
const dynamicResult = await this.runDynamicContextFold(
|
|
34243
|
-
filterResult.filtered
|
|
34956
|
+
filterResult.filtered,
|
|
34957
|
+
parsedGrammar
|
|
34244
34958
|
);
|
|
34245
34959
|
dynamicCategoriesIncluded = dynamicResult.categoriesIncluded;
|
|
34246
34960
|
const context = await this.assembleConciergeContext(
|
|
@@ -34311,7 +35025,8 @@ Note: this is a static reference block (v1.2.x). Dynamic context injection (live
|
|
|
34311
35025
|
...this.memory ? {
|
|
34312
35026
|
prior_turns_folded: memoryReadFailureReason === null ? priorTurns.length : 0
|
|
34313
35027
|
} : {},
|
|
34314
|
-
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {}
|
|
35028
|
+
...this.contextFetchers ? { dynamic_context_categories: [...dynamicCategoriesIncluded] } : {},
|
|
35029
|
+
parsed_grammar: auditSafeSummary(parsedGrammar)
|
|
34315
35030
|
};
|
|
34316
35031
|
this.emit(OPERATOR_CHAT_OPS.CONCIERGE_CHAT, payload, outcome === "ok" ? "success" : "failure");
|
|
34317
35032
|
return {
|
|
@@ -34526,8 +35241,12 @@ ${inbox}`
|
|
|
34526
35241
|
* proceeds with no fold. Returns the rendered section + the list of
|
|
34527
35242
|
* categories whose data made it into the section (used for the
|
|
34528
35243
|
* round-trip audit emission).
|
|
35244
|
+
*
|
|
35245
|
+
* Tau-4: receives the pre-parsed `ParsedQuery` and forwards it as the
|
|
35246
|
+
* `parsed` opt to `foldContext`, so fetchers see the structured
|
|
35247
|
+
* `FetcherHints` derived from it.
|
|
34529
35248
|
*/
|
|
34530
|
-
async runDynamicContextFold(query) {
|
|
35249
|
+
async runDynamicContextFold(query, parsedGrammar) {
|
|
34531
35250
|
if (!this.contextFetchers) {
|
|
34532
35251
|
return { section: "", categoriesIncluded: [] };
|
|
34533
35252
|
}
|
|
@@ -34536,10 +35255,24 @@ ${inbox}`
|
|
|
34536
35255
|
...this.contextLlmAssist ? { llmAssistClassify: this.contextLlmAssist } : {},
|
|
34537
35256
|
onFetcherFailure: (category, error) => {
|
|
34538
35257
|
this.emitContextFetcherFailed(category, classifyFetcherError(error));
|
|
34539
|
-
}
|
|
35258
|
+
},
|
|
35259
|
+
parsed: parsedGrammar
|
|
34540
35260
|
});
|
|
34541
35261
|
return result;
|
|
34542
35262
|
}
|
|
35263
|
+
/**
|
|
35264
|
+
* WP-V1.3-9 Tau-4: parse the (PII-filtered) operator query into a
|
|
35265
|
+
* `ParsedQuery`. Routes through the LLM-assist completion hook when
|
|
35266
|
+
* configured and the rule-based parse is below
|
|
35267
|
+
* `LLM_ASSIST_THRESHOLD`. Always returns a parse object (never
|
|
35268
|
+
* throws) so the audit emission can carry the result unconditionally.
|
|
35269
|
+
*/
|
|
35270
|
+
async runGrammarParse(query) {
|
|
35271
|
+
return parseQueryWithLlmAssist(query, this.grammarLlmAssist, {
|
|
35272
|
+
...this.agentRegistry !== void 0 ? { registry: this.agentRegistry } : {},
|
|
35273
|
+
eventClassEnum: CANONICAL_AUDIT_EVENT_CLASSES
|
|
35274
|
+
});
|
|
35275
|
+
}
|
|
34543
35276
|
/**
|
|
34544
35277
|
* Emit the WP-V1.3-9 Tau-3 fetcher-failure audit event. Pulled out
|
|
34545
35278
|
* of the fold path so the dynamic-context handler stays readable.
|
|
@@ -37051,7 +37784,7 @@ var init_memory = __esm({
|
|
|
37051
37784
|
|
|
37052
37785
|
// src/contracts/v1.1/constants.ts
|
|
37053
37786
|
var SIGNATURE_SCHEME_V12, EXIT_BUNDLE_MANIFEST_VERSION, EXIT_BUNDLE_ARTIFACT_KINDS;
|
|
37054
|
-
var
|
|
37787
|
+
var init_constants5 = __esm({
|
|
37055
37788
|
"src/contracts/v1.1/constants.ts"() {
|
|
37056
37789
|
SIGNATURE_SCHEME_V12 = "ed25519-v1";
|
|
37057
37790
|
EXIT_BUNDLE_MANIFEST_VERSION = "SANCTUARY_EXIT_BUNDLE_V1";
|
|
@@ -37469,7 +38202,7 @@ async function verifyExitBundle(bundleDir, options = {}) {
|
|
|
37469
38202
|
var InvalidExitBundleError, PRIVATE_MATERIAL_KEYS;
|
|
37470
38203
|
var init_verifier2 = __esm({
|
|
37471
38204
|
"src/exit/verifier.ts"() {
|
|
37472
|
-
|
|
38205
|
+
init_constants5();
|
|
37473
38206
|
init_exit_bundle_manifest();
|
|
37474
38207
|
init_encoding();
|
|
37475
38208
|
init_hashing();
|
|
@@ -38281,7 +39014,7 @@ var init_bundle = __esm({
|
|
|
38281
39014
|
"src/exit/bundle.ts"() {
|
|
38282
39015
|
init_state_store();
|
|
38283
39016
|
init_config();
|
|
38284
|
-
|
|
39017
|
+
init_constants5();
|
|
38285
39018
|
init_canonical_json();
|
|
38286
39019
|
init_hashing();
|
|
38287
39020
|
init_encoding();
|