@sixb/sqlite 0.1.25 → 0.1.26

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.
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAmI3B,eAAO,MAAM,yBAAyB,sBAAsB,CAAA;AAC5D,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD,eAAO,MAAM,uBAAuB,wBAyKlC,CAAA;AAEF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAQ9E;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC1C,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,QAAQ,CAAC,CAEzB;AAOD,mGAAmG;AACnG,wBAAgB,mBAAmB,IAAI,QAAQ,CAY9C;AAaD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAOzF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC5C,GAAG,eAAe,CAoBlB;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1E"}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAmI3B,eAAO,MAAM,yBAAyB,sBAAsB,CAAA;AAC5D,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD,eAAO,MAAM,uBAAuB,wBA2KlC,CAAA;AAEF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAQ9E;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC1C,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,QAAQ,CAAC,CAEzB;AAOD,mGAAmG;AACnG,wBAAgB,mBAAmB,IAAI,QAAQ,CAY9C;AAaD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAOzF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC5C,GAAG,eAAe,CAoBlB;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"query-compiler.d.ts","sourceRoot":"","sources":["../../src/objects/query-compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-compiler.d.ts","sourceRoot":"","sources":["../../src/objects/query-compiler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sixb/sqlite",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "SQLite storage provider for Sixb",
5
5
  "keywords": [
6
6
  "sixb",
@@ -37,10 +37,10 @@
37
37
  "prepack": "bun run build"
38
38
  },
39
39
  "peerDependencies": {
40
- "@sixb/core": "0.1.25"
40
+ "@sixb/core": "0.1.26"
41
41
  },
42
42
  "devDependencies": {
43
- "@sixb/core": "0.1.25",
43
+ "@sixb/core": "0.1.26",
44
44
  "@types/bun": "latest",
45
45
  "typescript": "^5.7.0"
46
46
  },
