itermbot 1.0.3 → 1.0.5

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 (130) hide show
  1. package/.github/workflows/ci.yml +15 -20
  2. package/.github/workflows/release.yml +32 -20
  3. package/README.md +11 -20
  4. package/cleanup-unused.patch +108 -0
  5. package/config/app.yaml +74 -19
  6. package/config/memory.yaml +38 -31
  7. package/config/model.yaml +33 -0
  8. package/config/skill.yaml +8 -0
  9. package/config/tool.yaml +64 -17
  10. package/config/tsconfig.json +4 -1
  11. package/dist/chat/builtin-commands.d.ts +8 -0
  12. package/dist/chat/builtin-commands.d.ts.map +1 -0
  13. package/dist/chat/builtin-commands.js +53 -0
  14. package/dist/chat/builtin-commands.js.map +1 -0
  15. package/dist/chat/progress.d.ts +3 -0
  16. package/dist/chat/progress.d.ts.map +1 -0
  17. package/dist/chat/progress.js +23 -0
  18. package/dist/chat/progress.js.map +1 -0
  19. package/dist/chat/response-safety.d.ts +8 -0
  20. package/dist/chat/response-safety.d.ts.map +1 -0
  21. package/dist/chat/response-safety.js +126 -0
  22. package/dist/chat/response-safety.js.map +1 -0
  23. package/dist/chat/step-display.d.ts +2 -0
  24. package/dist/chat/step-display.d.ts.map +1 -0
  25. package/dist/chat/step-display.js +50 -0
  26. package/dist/chat/step-display.js.map +1 -0
  27. package/dist/chat/tool-result.d.ts +4 -0
  28. package/dist/chat/tool-result.d.ts.map +1 -0
  29. package/dist/chat/tool-result.js +24 -0
  30. package/dist/chat/tool-result.js.map +1 -0
  31. package/dist/config.d.ts +12 -6
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +26 -12
  34. package/dist/config.js.map +1 -1
  35. package/dist/index.js +306 -154
  36. package/dist/index.js.map +1 -1
  37. package/dist/iterm/direct-command-router.d.ts +25 -0
  38. package/dist/iterm/direct-command-router.d.ts.map +1 -0
  39. package/dist/iterm/direct-command-router.js +292 -0
  40. package/dist/iterm/direct-command-router.js.map +1 -0
  41. package/dist/iterm/session-hint.d.ts +10 -0
  42. package/dist/iterm/session-hint.d.ts.map +1 -0
  43. package/dist/iterm/session-hint.js +43 -0
  44. package/dist/iterm/session-hint.js.map +1 -0
  45. package/dist/iterm/target-panel-policy.d.ts +12 -0
  46. package/dist/iterm/target-panel-policy.d.ts.map +1 -0
  47. package/dist/iterm/target-panel-policy.js +304 -0
  48. package/dist/iterm/target-panel-policy.js.map +1 -0
  49. package/dist/runtime/text-tool-call-recovery.d.ts +23 -0
  50. package/dist/runtime/text-tool-call-recovery.d.ts.map +1 -0
  51. package/dist/runtime/text-tool-call-recovery.js +211 -0
  52. package/dist/runtime/text-tool-call-recovery.js.map +1 -0
  53. package/dist/startup/colors.d.ts +37 -0
  54. package/dist/startup/colors.d.ts.map +1 -0
  55. package/dist/{startup-colors.js → startup/colors.js} +53 -29
  56. package/dist/startup/colors.js.map +1 -0
  57. package/dist/startup/diagnostics.d.ts +8 -0
  58. package/dist/startup/diagnostics.d.ts.map +1 -0
  59. package/dist/startup/diagnostics.js +18 -0
  60. package/dist/startup/diagnostics.js.map +1 -0
  61. package/dist/startup/os.d.ts +10 -0
  62. package/dist/startup/os.d.ts.map +1 -0
  63. package/dist/startup/os.js +67 -0
  64. package/dist/startup/os.js.map +1 -0
  65. package/dist/startup/ui.d.ts +11 -0
  66. package/dist/startup/ui.d.ts.map +1 -0
  67. package/dist/startup/ui.js +49 -0
  68. package/dist/startup/ui.js.map +1 -0
  69. package/package.json +24 -13
  70. package/scripts/build-internal-deps.mjs +48 -0
  71. package/scripts/internal-package-refs.mjs +158 -0
  72. package/scripts/patch-buildin-cache.sh +1 -4
  73. package/scripts/resolve-deps.js +5 -0
  74. package/scripts/test-llm.mjs +11 -5
  75. package/skills/gpu-ssh-monitor/SKILL.md +22 -3
  76. package/skills/k8s-cluster-investigate/SKILL.md +106 -0
  77. package/src/chat/builtin-commands.ts +70 -0
  78. package/src/chat/progress.ts +26 -0
  79. package/src/chat/response-safety.ts +134 -0
  80. package/src/chat/step-display.ts +54 -0
  81. package/src/chat/tool-result.ts +22 -0
  82. package/src/config.ts +49 -21
  83. package/src/index.ts +376 -175
  84. package/src/iterm/direct-command-router.ts +365 -0
  85. package/src/iterm/session-hint.ts +49 -0
  86. package/src/iterm/target-panel-policy.ts +361 -0
  87. package/src/runtime/text-tool-call-recovery.ts +257 -0
  88. package/src/{startup-colors.ts → startup/colors.ts} +66 -41
  89. package/src/startup/diagnostics.ts +25 -0
  90. package/src/startup/os.ts +63 -0
  91. package/src/startup/ui.ts +56 -0
  92. package/src/types/marked-terminal.d.ts +3 -0
  93. package/test/builtin-commands.test.mjs +50 -0
  94. package/test/chat-flow.integration.test.mjs +238 -0
  95. package/test/chat-progress.test.mjs +83 -0
  96. package/test/config.test.mjs +22 -0
  97. package/test/diagnostics.test.mjs +45 -0
  98. package/test/direct-command-router.test.mjs +261 -0
  99. package/test/live-iterm-llm.integration.test.mjs +153 -0
  100. package/test/response-safety.test.mjs +44 -0
  101. package/test/session-hint.test.mjs +78 -0
  102. package/test/startup-colors.test.mjs +174 -0
  103. package/test/target-panel-policy.test.mjs +233 -0
  104. package/test/tool-call-recovery.test.mjs +199 -0
  105. package/config/agent.yaml +0 -121
  106. package/config/models.yaml +0 -36
  107. package/config/skills.yaml +0 -4
  108. package/dist/agent.d.ts +0 -14
  109. package/dist/agent.d.ts.map +0 -1
  110. package/dist/agent.js +0 -16
  111. package/dist/agent.js.map +0 -1
  112. package/dist/context.d.ts +0 -12
  113. package/dist/context.d.ts.map +0 -1
  114. package/dist/context.js +0 -20
  115. package/dist/context.js.map +0 -1
  116. package/dist/session-hint.d.ts +0 -4
  117. package/dist/session-hint.d.ts.map +0 -1
  118. package/dist/session-hint.js +0 -25
  119. package/dist/session-hint.js.map +0 -1
  120. package/dist/startup-colors.d.ts +0 -26
  121. package/dist/startup-colors.d.ts.map +0 -1
  122. package/dist/startup-colors.js.map +0 -1
  123. package/dist/target-routing.d.ts +0 -15
  124. package/dist/target-routing.d.ts.map +0 -1
  125. package/dist/target-routing.js +0 -355
  126. package/dist/target-routing.js.map +0 -1
  127. package/src/agent.ts +0 -35
  128. package/src/context.ts +0 -35
  129. package/src/session-hint.ts +0 -28
  130. package/src/target-routing.ts +0 -419
