itermbot 1.0.2 → 1.0.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/.github/workflows/ci.yml +15 -20
- package/.github/workflows/release.yml +32 -20
- package/README.md +11 -20
- package/cleanup-unused.patch +108 -0
- package/config/app.yaml +32 -13
- package/config/memory.yaml +38 -31
- package/config/model.yaml +33 -0
- package/config/skill.yaml +8 -0
- package/config/tool.yaml +50 -17
- package/config/tsconfig.json +4 -1
- package/dist/chat/builtin-commands.d.ts +8 -0
- package/dist/chat/builtin-commands.d.ts.map +1 -0
- package/dist/chat/builtin-commands.js +53 -0
- package/dist/chat/builtin-commands.js.map +1 -0
- package/dist/chat/progress.d.ts +3 -0
- package/dist/chat/progress.d.ts.map +1 -0
- package/dist/chat/progress.js +23 -0
- package/dist/chat/progress.js.map +1 -0
- package/dist/chat/response-safety.d.ts +8 -0
- package/dist/chat/response-safety.d.ts.map +1 -0
- package/dist/chat/response-safety.js +126 -0
- package/dist/chat/response-safety.js.map +1 -0
- package/dist/chat/step-display.d.ts +2 -0
- package/dist/chat/step-display.d.ts.map +1 -0
- package/dist/chat/step-display.js +50 -0
- package/dist/chat/step-display.js.map +1 -0
- package/dist/chat/tool-result.d.ts +4 -0
- package/dist/chat/tool-result.d.ts.map +1 -0
- package/dist/chat/tool-result.js +24 -0
- package/dist/chat/tool-result.js.map +1 -0
- package/dist/config.d.ts +11 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +26 -12
- package/dist/config.js.map +1 -1
- package/dist/index.js +308 -151
- package/dist/index.js.map +1 -1
- package/dist/iterm/direct-command-router.d.ts +24 -0
- package/dist/iterm/direct-command-router.d.ts.map +1 -0
- package/dist/iterm/direct-command-router.js +213 -0
- package/dist/iterm/direct-command-router.js.map +1 -0
- package/dist/iterm/session-hint.d.ts +10 -0
- package/dist/iterm/session-hint.d.ts.map +1 -0
- package/dist/iterm/session-hint.js +43 -0
- package/dist/iterm/session-hint.js.map +1 -0
- package/dist/iterm/target-panel-policy.d.ts +12 -0
- package/dist/iterm/target-panel-policy.d.ts.map +1 -0
- package/dist/iterm/target-panel-policy.js +287 -0
- package/dist/iterm/target-panel-policy.js.map +1 -0
- package/dist/runtime/text-tool-call-recovery.d.ts +23 -0
- package/dist/runtime/text-tool-call-recovery.d.ts.map +1 -0
- package/dist/runtime/text-tool-call-recovery.js +211 -0
- package/dist/runtime/text-tool-call-recovery.js.map +1 -0
- package/dist/startup/colors.d.ts +37 -0
- package/dist/startup/colors.d.ts.map +1 -0
- package/dist/{startup-colors.js → startup/colors.js} +30 -15
- package/dist/startup/colors.js.map +1 -0
- package/dist/startup/diagnostics.d.ts +8 -0
- package/dist/startup/diagnostics.d.ts.map +1 -0
- package/dist/startup/diagnostics.js +18 -0
- package/dist/startup/diagnostics.js.map +1 -0
- package/dist/startup/os.d.ts +10 -0
- package/dist/startup/os.d.ts.map +1 -0
- package/dist/startup/os.js +67 -0
- package/dist/startup/os.js.map +1 -0
- package/dist/startup/ui.d.ts +11 -0
- package/dist/startup/ui.d.ts.map +1 -0
- package/dist/startup/ui.js +49 -0
- package/dist/startup/ui.js.map +1 -0
- package/package.json +23 -13
- package/scripts/internal-package-refs.mjs +158 -0
- package/scripts/patch-buildin-cache.sh +1 -4
- package/scripts/resolve-deps.js +5 -0
- package/scripts/test-llm.mjs +11 -5
- package/skills/gpu-ssh-monitor/SKILL.md +22 -3
- package/src/chat/builtin-commands.ts +70 -0
- package/src/chat/progress.ts +26 -0
- package/src/chat/response-safety.ts +134 -0
- package/src/chat/step-display.ts +54 -0
- package/src/chat/tool-result.ts +22 -0
- package/src/config.ts +48 -21
- package/src/index.ts +377 -167
- package/src/iterm/direct-command-router.ts +274 -0
- package/src/iterm/session-hint.ts +49 -0
- package/src/iterm/target-panel-policy.ts +341 -0
- package/src/runtime/text-tool-call-recovery.ts +257 -0
- package/src/{startup-colors.ts → startup/colors.ts} +42 -27
- package/src/startup/diagnostics.ts +25 -0
- package/src/startup/os.ts +63 -0
- package/src/startup/ui.ts +56 -0
- package/src/types/marked-terminal.d.ts +3 -0
- package/test/builtin-commands.test.mjs +50 -0
- package/test/chat-flow.integration.test.mjs +235 -0
- package/test/chat-progress.test.mjs +83 -0
- package/test/config.test.mjs +22 -0
- package/test/diagnostics.test.mjs +45 -0
- package/test/direct-command-router.test.mjs +149 -0
- package/test/live-iterm-llm.integration.test.mjs +153 -0
- package/test/response-safety.test.mjs +44 -0
- package/test/session-hint.test.mjs +78 -0
- package/test/startup-colors.test.mjs +145 -0
- package/test/target-panel-policy.test.mjs +180 -0
- package/test/tool-call-recovery.test.mjs +199 -0
- package/config/agent.yaml +0 -121
- package/config/models.yaml +0 -36
- package/config/skills.yaml +0 -4
- package/dist/agent.d.ts +0 -14
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -16
- package/dist/agent.js.map +0 -1
- package/dist/context.d.ts +0 -12
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -20
- package/dist/context.js.map +0 -1
- package/dist/session-hint.d.ts +0 -4
- package/dist/session-hint.d.ts.map +0 -1
- package/dist/session-hint.js +0 -25
- package/dist/session-hint.js.map +0 -1
- package/dist/startup-colors.d.ts +0 -26
- package/dist/startup-colors.d.ts.map +0 -1
- package/dist/startup-colors.js.map +0 -1
- package/dist/target-routing.d.ts +0 -15
- package/dist/target-routing.d.ts.map +0 -1
- package/dist/target-routing.js +0 -355
- package/dist/target-routing.js.map +0 -1
- package/src/agent.ts +0 -35
- package/src/context.ts +0 -35
- package/src/session-hint.ts +0 -28
- package/src/target-routing.ts +0 -419
package/.github/workflows/ci.yml
CHANGED
|
@@ -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:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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:
|
|
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:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
- **
|
|
88
|
-
- **
|
|
89
|
-
- **
|
|
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,9 +1,26 @@
|
|
|
1
|
-
|
|
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 expert.
|
|
16
|
+
You are highly experienced with Linux/macOS shells, filesystems, networking, process diagnostics, and incident triage.
|
|
17
|
+
You think step-by-step, prioritize verifiable evidence, and avoid guesses.
|
|
18
|
+
You communicate in clear, well-structured Markdown suitable for terminal display.
|
|
19
|
+
你是一位资深系统工程师与终端运维专家,熟悉 Linux/macOS 系统排障与性能分析,结论必须基于可验证证据。
|
|
2
20
|
|
|
3
|
-
app:
|
|
4
|
-
prompt_templates:
|
|
5
|
-
iterm_policy: |
|
|
6
21
|
## iTerm Operating Policy
|
|
22
|
+
- The chat panel receives user messages; understand intent, select a matching skill when available, then plan, execute on target panel, analyze, and reply.
|
|
23
|
+
- Skills are preferred over ad-hoc planning when a skill matches the request.
|
|
7
24
|
- Target panel output is the remote source of truth.
|
|
8
25
|
- Never use local machine commands for system/project data collection.
|
|
9
26
|
- For remote operations/investigation, use `itermRunCommandInSession` in target panel.
|
|
@@ -14,13 +31,15 @@ app:
|
|
|
14
31
|
- Host may auto-update target panel when focus moves to a non-chat panel.
|
|
15
32
|
- Final response must be valid Markdown with stable formatting.
|
|
16
33
|
- 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
34
|
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
{{targetSessionSection}}
|
|
36
|
+
|
|
37
|
+
{{targetOsSection}}
|
|
38
|
+
|
|
39
|
+
Response safety policy:
|
|
40
|
+
- Ground all conclusions in tool output evidence only.
|
|
41
|
+
- If tool output contains requestedPath/resolvedPath/pathFallbackUsed, treat those fields as source of truth.
|
|
42
|
+
- Never claim a missing path exists when fallback was used.
|
|
43
|
+
- If user request omits path/scope for inspection tasks, run one non-destructive check against current target-panel working directory first, and state this assumption explicitly.
|
|
44
|
+
- Do not suggest destructive commands (for example rm -rf, sudo rm, mkfs, dd, disk erase) unless the user explicitly asks to execute them.
|
|
45
|
+
- Prefer non-destructive and reversible recommendations before irreversible actions.
|
package/config/memory.yaml
CHANGED
|
@@ -1,33 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
+
|
package/config/tool.yaml
CHANGED
|
@@ -1,17 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
+
- pwd
|
|
25
|
+
- readlink
|
|
26
|
+
- rg
|
|
27
|
+
- sha1sum
|
|
28
|
+
- sha256sum
|
|
29
|
+
- stat
|
|
30
|
+
- tail
|
|
31
|
+
- uname -s
|
|
32
|
+
- uname
|
|
33
|
+
- wc
|
|
34
|
+
- whoami
|
|
35
|
+
# Add only explicit command prefixes here. Example:
|
|
36
|
+
# - hdfs dfs -ls
|
|
37
|
+
list:
|
|
38
|
+
- file:../../../agent-tool-buildin#listDir
|
|
39
|
+
- file:../../../agent-tool-buildin#itermCreateWindow
|
|
40
|
+
- file:../../../agent-tool-buildin#itermCreateTab
|
|
41
|
+
- file:../../../agent-tool-buildin#itermSplitPane
|
|
42
|
+
- file:../../../agent-tool-buildin#itermResizeWindow
|
|
43
|
+
- file:../../../agent-tool-buildin#itermRename
|
|
44
|
+
- file:../../../agent-tool-buildin#itermSetBackgroundColor
|
|
45
|
+
- file:../../../agent-tool-buildin#itermSetSessionColors
|
|
46
|
+
- file:../../../agent-tool-buildin#itermSendText
|
|
47
|
+
- file:../../../agent-tool-buildin#itermRunCommandInSession
|
|
48
|
+
- file:../../../agent-tool-buildin#itermListCurrentWindowSessions
|
|
49
|
+
- file:../../../agent-tool-buildin#itermGetSessionInfo
|
|
50
|
+
- file:../../../agent-tool-buildin#itermListWindows
|
package/config/tsconfig.json
CHANGED
|
@@ -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
|
-
"
|
|
17
|
+
"types": ["node"]
|
|
15
18
|
},
|
|
16
19
|
"include": ["../src/**/*"],
|
|
17
20
|
"exclude": ["../node_modules", "../dist"]
|
|
@@ -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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AgentContextTokens } from "@easynet/agent-common/context";
|
|
2
|
+
import { normalizeToolList, shortToolName } from "@easynet/agent-common/utils";
|
|
3
|
+
function isToolLike(tool) {
|
|
4
|
+
return Boolean(tool
|
|
5
|
+
&& typeof tool === "object"
|
|
6
|
+
&& typeof tool.name === "string");
|
|
7
|
+
}
|
|
8
|
+
function safeGet(runtime, token) {
|
|
9
|
+
try {
|
|
10
|
+
return runtime.context.get(token);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function formatTools(runtime) {
|
|
17
|
+
const raw = safeGet(runtime, AgentContextTokens.Tools);
|
|
18
|
+
const tools = normalizeToolList(raw, isToolLike);
|
|
19
|
+
if (tools.length === 0)
|
|
20
|
+
return "No tools are registered.";
|
|
21
|
+
const lines = [`Available tools (${tools.length}):`];
|
|
22
|
+
for (const tool of tools) {
|
|
23
|
+
const short = shortToolName(tool.name);
|
|
24
|
+
if (tool.description?.trim())
|
|
25
|
+
lines.push(`- ${short}: ${tool.description.trim()}`);
|
|
26
|
+
else
|
|
27
|
+
lines.push(`- ${short}`);
|
|
28
|
+
}
|
|
29
|
+
return lines.join("\n");
|
|
30
|
+
}
|
|
31
|
+
function formatSkills(runtime) {
|
|
32
|
+
const skillSet = safeGet(runtime, AgentContextTokens.SkillSet);
|
|
33
|
+
const skills = skillSet?.list?.() ?? [];
|
|
34
|
+
if (skills.length === 0)
|
|
35
|
+
return "No skills are configured.";
|
|
36
|
+
const lines = [`Available skills (${skills.length}):`];
|
|
37
|
+
for (const skill of skills) {
|
|
38
|
+
if (skill.description?.trim())
|
|
39
|
+
lines.push(`- ${skill.name}: ${skill.description.trim()}`);
|
|
40
|
+
else
|
|
41
|
+
lines.push(`- ${skill.name}`);
|
|
42
|
+
}
|
|
43
|
+
return lines.join("\n");
|
|
44
|
+
}
|
|
45
|
+
export function tryHandleBuiltinReadCommand(input, runtime) {
|
|
46
|
+
const normalized = input.trim().toLowerCase().replace(/\s+/g, " ");
|
|
47
|
+
if (normalized === "list tools")
|
|
48
|
+
return formatTools(runtime);
|
|
49
|
+
if (normalized === "list skills")
|
|
50
|
+
return formatSkills(runtime);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=builtin-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-commands.js","sourceRoot":"","sources":["../../src/chat/builtin-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAsB/E,SAAS,UAAU,CAAC,IAAa;IAC/B,OAAO,OAAO,CACZ,IAAI;WACD,OAAO,IAAI,KAAK,QAAQ;WACxB,OAAQ,IAA2B,CAAC,IAAI,KAAK,QAAQ,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAI,OAAoB,EAAE,KAAc;IACtD,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAI,KAAK,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,OAAoB;IACvC,MAAM,GAAG,GAAG,OAAO,CAAU,OAAO,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,iBAAiB,CAAW,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,oBAAoB,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;;YAC9E,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,OAAoB;IACxC,MAAM,QAAQ,GAAG,OAAO,CAA2B,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC5D,MAAM,KAAK,GAAG,CAAC,qBAAqB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;;YACrF,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa,EAAE,OAAoB;IAC7E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnE,IAAI,UAAU,KAAK,YAAY;QAAE,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,UAAU,KAAK,aAAa;QAAE,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/chat/progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAgBzG,wBAAgB,+BAA+B,CAC7C,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAkB,GAC3C,kBAAkB,CAOpB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createProgressAgentEventListener } from "@easynet/agent-common/events";
|
|
2
|
+
import { renderStepLine } from "./step-display.js";
|
|
3
|
+
function reasonForAction(action) {
|
|
4
|
+
if (action.startsWith("run command:")) {
|
|
5
|
+
return "Because we need verifiable terminal evidence, execute this command first.";
|
|
6
|
+
}
|
|
7
|
+
if (action.startsWith("list directory")) {
|
|
8
|
+
return "Because we need to confirm directory structure and contents, list the directory first.";
|
|
9
|
+
}
|
|
10
|
+
if (action.startsWith("read file:") || action === "read file" || action.startsWith("read path:")) {
|
|
11
|
+
return "Because conclusions depend on file content, read the file first.";
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
export function createChatProgressEventListener(writer = console.log) {
|
|
16
|
+
return createProgressAgentEventListener({
|
|
17
|
+
writer: (line) => writer(renderStepLine(line)),
|
|
18
|
+
runLabelReact: "analysis",
|
|
19
|
+
runLabelDeep: "deep analysis",
|
|
20
|
+
reasonForAction,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/chat/progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAA2B,MAAM,8BAA8B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACtC,OAAO,2EAA2E,CAAC;IACrF,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACxC,OAAO,wFAAwF,CAAC;IAClG,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjG,OAAO,kEAAkE,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,SAAiC,OAAO,CAAC,GAAG;IAE5C,OAAO,gCAAgC,CAAC;QACtC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACtD,aAAa,EAAE,UAAU;QACzB,YAAY,EAAE,eAAe;QAC7B,eAAe;KAChB,CAAC,CAAC;AACL,CAAC"}
|