@@ -120,6 +120,19 @@ export class SqliteAgentMessageStore implements AgentMessageStore {
120
120
 
121
121
  async deleteByRunId(input: DeleteAgentMessagesByRunInput): Promise<number> {
122
122
  return this.db.transaction(() => {
123
+ if (input.fence) {
124
+ const owner = this.db
125
+ .query(
126
+ "SELECT 1 AS present FROM agent_runs WHERE project_id = ? AND id = ? AND status = 'running' AND execution_token = ?"
127
+ )
128
+ .get(input.projectId, input.fence.runId, input.fence.executionToken)
129
+ if (!owner) {
130
+ throw new AgentStorageError(
131
+ "execution_lost",
132
+ `[SixbSqlite] Execution token is no longer current on agent run '${input.fence.runId}'.`
133
+ )
134
+ }
135
+ }
123
136
  const thread = this.db
124
137
  .query("SELECT 1 AS present FROM agent_threads WHERE project_id = ? AND id = ?")
125
138
  .get(input.projectId, input.threadId) as { present: number } | null
@@ -32,6 +32,8 @@ export interface AgentThreadRow {
32
32
  title: string | null
33
33
  sandbox_params: string | null
34
34
  sandbox_state: string | null
35
+ runs_on: "computer" | null
36
+ computer_id: string | null
35
37
  status: AgentThreadRecord["status"]
36
38
  active_run_id: string | null
37
39
  last_message_at: string | null
@@ -69,6 +71,7 @@ export interface AgentRunRow {
69
71
  attempt: number
70
72
  execution_token: string | null
71
73
  execution_queue_lease_expires_at: string | null
74
+ cancel_requested_at: string | null
72
75
  created_at: string
73
76
  started_at: string | null
74
77
  completed_at: string | null
@@ -133,6 +136,8 @@ export function rowToThreadRecord(row: AgentThreadRow): AgentThreadRecord {
133
136
  ...(row.sandbox_params == null
134
137
  ? {}
135
138
  : { sandboxParams: snapshotAgentThreadSandboxParams(JSON.parse(row.sandbox_params)) }),
139
+ ...(row.runs_on == null ? {} : { runsOn: row.runs_on }),
140
+ ...(row.computer_id == null ? {} : { computerId: row.computer_id }),
136
141
  status: row.status,
137
142
  activeRunId: row.active_run_id,
138
143
  lastMessageAt: row.last_message_at ? new Date(row.last_message_at) : undefined,
@@ -161,6 +166,7 @@ export function rowToRunRecord(row: AgentRunRow): AgentRunRecord {
161
166
  queueLeaseExpiresAt: new Date(row.execution_queue_lease_expires_at),
162
167
  }
163
168
  : undefined,
169
+ cancelRequestedAt: row.cancel_requested_at ? new Date(row.cancel_requested_at) : undefined,
164
170
  createdAt: new Date(row.created_at),
165
171
  startedAt: row.started_at ? new Date(row.started_at) : undefined,
166
172
  completedAt: row.completed_at ? new Date(row.completed_at) : undefined,
@@ -29,6 +29,7 @@ import {
29
29
  type ListAgentRunsResult,
30
30
  type ListThreadSubagentsInput,
31
31
  type ReclaimAgentRunInput,
32
+ type RequestAgentRunCancelInput,
32
33
  type StartAgentRunInput,
33
34
  type SubagentRunRecord,
34
35
  } from "@sixb/core/storage"
@@ -326,7 +327,17 @@ export class SqliteAgentRunStore implements AgentRunStore {
326
327
 
327
328
  async reclaim(input: ReclaimAgentRunInput): Promise<AgentRunRecord> {
328
329
  return this.db.transaction(() => {
329
- this.requireRunning(input.projectId, input.id)
330
+ const run = this.requireRunning(input.projectId, input.id)
331
+ if (
332
+ input.ifLapsedBy &&
333
+ run.execution_queue_lease_expires_at !== null &&
334
+ new Date(run.execution_queue_lease_expires_at).getTime() > input.ifLapsedBy.getTime()
335
+ ) {
336
+ throw new AgentStorageError(
337
+ "invalid_state",
338
+ `[SixbSqlite] Agent run '${input.id}' is still held by its runner, whose lease has not lapsed.`
339
+ )
340
+ }
330
341
  this.db
331
342
  .query(
332
343
  `
@@ -373,6 +384,21 @@ export class SqliteAgentRunStore implements AgentRunStore {
373
384
  })()
374
385
  }
375
386
 
387
+ async requestCancel(input: RequestAgentRunCancelInput): Promise<AgentRunRecord> {
388
+ return this.db.transaction(() => {
389
+ this.db
390
+ .query(
391
+ `
392
+ UPDATE agent_runs
393
+ SET cancel_requested_at = ?
394
+ WHERE project_id = ? AND id = ? AND status = 'running' AND cancel_requested_at IS NULL
395
+ `
396
+ )
397
+ .run((input.at ?? new Date()).toISOString(), input.projectId, input.id)
398
+ return this.requireRun(input.projectId, input.id)
399
+ })()
400
+ }
401
+
376
402
  async finish(input: FinishAgentRunInput): Promise<AgentRunRecord> {
377
403
  const completedAt = input.completedAt ?? new Date()
378
404
  const errorValue =
@@ -1,6 +1,9 @@
1
1
  import type { Database } from "bun:sqlite"
2
2
  import {
3
+ assertAssignableComputer,
4
+ assertComputerId,
3
5
  assertConversationThreadRow,
6
+ assertRunsOn,
4
7
  participantsToAdd,
5
8
  planAgentThreadFork,
6
9
  remapArtifactIds,
@@ -15,6 +18,7 @@ import {
15
18
  type AgentThreadRecord,
16
19
  type AgentThreadSandboxState,
17
20
  type AgentThreadStore,
21
+ type AssignAgentThreadComputerInput,
18
22
  type CreateAgentThreadInput,
19
23
  type ForkAgentThreadInput,
20
24
  type ListAgentThreadChildrenInput,
@@ -64,6 +68,7 @@ export class SqliteAgentThreadStore implements AgentThreadStore {
64
68
  }
65
69
 
66
70
  async create(input: CreateAgentThreadInput): Promise<AgentThreadRecord> {
71
+ assertRunsOn(input.runsOn, "Agent thread", "SixbSqlite")
67
72
  const sandboxParams =
68
73
  input.sandboxParams === undefined
69
74
  ? null
@@ -82,13 +87,14 @@ export class SqliteAgentThreadStore implements AgentThreadStore {
82
87
  owner_principal_id,
83
88
  title,
84
89
  sandbox_params,
90
+ runs_on,
85
91
  status,
86
92
  active_run_id,
87
93
  last_message_at,
88
94
  message_count,
89
95
  created_at,
90
96
  updated_at
91
- ) VALUES (?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, ?, ?)
97
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, ?, ?)
92
98
  `
93
99
  )
94
100
  .run(
@@ -98,6 +104,7 @@ export class SqliteAgentThreadStore implements AgentThreadStore {
98
104
  input.ownerPrincipal.id,
99
105
  input.title ?? null,
100
106
  sandboxParams,
107
+ input.runsOn ?? null,
101
108
  input.status ?? "active",
102
109
  createdAt.toISOString(),
103
110
  updatedAt.toISOString()
@@ -403,6 +410,25 @@ export class SqliteAgentThreadStore implements AgentThreadStore {
403
410
  return result.changes > 0
404
411
  }
405
412
 
413
+ async assignComputer(input: AssignAgentThreadComputerInput): Promise<AgentThreadRecord> {
414
+ assertComputerId(input.computerId, "SixbSqlite")
415
+ this.db
416
+ .query(`
417
+ UPDATE agent_threads SET computer_id = ?
418
+ WHERE project_id = ? AND id = ? AND runs_on = 'computer'
419
+ ${input.ifUnassigned ? "AND computer_id IS NULL" : ""}
420
+ `)
421
+ .run(input.computerId, input.projectId, input.id)
422
+
423
+ // Read in the same tick: nothing else writes to the database in between.
424
+ const row = this.db
425
+ .query("SELECT * FROM agent_threads WHERE project_id = ? AND id = ?")
426
+ .get(input.projectId, input.id) as AgentThreadRow | null
427
+ const thread = row ? rowToThreadRecord(row) : null
428
+ assertAssignableComputer(thread, input.id, "SixbSqlite")
429
+ return thread
430
+ }
431
+
406
432
  async listParticipants(
407
433
  input: ListAgentThreadParticipantsInput
408
434
  ): Promise<readonly AgentThreadParticipantRecord[]> {
@@ -0,0 +1,3 @@
1
+ -- A cancel is recorded on the run, not only broadcast: a runner that never hears the broker learns
2
+ -- of it at its next lease renewal, and the run token stops working at once.
3
+ ALTER TABLE agent_runs ADD COLUMN cancel_requested_at TEXT;
@@ -0,0 +1,4 @@
1
+ -- Where a conversation's turns run: NULL in the cloud, 'computer' on its owner's computer.
2
+ ALTER TABLE agent_threads ADD COLUMN runs_on TEXT CHECK (runs_on IS NULL OR runs_on = 'computer');
3
+ -- Which of its owner's computers runs a computer's thread: NULL until one claims its first turn.
4
+ ALTER TABLE agent_threads ADD COLUMN computer_id TEXT;
package/src/migrations.ts CHANGED
@@ -311,6 +311,8 @@ export const sqliteStorageMigrations = defineMigrations({
311
311
  { checksum: checksum(subagentThreadsSql) }
312
312
  ),
313
313
  sqliteSql("079-subagent-questions", subagentQuestionsSql),
314
+ sqliteSql("080-agent-run-cancel-requests", agentRunCancelRequestsSql),
315
+ sqliteSql("081-agent-thread-runs-on", agentThreadRunsOnSql),
314
316
  ],
315
317
  })
316
318
 
@@ -709,3 +711,7 @@ import agentApprovalResumeSql from "./migrations/077-agent-approval-resume.sql"
709
711
  }
710
712
  import subagentThreadsSql from "./migrations/078-subagent-threads.sql" with { type: "text" }
711
713
  import subagentQuestionsSql from "./migrations/079-subagent-questions.sql" with { type: "text" }
714
+ import agentRunCancelRequestsSql from "./migrations/080-agent-run-cancel-requests.sql" with {
715
+ type: "text",
716
+ }
717
+ import agentThreadRunsOnSql from "./migrations/081-agent-thread-runs-on.sql" with { type: "text" }
@@ -698,12 +698,12 @@ function compileExpansionsObject(
698
698
  return { sql: `json_object(${parts.join(", ")})`, args }
699
699
  }
700
700
 
701
- // One expansion's hydrated value. `row_number()` numbers a parent's links by the
702
- // order from `compileExpansionOrder` (the expansion's `orderBy` against the target
703
- // object's properties, then an identity tiebreak); `WHERE _ord <= N` keeps the
704
- // top-N per parent in-DB; each retained neighbour becomes a JSON object; and the
705
- // value is an ordered array ("many") or the first element or null ("one"). The
706
- // cardinality is core-resolved before pushdown.
701
+ // One expansion's hydrated value. A parent's links are read in the order from
702
+ // `compileExpansionOrder` (the expansion's `orderBy` against the target object's
703
+ // properties, then an identity tiebreak) and `LIMIT N` keeps the top-N per parent
704
+ // in-DB; each retained neighbour becomes a JSON object; and the value is an
705
+ // ordered array ("many", numbered by `row_number()` for `json_group_array`) or the
706
+ // first neighbour or null ("one"). The cardinality is core-resolved before pushdown.
707
707
  function compileExpansionValue(
708
708
  expansion: ObjectExpansion,
709
709
  parent: ExpansionParent,
@@ -736,8 +736,7 @@ function compileExpansionValue(
736
736
  whereArgs.push(expansion.sourceObjectTypeId)
737
737
  }
738
738
 
739
- const inner = `
740
- SELECT ${child.sql} AS elem, row_number() OVER (ORDER BY ${order.sql}) AS _ord
739
+ const from = `
741
740
  FROM ${ctx.source.linksTable} AS ${edge}
742
741
  JOIN ${ctx.source.objectsTable} AS ${target}
743
742
  ON ${target}.project_id = ${edge}.project_id
@@ -745,12 +744,13 @@ function compileExpansionValue(
745
744
  AND ${target}.primary_id = ${neighborId}
746
745
  WHERE ${whereParts.join(" AND ")}
747
746
  `
748
- const innerArgs = [...child.args, ...order.args, ...whereArgs]
749
747
 
748
+ // ORDER BY ... LIMIT stops at the kept neighbours, so only they are built as JSON. Filtering
749
+ // on row_number() would build every neighbour first, in a co-routine per parent.
750
750
  if (expansion.cardinality === "one") {
751
751
  return {
752
- sql: `(SELECT ${ranked}.elem FROM (${inner}) AS ${ranked} WHERE ${ranked}._ord = 1)`,
753
- args: innerArgs,
752
+ sql: `(SELECT ${child.sql} ${from} ORDER BY ${order.sql} LIMIT 1)`,
753
+ args: [...child.args, ...whereArgs, ...order.args],
754
754
  }
755
755
  }
756
756
 
@@ -759,8 +759,13 @@ function compileExpansionValue(
759
759
  // rather than the quoted JSON text the subquery column hands back.
760
760
  const limit = expansion.limit ?? DEFAULT_EXPANSION_FANOUT
761
761
  return {
762
- sql: `COALESCE((SELECT json_group_array(json(${ranked}.elem) ORDER BY ${ranked}._ord) FROM (${inner}) AS ${ranked} WHERE ${ranked}._ord <= ?), '[]')`,
763
- args: [...innerArgs, limit],
762
+ sql: `COALESCE((SELECT json_group_array(json(${ranked}.elem) ORDER BY ${ranked}._ord) FROM (
763
+ SELECT ${child.sql} AS elem, row_number() OVER (ORDER BY ${order.sql}) AS _ord
764
+ ${from}
765
+ ORDER BY ${order.sql}
766
+ LIMIT ?
767
+ ) AS ${ranked}), '[]')`,
768
+ args: [...child.args, ...order.args, ...whereArgs, ...order.args, limit],
764
769
  }
765
770
  }
766
771