gencode-ai 0.1.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 (274) hide show
  1. package/.env.example +11 -0
  2. package/CLAUDE.md +70 -0
  3. package/LICENSE +21 -0
  4. package/README.md +117 -0
  5. package/dist/agent/agent.d.ts +84 -0
  6. package/dist/agent/agent.d.ts.map +1 -0
  7. package/dist/agent/agent.js +233 -0
  8. package/dist/agent/agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +6 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/types.d.ts +47 -0
  14. package/dist/agent/types.d.ts.map +1 -0
  15. package/dist/agent/types.js +5 -0
  16. package/dist/agent/types.js.map +1 -0
  17. package/dist/cli/components/App.d.ts +14 -0
  18. package/dist/cli/components/App.d.ts.map +1 -0
  19. package/dist/cli/components/App.js +395 -0
  20. package/dist/cli/components/App.js.map +1 -0
  21. package/dist/cli/components/CommandSuggestions.d.ts +13 -0
  22. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
  23. package/dist/cli/components/CommandSuggestions.js +32 -0
  24. package/dist/cli/components/CommandSuggestions.js.map +1 -0
  25. package/dist/cli/components/Header.d.ts +9 -0
  26. package/dist/cli/components/Header.d.ts.map +1 -0
  27. package/dist/cli/components/Header.js +13 -0
  28. package/dist/cli/components/Header.js.map +1 -0
  29. package/dist/cli/components/Input.d.ts +13 -0
  30. package/dist/cli/components/Input.d.ts.map +1 -0
  31. package/dist/cli/components/Input.js +27 -0
  32. package/dist/cli/components/Input.js.map +1 -0
  33. package/dist/cli/components/Logo.d.ts +2 -0
  34. package/dist/cli/components/Logo.d.ts.map +1 -0
  35. package/dist/cli/components/Logo.js +8 -0
  36. package/dist/cli/components/Logo.js.map +1 -0
  37. package/dist/cli/components/Messages.d.ts +37 -0
  38. package/dist/cli/components/Messages.d.ts.map +1 -0
  39. package/dist/cli/components/Messages.js +106 -0
  40. package/dist/cli/components/Messages.js.map +1 -0
  41. package/dist/cli/components/ModelSelector.d.ts +13 -0
  42. package/dist/cli/components/ModelSelector.d.ts.map +1 -0
  43. package/dist/cli/components/ModelSelector.js +72 -0
  44. package/dist/cli/components/ModelSelector.js.map +1 -0
  45. package/dist/cli/components/Spinner.d.ts +12 -0
  46. package/dist/cli/components/Spinner.d.ts.map +1 -0
  47. package/dist/cli/components/Spinner.js +45 -0
  48. package/dist/cli/components/Spinner.js.map +1 -0
  49. package/dist/cli/components/index.d.ts +12 -0
  50. package/dist/cli/components/index.d.ts.map +1 -0
  51. package/dist/cli/components/index.js +12 -0
  52. package/dist/cli/components/index.js.map +1 -0
  53. package/dist/cli/components/theme.d.ts +31 -0
  54. package/dist/cli/components/theme.d.ts.map +1 -0
  55. package/dist/cli/components/theme.js +36 -0
  56. package/dist/cli/components/theme.js.map +1 -0
  57. package/dist/cli/index-legacy.d.ts +7 -0
  58. package/dist/cli/index-legacy.d.ts.map +1 -0
  59. package/dist/cli/index-legacy.js +431 -0
  60. package/dist/cli/index-legacy.js.map +1 -0
  61. package/dist/cli/index.d.ts +7 -0
  62. package/dist/cli/index.d.ts.map +1 -0
  63. package/dist/cli/index.js +116 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/ink-cli.d.ts +7 -0
  66. package/dist/cli/ink-cli.d.ts.map +1 -0
  67. package/dist/cli/ink-cli.js +105 -0
  68. package/dist/cli/ink-cli.js.map +1 -0
  69. package/dist/cli/session-picker.d.ts +16 -0
  70. package/dist/cli/session-picker.d.ts.map +1 -0
  71. package/dist/cli/session-picker.js +280 -0
  72. package/dist/cli/session-picker.js.map +1 -0
  73. package/dist/cli/ui.d.ts +61 -0
  74. package/dist/cli/ui.d.ts.map +1 -0
  75. package/dist/cli/ui.js +364 -0
  76. package/dist/cli/ui.js.map +1 -0
  77. package/dist/config/index.d.ts +7 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/manager.d.ts +31 -0
  82. package/dist/config/manager.d.ts.map +1 -0
  83. package/dist/config/manager.js +65 -0
  84. package/dist/config/manager.js.map +1 -0
  85. package/dist/config/types.d.ts +22 -0
  86. package/dist/config/types.d.ts.map +1 -0
  87. package/dist/config/types.js +6 -0
  88. package/dist/config/types.js.map +1 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +21 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/memory/index.d.ts +10 -0
  94. package/dist/memory/index.d.ts.map +1 -0
  95. package/dist/memory/index.js +9 -0
  96. package/dist/memory/index.js.map +1 -0
  97. package/dist/memory/init.d.ts +20 -0
  98. package/dist/memory/init.d.ts.map +1 -0
  99. package/dist/memory/init.js +332 -0
  100. package/dist/memory/init.js.map +1 -0
  101. package/dist/memory/manager.d.ts +85 -0
  102. package/dist/memory/manager.d.ts.map +1 -0
  103. package/dist/memory/manager.js +234 -0
  104. package/dist/memory/manager.js.map +1 -0
  105. package/dist/memory/types.d.ts +74 -0
  106. package/dist/memory/types.d.ts.map +1 -0
  107. package/dist/memory/types.js +6 -0
  108. package/dist/memory/types.js.map +1 -0
  109. package/dist/permissions/index.d.ts +7 -0
  110. package/dist/permissions/index.d.ts.map +1 -0
  111. package/dist/permissions/index.js +6 -0
  112. package/dist/permissions/index.js.map +1 -0
  113. package/dist/permissions/manager.d.ts +32 -0
  114. package/dist/permissions/manager.d.ts.map +1 -0
  115. package/dist/permissions/manager.js +79 -0
  116. package/dist/permissions/manager.js.map +1 -0
  117. package/dist/permissions/types.d.ts +14 -0
  118. package/dist/permissions/types.d.ts.map +1 -0
  119. package/dist/permissions/types.js +17 -0
  120. package/dist/permissions/types.js.map +1 -0
  121. package/dist/providers/anthropic.d.ts +20 -0
  122. package/dist/providers/anthropic.d.ts.map +1 -0
  123. package/dist/providers/anthropic.js +185 -0
  124. package/dist/providers/anthropic.js.map +1 -0
  125. package/dist/providers/gemini.d.ts +21 -0
  126. package/dist/providers/gemini.d.ts.map +1 -0
  127. package/dist/providers/gemini.js +241 -0
  128. package/dist/providers/gemini.js.map +1 -0
  129. package/dist/providers/index.d.ts +34 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +72 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai.d.ts +19 -0
  134. package/dist/providers/openai.d.ts.map +1 -0
  135. package/dist/providers/openai.js +221 -0
  136. package/dist/providers/openai.js.map +1 -0
  137. package/dist/providers/types.d.ts +125 -0
  138. package/dist/providers/types.d.ts.map +1 -0
  139. package/dist/providers/types.js +6 -0
  140. package/dist/providers/types.js.map +1 -0
  141. package/dist/session/index.d.ts +6 -0
  142. package/dist/session/index.d.ts.map +1 -0
  143. package/dist/session/index.js +6 -0
  144. package/dist/session/index.js.map +1 -0
  145. package/dist/session/manager.d.ts +101 -0
  146. package/dist/session/manager.d.ts.map +1 -0
  147. package/dist/session/manager.js +295 -0
  148. package/dist/session/manager.js.map +1 -0
  149. package/dist/session/types.d.ts +39 -0
  150. package/dist/session/types.d.ts.map +1 -0
  151. package/dist/session/types.js +10 -0
  152. package/dist/session/types.js.map +1 -0
  153. package/dist/tools/builtin/bash.d.ts +7 -0
  154. package/dist/tools/builtin/bash.d.ts.map +1 -0
  155. package/dist/tools/builtin/bash.js +80 -0
  156. package/dist/tools/builtin/bash.js.map +1 -0
  157. package/dist/tools/builtin/edit.d.ts +7 -0
  158. package/dist/tools/builtin/edit.d.ts.map +1 -0
  159. package/dist/tools/builtin/edit.js +32 -0
  160. package/dist/tools/builtin/edit.js.map +1 -0
  161. package/dist/tools/builtin/glob.d.ts +7 -0
  162. package/dist/tools/builtin/glob.d.ts.map +1 -0
  163. package/dist/tools/builtin/glob.js +36 -0
  164. package/dist/tools/builtin/glob.js.map +1 -0
  165. package/dist/tools/builtin/grep.d.ts +7 -0
  166. package/dist/tools/builtin/grep.d.ts.map +1 -0
  167. package/dist/tools/builtin/grep.js +59 -0
  168. package/dist/tools/builtin/grep.js.map +1 -0
  169. package/dist/tools/builtin/read.d.ts +7 -0
  170. package/dist/tools/builtin/read.d.ts.map +1 -0
  171. package/dist/tools/builtin/read.js +29 -0
  172. package/dist/tools/builtin/read.js.map +1 -0
  173. package/dist/tools/builtin/write.d.ts +7 -0
  174. package/dist/tools/builtin/write.d.ts.map +1 -0
  175. package/dist/tools/builtin/write.js +24 -0
  176. package/dist/tools/builtin/write.js.map +1 -0
  177. package/dist/tools/index.d.ts +38 -0
  178. package/dist/tools/index.d.ts.map +1 -0
  179. package/dist/tools/index.js +32 -0
  180. package/dist/tools/index.js.map +1 -0
  181. package/dist/tools/registry.d.ts +22 -0
  182. package/dist/tools/registry.d.ts.map +1 -0
  183. package/dist/tools/registry.js +71 -0
  184. package/dist/tools/registry.js.map +1 -0
  185. package/dist/tools/types.d.ts +62 -0
  186. package/dist/tools/types.d.ts.map +1 -0
  187. package/dist/tools/types.js +126 -0
  188. package/dist/tools/types.js.map +1 -0
  189. package/docs/README.md +16 -0
  190. package/docs/proposals/0001-web-fetch-tool.md +293 -0
  191. package/docs/proposals/0002-web-search-tool.md +306 -0
  192. package/docs/proposals/0003-task-subagents.md +333 -0
  193. package/docs/proposals/0004-plan-mode.md +338 -0
  194. package/docs/proposals/0005-todo-system.md +299 -0
  195. package/docs/proposals/0006-memory-system.md +539 -0
  196. package/docs/proposals/0007-context-management.md +429 -0
  197. package/docs/proposals/0008-checkpointing.md +327 -0
  198. package/docs/proposals/0009-hooks-system.md +343 -0
  199. package/docs/proposals/0010-mcp-integration.md +382 -0
  200. package/docs/proposals/0011-custom-commands.md +374 -0
  201. package/docs/proposals/0012-ask-user-question.md +317 -0
  202. package/docs/proposals/0013-multi-edit-tool.md +345 -0
  203. package/docs/proposals/0014-lsp-tool.md +478 -0
  204. package/docs/proposals/0015-ls-tool.md +407 -0
  205. package/docs/proposals/0016-kill-shell-tool.md +455 -0
  206. package/docs/proposals/0017-background-tasks.md +489 -0
  207. package/docs/proposals/0018-parallel-tool-execution.md +415 -0
  208. package/docs/proposals/0019-session-enhancements.md +462 -0
  209. package/docs/proposals/0020-session-summarization.md +447 -0
  210. package/docs/proposals/0021-skills-system.md +409 -0
  211. package/docs/proposals/0022-plugin-system.md +467 -0
  212. package/docs/proposals/0023-permission-enhancements.md +470 -0
  213. package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
  214. package/docs/proposals/0025-cost-tracking.md +447 -0
  215. package/docs/proposals/0026-git-integration.md +475 -0
  216. package/docs/proposals/0027-enhanced-read-tool.md +514 -0
  217. package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
  218. package/docs/proposals/0029-notebook-edit-tool.md +413 -0
  219. package/docs/proposals/0030-plugin-marketplace.md +360 -0
  220. package/docs/proposals/0031-command-suggestions.md +295 -0
  221. package/docs/proposals/0032-ide-integrations.md +328 -0
  222. package/docs/proposals/0033-enterprise-deployment.md +221 -0
  223. package/docs/proposals/0034-sandboxing.md +273 -0
  224. package/docs/proposals/0035-auto-updater.md +311 -0
  225. package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
  226. package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
  227. package/docs/proposals/0038-interactive-cli-ui.md +373 -0
  228. package/docs/proposals/0039-streaming-enhancements.md +359 -0
  229. package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
  230. package/docs/proposals/README.md +84 -0
  231. package/docs/proposals/TEMPLATE.md +57 -0
  232. package/docs/proposals/research/claude-code-research.md +307 -0
  233. package/examples/agent-demo.ts +115 -0
  234. package/examples/basic.ts +166 -0
  235. package/package.json +50 -0
  236. package/src/agent/agent.ts +276 -0
  237. package/src/agent/index.ts +6 -0
  238. package/src/agent/types.ts +62 -0
  239. package/src/cli/components/App.tsx +565 -0
  240. package/src/cli/components/CommandSuggestions.tsx +58 -0
  241. package/src/cli/components/Header.tsx +36 -0
  242. package/src/cli/components/Input.tsx +60 -0
  243. package/src/cli/components/Logo.tsx +16 -0
  244. package/src/cli/components/Messages.tsx +210 -0
  245. package/src/cli/components/ModelSelector.tsx +135 -0
  246. package/src/cli/components/Spinner.tsx +72 -0
  247. package/src/cli/components/index.ts +21 -0
  248. package/src/cli/components/theme.ts +36 -0
  249. package/src/cli/index.tsx +136 -0
  250. package/src/config/index.ts +7 -0
  251. package/src/config/manager.ts +77 -0
  252. package/src/config/types.ts +25 -0
  253. package/src/index.ts +86 -0
  254. package/src/permissions/index.ts +7 -0
  255. package/src/permissions/manager.ts +97 -0
  256. package/src/permissions/types.ts +29 -0
  257. package/src/providers/anthropic.ts +224 -0
  258. package/src/providers/gemini.ts +295 -0
  259. package/src/providers/index.ts +97 -0
  260. package/src/providers/openai.ts +261 -0
  261. package/src/providers/types.ts +181 -0
  262. package/src/session/index.ts +6 -0
  263. package/src/session/manager.ts +354 -0
  264. package/src/session/types.ts +49 -0
  265. package/src/tools/builtin/bash.ts +92 -0
  266. package/src/tools/builtin/edit.ts +37 -0
  267. package/src/tools/builtin/glob.ts +42 -0
  268. package/src/tools/builtin/grep.ts +67 -0
  269. package/src/tools/builtin/read.ts +34 -0
  270. package/src/tools/builtin/write.ts +27 -0
  271. package/src/tools/index.ts +36 -0
  272. package/src/tools/registry.ts +83 -0
  273. package/src/tools/types.ts +172 -0
  274. package/tsconfig.json +21 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Settings Manager - Persists user settings (Claude Code style)
