llmist 17.5.0 → 17.6.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/index.d.cts CHANGED
@@ -1010,6 +1010,11 @@ interface CreateGadgetConfig<TSchema extends ZodType> {
1010
1010
  * - `N > 1` = At most N concurrent
1011
1011
  */
1012
1012
  maxConcurrent?: number;
1013
+ /**
1014
+ * If true, this gadget's results are marked sticky and survive compaction.
1015
+ * See `AbstractGadget.stickyResult` for the full contract.
1016
+ */
1017
+ stickyResult?: boolean;
1013
1018
  }
1014
1019
  /**
1015
1020
  * Creates a gadget from a function (simpler than class-based approach).
@@ -1229,6 +1234,7 @@ declare function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>):
1229
1234
  * ```
1230
1235
  */
1231
1236
  execute(params: Record<string, unknown>, ctx?: ExecutionContext): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;
1237
+ stickyResult?: boolean;
1232
1238
  throwIfAborted(ctx?: ExecutionContext): void;
1233
1239
  onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void;
1234
1240
  createLinkedAbortController(ctx?: ExecutionContext): AbortController;
@@ -3858,6 +3864,15 @@ interface GadgetExecutionResult {
3858
3864
  mediaIds?: string[];
3859
3865
  /** Stored media with paths (for CLI display) */
3860
3866
  storedMedia?: StoredMedia[];
3867
+ /**
3868
+ * If true, the message persisting this gadget result is marked sticky
3869
+ * (`metadata.sticky = true`) so compaction strategies preserve it
3870
+ * indefinitely. Use for gadgets whose output the agent needs to remember
3871
+ * for the rest of the conversation (e.g. `LoadSkill` whose body is the
3872
+ * canonical reference the agent will keep consulting). Copied from
3873
+ * `AbstractGadget.stickyResult` by the executor.
3874
+ */
3875
+ stickyResult?: boolean;
3861
3876
  }
3862
3877
  /**
3863
3878
  * Result returned by gadget execute() method.
@@ -4131,6 +4146,22 @@ declare abstract class AbstractGadget {
4131
4146
  * This is a safety floor: external config cannot weaken it.
4132
4147
  */
4133
4148
  exclusive?: boolean;
4149
+ /**
4150
+ * If true, results produced by this gadget are marked sticky on the
4151
+ * conversation (`message.metadata.sticky === true`). Compaction strategies
4152
+ * preserve sticky messages past the truncation point, so the agent retains
4153
+ * the gadget's output for the rest of the conversation rather than having
4154
+ * it dropped on the next compaction pass.
4155
+ *
4156
+ * Use for gadgets whose output is *reference material* the agent will keep
4157
+ * consulting — `LoadSkill` is the canonical example: a multi-KB skill body
4158
+ * the agent needs to remember across iterations. Don't use for routine
4159
+ * gadget outputs (file reads, computation results) — those should churn
4160
+ * normally with the conversation.
4161
+ *
4162
+ * Has no effect on agents that don't enable compaction.
4163
+ */
4164
+ stickyResult?: boolean;
4134
4165
  /**
4135
4166
  * Execute the gadget with the given parameters.
4136
4167
  * Can be synchronous or asynchronous.
@@ -4554,7 +4585,7 @@ declare class LLMMessageBuilder {
4554
4585
  * @param mediaIds - Optional IDs for the media outputs
4555
4586
  * @param storedMedia - Optional stored media info including file paths
4556
4587
  */
4557
- addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): this;
4588
+ addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): this;
4558
4589
  /**
4559
4590
  * Format parameters as Block format with JSON Pointer paths.
4560
4591
  * Uses the configured argPrefix for consistency with system prompt.
@@ -5914,7 +5945,7 @@ interface IConversationManager {
5914
5945
  * Optionally includes media outputs (images, audio, etc.) for multimodal results.
5915
5946
  * If storedMedia is provided, file paths will be included in the result message.
5916
5947
  */
5917
- addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): void;
5948
+ addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): void;
5918
5949
  /**
5919
5950
  * Gets the complete conversation history including base messages (system prompts, gadget instructions).
5920
5951
  */