@@ -36,30 +36,25 @@ jobs:
36
36
  grep -q '@easynet:registry=' .npmrc || echo "@easynet:registry=https://registry.npmjs.org/" >> .npmrc
37
37
  grep -q '@wallee:registry=' .npmrc || echo "@wallee:registry=https://registry.npmjs.org/" >> .npmrc
38
38
 
39
- - name: Use @easynet deps from npm (CI has no file:../../)
40
- run: |
41
- node -e "
42
- const fs = require('fs');
43
- const pkgPath = 'package.json';
44
- const p = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
45
- const deps = { ...p.dependencies, ...p.devDependencies };
46
- let changed = false;
47
- for (const [name, v] of Object.entries(deps)) {
48
- if (name.startsWith('@easynet/') && typeof v === 'string' && v.startsWith('file:')) {
49
- if (p.dependencies[name]) { p.dependencies[name] = 'latest'; changed = true; }
50
- if (p.devDependencies[name]) { p.devDependencies[name] = 'latest'; changed = true; }
51
- }
52
- }
53
- if (changed) fs.writeFileSync(pkgPath, JSON.stringify(p, null, 2) + '\n');
54
- "
55
-
56
- - name: Remove lockfile to avoid stale local/git refs
57
- run: rm -f package-lock.json
39
+ - name: Rewrite file deps to npm/git refs for CI
40
+ env:
41
+ AGENT_SKILL_READ_TOKEN: ${{ secrets.AGENT_SKILL_READ_TOKEN }}
42
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43
+ run: node scripts/resolve-deps.js
58
44
 
