ideacode 1.1.2 → 1.1.4

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/context.js CHANGED
@@ -11,6 +11,9 @@ export function estimateTokens(messages, systemPrompt) {
11
11
  chars += systemPrompt.length;
12
12
  return Math.round(chars / 4);
13
13
  }
14
+ export function estimateTokensForString(str) {
15
+ return Math.round(str.length / 4);
16
+ }
14
17
  export async function compressState(apiKey, state, systemPrompt, model, options) {
15
18
  const { keepLast } = options;
16
19
  if (state.length <= keepLast)
package/dist/repl.js CHANGED
@@ -13,10 +13,10 @@ import { getModel, saveModel, saveBraveSearchApiKey, getBraveSearchApiKey } from
13
13
  import { loadConversation, saveConversation } from "./conversation.js";
14
14
  import { callApi, fetchModels } from "./api.js";
15
15
  import { getVersion, checkForUpdate } from "./version.js";
16
- import { estimateTokens, ensureUnderBudget } from "./context.js";
16
+ import { estimateTokens, estimateTokensForString, ensureUnderBudget } from "./context.js";
17
17
  import { runTool } from "./tools/index.js";
18
18
  import { COMMANDS, matchCommand, resolveCommand } from "./commands.js";
19
- import { colors, icons, separator, agentMessage, toolCallBox, toolResultLine, userPromptBox, inkColors, } from "./ui/index.js";
19
+ import { colors, icons, separator, agentMessage, toolCallBox, toolResultLine, toolResultTokenLine, userPromptBox, inkColors, } from "./ui/index.js";
20
20
  function wordStartBackward(value, cursor) {
21
21
  let i = cursor - 1;
22
22
  while (i >= 0 && /\s/.test(value[i]))
@@ -103,11 +103,14 @@ function replayMessagesToLogLines(messages) {
103
103
  const block = toolUses.find((b) => b.id === tr.tool_use_id);
104
104
  if (block?.name) {
105
105
  const firstVal = block.input && typeof block.input === "object" ? Object.values(block.input)[0] : undefined;
106
- const argPreview = String(firstVal ?? "").slice(0, 50);
107
- const ok = !(tr.content ?? "").startsWith("error:");
106
+ const argPreview = String(firstVal ?? "").slice(0, 50) || "—";
107
+ const content = tr.content ?? "";
108
+ const ok = !content.startsWith("error:");
108
109
  lines.push(toolCallBox(block.name, argPreview, ok));
109
- const preview = (tr.content ?? "").split("\n")[0]?.slice(0, 60) ?? "";
110
+ const preview = content.split("\n")[0]?.slice(0, 60) ?? "";
110
111
  lines.push(toolResultLine(preview, ok));
112
+ const tokens = estimateTokensForString(content);
113
+ lines.push(toolResultTokenLine(tokens, ok));
111
114
  }
112
115
  }
113
116
  }
@@ -116,7 +119,7 @@ function replayMessagesToLogLines(messages) {
116
119
  else if (msg.role === "assistant" && Array.isArray(msg.content)) {
117
120
  const blocks = msg.content;
118
121
  for (const block of blocks) {
119
- if (block.type === "text" && block.text) {
122
+ if (block.type === "text" && block.text?.trim()) {
120
123
  lines.push("");
121
124
  lines.push(...agentMessage(block.text).trimEnd().split("\n"));
122
125
  }
@@ -174,7 +177,8 @@ export function Repl({ apiKey, cwd, onQuit }) {
174
177
  messagesRef.current = messages;
175
178
  }, [messages]);
176
179
  useEffect(() => {
177
- if (messages.length > 0 && !hasRestoredLogRef.current) {
180
+ const loaded = loadConversation(cwd);
181
+ if (loaded.length > 0 && !hasRestoredLogRef.current) {
178
182
  hasRestoredLogRef.current = true;
179
183
  const model = getModel();
180
184
  const version = getVersion();
@@ -185,9 +189,9 @@ export function Repl({ apiKey, cwd, onQuit }) {
185
189
  colors.mutedDark(" / commands ! shell @ files · Ctrl+P palette · Ctrl+C or /q to quit"),
186
190
  "",
187
191
  ];
188
- setLogLines([...banner, ...replayMessagesToLogLines(messages)]);
192
+ setLogLines([...banner, ...replayMessagesToLogLines(loaded)]);
189
193
  }
190
- }, [messages, cwd]);
194
+ }, [cwd]);
191
195
  const saveDebounceRef = useRef(null);
192
196
  useEffect(() => {
193
197
  if (saveDebounceRef.current)
@@ -413,7 +417,7 @@ export function Repl({ apiKey, cwd, onQuit }) {
413
417
  const toolResults = [];
414
418
  for (let bi = 0; bi < contentBlocks.length; bi++) {
415
419
  const block = contentBlocks[bi];
416
- if (block.type === "text" && block.text) {
420
+ if (block.type === "text" && block.text?.trim()) {
417
421
  appendLog("");
418
422
  appendLog(agentMessage(block.text).trimEnd());
419
423
  }
@@ -421,19 +425,21 @@ export function Repl({ apiKey, cwd, onQuit }) {
421
425
  const toolName = block.name;
422
426
  const toolArgs = block.input;
423
427
  const firstVal = Object.values(toolArgs)[0];
424
- const argPreview = String(firstVal ?? "").slice(0, 50);
428
+ const argPreview = String(firstVal ?? "").slice(0, 100) || "—";
425
429
  const result = await runTool(toolName, toolArgs);
426
430
  const ok = !result.startsWith("error:");
427
431
  appendLog(toolCallBox(toolName, argPreview, ok));
428
432
  const resultLines = result.split("\n");
429
- let preview = resultLines[0]?.slice(0, 60) ?? "";
433
+ let preview = resultLines[0]?.slice(0, 80) ?? "";
430
434
  if (resultLines.length > 1)
431
435
  preview += ` ... +${resultLines.length - 1} lines`;
432
- else if (preview.length > 60)
436
+ else if (preview.length > 80)
433
437
  preview += "...";
434
438
  appendLog(toolResultLine(preview, ok));
439
+ const contentForApi = truncateToolResult(result);
440
+ const tokens = estimateTokensForString(contentForApi);
441
+ appendLog(toolResultTokenLine(tokens, ok));
435
442
  if (block.id) {
436
- const contentForApi = truncateToolResult(result);
437
443
  toolResults.push({ type: "tool_result", tool_use_id: block.id, content: contentForApi });
438
444
  }
439
445
  }
@@ -26,7 +26,7 @@ export const TOOLS = {
26
26
  grepFiles,
27
27
  ],
28
28
  bash: [
29
- "Run shell command. Prefer targeted commands (e.g. grep, head, tail with small line count); avoid tail -1000 or dumping huge output.",
29
+ "Run shell command. Use for things the other tools don't cover (e.g. running tests, installs, one-off commands, ephemeral << PY scripts, etc.). Always avoid dump outputs. Prefer read/grep/glob for file content and search; use targeted commands and avoid dumping huge output.",
30
30
  { cmd: "string" },
31
31
  runBash,
32
32
  ],
package/dist/ui/format.js CHANGED
@@ -90,6 +90,17 @@ export function toolResultLine(preview, success = true) {
90
90
  const textColor = success ? toolSubdued : colors.toolFail;
91
91
  return `${TOOL_INDENT}${TOOL_INDENT}${pipeColor(icons.pipe + " ")}${textColor(preview)}`;
92
92
  }
93
+ function formatTokenCount(n) {
94
+ if (n >= 1000)
95
+ return (n / 1000).toFixed(1).replace(/\.0$/, "") + "K";
96
+ return String(n);
97
+ }
98
+ export function toolResultTokenLine(tokens, success = true) {
99
+ const pipeColor = success ? toolSubdued : colors.toolFail;
100
+ const textColor = success ? toolSubdued : colors.toolFail;
101
+ const tokenStr = `+${formatTokenCount(tokens)} tokens`;
102
+ return `${TOOL_INDENT}${TOOL_INDENT}${pipeColor(icons.pipe + " ")}${textColor(tokenStr)}`;
103
+ }
93
104
  export function agentMessage(text) {
94
105
  const rendered = renderMarkdown(text.trim());
95
106
  return `${colors.accentPale(icons.agent)} ${rendered}`;
package/dist/ui/index.js CHANGED
@@ -1 +1 @@
1
- export { colors, icons, theme, inkColors, separator, agentMessage, toolCallBox, toolResultLine, userPromptBox, bashOutputLine, renderMarkdown, header, } from "./format.js";
1
+ export { colors, icons, theme, inkColors, separator, agentMessage, toolCallBox, toolResultLine, toolResultTokenLine, userPromptBox, bashOutputLine, renderMarkdown, header, } from "./format.js";
package/dist/version.js CHANGED
@@ -32,7 +32,7 @@ function isNewer(latest, current) {
32
32
  return false;
33
33
  }
34
34
  const UPDATE_CHECK_FILE = "last-update-check.json";
35
- const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
35
+ const CHECK_INTERVAL_MS = 60 * 60 * 1000;
36
36
  function shouldSkipCheck() {
37
37
  try {
38
38
  const file = path.join(getConfigDir(), UPDATE_CHECK_FILE);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideacode",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "CLI TUI for AI agents via OpenRouter — agentic loop, tools, markdown",
5
5
  "type": "module",
6
6
  "repository": {