@opencode/server 2.0.7 → 2.0.9

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.
Files changed (104) hide show
  1. package/dist/api.d.ts +4 -4
  2. package/dist/api.js +10 -9
  3. package/dist/auth.js +12 -17
  4. package/dist/chunks/fetch-00nn3k4b.js +20 -0
  5. package/dist/chunks/fetch-04xw3v55.js +23 -0
  6. package/dist/chunks/fetch-0d9kah4z.js +23 -0
  7. package/dist/chunks/fetch-19c9ysa1.js +61 -0
  8. package/dist/chunks/fetch-1c4qas2w.js +346 -0
  9. package/dist/chunks/fetch-254zvkj6.js +22 -0
  10. package/dist/chunks/fetch-3kzx88w9.js +26 -0
  11. package/dist/chunks/fetch-4cf3x1kw.js +21 -0
  12. package/dist/chunks/fetch-4g0fa6m0.js +32 -0
  13. package/dist/chunks/fetch-4vn5bvkr.js +25 -0
  14. package/dist/chunks/fetch-5rwqcaw2.js +33 -0
  15. package/dist/chunks/fetch-6gkz39ey.js +55 -0
  16. package/dist/chunks/fetch-6nvan4e0.js +17 -0
  17. package/dist/chunks/fetch-7rzt3wm8.js +13 -0
  18. package/dist/chunks/fetch-8bajbwjh.js +40 -0
  19. package/dist/chunks/fetch-99sfd1j8.js +83 -0
  20. package/dist/chunks/fetch-9rqn6x4v.js +16 -0
  21. package/dist/chunks/fetch-a6yp8301.js +156 -0
  22. package/dist/chunks/fetch-arj41x43.js +77 -0
  23. package/dist/chunks/fetch-b0b71rwa.js +39 -0
  24. package/dist/chunks/fetch-bjrwanme.js +22 -0
  25. package/dist/chunks/fetch-br99j6q1.js +35 -0
  26. package/dist/chunks/fetch-ceh2h0m9.js +25 -0
  27. package/dist/chunks/fetch-csspsf0t.js +99 -0
  28. package/dist/chunks/fetch-d4bshj6j.js +37 -0
  29. package/dist/chunks/fetch-hezj1jdf.js +7 -0
  30. package/dist/chunks/fetch-hjnxtxmk.js +34 -0
  31. package/dist/chunks/fetch-j2pfq4q6.js +42 -0
  32. package/dist/chunks/fetch-m6wvgbfq.js +60 -0
  33. package/dist/chunks/fetch-n0er2m55.js +163 -0
  34. package/dist/chunks/fetch-pnqq1zxv.js +29 -0
  35. package/dist/chunks/fetch-q0ycym90.js +13 -0
  36. package/dist/chunks/fetch-q4bn6dy8.js +39 -0
  37. package/dist/chunks/fetch-qm92ga5h.js +26 -0
  38. package/dist/chunks/fetch-qnwpcgp7.js +22 -0
  39. package/dist/chunks/fetch-r7e9r02j.js +13 -0
  40. package/dist/chunks/fetch-rcg4y18n.js +59 -0
  41. package/dist/chunks/fetch-req22b70.js +22 -0
  42. package/dist/chunks/fetch-s4aja1df.js +36 -0
  43. package/dist/chunks/fetch-smaf4a18.js +28 -0
  44. package/dist/chunks/fetch-t8yzmczr.js +18 -0
  45. package/dist/chunks/fetch-vgpejxxy.js +149 -0
  46. package/dist/chunks/fetch-xsrtpxyd.js +23 -0
  47. package/dist/chunks/fetch-yc7nft6q.js +5 -0
  48. package/dist/chunks/fetch-ychamt23.js +139 -0
  49. package/dist/chunks/fetch-ysabas57.js +13 -0
  50. package/dist/chunks/fetch-z5shrcz9.js +19 -0
  51. package/dist/chunks/fetch-zp2jm6dt.js +15 -0
  52. package/dist/chunks/fetch-zyv89x5n.js +30 -0
  53. package/dist/cors.js +10 -36
  54. package/dist/event-feed.js +20 -60
  55. package/dist/fetch.js +53 -11
  56. package/dist/handlers/agent.js +11 -17
  57. package/dist/handlers/command.js +11 -5
  58. package/dist/handlers/config.js +11 -16
  59. package/dist/handlers/credential.js +11 -14
  60. package/dist/handlers/debug.js +11 -11
  61. package/dist/handlers/event.js +12 -27
  62. package/dist/handlers/form.js +11 -9
  63. package/dist/handlers/fs.js +11 -22
  64. package/dist/handlers/generate.js +11 -15
  65. package/dist/handlers/integration.js +10 -142
  66. package/dist/handlers/location.js +11 -16
  67. package/dist/handlers/mcp.js +11 -31
  68. package/dist/handlers/message.js +10 -42
  69. package/dist/handlers/migration.js +11 -7
  70. package/dist/handlers/model.js +11 -14
  71. package/dist/handlers/permission.js +11 -57
  72. package/dist/handlers/persistent-pty.js +12 -135
  73. package/dist/handlers/plugin.js +11 -47
  74. package/dist/handlers/project.js +11 -9
  75. package/dist/handlers/provider.js +11 -20
  76. package/dist/handlers/pty-socket.js +6 -4
  77. package/dist/handlers/pty.js +13 -107
  78. package/dist/handlers/reference.js +11 -5
  79. package/dist/handlers/rpc.js +11 -15
  80. package/dist/handlers/server.js +12 -13
  81. package/dist/handlers/session-error.js +12 -26
  82. package/dist/handlers/session.js +10 -311
  83. package/dist/handlers/shell.js +11 -25
  84. package/dist/handlers/skill.js +11 -5
  85. package/dist/handlers/vcs.js +11 -19
  86. package/dist/handlers/websearch.js +11 -31
  87. package/dist/handlers/worktree.js +11 -37
  88. package/dist/handlers.d.ts +1 -1
  89. package/dist/handlers.js +46 -33
  90. package/dist/location.js +15 -49
  91. package/dist/middleware/authorization.js +11 -49
  92. package/dist/middleware/form-location.js +10 -25
  93. package/dist/middleware/schema-error.js +8 -15
  94. package/dist/middleware/session-location.js +10 -19
  95. package/dist/options.js +5 -1
  96. package/dist/process.js +108 -28
  97. package/dist/pty-environment.js +12 -9
  98. package/dist/request-tracing.js +6 -2
  99. package/dist/routes.d.ts +2 -2
  100. package/dist/routes.js +52 -118
  101. package/dist/server-info.js +12 -22
  102. package/dist/service-status.js +8 -11
  103. package/dist/workerd.js +80 -12
  104. package/package.json +8 -8
