agent-termo 1.0.0 → 1.0.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.
Files changed (65) hide show
  1. package/README.md +30 -11
  2. package/dist/agents/index.d.ts +5 -0
  3. package/dist/agents/index.d.ts.map +1 -0
  4. package/dist/agents/index.js +86 -0
  5. package/dist/agents/index.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +97 -164
  9. package/dist/cli.js.map +4 -4
  10. package/dist/diff/index.d.ts +9 -0
  11. package/dist/diff/index.d.ts.map +1 -0
  12. package/dist/diff/index.js +213 -0
  13. package/dist/diff/index.js.map +1 -0
  14. package/dist/llm/client.d.ts +39 -0
  15. package/dist/llm/client.d.ts.map +1 -0
  16. package/dist/llm/client.js +188 -0
  17. package/dist/llm/client.js.map +1 -0
  18. package/dist/llm/models.d.ts +19 -0
  19. package/dist/llm/models.d.ts.map +1 -0
  20. package/dist/llm/models.js +45 -0
  21. package/dist/llm/models.js.map +1 -0
  22. package/dist/llm/tools.d.ts +3 -0
  23. package/dist/llm/tools.d.ts.map +1 -0
  24. package/dist/llm/tools.js +204 -0
  25. package/dist/llm/tools.js.map +1 -0
  26. package/dist/main.d.ts +2 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/main.js +91 -140
  29. package/dist/main.js.map +4 -4
  30. package/dist/memory/index.d.ts +10 -0
  31. package/dist/memory/index.d.ts.map +1 -0
  32. package/dist/memory/index.js +117 -0
  33. package/dist/memory/index.js.map +1 -0
  34. package/dist/tools/index.d.ts +5 -0
  35. package/dist/tools/index.d.ts.map +1 -0
  36. package/dist/tools/index.js +334 -0
  37. package/dist/tools/index.js.map +1 -0
  38. package/dist/types/index.d.ts +119 -0
  39. package/dist/types/index.d.ts.map +1 -0
  40. package/dist/types/index.js +5 -0
  41. package/dist/types/index.js.map +1 -0
  42. package/dist/ui/index.d.ts +47 -0
  43. package/dist/ui/index.d.ts.map +1 -0
  44. package/dist/ui/index.js +321 -0
  45. package/dist/ui/index.js.map +1 -0
  46. package/dist/ui/screen.d.ts +59 -0
  47. package/dist/ui/screen.d.ts.map +1 -0
  48. package/dist/ui/screen.js +629 -0
  49. package/dist/ui/screen.js.map +1 -0
  50. package/dist/utils/ansi.d.ts +62 -0
  51. package/dist/utils/ansi.d.ts.map +1 -0
  52. package/dist/utils/ansi.js +116 -0
  53. package/dist/utils/ansi.js.map +1 -0
  54. package/dist/utils/config.d.ts +9 -0
  55. package/dist/utils/config.d.ts.map +1 -0
  56. package/dist/utils/config.js +120 -0
  57. package/dist/utils/config.js.map +1 -0
  58. package/package.json +2 -2
  59. package/src/cli.ts +91 -12
  60. package/src/llm/client.ts +24 -0
  61. package/src/llm/models.ts +55 -0
  62. package/src/main.ts +201 -75
  63. package/src/ui/index.ts +256 -389
  64. package/src/ui/screen.ts +698 -0
  65. package/src/utils/config.ts +62 -2
package/README.md CHANGED
@@ -39,17 +39,11 @@ npm run dev
39
39
 
40
40
  ## Configuration
41
41
 
42
- 1. Copy `.env.example` to `.env`:
43
- ```bash
44
- cp .env.example .env
45
- ```
42
+ On the first launch, Agent-Termo prompts you to enter your NVIDIA NIM API key. The input is hidden, and the key is saved in your user configuration at `~/.agent-termo/config.json` so you are not prompted again.
46
43
 
