@volter/teams 0.1.55 → 0.1.57

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/teams",
3
- "version": "0.1.55",
3
+ "version": "0.1.57",
4
4
  "type": "module",
5
5
  "description": "Volter Teams, the neutral team plane: machine identity and daemon core, the local door and server link, admission from machine grants, product doors, and the Teams server's neutral routes (company RFC 0008).",
6
6
  "license": "MIT",
package/server/core.mjs CHANGED
@@ -69,6 +69,17 @@ export async function maintain(api){const now=api.clock.nowMs();
69
69
  // they go (a backlog of them filled the database).
70
70
  const parts=await api.store.query(`SELECT p.team_id,p.capture_id,p.part_index FROM capture_parts p JOIN captures c ON c.team_id=p.team_id AND c.id=p.capture_id WHERE c.state='committed' LIMIT ${PART_PRUNE_BATCH}`,[]);
71
71
  for(let at=0;at<parts.length;at+=50)await api.store.transaction(parts.slice(at,at+50).map(({team_id,capture_id,part_index})=>({sql:'DELETE FROM capture_parts WHERE team_id=? AND capture_id=? AND part_index=?',params:[team_id,capture_id,part_index]})));
72
+ // Retired versions release their native bundles. Keep every bundle still named by a version,
73
+ // continuation (including completed receipts), or in-flight capture. Never-committed uploads retain their one-day grace.
74
+ const orphaned=await api.store.query(`SELECT u.team_id,u.id FROM uploads u WHERE u.committed=1
75
+ AND NOT EXISTS (SELECT 1 FROM session_artifacts a WHERE a.team_id=u.team_id AND a.upload_id=u.id)
76
+ AND NOT EXISTS (SELECT 1 FROM continuations c WHERE c.team_id=u.team_id AND instr(c.value_json,u.id)>0)
77
+ AND NOT EXISTS (SELECT 1 FROM captures c WHERE c.team_id=u.team_id AND c.state='staging' AND instr(c.begin_json,u.id)>0)
78
+ LIMIT 10`,[]);
79
+ for(const upload of orphaned)await api.store.transaction([{sql:`DELETE FROM uploads AS u WHERE team_id=? AND id=? AND committed=1
80
+ AND NOT EXISTS (SELECT 1 FROM session_artifacts a WHERE a.team_id=u.team_id AND a.upload_id=u.id)
81
+ AND NOT EXISTS (SELECT 1 FROM continuations c WHERE c.team_id=u.team_id AND instr(c.value_json,u.id)>0)
82
+ AND NOT EXISTS (SELECT 1 FROM captures c WHERE c.team_id=u.team_id AND c.state='staging' AND instr(c.begin_json,u.id)>0)`,params:[upload.team_id,upload.id]}]);
72
83
  // Every capture writes its session a new version (its messages are carried, not copied: schema 9), so versions pile
73
84
  // up (hundreds per session) until listing them outgrew a Worker's memory. Kept: each session's current version, the newest
74
85
  // version from each of its sources (the next capture and a correlation read that one), and every version an
@@ -85,14 +96,6 @@ export async function maintain(api){const now=api.clock.nowMs();
85
96
  {sql:'UPDATE messages SET revision=(SELECT MIN(k.revision) FROM session_versions k WHERE k.team_id=messages.team_id AND k.session_id=messages.session_id AND k.revision>messages.revision AND k.revision<COALESCE(messages.until_revision,messages.revision+1)) WHERE team_id=? AND session_id=? AND revision=? AND EXISTS (SELECT 1 FROM session_versions k WHERE k.team_id=messages.team_id AND k.session_id=messages.session_id AND k.revision>messages.revision AND k.revision<COALESCE(messages.until_revision,messages.revision+1))',params:[team_id,session_id,revision]},
86
97
  ...['messages','session_artifacts','session_versions'].map(table=>({sql:`DELETE FROM ${table} WHERE team_id=? AND session_id=? AND revision=?`,params:[team_id,session_id,revision]})),
87
98
  ]);
88
- // Retired versions release their native bundles. Keep every bundle still named by a version,
89
- // continuation (including completed receipts), or in-flight capture, and leave a full day for uploads.
90
- const orphaned=await api.store.query(`SELECT u.team_id,u.id FROM uploads u WHERE u.committed=1 AND u.created_at+86400000<=?
91
- AND NOT EXISTS (SELECT 1 FROM session_artifacts a WHERE a.team_id=u.team_id AND a.upload_id=u.id)
92
- AND NOT EXISTS (SELECT 1 FROM continuations c WHERE c.team_id=u.team_id AND instr(c.value_json,u.id)>0)
93
- AND NOT EXISTS (SELECT 1 FROM captures c WHERE c.team_id=u.team_id AND c.state='staging' AND instr(c.begin_json,u.id)>0)
94
- LIMIT 10`,[now]);
95
- for(const upload of orphaned)await api.store.transaction([{sql:'DELETE FROM uploads WHERE team_id=? AND id=?',params:[upload.team_id,upload.id]}]);
96
99
  await api.store.transaction([
97
100
  {sql:'DELETE FROM cursors WHERE expires_at<=?',params:[now]},
98
101
  {sql:'DELETE FROM global_cursors WHERE expires_at<=?',params:[now]},
@@ -4,6 +4,8 @@ export interface TeamSessionSnapshot {
4
4
  messages: Array<{ id: string; source_id?: string; native_key?: string; recorded_at?: number | null; value: { role: string; content?: unknown; metadata?: Record<string, unknown>; [field: string]: unknown } }>;
5
5
  names?: { members?: Array<{ principal?: { id: string; display_name?: string } }>; machines?: Array<{ id: string; name?: string }> };
6
6
  working?: unknown;
7
+ /** A fresh native observation. Unknown/stale activity never implies that a turn completed. */
8
+ turnActivity?: { state: 'working' | 'idle' | 'needs_input' | 'unknown'; since?: number; observedAt?: number };
7
9
  event_cursor?: string | number;
8
10
  revision?: number;
9
11
  [field: string]: unknown;