package/dist/api.d.ts CHANGED
@@ -6654,7 +6654,7 @@ export declare const Api: import("@opencode/protocol/api").Api<LocationMiddlewar
6654
6654
  readonly [x: string]: unknown;
6655
6655
  };
6656
6656
  readonly command: string;
6657
- readonly status: "running" | "exited" | "timeout" | "killed";
6657
+ readonly status: "timeout" | "running" | "exited" | "killed";
6658
6658
  readonly time: {
6659
6659
  readonly started: number;
6660
6660
  readonly completed?: number | undefined;
@@ -6679,7 +6679,7 @@ export declare const Api: import("@opencode/protocol/api").Api<LocationMiddlewar
6679
6679
  readonly id: string & import("effect/Brand").Brand<"Event.ID">;
6680
6680
  readonly data: {
6681
6681
  readonly id: string & import("effect/Brand").Brand<"Shell.ID">;
6682
- readonly status: "running" | "exited" | "timeout" | "killed";
6682
+ readonly status: "timeout" | "running" | "exited" | "killed";
6683
6683
  readonly exit?: number | undefined;
6684
6684
  };
6685
6685
  readonly type: "shell.exited";
@@ -7276,7 +7276,7 @@ export declare const Api: import("@opencode/protocol/api").Api<LocationMiddlewar
7276
7276
  readonly [x: string]: unknown;
7277
7277
  };
7278
7278
  readonly command: string;
7279
- readonly status: "running" | "exited" | "timeout" | "killed";
7279
+ readonly status: "timeout" | "running" | "exited" | "killed";
7280
7280
  readonly time: {
7281
7281
  readonly started: number;
7282
7282
  readonly completed?: number | undefined;
@@ -7312,7 +7312,7 @@ export declare const Api: import("@opencode/protocol/api").Api<LocationMiddlewar
7312
7312
  readonly [x: string]: unknown;
7313
7313
  };
7314
7314
  readonly command: string;
