@sixb/sqlite 0.1.2 → 0.1.3

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/src/index.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  createWorkflowRunOperationScope,
20
20
  } from "@sixb/core/internal/storage-operation-scope"
21
21
  import {
22
+ type AiCostStorage,
22
23
  type AiUsageStorage,
23
24
  createTransactionStorageProxy,
24
25
  StorageTransactionError,
@@ -26,6 +27,7 @@ import {
26
27
  } from "@sixb/core/storage"
27
28
  import { SqliteActionRunStorage } from "./action-run-storage"
28
29
  import { SqliteAgentStorage } from "./agents"
30
+ import { SqliteAiCostStorage } from "./ai-cost-storage"
29
31
  import { SqliteAiUsageStorage } from "./ai-usage-storage"
30
32
  import { SqliteAuthStorage } from "./auth-storage"
31
33
  import { SqliteConnectorConnectionStorage } from "./connector-connection-storage"
@@ -61,8 +63,8 @@ export interface SqliteStorageOptions {
61
63
  /**
62
64
  * SQLite storage provider for Sixb.
63
65
  *
64
- * Bundles object, timeseries, auth, execution, AI usage, sync run, pipeline run, projection run,
65
- * workflow run, webhook run, and connector connection storage backed by SQLite.
66
+ * Bundles object, timeseries, auth, execution, AI accounting, sync run, pipeline run, projection
67
+ * run, workflow run, webhook run, and connector connection storage backed by SQLite.
66
68
  *
67
69
  * Usage:
68
70
  * ```ts
@@ -81,6 +83,7 @@ export class SqliteStorage implements MigrationCapableStorage {
81
83
  readonly executions: SqliteExecutionStorage
82
84
  readonly agents: SqliteAgentStorage
83
85
  readonly aiUsage: AiUsageStorage
86
+ readonly aiCosts: AiCostStorage
84
87
  readonly actionRuns: SqliteActionRunStorage
85
88
  readonly pipelineRuns: SqlitePipelineRunStorage
86
89
  readonly syncRuns: SqliteSyncRunStorage
@@ -143,6 +146,7 @@ export class SqliteStorage implements MigrationCapableStorage {
143
146
  this.executions = createOperationScopedFacade(stores.executions, scope)
144
147
  this.agents = createAgentOperationScope(stores.agents, scope)
145
148
  this.aiUsage = createOperationScopedFacade(stores.aiUsage, scope)
149
+ this.aiCosts = createOperationScopedFacade(stores.aiCosts, scope)
146
150
  this.actionRuns = createOperationScopedFacade(stores.actionRuns, scope)
147
151
  this.pipelineRuns = createOperationScopedFacade(stores.pipelineRuns, scope)
148
152
  this.timeseries = createOperationScopedFacade(readTimeseries, readScope)
@@ -298,6 +302,7 @@ function createSqliteStores(
298
302
  executions,
299
303
  agents: new SqliteAgentStorage({ connection, executions }),
300
304
  aiUsage: new SqliteAiUsageStorage({ connection }),
305
+ aiCosts: new SqliteAiCostStorage(connection),
301
306
  actionRuns: new SqliteActionRunStorage({ connection, executions }),
302
307
  pipelineRuns: new SqlitePipelineRunStorage({ connection, executions }),
303
308
  timeseries: new SqliteTimeseriesStorage({ connection }),
@@ -318,6 +323,7 @@ interface SqliteStoreSet {
318
323
  readonly executions: SqliteExecutionStorage
319
324
  readonly agents: SqliteAgentStorage
320
325
  readonly aiUsage: SqliteAiUsageStorage
326
+ readonly aiCosts: SqliteAiCostStorage
321
327
  readonly actionRuns: SqliteActionRunStorage
322
328
  readonly pipelineRuns: SqlitePipelineRunStorage
323
329
  readonly syncRuns: SqliteSyncRunStorage
@@ -0,0 +1,57 @@
1
+ CREATE TABLE ai_model_call_valuations (
2
+ project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
3
+ usage_record_id TEXT NOT NULL CHECK (length(trim(usage_record_id)) > 0),
4
+ status TEXT NOT NULL CHECK (status IN ('rated', 'unpriceable')),
5
+ provider_id TEXT CHECK (provider_id IS NULL OR length(trim(provider_id)) > 0),
6
+ model_id TEXT CHECK (model_id IS NULL OR length(trim(model_id)) > 0),
7
+ currency TEXT CHECK (
8
+ currency IS NULL OR (length(currency) = 3 AND currency GLOB '[A-Z][A-Z][A-Z]')
9
+ ),
10
+ amount_nanos INTEGER CHECK (
11
+ amount_nanos IS NULL OR (typeof(amount_nanos) = 'integer' AND amount_nanos >= 0)
12
+ ),
13
+ reason TEXT CHECK (
14
+ reason IS NULL OR reason IN (
15
+ 'missingBillingIdentity',
16
+ 'missingCatalogEntry',
17
+ 'missingUsageMeter',
18
+ 'unsupportedPricingDimension',
19
+ 'invalidUsageForFormula'
20
+ )
21
+ ),
22
+ details TEXT NOT NULL CHECK (json_valid(details) AND json_type(details) = 'object'),
23
+ rated_at TEXT NOT NULL CHECK (length(trim(rated_at)) > 0),
24
+ PRIMARY KEY (project_id, usage_record_id),
25
+ FOREIGN KEY (project_id, usage_record_id)
26
+ REFERENCES ai_model_call_usage(project_id, id)
27
+ ON DELETE RESTRICT,
28
+ CHECK (
29
+ (
30
+ status = 'rated'
31
+ AND provider_id IS NOT NULL
32
+ AND model_id IS NOT NULL
33
+ AND currency IS NOT NULL
34
+ AND amount_nanos IS NOT NULL
35
+ AND reason IS NULL
36
+ )
37
+ OR
38
+ (
39
+ status = 'unpriceable'
40
+ AND currency IS NULL
41
+ AND amount_nanos IS NULL
42
+ AND reason IS NOT NULL
43
+ AND (
44
+ (reason = 'missingBillingIdentity' AND provider_id IS NULL AND model_id IS NULL)
45
+ OR
46
+ (reason <> 'missingBillingIdentity' AND provider_id IS NOT NULL AND model_id IS NOT NULL)
47
+ )
48
+ )
49
+ )
50
+ );
51
+
52
+ CREATE INDEX idx_ai_model_call_usage_provider_model_time
53
+ ON ai_model_call_usage (project_id, provider_id, requested_model_id, occurred_at, id);
54
+ CREATE INDEX idx_ai_model_call_usage_model_time
55
+ ON ai_model_call_usage (project_id, requested_model_id, occurred_at, id);
56
+ CREATE INDEX idx_ai_model_call_valuations_summary
57
+ ON ai_model_call_valuations (project_id, status, currency, usage_record_id);
@@ -0,0 +1,28 @@
1
+ CREATE TABLE agent_context_checkpoints (
2
+ project_id TEXT NOT NULL,
3
+ id TEXT NOT NULL,
4
+ thread_id TEXT NOT NULL,
5
+ created_by_run_id TEXT NOT NULL,
6
+ previous_checkpoint_id TEXT,
7
+ reason TEXT NOT NULL CHECK (reason IN ('threshold', 'overflow')),
8
+ summary TEXT NOT NULL CHECK (length(trim(summary)) > 0),
9
+ summary_format_version INTEGER NOT NULL CHECK (summary_format_version = 1),
10
+ summarized_through_seq INTEGER NOT NULL CHECK (summarized_through_seq >= 1),
11
+ observed_head_seq INTEGER NOT NULL,
12
+ estimated_input_tokens_before INTEGER NOT NULL CHECK (estimated_input_tokens_before >= 0),
13
+ estimated_input_tokens_after INTEGER NOT NULL CHECK (estimated_input_tokens_after >= 0),
14
+ summary_model_id TEXT NOT NULL CHECK (length(trim(summary_model_id)) > 0),
15
+ created_at TEXT NOT NULL,
16
+ PRIMARY KEY (project_id, id),
17
+ UNIQUE (project_id, created_by_run_id),
18
+ FOREIGN KEY (project_id, thread_id)
19
+ REFERENCES agent_threads(project_id, id) ON DELETE CASCADE,
20
+ FOREIGN KEY (project_id, created_by_run_id)
21
+ REFERENCES agent_runs(project_id, id) ON DELETE RESTRICT,
22
+ FOREIGN KEY (project_id, previous_checkpoint_id)
23
+ REFERENCES agent_context_checkpoints(project_id, id) ON DELETE RESTRICT,
24
+ CHECK (summarized_through_seq < observed_head_seq)
25
+ );
26
+
27
+ CREATE INDEX idx_agent_context_checkpoints_thread_latest
28
+ ON agent_context_checkpoints(project_id, thread_id, summarized_through_seq DESC, created_at DESC, id DESC);
@@ -0,0 +1,3 @@
1
+ ALTER TABLE ontology_object_overrides
2
+ ADD COLUMN edited_at TEXT NOT NULL DEFAULT '{}'
3
+ CHECK (json_valid(edited_at) AND json_type(edited_at) = 'object');
package/src/migrations.ts CHANGED
@@ -69,6 +69,13 @@ import ontologyCommitExecutionsSql from "./migrations/024-ontology-commit-execut
69
69
  import connectorConnectionsSql from "./migrations/025-connector-connections.sql" with {
70
70
  type: "text",
71
71
  }
72
+ import aiCostAccountingSql from "./migrations/026-ai-cost-accounting.sql" with { type: "text" }
73
+ import agentContextCheckpointsSql from "./migrations/027-agent-context-checkpoints.sql" with {
74
+ type: "text",
75
+ }
76
+ import objectOverrideEditTimesSql from "./migrations/028-object-override-edit-times.sql" with {
77
+ type: "text",
78
+ }
72
79
 
73
80
  const MIGRATIONS_TABLE_SQL = `
74
81
  CREATE TABLE IF NOT EXISTS sixb_migrations (
@@ -149,6 +156,9 @@ export const sqliteStorageMigrations = defineMigrations({
149
156
  { checksum: checksum(ontologyCommitExecutionsSql) }
150
157
  ),
151
158
  sqliteSql("025-connector-connections", connectorConnectionsSql),
159
+ sqliteSql("026-ai-cost-accounting", aiCostAccountingSql),
160
+ sqliteSql("027-agent-context-checkpoints", agentContextCheckpointsSql),
161
+ sqliteSql("028-object-override-edit-times", objectOverrideEditTimesSql),
152
162
  ],
153
163
  })
154
164
 
@@ -86,6 +86,7 @@ interface LinkScopeRow extends EffectiveLinkRow {
86
86
  interface ObjectOverrideRow extends SqliteStoredOverrideRow {
87
87
  readonly object_type_id: string
88
88
  readonly primary_id: string
89
+ readonly edited_at: string
89
90
  }
90
91
 
91
92
  interface LinkOverrideRow extends SqliteStoredOverrideRow {
@@ -1028,6 +1029,7 @@ function storedObjectOverride(row: ObjectOverrideRow): StoredObjectOverride {
1028
1029
  return {
1029
1030
  ref,
1030
1031
  value: parseJson<StoredObjectOverride["value"]>(row.value),
1032
+ editedAt: parseJson<Readonly<Record<string, string>>>(row.edited_at),
1031
1033
  lastCommitId: row.last_commit_id,
1032
1034
  updatedAt: row.updated_at,
1033
1035
  }
@@ -41,14 +41,16 @@ export class SqliteMaterializationWriter {
41
41
  this.db
42
42
  .query(
43
43
  `INSERT INTO ontology_object_overrides (
44
- project_id, object_type_id, primary_id, value, last_commit_id, updated_at
45
- ) VALUES (?, ?, ?, json(?), ?, ?)`
44
+ project_id, object_type_id, primary_id, value, edited_at,
45
+ last_commit_id, updated_at
46
+ ) VALUES (?, ?, ?, json(?), json(?), ?, ?)`
46
47
  )
47
48
  .run(
48
49
  projectId,
49
50
  item.ref.objectTypeId,
50
51
  item.ref.primaryId,
51
52
  canonicalJson(item.value),
53
+ canonicalJson(item.editedAt),
52
54
  item.lastCommitId,
53
55
  item.updatedAt
54
56
  )
@@ -64,12 +66,13 @@ export class SqliteMaterializationWriter {
64
66
  this.db
65
67
  .query(
66
68
  `UPDATE ontology_object_overrides
67
- SET value = json(?), last_commit_id = ?, updated_at = ?
69
+ SET value = json(?), edited_at = json(?), last_commit_id = ?, updated_at = ?
68
70
  WHERE project_id = ? AND object_type_id = ? AND primary_id = ?
69
71
  AND last_commit_id = ?`
70
72
  )
71
73
  .run(
72
74
  canonicalJson(item.value),
75
+ canonicalJson(item.editedAt),
73
76
  item.lastCommitId,
74
77
  item.updatedAt,
75
78
  projectId,