@route_33/opencode 0.4.7-rc.4 → 0.4.7-rc.6

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.
package/README.md CHANGED
@@ -5,29 +5,49 @@ usage, and use the route_33 models — no API keys to paste, ever.
5
5
 
6
6
  ## Install
7
7
 
8
+ **OpenCode v2 (recommended):**
9
+
8
10
  ```sh
9
11
  opencode plugin add @route_33/opencode
10
12
  ```
11
13
 
12
- Restart OpenCode afterwards — plugins load at startup.
14
+ Installs globally — one `plugins` entry in the config's `opencode.json`
15
+ loads every part (the server and TUI parts are auto-discovered from the
16
+ package exports; no `tui.json` exists on v2).
17
+
18
+ **OpenCode v1:**
13
19
 
14
- Prefer config? Add the package to `opencode.jsonc` instead:
20
+ ```sh
21
+ opencode plugin @route_33/opencode # project scope (default)
22
+ opencode plugin @route_33/opencode --global # global scope
23
+ ```
24
+
25
+ Installs at the nearest definition and registers the plugin twice: the
26
+ server part in `opencode.json` and the TUI part in `tui.json` — both files
27
+ are load-bearing on v1, which is why the installer writes both.
28
+
29
+ Either way, restart OpenCode afterwards — plugins load at startup. Prefer
30
+ config? Declare the plugin directly in `opencode.json(c)`:
15
31
 
16
32
  ```jsonc
17
- { "plugins": ["@route_33/opencode"] }
33
+ { "plugin": ["@route_33/opencode"] }
18
34
  ```
19
35
 
20
36
  ## First run
21
37
 
22
- 1. Pick any route_33 model (or run `/connect` and choose **Route 33**).
23
- 2. Open the sign-in link — your browser finishes at a Route 33 confirmation
24
- page.
25
- 3. Connect again and assign **which budget covers usage in this folder**: one of your
26
- Route 33 projects, or your personal key.
27
- 4. The route_33 models appear. Done.
38
+ With `ROUTE33_API_KEY` unset and `ROUTE33_AUTOCONNECT` not `0`, the wizard
39
+ auto-starts at launch and completes **before the first prompt** on OpenCode
40
+ v2 — the setup awaits the whole chain:
41
+
42
+ 1. The browser sign-in opens; finish it there.
43
+ 2. The budget picker follows in OpenCode — one of your Route 33 projects,
44
+ or your personal key.
45
+ 3. The route_33 models appear. Pick one and prompt away.
28
46
 
29
- To change the budget later, connect again and pick another option. `/r33` shows
30
- the current state at any time.
47
+ On OpenCode v1 the wizard also auto-starts, but the 1.x TUI API has no
48
+ pre-prompt hook, so it runs in parallel with the prompt — the models appear
49
+ after the wizard finishes and OpenCode restarts. Use `/r33` any time to
50
+ re-run connect, change the budget, or inspect the session.
31
51
 
32
52
  ## Commands
33
53
 
package/dist/index.js CHANGED
@@ -3245,6 +3245,26 @@ var Route33Runtime = class {
3245
3245
  }
3246
3246
  };
3247
3247
 
3248
+ // src/v1-entry/unattributed-prompt-gate/unattributed-prompt-gate.ts
3249
+ var createUnattributedPromptGate = ({ directory, outsideWorktree }) => (input) => {
3250
+ if (input.model?.providerID !== "route_33") return Promise.resolve();
3251
+ const attribution = readAttribution({ directory, outsideWorktree });
3252
+ if (attribution !== void 0) return Promise.resolve();
3253
+ return Promise.reject(
3254
+ new Error(
3255
+ "Route 33 needs a budget for this folder first \u2014 run /r33 in OpenCode, choose Route 33, and assign a budget."
3256
+ )
3257
+ );
3258
+ };
3259
+
3260
+ // src/v1-entry/workspace-key-headers/workspace-key-headers.ts
3261
+ var createWorkspaceKeyHeaders = ({ resolveKey, session }) => async (input, output) => {
3262
+ const workspace = await session.get({ sessionID: input.sessionID });
3263
+ const key = await resolveKey(workspace.location.directory);
3264
+ if (key === void 0) return;
3265
+ output.headers["Authorization"] = `Bearer ${key.value}`;
3266
+ };
3267
+
3248
3268
  // src/create-route33-plugin/create-route33-plugin.ts
