@miriad-systems/nuum 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +66 -24
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -31765,6 +31765,27 @@ Please check the tool's parameter schema and try again with correct arguments.`;
31765
31765
  };
31766
31766
  };
31767
31767
  }
31768
+ function prepareMessages(messages, system, cacheSystemPrompt) {
31769
+ if (!system) {
31770
+ return { messages, system: undefined };
31771
+ }
31772
+ if (!cacheSystemPrompt) {
31773
+ return { messages, system };
31774
+ }
31775
+ const systemMessage = {
31776
+ role: "system",
31777
+ content: system,
31778
+ providerOptions: {
31779
+ anthropic: {
31780
+ cacheControl: { type: "ephemeral" }
31781
+ }
31782
+ }
31783
+ };
31784
+ return {
31785
+ messages: [systemMessage, ...messages],
31786
+ system: undefined
31787
+ };
31788
+ }
31768
31789
  function prepareTools2(tools) {
31769
31790
  if (!tools)
31770
31791
  return;
@@ -31796,37 +31817,41 @@ Please check the tool's parameter schema and try again with correct arguments.`;
31796
31817
  return prepared;
31797
31818
  }
31798
31819
  async function generate(options) {
31820
+ const { messages, system } = prepareMessages(options.messages, options.system, options.cacheSystemPrompt ?? false);
31799
31821
  log3.debug("generate", {
31800
31822
  model: options.model.modelId,
31801
- messageCount: options.messages.length,
31802
- hasTools: !!options.tools
31823
+ messageCount: messages.length,
31824
+ hasTools: !!options.tools,
31825
+ cacheSystemPrompt: options.cacheSystemPrompt ?? false
31803
31826
  });
31804
31827
  return generateText({
31805
31828
  model: options.model,
31806
- messages: options.messages,
31829
+ messages,
31807
31830
  tools: prepareTools2(options.tools),
31808
31831
  maxTokens: options.maxTokens,
31809
31832
  temperature: options.temperature,
31810
31833
  abortSignal: options.abortSignal,
31811
- system: options.system,
31834
+ system,
31812
31835
  experimental_repairToolCall: createToolCallRepairFunction()
31813
31836
  });
31814
31837
  }
31815
31838
  Provider.generate = generate;
31816
31839
  async function stream(options) {
31840
+ const { messages, system } = prepareMessages(options.messages, options.system, options.cacheSystemPrompt ?? false);
31817
31841
  log3.debug("stream", {
31818
31842
  model: options.model.modelId,
31819
- messageCount: options.messages.length,
31820
- hasTools: !!options.tools
31843
+ messageCount: messages.length,
31844
+ hasTools: !!options.tools,
31845
+ cacheSystemPrompt: options.cacheSystemPrompt ?? false
31821
31846
  });
31822
31847
  return streamText({
31823
31848
  model: options.model,
31824
- messages: options.messages,
31849
+ messages,
31825
31850
  tools: prepareTools2(options.tools),
31826
31851
  maxTokens: options.maxTokens,
31827
31852
  temperature: options.temperature,
31828
31853
  abortSignal: options.abortSignal,
31829
- system: options.system,
31854
+ system,
31830
31855
  experimental_repairToolCall: createToolCallRepairFunction()
31831
31856
  });
31832
31857
  }
