Dashboard › opencode › Session 1Ott14A3vCIk
1Ott14A3vCIkpvzdrRead-only independent security review frozen v17. Base ab9408c81cc9916177641ae8e9f08624fc27b5b9. Patch /tmp/opencode/session-recovery-final-v17.patch SHA-256 0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e. SEA /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server SHA-256 308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4. Verify immutable inputs/clean apply/34 paths and inspect all. No mutation/tests/builds/services, no recall. Focus prior blocker: cancellation after durable Step.Failed while local tool settlement active must terminally settle ownership without duplicate assistant event; runner uses hasAssistantFailed after tool reconciliation to call exact live cancelling->cancelled transition; cleanup removes claim after fibers/finalizers; regression asserts one Failed, no Interrupted, no claim/recovery. Also monotonic cancellation guard/renew isolation/publication defects. Reassess stale owners, recovery identity/replay/supersession, explicit resume, scheduling DoS, tools, schema/clients/auth/dependencies. Accepted final check-call/process-local/skew residuals. Evidence 229 recovery, full Core 1186/0, typecheck, migration upgrades/script, exact smoke. PASS/CONCERN/MUST-FIX file:line; end MERGE or DO-NOT-MERGE. Empty invalid.
0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e /tmp/opencode/session-recovery-final-v17.patch 308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4 /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server /tmp/opencode/session-recovery-final-v17.patch 414241 bytes 2026-09-16 23:58:55.914307051 +0000 /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server 157879104 bytes 2026-09-16 23:57:25.659673826 +0000
dc661f30cb2055ad6248fdc59b14998d834497be commit M .lore.md M AGENTS.md M packages/client/src/generated/types.ts 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 ...
bf77604a044ec48ee2e7848865ddee41e317d78e1e8f525c1f326109443742e4 - 72 0 packages/client/src/generated/types.ts 567 48 packages/core/schema.json 1 0 packages/core/src/database/migration.gen.ts 62 0 packages/core/src/database/migration/20260914170650_session-recovery.ts 52 1 packages/core/src/database/schema.gen.ts 6 4 packages/core/src/session.ts 31 16 packages/core/src/session/compaction.ts 54 34 packages/core/src/session/context-epoch.ts 165 19 packages/core/src/session/execution/local.ts 391 31 packages/core/src/session/input.ts 69 0 packages/core/src/session/message-updater.ts 88 1 packages/core/src/session/projector.ts 504 0 packages/core/src/session/recovery.ts 30 5 packages/core/src/session/run-coordinator.ts 4 0 packages/core/src/session/runner/index.ts 300 104 packages/core/src/session/runner/llm.ts 108 46 packages/core/src/session/runner/publish-llm-event.ts 88 1 packages/core/src/session/sql.ts 66 1 packages/core/test/database-migration.test.ts 352 0 packages/core/test/sessi...
Found 34 matches /tmp/opencode/session-recovery-final-v17.patch: Line 1: diff --git a/packages/client/src/generated/types.ts b/packages/client/src/generated/types.ts Line 109: diff --git a/packages/core/schema.json b/packages/core/schema.json Line 1025: diff --git a/packages/core/src/database/migration.gen.ts b/packages/core/src/database/migration.gen.ts Line 1036: diff --git a/packages/core/src/database/migration/20260914170650_session-recovery.ts b/packages/core/src/database/migration/20260914170650_session-recovery.ts Line 1104: diff --git a/packages/core/src/database/schema.gen.ts b/packages/core/src/database/schema.gen.ts Line 1210: diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts Line 1250: diff --git a/packages/core/src/session/compaction.ts b/packages/core/src/session/compaction.ts Line 1339: diff --git a/packages/core/src/session/context-epoch.ts b/packages/core/src/session/context-epoch.ts Line 1515: diff --git ...
ab9408c81cc9916177641ae8e9f08624fc27b5b9 1 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-runner-tool-events.test.ts M packages/core/test/session-runner.test.ts M packages/opencode/src/server/routes/instance/ht...
Found 39 matches /tmp/opencode/session-recovery-final-v17.patch: Line 2: index 3b3188c874..5130fa9496 100644 Line 110: index d0eeeebd5c..81e5eca808 100644 Line 1026: index e6ea4eaa14..77948f1529 100644 Line 1037: new file mode 100644 Line 1038: index 0000000000..20eb1a4373 Line 1105: index ed60fde6c5..94881e7038 100644 Line 1211: index 2dabfb2d6f..1fbd6285d0 100644 Line 1251: index f714633295..92a934c44f 100644 Line 1340: index 65b17a86a4..880d42bcf9 100644 Line 1516: index d874c40832..0bb4f02b2c 100644 Line 1732: index 14b613678d..61f6a9a465 100644 Line 2327: index 46118a89fe..e2d7e6b38e 100644 Line 2421: index 792067017d..2742cabc24 100644 Line 2540: new file mode 100644 Line 2541: index 0000000000..e289b821c7 Line 3050: index 2f89aff9e3..ab4b833374 100644 Line 3119: index 634075dd91..7b9ac3ae83 100644 Line 3141: index 874086a06b..3853bb7d75 100644 Line 3725: index 33652a618c..e2b9b9b8f4 100644 Line 4071: index ...
fatal: path 'packages/core/src/database/migration/20260914170650_session-recovery.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9' fatal: path 'packages/core/src/session/recovery.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9' fatal: path 'packages/core/test/session-execution-local.test.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9' fatal: path 'packages/core/src/session/execution/claim.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9' fatal: path 'packages/core/src/session/recovery-id.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9' sections=34 clean_in_memory_apply=True base_and_worktree_blob_matches=True
<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, notInArray } 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 = ...
<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/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/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/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/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: ...
<path>/home/byk/Code/opencode/packages/core/src/session/projector.ts</path>
<type>file</type>
<content>
351: .where(eq(SessionTable.id, event.data.sessionID))
352: .run()
353: .pipe(Effect.orDie)
354: yield* run(db, event)
355: }),
356: )
357: yield* events.project(SessionEvent.Prompted, (event) =>
358: Effect.gen(function* () {
359: if (event.durable === undefined) return yield* Effect.die("Durable Session event is missing aggregate sequence")
360: yield* SessionInput.projectPrompted(db, {
361: id: event.data.messageID,
362: sessionID: event.data.sessionID,
363: prompt: event.data.prompt,
364: delivery: event.data.delivery,
365: timeCreated: event.data.timestamp,
366: promotedSeq: event.durable.seq,
367: })
368: yield* run(db, event)
369: }),
370: )
371: yield* events.project(SessionEvent.PromptAdmitted, (event) =>
372: ...
<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/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/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 21 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', 'cancelled'))
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 ...
<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/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/opencode/src/server/routes/instance/httpapi/server.ts</path>
<type>file</type>
<content>
181: Layer.provide([serverHttpApiAuthLayer, v2SchemaErrorLayer]),
182: )
183:
184: // `OpenApi.fromApi` is non-trivial; defer until /doc is actually hit so
185: // processes that never serve it (CLI, scripts) don't pay at module load.
186: // `HttpServerResponse.jsonUnsafe` runs JSON.stringify eagerly, so caching
187: // the response also caches the serialized body — every /doc request reuses
188: // the same Uint8Array instead of re-stringifying the spec.
189: const docResponse = lazy(() => HttpServerResponse.jsonUnsafe(OpenApi.fromApi(PublicApi)))
190:
191: const docRoute = HttpRouter.use((router) => router.add("GET", "/doc", () => Effect.succeed(docResponse()))).pipe(
192: Layer.provide(authOnlyRouterLayer),
193: )
194:
195: const uiRoute = HttpRouter.use((router) =>
196: Effect.gen(function* () {
197: const fs = yield* FSUtil.Service
198: ...
<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> 320: const boundary = anchor 321: ? order === "asc" 322: ? gt(SessionMessageTable.seq, anchor.seq) 323: : lt(SessionMessageTable.seq, anchor.seq) 324: : undefined 325: const where = boundary 326: ? and(eq(SessionMessageTable.session_id, input.sessionID), boundary) 327: : eq(SessionMessageTable.session_id, input.sessionID) 328: const query = db 329: .select() 330: .from(SessionMessageTable) 331: .where(where) 332: .orderBy(order === "asc" ? asc(SessionMessageTable.seq) : desc(SessionMessageTable.seq)) 333: const rows = yield* (input.limit === undefined ? query.all() : query.limit(input.limit).all()).pipe( 334: Effect.orDie, 335: ) 336: return yield* Effect.forEach(direction === "previous" ? rows.toReversed() : rows, decode) 337: ...
Found 84 matches
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
Line 752: it.effect("never dispatches a provider after ownership changes", () =>
Line 778: it.effect("never publishes streamed output after ownership changes", () =>
Line 787: yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "fence publication" }), resume: false })
Line 793: .set({ id: "publication-successor", owner_id: "successor", expires_at: 60_000 })
Line 805: it.effect("never starts a local tool after ownership changes", () =>
Line 845: it.effect("never fails interrupted tools after ownership changes", () =>
Line 2055: it.effect("keeps a running assistant recoverable when Step failure publication defects", () =>
Line 2060: yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail Step publication" }), resume: false })
Line 2063: CREATE TRIGGER fail_step_failure_publication
Line 2067: SELECT ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
700: LLMEvent.stepStart({ index: 0 }),
701: LLMEvent.stepFinish({ index: 0, reason: "stop" }),
702: LLMEvent.finish({ reason: "stop" }),
703: ]
704:
705: yield* session.resume(sessionID)
706:
707: expect(
708: yield* db.select().from(SessionInputTable).where(eq(SessionInputTable.id, message.id)).get(),
709: ).toMatchObject({
710: wake_pending: false,
711: })
712: }),
713: )
714:
715: it.effect("redrives an ordinary prompt after its advisory wake is lost", () =>
716: Effect.gen(function* () {
717: yield* setup
718: const session = yield* SessionV2.Service
719: const events = yield* EventV2.Service
720: const { db } = yield* Database.Service
721: const { admitted: message } = yield* SessionInput.admit(db, events, {
722: id: ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
3860: const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
3861: while (executions.length === 0) yield* Effect.yieldNow
3862: const { db } = yield* Database.Service
3863: expect(
3864: yield* db.select().from(SessionExecutionTable).where(eq(SessionExecutionTable.session_id, sessionID)).get(),
3865: ).toMatchObject({
3866: phase: "unknown",
3867: })
3868: yield* session.interrupt(sessionID)
3869: toolExecutionGate = undefined
3870:
3871: expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" })
3872: yield* session.interrupt(sessionID)
3873: expect(yield* session.context(sessionID)).toMatchObject([
3874: { type: "user", text: "Interrupt blocked tool" },
3875: {
3876: type: "assistant",
3877: finish: "error",
3878: error: { type: ...
<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 { SessionExecutionClaim } from "@opencode-ai/core/session/execution/claim"
11: import { SessionMessage } from "@opencode-ai/core/session/message"
12: import { SessionSchema } from "@opencode-ai/core/session/schema"
13: import { SessionExecutionTable, SessionTable } from "@opencode-ai/core/session/sql"
14: import { testEffect } from ...
Found 100 matches (more matches available)
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
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 752: it.effect("never dispatches a provider after ownership changes", () =>
Line 778: it.effect("never publishes streamed output after ownership changes", () =>
Line 805: it.effect("never starts a local tool after ownership changes", () =>
Line 845: it.effect("never fails interrupted tools after ownership changes", () =>
Line 902: it.effect("advertises and executes a globally attached application tool", () =>
Line 958: it.effect("starts a real runner turn after default prompt recording", () =>
Line 977: it.effect("streams one request with registry definitions from ...
Found 52 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> 700: wake: (id) => Effect.sync(() => wakes.push(id)).pipe(Effect.asVoid), 701: }) 702: 703: yield* SessionRecovery.recover().pipe(Effect.provideService(SessionExecution.Service, execution)) 704: expect(wakes).toEqual([]) 705: expect( 706: yield* db 707: .select() 708: .from(SessionRecoveryTable) 709: .where(eq(SessionRecoveryTable.recovery_error, "Invalid recovery continuation input")) 710: .all(), 711: ).toHaveLength(SessionRecovery.BATCH_SIZE) 712: 713: yield* SessionRecovery.recover().pipe(Effect.provideService(SessionExecution.Service, execution)) 714: expect(wakes).toEqual([sessions[poisonCount]]) 715: expect( 716: yield* db 717: .select() 718: .from(SessionRecoveryTable) 719: .where(eq(SessionRecoveryTable.recovery_error, ...
<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/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 50 matches
/home/byk/Code/opencode/packages/schema/test/event-manifest.test.ts:
Line 52: expect(EventManifest.Durable.get("session.next.prompt.execution_requested.1")).toBe(
Line 53: SessionEvent.PromptExecutionRequested,
/home/byk/Code/opencode/packages/client/src/generated/types.ts:
Line 784: readonly type: "session.next.prompt.execution_requested"
Line 908: readonly type: "session.next.step.recovered"
Line 1278: readonly type: "session.next.prompt.execution_requested"
Line 1402: readonly type: "session.next.step.recovered"
/home/byk/Code/opencode/packages/sdk/openapi.json:
Line 15312: "$ref": "#/components/schemas/EventSessionNextPromptExecution_requested"
Line 15339: "$ref": "#/components/schemas/EventSessionNextStepRecovered"
Line 17919: "enum": ["session.next.prompt.execution_requested"]
Line 18289: "enum": ["session.next.step.recovered"]
...
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
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 SyncEventSessionNextPromptExecutionRequested = {
3436: type: "sync"
3437: id: string
3438: syncEvent: {
3439: type: "session.next.prompt.execution_requested.1"
3440: id: string
3441: seq: number
3442: aggregateID: string
3443: data: {
3444: timestamp: number
3445: sessionID: string
3446: messageID: string
3447: }
3448: }
3449: }
3450:
3451: export type SyncEventSessionNextContextUpdated = {
3452: type: "sync"
3453: id: string
3454: syncEvent: {
3455: type: "session.next.context.updated.1"
3456: id: string
3457: seq: number
3458: aggregateID: string
3459: data: ...
<path>/home/byk/Code/opencode/packages/sdk/openapi.json</path>
<type>file</type>
<content>
35170: "timestamp": {
35171: "type": "number"
35172: },
35173: "sessionID": {
35174: "type": "string",
35175: "pattern": "^ses"
35176: },
35177: "assistantMessageID": {
35178: "type": "string",
35179: "pattern": "^msg_"
35180: },
35181: "error": {
35182: "$ref": "#/components/schemas/SessionErrorUnknown"
35183: }
35184: },
35185: "required": ["timestamp", "sessionID", "assistantMessageID", "error"],
35186: "additionalProperties": false
35187: }
35188: },
35189: "required": ["id", "type", "properties"],
35190: "additionalProperties": false
35191: },
35192: "EventSessionNextStepRecovered": {
35193: ...
Found 4 matches /home/byk/Code/opencode/packages/core/schema.json: Line 2306: "name": "session_execution_recovery_scan_idx", Line 2510: "name": "session_recovery_wake_pending_error_attempts_created_execution_idx", Line 2572: "name": "session_execution_phase_check", Line 2578: "name": "session_recovery_wake_attempts_check",
<path>/home/byk/Code/opencode/packages/core/schema.json</path>
<type>file</type>
<content>
2180: {
2181: "columns": [
2182: {
2183: "value": "project_id",
2184: "isExpression": false
2185: },
2186: {
2187: "value": "action",
2188: "isExpression": false
2189: },
2190: {
2191: "value": "resource",
2192: "isExpression": false
2193: }
2194: ],
2195: "isUnique": true,
2196: "where": null,
2197: "origin": "manual",
2198: "name": "permission_project_action_resource_idx",
2199: "entityType": "indexes",
2200: "table": "permission"
2201: },
2202: {
2203: "columns": [
2204: {
2205: "value": "session_id",
2206: "isExpression": false
2207: },
2208: {
2209: "value": "time_created",
2210: "isExpression": false
2211: },
2212: {
2213: ...
Found 3 matches /home/byk/Code/opencode/packages/core/schema.json: Line 66: "name": "session_execution", Line 70: "name": "session_input", Line 78: "name": "session_recovery",
<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/test/database-migration.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect, test } from "bun:test"
2: import { $ } from "bun"
3: import { fileURLToPath } from "url"
4: import path from "path"
5: import { SqliteClient } from "@effect/sql-sqlite-bun"
6: import { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
7: import { Effect, Exit, Layer } from "effect"
8: import { eq, inArray, sql } from "drizzle-orm"
9: import { DatabaseMigration } from "@opencode-ai/core/database/migration"
10: import { migrations } from "@opencode-ai/core/database/migration.gen"
11: import workspaceNameMigration from "@opencode-ai/core/database/migration/20260410174513_workspace-name"
12: import sessionUsageMigration from "@opencode-ai/core/database/migration/20260510033149_session_usage"
13: import normalizeStoragePathsMigration from "@opencode-ai/core/database/migration/20260601010001_normalize_storage_paths"
14: import ...
<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: ...
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>
130: SessionExecution.Service.of({
131: active: Effect.succeed(new Set()),
132: resume: () => Effect.void,
133: interrupt: () => Effect.void,
134: wake: (id) => Effect.sync(() => wakeCalls.push(id)).pipe(Effect.asVoid),
135: }),
136: ),
137: )
138:
139: describe("SessionV2.prompt", () => {
140: it.effect("exposes the execution registry", () =>
141: Effect.gen(function* () {
142: activeSessions.add(sessionID)
143: expect(Array.from(yield* (yield* SessionV2.Service).active)).toEqual([sessionID])
144: }).pipe(Effect.ensuring(Effect.sync(() => activeSessions.clear()))),
145: )
146:
147: it.effect("delegates execution continuation through SessionExecution", () =>
148: Effect.gen(function* () {
149: yield* setup
150: const session = yield* SessionV2.Service
151: executionCalls.length = ...
<path>/home/byk/Code/opencode/packages/core/test/session-run-coordinator.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { Cause, Deferred, Effect, Exit, Fiber, Layer } from "effect"
3: import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
4: import { testEffect } from "./lib/effect"
5:
6: const it = testEffect(Layer.empty)
7:
8: describe("SessionRunCoordinator", () => {
9: it.effect("joins concurrent resumes for one key", () =>
10: Effect.scoped(
11: Effect.gen(function* () {
12: const gate = yield* Deferred.make<void>()
13: let runs = 0
14: const coordinator = yield* SessionRunCoordinator.make({
15: drain: () => Effect.sync(() => runs++).pipe(Effect.andThen(Deferred.await(gate))),
16: })
17:
18: const first = yield* coordinator.run("session").pipe(Effect.forkChild)
19: yield* Effect.yieldNow
20: const second = yield* ...
<path>/tmp/opencode/session-recovery-final-v17.patch</path>
<type>file</type>
<content>
7850: Effect.scoped(
7851: Effect.gen(function* () {
7852: diff --git a/packages/core/test/session-runner-recorded.test.ts b/packages/core/test/session-runner-recorded.test.ts
7853: index d45cc8c734..ec91d1b4a4 100644
7854: --- a/packages/core/test/session-runner-recorded.test.ts
7855: +++ b/packages/core/test/session-runner-recorded.test.ts
7856: @@ -19,7 +19,7 @@ import { Snapshot } from "@opencode-ai/core/snapshot"
7857: import { Prompt } from "@opencode-ai/core/session/prompt"
7858: import { SessionProjector } from "@opencode-ai/core/session/projector"
7859: import { SessionExecution } from "@opencode-ai/core/session/execution"
7860: -import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
7861: +import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
7862: import { SessionRunner } from "@opencode-ai/core/session/runner"
7863: ...
<path>/tmp/opencode/session-recovery-final-v17.patch</path>
<type>file</type>
<content>
9390: }),
9391: )
9392:
9393: diff --git a/packages/opencode/src/server/routes/instance/httpapi/server.ts b/packages/opencode/src/server/routes/instance/httpapi/server.ts
9394: index fb9d2db656..748e8aa43b 100644
9395: --- a/packages/opencode/src/server/routes/instance/httpapi/server.ts
9396: +++ b/packages/opencode/src/server/routes/instance/httpapi/server.ts
9397: @@ -66,6 +66,7 @@ import { SessionProjector } from "@opencode-ai/core/session/projector"
9398: import { SessionV2 } from "@opencode-ai/core/session"
9399: import { SessionExecution } from "@opencode-ai/core/session/execution"
9400: import * as SessionExecutionLocal from "@opencode-ai/core/session/execution/local"
9401: +import { SessionRecovery } from "@opencode-ai/core/session/recovery"
9402: import { lazy } from "@/util/lazy"
9403: import { CorsConfig, isAllowedCorsOrigin, type CorsOptions } from ...
/home/byk/Code/opencode/packages/core/src/event.ts
<path>/home/byk/Code/opencode/packages/core/src/event.ts</path>
<type>file</type>
<content>
1: export * as EventV2 from "./event"
2:
3: import { Cause, Context, Effect, Layer, Option, PubSub, Queue, Schema, Stream } from "effect"
4: import { Event } from "@opencode-ai/schema/event"
5: import type { Data, Definition, Payload } from "@opencode-ai/schema/event"
6: import { and, asc, eq, gt, inArray } from "drizzle-orm"
7: import { Database } from "./database/database"
8: import { EventSequenceTable, EventTable } from "./event/sql"
9: import { Location } from "./location"
10: import { makeGlobalNode } from "./effect/app-node"
11: import { isDeepStrictEqual } from "node:util"
12: import { Durable } from "@opencode-ai/schema/durable-event-manifest"
13:
14: export const ID = Event.ID
15: export type ID = import("@opencode-ai/schema/event").ID
16: export type { Data, Definition, Payload } from "@opencode-ai/schema/event"
17:
18: export type Subscriber<D extends Definition = Definition> = ...
Found 76 matches
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
Line 818: const unsubscribe = yield* events.listen((event) =>
Line 3245: yield* events.listen((event) =>
/home/byk/Code/opencode/packages/core/test/permission.test.ts:
Line 93: const unsubscribe = yield* events.listen((event) =>
Line 292: const unsubscribe = yield* events.listen((event) =>
/home/byk/Code/opencode/packages/core/test/event.test.ts:
Line 257: const unsubscribe = yield* events.listen(() =>
Line 275: yield* events.listen(() => {
Line 278: yield* events.listen((event) =>
Line 297: yield* events.listen((event) =>
Line 358: yield* events.listen(() => Effect.interrupt)
Line 377: yield* events.listen(() => Effect.die(defect))
Line 966: yield* events.listen((event) => Effect.sync(() => received.push(event)))
Line 994: yield* events.listen((event) => Effect.sync(() => received.push(event)))
...
<path>/home/byk/Code/opencode/packages/opencode/src/event-v2-bridge.ts</path>
<type>file</type>
<content>
1: // Opencode publish boundary for core events. Attach routed instance location
2: // so direct EventV2 consumers can isolate directory/workspace streams.
3: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
4: import { InstanceRef, WorkspaceRef } from "@/effect/instance-ref"
5: import { GlobalBus } from "@/bus/global"
6: import { EventV2 } from "@opencode-ai/core/event"
7: import { Location } from "@opencode-ai/core/location"
8: import { Project } from "@opencode-ai/core/project"
9: import { AbsolutePath } from "@opencode-ai/core/schema"
10: import { Context, Effect, Layer } from "effect"
11:
12: export class Service extends Context.Service<Service, EventV2.Interface>()("@opencode/EventV2Bridge") {}
13:
14: const layer = Layer.effect(
15: Service,
16: Effect.gen(function* () {
17: const events = yield* EventV2.Service
18:
19: const publish: ...
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
2010: const claim = yield* db.select().from(SessionExecutionTable).get()
2011: const started = yield* db
2012: .select({ seq: EventTable.seq })
2013: .from(EventTable)
2014: .where(eq(EventTable.type, "session.next.step.started.1"))
2015: .get()
2016: expect(claim).toMatchObject({ phase: "unknown", assistant_seq: started?.seq })
2017: expect(
2018: (yield* session.context(sessionID))
2019: .filter((message) => message.type === "assistant")
2020: .flatMap((message) => message.content)
2021: .find((part) => part.type === "tool" && part.id === "call-hosted-pending"),
2022: ).toMatchObject({ type: "tool", state: { status: "running" } })
2023: expect(
2024: yield* db
2025: .select({ type: EventTable.type })
2026: .from(EventTable)
2027: ...
<path>/home/byk/Code/opencode/packages/client/src/generated/types.ts</path>
<type>file</type>
<content>
750: readonly delivery: "steer" | "queue"
751: }
752: }
753: | {
754: readonly id: string
755: readonly metadata?: { readonly [x: string]: JsonValue }
756: readonly type: "session.next.prompt.admitted"
757: readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
758: readonly location?: { readonly directory: string; readonly workspaceID?: string }
759: readonly data: {
760: readonly timestamp: number
761: readonly sessionID: string
762: readonly messageID: string
763: readonly prompt: {
764: readonly text: string
765: readonly files?: ReadonlyArray<{
766: readonly uri: string
767: readonly mime: string
768: readonly name?: string
769: readonly ...
Found 3 matches
/home/byk/Code/opencode/packages/core/src/session/runner/llm.ts:
Line 203: const renewCancellation = () => SessionExecutionClaim.settleCancellation(db, claim)
Line 205: SessionExecutionClaim.settleCancellation(db, claim, { phase: "cancelled", assistant_message_id: null })
Line 436: if (cancelling && publisher.hasAssistantFailed()) yield* settleCancellation()
ab9408c81cc9916177641ae8e9f08624fc27b5b9.0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e.308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4..lore.md, AGENTS.md, and perf.data* changes. I excluded them from the review.Step.Failed can still be followed by duplicate Step.InterruptedfailAssistant records assistantFailed = true only after events.publish(Step.Failed) returns:
packages/core/src/session/runner/publish-llm-event.ts:222-240Durable publication commits before notification completes. The transaction is uninterruptible, but notification occurs afterward and remains interruptible:
packages/core/src/event.ts:237-363packages/core/src/event.ts:378-390packages/core/src/event.ts:406-416Cancellation settlement later trusts only the in-memory flag:
packages/core/src/session/runner/llm.ts:431-443This leaves the following reproducible boundary:
Step.Failed commits durably.assistantFailed = true never executes.hasAssistantFailed() returns false.Step.Interrupted for the assistant that already has durable Step.Failed.The v17 regression checks the ordinary timing but does not control this boundary:
packages/core/test/session-runner.test.ts:3951-3995A ...