3249
3269
  var createRoute33Plugin = (options = {}) => {
3250
3270
  const baseURL = readEnvBaseUrl();
@@ -3285,6 +3305,8 @@ var createRoute33Plugin = (options = {}) => {
3285
3305
  }
3286
3306
  }
3287
3307
  let credentialProvider;
3308
+ let workspaceHeaders;
3309
+ let promptGate;
3288
3310
  if (directKey !== void 0) {
3289
3311
  credentialProvider = () => Promise.resolve(parseGatewayKey(directKey));
3290
3312
  } else if (runtime === void 0) {
@@ -3293,13 +3315,28 @@ var createRoute33Plugin = (options = {}) => {
3293
3315
  );
3294
3316
  } else {
3295
3317
  credentialProvider = () => runtime.resolveCredential();
3318
+ workspaceHeaders = createWorkspaceKeyHeaders({
3319
+ resolveKey: (directory) => runtime.resolveWorkspaceCredential(directory),
3320
+ session: {
3321
+ get: async ({ sessionID }) => {
3322
+ const session = await options.readSession?.(sessionID);
3323
+ return session ?? { location: { directory: input.worktree } };
3324
+ }
3325
+ }
3326
+ });
3327
+ promptGate = createUnattributedPromptGate({
3328
+ directory: input.worktree,
3329
+ outsideWorktree: "return-undefined"
3330
+ });
3296
3331
  }
3297
3332
  return Promise.resolve({
3298
3333
  config: createConfigHook({
3299
3334
  ...resolvedConfig,
3300
3335
  credentialProvider,
3301
3336
  cwd: input.worktree
3302
- })
3337
+ }),
3338
+ ...workspaceHeaders === void 0 ? {} : { "chat.headers": workspaceHeaders },
3339
+ ...promptGate === void 0 ? {} : { "chat.message": promptGate }
3303
3340
  });
3304
3341
  };
3305
3342
  };
@@ -6226,6 +6226,64 @@ var init_route33_runtime2 = __esm({
6226
6226
  }
6227
6227
  });
6228
6228
 
