agentpane 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,116 @@
1
+ export class EventBroadcaster {
2
+ bufferCapacity;
3
+ subscribers = new Map();
4
+ nextSubId = 0;
5
+ eventCounter = 0;
6
+ // Circular buffer: fixed-size array with head pointer
7
+ ring;
8
+ head = 0; // next write position
9
+ size = 0;
10
+ constructor(bufferCapacity = 1000) {
11
+ this.bufferCapacity = bufferCapacity;
12
+ this.ring = new Array(bufferCapacity);
13
+ }
14
+ get latestEventId() {
15
+ return this.eventCounter;
16
+ }
17
+ subscribe(afterEventId) {
18
+ const subscriberId = `sub-${++this.nextSubId}`;
19
+ let subscriber;
20
+ const stream = new ReadableStream({
21
+ start: (controller) => {
22
+ subscriber = { controller, closed: false };
23
+ // Replay buffered events then register — all synchronous in start(),
24
+ // so no gap between replay and live events (JS single-threaded)
25
+ const start = (this.head - this.size + this.bufferCapacity) % this.bufferCapacity;
26
+ for (let i = 0; i < this.size; i++) {
27
+ const evt = this.ring[(start + i) % this.bufferCapacity];
28
+ if (afterEventId !== undefined && evt.id <= afterEventId)
29
+ continue;
30
+ try {
31
+ controller.enqueue(evt.payload);
32
+ }
33
+ catch {
34
+ subscriber.closed = true;
35
+ return;
36
+ }
37
+ }
38
+ this.subscribers.set(subscriberId, subscriber);
39
+ },
40
+ cancel: () => {
41
+ this.removeSubscriber(subscriberId);
42
+ },
43
+ });
44
+ return { subscriberId, stream, latestEventId: this.eventCounter };
45
+ }
46
+ broadcast(eventData) {
47
+ const id = ++this.eventCounter;
48
+ const payload = `id: ${id}\ndata: ${JSON.stringify(eventData)}\n\n`;
49
+ // Store in circular buffer (O(1))
50
+ this.ring[this.head] = { id, payload };
51
+ this.head = (this.head + 1) % this.bufferCapacity;
52
+ if (this.size < this.bufferCapacity)
53
+ this.size++;
54
+ // Deliver to live subscribers
55
+ const dead = [];
56
+ for (const [subId, sub] of this.subscribers) {
57
+ if (sub.closed) {
58
+ dead.push(subId);
59
+ continue;
60
+ }
61
+ try {
62
+ sub.controller.enqueue(payload);
63
+ }
64
+ catch {
65
+ dead.push(subId);
66
+ }
67
+ }
68
+ for (const subId of dead)
69
+ this.removeSubscriber(subId);
70
+ }
71
+ sendTo(subscriberId, eventData) {
72
+ const sub = this.subscribers.get(subscriberId);
73
+ if (!sub || sub.closed)
74
+ return;
75
+ // sendTo uses id: 0 so it doesn't interfere with replay sequence
76
+ const payload = `id: 0\ndata: ${JSON.stringify(eventData)}\n\n`;
77
+ try {
78
+ sub.controller.enqueue(payload);
79
+ }
80
+ catch {
81
+ this.removeSubscriber(subscriberId);
82
+ }
83
+ }
84
+ unsubscribe(subscriberId) {
85
+ this.removeSubscriber(subscriberId);
86
+ }
87
+ close() {
88
+ for (const sub of this.subscribers.values()) {
89
+ if (!sub.closed) {
90
+ sub.closed = true;
91
+ try {
92
+ sub.controller.close();
93
+ }
94
+ catch { /* already closed */ }
95
+ }
96
+ }
97
+ this.subscribers.clear();
98
+ }
99
+ get subscriberCount() {
100
+ return this.subscribers.size;
101
+ }
102
+ removeSubscriber(subscriberId) {
103
+ const sub = this.subscribers.get(subscriberId);
104
+ if (sub) {
105
+ if (!sub.closed) {
106
+ sub.closed = true;
107
+ try {
108
+ sub.controller.close();
109
+ }
110
+ catch { /* already closed */ }
111
+ }
112
+ this.subscribers.delete(subscriberId);
113
+ }
114
+ }
115
+ }
116
+ //# sourceMappingURL=event-broadcaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-broadcaster.js","sourceRoot":"","sources":["../../src/lib/event-broadcaster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface Provider {
2
+ readonly id: string;
3
+ readonly name: string;
4
+ readonly bin: string;
5
+ }
6
+ export declare const PROVIDERS: Record<string, Provider>;
7
+ export declare const DEFAULT_PROVIDER = "claude-code";
8
+ export declare function resolveProviderBin(agentType: string): string;
@@ -0,0 +1,25 @@
1
+ import path from "node:path";
2
+ export const PROVIDERS = {
3
+ "claude-code": {
4
+ id: "claude-code",
5
+ name: "Claude Code",
6
+ bin: "node_modules/.bin/claude-code-acp",
7
+ },
8
+ codex: {
9
+ id: "codex",
10
+ name: "Codex",
11
+ bin: "node_modules/.bin/codex-acp",
12
+ },
13
+ };
14
+ export const DEFAULT_PROVIDER = "claude-code";
15
+ export function resolveProviderBin(agentType) {
16
+ const provider = PROVIDERS[agentType];
17
+ if (!provider) {
18
+ throw new Error(`Unknown provider: ${agentType}`);
19
+ }
20
+ if (path.isAbsolute(provider.bin)) {
21
+ return provider.bin;
22
+ }
23
+ return path.resolve(process.cwd(), provider.bin);
24
+ }
25
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/lib/providers.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAQ5B,MAAM,CAAC,MAAM,SAAS,GAA6B;IACjD,aAAa,EAAE;QACb,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,mCAAmC;KACzC;IACD,KAAK,EAAE;QACL,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,6BAA6B;KACnC;CACF,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAA;AAE7C,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC,GAAG,CAAA;IACrB,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ManagedRuntime } from "effect";
2
+ import { SessionRepo } from "./session-repo.js";
3
+ import { AcpClient } from "./acp-client.js";
4
+ export declare const AppRuntime: ManagedRuntime.ManagedRuntime<import("@effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | SessionRepo | AcpClient, import("@effect/sql/SqlError").SqlError | import("effect/ConfigError").ConfigError>;
@@ -0,0 +1,7 @@
1
+ import { Layer, ManagedRuntime } from "effect";
2
+ import { SqliteLive } from "./db.js";
3
+ import { SessionRepo } from "./session-repo.js";
4
+ import { AcpClient } from "./acp-client.js";
5
+ const AppLayer = AcpClient.layer.pipe(Layer.provideMerge(SessionRepo.layer), Layer.provideMerge(SqliteLive));
6
+ export const AppRuntime = ManagedRuntime.make(AppLayer);
7
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/lib/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CACnC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,EACrC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAC/B,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,95 @@
1
+ import { Schema } from "effect";
2
+ declare const Session_base: Schema.Class<Session, {
3
+ id: typeof Schema.String;
4
+ name: typeof Schema.String;
5
+ cwd: typeof Schema.String;
6
+ agent_type: typeof Schema.String;
7
+ agent_session_id: Schema.NullOr<typeof Schema.String>;
8
+ created_at: typeof Schema.Number;
9
+ }, Schema.Struct.Encoded<{
10
+ id: typeof Schema.String;
11
+ name: typeof Schema.String;
12
+ cwd: typeof Schema.String;
13
+ agent_type: typeof Schema.String;
14
+ agent_session_id: Schema.NullOr<typeof Schema.String>;
15
+ created_at: typeof Schema.Number;
16
+ }>, never, {
17
+ readonly cwd: string;
18
+ } & {
19
+ readonly name: string;
20
+ } & {
21
+ readonly id: string;
22
+ } & {
23
+ readonly created_at: number;
24
+ } & {
25
+ readonly agent_type: string;
26
+ } & {
27
+ readonly agent_session_id: string | null;
28
+ }, {}, {}>;
29
+ export declare class Session extends Session_base {
30
+ }
31
+ declare const Turn_base: Schema.Class<Turn, {
32
+ id: typeof Schema.String;
33
+ session_id: typeof Schema.String;
34
+ role: Schema.Literal<["user", "assistant"]>;
35
+ stop_reason: Schema.NullOr<typeof Schema.String>;
36
+ created_at: typeof Schema.Number;
37
+ }, Schema.Struct.Encoded<{
38
+ id: typeof Schema.String;
39
+ session_id: typeof Schema.String;
40
+ role: Schema.Literal<["user", "assistant"]>;
41
+ stop_reason: Schema.NullOr<typeof Schema.String>;
42
+ created_at: typeof Schema.Number;
43
+ }>, never, {
44
+ readonly id: string;
45
+ } & {
46
+ readonly session_id: string;
47
+ } & {
48
+ readonly created_at: number;
49
+ } & {
50
+ readonly role: "user" | "assistant";
51
+ } & {
52
+ readonly stop_reason: string | null;
53
+ }, {}, {}>;
54
+ export declare class Turn extends Turn_base {
55
+ }
56
+ declare const MessageBlock_base: Schema.Class<MessageBlock, {
57
+ id: typeof Schema.String;
58
+ turn_id: typeof Schema.String;
59
+ kind: typeof Schema.String;
60
+ content: typeof Schema.String;
61
+ created_at: typeof Schema.Number;
62
+ }, Schema.Struct.Encoded<{
63
+ id: typeof Schema.String;
64
+ turn_id: typeof Schema.String;
65
+ kind: typeof Schema.String;
66
+ content: typeof Schema.String;
67
+ created_at: typeof Schema.Number;
68
+ }>, never, {
69
+ readonly id: string;
70
+ } & {
71
+ readonly created_at: number;
72
+ } & {
73
+ readonly content: string;
74
+ } & {
75
+ readonly turn_id: string;
76
+ } & {
77
+ readonly kind: string;
78
+ }, {}, {}>;
79
+ export declare class MessageBlock extends MessageBlock_base {
80
+ }
81
+ declare const SessionNotFoundError_base: Schema.TaggedErrorClass<SessionNotFoundError, "SessionNotFoundError", {
82
+ readonly _tag: Schema.tag<"SessionNotFoundError">;
83
+ } & {
84
+ id: typeof Schema.String;
85
+ }>;
86
+ export declare class SessionNotFoundError extends SessionNotFoundError_base {
87
+ }
88
+ declare const AcpConnectionError_base: Schema.TaggedErrorClass<AcpConnectionError, "AcpConnectionError", {
89
+ readonly _tag: Schema.tag<"AcpConnectionError">;
90
+ } & {
91
+ message: typeof Schema.String;
92
+ }>;
93
+ export declare class AcpConnectionError extends AcpConnectionError_base {
94
+ }
95
+ export {};
@@ -0,0 +1,35 @@
1
+ import { Schema } from "effect";
2
+ export class Session extends Schema.Class("Session")({
3
+ id: Schema.String,
4
+ name: Schema.String,
5
+ cwd: Schema.String,
6
+ agent_type: Schema.String,
7
+ agent_session_id: Schema.NullOr(Schema.String),
8
+ created_at: Schema.Number,
9
+ }) {
10
+ }
11
+ export class Turn extends Schema.Class("Turn")({
12
+ id: Schema.String,
13
+ session_id: Schema.String,
14
+ role: Schema.Literal("user", "assistant"),
15
+ stop_reason: Schema.NullOr(Schema.String),
16
+ created_at: Schema.Number,
17
+ }) {
18
+ }
19
+ export class MessageBlock extends Schema.Class("MessageBlock")({
20
+ id: Schema.String,
21
+ turn_id: Schema.String,
22
+ kind: Schema.String,
23
+ content: Schema.String,
24
+ created_at: Schema.Number,
25
+ }) {
26
+ }
27
+ export class SessionNotFoundError extends Schema.TaggedError()("SessionNotFoundError", {
28
+ id: Schema.String,
29
+ }) {
30
+ }
31
+ export class AcpConnectionError extends Schema.TaggedError()("AcpConnectionError", {
32
+ message: Schema.String,
33
+ }) {
34
+ }
35
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/lib/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,OAAO,OAAQ,SAAQ,MAAM,CAAC,KAAK,CAAU,SAAS,CAAC,CAAC;IAC5D,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CAAC;CAAG;AAEL,MAAM,OAAO,IAAK,SAAQ,MAAM,CAAC,KAAK,CAAO,MAAM,CAAC,CAAC;IACnD,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CAAC;CAAG;AAEL,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,KAAK,CAAe,cAAc,CAAC,CAAC;IAC3E,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CAAC;CAAG;AAEL,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,EAAwB,CAClF,sBAAsB,EACtB;IACE,EAAE,EAAE,MAAM,CAAC,MAAM;CAClB,CACF;CAAG;AAEJ,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,oBAAoB,EACpB;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG"}
@@ -0,0 +1,24 @@
1
+ import { SqlClient } from "@effect/sql/SqlClient";
2
+ import type { SqlError } from "@effect/sql/SqlError";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { Session, Turn, MessageBlock, SessionNotFoundError } from "./schema.js";
5
+ declare const SessionRepo_base: Context.TagClass<SessionRepo, "@agentpane/SessionRepo", {
6
+ readonly list: () => Effect.Effect<ReadonlyArray<Session>, SqlError>;
7
+ readonly get: (id: string) => Effect.Effect<Session, SqlError | SessionNotFoundError>;
8
+ readonly create: (name?: string, agentType?: string) => Effect.Effect<Session, SqlError>;
9
+ readonly remove: (id: string) => Effect.Effect<void, SqlError>;
10
+ readonly rename: (id: string, name: string) => Effect.Effect<Session, SqlError | SessionNotFoundError>;
11
+ readonly updateCwd: (id: string, cwd: string) => Effect.Effect<void, SqlError>;
12
+ readonly updateConfig: (id: string, agentType: string, cwd: string) => Effect.Effect<Session, SqlError | SessionNotFoundError>;
13
+ readonly updateAgentSessionId: (id: string, agentSessionId: string | null) => Effect.Effect<void, SqlError>;
14
+ readonly addTurn: (sessionId: string, role: "user" | "assistant") => Effect.Effect<Turn, SqlError>;
15
+ readonly completeTurn: (turnId: string, stopReason: string) => Effect.Effect<void, SqlError>;
16
+ readonly addMessageBlock: (turnId: string, kind: string, content: string) => Effect.Effect<MessageBlock, SqlError>;
17
+ readonly getConversation: (sessionId: string) => Effect.Effect<ReadonlyArray<Turn & {
18
+ blocks: ReadonlyArray<MessageBlock>;
19
+ }>, SqlError>;
20
+ }>;
21
+ export declare class SessionRepo extends SessionRepo_base {
22
+ static readonly layer: Layer.Layer<SessionRepo, never, SqlClient>;
23
+ }
24
+ export {};
@@ -0,0 +1,125 @@
1
+ import { SqlClient } from "@effect/sql/SqlClient";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import * as crypto from "node:crypto";
4
+ import { Session, Turn, MessageBlock, SessionNotFoundError } from "./schema.js";
5
+ export class SessionRepo extends Context.Tag("@agentpane/SessionRepo")() {
6
+ static layer = Layer.effect(SessionRepo, Effect.gen(function* () {
7
+ const sql = yield* SqlClient;
8
+ const list = Effect.fn("SessionRepo.list")(function* () {
9
+ return yield* sql `SELECT id, name, cwd, agent_type, agent_session_id, created_at FROM sessions ORDER BY created_at`;
10
+ });
11
+ const get = Effect.fn("SessionRepo.get")(function* (id) {
12
+ const rows = yield* sql `SELECT id, name, cwd, agent_type, agent_session_id, created_at FROM sessions WHERE id = ${id}`;
13
+ if (rows.length === 0) {
14
+ return yield* new SessionNotFoundError({ id });
15
+ }
16
+ return rows[0];
17
+ });
18
+ const create = Effect.fn("SessionRepo.create")(function* (name, agentType) {
19
+ const id = crypto.randomUUID();
20
+ const now = Date.now();
21
+ const counts = yield* sql `SELECT COUNT(*) as cnt FROM sessions`;
22
+ const sessionName = name || `Session ${(counts[0]?.cnt ?? 0) + 1}`;
23
+ const home = process.env.HOME || "~";
24
+ const provider = agentType || "";
25
+ const rows = yield* sql `
26
+ INSERT INTO sessions (id, name, cwd, agent_type, agent_session_id, created_at)
27
+ VALUES (${id}, ${sessionName}, ${home}, ${provider}, ${null}, ${now})
28
+ RETURNING id, name, cwd, agent_type, agent_session_id, created_at
29
+ `;
30
+ return rows[0];
31
+ });
32
+ const remove = Effect.fn("SessionRepo.remove")(function* (id) {
33
+ yield* sql `DELETE FROM sessions WHERE id = ${id}`;
34
+ });
35
+ const rename = Effect.fn("SessionRepo.rename")(function* (id, name) {
36
+ const rows = yield* sql `
37
+ UPDATE sessions SET name = ${name} WHERE id = ${id}
38
+ RETURNING id, name, cwd, agent_type, agent_session_id, created_at
39
+ `;
40
+ if (rows.length === 0) {
41
+ return yield* new SessionNotFoundError({ id });
42
+ }
43
+ return rows[0];
44
+ });
45
+ const updateCwd = Effect.fn("SessionRepo.updateCwd")(function* (id, cwd) {
46
+ yield* sql `UPDATE sessions SET cwd = ${cwd} WHERE id = ${id}`;
47
+ });
48
+ const updateConfig = Effect.fn("SessionRepo.updateConfig")(function* (id, agentType, cwd) {
49
+ const rows = yield* sql `
50
+ UPDATE sessions SET agent_type = ${agentType}, cwd = ${cwd} WHERE id = ${id}
51
+ RETURNING id, name, cwd, agent_type, agent_session_id, created_at
52
+ `;
53
+ if (rows.length === 0) {
54
+ return yield* new SessionNotFoundError({ id });
55
+ }
56
+ return rows[0];
57
+ });
58
+ const updateAgentSessionId = Effect.fn("SessionRepo.updateAgentSessionId")(function* (id, agentSessionId) {
59
+ yield* sql `UPDATE sessions SET agent_session_id = ${agentSessionId} WHERE id = ${id}`;
60
+ });
61
+ const addTurn = Effect.fn("SessionRepo.addTurn")(function* (sessionId, role) {
62
+ const id = crypto.randomUUID();
63
+ const now = Date.now();
64
+ const rows = yield* sql `
65
+ INSERT INTO turns (id, session_id, role, stop_reason, created_at)
66
+ VALUES (${id}, ${sessionId}, ${role}, ${null}, ${now})
67
+ RETURNING id, session_id, role, stop_reason, created_at
68
+ `;
69
+ return rows[0];
70
+ });
71
+ const completeTurn = Effect.fn("SessionRepo.completeTurn")(function* (turnId, stopReason) {
72
+ yield* sql `UPDATE turns SET stop_reason = ${stopReason} WHERE id = ${turnId}`;
73
+ });
74
+ const addMessageBlock = Effect.fn("SessionRepo.addMessageBlock")(function* (turnId, kind, content) {
75
+ const id = crypto.randomUUID();
76
+ const now = Date.now();
77
+ const rows = yield* sql `
78
+ INSERT INTO message_blocks (id, turn_id, kind, content, created_at)
79
+ VALUES (${id}, ${turnId}, ${kind}, ${content}, ${now})
80
+ RETURNING id, turn_id, kind, content, created_at
81
+ `;
82
+ return rows[0];
83
+ });
84
+ const getConversation = Effect.fn("SessionRepo.getConversation")(function* (sessionId) {
85
+ const turns = yield* sql `
86
+ SELECT id, session_id, role, stop_reason, created_at
87
+ FROM turns
88
+ WHERE session_id = ${sessionId}
89
+ ORDER BY created_at, id
90
+ `;
91
+ const blocks = yield* sql `
92
+ SELECT mb.id, mb.turn_id, mb.kind, mb.content, mb.created_at
93
+ FROM message_blocks mb
94
+ JOIN turns t ON t.id = mb.turn_id
95
+ WHERE t.session_id = ${sessionId}
96
+ ORDER BY mb.created_at, mb.id
97
+ `;
98
+ const blocksByTurn = new Map();
99
+ for (const block of blocks) {
100
+ const arr = blocksByTurn.get(block.turn_id) ?? [];
101
+ arr.push(block);
102
+ blocksByTurn.set(block.turn_id, arr);
103
+ }
104
+ return turns.map((turn) => ({
105
+ ...turn,
106
+ blocks: blocksByTurn.get(turn.id) ?? [],
107
+ }));
108
+ });
109
+ return SessionRepo.of({
110
+ list,
111
+ get,
112
+ create,
113
+ remove,
114
+ rename,
115
+ updateCwd,
116
+ updateConfig,
117
+ updateAgentSessionId,
118
+ addTurn,
119
+ completeTurn,
120
+ addMessageBlock,
121
+ getConversation,
122
+ });
123
+ }));
124
+ }
125
+ //# sourceMappingURL=session-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-repo.js","sourceRoot":"","sources":["../../src/lib/session-repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Hono } from "hono";
2
+ export declare const sessionsRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;