47
- 2. Add your Nvidia NIM API key to `.env`:
48
- ```
49
- NIM_API_KEY=your_api_key_here
50
- ```
44
+ Get a free API key from [https://build.nvidia.com/](https://build.nvidia.com/).
51
45
 
52
- 3. Get your free API key from [https://build.nvidia.com/](https://build.nvidia.com/)
46
+ You can also provide `NIM_API_KEY` through your shell environment or a project `.env` file. Existing environment variables take precedence over the saved key.
53
47
 
54
48
  ## Usage
55
49
 
@@ -59,6 +53,31 @@ npm run dev
59
53
  agent-termo
60
54
  ```
61
55
 
56
+ ### The terminal UI
57
+
58
+ Like Claude Code, the input box stays pinned to the bottom of the terminal while the conversation scrolls above it. The status line under the box shows the active model and project.
59
+
60
+ | Key | Action |
61
+ |-----|--------|
62
+ | `Enter` | Send |
63
+ | `↑` / `↓` | Input history |
64
+ | `Tab` | Complete a `/command` (matching commands show on the status line as you type) |
65
+ | `←` `→`, `Ctrl+A` / `Ctrl+E`, `Ctrl+←` / `Ctrl+→` | Move by character, to line start/end, by word |
66
+ | `Ctrl+W` / `Ctrl+U` / `Ctrl+K` | Delete word / to line start / to line end |
67
+ | `Ctrl+C` | Clear the line; quit when the line is empty |
68
+
69
+ Pasted text is kept on one line (newlines become spaces). Terminals smaller than 12 rows × 40 columns, and non-interactive input, fall back to a plain `>` prompt.
70
+
71
+ ### Choosing a model
72
+
73
+ Agent-Termo works with any chat model on NVIDIA NIM.
74
+
75
+ - `/model` opens a picker with the models your API key can use (fetched live from NIM; embedding and reranking models are hidden). Use `↑`/`↓`, type to filter, `Enter` to select, `Esc` to cancel. Type an `org/name` ID that isn't listed to use it as typed.
76
+ - `/model <model-id>` switches directly, e.g. `/model meta/llama-3.3-70b-instruct`.
77
+ - `agent-termo --model <model-id>` picks the model for one run.
78
+
79
+ Your selection is saved in `~/.agent-termo/config.json` and used next time. Order of precedence: `--model` flag, then the saved `/model` choice, then `NIM_MODEL` from `.env`, then the built-in default. If the live list can't be fetched, a built-in list of suggestions is shown instead.
80
+
62
81
  ### Tell it what to build
63
82
 
64
83
  ```
@@ -79,9 +98,9 @@ agent-termo/
79
98
  ├── src/
80
99
  │ ├── cli.ts # Commander entry point
81
100
  │ ├── main.ts # Main application
82
- │ ├── ui/ # Terminal UI (blessed)
101
+ │ ├── ui/ # Terminal UI (output rendering, pinned input box, model picker)
83
102
  │ ├── agents/ # 12 agent implementations
84
- │ ├── llm/ # OpenAI/NIM integration
103
+ │ ├── llm/ # OpenAI/NIM integration, model catalogue
85
104
  │ ├── tools/ # File, bash, git tools
86
105
  │ └── memory/ # Memory system
87
106
  ├── .claude/agents/ # Agent prompts
@@ -0,0 +1,5 @@
1
+ import type { Agent } from '../types/index.js';
2
+ export declare function loadAgentPrompt(agentName: string, agentDir: string): string | null;
3
+ export declare function loadAllAgents(agentDir: string): Agent[];
4
+ export declare function buildSystemPrompt(memory: string, timeline: string, _agentDir: string): string;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAY/C,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,CAevD;AAqCD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY7F"}
@@ -0,0 +1,86 @@
1
+ // =============================================================================
2
+ // Agent Loader + System Prompt Builder
3
+ // =============================================================================
4
+ import { readdirSync, readFileSync } from 'node:fs';
5
+ import { resolve } from 'node:path';
6
+ function parseAgentMeta(content) {
7
+ const descMatch = content.match(/^description:\s*(.+)$/m);
8
+ const toolsMatch = content.match(/^tools:\s*\[(.+)\]/m);
9
+ const toolsStr = toolsMatch?.[1] ?? '';
10
+ const tools = toolsStr
11
+ ? toolsStr.split(',').map((t) => t.trim().replace(/^["']|["']$/g, ''))
12
+ : ['file:read', 'file:write', 'file:edit', 'file:glob', 'grep', 'bash:execute', 'git:status', 'git:commit', 'git:push', 'git:log'];
13
+ return { description: descMatch?.[1]?.trim() ?? '', tools };
14
+ }
15
+ export function loadAgentPrompt(agentName, agentDir) {
16
+ const candidate = resolve(agentDir, 'agents', agentName + '.md');
17
+ try {
18
+ const content = readFileSync(candidate, 'utf-8');
19
+ const withoutFrontmatter = content.replace(/^---[\s\S]+?---\n/, '');
20
+ return withoutFrontmatter.trim();
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export function loadAllAgents(agentDir) {
27
+ const agentsDir = resolve(agentDir, 'agents');
28
+ try {
29
+ const files = readdirSync(agentsDir).filter((f) => f.endsWith('.md'));
30
+ const agents = files.map((file) => {
31
+ const agentId = file.replace(/\.md$/, '');
32
+ const content = readFileSync(resolve(agentsDir, file), 'utf-8');
33
+ const meta = parseAgentMeta(content);
34
+ const withoutFrontmatter = content.replace(/^---[\s\S]+?---\n/, '').trim();
35
+ return { name: agentId, description: meta.description, systemPrompt: withoutFrontmatter, tools: meta.tools };
36
+ });
37
+ return agents.sort((a, b) => a.name.localeCompare(b.name));
38
+ }
39
+ catch {
40
+ return [];
41
+ }
42
+ }
43
+ // =============================================================================
44
+ // Agent System Prompt Builder
45
+ // =============================================================================
46
+ const SYSTEM_BASE = `You are Agent-Termo, a helpful AI assistant in a terminal.
47
+
48
+ RESPONSE RULES (follow these strictly):
49
+ - Be concise and direct. 1-3 sentences for simple questions.
50
+ - Never output verbose chain-of-thought or reasoning — just the answer.
51
+ - For coding tasks: briefly explain what you did, show key code.
52
+ - Never write "null" or placeholders in your response.
53
+ - When using function calls, respond with the function only — no preamble.
54
+
55
+ CONVERSATION MODE (default):
56
+ Just chat. Say things like "I'm doing well!" or "2+2 is 4." — no tools needed.
57
+
58
+ TOOL MODE (when asked to code/build/fix files):
59
+ Use these functions (JSON tool_calls format):
60
+ {"tool_calls":[{"id":"call_1","name":"function_name","arguments":{"key":"value"}}]}
61
+
62
+ Available functions:
63
+ - file:read(path) → read a file
64
+ - file:write(path, content) → overwrite a file completely
65
+ - file:edit(path, old_string, new_string) → edit a specific line section
66
+ - file:glob(pattern) → list files matching a glob (e.g. "src/**/*.ts")
67
+ - grep(pattern, path, glob?) → search for text in files
68
+ - bash:execute(command) → run a shell command
69
+ - git:status() / git:commit(message) / git:push() → version control
70
+
71
+ When done, say "Done: <brief summary>."
72
+
73
+ AVAILABLE FILES:
74
+ - docs/MEMORY.md — project context
75
+ - docs/TIMELINE.md — recent activity log`;
76
+ export function buildSystemPrompt(memory, timeline, _agentDir) {
77
+ let prompt = SYSTEM_BASE;
78
+ if (memory) {
79
+ prompt += '\n\n## Project Memory\n' + memory;
80
+ }
81
+ if (timeline) {
82
+ prompt += '\n\n## Recent Timeline (last entries)\n' + timeline.slice(-1500);
83
+ }
84
+ return prompt;
85
+ }
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}