Dashboard › opencode › Session 1bNLKbwmUcRm
1bNLKbwmUcRmlEOkURead-only independent security review frozen v14. Base ab9408c81cc9916177641ae8e9f08624fc27b5b9. Patch /tmp/opencode/session-recovery-final-v14.patch SHA-256 5efd9d74f450e9f875790a07c860248cb526f7144a822cf6df51761237f9789b. SEA /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server SHA-256 3c26981f57d37d15549b76657c20a090355911e80ea94d43f957422dc3276796. Verify immutable inputs/clean apply/33 paths; inspect all. No mutation/tests/builds/services. Focus stale-owner threats: promoteExact RecoveryConflict quarantine immediate transaction invokes exact live claim guard before update; ownership transfer between conflict and quarantine must prevent write. Startup quarantine live-owner transfer and expiry separately covered. Reassess assistant supersession boundary, identity/cross-Session, replay/retry reservation, cancellation/finalizers, provider/tools, fairness/DoS and retry reset, schema/auth/dependencies. Fresh Prompted reset only on updated row; duplicate replay must not erase newer debt. Accepted residuals final check-to-call, process-local interrupt, wall-clock skew. Evidence 245 recovery pass, Core 1180 pass plus two unrelated isolated failing tests (Location 5s timeout, WebFetch fixture mismatch), typechecks/manifest/migration/smoke pass. Exact line PASS/CONCERN/MUST-FIX, end MERGE or DO-NOT-MERGE. Empty invalid; no recall.
No files found
5efd9d74f450e9f875790a07c860248cb526f7144a822cf6df51761237f9789b /tmp/opencode/session-recovery-final-v14.patch 3c26981f57d37d15549b76657c20a090355911e80ea94d43f957422dc3276796 /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server
M .lore.md M AGENTS.md M packages/core/schema.json M packages/core/src/database/migration.gen.ts M packages/core/src/database/migration/20260914170650_session-recovery.ts D packages/core/src/database/migration/20260914214636_session-execution.ts D packages/core/src/database/migration/20260914222526_session-execution-phase.ts M packages/core/src/database/schema.gen.ts M packages/core/src/session.ts M packages/core/src/session/compaction.ts M packages/core/src/session/context-epoch.ts M packages/core/src/session/execution/local.ts M packages/core/src/session/input.ts M packages/core/src/session/message-updater.ts M packages/core/src/session/projector.ts M packages/core/src/session/recovery.ts M packages/core/src/session/run-coordinator.ts M packages/core/src/session/runner/index.ts M packages/core/src/session/runner/llm.ts M packages/core/src/session/runner/publish-llm-event.ts M packages/core/src/session/sql.ts M packages/core/test/database-migration.test.ts M ...
dc661f30cb2055ad6248fdc59b14998d834497be ab9408c81cc9916177641ae8e9f08624fc27b5b9 feat(core): recover interrupted sessions ab9408c81cc9916177641ae8e9f08624fc27b5b9 M .lore.md M packages/core/schema.json M packages/core/src/database/migration.gen.ts A packages/core/src/database/migration/20260914170650_session-recovery.ts A packages/core/src/database/migration/20260914214636_session-execution.ts A packages/core/src/database/migration/20260914222526_session-execution-phase.ts M packages/core/src/database/schema.gen.ts M packages/core/src/session/compaction.ts M packages/core/src/session/execution/local.ts M packages/core/src/session/message-updater.ts M packages/core/src/session/projector.ts A packages/core/src/session/recovery.ts M packages/core/src/session/runner/llm.ts M packages/core/src/session/runner/publish-llm-event.ts M packages/core/src/session/sql.ts A packages/core/test/session-execution-local.test.ts M packages/core/test/session-projector.test.ts M packages/core/test/session...
<path>/tmp/opencode/session-recovery-final-v14.patch</path>
<type>file</type>
<content>
1: diff --git a/packages/core/schema.json b/packages/core/schema.json
2: index d0eeeebd5c..dedf0cc600 100644
3: --- a/packages/core/schema.json
4: +++ b/packages/core/schema.json
5: @@ -1,8 +1,10 @@
6: {
7: "version": "7",
8: "dialect": "sqlite",
9: - "id": "f14a9b18-8207-487e-a3d3-227e629ba9ad",
10: - "prevIds": ["169a0f0f-d58f-479f-b024-fa1c7b9a09db"],
11: + "id": "3a5ec6d4-a60d-47da-a347-3c72396a13c1",
12: + "prevIds": [
13: + "f14a9b18-8207-487e-a3d3-227e629ba9ad"
14: + ],
15: "ddl": [
16: {
17: "name": "workspace",
18: @@ -60,6 +62,10 @@
19: "name": "session_context_epoch",
20: "entityType": "tables"
21: },
22: + {
23: + "name": "session_execution",
24: + "entityType": "tables"
25: + },
26: {
27: "name": "session_input",
28: "entityType": "tables"
29: @@ -68,6 +74,10 @@
30: "name": "session_message",
31: ...
21667cca5b8a8397ac761805538a90efca5727a91a792b28aa07194228ab9a7c -
paths=33 all_blob_ids_match=True packages/core/schema.json old=d0eeeebd5c base=d0eeeebd5c new=dedf0cc600 target=dedf0cc600 match=True packages/core/src/database/migration.gen.ts old=e6ea4eaa14 base=e6ea4eaa14 new=77948f1529 target=77948f1529 match=True packages/core/src/database/migration/20260914170650_session-recovery.ts old=0000000000 base=0000000000 new=b8f5093419 target=b8f5093419 match=True packages/core/src/database/schema.gen.ts old=ed60fde6c5 base=ed60fde6c5 new=07b6a91676 target=07b6a91676 match=True packages/core/src/session.ts old=2dabfb2d6f base=2dabfb2d6f new=fc5868837a target=fc5868837a match=True packages/core/src/session/compaction.ts old=f714633295 base=f714633295 new=92a934c44f target=92a934c44f match=True packages/core/src/session/context-epoch.ts old=65b17a86a4 base=65b17a86a4 new=880d42bcf9 target=880d42bcf9 match=True packages/core/src/session/execution/local.ts old=d874c40832 base=d874c40832 new=8c8f3532a1 target=8c8f3532a1 ...
<path>/home/byk/Code/opencode/packages/core/src/session/recovery.ts</path>
<type>file</type>
<content>
1: export * as SessionRecovery from "./recovery"
2:
3: import { and, asc, desc, eq, exists, gt, isNull, lte, or, sql } from "drizzle-orm"
4: import { Clock, DateTime, Effect, Layer, Option, Schedule, Schema } from "effect"
5: import { Database } from "../database/database"
6: import { makeGlobalNode } from "../effect/app-node"
7: import { EventV2 } from "../event"
8: import { SessionEvent } from "./event"
9: import { SessionExecution } from "./execution"
10: import { SessionProjector } from "./projector"
11: import { SessionExecutionClaim } from "./execution/claim"
12: import { SessionInput } from "./input"
13: import { continuation } from "./recovery-id"
14: import { SessionSchema } from "./schema"
15: import {
16: MAX_WAKE_ATTEMPTS,
17: SESSION_EXECUTION_LEASE_MS,
18: SessionExecutionTable,
19: SessionInputTable,
20: SessionRecoveryTable,
21: SessionMessageTable,
22: ...
<path>/home/byk/Code/opencode/packages/core/src/session/input.ts</path>
<type>file</type>
<content>
1: export * as SessionInput from "./input"
2:
3: import { and, asc, desc, eq, isNull, lte } from "drizzle-orm"
4: import { DateTime, Effect, Option, Schema } from "effect"
5: import { Admitted, Delivery } from "@opencode-ai/schema/session-input"
6: import type { Database } from "../database/database"
7: import { EventV2 } from "../event"
8: import { SessionEvent } from "./event"
9: import { SessionMessage } from "./message"
10: import { Prompt } from "./prompt"
11: import { continuation, message } from "./recovery-id"
12: import { SessionSchema } from "./schema"
13: import { SessionInputTable, SessionMessageTable, SessionRecoveryTable, SessionTable } from "./sql"
14:
15: type DatabaseService = Database.Interface["db"]
16:
17: export { Admitted, Delivery }
18:
19: const decodePrompt = Schema.decodeUnknownSync(Prompt)
20: const encodePrompt = Schema.encodeSync(Prompt)
21: const ...
<path>/home/byk/Code/opencode/packages/core/src/session/execution/claim.ts</path>
<type>file</type>
<content>
1: export * as SessionExecutionClaim from "./claim"
2:
3: import { and, eq, gt } from "drizzle-orm"
4: import { Clock, Effect } from "effect"
5: import type { Database } from "../../database/database"
6: import type { SessionSchema } from "../schema"
7: import { SESSION_EXECUTION_LEASE_MS, SessionExecutionTable } from "../sql"
8:
9: type DatabaseService = Database.Interface["db"]
10:
11: export type Claim = {
12: readonly sessionID: SessionSchema.ID
13: readonly executionID: string
14: readonly ownerID: string
15: }
16:
17: export type Values = Partial<
18: Pick<typeof SessionExecutionTable.$inferInsert, "assistant_message_id" | "assistant_seq" | "phase">
19: >
20:
21: export class Lost extends Error {
22: constructor(readonly claim: Claim) {
23: super(`Session execution claim lost: ${claim.executionID}`)
24: }
25: }
26:
27: const where = (claim: Claim, ...
<path>/home/byk/Code/opencode/packages/core/src/session/runner/index.ts</path>
<type>file</type>
<content>
1: export * as SessionRunner from "./index"
2:
3: import type { LLMError } from "@opencode-ai/llm"
4: import { Context, Effect } from "effect"
5: import { SessionSchema } from "../schema"
6: import type { SessionMessage } from "../message"
7: import type { ContextSnapshotDecodeError, MessageDecodeError } from "../error"
8: import { SessionRunnerModel } from "./model"
9: import type { SystemContext } from "../../system-context/index"
10: import type { ToolOutputStore } from "../../tool-output-store"
11:
12: export type RunError =
13: | LLMError
14: | SessionRunnerModel.Error
15: | MessageDecodeError
16: | ContextSnapshotDecodeError
17: | SystemContext.InitializationBlocked
18: | ToolOutputStore.Error
19:
20: /** Runs one local continuation from already-recorded Session history. */
21: export interface Interface {
22: /** Drains eligible durable work. ...
<path>/home/byk/Code/opencode/packages/core/src/session/execution/local.ts</path>
<type>file</type>
<content>
1: import { and, asc, desc, eq, isNull } from "drizzle-orm"
2: import { Cause, Clock, Duration, Effect, Exit, Layer, Schedule } from "effect"
3: import { Database } from "../../database/database"
4: import { LocationServiceMap } from "../../location-service-map"
5: import { makeGlobalNode } from "../../effect/app-node"
6: import { SessionRunCoordinator } from "../run-coordinator"
7: import { SessionRunner } from "../runner"
8: import { SessionMessage } from "../message"
9: import { SessionSchema } from "../schema"
10: import { SessionStore } from "../store"
11: import { SessionExecution } from "../execution"
12: import { SessionExecutionClaim } from "./claim"
13: import {
14: SESSION_EXECUTION_LEASE_MS,
15: SessionExecutionTable,
16: SessionMessageTable,
17: SessionRecoveryTable,
18: } from "../sql"
19:
20: /** Current-process routing for implicit-local Locations. ...
<path>/home/byk/Code/opencode/packages/core/src/session/runner/llm.ts</path>
<type>file</type>
<content>
1: import {
2: LLM,
3: LLMClient,
4: LLMError,
5: LLMEvent,
6: Message,
7: SystemPart,
8: isContextOverflowFailure,
9: type ProviderErrorEvent,
10: } from "@opencode-ai/llm"
11: import { Cause, DateTime, Effect, Exit, Fiber, Layer, Option, Semaphore, Stream } from "effect"
12: import { and, eq } from "drizzle-orm"
13: import { AgentV2 } from "../../agent"
14: import { Config } from "../../config"
15: import { Database } from "../../database/database"
16: import { EventV2 } from "../../event"
17: import { Location } from "../../location"
18: import { ModelV2 } from "../../model"
19: import { PermissionV2 } from "../../permission"
20: import { ProviderV2 } from "../../provider"
21: import { QuestionV2 } from "../../question"
22: import { SystemContext } from "../../system-context/index"
23: import { SystemContextRegistry } from "../../system-context/registry"
24: ...
<path>/home/byk/Code/opencode/packages/core/src/session/run-coordinator.ts</path>
<type>file</type>
<content>
1: export * as SessionRunCoordinator from "./run-coordinator"
2:
3: import { Deferred, Effect, Exit, Fiber, FiberSet, Scope } from "effect"
4:
5: /** Serializes execution for each key while allowing different keys to run concurrently. */
6: export interface Coordinator<Key, E> {
7: /** Snapshots keys with an execution owned by this coordinator. */
8: readonly active: Effect.Effect<ReadonlySet<Key>>
9: /** Starts execution while idle or joins the active execution. */
10: readonly run: (key: Key) => Effect.Effect<void, E>
11: /** Registers one coalesced follow-up after newly recorded work. */
12: readonly wake: (key: Key) => Effect.Effect<void>
13: /** Stops active execution, runs cleanup, then starts work that arrived while stopping. */
14: readonly interrupt: (key: Key, cleanup?: Effect.Effect<void>) => Effect.Effect<void>
15: }
16:
17: type Entry<E> = {
18: ...
<path>/home/byk/Code/opencode/packages/core/src/session/projector.ts</path>
<type>file</type>
<content>
1: export * as SessionProjector from "./projector"
2:
3: import { and, desc, eq, gt, or, sql } from "drizzle-orm"
4: import { DateTime, Effect, Layer, Schema } from "effect"
5: import { Database } from "../database/database"
6: import { EventV2 } from "../event"
7: import { makeGlobalNode } from "../effect/app-node"
8: import { SessionEvent } from "./event"
9: import { SessionV1 } from "../v1/session"
10: import { WorkspaceTable } from "../control-plane/workspace.sql"
11: import { SessionMessage } from "./message"
12: import { SessionMessageUpdater } from "./message-updater"
13: import { SessionInput } from "./input"
14: import { Prompt } from "./prompt"
15: import { continuation } from "./recovery-id"
16: import { WorkspaceV2 } from "../workspace"
17: import {
18: MessageTable,
19: PartTable,
20: SessionInputTable,
21: SessionMessageTable,
22: SessionRecoveryTable,
23: ...
No files found
/home/byk/Code/opencode/packages/core/src/event.ts
Found 23 matches
/home/byk/Code/opencode/packages/core/src/event.ts:
Line 122: /** Local operational projection committed atomically with a new durable event. Not replayed or serialized. */
Line 123: readonly commit?: (seq: number) => Effect.Effect<void>
Line 205: function commitDurableEvent(
Line 214: commit?: (seq: number) => Effect.Effect<void>,
Line 239: const committed = yield* db
Line 316: const committed = {
Line 321: yield* projector(committed)
Line 323: if (commit) yield* commit(seq)
Line 354: if (committed) {
Line 356: pubsub.durable.get(committed.aggregateID) ?? [],
Line 361: return committed
Line 369: function publishEvent<D extends Definition>(definition: D, event: Payload<D>, commit?: PublishOptions["commit"]) {
Line 371: if (!definition?.durable ...
<path>/home/byk/Code/opencode/packages/core/src/event.ts</path>
<type>file</type>
<content>
195: yield* PubSub.shutdown(pubsub.all)
196: yield* Effect.forEach(
197: pubsub.durable.values(),
198: (pubsubs) => Effect.forEach(pubsubs, PubSub.shutdown, { discard: true }),
199: { discard: true },
200: )
201: yield* Effect.forEach(pubsub.typed.values(), PubSub.shutdown, { discard: true })
202: }),
203: )
204:
205: function commitDurableEvent(
206: definition: Definition,
207: event: Payload,
208: input?: {
209: readonly seq: number
210: readonly aggregateID: string
211: readonly ownerID?: string
212: readonly strictOwner?: boolean
213: },
214: commit?: (seq: number) => Effect.Effect<void>,
215: ) {
216: return Effect.gen(function* () {
217: const durable = definition?.durable
218: if ...
<path>/home/byk/Code/opencode/packages/core/src/session/context-epoch.ts</path>
<type>file</type>
<content>
1: export * as SessionContextEpoch from "./context-epoch"
2:
3: import { eq } from "drizzle-orm"
4: import { DateTime, Effect, Schema } from "effect"
5: import type { Database } from "../database/database"
6: import { EventV2 } from "../event"
7: import { SystemContext } from "../system-context/index"
8: import { ContextSnapshotDecodeError } from "./error"
9: import { SessionEvent } from "./event"
10: import { SessionHistory } from "./history"
11: import { SessionInput } from "./input"
12: import { SessionMessage } from "./message"
13: import { SessionSchema } from "./schema"
14: import { SessionContextEpochTable } from "./sql"
15: import { SessionExecutionClaim } from "./execution/claim"
16:
17: type DatabaseService = Database.Interface["db"]
18:
19: interface Prepared {
20: readonly baseline: string
21: readonly baselineSeq: number
22: }
23:
24: export function ...
<path>/home/byk/Code/opencode/packages/core/src/session/compaction.ts</path>
<type>file</type>
<content>
1: export * as SessionCompaction from "./compaction"
2:
3: import { LLM, LLMError, LLMEvent, Message, type LLMRequest, type Model } from "@opencode-ai/llm"
4: import { DateTime, Effect, Stream } from "effect"
5: import type { Config } from "../config"
6: import type { EventV2 } from "../event"
7: import { SessionEvent } from "./event"
8: import { SessionMessage } from "./message"
9: import { SessionSchema } from "./schema"
10: import { Token } from "../util/token"
11:
12: const DEFAULT_BUFFER = 20_000
13: const DEFAULT_KEEP_TOKENS = 8_000
14: const TOOL_OUTPUT_MAX_CHARS = 2_000
15: const SUMMARY_OUTPUT_TOKENS = 4_096
16: const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside <template> and keep the section order unchanged. Do not include the <template> tags in your response. ...
<path>/home/byk/Code/opencode/packages/core/src/session/runner/publish-llm-event.ts</path>
<type>file</type>
<content>
1: import { ToolOutput, type LLMEvent, type ProviderMetadata, type ToolResultValue, type Usage } from "@opencode-ai/llm"
2: import { DateTime, Effect } from "effect"
3: import { EventV2 } from "../../event"
4: import { ModelV2 } from "../../model"
5: import { SessionEvent } from "../event"
6: import { SessionMessage } from "../message"
7: import { SessionSchema } from "../schema"
8:
9: type Input = {
10: readonly sessionID: SessionSchema.ID
11: readonly agent: string
12: readonly model: ModelV2.Ref
13: readonly snapshot?: string
14: readonly startCommit: (assistantMessageID: SessionMessage.ID, seq: number) => Effect.Effect<void>
15: readonly eventCommit: () => Effect.Effect<void>
16: }
17:
18: const safe = (value: number | undefined) => Math.max(0, Number.isFinite(value) ? (value ?? ...
<path>/home/byk/Code/opencode/packages/core/src/session/message-updater.ts</path>
<type>file</type>
<content>
1: import { castDraft, produce, type WritableDraft } from "immer"
2: import { Effect } from "effect"
3: import { SessionEvent } from "./event"
4: import { SessionMessage } from "./message"
5: import { message } from "./recovery-id"
6:
7: export type MemoryState = {
8: messages: SessionMessage.Message[]
9: }
10:
11: export interface Adapter {
12: readonly getCurrentAssistant: () => Effect.Effect<SessionMessage.Assistant | undefined>
13: readonly getAssistant: (messageID: SessionMessage.ID) => Effect.Effect<SessionMessage.Assistant | undefined>
14: readonly getCurrentShell: (callID: string) => Effect.Effect<SessionMessage.Shell | undefined>
15: readonly updateAssistant: (assistant: SessionMessage.Assistant) => Effect.Effect<void>
16: readonly updateShell: (shell: SessionMessage.Shell) => Effect.Effect<void>
17: readonly appendMessage: (message: ...
<path>/home/byk/Code/opencode/packages/core/src/session/sql.ts</path>
<type>file</type>
<content>
1: import { sql } from "drizzle-orm"
2: import { check, sqliteTable, text, integer, index, primaryKey, real, uniqueIndex } from "drizzle-orm/sqlite-core"
3: import * as DatabasePath from "../database/path"
4: import { ProjectTable } from "../project/sql"
5: import type { SessionMessage } from "./message"
6: import type { Prompt } from "./prompt"
7: import type { SessionInput } from "./input"
8: import type { Snapshot } from "../snapshot"
9: import { PermissionV1 } from "../v1/permission"
10: import { ProjectV2 } from "../project"
11: import type { SessionSchema } from "./schema"
12: import type { MessageID, PartID, SessionV1 } from "../v1/session"
13: import { WorkspaceV2 } from "../workspace"
14: import { Timestamps } from "../database/schema.sql"
15: import type { SystemContext } from "../system-context/index"
16: import { AgentV2 } from "../agent"
17: import type { Revert } from ...
<path>/home/byk/Code/opencode/packages/core/src/database/migration/20260914170650_session-recovery.ts</path>
<type>file</type>
<content>
1: import { Effect } from "effect"
2: import type { DatabaseMigration } from "../migration"
3:
4: export default {
5: id: "20260914170650_session-recovery",
6: up(tx) {
7: return Effect.gen(function* () {
8: yield* tx.run(`ALTER TABLE \`session_input\` ADD \`wake_pending\` integer DEFAULT false NOT NULL;`)
9: yield* tx.run(
10: `ALTER TABLE \`session\` ADD \`wake_attempts\` integer DEFAULT 0 NOT NULL CONSTRAINT \`session_wake_attempts_check\` CHECK(\`wake_attempts\` >= 0 AND \`wake_attempts\` <= 9007199254740991);`,
11: )
12: yield* tx.run(`
13: CREATE TABLE \`session_execution\` (
14: \`id\` text NOT NULL,
15: \`session_id\` text NOT NULL,
16: \`owner_id\` text NOT NULL,
17: \`assistant_message_id\` text,
18: \`phase\` text NOT NULL,
19: ...
Found 20 matches
/home/byk/Code/opencode/packages/core/src/database/schema.gen.ts:
Line 158: CREATE TABLE \`session_execution\` (
Line 168: CONSTRAINT \`session_execution_pk\` PRIMARY KEY(\`id\`),
Line 169: CONSTRAINT \`fk_session_execution_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE,
Line 170: CONSTRAINT "session_execution_phase_check" CHECK("phase" IN ('ready', 'safe', 'unknown', 'continue', 'cancelling'))
Line 181: \`wake_pending\` integer DEFAULT false NOT NULL,
Line 199: CREATE TABLE \`session_recovery\` (
Line 205: \`wake_pending\` integer DEFAULT true NOT NULL,
Line 206: \`wake_attempts\` integer DEFAULT 0 NOT NULL,
Line 209: CONSTRAINT \`session_recovery_pk\` PRIMARY KEY(\`execution_id\`),
Line 210: CONSTRAINT \`fk_session_recovery_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) ...
<path>/home/byk/Code/opencode/packages/core/src/database/schema.gen.ts</path> <type>file</type> <content> 140: \`message_id\` text NOT NULL, 141: \`session_id\` text NOT NULL, 142: \`time_created\` integer NOT NULL, 143: \`time_updated\` integer NOT NULL, 144: \`data\` text NOT NULL, 145: CONSTRAINT \`fk_part_message_id_message_id_fk\` FOREIGN KEY (\`message_id\`) REFERENCES \`message\`(\`id\`) ON DELETE CASCADE 146: ); 147: `) 148: yield* tx.run(` 149: CREATE TABLE \`session_context_epoch\` ( 150: \`session_id\` text PRIMARY KEY, 151: \`baseline\` text NOT NULL, 152: \`snapshot\` text NOT NULL, 153: \`baseline_seq\` integer NOT NULL, 154: CONSTRAINT \`fk_session_context_epoch_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE 155: ); 156: `) 157: yield* tx.run(` 158: ...
<path>/home/byk/Code/opencode/packages/opencode/src/server/routes/instance/httpapi/server.ts</path>
<type>file</type>
<content>
1: import { Config as EffectConfig, Context, Effect, Layer } from "effect"
2: import { HttpApiBuilder, OpenApi } from "effect/unstable/httpapi"
3: import { HttpClient, HttpMiddleware, HttpRouter, HttpServer, HttpServerResponse } from "effect/unstable/http"
4: import * as Socket from "effect/unstable/socket/Socket"
5: import { FSUtil } from "@opencode-ai/core/fs-util"
6: import * as Observability from "@opencode-ai/core/observability"
7: import { Account } from "@/account/account"
8: import { Agent } from "@/agent/agent"
9: import { Auth } from "@/auth"
10: import { BackgroundJob } from "@/background/job"
11: import { Command } from "@/command"
12: import { Config } from "@/config/config"
13: import { Workspace } from "@/control-plane/workspace"
14: import { Env } from "@/env"
15: import { EventV2Bridge } from "@/event-v2-bridge"
16: import { Format } from ...
<path>/home/byk/Code/opencode/packages/server/src/routes.ts</path>
<type>file</type>
<content>
1: import { Database } from "@opencode-ai/core/database/database"
2: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
3: import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
4: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
5: import { EventV2 } from "@opencode-ai/core/event"
6: import { Credential } from "@opencode-ai/core/credential"
7: import { PermissionSaved } from "@opencode-ai/core/permission/saved"
8: import { PtyTicket } from "@opencode-ai/core/pty/ticket"
9: import { SessionV2 } from "@opencode-ai/core/session"
10: import { SessionExecution } from "@opencode-ai/core/session/execution"
11: import { LocationServiceMap } from "@opencode-ai/core/location-service-map"
12: import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
13: import { SessionRecovery } from ...
<path>/home/byk/Code/opencode/packages/core/src/session.ts</path>
<type>file</type>
<content>
1: export * as SessionV2 from "./session"
2: export * from "./session/schema"
3:
4: import { DateTime, Effect, Layer, Schema, Context, Stream } from "effect"
5: import { ListAnchor } from "@opencode-ai/schema/session"
6: import { and, asc, desc, eq, gt, like, lt, or, type SQL } from "drizzle-orm"
7: import { ProjectV2 } from "./project"
8: import { WorkspaceV2 } from "./workspace"
9: import { ModelV2 } from "./model"
10: import { Location } from "./location"
11: import { SessionMessage } from "./session/message"
12: import { Prompt } from "./session/prompt"
13: import { PromptInput } from "@opencode-ai/schema/prompt-input"
14: import { EventV2 } from "./event"
15: import { Database } from "./database/database"
16: import { SessionProjector } from "./session/projector"
17: import { SessionMessageTable, SessionTable } from "./session/sql"
18: import { SessionSchema } from ...
<path>/home/byk/Code/opencode/packages/core/src/session.ts</path>
<type>file</type>
<content>
350: .pipe(Effect.as(events.durable({ aggregateID: input.sessionID, after: input.after }))),
351: ).pipe(Stream.filter((event): event is SessionEvent.DurableEvent => isDurableSessionEvent(event))),
352: history: Effect.fn("V2Session.history")(function* (input) {
353: yield* result.get(input.sessionID)
354: return yield* EventV2.readAggregate(db, {
355: ...input,
356: aggregateID: input.sessionID,
357: manifest: SessionDurable,
358: })
359: }),
360: prompt: Effect.fn("V2Session.prompt")((input) =>
361: Effect.uninterruptible(
362: Effect.gen(function* () {
363: yield* result.get(input.sessionID)
364: const prompt = resolvePrompt(input.prompt)
365: const messageID = input.id ?? SessionMessage.ID.create()
366: const delivery = ...
Found 13 matches
/home/byk/Code/opencode/packages/schema/src/session-event.ts:
Line 94: export const PromptAdmitted = Event.define({
Line 102: export type PromptAdmitted = typeof PromptAdmitted.Type
Line 104: export const PromptExecutionRequested = Event.define({
Line 112: export type PromptExecutionRequested = typeof PromptExecutionRequested.Type
Line 220: export const Recovered = Event.define({
Line 221: type: "session.next.step.recovered",
Line 230: export type Recovered = typeof Recovered.Type
Line 489: PromptAdmitted,
Line 490: PromptExecutionRequested,
Line 499: Step.Recovered,
Line 523: PromptAdmitted,
Line 524: PromptExecutionRequested,
Line 533: Step.Recovered,
<path>/home/byk/Code/opencode/packages/schema/src/session-event.ts</path>
<type>file</type>
<content>
70: messageID: SessionMessage.ID,
71: model: Model.Ref,
72: },
73: })
74: export type ModelSwitched = typeof ModelSwitched.Type
75:
76: export const Moved = Event.define({
77: type: "session.next.moved",
78: ...options,
79: schema: {
80: ...Base,
81: location: Location.Ref,
82: subdirectory: RelativePath.pipe(optional),
83: },
84: })
85: export type Moved = typeof Moved.Type
86:
87: export const Prompted = Event.define({
88: type: "session.next.prompted",
89: ...options,
90: schema: PromptFields,
91: })
92: export type Prompted = typeof Prompted.Type
93:
94: export const PromptAdmitted = Event.define({
95: type: "session.next.prompt.admitted",
96: ...options,
97: schema: {
98: ...PromptFields,
99: requestExecution: Schema.Boolean.pipe(optional),
100: },
101: })
102: export type PromptAdmitted = typeof PromptAdmitted.Type
103: ...
<path>/home/byk/Code/opencode/packages/schema/src/session-event.ts</path>
<type>file</type>
<content>
1: export * as SessionEvent from "./session-event"
2:
3: import { Schema } from "effect"
4: import { optional } from "./schema"
5: import { Event } from "./event"
6: import { ProviderMetadata, ToolContent } from "./llm"
7: import { Delivery } from "./session-delivery"
8: import { Model } from "./model"
9: import { DateTimeUtcFromMillis, NonNegativeInt, RelativePath } from "./schema"
10: import { FileAttachment, Prompt } from "./prompt"
11: import { SessionID } from "./session-id"
12: import { Location } from "./location"
13: import { SessionMessage } from "./session-message"
14: import { Revert } from "./revert"
15:
16: export { FileAttachment }
17:
18: export const Source = Schema.Struct({
19: start: NonNegativeInt,
20: end: NonNegativeInt,
21: text: Schema.String,
22: }).annotate({
23: identifier: "session.next.event.source",
24: })
25: export interface Source extends ...
<path>/home/byk/Code/opencode/packages/schema/src/session-event.ts</path>
<type>file</type>
<content>
470: export namespace RevertEvent {
471: export const Staged = Event.define({
472: type: "session.next.revert.staged",
473: ...options,
474: schema: { ...Base, revert: Revert.State },
475: })
476: export const Cleared = Event.define({ type: "session.next.revert.cleared", ...options, schema: Base })
477: export const Committed = Event.define({
478: type: "session.next.revert.committed",
479: ...options,
480: schema: { ...Base, messageID: SessionMessage.ID },
481: })
482: }
483:
484: export const DurableDefinitions = Event.inventory(
485: AgentSwitched,
486: ModelSwitched,
487: Moved,
488: Prompted,
489: PromptAdmitted,
490: PromptExecutionRequested,
491: ContextUpdated,
492: Synthetic,
493: Shell.Started,
494: Shell.Ended,
495: Step.Started,
496: Step.Ended,
497: Step.Failed,
498: Step.Interrupted,
499: ...
Found 20 matches /home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts: Line 867: type: "session.next.prompt.admitted" Line 874: requestExecution?: boolean Line 879: type: "session.next.prompt.execution_requested" Line 983: type: "session.next.step.recovered" Line 987: executionID: string Line 3420: type: "session.next.prompt.admitted.1" Line 3430: requestExecution?: boolean Line 3439: type: "session.next.prompt.execution_requested.1" Line 3606: type: "session.next.step.recovered.1" Line 3613: executionID: string Line 4349: type: "session.next.prompt.admitted" Line 4362: requestExecution?: boolean Line 4371: type: "session.next.prompt.execution_requested" Line 4565: type: "session.next.step.recovered" Line 4575: executionID: string Line 6457: type: "session.next.prompt.admitted" Line 6464: requestExecution?: boolean Line 6470: type: ...
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
840: messageID: string
841: model: ModelRef
842: }
843: }
844: | {
845: id: string
846: type: "session.next.moved"
847: properties: {
848: timestamp: number
849: sessionID: string
850: location: LocationRef
851: subdirectory?: string
852: }
853: }
854: | {
855: id: string
856: type: "session.next.prompted"
857: properties: {
858: timestamp: number
859: sessionID: string
860: messageID: string
861: prompt: Prompt
862: delivery: "steer" | "queue"
863: }
864: }
865: | {
866: id: string
867: type: "session.next.prompt.admitted"
868: properties: {
869: timestamp: number
870: sessionID: string
871: messageID: string
872: ...
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
3400: id: string
3401: syncEvent: {
3402: type: "session.next.prompted.1"
3403: id: string
3404: seq: number
3405: aggregateID: string
3406: data: {
3407: timestamp: number
3408: sessionID: string
3409: messageID: string
3410: prompt: Prompt
3411: delivery: "steer" | "queue"
3412: }
3413: }
3414: }
3415:
3416: export type SyncEventSessionNextPromptAdmitted = {
3417: type: "sync"
3418: id: string
3419: syncEvent: {
3420: type: "session.next.prompt.admitted.1"
3421: id: string
3422: seq: number
3423: aggregateID: string
3424: data: {
3425: timestamp: number
3426: sessionID: string
3427: messageID: string
3428: prompt: Prompt
3429: delivery: "steer" | "queue"
3430: requestExecution?: boolean
3431: }
3432: }
3433: }
3434:
3435: export type ...
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
4325: metadata?: {
4326: [key: string]: unknown
4327: }
4328: type: "session.next.prompted"
4329: durable?: {
4330: aggregateID: string
4331: seq: number
4332: version: number
4333: }
4334: location?: LocationRef
4335: data: {
4336: timestamp: number
4337: sessionID: string
4338: messageID: string
4339: prompt: Prompt
4340: delivery: "steer" | "queue"
4341: }
4342: }
4343:
4344: export type SessionNextPromptAdmitted = {
4345: id: string
4346: metadata?: {
4347: [key: string]: unknown
4348: }
4349: type: "session.next.prompt.admitted"
4350: durable?: {
4351: aggregateID: string
4352: seq: number
4353: version: number
4354: }
4355: location?: LocationRef
4356: data: {
4357: timestamp: number
4358: sessionID: string
4359: messageID: string
4360: prompt: Prompt
4361: delivery: ...
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
6430: }
6431:
6432: export type EventSessionNextMoved = {
6433: id: string
6434: type: "session.next.moved"
6435: properties: {
6436: timestamp: number
6437: sessionID: string
6438: location: LocationRef
6439: subdirectory?: string
6440: }
6441: }
6442:
6443: export type EventSessionNextPrompted = {
6444: id: string
6445: type: "session.next.prompted"
6446: properties: {
6447: timestamp: number
6448: sessionID: string
6449: messageID: string
6450: prompt: Prompt
6451: delivery: "steer" | "queue"
6452: }
6453: }
6454:
6455: export type EventSessionNextPromptAdmitted = {
6456: id: string
6457: type: "session.next.prompt.admitted"
6458: properties: {
6459: timestamp: number
6460: sessionID: string
6461: messageID: string
6462: prompt: Prompt
6463: delivery: "steer" | "queue"
6464: requestExecution?: ...
Found 12 matches /home/byk/Code/opencode/packages/sdk/openapi.json: Line 17876: "enum": ["session.next.prompt.admitted"] Line 17919: "enum": ["session.next.prompt.execution_requested"] Line 18289: "enum": ["session.next.step.recovered"] Line 25676: "enum": ["session.next.prompt.admitted.1"] Line 25740: "enum": ["session.next.prompt.execution_requested.1"] Line 26299: "enum": ["session.next.step.recovered.1"] Line 28557: "enum": ["session.next.prompt.admitted"] Line 28622: "enum": ["session.next.prompt.execution_requested"] Line 29190: "enum": ["session.next.step.recovered"] Line 34788: "enum": ["session.next.prompt.admitted"] Line 34831: "enum": ["session.next.prompt.execution_requested"] Line 35201: "enum": ["session.next.step.recovered"]
<path>/home/byk/Code/opencode/packages/sdk/openapi.json</path>
<type>file</type>
<content>
17850: "pattern": "^msg_"
17851: },
17852: "prompt": {
17853: "$ref": "#/components/schemas/Prompt"
17854: },
17855: "delivery": {
17856: "type": "string",
17857: "enum": ["steer", "queue"]
17858: }
17859: },
17860: "required": ["timestamp", "sessionID", "messageID", "prompt", "delivery"],
17861: "additionalProperties": false
17862: }
17863: },
17864: "required": ["id", "type", "properties"],
17865: "additionalProperties": false
17866: },
17867: {
17868: "type": "object",
17869: "properties": {
17870: ...
<path>/home/byk/Code/opencode/packages/core/src/database/migration.gen.ts</path>
<type>file</type>
<content>
1: import type { DatabaseMigration } from "./migration"
2:
3: export const migrations = (
4: await Promise.all([
5: import("./migration/20260127222353_familiar_lady_ursula"),
6: import("./migration/20260211171708_add_project_commands"),
7: import("./migration/20260213144116_wakeful_the_professor"),
8: import("./migration/20260225215848_workspace"),
9: import("./migration/20260227213759_add_session_workspace_id"),
10: import("./migration/20260228203230_blue_harpoon"),
11: import("./migration/20260303231226_add_workspace_fields"),
12: import("./migration/20260309230000_move_org_to_state"),
13: import("./migration/20260312043431_session_message_cursor"),
14: import("./migration/20260323234822_events"),
15: import("./migration/20260410174513_workspace-name"),
16: import("./migration/20260413175956_chief_energizer"),
17: ...
<path>/home/byk/Code/opencode/packages/core/src/session/recovery-id.ts</path>
<type>file</type>
<content>
1: import { SessionMessage } from "./message"
2:
3: export const message = (executionID: string, assistantMessageID?: SessionMessage.ID) =>
4: assistantMessageID ?? SessionMessage.ID.make(`msg_recovery_${executionID}`)
5:
6: export const continuation = (executionID: string) => SessionMessage.ID.make(`msg_recovery_continue_${executionID}`)
(End of file - total 6 lines)
</content>
Found 71 matches
/home/byk/Code/opencode/packages/core/test/session-projector.test.ts:
Line 68: it.effect("atomically reconciles one abandoned execution into one continuation", () =>
Line 222: it.effect("records a recovery continuation without forging an assistant identity", () =>
Line 258: it.effect("recovers each abandoned execution once across repeated startup scans", () =>
Line 304: it.effect("never recovers a live execution lease", () =>
Line 342: it.effect("never recovers an execution superseded by a newer assistant", () =>
Line 390: it.effect(`never recovers an assistant-less ${phase} execution superseded by a newer assistant`, () =>
Line 435: it.effect(`never commits assistant-less ${phase} recovery after concurrent assistant supersession`, () =>
Line 504: it.effect("recovers assistant-less continuation at its current assistant boundary", () =>
Line 555: it.effect("redrives a durable recovery wake after admission", () =>
Line ...
<path>/home/byk/Code/opencode/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
1280: .run()
1281: const wakes: string[] = []
1282:
1283: yield* SessionRecovery.recover().pipe(
1284: Effect.provideService(
1285: SessionExecution.Service,
1286: SessionExecution.Service.of({
1287: ...recoveryExecution,
1288: wake: (id) => Effect.sync(() => wakes.push(id)).pipe(Effect.asVoid),
1289: }),
1290: ),
1291: )
1292:
1293: expect(wakes).toEqual([sessionID])
1294: expect(yield* db.select().from(SessionExecutionTable).all()).toEqual([])
1295: expect(yield* db.select().from(SessionRecoveryTable).all()).toHaveLength(1)
1296: expect(yield* db.select().from(SessionInputTable).all()).toHaveLength(1)
1297: }),
1298: )
1299:
1300: it.effect("never recovers a pre-promotion claim when input commits at the recovery boundary", () =>
1301: ...
<path>/home/byk/Code/opencode/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
540:
541: expect(yield* db.select().from(SessionExecutionTable).all()).toEqual([])
542: expect(yield* db.select().from(SessionRecoveryTable).get()).toMatchObject({
543: execution_id: "assistant-less-current",
544: assistant_message_id: null,
545: phase: "continue",
546: })
547: expect(yield* db.select().from(SessionInputTable).get()).toMatchObject({
548: id: continuation("assistant-less-current"),
549: prompt: { text: "continue" },
550: delivery: "queue",
551: })
552: }),
553: )
554:
555: it.effect("redrives a durable recovery wake after admission", () =>
556: Effect.gen(function* () {
557: const { db } = yield* Database.Service
558: const events = yield* EventV2.Service
559: yield* db
560: .insert(ProjectTable)
561: .values({ id: Project.ID.global, ...
Found 25 matches
/home/byk/Code/opencode/packages/core/test/session-execution-local.test.ts:
Line 43: it.effect("clears the claim after a successful drain", () =>
Line 52: it.effect("snapshots the latest assistant sequence when acquiring a claim", () =>
Line 80: expect(yield* Deferred.await(observed)).toBe(7)
Line 84: it.effect("preserves the claim when its scope closes", () =>
Line 93: yield* Deferred.await(started)
Line 100: it.effect("clears the claim after explicit interruption", () =>
Line 108: yield* Deferred.await(started)
Line 114: it.effect("never starts a second owner while the lease is live", () =>
Line 128: yield* Deferred.await(firstStarted)
Line 137: it.effect("never overwrites an expired lease", () =>
Line 152: yield* Deferred.await(firstStarted)
Line 164: it.effect("never re-enters its own uncertain live lease", () =>
Line 191: it.effect("renews heartbeat expiry from the current clock", ...
<path>/home/byk/Code/opencode/packages/core/test/session-execution-local.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { Deferred, Effect, Exit, Fiber, Scope } from "effect"
3: import { TestClock } from "effect/testing"
4: import { eq, sql } from "drizzle-orm"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { Project } from "@opencode-ai/core/project"
7: import { ProjectTable } from "@opencode-ai/core/project/sql"
8: import { AbsolutePath } from "@opencode-ai/core/schema"
9: import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
10: import { SessionSchema } from "@opencode-ai/core/session/schema"
11: import { SessionExecutionTable, SessionTable } from "@opencode-ai/core/session/sql"
12: import { testEffect } from "./lib/effect"
13:
14: const sessionID = SessionSchema.ID.make("ses_execution_local")
15: const it = testEffect(Database.layerFromPath(":memory:"))
16:
17: const ...
Found 100 matches (more matches available)
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
Line 96: Effect.andThen(Deferred.await(streamGate)),
Line 146: if (toolExecutionGate) yield* Deferred.await(toolExecutionGate)
Line 588: yield* Deferred.await(streamed)
Line 619: it.effect("redrives only the synthetic recovery continuation", () =>
Line 688: it.effect("clears durable execution intent when ordinary input is promoted", () =>
Line 715: it.effect("redrives an ordinary prompt after its advisory wake is lost", () =>
Line 721: const { admitted: message } = yield* SessionInput.admit(db, events, {
Line 752: it.effect("never dispatches a provider after ownership changes", () =>
Line 759: modelResolveHook = Deferred.succeed(resolving, undefined).pipe(Effect.andThen(Deferred.await(resumeResolution)))
Line 763: yield* Deferred.await(resolving)
Line 771: yield* Fiber.await(run)
Line ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
600: event.type.startsWith(SessionEvent.Step.Interrupted.type),
601: ),
602: ).toBe(true)
603: expect(yield* session.context(sessionID)).toMatchObject([
604: { type: "user", text: prompt },
605: {
606: type: "assistant",
607: finish: "error",
608: error: { type: "unknown", message: "Provider Step outcome unknown after interruption" },
609: content: [
610: kind === "tool input"
611: ? { type: "tool", id: fragmentID(kind, "interrupted"), state: { status: "error" } }
612: : fixture.expectedContent,
613: ],
614: },
615: ])
616: })
617:
618: describe("SessionRunnerLLM", () => {
619: it.effect("redrives only the synthetic recovery continuation", () =>
620: Effect.gen(function* () {
621: yield* setup
622: const session = yield* SessionV2.Service
623: ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
1470: requests.length = 0
1471: executions.length = 0
1472: responses = [
1473: fragmentFixture("text", "text-summary-2", ["## Objective\n- Preserve the updated task"]).completeEvents,
1474: fragmentFixture("text", "text-final-2", ["Continued again"]).completeEvents,
1475: ]
1476: yield* session.prompt({
1477: sessionID,
1478: prompt: Prompt.make({ text: "Newest exact request ".repeat(180) }),
1479: resume: false,
1480: })
1481: yield* session.resume(sessionID)
1482:
1483: expect(requests).toHaveLength(2)
1484: expect(userTexts(requests[0])[0]).toContain(
1485: "<prior-summary>\n## Objective\n- Preserve the task\n</prior-summary>",
1486: )
1487: expect(userTexts(requests[0])[0]).toContain("Recent exact request")
1488: expect((yield* (yield* ...
Found 29 matches
/home/byk/Code/opencode/packages/core/test/session-prompt.test.ts:
Line 140: it.effect("exposes the execution registry", () =>
Line 147: it.effect("delegates execution continuation through SessionExecution", () =>
Line 159: it.effect("delegates process-local interruption through SessionExecution", () =>
Line 171: it.effect("delegates interruption without requiring a recorded Session", () =>
Line 181: it.effect("durably admits one user message before transcript promotion", () =>
Line 203: it.effect("resolves attachment MIME before admission", () =>
Line 224: it.effect("streams durable Session events after an aggregate sequence", () =>
Line 254: it.effect("resumes through a recorded message without appending another prompt", () =>
Line 275: it.effect("records distinct messages when the ID is omitted", () =>
Line 290: it.effect("returns the original recorded message when the ID is retried", () =>
Line 310: ...
<path>/home/byk/Code/opencode/packages/core/test/session-prompt.test.ts</path>
<type>file</type>
<content>
280:
281: const first = yield* session.prompt(input)
282: const second = yield* session.prompt(input)
283:
284: expect(second.id).not.toBe(first.id)
285: expect(yield* session.messages({ sessionID })).toEqual([])
286: expect(yield* admittedCount).toBe(2)
287: }),
288: )
289:
290: it.effect("returns the original recorded message when the ID is retried", () =>
291: Effect.gen(function* () {
292: yield* setup
293: const session = yield* SessionV2.Service
294: const input = {
295: sessionID,
296: id: messageID,
297: prompt: Prompt.make({ text: "Fix the failing tests" }),
298: resume: false,
299: }
300:
301: const first = yield* session.prompt(input)
302: const retried = yield* session.prompt(input)
303:
304: expect(retried).toEqual(first)
305: expect(yield* ...
<path>/home/byk/Code/opencode/packages/schema/test/event-manifest.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect, test } from "bun:test"
2: import { FileSystem, Integration, Permission, Project, Reference, Session, Workspace } from "../src"
3: import { EventManifest } from "../src/event-manifest"
4: import { IdeEvent } from "../src/ide-event"
5: import { SessionEvent } from "../src/session-event"
6: import { SessionTodo } from "../src/session-todo"
7: import { SessionV1 } from "../src/session-v1"
8: import { WorkspaceEvent } from "../src/workspace-event"
9:
10: describe("public event manifest", () => {
11: test("owns the complete public event surface", () => {
12: expect(EventManifest.ServerDefinitions.length).toBe(61)
13: expect(EventManifest.Definitions.length).toBe(91)
14: expect(SessionV1.Event.Definitions).toEqual([
15: SessionV1.Event.Created,
16: SessionV1.Event.Updated,
17: SessionV1.Event.Deleted,
18: ...
Found 8 matches
/home/byk/Code/opencode/packages/core/test/database-migration.test.ts:
Line 186: sql`SELECT "notnull" AS required FROM pragma_table_info('session_execution') WHERE name = 'id'`,
Line 191: sql`SELECT dflt_value AS value FROM pragma_table_info('session_input') WHERE name = 'wake_pending'`,
Line 195: yield* db.get(sql`SELECT dflt_value AS value FROM pragma_table_info('session') WHERE name = 'wake_attempts'`),
Line 199: sql`SELECT pk, "notnull" AS required FROM pragma_table_info('session_recovery') WHERE name = 'execution_id'`,
Line 204: sql`SELECT "notnull" AS required FROM pragma_table_info('session_recovery') WHERE name = 'assistant_message_id'`,
Line 209: sql`SELECT "notnull" AS required FROM pragma_table_info('session_recovery') WHERE name = 'phase'`,
Line 214: sql`SELECT "notnull" AS required FROM pragma_table_info('session_recovery') WHERE name = ...
<path>/home/byk/Code/opencode/packages/core/test/database-migration.test.ts</path>
<type>file</type>
<content>
120: .quiet()
121: .nothrow()
122: expect(result.exitCode, result.stderr.toString()).toBe(0)
123: expect(result.stdout.toString()).toContain("No schema changes, nothing to migrate")
124: }, 30_000)
125: }
126:
127: test("applies tracked migrations to an empty database", async () => {
128: await run(
129: Effect.gen(function* () {
130: const db = yield* makeDb
131: yield* DatabaseMigration.apply(db)
132:
133: expect(yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'session'`)).toEqual({
134: name: "session",
135: })
136: expect(
137: yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'session_input'`),
138: ).toEqual({ name: "session_input" })
139: expect(
140: yield* ...
No files found
Found 53 matches
/home/byk/Code/opencode/packages/core/test/session-run-coordinator.test.ts:
Line 9: it.effect("joins concurrent resumes for one key", () =>
Line 15: drain: () => Effect.sync(() => runs++).pipe(Effect.andThen(Deferred.await(gate))),
Line 31: it.effect("joins a wake-started execution without forcing a successor", () =>
Line 41: Effect.andThen(Deferred.await(gate)),
Line 46: yield* Deferred.await(started)
Line 57: it.effect("starts execution when woken while idle", () =>
Line 64: yield* Deferred.await(drained)
Line 69: it.effect("snapshots only active executions", () =>
Line 79: Effect.andThen(Deferred.await(key === "first" ? firstGate : secondGate)),
Line 85: yield* Deferred.await(firstStarted)
Line 89: yield* Deferred.await(secondStarted)
Line 102: it.effect("cleans active executions after failure and defect", () =>
Line 122: it.effect("cleans active ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner-recorded.test.ts</path>
<type>file</type>
<content>
1: import { HttpRecorder } from "@opencode-ai/http-recorder"
2: import { HttpRecorderInternal } from "@opencode-ai/http-recorder/internal"
3: import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat"
4: import { Auth, LLMClient, RequestExecutor } from "@opencode-ai/llm/route"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
7: import { LayerNodePlatform } from "@opencode-ai/core/effect/app-node-platform"
8: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
9: import { EventV2 } from "@opencode-ai/core/event"
10: import { EventTable } from "@opencode-ai/core/event/sql"
11: import { PermissionV2 } from "@opencode-ai/core/permission"
12: import { AgentV2 } from "@opencode-ai/core/agent"
13: import { Config } from "@opencode-ai/core/config"
14: import { ...
No files found
diff --git a/packages/core/test/session-runner-tool-events.test.ts b/packages/core/test/session-runner-tool-events.test.ts
index f96ea4dea2..47b92f55e2 100644
--- a/packages/core/test/session-runner-tool-events.test.ts
+++ b/packages/core/test/session-runner-tool-events.test.ts
@@ -1,136 +1,175 @@
import { expect, test } from "bun:test"
import { Effect, Schema, Stream } from "effect"
import { LLMEvent } from "@opencode-ai/llm"
import { EventV2 } from "@opencode-ai/core/event"
import { SessionEvent } from "@opencode-ai/core/session/event"
import { SessionMessage } from "@opencode-ai/core/session/message"
import { SessionV2 } from "@opencode-ai/core/session"
import { ModelV2 } from "@opencode-ai/core/model"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { createLLMEventPublisher } from "@opencode-ai/core/session/runner/publish-llm-event"
const sessionID = SessionV2.ID.make("ses_tool_event_test")
const base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB"
const ...
{"entityType": "tables", "name": "session_execution"}
{"entityType": "tables", "name": "session_recovery"}
{"autoincrement": false, "default": null, "entityType": "columns", "generated": null, "name": "id", "notNull": true, "table": "session_execution", "type": "text"}
{"autoincrement": false, "default": null, "entityType": "columns", "generated": null, "name": "session_id", "notNull": true, "table": "session_execution", "type": "text"}
{"autoincrement": false, "default": null, "entityType": "columns", "generated": null, "name": "owner_id", "notNull": true, "table": "session_execution", "type": "text"}
{"autoincrement": false, "default": null, "entityType": "columns", "generated": null, "name": "assistant_message_id", "notNull": false, "table": "session_execution", "type": "text"}
{"autoincrement": false, "default": null, "entityType": "columns", "generated": null, "name": "phase", "notNull": true, "table": "session_execution", "type": "text"}
{"autoincrement": false, "default": "-1", ...
<path>/home/byk/Code/opencode/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { DateTime, Deferred, Effect, Exit, Fiber, Schema } from "effect"
3: import { TestClock } from "effect/testing"
4: import { asc, eq, sql } from "drizzle-orm"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
7: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
8: import { EventV2 } from "@opencode-ai/core/event"
9: import { EventTable } from "@opencode-ai/core/event/sql"
10: import { ModelV2 } from "@opencode-ai/core/model"
11: import { Project } from "@opencode-ai/core/project"
12: import { ProjectTable } from "@opencode-ai/core/project/sql"
13: import { ProviderV2 } from "@opencode-ai/core/provider"
14: import { AbsolutePath } from "@opencode-ai/core/schema"
15: import { SessionV2 } from ...
<path>/home/byk/Code/opencode/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
2230:
2231: expect(yield* db.select().from(SessionExecutionTable).get()).toMatchObject({
2232: owner_id: "successor-owner",
2233: recovery_error: null,
2234: })
2235: }),
2236: )
2237:
2238: it.effect("quarantines failed execution conversion before scanning later claims", () =>
2239: Effect.gen(function* () {
2240: const { db } = yield* Database.Service
2241: const events = yield* EventV2.Service
2242: const count = SessionRecovery.BATCH_SIZE + 1
2243: const ids = Array.from({ length: count }, (_, index) =>
2244: SessionV2.ID.make(`ses_recovery_conversion_${index.toString().padStart(3, "0")}`),
2245: )
2246: yield* db
2247: .insert(ProjectTable)
2248: .values({ id: Project.ID.global, worktree: AbsolutePath.make("/project"), sandboxes: [] })
2249: .run()
2250: ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import {
3: LLMClient,
4: LLMError,
5: LLMEvent,
6: Model,
7: TransportReason,
8: InvalidRequestReason,
9: type LLMClientShape,
10: type LLMRequest,
11: } from "@opencode-ai/llm"
12: import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat"
13: import { Database } from "@opencode-ai/core/database/database"
14: import { makeLocationNode } from "@opencode-ai/core/effect/app-node"
15: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
16: import { LayerNodePlatform } from "@opencode-ai/core/effect/app-node-platform"
17: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
18: import { EventV2 } from "@opencode-ai/core/event"
19: import { PermissionV2 } from "@opencode-ai/core/permission"
20: import { EventTable } from "@opencode-ai/core/event/sql"
21: import { Project } ...
diff --git a/packages/core/test/session-run-coordinator.test.ts b/packages/core/test/session-run-coordinator.test.ts
index dfbeda664c..63dfad7a71 100644
--- a/packages/core/test/session-run-coordinator.test.ts
+++ b/packages/core/test/session-run-coordinator.test.ts
@@ -225,120 +225,165 @@ describe("SessionRunCoordinator", () => {
drain: () =>
Effect.sync(() => ++runs).pipe(
Effect.andThen(Deferred.succeed(started, undefined)),
Effect.andThen(Effect.never),
Effect.onInterrupt(() => Deferred.succeed(interrupted, undefined)),
),
})
const resumed = yield* coordinator.run("session").pipe(Effect.forkChild)
yield* Deferred.await(started)
yield* coordinator.wake("session")
yield* coordinator.interrupt("session")
yield* Deferred.await(interrupted)
const exit = yield* Fiber.await(resumed)
expect(Exit.isFailure(exit) && ...
PASS
ab9408c81cc9916177641ae8e9f08624fc27b5b9.5efd9d74f450e9f875790a07c860248cb526f7144a822cf6df51761237f9789b.3c26981f57d37d15549b76657c20a090355911e80ea94d43f957422dc3276796.None.
SessionInput.promoteExact starts an immediate transaction and invokes the supplied claim commit before changing recovery_error: packages/core/src/session/input.ts:591-617.updateExecution() guard: packages/core/src/session/runner/llm.ts:235-239.packages/core/src/session/execution/claim.ts:27-53.packages/core/test/session-projector.test.ts:1694-1780.packages/core/src/session/recovery.ts:121-138.packages/core/src/session/recovery.ts:236-255.packages/core/test/session-projector.test.ts:2000-2101 and projection failures at packages/core/test/session-projector.test.ts:2104-2235. ...