@poe-platform/safe-bash 0.1.821 → 0.1.823

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/safe-bash/chunks/{chunk-HNT2MR4W.js → chunk-363QOIDR.js} +2 -1
  2. package/dist/safe-bash/chunks/chunk-AGHV53VF.js +42 -0
  3. package/dist/safe-bash/chunks/{chunk-VF3Q2V3E.js → chunk-RAFD5ZAH.js} +1 -1
  4. package/dist/safe-bash/chunks/{chunk-67QE3JLU.js → chunk-TZRVK3NU.js} +1 -1
  5. package/dist/safe-bash/chunks/{chunk-IRJS54AA.js → chunk-VWLQDZFF.js} +20 -12
  6. package/dist/safe-bash/chunks/{chunk-NAETSXBW.js → chunk-ZJAXMB5M.js} +1 -1
  7. package/dist/safe-bash/command-chunks/{chunk-QX3WKBLI.js → chunk-36FV6BAG.js} +5 -3
  8. package/dist/safe-bash/command-chunks/{chunk-ZSHXZ3XG.js → chunk-3EAZRKI4.js} +7 -7
  9. package/dist/safe-bash/command-chunks/chunk-64HIOP7Q.js +993 -0
  10. package/dist/safe-bash/command-chunks/{chunk-WOT2YXBT.js → chunk-7ZQVMPSB.js} +213 -42
  11. package/dist/safe-bash/command-chunks/{chunk-GRFJKJFN.js → chunk-AVSINNZ6.js} +233 -3
  12. package/dist/safe-bash/command-chunks/{chunk-BZLLQWRK.js → chunk-E5CDHXFA.js} +2 -2
  13. package/dist/safe-bash/command-chunks/{chunk-RHXV2KG5.js → chunk-EO3RYGUZ.js} +1010 -58
  14. package/dist/safe-bash/command-chunks/{chunk-MCUDSE4H.js → chunk-EWECMOQ5.js} +1 -1
  15. package/dist/safe-bash/command-chunks/{chunk-RTUDDAAY.js → chunk-O3KFOFJM.js} +1 -1
  16. package/dist/safe-bash/command-chunks/{chunk-SLD5A7IL.js → chunk-OU5UEUZN.js} +1 -1
  17. package/dist/safe-bash/command-chunks/{chunk-RKAL5VFP.js → chunk-PLVFJ6FF.js} +255 -616
  18. package/dist/safe-bash/command-chunks/{chunk-CJIFJ45R.js → chunk-QBCEAYQT.js} +1 -1
  19. package/dist/safe-bash/command-chunks/{chunk-4Q3HP33O.js → chunk-RGKHTSUY.js} +146 -123
  20. package/dist/safe-bash/command-chunks/{chunk-I7MEH76L.js → chunk-UYNJF5QN.js} +1 -1
  21. package/dist/safe-bash/command-chunks/{chunk-IAHYG67O.js → chunk-V5ZBRM5R.js} +3 -3
  22. package/dist/safe-bash/command-chunks/{chunk-R4NPYXQX.js → chunk-WDTWJFPK.js} +320 -67
  23. package/dist/safe-bash/command-chunks/{chunk-GQV5RWMN.js → chunk-ZFXHSFTU.js} +1 -1
  24. package/dist/safe-bash/command-chunks/{prompt-tool-debug-ERJKK3XZ.js → prompt-tool-debug-3POFNRYP.js} +5 -5
  25. package/dist/safe-bash/commands/bc/index.browser.js +1 -1
  26. package/dist/safe-bash/commands/llm/index.browser.js +3 -1
  27. package/dist/safe-bash/commands/llm/index.js +1 -1
  28. package/dist/safe-bash/commands/python/executor.browser.js +12 -1
  29. package/dist/safe-bash/commands/python/executor.js +1 -1
  30. package/dist/safe-bash/commands/python/index.browser.js +23 -1
  31. package/dist/safe-bash/commands/python/index.js +1 -1
  32. package/dist/safe-bash/core.browser.js +2 -2
  33. package/dist/safe-bash/full-core.browser.js +30 -6
  34. package/dist/safe-bash/plugins/index.browser.js +3 -3
  35. package/dist/safe-bash/registry-entry.browser.js +2 -2
  36. package/dist/safe-bash/search.browser.js +1 -1
  37. package/dist/safe-bash/shell/runtime.d.ts +2 -2
  38. package/dist/safe-bash/shell/runtime.js +11 -2
  39. package/dist/safe-bash/shell/sync-extra-evaluators.js +12 -12
  40. package/dist/safe-bash/shell-entry.browser.js +2 -2
  41. package/dist/safe-bash-command-llm/collections.js +24 -65
  42. package/dist/safe-bash-command-llm/command.js +6 -6
  43. package/dist/safe-bash-command-llm/fragment-loaders.d.ts +3 -2
  44. package/dist/safe-bash-command-llm/index.d.ts +3 -2
  45. package/dist/safe-bash-command-llm/index.js +10 -8
  46. package/dist/safe-bash-command-llm/loader-provider.d.ts +25 -0
  47. package/dist/safe-bash-command-llm/openai-sse.js +2 -2
  48. package/dist/safe-bash-command-llm/openai.js +4 -4
  49. package/dist/safe-bash-command-llm/providers/index.js +4 -4
  50. package/dist/safe-bash-command-llm/providers/openai.js +4 -4
  51. package/dist/safe-bash-command-llm/python-unicode.d.ts +2 -0
  52. package/dist/safe-bash-command-llm/templates.d.ts +7 -2
  53. package/dist/safe-bash-command-llm/types.d.ts +7 -1
  54. package/dist/safe-bash-command-mcp/index.browser.js +3 -0
  55. package/dist/safe-bash-command-mcp/index.js +3 -0
  56. package/dist/safe-bash-command-patch/index.js +2 -2
  57. package/dist/safe-bash-command-patch/patch-publication.js +1 -1
  58. package/dist/safe-bash-command-patch/patch.js +2 -2
  59. package/dist/safe-bash-command-python/build-backend.d.ts +51 -0
  60. package/dist/safe-bash-command-python/build-dependencies.d.ts +12 -0
  61. package/dist/safe-bash-command-python/build-environment.d.ts +3 -0
  62. package/dist/safe-bash-command-python/build-wheel.d.ts +8 -0
  63. package/dist/safe-bash-command-python/executor.d.ts +12 -2
  64. package/dist/safe-bash-command-python/executor.js +26 -4
  65. package/dist/safe-bash-command-python/index.js +26 -4
  66. package/dist/safe-bash-command-python/jspi.js +2 -2
  67. package/dist/safe-bash-command-python/llm-assets-node.js +1 -1
  68. package/dist/safe-bash-command-python/llm-fragment-loader.d.ts +6 -0
  69. package/dist/safe-bash-command-python/llm-functions-loader.d.ts +5 -1
  70. package/dist/safe-bash-command-python/llm-loader-discovery.d.ts +13 -0
  71. package/dist/safe-bash-command-python/llm-package-manager.d.ts +7 -0
  72. package/dist/safe-bash-command-python/llm-template-loader.d.ts +6 -0
  73. package/dist/safe-bash-command-python/manifest.d.ts +13 -0
  74. package/dist/safe-bash-command-python/provisioning.d.ts +33 -5
  75. package/dist/safe-bash-command-python/provisioning.js +1 -1
  76. package/dist/safe-bash-command-python/source-environment.d.ts +9 -0
  77. package/dist/safe-bash-command-python/source-snapshot.d.ts +8 -0
  78. package/dist/safe-bash-command-python/worker.js +3 -185
  79. package/dist/safe-bash-csv-engine/index.js +1 -1
  80. package/dist/safe-bash-csv-engine/python-iso2022.d.ts +21 -0
  81. package/dist/safe-bash-csv-engine/python-utf7.d.ts +18 -0
  82. package/dist/safe-bash-csv-engine/text-decoder.d.ts +2 -0
  83. package/dist/safe-bash-csv-engine/text-decoder.js +7 -3
  84. package/dist/safe-bash-zip-engine/index.js +1 -1
  85. package/dist/safe-bash-zip-engine/zip/repair.js +1 -1
  86. package/dist/safe-bash-zip-engine/zip/sfx.js +1 -1
  87. package/dist/safe-bash-zip-engine/zip-format.d.ts +3 -1
  88. package/dist/safe-bash-zip-engine/zip-format.js +1 -1
  89. package/dist/safe-playwright-cloudflare/shell-browser-resource.d.ts +1 -1
  90. package/dist/safe-playwright-cloudflare/shell-browser-resource.js +35 -20
  91. package/package.json +3 -3
  92. package/dist/safe-bash/chunks/chunk-PSD2RSOS.js +0 -31
  93. package/dist/safe-bash/command-chunks/chunk-5EFNQ6FY.js +0 -458
