itermbot 1.0.18 → 1.0.19

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/README.md CHANGED
@@ -1,38 +1,10 @@
1
1
  # iTermBot
2
2
 
3
- ## Introduction
3
+ ## 介绍
4
4
 
5
- `apps/itermbot` is the application repo in this workspace. It runs an iTerm-focused agent on top of the BotBotGo runtime, model, memory, and tool packages.
5
+ `itermbot` 是一个运行在 iTerm2 环境中的终端智能体应用,基于 `@botbotgo/agent` 及相关框架包构建。
6
6
 
7
- ## Exposed Interfaces
8
-
9
- This repo is an app, not a reusable library. Its public interface is the executable entry:
10
-
11
- | Interface | Type | Purpose |
12
- | --- | --- | --- |
13
- | `itermbot` | CLI | Start the app from `dist/index.js`. |
14
-
15
- ## Configuration
16
-
17
- Main config files:
18
-
19
- - `config/app.yaml`
20
- - `config/agent.yaml`
21
- - `config/model.yaml`
22
- - `config/toolkit.yaml`
23
- - `config/memory.yaml`
24
- - `config/task-manager.yaml`
25
-
26
- `config/app.yaml` holds app-level behavior such as prompt templates and local startup settings. The model, memory, tool, and runtime files are delegated to the corresponding framework repos.
27
- `config/task-manager.yaml` defines the application task manager behavior and persistence file.
28
-
29
- Task manager commands in CLI:
30
-
31
- - `task list`
32
- - `task add <description>`
33
- - `task run [task-id]`
34
-
35
- ## Usage
7
+ ## 如何使用
36
8
 
37
9
  ```bash
38
10
  cd apps/itermbot
@@ -41,10 +13,27 @@ npm run build
41
13
  npm start
42
14
  ```
43
15
 
44
- Other entry modes:
16
+ 其他模式:
45
17
 
46
18
  ```bash
47
19
  npm run react
48
20
  npm run deep
49
- npm run test:llm
50
21
  ```
22
+
23
+ ## 如何设置
24
+
25
+ - Node.js >= 22
26
+ - 需在 iTerm2 内运行(依赖 `TERM_PROGRAM=iTerm.app` 或 `ITERM_SESSION_ID`)
27
+ - 主要配置文件:
28
+ - `config/app.yaml`
29
+ - `config/agent.yaml`
30
+ - `config/model.yaml`
31
+ - `config/memory.yaml`
32
+ - `config/toolkit.yaml`
33
+ - `config/task-manager.yaml`
34
+
35
+ ## 暴露 API
36
+
37
+ - 可执行命令:`itermbot`
38
+ - CLI 入口:`node dist/index.js [react|deep] [prompt]`
39
+ - npm 脚本接口:`npm run start`、`npm run react`、`npm run deep`、`npm run test:llm`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itermbot",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "iTermBot: ReAct agent (LangChain) + DeepAgent (DeepAgents) using BotBotGo packages",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,8 +10,8 @@
10
10
  "iTermbot": "dist/index.js"
11
11
  },
12
12
  "scripts": {
13
- "preinstall": "node scripts/resolve-deps.js",
14
- "prebuild": "node scripts/build-internal-deps.mjs",
13
+ "preinstall": "node -e \"const fs=require('fs'); const {execSync}=require('child_process'); if (fs.existsSync('../../scripts/run-resolve-deps.sh')) { execSync('bash ../../scripts/run-resolve-deps.sh .', { stdio: 'inherit' }); } else { console.log('Skipping workspace resolve-deps helper'); }\"",
14
+ "prebuild": "node ./scripts/run-iterm-build-internal-deps.mjs .",
15
15
  "build": "tsc -p config/tsconfig.json",
16
16
  "dev": "tsc -p config/tsconfig.json --watch",
17
17
  "start": "node dist/index.js",
@@ -22,16 +22,16 @@
22
22
  "test": "npm run typecheck && npm run build && npm run test:policy",
23
23
  "test:policy": "npm run build && node --test --test-concurrency=1 test/unit/*.test.mjs test/unit/**/*.test.mjs test/integration/*.test.mjs",
24
24
  "test:live": "npm run build && node --test --test-concurrency=1 test/integration/live-iterm-llm.integration.test.mjs",
25
- "test:llm": "node scripts/test-llm.mjs",
25
+ "test:llm": "node ../../scripts/run-iterm-test-llm.mjs .",
26
26
  "release": "semantic-release"
27
27
  },
