ideacode 1.1.0 → 1.1.2

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.js CHANGED
@@ -3,9 +3,15 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import "dotenv/config";
4
4
  import { render } from "ink";
5
5
  import { getApiKey } from "./config.js";
6
+ import { getVersion } from "./version.js";
6
7
  import { runOnboarding } from "./onboarding.js";
7
8
  import { Repl } from "./repl.js";
8
9
  async function main() {
10
+ const args = process.argv.slice(2);
11
+ if (args.includes("-v") || args.includes("--version")) {
12
+ console.log(getVersion());
13
+ process.exit(0);
14
+ }
9
15
  let apiKey = getApiKey();
10
16
  if (!apiKey) {
11
17
  await runOnboarding();
package/dist/repl.js CHANGED
@@ -12,6 +12,7 @@ const matchaGradient = gradient(["#7F9A65", "#5C4033"]);
12
12
  import { getModel, saveModel, saveBraveSearchApiKey, getBraveSearchApiKey } from "./config.js";
13
13
  import { loadConversation, saveConversation } from "./conversation.js";
14
14
  import { callApi, fetchModels } from "./api.js";
15
+ import { getVersion, checkForUpdate } from "./version.js";
15
16
  import { estimateTokens, ensureUnderBudget } from "./context.js";
16
17
  import { runTool } from "./tools/index.js";
17
18
  import { COMMANDS, matchCommand, resolveCommand } from "./commands.js";
@@ -155,10 +156,11 @@ export function Repl({ apiKey, cwd, onQuit }) {
155
156
  `;
156
157
  const [logLines, setLogLines] = useState(() => {
157
158
  const model = getModel();
159
+ const version = getVersion();
158
160
  return [
159
161
  "",
160
162
  matchaGradient(bigLogo),
161
- colors.accent(` ${model}`) + colors.dim(" · ") + colors.accentPale("OpenRouter") + colors.dim(` · ${cwd}`),
163
+ colors.accent(` ideacode v${version}`) + colors.dim(" · ") + colors.accentPale(model) + colors.dim(" · ") + colors.bold("OpenRouter") + colors.dim(` · ${cwd}`),
162
164
  colors.mutedDark(" / commands ! shell @ files · Ctrl+P palette · Ctrl+C or /q to quit"),
163
165
  "",
164
166
  ];
@@ -175,10 +177,11 @@ export function Repl({ apiKey, cwd, onQuit }) {
175
177
  if (messages.length > 0 && !hasRestoredLogRef.current) {
176
178
  hasRestoredLogRef.current = true;
177
179
  const model = getModel();
180
+ const version = getVersion();
178
181
  const banner = [
179
182
  "",
180
183
  matchaGradient(bigLogo),
181
- colors.accent(` ${model}`) + colors.dim(" · ") + colors.accentPale("OpenRouter") + colors.dim(` · ${cwd}`),
184
+ colors.accent(` ideacode v${version}`) + colors.dim(" · ") + colors.accent(model) + colors.dim(" · ") + colors.accentPale("OpenRouter") + colors.dim(` · ${cwd}`),
182
185
  colors.mutedDark(" / commands ! shell @ files · Ctrl+P palette · Ctrl+C or /q to quit"),
183
186
  "",
184
187
  ];
@@ -299,6 +302,13 @@ export function Repl({ apiKey, cwd, onQuit }) {
299
302
  lines.shift();
300
303
  setLogLines((prev) => [...prev, ...lines]);
301
304
  }, []);
305
+ useEffect(() => {
306
+ const version = getVersion();
307
+ checkForUpdate(version, (latest) => {
308
+ appendLog(colors.warn(` Update available: ideacode ${latest} (you have ${version}). Run: npm i -g ideacode`));
309
+ appendLog("");
310
+ });
311
+ }, [appendLog]);
302
312
  const braveKeyHadExistingRef = useRef(false);
303
313
  const BRAVE_KEY_PLACEHOLDER = "••••••••";
304
314
  const openBraveKeyModal = useCallback(() => {
@@ -0,0 +1,83 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { getConfigDir } from "./config.js";
5
+ const OWN_PACKAGE_JSON = (() => {
6
+ const dir = path.dirname(fileURLToPath(import.meta.url));
7
+ return path.join(dir, "..", "package.json");
8
+ })();
9
+ export function getVersion() {
10
+ try {
11
+ const raw = fs.readFileSync(OWN_PACKAGE_JSON, "utf-8");
12
+ const pkg = JSON.parse(raw);
13
+ return pkg.version ?? "0.0.0";
14
+ }
15
+ catch {
16
+ return "0.0.0";
17
+ }
18
+ }
19
+ function parseSemver(s) {
20
+ const parts = s.replace(/^v/, "").split(".").map((p) => parseInt(p, 10) || 0);
21
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
22
+ }
23
+ function isNewer(latest, current) {
24
+ const a = parseSemver(latest);
25
+ const b = parseSemver(current);
26
+ for (let i = 0; i < 3; i++) {
27
+ if (a[i] > b[i])
28
+ return true;
29
+ if (a[i] < b[i])
30
+ return false;
31
+ }
32
+ return false;
33
+ }
34
+ const UPDATE_CHECK_FILE = "last-update-check.json";
35
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
36
+ function shouldSkipCheck() {
37
+ try {
38
+ const file = path.join(getConfigDir(), UPDATE_CHECK_FILE);
39
+ const raw = fs.readFileSync(file, "utf-8");
40
+ const data = JSON.parse(raw);
41
+ const last = data.lastCheck ?? 0;
42
+ return Date.now() - last < CHECK_INTERVAL_MS;
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
48
+ function markCheckDone() {
49
+ try {
50
+ const dir = getConfigDir();
51
+ const file = path.join(dir, UPDATE_CHECK_FILE);
52
+ fs.mkdirSync(dir, { recursive: true });
53
+ fs.writeFileSync(file, JSON.stringify({ lastCheck: Date.now() }), "utf-8");
54
+ }
55
+ catch {
56
+ /* ignore */
57
+ }
58
+ }
59
+ export async function checkForUpdate(currentVersion, onNewVersion) {
60
+ if (process.env.IDEACODE_SHOW_UPDATE_NOTICE) {
61
+ onNewVersion(process.env.IDEACODE_SHOW_UPDATE_NOTICE || "99.0.0");
62
+ return;
63
+ }
64
+ if (shouldSkipCheck())
65
+ return;
66
+ try {
67
+ const res = await fetch("https://registry.npmjs.org/ideacode/latest", {
68
+ headers: { Accept: "application/json" },
69
+ });
70
+ if (!res.ok)
71
+ return;
72
+ const data = (await res.json());
73
+ const latest = data.version;
74
+ if (!latest || typeof latest !== "string")
75
+ return;
76
+ markCheckDone();
77
+ if (isNewer(latest, currentVersion))
78
+ onNewVersion(latest);
79
+ }
80
+ catch {
81
+ /* ignore */
82
+ }
83
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideacode",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "CLI TUI for AI agents via OpenRouter — agentic loop, tools, markdown",
5
5
  "type": "module",
6
6
  "repository": {