@@ -1,17 +1,22 @@
1
1
  import {
2
2
  pythonRepr
3
- } from "./chunk-MCUDSE4H.js";
3
+ } from "./chunk-EWECMOQ5.js";
4
4
  import {
5
+ chatOptionSuggestion,
6
+ chatOptions,
7
+ commandArguments,
5
8
  createLlmConfiguration,
6
9
  embeddingCommand,
7
- publishConfiguration
8
- } from "./chunk-WOT2YXBT.js";
10
+ loadLlmHelp,
11
+ publishConfiguration,
12
+ unicodeOrder
13
+ } from "./chunk-7ZQVMPSB.js";
9
14
  import {
10
15
  createLlmSpool,
11
16
  fileSource,
12
17
  isPythonWhitespace,
13
18
  stripPythonWhitespace
14
- } from "./chunk-BZLLQWRK.js";
19
+ } from "./chunk-E5CDHXFA.js";
15
20
  import {
16
21
  createLlmService,
17
22
  validateModelOptions
@@ -36,7 +41,7 @@ import {
36
41
  import {
37
42
  sourceBytes,
38
43
  waitForSource
39
- } from "./chunk-QX3WKBLI.js";
44
+ } from "./chunk-36FV6BAG.js";
40
45
  import {
41
46
  jsonValue
42
47
  } from "./chunk-GNPPPYDF.js";
@@ -46,46 +51,10 @@ import {
46
51
  } from "./chunk-VMA3NJXU.js";
47
52
 
48
53
  // packages/safe-bash-command-llm/src/plugins-command.ts
49
- var usage = "Usage: llm plugins [OPTIONS]\n";
50
- var help = usage + "\n List installed plugins\n\nOptions:\n --all Include built-in default plugins\n --hook TEXT Filter for plugins that implement this hook\n -h, --help Show this message and exit.\n";
51
54
  async function pluginsCommand(args, output, diagnostic, step, signal, load) {
52
- const error = async (message, withUsage = false) => {
53
- await diagnostic((withUsage ? usage + "Try 'llm plugins -h' for help.\n\n" : "") + "Error: " + message + "\n");
54
- return 2;
55
- };
56
- const hooks = [], extra = [];
57
- let all = false, showHelp = false, ended = false;
58
- for (let index = 0; index < args.length; index++) {
59
- await step();
60
- const token = args[index];
61
- if (ended || !token.startsWith("-") || token === "-") {
62
- extra.push(token);
63
- continue;
64
- }
65
- if (token === "--") {
66
- ended = true;
67
- continue;
68
- }
69
- const equals = token.indexOf("="), flag = equals < 0 ? token : token.slice(0, equals);
70
- if (flag === "--all" || flag === "--help") {
71
- if (equals >= 0) return error(`Option '${flag}' does not take a value.`);
72
- if (flag === "--all") all = true;
73
- else showHelp = true;
74
- } else if (flag === "--hook") {
75
- if (equals < 0 && args[++index] === void 0) return error("Option '--hook' requires an argument.");
76
- hooks.push(equals < 0 ? args[index] : token.slice(equals + 1));
77
- } else if (!token.startsWith("--")) {
78
- for (const letter of token.slice(1)) {
79
- if (letter !== "h") return error(`No such option: -${letter}`, true);
80
- showHelp = true;
81
- }
82
- } else return error(`No such option: ${flag}`, true);
83
- }
84
- if (showHelp) {
85
- await output(help);
86
- return 0;
87
- }
88
- if (extra.length) return error(`Got unexpected extra argument${extra.length === 1 ? "" : "s"} (${extra.join(" ")})`, true);
55
+ const parsed = await commandArguments("plugins", args, [], output, diagnostic, step);
56
+ if (typeof parsed === "number") return parsed;
57
+ const all = parsed.values.has("--all"), hooks = parsed.values.get("--hook") ?? [];
89
58
  if (!load) {
90
59
  await diagnostic("Error: Python plugin discovery is not configured\n");
91
60
  return 1;
@@ -99,83 +68,6 @@ async function pluginsCommand(args, output, diagnostic, step, signal, load) {
99
68
  return 0;
100
69
  }
101
70
 
102
- // packages/safe-bash-command-llm/src/chat-options.ts
103
- var chatOptions = [
104
- "-h",
105
- "--help",
106
- "--td",
107
- "--tools-debug",
108
- "--ta",
109
- "--tools-approve",
110
- "--no-stream",
111
- "--functions",
112
- "-T",
113
- "--tool",
114
- "--cl",
115
- "--chain-limit",
116
- "-f",
117
- "--fragment",
118
- "--sf",
119
- "--system-fragment",
120
- "-m",
121
- "--model",
122
- "-s",
123
- "--system",
124
- "-o",
125
- "--option",
126
- "-t",
127
- "--template",
128
- "-p",
129
- "--param",
130
- "--key"
131
- ];
132
- async function chatOptionSuggestion(value, step) {
133
- if (!value.startsWith("--")) return "";
134
- const options = chatOptions.filter((option) => option.startsWith("--"));
135
- const cutoff = 0.6;
136
- const maximum = Math.floor(Math.max(...options.map((option) => option.length)) * (2 / cutoff - 1));
137
- const input = [];
138
- for (const char of value) {
139
- await step();
140
- input.push(char);
141
- if (input.length > maximum) return "";
142
- }
143
- const matches = [];
144
- for (const option of options) {
145
- if (2 * Math.min(option.length, input.length) / (option.length + input.length) < cutoff) continue;
146
- const pending = [[0, option.length, 0, input.length]];
147
- let matched = 0;
148
- while (pending.length) {
149
- const [aStart, aEnd, bStart, bEnd] = pending.pop();
150
- let bestA = aStart, bestB = bStart, size = 0;
151
- for (let a = aStart; a < aEnd; a++) {
152
- await step();
153
- for (let b = bStart; b < bEnd; b++) {
154
- let length = 0;
155
- while (a + length < aEnd && b + length < bEnd && option[a + length] === input[b + length]) length++;
156
- if (length > size) {
157
- bestA = a;
158
- bestB = b;
159
- size = length;
160
- }
161
- }
162
- }
163
- if (!size) continue;
164
- matched += size;
165
- if (aStart < bestA && bStart < bestB) pending.push([aStart, bestA, bStart, bestB]);
166
- if (bestA + size < aEnd && bestB + size < bEnd) pending.push([bestA + size, aEnd, bestB + size, bEnd]);
167
- }
168
- const score = 2 * matched / (option.length + input.length);
169
- if (score >= cutoff) matches.push({ option, score });
170
- }
171
- matches.sort((left, right) => right.score - left.score || (left.option < right.option ? 1 : left.option > right.option ? -1 : 0));
172
- const suggestions = matches.slice(0, 3).map((match) => match.option).sort();
173
- return !suggestions.length ? "" : suggestions.length === 1 ? ` Did you mean ${suggestions[0]}?` : ` (Possible options: ${suggestions.join(", ")})`;
174
- }
175
-
176
- // packages/safe-bash-command-llm/src/chat-help.ts
177
- var chatHelp = "Usage: llm chat [OPTIONS]\n\n Hold an ongoing chat with a model.\n\nOptions:\n -s, --system TEXT System prompt to use\n -m, --model TEXT Model to use\n -f, --fragment TEXT Fragment (alias, URL, hash or file path) to\n add to the prompt\n --sf, --system-fragment TEXT Fragment to add to system prompt\n -t, --template TEXT Template to use\n -p, --param <TEXT TEXT>... Parameters for template\n -o, --option <TEXT TEXT>... key/value options for the model\n --no-stream Do not stream output\n --key TEXT API key to use\n -T, --tool TEXT Name of a tool to make available to the model\n --functions TEXT Python code block or file path defining\n functions to register as tools\n --td, --tools-debug Show full details of tool executions\n --ta, --tools-approve Manually approve every tool execution\n --cl, --chain-limit INTEGER How many chained tool responses to allow,\n default 5, set 0 for unlimited\n -h, --help Show this message and exit.\n";
178
-
179
71
  // packages/safe-bash-command-llm/src/chat-editor.ts
180
72
  import { FsError } from "../../safe-bash-contracts/index.js";
181
73
  var serial = 0;
@@ -987,7 +879,7 @@ async function* promptToolChain(options) {
987
879
  const write = options.debugWrite;
988
880
  diagnostics = diagnostics.then(async () => {
989
881
  signal.throwIfAborted();
990
- const { debugToolResult } = await import("./prompt-tool-debug-ERJKK3XZ.js");
882
+ const { debugToolResult } = await import("./prompt-tool-debug-3POFNRYP.js");
991
883
  await debugToolResult({ context: { ...context, signal }, result, output: content.spool, attachments, write });
992
884
  });
993
885
  await diagnostics;
@@ -1110,132 +1002,56 @@ function selectLlmTools(registry, names) {
1110
1002
  return names.map((name) => registry.get(name));
1111
1003
  }
1112
1004
 
1113
- // packages/safe-bash-command-llm/src/fragment-loader-command.ts
1114
- async function fragmentLoaderCommand(tokens, loaders, output, diagnostic) {
1115
- const usage3 = "Usage: llm fragments loaders [OPTIONS]\n";
1116
- let failure, help2 = false, ended = false;
1117
- const operands = [];
1118
- for (const token of tokens) {
1119
- if (!ended && token === "--") ended = true;
1120
- else if (!ended && (token === "--help" || token === "-h")) help2 = true;
1121
- else if (!ended && token.startsWith("-") && token !== "-") {
1122
- failure = `No such option: ${token.split("=")[0]}`;
1123
- break;
1124
- } else operands.push(token);
1125
- }
1126
- if (help2 && !failure) {
1127
- await output(usage3 + "\n Show fragment loaders registered by plugins\n\nOptions:\n -h, --help Show this message and exit.\n");
1128
- return 0;
1129
- }
1130
- failure ??= operands.length ? `Got unexpected extra argument (${operands[0]})` : void 0;
1131
- if (failure) {
1132
- await diagnostic(usage3 + "Try 'llm fragments loaders --help' for help.\n\nError: " + failure + "\n");
1133
- return 2;
1005
+ // packages/safe-bash-command-llm/src/loader-provider.ts
1006
+ var LlmLoaderLookupError = class extends Error {
1007
+ };
1008
+ async function discoverLlmLoaders(loaders, context, provider) {
1009
+ if (!provider) return loaders ?? /* @__PURE__ */ new Map();
1010
+ const result = await waitForSource(() => provider.discover(context), context.signal);
1011
+ return new Map([...result[context.kind === "fragments" ? "fragmentLoaders" : "templateLoaders"], ...loaders ?? []]);
1012
+ }
1013
+
1014
+ // packages/safe-bash-command-llm/src/loader-description.ts
1015
+ function formatLoaderDescription(value) {
1016
+ const lines = (value || "Undocumented").split("\n");
1017
+ let common;
1018
+ for (const line of lines) {
1019
+ if (!line.trim()) continue;
1020
+ let width = 0;
1021
+ while (line[width] === " " || line[width] === " ") width++;
1022
+ const indent = line.slice(0, width);
1023
+ if (common === void 0) common = indent;
1024
+ else {
1025
+ let i = 0;
1026
+ while (i < common.length && common[i] === indent[i]) i++;
1027
+ common = common.slice(0, i);
1028
+ }
1134
1029
  }
1030
+ const description = lines.map((line) => line.trim() ? line.slice(common?.length ?? 0) : "").join("\n").trim();
1031
+ return description.split("\n").map((line) => line ? ` ${line}` : line);
1032
+ }
1033
+
1034
+ // packages/safe-bash-command-llm/src/fragment-loader-command.ts
1035
+ async function fragmentLoaderCommand(tokens, loaders, output, diagnostic, step, discover) {
1036
+ const parsed = await commandArguments("fragments loaders", tokens, [], output, diagnostic, step);
1037
+ if (typeof parsed === "number") return parsed;
1135
1038
  let found = false;
1136
- for (const [prefix, loader] of loaders) {
1039
+ for (const [prefix, loader] of discover ? await discover() : loaders) {
1137
1040
  if (found) await output("\n");
1138
1041
  found = true;
1139
1042
  await output(`${prefix}:
1140
1043
  `);
1141
- const lines = (loader.description || "Undocumented").split("\n");
1142
- let common;
1143
- for (const line of lines) {
1144
- if (!line.trim()) continue;
1145
- let width = 0;
1146
- while (line[width] === " " || line[width] === " ") width++;
1147
- const indent = line.slice(0, width);
1148
- if (common === void 0) common = indent;
1149
- else {
1150
- let i = 0;
1151
- while (i < common.length && common[i] === indent[i]) i++;
1152
- common = common.slice(0, i);
1153
- }
1154
- }
1155
- const description = lines.map((line) => line.trim() ? line.slice(common?.length ?? 0) : "").join("\n").trim();
1156
- for (const line of description.split("\n")) await output((line.trim() ? ` ${line}` : line) + "\n");
1044
+ for (const line of formatLoaderDescription(loader.description)) await output(line + "\n");
1157
1045
  }
1158
1046
  if (!found) await output("No fragment loaders found\n");
1159
1047
  return 0;
1160
1048
  }
1161
1049
 
1162
1050
  // packages/safe-bash-command-llm/src/tools-command.ts
1163
- var usage2 = "Usage: llm tools list [OPTIONS] [TOOL_DEFS]...\n";
1164
- var groupHelp = "Usage: llm tools [OPTIONS] COMMAND [ARGS]...\n\n Manage tools that can be made available to LLMs\n\nOptions:\n -h, --help Show this message and exit.\n\nCommands:\n list* List available tools that have been provided by plugins\n";
1165
- var listHelp = usage2 + "\n List available tools that have been provided by plugins\n\nOptions:\n --json Output as JSON\n --functions TEXT Python code block or file path defining functions to\n register as tools\n -h, --help Show this message and exit.\n";
1166
- function compareNames(left, right) {
1167
- let a = 0, b = 0;
1168
- while (a < left.length && b < right.length) {
1169
- const x = left.codePointAt(a), y = right.codePointAt(b);
1170
- if (x !== y) return x - y;
1171
- a += x > 65535 ? 2 : 1;
1172
- b += y > 65535 ? 2 : 1;
1173
- }
1174
- return left.length - a - (right.length - b);
1175
- }
1176
1051
  async function toolsCommand(tokens, registry, output, diagnostic, step, signal, load) {
1177
- let groupEager = false, separator = -1;
1178
- const error = async (message, withUsage = false) => {
1179
- await diagnostic(
1180
- (withUsage ? usage2 + "Try 'llm tools list --help' for help.\n\n" : "") + "Error: " + message + "\n"
1181
- );
1182
- return 2;
1183
- };
1184
- for (let index = 0; index < tokens.length; index++) {
1185
- await step();
1186
- const token = tokens[index];
1187
- if (token === "--") {
1188
- separator = index;
1189
- break;
1190
- }
1191
- if (!token.startsWith("-") || token === "-") break;
1192
- if (token.startsWith("--help=")) return error("Option '--help' does not take a value.");
1193
- if (token === "--help" || !token.startsWith("--") && token.slice(1).includes("h"))
1194
- groupEager = true;
1195
- }
1196
- if (groupEager) {
1197
- await output(groupHelp);
1198
- return 0;
1199
- }
1200
- const groupArgs = tokens.filter((_, index) => index !== separator);
1201
- const args = groupArgs[0] === "list" ? groupArgs.slice(1) : groupArgs;
1202
- const names = [];
1203
- let json = false, help2 = false, ended = false;
1204
- const functions = [];
1205
- for (let index = 0; index < args.length; index++) {
1206
- await step();
1207
- const token = args[index];
1208
- if (ended || !token.startsWith("-") || token === "-") {
1209
- names.push(token);
1210
- continue;
1211
- }
1212
- if (token === "--") {
1213
- ended = true;
1214
- continue;
1215
- }
1216
- const equals = token.indexOf("="), flag = equals < 0 ? token : token.slice(0, equals);
1217
- if (["--json", "--help"].includes(flag) && equals >= 0)
1218
- return error(`Option '${flag}' does not take a value.`);
1219
- if (token === "--json") {
1220
- json = true;
1221
- continue;
1222
- }
1223
- if (token === "--help" || token === "-h") {
1224
- help2 = true;
1225
- continue;
1226
- }
1227
- if (flag === "--functions") {
1228
- if (equals < 0 && args[++index] === void 0)
1229
- return error("Option '--functions' requires an argument.");
1230
- functions.push(equals < 0 ? args[index] : token.slice(equals + 1));
1231
- continue;
1232
- }
1233
- return error(`No such option '${flag}'.`, true);
1234
- }
1235
- if (help2) {
1236
- await output(listHelp);
1237
- return 0;
1238
- }
1052
+ const parsed = await commandArguments("tools", tokens, ["list"], output, diagnostic, step);
1053
+ if (typeof parsed === "number") return parsed;
1054
+ const names = parsed.operands, functions = parsed.values.get("--functions") ?? [], json = parsed.values.has("--json");
1239
1055
  if (functions.length && !load) {
1240
1056
  await diagnostic("Error: Python tool loading is not configured\n");
1241
1057
  return 1;
@@ -1245,13 +1061,13 @@ async function toolsCommand(tokens, registry, output, diagnostic, step, signal,
1245
1061
  try {
1246
1062
  const dynamicNames = names.filter((name) => !registry.has(name));
1247
1063
  const loaded = load && (!names.length || functions.length || dynamicNames.length) ? await load(functions, dynamicNames, !names.length || dynamicNames.length > 0) : { tools: [] };
1248
- toolboxes = [...loaded.toolboxes ?? []].sort((left, right) => compareNames(left.name, right.name));
1064
+ toolboxes = [...loaded.toolboxes ?? []].sort((left, right) => unicodeOrder(left.name, right.name));
1249
1065
  selected = new Map(names.length ? [...loaded.tools, ...selectLlmTools(registry, load ? names.filter((name) => registry.has(name)) : names)].map((tool) => [tool.name, tool]) : [...registry, ...loaded.tools.map((tool) => [tool.registryKey ?? tool.name, tool])]);
1250
1066
  } catch (failure) {
1251
1067
  await diagnostic("Error: " + (failure instanceof Error ? failure.message : String(failure)) + "\n");
1252
1068
  return 1;
1253
1069
  }
1254
- const entries = [...selected].sort(([left], [right]) => compareNames(left, right));
1070
+ const entries = [...selected].sort(([left], [right]) => unicodeOrder(left, right));
1255
1071
  if (json) {
1256
1072
  const tools = entries.map(([name, tool]) => ({
1257
1073
  name,
@@ -1316,8 +1132,9 @@ function createLlmFragmentLoaders(entries) {
1316
1132
  }
1317
1133
  return loaders;
1318
1134
  }
1319
- async function* loadLlmPluginFragments(reference, loaders, context, allowAttachments = true) {
1320
- const prefix = getLlmFragmentPrefix(reference), loader = prefix === void 0 ? void 0 : loaders.get(prefix);
1135
+ async function* loadLlmPluginFragments(reference, loaders, context, allowAttachments = true, provider) {
1136
+ context.signal.throwIfAborted();
1137
+ const prefix = getLlmFragmentPrefix(reference), loader = prefix === void 0 ? void 0 : loaders.get(prefix) ?? provider?.fragments(prefix);
1321
1138
  if (!loader) throw new Error(`Unknown fragment prefix: ${prefix ?? reference}`);
1322
1139
  const { signal } = context;
1323
1140
  let iterator, ended = false;
@@ -1352,6 +1169,7 @@ async function* loadLlmPluginFragments(reference, loaders, context, allowAttachm
1352
1169
  }
1353
1170
  } catch (error) {
1354
1171
  signal.throwIfAborted();
1172
+ if (error instanceof LlmLoaderLookupError) throw error;
1355
1173
  throw new Error(`Could not load fragment ${reference}: ${error instanceof Error ? error.message : String(error)}`);
1356
1174
  } finally {
1357
1175
  if (iterator && !ended) {
@@ -1672,78 +1490,11 @@ async function createLlmFragmentSource(options) {
1672
1490
  }
1673
1491
 
1674
1492
  // packages/safe-bash-command-llm/src/embed-models-command.ts
1675
- var groupHelp2 = "Usage: llm embed-models [OPTIONS] COMMAND [ARGS]...\n\n Manage available embedding models\n\nOptions:\n -h, --help Show this message and exit.\n\nCommands:\n list* List available embedding models\n default Show or set the default embedding model\n";
1676
1493
  async function embeddingModelsCommand(context, service, tokens, emit, diagnostic, step, maxConfigurationBytes = Infinity) {
1677
- if (tokens[0] === "--" && ["list", "default"].includes(tokens[1] ?? "")) tokens = tokens.slice(1);
1678
- const defaults = tokens[0] === "default", explicit = tokens[0] === "list" || defaults;
1679
- const command = defaults ? "default" : "list";
1680
- const usage3 = `Usage: llm embed-models ${command} [OPTIONS]${defaults ? " [MODEL]" : ""}
1681
- `;
1682
- const fail = async (message, withUsage = true) => {
1683
- await diagnostic((withUsage ? usage3 + `Try 'llm embed-models ${command} -h' for help.
1684
-
1685
- ` : "") + `Error: ${message}
1686
- `);
1687
- return 2;
1688
- };
1689
- const terminator = tokens.indexOf("--");
1690
- const groupFlags = terminator < 0 ? tokens : tokens.slice(0, terminator);
1691
- if (!explicit && groupFlags.some((token) => token === "--help" || token.startsWith("-") && !token.startsWith("--") && token.slice(1).includes("h"))) {
1692
- await emit(groupHelp2);
1693
- return 0;
1694
- }
1695
- const args = explicit ? tokens.slice(1) : tokens.filter((_, index) => index !== terminator);
1696
- const queries = [], operands = [];
1697
- let ended = false, help2 = false, remove = false;
1698
- for (let index = 0; index < args.length; index++) {
1699
- await step();
1700
- const token = args[index];
1701
- if (!ended && token === "--") {
1702
- ended = true;
1703
- continue;
1704
- }
1705
- if (ended || !token.startsWith("-") || token === "-") {
1706
- operands.push(token);
1707
- continue;
1708
- }
1709
- if (token === "--help" || token === "-h") {
1710
- help2 = true;
1711
- continue;
1712
- }
1713
- if (defaults && token === "--remove-default") {
1714
- remove = true;
1715
- continue;
1716
- }
1717
- if (!token.startsWith("--")) {
1718
- for (let cursor = 1; cursor < token.length; cursor++) {
1719
- const flag2 = "-" + token[cursor];
1720
- if (flag2 === "-h") {
1721
- help2 = true;
1722
- continue;
1723
- }
1724
- if (defaults || flag2 !== "-q") return fail(`No such option: ${flag2}`);
1725
- const value2 = token.slice(cursor + 1) || args[++index];
1726
- if (value2 === void 0) return fail(`Option '${flag2}' requires an argument.`, false);
1727
- queries.push(value2.toLowerCase());
1728
- break;
1729
- }
1730
- continue;
1731
- }
1732
- const equals = token.indexOf("=");
1733
- const flag = token.slice(0, equals < 0 ? void 0 : equals);
1734
- if (equals >= 0 && (flag === "--help" || defaults && flag === "--remove-default")) return fail(`Option '${flag}' does not take a value.`, false);
1735
- if (defaults || flag !== "--query") return fail(`No such option: ${flag}`);
1736
- const attached = equals < 0 ? void 0 : token.slice(equals + 1);
1737
- const value = attached ?? args[++index];
1738
- if (value === void 0) return fail(`Option '${flag}' requires an argument.`, false);
1739
- queries.push(value.toLowerCase());
1740
- }
1741
- if (help2) {
1742
- await emit(usage3 + (defaults ? "\n Show or set the default embedding model\n\nOptions:\n --remove-default Reset to specifying no default model\n -h, --help Show this message and exit.\n" : "\n List available embedding models\n\nOptions:\n -q, --query TEXT Search for embedding models matching these strings\n -h, --help Show this message and exit.\n"));
1743
- return 0;
1744
- }
1745
- const extra = operands.slice(defaults ? 1 : 0);
1746
- if (extra.length) return fail(`Got unexpected extra argument${extra.length === 1 ? "" : "s"} (${extra.join(" ")})`);
1494
+ const parsed = await commandArguments("embed-models", tokens, ["list", "default"], emit, diagnostic, step);
1495
+ if (typeof parsed === "number") return parsed;
1496
+ const { command, operands, values } = parsed, defaults = command === "default";
1497
+ const queries = (values.get("--query") ?? []).map((value) => value.toLowerCase()), remove = values.has("--remove-default");
1747
1498
  const configuration = createLlmConfiguration(context, maxConfigurationBytes);
1748
1499
  if (defaults) {
1749
1500
  const selected = operands[0];
@@ -1789,18 +1540,18 @@ async function embeddingModelsCommand(context, service, tokens, emit, diagnostic
1789
1540
  }
1790
1541
 
1791
1542
  // packages/safe-bash-command-llm/src/usage.ts
1792
- async function* serializeLlmTokenUsage(usage3, signal) {
1543
+ async function* serializeLlmTokenUsage(usage, signal) {
1793
1544
  signal.throwIfAborted();
1794
1545
  const encoder = new TextEncoder();
1795
1546
  let separator = "";
1796
1547
  for (const name of ["input", "output"]) {
1797
- const value = usage3?.[name];
1548
+ const value = usage?.[name];
1798
1549
  if (value === void 0 || value === null) continue;
1799
1550
  if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(`Invalid LLM ${name} token count`);
1800
1551
  yield encoder.encode(`${separator}${value.toLocaleString("en-US", { maximumFractionDigits: 20 })} ${name}`);
1801
1552
  separator = ", ";
1802
1553
  }
1803
- const details = usage3?.details;
1554
+ const details = usage?.details;
1804
1555
  if (!details || typeof details !== "object") return;
1805
1556
  let nonempty = false;
1806
1557
  for (const key in details) if (Object.hasOwn(details, key)) {
@@ -1864,16 +1615,6 @@ import { pathOf as pathOf3 } from "../../safe-bash-contracts/path.js";
1864
1615
  // packages/safe-bash-command-llm/src/templates.ts
1865
1616
  import { FsError as FsError4 } from "../../safe-bash-contracts/index.js";
1866
1617
  import { pathOf } from "../../safe-bash-contracts/path.js";
1867
- function unicodeOrder(left, right) {
1868
- let a = 0, b = 0;
1869
- while (a < left.length && b < right.length) {
1870
- const x = left.codePointAt(a), y = right.codePointAt(b);
1871
- if (x !== y) return x - y;
1872
- a += x > 65535 ? 2 : 1;
1873
- b += y > 65535 ? 2 : 1;
1874
- }
1875
- return (a < left.length ? 1 : 0) - (b < right.length ? 1 : 0);
1876
- }
1877
1618
  var templateFields = ["name", "prompt", "system", "model", "defaults", "options", "attachments", "attachment_types", "extract", "extract_last", "schema_object", "fragments", "system_fragments", "tools", "functions"];
1878
1619
  function template(value, name) {
1879
1620
  if (typeof value === "string") return { name, prompt: value };
@@ -1960,30 +1701,6 @@ function evaluateLlmTemplate(value, input, params, admitText) {
1960
1701
  if (!value.prompt) admitText?.(input);
1961
1702
  return { prompt: value.prompt ? interpolate(value.prompt, variables, false, admitText) : input, ...value.system === void 0 ? {} : { system: interpolate(value.system, variables, false, admitText) } };
1962
1703
  }
1963
- function abortLoader(start, signal, late) {
1964
- signal.throwIfAborted();
1965
- return new Promise((resolve, reject) => {
1966
- const abort = () => {
1967
- signal.removeEventListener("abort", abort);
1968
- reject(signal.reason);
1969
- };
1970
- signal.addEventListener("abort", abort, { once: true });
1971
- Promise.resolve().then(() => {
1972
- signal.throwIfAborted();
1973
- return start();
1974
- }).then((value) => {
1975
- signal.removeEventListener("abort", abort);
1976
- if (signal.aborted) {
1977
- if (late) void Promise.resolve().then(() => late(value)).catch(() => void 0);
1978
- reject(signal.reason);
1979
- } else resolve(value);
1980
- }, (error) => {
1981
- signal.removeEventListener("abort", abort);
1982
- reject(signal.aborted ? signal.reason : error);
1983
- });
1984
- if (signal.aborted) abort();
1985
- });
1986
- }
1987
1704
  function createLlmTemplateStore(context, loaders) {
1988
1705
  const directory = `${createLlmConfiguration(context).directory}/templates`;
1989
1706
  const filename = (name) => {
@@ -2005,7 +1722,7 @@ function createLlmTemplateStore(context, loaders) {
2005
1722
  });
2006
1723
  };
2007
1724
  try {
2008
- response = await abortLoader(() => fetch(name, { signal: context.signal }), context.signal, async (response2) => {
1725
+ response = await waitForSource(() => fetch(name, { signal: context.signal }), context.signal, async (response2) => {
2009
1726
  await response2.body?.cancel();
2010
1727
  });
2011
1728
  if (!response.ok) {
@@ -2021,7 +1738,7 @@ For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/St
2021
1738
  let total = 0;
2022
1739
  while (reader) {
2023
1740
  context.signal.throwIfAborted();
2024
- const next = await abortLoader(() => reader.read(), context.signal);
1741
+ const next = await waitForSource(() => reader.read(), context.signal);
2025
1742
  context.signal.throwIfAborted();
2026
1743
  if (next.done) break;
2027
1744
  total += next.value.byteLength;
@@ -2068,34 +1785,27 @@ For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/St
2068
1785
  await context.fs.stat(path, { signal: context.signal });
2069
1786
  } catch (error) {
2070
1787
  if (!(error instanceof FsError4) || error.code !== "ENOENT") throw error;
2071
- const colon = name.indexOf(":");
2072
- if (colon > 0) {
2073
- const prefix = name.slice(0, colon);
2074
- let valid = true;
2075
- for (const letter of prefix) if (!"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-".includes(letter)) {
2076
- valid = false;
2077
- break;
2078
- }
2079
- if (valid) {
2080
- const loader = loaders?.loaders?.get(prefix);
2081
- if (!loader) throw new Error(`Unknown template prefix: ${prefix}`);
2082
- try {
2083
- const loaded = await abortLoader(() => loader(name.slice(colon + 1), context.signal), context.signal);
2084
- context.signal.throwIfAborted();
2085
- const materializedLimit = loaders?.maxBytes ?? Infinity;
2086
- let loadedBytes = 0;
2087
- if (loaders?.admitBytes || materializedLimit !== Infinity) for await (const bytes2 of jsonValue(loaded, context.signal)) {
2088
- loadedBytes += bytes2.byteLength;
2089
- if (loadedBytes > materializedLimit) throw new FsError4("EFBIG", { message: "llm buffered input byte limit exceeded" });
2090
- loaders?.admitBytes?.(bytes2.byteLength);
2091
- }
2092
- const value = template(loaded, loaded.name);
2093
- Object.defineProperty(value, "functionsTrusted", { value: false });
2094
- return value;
2095
- } catch (error2) {
2096
- context.signal.throwIfAborted();
2097
- throw new Error(`Could not load template ${name}: ${error2 instanceof Error ? error2.message : String(error2)}`);
1788
+ const prefix = getLlmFragmentPrefix(name);
1789
+ if (prefix !== void 0) {
1790
+ const loader = loaders?.loaders?.get(prefix) ?? loaders?.provider?.templates(prefix);
1791
+ if (!loader) throw new Error(`Unknown template prefix: ${prefix}`);
1792
+ try {
1793
+ const materializedLimit = loaders?.maxBytes ?? Infinity;
1794
+ const loaded = await waitForSource(() => loader(name.slice(prefix.length + 1), context.signal, { ...context, maxBytes: materializedLimit }), context.signal);
1795
+ context.signal.throwIfAborted();
1796
+ let loadedBytes = 0;
1797
+ if (loaders?.admitBytes || materializedLimit !== Infinity) for await (const bytes2 of jsonValue(loaded, context.signal)) {
1798
+ loadedBytes += bytes2.byteLength;
1799
+ if (loadedBytes > materializedLimit) throw new FsError4("EFBIG", { message: "llm buffered input byte limit exceeded" });
1800
+ loaders?.admitBytes?.(bytes2.byteLength);
2098
1801
  }
1802
+ const value = template(loaded, loaded.name);
1803
+ Object.defineProperty(value, "functionsTrusted", { value: false });
1804
+ return value;
1805
+ } catch (error2) {
1806
+ context.signal.throwIfAborted();
1807
+ if (error2 instanceof LlmLoaderLookupError) throw error2;
1808
+ throw new Error(`Could not load template ${name}: ${error2 instanceof Error ? error2.message : String(error2)}`);
2099
1809
  }
2100
1810
  }
2101
1811
  path = filename(name);
@@ -2131,90 +1841,18 @@ For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/St
2131
1841
  await publish(name, new TextEncoder().encode(stringify(value, { indent: 4, lineWidth: 0 })));
2132
1842
  },
2133
1843
  async command(args, output, diagnostic) {
2134
- const actions = ["list", "edit", "loaders", "path", "show"];
2135
- const grouped = args.length === 1 && ["--help", "-h"].includes(args[0]);
2136
- const routed = args[0] === "--" ? args.slice(1) : args;
2137
- const explicit = actions.includes(routed[0] ?? "");
2138
- const command = explicit ? routed[0] : "list";
2139
- const tokens = explicit ? routed.slice(1) : routed;
2140
- const descriptions = {
2141
- list: "List available prompt templates",
2142
- edit: "Edit the specified prompt template using the default $EDITOR",
2143
- loaders: "Show template loaders registered by plugins",
2144
- path: "Output the path to the templates directory",
2145
- show: "Show the specified prompt template"
2146
- };
2147
- const usage3 = `Usage: llm templates ${command} [OPTIONS]${["show", "edit"].includes(command) ? " NAME" : ""}
2148
- `;
2149
- if (grouped) {
2150
- await output("Usage: llm templates [OPTIONS] COMMAND [ARGS]...\n\n Manage stored prompt templates\n\nOptions:\n -h, --help Show this message and exit.\n\nCommands:\n list* List available prompt templates\n edit Edit the specified prompt template using the default $EDITOR\n loaders Show template loaders registered by plugins\n path Output the path to the templates directory\n show Show the specified prompt template\n");
2151
- return 0;
2152
- }
2153
- let optionsEnded = false;
2154
- const operands = [];
2155
- let failure;
2156
- let help2 = false, showUsage = true;
2157
- for (const token of tokens) {
1844
+ const parsed = await commandArguments("templates", args, ["list", "edit", "loaders", "path", "show"], output, diagnostic, async () => {
2158
1845
  context.signal.throwIfAborted();
2159
- if (!optionsEnded && token === "--") optionsEnded = true;
2160
- else if (!optionsEnded && token === "--help") help2 = true;
2161
- else if (!optionsEnded && token.startsWith("--help=")) {
2162
- failure = "Option '--help' does not take a value.";
2163
- showUsage = false;
2164
- break;
2165
- } else if (!optionsEnded && token.startsWith("-") && !token.startsWith("--") && token !== "-") {
2166
- for (const letter of token.slice(1)) {
2167
- if (letter === "h") help2 = true;
2168
- else {
2169
- failure = `No such option: -${letter}`;
2170
- break;
2171
- }
2172
- }
2173
- if (failure) break;
2174
- } else if (!optionsEnded && token.startsWith("-") && token !== "-") {
2175
- failure = `No such option: ${token.split("=")[0]}`;
2176
- break;
2177
- } else operands.push(token);
2178
- }
2179
- if (help2 && !failure) {
2180
- await output(usage3 + `
2181
- ${descriptions[command]}
2182
-
2183
- Options:
2184
- -h, --help Show this message and exit.
2185
- `);
2186
- return 0;
2187
- }
2188
- const needsName = ["show", "edit"].includes(command);
2189
- failure ??= needsName && !operands.length ? "Missing argument 'NAME'." : operands.length > (needsName ? 1 : 0) ? `Got unexpected extra argument (${operands[needsName ? 1 : 0]})` : void 0;
2190
- if (failure) {
2191
- await diagnostic((showUsage ? usage3 + `Try 'llm templates ${command} -h' for help.
2192
-
2193
- ` : "") + `Error: ${failure}
2194
- `);
2195
- return 2;
2196
- }
1846
+ });
1847
+ if (typeof parsed === "number") return parsed;
1848
+ const { command, operands } = parsed;
2197
1849
  const name = operands[0];
2198
1850
  if (command === "loaders") {
2199
- if (!loaders?.loaders?.size) await output("No template loaders found\n");
2200
- else for (const [prefix, loader] of loaders.loaders) {
1851
+ const registered = await discoverLlmLoaders(loaders?.loaders, { ...context, kind: "templates", maxBytes: loaders?.maxBytes ?? Infinity, admitBytes: loaders?.admitBytes }, loaders?.provider);
1852
+ if (!registered.size) await output("No template loaders found\n");
1853
+ else for (const [prefix, loader] of registered) {
2201
1854
  context.signal.throwIfAborted();
2202
- const lines = (loader.description || "Undocumented").split("\n");
2203
- let margin;
2204
- for (const line of lines) {
2205
- if (!line.trim()) continue;
2206
- let length = 0;
2207
- while (length < line.length && (line[length] === " " || line[length] === " ")) length++;
2208
- const leading = line.slice(0, length);
2209
- if (margin === void 0) margin = leading;
2210
- else {
2211
- let common = 0;
2212
- while (common < margin.length && common < leading.length && margin[common] === leading[common]) common++;
2213
- margin = margin.slice(0, common);
2214
- }
2215
- }
2216
- const docs = lines.map((line) => line.trim() ? line.slice(margin?.length ?? 0) : "").join("\n").trim();
2217
- await output(prefix + ":\n" + docs.split("\n").map((line) => line.trim() ? " " + line : line).join("\n") + "\n");
1855
+ await output(prefix + ":\n" + formatLoaderDescription(loader.description).join("\n") + "\n");
2218
1856
  }
2219
1857
  return 0;
2220
1858
  }
@@ -2474,25 +2112,48 @@ async function resolveLlmSchemaInput(context, input, options) {
2474
2112
  }
2475
2113
 
2476
2114
  // packages/safe-bash-command-llm/src/configuration-command.ts
2477
- async function configurationCommand(context, service, args, output, diagnostic, admitInput, maxConfigurationBytes = Infinity) {
2478
- if (args.length === 1 && args[0] === "--version") {
2479
- await output("llm, version 0.27.1\n");
2480
- return true;
2481
- }
2115
+ async function configurationCommand(context, service, args, output, diagnostic, admitInput, maxConfigurationBytes = Infinity, step = async () => {
2116
+ context.signal.throwIfAborted();
2117
+ }) {
2482
2118
  const keysCmd = args[0] === "keys";
2483
2119
  const aliases = args[0] === "aliases";
2484
2120
  const defaults = args[0] === "models" && args[1] === "default";
2485
- const options = args[0] === "models" && args[1] === "options";
2486
- if (!keysCmd && !aliases && !defaults && !options) return false;
2121
+ const group = args.slice(0, keysCmd || aliases ? 1 : 2).join(" ");
2122
+ const parsed = await commandArguments(group, args.slice(keysCmd || aliases ? 1 : 2), defaults ? [] : keysCmd ? ["list", "path", "get", "set"] : aliases ? ["list", "path", "set", "remove"] : ["list", "set", "show", "clear"], output, diagnostic, step, async () => {
2123
+ const decoder = new TextDecoder();
2124
+ let value = "";
2125
+ await output("Enter key: ");
2126
+ const source = context.stdinInput ? { [Symbol.asyncIterator]: () => ({ next: () => context.stdinInput.read(1, context.signal) }) } : context.stdin;
2127
+ for await (const bytes of sourceBytes(source, context.signal)) {
2128
+ await step();
2129
+ for (let offset = 0; offset < bytes.length; ) {
2130
+ const newline = bytes.indexOf(10, offset), end = newline < 0 ? bytes.length : newline;
2131
+ admitInput(end - offset + (newline < 0 ? 0 : 1), true);
2132
+ value += decoder.decode(bytes.subarray(offset, end), { stream: true });
2133
+ if (newline < 0) break;
2134
+ value += decoder.decode();
2135
+ if (value.endsWith("\r")) value = value.slice(0, -1);
2136
+ await output("\n");
2137
+ if (value) return value;
2138
+ await output("Enter key: ");
2139
+ offset = newline + 1;
2140
+ }
2141
+ }
2142
+ await output("\n");
2143
+ return value + decoder.decode() || void 0;
2144
+ });
2145
+ if (typeof parsed === "number") return parsed;
2146
+ const { command, operands, values: flags } = parsed;
2147
+ const tokens = [command, ...operands];
2487
2148
  const configuration = createLlmConfiguration(context, maxConfigurationBytes);
2488
2149
  if (keysCmd) {
2489
- const tokens2 = args.slice(1), sub = tokens2[0];
2490
- if (sub === "path" && tokens2.length === 1) {
2150
+ const sub = command;
2151
+ if (sub === "path") {
2491
2152
  await output(`${configuration.directory}/keys.json
2492
2153
  `);
2493
- return true;
2154
+ return 0;
2494
2155
  }
2495
- if (sub === void 0 || sub === "list" && tokens2.length === 1) {
2156
+ if (sub === "list") {
2496
2157
  const path = `${configuration.directory}/keys.json`;
2497
2158
  let exists = true;
2498
2159
  try {
@@ -2502,54 +2163,22 @@ async function configurationCommand(context, service, args, output, diagnostic,
2502
2163
  }
2503
2164
  if (!exists) {
2504
2165
  await output("No keys found\n");
2505
- return true;
2166
+ return 0;
2506
2167
  }
2507
2168
  const stored = await configuration.keys();
2508
2169
  for (const key of Object.keys(stored).sort()) {
2509
2170
  await output(`${key}
2510
2171
  `);
2511
2172
  }
2512
- return true;
2173
+ return 0;
2513
2174
  }
2514
- if (sub === "get" && tokens2.length === 2) {
2515
- await output(`${await configuration.getKey(tokens2[1])}
2175
+ if (sub === "get") {
2176
+ await output(`${await configuration.getKey(tokens[1])}
2516
2177
  `);
2517
- return true;
2518
- }
2519
- if (sub === "set") {
2520
- let name;
2521
- let value;
2522
- for (let i = 1; i < tokens2.length; i++) {
2523
- const token = tokens2[i];
2524
- if (token === "--value") {
2525
- if (++i >= tokens2.length) throw new Error("Option '--value' requires an argument");
2526
- value = tokens2[i];
2527
- } else if (token.startsWith("--value=")) {
2528
- value = token.slice(8);
2529
- } else if (token.startsWith("-")) {
2530
- throw new Error(`No such option: ${token}`);
2531
- } else if (name === void 0) {
2532
- name = token;
2533
- } else {
2534
- throw new Error("Unexpected extra arguments");
2535
- }
2536
- }
2537
- if (!name) throw new Error("Missing argument 'NAME'");
2538
- if (value === void 0) {
2539
- let stdinText = "";
2540
- const decoder = new TextDecoder();
2541
- for await (const chunk of context.stdin) {
2542
- context.signal.throwIfAborted();
2543
- admitInput(chunk.byteLength, true);
2544
- stdinText += decoder.decode(chunk, { stream: true });
2545
- }
2546
- stdinText += decoder.decode();
2547
- value = stdinText.replace(/\r?\n$/, "");
2548
- }
2549
- await configuration.setKey(name, value);
2550
- return true;
2178
+ return 0;
2551
2179
  }
2552
- throw new Error("Invalid keys command");
2180
+ await configuration.setKey(operands[0], flags.get("--value").at(-1));
2181
+ return 0;
2553
2182
  }
2554
2183
  const canonical = async (model) => {
2555
2184
  const resolved = await configuration.resolveAlias(model);
@@ -2559,34 +2188,20 @@ async function configurationCommand(context, service, args, output, diagnostic,
2559
2188
  return resolved;
2560
2189
  }
2561
2190
  };
2562
- const tokens = args.slice(aliases ? 1 : 2), command = tokens[0];
2563
2191
  if (defaults) {
2564
- if (tokens.length > 1) throw new Error("Unexpected extra arguments");
2565
- if (command === void 0) await output(`${await configuration.defaultModel() ?? service.resolve().model.id}
2192
+ if (!operands[0]) await output(`${await configuration.defaultModel() ?? service.resolve().model.id}
2566
2193
  `);
2567
2194
  else {
2568
- const model = service.resolve(await canonical(command)).model.id;
2195
+ const model = service.resolve(await canonical(operands[0])).model.id;
2569
2196
  await configuration.setDefaultModel(model);
2570
2197
  }
2571
- return true;
2198
+ return 0;
2572
2199
  }
2573
2200
  if (aliases) {
2574
- if (command === "path" && tokens.length === 1) await output(`${configuration.directory}/aliases.json
2201
+ if (command === "path") await output(`${configuration.directory}/aliases.json
2575
2202
  `);
2576
2203
  else if (command === "set") {
2577
- const operands = [], queries = [];
2578
- for (let index = 1; index < tokens.length; index++) {
2579
- const token = tokens[index];
2580
- if (token === "-q" || token === "--query") {
2581
- const query = tokens[++index];
2582
- if (query === void 0) throw new Error(`Option '${token}' requires an argument`);
2583
- queries.push(query);
2584
- } else if (token.startsWith("--query=")) queries.push(token.slice(8));
2585
- else if (token.startsWith("-q") && token.length > 2) queries.push(token.slice(2));
2586
- else if (token.startsWith("-")) throw new Error(`No such option: ${token}`);
2587
- else operands.push(token);
2588
- }
2589
- if (!operands.length || operands.length > 2) throw new Error("Invalid aliases set arguments");
2204
+ const queries = flags.get("--query") ?? [];
2590
2205
  let model = operands[1];
2591
2206
  const queried = model === void 0;
2592
2207
  if (model === void 0) {
@@ -2599,45 +2214,43 @@ async function configurationCommand(context, service, args, output, diagnostic,
2599
2214
  await configuration.setAlias(operands[0], await canonical(model));
2600
2215
  if (queried) await diagnostic(`Alias '${operands[0]}' set to model '${model}'
2601
2216
  `);
2602
- } else if (command === "remove" && tokens.length === 2) await configuration.removeAlias(tokens[1]);
2603
- else if ((command === void 0 || command === "list" || command === "--json") && tokens.slice(command === void 0 ? 0 : 1).every((token) => token === "--json")) {
2217
+ } else if (command === "remove") await configuration.removeAlias(tokens[1]);
2218
+ else {
2604
2219
  const values = {};
2605
2220
  for (const { model } of service.models) for (const alias of model.aliases ?? []) if (alias !== model.id) Object.defineProperty(values, alias, { value: model.id, enumerable: true, configurable: true, writable: true });
2606
2221
  const entries = Object.entries({ ...values, ...await configuration.aliases() });
2607
- if (tokens.includes("--json")) await output(JSON.stringify(Object.fromEntries(entries), null, 4) + "\n");
2222
+ if (flags.has("--json")) await output(JSON.stringify(Object.fromEntries(entries), null, 4) + "\n");
2608
2223
  else {
2609
2224
  const width = Math.max(0, ...entries.map(([alias]) => [...alias].length));
2610
2225
  for (const [alias, model] of entries) await output(`${alias}${" ".repeat(width - [...alias].length)} : ${model}
2611
2226
  `);
2612
2227
  }
2613
- } else throw new Error("Invalid aliases command");
2614
- return true;
2228
+ }
2229
+ return 0;
2615
2230
  }
2616
- if (command === "set" && tokens.length === 4) {
2231
+ if (command === "set") {
2617
2232
  const model = await canonical(tokens[1]);
2618
2233
  const entry = service.models.find((entry2) => entry2.model.id === model);
2619
2234
  if (entry) validateModelOptions(entry.model, { [tokens[2]]: tokens[3] });
2620
2235
  await configuration.setModelOption(model, tokens[2], tokens[3]);
2621
2236
  await diagnostic(`Set default option ${tokens[2]}=${tokens[3]} for model ${model}
2622
2237
  `);
2623
- } else if (command === "show" && tokens.length === 2) {
2238
+ } else if (command === "show") {
2624
2239
  const model = await canonical(tokens[1]), values = await configuration.modelOptions(model);
2625
2240
  if (!Object.keys(values).length) await diagnostic(`No default options set for model '${model}'.
2626
2241
  `);
2627
2242
  else for (const [key, value] of Object.entries(values)) await output(`${key}: ${value}
2628
2243
  `);
2629
- } else if (command === "clear" && (tokens.length === 2 || tokens.length === 3)) {
2244
+ } else if (command === "clear") {
2630
2245
  const model = await canonical(tokens[1]);
2631
- const keys = tokens[2] === void 0 ? Object.keys(await configuration.modelOptions(model)) : [tokens[2]];
2632
- await configuration.clearModelOption(model, tokens[2]);
2246
+ const keys = !tokens[2] ? Object.keys(await configuration.modelOptions(model)) : [tokens[2]];
2247
+ await configuration.clearModelOption(model, tokens[2] || void 0);
2633
2248
  if (keys.length === 1) await output(`Cleared option '${keys[0]}' for model ${model}
2634
2249
  `);
2635
2250
  else if (keys.length > 1) await output(`Cleared ${keys.join(", ")} options for model ${model}
2636
2251
  `);
2637
- } else if (command === "list" && tokens.length === 1 || command === void 0) {
2638
- await listOptions(configuration, output, diagnostic);
2639
- } else throw new Error("Invalid models options command");
2640
- return true;
2252
+ } else await listOptions(configuration, output, diagnostic);
2253
+ return 0;
2641
2254
  }
2642
2255
  async function listOptions(configuration, output, diagnostic) {
2643
2256
  const entries = Object.entries(await configuration.allModelOptions());
@@ -2676,10 +2289,9 @@ async function selectLlmModelByQuery(models, queries, configuredAliases = {}, si
2676
2289
  }
2677
2290
 
2678
2291
  // packages/safe-bash-command-llm/src/models-list.ts
2679
- var modelsGroupHelp = "Usage: llm models [OPTIONS] COMMAND [ARGS]...\n\n Manage available models\n\nOptions:\n -h, --help Show this message and exit.\n\nCommands:\n list* List available models\n default Show or set the default model\n options Manage default options for models\n";
2680
2292
  var LlmModelsUsageError = class extends Error {
2681
- constructor(message, usage3 = true) {
2682
- super((usage3 ? "Usage: llm models list [OPTIONS]\nTry 'llm models list -h' for help.\n\n" : "") + `Error: ${message}`);
2293
+ constructor(message, usage = true) {
2294
+ super((usage ? "Usage: llm models list [OPTIONS]\nTry 'llm models list -h' for help.\n\n" : "") + `Error: ${message}`);
2683
2295
  }
2684
2296
  };
2685
2297
  function wrapDescription(description) {
@@ -2701,11 +2313,11 @@ async function listLlmModels(context, service, tokens, emit, step, maxConfigurat
2701
2313
  const terminator = tokens.indexOf("--");
2702
2314
  const groupFlags = terminator < 0 ? tokens : tokens.slice(0, terminator);
2703
2315
  if (!explicit && groupFlags.some((token) => token === "--help" || token.startsWith("-") && !token.startsWith("--") && token.slice(1).includes("h"))) {
2704
- await emit(modelsGroupHelp);
2316
+ await emit(await loadLlmHelp("models"));
2705
2317
  return;
2706
2318
  }
2707
2319
  const queries = [], selected = [];
2708
- let schemas = false, tools = false, asyncModels = false, options = false, help2 = false, ended = false;
2320
+ let schemas = false, tools = false, asyncModels = false, options = false, help = false, ended = false;
2709
2321
  const unexpected = [];
2710
2322
  const args = explicit ? tokens.slice(1) : tokens.filter((_, index) => index !== terminator);
2711
2323
  for (let index = 0; index < args.length; index++) {
@@ -2720,7 +2332,7 @@ async function listLlmModels(context, service, tokens, emit, step, maxConfigurat
2720
2332
  continue;
2721
2333
  }
2722
2334
  if (argument === "--help" || argument === "-h") {
2723
- help2 = true;
2335
+ help = true;
2724
2336
  continue;
2725
2337
  }
2726
2338
  if (argument === "--options") {
@@ -2753,8 +2365,8 @@ async function listLlmModels(context, service, tokens, emit, step, maxConfigurat
2753
2365
  if (value === void 0) throw new LlmModelsUsageError(`Option '${flag}' requires an argument.`, false);
2754
2366
  (flag === "-q" || flag === "--query" ? queries : selected).push(value);
2755
2367
  }
2756
- if (help2) {
2757
- await emit("Usage: llm models list [OPTIONS]\n\n List available models\n\nOptions:\n --options Show options for each model, if available\n --async List async models\n --schemas List models that support schemas\n --tools List models that support tools\n -q, --query TEXT Search for models matching these strings\n -m, --model TEXT Specific model IDs\n -h, --help Show this message and exit.\n");
2368
+ if (help) {
2369
+ await emit(await loadLlmHelp("models-list"));
2758
2370
  return;
2759
2371
  }
2760
2372
  if (unexpected.length) throw new LlmModelsUsageError(`Got unexpected extra argument${unexpected.length === 1 ? "" : "s"} (${unexpected.join(" ")})`);
@@ -2814,8 +2426,42 @@ async function listLlmModels(context, service, tokens, emit, step, maxConfigurat
2814
2426
  var llmReferenceVersion = "0.27.1";
2815
2427
  var LlmPromptUsageError = class extends Error {
2816
2428
  };
2429
+ var chatUsage = "Usage: llm chat [OPTIONS]\nTry 'llm chat -h' for help.";
2430
+ function optionAliases(groups) {
2431
+ return Object.fromEntries(Object.entries(groups).flatMap(([name, flags]) => flags.split(" ").map((flag) => [flag, name])));
2432
+ }
2433
+ var promptSwitches = optionAliases({
2434
+ async: "--async",
2435
+ toolsDebug: "--td --tools-debug",
2436
+ toolsApprove: "--ta --tools-approve",
2437
+ noLog: "--no-log -n",
2438
+ extract: "-x --extract",
2439
+ extractLast: "--xl --extract-last",
2440
+ usage: "-u --usage",
2441
+ noStream: "--no-stream"
2442
+ });
2443
+ var promptValueOptions = optionAliases({
2444
+ functions: "--functions",
2445
+ toolNames: "-T --tool",
2446
+ chainLimit: "--cl --chain-limit",
2447
+ fragments: "-f --fragment",
2448
+ systemFragments: "--sf --system-fragment",
2449
+ queries: "-q --query",
2450
+ template: "-t --template",
2451
+ schema: "--schema",
2452
+ schemaMulti: "--schema-multi",
2453
+ key: "--key",
2454
+ save: "--save",
2455
+ params: "-p --param",
2456
+ model: "-m --model",
2457
+ system: "-s --system",
2458
+ options: "-o --option",
2459
+ attachmentType: "--at --attachment-type",
2460
+ attachment: "-a --attachment"
2461
+ });
2817
2462
  async function parse(length, text, step, chat = false, toolsDebugEnv) {
2818
2463
  const parsed = { toolNames: [], functions: [], chainLimit: 5, prompt: "", queries: [], fragments: [], systemFragments: [], params: {}, optionNames: [], options: /* @__PURE__ */ Object.create(null), attachments: [] };
2464
+ const usage = chat ? chatUsage : "Usage: llm prompt [OPTIONS] [PROMPT]\nTry 'llm prompt --help' for help.";
2819
2465
  const operands = [];
2820
2466
  let ended = false, chainLimit;
2821
2467
  for (let index = 0; index < length; index++) {
@@ -2833,65 +2479,51 @@ async function parse(length, text, step, chat = false, toolsDebugEnv) {
2833
2479
  for (let cursor = long ? 0 : 1; cursor < argument.length; cursor++) {
2834
2480
  await step();
2835
2481
  const flag = long ? argument.slice(0, equals < 0 ? void 0 : equals) : "-" + argument[cursor];
2482
+ if (flag === "-h" || flag === "--help") {
2483
+ if (long && equals >= 0) throw new LlmPromptUsageError(`Error: Option '${flag}' does not take a value.`);
2484
+ parsed.help = true;
2485
+ if (long) break;
2486
+ continue;
2487
+ }
2836
2488
  if (chat) {
2837
- if (flag === "-h" || flag === "--help") {
2838
- if (long && equals >= 0) throw new LlmPromptUsageError(`Error: Option '${flag}' does not take a value.`);
2839
- parsed.help = true;
2840
- if (long) break;
2841
- continue;
2842
- }
2843
2489
  if (!chatOptions.includes(flag))
2844
- throw new LlmPromptUsageError(`Usage: llm chat [OPTIONS]
2845
- Try 'llm chat -h' for help.
2490
+ throw new LlmPromptUsageError(`${usage}
2846
2491
 
2847
2492
  Error: No such option: ${flag}${await chatOptionSuggestion(flag, step)}`);
2848
2493
  }
2849
- const boolean = ["--async", "--td", "--tools-debug", "--ta", "--tools-approve", "--no-log", "-n", "-x", "--extract", "--xl", "--extract-last", "-u", "--usage", "--no-stream"].includes(flag);
2494
+ const boolean = promptSwitches[flag];
2850
2495
  if (boolean) {
2851
2496
  if (long && equals >= 0) throw new LlmPromptUsageError(`Error: Option '${flag}' does not take a value.`);
2852
- if (["-x", "--extract", "--xl", "--extract-last"].includes(flag)) {
2853
- parsed.extract = flag === "--xl" || flag === "--extract-last" ? "last" : parsed.extract ?? "first";
2497
+ if (boolean === "extract" || boolean === "extractLast") {
2498
+ parsed.extract = boolean === "extractLast" ? "last" : parsed.extract ?? "first";
2854
2499
  parsed.noStream = true;
2855
- } else if (flag === "-u" || flag === "--usage") parsed.usage = true;
2856
- else if (flag === "--no-stream") parsed.noStream = true;
2857
- else if (flag === "--async") parsed.async = true;
2858
- else if (flag === "--ta" || flag === "--tools-approve") parsed.toolsApprove = true;
2859
- else if (flag === "--td" || flag === "--tools-debug") parsed.toolsDebug = true;
2500
+ } else if (boolean !== "noLog") parsed[boolean] = true;
2860
2501
  if (long) break;
2861
2502
  continue;
2862
2503
  }
2863
- if (!["--functions", "-T", "--tool", "--cl", "--chain-limit", "-f", "--fragment", "--sf", "--system-fragment", "-q", "--query", "-m", "--model", "-s", "--system", "-o", "--option", "-a", "--attachment", "--at", "--attachment-type", "-t", "--template", "--save", "-p", "--param", "--key", "--schema", "--schema-multi"].includes(flag)) throw new Error(`Unknown option: ${flag}`);
2504
+ const option = promptValueOptions[flag];
2505
+ if (!option) throw new Error(`Unknown option: ${flag}`);
2864
2506
  const attached = long ? equals < 0 ? void 0 : argument.slice(equals + 1) : argument.slice(cursor + 1) || void 0;
2865
- const arity = ["-o", "--option", "-p", "--param", "--at", "--attachment-type"].includes(flag) ? 2 : 1;
2507
+ const arity = ["options", "params", "attachmentType"].includes(option) ? 2 : 1;
2866
2508
  if (length - index - 1 < arity - (attached === void 0 ? 0 : 1)) throw new LlmPromptUsageError(`Error: Option '${flag}' requires ${arity === 2 ? "2 arguments" : "an argument"}.`);
2867
2509
  const value = attached ?? text(++index);
2868
- if (flag === "--functions") parsed.functions.push(value);
2869
- else if (flag === "-T" || flag === "--tool") parsed.toolNames.push(value);
2870
- else if (flag === "--cl" || flag === "--chain-limit") chainLimit = value;
2871
- else if (flag === "-f" || flag === "--fragment") parsed.fragments.push(value);
2872
- else if (flag === "--sf" || flag === "--system-fragment") parsed.systemFragments.push(value);
2873
- else if (flag === "-q" || flag === "--query") parsed.queries.push(value);
2874
- else if (flag === "-t" || flag === "--template") parsed.template = value;
2875
- else if (flag === "--schema") parsed.schema = value;
2876
- else if (flag === "--schema-multi") parsed.schemaMulti = value;
2877
- else if (flag === "--key") parsed.key = value;
2878
- else if (flag === "--save") parsed.save = value;
2879
- else if (flag === "-p" || flag === "--param") Object.defineProperty(parsed.params, value, { value: text(++index), enumerable: true, configurable: true, writable: true });
2880
- else if (flag === "-m" || flag === "--model") parsed.model = value;
2881
- else if (flag === "-s" || flag === "--system") parsed.system = value;
2882
- else if (flag === "-o" || flag === "--option") {
2510
+ if (["functions", "toolNames", "fragments", "systemFragments", "queries"].includes(option))
2511
+ parsed[option].push(value);
2512
+ else if (option === "chainLimit") chainLimit = value;
2513
+ else if (option === "params") Object.defineProperty(parsed.params, value, { value: text(++index), enumerable: true, configurable: true, writable: true });
2514
+ else if (option === "options") {
2883
2515
  if (!Object.hasOwn(parsed.options, value)) parsed.optionNames.push(value);
2884
2516
  parsed.options[value] = text(++index);
2885
- } else if (flag === "--at" || flag === "--attachment-type") parsed.attachments.push({ path: value, mimeType: text(++index) });
2886
- else parsed.attachments.push({ path: value });
2517
+ } else if (option === "attachmentType") parsed.attachments.push({ path: value, mimeType: text(++index) });
2518
+ else if (option === "attachment") parsed.attachments.push({ path: value });
2519
+ else parsed[option] = value;
2887
2520
  break;
2888
2521
  }
2889
2522
  }
2890
2523
  if (parsed.help) return parsed;
2891
- const usage3 = chat ? "Usage: llm chat [OPTIONS]\nTry 'llm chat -h' for help." : "Usage: llm prompt [OPTIONS] [PROMPT]\nTry 'llm prompt --help' for help.";
2892
2524
  if (chainLimit !== void 0) {
2893
2525
  const integer = tokenInteger(chainLimit);
2894
- if (integer === void 0) throw new LlmPromptUsageError(`${usage3}
2526
+ if (integer === void 0) throw new LlmPromptUsageError(`${usage}
2895
2527
 
2896
2528
  Error: Invalid value for '--cl' / '--chain-limit': '${chainLimit}' is not a valid integer.`);
2897
2529
  parsed.chainLimit = BigInt(integer);
@@ -2901,19 +2533,15 @@ Error: Invalid value for '--cl' / '--chain-limit': '${chainLimit}' is not a vali
2901
2533
  if (["1", "true", "t", "yes", "y", "on"].includes(value)) parsed.toolsDebug = true;
2902
2534
  else if (!["", "0", "false", "f", "no", "n", "off"].includes(value)) {
2903
2535
  const detail = chat ? "" : " Recognized values: , 0, 1, f, false, n, no, off, on, t, true, y, yes";
2904
- throw new LlmPromptUsageError(`${usage3}
2536
+ throw new LlmPromptUsageError(`${usage}
2905
2537
 
2906
2538
  Error: Invalid value for '--td' / '--tools-debug': '${raw}' is not a valid boolean.${detail}`);
2907
2539
  }
2908
2540
  }
2909
- if (chat && operands.length) throw new LlmPromptUsageError(`Usage: llm chat [OPTIONS]
2910
- Try 'llm chat -h' for help.
2911
-
2912
- Error: Got unexpected extra argument${operands.length === 1 ? "" : "s"} (${operands.join(" ")})`);
2913
- if (operands.length > 1) throw new LlmPromptUsageError(`Usage: llm prompt [OPTIONS] [PROMPT]
2914
- Try 'llm prompt --help' for help.
2541
+ const unexpected = chat ? operands : operands.slice(1);
2542
+ if (unexpected.length) throw new LlmPromptUsageError(`${usage}
2915
2543
 
2916
- Error: Got unexpected extra argument${operands.length === 2 ? "" : "s"} (${operands.slice(1).join(" ")})`);
2544
+ Error: Got unexpected extra argument${unexpected.length === 1 ? "" : "s"} (${unexpected.join(" ")})`);
2917
2545
  parsed.prompt = operands[0] ?? "";
2918
2546
  parsed.promptSupplied = operands.length > 0;
2919
2547
  return parsed;
@@ -2938,7 +2566,7 @@ async function interrupted(start, signal) {
2938
2566
  );
2939
2567
  });
2940
2568
  }
2941
- async function execute(context, service, limits, templateLoaderOptions, collections, fragmentLoaders, tools, loadTools) {
2569
+ async function execute(context, service, limits, templateLoaderOptions, collections, fragmentLoaders, tools, loadTools, managePackages) {
2942
2570
  context.signal.throwIfAborted();
2943
2571
  const controller = new AbortController();
2944
2572
  const operation = createOutputOperation(context, context.stdout);
@@ -3008,19 +2636,22 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3008
2636
  };
3009
2637
  const admitBuffered = (size) => input.admit(size, true);
3010
2638
  const functionSessions = /* @__PURE__ */ new Set();
2639
+ const loaderContext = () => {
2640
+ const diagnostic = operation.child(context.stderr).output;
2641
+ return { ...context, signal, stdout: { write: (bytes) => write(bytes, true) }, stderr: { write: async (bytes) => {
2642
+ admitOutput(bytes.length);
2643
+ await writeOutput(diagnostic, bytes);
2644
+ } } };
2645
+ };
3011
2646
  const loadDefinitions = async (definitions, toolNames = [], discovery = false, pluginQuery) => {
3012
2647
  if (!loadTools) throw new Error("Python tool loading is not configured");
3013
- const diagnostic = operation.child(context.stderr).output;
3014
2648
  const loaded = await operation.acquire(async () => {
3015
2649
  const value = await loadTools({
3016
2650
  definitions,
3017
2651
  toolNames,
3018
2652
  discovery,
3019
2653
  ...pluginQuery ? { pluginQuery } : {},
3020
- context: { ...context, signal, stdout: { write: (bytes) => write(bytes, true) }, stderr: { write: async (bytes) => {
3021
- admitOutput(bytes.length);
3022
- await writeOutput(diagnostic, bytes);
3023
- } } },
2654
+ context: loaderContext(),
3024
2655
  maxInputBytes: input.remaining(true),
3025
2656
  maxOutputBytes: limits?.maxOutputBytes ?? Infinity
3026
2657
  });
@@ -3080,7 +2711,7 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3080
2711
  return { exitCode: 0 };
3081
2712
  }
3082
2713
  if (eager === "help") {
3083
- await emitText("Usage: llm [prompt] [-m MODEL] [-s SYSTEM] [-o KEY VALUE] [-a PATH] [--at PATH MIMETYPE]\n llm models\nOptions: --model, --system, --option, --attachment, -u/--usage; -- ends options\n");
2714
+ await emitText(await loadLlmHelp("root"));
3084
2715
  return { exitCode: 0 };
3085
2716
  }
3086
2717
  if (separator !== void 0) {
@@ -3090,9 +2721,17 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3090
2721
  if (argumentsValue.args.length === 2 && argumentsValue.args[0] === "models" && ["--help", "-h"].includes(argumentsValue.args[1])) {
3091
2722
  argumentText(0);
3092
2723
  argumentText(1);
3093
- await emitText(modelsGroupHelp);
2724
+ await emitText(await loadLlmHelp("models"));
3094
2725
  return { exitCode: 0 };
3095
2726
  }
2727
+ if (argumentsValue.args[0] === "install" || argumentsValue.args[0] === "uninstall") {
2728
+ const args2 = Array.from({ length: argumentsValue.args.length }, (_, index) => argumentText(index));
2729
+ if (!managePackages) {
2730
+ await writeDiagnostic2(context.stderr, "Error: Python package management is not configured\n", signal);
2731
+ return { exitCode: 1 };
2732
+ }
2733
+ return await managePackages({ args: args2, context: { ...context, signal, stdout: { write: (chunk) => write(chunk, true) }, registerCleanup: operation.registerCleanup } });
2734
+ }
3096
2735
  if (argumentsValue.args[0] === "plugins") {
3097
2736
  argumentText(0);
3098
2737
  const tokens = Array.from({ length: argumentsValue.args.length - 1 }, (_, index) => argumentText(index + 1));
@@ -3120,7 +2759,7 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3120
2759
  return { exitCode: 2 };
3121
2760
  }
3122
2761
  const tokens = Array.from({ length: argumentsValue.args.length - 2 }, (_, index) => argumentText(index + 2));
3123
- return { exitCode: await fragmentLoaderCommand(tokens, fragmentLoaders, emitText, (text) => writeDiagnostic2(context.stderr, text, signal)) };
2762
+ return { exitCode: await fragmentLoaderCommand(tokens, fragmentLoaders, emitText, (text) => writeDiagnostic2(context.stderr, text, signal), step, () => discoverLlmLoaders(fragmentLoaders, { ...loaderContext(), kind: "fragments", maxBytes: input.remaining(true), admitBytes: admitBuffered }, templateLoaderOptions.provider)) };
3124
2763
  }
3125
2764
  if (argumentsValue.args[0] === "schemas" && argumentsValue.args[1] !== "dsl") {
3126
2765
  await writeDiagnostic2(context.stderr, "Error: Stored schema history is host-owned. Use an inline schema, file, template, or 'llm schemas dsl'.\n", signal);
@@ -3128,9 +2767,9 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3128
2767
  }
3129
2768
  if (argumentsValue.args[0] === "schemas" && argumentsValue.args[1] === "dsl") {
3130
2769
  const tokens = Array.from({ length: argumentsValue.args.length - 2 }, (_, index) => argumentText(index + 2));
3131
- const usage3 = "Usage: llm schemas dsl [OPTIONS] INPUT\n";
2770
+ const usage = "Usage: llm schemas dsl [OPTIONS] INPUT\n";
3132
2771
  if (tokens.includes("--help") || tokens.includes("-h")) {
3133
- await emitText(usage3 + "\n Convert LLM's schema DSL to a JSON schema\n\n llm schema dsl 'name, age int, bio: their bio'\n\nOptions:\n --multi Wrap in an array\n -h, --help Show this message and exit.\n");
2772
+ await emitText(await loadLlmHelp("schemas-dsl"));
3134
2773
  return { exitCode: 0 };
3135
2774
  }
3136
2775
  let multi = false, optionsEnded = false;
@@ -3147,7 +2786,7 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3147
2786
  }
3148
2787
  failure ??= inputs.length === 0 ? "Missing argument 'INPUT'." : inputs.length > 1 ? `Got unexpected extra argument (${inputs[1]})` : void 0;
3149
2788
  if (failure) {
3150
- await writeDiagnostic2(context.stderr, usage3 + "Try 'llm schemas dsl -h' for help.\n\nError: " + failure + "\n", signal);
2789
+ await writeDiagnostic2(context.stderr, usage + "Try 'llm schemas dsl -h' for help.\n\nError: " + failure + "\n", signal);
3151
2790
  return { exitCode: 2 };
3152
2791
  }
3153
2792
  await emitText(JSON.stringify(parseLlmSchemaDsl(inputs[0], multi), null, 2) + "\n");
@@ -3172,17 +2811,17 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3172
2811
  if (argumentsValue.args[0] === "templates") {
3173
2812
  let exitCode = 0;
3174
2813
  try {
3175
- exitCode = await createLlmTemplateStore(context, invocationLoaders).command(Array.from({ length: argumentsValue.args.length - 1 }, (_, index) => argumentText(index + 1)), emitText, (text) => writeDiagnostic2(context.stderr, text, signal));
2814
+ exitCode = await createLlmTemplateStore(loaderContext(), invocationLoaders).command(Array.from({ length: argumentsValue.args.length - 1 }, (_, index) => argumentText(index + 1)), emitText, (text) => writeDiagnostic2(context.stderr, text, signal));
3176
2815
  } catch (error) {
3177
2816
  throw new Error(`Error: ${error instanceof Error ? error.message : "Template failed"}`);
3178
2817
  }
3179
2818
  return { exitCode };
3180
2819
  }
3181
- const configurationInvocation = argumentsValue.args[0] === "keys" || argumentsValue.args[0] === "aliases" || argumentsValue.args[0] === "models" && ["default", "options"].includes(argumentsValue.args[1] ?? "") || argumentsValue.args[0] === "--version";
2820
+ const configurationInvocation = argumentsValue.args[0] === "keys" || argumentsValue.args[0] === "aliases" || argumentsValue.args[0] === "models" && ["default", "options"].includes(argumentsValue.args[1] ?? "");
3182
2821
  if (configurationInvocation) {
3183
2822
  try {
3184
2823
  const tokens = Array.from({ length: argumentsValue.args.length }, (_, index) => argumentText(index));
3185
- if (await configurationCommand(context, service, tokens, emitText, (text) => writeDiagnostic2(context.stderr, text, signal), admitInput, limits?.maxConfigurationBytes)) return { exitCode: 0 };
2824
+ return { exitCode: await configurationCommand({ ...context, signal }, service, tokens, emitText, (text) => writeDiagnostic2(context.stderr, text, signal), admitInput, limits?.maxConfigurationBytes, step) };
3186
2825
  } catch (error) {
3187
2826
  throw new Error(`Error: ${error instanceof Error ? error.message : "Configuration failed"}`);
3188
2827
  }
@@ -3195,10 +2834,10 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3195
2834
  const promptOffset = argumentsValue.args[0] === "prompt" || isChat ? 1 : 0;
3196
2835
  let args = await parse(argumentsValue.args.length - promptOffset, (index) => argumentText(index + promptOffset), step, isChat, context.env.LLM_TOOLS_DEBUG);
3197
2836
  if (args.help) {
3198
- await emitText(chatHelp);
2837
+ await emitText(await loadLlmHelp(isChat ? "chat" : "prompt"));
3199
2838
  return { exitCode: 0 };
3200
2839
  }
3201
- const configuration = createLlmConfiguration(context, limits?.maxConfigurationBytes, invocationLoaders);
2840
+ const configuration = createLlmConfiguration(loaderContext(), limits?.maxConfigurationBytes, invocationLoaders);
3202
2841
  if (args.model === void 0 && args.queries.length) {
3203
2842
  try {
3204
2843
  args.model = (await selectLlmModelByQuery(service.models, args.queries, await configuration.aliases(), signal)).model.id;
@@ -3206,7 +2845,7 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3206
2845
  throw new Error(`Error: ${error instanceof Error ? error.message : "Model selection failed"}`);
3207
2846
  }
3208
2847
  }
3209
- const templateStore = createLlmTemplateStore(context, invocationLoaders);
2848
+ const templateStore = createLlmTemplateStore(loaderContext(), invocationLoaders);
3210
2849
  const schemaInput = args.schemaMulti ?? args.schema;
3211
2850
  let schema = schemaInput ? await resolveLlmSchemaInput({ ...context, signal }, schemaInput, {
3212
2851
  multi: Boolean(args.schemaMulti),
@@ -3250,8 +2889,7 @@ async function execute(context, service, limits, templateLoaderOptions, collecti
3250
2889
  if (!args.save && entry?.model.canStream === false) args.noStream = true;
3251
2890
  const streamed = entry !== void 0 && service.streamSources !== void 0 && entry.provider.completeSources !== void 0 && entry.model.inputSources !== false;
3252
2891
  const stagePrompt = streamed && stored === void 0 && args.save === void 0;
3253
- if (isChat && args.promptSupplied) throw new LlmPromptUsageError(`Usage: llm chat [OPTIONS]
3254
- Try 'llm chat -h' for help.
2892
+ if (isChat && args.promptSupplied) throw new LlmPromptUsageError(`${chatUsage}
3255
2893
 
3256
2894
  Error: Got unexpected extra argument (${args.prompt})`);
3257
2895
  let chatModelOptions;
@@ -3365,9 +3003,9 @@ Error: Got unexpected extra argument (${args.prompt})`);
3365
3003
  }
3366
3004
  if (getLlmFragmentPrefix(reference) !== void 0) {
3367
3005
  try {
3368
- for await (const loaded of loadLlmPluginFragments(reference, fragmentLoaders, { fs: context.fs, cwd: context.cwd, signal, capabilities: context.capabilities, get maxBytes() {
3006
+ for await (const loaded of loadLlmPluginFragments(reference, fragmentLoaders, { ...loaderContext(), get maxBytes() {
3369
3007
  return input.remaining(!streamed);
3370
- } }, !system)) {
3008
+ } }, !system, templateLoaderOptions.provider)) {
3371
3009
  const source2 = await operation.acquire(() => loaded.source, (value) => value.dispose());
3372
3010
  if (loaded.type === "text") {
3373
3011
  yield source2;
@@ -3874,10 +3512,10 @@ function createLlmCommand(options = {}) {
3874
3512
  const limits = options.limits === void 0 ? void 0 : Object.freeze({ ...options.limits });
3875
3513
  if (options.service && (options.providers !== void 0 || options.defaultModel !== void 0)) throw new TypeError("Configure providers and defaultModel on the injected LLM service");
3876
3514
  const maxRemoteBytes = options.maxRemoteTemplateBytes ?? limits?.maxInputBytes ?? Infinity;
3877
- const templateLoaderOptions = { maxRemoteBytes, ...options.templateLoaders ? { loaders: options.templateLoaders } : {} };
3515
+ const templateLoaderOptions = { maxRemoteBytes, provider: options.loaderProvider, loaders: options.templateLoaders };
3878
3516
  const service = options.service ?? createLlmService({ ...options, providers: options.providers ?? [] });
3879
3517
  const collections = options.collections;
3880
- return { name: "llm", description: "Query injected language and media models", execute: (context) => execute(context, service, limits, templateLoaderOptions, collections, options.fragmentLoaders ?? /* @__PURE__ */ new Map(), options.tools ?? /* @__PURE__ */ new Map(), options.loadTools) };
3518
+ return { name: "llm", description: "Query injected language and media models", execute: (context) => execute(context, service, limits, templateLoaderOptions, collections, options.fragmentLoaders ?? /* @__PURE__ */ new Map(), options.tools ?? /* @__PURE__ */ new Map(), options.loadTools, options.managePackages) };
3881
3519
  }
3882
3520
  function createLlmCommands(options = {}) {
3883
3521
  return [createLlmCommand(options)];
@@ -3893,6 +3531,7 @@ function llmCommands(options = {}) {
3893
3531
 
3894
3532
  export {
3895
3533
  serializeLlmTokenUsage,
3534
+ LlmLoaderLookupError,
3896
3535
  createLlmToolRegistry,
3897
3536
  selectLlmTools,
3898
3537
  LlmCancelToolCall,