alchemylab-opencode 1.0.19 → 1.0.21

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 (101) hide show
  1. package/dist/{log-TOR3B2F5.js → arktype-aI7TBD0R-ETU7X65Q.js} +1 -8
  2. package/dist/chunk-5MPKKAWG.js +2215 -0
  3. package/dist/chunk-7KKA6WBY.js +12 -0
  4. package/dist/chunk-A4S3BYGY.js +12 -0
  5. package/dist/chunk-ABCQLKMJ.js +12 -0
  6. package/dist/chunk-BGADAZN4.js +0 -1
  7. package/dist/chunk-CMU5MV6S.js +75 -0
  8. package/dist/chunk-DBKYWUEM.js +18 -0
  9. package/dist/{mcp-W2Z3DXFD.js → chunk-LTCXIXYM.js} +1 -12
  10. package/dist/chunk-M4CB72HE.js +13 -0
  11. package/dist/chunk-MBZTOEAD.js +12 -0
  12. package/dist/chunk-N2IDMOID.js +18 -0
  13. package/dist/chunk-N7PLTD3P.js +13 -0
  14. package/dist/chunk-T6MY2WE4.js +12 -0
  15. package/dist/{chunk-H5AN6PD4.js → chunk-T7EXROHP.js} +1 -19
  16. package/dist/{schema-EWYI6LGA.js → chunk-XREX5MYM.js} +1 -13
  17. package/dist/{run-service-B4BDQWO3.js → default-u_dwuiYb-5QQ4GXMV.js} +1 -12
  18. package/dist/effect-QlVUlMFu-ORZ7TVO5.js +12 -0
  19. package/dist/log-MVJ7H4K5.js +12 -0
  20. package/dist/mcp-BCTN55WE.js +12 -0
  21. package/dist/{default-u_dwuiYb-644FBWJS.js → pty.node-X2EITEZ4.js} +1 -11
  22. package/dist/registry-MRPMZCK4.js +12 -0
  23. package/dist/run-O75PTUSN.js +20 -0
  24. package/dist/run-service-IUIOP7ZW.js +12 -0
  25. package/dist/run.js +1 -11
  26. package/dist/schema-YWIVP7UR.js +12 -0
  27. package/dist/serve.js +1 -40
  28. package/dist/server-QXCNOJQJ.js +12 -0
  29. package/dist/session-OLERO43H.js +12 -0
  30. package/dist/share-next-7PZI7GKT.js +12 -0
  31. package/dist/sury-CWZTCd75-IXNCX752.js +12 -0
  32. package/dist/typebox-Dei93FPO-K67WT2FO.js +12 -0
  33. package/dist/valibot--1zFm7rT-SSCP4J5I.js +12 -0
  34. package/dist/valibot-D_HTw1Gn-KPCJMJMC.js +12 -0
  35. package/dist/worktree-43SDNYPU.js +12 -0
  36. package/dist/{arktype-aI7TBD0R-LH6JTJZZ.js → zod-Bwrt9trS-BYLM45IZ.js} +1 -10
  37. package/dist/{chunk-BI5OUHTQ.js → zod-DSgpEGAE-T3VJY2W3.js} +1 -20
  38. package/package.json +2 -2
  39. package/dist/arktype-aI7TBD0R-LH6JTJZZ.js.map +0 -7
  40. package/dist/chunk-2FM4SJ4F.js +0 -506
  41. package/dist/chunk-2FM4SJ4F.js.map +0 -7
  42. package/dist/chunk-4UCKACGO.js +0 -106
  43. package/dist/chunk-4UCKACGO.js.map +0 -7
  44. package/dist/chunk-AHJSL352.js +0 -160
  45. package/dist/chunk-AHJSL352.js.map +0 -7
  46. package/dist/chunk-ASJTXZ3G.js +0 -730
  47. package/dist/chunk-ASJTXZ3G.js.map +0 -7
  48. package/dist/chunk-BGADAZN4.js.map +0 -7
  49. package/dist/chunk-BI5OUHTQ.js.map +0 -7
  50. package/dist/chunk-COCF34ZS.js +0 -144
  51. package/dist/chunk-COCF34ZS.js.map +0 -7
  52. package/dist/chunk-E2D2QSW7.js +0 -6675
  53. package/dist/chunk-E2D2QSW7.js.map +0 -7
  54. package/dist/chunk-FXA7YNMN.js +0 -49
  55. package/dist/chunk-FXA7YNMN.js.map +0 -7
  56. package/dist/chunk-H5AN6PD4.js.map +0 -7
  57. package/dist/chunk-HORZKFCR.js +0 -88
  58. package/dist/chunk-HORZKFCR.js.map +0 -7
  59. package/dist/chunk-PV6JYN6T.js +0 -24205
  60. package/dist/chunk-PV6JYN6T.js.map +0 -7
  61. package/dist/chunk-RYVKLRJZ.js +0 -321
  62. package/dist/chunk-RYVKLRJZ.js.map +0 -7
  63. package/dist/chunk-SZM3G6UF.js +0 -1857
  64. package/dist/chunk-SZM3G6UF.js.map +0 -7
  65. package/dist/chunk-WHJ5FGUS.js +0 -5706
  66. package/dist/chunk-WHJ5FGUS.js.map +0 -7
  67. package/dist/default-u_dwuiYb-644FBWJS.js.map +0 -7
  68. package/dist/effect-QlVUlMFu-GLKKNZAC.js +0 -29
  69. package/dist/effect-QlVUlMFu-GLKKNZAC.js.map +0 -7
  70. package/dist/log-TOR3B2F5.js.map +0 -7
  71. package/dist/mcp-W2Z3DXFD.js.map +0 -7
  72. package/dist/pty.node-RHOAUGH6.js +0 -40
  73. package/dist/pty.node-RHOAUGH6.js.map +0 -7
  74. package/dist/registry-FWM7Q3YW.js +0 -24
  75. package/dist/registry-FWM7Q3YW.js.map +0 -7
  76. package/dist/run-PMUMTYTZ.js +0 -4796
  77. package/dist/run-PMUMTYTZ.js.map +0 -7
  78. package/dist/run-service-B4BDQWO3.js.map +0 -7
  79. package/dist/run.js.map +0 -7
  80. package/dist/schema-EWYI6LGA.js.map +0 -7
  81. package/dist/serve.js.map +0 -7
  82. package/dist/server-HETOVWO6.js +0 -30
  83. package/dist/server-HETOVWO6.js.map +0 -7
  84. package/dist/session-37HDF4U2.js +0 -24
  85. package/dist/session-37HDF4U2.js.map +0 -7
  86. package/dist/share-next-MP7REE74.js +0 -25
  87. package/dist/share-next-MP7REE74.js.map +0 -7
  88. package/dist/sury-CWZTCd75-SVV5EKIT.js +0 -29
  89. package/dist/sury-CWZTCd75-SVV5EKIT.js.map +0 -7
  90. package/dist/typebox-Dei93FPO-LMTONO64.js +0 -21
  91. package/dist/typebox-Dei93FPO-LMTONO64.js.map +0 -7
  92. package/dist/valibot--1zFm7rT-HRT4VHTJ.js +0 -29
  93. package/dist/valibot--1zFm7rT-HRT4VHTJ.js.map +0 -7
  94. package/dist/valibot-D_HTw1Gn-SZJR3J76.js +0 -60
  95. package/dist/valibot-D_HTw1Gn-SZJR3J76.js.map +0 -7
  96. package/dist/worktree-ADWVQ6IR.js +0 -64
  97. package/dist/worktree-ADWVQ6IR.js.map +0 -7
  98. package/dist/zod-Bwrt9trS-5S7UQQDY.js +0 -43
  99. package/dist/zod-Bwrt9trS-5S7UQQDY.js.map +0 -7
  100. package/dist/zod-DSgpEGAE-X2KPFU7C.js +0 -56
  101. package/dist/zod-DSgpEGAE-X2KPFU7C.js.map +0 -7
