@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 +31 -11
- package/dist/index.js +38 -1
- package/dist/tui-entry/index.js +231 -45
- package/dist/v2-entry/index.js +38 -1
- package/package.json +3 -3
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
|
-
|
|
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
|
-
|
|
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
|
-
{ "
|
|
33
|
+
{ "plugin": ["@route_33/opencode"] }
|
|
18
34
|
```
|
|
19
35
|
|
|
20
36
|
## First run
|
|
21
37
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
the
|
|
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
|
};
|
package/dist/tui-entry/index.js
CHANGED
|
@@ -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/
|
|
6797
|
-
|
|
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.
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
settle(
|
|
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/
|
|
6830
|
-
|
|
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.
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
settle(
|
|
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: () =>
|
|
7117
|
+
onSelect: () => void r33Menu(api, composeOptions),
|
|
6945
7118
|
slash: { name: "r33" },
|
|
6946
|
-
title: "Route 33:
|
|
6947
|
-
value: "route33.
|
|
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
|
|
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:
|
|
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
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
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
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
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
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
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
|
package/dist/v2-entry/index.js
CHANGED
|
@@ -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.
|
|
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/
|
|
46
|
-
"@cronos-ai-lab/
|
|
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:-}\\\"",
|