59
45
  - name: Install dependencies
60
46
  env:
61
47
  NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/"
62
- run: npm install --legacy-peer-deps
48
+ run: |
49
+ rm -rf node_modules
50
+ rm -f package-lock.json
51
+ unset NPM_CONFIG_USERCONFIG NODE_AUTH_TOKEN
52
+ for i in 1 2 3; do
53
+ if npm install --legacy-peer-deps --ignore-scripts; then exit 0; fi
54
+ echo "Attempt $i failed, retrying in 10s..."
55
+ sleep 10
56
+ done
57
+ exit 1
63
58
 
64
59
  - name: Build
65
60
  run: npm run build --if-present
@@ -42,30 +42,25 @@ jobs:
42
42
  grep -q '@easynet:registry=' .npmrc || echo "@easynet:registry=https://registry.npmjs.org/" >> .npmrc
43
43
  grep -q '@wallee:registry=' .npmrc || echo "@wallee:registry=https://registry.npmjs.org/" >> .npmrc
44
44
 
45
- - name: Use @easynet deps from npm (CI has no file:../../)
46
- run: |
47
- node -e "
48
- const fs = require('fs');
49
- const pkgPath = 'package.json';
50
- const p = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
51
- const deps = { ...p.dependencies, ...p.devDependencies };
52
- let changed = false;
53
- for (const [name, v] of Object.entries(deps)) {
54
- if (name.startsWith('@easynet/') && typeof v === 'string' && v.startsWith('file:')) {
55
- if (p.dependencies[name]) { p.dependencies[name] = 'latest'; changed = true; }
56
- if (p.devDependencies[name]) { p.devDependencies[name] = 'latest'; changed = true; }
57
- }
58
- }
59
- if (changed) fs.writeFileSync(pkgPath, JSON.stringify(p, null, 2) + '\n');
60
- "
61
-
62
- - name: Remove lockfile to avoid stale local/git refs
63
- run: rm -f package-lock.json
45
+ - name: Rewrite file deps to npm/git refs for CI
46
+ env:
47
+ AGENT_SKILL_READ_TOKEN: ${{ secrets.AGENT_SKILL_READ_TOKEN }}
48
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49
+ run: node scripts/resolve-deps.js
64
50
 
65
51
  - name: Install dependencies
66
52
  env:
67
53
  NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/"
68
- run: npm install --legacy-peer-deps
54
+ run: |
55
+ rm -rf node_modules
56
+ rm -f package-lock.json
57
+ unset NPM_CONFIG_USERCONFIG NODE_AUTH_TOKEN
58
+ for i in 1 2 3; do
59
+ if npm install --legacy-peer-deps --ignore-scripts; then exit 0; fi
60
+ echo "Attempt $i failed, retrying in 10s..."
61
+ sleep 10
62
+ done
63
+ exit 1
69
64
 
70
65
  - name: Build
71
66
  run: npm run build --if-present
@@ -76,8 +71,25 @@ jobs:
76
71
  - name: Test
77
72
  run: npm test --if-present
78
73
 
74
+ - name: Detect npm token
75
+ id: release_gate
76
+ env:
77
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
78
+ run: |
79
+ if [ -n "${NPM_TOKEN}" ]; then
80
+ echo "has_npm_token=true" >> "$GITHUB_OUTPUT"
81
+ else
82
+ echo "has_npm_token=false" >> "$GITHUB_OUTPUT"
83
+ fi
84
+
85
+ - name: Skip release (missing NPM_TOKEN)
86
+ if: ${{ steps.release_gate.outputs.has_npm_token == 'false' }}
87
+ run: echo "NPM_TOKEN is not configured. Skipping semantic-release."
88
+
79
89
  - name: Release
90
+ if: ${{ steps.release_gate.outputs.has_npm_token == 'true' }}
80
91
  env:
81
92
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
93
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
82
94
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
83
95
  run: npx semantic-release
