sleev 0.0.12 → 0.0.13

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 (143) hide show
  1. package/README.md +19 -39
  2. package/dist/auth/browser.d.ts +12 -0
  3. package/dist/auth/browser.js +33 -24
  4. package/dist/auth/browser.js.map +1 -0
  5. package/dist/auth/firebase-tokens.d.ts +39 -0
  6. package/dist/auth/firebase-tokens.js +173 -0
  7. package/dist/auth/firebase-tokens.js.map +1 -0
  8. package/dist/auth/firebase.d.ts +17 -0
  9. package/dist/auth/firebase.js +55 -0
  10. package/dist/auth/firebase.js.map +1 -0
  11. package/dist/auth/login.d.ts +22 -0
  12. package/dist/auth/login.js +31 -28
  13. package/dist/auth/login.js.map +1 -0
  14. package/dist/auth/loopback.d.ts +19 -0
  15. package/dist/auth/loopback.js +114 -44
  16. package/dist/auth/loopback.js.map +1 -0
  17. package/dist/auth/schema.d.ts +26 -0
  18. package/dist/auth/schema.js +59 -17
  19. package/dist/auth/schema.js.map +1 -0
  20. package/dist/auth/token.d.ts +19 -0
  21. package/dist/auth/token.js +53 -0
  22. package/dist/auth/token.js.map +1 -0
  23. package/dist/auth/verify.d.ts +6 -0
  24. package/dist/auth/verify.js +22 -0
  25. package/dist/auth/verify.js.map +1 -0
  26. package/dist/cli.d.ts +8 -0
  27. package/dist/cli.js +245 -59
  28. package/dist/cli.js.map +1 -0
  29. package/dist/config/paths.d.ts +12 -0
  30. package/dist/config/paths.js +34 -0
  31. package/dist/config/paths.js.map +1 -0
  32. package/dist/config/store.d.ts +63 -0
  33. package/dist/config/store.js +270 -0
  34. package/dist/config/store.js.map +1 -0
  35. package/dist/control/local-installations.d.ts +13 -0
  36. package/dist/control/local-installations.js +37 -0
  37. package/dist/control/local-installations.js.map +1 -0
  38. package/dist/daemon/config.d.ts +10 -0
  39. package/dist/daemon/config.js +52 -0
  40. package/dist/daemon/config.js.map +1 -0
  41. package/dist/daemon/controller.d.ts +29 -0
  42. package/dist/daemon/controller.js +34 -0
  43. package/dist/daemon/controller.js.map +1 -0
  44. package/dist/daemon/health.d.ts +8 -0
  45. package/dist/daemon/health.js +47 -0
  46. package/dist/daemon/health.js.map +1 -0
  47. package/dist/daemon/start.d.ts +5 -0
  48. package/dist/daemon/start.js +24 -0
  49. package/dist/daemon/start.js.map +1 -0
  50. package/dist/daemon/systemd.d.ts +35 -0
  51. package/dist/daemon/systemd.js +181 -0
  52. package/dist/daemon/systemd.js.map +1 -0
  53. package/dist/gateway/acquire.d.ts +14 -0
  54. package/dist/gateway/acquire.js +112 -0
  55. package/dist/gateway/acquire.js.map +1 -0
  56. package/dist/gateway/manifest.d.ts +26 -0
  57. package/dist/gateway/manifest.js +98 -0
  58. package/dist/gateway/manifest.js.map +1 -0
  59. package/dist/gateway/platform.d.ts +5 -0
  60. package/dist/gateway/platform.js +27 -0
  61. package/dist/gateway/platform.js.map +1 -0
  62. package/dist/harness/claude.d.ts +8 -0
  63. package/dist/{apps → harness}/claude.js +28 -28
  64. package/dist/harness/claude.js.map +1 -0
  65. package/dist/harness/codex.d.ts +10 -0
  66. package/dist/{apps → harness}/codex.js +50 -45
  67. package/dist/harness/codex.js.map +1 -0
  68. package/dist/harness/index.d.ts +13 -0
  69. package/dist/harness/index.js +63 -0
  70. package/dist/harness/index.js.map +1 -0
  71. package/dist/harness/opencode-config.d.ts +8 -0
  72. package/dist/{apps → harness}/opencode-config.js +116 -83
  73. package/dist/harness/opencode-config.js.map +1 -0
  74. package/dist/harness/opencode.d.ts +14 -0
  75. package/dist/harness/opencode.js +50 -0
  76. package/dist/harness/opencode.js.map +1 -0
  77. package/dist/harness/providers.d.ts +8 -0
  78. package/dist/harness/providers.js +30 -0
  79. package/dist/harness/providers.js.map +1 -0
  80. package/dist/harness/types.d.ts +14 -0
  81. package/dist/harness/types.js +2 -0
  82. package/dist/harness/types.js.map +1 -0
  83. package/dist/product.d.ts +12 -0
  84. package/dist/product.js +53 -10
  85. package/dist/product.js.map +1 -0
  86. package/dist/tui/clipboard.d.ts +1 -0
  87. package/dist/tui/clipboard.js +48 -0
  88. package/dist/tui/clipboard.js.map +1 -0
  89. package/dist/tui/openTuiApp.d.ts +1 -0
  90. package/dist/tui/openTuiApp.js +1436 -0
  91. package/dist/tui/openTuiApp.js.map +1 -0
  92. package/dist/tui/pages/flow-screen.d.ts +50 -0
  93. package/dist/tui/pages/flow-screen.js +435 -0
  94. package/dist/tui/pages/flow-screen.js.map +1 -0
  95. package/dist/tui/pages/footer.d.ts +7 -0
  96. package/dist/tui/pages/footer.js +14 -0
  97. package/dist/tui/pages/footer.js.map +1 -0
  98. package/dist/tui/pages/home-screen.d.ts +19 -0
  99. package/dist/tui/pages/home-screen.js +89 -0
  100. package/dist/tui/pages/home-screen.js.map +1 -0
  101. package/dist/tui/pages/index.d.ts +17 -0
  102. package/dist/tui/pages/index.js +11 -0
  103. package/dist/tui/pages/index.js.map +1 -0
  104. package/dist/tui/pages/local-setup-screen.d.ts +23 -0
  105. package/dist/tui/pages/local-setup-screen.js +134 -0
  106. package/dist/tui/pages/local-setup-screen.js.map +1 -0
  107. package/dist/tui/pages/location-card.d.ts +19 -0
  108. package/dist/tui/pages/location-card.js +116 -0
  109. package/dist/tui/pages/location-card.js.map +1 -0
  110. package/dist/tui/pages/menu-screen.d.ts +24 -0
  111. package/dist/tui/pages/menu-screen.js +117 -0
  112. package/dist/tui/pages/menu-screen.js.map +1 -0
  113. package/dist/tui/pages/session-grid.d.ts +23 -0
  114. package/dist/tui/pages/session-grid.js +552 -0
  115. package/dist/tui/pages/session-grid.js.map +1 -0
  116. package/dist/tui/pages/setup-screen.d.ts +15 -0
  117. package/dist/tui/pages/setup-screen.js +80 -0
  118. package/dist/tui/pages/setup-screen.js.map +1 -0
  119. package/dist/tui/pages/terminal-log.d.ts +14 -0
  120. package/dist/tui/pages/terminal-log.js +104 -0
  121. package/dist/tui/pages/terminal-log.js.map +1 -0
  122. package/dist/tui/pages/welcome-screen.d.ts +16 -0
  123. package/dist/tui/pages/welcome-screen.js +80 -0
  124. package/dist/tui/pages/welcome-screen.js.map +1 -0
  125. package/dist/tui/saved-tokens.d.ts +10 -0
  126. package/dist/tui/saved-tokens.js +104 -0
  127. package/dist/tui/saved-tokens.js.map +1 -0
  128. package/dist/tui/theme.d.ts +25 -0
  129. package/dist/tui/theme.js +27 -0
  130. package/dist/tui/theme.js.map +1 -0
  131. package/package.json +55 -38
  132. package/dist/apps/opencode.js +0 -158
  133. package/dist/apps.js +0 -148
  134. package/dist/auth/command.js +0 -109
  135. package/dist/auth/index.js +0 -2
  136. package/dist/auth/validation.js +0 -27
  137. package/dist/credentials/index.js +0 -3
  138. package/dist/credentials/schema.js +0 -63
  139. package/dist/credentials/store.js +0 -52
  140. package/dist/harnesses.js +0 -66
  141. package/dist/index.js +0 -3
  142. package/dist/providers.js +0 -30
  143. package/dist/terminal.js +0 -55