@@ -7643,7 +7674,7 @@ declare class ConversationManager implements IConversationManager {
7643
7674
  constructor(baseMessages: LLMMessage[], initialMessages: LLMMessage[], options?: ConversationManagerOptions);
7644
7675
  addUserMessage(content: MessageContent): void;
7645
7676
  addAssistantMessage(content: string): void;
7646
- addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): void;
7677
+ addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): void;
7647
7678
  getMessages(): LLMMessage[];
7648
7679
  getHistoryMessages(): LLMMessage[];
7649
7680
  getBaseMessages(): LLMMessage[];
package/dist/index.d.ts CHANGED
@@ -1010,6 +1010,11 @@ interface CreateGadgetConfig<TSchema extends ZodType> {
1010
1010
  * - `N > 1` = At most N concurrent
1011
1011
  */
1012
1012
  maxConcurrent?: number;
1013
+ /**
1014
+ * If true, this gadget's results are marked sticky and survive compaction.
1015
+ * See `AbstractGadget.stickyResult` for the full contract.
1016
+ */
1017
+ stickyResult?: boolean;
1013
1018
  }
1014
1019
  /**
1015
1020
  * Creates a gadget from a function (simpler than class-based approach).
@@ -1229,6 +1234,7 @@ declare function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>):
1229
1234
  * ```
1230
1235
  */
1231
1236
  execute(params: Record<string, unknown>, ctx?: ExecutionContext): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;
1237
+ stickyResult?: boolean;
1232
1238
  throwIfAborted(ctx?: ExecutionContext): void;
1233
1239
  onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void;
1234
1240
  createLinkedAbortController(ctx?: ExecutionContext): AbortController;
@@ -3858,6 +3864,15 @@ interface GadgetExecutionResult {
3858
3864
  mediaIds?: string[];
3859
3865
  /** Stored media with paths (for CLI display) */
3860
3866
  storedMedia?: StoredMedia[];
3867
+ /**
3868
+ * If true, the message persisting this gadget result is marked sticky
3869
+ * (`metadata.sticky = true`) so compaction strategies preserve it
3870
+ * indefinitely. Use for gadgets whose output the agent needs to remember
3871
+ * for the rest of the conversation (e.g. `LoadSkill` whose body is the
3872
+ * canonical reference the agent will keep consulting). Copied from
3873
+ * `AbstractGadget.stickyResult` by the executor.
3874
+ */
3875
+ stickyResult?: boolean;
3861
3876
  }
3862
3877
  /**
3863
3878
  * Result returned by gadget execute() method.
@@ -4131,6 +4146,22 @@ declare abstract class AbstractGadget {
4131
4146
  * This is a safety floor: external config cannot weaken it.
4132
4147
  */
4133
4148
  exclusive?: boolean;
4149
+ /**
4150
+ * If true, results produced by this gadget are marked sticky on the
4151
+ * conversation (`message.metadata.sticky === true`). Compaction strategies
4152
+ * preserve sticky messages past the truncation point, so the agent retains
4153
+ * the gadget's output for the rest of the conversation rather than having
4154
+ * it dropped on the next compaction pass.
4155
+ *
4156
+ * Use for gadgets whose output is *reference material* the agent will keep
4157
+ * consulting — `LoadSkill` is the canonical example: a multi-KB skill body
4158
+ * the agent needs to remember across iterations. Don't use for routine
4159
+ * gadget outputs (file reads, computation results) — those should churn
4160
+ * normally with the conversation.
4161
+ *
4162
+ * Has no effect on agents that don't enable compaction.
4163
+ */
4164
+ stickyResult?: boolean;
4134
4165
  /**
4135
4166
  * Execute the gadget with the given parameters.
4136
4167
  * Can be synchronous or asynchronous.
@@ -4554,7 +4585,7 @@ declare class LLMMessageBuilder {
4554
4585
  * @param mediaIds - Optional IDs for the media outputs
4555
4586
  * @param storedMedia - Optional stored media info including file paths
4556
4587
  */
4557
- addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): this;
4588
+ addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): this;
4558
4589
  /**
4559
4590
  * Format parameters as Block format with JSON Pointer paths.
4560
4591
  * Uses the configured argPrefix for consistency with system prompt.
@@ -5914,7 +5945,7 @@ interface IConversationManager {
5914
5945
  * Optionally includes media outputs (images, audio, etc.) for multimodal results.
5915
5946
  * If storedMedia is provided, file paths will be included in the result message.
5916
5947
  */
