codebot-ai 1.0.0

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -0
  3. package/bin/codebot +5 -0
  4. package/dist/agent.d.ts +31 -0
  5. package/dist/agent.js +256 -0
  6. package/dist/banner.d.ts +19 -0
  7. package/dist/banner.js +148 -0
  8. package/dist/browser/cdp.d.ts +29 -0
  9. package/dist/browser/cdp.js +292 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +518 -0
  12. package/dist/context/manager.d.ts +27 -0
  13. package/dist/context/manager.js +139 -0
  14. package/dist/context/repo-map.d.ts +5 -0
  15. package/dist/context/repo-map.js +100 -0
  16. package/dist/history.d.ts +27 -0
  17. package/dist/history.js +146 -0
  18. package/dist/index.d.ts +13 -0
  19. package/dist/index.js +42 -0
  20. package/dist/memory.d.ts +39 -0
  21. package/dist/memory.js +168 -0
  22. package/dist/parser.d.ts +8 -0
  23. package/dist/parser.js +79 -0
  24. package/dist/providers/anthropic.d.ts +9 -0
  25. package/dist/providers/anthropic.js +288 -0
  26. package/dist/providers/index.d.ts +5 -0
  27. package/dist/providers/index.js +13 -0
  28. package/dist/providers/openai.d.ts +11 -0
  29. package/dist/providers/openai.js +173 -0
  30. package/dist/providers/registry.d.ts +15 -0
  31. package/dist/providers/registry.js +115 -0
  32. package/dist/setup.d.ts +17 -0
  33. package/dist/setup.js +243 -0
  34. package/dist/tools/browser.d.ts +43 -0
  35. package/dist/tools/browser.js +329 -0
  36. package/dist/tools/edit.d.ts +26 -0
  37. package/dist/tools/edit.js +73 -0
  38. package/dist/tools/execute.d.ts +26 -0
  39. package/dist/tools/execute.js +52 -0
  40. package/dist/tools/glob.d.ts +24 -0
  41. package/dist/tools/glob.js +102 -0
  42. package/dist/tools/grep.d.ts +29 -0
  43. package/dist/tools/grep.js +125 -0
  44. package/dist/tools/index.d.ts +10 -0
  45. package/dist/tools/index.js +49 -0
  46. package/dist/tools/memory.d.ts +36 -0
  47. package/dist/tools/memory.js +114 -0
  48. package/dist/tools/read.d.ts +26 -0
  49. package/dist/tools/read.js +75 -0
  50. package/dist/tools/think.d.ts +18 -0
  51. package/dist/tools/think.js +20 -0
  52. package/dist/tools/web-fetch.d.ts +36 -0
  53. package/dist/tools/web-fetch.js +83 -0
  54. package/dist/tools/write.d.ts +22 -0
  55. package/dist/tools/write.js +65 -0
  56. package/dist/types.d.ts +82 -0
  57. package/dist/types.js +3 -0
  58. package/package.json +57 -0
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ReadFileTool = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class ReadFileTool {
40
+ name = 'read_file';
41
+ description = 'Read the contents of a file. Returns file content with line numbers.';
42
+ permission = 'auto';
43
+ parameters = {
44
+ type: 'object',
45
+ properties: {
46
+ path: { type: 'string', description: 'Path to the file to read' },
47
+ offset: { type: 'number', description: 'Line number to start from (1-based). Optional.' },
48
+ limit: { type: 'number', description: 'Max number of lines to read. Optional.' },
49
+ },
50
+ required: ['path'],
51
+ };
52
+ async execute(args) {
53
+ const filePath = path.resolve(args.path);
54
+ if (!fs.existsSync(filePath)) {
55
+ throw new Error(`File not found: ${filePath}`);
56
+ }
57
+ const stat = fs.statSync(filePath);
58
+ if (stat.isDirectory()) {
59
+ throw new Error(`Path is a directory: ${filePath}. Use glob to list files.`);
60
+ }
61
+ if (stat.size > 2 * 1024 * 1024) {
62
+ throw new Error(`File too large (${Math.round(stat.size / 1024)}KB). Use offset/limit to read in chunks.`);
63
+ }
64
+ const content = fs.readFileSync(filePath, 'utf-8');
65
+ const lines = content.split('\n');
66
+ const offset = Math.max(0, (args.offset || 1) - 1);
67
+ const limit = args.limit || lines.length;
68
+ const slice = lines.slice(offset, offset + limit);
69
+ return slice
70
+ .map((line, i) => `${String(offset + i + 1).padStart(5)}\t${line}`)
71
+ .join('\n');
72
+ }
73
+ }
74
+ exports.ReadFileTool = ReadFileTool;
75
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1,18 @@
1
+ import { Tool } from '../types';
2
+ export declare class ThinkTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ thought: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ };
14
+ required: string[];
15
+ };
16
+ execute(args: Record<string, unknown>): Promise<string>;
17
+ }
18
+ //# sourceMappingURL=think.d.ts.map
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ThinkTool = void 0;
4
+ class ThinkTool {
5
+ name = 'think';
6
+ description = 'A reasoning scratchpad. Use to plan your approach, analyze code, or work through complex problems before taking action. No side effects.';
7
+ permission = 'auto';
8
+ parameters = {
9
+ type: 'object',
10
+ properties: {
11
+ thought: { type: 'string', description: 'Your reasoning, analysis, or plan' },
12
+ },
13
+ required: ['thought'],
14
+ };
15
+ async execute(args) {
16
+ return 'Thought recorded.';
17
+ }
18
+ }
19
+ exports.ThinkTool = ThinkTool;
20
+ //# sourceMappingURL=think.js.map
@@ -0,0 +1,36 @@
1
+ import { Tool } from '../types';
2
+ export declare class WebFetchTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ url: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ method: {
14
+ type: string;
15
+ description: string;
16
+ enum: string[];
17
+ };
18
+ headers: {
19
+ type: string;
20
+ description: string;
21
+ };
22
+ body: {
23
+ type: string;
24
+ description: string;
25
+ };
26
+ json: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ };
31
+ required: string[];
32
+ };
33
+ execute(args: Record<string, unknown>): Promise<string>;
34
+ private htmlToText;
35
+ }
36
+ //# sourceMappingURL=web-fetch.d.ts.map
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebFetchTool = void 0;
4
+ class WebFetchTool {
5
+ name = 'web_fetch';
6
+ description = 'Make HTTP requests to URLs or APIs. Fetch web pages, call REST APIs, post data. Supports GET, POST, PUT, PATCH, DELETE.';
7
+ permission = 'prompt';
8
+ parameters = {
9
+ type: 'object',
10
+ properties: {
11
+ url: { type: 'string', description: 'URL to fetch' },
12
+ method: { type: 'string', description: 'HTTP method (default: GET)', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },
13
+ headers: { type: 'object', description: 'Request headers as key-value pairs' },
14
+ body: { type: 'string', description: 'Request body (for POST/PUT/PATCH)' },
15
+ json: { type: 'object', description: 'JSON body (auto-sets Content-Type)' },
16
+ },
17
+ required: ['url'],
18
+ };
19
+ async execute(args) {
20
+ const url = args.url;
21
+ const method = args.method || 'GET';
22
+ const headers = args.headers || {};
23
+ let body;
24
+ if (args.json) {
25
+ body = JSON.stringify(args.json);
26
+ if (!headers['Content-Type'] && !headers['content-type']) {
27
+ headers['Content-Type'] = 'application/json';
28
+ }
29
+ }
30
+ else if (args.body) {
31
+ body = args.body;
32
+ }
33
+ try {
34
+ const res = await fetch(url, {
35
+ method,
36
+ headers,
37
+ body,
38
+ signal: AbortSignal.timeout(30000),
39
+ });
40
+ const contentType = res.headers.get('content-type') || '';
41
+ const responseText = await res.text();
42
+ // Truncate very large responses
43
+ const maxLen = 50000;
44
+ const truncated = responseText.length > maxLen
45
+ ? responseText.substring(0, maxLen) + `\n\n... (truncated, ${responseText.length} total chars)`
46
+ : responseText;
47
+ const statusLine = `HTTP ${res.status} ${res.statusText}`;
48
+ // For HTML, strip tags to get readable text
49
+ if (contentType.includes('text/html')) {
50
+ const text = this.htmlToText(truncated);
51
+ return `${statusLine}\n\n${text}`;
52
+ }
53
+ return `${statusLine}\n\n${truncated}`;
54
+ }
55
+ catch (err) {
56
+ const msg = err instanceof Error ? err.message : String(err);
57
+ return `Error: ${msg}`;
58
+ }
59
+ }
60
+ htmlToText(html) {
61
+ return html
62
+ // Remove script/style blocks
63
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
64
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
65
+ // Convert common block elements to newlines
66
+ .replace(/<\/?(div|p|br|h[1-6]|li|tr|blockquote|pre|section|article|header|footer|nav|main)[^>]*>/gi, '\n')
67
+ // Remove all remaining tags
68
+ .replace(/<[^>]+>/g, '')
69
+ // Decode common entities
70
+ .replace(/&amp;/g, '&')
71
+ .replace(/&lt;/g, '<')
72
+ .replace(/&gt;/g, '>')
73
+ .replace(/&quot;/g, '"')
74
+ .replace(/&#39;/g, "'")
75
+ .replace(/&nbsp;/g, ' ')
76
+ // Clean up whitespace
77
+ .replace(/[ \t]+/g, ' ')
78
+ .replace(/\n\s*\n\s*\n/g, '\n\n')
79
+ .trim();
80
+ }
81
+ }
82
+ exports.WebFetchTool = WebFetchTool;
83
+ //# sourceMappingURL=web-fetch.js.map
@@ -0,0 +1,22 @@
1
+ import { Tool } from '../types';
2
+ export declare class WriteFileTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ path: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ content: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ };
18
+ required: string[];
19
+ };
20
+ execute(args: Record<string, unknown>): Promise<string>;
21
+ }
22
+ //# sourceMappingURL=write.d.ts.map
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WriteFileTool = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class WriteFileTool {
40
+ name = 'write_file';
41
+ description = 'Create a new file or overwrite an existing file with the given content.';
42
+ permission = 'prompt';
43
+ parameters = {
44
+ type: 'object',
45
+ properties: {
46
+ path: { type: 'string', description: 'Path to the file to write' },
47
+ content: { type: 'string', description: 'Content to write to the file' },
48
+ },
49
+ required: ['path', 'content'],
50
+ };
51
+ async execute(args) {
52
+ const filePath = path.resolve(args.path);
53
+ const content = args.content;
54
+ const dir = path.dirname(filePath);
55
+ if (!fs.existsSync(dir)) {
56
+ fs.mkdirSync(dir, { recursive: true });
57
+ }
58
+ const existed = fs.existsSync(filePath);
59
+ fs.writeFileSync(filePath, content, 'utf-8');
60
+ const lines = content.split('\n').length;
61
+ return `${existed ? 'Overwrote' : 'Created'} ${filePath} (${lines} lines, ${content.length} bytes)`;
62
+ }
63
+ }
64
+ exports.WriteFileTool = WriteFileTool;
65
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1,82 @@
1
+ export interface Message {
2
+ role: 'system' | 'user' | 'assistant' | 'tool';
3
+ content: string;
4
+ tool_calls?: ToolCall[];
5
+ tool_call_id?: string;
6
+ name?: string;
7
+ }
8
+ export interface ToolCall {
9
+ id: string;
10
+ type: 'function';
11
+ function: {
12
+ name: string;
13
+ arguments: string;
14
+ };
15
+ }
16
+ export interface ToolResult {
17
+ tool_call_id: string;
18
+ content: string;
19
+ is_error?: boolean;
20
+ }
21
+ export interface Tool {
22
+ name: string;
23
+ description: string;
24
+ parameters: Record<string, unknown>;
25
+ permission: 'auto' | 'prompt' | 'always-ask';
26
+ execute(args: Record<string, unknown>): Promise<string>;
27
+ }
28
+ export interface ProviderConfig {
29
+ baseUrl: string;
30
+ apiKey?: string;
31
+ model: string;
32
+ }
33
+ export interface LLMProvider {
34
+ name: string;
35
+ chat(messages: Message[], tools?: ToolSchema[]): AsyncGenerator<StreamEvent>;
36
+ listModels?(): Promise<string[]>;
37
+ }
38
+ export interface ToolSchema {
39
+ type: 'function';
40
+ function: {
41
+ name: string;
42
+ description: string;
43
+ parameters: Record<string, unknown>;
44
+ };
45
+ }
46
+ export interface StreamEvent {
47
+ type: 'text' | 'thinking' | 'tool_call_start' | 'tool_call_delta' | 'tool_call_end' | 'usage' | 'done' | 'error';
48
+ text?: string;
49
+ toolCall?: Partial<ToolCall>;
50
+ error?: string;
51
+ usage?: UsageStats;
52
+ }
53
+ export interface UsageStats {
54
+ inputTokens?: number;
55
+ outputTokens?: number;
56
+ totalTokens?: number;
57
+ }
58
+ export interface AgentEvent {
59
+ type: 'thinking' | 'text' | 'tool_call' | 'tool_result' | 'done' | 'error' | 'compaction' | 'usage';
60
+ text?: string;
61
+ toolCall?: {
62
+ name: string;
63
+ args: Record<string, unknown>;
64
+ };
65
+ toolResult?: {
66
+ name: string;
67
+ result: string;
68
+ is_error?: boolean;
69
+ };
70
+ error?: string;
71
+ usage?: UsageStats;
72
+ }
73
+ export interface Config {
74
+ provider: string;
75
+ model: string;
76
+ baseUrl: string;
77
+ apiKey?: string;
78
+ maxIterations: number;
79
+ autoApprove: boolean;
80
+ contextBudget?: number;
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "codebot-ai",
3
+ "version": "1.0.0",
4
+ "description": "Local-first AI coding assistant. Zero dependencies. Works with Ollama, LM Studio, vLLM, Claude, GPT, Gemini, and more.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "codebot": "./bin/codebot"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/cli.js",
14
+ "test": "node --test dist/*.test.js dist/**/*.test.js",
15
+ "lint": "tsc --noEmit",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "ai",
20
+ "coding-assistant",
21
+ "ollama",
22
+ "local-llm",
23
+ "agent",
24
+ "cli",
25
+ "code-generation",
26
+ "claude",
27
+ "gpt",
28
+ "gemini",
29
+ "autonomous",
30
+ "agentic"
31
+ ],
32
+ "author": "Ascendral Software Development & Innovation",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/AscendralSoftware/codebot-ai.git"
37
+ },
38
+ "homepage": "https://github.com/AscendralSoftware/codebot-ai#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/AscendralSoftware/codebot-ai/issues"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "files": [
46
+ "dist/**/*.js",
47
+ "dist/**/*.d.ts",
48
+ "!dist/**/*.test.*",
49
+ "bin",
50
+ "README.md",
51
+ "LICENSE"
52
+ ],
53
+ "devDependencies": {
54
+ "typescript": "^5.5.0",
55
+ "@types/node": "^20.0.0"
56
+ }
57
+ }