@route_33/opencode 0.4.7-rc.7 → 0.4.7-rc.8

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.
@@ -13,1003 +13,800 @@ var __export = (target, all) => {
13
13
  __defProp(target, name, { get: all[name], enumerable: true });
14
14
  };
15
15
 
16
- // src/attribution/detect-worktree-root/detect-worktree-root.ts
17
- import * as fs from "node:fs";
18
- import * as path from "node:path";
19
- var detectWorktreeRoot;
20
- var init_detect_worktree_root = __esm({
21
- "src/attribution/detect-worktree-root/detect-worktree-root.ts"() {
16
+ // src/cli/read-env-base-url/read-env-base-url.ts
17
+ var readEnvBaseUrl;
18
+ var init_read_env_base_url = __esm({
19
+ "src/cli/read-env-base-url/read-env-base-url.ts"() {
22
20
  "use strict";
23
- detectWorktreeRoot = (startDirectory) => {
24
- let directory = fs.realpathSync(startDirectory);
25
- for (; ; ) {
26
- const gitEntry = path.join(directory, ".git");
27
- if (fs.existsSync(gitEntry)) {
28
- const entry = fs.statSync(gitEntry);
29
- if (entry.isDirectory() || entry.isFile()) {
30
- return directory;
31
- }
32
- }
33
- const parent = path.dirname(directory);
34
- if (parent === directory) {
35
- return void 0;
36
- }
37
- directory = parent;
38
- }
21
+ readEnvBaseUrl = (env = process.env) => {
22
+ const value = env["ROUTE33_BASE_URL"]?.trim();
23
+ return value === "" ? void 0 : value;
39
24
  };
40
25
  }
41
26
  });
42
27
 
43
- // src/attribution/detect-worktree-root/index.ts
44
- var init_detect_worktree_root2 = __esm({
45
- "src/attribution/detect-worktree-root/index.ts"() {
28
+ // src/cli/read-env-base-url/index.ts
29
+ var init_read_env_base_url2 = __esm({
30
+ "src/cli/read-env-base-url/index.ts"() {
46
31
  "use strict";
47
- init_detect_worktree_root();
32
+ init_read_env_base_url();
48
33
  }
49
34
  });
50
35
 
51
- // src/attribution/resolve-attribution-file/resolve-attribution-file.ts
52
- import * as fs2 from "node:fs";
53
- import * as path2 from "node:path";
54
- var resolveAttributionFile;
55
- var init_resolve_attribution_file = __esm({
56
- "src/attribution/resolve-attribution-file/resolve-attribution-file.ts"() {
36
+ // src/cli/read-env-api-base/read-env-api-base.ts
37
+ var readEnvApiBase;
38
+ var init_read_env_api_base = __esm({
39
+ "src/cli/read-env-api-base/read-env-api-base.ts"() {
57
40
  "use strict";
58
- init_detect_worktree_root2();
59
- resolveAttributionFile = (options) => {
60
- const worktreeRoot = detectWorktreeRoot(options.directory);
61
- if (worktreeRoot !== void 0) {
62
- return path2.join(worktreeRoot, ".opencode", "route33.attribution.json");
63
- }
64
- const fallbackRoots = {
65
- "return-undefined": void 0,
66
- "use-directory": fs2.realpathSync(options.directory)
67
- };
68
- const fallbackRoot = fallbackRoots[options.outsideWorktree];
69
- return fallbackRoot === void 0 ? void 0 : path2.join(fallbackRoot, ".opencode", "route33.attribution.json");
41
+ readEnvApiBase = (env = process.env) => {
42
+ const value = env["ROUTE33_API_BASE"]?.trim();
43
+ return value === "" ? void 0 : value;
70
44
  };
71
45
  }
72
46
  });
73
47
 
74
- // src/attribution/resolve-attribution-file/index.ts
75
- var init_resolve_attribution_file2 = __esm({
76
- "src/attribution/resolve-attribution-file/index.ts"() {
48
+ // src/cli/read-env-api-base/index.ts
49
+ var init_read_env_api_base2 = __esm({
50
+ "src/cli/read-env-api-base/index.ts"() {
77
51
  "use strict";
78
- init_resolve_attribution_file();
52
+ init_read_env_api_base();
79
53
  }
80
54
  });
81
55
 
82
- // src/attribution/clear-attribution/clear-attribution.ts
83
- import * as fs3 from "node:fs";
84
- var clearAttribution;
85
- var init_clear_attribution = __esm({
86
- "src/attribution/clear-attribution/clear-attribution.ts"() {
56
+ // src/cli/read-env-auth-issuer/read-env-auth-issuer.ts
57
+ var readEnvAuthIssuer;
58
+ var init_read_env_auth_issuer = __esm({
59
+ "src/cli/read-env-auth-issuer/read-env-auth-issuer.ts"() {
87
60
  "use strict";
88
- init_resolve_attribution_file2();
89
- clearAttribution = (options) => {
90
- const file = resolveAttributionFile(options);
91
- if (file === void 0) {
92
- return false;
93
- }
94
- fs3.rmSync(file, { force: true });
95
- return true;
61
+ readEnvAuthIssuer = (env = process.env) => {
62
+ const value = env["ROUTE33_AUTH_ISSUER"]?.trim();
63
+ return value === "" ? void 0 : value;
96
64
  };
97
65
  }
98
66
  });
99
67
 
100
- // src/attribution/clear-attribution/index.ts
101
- var init_clear_attribution2 = __esm({
102
- "src/attribution/clear-attribution/index.ts"() {
68
+ // src/cli/read-env-auth-issuer/index.ts
69
+ var init_read_env_auth_issuer2 = __esm({
70
+ "src/cli/read-env-auth-issuer/index.ts"() {
103
71
  "use strict";
104
- init_clear_attribution();
72
+ init_read_env_auth_issuer();
105
73
  }
106
74
  });
107
75
 
108
- // src/contract/adapters/contract-parse-error/contract-parse-error.ts
109
- var ContractParseError;
110
- var init_contract_parse_error = __esm({
111
- "src/contract/adapters/contract-parse-error/contract-parse-error.ts"() {
76
+ // src/cli/read-env-autoconnect-disabled/read-env-autoconnect-disabled.ts
77
+ var readEnvAutoconnectDisabled;
78
+ var init_read_env_autoconnect_disabled = __esm({
79
+ "src/cli/read-env-autoconnect-disabled/read-env-autoconnect-disabled.ts"() {
112
80
  "use strict";
113
- ContractParseError = class extends Error {
81
+ readEnvAutoconnectDisabled = (env = process.env) => {
82
+ const value = env["ROUTE33_AUTOCONNECT"]?.trim().toLowerCase();
83
+ return value === "0" || value === "false" || value === "no" || value === "off";
114
84
  };
115
85
  }
116
86
  });
117
87
 
118
- // src/contract/adapters/contract-parse-error/index.ts
119
- var init_contract_parse_error2 = __esm({
120
- "src/contract/adapters/contract-parse-error/index.ts"() {
88
+ // src/cli/read-env-autoconnect-disabled/index.ts
89
+ var init_read_env_autoconnect_disabled2 = __esm({
90
+ "src/cli/read-env-autoconnect-disabled/index.ts"() {
121
91
  "use strict";
122
- init_contract_parse_error();
92
+ init_read_env_autoconnect_disabled();
123
93
  }
124
94
  });
125
95
 
126
- // src/contract/adapters/gateway-api-key/gateway-api-key.ts
127
- var GatewayApiKey;
128
- var init_gateway_api_key = __esm({
129
- "src/contract/adapters/gateway-api-key/gateway-api-key.ts"() {
96
+ // src/shared/canonical-slug/index.ts
97
+ var init_canonical_slug = __esm({
98
+ "src/shared/canonical-slug/index.ts"() {
130
99
  "use strict";
131
- GatewayApiKey = class {
132
- value;
133
- constructor(value) {
134
- this.value = value;
135
- }
136
- };
137
100
  }
138
101
  });
139
102
 
140
- // src/contract/adapters/gateway-api-key/index.ts
141
- var init_gateway_api_key2 = __esm({
142
- "src/contract/adapters/gateway-api-key/index.ts"() {
103
+ // src/shared/catalog-result/index.ts
104
+ var init_catalog_result = __esm({
105
+ "src/shared/catalog-result/index.ts"() {
143
106
  "use strict";
144
- init_gateway_api_key();
145
107
  }
146
108
  });
147
109
 
148
- // src/contract/adapters/management-jwt/management-jwt.ts
149
- var ManagementJwt;
150
- var init_management_jwt = __esm({
151
- "src/contract/adapters/management-jwt/management-jwt.ts"() {
110
+ // src/shared/catalog-source/index.ts
111
+ var init_catalog_source = __esm({
112
+ "src/shared/catalog-source/index.ts"() {
152
113
  "use strict";
153
- ManagementJwt = class {
154
- value;
155
- constructor(value) {
156
- this.value = value;
157
- }
158
- };
159
114
  }
160
115
  });
161
116
 
162
- // src/contract/adapters/management-jwt/index.ts
163
- var init_management_jwt2 = __esm({
164
- "src/contract/adapters/management-jwt/index.ts"() {
117
+ // src/shared/default-auth-issuer-url/default-auth-issuer-url.ts
118
+ var DEFAULT_AUTH_ISSUER_URL;
119
+ var init_default_auth_issuer_url = __esm({
120
+ "src/shared/default-auth-issuer-url/default-auth-issuer-url.ts"() {
165
121
  "use strict";
166
- init_management_jwt();
122
+ DEFAULT_AUTH_ISSUER_URL = "https://auth.route33.ai";
167
123
  }
168
124
  });
169
125
 
170
- // src/contract/adapters/parse-gateway-key/parse-gateway-key.ts
171
- var parseGatewayKey;
172
- var init_parse_gateway_key = __esm({
173
- "src/contract/adapters/parse-gateway-key/parse-gateway-key.ts"() {
126
+ // src/shared/default-auth-issuer-url/index.ts
127
+ var init_default_auth_issuer_url2 = __esm({
128
+ "src/shared/default-auth-issuer-url/index.ts"() {
174
129
  "use strict";
175
- init_gateway_api_key2();
176
- parseGatewayKey = (value) => {
177
- if (typeof value !== "string" || value.length === 0) {
178
- throw new Error("gateway key must be non-empty");
179
- }
180
- return new GatewayApiKey(value);
181
- };
130
+ init_default_auth_issuer_url();
182
131
  }
183
132
  });
184
133
 
185
- // src/contract/adapters/parse-gateway-key/index.ts
186
- var init_parse_gateway_key2 = __esm({
187
- "src/contract/adapters/parse-gateway-key/index.ts"() {
134
+ // src/shared/default-base-url/default-base-url.ts
135
+ var DEFAULT_BASE_URL;
136
+ var init_default_base_url = __esm({
137
+ "src/shared/default-base-url/default-base-url.ts"() {
188
138
  "use strict";
189
- init_parse_gateway_key();
139
+ DEFAULT_BASE_URL = "https://api.route33.ai/v1";
190
140
  }
191
141
  });
192
142
 
193
- // src/contract/adapters/parse-management-jwt/parse-management-jwt.ts
194
- var parseManagementJwt;
195
- var init_parse_management_jwt = __esm({
196
- "src/contract/adapters/parse-management-jwt/parse-management-jwt.ts"() {
143
+ // src/shared/default-base-url/index.ts
144
+ var init_default_base_url2 = __esm({
145
+ "src/shared/default-base-url/index.ts"() {
197
146
  "use strict";
198
- init_management_jwt2();
199
- parseManagementJwt = (value) => {
200
- if (typeof value !== "string" || value.length === 0) {
201
- throw new Error("management token must be non-empty");
202
- }
203
- return new ManagementJwt(value);
204
- };
147
+ init_default_base_url();
205
148
  }
206
149
  });
207
150
 
208
- // src/contract/adapters/parse-management-jwt/index.ts
209
- var init_parse_management_jwt2 = __esm({
210
- "src/contract/adapters/parse-management-jwt/index.ts"() {
151
+ // src/shared/default-management-api-base-url/default-management-api-base-url.ts
152
+ var DEFAULT_MANAGEMENT_API_BASE_URL;
153
+ var init_default_management_api_base_url = __esm({
154
+ "src/shared/default-management-api-base-url/default-management-api-base-url.ts"() {
211
155
  "use strict";
212
- init_parse_management_jwt();
156
+ DEFAULT_MANAGEMENT_API_BASE_URL = "https://mapi.route33.ai/api/v1";
213
157
  }
214
158
  });
215
159
 
216
- // src/contract/predicates/has-string-fields/has-string-fields.ts
217
- var hasStringFields;
218
- var init_has_string_fields = __esm({
219
- "src/contract/predicates/has-string-fields/has-string-fields.ts"() {
160
+ // src/shared/default-management-api-base-url/index.ts
161
+ var init_default_management_api_base_url2 = __esm({
162
+ "src/shared/default-management-api-base-url/index.ts"() {
220
163
  "use strict";
221
- hasStringFields = (record, fields) => fields.every((field) => typeof record[field] === "string");
164
+ init_default_management_api_base_url();
222
165
  }
223
166
  });
224
167
 
225
- // src/contract/predicates/has-string-fields/index.ts
226
- var init_has_string_fields2 = __esm({
227
- "src/contract/predicates/has-string-fields/index.ts"() {
168
+ // src/shared/default-catalog-ttl-ms/default-catalog-ttl-ms.ts
169
+ var DEFAULT_CATALOG_TTL_MS;
170
+ var init_default_catalog_ttl_ms = __esm({
171
+ "src/shared/default-catalog-ttl-ms/default-catalog-ttl-ms.ts"() {
228
172
  "use strict";
229
- init_has_string_fields();
173
+ DEFAULT_CATALOG_TTL_MS = 36e5;
230
174
  }
231
175
  });
232
176
 
233
- // src/contract/predicates/is-nullable-string/is-nullable-string.ts
234
- var isNullableString;
235
- var init_is_nullable_string = __esm({
236
- "src/contract/predicates/is-nullable-string/is-nullable-string.ts"() {
177
+ // src/shared/default-catalog-ttl-ms/index.ts
178
+ var init_default_catalog_ttl_ms2 = __esm({
179
+ "src/shared/default-catalog-ttl-ms/index.ts"() {
237
180
  "use strict";
238
- isNullableString = (value) => typeof value === "string" || value === null;
181
+ init_default_catalog_ttl_ms();
239
182
  }
240
183
  });
241
184
 
242
- // src/contract/predicates/is-nullable-string/index.ts
243
- var init_is_nullable_string2 = __esm({
244
- "src/contract/predicates/is-nullable-string/index.ts"() {
185
+ // src/shared/logger/logger.ts
186
+ var logger;
187
+ var init_logger = __esm({
188
+ "src/shared/logger/logger.ts"() {
245
189
  "use strict";
246
- init_is_nullable_string();
190
+ logger = {
191
+ info: (...args) => {
192
+ console.log("[route_33]", ...args);
193
+ },
194
+ warn: (...args) => {
195
+ console.warn("[route_33]", ...args);
196
+ },
197
+ error: (...args) => {
198
+ console.error("[route_33]", ...args);
199
+ }
200
+ };
247
201
  }
248
202
  });
249
203
 
250
- // src/contract/predicates/is-owner-type/is-owner-type.ts
251
- var isOwnerType;
252
- var init_is_owner_type = __esm({
253
- "src/contract/predicates/is-owner-type/is-owner-type.ts"() {
204
+ // src/shared/logger/index.ts
205
+ var init_logger2 = __esm({
206
+ "src/shared/logger/index.ts"() {
254
207
  "use strict";
255
- isOwnerType = (value) => value === "project" || value === "user_personal" || value === "user_project";
208
+ init_logger();
256
209
  }
257
210
  });
258
211
 
259
- // src/contract/predicates/is-owner-type/index.ts
260
- var init_is_owner_type2 = __esm({
261
- "src/contract/predicates/is-owner-type/index.ts"() {
212
+ // src/shared/model-capabilities/index.ts
213
+ var init_model_capabilities = __esm({
214
+ "src/shared/model-capabilities/index.ts"() {
262
215
  "use strict";
263
- init_is_owner_type();
264
216
  }
265
217
  });
266
218
 
267
- // src/contract/predicates/is-record/is-record.ts
268
- var isRecord;
269
- var init_is_record = __esm({
270
- "src/contract/predicates/is-record/is-record.ts"() {
219
+ // src/shared/model-cost/index.ts
220
+ var init_model_cost = __esm({
221
+ "src/shared/model-cost/index.ts"() {
271
222
  "use strict";
272
- isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
273
223
  }
274
224
  });
275
225
 
276
- // src/contract/predicates/is-record/index.ts
277
- var init_is_record2 = __esm({
278
- "src/contract/predicates/is-record/index.ts"() {
226
+ // src/shared/model-limit/index.ts
227
+ var init_model_limit = __esm({
228
+ "src/shared/model-limit/index.ts"() {
279
229
  "use strict";
280
- init_is_record();
281
230
  }
282
231
  });
283
232
 
284
- // src/contract/predicates/index.ts
285
- var init_predicates = __esm({
286
- "src/contract/predicates/index.ts"() {
233
+ // src/shared/model-meta/index.ts
234
+ var init_model_meta = __esm({
235
+ "src/shared/model-meta/index.ts"() {
287
236
  "use strict";
288
- init_has_string_fields2();
289
- init_is_nullable_string2();
290
- init_is_owner_type2();
291
- init_is_record2();
292
237
  }
293
238
  });
294
239
 
295
- // src/contract/adapters/parse-management-subject/parse-management-subject.ts
296
- var parseManagementSubject;
297
- var init_parse_management_subject = __esm({
298
- "src/contract/adapters/parse-management-subject/parse-management-subject.ts"() {
240
+ // src/shared/models-dev-ttl-ms/models-dev-ttl-ms.ts
241
+ var MODELS_DEV_TTL_MS;
242
+ var init_models_dev_ttl_ms = __esm({
243
+ "src/shared/models-dev-ttl-ms/models-dev-ttl-ms.ts"() {
299
244
  "use strict";
300
- init_predicates();
301
- init_contract_parse_error2();
302
- parseManagementSubject = (credential) => {
303
- const encodedPayload = credential.value.split(".")[1];
304
- if (encodedPayload === void 0 || encodedPayload.length === 0) {
305
- throw new ContractParseError("management token carries no usable subject");
306
- }
307
- let payload;
308
- try {
309
- payload = JSON.parse(
310
- Buffer.from(encodedPayload, "base64url").toString("utf8")
311
- );
312
- } catch {
313
- throw new ContractParseError("management token payload is not JSON");
314
- }
315
- if (!isRecord(payload)) {
316
- throw new ContractParseError("management token payload is not an object");
317
- }
318
- const subject = payload["sub"];
319
- if (typeof subject !== "string" || subject.length === 0) {
320
- throw new ContractParseError("management token carries no usable subject");
321
- }
322
- return subject;
323
- };
245
+ MODELS_DEV_TTL_MS = 864e5;
324
246
  }
325
247
  });
326
248
 
327
- // src/contract/adapters/parse-management-subject/index.ts
328
- var init_parse_management_subject2 = __esm({
329
- "src/contract/adapters/parse-management-subject/index.ts"() {
249
+ // src/shared/models-dev-ttl-ms/index.ts
250
+ var init_models_dev_ttl_ms2 = __esm({
251
+ "src/shared/models-dev-ttl-ms/index.ts"() {
330
252
  "use strict";
331
- init_parse_management_subject();
253
+ init_models_dev_ttl_ms();
332
254
  }
333
255
  });
334
256
 
335
- // src/contract/adapters/index.ts
336
- var init_adapters = __esm({
337
- "src/contract/adapters/index.ts"() {
257
+ // src/shared/native-sdk-api-key-placeholder/native-sdk-api-key-placeholder.ts
258
+ var NATIVE_SDK_API_KEY_PLACEHOLDER;
259
+ var init_native_sdk_api_key_placeholder = __esm({
260
+ "src/shared/native-sdk-api-key-placeholder/native-sdk-api-key-placeholder.ts"() {
338
261
  "use strict";
339
- init_contract_parse_error2();
340
- init_gateway_api_key2();
341
- init_management_jwt2();
342
- init_parse_gateway_key2();
343
- init_parse_management_jwt2();
344
- init_parse_management_subject2();
262
+ NATIVE_SDK_API_KEY_PLACEHOLDER = "__route33_fetch_shim_auth__";
345
263
  }
346
264
  });
347
265
 
348
- // src/attribution/parse-attribution/parse-attribution.ts
349
- var parseAttribution;
350
- var init_parse_attribution = __esm({
351
- "src/attribution/parse-attribution/parse-attribution.ts"() {
266
+ // src/shared/native-sdk-api-key-placeholder/index.ts
267
+ var init_native_sdk_api_key_placeholder2 = __esm({
268
+ "src/shared/native-sdk-api-key-placeholder/index.ts"() {
352
269
  "use strict";
353
- init_adapters();
354
- init_predicates();
355
- parseAttribution = (value) => {
356
- if (!isRecord(value)) {
357
- throw new ContractParseError("invalid attribution");
358
- }
359
- if (value["kind"] === "personal") {
360
- return { kind: "personal" };
361
- }
362
- if (value["kind"] === "project" && typeof value["projectId"] === "string") {
363
- return { kind: "project", projectId: value["projectId"] };
364
- }
365
- throw new ContractParseError("invalid attribution");
366
- };
270
+ init_native_sdk_api_key_placeholder();
367
271
  }
368
272
  });
369
273
 
370
- // src/attribution/parse-attribution/index.ts
371
- var init_parse_attribution2 = __esm({
372
- "src/attribution/parse-attribution/index.ts"() {
274
+ // src/shared/r33-catalog-model/index.ts
275
+ var init_r33_catalog_model = __esm({
276
+ "src/shared/r33-catalog-model/index.ts"() {
373
277
  "use strict";
374
- init_parse_attribution();
375
278
  }
376
279
  });
377
280
 
378
- // src/attribution/read-attribution/read-attribution.ts
379
- import * as fs4 from "node:fs";
380
- var readAttribution;
381
- var init_read_attribution = __esm({
382
- "src/attribution/read-attribution/read-attribution.ts"() {
281
+ // src/shared/resolve-cache-dir/resolve-cache-dir.ts
282
+ import * as os from "node:os";
283
+ import * as path from "node:path";
284
+ var resolveCacheDir;
285
+ var init_resolve_cache_dir = __esm({
286
+ "src/shared/resolve-cache-dir/resolve-cache-dir.ts"() {
383
287
  "use strict";
384
- init_parse_attribution2();
385
- init_resolve_attribution_file2();
386
- readAttribution = (options) => {
387
- const file = resolveAttributionFile(options);
388
- if (file === void 0) {
389
- return void 0;
390
- }
391
- try {
392
- const parsed = JSON.parse(fs4.readFileSync(file, "utf8"));
393
- return parseAttribution(parsed);
394
- } catch {
395
- return void 0;
288
+ resolveCacheDir = (env) => {
289
+ const override = env["ROUTE33_CACHE_DIR"];
290
+ if (override !== void 0 && override !== "") {
291
+ return override;
396
292
  }
293
+ return path.join(
294
+ env["XDG_CACHE_HOME"] ?? path.join(os.homedir(), ".cache"),
295
+ "opencode-route33"
296
+ );
397
297
  };
398
298
  }
399
299
  });
400
300
 
401
- // src/attribution/read-attribution/index.ts
402
- var init_read_attribution2 = __esm({
403
- "src/attribution/read-attribution/index.ts"() {
301
+ // src/shared/resolve-cache-dir/index.ts
302
+ var init_resolve_cache_dir2 = __esm({
303
+ "src/shared/resolve-cache-dir/index.ts"() {
404
304
  "use strict";
405
- init_read_attribution();
305
+ init_resolve_cache_dir();
406
306
  }
407
307
  });
408
308
 
409
- // src/attribution/write-attribution/write-attribution.ts
410
- import { randomUUID } from "node:crypto";
411
- import * as fs5 from "node:fs";
412
- import * as path3 from "node:path";
413
- var writeAttribution;
414
- var init_write_attribution = __esm({
415
- "src/attribution/write-attribution/write-attribution.ts"() {
309
+ // src/shared/index.ts
310
+ var init_shared = __esm({
311
+ "src/shared/index.ts"() {
416
312
  "use strict";
417
- init_resolve_attribution_file2();
418
- writeAttribution = (options, attribution) => {
419
- const file = resolveAttributionFile(options);
420
- if (file === void 0) {
421
- return false;
422
- }
423
- fs5.mkdirSync(path3.dirname(file), { recursive: true });
424
- const temporaryFile = `${file}.${String(process.pid)}.${randomUUID()}.tmp`;
425
- try {
426
- fs5.writeFileSync(temporaryFile, `${JSON.stringify(attribution)}
427
- `, "utf8");
428
- fs5.renameSync(temporaryFile, file);
429
- } catch (error) {
430
- fs5.rmSync(temporaryFile, { force: true });
431
- throw error;
432
- }
433
- return true;
434
- };
313
+ init_canonical_slug();
314
+ init_catalog_result();
315
+ init_catalog_source();
316
+ init_default_auth_issuer_url2();
317
+ init_default_base_url2();
318
+ init_default_management_api_base_url2();
319
+ init_default_catalog_ttl_ms2();
320
+ init_logger2();
321
+ init_model_capabilities();
322
+ init_model_cost();
323
+ init_model_limit();
324
+ init_model_meta();
325
+ init_models_dev_ttl_ms2();
326
+ init_native_sdk_api_key_placeholder2();
327
+ init_r33_catalog_model();
328
+ init_resolve_cache_dir2();
435
329
  }
436
330
  });
437
331
 
438
- // src/attribution/write-attribution/index.ts
439
- var init_write_attribution2 = __esm({
440
- "src/attribution/write-attribution/index.ts"() {
332
+ // src/cli/read-env-cache-dir/read-env-cache-dir.ts
333
+ var readEnvCacheDir;
334
+ var init_read_env_cache_dir = __esm({
335
+ "src/cli/read-env-cache-dir/read-env-cache-dir.ts"() {
441
336
  "use strict";
442
- init_write_attribution();
337
+ init_shared();
338
+ readEnvCacheDir = (env = process.env) => resolveCacheDir(env);
443
339
  }
444
340
  });
445
341
 
446
- // src/attribution/index.ts
447
- var init_attribution = __esm({
448
- "src/attribution/index.ts"() {
342
+ // src/cli/read-env-cache-dir/index.ts
343
+ var init_read_env_cache_dir2 = __esm({
344
+ "src/cli/read-env-cache-dir/index.ts"() {
449
345
  "use strict";
450
- init_clear_attribution2();
451
- init_detect_worktree_root2();
452
- init_parse_attribution2();
453
- init_read_attribution2();
454
- init_resolve_attribution_file2();
455
- init_write_attribution2();
346
+ init_read_env_cache_dir();
456
347
  }
457
348
  });
458
349
 
459
- // src/cli/read-env-base-url/read-env-base-url.ts
460
- var readEnvBaseUrl;
461
- var init_read_env_base_url = __esm({
462
- "src/cli/read-env-base-url/read-env-base-url.ts"() {
350
+ // src/cli/read-env-catalog-ttl-ms/read-env-catalog-ttl-ms.ts
351
+ var readEnvCatalogTtlMs;
352
+ var init_read_env_catalog_ttl_ms = __esm({
353
+ "src/cli/read-env-catalog-ttl-ms/read-env-catalog-ttl-ms.ts"() {
463
354
  "use strict";
464
- readEnvBaseUrl = (env = process.env) => {
465
- const value = env["ROUTE33_BASE_URL"]?.trim();
466
- return value === "" ? void 0 : value;
355
+ init_shared();
356
+ readEnvCatalogTtlMs = (env = process.env) => {
357
+ const value = Number(env["ROUTE33_CATALOG_TTL_MS"]);
358
+ return Number.isFinite(value) && value > 0 ? value : DEFAULT_CATALOG_TTL_MS;
467
359
  };
468
360
  }
469
361
  });
470
362
 
471
- // src/cli/read-env-base-url/index.ts
472
- var init_read_env_base_url2 = __esm({
473
- "src/cli/read-env-base-url/index.ts"() {
363
+ // src/cli/read-env-catalog-ttl-ms/index.ts
364
+ var init_read_env_catalog_ttl_ms2 = __esm({
365
+ "src/cli/read-env-catalog-ttl-ms/index.ts"() {
474
366
  "use strict";
475
- init_read_env_base_url();
367
+ init_read_env_catalog_ttl_ms();
476
368
  }
477
369
  });
478
370
 
479
- // src/cli/read-env-api-base/read-env-api-base.ts
480
- var readEnvApiBase;
481
- var init_read_env_api_base = __esm({
482
- "src/cli/read-env-api-base/read-env-api-base.ts"() {
371
+ // src/cli/read-env-client-id/read-env-client-id.ts
372
+ var readEnvClientId;
373
+ var init_read_env_client_id = __esm({
374
+ "src/cli/read-env-client-id/read-env-client-id.ts"() {
483
375
  "use strict";
484
- readEnvApiBase = (env = process.env) => {
485
- const value = env["ROUTE33_API_BASE"]?.trim();
376
+ readEnvClientId = (env = process.env) => {
377
+ const value = env["ROUTE33_CLIENT_ID"]?.trim();
486
378
  return value === "" ? void 0 : value;
487
379
  };
488
380
  }
489
381
  });
490
382
 
491
- // src/cli/read-env-api-base/index.ts
492
- var init_read_env_api_base2 = __esm({
493
- "src/cli/read-env-api-base/index.ts"() {
383
+ // src/cli/read-env-client-id/index.ts
384
+ var init_read_env_client_id2 = __esm({
385
+ "src/cli/read-env-client-id/index.ts"() {
494
386
  "use strict";
495
- init_read_env_api_base();
387
+ init_read_env_client_id();
496
388
  }
497
389
  });
498
390
 
499
- // src/cli/read-env-auth-issuer/read-env-auth-issuer.ts
500
- var readEnvAuthIssuer;
501
- var init_read_env_auth_issuer = __esm({
502
- "src/cli/read-env-auth-issuer/read-env-auth-issuer.ts"() {
391
+ // src/cli/read-env-direct-api-key/read-env-direct-api-key.ts
392
+ var readEnvDirectApiKey;
393
+ var init_read_env_direct_api_key = __esm({
394
+ "src/cli/read-env-direct-api-key/read-env-direct-api-key.ts"() {
503
395
  "use strict";
504
- readEnvAuthIssuer = (env = process.env) => {
505
- const value = env["ROUTE33_AUTH_ISSUER"]?.trim();
396
+ readEnvDirectApiKey = (env = process.env) => {
397
+ const value = env["ROUTE33_API_KEY"]?.trim();
506
398
  return value === "" ? void 0 : value;
507
399
  };
508
400
  }
509
401
  });
510
402
 
511
- // src/cli/read-env-auth-issuer/index.ts
512
- var init_read_env_auth_issuer2 = __esm({
513
- "src/cli/read-env-auth-issuer/index.ts"() {
403
+ // src/cli/read-env-direct-api-key/index.ts
404
+ var init_read_env_direct_api_key2 = __esm({
405
+ "src/cli/read-env-direct-api-key/index.ts"() {
514
406
  "use strict";
515
- init_read_env_auth_issuer();
407
+ init_read_env_direct_api_key();
516
408
  }
517
409
  });
518
410
 
519
- // src/cli/read-env-autoconnect-disabled/read-env-autoconnect-disabled.ts
520
- var readEnvAutoconnectDisabled;
521
- var init_read_env_autoconnect_disabled = __esm({
522
- "src/cli/read-env-autoconnect-disabled/read-env-autoconnect-disabled.ts"() {
411
+ // src/cli/read-env-disable-id-shim/read-env-disable-id-shim.ts
412
+ var readEnvDisableIdShim;
413
+ var init_read_env_disable_id_shim = __esm({
414
+ "src/cli/read-env-disable-id-shim/read-env-disable-id-shim.ts"() {
523
415
  "use strict";
524
- readEnvAutoconnectDisabled = (env = process.env) => {
525
- const value = env["ROUTE33_AUTOCONNECT"]?.trim().toLowerCase();
526
- return value === "0" || value === "false" || value === "no" || value === "off";
527
- };
416
+ readEnvDisableIdShim = (env = process.env) => env["ROUTE33_DISABLE_ID_SHIM"] === "1";
528
417
  }
529
418
  });
530
419
 
531
- // src/cli/read-env-autoconnect-disabled/index.ts
532
- var init_read_env_autoconnect_disabled2 = __esm({
533
- "src/cli/read-env-autoconnect-disabled/index.ts"() {
420
+ // src/cli/read-env-disable-id-shim/index.ts
421
+ var init_read_env_disable_id_shim2 = __esm({
422
+ "src/cli/read-env-disable-id-shim/index.ts"() {
534
423
  "use strict";
535
- init_read_env_autoconnect_disabled();
424
+ init_read_env_disable_id_shim();
536
425
  }
537
426
  });
538
427
 
539
- // src/shared/canonical-slug/index.ts
540
- var init_canonical_slug = __esm({
541
- "src/shared/canonical-slug/index.ts"() {
428
+ // src/cli/read-env-discovery/read-env-discovery.ts
429
+ var readEnvDiscovery;
430
+ var init_read_env_discovery = __esm({
431
+ "src/cli/read-env-discovery/read-env-discovery.ts"() {
542
432
  "use strict";
433
+ readEnvDiscovery = (env = process.env) => env["ROUTE33_DISCOVERY"] !== "0";
543
434
  }
544
435
  });
545
436
 
546
- // src/shared/catalog-result/index.ts
547
- var init_catalog_result = __esm({
548
- "src/shared/catalog-result/index.ts"() {
437
+ // src/cli/read-env-discovery/index.ts
438
+ var init_read_env_discovery2 = __esm({
439
+ "src/cli/read-env-discovery/index.ts"() {
549
440
  "use strict";
441
+ init_read_env_discovery();
550
442
  }
551
443
  });
552
444
 
553
- // src/shared/catalog-source/index.ts
554
- var init_catalog_source = __esm({
555
- "src/shared/catalog-source/index.ts"() {
445
+ // src/cli/read-env-strict/read-env-strict.ts
446
+ var readEnvStrict;
447
+ var init_read_env_strict = __esm({
448
+ "src/cli/read-env-strict/read-env-strict.ts"() {
556
449
  "use strict";
450
+ readEnvStrict = (env = process.env) => env["ROUTE33_STRICT"] !== "0";
557
451
  }
558
452
  });
559
453
 
560
- // src/shared/default-auth-issuer-url/default-auth-issuer-url.ts
561
- var DEFAULT_AUTH_ISSUER_URL;
562
- var init_default_auth_issuer_url = __esm({
563
- "src/shared/default-auth-issuer-url/default-auth-issuer-url.ts"() {
454
+ // src/cli/read-env-strict/index.ts
455
+ var init_read_env_strict2 = __esm({
456
+ "src/cli/read-env-strict/index.ts"() {
564
457
  "use strict";
565
- DEFAULT_AUTH_ISSUER_URL = "https://auth.route33.ai";
458
+ init_read_env_strict();
566
459
  }
567
460
  });
568
461
 
569
- // src/shared/default-auth-issuer-url/index.ts
570
- var init_default_auth_issuer_url2 = __esm({
571
- "src/shared/default-auth-issuer-url/index.ts"() {
462
+ // src/cli/resolve-v1-secret-store-directory/resolve-v1-secret-store-directory.ts
463
+ import * as os2 from "node:os";
464
+ import * as path2 from "node:path";
465
+ var resolveV1SecretStoreDirectory;
466
+ var init_resolve_v1_secret_store_directory = __esm({
467
+ "src/cli/resolve-v1-secret-store-directory/resolve-v1-secret-store-directory.ts"() {
572
468
  "use strict";
573
- init_default_auth_issuer_url();
469
+ resolveV1SecretStoreDirectory = (options = {}) => {
470
+ const explicit = options.directory?.trim();
471
+ if (explicit !== void 0 && explicit.length > 0) {
472
+ return path2.resolve(explicit);
473
+ }
474
+ const hostConfig = (options.env ?? process.env)["OPENCODE_CONFIG_DIR"]?.trim();
475
+ if (hostConfig !== void 0 && hostConfig.length > 0) {
476
+ return path2.join(path2.resolve(hostConfig), "route33");
477
+ }
478
+ return path2.join(
479
+ options.homeDirectory ?? os2.homedir(),
480
+ ".config",
481
+ "opencode",
482
+ "route33"
483
+ );
484
+ };
574
485
  }
575
486
  });
576
487
 
577
- // src/shared/default-base-url/default-base-url.ts
578
- var DEFAULT_BASE_URL;
579
- var init_default_base_url = __esm({
580
- "src/shared/default-base-url/default-base-url.ts"() {
488
+ // src/cli/resolve-v1-secret-store-directory/index.ts
489
+ var init_resolve_v1_secret_store_directory2 = __esm({
490
+ "src/cli/resolve-v1-secret-store-directory/index.ts"() {
581
491
  "use strict";
582
- DEFAULT_BASE_URL = "https://api.route33.ai/v1";
492
+ init_resolve_v1_secret_store_directory();
583
493
  }
584
494
  });
585
495
 
586
- // src/shared/default-base-url/index.ts
587
- var init_default_base_url2 = __esm({
588
- "src/shared/default-base-url/index.ts"() {
496
+ // src/cli/index.ts
497
+ var init_cli = __esm({
498
+ "src/cli/index.ts"() {
589
499
  "use strict";
590
- init_default_base_url();
500
+ init_read_env_base_url2();
501
+ init_read_env_api_base2();
502
+ init_read_env_auth_issuer2();
503
+ init_read_env_autoconnect_disabled2();
504
+ init_read_env_cache_dir2();
505
+ init_read_env_catalog_ttl_ms2();
506
+ init_read_env_client_id2();
507
+ init_read_env_direct_api_key2();
508
+ init_read_env_disable_id_shim2();
509
+ init_read_env_discovery2();
510
+ init_read_env_strict2();
511
+ init_resolve_v1_secret_store_directory2();
591
512
  }
592
513
  });
593
514
 
594
- // src/shared/default-management-api-base-url/default-management-api-base-url.ts
595
- var DEFAULT_MANAGEMENT_API_BASE_URL;
596
- var init_default_management_api_base_url = __esm({
597
- "src/shared/default-management-api-base-url/default-management-api-base-url.ts"() {
515
+ // src/auth/auth-error/auth-error.ts
516
+ var AuthError;
517
+ var init_auth_error = __esm({
518
+ "src/auth/auth-error/auth-error.ts"() {
598
519
  "use strict";
599
- DEFAULT_MANAGEMENT_API_BASE_URL = "https://mapi.route33.ai/api/v1";
520
+ AuthError = class extends Error {
521
+ constructor(code, options) {
522
+ super(
523
+ "Route 33 authorization failed",
524
+ options?.cause === void 0 ? void 0 : { cause: options.cause }
525
+ );
526
+ this.code = code;
527
+ this.name = "AuthError";
528
+ this.statusCode = options?.statusCode;
529
+ }
530
+ code;
531
+ statusCode;
532
+ };
600
533
  }
601
534
  });
602
535
 
603
- // src/shared/default-management-api-base-url/index.ts
604
- var init_default_management_api_base_url2 = __esm({
605
- "src/shared/default-management-api-base-url/index.ts"() {
536
+ // src/auth/auth-error/index.ts
537
+ var init_auth_error2 = __esm({
538
+ "src/auth/auth-error/index.ts"() {
606
539
  "use strict";
607
- init_default_management_api_base_url();
540
+ init_auth_error();
608
541
  }
609
542
  });
610
543
 
611
- // src/shared/default-catalog-ttl-ms/default-catalog-ttl-ms.ts
612
- var DEFAULT_CATALOG_TTL_MS;
613
- var init_default_catalog_ttl_ms = __esm({
614
- "src/shared/default-catalog-ttl-ms/default-catalog-ttl-ms.ts"() {
544
+ // src/auth/build-authorize-url/build-authorize-url.ts
545
+ var buildAuthorizeUrl;
546
+ var init_build_authorize_url = __esm({
547
+ "src/auth/build-authorize-url/build-authorize-url.ts"() {
615
548
  "use strict";
616
- DEFAULT_CATALOG_TTL_MS = 36e5;
549
+ buildAuthorizeUrl = (issuerUrl, request) => {
550
+ const url = new URL("/authorize", issuerUrl);
551
+ url.search = new URLSearchParams({
552
+ client_id: request.clientId,
553
+ code_challenge: request.codeChallenge,
554
+ code_challenge_method: "S256",
555
+ redirect_uri: request.redirectUri,
556
+ response_type: "code",
557
+ scope: request.scope,
558
+ state: request.state
559
+ }).toString();
560
+ return url;
561
+ };
617
562
  }
618
563
  });
619
564
 
620
- // src/shared/default-catalog-ttl-ms/index.ts
621
- var init_default_catalog_ttl_ms2 = __esm({
622
- "src/shared/default-catalog-ttl-ms/index.ts"() {
565
+ // src/auth/build-authorize-url/index.ts
566
+ var init_build_authorize_url2 = __esm({
567
+ "src/auth/build-authorize-url/index.ts"() {
623
568
  "use strict";
624
- init_default_catalog_ttl_ms();
569
+ init_build_authorize_url();
625
570
  }
626
571
  });
627
572
 
628
- // src/shared/logger/logger.ts
629
- var logger;
630
- var init_logger = __esm({
631
- "src/shared/logger/logger.ts"() {
573
+ // src/contract/adapters/contract-parse-error/contract-parse-error.ts
574
+ var ContractParseError;
575
+ var init_contract_parse_error = __esm({
576
+ "src/contract/adapters/contract-parse-error/contract-parse-error.ts"() {
632
577
  "use strict";
633
- logger = {
634
- info: (...args) => {
635
- console.log("[route_33]", ...args);
636
- },
637
- warn: (...args) => {
638
- console.warn("[route_33]", ...args);
639
- },
640
- error: (...args) => {
641
- console.error("[route_33]", ...args);
642
- }
578
+ ContractParseError = class extends Error {
643
579
  };
644
580
  }
645
581
  });
646
582
 
647
- // src/shared/logger/index.ts
648
- var init_logger2 = __esm({
649
- "src/shared/logger/index.ts"() {
583
+ // src/contract/adapters/contract-parse-error/index.ts
584
+ var init_contract_parse_error2 = __esm({
585
+ "src/contract/adapters/contract-parse-error/index.ts"() {
650
586
  "use strict";
651
- init_logger();
587
+ init_contract_parse_error();
652
588
  }
653
589
  });
654
590
 
655
- // src/shared/model-capabilities/index.ts
656
- var init_model_capabilities = __esm({
657
- "src/shared/model-capabilities/index.ts"() {
591
+ // src/contract/adapters/gateway-api-key/gateway-api-key.ts
592
+ var GatewayApiKey;
593
+ var init_gateway_api_key = __esm({
594
+ "src/contract/adapters/gateway-api-key/gateway-api-key.ts"() {
658
595
  "use strict";
596
+ GatewayApiKey = class {
597
+ value;
598
+ constructor(value) {
599
+ this.value = value;
600
+ }
601
+ };
659
602
  }
660
603
  });
661
604
 
662
- // src/shared/model-cost/index.ts
663
- var init_model_cost = __esm({
664
- "src/shared/model-cost/index.ts"() {
605
+ // src/contract/adapters/gateway-api-key/index.ts
606
+ var init_gateway_api_key2 = __esm({
607
+ "src/contract/adapters/gateway-api-key/index.ts"() {
665
608
  "use strict";
609
+ init_gateway_api_key();
666
610
  }
667
611
  });
668
612
 
669
- // src/shared/model-limit/index.ts
670
- var init_model_limit = __esm({
671
- "src/shared/model-limit/index.ts"() {
613
+ // src/contract/adapters/management-jwt/management-jwt.ts
614
+ var ManagementJwt;
615
+ var init_management_jwt = __esm({
616
+ "src/contract/adapters/management-jwt/management-jwt.ts"() {
672
617
  "use strict";
618
+ ManagementJwt = class {
619
+ value;
620
+ constructor(value) {
621
+ this.value = value;
622
+ }
623
+ };
673
624
  }
674
625
  });
675
626
 
676
- // src/shared/model-meta/index.ts
677
- var init_model_meta = __esm({
678
- "src/shared/model-meta/index.ts"() {
627
+ // src/contract/adapters/management-jwt/index.ts
628
+ var init_management_jwt2 = __esm({
629
+ "src/contract/adapters/management-jwt/index.ts"() {
679
630
  "use strict";
631
+ init_management_jwt();
680
632
  }
681
633
  });
682
634
 
683
- // src/shared/models-dev-ttl-ms/models-dev-ttl-ms.ts
684
- var MODELS_DEV_TTL_MS;
685
- var init_models_dev_ttl_ms = __esm({
686
- "src/shared/models-dev-ttl-ms/models-dev-ttl-ms.ts"() {
687
- "use strict";
688
- MODELS_DEV_TTL_MS = 864e5;
689
- }
690
- });
691
-
692
- // src/shared/models-dev-ttl-ms/index.ts
693
- var init_models_dev_ttl_ms2 = __esm({
694
- "src/shared/models-dev-ttl-ms/index.ts"() {
695
- "use strict";
696
- init_models_dev_ttl_ms();
697
- }
698
- });
699
-
700
- // src/shared/native-sdk-api-key-placeholder/native-sdk-api-key-placeholder.ts
701
- var NATIVE_SDK_API_KEY_PLACEHOLDER;
702
- var init_native_sdk_api_key_placeholder = __esm({
703
- "src/shared/native-sdk-api-key-placeholder/native-sdk-api-key-placeholder.ts"() {
704
- "use strict";
705
- NATIVE_SDK_API_KEY_PLACEHOLDER = "__route33_fetch_shim_auth__";
706
- }
707
- });
708
-
709
- // src/shared/native-sdk-api-key-placeholder/index.ts
710
- var init_native_sdk_api_key_placeholder2 = __esm({
711
- "src/shared/native-sdk-api-key-placeholder/index.ts"() {
712
- "use strict";
713
- init_native_sdk_api_key_placeholder();
714
- }
715
- });
716
-
717
- // src/shared/r33-catalog-model/index.ts
718
- var init_r33_catalog_model = __esm({
719
- "src/shared/r33-catalog-model/index.ts"() {
720
- "use strict";
721
- }
722
- });
723
-
724
- // src/shared/resolve-cache-dir/resolve-cache-dir.ts
725
- import * as os from "node:os";
726
- import * as path4 from "node:path";
727
- var resolveCacheDir;
728
- var init_resolve_cache_dir = __esm({
729
- "src/shared/resolve-cache-dir/resolve-cache-dir.ts"() {
635
+ // src/contract/adapters/parse-gateway-key/parse-gateway-key.ts
636
+ var parseGatewayKey;
637
+ var init_parse_gateway_key = __esm({
638
+ "src/contract/adapters/parse-gateway-key/parse-gateway-key.ts"() {
730
639
  "use strict";
731
- resolveCacheDir = (env) => {
732
- const override = env["ROUTE33_CACHE_DIR"];
733
- if (override !== void 0 && override !== "") {
734
- return override;
640
+ init_gateway_api_key2();
641
+ parseGatewayKey = (value) => {
642
+ if (typeof value !== "string" || value.length === 0) {
643
+ throw new Error("gateway key must be non-empty");
735
644
  }
736
- return path4.join(
737
- env["XDG_CACHE_HOME"] ?? path4.join(os.homedir(), ".cache"),
738
- "opencode-route33"
739
- );
645
+ return new GatewayApiKey(value);
740
646
  };
741
647
  }
742
648
  });
743
649
 
744
- // src/shared/resolve-cache-dir/index.ts
745
- var init_resolve_cache_dir2 = __esm({
746
- "src/shared/resolve-cache-dir/index.ts"() {
747
- "use strict";
748
- init_resolve_cache_dir();
749
- }
750
- });
751
-
752
- // src/shared/index.ts
753
- var init_shared = __esm({
754
- "src/shared/index.ts"() {
755
- "use strict";
756
- init_canonical_slug();
757
- init_catalog_result();
758
- init_catalog_source();
759
- init_default_auth_issuer_url2();
760
- init_default_base_url2();
761
- init_default_management_api_base_url2();
762
- init_default_catalog_ttl_ms2();
763
- init_logger2();
764
- init_model_capabilities();
765
- init_model_cost();
766
- init_model_limit();
767
- init_model_meta();
768
- init_models_dev_ttl_ms2();
769
- init_native_sdk_api_key_placeholder2();
770
- init_r33_catalog_model();
771
- init_resolve_cache_dir2();
772
- }
773
- });
774
-
775
- // src/cli/read-env-cache-dir/read-env-cache-dir.ts
776
- var readEnvCacheDir;
777
- var init_read_env_cache_dir = __esm({
778
- "src/cli/read-env-cache-dir/read-env-cache-dir.ts"() {
779
- "use strict";
780
- init_shared();
781
- readEnvCacheDir = (env = process.env) => resolveCacheDir(env);
782
- }
783
- });
784
-
785
- // src/cli/read-env-cache-dir/index.ts
786
- var init_read_env_cache_dir2 = __esm({
787
- "src/cli/read-env-cache-dir/index.ts"() {
650
+ // src/contract/adapters/parse-gateway-key/index.ts
651
+ var init_parse_gateway_key2 = __esm({
652
+ "src/contract/adapters/parse-gateway-key/index.ts"() {
788
653
  "use strict";
789
- init_read_env_cache_dir();
654
+ init_parse_gateway_key();
790
655
  }
791
656
  });
792
657
 
793
- // src/cli/read-env-catalog-ttl-ms/read-env-catalog-ttl-ms.ts
794
- var readEnvCatalogTtlMs;
795
- var init_read_env_catalog_ttl_ms = __esm({
796
- "src/cli/read-env-catalog-ttl-ms/read-env-catalog-ttl-ms.ts"() {
658
+ // src/contract/adapters/parse-management-jwt/parse-management-jwt.ts
659
+ var parseManagementJwt;
660
+ var init_parse_management_jwt = __esm({
661
+ "src/contract/adapters/parse-management-jwt/parse-management-jwt.ts"() {
797
662
  "use strict";
798
- init_shared();
799
- readEnvCatalogTtlMs = (env = process.env) => {
800
- const value = Number(env["ROUTE33_CATALOG_TTL_MS"]);
801
- return Number.isFinite(value) && value > 0 ? value : DEFAULT_CATALOG_TTL_MS;
663
+ init_management_jwt2();
664
+ parseManagementJwt = (value) => {
665
+ if (typeof value !== "string" || value.length === 0) {
666
+ throw new Error("management token must be non-empty");
667
+ }
668
+ return new ManagementJwt(value);
802
669
  };
803
670
  }
804
671
  });
805
672
 
806
- // src/cli/read-env-catalog-ttl-ms/index.ts
807
- var init_read_env_catalog_ttl_ms2 = __esm({
808
- "src/cli/read-env-catalog-ttl-ms/index.ts"() {
809
- "use strict";
810
- init_read_env_catalog_ttl_ms();
811
- }
812
- });
813
-
814
- // src/cli/read-env-client-id/read-env-client-id.ts
815
- var readEnvClientId;
816
- var init_read_env_client_id = __esm({
817
- "src/cli/read-env-client-id/read-env-client-id.ts"() {
673
+ // src/contract/adapters/parse-management-jwt/index.ts
674
+ var init_parse_management_jwt2 = __esm({
675
+ "src/contract/adapters/parse-management-jwt/index.ts"() {
818
676
  "use strict";
819
- readEnvClientId = (env = process.env) => {
820
- const value = env["ROUTE33_CLIENT_ID"]?.trim();
821
- return value === "" ? void 0 : value;
822
- };
677
+ init_parse_management_jwt();
823
678
  }
824
679
  });
825
680
 
826
- // src/cli/read-env-client-id/index.ts
827
- var init_read_env_client_id2 = __esm({
828
- "src/cli/read-env-client-id/index.ts"() {
681
+ // src/contract/predicates/has-string-fields/has-string-fields.ts
682
+ var hasStringFields;
683
+ var init_has_string_fields = __esm({
684
+ "src/contract/predicates/has-string-fields/has-string-fields.ts"() {
829
685
  "use strict";
830
- init_read_env_client_id();
686
+ hasStringFields = (record, fields) => fields.every((field) => typeof record[field] === "string");
831
687
  }
832
688
  });
833
689
 
834
- // src/cli/read-env-direct-api-key/read-env-direct-api-key.ts
835
- var readEnvDirectApiKey;
836
- var init_read_env_direct_api_key = __esm({
837
- "src/cli/read-env-direct-api-key/read-env-direct-api-key.ts"() {
690
+ // src/contract/predicates/has-string-fields/index.ts
691
+ var init_has_string_fields2 = __esm({
692
+ "src/contract/predicates/has-string-fields/index.ts"() {
838
693
  "use strict";
839
- readEnvDirectApiKey = (env = process.env) => {
840
- const value = env["ROUTE33_API_KEY"]?.trim();
841
- return value === "" ? void 0 : value;
842
- };
694
+ init_has_string_fields();
843
695
  }
844
696
  });
845
697
 
846
- // src/cli/read-env-direct-api-key/index.ts
847
- var init_read_env_direct_api_key2 = __esm({
848
- "src/cli/read-env-direct-api-key/index.ts"() {
698
+ // src/contract/predicates/is-nullable-string/is-nullable-string.ts
699
+ var isNullableString;
700
+ var init_is_nullable_string = __esm({
701
+ "src/contract/predicates/is-nullable-string/is-nullable-string.ts"() {
849
702
  "use strict";
850
- init_read_env_direct_api_key();
703
+ isNullableString = (value) => typeof value === "string" || value === null;
851
704
  }
852
705
  });
853
706
 
854
- // src/cli/read-env-disable-id-shim/read-env-disable-id-shim.ts
855
- var readEnvDisableIdShim;
856
- var init_read_env_disable_id_shim = __esm({
857
- "src/cli/read-env-disable-id-shim/read-env-disable-id-shim.ts"() {
707
+ // src/contract/predicates/is-nullable-string/index.ts
708
+ var init_is_nullable_string2 = __esm({
709
+ "src/contract/predicates/is-nullable-string/index.ts"() {
858
710
  "use strict";
859
- readEnvDisableIdShim = (env = process.env) => env["ROUTE33_DISABLE_ID_SHIM"] === "1";
711
+ init_is_nullable_string();
860
712
  }
861
713
  });
862
714
 
863
- // src/cli/read-env-disable-id-shim/index.ts
864
- var init_read_env_disable_id_shim2 = __esm({
865
- "src/cli/read-env-disable-id-shim/index.ts"() {
715
+ // src/contract/predicates/is-owner-type/is-owner-type.ts
716
+ var isOwnerType;
717
+ var init_is_owner_type = __esm({
718
+ "src/contract/predicates/is-owner-type/is-owner-type.ts"() {
866
719
  "use strict";
867
- init_read_env_disable_id_shim();
720
+ isOwnerType = (value) => value === "project" || value === "user_personal" || value === "user_project";
868
721
  }
869
722
  });
870
723
 
871
- // src/cli/read-env-discovery/read-env-discovery.ts
872
- var readEnvDiscovery;
873
- var init_read_env_discovery = __esm({
874
- "src/cli/read-env-discovery/read-env-discovery.ts"() {
724
+ // src/contract/predicates/is-owner-type/index.ts
725
+ var init_is_owner_type2 = __esm({
726
+ "src/contract/predicates/is-owner-type/index.ts"() {
875
727
  "use strict";
876
- readEnvDiscovery = (env = process.env) => env["ROUTE33_DISCOVERY"] !== "0";
728
+ init_is_owner_type();
877
729
  }
878
730
  });
879
731
 
880
- // src/cli/read-env-discovery/index.ts
881
- var init_read_env_discovery2 = __esm({
882
- "src/cli/read-env-discovery/index.ts"() {
732
+ // src/contract/predicates/is-record/is-record.ts
733
+ var isRecord;
734
+ var init_is_record = __esm({
735
+ "src/contract/predicates/is-record/is-record.ts"() {
883
736
  "use strict";
884
- init_read_env_discovery();
737
+ isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
885
738
  }
886
739
  });
887
740
 
888
- // src/cli/read-env-strict/read-env-strict.ts
889
- var readEnvStrict;
890
- var init_read_env_strict = __esm({
891
- "src/cli/read-env-strict/read-env-strict.ts"() {
741
+ // src/contract/predicates/is-record/index.ts
742
+ var init_is_record2 = __esm({
743
+ "src/contract/predicates/is-record/index.ts"() {
892
744
  "use strict";
893
- readEnvStrict = (env = process.env) => env["ROUTE33_STRICT"] !== "0";
745
+ init_is_record();
894
746
  }
895
747
  });
896
748
 
897
- // src/cli/read-env-strict/index.ts
898
- var init_read_env_strict2 = __esm({
899
- "src/cli/read-env-strict/index.ts"() {
749
+ // src/contract/predicates/index.ts
750
+ var init_predicates = __esm({
751
+ "src/contract/predicates/index.ts"() {
900
752
  "use strict";
901
- init_read_env_strict();
753
+ init_has_string_fields2();
754
+ init_is_nullable_string2();
755
+ init_is_owner_type2();
756
+ init_is_record2();
902
757
  }
903
758
  });
904
759
 
905
- // src/cli/resolve-v1-secret-store-directory/resolve-v1-secret-store-directory.ts
906
- import * as os2 from "node:os";
907
- import * as path5 from "node:path";
908
- var resolveV1SecretStoreDirectory;
909
- var init_resolve_v1_secret_store_directory = __esm({
910
- "src/cli/resolve-v1-secret-store-directory/resolve-v1-secret-store-directory.ts"() {
760
+ // src/contract/adapters/parse-management-subject/parse-management-subject.ts
761
+ var parseManagementSubject;
762
+ var init_parse_management_subject = __esm({
763
+ "src/contract/adapters/parse-management-subject/parse-management-subject.ts"() {
911
764
  "use strict";
912
- resolveV1SecretStoreDirectory = (options = {}) => {
913
- const explicit = options.directory?.trim();
914
- if (explicit !== void 0 && explicit.length > 0) {
915
- return path5.resolve(explicit);
916
- }
917
- const hostConfig = (options.env ?? process.env)["OPENCODE_CONFIG_DIR"]?.trim();
918
- if (hostConfig !== void 0 && hostConfig.length > 0) {
919
- return path5.join(path5.resolve(hostConfig), "route33");
765
+ init_predicates();
766
+ init_contract_parse_error2();
767
+ parseManagementSubject = (credential) => {
768
+ const encodedPayload = credential.value.split(".")[1];
769
+ if (encodedPayload === void 0 || encodedPayload.length === 0) {
770
+ throw new ContractParseError("management token carries no usable subject");
920
771
  }
921
- return path5.join(
922
- options.homeDirectory ?? os2.homedir(),
923
- ".config",
924
- "opencode",
925
- "route33"
926
- );
927
- };
928
- }
929
- });
930
-
931
- // src/cli/resolve-v1-secret-store-directory/index.ts
932
- var init_resolve_v1_secret_store_directory2 = __esm({
933
- "src/cli/resolve-v1-secret-store-directory/index.ts"() {
934
- "use strict";
935
- init_resolve_v1_secret_store_directory();
936
- }
937
- });
938
-
939
- // src/cli/index.ts
940
- var init_cli = __esm({
941
- "src/cli/index.ts"() {
942
- "use strict";
943
- init_read_env_base_url2();
944
- init_read_env_api_base2();
945
- init_read_env_auth_issuer2();
946
- init_read_env_autoconnect_disabled2();
947
- init_read_env_cache_dir2();
948
- init_read_env_catalog_ttl_ms2();
949
- init_read_env_client_id2();
950
- init_read_env_direct_api_key2();
951
- init_read_env_disable_id_shim2();
952
- init_read_env_discovery2();
953
- init_read_env_strict2();
954
- init_resolve_v1_secret_store_directory2();
955
- }
956
- });
957
-
958
- // src/auth/auth-error/auth-error.ts
959
- var AuthError;
960
- var init_auth_error = __esm({
961
- "src/auth/auth-error/auth-error.ts"() {
962
- "use strict";
963
- AuthError = class extends Error {
964
- constructor(code, options) {
965
- super(
966
- "Route 33 authorization failed",
967
- options?.cause === void 0 ? void 0 : { cause: options.cause }
772
+ let payload;
773
+ try {
774
+ payload = JSON.parse(
775
+ Buffer.from(encodedPayload, "base64url").toString("utf8")
968
776
  );
969
- this.code = code;
970
- this.name = "AuthError";
971
- this.statusCode = options?.statusCode;
777
+ } catch {
778
+ throw new ContractParseError("management token payload is not JSON");
779
+ }
780
+ if (!isRecord(payload)) {
781
+ throw new ContractParseError("management token payload is not an object");
782
+ }
783
+ const subject = payload["sub"];
784
+ if (typeof subject !== "string" || subject.length === 0) {
785
+ throw new ContractParseError("management token carries no usable subject");
972
786
  }
973
- code;
974
- statusCode;
787
+ return subject;
975
788
  };
976
789
  }
977
790
  });
978
791
 
979
- // src/auth/auth-error/index.ts
980
- var init_auth_error2 = __esm({
981
- "src/auth/auth-error/index.ts"() {
982
- "use strict";
983
- init_auth_error();
984
- }
985
- });
986
-
987
- // src/auth/build-authorize-url/build-authorize-url.ts
988
- var buildAuthorizeUrl;
989
- var init_build_authorize_url = __esm({
990
- "src/auth/build-authorize-url/build-authorize-url.ts"() {
792
+ // src/contract/adapters/parse-management-subject/index.ts
793
+ var init_parse_management_subject2 = __esm({
794
+ "src/contract/adapters/parse-management-subject/index.ts"() {
991
795
  "use strict";
992
- buildAuthorizeUrl = (issuerUrl, request) => {
993
- const url = new URL("/authorize", issuerUrl);
994
- url.search = new URLSearchParams({
995
- client_id: request.clientId,
996
- code_challenge: request.codeChallenge,
997
- code_challenge_method: "S256",
998
- redirect_uri: request.redirectUri,
999
- response_type: "code",
1000
- scope: request.scope,
1001
- state: request.state
1002
- }).toString();
1003
- return url;
1004
- };
796
+ init_parse_management_subject();
1005
797
  }
1006
798
  });
1007
799
 
1008
- // src/auth/build-authorize-url/index.ts
1009
- var init_build_authorize_url2 = __esm({
1010
- "src/auth/build-authorize-url/index.ts"() {
800
+ // src/contract/adapters/index.ts
801
+ var init_adapters = __esm({
802
+ "src/contract/adapters/index.ts"() {
1011
803
  "use strict";
1012
- init_build_authorize_url();
804
+ init_contract_parse_error2();
805
+ init_gateway_api_key2();
806
+ init_management_jwt2();
807
+ init_parse_gateway_key2();
808
+ init_parse_management_jwt2();
809
+ init_parse_management_subject2();
1013
810
  }
1014
811
  });
1015
812
 
@@ -2115,12 +1912,12 @@ var init_catalog_fetch_error2 = __esm({
2115
1912
  });
2116
1913
 
2117
1914
  // src/catalog/catalog-cache/cache-file-path/cache-file-path.ts
2118
- import * as path6 from "node:path";
1915
+ import * as path3 from "node:path";
2119
1916
  var cacheFilePath;
2120
1917
  var init_cache_file_path = __esm({
2121
1918
  "src/catalog/catalog-cache/cache-file-path/cache-file-path.ts"() {
2122
1919
  "use strict";
2123
- cacheFilePath = (keyHash, cacheDir) => path6.join(cacheDir, `catalog-${keyHash}.json`);
1920
+ cacheFilePath = (keyHash, cacheDir) => path3.join(cacheDir, `catalog-${keyHash}.json`);
2124
1921
  }
2125
1922
  });
2126
1923
 
@@ -2229,7 +2026,7 @@ var init_is_catalog_model_record2 = __esm({
2229
2026
  });
2230
2027
 
2231
2028
  // src/catalog/catalog-cache/read-disk/read-disk.ts
2232
- import * as fs6 from "node:fs";
2029
+ import * as fs from "node:fs";
2233
2030
  var readDisk;
2234
2031
  var init_read_disk = __esm({
2235
2032
  "src/catalog/catalog-cache/read-disk/read-disk.ts"() {
@@ -2241,7 +2038,7 @@ var init_read_disk = __esm({
2241
2038
  readDisk = (keyHash, cacheDir) => {
2242
2039
  try {
2243
2040
  const parsed = JSON.parse(
2244
- fs6.readFileSync(cacheFilePath(keyHash, cacheDir), "utf8")
2041
+ fs.readFileSync(cacheFilePath(keyHash, cacheDir), "utf8")
2245
2042
  );
2246
2043
  if (!isRecord(parsed) || parsed["version"] !== CATALOG_CACHE_VERSION || typeof parsed["fetchedAt"] !== "number" || !isCatalogModelRecord(parsed["models"])) {
2247
2044
  return void 0;
@@ -2326,7 +2123,7 @@ var init_read_stale_catalog2 = __esm({
2326
2123
  });
2327
2124
 
2328
2125
  // src/catalog/catalog-cache/write-catalog/write-catalog.ts
2329
- import * as fs7 from "node:fs";
2126
+ import * as fs2 from "node:fs";
2330
2127
  var writeCatalog;
2331
2128
  var init_write_catalog = __esm({
2332
2129
  "src/catalog/catalog-cache/write-catalog/write-catalog.ts"() {
@@ -2345,8 +2142,8 @@ var init_write_catalog = __esm({
2345
2142
  };
2346
2143
  catalogMemory.set(keyHash, record);
2347
2144
  try {
2348
- fs7.mkdirSync(options.cacheDir, { recursive: true });
2349
- fs7.writeFileSync(
2145
+ fs2.mkdirSync(options.cacheDir, { recursive: true });
2146
+ fs2.writeFileSync(
2350
2147
  cacheFilePath(keyHash, options.cacheDir),
2351
2148
  JSON.stringify({ version: CATALOG_CACHE_VERSION, ...record })
2352
2149
  );
@@ -3841,7 +3638,7 @@ var init_fetch_live2 = __esm({
3841
3638
  });
3842
3639
 
3843
3640
  // src/enrich/models-dev/read-models-dev-cache/read-models-dev-cache.ts
3844
- import * as fs8 from "node:fs";
3641
+ import * as fs3 from "node:fs";
3845
3642
  var readModelsDevCache;
3846
3643
  var init_read_models_dev_cache = __esm({
3847
3644
  "src/enrich/models-dev/read-models-dev-cache/read-models-dev-cache.ts"() {
@@ -3850,7 +3647,7 @@ var init_read_models_dev_cache = __esm({
3850
3647
  init_num2();
3851
3648
  readModelsDevCache = (cachePath) => {
3852
3649
  try {
3853
- const parsed = JSON.parse(fs8.readFileSync(cachePath, "utf8"));
3650
+ const parsed = JSON.parse(fs3.readFileSync(cachePath, "utf8"));
3854
3651
  if (!isRecord(parsed)) {
3855
3652
  return void 0;
3856
3653
  }
@@ -3876,8 +3673,8 @@ var init_read_models_dev_cache2 = __esm({
3876
3673
  });
3877
3674
 
3878
3675
  // src/enrich/models-dev/write-models-dev-cache/write-models-dev-cache.ts
3879
- import * as fs9 from "node:fs";
3880
- import * as path7 from "node:path";
3676
+ import * as fs4 from "node:fs";
3677
+ import * as path4 from "node:path";
3881
3678
  var writeModelsDevCache;
3882
3679
  var init_write_models_dev_cache = __esm({
3883
3680
  "src/enrich/models-dev/write-models-dev-cache/write-models-dev-cache.ts"() {
@@ -3885,8 +3682,8 @@ var init_write_models_dev_cache = __esm({
3885
3682
  init_shared();
3886
3683
  writeModelsDevCache = (cachePath, envelope) => {
3887
3684
  try {
3888
- fs9.mkdirSync(path7.dirname(cachePath), { recursive: true });
3889
- fs9.writeFileSync(cachePath, JSON.stringify(envelope), "utf8");
3685
+ fs4.mkdirSync(path4.dirname(cachePath), { recursive: true });
3686
+ fs4.writeFileSync(cachePath, JSON.stringify(envelope), "utf8");
3890
3687
  } catch (error) {
3891
3688
  logger.warn(
3892
3689
  "failed to write models.dev cache:",
@@ -3906,7 +3703,7 @@ var init_write_models_dev_cache2 = __esm({
3906
3703
  });
3907
3704
 
3908
3705
  // src/enrich/models-dev/load-models-dev/load-models-dev.ts
3909
- import * as path8 from "node:path";
3706
+ import * as path5 from "node:path";
3910
3707
  var CACHE_FILE, loadModelsDev;
3911
3708
  var init_load_models_dev = __esm({
3912
3709
  "src/enrich/models-dev/load-models-dev/load-models-dev.ts"() {
@@ -3922,7 +3719,7 @@ var init_load_models_dev = __esm({
3922
3719
  const cacheDir = options.cacheDir ?? resolveCacheDir({});
3923
3720
  const ttlMs = options.ttlMs ?? MODELS_DEV_TTL_MS;
3924
3721
  const now = options.now ?? Date.now;
3925
- const cachePath = path8.join(cacheDir, CACHE_FILE);
3722
+ const cachePath = path5.join(cacheDir, CACHE_FILE);
3926
3723
  const cached = readModelsDevCache(cachePath);
3927
3724
  if (cached !== void 0 && now() - cached.fetchedAt < ttlMs) {
3928
3725
  return createModelsDevSource("cache", cached.data);
@@ -4087,20 +3884,20 @@ var init_regenerate_models2 = __esm({
4087
3884
  });
4088
3885
 
4089
3886
  // src/config/remove-legacy-manifest/remove-legacy-manifest.ts
4090
- import * as fs10 from "node:fs";
4091
- import * as path9 from "node:path";
3887
+ import * as fs5 from "node:fs";
3888
+ import * as path6 from "node:path";
4092
3889
  var removeLegacyManifest;
4093
3890
  var init_remove_legacy_manifest = __esm({
4094
3891
  "src/config/remove-legacy-manifest/remove-legacy-manifest.ts"() {
4095
3892
  "use strict";
4096
3893
  init_shared();
4097
3894
  removeLegacyManifest = (root) => {
4098
- const file = path9.join(root, ".opencode", "route33-generated.json");
3895
+ const file = path6.join(root, ".opencode", "route33-generated.json");
4099
3896
  try {
4100
- if (!fs10.existsSync(file)) {
3897
+ if (!fs5.existsSync(file)) {
4101
3898
  return;
4102
3899
  }
4103
- fs10.rmSync(file);
3900
+ fs5.rmSync(file);
4104
3901
  logger.info(
4105
3902
  "route_33: removed obsolete route33-generated.json (regeneration is stateless since 0.4.4)"
4106
3903
  );
@@ -4745,9 +4542,9 @@ var init_default_gateway_key_ttl_ms2 = __esm({
4745
4542
  });
4746
4543
 
4747
4544
  // src/key-lease/file-secret-store/file-secret-store.ts
4748
- import { randomUUID as randomUUID2 } from "node:crypto";
4749
- import * as fs11 from "node:fs/promises";
4750
- import * as path10 from "node:path";
4545
+ import { randomUUID } from "node:crypto";
4546
+ import * as fs6 from "node:fs/promises";
4547
+ import * as path7 from "node:path";
4751
4548
  var FileSecretStore;
4752
4549
  var init_file_secret_store = __esm({
4753
4550
  "src/key-lease/file-secret-store/file-secret-store.ts"() {
@@ -4764,7 +4561,7 @@ var init_file_secret_store = __esm({
4764
4561
  throw new TypeError("File secret store scope is not portable");
4765
4562
  }
4766
4563
  this.#directory = options.directory;
4767
- this.#file = path10.join(options.directory, `lease-${options.scopeId}.json`);
4564
+ this.#file = path7.join(options.directory, `lease-${options.scopeId}.json`);
4768
4565
  }
4769
4566
  /** Reads and parses the scoped gateway credential.
4770
4567
  * @returns The persisted credential, when present.
@@ -4772,7 +4569,7 @@ var init_file_secret_store = __esm({
4772
4569
  async get() {
4773
4570
  let contents;
4774
4571
  try {
4775
- contents = await fs11.readFile(this.#file, "utf8");
4572
+ contents = await fs6.readFile(this.#file, "utf8");
4776
4573
  } catch (cause) {
4777
4574
  if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") {
4778
4575
  return void 0;
@@ -4788,22 +4585,22 @@ var init_file_secret_store = __esm({
4788
4585
  */
4789
4586
  async set(key) {
4790
4587
  if (key === void 0) {
4791
- await fs11.rm(this.#file, { force: true });
4588
+ await fs6.rm(this.#file, { force: true });
4792
4589
  return;
4793
4590
  }
4794
- await fs11.mkdir(this.#directory, { mode: 448, recursive: true });
4795
- await fs11.chmod(this.#directory, 448);
4796
- const temporary = path10.join(this.#directory, `.lease-${randomUUID2()}.tmp`);
4591
+ await fs6.mkdir(this.#directory, { mode: 448, recursive: true });
4592
+ await fs6.chmod(this.#directory, 448);
4593
+ const temporary = path7.join(this.#directory, `.lease-${randomUUID()}.tmp`);
4797
4594
  try {
4798
- await fs11.writeFile(temporary, `${JSON.stringify(key.value)}
4595
+ await fs6.writeFile(temporary, `${JSON.stringify(key.value)}
4799
4596
  `, {
4800
4597
  encoding: "utf8",
4801
4598
  flag: "wx",
4802
4599
  mode: 384
4803
4600
  });
4804
- await fs11.rename(temporary, this.#file);
4601
+ await fs6.rename(temporary, this.#file);
4805
4602
  } finally {
4806
- await fs11.rm(temporary, { force: true });
4603
+ await fs6.rm(temporary, { force: true });
4807
4604
  }
4808
4605
  }
4809
4606
  };
@@ -5402,70 +5199,273 @@ var init_lease_for_attribution = __esm({
5402
5199
  state: options.installation.state
5403
5200
  });
5404
5201
  }
5405
- if (options.rejection !== void 0) {
5406
- return rejectLease({
5407
- current,
5408
- rejection: options.rejection,
5409
- secretStore: options.installation.secretStore,
5410
- state: options.installation.state,
5411
- storedKey
5412
- });
5202
+ if (options.rejection !== void 0) {
5203
+ return rejectLease({
5204
+ current,
5205
+ rejection: options.rejection,
5206
+ secretStore: options.installation.secretStore,
5207
+ state: options.installation.state,
5208
+ storedKey
5209
+ });
5210
+ }
5211
+ const reusable = reusableLease({
5212
+ attribution: options.attribution,
5213
+ current,
5214
+ now,
5215
+ policy,
5216
+ state: options.installation.state,
5217
+ storedKey
5218
+ });
5219
+ if (reusable !== void 0) {
5220
+ return reusable;
5221
+ }
5222
+ try {
5223
+ const renewed = await renewKey({
5224
+ leaseState: options.installation.state,
5225
+ mint: {
5226
+ attribution: options.attribution,
5227
+ clock,
5228
+ identity: {
5229
+ credential: await resolveSeamValue(options.management.credential),
5230
+ subject: await resolveSeamValue(options.management.subject)
5231
+ },
5232
+ installation: {
5233
+ keyName: options.installation.keyName,
5234
+ ttlMs: policy.ttlMs
5235
+ },
5236
+ managementClient: options.management.client
5237
+ },
5238
+ secretStore: options.installation.secretStore
5239
+ });
5240
+ if (policy.orphanRetentionCycles !== void 0) {
5241
+ await controlOrphans({
5242
+ clock,
5243
+ currentKeyId: renewed.lease.keyId,
5244
+ keyName: options.installation.keyName,
5245
+ managementClient: options.management.client,
5246
+ managementCredential: await resolveSeamValue(
5247
+ options.management.credential
5248
+ ),
5249
+ retentionCycles: policy.orphanRetentionCycles,
5250
+ ttlMs: policy.ttlMs
5251
+ });
5252
+ }
5253
+ return renewed;
5254
+ } catch (cause) {
5255
+ return mapRenewalFailure({ cause, current, now });
5256
+ }
5257
+ };
5258
+ }
5259
+ });
5260
+
5261
+ // src/key-lease/lease-for-attribution/index.ts
5262
+ var init_lease_for_attribution2 = __esm({
5263
+ "src/key-lease/lease-for-attribution/index.ts"() {
5264
+ "use strict";
5265
+ init_lease_for_attribution();
5266
+ }
5267
+ });
5268
+
5269
+ // src/attribution/detect-worktree-root/detect-worktree-root.ts
5270
+ import * as fs7 from "node:fs";
5271
+ import * as path8 from "node:path";
5272
+ var detectWorktreeRoot;
5273
+ var init_detect_worktree_root = __esm({
5274
+ "src/attribution/detect-worktree-root/detect-worktree-root.ts"() {
5275
+ "use strict";
5276
+ detectWorktreeRoot = (startDirectory) => {
5277
+ let directory = fs7.realpathSync(startDirectory);
5278
+ for (; ; ) {
5279
+ const gitEntry = path8.join(directory, ".git");
5280
+ if (fs7.existsSync(gitEntry)) {
5281
+ const entry = fs7.statSync(gitEntry);
5282
+ if (entry.isDirectory() || entry.isFile()) {
5283
+ return directory;
5284
+ }
5285
+ }
5286
+ const parent = path8.dirname(directory);
5287
+ if (parent === directory) {
5288
+ return void 0;
5289
+ }
5290
+ directory = parent;
5291
+ }
5292
+ };
5293
+ }
5294
+ });
5295
+
5296
+ // src/attribution/detect-worktree-root/index.ts
5297
+ var init_detect_worktree_root2 = __esm({
5298
+ "src/attribution/detect-worktree-root/index.ts"() {
5299
+ "use strict";
5300
+ init_detect_worktree_root();
5301
+ }
5302
+ });
5303
+
5304
+ // src/attribution/resolve-attribution-file/resolve-attribution-file.ts
5305
+ import * as fs8 from "node:fs";
5306
+ import * as path9 from "node:path";
5307
+ var resolveAttributionFile;
5308
+ var init_resolve_attribution_file = __esm({
5309
+ "src/attribution/resolve-attribution-file/resolve-attribution-file.ts"() {
5310
+ "use strict";
5311
+ init_detect_worktree_root2();
5312
+ resolveAttributionFile = (options) => {
5313
+ const worktreeRoot = detectWorktreeRoot(options.directory);
5314
+ if (worktreeRoot !== void 0) {
5315
+ return path9.join(worktreeRoot, ".opencode", "route33.attribution.json");
5316
+ }
5317
+ const fallbackRoots = {
5318
+ "return-undefined": void 0,
5319
+ "use-directory": fs8.realpathSync(options.directory)
5320
+ };
5321
+ const fallbackRoot = fallbackRoots[options.outsideWorktree];
5322
+ return fallbackRoot === void 0 ? void 0 : path9.join(fallbackRoot, ".opencode", "route33.attribution.json");
5323
+ };
5324
+ }
5325
+ });
5326
+
5327
+ // src/attribution/resolve-attribution-file/index.ts
5328
+ var init_resolve_attribution_file2 = __esm({
5329
+ "src/attribution/resolve-attribution-file/index.ts"() {
5330
+ "use strict";
5331
+ init_resolve_attribution_file();
5332
+ }
5333
+ });
5334
+
5335
+ // src/attribution/clear-attribution/clear-attribution.ts
5336
+ import * as fs9 from "node:fs";
5337
+ var clearAttribution;
5338
+ var init_clear_attribution = __esm({
5339
+ "src/attribution/clear-attribution/clear-attribution.ts"() {
5340
+ "use strict";
5341
+ init_resolve_attribution_file2();
5342
+ clearAttribution = (options) => {
5343
+ const file = resolveAttributionFile(options);
5344
+ if (file === void 0) {
5345
+ return false;
5346
+ }
5347
+ fs9.rmSync(file, { force: true });
5348
+ return true;
5349
+ };
5350
+ }
5351
+ });
5352
+
5353
+ // src/attribution/clear-attribution/index.ts
5354
+ var init_clear_attribution2 = __esm({
5355
+ "src/attribution/clear-attribution/index.ts"() {
5356
+ "use strict";
5357
+ init_clear_attribution();
5358
+ }
5359
+ });
5360
+
5361
+ // src/attribution/parse-attribution/parse-attribution.ts
5362
+ var parseAttribution;
5363
+ var init_parse_attribution = __esm({
5364
+ "src/attribution/parse-attribution/parse-attribution.ts"() {
5365
+ "use strict";
5366
+ init_adapters();
5367
+ init_predicates();
5368
+ parseAttribution = (value) => {
5369
+ if (!isRecord(value)) {
5370
+ throw new ContractParseError("invalid attribution");
5371
+ }
5372
+ if (value["kind"] === "personal") {
5373
+ return { kind: "personal" };
5374
+ }
5375
+ if (value["kind"] === "project" && typeof value["projectId"] === "string") {
5376
+ return { kind: "project", projectId: value["projectId"] };
5377
+ }
5378
+ throw new ContractParseError("invalid attribution");
5379
+ };
5380
+ }
5381
+ });
5382
+
5383
+ // src/attribution/parse-attribution/index.ts
5384
+ var init_parse_attribution2 = __esm({
5385
+ "src/attribution/parse-attribution/index.ts"() {
5386
+ "use strict";
5387
+ init_parse_attribution();
5388
+ }
5389
+ });
5390
+
5391
+ // src/attribution/read-attribution/read-attribution.ts
5392
+ import * as fs10 from "node:fs";
5393
+ var readAttribution;
5394
+ var init_read_attribution = __esm({
5395
+ "src/attribution/read-attribution/read-attribution.ts"() {
5396
+ "use strict";
5397
+ init_parse_attribution2();
5398
+ init_resolve_attribution_file2();
5399
+ readAttribution = (options) => {
5400
+ const file = resolveAttributionFile(options);
5401
+ if (file === void 0) {
5402
+ return void 0;
5403
+ }
5404
+ try {
5405
+ const parsed = JSON.parse(fs10.readFileSync(file, "utf8"));
5406
+ return parseAttribution(parsed);
5407
+ } catch {
5408
+ return void 0;
5413
5409
  }
5414
- const reusable = reusableLease({
5415
- attribution: options.attribution,
5416
- current,
5417
- now,
5418
- policy,
5419
- state: options.installation.state,
5420
- storedKey
5421
- });
5422
- if (reusable !== void 0) {
5423
- return reusable;
5410
+ };
5411
+ }
5412
+ });
5413
+
5414
+ // src/attribution/read-attribution/index.ts
5415
+ var init_read_attribution2 = __esm({
5416
+ "src/attribution/read-attribution/index.ts"() {
5417
+ "use strict";
5418
+ init_read_attribution();
5419
+ }
5420
+ });
5421
+
5422
+ // src/attribution/write-attribution/write-attribution.ts
5423
+ import { randomUUID as randomUUID2 } from "node:crypto";
5424
+ import * as fs11 from "node:fs";
5425
+ import * as path10 from "node:path";
5426
+ var writeAttribution;
5427
+ var init_write_attribution = __esm({
5428
+ "src/attribution/write-attribution/write-attribution.ts"() {
5429
+ "use strict";
5430
+ init_resolve_attribution_file2();
5431
+ writeAttribution = (options, attribution) => {
5432
+ const file = resolveAttributionFile(options);
5433
+ if (file === void 0) {
5434
+ return false;
5424
5435
  }
5436
+ fs11.mkdirSync(path10.dirname(file), { recursive: true });
5437
+ const temporaryFile = `${file}.${String(process.pid)}.${randomUUID2()}.tmp`;
5425
5438
  try {
5426
- const renewed = await renewKey({
5427
- leaseState: options.installation.state,
5428
- mint: {
5429
- attribution: options.attribution,
5430
- clock,
5431
- identity: {
5432
- credential: await resolveSeamValue(options.management.credential),
5433
- subject: await resolveSeamValue(options.management.subject)
5434
- },
5435
- installation: {
5436
- keyName: options.installation.keyName,
5437
- ttlMs: policy.ttlMs
5438
- },
5439
- managementClient: options.management.client
5440
- },
5441
- secretStore: options.installation.secretStore
5442
- });
5443
- if (policy.orphanRetentionCycles !== void 0) {
5444
- await controlOrphans({
5445
- clock,
5446
- currentKeyId: renewed.lease.keyId,
5447
- keyName: options.installation.keyName,
5448
- managementClient: options.management.client,
5449
- managementCredential: await resolveSeamValue(
5450
- options.management.credential
5451
- ),
5452
- retentionCycles: policy.orphanRetentionCycles,
5453
- ttlMs: policy.ttlMs
5454
- });
5455
- }
5456
- return renewed;
5457
- } catch (cause) {
5458
- return mapRenewalFailure({ cause, current, now });
5439
+ fs11.writeFileSync(temporaryFile, `${JSON.stringify(attribution)}
5440
+ `, "utf8");
5441
+ fs11.renameSync(temporaryFile, file);
5442
+ } catch (error) {
5443
+ fs11.rmSync(temporaryFile, { force: true });
5444
+ throw error;
5459
5445
  }
5446
+ return true;
5460
5447
  };
5461
5448
  }
5462
5449
  });
5463
5450
 
5464
- // src/key-lease/lease-for-attribution/index.ts
5465
- var init_lease_for_attribution2 = __esm({
5466
- "src/key-lease/lease-for-attribution/index.ts"() {
5451
+ // src/attribution/write-attribution/index.ts
5452
+ var init_write_attribution2 = __esm({
5453
+ "src/attribution/write-attribution/index.ts"() {
5467
5454
  "use strict";
5468
- init_lease_for_attribution();
5455
+ init_write_attribution();
5456
+ }
5457
+ });
5458
+
5459
+ // src/attribution/index.ts
5460
+ var init_attribution = __esm({
5461
+ "src/attribution/index.ts"() {
5462
+ "use strict";
5463
+ init_clear_attribution2();
5464
+ init_detect_worktree_root2();
5465
+ init_parse_attribution2();
5466
+ init_read_attribution2();
5467
+ init_resolve_attribution_file2();
5468
+ init_write_attribution2();
5469
5469
  }
5470
5470
  });
5471
5471
 
@@ -6387,7 +6387,6 @@ var init_create_route33_plugin2 = __esm({
6387
6387
  });
6388
6388
 
6389
6389
  // src/tui-entry/v1-connect-wizard/v1-connect-wizard.ts
6390
- init_attribution();
6391
6390
  init_cli();
6392
6391
 
6393
6392
  // src/tui-entry/production-options/production-options.ts
@@ -6902,12 +6901,10 @@ init_create_route33_plugin2();
6902
6901
  // src/v2-entry/parse-r33-subcommand/parse-r33-subcommand.ts
6903
6902
  var SUBCOMMANDS = ["inspect", "rotate", "reset"];
6904
6903
  var parseR33Subcommand = (promptText) => {
6905
- const [invocation, argument] = promptText.trim().split(/\s+/u);
6906
- const name = invocation?.replace(/^\/+/u, "").split(":")[0] ?? "";
6907
- if (name !== "r33") {
6908
- return "help";
6909
- }
6910
- if (argument === void 0) {
6904
+ const [first = "", ...rest] = promptText.trim().split(/\s+/u).filter(Boolean);
6905
+ const name = first.replace(/^\/+/u, "").split(":")[0] ?? "";
6906
+ const argument = name === "r33" ? rest[0] : first;
6907
+ if (argument === void 0 || argument === "") {
6911
6908
  return "inspect";
6912
6909
  }
6913
6910
  return SUBCOMMANDS.includes(argument) ? argument : "help";
@@ -7098,19 +7095,82 @@ var r33Menu = async (api, composeOptions) => {
7098
7095
  await r33MenuActions({ api, composeOptions })(selection);
7099
7096
  };
7100
7097
 
7098
+ // src/tui-entry/v2-setup-directory/v2-setup-directory.ts
7099
+ init_attribution();
7100
+ init_cli();
7101
+ var v2SetupDirectory = (context) => {
7102
+ if (readEnvDirectApiKey() !== void 0) return void 0;
7103
+ if (readEnvAutoconnectDisabled()) return void 0;
7104
+ const location = context.location;
7105
+ if (location === void 0) return void 0;
7106
+ if (detectWorktreeRoot(location.directory) === void 0) {
7107
+ return void 0;
7108
+ }
7109
+ const attributed = readAttribution({
7110
+ directory: location.directory,
7111
+ outsideWorktree: "return-undefined"
7112
+ }) !== void 0;
7113
+ return attributed ? void 0 : location.directory;
7114
+ };
7115
+
7116
+ // src/tui-entry/v1-setup-lock/v1-setup-lock.ts
7117
+ var SETUP_MODE = "route33-setup";
7118
+ var RESUME_BIND = "enter";
7119
+ var v1SetupLock = (deps) => {
7120
+ const setupPending = () => v2SetupDirectory({ location: { directory: deps.directory() } }) !== void 0;
7121
+ const pop = setupPending() ? deps.mode?.push(SETUP_MODE) : void 0;
7122
+ if (pop !== void 0) {
7123
+ deps.keymap?.registerLayer({
7124
+ bindings: ["route33.setup"],
7125
+ commands: [
7126
+ {
7127
+ bind: RESUME_BIND,
7128
+ id: "route33.setup",
7129
+ run: () => {
7130
+ void settle();
7131
+ },
7132
+ suggested: true,
7133
+ title: "Route 33: pick the budget for this folder"
7134
+ }
7135
+ ],
7136
+ mode: SETUP_MODE,
7137
+ priority: 10
7138
+ });
7139
+ }
7140
+ let running = false;
7141
+ const settle = async () => {
7142
+ if (running) return;
7143
+ running = true;
7144
+ try {
7145
+ if (setupPending()) {
7146
+ await deps.run();
7147
+ }
7148
+ } finally {
7149
+ running = false;
7150
+ }
7151
+ if (setupPending()) return;
7152
+ pop?.();
7153
+ };
7154
+ return { start: settle };
7155
+ };
7156
+
7101
7157
  // src/tui-entry/v1-connect-wizard/v1-connect-wizard.ts
7102
7158
  var createV1ConnectWizard = (composeOptions = productionOptions) => (api) => {
7103
7159
  if (readEnvDirectApiKey() !== void 0 || readEnvAutoconnectDisabled()) {
7104
7160
  return Promise.resolve();
7105
7161
  }
7106
- const directory = api.state.path.directory;
7107
- const unconnected = readAttribution({
7108
- directory,
7109
- outsideWorktree: "return-undefined"
7110
- }) === void 0;
7111
- if (unconnected) {
7112
- void runConnect(api, composeOptions);
7113
- }
7162
+ const surfaces = api;
7163
+ const lock = v1SetupLock({
7164
+ directory: () => api.state.path.directory,
7165
+ ...surfaces.keymap === void 0 ? {} : {
7166
+ keymap: {
7167
+ registerLayer: (layer) => surfaces.keymap?.registerLayer(layer)
7168
+ }
7169
+ },
7170
+ ...surfaces.mode === void 0 ? {} : { mode: surfaces.mode },
7171
+ run: () => runConnect(api, composeOptions)
7172
+ });
7173
+ void lock.start();
7114
7174
  const legacyCommands = api.command;
7115
7175
  legacyCommands?.register(() => [
7116
7176
  {
@@ -7167,70 +7227,405 @@ var showR33Menu = async (context) => {
7167
7227
 
7168
7228
  // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
7169
7229
  init_attribution();
7170
- init_cli();
7171
7230
 
7172
- // src/tui-entry/is-method-not-registered/is-method-not-registered.ts
7173
- var isMethodNotRegistered = (error) => error instanceof Error && error.message.includes("OAuth method not found");
7231
+ // src/tui-entry/v2-attribution-field/v2-attribution-field.ts
7232
+ var v2AttributionField = (methods) => {
7233
+ const browserMethods = methods?.filter(
7234
+ (entry) => entry.type === "oauth" && entry.id === "browser"
7235
+ );
7236
+ const fields = browserMethods?.flatMap((entry) => entry.form ?? []);
7237
+ const field = fields?.find((entry) => entry.key === "attribution");
7238
+ if (field?.options === void 0 || field.options.length === 0) {
7239
+ return void 0;
7240
+ }
7241
+ return field;
7242
+ };
7243
+
7244
+ // src/tui-entry/v2-integration-surface/v2-integration-surface.ts
7245
+ var v2IntegrationSurface = (context) => context.client?.integration ?? context.client?.api?.integration;
7246
+
7247
+ // src/tui-entry/v2-attribution-form/v2-attribution-form.ts
7248
+ var v2AttributionForm = async (context) => {
7249
+ const get = v2IntegrationSurface(context)?.get;
7250
+ if (get === void 0) return void 0;
7251
+ const integration = await get({
7252
+ integrationID: "route33",
7253
+ ...context.location === void 0 ? {} : { location: { directory: context.location.directory } }
7254
+ }).catch(() => void 0);
7255
+ return v2AttributionField(integration?.data.methods);
7256
+ };
7257
+
7258
+ // src/tui-entry/v2-connect-copy/v2-connect-copy.ts
7259
+ var V2_CONNECT_COPY = {
7260
+ dismissed: "Route 33 is not set up for this folder yet. Press Enter to pick the budget, or run /connect and choose Route 33.",
7261
+ expired: "The Route 33 sign-in link expired. Press Enter to retry, or run /connect and choose Route 33.",
7262
+ manualFallback: "Route 33 is not connected in this folder. Run /connect, choose Route 33, and follow the steps.",
7263
+ manualPath: "Press Enter to retry, or run /connect, choose Route 33, and follow the steps.",
7264
+ pickerTitle: "Which budget covers Route 33 usage in this folder?",
7265
+ setupIncomplete: "Route 33 setup did not complete. Press Enter to retry, or run /connect and choose Route 33.",
7266
+ signInFailed: "Route 33 sign-in did not complete. Press Enter to retry, or run /connect and choose Route 33.",
7267
+ signInTitle: "Route 33 \u2014 sign in",
7268
+ statusUnavailable: "Route 33 sign-in did not settle. Press Enter to retry, or run /connect and choose Route 33.",
7269
+ stale: "That Route 33 option is no longer available. Press Enter to retry, or run /connect and choose Route 33.",
7270
+ success: "Route 33 connected \u2713 \u2014 pick a route_33 model and start.",
7271
+ timedOut: "Route 33 sign-in timed out. Press Enter to retry, or run /connect and choose Route 33."
7272
+ };
7273
+
7274
+ // src/tui-entry/v2-outcome-copy/v2-outcome-copy.ts
7275
+ var v2OutcomeCopy = (outcome, failedFallback) => {
7276
+ if (outcome.kind === "failed") {
7277
+ return {
7278
+ message: `${outcome.message ?? failedFallback} ${V2_CONNECT_COPY.manualPath}`,
7279
+ variant: "error"
7280
+ };
7281
+ }
7282
+ const byKind = {
7283
+ complete: V2_CONNECT_COPY.manualFallback,
7284
+ expired: V2_CONNECT_COPY.expired,
7285
+ failed: failedFallback,
7286
+ timeout: V2_CONNECT_COPY.timedOut,
7287
+ unavailable: V2_CONNECT_COPY.statusUnavailable
7288
+ };
7289
+ return { message: byKind[outcome.kind], variant: "error" };
7290
+ };
7291
+
7292
+ // src/tui-entry/v2-budget-picker/v2-budget-picker.ts
7293
+ var v2BudgetPicker = async (deps) => {
7294
+ if (!deps.unattributed()) {
7295
+ deps.toast({ message: V2_CONNECT_COPY.success, variant: "success" });
7296
+ return;
7297
+ }
7298
+ const options = deps.form.options ?? [];
7299
+ const selection = await deps.dialog.select({
7300
+ options: options.map((option) => ({
7301
+ description: option.description,
7302
+ title: option.label,
7303
+ value: option.value
7304
+ })),
7305
+ title: deps.form.title ?? V2_CONNECT_COPY.pickerTitle
7306
+ });
7307
+ if (selection === void 0) {
7308
+ deps.toast({ message: V2_CONNECT_COPY.dismissed });
7309
+ return;
7310
+ }
7311
+ if (!options.some((option) => option.value === selection)) {
7312
+ deps.toast({ message: V2_CONNECT_COPY.stale, variant: "error" });
7313
+ return;
7314
+ }
7315
+ if (!deps.unattributed()) {
7316
+ deps.toast({ message: V2_CONNECT_COPY.success, variant: "success" });
7317
+ return;
7318
+ }
7319
+ let second;
7320
+ try {
7321
+ second = await deps.connect({
7322
+ answer: { [deps.form.key]: selection },
7323
+ integrationID: "route33",
7324
+ location: deps.locationInput,
7325
+ methodID: "browser"
7326
+ });
7327
+ } catch (error) {
7328
+ deps.toast({
7329
+ message: `${error instanceof Error ? error.message : String(error)} ${V2_CONNECT_COPY.manualPath}`,
7330
+ variant: "error"
7331
+ });
7332
+ return;
7333
+ }
7334
+ const settled = await deps.pollTerminal(second.data.attemptID);
7335
+ if (settled.kind === "complete") {
7336
+ deps.toast({ message: V2_CONNECT_COPY.success, variant: "success" });
7337
+ return;
7338
+ }
7339
+ const copy = v2OutcomeCopy(settled, V2_CONNECT_COPY.setupIncomplete);
7340
+ deps.toast(copy);
7341
+ };
7174
7342
 
7175
7343
  // src/tui-entry/v2-connect-surface/v2-connect-surface.ts
7176
- var v2ConnectSurface = (context) => {
7177
- const oauth = context.client?.integration?.oauth ?? context.client?.api?.integration?.oauth;
7178
- return oauth?.connect;
7344
+ var v2ConnectSurface = (context) => v2IntegrationSurface(context)?.oauth?.connect;
7345
+
7346
+ // src/tui-entry/v2-form-reader/v2-form-reader.ts
7347
+ init_abortable_sleep2();
7348
+ var createV2FormReader = ({ attempts = 5, context, retryDelayMs = 500 }) => async () => {
7349
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
7350
+ const form = await v2AttributionForm(context);
7351
+ if (form !== void 0) return form;
7352
+ if (attempt < attempts) {
7353
+ await abortableSleep(retryDelayMs);
7354
+ }
7355
+ }
7356
+ return void 0;
7179
7357
  };
7180
7358
 
7181
- // src/tui-entry/v2-connect-runner/v2-connect-runner.ts
7182
- var createV2ConnectRunner = ({
7183
- context,
7359
+ // src/tui-entry/v2-poll-terminal/v2-poll-terminal.ts
7360
+ init_abortable_sleep2();
7361
+ var createV2PollTerminal = ({
7362
+ locationInput,
7363
+ maxPolls = 600,
7364
+ pollDelayMs = 1e3,
7365
+ status,
7366
+ statusErrorLimit = 5
7367
+ }) => async (attemptID) => {
7368
+ let errors = 0;
7369
+ for (let poll = 0; poll < maxPolls; poll += 1) {
7370
+ await abortableSleep(pollDelayMs);
7371
+ try {
7372
+ const result = await status({
7373
+ attemptID,
7374
+ integrationID: "route33",
7375
+ location: locationInput
7376
+ });
7377
+ errors = 0;
7378
+ const state = result.data.status;
7379
+ if (state === "pending") continue;
7380
+ if (state === "failed") {
7381
+ return { kind: "failed", message: result.data.message };
7382
+ }
7383
+ return { kind: state };
7384
+ } catch {
7385
+ errors += 1;
7386
+ if (errors >= statusErrorLimit) return { kind: "unavailable" };
7387
+ }
7388
+ }
7389
+ return { kind: "timeout" };
7390
+ };
7391
+
7392
+ // src/tui-entry/v2-connect-retry/v2-connect-retry.ts
7393
+ init_abortable_sleep2();
7394
+
7395
+ // src/tui-entry/is-method-not-registered/is-method-not-registered.ts
7396
+ var isMethodNotRegistered = (error) => error instanceof Error && error.message.includes("OAuth method not found");
7397
+
7398
+ // src/tui-entry/v2-connect-retry/v2-connect-retry.ts
7399
+ var v2ConnectRetry = async ({
7400
+ connect,
7401
+ input,
7184
7402
  maxAttempts = 20,
7185
- retryDelayMs = 500,
7403
+ retryDelayMs = 500
7404
+ }) => {
7405
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
7406
+ try {
7407
+ return await connect(input);
7408
+ } catch (error) {
7409
+ if (!isMethodNotRegistered(error)) {
7410
+ throw error;
7411
+ }
7412
+ if (attempt < maxAttempts) {
7413
+ await abortableSleep(retryDelayMs);
7414
+ }
7415
+ }
7416
+ }
7417
+ return void 0;
7418
+ };
7419
+
7420
+ // src/tui-entry/v2-sign-in-wait/v2-sign-in-wait.ts
7421
+ var v2SignInWait = async (deps) => {
7422
+ const state = { dismissed: false };
7423
+ void deps.alert().then(() => {
7424
+ state.dismissed = true;
7425
+ }).catch(() => {
7426
+ state.dismissed = true;
7427
+ });
7428
+ const outcome = await deps.pollTerminal(deps.attemptID);
7429
+ return { dismissed: state.dismissed, outcome };
7430
+ };
7431
+
7432
+ // src/tui-entry/v2-sign-in-pass/v2-sign-in-pass.ts
7433
+ var v2SignInPass = async ({
7434
+ connect,
7435
+ dialog,
7436
+ formReader,
7437
+ locationInput,
7438
+ maxAttempts,
7439
+ pollTerminal,
7440
+ retryDelayMs,
7441
+ toast,
7186
7442
  unattributed
7187
7443
  }) => {
7188
- const connect = v2ConnectSurface(context);
7189
- const sleep = (ms) => new Promise((resolve2) => {
7190
- setTimeout(resolve2, ms);
7444
+ let attempt;
7445
+ try {
7446
+ attempt = await v2ConnectRetry({
7447
+ connect,
7448
+ input: {
7449
+ integrationID: "route33",
7450
+ location: locationInput,
7451
+ methodID: "browser"
7452
+ },
7453
+ maxAttempts,
7454
+ retryDelayMs
7455
+ });
7456
+ } catch (error) {
7457
+ toast({
7458
+ message: `${error instanceof Error ? error.message : String(error)} ${V2_CONNECT_COPY.manualPath}`,
7459
+ variant: "error"
7460
+ });
7461
+ return { aborted: true };
7462
+ }
7463
+ if (attempt === void 0) {
7464
+ toast({ message: V2_CONNECT_COPY.manualFallback, variant: "error" });
7465
+ return { aborted: true };
7466
+ }
7467
+ const waited = await v2SignInWait({
7468
+ alert: () => dialog.alert({
7469
+ message: `${attempt.data.instructions}
7470
+
7471
+ ${attempt.data.url}`,
7472
+ title: V2_CONNECT_COPY.signInTitle
7473
+ }),
7474
+ attemptID: attempt.data.attemptID,
7475
+ pollTerminal
7191
7476
  });
7192
- return async (message) => {
7193
- if (connect === void 0) return;
7194
- if (!unattributed()) return;
7195
- context.ui.toast.show({ message, variant: "info" });
7196
- for (let attempt = 1; ; attempt += 1) {
7197
- if (!unattributed()) return;
7198
- try {
7199
- await connect({
7200
- integrationID: "route33",
7201
- methodID: "browser"
7202
- });
7203
- return;
7204
- } catch (error) {
7205
- if (attempt >= maxAttempts || !isMethodNotRegistered(error)) return;
7206
- await sleep(retryDelayMs);
7207
- }
7477
+ if (waited.dismissed) {
7478
+ if (waited.outcome.kind === "complete") {
7479
+ return { connected: true };
7208
7480
  }
7481
+ toast({ message: V2_CONNECT_COPY.dismissed });
7482
+ return { aborted: true };
7483
+ }
7484
+ dialog.clear();
7485
+ const outcome = waited.outcome;
7486
+ if (outcome.kind === "complete") {
7487
+ return { connected: true };
7488
+ }
7489
+ if (outcome.kind === "failed") {
7490
+ if (!unattributed()) {
7491
+ return { connected: true };
7492
+ }
7493
+ const form = await formReader();
7494
+ if (form === void 0) {
7495
+ toast(v2OutcomeCopy(outcome, V2_CONNECT_COPY.signInFailed));
7496
+ return { aborted: true };
7497
+ }
7498
+ return { form };
7499
+ }
7500
+ toast(v2OutcomeCopy(outcome, V2_CONNECT_COPY.signInFailed));
7501
+ return { aborted: true };
7502
+ };
7503
+
7504
+ // src/tui-entry/v2-status-surface/v2-status-surface.ts
7505
+ var v2StatusSurface = (context) => v2IntegrationSurface(context)?.oauth?.status;
7506
+
7507
+ // src/tui-entry/v2-connect-runner/v2-connect-runner.ts
7508
+ var v2GuidedConnect = async (deps) => {
7509
+ const { context, unattributed } = deps;
7510
+ const connect = v2ConnectSurface(context);
7511
+ const status = v2StatusSurface(context);
7512
+ const dialog = context.ui.dialog;
7513
+ const toast = (input) => {
7514
+ context.ui.toast.show(input);
7209
7515
  };
7516
+ const location = context.location;
7517
+ if (connect === void 0 || location === void 0) return;
7518
+ if (!unattributed()) return;
7519
+ if (status === void 0 || dialog === void 0) {
7520
+ toast({ message: V2_CONNECT_COPY.manualFallback });
7521
+ return;
7522
+ }
7523
+ const locationInput = { directory: location.directory };
7524
+ const pollTerminal = createV2PollTerminal({
7525
+ locationInput,
7526
+ maxPolls: deps.maxPolls,
7527
+ pollDelayMs: deps.pollDelayMs,
7528
+ status,
7529
+ statusErrorLimit: deps.statusErrorLimit
7530
+ });
7531
+ const earlyForm = await v2AttributionForm(context);
7532
+ if (earlyForm !== void 0) {
7533
+ await v2BudgetPicker({
7534
+ connect,
7535
+ dialog,
7536
+ form: earlyForm,
7537
+ locationInput,
7538
+ pollTerminal,
7539
+ toast,
7540
+ unattributed
7541
+ });
7542
+ return;
7543
+ }
7544
+ const result = await v2SignInPass({
7545
+ connect,
7546
+ dialog,
7547
+ formReader: createV2FormReader({
7548
+ attempts: deps.formReadAttempts,
7549
+ context,
7550
+ retryDelayMs: deps.retryDelayMs
7551
+ }),
7552
+ locationInput,
7553
+ maxAttempts: deps.maxAttempts,
7554
+ pollTerminal,
7555
+ retryDelayMs: deps.retryDelayMs,
7556
+ toast,
7557
+ unattributed
7558
+ });
7559
+ if ("aborted" in result) return;
7560
+ if ("connected" in result) {
7561
+ toast({ message: V2_CONNECT_COPY.success, variant: "success" });
7562
+ return;
7563
+ }
7564
+ await v2BudgetPicker({
7565
+ connect,
7566
+ dialog,
7567
+ form: result.form,
7568
+ locationInput,
7569
+ pollTerminal,
7570
+ toast,
7571
+ unattributed
7572
+ });
7210
7573
  };
7211
7574
 
7212
7575
  // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
7213
7576
  var v2Autoconnect = async (context) => {
7214
- if (readEnvDirectApiKey() !== void 0) return;
7215
- if (readEnvAutoconnectDisabled()) return;
7216
- const location = context.location;
7217
- if (location === void 0) return;
7577
+ const directory = v2SetupDirectory(context);
7578
+ if (directory === void 0) return;
7218
7579
  const unattributed = () => readAttribution({
7219
- directory: location.directory,
7580
+ directory,
7220
7581
  outsideWorktree: "return-undefined"
7221
7582
  }) === void 0;
7222
- const connectPass = createV2ConnectRunner({ context, unattributed });
7223
- await connectPass(
7224
- "Route 33 is not connected \u2014 signing in now, then pick the budget for this folder."
7225
- );
7226
- await connectPass("Signed in to Route 33 \u2014 opening the budget picker.");
7583
+ await v2GuidedConnect({ context, unattributed });
7584
+ };
7585
+
7586
+ // src/tui-entry/v2-setup-lock/v2-setup-lock.ts
7587
+ var SETUP_MODE2 = "route33-setup";
7588
+ var RESUME_BIND2 = "enter";
7589
+ var v2SetupLock = (context) => {
7590
+ const required = v2SetupDirectory(context) !== void 0;
7591
+ const release = required ? context.keymap?.mode.push(SETUP_MODE2) : void 0;
7592
+ if (required) {
7593
+ context.keymap?.layer(() => ({
7594
+ bindings: ["route33.setup"],
7595
+ commands: [
7596
+ {
7597
+ bind: RESUME_BIND2,
7598
+ id: "route33.setup",
7599
+ run: () => {
7600
+ void settle();
7601
+ },
7602
+ suggested: true,
7603
+ title: "Route 33: pick the budget for this folder"
7604
+ }
7605
+ ],
7606
+ mode: SETUP_MODE2,
7607
+ priority: 10
7608
+ }));
7609
+ }
7610
+ let running = false;
7611
+ const settle = async () => {
7612
+ if (running) return;
7613
+ running = true;
7614
+ try {
7615
+ await v2Autoconnect(context);
7616
+ } finally {
7617
+ running = false;
7618
+ }
7619
+ if (v2SetupDirectory(context) !== void 0) return;
7620
+ release?.();
7621
+ };
7622
+ return { start: settle };
7227
7623
  };
7228
7624
 
7229
7625
  // src/tui-entry/v2-tui/v2-tui.ts
7230
7626
  var createV2Tui = () => ({
7231
7627
  id: "route33",
7232
- setup: async (context) => {
7233
- await v2Autoconnect(context);
7628
+ setup: (context) => {
7234
7629
  context.keymap?.layer(() => ({
7235
7630
  mode: "global",
7236
7631
  priority: 10,
@@ -7248,6 +7643,7 @@ var createV2Tui = () => ({
7248
7643
  ],
7249
7644
  bindings: ["route33.menu"]
7250
7645
  }));
7646
+ void v2SetupLock(context).start().catch(() => void 0);
7251
7647
  }
7252
7648
  });
7253
7649