@@ -1,20 +1,16 @@
1
- // OpenCode config ownership picks the active config file and edits its provider state.
2
- import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
3
- import { homedir } from 'node:os';
4
- import { dirname, join } from 'node:path';
5
- import { applyEdits, modify, parse } from 'jsonc-parser';
6
- import { provider as registryProvider } from '../providers.js';
7
- export async function patchOpenCodeConfig(auth, path, provider = 'openai') {
1
+ // OpenCode config ownership picks the active config file and edits provider state.
2
+ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { provider as registryProvider } from "./providers.js";
6
+ export async function patchOpenCodeConfig(auth, path, provider = "openai") {
8
7
  const target = path ?? (await resolveOpenCodePath());
9
8
  const existing = await readJson(target);
10
- await mkdir(dirname(target), { recursive: true, mode: 0o700 });
11
- if (jsoncPath(target)) {
12
- const raw = await readRaw(target);
13
- await writeFile(target, patchJsonc(raw, existing, auth, provider), { mode: 0o600 });
14
- return target;
15
- }
16
9
  const config = patchConfig(existing, auth, provider);
17
- await writeFile(target, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
10
+ await mkdir(dirname(target), { recursive: true, mode: 0o700 });
11
+ await writeFile(target, `${JSON.stringify(config, null, 2)}\n`, {
12
+ mode: 0o600,
13
+ });
18
14
  return target;
19
15
  }
20
16
  export async function unpatchOpenCodeConfig(path) {
@@ -23,32 +19,30 @@ export async function unpatchOpenCodeConfig(path) {
23
19
  if (!existing)
24
20
  return null;
25
21
  const provider = object(existing.provider);
26
- const next = unpatchProvider(unpatchOpenCodeZen(provider), 'openai');
22
+ const next = unpatchProvider(unpatchProvider(unpatchOpenCodeZen(provider), "openai"), "anthropic");
27
23
  await mkdir(dirname(target), { recursive: true, mode: 0o700 });
28
- if (jsoncPath(target)) {
29
- const raw = await readRaw(target);
30
- await writeFile(target, unpatchJsonc(raw, provider, next), { mode: 0o600 });
31
- return target;
32
- }
33
24
  await writeFile(target, `${JSON.stringify({ ...existing, provider: next }, null, 2)}\n`, { mode: 0o600 });
34
25
  return target;
35
26
  }
36
27
  export function openCodePath(env = process.env, platform = process.platform) {
37
- return join(openCodeRoot(env, platform), 'opencode.json');
28
+ return join(openCodeRoot(env, platform), "opencode.json");
38
29
  }
39
30
  export function openCodeJsoncPath(env = process.env, platform = process.platform) {
40
- return join(openCodeRoot(env, platform), 'opencode.jsonc');
31
+ return join(openCodeRoot(env, platform), "opencode.jsonc");
41
32
  }
42
33
  export function openCodeAuthPath(env = process.env, platform = process.platform) {
43
- const root = platform === 'win32'
44
- ? join(homedir(), '.local', 'share')
45
- : env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
46
- return join(root, 'opencode', 'auth.json');
34
+ const root = platform === "win32"
35
+ ? join(homedir(), ".local", "share")
36
+ : env.XDG_DATA_HOME || join(homedir(), ".local", "share");
37
+ return join(root, "opencode", "auth.json");
47
38
  }
48
39
  export async function resolveOpenCodePath(env = process.env, platform = process.platform) {
49
40
  const jsonc = openCodeJsoncPath(env, platform);
50
41
  const json = openCodePath(env, platform);
51
- const [jsoncConfig, jsonConfig] = await Promise.all([readExistingJson(jsonc), readExistingJson(json)]);
42
+ const [jsoncConfig, jsonConfig] = await Promise.all([
43
+ readExistingJson(jsonc),
44
+ readExistingJson(json),
45
+ ]);
52
46
  if (hasProvider(jsoncConfig))
53
47
  return jsonc;
54
48
  if (hasProvider(jsonConfig))
@@ -58,15 +52,17 @@ export async function resolveOpenCodePath(env = process.env, platform = process.
58
52
  return json;
59
53
  }
60
54
  function openCodeRoot(env = process.env, platform = process.platform) {
61
- const root = platform === 'win32'
62
- ? join(homedir(), '.config')
63
- : env.XDG_CONFIG_HOME || join(homedir(), '.config');
64
- return join(root, 'opencode');
55
+ const root = platform === "win32"
56
+ ? join(homedir(), ".config")
57
+ : env.XDG_CONFIG_HOME || join(homedir(), ".config");
58
+ return join(root, "opencode");
65
59
  }
66
60
  function patchConfig(input, auth, id) {
67
61
  const provider = object(input.provider);
68
62
  const base = trim(auth.proxyUrl);
69
- const next = id === 'opencode' ? patchOpenCodeZen(provider, auth, base) : patchProvider(provider, auth, base, id);
63
+ const next = id === "opencode"
64
+ ? patchOpenCodeZen(provider, auth, base)
65
+ : patchProvider(provider, auth, base, id);
70
66
  return {
71
67
  ...input,
72
68
  provider: next,
@@ -85,7 +81,7 @@ function patchProvider(provider, auth, base, id) {
85
81
  baseURL: base,
86
82
  headers: {
87
83
  ...headers,
88
- ...sleeveHeaders(auth, id === 'openai' ? 'codex' : id),
84
+ ...sleeveHeaders(auth, id === "openai" ? "codex" : id),
89
85
  },
90
86
  },
91
87
  },
@@ -95,9 +91,9 @@ function unpatchProvider(provider, id) {
95
91
  const existing = object(provider[id]);
96
92
  const options = object(existing.options);
97
93
  const headers = object(options.headers);
98
- if (headers['sleeve-harness'] !== 'opencode')
94
+ if (headers["sleeve-harness"] !== "opencode")
99
95
  return provider;
100
- const { ['sleeve-token']: _token, ['sleeve-provider']: _provider, ['sleeve-harness']: _harness, ...rest } = headers;
96
+ const { ["sleeve-token"]: _token, ["sleeve-provider"]: _provider, ["sleeve-harness"]: _harness, ...rest } = headers;
101
97
  const { baseURL: _base, ...other } = options;
102
98
  return {
103
99
  ...provider,
@@ -113,7 +109,7 @@ function unpatchProvider(provider, id) {
113
109
  function patchOpenCodeZen(provider, auth, base) {
114
110
  const existing = object(provider.opencode);
115
111
  const models = object(existing.models);
116
- const registry = registryProvider('opencode');
112
+ const registry = registryProvider("opencode");
117
113
  const patched = Object.fromEntries((registry.models ?? []).map((id) => {
118
114
  const model = object(models[id]);
119
115
  const source = object(model.provider);
@@ -128,7 +124,7 @@ function patchOpenCodeZen(provider, auth, base) {
128
124
  },
129
125
  headers: {
130
126
  ...headers,
131
- ...sleeveHeaders(auth, 'opencode'),
127
+ ...sleeveHeaders(auth, "opencode"),
132
128
  },
133
129
  },
134
130
  ];
@@ -150,9 +146,9 @@ function unpatchOpenCodeZen(provider) {
150
146
  const patched = Object.fromEntries(Object.entries(models).map(([id, value]) => {
151
147
  const model = object(value);
152
148
  const headers = object(model.headers);
153
- if (headers['sleeve-harness'] !== 'opencode')
149
+ if (headers["sleeve-harness"] !== "opencode")
154
150
  return [id, model];
155
- const { ['sleeve-token']: _token, ['sleeve-provider']: _provider, ['sleeve-harness']: _harness, ...rest } = headers;
151
+ const { ["sleeve-token"]: _token, ["sleeve-provider"]: _provider, ["sleeve-harness"]: _harness, ...rest } = headers;
156
152
  const source = object(model.provider);
157
153
  const { api: _api, ...provider } = source;
158
154
  return [
@@ -174,52 +170,42 @@ function unpatchOpenCodeZen(provider) {
174
170
  }
175
171
  function sleeveHeaders(auth, provider) {
176
172
  return {
177
- 'sleeve-token': auth.token,
178
- 'sleeve-provider': provider,
179
- 'sleeve-harness': 'opencode',
173
+ "sleeve-token": auth.token,
174
+ "sleeve-provider": provider,
175
+ "sleeve-harness": "opencode",
180
176
  };
181
177
  }
182
178
  async function readJson(path) {
183
179
  try {
184
- const raw = await readFile(path, 'utf8');
185
- const parsed = jsoncPath(path) ? parse(raw, [], { allowTrailingComma: true }) : JSON.parse(raw);
180
+ const raw = await readFile(path, "utf8");
181
+ const parsed = parseConfig(raw, path);
186
182
  return object(parsed);
187
183
  }
188
184
  catch (err) {
189
- if (code(err) === 'ENOENT')
185
+ if (code(err) === "ENOENT")
190
186
  return {};
191
187
  throw err;
192
188
  }
193
189
  }
194
190
  async function readExistingJson(path) {
195
191
  try {
196
- const raw = await readFile(path, 'utf8');
197
- const parsed = jsoncPath(path) ? parse(raw, [], { allowTrailingComma: true }) : JSON.parse(raw);
192
+ const raw = await readFile(path, "utf8");
193
+ const parsed = parseConfig(raw, path);
198
194
  return object(parsed);
199
195
  }
200
196
  catch (err) {
201
- if (code(err) === 'ENOENT')
197
+ if (code(err) === "ENOENT")
202
198
  return null;
203
199
  throw err;
204
200
  }
205
201
  }
206
- async function readRaw(path) {
207
- try {
208
- return await readFile(path, 'utf8');
209
- }
210
- catch (err) {
211
- if (code(err) === 'ENOENT')
212
- return '{}\n';
213
- throw err;
214
- }
215
- }
216
202
  async function exists(path) {
217
203
  try {
218
204
  await access(path);
219
205
  return true;
220
206
  }
221
207
  catch (err) {
222
- if (code(err) === 'ENOENT')
208
+ if (code(err) === "ENOENT")
223
209
  return false;
224
210
  throw err;
225
211
  }
@@ -227,42 +213,89 @@ async function exists(path) {
227
213
  function hasProvider(config) {
228
214
  if (!config)
229
215
  return false;
230
- return 'provider' in config && typeof config.provider === 'object' && config.provider !== null && !Array.isArray(config.provider);
216
+ return ("provider" in config &&
217
+ typeof config.provider === "object" &&
218
+ config.provider !== null &&
219
+ !Array.isArray(config.provider));
231
220
  }
232
- function patchJsonc(raw, existing, auth, id) {
233
- const provider = object(existing.provider);
234
- const base = trim(auth.proxyUrl);
235
- const next = id === 'opencode' ? patchOpenCodeZen(provider, auth, base) : patchProvider(provider, auth, base, id);
236
- const key = id === 'opencode' ? 'opencode' : id;
237
- const value = next[key];
238
- return editJsonc(raw, ['provider', key], value);
221
+ function jsoncPath(path) {
222
+ return path.endsWith(".jsonc");
239
223
  }
240
- function unpatchJsonc(raw, provider, next) {
241
- const openai = object(next.openai);
242
- const opencode = object(next.opencode);
243
- const target = 'openai' in provider ? editJsonc(raw, ['provider', 'openai'], 'openai' in next ? openai : undefined) : raw;
244
- return 'opencode' in provider ? editJsonc(target, ['provider', 'opencode'], 'opencode' in next ? opencode : undefined) : target;
224
+ function parseConfig(raw, path) {
225
+ const input = jsoncPath(path)
226
+ ? stripTrailingCommas(stripComments(raw))
227
+ : raw;
228
+ return JSON.parse(input);
245
229
  }
246
- function editJsonc(raw, path, value) {
247
- const edits = modify(raw, path, value, {
248
- formattingOptions: { insertSpaces: true, tabSize: 2, keepLines: true, insertFinalNewline: true },
249
- });
250
- return applyEdits(raw, edits);
230
+ function stripComments(input) {
231
+ let output = "";
232
+ let quoted = false;
233
+ let escaped = false;
234
+ let index = 0;
235
+ while (index < input.length) {
236
+ const char = input[index] ?? "";
237
+ const next = input[index + 1] ?? "";
238
+ if (quoted) {
239
+ output += char;
240
+ if (escaped) {
241
+ escaped = false;
242
+ index += 1;
243
+ continue;
244
+ }
245
+ if (char === "\\") {
246
+ escaped = true;
247
+ index += 1;
248
+ continue;
249
+ }
250
+ if (char === '"')
251
+ quoted = false;
252
+ index += 1;
253
+ continue;
254
+ }
255
+ if (char === '"') {
256
+ quoted = true;
257
+ output += char;
258
+ index += 1;
259
+ continue;
260
+ }
261
+ if (char === "/" && next === "/") {
262
+ while (index < input.length && input[index] !== "\n")
263
+ index += 1;
264
+ output += "\n";
265
+ index += 1;
266
+ continue;
267
+ }
268
+ if (char === "/" && next === "*") {
269
+ index += 2;
270
+ while (index < input.length &&
271
+ !(input[index] === "*" && input[index + 1] === "/")) {
272
+ if (input[index] === "\n")
273
+ output += "\n";
274
+ index += 1;
275
+ }
276
+ index += 2;
277
+ continue;
278
+ }
279
+ output += char;
280
+ index += 1;
281
+ }
282
+ return output;
251
283
  }
252
- function jsoncPath(path) {
253
- return path.endsWith('.jsonc');
284
+ function stripTrailingCommas(input) {
285
+ return input.replace(/,\s*([}\]])/g, "$1");
254
286
  }
255
287
  function object(value) {
256
- if (typeof value !== 'object' || value === null || Array.isArray(value))
288
+ if (typeof value !== "object" || value === null || Array.isArray(value))
257
289
  return {};
258
290
  return value;
259
291
  }
260
292
  function trim(url) {
261
- return url.replace(/\/+$/, '');
293
+ return url.replace(/\/+$/, "");
262
294
  }
263
295
  function code(err) {
264
- if (typeof err !== 'object' || err === null || !('code' in err))
296
+ if (typeof err !== "object" || err === null || !("code" in err))
265
297
  return undefined;
266
298
  const value = err.code;
267
- return typeof value === 'string' ? value : undefined;
299
+ return typeof value === "string" ? value : undefined;
268
300
  }
301
+ //# sourceMappingURL=opencode-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-config.js","sourceRoot":"","sources":["../../src/harness/opencode-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type Provider } from "./providers.js";
2
+ import { openCodeAuthPath, openCodeJsoncPath, openCodePath, resolveOpenCodePath } from "./opencode-config.js";
3
+ import type { HarnessAuth } from "./types.js";
4
+ export type OpenCodePatchResult = {
5
+ path: string;
6
+ provider: string;
7
+ };
8
+ export declare function setupOpenCode(auth: HarnessAuth, options?: {
9
+ authPath?: string;
10
+ configPath?: string;
11
+ }): Promise<OpenCodePatchResult | null>;
12
+ export declare function availableOpenCodeProviders(path?: string): Promise<Provider[]>;
13
+ export declare function unpatchOpenCode(path?: string): Promise<void>;
14
+ export { openCodeAuthPath, openCodeJsoncPath, openCodePath, resolveOpenCodePath, };
@@ -0,0 +1,50 @@
1
+ // OpenCode setup owns credential discovery and provider selection for config patching.
2
+ import { readFile } from "node:fs/promises";
3
+ import { PROVIDERS } from "./providers.js";
4
+ import { openCodeAuthPath, openCodeJsoncPath, openCodePath, patchOpenCodeConfig, resolveOpenCodePath, unpatchOpenCodeConfig, } from "./opencode-config.js";
5
+ export async function setupOpenCode(auth, options = {}) {
6
+ const path = options.configPath ?? (await resolveOpenCodePath());
7
+ const available = await availableOpenCodeProviders(options.authPath);
8
+ if (available.length === 0)
9
+ return null;
10
+ const results = [];
11
+ for (const item of available) {
12
+ results.push(await patchOpenCodeConfig(auth, path, item.id));
13
+ }
14
+ const first = available[0];
15
+ if (!first)
16
+ return null;
17
+ return { path: results[0] ?? path, provider: first.id };
18
+ }
19
+ export async function availableOpenCodeProviders(path = openCodeAuthPath()) {
20
+ const auth = await readAuth(path);
21
+ return PROVIDERS.filter((provider) => provider.id in auth);
22
+ }
23
+ export async function unpatchOpenCode(path) {
24
+ await unpatchOpenCodeConfig(path);
25
+ }
26
+ export { openCodeAuthPath, openCodeJsoncPath, openCodePath, resolveOpenCodePath, };
27
+ async function readAuth(path) {
28
+ try {
29
+ const raw = await readFile(path, "utf8");
30
+ const parsed = JSON.parse(raw);
31
+ return object(parsed);
32
+ }
33
+ catch (err) {
34
+ if (code(err) === "ENOENT")
35
+ return {};
36
+ throw err;
37
+ }
38
+ }
39
+ function object(value) {
40
+ if (typeof value !== "object" || value === null || Array.isArray(value))
41
+ return {};
42
+ return value;
43
+ }
44
+ function code(err) {
45
+ if (typeof err !== "object" || err === null || !("code" in err))
46
+ return undefined;
47
+ const value = err.code;
48
+ return typeof value === "string" ? value : undefined;
49
+ }
50
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/harness/opencode.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAiB,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACxB,MAAM,sBAAsB,CAAC;AAU9B,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,IAAiB,EACjB,UAAsD,EAAE;IAExD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,MAAM,mBAAmB,EAAE,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,MAAM,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC5C,OAAe,gBAAgB,EAAE;IAEjC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAa;IAC/C,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,GACtB,CAAC;AAEF,KAAK,UAAU,QAAQ,CAAC,IAAY;IAChC,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACtC,MAAM,GAAG,CAAC;IACd,CAAC;AACL,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACnE,OAAO,EAAE,CAAC;IACd,OAAO,KAAmB,CAAC;AAC/B,CAAC;AAED,SAAS,IAAI,CAAC,GAAY;IACtB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC;QAC3D,OAAO,SAAS,CAAC;IACrB,MAAM,KAAK,GAAI,GAA0B,CAAC,IAAI,CAAC;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type ProviderId = "openai" | "anthropic" | "opencode";
2
+ export type Provider = {
3
+ id: ProviderId;
4
+ label: string;
5
+ models?: readonly string[];
6
+ };
7
+ export declare const PROVIDERS: readonly Provider[];
8
+ export declare function provider(id: ProviderId): Provider;
@@ -0,0 +1,30 @@
1
+ export const PROVIDERS = [
2
+ { id: "openai", label: "OpenAI" },
3
+ { id: "anthropic", label: "Anthropic" },
4
+ {
5
+ id: "opencode",
6
+ label: "OpenCode Zen",
7
+ models: [
8
+ "claude-sonnet-4-5",
9
+ "claude-sonnet-4-6",
10
+ "claude-opus-4-5",
11
+ "claude-opus-4-6",
12
+ "claude-opus-4-7",
13
+ "gpt-5.3-codex",
14
+ "gpt-5.3-codex-spark",
15
+ "gpt-5.4",
16
+ "gpt-5.4-mini",
17
+ "gpt-5.4-nano",
18
+ "gpt-5.4-pro",
19
+ "gpt-5.5",
20
+ "gpt-5.5-pro",
21
+ ],
22
+ },
23
+ ];
24
+ export function provider(id) {
25
+ const value = PROVIDERS.find((item) => item.id === id);
26
+ if (!value)
27
+ throw new Error(`Unsupported provider: ${id}`);
28
+ return value;
29
+ }
30
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/harness/providers.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,SAAS,GAAwB;IAC1C,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACjC,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IACvC;QACI,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,cAAc;QACrB,MAAM,EAAE;YACJ,mBAAmB;YACnB,mBAAmB;YACnB,iBAAiB;YACjB,iBAAiB;YACjB,iBAAiB;YACjB,eAAe;YACf,qBAAqB;YACrB,SAAS;YACT,cAAc;YACd,cAAc;YACd,aAAa;YACb,SAAS;YACT,aAAa;SAChB;KACJ;CACJ,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,EAAc;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type HarnessId = "opencode" | "claude-code" | "codex";
2
+ export type HarnessAuth = {
3
+ token: string;
4
+ label: string | null;
5
+ proxyUrl: string;
6
+ createdAt: string;
7
+ };
8
+ export type Harness = {
9
+ id: HarnessId;
10
+ label: string;
11
+ command: string;
12
+ setup: (auth: HarnessAuth) => Promise<unknown>;
13
+ unpatch: () => Promise<void>;
14
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export declare function webOrigin(env?: NodeJS.ProcessEnv): string;
2
+ export declare function apiOrigin(env?: NodeJS.ProcessEnv): string;
3
+ export type FirebaseConfig = {
4
+ apiKey: string;
5
+ projectId: string;
6
+ };
7
+ export declare function firebaseConfig(env?: NodeJS.ProcessEnv): FirebaseConfig;
8
+ export type GatewayUpdates = {
9
+ baseUrl: string;
10
+ channel: string;
11
+ };
12
+ export declare function gatewayUpdates(env?: NodeJS.ProcessEnv): GatewayUpdates;
package/dist/product.js CHANGED
@@ -1,21 +1,63 @@
1
- // Product defaults and environment escape hatches for local development.
2
- const DEFAULT_WEB_ORIGIN = 'https://sleev.ai';
3
- const DEFAULT_PROXY_URL = 'https://api.sleev.ai';
1
+ const DEFAULT_WEB_ORIGIN = "https://sleev.ai";
4
2
  export function webOrigin(env = process.env) {
5
3
  const raw = env.SLEEV_WEB_ORIGIN?.trim();
6
4
  if (!raw)
7
5
  return DEFAULT_WEB_ORIGIN;
8
- const url = parseUrl(raw, 'SLEEV_WEB_ORIGIN');
9
- if (url.protocol !== 'https:' && url.protocol !== 'http:') {
10
- throw new Error('SLEEV_WEB_ORIGIN must use http or https.');
6
+ const url = parseUrl(raw, "SLEEV_WEB_ORIGIN");
7
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
8
+ throw new Error("SLEEV_WEB_ORIGIN must use http or https.");
11
9
  }
12
- if (url.pathname !== '/' || url.search || url.hash) {
13
- throw new Error('SLEEV_WEB_ORIGIN must be an origin without a path.');
10
+ if (url.pathname !== "/" || url.search || url.hash) {
11
+ throw new Error("SLEEV_WEB_ORIGIN must be an origin without a path.");
14
12
  }
15
13
  return url.origin;
16
14
  }
17
- export function proxyUrl() {
18
- return DEFAULT_PROXY_URL;
15
+ const DEFAULT_API_ORIGIN = "https://api.sleev.ai";
16
+ // Control-server API origin. Override (e.g. http://127.0.0.1:8001) for local
17
+ // end-to-end testing against a dev control server.
18
+ export function apiOrigin(env = process.env) {
19
+ const raw = env.SLEEV_API_ORIGIN?.trim();
20
+ if (!raw)
21
+ return DEFAULT_API_ORIGIN;
22
+ const url = parseUrl(raw, "SLEEV_API_ORIGIN");
23
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
24
+ throw new Error("SLEEV_API_ORIGIN must use http or https.");
25
+ }
26
+ if (url.pathname !== "/" || url.search || url.hash) {
27
+ throw new Error("SLEEV_API_ORIGIN must be an origin without a path.");
28
+ }
29
+ return url.origin;
30
+ }
31
+ // Public Firebase client config (same values shipped in the website bundle).
32
+ // Used to exchange the handoff refresh token for short-lived ID tokens.
33
+ const DEFAULT_FIREBASE_API_KEY = "AIzaSyC7oGsdPGTwfAofbWySSm5_qXLRa9WaYgc";
34
+ const DEFAULT_FIREBASE_PROJECT_ID = "sleev3-23727";
35
+ export function firebaseConfig(env = process.env) {
36
+ return {
37
+ apiKey: env.SLEEV_FIREBASE_API_KEY?.trim() || DEFAULT_FIREBASE_API_KEY,
38
+ projectId: env.SLEEV_FIREBASE_PROJECT_ID?.trim() ||
39
+ DEFAULT_FIREBASE_PROJECT_ID,
40
+ };
41
+ }
42
+ // Where the packaged gateway binary + channel manifest are published. The
43
+ // GitHub release workflow publishes to this GCS bucket; the channel manifest
44
+ // (`gateway/<channel>.json`) is the always-latest pointer the CLI follows.
45
+ const DEFAULT_UPDATES_BASE_URL = "https://storage.googleapis.com/sleeve-releases";
46
+ const DEFAULT_GATEWAY_CHANNEL = "stable";
47
+ export function gatewayUpdates(env = process.env) {
48
+ const rawBase = env.SLEEVE_UPDATES_BASE_URL?.trim();
49
+ let baseUrl = DEFAULT_UPDATES_BASE_URL;
50
+ if (rawBase) {
51
+ const url = parseUrl(rawBase, "SLEEVE_UPDATES_BASE_URL");
52
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
53
+ throw new Error("SLEEVE_UPDATES_BASE_URL must use http or https.");
54
+ }
55
+ baseUrl = rawBase.replace(/\/+$/, "");
56
+ }
57
+ return {
58
+ baseUrl,
59
+ channel: env.SLEEVE_GATEWAY_CHANNEL?.trim() || DEFAULT_GATEWAY_CHANNEL,
60
+ };
19
61
  }
20
62
  function parseUrl(raw, name) {
21
63
  try {
@@ -25,3 +67,4 @@ function parseUrl(raw, name) {
25
67
  throw new Error(`${name} must be a valid URL.`);
26
68
  }
27
69
  }
70
+ //# sourceMappingURL=product.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.js","sourceRoot":"","sources":["../src/product.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function copyText(text: string): Promise<boolean>;
@@ -0,0 +1,48 @@
1
+ // Centralizes terminal clipboard writes for clickable TUI links.
2
+ import { spawn } from "node:child_process";
3
+ export async function copyText(text) {
4
+ const commands = clipboardCommands();
5
+ const write = async (index) => {
6
+ const command = commands[index];
7
+ if (!command)
8
+ return copyOsc52(text);
9
+ if (await writeCommand(command, text))
10
+ return true;
11
+ return write(index + 1);
12
+ };
13
+ return write(0);
14
+ }
15
+ function clipboardCommands() {
16
+ if (process.platform === "darwin")
17
+ return [{ name: "pbcopy", args: [] }];
18
+ if (process.platform === "win32")
19
+ return [{ name: "clip", args: [] }];
20
+ return [
21
+ { name: "clip.exe", args: [] },
22
+ { name: "wl-copy", args: [] },
23
+ ];
24
+ }
25
+ function writeCommand(command, text) {
26
+ return new Promise((resolve) => {
27
+ const child = spawn(command.name, command.args, {
28
+ stdio: ["pipe", "ignore", "ignore"],
29
+ windowsHide: true,
30
+ });
31
+ let settled = false;
32
+ const finish = (ok) => {
33
+ if (settled)
34
+ return;
35
+ settled = true;
36
+ resolve(ok);
37
+ };
38
+ child.once("error", () => finish(false));
39
+ child.once("close", (code) => finish(code === 0));
40
+ child.stdin.once("error", () => finish(false));
41
+ child.stdin.end(text);
42
+ });
43
+ }
44
+ function copyOsc52(text) {
45
+ const encoded = Buffer.from(text).toString("base64");
46
+ return process.stdout.write(`\u001B]52;c;${encoded}\u0007`);
47
+ }
48
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/tui/clipboard.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAO3C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACvC,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,EAAE,KAAa,EAAoB,EAAE;QACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACnD,OAAO,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,iBAAiB;IACtB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAEtE,OAAO;QACH,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE;QAC9B,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;KAChC,CAAC;AACN,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB,EAAE,IAAY;IAChD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;YAC5C,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACnC,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,EAAW,EAAE,EAAE;YAC3B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;QAClD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,OAAO,QAAQ,CAAC,CAAC;AAChE,CAAC"}