llmist 0.6.1 → 0.7.0

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/dist/cli.cjs CHANGED
@@ -31,6 +31,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
+ // src/core/constants.ts
35
+ var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
36
+ var init_constants = __esm({
37
+ "src/core/constants.ts"() {
38
+ "use strict";
39
+ GADGET_START_PREFIX = "!!!GADGET_START:";
40
+ GADGET_END_PREFIX = "!!!GADGET_END";
41
+ DEFAULT_GADGET_OUTPUT_LIMIT = true;
42
+ DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
43
+ CHARS_PER_TOKEN = 4;
44
+ FALLBACK_CONTEXT_WINDOW = 128e3;
45
+ }
46
+ });
47
+
34
48
  // src/core/model-shortcuts.ts
35
49
  function isKnownModelPattern(model) {
36
50
  const normalized = model.toLowerCase();
@@ -328,20 +342,6 @@ var init_registry = __esm({
328
342
  }
329
343
  });
330
344
 
331
- // src/core/constants.ts
332
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
333
- var init_constants = __esm({
334
- "src/core/constants.ts"() {
335
- "use strict";
336
- GADGET_START_PREFIX = "!!!GADGET_START:";
337
- GADGET_END_PREFIX = "!!!GADGET_END";
338
- DEFAULT_GADGET_OUTPUT_LIMIT = true;
339
- DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
340
- CHARS_PER_TOKEN = 4;
341
- FALLBACK_CONTEXT_WINDOW = 128e3;
342
- }
343
- });
344
-
345
345
  // src/core/prompt-config.ts