7315
- readonly status: "running" | "exited" | "timeout" | "killed";
7315
+ readonly status: "timeout" | "running" | "exited" | "killed";
7316
7316
  readonly time: {
7317
7317
  readonly started: number;
7318
7318
  readonly completed?: number | undefined;
package/dist/api.js CHANGED
@@ -1,9 +1,10 @@
1
- import { makeDefaultApi } from "@opencode/protocol/api";
2
- import { LocationMiddleware } from "./location";
3
- import { FormLocationMiddleware } from "./middleware/form-location";
4
- import { SessionLocationMiddleware } from "./middleware/session-location";
5
- export const Api = makeDefaultApi({
6
- locationMiddleware: LocationMiddleware,
7
- formLocationMiddleware: FormLocationMiddleware,
8
- sessionLocationMiddleware: SessionLocationMiddleware
9
- });
1
+ import {
2
+ Api2
3
+ } from "./chunks/fetch-z5shrcz9.js";
4
+ import"./chunks/fetch-3kzx88w9.js";
5
+ import"./chunks/fetch-5rwqcaw2.js";
6
+ import"./chunks/fetch-6gkz39ey.js";
7
+ import"./chunks/fetch-smaf4a18.js";
8
+ export {
9
+ Api2 as Api
10
+ };
package/dist/auth.js CHANGED
@@ -1,17 +1,12 @@
1
- export * as ServerAuth from "./auth";
2
- import { Context, Layer, Option, Redacted } from "effect";
3
-
4
- export class Config extends Context.Service()("@opencode/ServerAuthConfig") {
5
- static configLayer(input) {
6
- return Layer.succeed(this, this.of({ ...input, username: "opencode" }));
7
- }
8
- static get layer() {
9
- return this.configLayer({ password: Option.none() });
10
- }
11
- }
12
- export function required(config) {
13
- return Option.isSome(config.password) && config.password.value !== "";
14
- }
15
- export function authorized(credentials, config) {
16
- return Option.isSome(config.password) && credentials.username === config.username && Redacted.value(credentials.password) === config.password.value;
17
- }
1
+ import {
2
+ Config2,
3
+ required2,
4
+ authorized2,
5
+ exports_auth
6
+ } from "./chunks/fetch-zyv89x5n.js";
7
+ export {
8
+ Config2 as Config,
9
+ exports_auth as ServerAuth,
10
+ authorized2 as authorized,
11
+ required2 as required
12
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ requestRef2
3
+ } from "./fetch-6gkz39ey.js";
4
+ import {
5
+ Api2
6
+ } from "./fetch-z5shrcz9.js";
7
+
8
+ // src/handlers/debug.ts
9
+ import { LocationServiceMap } from "@opencode/core/location-service-map";
10
+ import { Effect, Option, RcMap } from "effect";
11
+ import { HttpApiBuilder } from "effect/unstable/httpapi";
12
+ var DebugHandler2 = HttpApiBuilder.group(Api2, "server.debug", (handlers) => handlers.handle("debug.location", Effect.fn(function* () {
13
+ const locations = Option.getOrThrow(yield* Effect.serviceOption(LocationServiceMap.Service));
14
+ return Array.from(yield* RcMap.keys(locations.rcMap));
15
+ })).handle("debug.location.evict", Effect.fn(function* (ctx) {
16
+ const locations = Option.getOrThrow(yield* Effect.serviceOption(LocationServiceMap.Service));
17
+ yield* locations.invalidate(requestRef2(ctx.request));
18
+ })));
19
+
20
+ export { DebugHandler2 };
@@ -0,0 +1,23 @@
1
+ import {
2
+ Api2
3
+ } from "./fetch-z5shrcz9.js";
4
+
5
+ // src/handlers/credential.ts
6
+ import { Credential } from "@opencode/core/credential";
7
+ import { Effect } from "effect";
8
+ import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi";
9
+ var CredentialHandler2 = HttpApiBuilder.group(Api2, "server.credential", (handlers) => handlers.handle("credential.update", Effect.fn(function* (ctx) {
10
+ const credential = yield* Credential.Service;
11
+ yield* credential.update(ctx.params.credentialID, { label: ctx.payload.label });
12
+ return HttpApiSchema.NoContent.make();
13
+ })).handle("credential.activate", Effect.fn(function* (ctx) {
14
+ const credential = yield* Credential.Service;
15
+ yield* credential.activate(ctx.params.credentialID);
16
+ return HttpApiSchema.NoContent.make();
17
+ })).handle("credential.remove", Effect.fn(function* (ctx) {
18
+ const credential = yield* Credential.Service;
19
+ yield* credential.remove(ctx.params.credentialID);
20
+ return HttpApiSchema.NoContent.make();
21
+ })));
22
+
23
+ export { CredentialHandler2 };
@@ -0,0 +1,23 @@
1
+ import {
2
+ __export
3
+ } from "./fetch-9rqn6x4v.js";
4
+
5
+ // src/pty-environment.ts
6
+ var exports_pty_environment = {};
7
+ __export(exports_pty_environment, {
8
+ PtyEnvironment: () => exports_pty_environment,
9
+ Service: () => Service3,
10
+ layer: () => layer3,
11
+ node: () => node2
12
+ });
13
+ import { Context, Effect, Layer } from "effect";
14
+ import { makeGlobalNode } from "@opencode/util/effect/app-node";
15
+
16
+ class Service3 extends Context.Service()("@opencode/ServerPtyEnvironment") {
17
+ }
18
+ var layer3 = Layer.succeed(Service3, Service3.of({
19
+ get: () => Effect.succeed({})
20
+ }));
21
+ var node2 = makeGlobalNode({ service: Service3, layer: layer3, deps: [] });
22
+
23
+ export { Service3, layer3, node2, exports_pty_environment };
@@ -0,0 +1,61 @@
1
+ import {
2
+ response2
3
+ } from "./fetch-6gkz39ey.js";
4
+ import {
5
+ Api2
6
+ } from "./fetch-z5shrcz9.js";
7
+
8
+ // src/handlers/plugin.ts
9
+ import { Plugin } from "@opencode/core/plugin";
10
+ import { PluginUpdate } from "@opencode/core/plugin/update";
11
+ import { InvalidRequestError, ServiceUnavailableError } from "@opencode/protocol/errors";
12
+ import { Cause, Effect, Exit } from "effect";
13
+ import { HttpApiBuilder } from "effect/unstable/httpapi";
14
+ var PluginHandler2 = HttpApiBuilder.group(Api2, "server.plugin", (handlers) => handlers.handle("plugin.list", () => Effect.gen(function* () {
15
+ return yield* response2(Plugin.Service.use((plugin) => plugin.list()));
16
+ })).handle("plugin.check", (ctx) => Effect.gen(function* () {
17
+ const plugins = yield* Plugin.Service;
18
+ const inventory = yield* plugins.list();
19
+ const targets = [
20
+ ...new Set(inventory.flatMap((plugin) => plugin.source.type === "package" ? [plugin.source.target] : []))
21
+ ].filter((target) => ctx.payload.target === undefined || target === ctx.payload.target);
22
+ if (ctx.payload.target !== undefined && !targets.length)
23
+ return yield* new InvalidRequestError({
24
+ message: `Plugin package is not in the current server inventory: ${ctx.payload.target}`,
25
+ field: "target"
26
+ });
27
+ const updates = yield* PluginUpdate.Service;
28
+ const outdated = new Map(yield* Effect.forEach(targets, (target) => updates.check(target, { refresh: true }).pipe(Effect.map((value) => [target, value])), { concurrency: "unbounded" }));
29
+ return yield* response2(Effect.succeed(inventory.map((plugin) => {
30
+ if (plugin.source.type !== "package" || !outdated.has(plugin.source.target))
31
+ return plugin;
32
+ return {
33
+ ...plugin,
34
+ source: {
35
+ type: "package",
36
+ target: plugin.source.target,
37
+ ...plugin.source.version ? { version: plugin.source.version } : {},
38
+ ...outdated.get(plugin.source.target) ? { outdated: true } : {},
39
+ ...plugin.source.updating ? { updating: true } : {}
40
+ }
41
+ };
42
+ })));
43
+ })).handle("plugin.update", (ctx) => Effect.gen(function* () {
44
+ const plugins = yield* Plugin.Service;
45
+ const inventory = new Set((yield* plugins.list()).flatMap((plugin) => plugin.source.type === "package" ? [plugin.source.target] : []));
46
+ const unknown = ctx.payload.targets.filter((target) => !inventory.has(target));
47
+ if (unknown.length)
48
+ return yield* new InvalidRequestError({
49
+ message: `Plugin packages are not in the current server inventory: ${unknown.join(", ")}`,
50
+ field: "targets"
51
+ });
52
+ const updates = yield* PluginUpdate.Service;
53
+ const failures = yield* Effect.forEach(ctx.payload.targets, (target) => updates.update(target).pipe(Effect.exit, Effect.map((exit) => Exit.isFailure(exit) ? [`${target}: ${Cause.pretty(exit.cause)}`] : [])), { concurrency: "unbounded" }).pipe(Effect.map((results) => results.flat()));
54
+ if (failures.length)
55
+ return yield* new ServiceUnavailableError({
56
+ message: `Failed to update plugin packages: ${failures.join("; ")}`,
57
+ service: "plugin"
58
+ });
59
+ })));
60
+
61
+ export { PluginHandler2 };
@@ -0,0 +1,346 @@
1
+ import {
2
+ missingSession2,
3
+ missingMessage2,
4
+ failedMessageDecode2,
5
+ failedSnapshot2
6
+ } from "./fetch-smaf4a18.js";
7
+ import {
8
+ Api2
9
+ } from "./fetch-z5shrcz9.js";
10
+
11
+ // src/handlers/session.ts
12
+ import { Session } from "@opencode/core/session";
13
+ import { SessionStats } from "@opencode/core/session/stats";
14
+ import { SessionTitle } from "@opencode/core/session/title";
15
+ import { SessionTransfer } from "@opencode/core/session/transfer";
16
+ import { InstructionEntry } from "@opencode/core/session/instruction-entry";
17
+ import { Form } from "@opencode/core/form";
18
+ import { DateTime, Effect, Stream } from "effect";
19
+ import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi";
20
+ import { SessionsCursor } from "@opencode/protocol/groups/session";
21
+ import {
22
+ ConflictError,
23
+ CommandExecutionError,
24
+ CommandNotFoundError,
25
+ FormAlreadySettledError,
26
+ FormInvalidAnswerError,
27
+ FormNotFoundError,
28
+ InvalidRequestError,
29
+ InvalidCursorError,
30
+ MessageNotFoundError,
31
+ ServiceUnavailableError,
32
+ SessionBusyError,
33
+ SkillNotFoundError
34
+ } from "@opencode/protocol/errors";
35
+ import { AbsolutePath } from "@opencode/core/schema";
36
+ var DefaultSessionsLimit = 50;
37
+ function missingForm(id) {
38
+ return new FormNotFoundError({ id, message: `Form not found: ${id}` });
39
+ }
40
+ var SessionHandler2 = HttpApiBuilder.group(Api2, "server.session", (handlers) => Effect.gen(function* () {
41
+ const session = yield* Session.Service;
42
+ const transfer = yield* SessionTransfer.Service;
43
+ const requireOwnedForm = Effect.fnUntraced(function* (sessionID, formID) {
44
+ const form = yield* Form.Service;
45
+ const info = yield* form.get(formID).pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(formID)));
46
+ if (info.sessionID !== sessionID)
47
+ return yield* missingForm(formID);
48
+ return { form, info };
49
+ });
50
+ const busySession = (error) => new SessionBusyError({
51
+ sessionID: error.sessionID,
52
+ message: `Session is busy: ${error.sessionID}`
53
+ });
54
+ const pendingMutation = (effect, conflict) => effect.pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.InboxConflictError", (error) => new ConflictError({ resource: error.inboxID, message: `${conflict}: ${error.inboxID}` })), Effect.as(HttpApiSchema.NoContent.make()));
55
+ return handlers.handle("session.list", Effect.fn(function* (ctx) {
56
+ const query = ctx.query.cursor !== undefined ? yield* SessionsCursor.parse(ctx.query.cursor).pipe(Effect.mapError(() => new InvalidCursorError({ message: "Invalid cursor" }))) : ctx.query;
57
+ const page = yield* session.list({
58
+ ...query,
59
+ limit: ctx.query.limit ?? DefaultSessionsLimit
60
+ });
61
+ const sessions = page.data;
62
+ const first = sessions[0];
63
+ const last = sessions.at(-1);
64
+ return {
65
+ data: sessions,
66
+ cursor: {
67
+ previous: first ? SessionsCursor.make({
68
+ ...query,
69
+ anchor: {
70
+ id: first.id,
71
+ time: DateTime.toEpochMillis(first.time.updated),
72
+ direction: "previous"
73
+ }
74
+ }) : undefined,
75
+ next: last ? SessionsCursor.make({
76
+ ...query,
77
+ anchor: {
78
+ id: last.id,
79
+ time: DateTime.toEpochMillis(last.time.updated),
80
+ direction: "next"
81
+ }
82
+ }) : undefined
83
+ }
84
+ };
85
+ })).handle("session.stats", Effect.fn(function* (ctx) {
86
+ const timezone = ctx.query.timezone ?? "UTC";
87
+ yield* Effect.try({
88
+ try: () => new Intl.DateTimeFormat("en-US", { timeZone: timezone }),
89
+ catch: () => new InvalidRequestError({ message: `Invalid time zone: ${timezone}` })
90
+ });
91
+ return {
92
+ data: yield* SessionStats.get({
93
+ from: ctx.query.from,
94
+ to: ctx.query.to,
95
+ projectID: ctx.query.project,
96
+ timezone,
97
+ tools: ctx.query.tools
98
+ }).pipe(Effect.mapError(() => new InvalidRequestError({ message: "Stats range must end after it starts" })))
99
+ };
100
+ })).handle("session.create", Effect.fn(function* (ctx) {
101
+ return {
102
+ data: yield* session.create({
103
+ id: ctx.payload.id,
104
+ title: ctx.payload.title,
105
+ agent: ctx.payload.agent,
106
+ model: ctx.payload.model,
107
+ metadata: ctx.payload.metadata,
108
+ permissions: ctx.payload.permissions,
109
+ location: ctx.payload.location ?? { directory: AbsolutePath.make(process.cwd()) }
110
+ }).pipe(Effect.orDie)
111
+ };
112
+ })).handle("session.import", Effect.fn(function* (ctx) {
113
+ return {
114
+ data: yield* transfer.import({
115
+ data: { info: ctx.payload.info, messages: ctx.payload.messages },
116
+ location: ctx.payload.location ?? { directory: AbsolutePath.make(process.cwd()) }
117
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("SessionTransfer.ImportConflictError", (error) => new ConflictError({
118
+ message: `Session already exists: ${error.sessionID}`,
119
+ resource: error.sessionID
120
+ })))
121
+ };
122
+ })).handle("session.export", Effect.fn(function* (ctx) {
123
+ return {
124
+ data: yield* transfer.export({ sessionID: ctx.params.sessionID, sanitize: ctx.query.sanitize }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.MessageDecodeError", failedMessageDecode2))
125
+ };
126
+ })).handle("session.active", Effect.fn(function* () {
127
+ const active = yield* session.active;
128
+ return {
129
+ data: Object.fromEntries(Array.from(active, (sessionID) => [sessionID, { type: "running" }]))
130
+ };
131
+ })).handle("session.get", Effect.fn(function* (ctx) {
132
+ return {
133
+ data: yield* session.get(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2))
134
+ };
135
+ })).handle("session.view", Effect.fn(function* (ctx) {
136
+ yield* session.view({ sessionID: ctx.params.sessionID, idle: DateTime.toEpochMillis(ctx.payload.idle) }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
137
+ return HttpApiSchema.NoContent.make();
138
+ })).handle("session.remove", Effect.fn(function* (ctx) {
139
+ yield* session.remove(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
140
+ return HttpApiSchema.NoContent.make();
141
+ })).handle("session.environment", Effect.fn(function* (ctx) {
142
+ yield* session.environment({ sessionID: ctx.params.sessionID, variables: ctx.payload.variables }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
143
+ return HttpApiSchema.NoContent.make();
144
+ })).handle("session.fork", Effect.fn(function* (ctx) {
145
+ return {
146
+ data: yield* session.fork({ sessionID: ctx.params.sessionID, before: ctx.payload.before }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.MessageNotFoundError", missingMessage2), Effect.catchTag("Session.ForkEmptyError", (error) => new InvalidRequestError({ message: error.message, kind: "empty_session" })))
147
+ };
148
+ })).handle("session.switchAgent", Effect.fn(function* (ctx) {
149
+ yield* session.switchAgent({ sessionID: ctx.params.sessionID, agent: ctx.payload.agent }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
150
+ return HttpApiSchema.NoContent.make();
151
+ })).handle("session.switchModel", Effect.fn(function* (ctx) {
152
+ yield* session.switchModel({ sessionID: ctx.params.sessionID, model: ctx.payload.model }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
153
+ return HttpApiSchema.NoContent.make();
154
+ })).handle("session.update", Effect.fn(function* (ctx) {
155
+ yield* session.get(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
156
+ if (ctx.payload.title !== undefined) {
157
+ if (ctx.payload.title) {
158
+ yield* session.rename({ sessionID: ctx.params.sessionID, title: ctx.payload.title }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
159
+ } else {
160
+ const title = yield* SessionTitle.Service;
161
+ yield* title.generate(ctx.params.sessionID);
162
+ }
163
+ }
164
+ if (ctx.payload.permissions !== undefined)
165
+ yield* session.setPermissions({ sessionID: ctx.params.sessionID, permissions: ctx.payload.permissions }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
166
+ return HttpApiSchema.NoContent.make();
167
+ })).handle("session.move", Effect.fn(function* (ctx) {
168
+ yield* session.move({
169
+ sessionID: ctx.params.sessionID,
170
+ directory: ctx.payload.directory,
171
+ delivery: ctx.payload.delivery
172
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.DestinationNotFoundError", (error) => Effect.fail(new InvalidRequestError({ message: `Directory does not exist: ${error.directory}` }))), Effect.catchTag("Session.DestinationNotDirectoryError", (error) => Effect.fail(new InvalidRequestError({ message: `Not a directory: ${error.directory}` }))), Effect.catchTag("Session.DestinationUnavailableError", (error) => Effect.fail(new InvalidRequestError({ message: `Directory is unavailable: ${error.directory}` }))));
173
+ return HttpApiSchema.NoContent.make();
174
+ })).handle("session.prompt", Effect.fn(function* (ctx) {
175
+ return {
176
+ data: yield* session.prompt({
177
+ sessionID: ctx.params.sessionID,
178
+ id: ctx.payload.id,
179
+ text: ctx.payload.text,
180
+ files: ctx.payload.files,
181
+ agents: ctx.payload.agents,
182
+ skills: ctx.payload.skills,
183
+ metadata: ctx.payload.metadata,
184
+ delivery: ctx.payload.delivery,
185
+ resume: ctx.payload.resume
186
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.PromptConflictError", (error) => Effect.fail(new ConflictError({
187
+ message: `Prompt message ID conflicts with an existing durable record: ${error.messageID}`,
188
+ resource: error.messageID
189
+ }))), Effect.catchTag("Session.AttachmentError", (error) => Effect.fail(new InvalidRequestError({ message: error.message, field: "files" }))), Effect.catchTag("Session.SkillNotFoundError", (error) => Effect.fail(new InvalidRequestError({ message: `Skill not found: ${error.skill}`, field: "skills" }))))
190
+ };
191
+ })).handle("session.command", Effect.fn(function* (ctx) {
192
+ yield* session.command({
193
+ sessionID: ctx.params.sessionID,
194
+ command: ctx.payload.name,
195
+ text: ctx.payload.text,
196
+ files: ctx.payload.files,
197
+ agents: ctx.payload.agents,
198
+ skills: ctx.payload.skills,
199
+ delivery: ctx.payload.delivery
200
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Command.NotFoundError", (error) => Effect.fail(new CommandNotFoundError({
201
+ command: error.command,
202
+ message: error.message
203
+ }))), Effect.catchTag("Command.ExecutionError", (error) => Effect.fail(new CommandExecutionError({
204
+ command: error.command,
205
+ message: error.message
206
+ }))));
207
+ return HttpApiSchema.NoContent.make();
208
+ })).handle("session.skill", Effect.fn(function* (ctx) {
209
+ yield* session.skill({
210
+ sessionID: ctx.params.sessionID,
211
+ skill: ctx.payload.id,
212
+ resume: ctx.payload.resume
213
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.SkillNotFoundError", (error) => Effect.fail(new SkillNotFoundError({ skill: error.skill, message: `Skill not found: ${error.skill}` }))));
214
+ return HttpApiSchema.NoContent.make();
215
+ })).handle("session.synthetic", Effect.fn(function* (ctx) {
216
+ const data = yield* session.synthetic({
217
+ id: ctx.payload.id,
218
+ sessionID: ctx.params.sessionID,
219
+ text: ctx.payload.text,
220
+ description: ctx.payload.description,
221
+ metadata: ctx.payload.metadata,
222
+ delivery: ctx.payload.delivery,
223
+ resume: ctx.payload.resume
224
+ }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.SyntheticConflictError", (error) => Effect.fail(new ConflictError({
225
+ message: `Synthetic input ID conflicts with an existing durable record: ${error.inputID}`,
226
+ resource: error.inputID
227
+ }))));
228
+ return { data };
229
+ })).handle("session.shell", Effect.fn(function* (ctx) {
230
+ yield* session.shell({ sessionID: ctx.params.sessionID, id: ctx.payload.id, command: ctx.payload.command }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
231
+ return HttpApiSchema.NoContent.make();
232
+ })).handle("session.compact", Effect.fn(function* (ctx) {
233
+ return {
234
+ data: yield* session.compact({ sessionID: ctx.params.sessionID, id: ctx.payload.id, delivery: ctx.payload.delivery }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.CompactionConflictError", (error) => Effect.fail(new ConflictError({
235
+ message: `Compaction input ID conflicts with an existing durable record: ${error.inputID}`,
236
+ resource: error.inputID
237
+ }))))
238
+ };
239
+ })).handle("session.wait", Effect.fn(function* (ctx) {
240
+ yield* session.wait(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
241
+ return HttpApiSchema.NoContent.make();
242
+ })).handle("session.revert.stage", Effect.fn(function* (ctx) {
243
+ yield* Effect.log("session.revert.stage", {
244
+ sessionID: ctx.params.sessionID,
245
+ messageID: ctx.payload.messageID,
246
+ files: ctx.payload.files
247
+ });
248
+ return {
249
+ data: yield* session.revert.stage({ ...ctx.params, ...ctx.payload }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.MessageNotFoundError", missingMessage2), Effect.catchTag("Session.BusyError", busySession), Effect.catchTag("Snapshot.Error", failedSnapshot2("stage session revert", ctx.params.sessionID)))
250
+ };
251
+ })).handle("session.revert.clear", Effect.fn(function* (ctx) {
252
+ yield* Effect.log("session.revert.clear", { sessionID: ctx.params.sessionID });
253
+ yield* session.revert.clear(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.BusyError", busySession), Effect.catchTag("Snapshot.Error", failedSnapshot2("clear session revert", ctx.params.sessionID)));
254
+ return HttpApiSchema.NoContent.make();
255
+ })).handle("session.revert.commit", Effect.fn(function* (ctx) {
256
+ yield* Effect.log("session.revert.commit", { sessionID: ctx.params.sessionID });
257
+ yield* session.revert.commit(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.BusyError", busySession));
258
+ return HttpApiSchema.NoContent.make();
259
+ })).handle("session.context", Effect.fn(function* (ctx) {
260
+ return {
261
+ data: yield* session.context(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.MessageDecodeError", failedMessageDecode2))
262
+ };
263
+ })).handle("session.diff", Effect.fn(function* (ctx) {
264
+ return {
265
+ data: yield* session.diff({ sessionID: ctx.params.sessionID, ...ctx.query }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.MessageNotFoundError", missingMessage2), Effect.catchTag("Session.TurnRangeError", (error) => new InvalidRequestError({ message: error.message, field: error.field })), Effect.catchTag("Snapshot.Error", failedSnapshot2("diff session turn", ctx.params.sessionID)))
266
+ };
267
+ })).handle("session.inbox.list", Effect.fn(function* (ctx) {
268
+ return {
269
+ data: yield* session.inbox(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2))
270
+ };
271
+ })).handle("session.inbox.cancel", Effect.fn(function* (ctx) {
272
+ yield* session.cancelInbox({ sessionID: ctx.params.sessionID, inboxID: ctx.params.inboxID }).pipe(Effect.catchTag("Session.NotFoundError", missingSession2), Effect.catchTag("Session.InboxConflictError", () => Effect.void));
273
+ return HttpApiSchema.NoContent.make();
274
+ })).handle("session.inbox.update", Effect.fn(function* (ctx) {
275
+ return yield* pendingMutation(ctx.payload.delivery === "steer" ? session.steerInbox({ sessionID: ctx.params.sessionID, inboxID: ctx.params.inboxID }) : session.queueInbox({ sessionID: ctx.params.sessionID, inboxID: ctx.params.inboxID }), `Pending input cannot change to ${ctx.payload.delivery}`);
276
+ })).handle("session.instructions.entry.list", Effect.fn(function* (ctx) {
277
+ const instructions = yield* InstructionEntry.Service;
278
+ return { data: yield* instructions.list(ctx.params.sessionID) };
279
+ })).handle("session.instructions.entry.put", Effect.fn(function* (ctx) {
280
+ const instructions = yield* InstructionEntry.Service;
281
+ yield* instructions.put({ sessionID: ctx.params.sessionID, key: ctx.params.key, value: ctx.payload.value });
282
+ return HttpApiSchema.NoContent.make();
283
+ })).handle("session.instructions.entry.remove", Effect.fn(function* (ctx) {
284
+ const instructions = yield* InstructionEntry.Service;
285
+ yield* instructions.remove({ sessionID: ctx.params.sessionID, key: ctx.params.key });
286
+ return HttpApiSchema.NoContent.make();
287
+ })).handle("session.generate", Effect.fn(function* (ctx) {
288
+ const text = yield* session.generate({ sessionID: ctx.params.sessionID, prompt: ctx.payload.prompt }).pipe(Effect.mapError((error) => error._tag === "Session.NotFoundError" ? missingSession2(error) : new ServiceUnavailableError({ message: error.message, service: "session generation" })));
289
+ return { data: { text } };
290
+ })).handle("session.log", Effect.fn(function* (ctx) {
291
+ yield* session.get(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
292
+ return session.log({ sessionID: ctx.params.sessionID, after: ctx.query.after, follow: ctx.query.follow }).pipe(Stream.orDie);
293
+ })).handle("session.interrupt", Effect.fn(function* (ctx) {
294
+ return { interrupted: yield* session.interrupt(ctx.params.sessionID, { resume: ctx.query.resume }) };
295
+ })).handle("session.background", Effect.fn(function* (ctx) {
296
+ yield* session.background(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
297
+ return HttpApiSchema.NoContent.make();
298
+ })).handle("session.message", Effect.fn(function* (ctx) {
299
+ yield* session.get(ctx.params.sessionID).pipe(Effect.catchTag("Session.NotFoundError", missingSession2));
300
+ const message = yield* session.message(ctx.params);
301
+ if (message)
302
+ return { data: message };
303
+ return yield* new MessageNotFoundError({
304
+ sessionID: ctx.params.sessionID,
305
+ messageID: ctx.params.messageID,
306
+ message: `Message not found: ${ctx.params.messageID}`
307
+ });
308
+ })).handle("session.form.list", Effect.fn(function* (ctx) {
309
+ const form = yield* Form.Service;
310
+ return { data: yield* form.list({ sessionID: ctx.params.sessionID }) };
311
+ })).handle("session.form.create", Effect.fn(function* (ctx) {
312
+ const form = yield* Form.Service;
313
+ const created = yield* form.create({
314
+ id: ctx.payload.id,
315
+ sessionID: ctx.params.sessionID,
316
+ title: ctx.payload.title,
317
+ metadata: ctx.payload.metadata,
318
+ fields: ctx.payload.fields
319
+ }).pipe(Effect.catchTags({
320
+ "Form.AlreadyExistsError": (error) => new ConflictError({ resource: error.id, message: error.message }),
321
+ "Form.InvalidFormError": (error) => new InvalidRequestError({ message: error.message, field: "fields" })
322
+ }));
323
+ return { data: created };
324
+ })).handle("session.form.get", Effect.fn(function* (ctx) {
325
+ const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID);
326
+ const state = yield* owned.form.state(ctx.params.formID).pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(ctx.params.formID)));
327
+ return { data: { ...owned.info, state } };
328
+ })).handle("session.form.reply", Effect.fn(function* (ctx) {
329
+ const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID);
330
+ yield* owned.form.reply({ id: ctx.params.formID, answer: ctx.payload.answer }).pipe(Effect.catchTags({
331
+ "Form.AlreadySettledError": (error) => new FormAlreadySettledError({ id: error.id, message: error.message }),
332
+ "Form.InvalidAnswerError": (error) => new FormInvalidAnswerError({ id: error.id, message: error.message }),
333
+ "Form.NotFoundError": () => missingForm(ctx.params.formID)
334
+ }));
335
+ return HttpApiSchema.NoContent.make();
336
+ })).handle("session.form.cancel", Effect.fn(function* (ctx) {
337
+ const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID);
338
+ yield* owned.form.cancel(ctx.params.formID).pipe(Effect.catchTags({
339
+ "Form.AlreadySettledError": (error) => new FormAlreadySettledError({ id: error.id, message: error.message }),
340
+ "Form.NotFoundError": () => missingForm(ctx.params.formID)
341
+ }));
342
+ return HttpApiSchema.NoContent.make();
343
+ }));
344
+ }));
345
+
346
+ export { SessionHandler2 };
@@ -0,0 +1,22 @@
1
+ import {
2
+ response2
3
+ } from "./fetch-6gkz39ey.js";
4
+ import {
5
+ Api2
6
+ } from "./fetch-z5shrcz9.js";
7
+
8
+ // src/handlers/model.ts
9
+ import { Model } from "@opencode/core/model";
10
+ import { Effect } from "effect";
11
+ import { HttpApiBuilder } from "effect/unstable/httpapi";
12
+ var ModelHandler2 = HttpApiBuilder.group(Api2, "server.model", (handlers) => Effect.gen(function* () {
13
+ return handlers.handle("model.list", Effect.fn(function* () {
14
+ const models = yield* Model.Service;
15
+ return yield* response2(models.available());
16
+ })).handle("model.default", Effect.fn(function* () {
17
+ const models = yield* Model.Service;
18
+ return yield* response2(models.default());
19
+ }));
20
+ }));
21
+
22
+ export { ModelHandler2 };
@@ -0,0 +1,26 @@
1
+ import {
2
+ sessionInfo2
3
+ } from "./fetch-6gkz39ey.js";
4
+
5
+ // src/middleware/session-location.ts
6
+ import { Instance } from "@opencode/core/instance/service";
7
+ import { Session } from "@opencode/core/session";
8
+ import { Effect, Layer } from "effect";
9
+ import { HttpRouter } from "effect/unstable/http";
10
+ import { HttpApiMiddleware } from "effect/unstable/httpapi";
11
+ import { InvalidRequestError, SessionNotFoundError } from "@opencode/protocol/errors";
12
+ class SessionLocationMiddleware2 extends HttpApiMiddleware.Service()("@opencode/HttpApiSessionLocation", {
13
+ error: [InvalidRequestError, SessionNotFoundError]
14
+ }) {
15
+ }
16
+ var sessionLocationLayer2 = Layer.effect(SessionLocationMiddleware2, Effect.gen(function* () {
17
+ const sessions = yield* Session.Service;
18
+ const instances = yield* Instance.Service;
19
+ return SessionLocationMiddleware2.of((effect) => Effect.gen(function* () {
20
+ const route = yield* HttpRouter.RouteContext;
21
+ const session = yield* sessionInfo2(sessions, route.params.sessionID);
22
+ return yield* effect.pipe(instances.provide(session));
23
+ }));
24
+ }));
25
+
26
+ export { SessionLocationMiddleware2, sessionLocationLayer2 };
@@ -0,0 +1,21 @@
1
+ import {
2
+ Api2
3
+ } from "./fetch-z5shrcz9.js";
4
+ import {
5
+ Service2
6
+ } from "./fetch-s4aja1df.js";
7
+
8
+ // src/handlers/server.ts
9
+ import { Effect } from "effect";
10
+ import { HttpApiBuilder } from "effect/unstable/httpapi";
11
+ var ServerHandler2 = HttpApiBuilder.group(Api2, "server.server", (handlers) => handlers.handle("server.info", () => Effect.gen(function* () {
12
+ const info = yield* Service2;
13
+ return {
14
+ version: info.app.version ?? "unknown",
15
+ pid: process.pid ?? 0,
16
+ urls: info.urls(),
17
+ paths: info.paths
18
+ };
19
+ })));
20
+
21
+ export { ServerHandler2 };