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

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,16 +5,27 @@ usage, and use the route_33 models — no API keys to paste, ever.
5
5
 
6
6
  ## Install
7
7
 
8
+ **OpenCode v2 (recommended)** uses the `add` subcommand and installs into
9
+ the global configuration (`~/.config/opencode/opencode.json` + `tui.json`):
10
+
8
11
  ```sh
9
12
  opencode plugin add @route_33/opencode
10
13
  ```
11
14
 
12
- Restart OpenCode afterwards — plugins load at startup.
15
+ **OpenCode v1** installs the package and registers the plugin at the nearest
16
+ definition — the project's `.opencode/opencode.json` (plus the TUI part in
17
+ `tui.json`) when run inside a project, the global config with `--global`:
18
+
19
+ ```sh
20
+ opencode plugin @route_33/opencode # project scope
21
+ opencode plugin @route_33/opencode --global # global scope
22
+ ```
13
23
 
14
- Prefer config? Add the package to `opencode.jsonc` instead:
24
+ Either way, restart OpenCode afterwards — plugins load at startup. Prefer
25
+ config? Declare the plugin directly in `opencode.json(c)`:
15
26
 
16
27
  ```jsonc
17
- { "plugins": ["@route_33/opencode"] }
28
+ { "plugin": ["@route_33/opencode"] }
18
29
  ```
19
30
 
20
31
  ## First run
@@ -6793,12 +6793,8 @@ var productionOptions = () => {
6793
6793
  };
6794
6794
  };
