@chatpanel/events 0.102.0 → 0.104.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/adapters.js +1 -83
- package/adaptive-tool-policy.js +1 -45
- package/agent.js +2 -255
- package/attribution.js +1 -132
- package/backup-envelope.js +1 -221
- package/board-tool.js +2 -165
- package/budget.js +1 -116
- package/capability.js +1 -126
- package/citations.js +5 -127
- package/client-prefs.js +1 -148
- package/context-attachments.js +8 -144
- package/cowriter-router.js +1 -83
- package/cowriter-writer.js +19 -193
- package/cowriter.js +1 -190
- package/curate.js +3 -509
- package/distance.js +1 -124
- package/engine.js +1 -131
- package/entitlement.js +1 -332
- package/entity.js +1 -354
- package/event.js +1 -175
- package/extraction.js +4 -293
- package/failover.js +1 -93
- package/find-tool.js +1 -66
- package/flowchart.js +2 -644
- package/gate.js +1 -74
- package/harness.js +4 -101
- package/index.js +1 -345
- package/invariants.js +1 -174
- package/job.js +3 -147
- package/kernel.js +1 -255
- package/knowledge-derive.js +1 -267
- package/knowledge.js +3 -230
- package/library.js +11 -280
- package/loop.js +1 -132
- package/manifest.js +1 -107
- package/markdown-authoring.js +11 -288
- package/markdown-render.js +0 -0
- package/mcp-client.js +8 -358
- package/mcp-dispatch.js +1 -52
- package/mcp-errors.js +1 -106
- package/mcp-manager.js +1 -127
- package/media-transcript.js +8 -531
- package/meeting-analyzers.js +1 -83
- package/meeting-insights.js +7 -164
- package/meeting-shape.js +1 -282
- package/meeting-text.js +5 -94
- package/memory.js +2 -638
- package/model-candidates.js +1 -358
- package/model-health.js +1 -182
- package/model-ledger.js +1 -228
- package/model-picker.js +1 -188
- package/note-actions.js +15 -246
- package/note-graph.js +1 -158
- package/note-links.js +1 -68
- package/note-mentions.js +8 -114
- package/note-plan.js +9 -107
- package/note-research.js +1 -135
- package/observability.js +1 -119
- package/omni.js +1 -125
- package/order.js +1 -78
- package/package.json +4 -5
- package/pdf-layout.js +7 -253
- package/policy.js +1 -0
- package/project-run.js +20 -444
- package/project.js +1 -170
- package/promotion.js +1 -171
- package/queue.js +1 -98
- package/reach.js +1 -23
- package/recipe-tool.js +2 -161
- package/recipe.js +1 -264
- package/record-list.js +2 -110
- package/recruit.js +3 -456
- package/redaction-tokens.js +1 -61
- package/ref.js +1 -55
- package/registry.js +1 -240
- package/route-graph.js +1 -115
- package/route-strategies.js +2 -232
- package/router.js +2 -880
- package/rrf.js +1 -89
- package/rules.js +1 -142
- package/schedule.js +1 -663
- package/scm-connection.js +1 -180
- package/scopes.js +1 -12
- package/scorecard.js +1 -335
- package/search-engines.js +1 -81
- package/skill-manifest.js +1 -330
- package/skill-scan.js +3 -209
- package/skill-sources.js +1 -162
- package/skill-vars.js +2 -252
- package/slash-commands.js +1 -158
- package/source-gate.js +1 -92
- package/sources-retrieval.js +5 -186
- package/sources.js +1 -273
- package/store.js +1 -171
- package/structured.js +4 -901
- package/subject-kinds.js +1 -5
- package/subject-name.js +1 -96
- package/sync-plan.js +1 -213
- package/synthesis.js +3 -123
- package/tags.js +1 -203
- package/team-board.js +6 -337
- package/team-cache.js +2 -63
- package/team-observe.js +1 -118
- package/team-org.js +1 -442
- package/team-plan.js +4 -131
- package/team-record.js +1 -225
- package/team-run.js +9 -652
- package/team-subtask.js +2 -191
- package/team-task.js +2 -124
- package/team-tool.js +2 -196
- package/team-trail.js +2 -73
- package/team-worklog.js +2 -149
- package/team.js +1 -302
- package/text-search.js +1 -155
- package/theme.js +17 -154
- package/titles.js +4 -285
- package/tool-discovery.js +1 -87
- package/tool-dispatch.js +5 -230
- package/tool-groups.js +1 -81
- package/tool-hints.js +10 -185
- package/tool-loop-guard.js +4 -182
- package/tool-need.js +2 -124
- package/tool-result.js +2 -438
- package/tool-round.js +0 -0
- package/tool-schema.js +1 -155
- package/tool-traits.js +1 -182
- package/toolset.js +2 -88
- package/trajectory.js +1 -530
- package/turn-loop.js +4 -440
- package/upcast.js +1 -37
- package/vault.js +2 -250
- package/view.js +1 -88
- package/voice-intents.js +2 -1488
- package/voice-speaker.js +1 -98
- package/weather-tool.js +1 -65
- package/weather.js +2 -211
- package/web-search-tool.js +14 -102
- package/web-search.js +1 -160
- package/widget.js +1 -153
package/store.js
CHANGED
|
@@ -1,171 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// PERSISTENCE IS A HOST ADAPTER. The spine is host-independent, so the *semantics* live
|
|
4
|
-
// here and each host supplies the storage underneath: IndexedDB in the extension,
|
|
5
|
-
// SQLite on a gateway or daemon, a capped ring buffer colocated. One in-memory adapter
|
|
6
|
-
// ships here because tests, colocated hosts and the replay harness all want it.
|
|
7
|
-
//
|
|
8
|
-
// TWO STORES, DELIBERATELY SEPARATE.
|
|
9
|
-
// • the LOG holds events — small, uniform, append-only, ~300-500 B each;
|
|
10
|
-
// • the BLOB store holds content, addressed by hash and deduped, so the same note
|
|
11
|
-
// excerpt attached across a hundred turns costs one copy.
|
|
12
|
-
// Keeping them apart is what makes crypto-shredding work: drop a blob and the event
|
|
13
|
-
// skeleton, causality chain and audit trail all survive.
|
|
14
|
-
//
|
|
15
|
-
// APPEND IS IDEMPOTENT ON EVENT ID. Replicating the log to a warm tier can retry
|
|
16
|
-
// safely — the log-level counterpart of the idempotency keys capabilities carry.
|
|
17
|
-
|
|
18
|
-
import { validateEvent, EventError } from './event.js';
|
|
19
|
-
import { linearize } from './order.js';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Minimal adapter contract a host implements.
|
|
23
|
-
* get(key) -> value | undefined put(key, value) delete(key)
|
|
24
|
-
* keys(prefix?) -> string[] size() -> bytes (approximate)
|
|
25
|
-
*/
|
|
26
|
-
export function createMemoryAdapter() {
|
|
27
|
-
const map = new Map();
|
|
28
|
-
return {
|
|
29
|
-
get: (k) => map.get(k),
|
|
30
|
-
put: (k, v) => { map.set(k, v); },
|
|
31
|
-
delete: (k) => map.delete(k),
|
|
32
|
-
keys: (prefix = '') => [...map.keys()].filter((k) => k.startsWith(prefix)).sort(),
|
|
33
|
-
size: () => {
|
|
34
|
-
let n = 0;
|
|
35
|
-
for (const [k, v] of map) n += k.length + (typeof v === 'string' ? v.length : JSON.stringify(v).length);
|
|
36
|
-
return n;
|
|
37
|
-
},
|
|
38
|
-
clear: () => map.clear(),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const EV = 'e/'; // event by id
|
|
43
|
-
const SEQ = 's/'; // host -> highest seq seen
|
|
44
|
-
|
|
45
|
-
/** The append-only event log over a host adapter. */
|
|
46
|
-
export function createLogStore(adapter = createMemoryAdapter()) {
|
|
47
|
-
const store = {
|
|
48
|
-
/**
|
|
49
|
-
* Append a validated event. Idempotent on `id`: re-appending the same event is a
|
|
50
|
-
* no-op returning `{ appended: false }`, so replication retries are safe.
|
|
51
|
-
* Rejects a seq that moves backwards for a host — that is a corrupt writer, not a gap.
|
|
52
|
-
*/
|
|
53
|
-
append(event) {
|
|
54
|
-
validateEvent(event);
|
|
55
|
-
if (adapter.get(EV + event.id) !== undefined) return { appended: false, event };
|
|
56
|
-
const highest = adapter.get(SEQ + event.host);
|
|
57
|
-
if (highest !== undefined && event.seq <= highest) {
|
|
58
|
-
throw new EventError('SEQ', `seq ${event.seq} <= ${highest} already seen for host ${event.host}`, event.host);
|
|
59
|
-
}
|
|
60
|
-
adapter.put(EV + event.id, event);
|
|
61
|
-
adapter.put(SEQ + event.host, event.seq);
|
|
62
|
-
return { appended: true, event };
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
appendAll(events) {
|
|
66
|
-
const res = events.map((e) => store.append(e));
|
|
67
|
-
return { appended: res.filter((r) => r.appended).length, total: events.length };
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
get: (id) => adapter.get(EV + id),
|
|
71
|
-
has: (id) => adapter.get(EV + id) !== undefined,
|
|
72
|
-
|
|
73
|
-
all: () => adapter.keys(EV).map((k) => adapter.get(k)),
|
|
74
|
-
|
|
75
|
-
/** Every event in replay order — the only ordering anything should read. */
|
|
76
|
-
ordered: () => linearize(store.all()),
|
|
77
|
-
|
|
78
|
-
byType: (type) => store.all().filter((e) => e.type === type),
|
|
79
|
-
|
|
80
|
-
/** One host's slice, for replication cursors. */
|
|
81
|
-
range({ host, fromSeq = 0, toSeq = Infinity } = {}) {
|
|
82
|
-
return store.all()
|
|
83
|
-
.filter((e) => (!host || e.host === host) && e.seq >= fromSeq && e.seq <= toSeq)
|
|
84
|
-
.sort((a, b) => a.seq - b.seq);
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
/** Highest seq per host — the cursor a replica sends to ask for what it lacks. */
|
|
88
|
-
cursor() {
|
|
89
|
-
const out = {};
|
|
90
|
-
for (const k of adapter.keys(SEQ)) out[k.slice(SEQ.length)] = adapter.get(k);
|
|
91
|
-
return out;
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
/** Events a replica with this cursor has not seen. */
|
|
95
|
-
since(cursor = {}) {
|
|
96
|
-
return store.all()
|
|
97
|
-
.filter((e) => e.seq > (cursor[e.host] ?? -1))
|
|
98
|
-
.sort((a, b) => (a.host === b.host ? a.seq - b.seq : a.host < b.host ? -1 : 1));
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
/** Walk the causality chain backwards from an event. */
|
|
102
|
-
ancestry(id, seen = new Set()) {
|
|
103
|
-
const e = store.get(id);
|
|
104
|
-
if (!e || seen.has(id)) return [];
|
|
105
|
-
seen.add(id);
|
|
106
|
-
return [e, ...e.causes.flatMap((c) => store.ancestry(c, seen))];
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
stats: () => ({ events: adapter.keys(EV).length, bytes: adapter.size() }),
|
|
110
|
-
};
|
|
111
|
-
return store;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Content-addressed blob store. Dedupes by hash, so attaching the same excerpt a
|
|
116
|
-
* hundred times costs one copy — the rule that keeps the log from growing linearly in
|
|
117
|
-
* content.
|
|
118
|
-
*
|
|
119
|
-
* `digest` is injected: no ambient dependency on a crypto implementation, and tests stay
|
|
120
|
-
* deterministic. Defaults to SHA-256 via WebCrypto, present in browsers and Node >= 18.
|
|
121
|
-
*/
|
|
122
|
-
export function createBlobStore(adapter = createMemoryAdapter(), { digest = sha256Hex } = {}) {
|
|
123
|
-
const B = 'b/';
|
|
124
|
-
const store = {
|
|
125
|
-
async put(content) {
|
|
126
|
-
const hash = await digest(content);
|
|
127
|
-
const key = B + hash;
|
|
128
|
-
if (adapter.get(key) === undefined) adapter.put(key, content);
|
|
129
|
-
return hash;
|
|
130
|
-
},
|
|
131
|
-
get: (hash) => adapter.get(B + hash),
|
|
132
|
-
has: (hash) => adapter.get(B + hash) !== undefined,
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* CRYPTO-SHRED. Drops the payload and leaves a tombstone, so "delete this meeting"
|
|
136
|
-
* can be honoured against an append-only log: the content is unrecoverable while
|
|
137
|
-
* every event that referenced it, and the causality chain, stay intact. Replay then
|
|
138
|
-
* reports verified-but-unavailable rather than substituting current content.
|
|
139
|
-
*/
|
|
140
|
-
shred(hash) {
|
|
141
|
-
if (adapter.get(B + hash) === undefined) return false;
|
|
142
|
-
adapter.delete(B + hash);
|
|
143
|
-
adapter.put(`t/${hash}`, { shredded: true });
|
|
144
|
-
return true;
|
|
145
|
-
},
|
|
146
|
-
isShredded: (hash) => adapter.get(`t/${hash}`) !== undefined,
|
|
147
|
-
|
|
148
|
-
/** Resolve a Ref the way replay must: exact, shredded, or absent. */
|
|
149
|
-
lookup(ref) {
|
|
150
|
-
const value = store.get(ref.hash);
|
|
151
|
-
if (value === undefined) return null;
|
|
152
|
-
return { hash: ref.hash, value };
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
stats: () => ({
|
|
156
|
-
blobs: adapter.keys(B).length,
|
|
157
|
-
shredded: adapter.keys('t/').length,
|
|
158
|
-
bytes: adapter.size(),
|
|
159
|
-
}),
|
|
160
|
-
};
|
|
161
|
-
return store;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Global WebCrypto: present in every browser and in Node from 19 onward. Callers on an
|
|
165
|
-
// older or unusual runtime inject their own `digest` rather than the package reaching
|
|
166
|
-
// for `node:crypto`, which would put a Node import in a browser-first module.
|
|
167
|
-
async function sha256Hex(content) {
|
|
168
|
-
const bytes = typeof content === 'string' ? new TextEncoder().encode(content) : content;
|
|
169
|
-
const buf = await globalThis.crypto.subtle.digest('SHA-256', bytes);
|
|
170
|
-
return `sha256:${[...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, '0')).join('')}`;
|
|
171
|
-
}
|
|
1
|
+
import{validateEvent as h,EventError as g}from"./event.js";import{linearize as c}from"./order.js";function f(){const t=new Map;return{get:r=>t.get(r),put:(r,e)=>{t.set(r,e)},delete:r=>t.delete(r),keys:(r="")=>[...t.keys()].filter(e=>e.startsWith(r)).sort(),size:()=>{let r=0;for(const[e,s]of t)r+=e.length+(typeof s=="string"?s.length:JSON.stringify(s).length);return r},clear:()=>t.clear()}}const i="e/",u="s/";function a(t=f()){const r={append(e){if(h(e),t.get(i+e.id)!==void 0)return{appended:!1,event:e};const s=t.get(u+e.host);if(s!==void 0&&e.seq<=s)throw new g("SEQ",`seq ${e.seq} <= ${s} already seen for host ${e.host}`,e.host);return t.put(i+e.id,e),t.put(u+e.host,e.seq),{appended:!0,event:e}},appendAll(e){return{appended:e.map(n=>r.append(n)).filter(n=>n.appended).length,total:e.length}},get:e=>t.get(i+e),has:e=>t.get(i+e)!==void 0,all:()=>t.keys(i).map(e=>t.get(e)),ordered:()=>c(r.all()),byType:e=>r.all().filter(s=>s.type===e),range({host:e,fromSeq:s=0,toSeq:n=1/0}={}){return r.all().filter(o=>(!e||o.host===e)&&o.seq>=s&&o.seq<=n).sort((o,l)=>o.seq-l.seq)},cursor(){const e={};for(const s of t.keys(u))e[s.slice(u.length)]=t.get(s);return e},since(e={}){return r.all().filter(s=>s.seq>(e[s.host]??-1)).sort((s,n)=>s.host===n.host?s.seq-n.seq:s.host<n.host?-1:1)},ancestry(e,s=new Set){const n=r.get(e);return!n||s.has(e)?[]:(s.add(e),[n,...n.causes.flatMap(o=>r.ancestry(o,s))])},stats:()=>({events:t.keys(i).length,bytes:t.size()})};return r}function k(t=f(),{digest:r=d}={}){const s={async put(n){const o=await r(n),l="b/"+o;return t.get(l)===void 0&&t.put(l,n),o},get:n=>t.get("b/"+n),has:n=>t.get("b/"+n)!==void 0,shred(n){return t.get("b/"+n)===void 0?!1:(t.delete("b/"+n),t.put(`t/${n}`,{shredded:!0}),!0)},isShredded:n=>t.get(`t/${n}`)!==void 0,lookup(n){const o=s.get(n.hash);return o===void 0?null:{hash:n.hash,value:o}},stats:()=>({blobs:t.keys("b/").length,shredded:t.keys("t/").length,bytes:t.size()})};return s}async function d(t){const r=typeof t=="string"?new TextEncoder().encode(t):t,e=await globalThis.crypto.subtle.digest("SHA-256",r);return`sha256:${[...new Uint8Array(e)].map(s=>s.toString(16).padStart(2,"0")).join("")}`}export{k as createBlobStore,a as createLogStore,f as createMemoryAdapter};
|