sentinelayer-cli 0.41.0 → 0.42.0
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/README.md +18 -0
- package/package.json +3 -2
- package/src/auth/admission-scope.js +34 -0
- package/src/auth/gate.js +6 -0
- package/src/auth/http.js +4 -0
- package/src/auth/service.js +6 -0
- package/src/board/done-gate.js +155 -0
- package/src/board/evidence-resolvers.js +138 -0
- package/src/cli.js +24 -1
- package/src/commands/board.js +116 -0
- package/src/commands/session.js +483 -47
- package/src/engram/build-state.js +183 -0
- package/src/engram/canonical.js +75 -0
- package/src/engram/document.js +190 -0
- package/src/engram/index.js +11 -2
- package/src/engram/ingest-document.js +107 -0
- package/src/engram/store.js +6 -1
- package/src/engram/tools.js +6 -0
- package/src/events/schema.js +18 -0
- package/src/legacy-cli.js +2 -2
- package/src/net/test-egress-guard.js +158 -0
- package/src/review/investor-dd-orchestrator.js +14 -2
- package/src/session/admission-auth.js +312 -0
- package/src/session/admission-preimage.js +90 -0
- package/src/session/admission.js +620 -0
- package/src/session/checkpoints.js +25 -1
- package/src/session/codebase-context.js +54 -0
- package/src/session/coordination-guidance.js +1 -1
- package/src/session/daemon-spawn.js +20 -2
- package/src/session/daemon.js +7 -1
- package/src/session/event-identity.js +9 -2
- package/src/session/first-message.js +11 -3
- package/src/session/listener.js +3 -0
- package/src/session/live-source.js +47 -16
- package/src/session/message-edits.js +89 -0
- package/src/session/recap.js +26 -4
- package/src/session/remote-hydrate.js +7 -19
- package/src/session/store.js +13 -14
- package/src/session/stream.js +23 -3
- package/src/session/sync.js +128 -11
- package/src/session/tickets.js +316 -0
- package/src/session/title-sync.js +2 -1
- package/src/session/usage-report.js +41 -2
- package/src/session/wake/resolve-target.js +10 -5
|
@@ -64,6 +64,45 @@ function optionalUsdCell(value, hasValue) {
|
|
|
64
64
|
return hasValue ? usdCell(value) : "-";
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
function booleanFlag(value) {
|
|
68
|
+
if (typeof value === "boolean") return value;
|
|
69
|
+
if (typeof value === "number" && Number.isFinite(value)) return value !== 0;
|
|
70
|
+
const text = normalize(value).toLowerCase();
|
|
71
|
+
if (!text) return null;
|
|
72
|
+
if (["1", "true", "t", "yes", "y"].includes(text)) return true;
|
|
73
|
+
if (["0", "false", "f", "no", "n"].includes(text)) return false;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function hasHostedCustomerCost(bag) {
|
|
78
|
+
const camelFlag = booleanFlag(bag.hasCustomerCost);
|
|
79
|
+
if (camelFlag != null) return camelFlag;
|
|
80
|
+
const snakeFlag = booleanFlag(bag.has_customer_cost);
|
|
81
|
+
if (snakeFlag != null) return snakeFlag;
|
|
82
|
+
return [
|
|
83
|
+
bag.customerCostUsd,
|
|
84
|
+
bag.customer_cost_usd,
|
|
85
|
+
bag.billableCostUsd,
|
|
86
|
+
bag.billable_cost_usd,
|
|
87
|
+
].some((value) => value != null && value !== "");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function rollupCostSummary(rollup = {}) {
|
|
91
|
+
const parts = [`provider ${usdCell(rollup.providerCostUsd)}`];
|
|
92
|
+
if (rollup.customerCostUsd != null) {
|
|
93
|
+
parts.push(`customer ${usdCell(rollup.customerCostUsd)}`);
|
|
94
|
+
}
|
|
95
|
+
const unpriced = nonNegativeInt(rollup.unpriced);
|
|
96
|
+
if (unpriced > 0) {
|
|
97
|
+
parts.push(`unpriced ${intCell(unpriced)}`);
|
|
98
|
+
}
|
|
99
|
+
const estimatedEntries = nonNegativeInt(rollup.estimatedEntries);
|
|
100
|
+
if (estimatedEntries > 0) {
|
|
101
|
+
parts.push(`estimated ${intCell(estimatedEntries)}`);
|
|
102
|
+
}
|
|
103
|
+
return parts.join(", ");
|
|
104
|
+
}
|
|
105
|
+
|
|
67
106
|
function timestampOnly(iso) {
|
|
68
107
|
if (!iso) return "";
|
|
69
108
|
const date = new Date(iso);
|
|
@@ -122,7 +161,7 @@ function rollupToJson(rollup) {
|
|
|
122
161
|
|
|
123
162
|
function hostedRollupToJson(rollup, fallbackLabel = "") {
|
|
124
163
|
const bag = object(rollup);
|
|
125
|
-
const hasCustomerCost =
|
|
164
|
+
const hasCustomerCost = hasHostedCustomerCost(bag);
|
|
126
165
|
return {
|
|
127
166
|
label: normalize(bag.label ?? bag.agentId ?? bag.agent_id ?? bag.action ?? fallbackLabel) || "unknown",
|
|
128
167
|
entries: nonNegativeInt(bag.entries ?? bag.entryCount ?? bag.entry_count ?? bag.count ?? bag.interactions),
|
|
@@ -412,7 +451,7 @@ export function renderSessionUsageSummary(report = {}) {
|
|
|
412
451
|
lines.push("Per agent:");
|
|
413
452
|
for (const agent of agents) {
|
|
414
453
|
lines.push(
|
|
415
|
-
`- ${agent.label}: ${intCell(agent.totalTokens)} tokens, ${intCell(agent.entries)} entries,
|
|
454
|
+
`- ${agent.label}: ${intCell(agent.totalTokens)} tokens, ${intCell(agent.entries)} entries, ${rollupCostSummary(agent)}`,
|
|
416
455
|
);
|
|
417
456
|
}
|
|
418
457
|
}
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
// transitive graph (auth/sync/`open`/...) into the wake daemon. The matcher
|
|
17
17
|
// here is small enough to own.
|
|
18
18
|
|
|
19
|
+
import { messageRevision, sessionMessageEditSnapshot, sessionMessageRoutingEvent } from "../message-edits.js";
|
|
20
|
+
|
|
19
21
|
const BROADCAST_RECIPIENTS = new Set(["*", "all", "broadcast", "everyone", "anyone", "agents", "all-agents"]);
|
|
20
|
-
const DEFAULT_WAKE_EVENT_TYPES = new Set(["session_message", "help_request"]);
|
|
22
|
+
const DEFAULT_WAKE_EVENT_TYPES = new Set(["session_message", "help_request", "session_message_edited"]);
|
|
21
23
|
const MAX_WAKE_MESSAGE_CHARS = 16_000;
|
|
22
24
|
|
|
23
25
|
function requireNonEmptyString(value, label) {
|
|
@@ -98,7 +100,7 @@ function defaultFormatMessage(event, agentId) {
|
|
|
98
100
|
const author = agentIdOf(event) || "unknown";
|
|
99
101
|
const text = event?.payload?.message ?? event?.message ?? "";
|
|
100
102
|
const body = typeof text === "string" ? text : "";
|
|
101
|
-
const head = `Senti wake for ${agentId}: new message from ${author}.`;
|
|
103
|
+
const head = `Senti wake for ${agentId}: ${event.event === "session_message_edited" ? "edited message" : "new message"} from ${author}.`;
|
|
102
104
|
const combined = body ? `${head}\n\n${body}` : head;
|
|
103
105
|
return combined.length > MAX_WAKE_MESSAGE_CHARS ? combined.slice(0, MAX_WAKE_MESSAGE_CHARS) : combined;
|
|
104
106
|
}
|
|
@@ -128,18 +130,21 @@ export function createResolveTarget({
|
|
|
128
130
|
// Only wake on real message events; acks/reactions/views/system are skips.
|
|
129
131
|
const type = eventTypeOf(event);
|
|
130
132
|
if (!type || !wakeEventTypes.has(type)) return null;
|
|
133
|
+
if (type === "session_message" && messageRevision(event) > 1) return null;
|
|
134
|
+
if (type === "session_message_edited" && !sessionMessageEditSnapshot(event)) return null;
|
|
135
|
+
const routed = sessionMessageRoutingEvent(event);
|
|
131
136
|
|
|
132
137
|
// No self-wake: never wake the agent on its own message. Normalize both
|
|
133
138
|
// sides (handles @-prefix / casing / punctuation) so the loop-guard can't
|
|
134
139
|
// be slipped by a non-canonical author id.
|
|
135
|
-
const author = agentIdOf(
|
|
140
|
+
const author = agentIdOf(routed);
|
|
136
141
|
if (author && normalizeComparableId(author) === selfLower) return null;
|
|
137
142
|
|
|
138
143
|
// Routing: directed-to-me / broadcast / untargeted-room wakes us; a message
|
|
139
144
|
// aimed at a different specific agent is intentionally unroutable.
|
|
140
|
-
if (!matchesAgent(
|
|
145
|
+
if (!matchesAgent(routed, selfLower)) return null;
|
|
141
146
|
|
|
142
|
-
return { host: hostName, sessionId: resumeId, message: formatMessage(event, selfId) };
|
|
147
|
+
return { host: hostName, sessionId: resumeId, message: formatMessage({ ...routed, event: type }, selfId) };
|
|
143
148
|
};
|
|
144
149
|
}
|
|
145
150
|
|