refactor(session): nuke dead sessionParams / sessionDisplayId pipeline (v43)
These columns and the messages that plumbed them existed for the CLI-
adapter era — Gemini's resume id and provider-specific session params
rode the run-finished envelope back onto the session row so the next
turn could resume. Pi Mono dispatches every provider through pi-ai and
emits neither value. The worker has been posting literal null on every
finish, finalizeRun has been writing null into task_sessions, and
rotateSession has been carrying null forward.
Remove the wire, the writer, the carry-forward, and the columns:
- v43 migration rebuilds task_sessions without session_params_json /
session_display_id, and runs without session_display_id. Follows
the idempotent "create new, copy, swap, reindex" pattern used by
v41. context_snapshot_json is preserved (also unreferenced today
but outside this cleanup's scope).
- RunJob / EnqueueRunPayload / ChildMessage / worker-types zod
schema no longer carry the fields. finishRun() / createNewSession()
signatures tighten in lockstep.
- rotateSession starts the new session with fresh counters and no
carry-forward.
- turn-context resolveSession returns just the session id.
- TaskSessionRecord / RunRecord lose the dead fields.
498/498 unit tests pass. typecheck + build clean.
This commit is contained in:
1 parent
88a1f8b334
commit
e0e43d6127
32 files changed
+167
-205
No files matched your search
@@ -339,11 +339,10 @@ export class AppDatabaseBase {
|
|||||||
saveTask(input: { id?: string | null; companyId: string; projectId?: string | null; goalId?: string | null; parentId?: string | null; title: string; description: string; assigneeAgentId?: string | null; workspaceId?: string | null; priority: string; status: string }) { return this.tasks.saveTask(input); }
|
saveTask(input: { id?: string | null; companyId: string; projectId?: string | null; goalId?: string | null; parentId?: string | null; title: string; description: string; assigneeAgentId?: string | null; workspaceId?: string | null; priority: string; status: string }) { return this.tasks.saveTask(input); }
|
||||||
getTask(id: string) { return this.entityCrud.getTask(id); }
|
getTask(id: string) { return this.entityCrud.getTask(id); }
|
||||||
deleteTask(id: string, companyId: string) { return this.tasks.deleteTask(id, companyId); }
|
deleteTask(id: string, companyId: string) { return this.tasks.deleteTask(id, companyId); }
|
||||||
updateSessionParams(sessionId: string, sessionParams: Record<string, unknown> | null, sessionDisplayId: string | null) { return this.tasks.updateSessionParams(sessionId, sessionParams, sessionDisplayId); }
|
|
||||||
getSessionById(sessionId: string) { return this.tasks.getSessionById(sessionId); }
|
getSessionById(sessionId: string) { return this.tasks.getSessionById(sessionId); }
|
||||||
incrementSessionUsage(sessionId: string, inputTokens: number, outputTokens: number, runId: string) { return this.tasks.incrementSessionUsage(sessionId, inputTokens, outputTokens, runId); }
|
incrementSessionUsage(sessionId: string, inputTokens: number, outputTokens: number, runId: string) { return this.tasks.incrementSessionUsage(sessionId, inputTokens, outputTokens, runId); }
|
||||||
archiveSession(sessionId: string, reason: string, handoffMarkdown: string) { return this.tasks.archiveSession(sessionId, reason, handoffMarkdown); }
|
archiveSession(sessionId: string, reason: string, handoffMarkdown: string) { return this.tasks.archiveSession(sessionId, reason, handoffMarkdown); }
|
||||||
createNewSession(input: { companyId: string; agentId: string; adapterType: string; sessionParamsJson: string | null; sessionDisplayId: string | null }) { return this.tasks.createNewSession(input); }
|
createNewSession(input: { companyId: string; agentId: string; adapterType: string }) { return this.tasks.createNewSession(input); }
|
||||||
ensureAgentSession(input: { agentId: string; companyId: string; adapterType: string }) { return this.tasks.ensureAgentSession(input); }
|
ensureAgentSession(input: { agentId: string; companyId: string; adapterType: string }) { return this.tasks.ensureAgentSession(input); }
|
||||||
setAgentSessionId(agentId: string, sessionId: string) { return this.tasks.setAgentSessionId(agentId, sessionId); }
|
setAgentSessionId(agentId: string, sessionId: string) { return this.tasks.setAgentSessionId(agentId, sessionId); }
|
||||||
getRecentRunsForTask(taskId: string, limit: number) { return this.tasks.getRecentRunsForTask(taskId, limit); }
|
getRecentRunsForTask(taskId: string, limit: number) { return this.tasks.getRecentRunsForTask(taskId, limit); }
|
||||||
@@ -385,7 +384,7 @@ export class AppDatabaseBase {
|
|||||||
readRunLog(runId: string) { return this.runs.readRunLog(runId); }
|
readRunLog(runId: string) { return this.runs.readRunLog(runId); }
|
||||||
readRunLogChunk(runId: string, offset = 0, limit = 65_536) { return this.runs.readRunLogChunk(runId, offset, limit); }
|
readRunLogChunk(runId: string, offset = 0, limit = 65_536) { return this.runs.readRunLogChunk(runId, offset, limit); }
|
||||||
markRunStatus(runId: string, status: RunStatus, message: string) { return this.runs.markRunStatus(runId, status, message); }
|
markRunStatus(runId: string, status: RunStatus, message: string) { return this.runs.markRunStatus(runId, status, message); }
|
||||||
finishRun(input: { runId: string; status: RunStatus; summary: string | null; errorMessage: string | null; exitCode: number | null; signal: string | null; model: string | null; sessionDisplayId: string | null; unattributedCost: boolean }) { return this.runs.finishRun(input); }
|
finishRun(input: { runId: string; status: RunStatus; summary: string | null; errorMessage: string | null; exitCode: number | null; signal: string | null; model: string | null; unattributedCost: boolean }) { return this.runs.finishRun(input); }
|
||||||
recordCostEntry(input: { runId: string; companyId: string; agentId: string; taskId: string | null; connectorId: string; amountUsd: number | null; unattributed: boolean }) { return this.runs.recordCostEntry(input); }
|
recordCostEntry(input: { runId: string; companyId: string; agentId: string; taskId: string | null; connectorId: string; amountUsd: number | null; unattributed: boolean }) { return this.runs.recordCostEntry(input); }
|
||||||
hasActiveRun(filter: { companyId: string; taskId?: string; agentId?: string }) { return this.runs.hasActiveRun(filter); }
|
hasActiveRun(filter: { companyId: string; taskId?: string; agentId?: string }) { return this.runs.hasActiveRun(filter); }
|
||||||
listQueuedRuns() { return this.runs.listQueuedRuns(); }
|
listQueuedRuns() { return this.runs.listQueuedRuns(); }
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
import log from "electron-log/main.js";
|
||||||
|
import type { Migration, MigrationDeps } from "./types";
|
||||||
|
import { columnExists, tableExists } from "./types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the Pi Mono-dead session carry-forward columns.
|
||||||
|
*
|
||||||
|
* The `task_sessions.session_params_json` / `task_sessions.session_display_id`
|
||||||
|
* columns and the matching `runs.session_display_id` column were meaningful
|
||||||
|
* in the CLI-adapter era: Gemini's resume id and provider-specific session
|
||||||
|
* params rode the run-finished message back into the session row so the next
|
||||||
|
* turn could resume. Pi Mono dispatches every provider through `pi-ai` and
|
||||||
|
* emits neither value — the worker has been writing literal `null` on every
|
||||||
|
* finish and `rotateSession` has been carrying `null` forward.
|
||||||
|
*
|
||||||
|
* Three columns of unused storage plus a hot path that writes them every
|
||||||
|
* run. Drop them.
|
||||||
|
*
|
||||||
|
* The migration mirrors v41's "copy to new table, swap, reindex" shape —
|
||||||
|
* SQLite still has no multi-column `DROP COLUMN`, and the task_sessions
|
||||||
|
* index topology plus the runs secondary indexes need to be restored
|
||||||
|
* identically. `PRAGMA foreign_keys` is disabled across the swap window
|
||||||
|
* so child rows are not cascade-deleted mid-rebuild.
|
||||||
|
*/
|
||||||
|
export function createMigrationsV43V43(deps: MigrationDeps): Migration[] {
|
||||||
|
const { db } = deps;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
version: 43,
|
||||||
|
name: "drop_dead_pi_mono_session_columns",
|
||||||
|
fn: () => {
|
||||||
|
const sessionsHasDeadCols =
|
||||||
|
tableExists(db, "task_sessions") &&
|
||||||
|
(columnExists(db, "task_sessions", "session_params_json") ||
|
||||||
|
columnExists(db, "task_sessions", "session_display_id"));
|
||||||
|
const runsHasDeadCol =
|
||||||
|
tableExists(db, "runs") && columnExists(db, "runs", "session_display_id");
|
||||||
|
|
||||||
|
if (!sessionsHasDeadCols && !runsHasDeadCol) {
|
||||||
|
log.info("[migration v43] dead columns already absent; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.exec("PRAGMA foreign_keys = OFF");
|
||||||
|
try {
|
||||||
|
if (sessionsHasDeadCols) {
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE task_sessions_new (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
company_id TEXT NOT NULL,
|
||||||
|
agent_id TEXT NOT NULL,
|
||||||
|
adapter_type TEXT NOT NULL,
|
||||||
|
last_run_id TEXT,
|
||||||
|
last_error TEXT,
|
||||||
|
run_count INTEGER NOT NULL DEFAULT 0,
|
||||||
|
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
||||||
|
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
||||||
|
rotated_at TEXT,
|
||||||
|
rotation_reason TEXT,
|
||||||
|
handoff_markdown TEXT,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO task_sessions_new (
|
||||||
|
id, company_id, agent_id, adapter_type, last_run_id, last_error,
|
||||||
|
run_count, total_input_tokens, total_output_tokens, rotated_at,
|
||||||
|
rotation_reason, handoff_markdown, created_at, updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
id, company_id, agent_id, adapter_type, last_run_id, last_error,
|
||||||
|
run_count, total_input_tokens, total_output_tokens, rotated_at,
|
||||||
|
rotation_reason, handoff_markdown, created_at, updated_at
|
||||||
|
FROM task_sessions;
|
||||||
|
DROP TABLE task_sessions;
|
||||||
|
ALTER TABLE task_sessions_new RENAME TO task_sessions;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_task_sessions_company_agent
|
||||||
|
ON task_sessions(company_id, agent_id, updated_at);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_task_sessions_lookup
|
||||||
|
ON task_sessions(company_id, agent_id, adapter_type);
|
||||||
|
`);
|
||||||
|
log.info("[migration v43] rebuilt task_sessions without session_params_json/session_display_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runsHasDeadCol) {
|
||||||
|
// v16-v25 added `context_snapshot_json`; it is unreferenced by
|
||||||
|
// production code today but the column exists on real databases
|
||||||
|
// and carries no policy against preservation. Keep it so this
|
||||||
|
// migration's blast radius stays exactly one column.
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE runs_new (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
company_id TEXT NOT NULL,
|
||||||
|
task_id TEXT,
|
||||||
|
agent_id TEXT NOT NULL,
|
||||||
|
workspace_id TEXT,
|
||||||
|
connector_id TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
summary TEXT NOT NULL,
|
||||||
|
error_message TEXT,
|
||||||
|
exit_code INTEGER,
|
||||||
|
signal TEXT,
|
||||||
|
model TEXT,
|
||||||
|
cost_usd REAL,
|
||||||
|
unattributed_cost INTEGER NOT NULL DEFAULT 0,
|
||||||
|
context_snapshot_json TEXT,
|
||||||
|
actor_type TEXT,
|
||||||
|
actor_id TEXT,
|
||||||
|
started_at TEXT,
|
||||||
|
finished_at TEXT,
|
||||||
|
log_path TEXT,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO runs_new (
|
||||||
|
id, company_id, task_id, agent_id, workspace_id, connector_id,
|
||||||
|
status, summary, error_message, exit_code, signal, model,
|
||||||
|
cost_usd, unattributed_cost, context_snapshot_json, actor_type,
|
||||||
|
actor_id, started_at, finished_at, log_path, created_at, updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
id, company_id, task_id, agent_id, workspace_id, connector_id,
|
||||||
|
status, summary, error_message, exit_code, signal, model,
|
||||||
|
cost_usd, unattributed_cost, context_snapshot_json, actor_type,
|
||||||
|
actor_id, started_at, finished_at, log_path, created_at, updated_at
|
||||||
|
FROM runs;
|
||||||
|
DROP TABLE runs;
|
||||||
|
ALTER TABLE runs_new RENAME TO runs;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_company ON runs(company_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_task ON runs(task_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_agent ON runs(agent_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_company_status ON runs(company_id, status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_company_created_at ON runs(company_id, created_at DESC);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_runs_agent_created_at ON runs(agent_id, created_at DESC);
|
||||||
|
`);
|
||||||
|
log.info("[migration v43] rebuilt runs without session_display_id");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
db.exec("PRAGMA foreign_keys = ON");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ export function buildRunMethods(
|
|||||||
getRun(id: string): RunRecord {
|
getRun(id: string): RunRecord {
|
||||||
const row = getDb()
|
const row = getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
"select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId, connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode, signal, model, session_display_id as sessionDisplayId, cost_usd as costUsd, unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt, log_path as logPath, created_at as createdAt, updated_at as updatedAt from runs where id = ?",
|
"select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId, connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode, signal, model, cost_usd as costUsd, unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt, log_path as logPath, created_at as createdAt, updated_at as updatedAt from runs where id = ?",
|
||||||
)
|
)
|
||||||
.get(id) as RunRecord | undefined;
|
.get(id) as RunRecord | undefined;
|
||||||
if (!row) throw new Error(`Run not found: ${id}`);
|
if (!row) throw new Error(`Run not found: ${id}`);
|
||||||
@@ -93,7 +93,6 @@ export function buildRunMethods(
|
|||||||
exitCode: number | null;
|
exitCode: number | null;
|
||||||
signal: string | null;
|
signal: string | null;
|
||||||
model: string | null;
|
model: string | null;
|
||||||
sessionDisplayId: string | null;
|
|
||||||
unattributedCost: boolean;
|
unattributedCost: boolean;
|
||||||
}) {
|
}) {
|
||||||
const run = getDb().prepare("select task_id as taskId, agent_id as agentId, company_id as companyId, connector_id as connectorId, started_at as startedAt from runs where id = ?").get(input.runId) as
|
const run = getDb().prepare("select task_id as taskId, agent_id as agentId, company_id as companyId, connector_id as connectorId, started_at as startedAt from runs where id = ?").get(input.runId) as
|
||||||
@@ -134,11 +133,11 @@ export function buildRunMethods(
|
|||||||
transaction(() => {
|
transaction(() => {
|
||||||
getDb()
|
getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
"update runs set status = ?, summary = ?, error_message = ?, exit_code = ?, signal = ?, model = ?, session_display_id = ?, cost_usd = ?, unattributed_cost = ?, finished_at = ?, updated_at = ? where id = ?",
|
"update runs set status = ?, summary = ?, error_message = ?, exit_code = ?, signal = ?, model = ?, cost_usd = ?, unattributed_cost = ?, finished_at = ?, updated_at = ? where id = ?",
|
||||||
)
|
)
|
||||||
.run(
|
.run(
|
||||||
input.status, input.summary ?? "", input.errorMessage, input.exitCode,
|
input.status, input.summary ?? "", input.errorMessage, input.exitCode,
|
||||||
input.signal, input.model, input.sessionDisplayId, runCostUsd,
|
input.signal, input.model, runCostUsd,
|
||||||
input.unattributedCost ? 1 : 0, ts, ts, input.runId,
|
input.unattributedCost ? 1 : 0, ts, ts, input.runId,
|
||||||
);
|
);
|
||||||
if (run.taskId !== null) {
|
if (run.taskId !== null) {
|
||||||
@@ -201,7 +200,7 @@ export function buildRunMethods(
|
|||||||
const ts = nowIso();
|
const ts = nowIso();
|
||||||
getDb()
|
getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
"update runs set status = 'cancelled', summary = ?, error_message = null, exit_code = null, signal = null, model = null, session_display_id = null, cost_usd = null, unattributed_cost = 1, finished_at = ?, updated_at = ? where id = ?",
|
"update runs set status = 'cancelled', summary = ?, error_message = null, exit_code = null, signal = null, model = null, cost_usd = null, unattributed_cost = 1, finished_at = ?, updated_at = ? where id = ?",
|
||||||
)
|
)
|
||||||
.run(summary, ts, ts, runId);
|
.run(summary, ts, ts, runId);
|
||||||
if (taskId !== null) {
|
if (taskId !== null) {
|
||||||
@@ -242,7 +241,7 @@ export function buildRunMethods(
|
|||||||
return readAll<RunRecord>(
|
return readAll<RunRecord>(
|
||||||
`select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId,
|
`select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId,
|
||||||
connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode,
|
connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode,
|
||||||
signal, model, session_display_id as sessionDisplayId, cost_usd as costUsd,
|
signal, model, cost_usd as costUsd,
|
||||||
unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt,
|
unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt,
|
||||||
log_path as logPath, created_at as createdAt, updated_at as updatedAt
|
log_path as logPath, created_at as createdAt, updated_at as updatedAt
|
||||||
from runs
|
from runs
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { createMigrationsV38V39 } from "./migrations/v38-v39";
|
|||||||
import { createMigrationsV40V40 } from "./migrations/v40-v40";
|
import { createMigrationsV40V40 } from "./migrations/v40-v40";
|
||||||
import { createMigrationsV41V41 } from "./migrations/v41-v41";
|
import { createMigrationsV41V41 } from "./migrations/v41-v41";
|
||||||
import { createMigrationsV42V42 } from "./migrations/v42-v42";
|
import { createMigrationsV42V42 } from "./migrations/v42-v42";
|
||||||
|
import { createMigrationsV43V43 } from "./migrations/v43-v43";
|
||||||
import {
|
import {
|
||||||
columnExists,
|
columnExists,
|
||||||
nowIso,
|
nowIso,
|
||||||
@@ -180,6 +181,7 @@ export function runMigrations(
|
|||||||
...createMigrationsV40V40(deps),
|
...createMigrationsV40V40(deps),
|
||||||
...createMigrationsV41V41(deps),
|
...createMigrationsV41V41(deps),
|
||||||
...createMigrationsV42V42(deps),
|
...createMigrationsV42V42(deps),
|
||||||
|
...createMigrationsV43V43(deps),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const migration of migrations) {
|
for (const migration of migrations) {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export function buildSnapshotMethods(
|
|||||||
...companyArgs,
|
...companyArgs,
|
||||||
),
|
),
|
||||||
runs: readAll<RunRecord>(
|
runs: readAll<RunRecord>(
|
||||||
`select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId, connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode, signal, model, session_display_id as sessionDisplayId, cost_usd as costUsd, unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt, log_path as logPath, created_at as createdAt, updated_at as updatedAt from runs${companyWhere} order by created_at desc limit ${companyId ? 2000 : 2000}`,
|
`select id, company_id as companyId, task_id as taskId, agent_id as agentId, workspace_id as workspaceId, connector_id as connectorId, status, summary, error_message as errorMessage, exit_code as exitCode, signal, model, cost_usd as costUsd, unattributed_cost as unattributedCost, started_at as startedAt, finished_at as finishedAt, log_path as logPath, created_at as createdAt, updated_at as updatedAt from runs${companyWhere} order by created_at desc limit ${companyId ? 2000 : 2000}`,
|
||||||
...companyArgs,
|
...companyArgs,
|
||||||
).map((record) => ({ ...record, unattributedCost: Boolean(record.unattributedCost) })) as RunRecord[],
|
).map((record) => ({ ...record, unattributedCost: Boolean(record.unattributedCost) })) as RunRecord[],
|
||||||
costs: readAll<CostRecord>(
|
costs: readAll<CostRecord>(
|
||||||
|
|||||||
@@ -17,25 +17,6 @@ export function buildTaskSessionMethods(
|
|||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
/**
|
|
||||||
* Stamp pi-ai's transient per-turn state (session resume params,
|
|
||||||
* display id) onto the given agent session row. Called by the
|
|
||||||
* worker's run-finished handler with `event.taskSessionId`.
|
|
||||||
*/
|
|
||||||
updateSessionParams(
|
|
||||||
sessionId: string,
|
|
||||||
sessionParams: Record<string, unknown> | null,
|
|
||||||
sessionDisplayId: string | null,
|
|
||||||
): void {
|
|
||||||
const ts = nowIso();
|
|
||||||
const sessionParamsJson = sessionParams ? JSON.stringify(sessionParams) : null;
|
|
||||||
getDb()
|
|
||||||
.prepare(
|
|
||||||
"update task_sessions set session_params_json = ?, session_display_id = ?, updated_at = ? where id = ?",
|
|
||||||
)
|
|
||||||
.run(sessionParamsJson, sessionDisplayId, ts, sessionId);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a session by its primary key. This is the single lookup
|
* Fetch a session by its primary key. This is the single lookup
|
||||||
* path — the rotation evaluator, the worker's finalizer, and the
|
* path — the rotation evaluator, the worker's finalizer, and the
|
||||||
@@ -48,8 +29,7 @@ export function buildTaskSessionMethods(
|
|||||||
(getDb()
|
(getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
`SELECT id, company_id as companyId, agent_id as agentId,
|
`SELECT id, company_id as companyId, agent_id as agentId,
|
||||||
adapter_type as adapterType, session_params_json as sessionParamsJson,
|
adapter_type as adapterType, last_run_id as lastRunId,
|
||||||
session_display_id as sessionDisplayId, last_run_id as lastRunId,
|
|
||||||
last_error as lastError, run_count as runCount,
|
last_error as lastError, run_count as runCount,
|
||||||
total_input_tokens as totalInputTokens, total_output_tokens as totalOutputTokens,
|
total_input_tokens as totalInputTokens, total_output_tokens as totalOutputTokens,
|
||||||
rotated_at as rotatedAt, rotation_reason as rotationReason,
|
rotated_at as rotatedAt, rotation_reason as rotationReason,
|
||||||
@@ -111,9 +91,8 @@ export function buildTaskSessionMethods(
|
|||||||
getDb()
|
getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
`INSERT INTO task_sessions (id, company_id, agent_id, adapter_type,
|
`INSERT INTO task_sessions (id, company_id, agent_id, adapter_type,
|
||||||
session_params_json, session_display_id, run_count, total_input_tokens,
|
run_count, total_input_tokens, total_output_tokens, created_at, updated_at)
|
||||||
total_output_tokens, created_at, updated_at)
|
VALUES (?, ?, ?, ?, 0, 0, 0, ?, ?)`,
|
||||||
VALUES (?, ?, ?, ?, NULL, NULL, 0, 0, 0, ?, ?)`,
|
|
||||||
)
|
)
|
||||||
.run(sessionId, input.companyId, input.agentId, input.adapterType, ts, ts);
|
.run(sessionId, input.companyId, input.agentId, input.adapterType, ts, ts);
|
||||||
getDb()
|
getDb()
|
||||||
@@ -132,34 +111,22 @@ export function buildTaskSessionMethods(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a replacement session row after rotation. Inherits the
|
* Create a replacement session row after rotation. Inherits the
|
||||||
* agent / company / adapter type from the caller; session params
|
* agent / company / adapter type from the caller. Counters start
|
||||||
* and display id carry forward so the next pi-ai turn can resume.
|
* at zero — Pi Mono has no per-turn provider state to carry forward.
|
||||||
*/
|
*/
|
||||||
createNewSession(input: {
|
createNewSession(input: {
|
||||||
companyId: string;
|
companyId: string;
|
||||||
agentId: string;
|
agentId: string;
|
||||||
adapterType: string;
|
adapterType: string;
|
||||||
sessionParamsJson: string | null;
|
|
||||||
sessionDisplayId: string | null;
|
|
||||||
}): string {
|
}): string {
|
||||||
const sessionId = randomUUID();
|
const sessionId = randomUUID();
|
||||||
const ts = nowIso();
|
const ts = nowIso();
|
||||||
getDb()
|
getDb()
|
||||||
.prepare(
|
.prepare(
|
||||||
`INSERT INTO task_sessions (id, company_id, agent_id, adapter_type,
|
`INSERT INTO task_sessions (id, company_id, agent_id, adapter_type, created_at, updated_at)
|
||||||
session_params_json, session_display_id, created_at, updated_at)
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
||||||
)
|
)
|
||||||
.run(
|
.run(sessionId, input.companyId, input.agentId, input.adapterType, ts, ts);
|
||||||
sessionId,
|
|
||||||
input.companyId,
|
|
||||||
input.agentId,
|
|
||||||
input.adapterType,
|
|
||||||
input.sessionParamsJson,
|
|
||||||
input.sessionDisplayId,
|
|
||||||
ts,
|
|
||||||
ts,
|
|
||||||
);
|
|
||||||
return sessionId;
|
return sessionId;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ export function createRunDispatch(deps: OrchestrationDependencies) {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ export function createTaskRunner(
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
db.addActivity({
|
db.addActivity({
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ function resolveEnabledConnectorModels(
|
|||||||
function resolveSession(
|
function resolveSession(
|
||||||
db: AppDatabase,
|
db: AppDatabase,
|
||||||
agent: RunDispatchParams["agent"],
|
agent: RunDispatchParams["agent"],
|
||||||
task: RunDispatchParams["task"],
|
|
||||||
companyId: string,
|
companyId: string,
|
||||||
connectorId: string,
|
connectorId: string,
|
||||||
sessionHandoff: string | null,
|
sessionHandoff: string | null,
|
||||||
@@ -172,23 +171,8 @@ function resolveSession(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `sessionParams` / `sessionDisplayId` are transient per-run state pi-ai
|
|
||||||
// stamps onto the session row after a turn (e.g., Gemini's resume id).
|
|
||||||
// They live on the agent session; read directly by session id.
|
|
||||||
let sessionParams: Record<string, unknown> | null = null;
|
|
||||||
let sessionDisplayId: string | null = null;
|
|
||||||
const currentSession = db.getSessionById(currentSessionId);
|
|
||||||
if (currentSession?.sessionParamsJson) {
|
|
||||||
sessionParams = JSON.parse(currentSession.sessionParamsJson) as Record<string, unknown>;
|
|
||||||
sessionDisplayId = currentSession.sessionDisplayId;
|
|
||||||
}
|
|
||||||
// Suppress the unused-parameter warning while keeping the signature
|
|
||||||
// stable — task identity is reported through other fields on the
|
|
||||||
// payload, not through the session row anymore.
|
|
||||||
void task;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
taskSession: { id: currentSessionId, sessionParams, sessionDisplayId },
|
taskSessionId: currentSessionId,
|
||||||
sessionHandoff: finalHandoff,
|
sessionHandoff: finalHandoff,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -292,7 +276,7 @@ export function buildRunPayload(params: RunDispatchParams, deps: TurnContextDeps
|
|||||||
const reviewTasks = db.listReviewTasksForManager(agent.id, companyId);
|
const reviewTasks = db.listReviewTasksForManager(agent.id, companyId);
|
||||||
const recentComments = assembleRecentComments(assignedTasks, reviewTasks, snapshot);
|
const recentComments = assembleRecentComments(assignedTasks, reviewTasks, snapshot);
|
||||||
const initialHandoff = resolveSessionHandoff(agent.id, deps);
|
const initialHandoff = resolveSessionHandoff(agent.id, deps);
|
||||||
const { taskSession, sessionHandoff } = resolveSession(db, agent, task, companyId, connector.id, initialHandoff, deps);
|
const { taskSessionId, sessionHandoff } = resolveSession(db, agent, companyId, connector.id, initialHandoff, deps);
|
||||||
const skills = resolveSkills(companyId, agent.id, connector.id, agent.name, deps);
|
const skills = resolveSkills(companyId, agent.id, connector.id, agent.name, deps);
|
||||||
|
|
||||||
const systemPrompt = apiUrl ? buildTaskPrompt({
|
const systemPrompt = apiUrl ? buildTaskPrompt({
|
||||||
@@ -363,10 +347,9 @@ export function buildRunPayload(params: RunDispatchParams, deps: TurnContextDeps
|
|||||||
model: modelSelection.effectiveModel,
|
model: modelSelection.effectiveModel,
|
||||||
thinkingEffort,
|
thinkingEffort,
|
||||||
env,
|
env,
|
||||||
sessionParams: taskSession.sessionParams,
|
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
trigger,
|
trigger,
|
||||||
taskSessionId: taskSession.id ?? runId,
|
taskSessionId: taskSessionId ?? runId,
|
||||||
executionMode: db.getCompanyExecutionMode(companyId) as "ai_ceo" | "ai_cofounder",
|
executionMode: db.getCompanyExecutionMode(companyId) as "ai_ceo" | "ai_cofounder",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,6 @@ export interface EnqueueRunPayload {
|
|||||||
model: string | null;
|
model: string | null;
|
||||||
thinkingEffort: string | null;
|
thinkingEffort: string | null;
|
||||||
env: Record<string, string>;
|
env: Record<string, string>;
|
||||||
sessionParams: Record<string, unknown> | null;
|
|
||||||
systemPrompt: string | null;
|
systemPrompt: string | null;
|
||||||
trigger: string | null;
|
trigger: string | null;
|
||||||
/** Task session id used by SqliteSessionStore to load/append messages. */
|
/** Task session id used by SqliteSessionStore to load/append messages. */
|
||||||
|
|||||||
@@ -136,28 +136,22 @@ export function createSessionManagementService({ db, logger }: SessionManagement
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Archive current session, generate handoff, create new agent-scoped
|
// Archive current session, generate handoff, create new agent-scoped
|
||||||
// session, update the agent pointer and any task active-session pointers
|
// session, update the agent pointer. Counters reset; Pi Mono carries no
|
||||||
// still referencing the old session.
|
// provider-side resume state across rotations.
|
||||||
function rotateSession(session: TaskSessionRecord): string {
|
function rotateSession(session: TaskSessionRecord): string {
|
||||||
const reason = "threshold_exceeded";
|
const reason = "threshold_exceeded";
|
||||||
const handoff = generateHandoff(session);
|
const handoff = generateHandoff(session);
|
||||||
|
|
||||||
logger.info(`[session] Rotating session ${session.id} for agent ${session.agentId}: ${reason}`);
|
logger.info(`[session] Rotating session ${session.id} for agent ${session.agentId}: ${reason}`);
|
||||||
|
|
||||||
// 1. Archive old session
|
|
||||||
db.archiveSession(session.id, reason, handoff);
|
db.archiveSession(session.id, reason, handoff);
|
||||||
|
|
||||||
// 2. Create new session row with fresh counters, carry forward
|
|
||||||
// session_params so pi-ai can resume.
|
|
||||||
const newSessionId = db.createNewSession({
|
const newSessionId = db.createNewSession({
|
||||||
companyId: session.companyId,
|
companyId: session.companyId,
|
||||||
agentId: session.agentId,
|
agentId: session.agentId,
|
||||||
adapterType: session.adapterType,
|
adapterType: session.adapterType,
|
||||||
sessionParamsJson: session.sessionParamsJson,
|
|
||||||
sessionDisplayId: session.sessionDisplayId,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. Point the agent at the freshly-minted session.
|
|
||||||
db.setAgentSessionId(session.agentId, newSessionId);
|
db.setAgentSessionId(session.agentId, newSessionId);
|
||||||
|
|
||||||
logger.info(`[session] New session ${newSessionId} created for agent ${session.agentId}`);
|
logger.info(`[session] New session ${newSessionId} created for agent ${session.agentId}`);
|
||||||
|
|||||||
@@ -176,7 +176,6 @@ export function createWorkerService({
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
if (run.workspaceId) {
|
if (run.workspaceId) {
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ export function finalizeRun(
|
|||||||
exitCode: event.exitCode,
|
exitCode: event.exitCode,
|
||||||
signal: event.signal,
|
signal: event.signal,
|
||||||
model: event.model,
|
model: event.model,
|
||||||
sessionDisplayId: event.sessionDisplayId,
|
|
||||||
unattributedCost: event.unattributedCost,
|
unattributedCost: event.unattributedCost,
|
||||||
inputTokens: event.inputTokens,
|
inputTokens: event.inputTokens,
|
||||||
outputTokens: event.outputTokens,
|
outputTokens: event.outputTokens,
|
||||||
@@ -66,21 +65,6 @@ export function finalizeRun(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stamp pi-ai's transient per-turn state (session resume params,
|
|
||||||
// display id) onto the agent's current session row. Sessions are
|
|
||||||
// agent-scoped, so the session id comes from agents.session_id —
|
|
||||||
// not from a task pointer (that indirection was dropped in v41).
|
|
||||||
try {
|
|
||||||
const agent = db.getAgent(run.agentId);
|
|
||||||
if (agent.sessionId) {
|
|
||||||
db.updateSessionParams(agent.sessionId, event.sessionParams, event.sessionDisplayId ?? null);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.warn(
|
|
||||||
`[finalizeRun] updateSessionParams failed for run ${event.runId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
leaseRenewalMap.delete(event.runId);
|
leaseRenewalMap.delete(event.runId);
|
||||||
const runOutcome = db.finishRun(event);
|
const runOutcome = db.finishRun(event);
|
||||||
if (run.workspaceId) {
|
if (run.workspaceId) {
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ export function handleWorkerExit(
|
|||||||
exitCode: code,
|
exitCode: code,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
if (run.workspaceId) {
|
if (run.workspaceId) {
|
||||||
@@ -128,7 +127,6 @@ export function handleWorkerExit(
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
if (candidate.workspaceId) {
|
if (candidate.workspaceId) {
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ function cancelRun(runId: string) {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionParams: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
inputTokens: null,
|
inputTokens: null,
|
||||||
outputTokens: null,
|
outputTokens: null,
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export interface RunJob {
|
|||||||
model: string | null;
|
model: string | null;
|
||||||
thinkingEffort: string | null;
|
thinkingEffort: string | null;
|
||||||
env: Record<string, string>;
|
env: Record<string, string>;
|
||||||
sessionParams: Record<string, unknown> | null;
|
|
||||||
systemPrompt: string | null;
|
systemPrompt: string | null;
|
||||||
trigger: string | null;
|
trigger: string | null;
|
||||||
taskSessionId: string;
|
taskSessionId: string;
|
||||||
@@ -41,8 +40,6 @@ export type ChildMessage =
|
|||||||
exitCode: number | null;
|
exitCode: number | null;
|
||||||
signal: string | null;
|
signal: string | null;
|
||||||
model: string | null;
|
model: string | null;
|
||||||
sessionParams: Record<string, unknown> | null;
|
|
||||||
sessionDisplayId: string | null;
|
|
||||||
unattributedCost: boolean;
|
unattributedCost: boolean;
|
||||||
inputTokens: number | null;
|
inputTokens: number | null;
|
||||||
outputTokens: number | null;
|
outputTokens: number | null;
|
||||||
|
|||||||
@@ -194,8 +194,6 @@ export class WorkerRunner {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: resolvedModelId,
|
model: resolvedModelId,
|
||||||
sessionParams: job.sessionParams,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
// Worker no longer owns cost attribution — CostWriter (main-side)
|
// Worker no longer owns cost attribution — CostWriter (main-side)
|
||||||
// writes per-message rows, finishRun sums them. This flag stays true
|
// writes per-message rows, finishRun sums them. This flag stays true
|
||||||
// only for run paths that never had a chance to emit usage (errors
|
// only for run paths that never had a chance to emit usage (errors
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ export const workerMessageSchema = z.union([
|
|||||||
exitCode: z.number().int().nullable(),
|
exitCode: z.number().int().nullable(),
|
||||||
signal: z.string().nullable(),
|
signal: z.string().nullable(),
|
||||||
model: z.string().nullable(),
|
model: z.string().nullable(),
|
||||||
sessionParams: z.record(z.string(), z.unknown()).nullable(),
|
|
||||||
sessionDisplayId: z.string().nullable(),
|
|
||||||
unattributedCost: z.boolean(),
|
unattributedCost: z.boolean(),
|
||||||
inputTokens: z.number().nullable(),
|
inputTokens: z.number().nullable(),
|
||||||
outputTokens: z.number().nullable(),
|
outputTokens: z.number().nullable(),
|
||||||
|
|||||||
@@ -192,7 +192,6 @@ export interface RunRecord {
|
|||||||
exitCode: number | null;
|
exitCode: number | null;
|
||||||
signal: string | null;
|
signal: string | null;
|
||||||
model: string | null;
|
model: string | null;
|
||||||
sessionDisplayId: string | null;
|
|
||||||
costUsd: number | null;
|
costUsd: number | null;
|
||||||
unattributedCost: boolean;
|
unattributedCost: boolean;
|
||||||
startedAt: string | null;
|
startedAt: string | null;
|
||||||
@@ -275,8 +274,6 @@ export interface TaskSessionRecord {
|
|||||||
companyId: string;
|
companyId: string;
|
||||||
agentId: string;
|
agentId: string;
|
||||||
adapterType: string;
|
adapterType: string;
|
||||||
sessionParamsJson: string | null;
|
|
||||||
sessionDisplayId: string | null;
|
|
||||||
lastRunId: string | null;
|
lastRunId: string | null;
|
||||||
lastError: string | null;
|
lastError: string | null;
|
||||||
runCount: number;
|
runCount: number;
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ describe("agent model switching", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gpt-5.4",
|
model: "gpt-5.4",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
|
|||||||
exitCode: 1,
|
exitCode: 1,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ describe("Step 6: Run failure escalation (database layer)", () => {
|
|||||||
exitCode: 1,
|
exitCode: 1,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gpt-5-codex",
|
model: "gpt-5-codex",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-2.5-pro",
|
model: "gemini-2.5-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -226,8 +225,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
companyId: s.companyId,
|
companyId: s.companyId,
|
||||||
agentId: s.agentId,
|
agentId: s.agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
sessionService.accumulateTokenUsage(sessionId, 5000, 2000, runId);
|
sessionService.accumulateTokenUsage(sessionId, 5000, 2000, runId);
|
||||||
|
|
||||||
@@ -344,7 +341,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-2.5-pro",
|
model: "gemini-2.5-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -383,8 +379,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
companyId: s.companyId,
|
companyId: s.companyId,
|
||||||
agentId: s.agentId,
|
agentId: s.agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Run 1: create run and accumulate tokens
|
// Run 1: create run and accumulate tokens
|
||||||
@@ -456,7 +450,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-2.5-pro",
|
model: "gemini-2.5-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -498,7 +491,6 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-2.5-pro",
|
model: "gemini-2.5-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ describe("AppDatabase", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gpt-5-codex",
|
model: "gpt-5-codex",
|
||||||
sessionDisplayId: "session-1",
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -444,8 +444,6 @@ describe("Process Recovery -- Context Preservation (D-02)", () => {
|
|||||||
companyId: s.companyId,
|
companyId: s.companyId,
|
||||||
agentId: s.agentId,
|
agentId: s.agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add token usage to simulate real work
|
// Add token usage to simulate real work
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ describe("CAS checkout", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -337,7 +336,6 @@ describe("CAS checkout", () => {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -382,7 +380,6 @@ describe("CAS checkout", () => {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -417,7 +414,6 @@ describe("CAS checkout", () => {
|
|||||||
exitCode: 1,
|
exitCode: 1,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ function makeRun(overrides: Partial<RunRecord> = {}): RunRecord {
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
costUsd: null,
|
costUsd: null,
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
startedAt: null,
|
startedAt: null,
|
||||||
|
|||||||
@@ -296,7 +296,6 @@ describe("AppDatabase", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gpt-5",
|
model: "gpt-5",
|
||||||
sessionDisplayId: "session-budget",
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -515,7 +514,6 @@ describe("AppDatabase", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: true,
|
unattributedCost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -182,7 +181,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -234,7 +232,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -283,7 +280,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -341,7 +337,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -394,7 +389,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -443,7 +437,6 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -118,8 +118,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Simulate runs until we reach the maxRuns threshold (20)
|
// Simulate runs until we reach the maxRuns threshold (20)
|
||||||
@@ -146,8 +144,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accumulate tokens past the threshold in one big call
|
// Accumulate tokens past the threshold in one big call
|
||||||
@@ -172,8 +168,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accumulate enough to trigger rotation
|
// Accumulate enough to trigger rotation
|
||||||
@@ -197,7 +191,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -229,8 +222,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: JSON.stringify({ resumeKey: "abc" }),
|
|
||||||
sessionDisplayId: "gemini-session-1",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add usage to the old session
|
// Add usage to the old session
|
||||||
@@ -244,8 +235,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: JSON.stringify({ resumeKey: "abc" }),
|
|
||||||
sessionDisplayId: "gemini-session-2",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get the new active session
|
// Get the new active session
|
||||||
@@ -268,8 +257,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accumulate way past all thresholds
|
// Accumulate way past all thresholds
|
||||||
@@ -292,8 +279,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "openai-codex",
|
adapterType: "openai-codex",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accumulate way past all thresholds
|
// Accumulate way past all thresholds
|
||||||
@@ -317,8 +302,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
db.incrementSessionUsage(sessionId, 300000, 200000, "run-1");
|
db.incrementSessionUsage(sessionId, 300000, 200000, "run-1");
|
||||||
|
|
||||||
@@ -338,7 +321,6 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -106,8 +106,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: JSON.stringify({ sessionId: "abc123" }),
|
|
||||||
sessionDisplayId: "claude-abc123",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const session = db.getSessionById(sessionId);
|
const session = db.getSessionById(sessionId);
|
||||||
@@ -116,8 +114,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
expect(session!.companyId).toBe(companyId);
|
expect(session!.companyId).toBe(companyId);
|
||||||
expect(session!.agentId).toBe(agentId);
|
expect(session!.agentId).toBe(agentId);
|
||||||
expect(session!.adapterType).toBe("claude-pro");
|
expect(session!.adapterType).toBe("claude-pro");
|
||||||
expect(session!.sessionParamsJson).toBe(JSON.stringify({ sessionId: "abc123" }));
|
|
||||||
expect(session!.sessionDisplayId).toBe("claude-abc123");
|
|
||||||
expect(session!.runCount).toBe(0);
|
expect(session!.runCount).toBe(0);
|
||||||
expect(session!.totalInputTokens).toBe(0);
|
expect(session!.totalInputTokens).toBe(0);
|
||||||
expect(session!.totalOutputTokens).toBe(0);
|
expect(session!.totalOutputTokens).toBe(0);
|
||||||
@@ -132,8 +128,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
db.incrementSessionUsage(sessionId, 1000, 500, "run-001");
|
db.incrementSessionUsage(sessionId, 1000, 500, "run-001");
|
||||||
@@ -159,8 +153,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
db.archiveSession(sessionId, "max_runs", "# Handoff\nSession reached 20 runs.");
|
db.archiveSession(sessionId, "max_runs", "# Handoff\nSession reached 20 runs.");
|
||||||
@@ -178,8 +170,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: JSON.stringify({ key: "val" }),
|
|
||||||
sessionDisplayId: "gemini-session-1",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(typeof sessionId).toBe("string");
|
expect(typeof sessionId).toBe("string");
|
||||||
@@ -204,7 +194,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "claude-4-opus",
|
model: "claude-4-opus",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -217,7 +206,6 @@ describe("task_sessions CRUD", () => {
|
|||||||
exitCode: 1,
|
exitCode: 1,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "claude-4-opus",
|
model: "claude-4-opus",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -292,8 +280,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 5,
|
runCount: 5,
|
||||||
@@ -317,8 +303,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 20,
|
runCount: 20,
|
||||||
@@ -342,8 +326,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 3,
|
runCount: 3,
|
||||||
@@ -368,8 +350,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 1,
|
runCount: 1,
|
||||||
@@ -398,8 +378,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 100, // Way over threshold
|
runCount: 100, // Way over threshold
|
||||||
@@ -428,8 +406,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 5,
|
runCount: 5,
|
||||||
@@ -453,8 +429,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 10, // Below default 20
|
runCount: 10, // Below default 20
|
||||||
@@ -478,8 +452,6 @@ describe("session management service", () => {
|
|||||||
companyId: "co-1",
|
companyId: "co-1",
|
||||||
agentId: "agent-1",
|
agentId: "agent-1",
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
lastRunId: null,
|
lastRunId: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
runCount: 19, // Just below default 20
|
runCount: 19, // Just below default 20
|
||||||
@@ -512,8 +484,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "claude-pro",
|
adapterType: "claude-pro",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
const svc = createSessionManagementService({ db, logger: mockLogger });
|
const svc = createSessionManagementService({ db, logger: mockLogger });
|
||||||
|
|
||||||
@@ -537,8 +507,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a completed run for history
|
// Create a completed run for history
|
||||||
@@ -551,7 +519,6 @@ describe("session management service", () => {
|
|||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: "gemini-pro",
|
model: "gemini-pro",
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -584,8 +551,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: JSON.stringify({ resumeId: "old-abc" }),
|
|
||||||
sessionDisplayId: "gemini-old",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add some usage
|
// Add some usage
|
||||||
@@ -606,14 +571,12 @@ describe("session management service", () => {
|
|||||||
expect(archivedRows[0].rotationReason).toBe("threshold_exceeded");
|
expect(archivedRows[0].rotationReason).toBe("threshold_exceeded");
|
||||||
expect(archivedRows[0].handoffMarkdown).toContain("# Session Handoff");
|
expect(archivedRows[0].handoffMarkdown).toContain("# Session Handoff");
|
||||||
|
|
||||||
// New session is a distinct row, with fresh counters and copied params
|
// New session is a distinct row with fresh counters.
|
||||||
const newSession = db.getSessionById(newSessionId)!;
|
const newSession = db.getSessionById(newSessionId)!;
|
||||||
expect(newSession.id).toBe(newSessionId);
|
expect(newSession.id).toBe(newSessionId);
|
||||||
expect(newSession.runCount).toBe(0);
|
expect(newSession.runCount).toBe(0);
|
||||||
expect(newSession.totalInputTokens).toBe(0);
|
expect(newSession.totalInputTokens).toBe(0);
|
||||||
expect(newSession.totalOutputTokens).toBe(0);
|
expect(newSession.totalOutputTokens).toBe(0);
|
||||||
expect(newSession.sessionParamsJson).toBe(JSON.stringify({ resumeId: "old-abc" }));
|
|
||||||
expect(newSession.sessionDisplayId).toBe("gemini-old");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -630,8 +593,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
db.incrementSessionUsage(session1Id, 100000, 50000, "run-1");
|
db.incrementSessionUsage(session1Id, 100000, 50000, "run-1");
|
||||||
const session1 = db.getSessionById(session1Id)!;
|
const session1 = db.getSessionById(session1Id)!;
|
||||||
@@ -648,8 +609,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
const svc = createSessionManagementService({ db, logger: mockLogger });
|
const svc = createSessionManagementService({ db, logger: mockLogger });
|
||||||
|
|
||||||
@@ -668,8 +627,6 @@ describe("session management service", () => {
|
|||||||
companyId,
|
companyId,
|
||||||
agentId,
|
agentId,
|
||||||
adapterType: "gemini-cli",
|
adapterType: "gemini-cli",
|
||||||
sessionParamsJson: null,
|
|
||||||
sessionDisplayId: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pre-populate some usage
|
// Pre-populate some usage
|
||||||
|
|||||||
@@ -270,7 +270,6 @@ const fakeTask = (id: string, title = "Task"): TaskRecord => ({
|
|||||||
priority: "medium",
|
priority: "medium",
|
||||||
activeRunId: null,
|
activeRunId: null,
|
||||||
sessionJson: null,
|
sessionJson: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
requiresUserReview: false,
|
requiresUserReview: false,
|
||||||
startedAt: null,
|
startedAt: null,
|
||||||
completedAt: null,
|
completedAt: null,
|
||||||
@@ -292,7 +291,6 @@ const fakeRun = (id: string): RunRecord => ({
|
|||||||
exitCode: null,
|
exitCode: null,
|
||||||
signal: null,
|
signal: null,
|
||||||
model: null,
|
model: null,
|
||||||
sessionDisplayId: null,
|
|
||||||
unattributedCost: false,
|
unattributedCost: false,
|
||||||
startedAt: null,
|
startedAt: null,
|
||||||
finishedAt: null,
|
finishedAt: null,
|
||||||
|
|||||||
Reference in new issue
Block a user