sparkecoder 0.1.84 → 0.1.86
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/agent/index.js +30 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +30 -2
- package/dist/cli.js.map +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +30 -2
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +1 -8
- package/dist/tools/index.js +30 -2
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/package-lock.json +3 -3
- /package/web/.next/standalone/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_ssgManifest.js +0 -0
- /package/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_buildManifest.js +0 -0
- /package/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{VBh1WkbuEIMDsCx5In9kr → Pt6kwIO6lniM7h7I5E6kk}/_ssgManifest.js +0 -0
package/dist/db/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/db/remote.ts","../../src/db/index.ts"],"sourcesContent":["/**\n * Remote database client\n * \n * Implements the same interface as the local SQLite database\n * but calls the remote server via HTTP.\n */\n\nimport type {\n Session,\n Message,\n ToolExecution,\n TodoItem,\n ModelMessage,\n Terminal,\n ActiveStream,\n Checkpoint,\n FileBackup,\n SubagentExecution,\n SubagentStep,\n IndexedChunk,\n IndexStatusRecord,\n LoadedSkill,\n} from './schema.js';\n\nlet remoteServerUrl: string | null = null;\nlet authKey: string | null = null;\n\n/**\n * Initialize the remote database client\n */\nexport function initRemoteDatabase(serverUrl: string, key: string) {\n remoteServerUrl = serverUrl.replace(/\\/$/, ''); // Remove trailing slash\n authKey = key;\n}\n\n/**\n * Close the remote client (no-op, just for API compatibility)\n */\nexport function closeRemoteDatabase() {\n remoteServerUrl = null;\n authKey = null;\n}\n\n/**\n * Check if remote database is configured\n */\nexport function isRemoteConfigured(): boolean {\n return !!remoteServerUrl && !!authKey;\n}\n\n/**\n * Date fields that should be parsed from ISO strings to Date objects.\n * These are top-level metadata fields on database records (Session, Message, etc.),\n * NOT fields inside modelMessage content (tool outputs, etc.).\n */\nconst DATE_FIELDS = ['createdAt', 'updatedAt', 'startedAt', 'completedAt', 'stoppedAt', 'finishedAt', 'loadedAt', 'indexedAt', 'lastFullIndex', 'lastIncrementalIndex'];\n\n/**\n * Fields that contain AI SDK ModelMessage data and should NOT be recursively\n * processed by parseDates. The AI SDK's Zod schema requires tool output values\n * to be valid JSON primitives (string, number, boolean, null, object, array).\n * Converting date strings to Date objects inside these fields corrupts them and\n * causes AI_InvalidPromptError when the messages are passed back to streamText().\n */\nconst MODEL_MESSAGE_FIELDS = ['modelMessage', 'modelMessages'];\n\n/**\n * Parse date strings to Date objects on top-level record fields only.\n * \n * IMPORTANT: Does NOT recurse into `modelMessage` / `modelMessages` fields.\n * Those contain AI SDK ModelMessage data that must remain JSON-serializable.\n * Recursing into them converts date strings (e.g. `createdAt` inside tool\n * result outputs) to Date objects, which violates the AI SDK's jsonValueSchema\n * and triggers AI_InvalidPromptError on subsequent streamText() calls.\n */\nfunction parseDates(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n if (Array.isArray(obj)) return obj.map(parseDates);\n if (typeof obj !== 'object' || obj instanceof Date) return obj;\n \n const result = { ...obj };\n for (const key of Object.keys(result)) {\n // Skip modelMessage fields entirely - these must stay JSON-serializable\n if (MODEL_MESSAGE_FIELDS.includes(key)) {\n continue;\n }\n if (DATE_FIELDS.includes(key) && typeof result[key] === 'string') {\n result[key] = new Date(result[key]);\n } else if (typeof result[key] === 'object') {\n result[key] = parseDates(result[key]);\n }\n }\n return result;\n}\n\n/**\n * HTTP helper for remote API calls\n * @param options.skipParseDates - If true, skip the parseDates post-processing.\n * Use for endpoints that return ModelMessage[] directly, since those must\n * remain JSON-serializable for the AI SDK.\n */\nasync function api<T>(\n path: string,\n options: { method?: string; body?: unknown; skipParseDates?: boolean } = {}\n): Promise<T> {\n if (!remoteServerUrl || !authKey) {\n throw new Error('Remote database not initialized');\n }\n \n const url = `${remoteServerUrl}/db${path}`;\n const init: RequestInit = {\n method: options.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authKey}`,\n },\n };\n \n if (options.body) {\n init.body = JSON.stringify(options.body);\n }\n \n const response = await fetch(url, init);\n \n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n \n const text = await response.text();\n if (!text || text === 'null') {\n return null as T;\n }\n \n const parsed = JSON.parse(text);\n\n // Skip date parsing for raw ModelMessage data - it must stay JSON-serializable\n if (options.skipParseDates) {\n return parsed as T;\n }\n\n // Parse JSON and convert date strings to Date objects\n return parseDates(parsed) as T;\n}\n\n// ============================================\n// Session Queries\n// ============================================\n\nexport const remoteSessionQueries = {\n create(data: { workingDirectory: string; model: string; name?: string; config?: any }): Promise<Session> {\n return api<Session>('/sessions', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`).catch(() => undefined);\n },\n\n list(limit = 50, offset = 0): Promise<Session[]> {\n return api<Session[]>(`/sessions?limit=${limit}&offset=${offset}`);\n },\n\n updateStatus(id: string, status: Session['status']): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: { status } });\n },\n\n updateModel(id: string, model: string): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: { model } });\n },\n\n update(id: string, updates: { model?: string; name?: string; config?: any }): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: updates });\n },\n\n delete(id: string): Promise<boolean> {\n return api<{ success: boolean }>(`/sessions/${id}`, { method: 'DELETE' }).then(r => r?.success ?? false);\n },\n};\n\n// ============================================\n// Message Queries\n// ============================================\n\nexport const remoteMessageQueries = {\n async getNextSequence(sessionId: string): Promise<number> {\n const result = await api<{ nextSequence: number }>(`/messages/session/${sessionId}/next-sequence`);\n return result.nextSequence;\n },\n\n create(sessionId: string, modelMessage: ModelMessage): Promise<Message> {\n return api<Message>('/messages', { method: 'POST', body: { sessionId, modelMessage } });\n },\n\n addMany(sessionId: string, modelMessages: ModelMessage[]): Promise<Message[]> {\n return api<Message[]>('/messages/batch', { method: 'POST', body: { sessionId, modelMessages } });\n },\n\n getBySession(sessionId: string): Promise<Message[]> {\n return api<Message[]>(`/messages/session/${sessionId}`);\n },\n\n getModelMessages(sessionId: string): Promise<ModelMessage[]> {\n // IMPORTANT: skipParseDates=true because ModelMessage data must remain\n // JSON-serializable. The parseDates function would convert date strings\n // inside tool result outputs (e.g. todo items with createdAt) to Date\n // objects, which violates the AI SDK's jsonValueSchema and causes\n // AI_InvalidPromptError on subsequent streamText() calls.\n return api<ModelMessage[]>(`/messages/session/${sessionId}/model-messages`, { skipParseDates: true });\n },\n\n async getRecentBySession(sessionId: string, limit = 50): Promise<Message[]> {\n const messages = await api<Message[]>(`/messages/session/${sessionId}`);\n return messages.slice(-limit);\n },\n\n async countBySession(sessionId: string): Promise<number> {\n const result = await api<{ count: number }>(`/messages/session/${sessionId}/count`);\n return result.count;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/messages/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n\n async deleteFromSequence(sessionId: string, fromSequence: number): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/messages/session/${sessionId}/from-sequence/${fromSequence}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n};\n\n// ============================================\n// Tool Execution Queries\n// ============================================\n\nexport const remoteToolExecutionQueries = {\n create(data: {\n sessionId: string;\n messageId?: string;\n toolName: string;\n toolCallId: string;\n input?: any;\n requiresApproval?: boolean;\n status?: 'pending' | 'approved' | 'rejected' | 'completed' | 'error';\n }): Promise<ToolExecution> {\n return api<ToolExecution>('/tool-executions', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`).catch(() => undefined);\n },\n\n getByToolCallId(toolCallId: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/by-tool-call-id/${toolCallId}`).catch(() => undefined);\n },\n\n getPendingApprovals(sessionId: string): Promise<ToolExecution[]> {\n return api<ToolExecution[]>(`/tool-executions/session/${sessionId}/pending`);\n },\n\n approve(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, { method: 'PATCH', body: { status: 'approved' } });\n },\n\n reject(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, { method: 'PATCH', body: { status: 'rejected' } });\n },\n\n complete(id: string, output: unknown, error?: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, {\n method: 'PATCH',\n body: { status: error ? 'error' : 'completed', output, error },\n });\n },\n\n getBySession(sessionId: string): Promise<ToolExecution[]> {\n return api<ToolExecution[]>(`/tool-executions/session/${sessionId}`);\n },\n\n async deleteAfterTime(sessionId: string, afterTime: Date | string): Promise<number> {\n // Handle both Date objects and ISO strings\n const timestamp = afterTime instanceof Date ? afterTime.getTime() : new Date(afterTime).getTime();\n const result = await api<{ deleted: number }>(\n `/tool-executions/session/${sessionId}/after/${timestamp}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n};\n\n// ============================================\n// Todo Queries\n// ============================================\n\nexport const remoteTodoQueries = {\n create(data: { sessionId: string; content: string; order?: number }): Promise<TodoItem> {\n return api<TodoItem>('/todos', { method: 'POST', body: data });\n },\n\n createMany(sessionId: string, items: Array<{ content: string; order?: number }>): Promise<TodoItem[]> {\n return api<TodoItem[]>('/todos/batch', { method: 'POST', body: { sessionId, items } });\n },\n\n getBySession(sessionId: string): Promise<TodoItem[]> {\n return api<TodoItem[]>(`/todos/session/${sessionId}`);\n },\n\n updateStatus(id: string, status: TodoItem['status']): Promise<TodoItem | undefined> {\n return api<TodoItem | undefined>(`/todos/${id}`, { method: 'PATCH', body: { status } });\n },\n\n async delete(id: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/todos/${id}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n async clearSession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/todos/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Skill Queries\n// ============================================\n\nexport const remoteSkillQueries = {\n load(sessionId: string, skillName: string): Promise<LoadedSkill> {\n return api<LoadedSkill>('/skills', { method: 'POST', body: { sessionId, skillName } });\n },\n\n getBySession(sessionId: string): Promise<LoadedSkill[]> {\n return api<LoadedSkill[]>(`/skills/session/${sessionId}`);\n },\n\n async isLoaded(sessionId: string, skillName: string): Promise<boolean> {\n const result = await api<{ isLoaded: boolean }>(`/skills/session/${sessionId}/is-loaded/${skillName}`);\n return result.isLoaded;\n },\n};\n\n// ============================================\n// Terminal Queries\n// ============================================\n\nexport const remoteTerminalQueries = {\n create(data: { sessionId: string; command: string; cwd: string; name?: string }): Promise<Terminal> {\n return api<Terminal>('/terminals', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<Terminal[]> {\n return api<Terminal[]>(`/terminals/session/${sessionId}`);\n },\n\n getRunning(sessionId: string): Promise<Terminal[]> {\n return api<Terminal[]>(`/terminals/session/${sessionId}/running`);\n },\n\n updateStatus(id: string, status: Terminal['status'], exitCode?: number, error?: string): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`, { method: 'PATCH', body: { status, exitCode, error } });\n },\n\n updatePid(id: string, pid: number): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`, { method: 'PATCH', body: { pid } });\n },\n\n async delete(id: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/terminals/${id}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/terminals/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Active Stream Queries\n// ============================================\n\nexport const remoteActiveStreamQueries = {\n create(sessionId: string, streamId: string): Promise<ActiveStream> {\n return api<ActiveStream>('/streams', { method: 'POST', body: { sessionId, streamId } });\n },\n\n getBySessionId(sessionId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | null>(`/streams/session/${sessionId}`).then(r => r ?? undefined);\n },\n\n getByStreamId(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`).catch(() => undefined);\n },\n\n finish(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`, { method: 'PATCH', body: { status: 'finished' } });\n },\n\n markError(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`, { method: 'PATCH', body: { status: 'error' } });\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/streams/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Checkpoint Queries\n// ============================================\n\nexport const remoteCheckpointQueries = {\n create(data: { sessionId: string; messageSequence: number; gitHead?: string }): Promise<Checkpoint> {\n return api<Checkpoint>('/checkpoints', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Checkpoint | undefined> {\n return api<Checkpoint | undefined>(`/checkpoints/${id}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<Checkpoint[]> {\n return api<Checkpoint[]>(`/checkpoints/session/${sessionId}`);\n },\n\n getByMessageSequence(sessionId: string, messageSequence: number): Promise<Checkpoint | undefined> {\n return api<Checkpoint | null>(`/checkpoints/session/${sessionId}/by-sequence/${messageSequence}`).then(r => r ?? undefined);\n },\n\n getLatest(sessionId: string): Promise<Checkpoint | undefined> {\n return api<Checkpoint | null>(`/checkpoints/session/${sessionId}/latest`).then(r => r ?? undefined);\n },\n\n async deleteAfterSequence(sessionId: string, messageSequence: number): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/checkpoints/session/${sessionId}/after-sequence/${messageSequence}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/checkpoints/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// File Backup Queries\n// ============================================\n\nexport const remoteFileBackupQueries = {\n create(data: {\n checkpointId: string;\n sessionId: string;\n filePath: string;\n originalContent: string | null;\n existed: boolean;\n }): Promise<FileBackup> {\n return api<FileBackup>('/file-backups', { method: 'POST', body: data });\n },\n\n getByCheckpoint(checkpointId: string): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/checkpoint/${checkpointId}`);\n },\n\n getBySession(sessionId: string): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/session/${sessionId}`);\n },\n\n getFromSequence(sessionId: string, messageSequence: number): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/session/${sessionId}/from-sequence/${messageSequence}`);\n },\n\n async hasBackup(checkpointId: string, filePath: string): Promise<boolean> {\n const result = await api<{ hasBackup: boolean }>(\n `/file-backups/checkpoint/${checkpointId}/has-backup/${encodeURIComponent(filePath)}`\n );\n return result.hasBackup;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/file-backups/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Subagent Queries\n// ============================================\n\nexport const remoteSubagentQueries = {\n create(data: {\n sessionId: string;\n toolCallId: string;\n subagentType: string;\n task: string;\n model: string;\n }): Promise<SubagentExecution> {\n return api<SubagentExecution>('/subagents', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`).catch(() => undefined);\n },\n\n getByToolCallId(toolCallId: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/by-tool-call-id/${toolCallId}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<SubagentExecution[]> {\n return api<SubagentExecution[]>(`/subagents/session/${sessionId}`);\n },\n\n addStep(id: string, step: SubagentStep): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}/add-step`, { method: 'POST', body: { step } }).catch(() => undefined);\n },\n\n complete(id: string, result: unknown): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'completed', result } }).catch(() => undefined);\n },\n\n markError(id: string, error: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'error', error } }).catch(() => undefined);\n },\n\n cancel(id: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'cancelled' } }).catch(() => undefined);\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/subagents/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Indexed Chunk Queries\n// ============================================\n\nexport const remoteIndexedChunkQueries = {\n upsert(\n _db: any, // Ignored - for API compatibility\n data: {\n id: string;\n contentHash: string;\n filePath: string;\n repoNamespace: string;\n startLine?: number;\n endLine?: number;\n language?: string;\n }\n ): Promise<IndexedChunk> {\n return api<IndexedChunk>('/indexed-chunks', { method: 'POST', body: data });\n },\n\n batchUpsert(\n _db: any,\n chunks: Array<{\n id: string;\n contentHash: string;\n filePath: string;\n repoNamespace: string;\n startLine?: number;\n endLine?: number;\n language?: string;\n }>\n ): Promise<{ created: number; updated: number }> {\n return api<{ created: number; updated: number }>('/indexed-chunks/batch', { \n method: 'POST', \n body: { chunks } \n });\n },\n\n getById(_db: any, id: string): Promise<IndexedChunk | undefined> {\n return api<IndexedChunk | undefined>(`/indexed-chunks/${id}`).catch(() => undefined);\n },\n\n getByNamespace(_db: any, namespace: string): Promise<IndexedChunk[]> {\n return api<IndexedChunk[]>(`/indexed-chunks/namespace/${namespace}`);\n },\n\n getByFilePath(_db: any, namespace: string, filePath: string): Promise<IndexedChunk[]> {\n return api<IndexedChunk[]>(`/indexed-chunks/namespace/${namespace}/file/${encodeURIComponent(filePath)}`);\n },\n\n async deleteByNamespace(_db: any, namespace: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/indexed-chunks/namespace/${namespace}`, { method: 'DELETE' });\n return result.deleted;\n },\n\n async deleteByFilePath(_db: any, namespace: string, filePath: string): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/indexed-chunks/namespace/${namespace}/file/${encodeURIComponent(filePath)}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n\n async countByNamespace(_db: any, namespace: string): Promise<number> {\n const result = await api<{ count: number }>(`/indexed-chunks/namespace/${namespace}/count`);\n return result.count;\n },\n};\n\n// ============================================\n// Index Status Queries\n// ============================================\n\nexport const remoteIndexStatusQueries = {\n upsert(\n _db: any, // Ignored\n data: {\n id: string;\n repoNamespace: string;\n totalChunks?: number;\n lastFullIndex?: Date;\n lastIncrementalIndex?: Date;\n }\n ): Promise<IndexStatusRecord> {\n return api<IndexStatusRecord>('/index-status', {\n method: 'POST',\n body: {\n ...data,\n lastFullIndex: data.lastFullIndex?.toISOString(),\n lastIncrementalIndex: data.lastIncrementalIndex?.toISOString(),\n },\n });\n },\n\n get(_db: any, namespace: string): Promise<IndexStatusRecord | undefined> {\n return api<IndexStatusRecord | null>(`/index-status/namespace/${namespace}`).then(r => r ?? undefined);\n },\n\n async delete(_db: any, namespace: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/index-status/namespace/${namespace}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n list(_db: any): Promise<IndexStatusRecord[]> {\n return api<IndexStatusRecord[]>('/index-status');\n },\n};\n\n// ============================================\n// Storage (GCS) — calls /storage/* endpoints\n// ============================================\n\nexport interface SessionFile {\n id: string;\n fileName: string;\n contentType: string;\n sizeBytes: number | null;\n category: string;\n createdAt: string;\n downloadUrl: string | null;\n downloadUrlExpiresAt: string | null;\n}\n\nexport interface UploadUrlResponse {\n fileId: string;\n uploadUrl: string;\n gcsPath: string;\n expiresAt: string;\n}\n\nasync function storageApi<T>(\n path: string,\n options: { method?: string; body?: unknown } = {}\n): Promise<T> {\n if (!remoteServerUrl || !authKey) {\n throw new Error('Remote database not initialized');\n }\n\n const url = `${remoteServerUrl}/storage${path}`;\n const init: RequestInit = {\n method: options.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authKey}`,\n },\n };\n\n if (options.body) {\n init.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, init);\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`Storage API error ${response.status}: ${errorText}`);\n }\n return response.json() as Promise<T>;\n}\n\nexport const storageQueries = {\n async getUploadUrl(\n sessionId: string,\n fileName: string,\n contentType: string,\n category?: string\n ): Promise<UploadUrlResponse> {\n return storageApi<UploadUrlResponse>('/upload-url', {\n method: 'POST',\n body: { sessionId, fileName, contentType, category },\n });\n },\n\n async getSessionFiles(sessionId: string): Promise<SessionFile[]> {\n const result = await storageApi<{ files: SessionFile[] }>(`/files/${sessionId}`);\n return result.files;\n },\n\n async getDownloadUrl(fileId: string): Promise<{ downloadUrl: string; expiresAt: string }> {\n return storageApi<{ downloadUrl: string; expiresAt: string }>(`/download/${fileId}`);\n },\n\n async deleteFile(fileId: string): Promise<void> {\n await storageApi(`/files/${fileId}`, { method: 'DELETE' });\n },\n\n async updateFile(fileId: string, data: { sizeBytes?: number }): Promise<void> {\n await storageApi(`/files/${fileId}`, { method: 'PATCH', body: data });\n },\n};\n","/**\n * Database layer - Remote MongoDB only\n * \n * All data is stored on the remote server at agent.sparkecode.com\n */\n\nimport {\n initRemoteDatabase,\n closeRemoteDatabase,\n remoteSessionQueries,\n remoteMessageQueries,\n remoteToolExecutionQueries,\n remoteTodoQueries,\n remoteSkillQueries,\n remoteTerminalQueries,\n remoteActiveStreamQueries,\n remoteCheckpointQueries,\n remoteFileBackupQueries,\n remoteSubagentQueries,\n remoteIndexedChunkQueries,\n remoteIndexStatusQueries,\n} from './remote.js';\n\n// Re-export types from schema\nexport type {\n Session,\n NewSession,\n Message,\n NewMessage,\n ToolExecution,\n NewToolExecution,\n TodoItem,\n NewTodoItem,\n SessionConfig,\n ModelMessage,\n UserModelMessage,\n UserContentPart,\n UserTextPart,\n UserImagePart,\n UserFilePart,\n Terminal,\n NewTerminal,\n ActiveStream,\n NewActiveStream,\n Checkpoint,\n NewCheckpoint,\n FileBackup,\n NewFileBackup,\n SubagentExecution,\n NewSubagentExecution,\n SubagentStep,\n IndexedChunk,\n NewIndexedChunk,\n IndexStatusRecord,\n NewIndexStatusRecord,\n LoadedSkill,\n TaskConfig,\n} from './schema.js';\n\nlet initialized = false;\n\n/**\n * Initialize the database with remote server config\n * @param config - Remote server configuration { url, authKey }\n */\nexport function initDatabase(config: { url: string; authKey: string }) {\n initRemoteDatabase(config.url, config.authKey);\n initialized = true;\n}\n\n/**\n * Get a stub database object for API compatibility\n * Functions that take a db parameter will ignore it for remote operations\n */\nexport function getDb() {\n if (!initialized) {\n throw new Error('Database not initialized. Call initDatabase first.');\n }\n // Return a stub - the actual queries use remote API calls\n return {} as any;\n}\n\n/**\n * Check if using remote database (always true now)\n */\nexport function isUsingRemote(): boolean {\n return true;\n}\n\n/**\n * Close the database connection\n */\nexport function closeDatabase() {\n closeRemoteDatabase();\n initialized = false;\n}\n\n// Re-export query objects with cleaner names\nexport const sessionQueries = remoteSessionQueries;\nexport const messageQueries = remoteMessageQueries;\nexport const toolExecutionQueries = remoteToolExecutionQueries;\nexport const todoQueries = remoteTodoQueries;\nexport const skillQueries = remoteSkillQueries;\nexport const terminalQueries = remoteTerminalQueries;\nexport const activeStreamQueries = remoteActiveStreamQueries;\nexport const checkpointQueries = remoteCheckpointQueries;\nexport const fileBackupQueries = remoteFileBackupQueries;\nexport const subagentQueries = remoteSubagentQueries;\nexport const indexedChunkQueries = remoteIndexedChunkQueries;\nexport const indexStatusQueries = remoteIndexStatusQueries;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/db/remote.ts","../../src/db/index.ts"],"sourcesContent":["/**\n * Remote database client\n * \n * Implements the same interface as the local SQLite database\n * but calls the remote server via HTTP.\n */\n\nimport type {\n Session,\n Message,\n ToolExecution,\n TodoItem,\n ModelMessage,\n Terminal,\n ActiveStream,\n Checkpoint,\n FileBackup,\n SubagentExecution,\n SubagentStep,\n IndexedChunk,\n IndexStatusRecord,\n LoadedSkill,\n} from './schema.js';\n\nlet remoteServerUrl: string | null = null;\nlet authKey: string | null = null;\n\n/**\n * Initialize the remote database client\n */\nexport function initRemoteDatabase(serverUrl: string, key: string) {\n remoteServerUrl = serverUrl.replace(/\\/$/, ''); // Remove trailing slash\n authKey = key;\n}\n\n/**\n * Close the remote client (no-op, just for API compatibility)\n */\nexport function closeRemoteDatabase() {\n remoteServerUrl = null;\n authKey = null;\n}\n\n/**\n * Check if remote database is configured\n */\nexport function isRemoteConfigured(): boolean {\n return !!remoteServerUrl && !!authKey;\n}\n\n/**\n * Date fields that should be parsed from ISO strings to Date objects.\n * These are top-level metadata fields on database records (Session, Message, etc.),\n * NOT fields inside modelMessage content (tool outputs, etc.).\n */\nconst DATE_FIELDS = ['createdAt', 'updatedAt', 'startedAt', 'completedAt', 'stoppedAt', 'finishedAt', 'loadedAt', 'indexedAt', 'lastFullIndex', 'lastIncrementalIndex'];\n\n/**\n * Fields that contain AI SDK ModelMessage data and should NOT be recursively\n * processed by parseDates. The AI SDK's Zod schema requires tool output values\n * to be valid JSON primitives (string, number, boolean, null, object, array).\n * Converting date strings to Date objects inside these fields corrupts them and\n * causes AI_InvalidPromptError when the messages are passed back to streamText().\n */\nconst MODEL_MESSAGE_FIELDS = ['modelMessage', 'modelMessages'];\n\n/**\n * Parse date strings to Date objects on top-level record fields only.\n * \n * IMPORTANT: Does NOT recurse into `modelMessage` / `modelMessages` fields.\n * Those contain AI SDK ModelMessage data that must remain JSON-serializable.\n * Recursing into them converts date strings (e.g. `createdAt` inside tool\n * result outputs) to Date objects, which violates the AI SDK's jsonValueSchema\n * and triggers AI_InvalidPromptError on subsequent streamText() calls.\n */\nfunction parseDates(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n if (Array.isArray(obj)) return obj.map(parseDates);\n if (typeof obj !== 'object' || obj instanceof Date) return obj;\n \n const result = { ...obj };\n for (const key of Object.keys(result)) {\n // Skip modelMessage fields entirely - these must stay JSON-serializable\n if (MODEL_MESSAGE_FIELDS.includes(key)) {\n continue;\n }\n if (DATE_FIELDS.includes(key) && typeof result[key] === 'string') {\n result[key] = new Date(result[key]);\n } else if (typeof result[key] === 'object') {\n result[key] = parseDates(result[key]);\n }\n }\n return result;\n}\n\n/**\n * HTTP helper for remote API calls\n * @param options.skipParseDates - If true, skip the parseDates post-processing.\n * Use for endpoints that return ModelMessage[] directly, since those must\n * remain JSON-serializable for the AI SDK.\n */\nasync function api<T>(\n path: string,\n options: { method?: string; body?: unknown; skipParseDates?: boolean } = {}\n): Promise<T> {\n if (!remoteServerUrl || !authKey) {\n throw new Error('Remote database not initialized');\n }\n \n const url = `${remoteServerUrl}/db${path}`;\n const init: RequestInit = {\n method: options.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authKey}`,\n },\n };\n \n if (options.body) {\n init.body = JSON.stringify(options.body);\n }\n \n const response = await fetch(url, init);\n \n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n \n const text = await response.text();\n if (!text || text === 'null') {\n return null as T;\n }\n \n const parsed = JSON.parse(text);\n\n // Skip date parsing for raw ModelMessage data - it must stay JSON-serializable\n if (options.skipParseDates) {\n return parsed as T;\n }\n\n // Parse JSON and convert date strings to Date objects\n return parseDates(parsed) as T;\n}\n\n// ============================================\n// Session Queries\n// ============================================\n\nexport const remoteSessionQueries = {\n create(data: { workingDirectory: string; model: string; name?: string; config?: any }): Promise<Session> {\n return api<Session>('/sessions', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`).catch(() => undefined);\n },\n\n list(limit = 50, offset = 0): Promise<Session[]> {\n return api<Session[]>(`/sessions?limit=${limit}&offset=${offset}`);\n },\n\n updateStatus(id: string, status: Session['status']): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: { status } });\n },\n\n updateModel(id: string, model: string): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: { model } });\n },\n\n update(id: string, updates: { model?: string; name?: string; config?: any }): Promise<Session | undefined> {\n return api<Session | undefined>(`/sessions/${id}`, { method: 'PATCH', body: updates });\n },\n\n delete(id: string): Promise<boolean> {\n return api<{ success: boolean }>(`/sessions/${id}`, { method: 'DELETE' }).then(r => r?.success ?? false);\n },\n};\n\n// ============================================\n// Message Queries\n// ============================================\n\nexport const remoteMessageQueries = {\n async getNextSequence(sessionId: string): Promise<number> {\n const result = await api<{ nextSequence: number }>(`/messages/session/${sessionId}/next-sequence`);\n return result.nextSequence;\n },\n\n create(sessionId: string, modelMessage: ModelMessage): Promise<Message> {\n return api<Message>('/messages', { method: 'POST', body: { sessionId, modelMessage } });\n },\n\n addMany(sessionId: string, modelMessages: ModelMessage[]): Promise<Message[]> {\n return api<Message[]>('/messages/batch', { method: 'POST', body: { sessionId, modelMessages } });\n },\n\n getBySession(sessionId: string): Promise<Message[]> {\n return api<Message[]>(`/messages/session/${sessionId}`);\n },\n\n getModelMessages(sessionId: string): Promise<ModelMessage[]> {\n // IMPORTANT: skipParseDates=true because ModelMessage data must remain\n // JSON-serializable. The parseDates function would convert date strings\n // inside tool result outputs (e.g. todo items with createdAt) to Date\n // objects, which violates the AI SDK's jsonValueSchema and causes\n // AI_InvalidPromptError on subsequent streamText() calls.\n return api<ModelMessage[]>(`/messages/session/${sessionId}/model-messages`, { skipParseDates: true });\n },\n\n async getRecentBySession(sessionId: string, limit = 50): Promise<Message[]> {\n const messages = await api<Message[]>(`/messages/session/${sessionId}`);\n return messages.slice(-limit);\n },\n\n async countBySession(sessionId: string): Promise<number> {\n const result = await api<{ count: number }>(`/messages/session/${sessionId}/count`);\n return result.count;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/messages/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n\n async deleteFromSequence(sessionId: string, fromSequence: number): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/messages/session/${sessionId}/from-sequence/${fromSequence}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n};\n\n// ============================================\n// Tool Execution Queries\n// ============================================\n\nexport const remoteToolExecutionQueries = {\n create(data: {\n sessionId: string;\n messageId?: string;\n toolName: string;\n toolCallId: string;\n input?: any;\n requiresApproval?: boolean;\n status?: 'pending' | 'approved' | 'rejected' | 'completed' | 'error';\n }): Promise<ToolExecution> {\n return api<ToolExecution>('/tool-executions', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`).catch(() => undefined);\n },\n\n getByToolCallId(toolCallId: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/by-tool-call-id/${toolCallId}`).catch(() => undefined);\n },\n\n getPendingApprovals(sessionId: string): Promise<ToolExecution[]> {\n return api<ToolExecution[]>(`/tool-executions/session/${sessionId}/pending`);\n },\n\n approve(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, { method: 'PATCH', body: { status: 'approved' } });\n },\n\n reject(id: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, { method: 'PATCH', body: { status: 'rejected' } });\n },\n\n complete(id: string, output: unknown, error?: string): Promise<ToolExecution | undefined> {\n return api<ToolExecution | undefined>(`/tool-executions/${id}`, {\n method: 'PATCH',\n body: { status: error ? 'error' : 'completed', output, error },\n });\n },\n\n getBySession(sessionId: string): Promise<ToolExecution[]> {\n return api<ToolExecution[]>(`/tool-executions/session/${sessionId}`);\n },\n\n async deleteAfterTime(sessionId: string, afterTime: Date | string): Promise<number> {\n // Handle both Date objects and ISO strings\n const timestamp = afterTime instanceof Date ? afterTime.getTime() : new Date(afterTime).getTime();\n const result = await api<{ deleted: number }>(\n `/tool-executions/session/${sessionId}/after/${timestamp}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n};\n\n// ============================================\n// Todo Queries\n// ============================================\n\nexport const remoteTodoQueries = {\n create(data: { sessionId: string; content: string; order?: number }): Promise<TodoItem> {\n return api<TodoItem>('/todos', { method: 'POST', body: data });\n },\n\n createMany(sessionId: string, items: Array<{ content: string; order?: number }>): Promise<TodoItem[]> {\n return api<TodoItem[]>('/todos/batch', { method: 'POST', body: { sessionId, items } });\n },\n\n getBySession(sessionId: string): Promise<TodoItem[]> {\n return api<TodoItem[]>(`/todos/session/${sessionId}`);\n },\n\n updateStatus(id: string, status: TodoItem['status']): Promise<TodoItem | undefined> {\n return api<TodoItem | undefined>(`/todos/${id}`, { method: 'PATCH', body: { status } });\n },\n\n async delete(id: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/todos/${id}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n async clearSession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/todos/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Skill Queries\n// ============================================\n\nexport const remoteSkillQueries = {\n load(sessionId: string, skillName: string): Promise<LoadedSkill> {\n return api<LoadedSkill>('/skills', { method: 'POST', body: { sessionId, skillName } });\n },\n\n getBySession(sessionId: string): Promise<LoadedSkill[]> {\n return api<LoadedSkill[]>(`/skills/session/${sessionId}`);\n },\n\n async isLoaded(sessionId: string, skillName: string): Promise<boolean> {\n const result = await api<{ isLoaded: boolean }>(`/skills/session/${sessionId}/is-loaded/${skillName}`);\n return result.isLoaded;\n },\n};\n\n// ============================================\n// Terminal Queries\n// ============================================\n\nexport const remoteTerminalQueries = {\n create(data: { sessionId: string; command: string; cwd: string; name?: string }): Promise<Terminal> {\n return api<Terminal>('/terminals', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<Terminal[]> {\n return api<Terminal[]>(`/terminals/session/${sessionId}`);\n },\n\n getRunning(sessionId: string): Promise<Terminal[]> {\n return api<Terminal[]>(`/terminals/session/${sessionId}/running`);\n },\n\n updateStatus(id: string, status: Terminal['status'], exitCode?: number, error?: string): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`, { method: 'PATCH', body: { status, exitCode, error } });\n },\n\n updatePid(id: string, pid: number): Promise<Terminal | undefined> {\n return api<Terminal | undefined>(`/terminals/${id}`, { method: 'PATCH', body: { pid } });\n },\n\n async delete(id: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/terminals/${id}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/terminals/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Active Stream Queries\n// ============================================\n\nexport const remoteActiveStreamQueries = {\n create(sessionId: string, streamId: string): Promise<ActiveStream> {\n return api<ActiveStream>('/streams', { method: 'POST', body: { sessionId, streamId } });\n },\n\n getBySessionId(sessionId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | null>(`/streams/session/${sessionId}`).then(r => r ?? undefined);\n },\n\n getByStreamId(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`).catch(() => undefined);\n },\n\n finish(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`, { method: 'PATCH', body: { status: 'finished' } });\n },\n\n markError(streamId: string): Promise<ActiveStream | undefined> {\n return api<ActiveStream | undefined>(`/streams/by-stream-id/${streamId}`, { method: 'PATCH', body: { status: 'error' } });\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/streams/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Checkpoint Queries\n// ============================================\n\nexport const remoteCheckpointQueries = {\n create(data: { sessionId: string; messageSequence: number; gitHead?: string }): Promise<Checkpoint> {\n return api<Checkpoint>('/checkpoints', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<Checkpoint | undefined> {\n return api<Checkpoint | undefined>(`/checkpoints/${id}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<Checkpoint[]> {\n return api<Checkpoint[]>(`/checkpoints/session/${sessionId}`);\n },\n\n getByMessageSequence(sessionId: string, messageSequence: number): Promise<Checkpoint | undefined> {\n return api<Checkpoint | null>(`/checkpoints/session/${sessionId}/by-sequence/${messageSequence}`).then(r => r ?? undefined);\n },\n\n getLatest(sessionId: string): Promise<Checkpoint | undefined> {\n return api<Checkpoint | null>(`/checkpoints/session/${sessionId}/latest`).then(r => r ?? undefined);\n },\n\n async deleteAfterSequence(sessionId: string, messageSequence: number): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/checkpoints/session/${sessionId}/after-sequence/${messageSequence}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/checkpoints/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// File Backup Queries\n// ============================================\n\nexport const remoteFileBackupQueries = {\n create(data: {\n checkpointId: string;\n sessionId: string;\n filePath: string;\n originalContent: string | null;\n existed: boolean;\n }): Promise<FileBackup> {\n return api<FileBackup>('/file-backups', { method: 'POST', body: data });\n },\n\n getByCheckpoint(checkpointId: string): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/checkpoint/${checkpointId}`);\n },\n\n getBySession(sessionId: string): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/session/${sessionId}`);\n },\n\n getFromSequence(sessionId: string, messageSequence: number): Promise<FileBackup[]> {\n return api<FileBackup[]>(`/file-backups/session/${sessionId}/from-sequence/${messageSequence}`);\n },\n\n async hasBackup(checkpointId: string, filePath: string): Promise<boolean> {\n const result = await api<{ hasBackup: boolean }>(\n `/file-backups/checkpoint/${checkpointId}/has-backup/${encodeURIComponent(filePath)}`\n );\n return result.hasBackup;\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/file-backups/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Subagent Queries\n// ============================================\n\nexport const remoteSubagentQueries = {\n create(data: {\n sessionId: string;\n toolCallId: string;\n subagentType: string;\n task: string;\n model: string;\n }): Promise<SubagentExecution> {\n return api<SubagentExecution>('/subagents', { method: 'POST', body: data });\n },\n\n getById(id: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`).catch(() => undefined);\n },\n\n getByToolCallId(toolCallId: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/by-tool-call-id/${toolCallId}`).catch(() => undefined);\n },\n\n getBySession(sessionId: string): Promise<SubagentExecution[]> {\n return api<SubagentExecution[]>(`/subagents/session/${sessionId}`);\n },\n\n addStep(id: string, step: SubagentStep): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}/add-step`, { method: 'POST', body: { step } }).catch(() => undefined);\n },\n\n complete(id: string, result: unknown): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'completed', result } }).catch(() => undefined);\n },\n\n markError(id: string, error: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'error', error } }).catch(() => undefined);\n },\n\n cancel(id: string): Promise<SubagentExecution | undefined> {\n return api<SubagentExecution | undefined>(`/subagents/${id}`, { method: 'PATCH', body: { status: 'cancelled' } }).catch(() => undefined);\n },\n\n async deleteBySession(sessionId: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/subagents/session/${sessionId}`, { method: 'DELETE' });\n return result.deleted;\n },\n};\n\n// ============================================\n// Indexed Chunk Queries\n// ============================================\n\nexport const remoteIndexedChunkQueries = {\n upsert(\n _db: any, // Ignored - for API compatibility\n data: {\n id: string;\n contentHash: string;\n filePath: string;\n repoNamespace: string;\n startLine?: number;\n endLine?: number;\n language?: string;\n }\n ): Promise<IndexedChunk> {\n return api<IndexedChunk>('/indexed-chunks', { method: 'POST', body: data });\n },\n\n batchUpsert(\n _db: any,\n chunks: Array<{\n id: string;\n contentHash: string;\n filePath: string;\n repoNamespace: string;\n startLine?: number;\n endLine?: number;\n language?: string;\n }>\n ): Promise<{ created: number; updated: number }> {\n return api<{ created: number; updated: number }>('/indexed-chunks/batch', { \n method: 'POST', \n body: { chunks } \n });\n },\n\n getById(_db: any, id: string): Promise<IndexedChunk | undefined> {\n return api<IndexedChunk | undefined>(`/indexed-chunks/${id}`).catch(() => undefined);\n },\n\n getByNamespace(_db: any, namespace: string): Promise<IndexedChunk[]> {\n return api<IndexedChunk[]>(`/indexed-chunks/namespace/${namespace}`);\n },\n\n getByFilePath(_db: any, namespace: string, filePath: string): Promise<IndexedChunk[]> {\n return api<IndexedChunk[]>(`/indexed-chunks/namespace/${namespace}/file/${encodeURIComponent(filePath)}`);\n },\n\n async deleteByNamespace(_db: any, namespace: string): Promise<number> {\n const result = await api<{ deleted: number }>(`/indexed-chunks/namespace/${namespace}`, { method: 'DELETE' });\n return result.deleted;\n },\n\n async deleteByFilePath(_db: any, namespace: string, filePath: string): Promise<number> {\n const result = await api<{ deleted: number }>(\n `/indexed-chunks/namespace/${namespace}/file/${encodeURIComponent(filePath)}`,\n { method: 'DELETE' }\n );\n return result.deleted;\n },\n\n async countByNamespace(_db: any, namespace: string): Promise<number> {\n const result = await api<{ count: number }>(`/indexed-chunks/namespace/${namespace}/count`);\n return result.count;\n },\n};\n\n// ============================================\n// Index Status Queries\n// ============================================\n\nexport const remoteIndexStatusQueries = {\n upsert(\n _db: any, // Ignored\n data: {\n id: string;\n repoNamespace: string;\n totalChunks?: number;\n lastFullIndex?: Date;\n lastIncrementalIndex?: Date;\n }\n ): Promise<IndexStatusRecord> {\n return api<IndexStatusRecord>('/index-status', {\n method: 'POST',\n body: {\n ...data,\n lastFullIndex: data.lastFullIndex?.toISOString(),\n lastIncrementalIndex: data.lastIncrementalIndex?.toISOString(),\n },\n });\n },\n\n get(_db: any, namespace: string): Promise<IndexStatusRecord | undefined> {\n return api<IndexStatusRecord | null>(`/index-status/namespace/${namespace}`).then(r => r ?? undefined);\n },\n\n async delete(_db: any, namespace: string): Promise<boolean> {\n const result = await api<{ success: boolean }>(`/index-status/namespace/${namespace}`, { method: 'DELETE' });\n return result?.success ?? false;\n },\n\n list(_db: any): Promise<IndexStatusRecord[]> {\n return api<IndexStatusRecord[]>('/index-status');\n },\n};\n\n// ============================================\n// Storage (GCS) — calls /storage/* endpoints\n// ============================================\n\nexport interface SessionFile {\n id: string;\n fileName: string;\n contentType: string;\n sizeBytes: number | null;\n category: string;\n createdAt: string;\n downloadUrl: string | null;\n downloadUrlExpiresAt: string | null;\n}\n\nexport interface UploadUrlResponse {\n fileId: string;\n uploadUrl: string;\n gcsPath: string;\n expiresAt: string;\n}\n\nasync function storageApi<T>(\n path: string,\n options: { method?: string; body?: unknown } = {}\n): Promise<T> {\n if (!remoteServerUrl || !authKey) {\n throw new Error('Remote database not initialized');\n }\n\n const url = `${remoteServerUrl}/storage${path}`;\n const init: RequestInit = {\n method: options.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authKey}`,\n },\n };\n\n if (options.body) {\n init.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, init);\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`Storage API error ${response.status}: ${errorText}`);\n }\n return response.json() as Promise<T>;\n}\n\nexport const storageQueries = {\n async getUploadUrl(\n sessionId: string,\n fileName: string,\n contentType: string,\n category?: string\n ): Promise<UploadUrlResponse> {\n return storageApi<UploadUrlResponse>('/upload-url', {\n method: 'POST',\n body: { sessionId, fileName, contentType, category },\n });\n },\n\n async getSessionFiles(sessionId: string): Promise<SessionFile[]> {\n const result = await storageApi<{ files: SessionFile[] }>(`/files/${sessionId}`);\n return result.files;\n },\n\n async getDownloadUrl(fileId: string): Promise<{ downloadUrl: string; expiresAt: string }> {\n const result = await storageApi<{ downloadUrl: string; shortUrl?: string; expiresAt: string }>(`/download/${fileId}`);\n return {\n downloadUrl: result.shortUrl || result.downloadUrl,\n expiresAt: result.expiresAt,\n };\n },\n\n async deleteFile(fileId: string): Promise<void> {\n await storageApi(`/files/${fileId}`, { method: 'DELETE' });\n },\n\n async updateFile(fileId: string, data: { sizeBytes?: number }): Promise<void> {\n await storageApi(`/files/${fileId}`, { method: 'PATCH', body: data });\n },\n};\n","/**\n * Database layer - Remote MongoDB only\n * \n * All data is stored on the remote server at agent.sparkecode.com\n */\n\nimport {\n initRemoteDatabase,\n closeRemoteDatabase,\n remoteSessionQueries,\n remoteMessageQueries,\n remoteToolExecutionQueries,\n remoteTodoQueries,\n remoteSkillQueries,\n remoteTerminalQueries,\n remoteActiveStreamQueries,\n remoteCheckpointQueries,\n remoteFileBackupQueries,\n remoteSubagentQueries,\n remoteIndexedChunkQueries,\n remoteIndexStatusQueries,\n} from './remote.js';\n\n// Re-export types from schema\nexport type {\n Session,\n NewSession,\n Message,\n NewMessage,\n ToolExecution,\n NewToolExecution,\n TodoItem,\n NewTodoItem,\n SessionConfig,\n ModelMessage,\n UserModelMessage,\n UserContentPart,\n UserTextPart,\n UserImagePart,\n UserFilePart,\n Terminal,\n NewTerminal,\n ActiveStream,\n NewActiveStream,\n Checkpoint,\n NewCheckpoint,\n FileBackup,\n NewFileBackup,\n SubagentExecution,\n NewSubagentExecution,\n SubagentStep,\n IndexedChunk,\n NewIndexedChunk,\n IndexStatusRecord,\n NewIndexStatusRecord,\n LoadedSkill,\n TaskConfig,\n} from './schema.js';\n\nlet initialized = false;\n\n/**\n * Initialize the database with remote server config\n * @param config - Remote server configuration { url, authKey }\n */\nexport function initDatabase(config: { url: string; authKey: string }) {\n initRemoteDatabase(config.url, config.authKey);\n initialized = true;\n}\n\n/**\n * Get a stub database object for API compatibility\n * Functions that take a db parameter will ignore it for remote operations\n */\nexport function getDb() {\n if (!initialized) {\n throw new Error('Database not initialized. Call initDatabase first.');\n }\n // Return a stub - the actual queries use remote API calls\n return {} as any;\n}\n\n/**\n * Check if using remote database (always true now)\n */\nexport function isUsingRemote(): boolean {\n return true;\n}\n\n/**\n * Close the database connection\n */\nexport function closeDatabase() {\n closeRemoteDatabase();\n initialized = false;\n}\n\n// Re-export query objects with cleaner names\nexport const sessionQueries = remoteSessionQueries;\nexport const messageQueries = remoteMessageQueries;\nexport const toolExecutionQueries = remoteToolExecutionQueries;\nexport const todoQueries = remoteTodoQueries;\nexport const skillQueries = remoteSkillQueries;\nexport const terminalQueries = remoteTerminalQueries;\nexport const activeStreamQueries = remoteActiveStreamQueries;\nexport const checkpointQueries = remoteCheckpointQueries;\nexport const fileBackupQueries = remoteFileBackupQueries;\nexport const subagentQueries = remoteSubagentQueries;\nexport const indexedChunkQueries = remoteIndexedChunkQueries;\nexport const indexStatusQueries = remoteIndexStatusQueries;\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -974,7 +974,11 @@ var init_remote = __esm({
|
|
|
974
974
|
return result.files;
|
|
975
975
|
},
|
|
976
976
|
async getDownloadUrl(fileId) {
|
|
977
|
-
|
|
977
|
+
const result = await storageApi(`/download/${fileId}`);
|
|
978
|
+
return {
|
|
979
|
+
downloadUrl: result.shortUrl || result.downloadUrl,
|
|
980
|
+
expiresAt: result.expiresAt
|
|
981
|
+
};
|
|
978
982
|
},
|
|
979
983
|
async deleteFile(fileId) {
|
|
980
984
|
await storageApi(`/files/${fileId}`, { method: "DELETE" });
|
|
@@ -1169,10 +1173,34 @@ Plans should be markdown with this structure:
|
|
|
1169
1173
|
error: `Todo item not found: ${todoId}`
|
|
1170
1174
|
};
|
|
1171
1175
|
}
|
|
1176
|
+
let planContinuation;
|
|
1177
|
+
if (status === "completed") {
|
|
1178
|
+
const allTodos = await todoQueries.getBySession(options.sessionId);
|
|
1179
|
+
const allDone = allTodos.every(
|
|
1180
|
+
(t) => t.status === "completed" || t.status === "cancelled"
|
|
1181
|
+
);
|
|
1182
|
+
if (allDone) {
|
|
1183
|
+
const plansDir = getPlansDir(options.workingDirectory, options.sessionId);
|
|
1184
|
+
if (existsSync9(plansDir)) {
|
|
1185
|
+
const planFiles = readdirSync(plansDir).filter((f) => f.endsWith(".md"));
|
|
1186
|
+
for (const f of planFiles) {
|
|
1187
|
+
try {
|
|
1188
|
+
const content = await readFile6(join4(plansDir, f), "utf-8");
|
|
1189
|
+
if (parseNextUncompletedPhase(content) !== null) {
|
|
1190
|
+
planContinuation = "All todos are done but your plan has remaining phases. Update the plan now: mark the completed phase heading with [completed] and its items with [x], then call save_plan to save \u2014 new todos will be auto-created from the next phase.";
|
|
1191
|
+
break;
|
|
1192
|
+
}
|
|
1193
|
+
} catch {
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1172
1199
|
return {
|
|
1173
1200
|
success: true,
|
|
1174
1201
|
action: "mark",
|
|
1175
|
-
item: formatTodoItem(updated)
|
|
1202
|
+
item: formatTodoItem(updated),
|
|
1203
|
+
...planContinuation ? { planContinuation } : {}
|
|
1176
1204
|
};
|
|
1177
1205
|
}
|
|
1178
1206
|
case "clear": {
|