@@ -34330,7 +34355,6 @@ function estimateTokens(text3) {
34330
34355
  async function buildSystemPrompt(storage) {
34331
34356
  const identity = await storage.ltm.read("identity");
34332
34357
  const behavior = await storage.ltm.read("behavior");
34333
- const present = await storage.present.get();
34334
34358
  let prompt = `You are a coding assistant with persistent memory.
34335
34359
 
34336
34360
  Your memory spans across conversations, allowing you to remember past decisions, track ongoing projects, and learn user preferences.
@@ -34350,19 +34374,6 @@ ${behavior.body}
34350
34374
 
34351
34375
  `;
34352
34376
  }
34353
- prompt += `<present_state>
34354
- <mission>${present.mission ?? "(none)"}</mission>
34355
- <status>${present.status ?? "(none)"}</status>
34356
- <tasks>
34357
- `;
34358
- for (const task of present.tasks) {
34359
- prompt += ` <task status="${task.status}">${task.content}</task>
34360
- `;
34361
- }
34362
- prompt += `</tasks>
34363
- </present_state>
34364
-
34365
- `;
34366
34377
  prompt += `You have access to tools for file operations (read, write, edit, bash, glob, grep).
34367
34378
  Use tools to accomplish tasks. Always explain what you're doing.
34368
34379
 
@@ -34664,6 +34675,21 @@ function estimateSummaryTokens(input) {
34664
34675
  }
34665
34676
  // src/agent/loop.ts
34666
34677
  var log5 = Log.create({ service: "agent-loop" });
34678
+ function addCacheMarkers(messages) {
34679
+ if (messages.length === 0)
34680
+ return messages;
34681
+ const result = [...messages];
34682
+ const startIdx = Math.max(0, messages.length - 3);
34683
+ for (let i = startIdx;i < messages.length; i++) {
34684
+ result[i] = {
34685
+ ...result[i],
34686
+ providerOptions: {
34687
+ anthropic: { cacheControl: { type: "ephemeral" } }
34688
+ }
34689
+ };
34690
+ }
34691
+ return result;
34692
+ }
34667
34693
 
34668
34694
  class AgentLoopCancelledError extends Error {
34669
34695
  constructor() {
@@ -34710,16 +34736,32 @@ async function runAgentLoop(options) {
34710
34736
  log5.info("injected mid-turn user message", { contentLength: injectedContent.length });
34711
34737
  }
34712
34738
  turnsUsed++;
34739
+ const messagesWithCache = addCacheMarkers(messages);
34713
34740
  const response = await Provider.generate({
34714
34741
  model,
34715
34742
  system: systemPrompt,
34716
- messages,
34743
+ messages: messagesWithCache,
34717
34744
  tools,
34718
34745
  maxTokens,
34719
- temperature
34746
+ temperature,
34747
+ cacheSystemPrompt: true
34720
34748
  });
34721
34749
  totalInputTokens += response.usage.promptTokens;
34722
34750
  totalOutputTokens += response.usage.completionTokens;
34751
+ const anthropicMeta = response.providerMetadata?.anthropic;
34752
+ if (anthropicMeta) {
34753
+ const cacheCreation = anthropicMeta.cacheCreationInputTokens ?? 0;
34754
+ const cacheRead = anthropicMeta.cacheReadInputTokens ?? 0;
34755
+ const uncached = response.usage.promptTokens - cacheCreation - cacheRead;
34756
+ log5.info("token usage", {
34757
+ input: response.usage.promptTokens,
34758
+ output: response.usage.completionTokens,
34759
+ cacheWrite: cacheCreation,
34760
+ cacheRead,
34761
+ uncached,
34762
+ cacheHitRate: response.usage.promptTokens > 0 ? `${Math.round(cacheRead / response.usage.promptTokens * 100)}%` : "0%"
34763
+ });
34764
+ }
34723
34765
  if (response.text) {
34724
34766
  finalText = response.text;
34725
34767
  await onText?.(response.text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miriad-systems/nuum",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "AI coding agent with continuous memory - infinite context across sessions",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,7 @@
11
11
  "src/storage/migrations"
12
12
  ],
13
13
  "scripts": {
14
- "build": "bun build ./src/cli/index.ts --outdir ./dist --target bun && sed -i '' '1s|#!/usr/bin/env node|#!/usr/bin/env bun|' ./dist/index.js",
14
+ "build": "bun build ./src/cli/index.ts --outdir ./dist --target bun && node -e \"const fs=require('fs');const f='./dist/index.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace('#!/usr/bin/env node','#!/usr/bin/env bun'))\"",
15
15
  "dev": "bun run ./src/cli/index.ts",
16
16
  "typecheck": "tsc --noEmit",
17
17
  "test": "bun test",