@@ -1,1857 +0,0 @@
1
- // Built by esbuild from opencode-server source
2
- if (typeof globalThis.Bun === 'undefined') {
3
- globalThis.Bun = {
4
- version: '0.0.0-node-compat',
5
- stdin: { async text() { const chunks = []; for await (const c of process.stdin) chunks.push(c); return Buffer.concat(chunks).toString(); } },
6
- which(cmd) { try { return require('child_process').execFileSync('which', [cmd], { encoding: 'utf8' }).trim(); } catch { return null; } },
7
- };
8
- }
9
- if (typeof globalThis.__name === 'undefined') { globalThis.__name = (t, n) => { Object.defineProperty(t, 'name', { value: n, configurable: true }); return t; }; }
10
- if (typeof globalThis.__export === 'undefined') { globalThis.__export = (t, a) => { for (const k in a) Object.defineProperty(t, k, { get: a[k], enumerable: true }); }; }
11
-
12
- import {
13
- withStatics
14
- } from "./chunk-BI5OUHTQ.js";
15
- import {
16
- Filesystem,
17
- Glob,
18
- Global,
19
- Log
20
- } from "./chunk-2FM4SJ4F.js";
21
- import {
22
- __export,
23
- __reExport
24
- } from "./chunk-HORZKFCR.js";
25
-
26
- // packages/opencode/src/effect/run-service.ts
27
- import { Effect as Effect5, Layer as Layer4, ManagedRuntime } from "effect";
28
-
29
- // packages/opencode/src/bus/global.ts
30
- import { EventEmitter } from "events";
31
- var GlobalBus = new EventEmitter();
32
-
33
- // packages/opencode/src/effect/instance-registry.ts
34
- var disposers = /* @__PURE__ */ new Set();
35
- function registerDisposer(disposer) {
36
- disposers.add(disposer);
37
- return () => {
38
- disposers.delete(disposer);
39
- };
40
- }
41
- async function disposeInstance(directory) {
42
- await Promise.allSettled([...disposers].map((disposer) => disposer(directory)));
43
- }
44
-
45
- // packages/opencode/src/util/iife.ts
46
- function iife(fn) {
47
- return fn();
48
- }
49
-
50
- // packages/opencode/src/util/context.ts
51
- import { AsyncLocalStorage } from "async_hooks";
52
- var Context;
53
- ((Context2) => {
54
- class NotFound extends Error {
55
- constructor(name) {
56
- super(`No context found for ${name}`);
57
- this.name = name;
58
- }
59
- name;
60
- }
61
- Context2.NotFound = NotFound;
62
- function create(name) {
63
- const storage = new AsyncLocalStorage();
64
- return {
65
- use() {
66
- const result = storage.getStore();
67
- if (!result) {
68
- throw new NotFound(name);
69
- }
70
- return result;
71
- },
72
- provide(value, fn) {
73
- return storage.run(value, fn);
74
- }
75
- };
76
- }
77
- Context2.create = create;
78
- })(Context || (Context = {}));
79
-
80
- // packages/opencode/src/project/project.ts
81
- import z5 from "zod";
82
-
83
- // packages/opencode/src/storage/db.ts
84
- var db_exports = {};
85
- __export(db_exports, {
86
- Database: () => Database,
87
- NotFoundError: () => NotFoundError
88
- });
89
- __reExport(db_exports, drizzle_orm_star);
90
- import { migrate } from "drizzle-orm/node-sqlite/migrator";
91
- import * as drizzle_orm_star from "drizzle-orm";
92
-
93
- // packages/opencode/src/util/lazy.ts
94
- function lazy(fn) {
95
- let value;
96
- let loaded = false;
97
- const result = () => {
98
- if (loaded) return value;
99
- try {
100
- value = fn();
101
- loaded = true;
102
- return value;
103
- } catch (e) {
104
- throw e;
105
- }
106
- };
107
- result.reset = () => {
108
- loaded = false;
109
- value = void 0;
110
- };
111
- return result;
112
- }
113
-
114
- // packages/util/src/error.ts
115
- import z from "zod";
116
- var NamedError = class _NamedError extends Error {
117
- static create(name, data) {
118
- const schema = z.object({
119
- name: z.literal(name),
120
- data
121
- }).meta({
122
- ref: name
123
- });
124
- const result = class extends _NamedError {
125
- constructor(data2, options) {
126
- super(name, options);
127
- this.data = data2;
128
- this.name = name;
129
- }
130
- data;
131
- static Schema = schema;
132
- name = name;
133
- static isInstance(input) {
134
- return typeof input === "object" && "name" in input && input.name === name;
135
- }
136
- schema() {
137
- return schema;
138
- }
139
- toObject() {
140
- return {
141
- name,
142
- data: this.data
143
- };
144
- }
145
- };
146
- Object.defineProperty(result, "name", { value: name });
147
- return result;
148
- }
149
- static Unknown = _NamedError.create(
150
- "UnknownError",
151
- z.object({
152
- message: z.string()
153
- })
154
- );
155
- };
156
-
157
- // packages/opencode/src/storage/db.ts
158
- import z2 from "zod";
159
- import path from "path";
160
- import { readFileSync, readdirSync, existsSync } from "fs";
161
-
162
- // packages/opencode/src/flag/flag.ts
163
- import { Config } from "effect";
164
- function truthy(key) {
165
- const value = process.env[key]?.toLowerCase();
166
- return value === "true" || value === "1";
167
- }
168
- function falsy(key) {
169
- const value = process.env[key]?.toLowerCase();
170
- return value === "false" || value === "0";
171
- }
172
- var Flag;
173
- ((Flag2) => {
174
- Flag2.OPENCODE_AUTO_SHARE = truthy("OPENCODE_AUTO_SHARE");
175
- Flag2.OPENCODE_AUTO_HEAP_SNAPSHOT = truthy("OPENCODE_AUTO_HEAP_SNAPSHOT");
176
- Flag2.OPENCODE_GIT_BASH_PATH = process.env["OPENCODE_GIT_BASH_PATH"];
177
- Flag2.OPENCODE_CONFIG = process.env["OPENCODE_CONFIG"];
178
- Flag2.OPENCODE_CONFIG_CONTENT = process.env["OPENCODE_CONFIG_CONTENT"];
179
- Flag2.OPENCODE_DISABLE_AUTOUPDATE = truthy("OPENCODE_DISABLE_AUTOUPDATE");
180
- Flag2.OPENCODE_ALWAYS_NOTIFY_UPDATE = truthy("OPENCODE_ALWAYS_NOTIFY_UPDATE");
181
- Flag2.OPENCODE_DISABLE_PRUNE = truthy("OPENCODE_DISABLE_PRUNE");
182
- Flag2.OPENCODE_DISABLE_TERMINAL_TITLE = truthy("OPENCODE_DISABLE_TERMINAL_TITLE");
183
- Flag2.OPENCODE_SHOW_TTFD = truthy("OPENCODE_SHOW_TTFD");
184
- Flag2.OPENCODE_PERMISSION = process.env["OPENCODE_PERMISSION"];
185
- Flag2.OPENCODE_DISABLE_DEFAULT_PLUGINS = truthy("OPENCODE_DISABLE_DEFAULT_PLUGINS");
186
- Flag2.OPENCODE_DISABLE_LSP_DOWNLOAD = truthy("OPENCODE_DISABLE_LSP_DOWNLOAD");
187
- Flag2.OPENCODE_ENABLE_EXPERIMENTAL_MODELS = truthy("OPENCODE_ENABLE_EXPERIMENTAL_MODELS");
188
- Flag2.OPENCODE_DISABLE_AUTOCOMPACT = truthy("OPENCODE_DISABLE_AUTOCOMPACT");
189
- Flag2.OPENCODE_DISABLE_MODELS_FETCH = truthy("OPENCODE_DISABLE_MODELS_FETCH");
190
- Flag2.OPENCODE_DISABLE_MOUSE = truthy("OPENCODE_DISABLE_MOUSE");
191
- Flag2.OPENCODE_DISABLE_CLAUDE_CODE = truthy("OPENCODE_DISABLE_CLAUDE_CODE");
192
- Flag2.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT = Flag2.OPENCODE_DISABLE_CLAUDE_CODE || truthy("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT");
193
- Flag2.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = Flag2.OPENCODE_DISABLE_CLAUDE_CODE || truthy("OPENCODE_DISABLE_CLAUDE_CODE_SKILLS");
194
- Flag2.OPENCODE_DISABLE_EXTERNAL_SKILLS = Flag2.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS || truthy("OPENCODE_DISABLE_EXTERNAL_SKILLS");
195
- Flag2.OPENCODE_FAKE_VCS = process.env["OPENCODE_FAKE_VCS"];
196
- Flag2.OPENCODE_SERVER_PASSWORD = process.env["OPENCODE_SERVER_PASSWORD"];
197
- Flag2.OPENCODE_SERVER_USERNAME = process.env["OPENCODE_SERVER_USERNAME"];
198
- Flag2.OPENCODE_ENABLE_QUESTION_TOOL = truthy("OPENCODE_ENABLE_QUESTION_TOOL");
199
- Flag2.OPENCODE_EXPERIMENTAL = truthy("OPENCODE_EXPERIMENTAL");
200
- Flag2.OPENCODE_EXPERIMENTAL_FILEWATCHER = Config.boolean("OPENCODE_EXPERIMENTAL_FILEWATCHER").pipe(
201
- Config.withDefault(false)
202
- );
203
- Flag2.OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER = Config.boolean(
204
- "OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER"
205
- ).pipe(Config.withDefault(false));
206
- Flag2.OPENCODE_EXPERIMENTAL_ICON_DISCOVERY = Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY");
207
- const copy = process.env["OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"];
208
- Flag2.OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT = copy === void 0 ? process.platform === "win32" : truthy("OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT");
209
- Flag2.OPENCODE_ENABLE_EXA = truthy("OPENCODE_ENABLE_EXA") || Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_EXA");
210
- Flag2.OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS = number("OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS");
211
- Flag2.OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX = number("OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX");
212
- Flag2.OPENCODE_EXPERIMENTAL_OXFMT = Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_OXFMT");
213
- Flag2.OPENCODE_EXPERIMENTAL_LSP_TY = truthy("OPENCODE_EXPERIMENTAL_LSP_TY");
214
- Flag2.OPENCODE_EXPERIMENTAL_LSP_TOOL = Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_LSP_TOOL");
215
- Flag2.OPENCODE_DISABLE_FILETIME_CHECK = Config.boolean("OPENCODE_DISABLE_FILETIME_CHECK").pipe(
216
- Config.withDefault(false)
217
- );
218
- Flag2.OPENCODE_EXPERIMENTAL_PLAN_MODE = Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_PLAN_MODE");
219
- Flag2.OPENCODE_EXPERIMENTAL_WORKSPACES = Flag2.OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_WORKSPACES");
220
- Flag2.OPENCODE_EXPERIMENTAL_MARKDOWN = !falsy("OPENCODE_EXPERIMENTAL_MARKDOWN");
221
- Flag2.OPENCODE_MODELS_URL = process.env["OPENCODE_MODELS_URL"];
222
- Flag2.OPENCODE_MODELS_PATH = process.env["OPENCODE_MODELS_PATH"];
223
- Flag2.OPENCODE_DISABLE_EMBEDDED_WEB_UI = truthy("OPENCODE_DISABLE_EMBEDDED_WEB_UI");
224
- Flag2.OPENCODE_DB = process.env["OPENCODE_DB"];
225
- Flag2.OPENCODE_DISABLE_CHANNEL_DB = truthy("OPENCODE_DISABLE_CHANNEL_DB");
226
- Flag2.OPENCODE_SKIP_MIGRATIONS = truthy("OPENCODE_SKIP_MIGRATIONS");
227
- Flag2.OPENCODE_STRICT_CONFIG_DEPS = truthy("OPENCODE_STRICT_CONFIG_DEPS");
228
- function number(key) {
229
- const value = process.env[key];
230
- if (!value) return void 0;
231
- const parsed = Number(value);
232
- return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
233
- }
234
- })(Flag || (Flag = {}));
235
- Object.defineProperty(Flag, "OPENCODE_DISABLE_PROJECT_CONFIG", {
236
- get() {
237
- return truthy("OPENCODE_DISABLE_PROJECT_CONFIG");
238
- },
239
- enumerable: true,
240
- configurable: false
241
- });
242
- Object.defineProperty(Flag, "OPENCODE_TUI_CONFIG", {
243
- get() {
244
- return process.env["OPENCODE_TUI_CONFIG"];
245
- },
246
- enumerable: true,
247
- configurable: false
248
- });
249
- Object.defineProperty(Flag, "OPENCODE_CONFIG_DIR", {
250
- get() {
251
- return process.env["OPENCODE_CONFIG_DIR"];
252
- },
253
- enumerable: true,
254
- configurable: false
255
- });
256
- Object.defineProperty(Flag, "OPENCODE_PURE", {
257
- get() {
258
- return truthy("OPENCODE_PURE");
259
- },
260
- enumerable: true,
261
- configurable: false
262
- });
263
- Object.defineProperty(Flag, "OPENCODE_PLUGIN_META_FILE", {
264
- get() {
265
- return process.env["OPENCODE_PLUGIN_META_FILE"];
266
- },
267
- enumerable: true,
268
- configurable: false
269
- });
270
- Object.defineProperty(Flag, "OPENCODE_CLIENT", {
271
- get() {
272
- return process.env["OPENCODE_CLIENT"] ?? "cli";
273
- },
274
- enumerable: true,
275
- configurable: false
276
- });
277
-
278
- // packages/opencode/src/installation/meta.ts
279
- var VERSION = typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "local";
280
- var CHANNEL = typeof OPENCODE_CHANNEL === "string" ? OPENCODE_CHANNEL : "local";
281
-
282
- // packages/opencode/src/effect/instance-state.ts
283
- import { Effect, Fiber, ScopedCache, ServiceMap as ServiceMap2 } from "effect";
284
-
285
- // packages/opencode/src/effect/instance-ref.ts
286
- import { ServiceMap } from "effect";
287
- var InstanceRef = ServiceMap.Reference("~opencode/InstanceRef", {
288
- defaultValue: () => void 0
289
- });
290
-
291
- // packages/opencode/src/effect/instance-state.ts
292
- var TypeId = "~opencode/InstanceState";
293
- var InstanceState;
294
- ((InstanceState2) => {
295
- InstanceState2.bind = (fn) => {
296
- try {
297
- return Instance.bind(fn);
298
- } catch (err) {
299
- if (!(err instanceof Context.NotFound)) throw err;
300
- }
301
- const fiber = Fiber.getCurrent();
302
- const ctx = fiber ? ServiceMap2.getReferenceUnsafe(fiber.services, InstanceRef) : void 0;
303
- if (!ctx) return fn;
304
- return ((...args) => Instance.restore(ctx, () => fn(...args)));
305
- };
306
- InstanceState2.context = Effect.gen(function* () {
307
- return (yield* InstanceRef) ?? Instance.current;
308
- });
309
- InstanceState2.directory = Effect.map(InstanceState2.context, (ctx) => ctx.directory);
310
- InstanceState2.make = (init2) => Effect.gen(function* () {
311
- const cache2 = yield* ScopedCache.make({
312
- capacity: Number.POSITIVE_INFINITY,
313
- lookup: () => Effect.gen(function* () {
314
- return yield* init2(yield* InstanceState2.context);
315
- })
316
- });
317
- const off = registerDisposer((directory2) => Effect.runPromise(ScopedCache.invalidate(cache2, directory2)));
318
- yield* Effect.addFinalizer(() => Effect.sync(off));
319
- return {
320
- [TypeId]: TypeId,
321
- cache: cache2
322
- };
323
- });
324
- InstanceState2.get = (self) => Effect.gen(function* () {
325
- return yield* ScopedCache.get(self.cache, yield* InstanceState2.directory);
326
- });
327
- InstanceState2.use = (self, select) => Effect.map((0, InstanceState2.get)(self), select);
328
- InstanceState2.useEffect = (self, select) => Effect.flatMap((0, InstanceState2.get)(self), select);
329
- InstanceState2.has = (self) => Effect.gen(function* () {
330
- return yield* ScopedCache.has(self.cache, yield* InstanceState2.directory);
331
- });
332
- InstanceState2.invalidate = (self) => Effect.gen(function* () {
333
- return yield* ScopedCache.invalidate(self.cache, yield* InstanceState2.directory);
334
- });
335
- InstanceState2.withALS = (fn) => Effect.map(InstanceState2.context, (ctx) => Instance.restore(ctx, fn));
336
- })(InstanceState || (InstanceState = {}));
337
-
338
- // packages/opencode/src/storage/db.node.ts
339
- import { DatabaseSync } from "node:sqlite";
340
- import { drizzle } from "drizzle-orm/node-sqlite";
341
- function init(path3) {
342
- const sqlite = new DatabaseSync(path3);
343
- const db = drizzle({ client: sqlite });
344
- return db;
345
- }
346
-
347
- // packages/opencode/src/storage/db.ts
348
- var NotFoundError = NamedError.create(
349
- "NotFoundError",
350
- z2.object({
351
- message: z2.string()
352
- })
353
- );
354
- var log = Log.create({ service: "db" });
355
- var Database;
356
- ((Database2) => {
357
- function getChannelPath() {
358
- if (["latest", "beta"].includes(CHANNEL) || Flag.OPENCODE_DISABLE_CHANNEL_DB)
359
- return path.join(Global.Path.data, "opencode.db");
360
- const safe = CHANNEL.replace(/[^a-zA-Z0-9._-]/g, "-");
361
- return path.join(Global.Path.data, `opencode-${safe}.db`);
362
- }
363
- Database2.getChannelPath = getChannelPath;
364
- Database2.Path = iife(() => {
365
- if (Flag.OPENCODE_DB) {
366
- if (Flag.OPENCODE_DB === ":memory:" || path.isAbsolute(Flag.OPENCODE_DB)) return Flag.OPENCODE_DB;
367
- return path.join(Global.Path.data, Flag.OPENCODE_DB);
368
- }
369
- return getChannelPath();
370
- });
371
- function time(tag) {
372
- const match = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(tag);
373
- if (!match) return 0;
374
- return Date.UTC(
375
- Number(match[1]),
376
- Number(match[2]) - 1,
377
- Number(match[3]),
378
- Number(match[4]),
379
- Number(match[5]),
380
- Number(match[6])
381
- );
382
- }
383
- function migrations(dir) {
384
- const dirs = readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
385
- const sql = dirs.map((name) => {
386
- const file = path.join(dir, name, "migration.sql");
387
- if (!existsSync(file)) return;
388
- return {
389
- sql: readFileSync(file, "utf-8"),
390
- timestamp: time(name),
391
- name
392
- };
393
- }).filter(Boolean);
394
- return sql.sort((a, b) => a.timestamp - b.timestamp);
395
- }
396
- Database2.Client = lazy(() => {
397
- log.info("opening database", { path: Database2.Path });
398
- const db = init(Database2.Path);
399
- db.run("PRAGMA journal_mode = WAL");
400
- db.run("PRAGMA synchronous = NORMAL");
401
- db.run("PRAGMA busy_timeout = 5000");
402
- db.run("PRAGMA cache_size = -64000");
403
- db.run("PRAGMA foreign_keys = ON");
404
- db.run("PRAGMA wal_checkpoint(PASSIVE)");
405
- const migrationsDir = path.join(import.meta.dirname, "../packages/opencode/migration");
406
- if (typeof OPENCODE_MIGRATIONS !== "undefined") {
407
- const entries = OPENCODE_MIGRATIONS;
408
- if (entries.length > 0) {
409
- log.info("applying migrations", { count: entries.length, mode: "bundled" });
410
- if (Flag.OPENCODE_SKIP_MIGRATIONS) {
411
- for (const item of entries) item.sql = "select 1;";
412
- }
413
- migrate(db, entries);
414
- }
415
- } else {
416
- const entries = migrations(migrationsDir);
417
- log.info("applying migrations", { count: entries.length, mode: "dev" });
418
- if (!Flag.OPENCODE_SKIP_MIGRATIONS && entries.length > 0) {
419
- migrate(db, { migrationsFolder: migrationsDir });
420
- }
421
- }
422
- return db;
423
- });
424
- function close() {
425
- (0, Database2.Client)().$client.close();
426
- Database2.Client.reset();
427
- }
428
- Database2.close = close;
429
- const ctx = Context.create("database");
430
- function use(callback2) {
431
- try {
432
- return callback2(ctx.use().tx);
433
- } catch (err) {
434
- if (err instanceof Context.NotFound) {
435
- const effects = [];
436
- const result = ctx.provide({ effects, tx: (0, Database2.Client)() }, () => callback2((0, Database2.Client)()));
437
- for (const effect3 of effects) effect3();
438
- return result;
439
- }
440
- throw err;
441
- }
442
- }
443
- Database2.use = use;
444
- function effect2(fn) {
445
- const bound = InstanceState.bind(fn);
446
- try {
447
- ctx.use().effects.push(bound);
448
- } catch {
449
- bound();
450
- }
451
- }
452
- Database2.effect = effect2;
453
- function transaction(callback2, options) {
454
- try {
455
- return callback2(ctx.use().tx);
456
- } catch (err) {
457
- if (err instanceof Context.NotFound) {
458
- const effects = [];
459
- const txCallback = InstanceState.bind((tx) => ctx.provide({ tx, effects }, () => callback2(tx)));
460
- const result = (0, Database2.Client)().transaction(txCallback, { behavior: options?.behavior });
461
- for (const effect3 of effects) effect3();
462
- return result;
463
- }
464
- throw err;
465
- }
466
- }
467
- Database2.transaction = transaction;
468
- })(Database || (Database = {}));
469
-
470
- // packages/opencode/src/project/project.sql.ts
471
- import { sqliteTable, text, integer as integer2 } from "drizzle-orm/sqlite-core";
472
-
473
- // packages/opencode/src/storage/schema.sql.ts
474
- import { integer } from "drizzle-orm/sqlite-core";
475
- var Timestamps = {
476
- time_created: integer().notNull().$default(() => Date.now()),
477
- time_updated: integer().notNull().$onUpdate(() => Date.now())
478
- };
479
-
480
- // packages/opencode/src/project/project.sql.ts
481
- var ProjectTable = sqliteTable("project", {
482
- id: text().$type().primaryKey(),
483
- worktree: text().notNull(),
484
- vcs: text(),
485
- name: text(),
486
- icon_url: text(),
487
- icon_color: text(),
488
- ...Timestamps,
489
- time_initialized: integer2(),
490
- sandboxes: text({ mode: "json" }).notNull().$type(),
491
- commands: text({ mode: "json" }).$type()
492
- });
493
-
494
- // packages/opencode/src/session/session.sql.ts
495
- import { sqliteTable as sqliteTable2, text as text2, integer as integer3, index, primaryKey } from "drizzle-orm/sqlite-core";
496
- var SessionTable = sqliteTable2(
497
- "session",
498
- {
499
- id: text2().$type().primaryKey(),
500
- project_id: text2().$type().notNull().references(() => ProjectTable.id, { onDelete: "cascade" }),
501
- workspace_id: text2().$type(),
502
- parent_id: text2().$type(),
503
- slug: text2().notNull(),
504
- directory: text2().notNull(),
505
- title: text2().notNull(),
506
- version: text2().notNull(),
507
- share_url: text2(),
508
- summary_additions: integer3(),
509
- summary_deletions: integer3(),
510
- summary_files: integer3(),
511
- summary_diffs: text2({ mode: "json" }).$type(),
512
- revert: text2({ mode: "json" }).$type(),
513
- permission: text2({ mode: "json" }).$type(),
514
- ...Timestamps,
515
- metadata: text2({ mode: "json" }).$type(),
516
- time_compacting: integer3(),
517
- time_archived: integer3()
518
- },
519
- (table) => [
520
- index("session_project_idx").on(table.project_id),
521
- index("session_workspace_idx").on(table.workspace_id),
522
- index("session_parent_idx").on(table.parent_id)
523
- ]
524
- );
525
- var MessageTable = sqliteTable2(
526
- "message",
527
- {
528
- id: text2().$type().primaryKey(),
529
- session_id: text2().$type().notNull().references(() => SessionTable.id, { onDelete: "cascade" }),
530
- ...Timestamps,
531
- data: text2({ mode: "json" }).notNull().$type()
532
- },
533
- (table) => [index("message_session_time_created_id_idx").on(table.session_id, table.time_created, table.id)]
534
- );
535
- var PartTable = sqliteTable2(
536
- "part",
537
- {
538
- id: text2().$type().primaryKey(),
539
- message_id: text2().$type().notNull().references(() => MessageTable.id, { onDelete: "cascade" }),
540
- session_id: text2().$type().notNull(),
541
- ...Timestamps,
542
- data: text2({ mode: "json" }).notNull().$type()
543
- },
544
- (table) => [
545
- index("part_message_id_id_idx").on(table.message_id, table.id),
546
- index("part_session_idx").on(table.session_id)
547
- ]
548
- );
549
- var TodoTable = sqliteTable2(
550
- "todo",
551
- {
552
- session_id: text2().$type().notNull().references(() => SessionTable.id, { onDelete: "cascade" }),
553
- content: text2().notNull(),
554
- status: text2().notNull(),
555
- priority: text2().notNull(),
556
- position: integer3().notNull(),
557
- ...Timestamps
558
- },
559
- (table) => [
560
- primaryKey({ columns: [table.session_id, table.position] }),
561
- index("todo_session_idx").on(table.session_id)
562
- ]
563
- );
564
- var PermissionTable = sqliteTable2("permission", {
565
- project_id: text2().primaryKey().references(() => ProjectTable.id, { onDelete: "cascade" }),
566
- ...Timestamps,
567
- data: text2({ mode: "json" }).notNull().$type()
568
- });
569
-
570
- // packages/opencode/src/bus/bus-event.ts
571
- import z3 from "zod";
572
- var BusEvent;
573
- ((BusEvent2) => {
574
- const registry = /* @__PURE__ */ new Map();
575
- function define(type, properties) {
576
- const result = {
577
- type,
578
- properties
579
- };
580
- registry.set(type, result);
581
- return result;
582
- }
583
- BusEvent2.define = define;
584
- function payloads() {
585
- return z3.discriminatedUnion(
586
- "type",
587
- registry.entries().map(([type, def]) => {
588
- return z3.object({
589
- type: z3.literal(type),
590
- properties: def.properties
591
- }).meta({
592
- ref: "Event." + def.type
593
- });
594
- }).toArray()
595
- ).meta({
596
- ref: "Event"
597
- });
598
- }
599
- BusEvent2.payloads = payloads;
600
- })(BusEvent || (BusEvent = {}));
601
-
602
- // packages/opencode/src/util/which.ts
603
- import whichPkg from "which";
604
- import path2 from "path";
605
- function which(cmd, env) {
606
- const base = env?.PATH ?? env?.Path ?? process.env.PATH ?? process.env.Path ?? "";
607
- const full = base ? base + path2.delimiter + Global.Path.bin : Global.Path.bin;
608
- const result = whichPkg.sync(cmd, {
609
- nothrow: true,
610
- path: full,
611
- pathExt: env?.PATHEXT ?? env?.PathExt ?? process.env.PATHEXT ?? process.env.PathExt
612
- });
613
- return typeof result === "string" ? result : null;
614
- }
615
-
616
- // packages/opencode/src/project/schema.ts
617
- import { Schema } from "effect";
618
- import z4 from "zod";
619
- var projectIdSchema = Schema.String.pipe(Schema.brand("ProjectID"));
620
- var ProjectID = projectIdSchema.pipe(
621
- withStatics((schema) => ({
622
- global: schema.makeUnsafe("global"),
623
- make: (id) => schema.makeUnsafe(id),
624
- zod: z4.string().pipe(z4.custom())
625
- }))
626
- );
627
-
628
- // packages/opencode/src/project/project.ts
629
- import { Effect as Effect4, Layer as Layer3, Path as Path3, Scope as Scope2, ServiceMap as ServiceMap4, Stream as Stream2 } from "effect";
630
- import { ChildProcess as ChildProcess2, ChildProcessSpawner as ChildProcessSpawner2 } from "effect/unstable/process";
631
- import { NodePath as NodePath2 } from "@effect/platform-node";
632
-
633
- // packages/opencode/src/filesystem/index.ts
634
- import { NodeFileSystem } from "@effect/platform-node";
635
- import { dirname, join, relative, resolve as pathResolve } from "path";
636
- import { realpathSync } from "fs";
637
- import * as NFS from "fs/promises";
638
- import { lookup } from "mime-types";
639
- import { Effect as Effect2, FileSystem, Layer, Schema as Schema2, ServiceMap as ServiceMap3 } from "effect";
640
- var AppFileSystem;
641
- ((AppFileSystem2) => {
642
- class FileSystemError extends Schema2.TaggedErrorClass()("FileSystemError", {
643
- method: Schema2.String,
644
- cause: Schema2.optional(Schema2.Defect)
645
- }) {
646
- }
647
- AppFileSystem2.FileSystemError = FileSystemError;
648
- class Service extends ServiceMap3.Service()("@opencode/FileSystem") {
649
- }
650
- AppFileSystem2.Service = Service;
651
- AppFileSystem2.layer = Layer.effect(
652
- Service,
653
- Effect2.gen(function* () {
654
- const fs = yield* FileSystem.FileSystem;
655
- const existsSafe = Effect2.fn("FileSystem.existsSafe")(function* (path3) {
656
- return yield* fs.exists(path3).pipe(Effect2.orElseSucceed(() => false));
657
- });
658
- const isDir = Effect2.fn("FileSystem.isDir")(function* (path3) {
659
- const info = yield* fs.stat(path3).pipe(Effect2.catch(() => Effect2.void));
660
- return info?.type === "Directory";
661
- });
662
- const isFile = Effect2.fn("FileSystem.isFile")(function* (path3) {
663
- const info = yield* fs.stat(path3).pipe(Effect2.catch(() => Effect2.void));
664
- return info?.type === "File";
665
- });
666
- const readDirectoryEntries = Effect2.fn("FileSystem.readDirectoryEntries")(function* (dirPath) {
667
- return yield* Effect2.tryPromise({
668
- try: async () => {
669
- const entries = await NFS.readdir(dirPath, { withFileTypes: true });
670
- return entries.map(
671
- (e) => ({
672
- name: e.name,
673
- type: e.isDirectory() ? "directory" : e.isSymbolicLink() ? "symlink" : e.isFile() ? "file" : "other"
674
- })
675
- );
676
- },
677
- catch: (cause) => new FileSystemError({ method: "readDirectoryEntries", cause })
678
- });
679
- });
680
- const readJson = Effect2.fn("FileSystem.readJson")(function* (path3) {
681
- const text3 = yield* fs.readFileString(path3);
682
- return JSON.parse(text3);
683
- });
684
- const writeJson = Effect2.fn("FileSystem.writeJson")(function* (path3, data, mode) {
685
- const content = JSON.stringify(data, null, 2);
686
- const tmp = `${path3}.tmp-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
687
- yield* fs.writeFileString(tmp, content);
688
- if (mode) yield* fs.chmod(tmp, mode);
689
- yield* Effect2.tryPromise({
690
- try: () => NFS.rename(tmp, path3),
691
- catch: (cause) => new FileSystemError({ method: "writeJson.rename", cause })
692
- });
693
- });
694
- const ensureDir = Effect2.fn("FileSystem.ensureDir")(function* (path3) {
695
- yield* fs.makeDirectory(path3, { recursive: true });
696
- });
697
- const writeWithDirs = Effect2.fn("FileSystem.writeWithDirs")(function* (path3, content, mode) {
698
- const write = typeof content === "string" ? fs.writeFileString(path3, content) : fs.writeFile(path3, content);
699
- yield* write.pipe(
700
- Effect2.catchIf(
701
- (e) => e.reason._tag === "NotFound",
702
- () => Effect2.gen(function* () {
703
- yield* fs.makeDirectory(dirname(path3), { recursive: true });
704
- yield* write;
705
- })
706
- )
707
- );
708
- if (mode) yield* fs.chmod(path3, mode);
709
- });
710
- const glob = Effect2.fn("FileSystem.glob")(function* (pattern, options) {
711
- return yield* Effect2.tryPromise({
712
- try: () => Glob.scan(pattern, options),
713
- catch: (cause) => new FileSystemError({ method: "glob", cause })
714
- });
715
- });
716
- const findUp = Effect2.fn("FileSystem.findUp")(function* (target, start, stop) {
717
- const result = [];
718
- let current = start;
719
- while (true) {
720
- const search = join(current, target);
721
- if (yield* fs.exists(search)) result.push(search);
722
- if (stop === current) break;
723
- const parent = dirname(current);
724
- if (parent === current) break;
725
- current = parent;
726
- }
727
- return result;
728
- });
729
- const up = Effect2.fn("FileSystem.up")(function* (options) {
730
- const result = [];
731
- let current = options.start;
732
- while (true) {
733
- for (const target of options.targets) {
734
- const search = join(current, target);
735
- if (yield* fs.exists(search)) result.push(search);
736
- }
737
- if (options.stop === current) break;
738
- const parent = dirname(current);
739
- if (parent === current) break;
740
- current = parent;
741
- }
742
- return result;
743
- });
744
- const globUp = Effect2.fn("FileSystem.globUp")(function* (pattern, start, stop) {
745
- const result = [];
746
- let current = start;
747
- while (true) {
748
- const matches = yield* glob(pattern, { cwd: current, absolute: true, include: "file", dot: true }).pipe(
749
- Effect2.catch(() => Effect2.succeed([]))
750
- );
751
- result.push(...matches);
752
- if (stop === current) break;
753
- const parent = dirname(current);
754
- if (parent === current) break;
755
- current = parent;
756
- }
757
- return result;
758
- });
759
- return Service.of({
760
- ...fs,
761
- existsSafe,
762
- isDir,
763
- isFile,
764
- readDirectoryEntries,
765
- readJson,
766
- writeJson,
767
- ensureDir,
768
- writeWithDirs,
769
- findUp,
770
- up,
771
- globUp,
772
- glob,
773
- globMatch: Glob.match
774
- });
775
- })
776
- );
777
- AppFileSystem2.defaultLayer = AppFileSystem2.layer.pipe(Layer.provide(NodeFileSystem.layer));
778
- function mimeType(p) {
779
- return lookup(p) || "application/octet-stream";
780
- }
781
- AppFileSystem2.mimeType = mimeType;
782
- function normalizePath(p) {
783
- if (process.platform !== "win32") return p;
784
- const resolved = pathResolve(windowsPath(p));
785
- try {
786
- return realpathSync.native(resolved);
787
- } catch {
788
- return resolved;
789
- }
790
- }
791
- AppFileSystem2.normalizePath = normalizePath;
792
- function normalizePathPattern(p) {
793
- if (process.platform !== "win32") return p;
794
- if (p === "*") return p;
795
- const match = p.match(/^(.*)[\\/]\*$/);
796
- if (!match) return normalizePath(p);
797
- const dir = /^[A-Za-z]:$/.test(match[1]) ? match[1] + "\\" : match[1];
798
- return join(normalizePath(dir), "*");
799
- }
800
- AppFileSystem2.normalizePathPattern = normalizePathPattern;
801
- function resolve(p) {
802
- const resolved = pathResolve(windowsPath(p));
803
- try {
804
- return normalizePath(realpathSync(resolved));
805
- } catch (e) {
806
- if (e?.code === "ENOENT") return normalizePath(resolved);
807
- throw e;
808
- }
809
- }
810
- AppFileSystem2.resolve = resolve;
811
- function windowsPath(p) {
812
- if (process.platform !== "win32") return p;
813
- return p.replace(/^\/([a-zA-Z]):(?:[\\/]|$)/, (_, drive) => `${drive.toUpperCase()}:/`).replace(/^\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`).replace(/^\/cygdrive\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`).replace(/^\/mnt\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`);
814
- }
815
- AppFileSystem2.windowsPath = windowsPath;
816
- function overlaps(a, b) {
817
- const relA = relative(a, b);
818
- const relB = relative(b, a);
819
- return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..");
820
- }
821
- AppFileSystem2.overlaps = overlaps;
822
- function contains(parent, child) {
823
- return !relative(parent, child).startsWith("..");
824
- }
825
- AppFileSystem2.contains = contains;
826
- })(AppFileSystem || (AppFileSystem = {}));
827
-
828
- // packages/opencode/src/effect/cross-spawn-spawner.ts
829
- import { NodeFileSystem as NodeFileSystem2, NodeSink, NodeStream } from "@effect/platform-node";
830
- import * as NodePath from "@effect/platform-node/NodePath";
831
- import * as Deferred from "effect/Deferred";
832
- import * as Effect3 from "effect/Effect";
833
- import * as Exit from "effect/Exit";
834
- import * as FileSystem2 from "effect/FileSystem";
835
- import * as Layer2 from "effect/Layer";
836
- import * as Path from "effect/Path";
837
- import * as PlatformError from "effect/PlatformError";
838
- import * as Predicate from "effect/Predicate";
839
- import * as Sink from "effect/Sink";
840
- import * as Stream from "effect/Stream";
841
- import * as ChildProcess from "effect/unstable/process/ChildProcess";
842
- import {
843
- ChildProcessSpawner,
844
- ExitCode,
845
- make as makeSpawner,
846
- makeHandle,
847
- ProcessId
848
- } from "effect/unstable/process/ChildProcessSpawner";
849
- import * as NodeChildProcess from "node:child_process";
850
- import { PassThrough } from "node:stream";
851
- import launch from "cross-spawn";
852
- var toError = (err) => err instanceof globalThis.Error ? err : new globalThis.Error(String(err));
853
- var toTag = (err) => {
854
- switch (err.code) {
855
- case "ENOENT":
856
- return "NotFound";
857
- case "EACCES":
858
- return "PermissionDenied";
859
- case "EEXIST":
860
- return "AlreadyExists";
861
- case "EISDIR":
862
- return "BadResource";
863
- case "ENOTDIR":
864
- return "BadResource";
865
- case "EBUSY":
866
- return "Busy";
867
- case "ELOOP":
868
- return "BadResource";
869
- default:
870
- return "Unknown";
871
- }
872
- };
873
- var flatten = (command) => {
874
- const commands = [];
875
- const opts = [];
876
- const walk = (cmd) => {
877
- switch (cmd._tag) {
878
- case "StandardCommand":
879
- commands.push(cmd);
880
- return;
881
- case "PipedCommand":
882
- walk(cmd.left);
883
- opts.push(cmd.options);
884
- walk(cmd.right);
885
- return;
886
- }
887
- };
888
- walk(command);
889
- if (commands.length === 0) throw new Error("flatten produced empty commands array");
890
- const [head, ...tail] = commands;
891
- return {
892
- commands: [head, ...tail],
893
- opts
894
- };
895
- };
896
- var toPlatformError = (method, err, command) => {
897
- const cmd = flatten(command).commands.map((x) => `${x.command} ${x.args.join(" ")}`).join(" | ");
898
- return PlatformError.systemError({
899
- _tag: toTag(err),
900
- module: "ChildProcess",
901
- method,
902
- pathOrDescriptor: cmd,
903
- syscall: err.syscall,
904
- cause: err
905
- });
906
- };
907
- var make2 = Effect3.gen(function* () {
908
- const fs = yield* FileSystem2.FileSystem;
909
- const path3 = yield* Path.Path;
910
- const cwd = Effect3.fnUntraced(function* (opts) {
911
- if (Predicate.isUndefined(opts.cwd)) return void 0;
912
- yield* fs.access(opts.cwd);
913
- return path3.resolve(opts.cwd);
914
- });
915
- const env = (opts) => opts.extendEnv ? { ...globalThis.process.env, ...opts.env } : opts.env;
916
- const input = (x) => Stream.isStream(x) ? "pipe" : x;
917
- const output = (x) => Sink.isSink(x) ? "pipe" : x;
918
- const stdin = (opts) => {
919
- const cfg = { stream: "pipe", encoding: "utf-8", endOnDone: true };
920
- if (Predicate.isUndefined(opts.stdin)) return cfg;
921
- if (typeof opts.stdin === "string") return { ...cfg, stream: opts.stdin };
922
- if (Stream.isStream(opts.stdin)) return { ...cfg, stream: opts.stdin };
923
- return {
924
- stream: opts.stdin.stream,
925
- encoding: opts.stdin.encoding ?? cfg.encoding,
926
- endOnDone: opts.stdin.endOnDone ?? cfg.endOnDone
927
- };
928
- };
929
- const stdio = (opts, key) => {
930
- const cfg = opts[key];
931
- if (Predicate.isUndefined(cfg)) return { stream: "pipe" };
932
- if (typeof cfg === "string") return { stream: cfg };
933
- if (Sink.isSink(cfg)) return { stream: cfg };
934
- return { stream: cfg.stream };
935
- };
936
- const fds = (opts) => {
937
- if (Predicate.isUndefined(opts.additionalFds)) return [];
938
- return Object.entries(opts.additionalFds).flatMap(([name, config]) => {
939
- const fd = ChildProcess.parseFdName(name);
940
- return Predicate.isUndefined(fd) ? [] : [{ fd, config }];
941
- }).toSorted((a, b) => a.fd - b.fd);
942
- };
943
- const stdios = (sin, sout, serr, extra) => {
944
- const pipe = (x) => process.platform === "win32" && x === "pipe" ? "overlapped" : x;
945
- const arr = [
946
- pipe(input(sin.stream)),
947
- pipe(output(sout.stream)),
948
- pipe(output(serr.stream))
949
- ];
950
- if (extra.length === 0) return arr;
951
- const max = extra.reduce((acc, x) => Math.max(acc, x.fd), 2);
952
- for (let i = 3; i <= max; i++) arr[i] = "ignore";
953
- for (const x of extra) arr[x.fd] = pipe("pipe");
954
- return arr;
955
- };
956
- const setupFds = Effect3.fnUntraced(function* (command, proc, extra) {
957
- if (extra.length === 0) {
958
- return {
959
- getInputFd: () => Sink.drain,
960
- getOutputFd: () => Stream.empty
961
- };
962
- }
963
- const ins = /* @__PURE__ */ new Map();
964
- const outs = /* @__PURE__ */ new Map();
965
- for (const x of extra) {
966
- const node = proc.stdio[x.fd];
967
- switch (x.config.type) {
968
- case "input": {
969
- let sink = Sink.drain;
970
- if (node && "write" in node) {
971
- sink = NodeSink.fromWritable({
972
- evaluate: () => node,
973
- onError: (err) => toPlatformError(`fromWritable(fd${x.fd})`, toError(err), command),
974
- endOnDone: true
975
- });
976
- }
977
- if (x.config.stream) yield* Effect3.forkScoped(Stream.run(x.config.stream, sink));
978
- ins.set(x.fd, sink);
979
- break;
980
- }
981
- case "output": {
982
- let stream = Stream.empty;
983
- if (node && "read" in node) {
984
- const tap = new PassThrough();
985
- node.on("error", (err) => tap.destroy(toError(err)));
986
- node.pipe(tap);
987
- stream = NodeStream.fromReadable({
988
- evaluate: () => tap,
989
- onError: (err) => toPlatformError(`fromReadable(fd${x.fd})`, toError(err), command)
990
- });
991
- }
992
- if (x.config.sink) stream = Stream.transduce(stream, x.config.sink);
993
- outs.set(x.fd, stream);
994
- break;
995
- }
996
- }
997
- }
998
- return {
999
- getInputFd: (fd) => ins.get(fd) ?? Sink.drain,
1000
- getOutputFd: (fd) => outs.get(fd) ?? Stream.empty
1001
- };
1002
- });
1003
- const setupStdin = (command, proc, cfg) => Effect3.suspend(() => {
1004
- let sink = Sink.drain;
1005
- if (Predicate.isNotNull(proc.stdin)) {
1006
- sink = NodeSink.fromWritable({
1007
- evaluate: () => proc.stdin,
1008
- onError: (err) => toPlatformError("fromWritable(stdin)", toError(err), command),
1009
- endOnDone: cfg.endOnDone,
1010
- encoding: cfg.encoding
1011
- });
1012
- }
1013
- if (Stream.isStream(cfg.stream)) return Effect3.as(Effect3.forkScoped(Stream.run(cfg.stream, sink)), sink);
1014
- return Effect3.succeed(sink);
1015
- });
1016
- const setupOutput = (command, proc, out, err) => {
1017
- let stdout = proc.stdout ? NodeStream.fromReadable({
1018
- evaluate: () => proc.stdout,
1019
- onError: (cause) => toPlatformError("fromReadable(stdout)", toError(cause), command)
1020
- }) : Stream.empty;
1021
- let stderr = proc.stderr ? NodeStream.fromReadable({
1022
- evaluate: () => proc.stderr,
1023
- onError: (cause) => toPlatformError("fromReadable(stderr)", toError(cause), command)
1024
- }) : Stream.empty;
1025
- if (Sink.isSink(out.stream)) stdout = Stream.transduce(stdout, out.stream);
1026
- if (Sink.isSink(err.stream)) stderr = Stream.transduce(stderr, err.stream);
1027
- return { stdout, stderr, all: Stream.merge(stdout, stderr) };
1028
- };
1029
- const spawn = (command, opts) => Effect3.callback((resume) => {
1030
- const signal = Deferred.makeUnsafe();
1031
- const proc = launch(command.command, command.args, opts);
1032
- let end = false;
1033
- let exit;
1034
- proc.on("error", (err) => {
1035
- resume(Effect3.fail(toPlatformError("spawn", err, command)));
1036
- });
1037
- proc.on("exit", (...args) => {
1038
- exit = args;
1039
- });
1040
- proc.on("close", (...args) => {
1041
- if (end) return;
1042
- end = true;
1043
- Deferred.doneUnsafe(signal, Exit.succeed(exit ?? args));
1044
- });
1045
- proc.on("spawn", () => {
1046
- resume(Effect3.succeed([proc, signal]));
1047
- });
1048
- return Effect3.sync(() => {
1049
- proc.kill("SIGTERM");
1050
- });
1051
- });
1052
- const killGroup = (command, proc, signal) => {
1053
- if (globalThis.process.platform === "win32") {
1054
- return Effect3.callback((resume) => {
1055
- NodeChildProcess.exec(`taskkill /pid ${proc.pid} /T /F`, { windowsHide: true }, (err) => {
1056
- if (err) return resume(Effect3.fail(toPlatformError("kill", toError(err), command)));
1057
- resume(Effect3.void);
1058
- });
1059
- });
1060
- }
1061
- return Effect3.try({
1062
- try: () => {
1063
- globalThis.process.kill(-proc.pid, signal);
1064
- },
1065
- catch: (err) => toPlatformError("kill", toError(err), command)
1066
- });
1067
- };
1068
- const killOne = (command, proc, signal) => Effect3.suspend(() => {
1069
- if (proc.kill(signal)) return Effect3.void;
1070
- return Effect3.fail(toPlatformError("kill", new Error("Failed to kill child process"), command));
1071
- });
1072
- const timeout = (proc, command, opts) => (f) => {
1073
- const signal = opts?.killSignal ?? "SIGTERM";
1074
- if (Predicate.isUndefined(opts?.forceKillAfter)) return f(command, proc, signal);
1075
- return Effect3.timeoutOrElse(f(command, proc, signal), {
1076
- duration: opts.forceKillAfter,
1077
- orElse: () => f(command, proc, "SIGKILL")
1078
- });
1079
- };
1080
- const source = (handle, from) => {
1081
- const opt = from ?? "stdout";
1082
- switch (opt) {
1083
- case "stdout":
1084
- return handle.stdout;
1085
- case "stderr":
1086
- return handle.stderr;
1087
- case "all":
1088
- return handle.all;
1089
- default: {
1090
- const fd = ChildProcess.parseFdName(opt);
1091
- return Predicate.isNotUndefined(fd) ? handle.getOutputFd(fd) : handle.stdout;
1092
- }
1093
- }
1094
- };
1095
- const spawnCommand = Effect3.fnUntraced(
1096
- function* (command) {
1097
- switch (command._tag) {
1098
- case "StandardCommand": {
1099
- const sin = stdin(command.options);
1100
- const sout = stdio(command.options, "stdout");
1101
- const serr = stdio(command.options, "stderr");
1102
- const extra = fds(command.options);
1103
- const dir = yield* cwd(command.options);
1104
- const [proc, signal] = yield* Effect3.acquireRelease(
1105
- spawn(command, {
1106
- cwd: dir,
1107
- env: env(command.options),
1108
- stdio: stdios(sin, sout, serr, extra),
1109
- detached: command.options.detached ?? process.platform !== "win32",
1110
- shell: command.options.shell,
1111
- windowsHide: process.platform === "win32"
1112
- }),
1113
- Effect3.fnUntraced(function* ([proc2, signal2]) {
1114
- const done = yield* Deferred.isDone(signal2);
1115
- const kill = timeout(proc2, command, command.options);
1116
- if (done) {
1117
- const [code] = yield* Deferred.await(signal2);
1118
- if (process.platform === "win32") return yield* Effect3.void;
1119
- if (code !== 0 && Predicate.isNotNull(code)) return yield* Effect3.ignore(kill(killGroup));
1120
- return yield* Effect3.void;
1121
- }
1122
- const send = (s) => Effect3.catch(killGroup(command, proc2, s), () => killOne(command, proc2, s));
1123
- const sig = command.options.killSignal ?? "SIGTERM";
1124
- const attempt = send(sig).pipe(Effect3.andThen(Deferred.await(signal2)), Effect3.asVoid);
1125
- const escalated = command.options.forceKillAfter ? Effect3.timeoutOrElse(attempt, {
1126
- duration: command.options.forceKillAfter,
1127
- orElse: () => send("SIGKILL").pipe(Effect3.andThen(Deferred.await(signal2)), Effect3.asVoid)
1128
- }) : attempt;
1129
- return yield* Effect3.ignore(escalated);
1130
- })
1131
- );
1132
- const fd = yield* setupFds(command, proc, extra);
1133
- const out = setupOutput(command, proc, sout, serr);
1134
- return makeHandle({
1135
- pid: ProcessId(proc.pid),
1136
- stdin: yield* setupStdin(command, proc, sin),
1137
- stdout: out.stdout,
1138
- stderr: out.stderr,
1139
- all: out.all,
1140
- getInputFd: fd.getInputFd,
1141
- getOutputFd: fd.getOutputFd,
1142
- isRunning: Effect3.map(Deferred.isDone(signal), (done) => !done),
1143
- exitCode: Effect3.flatMap(Deferred.await(signal), ([code, signal2]) => {
1144
- if (Predicate.isNotNull(code)) return Effect3.succeed(ExitCode(code));
1145
- return Effect3.fail(
1146
- toPlatformError(
1147
- "exitCode",
1148
- new Error(`Process interrupted due to receipt of signal: '${signal2}'`),
1149
- command
1150
- )
1151
- );
1152
- }),
1153
- kill: (opts) => {
1154
- const sig = opts?.killSignal ?? "SIGTERM";
1155
- const send = (s) => Effect3.catch(killGroup(command, proc, s), () => killOne(command, proc, s));
1156
- const attempt = send(sig).pipe(Effect3.andThen(Deferred.await(signal)), Effect3.asVoid);
1157
- if (!opts?.forceKillAfter) return attempt;
1158
- return Effect3.timeoutOrElse(attempt, {
1159
- duration: opts.forceKillAfter,
1160
- orElse: () => send("SIGKILL").pipe(Effect3.andThen(Deferred.await(signal)), Effect3.asVoid)
1161
- });
1162
- }
1163
- });
1164
- }
1165
- case "PipedCommand": {
1166
- const flat = flatten(command);
1167
- const [head, ...tail] = flat.commands;
1168
- let handle = spawnCommand(head);
1169
- for (let i = 0; i < tail.length; i++) {
1170
- const next = tail[i];
1171
- const opts = flat.opts[i] ?? {};
1172
- const sin = stdin(next.options);
1173
- const stream = Stream.unwrap(Effect3.map(handle, (x) => source(x, opts.from)));
1174
- const to = opts.to ?? "stdin";
1175
- if (to === "stdin") {
1176
- handle = spawnCommand(
1177
- ChildProcess.make(next.command, next.args, {
1178
- ...next.options,
1179
- stdin: { ...sin, stream }
1180
- })
1181
- );
1182
- continue;
1183
- }
1184
- const fd = ChildProcess.parseFdName(to);
1185
- if (Predicate.isUndefined(fd)) {
1186
- handle = spawnCommand(
1187
- ChildProcess.make(next.command, next.args, {
1188
- ...next.options,
1189
- stdin: { ...sin, stream }
1190
- })
1191
- );
1192
- continue;
1193
- }
1194
- handle = spawnCommand(
1195
- ChildProcess.make(next.command, next.args, {
1196
- ...next.options,
1197
- additionalFds: {
1198
- ...next.options.additionalFds,
1199
- [ChildProcess.fdName(fd)]: { type: "input", stream }
1200
- }
1201
- })
1202
- );
1203
- }
1204
- return yield* handle;
1205
- }
1206
- }
1207
- }
1208
- );
1209
- return makeSpawner(spawnCommand);
1210
- });
1211
- var layer2 = Layer2.effect(
1212
- ChildProcessSpawner,
1213
- make2
1214
- );
1215
- var defaultLayer = layer2.pipe(Layer2.provide(NodeFileSystem2.layer), Layer2.provide(NodePath.layer));
1216
- var rt = lazy(async () => {
1217
- const { makeRuntime: makeRuntime2 } = await import("./run-service-B4BDQWO3.js");
1218
- return makeRuntime2(ChildProcessSpawner, defaultLayer);
1219
- });
1220
- var runPromiseExit = async (...args) => (await rt()).runPromiseExit(...args);
1221
-
1222
- // packages/opencode/src/project/project.ts
1223
- var Project;
1224
- ((Project2) => {
1225
- const log2 = Log.create({ service: "project" });
1226
- Project2.Info = z5.object({
1227
- id: ProjectID.zod,
1228
- worktree: z5.string(),
1229
- vcs: z5.literal("git").optional(),
1230
- name: z5.string().optional(),
1231
- icon: z5.object({
1232
- url: z5.string().optional(),
1233
- override: z5.string().optional(),
1234
- color: z5.string().optional()
1235
- }).optional(),
1236
- commands: z5.object({
1237
- start: z5.string().optional().describe("Startup script to run when creating a new workspace (worktree)")
1238
- }).optional(),
1239
- time: z5.object({
1240
- created: z5.number(),
1241
- updated: z5.number(),
1242
- initialized: z5.number().optional()
1243
- }),
1244
- sandboxes: z5.array(z5.string())
1245
- }).meta({
1246
- ref: "Project"
1247
- });
1248
- Project2.Event = {
1249
- Updated: BusEvent.define("project.updated", Project2.Info)
1250
- };
1251
- function fromRow(row) {
1252
- const icon = row.icon_url || row.icon_color ? { url: row.icon_url ?? void 0, color: row.icon_color ?? void 0 } : void 0;
1253
- return {
1254
- id: row.id,
1255
- worktree: row.worktree,
1256
- vcs: row.vcs ? Project2.Info.shape.vcs.parse(row.vcs) : void 0,
1257
- name: row.name ?? void 0,
1258
- icon,
1259
- time: {
1260
- created: row.time_created,
1261
- updated: row.time_updated,
1262
- initialized: row.time_initialized ?? void 0
1263
- },
1264
- sandboxes: row.sandboxes,
1265
- commands: row.commands ?? void 0
1266
- };
1267
- }
1268
- Project2.fromRow = fromRow;
1269
- Project2.UpdateInput = z5.object({
1270
- projectID: ProjectID.zod,
1271
- name: z5.string().optional(),
1272
- icon: Project2.Info.shape.icon.optional(),
1273
- commands: Project2.Info.shape.commands.optional()
1274
- });
1275
- class Service extends ServiceMap4.Service()("@opencode/Project") {
1276
- }
1277
- Project2.Service = Service;
1278
- Project2.layer = Layer3.effect(
1279
- Service,
1280
- Effect4.gen(function* () {
1281
- const fs = yield* AppFileSystem.Service;
1282
- const pathSvc = yield* Path3.Path;
1283
- const spawner = yield* ChildProcessSpawner2.ChildProcessSpawner;
1284
- const git = Effect4.fnUntraced(
1285
- function* (args, opts) {
1286
- const handle = yield* spawner.spawn(
1287
- ChildProcess2.make("git", args, { cwd: opts?.cwd, extendEnv: true, stdin: "ignore" })
1288
- );
1289
- const [text3, stderr] = yield* Effect4.all(
1290
- [Stream2.mkString(Stream2.decodeText(handle.stdout)), Stream2.mkString(Stream2.decodeText(handle.stderr))],
1291
- { concurrency: 2 }
1292
- );
1293
- const code = yield* handle.exitCode;
1294
- return { code, text: text3, stderr };
1295
- },
1296
- Effect4.scoped,
1297
- Effect4.catch(() => Effect4.succeed({ code: 1, text: "", stderr: "" }))
1298
- );
1299
- const db = (fn) => Effect4.sync(() => Database.use(fn));
1300
- const emitUpdated = (data) => Effect4.sync(
1301
- () => GlobalBus.emit("event", {
1302
- payload: { type: Project2.Event.Updated.type, properties: data }
1303
- })
1304
- );
1305
- const fakeVcs = Project2.Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS);
1306
- const resolveGitPath = (cwd, name) => {
1307
- if (!name) return cwd;
1308
- name = name.replace(/[\r\n]+$/, "");
1309
- if (!name) return cwd;
1310
- name = AppFileSystem.windowsPath(name);
1311
- if (pathSvc.isAbsolute(name)) return pathSvc.normalize(name);
1312
- return pathSvc.resolve(cwd, name);
1313
- };
1314
- const scope = yield* Scope2.Scope;
1315
- const readCachedProjectId = Effect4.fnUntraced(function* (dir) {
1316
- return yield* fs.readFileString(pathSvc.join(dir, "opencode")).pipe(
1317
- Effect4.map((x) => x.trim()),
1318
- Effect4.map(ProjectID.make),
1319
- Effect4.catch(() => Effect4.succeed(void 0))
1320
- );
1321
- });
1322
- const fromDirectory2 = Effect4.fn("Project.fromDirectory")(function* (directory) {
1323
- log2.info("fromDirectory", { directory });
1324
- const data = yield* Effect4.gen(function* () {
1325
- const dotgitMatches = yield* fs.up({ targets: [".git"], start: directory }).pipe(Effect4.orDie);
1326
- const dotgit = dotgitMatches[0];
1327
- if (!dotgit) {
1328
- return {
1329
- id: ProjectID.global,
1330
- worktree: "/",
1331
- sandbox: "/",
1332
- vcs: fakeVcs
1333
- };
1334
- }
1335
- let sandbox = pathSvc.dirname(dotgit);
1336
- const gitBinary = yield* Effect4.sync(() => which("git"));
1337
- let id = yield* readCachedProjectId(dotgit);
1338
- if (!gitBinary) {
1339
- return {
1340
- id: id ?? ProjectID.global,
1341
- worktree: sandbox,
1342
- sandbox,
1343
- vcs: fakeVcs
1344
- };
1345
- }
1346
- const commonDir = yield* git(["rev-parse", "--git-common-dir"], { cwd: sandbox });
1347
- if (commonDir.code !== 0) {
1348
- return {
1349
- id: id ?? ProjectID.global,
1350
- worktree: sandbox,
1351
- sandbox,
1352
- vcs: fakeVcs
1353
- };
1354
- }
1355
- const worktree = (() => {
1356
- const common = resolveGitPath(sandbox, commonDir.text.trim());
1357
- return common === sandbox ? sandbox : pathSvc.dirname(common);
1358
- })();
1359
- if (id == null) {
1360
- id = yield* readCachedProjectId(pathSvc.join(worktree, ".git"));
1361
- }
1362
- if (!id) {
1363
- const revList = yield* git(["rev-list", "--max-parents=0", "HEAD"], { cwd: sandbox });
1364
- const roots = revList.text.split("\n").filter(Boolean).map((x) => x.trim()).toSorted();
1365
- id = roots[0] ? ProjectID.make(roots[0]) : void 0;
1366
- if (id) {
1367
- yield* fs.writeFileString(pathSvc.join(worktree, ".git", "opencode"), id).pipe(Effect4.ignore);
1368
- }
1369
- }
1370
- if (!id) {
1371
- return { id: ProjectID.global, worktree: sandbox, sandbox, vcs: "git" };
1372
- }
1373
- const topLevel = yield* git(["rev-parse", "--show-toplevel"], { cwd: sandbox });
1374
- if (topLevel.code !== 0) {
1375
- return {
1376
- id,
1377
- worktree: sandbox,
1378
- sandbox,
1379
- vcs: fakeVcs
1380
- };
1381
- }
1382
- sandbox = resolveGitPath(sandbox, topLevel.text.trim());
1383
- return { id, sandbox, worktree, vcs: "git" };
1384
- });
1385
- const row = yield* db((d) => d.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, data.id)).get());
1386
- const existing = row ? fromRow(row) : {
1387
- id: data.id,
1388
- worktree: data.worktree,
1389
- vcs: data.vcs,
1390
- sandboxes: [],
1391
- time: { created: Date.now(), updated: Date.now() }
1392
- };
1393
- if (Flag.OPENCODE_EXPERIMENTAL_ICON_DISCOVERY)
1394
- yield* discover2(existing).pipe(Effect4.ignore, Effect4.forkIn(scope));
1395
- const result = {
1396
- ...existing,
1397
- worktree: data.worktree,
1398
- vcs: data.vcs,
1399
- time: { ...existing.time, updated: Date.now() }
1400
- };
1401
- if (data.sandbox !== result.worktree && !result.sandboxes.includes(data.sandbox))
1402
- result.sandboxes.push(data.sandbox);
1403
- result.sandboxes = yield* Effect4.forEach(
1404
- result.sandboxes,
1405
- (s) => fs.exists(s).pipe(
1406
- Effect4.orDie,
1407
- Effect4.map((exists) => exists ? s : void 0)
1408
- ),
1409
- { concurrency: "unbounded" }
1410
- ).pipe(Effect4.map((arr) => arr.filter((x) => x !== void 0)));
1411
- yield* db(
1412
- (d) => d.insert(ProjectTable).values({
1413
- id: result.id,
1414
- worktree: result.worktree,
1415
- vcs: result.vcs ?? null,
1416
- name: result.name,
1417
- icon_url: result.icon?.url,
1418
- icon_color: result.icon?.color,
1419
- time_created: result.time.created,
1420
- time_updated: result.time.updated,
1421
- time_initialized: result.time.initialized,
1422
- sandboxes: result.sandboxes,
1423
- commands: result.commands
1424
- }).onConflictDoUpdate({
1425
- target: ProjectTable.id,
1426
- set: {
1427
- worktree: result.worktree,
1428
- vcs: result.vcs ?? null,
1429
- name: result.name,
1430
- icon_url: result.icon?.url,
1431
- icon_color: result.icon?.color,
1432
- time_updated: result.time.updated,
1433
- time_initialized: result.time.initialized,
1434
- sandboxes: result.sandboxes,
1435
- commands: result.commands
1436
- }
1437
- }).run()
1438
- );
1439
- if (data.id !== ProjectID.global) {
1440
- yield* db(
1441
- (d) => d.update(SessionTable).set({ project_id: data.id }).where((0, db_exports.and)((0, db_exports.eq)(SessionTable.project_id, ProjectID.global), (0, db_exports.eq)(SessionTable.directory, data.worktree))).run()
1442
- );
1443
- }
1444
- yield* emitUpdated(result);
1445
- return { project: result, sandbox: data.sandbox };
1446
- });
1447
- const discover2 = Effect4.fn("Project.discover")(function* (input) {
1448
- if (input.vcs !== "git") return;
1449
- if (input.icon?.override) return;
1450
- if (input.icon?.url) return;
1451
- const matches = yield* fs.glob("**/favicon.{ico,png,svg,jpg,jpeg,webp}", {
1452
- cwd: input.worktree,
1453
- absolute: true,
1454
- include: "file"
1455
- }).pipe(Effect4.orDie);
1456
- const shortest = matches.sort((a, b) => a.length - b.length)[0];
1457
- if (!shortest) return;
1458
- const buffer = yield* fs.readFile(shortest).pipe(Effect4.orDie);
1459
- const base64 = Buffer.from(buffer).toString("base64");
1460
- const mime = AppFileSystem.mimeType(shortest);
1461
- const url = `data:${mime};base64,${base64}`;
1462
- yield* update2({ projectID: input.id, icon: { url } });
1463
- });
1464
- const list2 = Effect4.fn("Project.list")(function* () {
1465
- return yield* db((d) => d.select().from(ProjectTable).all().map(fromRow));
1466
- });
1467
- const get2 = Effect4.fn("Project.get")(function* (id) {
1468
- const row = yield* db((d) => d.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, id)).get());
1469
- return row ? fromRow(row) : void 0;
1470
- });
1471
- const update2 = Effect4.fn("Project.update")(function* (input) {
1472
- const result = yield* db(
1473
- (d) => d.update(ProjectTable).set({
1474
- name: input.name,
1475
- icon_url: input.icon?.url,
1476
- icon_color: input.icon?.color,
1477
- commands: input.commands,
1478
- time_updated: Date.now()
1479
- }).where((0, db_exports.eq)(ProjectTable.id, input.projectID)).returning().get()
1480
- );
1481
- if (!result) throw new Error(`Project not found: ${input.projectID}`);
1482
- const data = fromRow(result);
1483
- yield* emitUpdated(data);
1484
- return data;
1485
- });
1486
- const initGit2 = Effect4.fn("Project.initGit")(function* (input) {
1487
- if (input.project.vcs === "git") return input.project;
1488
- if (!(yield* Effect4.sync(() => which("git")))) throw new Error("Git is not installed");
1489
- const result = yield* git(["init", "--quiet"], { cwd: input.directory });
1490
- if (result.code !== 0) {
1491
- throw new Error(result.stderr.trim() || result.text.trim() || "Failed to initialize git repository");
1492
- }
1493
- const { project } = yield* fromDirectory2(input.directory);
1494
- return project;
1495
- });
1496
- const setInitialized2 = Effect4.fn("Project.setInitialized")(function* (id) {
1497
- yield* db(
1498
- (d) => d.update(ProjectTable).set({ time_initialized: Date.now() }).where((0, db_exports.eq)(ProjectTable.id, id)).run()
1499
- );
1500
- });
1501
- const sandboxes2 = Effect4.fn("Project.sandboxes")(function* (id) {
1502
- const row = yield* db((d) => d.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, id)).get());
1503
- if (!row) return [];
1504
- const data = fromRow(row);
1505
- return yield* Effect4.forEach(
1506
- data.sandboxes,
1507
- (dir) => fs.isDir(dir).pipe(
1508
- Effect4.orDie,
1509
- Effect4.map((ok) => ok ? dir : void 0)
1510
- ),
1511
- { concurrency: "unbounded" }
1512
- ).pipe(Effect4.map((arr) => arr.filter((x) => x !== void 0)));
1513
- });
1514
- const addSandbox2 = Effect4.fn("Project.addSandbox")(function* (id, directory) {
1515
- const row = yield* db((d) => d.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, id)).get());
1516
- if (!row) throw new Error(`Project not found: ${id}`);
1517
- const sboxes = [...row.sandboxes];
1518
- if (!sboxes.includes(directory)) sboxes.push(directory);
1519
- const result = yield* db(
1520
- (d) => d.update(ProjectTable).set({ sandboxes: sboxes, time_updated: Date.now() }).where((0, db_exports.eq)(ProjectTable.id, id)).returning().get()
1521
- );
1522
- if (!result) throw new Error(`Project not found: ${id}`);
1523
- yield* emitUpdated(fromRow(result));
1524
- });
1525
- const removeSandbox2 = Effect4.fn("Project.removeSandbox")(function* (id, directory) {
1526
- const row = yield* db((d) => d.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, id)).get());
1527
- if (!row) throw new Error(`Project not found: ${id}`);
1528
- const sboxes = row.sandboxes.filter((s) => s !== directory);
1529
- const result = yield* db(
1530
- (d) => d.update(ProjectTable).set({ sandboxes: sboxes, time_updated: Date.now() }).where((0, db_exports.eq)(ProjectTable.id, id)).returning().get()
1531
- );
1532
- if (!result) throw new Error(`Project not found: ${id}`);
1533
- yield* emitUpdated(fromRow(result));
1534
- });
1535
- return Service.of({
1536
- fromDirectory: fromDirectory2,
1537
- discover: discover2,
1538
- list: list2,
1539
- get: get2,
1540
- update: update2,
1541
- initGit: initGit2,
1542
- setInitialized: setInitialized2,
1543
- sandboxes: sandboxes2,
1544
- addSandbox: addSandbox2,
1545
- removeSandbox: removeSandbox2
1546
- });
1547
- })
1548
- );
1549
- Project2.defaultLayer = Project2.layer.pipe(
1550
- Layer3.provide(defaultLayer),
1551
- Layer3.provide(AppFileSystem.defaultLayer),
1552
- Layer3.provide(NodePath2.layer)
1553
- );
1554
- const { runPromise } = makeRuntime(Service, Project2.defaultLayer);
1555
- function fromDirectory(directory) {
1556
- return runPromise((svc) => svc.fromDirectory(directory));
1557
- }
1558
- Project2.fromDirectory = fromDirectory;
1559
- function discover(input) {
1560
- return runPromise((svc) => svc.discover(input));
1561
- }
1562
- Project2.discover = discover;
1563
- function list() {
1564
- return Database.use(
1565
- (db) => db.select().from(ProjectTable).all().map((row) => fromRow(row))
1566
- );
1567
- }
1568
- Project2.list = list;
1569
- function get(id) {
1570
- const row = Database.use((db) => db.select().from(ProjectTable).where((0, db_exports.eq)(ProjectTable.id, id)).get());
1571
- if (!row) return void 0;
1572
- return fromRow(row);
1573
- }
1574
- Project2.get = get;
1575
- function setInitialized(id) {
1576
- Database.use(
1577
- (db) => db.update(ProjectTable).set({ time_initialized: Date.now() }).where((0, db_exports.eq)(ProjectTable.id, id)).run()
1578
- );
1579
- }
1580
- Project2.setInitialized = setInitialized;
1581
- function initGit(input) {
1582
- return runPromise((svc) => svc.initGit(input));
1583
- }
1584
- Project2.initGit = initGit;
1585
- function update(input) {
1586
- return runPromise((svc) => svc.update(input));
1587
- }
1588
- Project2.update = update;
1589
- function sandboxes(id) {
1590
- return runPromise((svc) => svc.sandboxes(id));
1591
- }
1592
- Project2.sandboxes = sandboxes;
1593
- function addSandbox(id, directory) {
1594
- return runPromise((svc) => svc.addSandbox(id, directory));
1595
- }
1596
- Project2.addSandbox = addSandbox;
1597
- function removeSandbox(id, directory) {
1598
- return runPromise((svc) => svc.removeSandbox(id, directory));
1599
- }
1600
- Project2.removeSandbox = removeSandbox;
1601
- })(Project || (Project = {}));
1602
-
1603
- // packages/opencode/src/project/state.ts
1604
- var State;
1605
- ((State2) => {
1606
- const log2 = Log.create({ service: "state" });
1607
- const recordsByKey = /* @__PURE__ */ new Map();
1608
- function create(root, init2, dispose2) {
1609
- return () => {
1610
- const key = root();
1611
- let entries = recordsByKey.get(key);
1612
- if (!entries) {
1613
- entries = /* @__PURE__ */ new Map();
1614
- recordsByKey.set(key, entries);
1615
- }
1616
- const exists = entries.get(init2);
1617
- if (exists) return exists.state;
1618
- const state = init2();
1619
- entries.set(init2, {
1620
- state,
1621
- dispose: dispose2
1622
- });
1623
- return state;
1624
- };
1625
- }
1626
- State2.create = create;
1627
- async function dispose(key) {
1628
- const entries = recordsByKey.get(key);
1629
- if (!entries) return;
1630
- log2.info("waiting for state disposal to complete", { key });
1631
- let disposalFinished = false;
1632
- setTimeout(() => {
1633
- if (!disposalFinished) {
1634
- log2.warn(
1635
- "state disposal is taking an unusually long time - if it does not complete in a reasonable time, please report this as a bug",
1636
- { key }
1637
- );
1638
- }
1639
- }, 1e4).unref();
1640
- const tasks = [];
1641
- for (const [init2, entry] of entries) {
1642
- if (!entry.dispose) continue;
1643
- const label = typeof init2 === "function" ? init2.name : String(init2);
1644
- const task = Promise.resolve(entry.state).then((state) => entry.dispose(state)).catch((error) => {
1645
- log2.error("Error while disposing state:", { error, key, init: label });
1646
- });
1647
- tasks.push(task);
1648
- }
1649
- await Promise.all(tasks);
1650
- entries.clear();
1651
- recordsByKey.delete(key);
1652
- disposalFinished = true;
1653
- log2.info("state disposal completed", { key });
1654
- }
1655
- State2.dispose = dispose;
1656
- })(State || (State = {}));
1657
-
1658
- // packages/opencode/src/project/instance.ts
1659
- var context = Context.create("instance");
1660
- var cache = /* @__PURE__ */ new Map();
1661
- var disposal = {
1662
- all: void 0
1663
- };
1664
- function emit(directory) {
1665
- GlobalBus.emit("event", {
1666
- directory,
1667
- payload: {
1668
- type: "server.instance.disposed",
1669
- properties: {
1670
- directory
1671
- }
1672
- }
1673
- });
1674
- }
1675
- function boot(input) {
1676
- return iife(async () => {
1677
- const ctx = input.project && input.worktree ? {
1678
- directory: input.directory,
1679
- worktree: input.worktree,
1680
- project: input.project
1681
- } : await Project.fromDirectory(input.directory).then(({ project, sandbox }) => ({
1682
- directory: input.directory,
1683
- worktree: sandbox,
1684
- project
1685
- }));
1686
- await context.provide(ctx, async () => {
1687
- await input.init?.();
1688
- });
1689
- return ctx;
1690
- });
1691
- }
1692
- function track(directory, next) {
1693
- const task = next.catch((error) => {
1694
- if (cache.get(directory) === task) cache.delete(directory);
1695
- throw error;
1696
- });
1697
- cache.set(directory, task);
1698
- return task;
1699
- }
1700
- var Instance = {
1701
- async provide(input) {
1702
- const directory = Filesystem.resolve(input.directory);
1703
- let existing = cache.get(directory);
1704
- if (!existing) {
1705
- Log.Default.info("creating instance", { directory });
1706
- existing = track(
1707
- directory,
1708
- boot({
1709
- directory,
1710
- init: input.init
1711
- })
1712
- );
1713
- }
1714
- const ctx = await existing;
1715
- return context.provide(ctx, async () => {
1716
- return input.fn();
1717
- });
1718
- },
1719
- get current() {
1720
- return context.use();
1721
- },
1722
- get directory() {
1723
- return context.use().directory;
1724
- },
1725
- get worktree() {
1726
- return context.use().worktree;
1727
- },
1728
- get project() {
1729
- return context.use().project;
1730
- },
1731
- /**
1732
- * Check if a path is within the project boundary.
1733
- * Returns true if path is inside Instance.directory OR Instance.worktree.
1734
- * Paths within the worktree but outside the working directory should not trigger external_directory permission.
1735
- */
1736
- containsPath(filepath) {
1737
- if (Filesystem.contains(Instance.directory, filepath)) return true;
1738
- if (Instance.worktree === "/") return false;
1739
- return Filesystem.contains(Instance.worktree, filepath);
1740
- },
1741
- /**
1742
- * Captures the current instance ALS context and returns a wrapper that
1743
- * restores it when called. Use this for callbacks that fire outside the
1744
- * instance async context (native addons, event emitters, timers, etc.).
1745
- */
1746
- bind(fn) {
1747
- const ctx = context.use();
1748
- return ((...args) => context.provide(ctx, () => fn(...args)));
1749
- },
1750
- /**
1751
- * Run a synchronous function within the given instance context ALS.
1752
- * Use this to bridge from Effect (where InstanceRef carries context)
1753
- * back to sync code that reads Instance.directory from ALS.
1754
- */
1755
- restore(ctx, fn) {
1756
- return context.provide(ctx, fn);
1757
- },
1758
- state(init2, dispose) {
1759
- return State.create(() => Instance.directory, init2, dispose);
1760
- },
1761
- async reload(input) {
1762
- const directory = Filesystem.resolve(input.directory);
1763
- Log.Default.info("reloading instance", { directory });
1764
- await Promise.all([State.dispose(directory), disposeInstance(directory)]);
1765
- cache.delete(directory);
1766
- const next = track(directory, boot({ ...input, directory }));
1767
- emit(directory);
1768
- return await next;
1769
- },
1770
- async dispose() {
1771
- const directory = Instance.directory;
1772
- Log.Default.info("disposing instance", { directory });
1773
- await Promise.all([State.dispose(directory), disposeInstance(directory)]);
1774
- cache.delete(directory);
1775
- emit(directory);
1776
- },
1777
- async disposeAll() {
1778
- if (disposal.all) return disposal.all;
1779
- disposal.all = iife(async () => {
1780
- Log.Default.info("disposing all instances");
1781
- const entries = [...cache.entries()];
1782
- for (const [key, value] of entries) {
1783
- if (cache.get(key) !== value) continue;
1784
- const ctx = await value.catch((error) => {
1785
- Log.Default.warn("instance dispose failed", { key, error });
1786
- return void 0;
1787
- });
1788
- if (!ctx) {
1789
- if (cache.get(key) === value) cache.delete(key);
1790
- continue;
1791
- }
1792
- if (cache.get(key) !== value) continue;
1793
- await context.provide(ctx, async () => {
1794
- await Instance.dispose();
1795
- });
1796
- }
1797
- }).finally(() => {
1798
- disposal.all = void 0;
1799
- });
1800
- return disposal.all;
1801
- }
1802
- };
1803
-
1804
- // packages/opencode/src/effect/run-service.ts
1805
- var memoMap = Layer4.makeMemoMapUnsafe();
1806
- function attach(effect2) {
1807
- try {
1808
- const ctx = Instance.current;
1809
- return Effect5.provideService(effect2, InstanceRef, ctx);
1810
- } catch (err) {
1811
- if (!(err instanceof Context.NotFound)) throw err;
1812
- }
1813
- return effect2;
1814
- }
1815
- function makeRuntime(service, layer3) {
1816
- let rt2;
1817
- const getRuntime = () => rt2 ??= ManagedRuntime.make(layer3, { memoMap });
1818
- return {
1819
- runSync: (fn) => getRuntime().runSync(attach(service.use(fn))),
1820
- runPromiseExit: (fn, options) => getRuntime().runPromiseExit(attach(service.use(fn)), options),
1821
- runPromise: (fn, options) => getRuntime().runPromise(attach(service.use(fn)), options),
1822
- runFork: (fn) => getRuntime().runFork(attach(service.use(fn))),
1823
- runCallback: (fn) => getRuntime().runCallback(attach(service.use(fn)))
1824
- };
1825
- }
1826
-
1827
- export {
1828
- GlobalBus,
1829
- iife,
1830
- lazy,
1831
- NamedError,
1832
- Flag,
1833
- VERSION,
1834
- CHANNEL,
1835
- InstanceState,
1836
- NotFoundError,
1837
- Database,
1838
- db_exports,
1839
- Timestamps,
1840
- ProjectTable,
1841
- SessionTable,
1842
- MessageTable,
1843
- PartTable,
1844
- TodoTable,
1845
- PermissionTable,
1846
- BusEvent,
1847
- which,
1848
- ProjectID,
1849
- AppFileSystem,
1850
- defaultLayer,
1851
- runPromiseExit,
1852
- Project,
1853
- Instance,
1854
- memoMap,
1855
- makeRuntime
1856
- };
1857
- //# sourceMappingURL=chunk-SZM3G6UF.js.map