6229
+ // src/v1-entry/unattributed-prompt-gate/unattributed-prompt-gate.ts
6230
+ var createUnattributedPromptGate;
6231
+ var init_unattributed_prompt_gate = __esm({
6232
+ "src/v1-entry/unattributed-prompt-gate/unattributed-prompt-gate.ts"() {
6233
+ "use strict";
6234
+ init_attribution();
6235
+ createUnattributedPromptGate = ({ directory, outsideWorktree }) => (input) => {
6236
+ if (input.model?.providerID !== "route_33") return Promise.resolve();
6237
+ const attribution = readAttribution({ directory, outsideWorktree });
6238
+ if (attribution !== void 0) return Promise.resolve();
6239
+ return Promise.reject(
6240
+ new Error(
6241
+ "Route 33 needs a budget for this folder first \u2014 run /r33 in OpenCode, choose Route 33, and assign a budget."
6242
+ )
6243
+ );
6244
+ };
6245
+ }
6246
+ });
6247
+
6248
+ // src/v1-entry/unattributed-prompt-gate/index.ts
6249
+ var init_unattributed_prompt_gate2 = __esm({
6250
+ "src/v1-entry/unattributed-prompt-gate/index.ts"() {
6251
+ "use strict";
6252
+ init_unattributed_prompt_gate();
6253
+ }
6254
+ });
6255
+
6256
+ // src/v1-entry/workspace-key-headers/workspace-key-headers.ts
6257
+ var createWorkspaceKeyHeaders;
6258
+ var init_workspace_key_headers = __esm({
6259
+ "src/v1-entry/workspace-key-headers/workspace-key-headers.ts"() {
6260
+ "use strict";
6261
+ createWorkspaceKeyHeaders = ({ resolveKey, session }) => async (input, output) => {
6262
+ const workspace = await session.get({ sessionID: input.sessionID });
6263
+ const key = await resolveKey(workspace.location.directory);
6264
+ if (key === void 0) return;
6265
+ output.headers["Authorization"] = `Bearer ${key.value}`;
6266
+ };
6267
+ }
6268
+ });
6269
+
6270
+ // src/v1-entry/workspace-key-headers/index.ts
6271
+ var init_workspace_key_headers2 = __esm({
6272
+ "src/v1-entry/workspace-key-headers/index.ts"() {
6273
+ "use strict";
6274
+ init_workspace_key_headers();
6275
+ }
6276
+ });
6277
+
6278
+ // src/v1-entry/index.ts
6279
+ var init_v1_entry = __esm({
6280
+ "src/v1-entry/index.ts"() {
6281
+ "use strict";
6282
+ init_unattributed_prompt_gate2();
6283
+ init_workspace_key_headers2();
6284
+ }
6285
+ });
6286
+
6229
6287
  // src/create-route33-plugin/create-route33-plugin.ts
6230
6288
  var createRoute33Plugin;