28
28
  "dependencies": {
29
- "@botbotgo/common": "file:../../framework/common",
30
- "@botbotgo/memory": "file:../../framework/memory",
31
- "@botbotgo/model": "file:../../framework/model",
32
- "@botbotgo/agent": "file:../../framework/agent",
33
- "@botbotgo/toolkit": "file:../../framework/toolkit",
34
- "@botbotgo/toolkit-builtin": "file:../../framework/toolkit-builtin",
29
+ "@botbotgo/common": "1.0.15",
30
+ "@botbotgo/memory": "1.0.64",
31
+ "@botbotgo/model": "1.0.9",
32
+ "@botbotgo/agent": "1.1.20",
33
+ "@botbotgo/toolkit": "1.0.122",
34
+ "@botbotgo/toolkit-builtin": "0.0.114",
35
35
  "@langchain/core": "1.1.31",
36
36
  "@langchain/langgraph": "1.2.0",
37
37
  "@langchain/langgraph-checkpoint": "1.0.0",
@@ -1,49 +1,91 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
- import { dirname, resolve } from "node:path";
5
- import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
4
+ import { dirname, join, resolve } from "node:path";
5
+ import { execSync } from "node:child_process";
6
+ import { fileURLToPath } from "node:url";
6
7
 
7
8
  const DEP_SECTIONS = ["dependencies", "devDependencies", "optionalDependencies"];
9
+ const SCOPES = ["@botbotgo/", "@wallee/"];
10
+ const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "coverage"]);
8
11
 
9
- function fallbackRewriteCurrentPackage(scriptUrl) {
10
- const scriptDir = dirname(fileURLToPath(scriptUrl));
11
- const packageDir = resolve(scriptDir, "..");
12
- const packageJsonPath = resolve(packageDir, "package.json");
13
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
12
+ function readJson(path) { return JSON.parse(readFileSync(path, "utf8")); }
13
+ function writeJson(path, value) { writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`); }
14
+ function isInternalPackage(name) { return SCOPES.some((scope) => name.startsWith(scope)); }
15
+
16
+ function tryResolveLocalVersion(pkgDir, spec) {
17
+ if (!spec.startsWith("file:")) return null;
18
+ const pkgPath = resolve(pkgDir, spec.slice(5), "package.json");
19
+ if (!existsSync(pkgPath)) return null;
20
+ const parsed = readJson(pkgPath);
21
+ return typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : null;
22
+ }
23
+
24
+ function fetchPublishedVersion(name) {
25
+ try {
26
+ const raw = execSync(`npm view ${name} version --json`, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
27
+ const parsed = JSON.parse(raw);
28
+ return typeof parsed === "string" && parsed.length > 0 ? parsed : null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ function collectPackageJsonPaths(rootDir) {
35
+ const out = [];
36
+ function walk(currentDir) {
37
+ for (const entry of readdirSync(currentDir)) {
38
+ if (SKIP_DIRS.has(entry)) continue;
39
+ const abs = join(currentDir, entry);
40
+ const st = statSync(abs);
41
+ if (st.isDirectory()) {
42
+ walk(abs);
43
+ continue;
44
+ }
45
+ if (entry === "package.json") out.push(abs);
46
+ }
47
+ }
48
+ walk(rootDir);
49
+ return out.sort();
50
+ }
51
+
52
+ function rewritePackageJson(pkgPath) {
53
+ const pkg = readJson(pkgPath);
54
+ const pkgDir = dirname(pkgPath);
14
55
  let changed = false;
15
56
 
16
57
  for (const section of DEP_SECTIONS) {
17
58
  const deps = pkg[section];
18
59
  if (!deps || typeof deps !== "object") continue;
19
- for (const [name, version] of Object.entries(deps)) {
20
- if (!name.startsWith("@botbotgo/")) continue;
21
- if (typeof version !== "string" || !version.startsWith("file:")) continue;
22
- const target = resolve(packageDir, version.slice("file:".length));
23
- if (existsSync(target)) continue;
24
- deps[name] = "latest";
25
- changed = true;
26
- console.log(`[resolve-deps:fallback] ${section}.${name}: ${version} -> latest`);
60
+ for (const [name, current] of Object.entries(deps)) {
61
+ if (typeof current !== "string" || !isInternalPackage(name) || !current.startsWith("file:")) continue;
62
+ const next = tryResolveLocalVersion(pkgDir, current) ?? fetchPublishedVersion(name);
63
+ if (!next) {
64
+ console.warn(`[resolve-deps] warn: could not resolve ${name} for ${pkgPath}`);
65
+ continue;
66
+ }
67
+ if (next !== current) {
68
+ deps[name] = next;
69
+ changed = true;
70
+ console.log(`[resolve-deps] ${pkg.name ?? pkgPath} ${section}.${name}: ${current} -> ${next}`);
71
+ }
27
72
  }
28
73
  }
29
74
 
30
- if (changed) {
31
- writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`);
32
- }
75
+ if (changed) writeJson(pkgPath, pkg);
76
+ return changed;
33
77
  }
