@sixb/sqlite 0.1.25 → 0.2.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/dist/agents/agent-storage.d.ts +8 -3
- package/dist/agents/agent-storage.d.ts.map +1 -1
- package/dist/agents/computers.d.ts +22 -0
- package/dist/agents/computers.d.ts.map +1 -0
- package/dist/agents/messages.d.ts.map +1 -1
- package/dist/agents/rows.d.ts +6 -0
- package/dist/agents/rows.d.ts.map +1 -1
- package/dist/agents/runs.d.ts +2 -1
- package/dist/agents/runs.d.ts.map +1 -1
- package/dist/agents/threads.d.ts +4 -1
- package/dist/agents/threads.d.ts.map +1 -1
- package/dist/agents/token-rates.d.ts +13 -0
- package/dist/agents/token-rates.d.ts.map +1 -0
- package/dist/ai-accounting-filters.d.ts +14 -0
- package/dist/ai-accounting-filters.d.ts.map +1 -0
- package/dist/ai-cost-groups.d.ts +1 -1
- package/dist/ai-cost-groups.d.ts.map +1 -1
- package/dist/ai-cost-storage.d.ts.map +1 -1
- package/dist/index.js +465 -63
- package/dist/index.js.map +17 -14
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/query-compiler.d.ts.map +1 -1
- package/dist/ontology-storage/commits.d.ts.map +1 -1
- package/dist/ontology-storage/materializations.d.ts +2 -1
- package/dist/ontology-storage/materializations.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/agents/agent-storage.ts +10 -3
- package/src/agents/computers.ts +112 -0
- package/src/agents/messages.ts +13 -0
- package/src/agents/rows.ts +14 -0
- package/src/agents/runs.ts +52 -4
- package/src/agents/threads.ts +108 -4
- package/src/agents/token-rates.ts +90 -0
- package/src/ai-accounting-filters.ts +51 -0
- package/src/ai-cost-groups.ts +52 -14
- package/src/ai-cost-storage.ts +101 -39
- package/src/migrations/080-agent-run-cancel-requests.sql +3 -0
- package/src/migrations/081-agent-thread-runs-on.sql +4 -0
- package/src/migrations/082-agent-token-rates.sql +17 -0
- package/src/migrations/083-agent-computer-sessions.sql +27 -0
- package/src/migrations.ts +12 -0
- package/src/objects/query-compiler.ts +44 -28
- package/src/ontology-storage/commits.ts +9 -0
- package/src/ontology-storage/materializations.ts +18 -1
package/dist/index.js
CHANGED
|
@@ -5962,6 +5962,69 @@ CREATE INDEX idx_agent_runs_paused_on_question
|
|
|
5962
5962
|
WHERE kind = 'subagent' AND finish_reason = 'awaiting_answer';
|
|
5963
5963
|
`;
|
|
5964
5964
|
|
|
5965
|
+
// src/migrations/080-agent-run-cancel-requests.sql
|
|
5966
|
+
var _080_agent_run_cancel_requests_default = `-- A cancel is recorded on the run, not only broadcast: a runner that never hears the broker learns
|
|
5967
|
+
-- of it at its next lease renewal, and the run token stops working at once.
|
|
5968
|
+
ALTER TABLE agent_runs ADD COLUMN cancel_requested_at TEXT;
|
|
5969
|
+
`;
|
|
5970
|
+
|
|
5971
|
+
// src/migrations/081-agent-thread-runs-on.sql
|
|
5972
|
+
var _081_agent_thread_runs_on_default = `-- Where a conversation's turns run: NULL in the cloud, 'computer' on its owner's computer.
|
|
5973
|
+
ALTER TABLE agent_threads ADD COLUMN runs_on TEXT CHECK (runs_on IS NULL OR runs_on = 'computer');
|
|
5974
|
+
-- Which of its owner's computers runs a computer's thread: NULL until one claims its first turn.
|
|
5975
|
+
ALTER TABLE agent_threads ADD COLUMN computer_id TEXT;
|
|
5976
|
+
`;
|
|
5977
|
+
|
|
5978
|
+
// src/migrations/082-agent-token-rates.sql
|
|
5979
|
+
var _082_agent_token_rates_default = `-- What each model's tokenizer measured on a project's agent runs, one row per run: the bytes of a
|
|
5980
|
+
-- request's text as the Agent's context estimator weighs them, against the text tokens the
|
|
5981
|
+
-- provider counted. A record deletes the model's rows past its newest 20, so the table stays small.
|
|
5982
|
+
-- Timestamps are ISO-8601 UTC text and compare lexicographically.
|
|
5983
|
+
CREATE TABLE agent_token_rates (
|
|
5984
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
5985
|
+
run_id TEXT NOT NULL CHECK (length(trim(run_id)) > 0),
|
|
5986
|
+
provider_id TEXT NOT NULL CHECK (length(trim(provider_id)) > 0),
|
|
5987
|
+
model_id TEXT NOT NULL CHECK (length(trim(model_id)) > 0),
|
|
5988
|
+
bytes INTEGER NOT NULL CHECK (bytes > 0),
|
|
5989
|
+
tokens INTEGER NOT NULL CHECK (tokens > 0),
|
|
5990
|
+
measured_at TEXT NOT NULL,
|
|
5991
|
+
PRIMARY KEY (project_id, run_id)
|
|
5992
|
+
);
|
|
5993
|
+
|
|
5994
|
+
CREATE INDEX idx_agent_token_rates_model
|
|
5995
|
+
ON agent_token_rates (project_id, provider_id, model_id, measured_at DESC, run_id DESC);
|
|
5996
|
+
`;
|
|
5997
|
+
|
|
5998
|
+
// src/migrations/083-agent-computer-sessions.sql
|
|
5999
|
+
var _083_agent_computer_sessions_default = `-- Where a computer's thread runs: the computer's name and the folder there, beside its id. A
|
|
6000
|
+
-- computer kept before folders were has none until its owner moves the thread.
|
|
6001
|
+
ALTER TABLE agent_threads ADD COLUMN computer_name TEXT;
|
|
6002
|
+
ALTER TABLE agent_threads ADD COLUMN computer_folder TEXT;
|
|
6003
|
+
UPDATE agent_threads SET computer_id = NULL WHERE computer_id IS NOT NULL;
|
|
6004
|
+
-- When its turns last moved to where they run now: the files earlier turns used are not there.
|
|
6005
|
+
ALTER TABLE agent_threads ADD COLUMN moved_at TEXT;
|
|
6006
|
+
|
|
6007
|
+
-- Each open sixb on its owner's computers, a lease it renews: while one is live, the threads that
|
|
6008
|
+
-- run on its computer in its folder are reachable there.
|
|
6009
|
+
CREATE TABLE agent_computer_sessions (
|
|
6010
|
+
project_id TEXT NOT NULL,
|
|
6011
|
+
owner_principal_type TEXT NOT NULL CHECK (owner_principal_type IN ('user', 'serviceAccount', 'system')),
|
|
6012
|
+
owner_principal_id TEXT NOT NULL CHECK (length(owner_principal_id) > 0),
|
|
6013
|
+
id TEXT NOT NULL CHECK (length(id) > 0),
|
|
6014
|
+
computer_id TEXT NOT NULL,
|
|
6015
|
+
computer_name TEXT NOT NULL,
|
|
6016
|
+
folder TEXT NOT NULL,
|
|
6017
|
+
expires_at TEXT NOT NULL,
|
|
6018
|
+
PRIMARY KEY (project_id, owner_principal_type, owner_principal_id, id)
|
|
6019
|
+
);
|
|
6020
|
+
CREATE INDEX agent_computer_sessions_by_expiry ON agent_computer_sessions (project_id, expires_at);
|
|
6021
|
+
|
|
6022
|
+
-- Each open sixb asks every 20 seconds which of its owner's threads here have a turn active.
|
|
6023
|
+
CREATE INDEX agent_threads_active_on_computer
|
|
6024
|
+
ON agent_threads (project_id, owner_principal_type, owner_principal_id, computer_id, computer_folder)
|
|
6025
|
+
WHERE active_run_id IS NOT NULL;
|
|
6026
|
+
`;
|
|
6027
|
+
|
|
5965
6028
|
// src/migrations.ts
|
|
5966
6029
|
var MIGRATIONS_TABLE_SQL = `
|
|
5967
6030
|
CREATE TABLE IF NOT EXISTS sixb_migrations (
|
|
@@ -6095,7 +6158,11 @@ var sqliteStorageMigrations = defineMigrations({
|
|
|
6095
6158
|
throw new Error("[SixbSqliteStorage] Agent runs, threads or messages were lost while giving sub-agents their threads.");
|
|
6096
6159
|
}
|
|
6097
6160
|
}, { checksum: checksum(_078_subagent_threads_default) }),
|
|
6098
|
-
sqliteSql("079-subagent-questions", _079_subagent_questions_default)
|
|
6161
|
+
sqliteSql("079-subagent-questions", _079_subagent_questions_default),
|
|
6162
|
+
sqliteSql("080-agent-run-cancel-requests", _080_agent_run_cancel_requests_default),
|
|
6163
|
+
sqliteSql("081-agent-thread-runs-on", _081_agent_thread_runs_on_default),
|
|
6164
|
+
sqliteSql("082-agent-token-rates", _082_agent_token_rates_default),
|
|
6165
|
+
sqliteSql("083-agent-computer-sessions", _083_agent_computer_sessions_default)
|
|
6099
6166
|
]
|
|
6100
6167
|
});
|
|
6101
6168
|
function sqliteStoragePath(basePath) {
|
|
@@ -7061,6 +7128,11 @@ function rowToThreadRecord(row) {
|
|
|
7061
7128
|
sandboxState: JSON.parse(row.sandbox_state)
|
|
7062
7129
|
},
|
|
7063
7130
|
...row.sandbox_params == null ? {} : { sandboxParams: snapshotAgentThreadSandboxParams(JSON.parse(row.sandbox_params)) },
|
|
7131
|
+
...row.runs_on == null ? {} : { runsOn: row.runs_on },
|
|
7132
|
+
...row.computer_id == null || row.computer_name == null || row.computer_folder == null ? {} : {
|
|
7133
|
+
computer: { id: row.computer_id, name: row.computer_name, folder: row.computer_folder }
|
|
7134
|
+
},
|
|
7135
|
+
...row.moved_at == null ? {} : { movedAt: new Date(row.moved_at) },
|
|
7064
7136
|
status: row.status,
|
|
7065
7137
|
activeRunId: row.active_run_id,
|
|
7066
7138
|
lastMessageAt: row.last_message_at ? new Date(row.last_message_at) : undefined,
|
|
@@ -7084,6 +7156,7 @@ function rowToRunRecord(row) {
|
|
|
7084
7156
|
token: row.execution_token,
|
|
7085
7157
|
queueLeaseExpiresAt: new Date(row.execution_queue_lease_expires_at)
|
|
7086
7158
|
} : undefined,
|
|
7159
|
+
cancelRequestedAt: row.cancel_requested_at ? new Date(row.cancel_requested_at) : undefined,
|
|
7087
7160
|
createdAt: new Date(row.created_at),
|
|
7088
7161
|
startedAt: row.started_at ? new Date(row.started_at) : undefined,
|
|
7089
7162
|
completedAt: row.completed_at ? new Date(row.completed_at) : undefined
|
|
@@ -7542,6 +7615,55 @@ class SqliteAgentContextCheckpointStore {
|
|
|
7542
7615
|
}
|
|
7543
7616
|
}
|
|
7544
7617
|
|
|
7618
|
+
// src/agents/computers.ts
|
|
7619
|
+
import { assertAgentComputerSession } from "@sixb/core/internal/agent-run-storage-provider";
|
|
7620
|
+
|
|
7621
|
+
class SqliteAgentComputerSessionStore {
|
|
7622
|
+
db;
|
|
7623
|
+
constructor(db) {
|
|
7624
|
+
this.db = db;
|
|
7625
|
+
}
|
|
7626
|
+
async hold(input) {
|
|
7627
|
+
assertAgentComputerSession(input, "SixbSqlite");
|
|
7628
|
+
this.db.query(`INSERT INTO agent_computer_sessions (
|
|
7629
|
+
project_id, owner_principal_type, owner_principal_id, id,
|
|
7630
|
+
computer_id, computer_name, folder, expires_at
|
|
7631
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
7632
|
+
ON CONFLICT (project_id, owner_principal_type, owner_principal_id, id)
|
|
7633
|
+
DO UPDATE SET
|
|
7634
|
+
computer_id = excluded.computer_id,
|
|
7635
|
+
computer_name = excluded.computer_name,
|
|
7636
|
+
folder = excluded.folder,
|
|
7637
|
+
expires_at = excluded.expires_at`).run(input.projectId, input.ownerPrincipal.type, input.ownerPrincipal.id, input.id, input.computer.id, input.computer.name, input.computer.folder, input.expiresAt.toISOString());
|
|
7638
|
+
}
|
|
7639
|
+
async release(input) {
|
|
7640
|
+
const row = this.db.query(`DELETE FROM agent_computer_sessions
|
|
7641
|
+
WHERE project_id = ? AND owner_principal_type = ? AND owner_principal_id = ? AND id = ?
|
|
7642
|
+
RETURNING *`).get(input.projectId, input.ownerPrincipal.type, input.ownerPrincipal.id, input.id);
|
|
7643
|
+
return row && rowToSession(row);
|
|
7644
|
+
}
|
|
7645
|
+
async listLive(input) {
|
|
7646
|
+
const rows = this.db.query(`SELECT * FROM agent_computer_sessions
|
|
7647
|
+
WHERE project_id = ? AND owner_principal_type = ? AND owner_principal_id = ?
|
|
7648
|
+
AND expires_at > ?
|
|
7649
|
+
ORDER BY id`).all(input.projectId, input.ownerPrincipal.type, input.ownerPrincipal.id, input.now.toISOString());
|
|
7650
|
+
return rows.map(rowToSession);
|
|
7651
|
+
}
|
|
7652
|
+
async removeLapsed(input) {
|
|
7653
|
+
const rows = this.db.query(`DELETE FROM agent_computer_sessions WHERE project_id = ? AND expires_at <= ? RETURNING *`).all(input.projectId, input.now.toISOString());
|
|
7654
|
+
return rows.map(rowToSession);
|
|
7655
|
+
}
|
|
7656
|
+
}
|
|
7657
|
+
function rowToSession(row) {
|
|
7658
|
+
return {
|
|
7659
|
+
projectId: row.project_id,
|
|
7660
|
+
id: row.id,
|
|
7661
|
+
ownerPrincipal: { type: row.owner_principal_type, id: row.owner_principal_id },
|
|
7662
|
+
computer: { id: row.computer_id, name: row.computer_name, folder: row.folder },
|
|
7663
|
+
expiresAt: new Date(row.expires_at)
|
|
7664
|
+
};
|
|
7665
|
+
}
|
|
7666
|
+
|
|
7545
7667
|
// src/agents/memory.ts
|
|
7546
7668
|
import {
|
|
7547
7669
|
agentMemoryConflicts,
|
|
@@ -7708,6 +7830,12 @@ class SqliteAgentMessageStore {
|
|
|
7708
7830
|
}
|
|
7709
7831
|
async deleteByRunId(input) {
|
|
7710
7832
|
return this.db.transaction(() => {
|
|
7833
|
+
if (input.fence) {
|
|
7834
|
+
const owner = this.db.query("SELECT 1 AS present FROM agent_runs WHERE project_id = ? AND id = ? AND status = 'running' AND execution_token = ?").get(input.projectId, input.fence.runId, input.fence.executionToken);
|
|
7835
|
+
if (!owner) {
|
|
7836
|
+
throw new AgentStorageError3("execution_lost", `[SixbSqlite] Execution token is no longer current on agent run '${input.fence.runId}'.`);
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7711
7839
|
const thread = this.db.query("SELECT 1 AS present FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.threadId);
|
|
7712
7840
|
if (!thread) {
|
|
7713
7841
|
throw new AgentStorageError3("thread_not_found", `[SixbSqlite] Agent thread '${input.threadId}' not found for project '${input.projectId}'.`);
|
|
@@ -7782,7 +7910,9 @@ import {
|
|
|
7782
7910
|
assertConversationAgentRunSpec,
|
|
7783
7911
|
assertConversationThreadRow,
|
|
7784
7912
|
assertCreateSubagentRunInput,
|
|
7913
|
+
assertStartsOnComputer,
|
|
7785
7914
|
assertSubagentThreadTakesRun,
|
|
7915
|
+
assertTurnInThreadPlace,
|
|
7786
7916
|
newSubagentThreadRecord,
|
|
7787
7917
|
subagentRunMatchesCreateInput
|
|
7788
7918
|
} from "@sixb/core/internal/agent-run-storage-provider";
|
|
@@ -7864,7 +7994,7 @@ class SqliteAgentRunStore {
|
|
|
7864
7994
|
runId: input.id
|
|
7865
7995
|
});
|
|
7866
7996
|
return this.db.transaction(() => {
|
|
7867
|
-
const thread = this.db.query("SELECT id, kind, active_run_id FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.threadId);
|
|
7997
|
+
const thread = this.db.query("SELECT id, kind, active_run_id, runs_on FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.threadId);
|
|
7868
7998
|
if (!thread) {
|
|
7869
7999
|
throw new AgentStorageError4("thread_not_found", `[SixbSqlite] Agent thread '${input.threadId}' not found for project '${input.projectId}'.`);
|
|
7870
8000
|
}
|
|
@@ -7872,6 +8002,7 @@ class SqliteAgentRunStore {
|
|
|
7872
8002
|
if (thread.active_run_id !== null) {
|
|
7873
8003
|
throw new AgentStorageError4("active_run_exists", `[SixbSqlite] Agent thread '${input.threadId}' already has an active run '${thread.active_run_id}'.`);
|
|
7874
8004
|
}
|
|
8005
|
+
assertTurnInThreadPlace(thread.runs_on, input.spec, input.threadId, "SixbSqlite");
|
|
7875
8006
|
try {
|
|
7876
8007
|
this.db.query(`
|
|
7877
8008
|
INSERT INTO agent_runs (
|
|
@@ -7971,7 +8102,11 @@ class SqliteAgentRunStore {
|
|
|
7971
8102
|
async start(input) {
|
|
7972
8103
|
const startedAt = input.startedAt ?? new Date;
|
|
7973
8104
|
return this.db.transaction(() => {
|
|
7974
|
-
this.requireStatus(input.projectId, input.id, "queued");
|
|
8105
|
+
const run = this.requireStatus(input.projectId, input.id, "queued");
|
|
8106
|
+
if (input.onComputer) {
|
|
8107
|
+
const thread = this.db.query("SELECT computer_id AS id, computer_folder AS folder FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, run.thread_id);
|
|
8108
|
+
assertStartsOnComputer(rowToRunRecord(run), thread?.id ? thread : undefined, input.onComputer, "SixbSqlite");
|
|
8109
|
+
}
|
|
7975
8110
|
this.db.query(`
|
|
7976
8111
|
UPDATE agent_runs
|
|
7977
8112
|
SET
|
|
@@ -8001,7 +8136,10 @@ class SqliteAgentRunStore {
|
|
|
8001
8136
|
}
|
|
8002
8137
|
async reclaim(input) {
|
|
8003
8138
|
return this.db.transaction(() => {
|
|
8004
|
-
this.requireRunning(input.projectId, input.id);
|
|
8139
|
+
const run = this.requireRunning(input.projectId, input.id);
|
|
8140
|
+
if (input.ifLapsedBy && run.execution_queue_lease_expires_at !== null && new Date(run.execution_queue_lease_expires_at).getTime() > input.ifLapsedBy.getTime()) {
|
|
8141
|
+
throw new AgentStorageError4("invalid_state", `[SixbSqlite] Agent run '${input.id}' is still held by its runner, whose lease has not lapsed.`);
|
|
8142
|
+
}
|
|
8005
8143
|
this.db.query(`
|
|
8006
8144
|
UPDATE agent_runs
|
|
8007
8145
|
SET
|
|
@@ -8027,6 +8165,16 @@ class SqliteAgentRunStore {
|
|
|
8027
8165
|
return this.requireRun(input.projectId, input.id);
|
|
8028
8166
|
})();
|
|
8029
8167
|
}
|
|
8168
|
+
async requestCancel(input) {
|
|
8169
|
+
return this.db.transaction(() => {
|
|
8170
|
+
this.db.query(`
|
|
8171
|
+
UPDATE agent_runs
|
|
8172
|
+
SET cancel_requested_at = ?
|
|
8173
|
+
WHERE project_id = ? AND id = ? AND status = 'running' AND cancel_requested_at IS NULL
|
|
8174
|
+
`).run((input.at ?? new Date).toISOString(), input.projectId, input.id);
|
|
8175
|
+
return this.requireRun(input.projectId, input.id);
|
|
8176
|
+
})();
|
|
8177
|
+
}
|
|
8030
8178
|
async finish(input) {
|
|
8031
8179
|
const completedAt = input.completedAt ?? new Date;
|
|
8032
8180
|
const errorValue = input.status === "succeeded" || input.error === undefined ? null : serializeSixbFailure(input.error, AGENT_RUN_FAILURE_CODES2);
|
|
@@ -8142,6 +8290,9 @@ class SqliteAgentRunStore {
|
|
|
8142
8290
|
whereClauses.push("parent_run_id = ?");
|
|
8143
8291
|
args.push(input.parentRunId);
|
|
8144
8292
|
}
|
|
8293
|
+
if (input.excludeComputerTurns) {
|
|
8294
|
+
whereClauses.push("json_extract(spec, '$.runsOn') IS NOT 'computer'");
|
|
8295
|
+
}
|
|
8145
8296
|
appendRunListFilters(whereClauses, args, input, "COALESCE(started_at, created_at)");
|
|
8146
8297
|
const { rows, total, hasMore } = queryRunList({
|
|
8147
8298
|
db: this.db,
|
|
@@ -8259,9 +8410,15 @@ class SqliteAgentApprovalModeStore {
|
|
|
8259
8410
|
|
|
8260
8411
|
// src/agents/threads.ts
|
|
8261
8412
|
import {
|
|
8413
|
+
assertAgentThreadComputer,
|
|
8414
|
+
assertAssignableComputer,
|
|
8415
|
+
assertComputerPlace,
|
|
8262
8416
|
assertConversationThreadRow as assertConversationThreadRow2,
|
|
8417
|
+
assertMovableToCloud,
|
|
8418
|
+
movesComputerPlace,
|
|
8263
8419
|
participantsToAdd,
|
|
8264
8420
|
planAgentThreadFork,
|
|
8421
|
+
queuedTurnInCloud,
|
|
8265
8422
|
remapArtifactIds,
|
|
8266
8423
|
snapshotAgentThreadSandboxParams as snapshotAgentThreadSandboxParams2,
|
|
8267
8424
|
transitionAgentThreadSandbox
|
|
@@ -8284,6 +8441,7 @@ class SqliteAgentThreadStore {
|
|
|
8284
8441
|
}).immediate();
|
|
8285
8442
|
}
|
|
8286
8443
|
async create(input) {
|
|
8444
|
+
assertComputerPlace(input.runsOn, input.computer, "SixbSqlite");
|
|
8287
8445
|
const sandboxParams = input.sandboxParams === undefined ? null : JSON.stringify(snapshotAgentThreadSandboxParams2(input.sandboxParams));
|
|
8288
8446
|
const createdAt = input.createdAt ?? new Date;
|
|
8289
8447
|
const updatedAt = input.updatedAt ?? createdAt;
|
|
@@ -8296,14 +8454,18 @@ class SqliteAgentThreadStore {
|
|
|
8296
8454
|
owner_principal_id,
|
|
8297
8455
|
title,
|
|
8298
8456
|
sandbox_params,
|
|
8457
|
+
runs_on,
|
|
8458
|
+
computer_id,
|
|
8459
|
+
computer_name,
|
|
8460
|
+
computer_folder,
|
|
8299
8461
|
status,
|
|
8300
8462
|
active_run_id,
|
|
8301
8463
|
last_message_at,
|
|
8302
8464
|
message_count,
|
|
8303
8465
|
created_at,
|
|
8304
8466
|
updated_at
|
|
8305
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, ?, ?)
|
|
8306
|
-
`).run(input.projectId, input.id, input.ownerPrincipal.type, input.ownerPrincipal.id, input.title ?? null, sandboxParams, input.status ?? "active", createdAt.toISOString(), updatedAt.toISOString());
|
|
8467
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, ?, ?)
|
|
8468
|
+
`).run(input.projectId, input.id, input.ownerPrincipal.type, input.ownerPrincipal.id, input.title ?? null, sandboxParams, input.runsOn ?? null, input.computer?.id ?? null, input.computer?.name ?? null, input.computer?.folder ?? null, input.status ?? "active", createdAt.toISOString(), updatedAt.toISOString());
|
|
8307
8469
|
} catch (error) {
|
|
8308
8470
|
if (isUniqueConstraintError(error)) {
|
|
8309
8471
|
throw new AgentStorageError6("duplicate_id", `[SixbSqlite] Agent thread '${input.id}' already exists for project '${input.projectId}'.`);
|
|
@@ -8312,9 +8474,13 @@ class SqliteAgentThreadStore {
|
|
|
8312
8474
|
}
|
|
8313
8475
|
return this.requireThread(input.projectId, input.id);
|
|
8314
8476
|
}
|
|
8477
|
+
activeRunOf(projectId, thread) {
|
|
8478
|
+
const row = thread?.activeRunId ? this.db.query("SELECT * FROM agent_runs WHERE project_id = ? AND id = ?").get(projectId, thread.activeRunId) : null;
|
|
8479
|
+
return row ? rowToRunRecord(row) : null;
|
|
8480
|
+
}
|
|
8315
8481
|
async fork(input) {
|
|
8316
8482
|
return this.db.transaction(() => {
|
|
8317
|
-
const source = this.db.query("SELECT id, kind, active_run_id FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.sourceThreadId);
|
|
8483
|
+
const source = this.db.query("SELECT id, kind, active_run_id, runs_on, moved_at FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.sourceThreadId);
|
|
8318
8484
|
if (!source) {
|
|
8319
8485
|
throw new AgentStorageError6("thread_not_found", `[SixbSqlite] Agent thread '${input.sourceThreadId}' not found for project '${input.projectId}'.`);
|
|
8320
8486
|
}
|
|
@@ -8336,6 +8502,7 @@ class SqliteAgentThreadStore {
|
|
|
8336
8502
|
ORDER BY summarized_through_seq DESC, created_at DESC, id DESC
|
|
8337
8503
|
`).all(input.projectId, source.id);
|
|
8338
8504
|
const plan = planAgentThreadFork(input, {
|
|
8505
|
+
workspace: { runsOn: source.runs_on, movedAt: source.moved_at },
|
|
8339
8506
|
...activeRun?.trigger_message_id ? { triggerMessageId: activeRun.trigger_message_id } : {},
|
|
8340
8507
|
messages,
|
|
8341
8508
|
checkpoints: checkpoints.map(rowToContextCheckpointRecord)
|
|
@@ -8438,6 +8605,10 @@ class SqliteAgentThreadStore {
|
|
|
8438
8605
|
)`);
|
|
8439
8606
|
args.push(input.participantPrincipal.type, input.participantPrincipal.id);
|
|
8440
8607
|
}
|
|
8608
|
+
if (input.activeOnComputer) {
|
|
8609
|
+
whereClauses.push("computer_id = ? AND computer_folder = ? AND active_run_id IS NOT NULL");
|
|
8610
|
+
args.push(input.activeOnComputer.id, input.activeOnComputer.folder);
|
|
8611
|
+
}
|
|
8441
8612
|
const dir = input.order === "asc" ? "ASC" : "DESC";
|
|
8442
8613
|
const { rows, total, hasMore } = queryAgentList({
|
|
8443
8614
|
db: this.db,
|
|
@@ -8484,6 +8655,42 @@ class SqliteAgentThreadStore {
|
|
|
8484
8655
|
`).run(input.projectId, input.threadId, input.principal.type, input.principal.id);
|
|
8485
8656
|
return result.changes > 0;
|
|
8486
8657
|
}
|
|
8658
|
+
async assignComputer(input) {
|
|
8659
|
+
assertAgentThreadComputer(input.computer, "SixbSqlite");
|
|
8660
|
+
return this.db.transaction(() => {
|
|
8661
|
+
const row = this.db.query("SELECT * FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.id);
|
|
8662
|
+
const thread = row ? rowToThreadRecord(row) : null;
|
|
8663
|
+
assertAssignableComputer(thread, this.activeRunOf(input.projectId, thread), input.computer, input.id, "SixbSqlite");
|
|
8664
|
+
const movedAt = movesComputerPlace(thread, input.computer) ? (input.movedAt ?? new Date).toISOString() : null;
|
|
8665
|
+
this.db.query(`
|
|
8666
|
+
UPDATE agent_threads
|
|
8667
|
+
SET computer_id = ?, computer_name = ?, computer_folder = ?,
|
|
8668
|
+
moved_at = COALESCE(?, moved_at)
|
|
8669
|
+
WHERE project_id = ? AND id = ?
|
|
8670
|
+
`).run(input.computer.id, input.computer.name, input.computer.folder, movedAt, input.projectId, input.id);
|
|
8671
|
+
return this.requireThread(input.projectId, input.id);
|
|
8672
|
+
}).immediate();
|
|
8673
|
+
}
|
|
8674
|
+
async moveToCloud(input) {
|
|
8675
|
+
return this.db.transaction(() => {
|
|
8676
|
+
const row = this.db.query("SELECT * FROM agent_threads WHERE project_id = ? AND id = ?").get(input.projectId, input.id);
|
|
8677
|
+
const thread = row ? rowToThreadRecord(row) : null;
|
|
8678
|
+
const active = this.activeRunOf(input.projectId, thread);
|
|
8679
|
+
assertMovableToCloud(thread, active, input.id, "SixbSqlite");
|
|
8680
|
+
const queued = queuedTurnInCloud(active);
|
|
8681
|
+
if (queued) {
|
|
8682
|
+
this.db.query("UPDATE agent_runs SET spec = ? WHERE project_id = ? AND id = ?").run(JSON.stringify(queued.spec), input.projectId, queued.id);
|
|
8683
|
+
}
|
|
8684
|
+
this.db.query(`
|
|
8685
|
+
UPDATE agent_threads
|
|
8686
|
+
SET runs_on = NULL, computer_id = NULL, computer_name = NULL, computer_folder = NULL,
|
|
8687
|
+
moved_at = ?
|
|
8688
|
+
WHERE project_id = ? AND id = ?
|
|
8689
|
+
`).run((input.movedAt ?? new Date).toISOString(), input.projectId, input.id);
|
|
8690
|
+
const moved = this.requireThread(input.projectId, input.id);
|
|
8691
|
+
return { thread: moved, ...queued ? { queued } : {} };
|
|
8692
|
+
}).immediate();
|
|
8693
|
+
}
|
|
8487
8694
|
async listParticipants(input) {
|
|
8488
8695
|
return this.selectParticipants(input.projectId, [...new Set(input.threadIds)]);
|
|
8489
8696
|
}
|
|
@@ -8518,10 +8725,11 @@ class SqliteAgentThreadStore {
|
|
|
8518
8725
|
active_run_id,
|
|
8519
8726
|
last_message_at,
|
|
8520
8727
|
message_count,
|
|
8728
|
+
moved_at,
|
|
8521
8729
|
created_at,
|
|
8522
8730
|
updated_at
|
|
8523
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
8524
|
-
`).run(thread.projectId, thread.id, thread.ownerPrincipal.type, thread.ownerPrincipal.id, thread.title ?? null, thread.sandboxParams === undefined ? null : JSON.stringify(thread.sandboxParams), thread.sandboxState === undefined ? null : JSON.stringify(thread.sandboxState), thread.status, thread.lastMessageAt?.toISOString() ?? null, thread.messageCount, thread.createdAt.toISOString(), thread.updatedAt.toISOString());
|
|
8731
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?)
|
|
8732
|
+
`).run(thread.projectId, thread.id, thread.ownerPrincipal.type, thread.ownerPrincipal.id, thread.title ?? null, thread.sandboxParams === undefined ? null : JSON.stringify(thread.sandboxParams), thread.sandboxState === undefined ? null : JSON.stringify(thread.sandboxState), thread.status, thread.lastMessageAt?.toISOString() ?? null, thread.messageCount, thread.movedAt?.toISOString() ?? null, thread.createdAt.toISOString(), thread.updatedAt.toISOString());
|
|
8525
8733
|
} catch (error) {
|
|
8526
8734
|
if (isUniqueConstraintError(error)) {
|
|
8527
8735
|
throw new AgentStorageError6("duplicate_id", `[SixbSqlite] Agent thread '${thread.id}' already exists for project '${thread.projectId}'.`);
|
|
@@ -8569,6 +8777,53 @@ class SqliteAgentThreadStore {
|
|
|
8569
8777
|
}
|
|
8570
8778
|
}
|
|
8571
8779
|
|
|
8780
|
+
// src/agents/token-rates.ts
|
|
8781
|
+
import {
|
|
8782
|
+
AGENT_TOKEN_RATE_SAMPLES,
|
|
8783
|
+
assertAgentTokenRateRecord
|
|
8784
|
+
} from "@sixb/core/internal/agent-run-storage-provider";
|
|
8785
|
+
class SqliteAgentTokenRateStore {
|
|
8786
|
+
db;
|
|
8787
|
+
constructor(db) {
|
|
8788
|
+
this.db = db;
|
|
8789
|
+
}
|
|
8790
|
+
async record(input) {
|
|
8791
|
+
assertAgentTokenRateRecord(input, "SixbSqlite");
|
|
8792
|
+
runImmediateTransaction(this.db, () => {
|
|
8793
|
+
this.db.query(`INSERT INTO agent_token_rates (
|
|
8794
|
+
project_id, run_id, provider_id, model_id, bytes, tokens, measured_at
|
|
8795
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
8796
|
+
ON CONFLICT (project_id, run_id) DO UPDATE SET
|
|
8797
|
+
provider_id = excluded.provider_id, model_id = excluded.model_id,
|
|
8798
|
+
bytes = excluded.bytes, tokens = excluded.tokens, measured_at = excluded.measured_at`).run(input.projectId, input.runId, input.providerId, input.modelId, input.bytes, input.tokens, input.measuredAt.toISOString());
|
|
8799
|
+
this.db.query(`DELETE FROM agent_token_rates
|
|
8800
|
+
WHERE project_id = ?1 AND provider_id = ?2 AND model_id = ?3
|
|
8801
|
+
AND run_id NOT IN (
|
|
8802
|
+
SELECT run_id FROM agent_token_rates
|
|
8803
|
+
WHERE project_id = ?1 AND provider_id = ?2 AND model_id = ?3
|
|
8804
|
+
ORDER BY measured_at DESC, run_id DESC
|
|
8805
|
+
LIMIT ?4
|
|
8806
|
+
)`).run(input.projectId, input.providerId, input.modelId, AGENT_TOKEN_RATE_SAMPLES);
|
|
8807
|
+
});
|
|
8808
|
+
}
|
|
8809
|
+
async listLatest(input) {
|
|
8810
|
+
const rows = this.db.query(`SELECT project_id, run_id, provider_id, model_id, bytes, tokens, measured_at
|
|
8811
|
+
FROM agent_token_rates
|
|
8812
|
+
WHERE project_id = ? AND provider_id = ? AND model_id = ?
|
|
8813
|
+
ORDER BY measured_at DESC, run_id DESC
|
|
8814
|
+
LIMIT ?`).all(input.projectId, input.providerId, input.modelId, AGENT_TOKEN_RATE_SAMPLES);
|
|
8815
|
+
return rows.map((row) => ({
|
|
8816
|
+
projectId: row.project_id,
|
|
8817
|
+
providerId: row.provider_id,
|
|
8818
|
+
modelId: row.model_id,
|
|
8819
|
+
runId: row.run_id,
|
|
8820
|
+
bytes: row.bytes,
|
|
8821
|
+
tokens: row.tokens,
|
|
8822
|
+
measuredAt: new Date(row.measured_at)
|
|
8823
|
+
}));
|
|
8824
|
+
}
|
|
8825
|
+
}
|
|
8826
|
+
|
|
8572
8827
|
// src/agents/agent-storage.ts
|
|
8573
8828
|
class SqliteAgentStorage {
|
|
8574
8829
|
threads;
|
|
@@ -8578,6 +8833,8 @@ class SqliteAgentStorage {
|
|
|
8578
8833
|
memory;
|
|
8579
8834
|
approvals;
|
|
8580
8835
|
approvalModes;
|
|
8836
|
+
computers;
|
|
8837
|
+
tokenRates;
|
|
8581
8838
|
connection;
|
|
8582
8839
|
constructor(options) {
|
|
8583
8840
|
this.connection = openSqliteStoreConnection(options);
|
|
@@ -8588,6 +8845,8 @@ class SqliteAgentStorage {
|
|
|
8588
8845
|
this.memory = new SqliteAgentMemoryStore(this.connection.db);
|
|
8589
8846
|
this.approvals = new SqliteAgentApprovalStore(this.connection.db);
|
|
8590
8847
|
this.approvalModes = new SqliteAgentApprovalModeStore(this.connection.db);
|
|
8848
|
+
this.computers = new SqliteAgentComputerSessionStore(this.connection.db);
|
|
8849
|
+
this.tokenRates = new SqliteAgentTokenRateStore(this.connection.db);
|
|
8591
8850
|
}
|
|
8592
8851
|
close() {
|
|
8593
8852
|
closeSqliteStoreConnection(this.connection);
|
|
@@ -8611,15 +8870,52 @@ import {
|
|
|
8611
8870
|
AiCostStorageError
|
|
8612
8871
|
} from "@sixb/core/storage";
|
|
8613
8872
|
|
|
8873
|
+
// src/ai-accounting-filters.ts
|
|
8874
|
+
var SQLITE_SOURCE_WORKFLOW = `COALESCE(
|
|
8875
|
+
workflow_node.workflow_id,
|
|
8876
|
+
CASE WHEN execution.executor_kind = 'workflow' THEN execution.authority_primitive_id END
|
|
8877
|
+
)`;
|
|
8878
|
+
var SQLITE_SOURCE_KIND = `CASE
|
|
8879
|
+
WHEN direct_agent.id IS NOT NULL THEN 'agent'
|
|
8880
|
+
WHEN ${SQLITE_SOURCE_WORKFLOW} IS NOT NULL THEN 'workflow'
|
|
8881
|
+
WHEN execution.executor_kind = 'action' THEN 'action'
|
|
8882
|
+
ELSE 'other'
|
|
8883
|
+
END`;
|
|
8884
|
+
function sqliteAccountingFilter(columns) {
|
|
8885
|
+
return `(? IS NULL OR ${columns.kind} = ?)
|
|
8886
|
+
AND (? IS NULL OR ${columns.sourceKind} = ?)
|
|
8887
|
+
AND (? IS NULL OR ${columns.sourceWorkflow} = ?)
|
|
8888
|
+
AND (
|
|
8889
|
+
? IS NULL
|
|
8890
|
+
OR (? = 'none' AND ${columns.userId} IS NULL AND ${columns.serviceAccountId} IS NULL)
|
|
8891
|
+
OR (? = 'user' AND ${columns.userId} = ?)
|
|
8892
|
+
OR (? = 'serviceAccount' AND ${columns.serviceAccountId} = ?)
|
|
8893
|
+
)`;
|
|
8894
|
+
}
|
|
8895
|
+
function sqliteAccountingFilterParameters(query) {
|
|
8896
|
+
const kind = query.modelKind ?? null;
|
|
8897
|
+
const source = query.source?.kind ?? null;
|
|
8898
|
+
const workflow = query.source?.kind === "workflow" ? query.source.workflowId ?? null : null;
|
|
8899
|
+
const mode = query.requester === undefined ? null : query.requester === "none" ? "none" : query.requester.type;
|
|
8900
|
+
const id = query.requester === undefined || query.requester === "none" ? null : query.requester.id;
|
|
8901
|
+
return [kind, kind, source, source, workflow, workflow, mode, mode, mode, id, mode, id];
|
|
8902
|
+
}
|
|
8903
|
+
|
|
8614
8904
|
// src/ai-cost-groups.ts
|
|
8615
8905
|
import {
|
|
8616
8906
|
aiModelCallGroupFragmentFromRow,
|
|
8617
8907
|
buildAiModelCallGroupsFromFragments,
|
|
8618
8908
|
normalizeAiModelCallAccountingQuery,
|
|
8909
|
+
normalizeAiModelCallGroupSort,
|
|
8619
8910
|
TOKENLESS_MODEL_KINDS
|
|
8620
8911
|
} from "@sixb/core/internal/ai-cost-storage-provider";
|
|
8912
|
+
function numbered(sql, start) {
|
|
8913
|
+
let next = start;
|
|
8914
|
+
return sql.replace(/\?(?!\d)/g, () => `?${next++}`);
|
|
8915
|
+
}
|
|
8621
8916
|
async function listAiModelCallGroups(connection, input) {
|
|
8622
8917
|
const query = normalizeAiModelCallAccountingQuery(input);
|
|
8918
|
+
const sort = normalizeAiModelCallGroupSort(input.sort);
|
|
8623
8919
|
const parameters = [
|
|
8624
8920
|
query.projectId,
|
|
8625
8921
|
query.from.toISOString(),
|
|
@@ -8628,20 +8924,28 @@ async function listAiModelCallGroups(connection, input) {
|
|
|
8628
8924
|
query.modelId ?? null,
|
|
8629
8925
|
query.valuationStatus ?? null
|
|
8630
8926
|
];
|
|
8631
|
-
const
|
|
8632
|
-
const
|
|
8927
|
+
const filters = sqliteAccountingFilterParameters(query);
|
|
8928
|
+
const count = connection.db.query(COUNT_SQL).get(...parameters, ...filters);
|
|
8929
|
+
const rows = connection.db.query(PAGE_SQL).all(...parameters, ...filters, query.limit, query.offset, sort);
|
|
8633
8930
|
const total = Number(count?.total);
|
|
8634
8931
|
if (!Number.isSafeInteger(total) || total < 0)
|
|
8635
8932
|
throw new RangeError("[Sixb] Invalid model-call group count.");
|
|
8636
|
-
const items = buildAiModelCallGroupsFromFragments(rows.map(aiModelCallGroupFragmentFromRow));
|
|
8933
|
+
const items = buildAiModelCallGroupsFromFragments(rows.map(aiModelCallGroupFragmentFromRow), sort);
|
|
8637
8934
|
return { items, total, hasMore: query.offset + items.length < total };
|
|
8638
8935
|
}
|
|
8639
8936
|
var TOKENLESS_KINDS = TOKENLESS_MODEL_KINDS.map((kind) => `'${kind}'`).join(", ");
|
|
8640
8937
|
var FILTERED_SQL = `
|
|
8641
8938
|
WITH filtered AS (
|
|
8642
8939
|
SELECT COALESCE(root_agent.execution_id, usage.execution_id) AS root_execution_id,
|
|
8940
|
+
-- What the call is listed under, as aiModelCallGroupKey computes it.
|
|
8941
|
+
CASE
|
|
8942
|
+
WHEN root_agent.thread_id IS NOT NULL THEN 'thread:' || root_agent.thread_id
|
|
8943
|
+
WHEN workflow_node.workflow_run_id IS NOT NULL THEN 'workflowRun:' || workflow_node.workflow_run_id
|
|
8944
|
+
ELSE COALESCE(root_agent.execution_id, usage.execution_id)
|
|
8945
|
+
END AS group_key,
|
|
8643
8946
|
usage.execution_id, usage.provider_id, usage.requested_model_id, usage.occurred_at,
|
|
8644
|
-
usage.total_tokens, usage.
|
|
8947
|
+
usage.total_tokens, usage.input_tokens, usage.cache_read_input_tokens,
|
|
8948
|
+
usage.model_kind, usage.output_images, usage.input_characters,
|
|
8645
8949
|
usage.audio_duration_ms,
|
|
8646
8950
|
execution.executor_kind, execution.executor_id, execution.authority_primitive_id AS primitive_id,
|
|
8647
8951
|
COALESCE(cost.status, 'unvalued') AS valuation_status,
|
|
@@ -8654,7 +8958,8 @@ WITH filtered AS (
|
|
|
8654
8958
|
workflow_node.node_id AS workflow_agent_step_id,
|
|
8655
8959
|
workflow_agent.node_run_id AS workflow_node_run_id,
|
|
8656
8960
|
workflow_node.workflow_id AS workflow_id,
|
|
8657
|
-
workflow_node.workflow_run_id AS workflow_run_id
|
|
8961
|
+
workflow_node.workflow_run_id AS workflow_run_id,
|
|
8962
|
+
execution.requested_by_user_id, execution.requested_by_service_account_id
|
|
8658
8963
|
FROM ai_model_call_usage AS usage
|
|
8659
8964
|
JOIN executions AS execution ON execution.project_id = usage.project_id AND execution.id = usage.execution_id
|
|
8660
8965
|
LEFT JOIN agent_runs AS direct_agent
|
|
@@ -8674,23 +8979,33 @@ WITH filtered AS (
|
|
|
8674
8979
|
AND (?4 IS NULL OR usage.provider_id = ?4)
|
|
8675
8980
|
AND (?5 IS NULL OR usage.requested_model_id = ?5)
|
|
8676
8981
|
AND (?6 IS NULL OR COALESCE(cost.status, 'unvalued') = ?6)
|
|
8982
|
+
AND ${numbered(sqliteAccountingFilter({
|
|
8983
|
+
kind: "usage.model_kind",
|
|
8984
|
+
sourceKind: SQLITE_SOURCE_KIND,
|
|
8985
|
+
sourceWorkflow: SQLITE_SOURCE_WORKFLOW,
|
|
8986
|
+
userId: "execution.requested_by_user_id",
|
|
8987
|
+
serviceAccountId: "execution.requested_by_service_account_id"
|
|
8988
|
+
}), 7)}
|
|
8677
8989
|
), roots AS (
|
|
8678
|
-
SELECT
|
|
8679
|
-
FROM filtered GROUP BY
|
|
8990
|
+
SELECT group_key, MAX(occurred_at) AS last_call_at, TOTAL(amount_nanos) AS cost_nanos
|
|
8991
|
+
FROM filtered GROUP BY group_key
|
|
8680
8992
|
)
|
|
8681
8993
|
`;
|
|
8682
8994
|
var COUNT_SQL = `${FILTERED_SQL} SELECT CAST(COUNT(*) AS TEXT) AS total FROM roots`;
|
|
8683
8995
|
var PAGE_SQL = `${FILTERED_SQL}, page AS (
|
|
8684
|
-
SELECT
|
|
8685
|
-
ORDER BY last_call_at DESC,
|
|
8996
|
+
SELECT group_key FROM roots
|
|
8997
|
+
ORDER BY CASE WHEN ?21 = 'cost' THEN cost_nanos END DESC, last_call_at DESC, group_key ASC
|
|
8998
|
+
LIMIT ?19 OFFSET ?20
|
|
8686
8999
|
)
|
|
8687
|
-
SELECT filtered.root_execution_id, execution_id, provider_id, requested_model_id,
|
|
9000
|
+
SELECT filtered.group_key, root_execution_id, execution_id, provider_id, requested_model_id,
|
|
8688
9001
|
MIN(occurred_at) AS first_call_at, MAX(occurred_at) AS last_call_at,
|
|
8689
9002
|
CAST(COUNT(*) AS TEXT) AS call_count,
|
|
8690
9003
|
CAST(COUNT(total_tokens) AS TEXT) AS token_count,
|
|
8691
9004
|
CAST(COUNT(CASE WHEN total_tokens IS NULL AND model_kind IN (${TOKENLESS_KINDS}) THEN 1 END) AS TEXT)
|
|
8692
9005
|
AS tokenless_count,
|
|
8693
9006
|
CAST(SUM(total_tokens) AS TEXT) AS total_tokens,
|
|
9007
|
+
CAST(SUM(input_tokens) AS TEXT) AS input_tokens,
|
|
9008
|
+
CAST(SUM(cache_read_input_tokens) AS TEXT) AS cache_read_input_tokens,
|
|
8694
9009
|
CAST(SUM(output_images) AS TEXT) AS output_images,
|
|
8695
9010
|
CAST(SUM(input_characters) AS TEXT) AS input_characters,
|
|
8696
9011
|
CAST(SUM(audio_duration_ms) AS TEXT) AS audio_duration_ms,
|
|
@@ -8707,9 +9022,11 @@ SELECT filtered.root_execution_id, execution_id, provider_id, requested_model_id
|
|
|
8707
9022
|
MAX(workflow_agent_step_id) AS workflow_agent_step_id,
|
|
8708
9023
|
MAX(workflow_node_run_id) AS workflow_node_run_id,
|
|
8709
9024
|
MAX(workflow_id) AS workflow_id,
|
|
8710
|
-
MAX(workflow_run_id) AS workflow_run_id
|
|
8711
|
-
|
|
8712
|
-
|
|
9025
|
+
MAX(workflow_run_id) AS workflow_run_id,
|
|
9026
|
+
MAX(requested_by_user_id) AS requested_by_user_id,
|
|
9027
|
+
MAX(requested_by_service_account_id) AS requested_by_service_account_id
|
|
9028
|
+
FROM filtered JOIN page ON page.group_key = filtered.group_key
|
|
9029
|
+
GROUP BY filtered.group_key, root_execution_id, execution_id, provider_id, requested_model_id,
|
|
8713
9030
|
valuation_status, amount_currency
|
|
8714
9031
|
`;
|
|
8715
9032
|
|
|
@@ -9013,7 +9330,7 @@ class SqliteAiCostStorage {
|
|
|
9013
9330
|
}
|
|
9014
9331
|
async queryProjectOverview(input) {
|
|
9015
9332
|
const query = normalizeAiAccountingQuery(input);
|
|
9016
|
-
const rows = this.connection.db.query(SQLITE_ACCOUNTING_OVERVIEW_SQL).all(query.projectId, query.from.toISOString(), query.to.toISOString(), query.providerId ?? null, query.providerId ?? null, query.modelId ?? null, query.modelId ?? null, input.bucket);
|
|
9333
|
+
const rows = this.connection.db.query(SQLITE_ACCOUNTING_OVERVIEW_SQL).all(query.projectId, query.from.toISOString(), query.to.toISOString(), query.providerId ?? null, query.providerId ?? null, query.modelId ?? null, query.modelId ?? null, ...sqliteAccountingFilterParameters(query), input.bucket, input.bucket);
|
|
9017
9334
|
return buildAiAccountingOverviewFromFragments(input, rows.map(aggregateFragmentFromRow));
|
|
9018
9335
|
}
|
|
9019
9336
|
async listModelCalls(input) {
|
|
@@ -9060,12 +9377,32 @@ var SQLITE_ACCOUNTING_LIST_FILTER = `
|
|
|
9060
9377
|
ELSE 'unvalued'
|
|
9061
9378
|
END
|
|
9062
9379
|
)
|
|
9380
|
+
AND ${sqliteAccountingFilter({
|
|
9381
|
+
kind: "usage.model_kind",
|
|
9382
|
+
sourceKind: SQLITE_SOURCE_KIND,
|
|
9383
|
+
sourceWorkflow: SQLITE_SOURCE_WORKFLOW,
|
|
9384
|
+
userId: "execution.requested_by_user_id",
|
|
9385
|
+
serviceAccountId: "execution.requested_by_service_account_id"
|
|
9386
|
+
})}
|
|
9387
|
+
`;
|
|
9388
|
+
var SQLITE_ACCOUNTING_LIST_JOINS = `
|
|
9389
|
+
JOIN executions AS execution ON execution.project_id = usage.project_id AND execution.id = usage.execution_id
|
|
9390
|
+
LEFT JOIN agent_runs AS direct_agent
|
|
9391
|
+
ON direct_agent.project_id = usage.project_id
|
|
9392
|
+
AND direct_agent.execution_id = usage.execution_id
|
|
9393
|
+
LEFT JOIN workflow_agent_node_runs AS workflow_agent
|
|
9394
|
+
ON workflow_agent.project_id = usage.project_id
|
|
9395
|
+
AND workflow_agent.execution_id = usage.execution_id
|
|
9396
|
+
LEFT JOIN workflow_node_runs AS workflow_node
|
|
9397
|
+
ON workflow_node.project_id = workflow_agent.project_id
|
|
9398
|
+
AND workflow_node.id = workflow_agent.node_run_id
|
|
9399
|
+
LEFT JOIN ai_model_call_valuations AS cost
|
|
9400
|
+
ON cost.project_id = usage.project_id AND cost.usage_record_id = usage.id
|
|
9063
9401
|
`;
|
|
9064
9402
|
var SQLITE_ACCOUNTING_LIST_COUNT_SQL = `
|
|
9065
9403
|
SELECT CAST(COUNT(*) AS TEXT) AS total
|
|
9066
9404
|
FROM ai_model_call_usage AS usage
|
|
9067
|
-
|
|
9068
|
-
ON cost.project_id = usage.project_id AND cost.usage_record_id = usage.id
|
|
9405
|
+
${SQLITE_ACCOUNTING_LIST_JOINS}
|
|
9069
9406
|
WHERE ${SQLITE_ACCOUNTING_LIST_FILTER}
|
|
9070
9407
|
`;
|
|
9071
9408
|
var SQLITE_ACCOUNTING_LIST_PAGE_SQL = `
|
|
@@ -9100,18 +9437,7 @@ var SQLITE_ACCOUNTING_LIST_PAGE_SQL = `
|
|
|
9100
9437
|
cost.details AS cost_details,
|
|
9101
9438
|
cost.rated_at AS cost_rated_at
|
|
9102
9439
|
FROM ai_model_call_usage AS usage
|
|
9103
|
-
|
|
9104
|
-
LEFT JOIN agent_runs AS direct_agent
|
|
9105
|
-
ON direct_agent.project_id = usage.project_id
|
|
9106
|
-
AND direct_agent.execution_id = usage.execution_id
|
|
9107
|
-
LEFT JOIN workflow_agent_node_runs AS workflow_agent
|
|
9108
|
-
ON workflow_agent.project_id = usage.project_id
|
|
9109
|
-
AND workflow_agent.execution_id = usage.execution_id
|
|
9110
|
-
LEFT JOIN workflow_node_runs AS workflow_node
|
|
9111
|
-
ON workflow_node.project_id = workflow_agent.project_id
|
|
9112
|
-
AND workflow_node.id = workflow_agent.node_run_id
|
|
9113
|
-
LEFT JOIN ai_model_call_valuations AS cost
|
|
9114
|
-
ON cost.project_id = usage.project_id AND cost.usage_record_id = usage.id
|
|
9440
|
+
${SQLITE_ACCOUNTING_LIST_JOINS}
|
|
9115
9441
|
WHERE ${SQLITE_ACCOUNTING_LIST_FILTER}
|
|
9116
9442
|
ORDER BY usage.occurred_at DESC, usage.id ASC
|
|
9117
9443
|
LIMIT ? OFFSET ?
|
|
@@ -9150,7 +9476,10 @@ var SQLITE_ACCOUNTING_OVERVIEW_SQL = `
|
|
|
9150
9476
|
ELSE 'unvalued'
|
|
9151
9477
|
END AS valuation_status,
|
|
9152
9478
|
CASE WHEN cost.status = 'rated' THEN cost.currency ELSE NULL END AS amount_currency,
|
|
9153
|
-
CASE WHEN cost.status = 'rated' THEN cost.amount_nanos ELSE NULL END AS amount_nanos
|
|
9479
|
+
CASE WHEN cost.status = 'rated' THEN cost.amount_nanos ELSE NULL END AS amount_nanos,
|
|
9480
|
+
execution.requested_by_user_id AS requester_user_id,
|
|
9481
|
+
execution.requested_by_service_account_id AS requester_service_account_id,
|
|
9482
|
+
${SQLITE_SOURCE_KIND} AS source_kind
|
|
9154
9483
|
FROM ai_model_call_usage AS usage
|
|
9155
9484
|
JOIN executions AS execution ON execution.project_id = usage.project_id AND execution.id = usage.execution_id
|
|
9156
9485
|
LEFT JOIN agent_runs AS direct_agent
|
|
@@ -9167,10 +9496,19 @@ var SQLITE_ACCOUNTING_OVERVIEW_SQL = `
|
|
|
9167
9496
|
WHERE usage.project_id = ? AND usage.occurred_at >= ? AND usage.occurred_at < ?
|
|
9168
9497
|
AND (? IS NULL OR usage.provider_id = ?)
|
|
9169
9498
|
AND (? IS NULL OR usage.requested_model_id = ?)
|
|
9499
|
+
), filtered AS (
|
|
9500
|
+
SELECT * FROM classified
|
|
9501
|
+
WHERE ${sqliteAccountingFilter({
|
|
9502
|
+
kind: "model_kind",
|
|
9503
|
+
sourceKind: "source_kind",
|
|
9504
|
+
sourceWorkflow: "attribution_workflow_id",
|
|
9505
|
+
userId: "requester_user_id",
|
|
9506
|
+
serviceAccountId: "requester_service_account_id"
|
|
9507
|
+
})}
|
|
9170
9508
|
), expanded AS (
|
|
9171
9509
|
SELECT 'totals' AS dimension, NULL AS key_1, NULL AS key_2, NULL AS key_3, NULL AS bucket_start,
|
|
9172
|
-
|
|
9173
|
-
FROM
|
|
9510
|
+
filtered.*
|
|
9511
|
+
FROM filtered
|
|
9174
9512
|
UNION ALL
|
|
9175
9513
|
SELECT 'series', NULL, NULL, NULL,
|
|
9176
9514
|
CASE ?
|
|
@@ -9182,18 +9520,39 @@ var SQLITE_ACCOUNTING_OVERVIEW_SQL = `
|
|
|
9182
9520
|
printf('-%d days', (CAST(strftime('%w', occurred_at) AS INTEGER) + 6) % 7)
|
|
9183
9521
|
)
|
|
9184
9522
|
END,
|
|
9185
|
-
|
|
9186
|
-
FROM
|
|
9523
|
+
filtered.*
|
|
9524
|
+
FROM filtered
|
|
9187
9525
|
UNION ALL
|
|
9188
|
-
SELECT '
|
|
9526
|
+
SELECT 'modelSeries', provider_id, requested_model_id, NULL,
|
|
9527
|
+
CASE ?
|
|
9528
|
+
WHEN 'hour' THEN strftime('%Y-%m-%dT%H:00:00.000Z', occurred_at)
|
|
9529
|
+
WHEN 'day' THEN strftime('%Y-%m-%dT00:00:00.000Z', occurred_at)
|
|
9530
|
+
ELSE strftime(
|
|
9531
|
+
'%Y-%m-%dT00:00:00.000Z',
|
|
9532
|
+
occurred_at,
|
|
9533
|
+
printf('-%d days', (CAST(strftime('%w', occurred_at) AS INTEGER) + 6) % 7)
|
|
9534
|
+
)
|
|
9535
|
+
END,
|
|
9536
|
+
filtered.*
|
|
9537
|
+
FROM filtered
|
|
9189
9538
|
UNION ALL
|
|
9190
|
-
SELECT '
|
|
9539
|
+
SELECT 'model', provider_id, requested_model_id, NULL, NULL, filtered.* FROM filtered
|
|
9191
9540
|
UNION ALL
|
|
9192
|
-
SELECT '
|
|
9193
|
-
|
|
9541
|
+
SELECT 'person',
|
|
9542
|
+
CASE
|
|
9543
|
+
WHEN requester_user_id IS NOT NULL THEN 'user'
|
|
9544
|
+
WHEN requester_service_account_id IS NOT NULL THEN 'serviceAccount'
|
|
9545
|
+
END,
|
|
9546
|
+
COALESCE(requester_user_id, requester_service_account_id), NULL, NULL, filtered.*
|
|
9547
|
+
FROM filtered
|
|
9194
9548
|
UNION ALL
|
|
9195
|
-
SELECT '
|
|
9196
|
-
|
|
9549
|
+
SELECT 'kind', model_kind, NULL, NULL, NULL, filtered.* FROM filtered
|
|
9550
|
+
UNION ALL
|
|
9551
|
+
SELECT 'agent', attribution_agent_kind, attribution_workflow_id, attribution_agent_step_id, NULL, filtered.*
|
|
9552
|
+
FROM filtered WHERE attribution_agent_kind IS NOT NULL
|
|
9553
|
+
UNION ALL
|
|
9554
|
+
SELECT 'workflow', attribution_workflow_id, NULL, NULL, NULL, filtered.*
|
|
9555
|
+
FROM filtered WHERE attribution_workflow_id IS NOT NULL
|
|
9197
9556
|
)
|
|
9198
9557
|
SELECT dimension,
|
|
9199
9558
|
key_1,
|
|
@@ -9254,11 +9613,16 @@ function accountingListFilterParameters(query) {
|
|
|
9254
9613
|
query.executionId ?? null,
|
|
9255
9614
|
query.executionId ?? null,
|
|
9256
9615
|
query.valuationStatus ?? null,
|
|
9257
|
-
query.valuationStatus ?? null
|
|
9616
|
+
query.valuationStatus ?? null,
|
|
9617
|
+
...sqliteAccountingFilterParameters(query)
|
|
9258
9618
|
];
|
|
9259
9619
|
}
|
|
9260
9620
|
function aggregateFragmentFromRow(row) {
|
|
9261
|
-
const dimensionKeys = row.dimension === "model" ? { providerId: required(row.key_1), modelId: required(row.key_2) } : row.dimension === "
|
|
9621
|
+
const dimensionKeys = row.dimension === "model" ? { providerId: required(row.key_1), modelId: required(row.key_2) } : row.dimension === "modelSeries" ? {
|
|
9622
|
+
providerId: required(row.key_1),
|
|
9623
|
+
modelId: required(row.key_2),
|
|
9624
|
+
start: new Date(required(row.bucket_start))
|
|
9625
|
+
} : row.dimension === "person" ? row.key_1 && row.key_2 ? { requesterType: row.key_1, requesterId: row.key_2 } : {} : row.dimension === "kind" ? withModelKind(aiAccountingModelKind(row.key_1)) : row.dimension === "agent" ? {
|
|
9262
9626
|
agentKind: required(row.key_1),
|
|
9263
9627
|
...row.key_1 === "workflowAgent" ? { workflowId: required(row.key_2), agentStepId: required(row.key_3) } : {}
|
|
9264
9628
|
} : row.dimension === "workflow" ? { workflowId: required(row.key_1) } : row.dimension === "series" ? { start: new Date(required(row.bucket_start)) } : {};
|
|
@@ -13209,6 +13573,7 @@ import {
|
|
|
13209
13573
|
import {
|
|
13210
13574
|
hasVectorProfile,
|
|
13211
13575
|
isVectorProfileQuery,
|
|
13576
|
+
linkEndpointObjectTypeIds,
|
|
13212
13577
|
normalizeVector,
|
|
13213
13578
|
vectorSearchCandidateLimit
|
|
13214
13579
|
} from "@sixb/core/internal/query";
|
|
@@ -13270,7 +13635,7 @@ function compileObjectQueryInternal(projectId, query, ctx) {
|
|
|
13270
13635
|
case "page":
|
|
13271
13636
|
return compilePage(projectId, query.input, query.pageSize, query.pageToken, ctx);
|
|
13272
13637
|
case "traverse":
|
|
13273
|
-
return compileTraversal(projectId, query
|
|
13638
|
+
return compileTraversal(projectId, query, ctx);
|
|
13274
13639
|
case "set":
|
|
13275
13640
|
return compileSet(projectId, query.op, query.inputs, ctx);
|
|
13276
13641
|
case "project":
|
|
@@ -13551,9 +13916,11 @@ function compilePage(projectId, inputQuery, rawPageSize, pageToken, ctx) {
|
|
|
13551
13916
|
}
|
|
13552
13917
|
};
|
|
13553
13918
|
}
|
|
13554
|
-
function compileTraversal(projectId,
|
|
13555
|
-
const
|
|
13919
|
+
function compileTraversal(projectId, traversal, ctx) {
|
|
13920
|
+
const { linkId, direction, sourceObjectTypeId } = traversal;
|
|
13921
|
+
const input = compileObjectQueryInternal(projectId, traversal.input, exactContext(ctx));
|
|
13556
13922
|
const outputAlias = direction === "outgoing" ? "target_object" : "source_object";
|
|
13923
|
+
const endpointType = compileEndpointTypes(outputAlias, linkEndpointObjectTypeIds(traversal));
|
|
13557
13924
|
const joinSql = direction === "outgoing" ? `
|
|
13558
13925
|
JOIN ${ctx.source.linksTable} AS edge
|
|
13559
13926
|
ON edge.project_id = input.project_id
|
|
@@ -13564,6 +13931,7 @@ function compileTraversal(projectId, inputQuery, linkId, direction, sourceObject
|
|
|
13564
13931
|
ON target_object.project_id = edge.project_id
|
|
13565
13932
|
AND target_object.object_type_id = edge.target_type_id
|
|
13566
13933
|
AND target_object.primary_id = edge.target_id
|
|
13934
|
+
${endpointType.sql}
|
|
13567
13935
|
` : `
|
|
13568
13936
|
JOIN ${ctx.source.linksTable} AS edge
|
|
13569
13937
|
ON edge.project_id = input.project_id
|
|
@@ -13575,6 +13943,7 @@ function compileTraversal(projectId, inputQuery, linkId, direction, sourceObject
|
|
|
13575
13943
|
ON source_object.project_id = edge.project_id
|
|
13576
13944
|
AND source_object.object_type_id = edge.source_type_id
|
|
13577
13945
|
AND source_object.primary_id = edge.source_id
|
|
13946
|
+
${endpointType.sql}
|
|
13578
13947
|
`;
|
|
13579
13948
|
const order = compileOrder(identityOrderFields());
|
|
13580
13949
|
const qualifiedOrder = compileOrder(identityOrderFields(), outputAlias);
|
|
@@ -13587,7 +13956,8 @@ function compileTraversal(projectId, inputQuery, linkId, direction, sourceObject
|
|
|
13587
13956
|
const args = [
|
|
13588
13957
|
...input.args,
|
|
13589
13958
|
linkId,
|
|
13590
|
-
...
|
|
13959
|
+
...direction === "incoming" && sourceObjectTypeId !== undefined ? [sourceObjectTypeId] : [],
|
|
13960
|
+
...endpointType.args,
|
|
13591
13961
|
...qualifiedOrder.args
|
|
13592
13962
|
];
|
|
13593
13963
|
return {
|
|
@@ -13603,6 +13973,14 @@ function compileTraversal(projectId, inputQuery, linkId, direction, sourceObject
|
|
|
13603
13973
|
}
|
|
13604
13974
|
};
|
|
13605
13975
|
}
|
|
13976
|
+
function compileEndpointTypes(alias, objectTypeIds) {
|
|
13977
|
+
if (!objectTypeIds?.length)
|
|
13978
|
+
return { sql: "", args: [] };
|
|
13979
|
+
return {
|
|
13980
|
+
sql: `AND ${alias}.object_type_id IN (${objectTypeIds.map(() => "?").join(", ")})`,
|
|
13981
|
+
args: [...objectTypeIds]
|
|
13982
|
+
};
|
|
13983
|
+
}
|
|
13606
13984
|
function compileExpand(projectId, inputQuery, expansions, ctx) {
|
|
13607
13985
|
const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx));
|
|
13608
13986
|
const expand = compileExpansionsObject(expansions, { project: "input.project_id", type: "input.object_type_id", id: "input.primary_id" }, "", ctx);
|
|
@@ -13653,31 +14031,36 @@ function compileExpansionValue(expansion, parent, path, ctx) {
|
|
|
13653
14031
|
`${parentId} = ${parent.id}`,
|
|
13654
14032
|
`${edge}.link_id = ?`
|
|
13655
14033
|
];
|
|
13656
|
-
const
|
|
14034
|
+
const endpointType = compileEndpointTypes(target, expansion.endpointObjectTypeIds);
|
|
14035
|
+
const whereArgs = [...endpointType.args, expansion.linkId];
|
|
13657
14036
|
if (incoming && expansion.sourceObjectTypeId !== undefined) {
|
|
13658
14037
|
whereParts.push(`${edge}.source_type_id = ?`);
|
|
13659
14038
|
whereArgs.push(expansion.sourceObjectTypeId);
|
|
13660
14039
|
}
|
|
13661
|
-
const
|
|
13662
|
-
SELECT ${child.sql} AS elem, row_number() OVER (ORDER BY ${order.sql}) AS _ord
|
|
14040
|
+
const from = `
|
|
13663
14041
|
FROM ${ctx.source.linksTable} AS ${edge}
|
|
13664
14042
|
JOIN ${ctx.source.objectsTable} AS ${target}
|
|
13665
14043
|
ON ${target}.project_id = ${edge}.project_id
|
|
13666
14044
|
AND ${target}.object_type_id = ${neighborType}
|
|
13667
14045
|
AND ${target}.primary_id = ${neighborId}
|
|
14046
|
+
${endpointType.sql}
|
|
13668
14047
|
WHERE ${whereParts.join(" AND ")}
|
|
13669
14048
|
`;
|
|
13670
|
-
const innerArgs = [...child.args, ...order.args, ...whereArgs];
|
|
13671
14049
|
if (expansion.cardinality === "one") {
|
|
13672
14050
|
return {
|
|
13673
|
-
sql: `(SELECT ${
|
|
13674
|
-
args:
|
|
14051
|
+
sql: `(SELECT ${child.sql} ${from} ORDER BY ${order.sql} LIMIT 1)`,
|
|
14052
|
+
args: [...child.args, ...whereArgs, ...order.args]
|
|
13675
14053
|
};
|
|
13676
14054
|
}
|
|
13677
14055
|
const limit = expansion.limit ?? DEFAULT_EXPANSION_FANOUT;
|
|
13678
14056
|
return {
|
|
13679
|
-
sql: `COALESCE((SELECT json_group_array(json(${ranked}.elem) ORDER BY ${ranked}._ord) FROM (
|
|
13680
|
-
|
|
14057
|
+
sql: `COALESCE((SELECT json_group_array(json(${ranked}.elem) ORDER BY ${ranked}._ord) FROM (
|
|
14058
|
+
SELECT ${child.sql} AS elem, row_number() OVER (ORDER BY ${order.sql}) AS _ord
|
|
14059
|
+
${from}
|
|
14060
|
+
ORDER BY ${order.sql}
|
|
14061
|
+
LIMIT ?
|
|
14062
|
+
) AS ${ranked}), '[]')`,
|
|
14063
|
+
args: [...child.args, ...order.args, ...whereArgs, ...order.args, limit]
|
|
13681
14064
|
};
|
|
13682
14065
|
}
|
|
13683
14066
|
function compileExpansionChildJson(expansion, edge, target, path, ctx) {
|
|
@@ -15563,6 +15946,9 @@ class SqliteOntologyCommitStorage {
|
|
|
15563
15946
|
assertNonnegativeInteger(offset, "Ontology commit list offset");
|
|
15564
15947
|
if (limit !== -1)
|
|
15565
15948
|
assertNonnegativeInteger(limit, "Ontology commit list limit");
|
|
15949
|
+
if (input.committedAt !== undefined) {
|
|
15950
|
+
assertTimestamp(input.committedAt, "Ontology commit list committedAt");
|
|
15951
|
+
}
|
|
15566
15952
|
const filters = ["project_id = ?"];
|
|
15567
15953
|
const values = [input.projectId];
|
|
15568
15954
|
if (input.run?.kind === "action") {
|
|
@@ -15572,6 +15958,10 @@ class SqliteOntologyCommitStorage {
|
|
|
15572
15958
|
filters.push("origin_run_id = ? AND origin_kind IN ('projection', 'telemetry')");
|
|
15573
15959
|
values.push(input.run.id);
|
|
15574
15960
|
}
|
|
15961
|
+
if (input.committedAt !== undefined) {
|
|
15962
|
+
filters.push("committed_at = ?");
|
|
15963
|
+
values.push(input.committedAt);
|
|
15964
|
+
}
|
|
15575
15965
|
const where = filters.join(" AND ");
|
|
15576
15966
|
const totalRow = this.db.query(`SELECT COUNT(*) AS total FROM ontology_commits WHERE ${where}`).get(...values);
|
|
15577
15967
|
const direction = input.order === "desc" ? "DESC" : "ASC";
|
|
@@ -15623,6 +16013,7 @@ import {
|
|
|
15623
16013
|
invalidCorrelation as invalidCorrelation2,
|
|
15624
16014
|
materializationOutboxWrite,
|
|
15625
16015
|
materializationPlanChunk,
|
|
16016
|
+
prepareMaterializationStateRead,
|
|
15626
16017
|
sameNonnegativeCounts as sameCounts,
|
|
15627
16018
|
uniqueSorted
|
|
15628
16019
|
} from "@sixb/core/internal/ontology-storage-provider";
|
|
@@ -17794,6 +18185,17 @@ class SqliteOntologyMaterializationStorage {
|
|
|
17794
18185
|
}
|
|
17795
18186
|
}
|
|
17796
18187
|
}
|
|
18188
|
+
async readState(input) {
|
|
18189
|
+
const request = prepareMaterializationStateRead(input);
|
|
18190
|
+
return runDeferredReadTransaction(this.db, () => {
|
|
18191
|
+
const reader = new SqliteMaterializationStateReader(this.db, request.projectId);
|
|
18192
|
+
return {
|
|
18193
|
+
objects: reader.objectStates(request.objects),
|
|
18194
|
+
links: reader.linkStates(request.links),
|
|
18195
|
+
linkScopes: reader.linkSlotStates(request.linkScopes)
|
|
18196
|
+
};
|
|
18197
|
+
});
|
|
18198
|
+
}
|
|
17797
18199
|
async stageWork(input) {
|
|
17798
18200
|
this.sessions.stage(input);
|
|
17799
18201
|
await yieldSqliteEventLoop();
|
|
@@ -21808,4 +22210,4 @@ export {
|
|
|
21808
22210
|
migrateSqliteStorage
|
|
21809
22211
|
};
|
|
21810
22212
|
|
|
21811
|
-
//# debugId=
|
|
22213
|
+
//# debugId=38D04B34BA5E877464756E2164756E21
|