6231
6289
  var init_create_route33_plugin = __esm({
@@ -6238,6 +6296,7 @@ var init_create_route33_plugin = __esm({
6238
6296
  init_requested_client_id2();
6239
6297
  init_route33_runtime2();
6240
6298
  init_ux();
6299
+ init_v1_entry();
6241
6300
  createRoute33Plugin = (options = {}) => {
6242
6301
  const baseURL = readEnvBaseUrl();
6243
6302
  const clientId = options.clientId ?? readEnvClientId() ?? DEFAULT_ROUTE33_CLIENT_ID;
@@ -6277,6 +6336,8 @@ var init_create_route33_plugin = __esm({
6277
6336
  }
6278
6337
  }
6279
6338
  let credentialProvider;
6339
+ let workspaceHeaders;
6340
+ let promptGate;
6280
6341
  if (directKey !== void 0) {
6281
6342
  credentialProvider = () => Promise.resolve(parseGatewayKey(directKey));
6282
6343
  } else if (runtime === void 0) {
@@ -6285,13 +6346,28 @@ var init_create_route33_plugin = __esm({
6285
6346
  );
6286
6347
  } else {
6287
6348
  credentialProvider = () => runtime.resolveCredential();
6349
+ workspaceHeaders = createWorkspaceKeyHeaders({
6350
+ resolveKey: (directory) => runtime.resolveWorkspaceCredential(directory),
6351
+ session: {
6352
+ get: async ({ sessionID }) => {
6353
+ const session = await options.readSession?.(sessionID);
6354
+ return session ?? { location: { directory: input.worktree } };
6355
+ }
6356
+ }
6357
+ });
6358
+ promptGate = createUnattributedPromptGate({
6359
+ directory: input.worktree,
6360
+ outsideWorktree: "return-undefined"
6361
+ });
6288
6362
  }
6289
6363
  return Promise.resolve({
6290
6364
  config: createConfigHook({
6291
6365
  ...resolvedConfig,
6292
6366
  credentialProvider,
6293
6367
  cwd: input.worktree
6294
- })
6368
+ }),
6369
+ ...workspaceHeaders === void 0 ? {} : { "chat.headers": workspaceHeaders },
6370
+ ...promptGate === void 0 ? {} : { "chat.message": promptGate }
6295
6371
  });
6296
6372
  };
6297
6373
  };
@@ -6793,12 +6869,8 @@ var productionOptions = () => {
6793
6869
  };
6794
6870
  };
6795
6871
 
6796
- // src/tui-entry/run-connect/run-connect.ts
6797
- init_attribution();
6798
- init_config();
6799
-
6800
- // src/tui-entry/dialog-confirm/dialog-confirm.ts
6801
- var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6872
+ // src/tui-entry/dialog-select/dialog-select.ts
6873
+ var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6802
6874
  let settled = false;
6803
6875
  const settle = (value) => {
6804
6876
  if (settled) {
@@ -6810,14 +6882,12 @@ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6810
6882
  };
6811
6883
  const dialog = api.ui.dialog;
6812
6884
  dialog.replace(
6813
- () => api.ui.DialogConfirm({
6814
- message: input.message,
6815
- onCancel: () => {
6816
- settle(false);
6817
- },
6818
- onConfirm: () => {
6819
- settle(true);
6885
+ () => api.ui.DialogSelect({
6886
+ current: input.current,
6887
+ onSelect: (option) => {
6888
+ settle(option.value);
6820
6889
  },
6890
+ options: input.options,
6821
6891
  title: input.title
6822
6892
  }),
6823
6893
  () => {
@@ -6826,8 +6896,70 @@ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6826
6896
  );
6827
6897
  });
6828
6898
 
6829
- // src/tui-entry/dialog-select/dialog-select.ts
6830
- var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6899
+ // src/tui-entry/r33-command-reply/r33-command-reply.ts
6900
+ init_create_route33_plugin2();
6901
+
6902
+ // src/v2-entry/parse-r33-subcommand/parse-r33-subcommand.ts
6903
+ var SUBCOMMANDS = ["inspect", "rotate", "reset"];
6904
+ 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) {
6911
+ return "inspect";
6912
+ }
6913
+ return SUBCOMMANDS.includes(argument) ? argument : "help";
6914
+ };
6915
+
6916
+ // src/v2-entry/r33-command/r33-command.ts
6917
+ var executeR33Command = async (input) => {
6918
+ const subcommand = parseR33Subcommand(input.promptText);
6919
+ if (input.handlers === void 0) {
6920
+ return "Route 33 is not connected in this folder. Run /connect, choose Route 33, and follow the steps.";
6921
+ }
6922
+ if (subcommand === "help") {
6923
+ return "Route 33 usage: /r33 [inspect|rotate|reset] \u2014 inspect shows attribution and key rotation, rotate rotates the key now, reset clears the assigned budget (assign again with /connect).";
6924
+ }
6925
+ switch (subcommand) {
6926
+ case "rotate": {
6927
+ const lease = await input.handlers["rotate-now"]();
6928
+ return `Route 33 key rotated. Key ${lease.keyId} is valid until ${lease.expiresAt}.`;
6929
+ }
6930
+ case "reset": {
6931
+ await input.handlers["reset-attribution"]();
6932
+ return "Route 33 attribution cleared. Run /connect, choose Route 33, and assign a budget again.";
6933
+ }
6934
+ default: {
6935
+ return JSON.stringify(input.handlers["inspect-session"](), null, 2);
6936
+ }
6937
+ }
6938
+ };
6939
+
6940
+ // src/tui-entry/r33-command-reply/r33-command-reply.ts
6941
+ var r33CommandReply = (deps) => async (subcommand) => {
6942
+ let runtime;
6943
+ const entry = createRoute33Plugin({
6944
+ ...deps.composeOptions(),
6945
+ bindRuntime: (instance) => {
6946
+ runtime = instance;
6947
+ }
6948
+ });
6949
+ await entry({ worktree: deps.api.state.path.directory });
6950
+ const handlers = runtime?.commandHandlers();
6951
+ return executeR33Command({
6952
+ handlers,
6953
+ promptText: `/r33 ${subcommand}`
6954
+ });
6955
+ };
6956
+
6957
+ // src/tui-entry/run-connect/run-connect.ts
6958
+ init_attribution();
6959
+ init_config();
6960
+
6961
+ // src/tui-entry/dialog-confirm/dialog-confirm.ts
6962
+ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6831
6963
  let settled = false;
6832
6964
  const settle = (value) => {
6833
6965
  if (settled) {
@@ -6839,12 +6971,14 @@ var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6839
6971
  };
6840
6972
  const dialog = api.ui.dialog;
6841
6973
  dialog.replace(
6842
- () => api.ui.DialogSelect({
6843
- current: input.current,
6844
- onSelect: (option) => {
6845
- settle(option.value);
6974
+ () => api.ui.DialogConfirm({
6975
+ message: input.message,
6976
+ onCancel: () => {
6977
+ settle(false);
6978
+ },
6979
+ onConfirm: () => {
6980
+ settle(true);
6846
6981
  },
6847
- options: input.options,
6848
6982
  title: input.title
6849
6983
  }),
6850
6984
  () => {
@@ -6925,6 +7059,45 @@ var runConnect = async (api, composeOptions) => {
6925
7059
  }
6926
7060
  };
6927
7061
 
7062
+ // src/tui-entry/r33-menu-actions/r33-menu-actions.ts
7063
+ var r33MenuActions = (deps) => async (selection) => {
7064
+ if (selection === "connect" || selection === "change") {
7065
+ await runConnect(deps.api, deps.composeOptions);
7066
+ return;
7067
+ }
7068
+ try {
7069
+ const reply = await r33CommandReply(deps)(selection);
7070
+ deps.api.ui.toast({
7071
+ message: reply,
7072
+ title: "Route 33",
7073
+ variant: "info"
7074
+ });
7075
+ } catch (error) {
7076
+ deps.api.ui.toast({
7077
+ message: error instanceof Error ? error.message : String(error),
7078
+ title: "Route 33",
7079
+ variant: "error"
7080
+ });
7081
+ }
7082
+ };
7083
+
7084
+ // src/tui-entry/r33-menu/r33-menu.ts
7085
+ var menuOptions = [
7086
+ { title: "Connect \u2014 sign in and assign a budget", value: "connect" },
7087
+ { title: "Inspect session \u2014 attribution and key metadata", value: "inspect" },
7088
+ { title: "Rotate key now", value: "rotate" },
7089
+ { title: "Change budget \u2014 reassign this folder", value: "change" },
7090
+ { title: "Reset attribution \u2014 clear the assigned budget", value: "reset" }
7091
+ ];
7092
+ var r33Menu = async (api, composeOptions) => {
7093
+ const selection = await selectFromDialog(api, {
7094
+ options: menuOptions,
7095
+ title: "Route 33 \u2014 choose an action"
7096
+ });
7097
+ if (selection === void 0) return;
7098
+ await r33MenuActions({ api, composeOptions })(selection);
7099
+ };
7100
+
6928
7101
  // src/tui-entry/v1-connect-wizard/v1-connect-wizard.ts
6929
7102
  var createV1ConnectWizard = (composeOptions = productionOptions) => (api) => {
6930
7103
  if (readEnvDirectApiKey() !== void 0 || readEnvAutoconnectDisabled()) {
@@ -6941,17 +7114,17 @@ var createV1ConnectWizard = (composeOptions = productionOptions) => (api) => {
6941
7114
  const legacyCommands = api.command;
6942
7115
  legacyCommands?.register(() => [
6943
7116
  {
6944
- onSelect: () => runConnect(api, composeOptions),
7117
+ onSelect: () => void r33Menu(api, composeOptions),
6945
7118
  slash: { name: "r33" },
6946
- title: "Route 33: sign in and assign a budget for this folder",
6947
- value: "route33.connect"
7119
+ title: "Route 33: status, budget, and key management",
7120
+ value: "route33.menu"
6948
7121
  }
6949
7122
  ]);
6950
7123
  return Promise.resolve();
6951
7124
  };
6952
7125
 
6953
7126
  // src/tui-entry/show-r33-menu/show-r33-menu.ts
6954
- var menuOptions = [
7127
+ var menuOptions2 = [
6955
7128
  {
6956
7129
  title: "Connect \u2014 sign in and assign a budget",
6957
7130
  value: "connect"
@@ -6976,7 +7149,7 @@ var menuOptions = [
6976
7149
  var showR33Menu = async (context) => {
6977
7150
  const selection = await context.ui.dialog.select({
6978
7151
  title: "Route 33 \u2014 choose an action",
6979
- options: menuOptions
7152
+ options: menuOptions2
6980
7153
  });
6981
7154
  if (selection === void 0) return;
6982
7155
  if (selection === "connect") {
@@ -6995,27 +7168,40 @@ var showR33Menu = async (context) => {
6995
7168
  // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
6996
7169
  init_attribution();
6997
7170
  init_cli();
6998
- var v2Autoconnect = async (context) => {
6999
- if (readEnvDirectApiKey() !== void 0 || readEnvAutoconnectDisabled() || context.location === void 0) {
7000
- return;
7001
- }
7171
+
7172
+ // src/tui-entry/v2-connect-runner/v2-connect-runner.ts
7173
+ var createV2ConnectRunner = ({
7174
+ context,
7175
+ unattributed
7176
+ }) => {
7002
7177
  const oauth = context.client?.api?.integration?.oauth;
7003
- if (oauth === void 0 || oauth.connect === void 0) return;
7004
- const attribution = readAttribution({
7005
- directory: context.location.directory,
7178
+ return async (message) => {
7179
+ const connect = oauth?.connect;
7180
+ if (connect === void 0) return;
7181
+ if (!unattributed()) return;
7182
+ context.ui.toast.show({ message, variant: "info" });
7183
+ await connect({
7184
+ integrationID: "route33",
7185
+ methodID: "browser"
7186
+ }).catch(() => void 0);
7187
+ };
7188
+ };
7189
+
7190
+ // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
7191
+ var v2Autoconnect = async (context) => {
7192
+ if (readEnvDirectApiKey() !== void 0) return;
7193
+ if (readEnvAutoconnectDisabled()) return;
7194
+ const location = context.location;
7195
+ if (location === void 0) return;
7196
+ const unattributed = () => readAttribution({
7197
+ directory: location.directory,
7006
7198
  outsideWorktree: "return-undefined"
7007
- });
7008
- if (attribution !== void 0) {
7009
- return;
7010
- }
7011
- context.ui.toast.show({
7012
- message: "Route 33 is not connected \u2014 signing in now. Follow the browser prompt, then run /connect to assign a budget.",
7013
- variant: "info"
7014
- });
7015
- await oauth.connect({
7016
- integrationID: "route33",
7017
- methodID: "browser"
7018
- }).catch(() => void 0);
7199
+ }) === void 0;
7200
+ const connectPass = createV2ConnectRunner({ context, unattributed });
7201
+ await connectPass(
7202
+ "Route 33 is not connected \u2014 signing in now, then pick the budget for this folder."
7203
+ );
7204
+ await connectPass("Signed in to Route 33 \u2014 opening the budget picker.");
7019
7205
  };
7020
7206
 
7021
7207
  // src/tui-entry/v2-tui/v2-tui.ts
@@ -3248,6 +3248,26 @@ var Route33Runtime = class {
3248
3248
  }
3249
3249
  };
3250
3250
 
3251
+ // src/v1-entry/unattributed-prompt-gate/unattributed-prompt-gate.ts
3252
+ var createUnattributedPromptGate = ({ directory, outsideWorktree }) => (input) => {
3253
+ if (input.model?.providerID !== "route_33") return Promise.resolve();
3254
+ const attribution = readAttribution({ directory, outsideWorktree });
3255
+ if (attribution !== void 0) return Promise.resolve();
3256
+ return Promise.reject(
3257
+ new Error(
3258
+ "Route 33 needs a budget for this folder first \u2014 run /r33 in OpenCode, choose Route 33, and assign a budget."
3259
+ )
3260
+ );
3261
+ };
3262
+
3263
+ // src/v1-entry/workspace-key-headers/workspace-key-headers.ts
3264
+ var createWorkspaceKeyHeaders = ({ resolveKey, session }) => async (input, output) => {
3265
+ const workspace = await session.get({ sessionID: input.sessionID });
3266
+ const key = await resolveKey(workspace.location.directory);
3267
+ if (key === void 0) return;
3268
+ output.headers["Authorization"] = `Bearer ${key.value}`;
3269
+ };
3270
+
3251
3271
  // src/create-route33-plugin/create-route33-plugin.ts
3252
3272
  var createRoute33Plugin = (options = {}) => {
3253
3273
  const baseURL = readEnvBaseUrl();
@@ -3288,6 +3308,8 @@ var createRoute33Plugin = (options = {}) => {
3288
3308
  }
3289
3309
  }
3290
3310
  let credentialProvider;
3311
+ let workspaceHeaders;
3312
+ let promptGate;
3291
3313
  if (directKey !== void 0) {
3292
3314
  credentialProvider = () => Promise.resolve(parseGatewayKey(directKey));
3293
3315
  } else if (runtime === void 0) {
@@ -3296,13 +3318,28 @@ var createRoute33Plugin = (options = {}) => {
3296
3318
  );
3297
3319
  } else {
3298
3320
  credentialProvider = () => runtime.resolveCredential();
3321
+ workspaceHeaders = createWorkspaceKeyHeaders({
3322
+ resolveKey: (directory) => runtime.resolveWorkspaceCredential(directory),
3323
+ session: {
3324
+ get: async ({ sessionID }) => {
3325
+ const session = await options.readSession?.(sessionID);
3326
+ return session ?? { location: { directory: input.worktree } };
3327
+ }
3328
+ }
3329
+ });
3330
+ promptGate = createUnattributedPromptGate({
3331
+ directory: input.worktree,
3332
+ outsideWorktree: "return-undefined"
3333
+ });
3299
3334
  }
3300
3335
  return Promise.resolve({
3301
3336
  config: createConfigHook({
3302
3337
  ...resolvedConfig,
3303
3338
  credentialProvider,
3304
3339
  cwd: input.worktree
3305
- })
3340
+ }),
3341
+ ...workspaceHeaders === void 0 ? {} : { "chat.headers": workspaceHeaders },
3342
+ ...promptGate === void 0 ? {} : { "chat.message": promptGate }
3306
3343
  });
3307
3344
  };
3308
3345
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@route_33/opencode",
3
- "version": "0.4.7-rc.4",
3
+ "version": "0.4.7-rc.6",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,8 +42,8 @@
42
42
  "eslint": "10.13.0",
43
43
  "typescript": "6.0.3",
44
44
  "vitest": "5.0.5",
45
- "@cronos-ai-lab/eslint-config": "0.1.2",
46
- "@cronos-ai-lab/typescript-config": "0.1.2"
45
+ "@cronos-ai-lab/typescript-config": "0.1.2",
46
+ "@cronos-ai-lab/eslint-config": "0.1.2"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "esbuild src/index.ts src/v2-entry/index.ts src/tui-entry/index.ts src/cli/production-smoke/production-smoke.ts --bundle --format=esm --platform=node --packages=external --outbase=src --outdir=dist --alias:@opencode-ai/plugin-v2=@opencode/plugin --define:__ROUTE33_DEFAULT_CLIENT_ID__=\\\"${ROUTE33_DEFAULT_CLIENT_ID:-}\\\"",