34
78
 
35
- async function run() {
36
- const scriptDir = dirname(fileURLToPath(import.meta.url));
37
- const workspaceRunner = resolve(scriptDir, "../../../scripts/resolve-deps-runner.mjs");
38
-
39
- if (existsSync(workspaceRunner)) {
40
- const { runResolveDeps } = await import(pathToFileURL(workspaceRunner).href);
41
- await runResolveDeps(import.meta.url, "../../../scripts/internal-package-refs.mjs");
79
+ function main() {
80
+ if (!process.env.CI) {
81
+ console.log("[resolve-deps] skipping because CI is not set");
42
82
  return;
43
83
  }
44
-
45
- console.log(`[resolve-deps] workspace helper not found at ${workspaceRunner}; using local fallback`);
46
- fallbackRewriteCurrentPackage(import.meta.url);
84
+ const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
85
+ const packageJsonPaths = collectPackageJsonPaths(repoRoot);
86
+ let changed = false;
87
+ for (const pkgPath of packageJsonPaths) changed = rewritePackageJson(pkgPath) || changed;
88
+ if (!changed) console.log("[resolve-deps] no file-based internal deps to rewrite");
47
89
  }
48
90
 
49
- await run();
91
+ main();
@@ -3,16 +3,10 @@
3
3
  import { execSync } from "node:child_process";
4
4
  import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, symlinkSync } from "node:fs";
5
5
  import { dirname, resolve } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
6
 
8
- const scriptDir = dirname(fileURLToPath(import.meta.url));
9
- const appDir = resolve(scriptDir, "..");
7
+ const appDir = process.argv[2] ? resolve(process.argv[2]) : process.cwd();
10
8
  const packageJson = JSON.parse(readFileSync(resolve(appDir, "package.json"), "utf8"));
11
- const dependencySections = [
12
- packageJson.dependencies ?? {},
13
- packageJson.devDependencies ?? {},
14
- packageJson.optionalDependencies ?? {},
15
- ];
9
+ const dependencySections = [packageJson.dependencies ?? {}, packageJson.devDependencies ?? {}, packageJson.optionalDependencies ?? {}];
16
10
 
17
11
  const WORKSPACE_PACKAGE_DIRS = {
18
12
  "@botbotgo/common": "framework/common",
@@ -45,9 +39,7 @@ function resolveWorkspacePackageDir(packageName) {
45
39
 
46
40
  function syncWorkspacePackage(packageName, packageDir) {
47
41
  const [, scope, shortName] = packageName.match(/^@([^/]+)\/(.+)$/) ?? [];
48
- if (!scope || !shortName) {
49
- throw new Error(`Unsupported scoped package name: ${packageName}`);
50
- }
42
+ if (!scope || !shortName) throw new Error(`Unsupported scoped package name: ${packageName}`);
51
43
  const scopeDir = resolve(appDir, "node_modules", `@${scope}`);
52
44
  const targetDir = resolve(scopeDir, shortName);
53
45
  mkdirSync(scopeDir, { recursive: true });
@@ -81,7 +73,7 @@ function syncPeerDependenciesFromApp(packageDir) {
81
73
  }
82
74
  }
83
75
 
84
- function ensureInstalledDependencies(packageName, packageDir) {
76
+ function ensureInstalledDependencies(packageDir) {
85
77
  if (hasInstalledDependencies(packageDir)) return;
86
78
  console.log(`[build-internal-deps] npm install --prefix ${packageDir}`);
87
79
  execSync(`npm install --prefix ${JSON.stringify(packageDir)} --legacy-peer-deps --ignore-scripts`, {
@@ -91,33 +83,16 @@ function ensureInstalledDependencies(packageName, packageDir) {
91
83
  syncPeerDependenciesFromApp(packageDir);
92
84
  }
93
85
 
94
- const packageNames = [
95
- "@botbotgo/common",
96
- "@botbotgo/model",
97
- "@botbotgo/memory",
98
- "@botbotgo/toolkit",
99
- "@botbotgo/agent",
100
- "@botbotgo/toolkit-builtin",
101
- ];
86
+ const packageNames = ["@botbotgo/common", "@botbotgo/model", "@botbotgo/memory", "@botbotgo/toolkit", "@botbotgo/agent", "@botbotgo/toolkit-builtin"];
102
87
 
103
88
  for (const packageName of packageNames) {
104
89
  const spec = getDependencySpec(packageName);
105
- const packageDir = spec?.startsWith("file:")
106
- ? resolve(appDir, spec.slice("file:".length))
107
- : resolveWorkspacePackageDir(packageName);
108
- if (!packageDir || !existsSync(resolve(packageDir, "package.json"))) {
109
- if (spec?.startsWith("file:")) {
110
- console.warn(`[build-internal-deps] skipping missing workspace package for ${packageName}: ${packageDir}`);
111
- }
112
- continue;
113
- }
114
- ensureInstalledDependencies(packageName, packageDir);
90
+ const packageDir = spec?.startsWith("file:") ? resolve(appDir, spec.slice("file:".length)) : resolveWorkspacePackageDir(packageName);
91
+ if (!packageDir || !existsSync(resolve(packageDir, "package.json"))) continue;
92
+ ensureInstalledDependencies(packageDir);
115
93
  console.log(`[build-internal-deps] npm run build --prefix ${packageDir}`);
116
94
  try {
117
- execSync(`npm run build --prefix ${JSON.stringify(packageDir)}`, {
118
- cwd: appDir,
119
- stdio: "inherit",
120
- });
95
+ execSync(`npm run build --prefix ${JSON.stringify(packageDir)}`, { cwd: appDir, stdio: "inherit" });
121
96
  } catch (error) {
122
97
  if (!hasBuiltOutput(packageDir)) throw error;
123
98
  console.warn(`[build-internal-deps] build failed for ${packageName}, using existing dist at ${packageDir}`);
@@ -1,33 +0,0 @@
1
- /**
2
- * Quick LLM config test. Run from app root: npm run test:llm
3
- */
4
- import { AgentContextTokens, getDefaultAgentContext } from "@botbotgo/common/context";
5
- import { createAgentModel } from "@botbotgo/model";
6
- import { loadAppConfig, getModelsConfigPath } from "../dist/config.js";
7
-
8
- async function main() {
9
- try {
10
- const appConfig = await loadAppConfig("config/app.yaml");
11
- const agentNames = Object.keys(appConfig?.app?.agent ?? {});
12
- const agentName = appConfig?.app?.defaultAgent ?? agentNames[0];
13
- const modelPath = getModelsConfigPath(appConfig, agentName);
14
- console.log(`[test-llm] Loading LLM from ${modelPath} ...`);
15
- await createAgentModel({
16
- configPath: modelPath,
17
- });
18
- const llm = getDefaultAgentContext().get(AgentContextTokens.ChatModel);
19
-
20
- console.log("[test-llm] Invoking LLM ...");
21
- const res = await llm.invoke(
22
- "In one sentence, introduce yourself and say you are being used to test iTermBot's LLM config."
23
- );
24
-
25
- console.log("[test-llm] Raw response:");
26
- console.log(JSON.stringify(res, null, 2));
27
- } catch (err) {
28
- console.error("[test-llm] Error:", err);
29
- process.exit(1);
30
- }
31
- }
32
-
33
- main();