346
346
  function resolvePromptTemplate(template, defaultValue, context) {
347
347
  const resolved = template ?? defaultValue;
@@ -625,7 +625,9 @@ This content can contain:
625
625
  - Multiple paragraphs
626
626
  EOF
627
627
 
628
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.`);
628
+ The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
629
+ IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
630
+ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
629
631
  }
630
632
  return parts.join("");
631
633
  }
@@ -673,9 +675,9 @@ ${this.endPrefix}`
673
675
  if (format === "toml") {
674
676
  return Object.entries(parameters).map(([key, value]) => {
675
677
  if (typeof value === "string" && value.includes("\n")) {
676
- return `${key} = """
678
+ return `${key} = <<<EOF
677
679
  ${value}
678
- """`;
680
+ EOF`;
679
681
  }
680
682
  return `${key} = ${JSON.stringify(value)}`;
681
683
  }).join("\n");
@@ -921,6 +923,10 @@ function formatParamsAsYaml(params) {
921
923
  }
922
924
  return lines.join("\n");
923
925
  }
926
+ function formatTomlInlineTable(obj) {
927
+ const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
928
+ return `{ ${entries.join(", ")} }`;
929
+ }
924
930
  function formatTomlValue(value) {
925
931
  if (typeof value === "string") {
926
932
  if (value.includes("\n")) {
@@ -938,10 +944,17 @@ ${delimiter}`;
938
944
  return '""';
939
945
  }
940
946
  if (Array.isArray(value)) {
941
- return JSON.stringify(value);
947
+ if (value.length === 0) return "[]";
948
+ const items = value.map((item) => {
949
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
950
+ return formatTomlInlineTable(item);
951
+ }
952
+ return formatTomlValue(item);
953
+ });
954
+ return `[${items.join(", ")}]`;
942
955
  }
943
956
  if (typeof value === "object") {
944
- return JSON.stringify(value);
957
+ return formatTomlInlineTable(value);
945
958
  }
946
959
  return JSON.stringify(value);
947
960
  }
@@ -1632,7 +1645,8 @@ var init_executor = __esm({
1632
1645
  if (call.parseError || !call.parameters) {
1633
1646
  this.logger.error("Gadget parameter parse error", {
1634
1647
  gadgetName: call.gadgetName,
1635
- parseError: call.parseError
1648
+ parseError: call.parseError,
1649
+ rawParameters: call.parametersYaml
1636
1650
  });
1637
1651
  return {
1638
1652
  gadgetName: call.gadgetName,
@@ -1911,6 +1925,9 @@ function preprocessYaml(yamlStr) {
1911
1925
  }
1912
1926
  return result.join("\n");
1913
1927
  }
1928
+ function unescapeHeredocContent(content) {
1929
+ return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1930
+ }
1914
1931
  function preprocessTomlHeredoc(tomlStr) {
1915
1932
  const lines = tomlStr.split("\n");
1916
1933
  const result = [];
@@ -1936,13 +1953,13 @@ function preprocessTomlHeredoc(tomlStr) {
1936
1953
  i++;
1937
1954
  }
1938
1955
  if (bodyLines.length === 0) {
1939
- result.push(`${indent}${key} = """"""`);
1956
+ result.push(`${indent}${key} = ''''''`);
1940
1957
  } else {
1941
- result.push(`${indent}${key} = """`);
1958
+ result.push(`${indent}${key} = '''`);
1942
1959
  for (let j = 0; j < bodyLines.length - 1; j++) {
1943
- result.push(bodyLines[j]);
1960
+ result.push(unescapeHeredocContent(bodyLines[j]));
1944
1961
  }
1945
- result.push(`${bodyLines[bodyLines.length - 1]}"""`);
1962
+ result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
1946
1963
  }
1947
1964
  if (!foundClosing) {
1948
1965
  }
@@ -1953,6 +1970,14 @@ function preprocessTomlHeredoc(tomlStr) {
1953
1970
  }
1954
1971
  return result.join("\n");
1955
1972
  }
1973
+ function stripMarkdownFences(content) {
1974
+ let cleaned = content.trim();
1975
+ const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
1976
+ const closingFence = /\n?```\s*$/;
1977
+ cleaned = cleaned.replace(openingFence, "");
1978
+ cleaned = cleaned.replace(closingFence, "");
1979
+ return cleaned.trim();
1980
+ }
1956
1981
  var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1957
1982
  var init_parser = __esm({
1958
1983
  "src/gadgets/parser.ts"() {
@@ -1991,43 +2016,55 @@ var init_parser = __esm({
1991
2016
  }
1992
2017
  return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
1993
2018
  }
2019
+ /**
2020
+ * Truncate verbose parse errors to avoid context overflow.
2021
+ * Keeps first meaningful line and limits total length.
2022
+ */
2023
+ truncateParseError(error, format) {
2024
+ const message = error instanceof Error ? error.message : String(error);
2025
+ const firstLine = message.split("\n")[0];
2026
+ const maxLen = 200;
2027
+ if (firstLine.length <= maxLen) {
2028
+ return firstLine;
2029
+ }
2030
+ return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
2031
+ }
1994
2032
  /**
1995
2033
  * Parse parameter string according to configured format
1996
2034
  */
1997
2035
  parseParameters(raw) {
2036
+ const cleaned = stripMarkdownFences(raw);
1998
2037
  if (this.parameterFormat === "json") {
1999
2038
  try {
2000
- return { parameters: JSON.parse(raw) };
2039
+ return { parameters: JSON.parse(cleaned) };
2001
2040
  } catch (error) {
2002
- return { parseError: error instanceof Error ? error.message : "Failed to parse JSON" };
2041
+ return { parseError: this.truncateParseError(error, "JSON") };
2003
2042
  }
2004
2043
  }
2005
2044
  if (this.parameterFormat === "yaml") {
2006
2045
  try {
2007
- return { parameters: yaml2.load(preprocessYaml(raw)) };
2046
+ return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2008
2047
  } catch (error) {
2009
- return { parseError: error instanceof Error ? error.message : "Failed to parse YAML" };
2048
+ return { parseError: this.truncateParseError(error, "YAML") };
2010
2049
  }
2011
2050
  }
2012
2051
  if (this.parameterFormat === "toml") {
2013
2052
  try {
2014
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(raw)) };
2053
+ return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2015
2054
  } catch (error) {
2016
- return { parseError: error instanceof Error ? error.message : "Failed to parse TOML" };
2055
+ return { parseError: this.truncateParseError(error, "TOML") };
2017
2056
  }
2018
2057
  }
2019
2058
  try {
2020
- return { parameters: JSON.parse(raw) };
2059
+ return { parameters: JSON.parse(cleaned) };
2021
2060
  } catch {
2022
2061
  try {
2023
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(raw)) };
2062
+ return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2024
2063
  } catch {
2025
2064
  try {
2026
- return { parameters: yaml2.load(preprocessYaml(raw)) };
2065
+ return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2027
2066
  } catch (error) {
2028
- return {
2029
- parseError: error instanceof Error ? error.message : "Failed to parse as JSON, TOML, or YAML"
2030
- };
2067
+ return { parseError: this.truncateParseError(error, "auto") };
2031
2068
  }
2032
2069
  }
2033
2070
  }
@@ -2329,7 +2366,8 @@ var init_stream_processor = __esm({
2329
2366
  if (call.parseError) {
2330
2367
  this.logger.warn("Gadget has parse error", {
2331
2368
  gadgetName: call.gadgetName,
2332
- error: call.parseError
2369
+ error: call.parseError,
2370
+ rawParameters: call.parametersYaml
2333
2371
  });
2334
2372
  const shouldContinue = await this.checkContinueAfterError(
2335
2373
  call.parseError,
@@ -2570,6 +2608,7 @@ var init_agent = __esm({
2570
2608
  gadgetEndPrefix;
2571
2609
  onHumanInputRequired;
2572
2610
  textOnlyHandler;
2611
+ textWithGadgetsHandler;
2573
2612
  stopOnGadgetError;
2574
2613
  shouldContinueAfterError;
2575
2614
  defaultGadgetTimeoutMs;
@@ -2600,6 +2639,7 @@ var init_agent = __esm({
2600
2639
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2601
2640
  this.onHumanInputRequired = options.onHumanInputRequired;
2602
2641
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2642
+ this.textWithGadgetsHandler = options.textWithGadgetsHandler;
2603
2643
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2604
2644
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2605
2645
  this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;
@@ -2787,6 +2827,17 @@ var init_agent = __esm({
2787
2827
  }
2788
2828
  }
2789
2829
  if (result.didExecuteGadgets) {
2830
+ if (this.textWithGadgetsHandler) {
2831
+ const textContent = result.outputs.filter((output) => output.type === "text").map((output) => output.content).join("");
2832
+ if (textContent.trim()) {
2833
+ const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;
2834
+ this.conversation.addGadgetCall(
2835
+ gadgetName,
2836
+ parameterMapping(textContent),
2837
+ resultMapping ? resultMapping(textContent) : textContent
2838
+ );
2839
+ }
2840
+ }
2790
2841
  for (const output of result.outputs) {
2791
2842
  if (output.type === "gadget_result") {
2792
2843
  const gadgetResult = output.result;
@@ -2798,7 +2849,13 @@ var init_agent = __esm({
2798
2849
  }
2799
2850
  }
2800
2851
  } else {
2801
- this.conversation.addAssistantMessage(finalMessage);
2852
+ if (finalMessage.trim()) {
2853
+ this.conversation.addGadgetCall(
2854
+ "TellUser",
2855
+ { message: finalMessage, done: false, type: "info" },
2856
+ `\u2139\uFE0F ${finalMessage}`
2857
+ );
2858
+ }
2802
2859
  const shouldBreak = await this.handleTextOnlyResponse(finalMessage);
2803
2860
  if (shouldBreak) {
2804
2861
  break;
@@ -4672,6 +4729,7 @@ var AgentBuilder;
4672
4729
  var init_builder = __esm({
4673
4730
  "src/agent/builder.ts"() {
4674
4731
  "use strict";
4732
+ init_constants();
4675
4733
  init_model_shortcuts();
4676
4734
  init_registry();
4677
4735
  init_agent();
@@ -4693,6 +4751,7 @@ var init_builder = __esm({
4693
4751
  gadgetStartPrefix;
4694
4752
  gadgetEndPrefix;
4695
4753
  textOnlyHandler;
4754
+ textWithGadgetsHandler;
4696
4755
  stopOnGadgetError;
4697
4756
  shouldContinueAfterError;
4698
4757
  defaultGadgetTimeoutMs;
@@ -4955,6 +5014,30 @@ var init_builder = __esm({
4955
5014
  this.textOnlyHandler = handler;
4956
5015
  return this;
4957
5016
  }
5017
+ /**
5018
+ * Set the handler for text content that appears alongside gadget calls.
5019
+ *
5020
+ * When set, text accompanying gadget responses will be wrapped as a
5021
+ * synthetic gadget call before the actual gadget results in the
5022
+ * conversation history.
5023
+ *
5024
+ * @param handler - Configuration for wrapping text
5025
+ * @returns This builder for chaining
5026
+ *
5027
+ * @example
5028
+ * ```typescript
5029
+ * // Wrap text as TellUser gadget
5030
+ * .withTextWithGadgetsHandler({
5031
+ * gadgetName: "TellUser",
5032
+ * parameterMapping: (text) => ({ message: text, done: false, type: "info" }),
5033
+ * resultMapping: (text) => `ℹ️ ${text}`,
5034
+ * })
5035
+ * ```
5036
+ */
5037
+ withTextWithGadgetsHandler(handler) {
5038
+ this.textWithGadgetsHandler = handler;
5039
+ return this;
5040
+ }
4958
5041
  /**
4959
5042
  * Set whether to stop gadget execution on first error.
4960
5043
  *
@@ -5069,6 +5152,69 @@ var init_builder = __esm({
5069
5152
  this.gadgetOutputLimitPercent = percent;
5070
5153
  return this;
5071
5154
  }
5155
+ /**
5156
+ * Add a synthetic gadget call to the conversation history.
5157
+ *
5158
+ * This is useful for in-context learning - showing the LLM what "past self"
5159
+ * did correctly so it mimics the pattern. The call is formatted with proper
5160
+ * markers and parameter format.
5161
+ *
5162
+ * @param gadgetName - Name of the gadget
5163
+ * @param parameters - Parameters passed to the gadget
5164
+ * @param result - Result returned by the gadget
5165
+ * @returns This builder for chaining
5166
+ *
5167
+ * @example
5168
+ * ```typescript
5169
+ * .withSyntheticGadgetCall(
5170
+ * 'TellUser',
5171
+ * {
5172
+ * message: '👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands',
5173
+ * done: false,
5174
+ * type: 'info'
5175
+ * },
5176
+ * 'ℹ️ 👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands'
5177
+ * )
5178
+ * ```
5179
+ */
5180
+ withSyntheticGadgetCall(gadgetName, parameters, result) {
5181
+ const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
5182
+ const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
5183
+ const format = this.parameterFormat ?? "yaml";
5184
+ const paramStr = this.formatSyntheticParameters(parameters, format);
5185
+ this.initialMessages.push({
5186
+ role: "assistant",
5187
+ content: `${startPrefix}${gadgetName}
5188
+ ${paramStr}
5189
+ ${endPrefix}`
5190
+ });
5191
+ this.initialMessages.push({
5192
+ role: "user",
5193
+ content: `Result: ${result}`
5194
+ });
5195
+ return this;
5196
+ }
5197
+ /**
5198
+ * Format parameters for synthetic gadget calls.
5199
+ * Uses heredoc for multiline string values.
5200
+ */
5201
+ formatSyntheticParameters(parameters, format) {
5202
+ if (format === "json" || format === "auto") {
5203
+ return JSON.stringify(parameters);
5204
+ }
5205
+ return Object.entries(parameters).map(([key, value]) => {
5206
+ if (typeof value === "string" && value.includes("\n")) {
5207
+ const separator = format === "yaml" ? ":" : " =";
5208
+ return `${key}${separator} <<<EOF
5209
+ ${value}
5210
+ EOF`;
5211
+ }
5212
+ if (format === "yaml") {
5213
+ return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
5214
+ }
5215
+ return `${key} = ${JSON.stringify(value)}`;
5216
+ }).join("\n");
5217
+ }
5072
5218
  /**
5073
5219
  * Build and create the agent with the given user prompt.
5074
5220
  * Returns the Agent instance ready to run.
@@ -5111,6 +5257,7 @@ var init_builder = __esm({
5111
5257
  gadgetStartPrefix: this.gadgetStartPrefix,
5112
5258
  gadgetEndPrefix: this.gadgetEndPrefix,
5113
5259
  textOnlyHandler: this.textOnlyHandler,
5260
+ textWithGadgetsHandler: this.textWithGadgetsHandler,
5114
5261
  stopOnGadgetError: this.stopOnGadgetError,
5115
5262
  shouldContinueAfterError: this.shouldContinueAfterError,
5116
5263
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
@@ -5212,6 +5359,7 @@ var init_builder = __esm({
5212
5359
  gadgetStartPrefix: this.gadgetStartPrefix,
5213
5360
  gadgetEndPrefix: this.gadgetEndPrefix,
5214
5361
  textOnlyHandler: this.textOnlyHandler,
5362
+ textWithGadgetsHandler: this.textWithGadgetsHandler,
5215
5363
  stopOnGadgetError: this.stopOnGadgetError,
5216
5364
  shouldContinueAfterError: this.shouldContinueAfterError,
5217
5365
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
@@ -5271,7 +5419,7 @@ var import_commander3 = require("commander");
5271
5419
  // package.json
5272
5420
  var package_default = {
5273
5421
  name: "llmist",
5274
- version: "0.6.0",
5422
+ version: "0.6.2",
5275
5423
  description: "Universal TypeScript LLM client with streaming-first agent framework. Works with any model - no structured outputs or native tool calling required. Implements its own flexible grammar for function calling.",
5276
5424
  type: "module",
5277
5425
  main: "dist/index.cjs",
@@ -5419,7 +5567,7 @@ var tellUser = createGadget({
5419
5567
  name: "TellUser",
5420
5568
  description: "Tell the user something important. Set done=true when your work is complete and you want to end the conversation.",
5421
5569
  schema: import_zod2.z.object({
5422
- message: import_zod2.z.string().describe("The message to display to the user in Markdown"),
5570
+ message: import_zod2.z.string().optional().describe("The message to display to the user in Markdown"),
5423
5571
  done: import_zod2.z.boolean().default(false).describe("Set to true to end the conversation, false to continue"),
5424
5572
  type: import_zod2.z.enum(["info", "success", "warning", "error"]).default("info").describe("Message type: info, success, warning, or error")
5425
5573
  }),
@@ -5439,9 +5587,20 @@ var tellUser = createGadget({
5439
5587
  done: false,
5440
5588
  type: "warning"
5441
5589
  }
5590
+ },
5591
+ {
5592
+ comment: "Share detailed analysis with bullet points (use heredoc for multiline)",
5593
+ params: {
5594
+ message: "Here's what I found in the codebase:\n\n1. **Main entry point**: `src/index.ts` exports all public APIs\n2. **Core logic**: Located in `src/core/` with 5 modules\n3. **Tests**: Good coverage in `src/__tests__/`\n\nI'll continue exploring the core modules.",
5595
+ done: false,
5596
+ type: "info"
5597
+ }
5442
5598
  }
5443
5599
  ],
5444
5600
  execute: ({ message, done, type }) => {
5601
+ if (!message || message.trim() === "") {
5602
+ return "\u26A0\uFE0F TellUser was called without a message. Please provide content in the 'message' field.";
5603
+ }
5445
5604
  const prefixes = {
5446
5605
  info: "\u2139\uFE0F ",
5447
5606
  success: "\u2705 ",
@@ -5723,53 +5882,6 @@ ${rendered}`;
5723
5882
  }
5724
5883
 
5725
5884
  // src/cli/utils.ts
5726
- var RARE_EMOJI = [
5727
- "\u{1F531}",
5728
- "\u2697\uFE0F",
5729
- "\u{1F9FF}",
5730
- "\u{1F530}",
5731
- "\u269B\uFE0F",
5732
- "\u{1F3FA}",
5733
- "\u{1F9EB}",
5734
- "\u{1F52C}",
5735
- "\u2695\uFE0F",
5736
- "\u{1F5DD}\uFE0F",
5737
- "\u2696\uFE0F",
5738
- "\u{1F52E}",
5739
- "\u{1FAAC}",
5740
- "\u{1F9EC}",
5741
- "\u2699\uFE0F",
5742
- "\u{1F529}",
5743
- "\u{1FA9B}",
5744
- "\u26CF\uFE0F",
5745
- "\u{1FA83}",
5746
- "\u{1F3F9}",
5747
- "\u{1F6E1}\uFE0F",
5748
- "\u2694\uFE0F",
5749
- "\u{1F5E1}\uFE0F",
5750
- "\u{1FA93}",
5751
- "\u{1F5C3}\uFE0F",
5752
- "\u{1F4DC}",
5753
- "\u{1F4EF}",
5754
- "\u{1F3B4}",
5755
- "\u{1F004}",
5756
- "\u{1F3B2}"
5757
- ];
5758
- function generateMarkers() {
5759
- const pick = (count) => {
5760
- const result = [];
5761
- const pool = [...RARE_EMOJI];
5762
- for (let i = 0; i < count && pool.length > 0; i++) {
5763
- const idx = Math.floor(Math.random() * pool.length);
5764
- result.push(pool.splice(idx, 1)[0]);
5765
- }
5766
- return result.join("");
5767
- };
5768
- return {
5769
- startPrefix: pick(5),
5770
- endPrefix: pick(5)
5771
- };
5772
- }
5773
5885
  function createNumericParser({
5774
5886
  label,
5775
5887
  integer = false,
@@ -6195,6 +6307,10 @@ function configToAgentOptions(config) {
6195
6307
  if (config.builtins !== void 0) result.builtins = config.builtins;
6196
6308
  if (config["builtin-interaction"] !== void 0)
6197
6309
  result.builtinInteraction = config["builtin-interaction"];
6310
+ if (config["gadget-start-prefix"] !== void 0)
6311
+ result.gadgetStartPrefix = config["gadget-start-prefix"];
6312
+ if (config["gadget-end-prefix"] !== void 0)
6313
+ result.gadgetEndPrefix = config["gadget-end-prefix"];
6198
6314
  return result;
6199
6315
  }
6200
6316
 
@@ -6409,9 +6525,27 @@ Command rejected by user with message: "${response}"`
6409
6525
  builder.withGadgets(...gadgets);
6410
6526
  }
6411
6527
  builder.withParameterFormat(options.parameterFormat);
6412
- const markers = generateMarkers();
6413
- builder.withGadgetStartPrefix(markers.startPrefix);
6414
- builder.withGadgetEndPrefix(markers.endPrefix);
6528
+ if (options.gadgetStartPrefix) {
6529
+ builder.withGadgetStartPrefix(options.gadgetStartPrefix);
6530
+ }
6531
+ if (options.gadgetEndPrefix) {
6532
+ builder.withGadgetEndPrefix(options.gadgetEndPrefix);
6533
+ }
6534
+ builder.withSyntheticGadgetCall(
6535
+ "TellUser",
6536
+ {
6537
+ message: "\u{1F44B} Hello! I'm ready to help.\n\nHere's what I can do:\n- Analyze your codebase\n- Execute commands\n- Answer questions\n\nWhat would you like me to work on?",
6538
+ done: false,
6539
+ type: "info"
6540
+ },
6541
+ "\u2139\uFE0F \u{1F44B} Hello! I'm ready to help.\n\nHere's what I can do:\n- Analyze your codebase\n- Execute commands\n- Answer questions\n\nWhat would you like me to work on?"
6542
+ );
6543
+ builder.withTextOnlyHandler("acknowledge");
6544
+ builder.withTextWithGadgetsHandler({
6545
+ gadgetName: "TellUser",
6546
+ parameterMapping: (text) => ({ message: text, done: false, type: "info" }),
6547
+ resultMapping: (text) => `\u2139\uFE0F ${text}`
6548
+ });
6415
6549
  const agent = builder.ask(prompt);
6416
6550
  for await (const event of agent.run()) {
6417
6551
  if (event.type === "text") {
@@ -6533,7 +6667,9 @@ var AGENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
6533
6667
  "gadget",
6534
6668
  "parameter-format",
6535
6669
  "builtins",
6536
- "builtin-interaction"
6670
+ "builtin-interaction",
6671
+ "gadget-start-prefix",
6672
+ "gadget-end-prefix"
6537
6673
  ]);
6538
6674
  var CUSTOM_CONFIG_KEYS = /* @__PURE__ */ new Set([
6539
6675
  ...COMPLETE_CONFIG_KEYS,
@@ -6695,6 +6831,20 @@ function validateAgentConfig(raw, section) {
6695
6831
  section
6696
6832
  );
6697
6833
  }
6834
+ if ("gadget-start-prefix" in rawObj) {
6835
+ result["gadget-start-prefix"] = validateString(
6836
+ rawObj["gadget-start-prefix"],
6837
+ "gadget-start-prefix",
6838
+ section
6839
+ );
6840
+ }
6841
+ if ("gadget-end-prefix" in rawObj) {
6842
+ result["gadget-end-prefix"] = validateString(
6843
+ rawObj["gadget-end-prefix"],
6844
+ "gadget-end-prefix",
6845
+ section
6846
+ );
6847
+ }
6698
6848
  return result;
6699
6849
  }
6700
6850
  function validateCustomConfig(raw, section) {
@@ -6750,6 +6900,20 @@ function validateCustomConfig(raw, section) {
6750
6900
  section
6751
6901
  );
6752
6902
  }
6903
+ if ("gadget-start-prefix" in rawObj) {
6904
+ result["gadget-start-prefix"] = validateString(
6905
+ rawObj["gadget-start-prefix"],
6906
+ "gadget-start-prefix",
6907
+ section
6908
+ );
6909
+ }
6910
+ if ("gadget-end-prefix" in rawObj) {
6911
+ result["gadget-end-prefix"] = validateString(
6912
+ rawObj["gadget-end-prefix"],
6913
+ "gadget-end-prefix",
6914
+ section
6915
+ );
6916
+ }
6753
6917
  if ("max-tokens" in rawObj) {
6754
6918
  result["max-tokens"] = validateNumber(rawObj["max-tokens"], "max-tokens", section, {
6755
6919
  integer: true,