6795
6795
 
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) => {
6796
+ // src/tui-entry/dialog-select/dialog-select.ts
6797
+ var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6802
6798
  let settled = false;
6803
6799
  const settle = (value) => {
6804
6800
  if (settled) {
@@ -6810,14 +6806,12 @@ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6810
6806
  };
6811
6807
  const dialog = api.ui.dialog;
6812
6808
  dialog.replace(
6813
- () => api.ui.DialogConfirm({
6814
- message: input.message,
6815
- onCancel: () => {
6816
- settle(false);
6817
- },
6818
- onConfirm: () => {
6819
- settle(true);
6809
+ () => api.ui.DialogSelect({
6810
+ current: input.current,
6811
+ onSelect: (option) => {
6812
+ settle(option.value);
6820
6813
  },
6814
+ options: input.options,
6821
6815
  title: input.title
6822
6816
  }),
6823
6817
  () => {
@@ -6826,8 +6820,70 @@ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6826
6820
  );
6827
6821
  });
6828
6822
 
6829
- // src/tui-entry/dialog-select/dialog-select.ts
6830
- var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6823
+ // src/tui-entry/r33-command-reply/r33-command-reply.ts
6824
+ init_create_route33_plugin2();
6825
+
6826
+ // src/v2-entry/parse-r33-subcommand/parse-r33-subcommand.ts
6827
+ var SUBCOMMANDS = ["inspect", "rotate", "reset"];
6828
+ var parseR33Subcommand = (promptText) => {
6829
+ const [invocation, argument] = promptText.trim().split(/\s+/u);
6830
+ const name = invocation?.replace(/^\/+/u, "").split(":")[0] ?? "";
6831
+ if (name !== "r33") {
6832
+ return "help";
6833
+ }
6834
+ if (argument === void 0) {
6835
+ return "inspect";
6836
+ }
6837
+ return SUBCOMMANDS.includes(argument) ? argument : "help";
6838
+ };
6839
+
6840
+ // src/v2-entry/r33-command/r33-command.ts
6841
+ var executeR33Command = async (input) => {
6842
+ const subcommand = parseR33Subcommand(input.promptText);
6843
+ if (input.handlers === void 0) {
6844
+ return "Route 33 is not connected in this folder. Run /connect, choose Route 33, and follow the steps.";
6845
+ }
6846
+ if (subcommand === "help") {
6847
+ 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).";
6848
+ }
6849
+ switch (subcommand) {
6850
+ case "rotate": {
6851
+ const lease = await input.handlers["rotate-now"]();
6852
+ return `Route 33 key rotated. Key ${lease.keyId} is valid until ${lease.expiresAt}.`;
6853
+ }
6854
+ case "reset": {
6855
+ await input.handlers["reset-attribution"]();
6856
+ return "Route 33 attribution cleared. Run /connect, choose Route 33, and assign a budget again.";
6857
+ }
6858
+ default: {
6859
+ return JSON.stringify(input.handlers["inspect-session"](), null, 2);
6860
+ }
6861
+ }
6862
+ };
6863
+
6864
+ // src/tui-entry/r33-command-reply/r33-command-reply.ts
6865
+ var r33CommandReply = (deps) => async (subcommand) => {
6866
+ let runtime;
6867
+ const entry = createRoute33Plugin({
6868
+ ...deps.composeOptions(),
6869
+ bindRuntime: (instance) => {
6870
+ runtime = instance;
6871
+ }
6872
+ });
6873
+ await entry({ worktree: deps.api.state.path.directory });
6874
+ const handlers = runtime?.commandHandlers();
6875
+ return executeR33Command({
6876
+ handlers,
6877
+ promptText: `/r33 ${subcommand}`
6878
+ });
6879
+ };
6880
+
6881
+ // src/tui-entry/run-connect/run-connect.ts
6882
+ init_attribution();
6883
+ init_config();
6884
+
6885
+ // src/tui-entry/dialog-confirm/dialog-confirm.ts
6886
+ var confirmFromDialog = (api, input) => new Promise((resolve2) => {
6831
6887
  let settled = false;
6832
6888
  const settle = (value) => {
6833
6889
  if (settled) {
@@ -6839,12 +6895,14 @@ var selectFromDialog = async (api, input) => new Promise((resolve2) => {
6839
6895
  };
6840
6896
  const dialog = api.ui.dialog;
6841
6897
  dialog.replace(
6842
- () => api.ui.DialogSelect({
6843
- current: input.current,
6844
- onSelect: (option) => {
6845
- settle(option.value);
6898
+ () => api.ui.DialogConfirm({
6899
+ message: input.message,
6900
+ onCancel: () => {
6901
+ settle(false);
6902
+ },
6903
+ onConfirm: () => {
6904
+ settle(true);
6846
6905
  },
6847
- options: input.options,
6848
6906
  title: input.title
6849
6907
  }),
6850
6908
  () => {
@@ -6925,6 +6983,45 @@ var runConnect = async (api, composeOptions) => {
6925
6983
  }
6926
6984
  };
6927
6985
 
6986
+ // src/tui-entry/r33-menu-actions/r33-menu-actions.ts
6987
+ var r33MenuActions = (deps) => async (selection) => {
6988
+ if (selection === "connect" || selection === "change") {
6989
+ await runConnect(deps.api, deps.composeOptions);
6990
+ return;
6991
+ }
6992
+ try {
6993
+ const reply = await r33CommandReply(deps)(selection);
6994
+ deps.api.ui.toast({
6995
+ message: reply,
6996
+ title: "Route 33",
6997
+ variant: "info"
6998
+ });
6999
+ } catch (error) {
7000
+ deps.api.ui.toast({
7001
+ message: error instanceof Error ? error.message : String(error),
7002
+ title: "Route 33",
7003
+ variant: "error"
7004
+ });
7005
+ }
7006
+ };
7007
+
7008
+ // src/tui-entry/r33-menu/r33-menu.ts
7009
+ var menuOptions = [
7010
+ { title: "Connect \u2014 sign in and assign a budget", value: "connect" },
7011
+ { title: "Inspect session \u2014 attribution and key metadata", value: "inspect" },
7012
+ { title: "Rotate key now", value: "rotate" },
7013
+ { title: "Change budget \u2014 reassign this folder", value: "change" },
7014
+ { title: "Reset attribution \u2014 clear the assigned budget", value: "reset" }
7015
+ ];
7016
+ var r33Menu = async (api, composeOptions) => {
7017
+ const selection = await selectFromDialog(api, {
7018
+ options: menuOptions,
7019
+ title: "Route 33 \u2014 choose an action"
7020
+ });
7021
+ if (selection === void 0) return;
7022
+ await r33MenuActions({ api, composeOptions })(selection);
7023
+ };
7024
+
6928
7025
  // src/tui-entry/v1-connect-wizard/v1-connect-wizard.ts
6929
7026
  var createV1ConnectWizard = (composeOptions = productionOptions) => (api) => {
6930
7027
  if (readEnvDirectApiKey() !== void 0 || readEnvAutoconnectDisabled()) {
@@ -6941,17 +7038,17 @@ var createV1ConnectWizard = (composeOptions = productionOptions) => (api) => {
6941
7038
  const legacyCommands = api.command;
6942
7039
  legacyCommands?.register(() => [
6943
7040
  {
6944
- onSelect: () => runConnect(api, composeOptions),
7041
+ onSelect: () => void r33Menu(api, composeOptions),
6945
7042
  slash: { name: "r33" },
6946
- title: "Route 33: sign in and assign a budget for this folder",
6947
- value: "route33.connect"
7043
+ title: "Route 33: status, budget, and key management",
7044
+ value: "route33.menu"
6948
7045
  }
6949
7046
  ]);
6950
7047
  return Promise.resolve();
6951
7048
  };
6952
7049
 
6953
7050
  // src/tui-entry/show-r33-menu/show-r33-menu.ts
6954
- var menuOptions = [
7051
+ var menuOptions2 = [
6955
7052
  {
6956
7053
  title: "Connect \u2014 sign in and assign a budget",
6957
7054
  value: "connect"
@@ -6976,7 +7073,7 @@ var menuOptions = [
6976
7073
  var showR33Menu = async (context) => {
6977
7074
  const selection = await context.ui.dialog.select({
6978
7075
  title: "Route 33 \u2014 choose an action",
6979
- options: menuOptions
7076
+ options: menuOptions2
6980
7077
  });
6981
7078
  if (selection === void 0) return;
6982
7079
  if (selection === "connect") {
@@ -6995,27 +7092,40 @@ var showR33Menu = async (context) => {
6995
7092
  // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
6996
7093
  init_attribution();
6997
7094
  init_cli();
6998
- var v2Autoconnect = async (context) => {
6999
- if (readEnvDirectApiKey() !== void 0 || readEnvAutoconnectDisabled() || context.location === void 0) {
7000
- return;
7001
- }
7095
+
7096
+ // src/tui-entry/v2-connect-runner/v2-connect-runner.ts
7097
+ var createV2ConnectRunner = ({
7098
+ context,
7099
+ unattributed
7100
+ }) => {
7002
7101
  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,
7102
+ return async (message) => {
7103
+ const connect = oauth?.connect;
7104
+ if (connect === void 0) return;
7105
+ if (!unattributed()) return;
7106
+ context.ui.toast.show({ message, variant: "info" });
7107
+ await connect({
7108
+ integrationID: "route33",
7109
+ methodID: "browser"
7110
+ }).catch(() => void 0);
7111
+ };
7112
+ };
7113
+
7114
+ // src/tui-entry/v2-autoconnect/v2-autoconnect.ts
7115
+ var v2Autoconnect = async (context) => {
7116
+ if (readEnvDirectApiKey() !== void 0) return;
7117
+ if (readEnvAutoconnectDisabled()) return;
7118
+ const location = context.location;
7119
+ if (location === void 0) return;
7120
+ const unattributed = () => readAttribution({
7121
+ directory: location.directory,
7006
7122
  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);
7123
+ }) === void 0;
7124
+ const connectPass = createV2ConnectRunner({ context, unattributed });
7125
+ await connectPass(
7126
+ "Route 33 is not connected \u2014 signing in now, then pick the budget for this folder."
7127
+ );
7128
+ await connectPass("Signed in to Route 33 \u2014 opening the budget picker.");
7019
7129
  };
7020
7130
 
7021
7131
  // src/tui-entry/v2-tui/v2-tui.ts
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.5",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",