5917
- addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): void;
5948
+ addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): void;
5918
5949
  /**
5919
5950
  * Gets the complete conversation history including base messages (system prompts, gadget instructions).
5920
5951
  */
@@ -7643,7 +7674,7 @@ declare class ConversationManager implements IConversationManager {
7643
7674
  constructor(baseMessages: LLMMessage[], initialMessages: LLMMessage[], options?: ConversationManagerOptions);
7644
7675
  addUserMessage(content: MessageContent): void;
7645
7676
  addAssistantMessage(content: string): void;
7646
- addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[]): void;
7677
+ addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[], storedMedia?: StoredMedia[], metadata?: Record<string, unknown>): void;
7647
7678
  getMessages(): LLMMessage[];
7648
7679
  getHistoryMessages(): LLMMessage[];
7649
7680
  getBaseMessages(): LLMMessage[];
package/dist/index.js CHANGED
@@ -81,7 +81,7 @@ import {
81
81
  toBase64,
82
82
  validateGadgetSchema,
83
83
  withErrorHandling
84
- } from "./chunk-HM7PUGPA.js";
84
+ } from "./chunk-EXFIXEGW.js";
85
85
 
86
86
  // src/core/execution-tree-aggregator.ts
87
87
  var ExecutionTreeAggregator;