package/README.md CHANGED
@@ -8,7 +8,7 @@ iTermBot is an application built on the **@easynet** agent framework. It runs tw
8
8
  Both agents share:
9
9
 
10
10
  - **@easynet/agent-common** — YAML config (app, paths).
11
- - **@easynet/agent-model** — LLM and embedding models from `models.yaml`.
11
+ - **@easynet/agent-model** — LLM and embedding models (falls back to module default config).
12
12
  - **@easynet/agent-memory** — Agent memory (recall/inject for ReAct; store adapter for Deep).
13
13
  - **@easynet/agent-tool** + **@easynet/agent-tool-buildin** — Tools (FS, HTTP, util, exec, etc.).
14
14
 
@@ -19,7 +19,7 @@ Both agents share:
19
19
 
20
20
  ## Setup
21
21
 
22
- The app uses **npm packages** only (no file: links), so it builds from a clean install:
22
+ Build from source workspace:
23
23
 
24
24
  ```bash
25
25
  cd apps/itermbot
@@ -33,23 +33,12 @@ Tool support uses agent-tool’s `@easynet/agent-tool` and `@easynet/agent-tool-
33
33
 
34
34
  | File | Purpose |
35
35
  |------|--------|
36
- | `config/app.yaml` | App name and paths (loaded via agent-common). |
37
- | `config/models.yaml` | LLM + embedding instances (agent-model). |
38
- | `config/memory.yaml` | Memory backend config (agent-memory). |
39
- | `config/tool.yaml` | Tool list used by all environments. |
36
+ | `config/app.yaml` | App-level settings (`agent`, `printSteps`, prompt templates). |
40
37
 
41
- Paths in `config/app.yaml` are relative to the app root (current working directory when you run the app).
38
+ Agent profile defaults (model/memory/tool/skills) are resolved by `@easynet/agent-runtime`.
39
+ Top-level app config only overrides runtime defaults.
42
40
 
43
- ### Tool source by environment
44
-
45
- - `APP_ENV=development` and `APP_ENV=production` both use `config/tool.yaml`
46
-
47
- Example:
48
-
49
- ```bash
50
- APP_ENV=development npm run react
51
- APP_ENV=production npm run react
52
- ```
41
+ Tool config now falls back to `@easynet/agent-tool` module defaults when app-level tool config is not provided.
53
42
 
54
43
  ## Usage
55
44
 
@@ -84,8 +73,10 @@ APP_ENV=production npm run react
84
73
 
85
74
  ## Architecture
86
75
 