3
+ */
4
+
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+ import type { Settings, SettingsManagerOptions } from './types.js';
9
+ import { DEFAULT_SETTINGS_DIR, SETTINGS_FILE_NAME } from './types.js';
10
+
11
+ export class SettingsManager {
12
+ private settingsDir: string;
13
+ private settingsPath: string;
14
+ private settings: Settings = {};
15
+
16
+ constructor(options: SettingsManagerOptions = {}) {
17
+ const dir = options.settingsDir ?? DEFAULT_SETTINGS_DIR;
18
+ this.settingsDir = dir.replace('~', os.homedir());
19
+ this.settingsPath = path.join(this.settingsDir, SETTINGS_FILE_NAME);
20
+ }
21
+
22
+ /**
23
+ * Ensure settings directory exists
24
+ */
25
+ private async ensureDir(): Promise<void> {
26
+ try {
27
+ await fs.mkdir(this.settingsDir, { recursive: true });
28
+ } catch {
29
+ // Directory may already exist
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Load settings from disk
35
+ */
36
+ async load(): Promise<Settings> {
37
+ try {
38
+ const content = await fs.readFile(this.settingsPath, 'utf-8');
39
+ this.settings = JSON.parse(content);
40
+ return this.settings;
41
+ } catch {
42
+ // File doesn't exist or is invalid
43
+ this.settings = {};
44
+ return this.settings;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Save settings to disk (merges with existing)
50
+ */
51
+ async save(updates: Partial<Settings>): Promise<void> {
52
+ await this.ensureDir();
53
+
54
+ // Merge updates with existing settings
55
+ this.settings = { ...this.settings, ...updates };
56
+
57
+ await fs.writeFile(
58
+ this.settingsPath,
59
+ JSON.stringify(this.settings, null, 2),
60
+ 'utf-8'
61
+ );
62
+ }
63
+
64
+ /**
65
+ * Get current settings
66
+ */
67
+ get(): Settings {
68
+ return { ...this.settings };
69
+ }
70
+
71
+ /**
72
+ * Get settings file path
73
+ */
74
+ getPath(): string {
75
+ return this.settingsPath;
76
+ }
77
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Settings Types - User settings persistence (Claude Code style)
3
+ */
4
+
5
+ export type ProviderName = 'openai' | 'anthropic' | 'gemini';
6
+
7
+ /**
8
+ * Settings file structure (~/.gencode/settings.json)
9
+ * Similar to Claude Code's settings.json
10
+ */
11
+ export interface Settings {
12
+ model?: string;
13
+ provider?: ProviderName;
14
+ permissions?: {
15
+ allow?: string[];
16
+ deny?: string[];
17
+ };
18
+ }
19
+
20
+ export interface SettingsManagerOptions {
21
+ settingsDir?: string;
22
+ }
23
+
24
+ export const DEFAULT_SETTINGS_DIR = '~/.gencode';
25
+ export const SETTINGS_FILE_NAME = 'settings.json';
package/src/index.ts ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Recode - Multi-LLM Agent SDK
3
+ *
4
+ * A unified SDK for building AI agents with support for
5
+ * OpenAI, Anthropic, and Google Gemini models.
6
+ */
7
+
8
+ // Providers
9
+ export {
10
+ // Types
11
+ type LLMProvider,
12
+ type Message,
13
+ type MessageRole,
14
+ type MessageContent,
15
+ type TextContent,
16
+ type ToolUseContent,
17
+ type ToolResultContent,
18
+ type ToolDefinition,
19
+ type ToolCall,
20
+ type ToolResult,
21
+ type CompletionOptions,
22
+ type CompletionResponse,
23
+ type StreamChunk,
24
+ type StopReason,
25
+ type OpenAIConfig,
26
+ type AnthropicConfig,
27
+ type GeminiConfig,
28
+ type ProviderConfig,
29
+ type ProviderName,
30
+ // Providers
31
+ OpenAIProvider,
32
+ AnthropicProvider,
33
+ GeminiProvider,
34
+ // Factory
35
+ createProvider,
36
+ inferProvider,
37
+ ModelAliases,
38
+ } from './providers/index.js';
39
+
40
+ // Tools
41
+ export {
42
+ type Tool,
43
+ type ToolContext,
44
+ type ToolResult as ToolExecutionResult,
45
+ ToolRegistry,
46
+ createDefaultRegistry,
47
+ builtinTools,
48
+ readTool,
49
+ writeTool,
50
+ editTool,
51
+ bashTool,
52
+ globTool,
53
+ grepTool,
54
+ } from './tools/index.js';
55
+
56
+ // Permissions
57
+ export {
58
+ type PermissionMode,
59
+ type PermissionRule,
60
+ type PermissionConfig,
61
+ type ConfirmCallback,
62
+ PermissionManager,
63
+ DEFAULT_PERMISSION_CONFIG,
64
+ } from './permissions/index.js';
65
+
66
+ // Agent
67
+ export {
68
+ type AgentConfig,
69
+ type AgentEvent,
70
+ type AgentEventText,
71
+ type AgentEventToolStart,
72
+ type AgentEventToolResult,
73
+ type AgentEventError,
74
+ type AgentEventDone,
75
+ Agent,
76
+ } from './agent/index.js';
77
+
78
+ // Session
79
+ export {
80
+ type Session,
81
+ type SessionMetadata,
82
+ type SessionListItem,
83
+ type SessionConfig,
84
+ SessionManager,
85
+ DEFAULT_SESSION_CONFIG,
86
+ } from './session/index.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Permission System
3
+ */
4
+
5
+ export * from './types.js';
6
+ export { PermissionManager } from './manager.js';
7
+ export type { ConfirmCallback } from './manager.js';
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Permission Manager - Controls tool execution permissions
3
+ */
4
+
5
+ import type { PermissionConfig, PermissionMode } from './types.js';
6
+ import { DEFAULT_PERMISSION_CONFIG } from './types.js';
7
+
8
+ export type ConfirmCallback = (
9
+ tool: string,
10
+ input: unknown
11
+ ) => Promise<boolean>;
12
+
13
+ export class PermissionManager {
14
+ private config: PermissionConfig;
15
+ private confirmCallback?: ConfirmCallback;
16
+ private approvedTools: Set<string> = new Set();
17
+
18
+ constructor(config?: Partial<PermissionConfig>) {
19
+ this.config = {
20
+ ...DEFAULT_PERMISSION_CONFIG,
21
+ ...config,
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Set the confirmation callback
27
+ */
28
+ setConfirmCallback(callback: ConfirmCallback): void {
29
+ this.confirmCallback = callback;
30
+ }
31
+
32
+ /**
33
+ * Get the permission mode for a tool
34
+ */
35
+ getModeForTool(tool: string): PermissionMode {
36
+ for (const rule of this.config.rules) {
37
+ if (typeof rule.tool === 'string') {
38
+ if (rule.tool === tool) {
39
+ return rule.mode;
40
+ }
41
+ } else if (rule.tool.test(tool)) {
42
+ return rule.mode;
43
+ }
44
+ }
45
+ return this.config.defaultMode;
46
+ }
47
+
48
+ /**
49
+ * Check if a tool can be executed
50
+ */
51
+ async checkPermission(tool: string, input: unknown): Promise<boolean> {
52
+ const mode = this.getModeForTool(tool);
53
+
54
+ switch (mode) {
55
+ case 'auto':
56
+ return true;
57
+
58
+ case 'deny':
59
+ return false;
60
+
61
+ case 'confirm':
62
+ // Check if already approved this session
63
+ const key = `${tool}:${JSON.stringify(input)}`;
64
+ if (this.approvedTools.has(key)) {
65
+ return true;
66
+ }
67
+
68
+ if (!this.confirmCallback) {
69
+ // No callback, auto-approve in non-interactive mode
70
+ return true;
71
+ }
72
+
73
+ const approved = await this.confirmCallback(tool, input);
74
+ if (approved) {
75
+ this.approvedTools.add(key);
76
+ }
77
+ return approved;
78
+
79
+ default:
80
+ return false;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Approve a tool for this session
86
+ */
87
+ approveToolForSession(tool: string): void {
88
+ this.approvedTools.add(tool);
89
+ }
90
+
91
+ /**
92
+ * Clear all session approvals
93
+ */
94
+ clearApprovals(): void {
95
+ this.approvedTools.clear();
96
+ }
97
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Permission System Types
3
+ */
4
+
5
+ export type PermissionMode = 'auto' | 'confirm' | 'deny';
6
+
7
+ export interface PermissionRule {
8
+ tool: string | RegExp;
9
+ mode: PermissionMode;
10
+ }
11
+
12
+ export interface PermissionConfig {
13
+ defaultMode: PermissionMode;
14
+ rules: PermissionRule[];
15
+ }
16
+
17
+ export const DEFAULT_PERMISSION_CONFIG: PermissionConfig = {
18
+ defaultMode: 'confirm',
19
+ rules: [
20
+ // Read-only tools are auto-approved
21
+ { tool: 'Read', mode: 'auto' },
22
+ { tool: 'Glob', mode: 'auto' },
23
+ { tool: 'Grep', mode: 'auto' },
24
+ // Write operations require confirmation
25
+ { tool: 'Write', mode: 'confirm' },
26
+ { tool: 'Edit', mode: 'confirm' },
27
+ { tool: 'Bash', mode: 'confirm' },
28
+ ],
29
+ };
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Anthropic Provider Implementation
3
+ * Supports Claude 3.5 Sonnet, Claude 3 Opus, Claude 3 Haiku, etc.
4
+ */
5
+
6
+ import Anthropic from '@anthropic-ai/sdk';
7
+ import type {
8
+ LLMProvider,
9
+ CompletionOptions,
10
+ CompletionResponse,
11
+ StreamChunk,
12
+ Message,
13
+ MessageContent,
14
+ ToolDefinition,
15
+ StopReason,
16
+ AnthropicConfig,
17
+ ModelInfo,
18
+ } from './types.js';
19
+
20
+ type AnthropicMessage = Anthropic.MessageParam;
21
+ type AnthropicTool = Anthropic.Tool;
22
+ type AnthropicContent = Anthropic.ContentBlockParam;
23
+
24
+ export class AnthropicProvider implements LLMProvider {
25
+ readonly name = 'anthropic';
26
+ private client: Anthropic;
27
+
28
+ constructor(config: AnthropicConfig = {}) {
29
+ this.client = new Anthropic({
30
+ apiKey: config.apiKey ?? process.env.ANTHROPIC_API_KEY,
31
+ baseURL: config.baseURL,
32
+ });
33
+ }
34
+
35
+ async complete(options: CompletionOptions): Promise<CompletionResponse> {
36
+ const messages = this.convertMessages(options.messages);
37
+ const tools = options.tools ? this.convertTools(options.tools) : undefined;
38
+
39
+ const response = await this.client.messages.create({
40
+ model: options.model,
41
+ messages,
42
+ tools,
43
+ system: options.systemPrompt,
44
+ max_tokens: options.maxTokens ?? 4096,
45
+ temperature: options.temperature,
46
+ });
47
+
48
+ return this.convertResponse(response);
49
+ }
50
+
51
+ async *stream(options: CompletionOptions): AsyncGenerator<StreamChunk, void, unknown> {
52
+ const messages = this.convertMessages(options.messages);
53
+ const tools = options.tools ? this.convertTools(options.tools) : undefined;
54
+
55
+ const stream = this.client.messages.stream({
56
+ model: options.model,
57
+ messages,
58
+ tools,
59
+ system: options.systemPrompt,
60
+ max_tokens: options.maxTokens ?? 4096,
61
+ temperature: options.temperature,
62
+ });
63
+
64
+ const toolInputBuffers: Map<number, { id: string; name: string; input: string }> = new Map();
65
+
66
+ for await (const event of stream) {
67
+ if (event.type === 'content_block_start') {
68
+ const block = event.content_block;
69
+
70
+ if (block.type === 'tool_use') {
71
+ toolInputBuffers.set(event.index, {
72
+ id: block.id,
73
+ name: block.name,
74
+ input: '',
75
+ });
76
+ yield { type: 'tool_start', id: block.id, name: block.name };
77
+ }
78
+ } else if (event.type === 'content_block_delta') {
79
+ const delta = event.delta;
80
+
81
+ if (delta.type === 'text_delta') {
82
+ yield { type: 'text', text: delta.text };
83
+ } else if (delta.type === 'input_json_delta') {
84
+ const buffer = toolInputBuffers.get(event.index);
85
+ if (buffer) {
86
+ buffer.input += delta.partial_json;
87
+ yield { type: 'tool_input', id: buffer.id, input: delta.partial_json };
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ // Get final message
94
+ const finalMessage = await stream.finalMessage();
95
+ const content = this.convertContent(finalMessage.content);
96
+
97
+ yield {
98
+ type: 'done',
99
+ response: {
100
+ content,
101
+ stopReason: this.convertStopReason(finalMessage.stop_reason),
102
+ usage: {
103
+ inputTokens: finalMessage.usage.input_tokens,
104
+ outputTokens: finalMessage.usage.output_tokens,
105
+ },
106
+ },
107
+ };
108
+ }
109
+
110
+ private convertMessages(messages: Message[]): AnthropicMessage[] {
111
+ const result: AnthropicMessage[] = [];
112
+
113
+ for (const msg of messages) {
114
+ // Skip system messages - handled separately
115
+ if (msg.role === 'system') {
116
+ continue;
117
+ }
118
+
119
+ if (msg.role === 'user') {
120
+ const content = this.convertToAnthropicContent(msg.content, 'user');
121
+ result.push({ role: 'user', content });
122
+ } else if (msg.role === 'assistant') {
123
+ const content = this.convertToAnthropicContent(msg.content, 'assistant');
124
+ result.push({ role: 'assistant', content });
125
+ }
126
+ }
127
+
128
+ return result;
129
+ }
130
+
131
+ private convertToAnthropicContent(
132
+ content: string | MessageContent[],
133
+ role: 'user' | 'assistant'
134
+ ): AnthropicContent[] | string {
135
+ if (typeof content === 'string') {
136
+ return content;
137
+ }
138
+
139
+ const result: AnthropicContent[] = [];
140
+
141
+ for (const item of content) {
142
+ if (item.type === 'text') {
143
+ result.push({ type: 'text', text: item.text });
144
+ } else if (item.type === 'tool_use' && role === 'assistant') {
145
+ result.push({
146
+ type: 'tool_use',
147
+ id: item.id,
148
+ name: item.name,
149
+ input: item.input,
150
+ });
151
+ } else if (item.type === 'tool_result' && role === 'user') {
152
+ result.push({
153
+ type: 'tool_result',
154
+ tool_use_id: item.toolUseId,
155
+ content: item.content,
156
+ is_error: item.isError,
157
+ });
158
+ }
159
+ }
160
+
161
+ return result.length > 0 ? result : '';
162
+ }
163
+
164
+ private convertTools(tools: ToolDefinition[]): AnthropicTool[] {
165
+ return tools.map((tool) => ({
166
+ name: tool.name,
167
+ description: tool.description,
168
+ input_schema: tool.parameters as Anthropic.Tool.InputSchema,
169
+ }));
170
+ }
171
+
172
+ private convertResponse(response: Anthropic.Message): CompletionResponse {
173
+ return {
174
+ content: this.convertContent(response.content),
175
+ stopReason: this.convertStopReason(response.stop_reason),
176
+ usage: {
177
+ inputTokens: response.usage.input_tokens,
178
+ outputTokens: response.usage.output_tokens,
179
+ },
180
+ };
181
+ }
182
+
183
+ private convertContent(content: Anthropic.ContentBlock[]): MessageContent[] {
184
+ return content.map((block) => {
185
+ if (block.type === 'text') {
186
+ return { type: 'text' as const, text: block.text };
187
+ } else if (block.type === 'tool_use') {
188
+ return {
189
+ type: 'tool_use' as const,
190
+ id: block.id,
191
+ name: block.name,
192
+ input: block.input as Record<string, unknown>,
193
+ };
194
+ }
195
+ // Fallback for unknown types
196
+ return { type: 'text' as const, text: '' };
197
+ });
198
+ }
199
+
200
+ private convertStopReason(reason: Anthropic.Message['stop_reason']): StopReason {
201
+ switch (reason) {
202
+ case 'tool_use':
203
+ return 'tool_use';
204
+ case 'max_tokens':
205
+ return 'max_tokens';
206
+ case 'stop_sequence':
207
+ return 'stop_sequence';
208
+ case 'end_turn':
209
+ default:
210
+ return 'end_turn';
211
+ }
212
+ }
213
+
214
+ async listModels(): Promise<ModelInfo[]> {
215
+ const models: ModelInfo[] = [];
216
+ for await (const model of this.client.models.list()) {
217
+ models.push({
218
+ id: model.id,
219
+ name: model.display_name || model.id,
220
+ });
221
+ }
222
+ return models;
223
+ }
224
+ }