@@ -1884,11 +1884,19 @@ var init_sliding_window = __esm({
1884
1884
  }
1885
1885
  const turnsToKeep = turns.slice(-preserveCount);
1886
1886
  const turnsRemoved = turns.length - preserveCount;
1887
+ const keptMessageRefs = new Set(turnsToKeep.flatMap((turn) => turn.messages));
1888
+ const stickyToPreserve = messages.filter(
1889
+ (msg) => msg.metadata?.sticky === true && !keptMessageRefs.has(msg)
1890
+ );
1887
1891
  const truncationMarker = {
1888
1892
  role: "user",
1889
1893
  content: TRUNCATION_MARKER_TEMPLATE.replace("{count}", turnsRemoved.toString())
1890
1894
  };
1891
- const compactedMessages = [truncationMarker, ...flattenTurns(turnsToKeep)];
1895
+ const compactedMessages = [
1896
+ truncationMarker,
1897
+ ...stickyToPreserve,
1898
+ ...flattenTurns(turnsToKeep)
1899
+ ];
1892
1900
  const tokensAfter = Math.ceil(
1893
1901
  compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4
1894
1902
  );
@@ -1932,7 +1940,14 @@ var init_summarization = __esm({
1932
1940
  }
1933
1941
  const turnsToSummarize = turns.slice(0, -preserveCount);
1934
1942
  const turnsToKeep = turns.slice(-preserveCount);
1935
- const conversationToSummarize = this.formatTurnsForSummary(flattenTurns(turnsToSummarize));
1943
+ const keptMessageRefs = new Set(turnsToKeep.flatMap((turn) => turn.messages));
1944
+ const stickyToPreserve = messages.filter(
1945
+ (msg) => msg.metadata?.sticky === true && !keptMessageRefs.has(msg)
1946
+ );
1947
+ const turnsToSummarizeMessages = flattenTurns(turnsToSummarize).filter(
1948
+ (msg) => msg.metadata?.sticky !== true
1949
+ );
1950
+ const conversationToSummarize = this.formatTurnsForSummary(turnsToSummarizeMessages);
1936
1951
  const summary = await this.generateSummary(conversationToSummarize, config, context);
1937
1952
  const summaryMessage = {
1938
1953
  role: "user",
@@ -1940,7 +1955,11 @@ var init_summarization = __esm({
1940
1955
  ${summary}
1941
1956
  [End of summary - conversation continues below]`
1942
1957
  };
1943
- const compactedMessages = [summaryMessage, ...flattenTurns(turnsToKeep)];
1958
+ const compactedMessages = [
1959
+ summaryMessage,
1960
+ ...stickyToPreserve,
1961
+ ...flattenTurns(turnsToKeep)
1962
+ ];
1944
1963
  const tokensAfter = Math.ceil(
1945
1964
  compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4
1946
1965
  );
@@ -2261,7 +2280,7 @@ var init_conversation_manager = __esm({
2261
2280
  addAssistantMessage(content) {
2262
2281
  this.historyBuilder.addAssistant(content);
2263
2282
  }
2264
- addGadgetCallResult(gadgetName, parameters, result, invocationId, media, mediaIds, storedMedia) {
2283
+ addGadgetCallResult(gadgetName, parameters, result, invocationId, media, mediaIds, storedMedia, metadata) {
2265
2284
  this.historyBuilder.addGadgetCallResult(
2266
2285
  gadgetName,
2267
2286
  parameters,
@@ -2269,7 +2288,8 @@ var init_conversation_manager = __esm({
2269
2288
  invocationId,
2270
2289
  media,
2271
2290
  mediaIds,
2272
- storedMedia
2291
+ storedMedia,
2292
+ metadata
2273
2293
  );
2274
2294
  }
2275
2295
  getMessages() {
@@ -2401,6 +2421,7 @@ var init_conversation_updater = __esm({
2401
2421
  for (const output of gadgetResults) {
2402
2422
  if (output.type === "gadget_result") {
2403
2423
  const gadgetResult = output.result;
2424
+ const metadata = gadgetResult.stickyResult === true && gadgetResult.error === void 0 ? { sticky: true } : void 0;
2404
2425
  this.conversation.addGadgetCallResult(
2405
2426
  gadgetResult.gadgetName,
2406
2427
  gadgetResult.parameters,
@@ -2408,7 +2429,8 @@ var init_conversation_updater = __esm({
2408
2429
  gadgetResult.invocationId,
2409
2430
  gadgetResult.media,
2410
2431
  gadgetResult.mediaIds,
2411
- gadgetResult.storedMedia
2432
+ gadgetResult.storedMedia,
2433
+ metadata
2412
2434
  );
2413
2435
  }
2414
2436
  }
@@ -3829,7 +3851,6 @@ var init_retry_orchestrator = __esm({
3829
3851
  for await (const event of processor.process(stream2)) {
3830
3852
  if (event.type === "stream_complete") {
3831
3853
  streamMetadata = event;
3832
- continue;
3833
3854
  }
3834
3855
  if (event.type === "llm_response_end") {
3835
3856
  this.tree.endLLMResponse(llmNodeId, {
@@ -4119,6 +4140,12 @@ function createLoadSkillGadget(registry) {
4119
4140
  skill: z2.enum(skillNames).describe("Name of the skill to load"),
4120
4141
  arguments: z2.string().optional().describe("Arguments for the skill (e.g., a filename, issue number, or search query)")
4121
4142
  }),
4143
+ // LoadSkill exists specifically so the agent can keep a skill body in
4144
+ // context for the rest of the task — marking its results sticky lets the
4145
+ // compaction layer preserve them past truncation. Without this the agent
4146
+ // gets the skill body once, compaction drops it, and the next iteration
4147
+ // falls back to stale training knowledge of whatever the skill covered.
4148
+ stickyResult: true,
4122
4149
  execute: async ({ skill: skillName, arguments: args }) => {
4123
4150
  const skill = registry.get(skillName);
4124
4151
  if (!skill) {
@@ -13500,7 +13527,13 @@ var init_executor = __esm({
13500
13527
  cost: totalCost,
13501
13528
  media,
13502
13529
  mediaIds,
13503
- storedMedia
13530
+ storedMedia,
13531
+ // Copy the gadget's sticky flag into the result envelope so the
13532
+ // conversation-updater can mark the persisted message sticky for
13533
+ // the compaction layer. Only set on success — errors and other
13534
+ // unsuccessful exits skip this so failed loads don't pin themselves
13535
+ // in context.
13536
+ stickyResult: gadget.stickyResult
13504
13537
  };
13505
13538
  } catch (error) {
13506
13539
  const isTaskCompletionSignal = error instanceof Error && error.name === "TaskCompletionSignal";
@@ -15689,7 +15722,7 @@ var init_agent = __esm({
15689
15722
  }
15690
15723
  const unsubscribeBridge = bridgeTreeToHooks(this.tree, this.hooks, this.logger);
15691
15724
  if (this.mcpSpecs.length > 0) {
15692
- const { setupMcpServers } = await import("./runtime-GKQ6QIQP.js");
15725
+ const { setupMcpServers } = await import("./runtime-LKTAP7X6.js");
15693
15726
  this.mcpLifecycle = await setupMcpServers({
15694
15727
  specs: this.mcpSpecs,
15695
15728
  registry: this.registry,