87
- - **context.ts** — Builds shared `BotContext`: LLM (`createAgentLlm`), memory (`createAgentMemory`), tools (`createAgentTools` with env-selected tool config and `coreTools`).
88
- - **agents/react-agent.ts** — LangChain `createAgent`; before each run, injects memory via `memory.recall`; optional `remember()` with `memory.memorize`.
89
- - **agents/deep-agent.ts** — DeepAgents `createDeepAgent` with state backend (no extra memory store adapter wiring).
76
+ - **src/index.ts** — CLI startup and orchestration.
77
+ - **src/context.ts** — Shared `BotContext` builders (LLM/memory/tools/skills).
78
+ - **src/config.ts** — App-level override adapter on top of runtime config.
79
+ - **src/startup/** — startup UI, diagnostics, and panel color bootstrapping.
80
+ - **src/iterm/** — iTerm session routing and target session prompt injection.
90
81
 
91
82
  Both agents use the same LLM, memory backend, and tool set; only the orchestration (ReAct vs Deep) differs.
@@ -0,0 +1,108 @@
1
+ *** Begin Patch
2
+ *** Update File: src/iterm/session-hint.ts
3
+ @@
4
+ /**
5
+ * Build the full system prompt by prepending iTerm policy and session info
6
+ * to an optional base prompt. Called before createReactAgentRuntime().
7
+ */
8
+ export function buildSystemPrompt(
9
+ templates: PromptTemplates | undefined,
10
+ startup: StartupResult,
11
+ basePrompt = "",
12
+ ): string {
13
+ @@
14
+ if (basePrompt.trim()) parts.push(basePrompt.trim());
15
+ return parts.join("\n\n");
16
+ }
17
+ -
18
+ -/**
19
+ - * Update just the target session section in an existing system prompt.
20
+ - * Used when target routing changes at runtime.
21
+ - */
22
+ -export function updateTargetSessionInPrompt(
23
+ - currentPrompt: string,
24
+ - templates: PromptTemplates | undefined,
25
+ - startup: StartupResult,
26
+ -): string {
27
+ - const targetTemplate = templates?.targetSession?.trim() ?? "";
28
+ - if (!targetTemplate) return currentPrompt;
29
+ - const rendered = startup.targetSessionId
30
+ - ? formatTargetSessionHint(targetTemplate, startup)
31
+ - : "";
32
+ - if (!rendered) return currentPrompt;
33
+ - // Replace existing target session block or append
34
+ - const headerLine = "## Target Panel Session";
35
+ - const idx = currentPrompt.indexOf(headerLine);
36
+ - if (idx !== -1) {
37
+ - // Find end of block (next ## heading or end of string)
38
+ - const afterHeader = currentPrompt.indexOf("\n##", idx + 1);
39
+ - const before = currentPrompt.slice(0, idx).trimEnd();
40
+ - const after = afterHeader !== -1 ? "\n\n" + currentPrompt.slice(afterHeader).trimStart() : "";
41
+ - return (before + "\n\n" + rendered + after).trim();
42
+ - }
43
+ - return currentPrompt + "\n\n" + rendered;
44
+ -}
45
+ *** End Patch
46
+
47
+ *** Begin Patch
48
+ *** Update File: src/startup/colors.ts
49
+ @@
50
+ function captureSessionColorsSync(args: {
51
+ windowId: number;
52
+ tabIndex: number;
53
+ sessionId: string;
54
+ }): SessionColorSnapshot | null {
55
+ @@
56
+ }
57
+ }
58
+ -
59
+ -export function captureSessionColorsByIdSync(args: {
60
+ - windowId: number;
61
+ - tabIndex: number;
62
+ - sessionId: string;
63
+ -}): SessionColorSnapshot | null {
64
+ - return captureSessionColorsSync(args);
65
+ -}
66
+
67
+ export function restoreSessionColorsSync(snapshots: SessionColorSnapshot[]): void {
68
+ *** End Patch
69
+
70
+ *** Begin Patch
71
+ *** Update File: src/startup/diagnostics.ts
72
+ @@
73
+ -import { loadYamlFile, AgentContextTokens } from "@easynet/agent-common";
74
+ +import { AgentContextTokens } from "@easynet/agent-common";
75
+ @@
76
+ type AgentRuntimeLike = {
77
+ context: {
78
+ get<T>(token: unknown): T;
79
+ };
80
+ };
81
+ -
82
+ -export async function getLlmSelectionLabel(modelsPath: string): Promise<string> {
83
+ - try {
84
+ - const raw = await loadYamlFile<Record<string, unknown>>(modelsPath);
85
+ - const spec = raw?.spec && typeof raw.spec === "object" && !Array.isArray(raw.spec)
86
+ - ? (raw.spec as Record<string, unknown>)
87
+ - : undefined;
88
+ - const llm = ((spec?.llm ?? raw?.llm) ?? null) as Record<string, unknown> | null;
89
+ - if (!llm) return "name=unknown, model=unknown";
90
+ - const selectedName =
91
+ - typeof llm.default === "string" && llm.default.trim().length > 0
92
+ - ? llm.default.trim()
93
+ - : "unknown";
94
+ - const selected = llm[selectedName];
95
+ - const selectedRec =
96
+ - typeof selected === "object" && selected !== null
97
+ - ? (selected as Record<string, unknown>)
98
+ - : null;
99
+ - const model =
100
+ - selectedRec && typeof selectedRec.model === "string" && selectedRec.model.trim().length > 0
101
+ - ? selectedRec.model.trim()
102
+ - : "unknown";
103
+ - return `name=${selectedName}, model=${model}`;
104
+ - } catch {
105
+ - return "name=unknown, model=unknown";
106
+ - }
107
+ -}
108
+ *** End Patch
package/config/app.yaml CHANGED
@@ -1,26 +1,81 @@
1
- # iTermBot app-level config
1
+ apiVersion: easynet.world/v1
2
+ kind: AppConfig
3
+ metadata:
4
+ name: itermbot
5
+ spec:
6
+ agent: react
7
+
8
+ printSteps: true
9
+ maxSteps: 100
10
+ responseSafetyMode: balanced
11
+
12
+ promptTemplates:
13
+ systemPrompt: |
14
+ ## Role
15
+ You are a senior systems engineer and terminal operations specialist.
16
+ Your domain includes Linux and macOS shells, filesystems, networking, process diagnostics, and incident triage.
17
+ Operate as an evidence-driven investigator: reason step by step, avoid unsupported assumptions, and present conclusions in clear, terminal-friendly Markdown.
18
+ 你是一位资深系统工程师与终端运维专家,熟悉 Linux/macOS Shell、文件系统、网络、进程诊断与故障排查;你的结论必须基于可验证证据。
2
19
 
3
- app:
4
- prompt_templates:
5
- iterm_policy: |
6
20
  ## iTerm Operating Policy
21
+ - The chat panel receives user requests. Determine intent, use a matching skill when available, then plan, execute in the target panel, analyze results, and respond.
22
+ - Prefer skill-based workflows over ad-hoc planning when a relevant skill exists.
7
23
  - Target panel output is the remote source of truth.
8
24
  - Never use local machine commands for system/project data collection.
9
- - For remote operations/investigation, use `itermRunCommandInSession` in target panel.
10
- - For current screen/panel analysis, never ask user to paste text; capture via no-op `:`.
11
- - For full coverage, paginate with `outputOffsetLines + maxOutputLines`, summarize by chunk, then merge.
12
- - If output is long, use bounded chunk analysis with interim summaries and one final conclusion.
13
- - Prefer fast/low-cost commands; avoid heavy full scans/builds/tests unless required.
25
+ - For remote inspection or operations, use `itermRunCommandInSession` in the target panel.
26
+ - Every `itermRunCommandInSession` call must be exactly one command. Do not use shell operators or composition such as `|`, `;`, `&&`, `||`, `>`, `<`, or command substitution.
27
+ - For current screen or panel analysis, do not ask the user to paste terminal text; capture it via no-op `:`.
28
+ - For long output, paginate with `outputOffsetLines + maxOutputLines`, summarize by chunk, then synthesize a final conclusion.
29
+ - Prefer fast, low-cost commands. Avoid heavy scans, builds, or tests unless they are necessary.
30
+ - If a command is rejected by policy or compatibility constraints, do not repeat it unchanged; choose a compliant alternative.
31
+ - Respect the detected target OS. Use only compatible commands. If OS evidence is weak or unavailable, start with portable read-only commands.
14
32
  - Host may auto-update target panel when focus moves to a non-chat panel.
15
33
  - Final response must be valid Markdown with stable formatting.
16
34
  - Host may auto-recover target routing (reuse non-chat pane or auto-split); if still failing, ask user.
17
- target_session: |
18
- ## Target Panel Session
19
- Routed target panel (may change at runtime):
20
- - sessionId: "{{sessionId}}"
21
- - windowId: {{windowId}}
22
- - tabIndex: {{tabIndex}}
23
- Never use `windowId: 0` and never guess IDs.
24
-
25
- agent:
26
- path: ./config/agent.yaml
35
+
36
+ {{targetSessionSection}}
37
+
38
+ {{targetOsSection}}
39
+
40
+ Response safety policy:
41
+ - Base all conclusions strictly on tool-output evidence.
42
+ - If tool output contains requestedPath, resolvedPath, or pathFallbackUsed, treat those fields as authoritative.
43
+ - Never claim that a missing path exists when fallback was used.
44
+ - If an inspection request omits path or scope, first run one non-destructive check against the current target-panel working directory and state that assumption explicitly.
45
+ - Do not suggest destructive commands (for example rm -rf, sudo rm, mkfs, dd, or disk erase) unless the user explicitly asks to execute them.
46
+ - Prefer non-destructive and reversible recommendations before irreversible actions.
47
+ directCommandTranslationPrompt: |
48
+ Role: you are a terminal command translator for direct execution.
49
+ Translate one user request into one executable read-only terminal command.
50
+ Return exactly one shell command or exactly NO_COMMAND.
51
+ Output one plain-text line only: no markdown, quotes, backticks, labels, or explanation.
52
+ Return a command only if the user clearly wants to inspect or fetch terminal-visible state, including direct question forms such as "what is", and one direct read-only command is sufficient.
53
+ Return NO_COMMAND if the request is analytical, explanatory, conversational, diagnostic rather than collection-oriented, requires multiple commands, would edit files or change system state, or is too ambiguous to execute safely.
54
+ Use read-only inspection commands only. Do not use shell operators or composition: ; && || | > >> < $() ``. Do not wrap the command in a shell or invent placeholders. Preserve user-provided names, namespaces, paths, and flags. If the user explicitly names a read-only subcommand such as logs, describe, get, or status, preserve it.
55
+
56
+ Examples:
57
+ user: show current directory
58
+ assistant: pwd
59
+
60
+ user: list files here
61
+ assistant: ls
62
+
63
+ user: get kubernetes pods
64
+ assistant: kubectl get pods -A
65
+
66
+ user: show kubectl logs for api-server in kube-system
67
+ assistant: kubectl logs -n kube-system api-server
68
+
69
+ user: describe node mario
70
+ assistant: kubectl describe node mario
71
+
72
+ user: what is current k8s cluster name
73
+ assistant: kubectl config view --minify -o jsonpath={.contexts[0].context.cluster}
74
+
75
+ user: explain why the service is failing
76
+ assistant: NO_COMMAND
77
+
78
+ user: restart the deployment
79
+ assistant: NO_COMMAND
80
+
81
+ User request:
@@ -1,33 +1,40 @@
1
- # iTermBot agent memory (@easynet/agent-memory)
2
- memory:
3
- thread:
4
- store:
5
- type: sqlite
6
- config:
7
- dbPath: ../data/thread.db
8
- sessionCompaction:
9
- enabled: true
10
- maxTokens: 3000
11
- keepRecentTurns: 12
12
- summaryKey: "__session_summary__"
13
- checkEveryTurns: 3
14
- cross_thread:
15
- store:
16
- type: sqlite
17
- config:
18
- dbPath: ../data/cross-thread.db
19
- knowledge:
20
- store:
21
- type: sqlite
22
- config:
23
- dbPath: ../data/knowledge.db
1
+ apiVersion: easynet.world/v1
2
+ kind: MemoryConfig
3
+ metadata:
4
+ name: itermbot-memory
5
+ spec:
6
+ memory:
7
+ thread:
8
+ store:
9
+ type: in_memory
10
+ allowWrite: true
11
+ maxItems: 20
12
+ sessionCompaction:
13
+ enabled: true
14
+ maxTokens: 3000
15
+ keepRecentTurns: 12
16
+ summaryKey: __session_summary__
17
+ checkEveryTurns: 3
24
18
 
25
- observability:
26
- trace: false
19
+ cross_thread:
20
+ store:
21
+ type: in_memory
22
+ allowWrite: true
23
+ maxItems: 20
24
+
25
+ knowledge:
26
+ store:
27
+ type: in_memory
28
+ allowWrite: true
29
+ maxItems: 20
30
+
31
+ observability:
32
+ trace: false
33
+
34
+ privacy:
35
+ forbiddenMetadataKeys:
36
+ - password
37
+ - api_key
38
+ - secret
39
+ - token
27
40
 
28
- privacy:
29
- forbiddenMetadataKeys:
30
- - password
31
- - api_key
32
- - secret
33
- - token
@@ -0,0 +1,33 @@
1
+ apiVersion: easynet.world/v1
2
+ kind: ModelConfig
3
+ metadata:
4
+ name: itermbot-models
5
+ spec:
6
+ llm:
7
+ default: lfm2
8
+ small:
9
+ provider: openai
10
+ base_url: http://localhost:11434/v1
11
+ model: qwen3:0.6b
12
+ lfm2:
13
+ provider: openai
14
+ base_url: https://ollama-rtx-4070.easynet.world/v1
15
+ model: lfm2:latest
16
+
17
+ embed:
18
+ default: local
19
+ local:
20
+ provider: openai
21
+ base_url: http://localhost:11434/v1
22
+ model: qwen3-embedding:0.6b
23
+ apiKey: not-needed
24
+
25
+ vlm:
26
+ default: glm_ocr
27
+ glm_ocr:
28
+ type: image
29
+ provider: openai
30
+ base_url: http://localhost:11434/v1
31
+ model: glm-ocr:q8_0
32
+ apiKey: not-needed
33
+
@@ -0,0 +1,8 @@
1
+ apiVersion: easynet.world/v1
2
+ kind: SkillConfig
3
+ metadata:
4
+ name: itermbot-skills
5
+ spec:
6
+ path: ../skills
7
+ mode: prompt
8
+ inject_metadata: true
package/config/tool.yaml CHANGED
@@ -1,17 +1,64 @@
1
- # iTermBot tools (shared across development and production)
2
- # Only load the iterm tools needed — no fs/http/util tools that would
3
- # distract the LLM from using itermRunCommandInSession.
4
- tools:
5
- list:
6
- - "npm:@easynet/agent-tool-buildin@latest#itermRunCommandInSession"
7
- - "npm:@easynet/agent-tool-buildin@latest#itermSendText"
8
- - "npm:@easynet/agent-tool-buildin@latest#itermListCurrentWindowSessions"
9
- - "npm:@easynet/agent-tool-buildin@latest#itermListWindows"
10
- - "npm:@easynet/agent-tool-buildin@latest#itermSetSessionColors"
11
- - "npm:@easynet/agent-tool-buildin@latest#itermSplitPane"
12
- - "npm:@easynet/agent-tool-buildin@latest#itermGetSessionInfo"
13
- sandboxedPath: .
14
- allowedHosts:
15
- - api.github.com
16
- - duckduckgo.com
17
- - www.duckduckgo.com
1
+ apiVersion: easynet.world/v1
2
+ kind: ToolConfig
3
+ metadata:
4
+ name: itermbot-local-tool-config
5
+ spec:
6
+ tools:
7
+ defaults:
8
+ itermRunCommandInSession:
9
+ allowedCommandPrefixes:
10
+ - cat
11
+ - cd
12
+ - date
13
+ - df
14
+ - du
15
+ - env
16
+ - file
17
+ - find
18
+ - grep
19
+ - head
20
+ - hostname
21
+ - id
22
+ - ls
23
+ - md5sum
24
+ - pgrep
25
+ - ps
26
+ - pwd
27
+ - readlink
28
+ - rg
29
+ - sha1sum
30
+ - sha256sum
31
+ - stat
32
+ - sysctl
33
+ - tail
34
+ - top
35
+ - uname -s
36
+ - uname
37
+ - uptime
38
+ - vm_stat
39
+ - wc
40
+ - whoami
41
+ - free
42
+ - kubectl config current-context
43
+ - kubectl config get-contexts
44
+ - kubectl config view
45
+ - kubectl cluster-info
46
+ - kubectl get
47
+ - kubectl logs
48
+ - kubectl describe
49
+ # Add only explicit command prefixes here. Example:
50
+ # - hdfs dfs -ls
51
+ list:
52
+ - file:../../../agent-tool-buildin#listDir
53
+ - file:../../../agent-tool-buildin#itermCreateWindow
54
+ - file:../../../agent-tool-buildin#itermCreateTab
55
+ - file:../../../agent-tool-buildin#itermSplitPane
56
+ - file:../../../agent-tool-buildin#itermResizeWindow
57
+ - file:../../../agent-tool-buildin#itermRename
58
+ - file:../../../agent-tool-buildin#itermSetBackgroundColor
59
+ - file:../../../agent-tool-buildin#itermSetSessionColors
60
+ - file:../../../agent-tool-buildin#itermSendText
61
+ - file:../../../agent-tool-buildin#itermRunCommandInSession
62
+ - file:../../../agent-tool-buildin#itermListCurrentWindowSessions
63
+ - file:../../../agent-tool-buildin#itermGetSessionInfo
64
+ - file:../../../agent-tool-buildin#itermListWindows
@@ -3,15 +3,18 @@
3
3
  "target": "ES2022",
4
4
  "module": "NodeNext",
5
5
  "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
6
7
  "outDir": "../dist",
7
8
  "rootDir": "../src",
8
9
  "strict": true,
9
10
  "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "resolveJsonModule": true,
10
13
  "skipLibCheck": true,
11
14
  "declaration": true,
12
15
  "declarationMap": true,
13
16
  "sourceMap": true,
14
- "resolveJsonModule": true
17
+ "types": ["node"]
15
18
  },
16
19
  "include": ["../src/**/*"],
17
20
  "exclude": ["../node_modules", "../dist"]
@@ -0,0 +1,8 @@
1
+ type RuntimeLike = {
2
+ context: {
3
+ get<T>(token: unknown): T;
4
+ };
5
+ };
6
+ export declare function tryHandleBuiltinReadCommand(input: string, runtime: RuntimeLike): string | null;
7
+ export {};
8
+ //# sourceMappingURL=builtin-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin-commands.d.ts","sourceRoot":"","sources":["../../src/chat/builtin-commands.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QACP,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC;KAC3B,CAAC;CACH,CAAC;AAyDF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAK9F"}