@teleforge-ai/anya 0.5.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 (200) hide show
  1. package/README.md +69 -0
  2. package/assets/anya.jpg +0 -0
  3. package/assets/anya.png +0 -0
  4. package/dist/chat/session.d.ts +15 -0
  5. package/dist/chat/session.d.ts.map +1 -0
  6. package/dist/chat/session.js +59 -0
  7. package/dist/chat/session.js.map +1 -0
  8. package/dist/chat/stream.d.ts +13 -0
  9. package/dist/chat/stream.d.ts.map +1 -0
  10. package/dist/chat/stream.js +86 -0
  11. package/dist/chat/stream.js.map +1 -0
  12. package/dist/commands/providerFactory.d.ts +12 -0
  13. package/dist/commands/providerFactory.d.ts.map +1 -0
  14. package/dist/commands/providerFactory.js +73 -0
  15. package/dist/commands/providerFactory.js.map +1 -0
  16. package/dist/config/encryption.d.ts +3 -0
  17. package/dist/config/encryption.d.ts.map +1 -0
  18. package/dist/config/encryption.js +47 -0
  19. package/dist/config/encryption.js.map +1 -0
  20. package/dist/config/schema.d.ts +94 -0
  21. package/dist/config/schema.d.ts.map +1 -0
  22. package/dist/config/schema.js +28 -0
  23. package/dist/config/schema.js.map +1 -0
  24. package/dist/config/store.d.ts +40 -0
  25. package/dist/config/store.d.ts.map +1 -0
  26. package/dist/config/store.js +195 -0
  27. package/dist/config/store.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +97 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/providers/anthropic.d.ts +10 -0
  33. package/dist/providers/anthropic.d.ts.map +1 -0
  34. package/dist/providers/anthropic.js +128 -0
  35. package/dist/providers/anthropic.js.map +1 -0
  36. package/dist/providers/base.d.ts +39 -0
  37. package/dist/providers/base.d.ts.map +1 -0
  38. package/dist/providers/base.js +28 -0
  39. package/dist/providers/base.js.map +1 -0
  40. package/dist/providers/custom.d.ts +11 -0
  41. package/dist/providers/custom.d.ts.map +1 -0
  42. package/dist/providers/custom.js +90 -0
  43. package/dist/providers/custom.js.map +1 -0
  44. package/dist/providers/deepseek.d.ts +10 -0
  45. package/dist/providers/deepseek.d.ts.map +1 -0
  46. package/dist/providers/deepseek.js +88 -0
  47. package/dist/providers/deepseek.js.map +1 -0
  48. package/dist/providers/google.d.ts +10 -0
  49. package/dist/providers/google.d.ts.map +1 -0
  50. package/dist/providers/google.js +131 -0
  51. package/dist/providers/google.js.map +1 -0
  52. package/dist/providers/groq.d.ts +10 -0
  53. package/dist/providers/groq.d.ts.map +1 -0
  54. package/dist/providers/groq.js +88 -0
  55. package/dist/providers/groq.js.map +1 -0
  56. package/dist/providers/index.d.ts +10 -0
  57. package/dist/providers/index.d.ts.map +1 -0
  58. package/dist/providers/index.js +39 -0
  59. package/dist/providers/index.js.map +1 -0
  60. package/dist/providers/mistral.d.ts +10 -0
  61. package/dist/providers/mistral.d.ts.map +1 -0
  62. package/dist/providers/mistral.js +88 -0
  63. package/dist/providers/mistral.js.map +1 -0
  64. package/dist/providers/ollama.d.ts +11 -0
  65. package/dist/providers/ollama.d.ts.map +1 -0
  66. package/dist/providers/ollama.js +82 -0
  67. package/dist/providers/ollama.js.map +1 -0
  68. package/dist/providers/openai.d.ts +10 -0
  69. package/dist/providers/openai.d.ts.map +1 -0
  70. package/dist/providers/openai.js +127 -0
  71. package/dist/providers/openai.js.map +1 -0
  72. package/dist/providers/opencode.d.ts +11 -0
  73. package/dist/providers/opencode.d.ts.map +1 -0
  74. package/dist/providers/opencode.js +99 -0
  75. package/dist/providers/opencode.js.map +1 -0
  76. package/dist/providers/openrouter.d.ts +10 -0
  77. package/dist/providers/openrouter.d.ts.map +1 -0
  78. package/dist/providers/openrouter.js +119 -0
  79. package/dist/providers/openrouter.js.map +1 -0
  80. package/dist/providers/together.d.ts +10 -0
  81. package/dist/providers/together.d.ts.map +1 -0
  82. package/dist/providers/together.js +88 -0
  83. package/dist/providers/together.js.map +1 -0
  84. package/dist/providers/xai.d.ts +10 -0
  85. package/dist/providers/xai.d.ts.map +1 -0
  86. package/dist/providers/xai.js +88 -0
  87. package/dist/providers/xai.js.map +1 -0
  88. package/dist/tui/ansi.d.ts +49 -0
  89. package/dist/tui/ansi.d.ts.map +1 -0
  90. package/dist/tui/ansi.js +208 -0
  91. package/dist/tui/ansi.js.map +1 -0
  92. package/dist/tui/components/anyaArt.d.ts +2 -0
  93. package/dist/tui/components/anyaArt.d.ts.map +1 -0
  94. package/dist/tui/components/anyaArt.js +20 -0
  95. package/dist/tui/components/anyaArt.js.map +1 -0
  96. package/dist/tui/components/dialog.d.ts +15 -0
  97. package/dist/tui/components/dialog.d.ts.map +1 -0
  98. package/dist/tui/components/dialog.js +115 -0
  99. package/dist/tui/components/dialog.js.map +1 -0
  100. package/dist/tui/components/messages.d.ts +10 -0
  101. package/dist/tui/components/messages.d.ts.map +1 -0
  102. package/dist/tui/components/messages.js +100 -0
  103. package/dist/tui/components/messages.js.map +1 -0
  104. package/dist/tui/render.d.ts +3 -0
  105. package/dist/tui/render.d.ts.map +1 -0
  106. package/dist/tui/render.js +137 -0
  107. package/dist/tui/render.js.map +1 -0
  108. package/dist/tui/screen.d.ts +19 -0
  109. package/dist/tui/screen.d.ts.map +1 -0
  110. package/dist/tui/screen.js +98 -0
  111. package/dist/tui/screen.js.map +1 -0
  112. package/dist/tui/state.d.ts +41 -0
  113. package/dist/tui/state.d.ts.map +1 -0
  114. package/dist/tui/state.js +306 -0
  115. package/dist/tui/state.js.map +1 -0
  116. package/dist/ui/App.d.ts +3 -0
  117. package/dist/ui/App.d.ts.map +1 -0
  118. package/dist/ui/App.js +207 -0
  119. package/dist/ui/App.js.map +1 -0
  120. package/dist/ui/components/CommandPalette.d.ts +8 -0
  121. package/dist/ui/components/CommandPalette.d.ts.map +1 -0
  122. package/dist/ui/components/CommandPalette.js +63 -0
  123. package/dist/ui/components/CommandPalette.js.map +1 -0
  124. package/dist/ui/components/HomeScreen.d.ts +8 -0
  125. package/dist/ui/components/HomeScreen.d.ts.map +1 -0
  126. package/dist/ui/components/HomeScreen.js +29 -0
  127. package/dist/ui/components/HomeScreen.js.map +1 -0
  128. package/dist/ui/components/ImageRenderer.d.ts +8 -0
  129. package/dist/ui/components/ImageRenderer.d.ts.map +1 -0
  130. package/dist/ui/components/ImageRenderer.js +42 -0
  131. package/dist/ui/components/ImageRenderer.js.map +1 -0
  132. package/dist/ui/components/InputBox.d.ts +12 -0
  133. package/dist/ui/components/InputBox.d.ts.map +1 -0
  134. package/dist/ui/components/InputBox.js +96 -0
  135. package/dist/ui/components/InputBox.js.map +1 -0
  136. package/dist/ui/components/MessageList.d.ts +13 -0
  137. package/dist/ui/components/MessageList.d.ts.map +1 -0
  138. package/dist/ui/components/MessageList.js +10 -0
  139. package/dist/ui/components/MessageList.js.map +1 -0
  140. package/dist/ui/components/ModelSelector.d.ts +9 -0
  141. package/dist/ui/components/ModelSelector.d.ts.map +1 -0
  142. package/dist/ui/components/ModelSelector.js +77 -0
  143. package/dist/ui/components/ModelSelector.js.map +1 -0
  144. package/dist/ui/components/ProviderForm.d.ts +8 -0
  145. package/dist/ui/components/ProviderForm.d.ts.map +1 -0
  146. package/dist/ui/components/ProviderForm.js +88 -0
  147. package/dist/ui/components/ProviderForm.js.map +1 -0
  148. package/dist/ui/components/SettingsPanel.d.ts +7 -0
  149. package/dist/ui/components/SettingsPanel.d.ts.map +1 -0
  150. package/dist/ui/components/SettingsPanel.js +87 -0
  151. package/dist/ui/components/SettingsPanel.js.map +1 -0
  152. package/dist/ui/components/StatusBar.d.ts +8 -0
  153. package/dist/ui/components/StatusBar.d.ts.map +1 -0
  154. package/dist/ui/components/StatusBar.js +15 -0
  155. package/dist/ui/components/StatusBar.js.map +1 -0
  156. package/dist/ui/components/StatusDashboard.d.ts +7 -0
  157. package/dist/ui/components/StatusDashboard.d.ts.map +1 -0
  158. package/dist/ui/components/StatusDashboard.js +29 -0
  159. package/dist/ui/components/StatusDashboard.js.map +1 -0
  160. package/dist/ui/components/TitleBar.d.ts +8 -0
  161. package/dist/ui/components/TitleBar.d.ts.map +1 -0
  162. package/dist/ui/components/TitleBar.js +7 -0
  163. package/dist/ui/components/TitleBar.js.map +1 -0
  164. package/dist/ui/hooks/useConfig.d.ts +28 -0
  165. package/dist/ui/hooks/useConfig.d.ts.map +1 -0
  166. package/dist/ui/hooks/useConfig.js +20 -0
  167. package/dist/ui/hooks/useConfig.js.map +1 -0
  168. package/dist/ui/hooks/useModels.d.ts +10 -0
  169. package/dist/ui/hooks/useModels.d.ts.map +1 -0
  170. package/dist/ui/hooks/useModels.js +30 -0
  171. package/dist/ui/hooks/useModels.js.map +1 -0
  172. package/dist/ui/hooks/useProviders.d.ts +18 -0
  173. package/dist/ui/hooks/useProviders.d.ts.map +1 -0
  174. package/dist/ui/hooks/useProviders.js +56 -0
  175. package/dist/ui/hooks/useProviders.js.map +1 -0
  176. package/dist/ui/theme.d.ts +22 -0
  177. package/dist/ui/theme.d.ts.map +1 -0
  178. package/dist/ui/theme.js +99 -0
  179. package/dist/ui/theme.js.map +1 -0
  180. package/dist/utils/fuzzysearch.d.ts +8 -0
  181. package/dist/utils/fuzzysearch.d.ts.map +1 -0
  182. package/dist/utils/fuzzysearch.js +19 -0
  183. package/dist/utils/fuzzysearch.js.map +1 -0
  184. package/dist/utils/image.d.ts +8 -0
  185. package/dist/utils/image.d.ts.map +1 -0
  186. package/dist/utils/image.js +63 -0
  187. package/dist/utils/image.js.map +1 -0
  188. package/dist/utils/json.d.ts +2 -0
  189. package/dist/utils/json.d.ts.map +1 -0
  190. package/dist/utils/json.js +9 -0
  191. package/dist/utils/json.js.map +1 -0
  192. package/dist/utils/logger.d.ts +19 -0
  193. package/dist/utils/logger.d.ts.map +1 -0
  194. package/dist/utils/logger.js +23 -0
  195. package/dist/utils/logger.js.map +1 -0
  196. package/dist/utils/terminal.d.ts +11 -0
  197. package/dist/utils/terminal.d.ts.map +1 -0
  198. package/dist/utils/terminal.js +38 -0
  199. package/dist/utils/terminal.js.map +1 -0
  200. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @teleforge-ai/anya
2
+
3
+ A multi-provider AI command line assistant with a rich TUI.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx @teleforge-ai/anya
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ # Start the TUI (first run shows onboarding)
15
+ anya
16
+
17
+ # Quick connect to a provider
18
+ anya --connect openrouter
19
+
20
+ # Show version
21
+ anya --version
22
+ ```
23
+
24
+ ## Features
25
+
26
+ - **Rich TUI** — Full pink border frame, Anya ASCII art, input box, status bar
27
+ - **5 AI providers** — OpenAI, Anthropic, Google, OpenRouter, OpenCode (local)
28
+ - **Tab to switch** between Build / Plan modes
29
+ - **`/` commands** — `/connect`, `/model`, `/clear`, `/help`, `/quit`
30
+ - **Ctrl+P** — Command palette with filtering
31
+ - **Response timing** — "Thought: Xms" after each response
32
+ - **First-run onboarding** — Guided provider setup on first launch
33
+
34
+ ## Providers
35
+
36
+ | Provider | ID | Env Variable |
37
+ |----------|----|-------------|
38
+ | OpenAI | `openai` | `OPENAI_API_KEY` |
39
+ | Anthropic | `anthropic` | `ANTHROPIC_API_KEY` |
40
+ | Google Gemini | `google` | `GEMINI_API_KEY` |
41
+ | OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
42
+ | OpenCode (local) | `opencode` | — |
43
+
44
+ API keys are stored in `~/.config/anya/config.json`.
45
+
46
+ ## Keyboard
47
+
48
+ | Key | Action |
49
+ |-----|--------|
50
+ | `Tab` | Switch Build / Plan mode |
51
+ | `Ctrl+P` | Open command palette |
52
+ | `↑` / `↓` | History navigation |
53
+ | `Enter` | Send message |
54
+ | `Esc` | Close palette / cancel |
55
+ | `Ctrl+C` | Quit |
56
+
57
+ ## Commands
58
+
59
+ | Command | Description |
60
+ |---------|-------------|
61
+ | `/connect [provider]` | Connect a provider |
62
+ | `/model <name>` | Switch AI model |
63
+ | `/clear` | Clear chat history |
64
+ | `/help` | Show help |
65
+ | `/quit` | Exit |
66
+
67
+ ## License
68
+
69
+ MIT
Binary file
Binary file
@@ -0,0 +1,15 @@
1
+ import { Message } from '../providers/base.js';
2
+ export declare class ChatSession {
3
+ private messages;
4
+ private maxHistory;
5
+ constructor(maxHistory?: number);
6
+ addMessage(role: Message['role'], content: string): void;
7
+ getMessages(): Message[];
8
+ getRecent(n: number): Message[];
9
+ clear(): void;
10
+ setSystemPrompt(prompt: string): void;
11
+ get length(): number;
12
+ export(format: 'openai' | 'anthropic' | 'google'): any[];
13
+ getSystemPrompt(): string | null;
14
+ }
15
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/chat/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAE9C,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,UAAU,CAAQ;gBAEd,UAAU,SAAK;IAI3B,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IASxD,WAAW,IAAI,OAAO,EAAE;IAIxB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE;IAI/B,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASrC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,GAAG,EAAE;IAoBxD,eAAe,IAAI,MAAM,GAAG,IAAI;CAIjC"}
@@ -0,0 +1,59 @@
1
+ export class ChatSession {
2
+ constructor(maxHistory = 50) {
3
+ this.messages = [];
4
+ this.maxHistory = maxHistory;
5
+ }
6
+ addMessage(role, content) {
7
+ this.messages.push({ role, content });
8
+ if (this.messages.length > this.maxHistory * 2) {
9
+ const keep = this.messages.slice(-this.maxHistory);
10
+ const systemMsgs = this.messages.filter((m) => m.role === 'system');
11
+ this.messages = [...systemMsgs, ...keep];
12
+ }
13
+ }
14
+ getMessages() {
15
+ return this.messages;
16
+ }
17
+ getRecent(n) {
18
+ return this.messages.slice(-n);
19
+ }
20
+ clear() {
21
+ this.messages = [];
22
+ }
23
+ setSystemPrompt(prompt) {
24
+ const idx = this.messages.findIndex(m => m.role === 'system');
25
+ if (idx >= 0) {
26
+ this.messages[idx].content = prompt;
27
+ }
28
+ else {
29
+ this.messages.unshift({ role: 'system', content: prompt });
30
+ }
31
+ }
32
+ get length() {
33
+ return this.messages.length;
34
+ }
35
+ export(format) {
36
+ switch (format) {
37
+ case 'openai':
38
+ return this.messages.map(m => ({ role: m.role, content: m.content }));
39
+ case 'anthropic': {
40
+ const msgs = this.messages.filter((m) => m.role !== 'system');
41
+ return msgs.map(m => ({ role: m.role === 'assistant' ? 'assistant' : 'user', content: m.content }));
42
+ }
43
+ case 'google': {
44
+ const msgs = this.messages.filter((m) => m.role !== 'system');
45
+ return msgs.map((m) => ({
46
+ role: m.role === 'assistant' ? 'model' : 'user',
47
+ parts: [{ text: m.content }]
48
+ }));
49
+ }
50
+ default:
51
+ return this.messages;
52
+ }
53
+ }
54
+ getSystemPrompt() {
55
+ const sys = this.messages.find((m) => m.role === 'system');
56
+ return sys?.content || null;
57
+ }
58
+ }
59
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/chat/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare class SSEStreamParser {
2
+ private buffer;
3
+ constructor();
4
+ push(data: string): Array<{
5
+ event: string;
6
+ data: string;
7
+ }>;
8
+ reset(): void;
9
+ }
10
+ export declare function parseOpenAIStream(chunk: string): string | null;
11
+ export declare function parseAnthropicStream(chunk: string): string | null;
12
+ export declare function parseGoogleStream(chunk: string): string | null;
13
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/chat/stream.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAQ;;IAMtB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IA8B1D,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBjE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa9D"}
@@ -0,0 +1,86 @@
1
+ export class SSEStreamParser {
2
+ constructor() {
3
+ this.buffer = '';
4
+ }
5
+ push(data) {
6
+ this.buffer += data;
7
+ const events = [];
8
+ const parts = this.buffer.split('\n\n');
9
+ this.buffer = parts.pop() || '';
10
+ for (const part of parts) {
11
+ const lines = part.split('\n');
12
+ let event = 'message';
13
+ let dataLines = [];
14
+ for (const line of lines) {
15
+ if (line.startsWith('event: ')) {
16
+ event = line.slice(7).trim();
17
+ }
18
+ else if (line.startsWith('data: ')) {
19
+ dataLines.push(line.slice(6));
20
+ }
21
+ else if (line.startsWith('data:')) {
22
+ dataLines.push(line.slice(5));
23
+ }
24
+ }
25
+ if (dataLines.length > 0) {
26
+ events.push({ event, data: dataLines.join('\n') });
27
+ }
28
+ }
29
+ return events;
30
+ }
31
+ reset() {
32
+ this.buffer = '';
33
+ }
34
+ }
35
+ export function parseOpenAIStream(chunk) {
36
+ const parser = new SSEStreamParser();
37
+ const events = parser.push(chunk);
38
+ for (const evt of events) {
39
+ if (evt.event === 'message' || evt.event === 'data') {
40
+ try {
41
+ const parsed = JSON.parse(evt.data);
42
+ const content = parsed.choices?.[0]?.delta?.content;
43
+ if (content)
44
+ return content;
45
+ if (parsed.choices?.[0]?.finish_reason === 'stop')
46
+ return null;
47
+ }
48
+ catch {
49
+ }
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ export function parseAnthropicStream(chunk) {
55
+ const parser = new SSEStreamParser();
56
+ const events = parser.push(chunk);
57
+ for (const evt of events) {
58
+ if (evt.event === 'content_block_delta') {
59
+ try {
60
+ const parsed = JSON.parse(evt.data);
61
+ if (parsed.delta?.type === 'text_delta' && parsed.delta.text) {
62
+ return parsed.delta.text;
63
+ }
64
+ }
65
+ catch {
66
+ }
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ export function parseGoogleStream(chunk) {
72
+ const parser = new SSEStreamParser();
73
+ const events = parser.push(chunk);
74
+ for (const evt of events) {
75
+ try {
76
+ const parsed = JSON.parse(evt.data);
77
+ const text = parsed.candidates?.[0]?.content?.parts?.[0]?.text;
78
+ if (text)
79
+ return text;
80
+ }
81
+ catch {
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/chat/stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { AIProvider, ModelInfo } from '../providers/base.js';
2
+ export declare function createProvider(providerId: string, apiKey?: string, model?: string, baseUrl?: string): AIProvider;
3
+ export declare function envVarFor(providerId: string): string;
4
+ export declare function fetchModelsFromProvider(providerId: string, apiKey?: string): Promise<ModelInfo[]>;
5
+ export declare const CONNECT_PROVIDERS: {
6
+ id: any;
7
+ name: any;
8
+ desc: string;
9
+ env: string;
10
+ needsKey: boolean;
11
+ }[];
12
+ //# sourceMappingURL=providerFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerFactory.d.ts","sourceRoot":"","sources":["../../src/commands/providerFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAevE,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,UAAU,CA4BZ;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAgBpD;AAED,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAOvG;AAED,eAAO,MAAM,iBAAiB;;;;;;GAM3B,CAAA"}
@@ -0,0 +1,73 @@
1
+ import { PROVIDERS } from '../providers/base.js';
2
+ import { OpenAIProvider } from '../providers/openai.js';
3
+ import { AnthropicProvider } from '../providers/anthropic.js';
4
+ import { GoogleProvider } from '../providers/google.js';
5
+ import { OpenRouterProvider } from '../providers/openrouter.js';
6
+ import { OpenCodeProvider } from '../providers/opencode.js';
7
+ import { DeepSeekProvider } from '../providers/deepseek.js';
8
+ import { MistralProvider } from '../providers/mistral.js';
9
+ import { GroqProvider } from '../providers/groq.js';
10
+ import { XAIProvider } from '../providers/xai.js';
11
+ import { TogetherProvider } from '../providers/together.js';
12
+ import { OllamaProvider } from '../providers/ollama.js';
13
+ import { CustomProvider } from '../providers/custom.js';
14
+ import { getApiKey, getModel } from '../config/store.js';
15
+ export function createProvider(providerId, apiKey, model, baseUrl) {
16
+ const key = apiKey || getApiKey(providerId);
17
+ if (!key && providerId !== 'opencode' && providerId !== 'ollama') {
18
+ throw new Error(`No API key configured for ${providerId}.\n` +
19
+ ` Set it with: anya config set ${providerId} YOUR_API_KEY\n` +
20
+ ` Or set environment variable: ${envVarFor(providerId)}`);
21
+ }
22
+ const mdl = model || getModel(providerId) || PROVIDERS.find((p) => p.id === providerId)?.defaultModel || '';
23
+ switch (providerId) {
24
+ case 'openai': return new OpenAIProvider(key, mdl);
25
+ case 'anthropic': return new AnthropicProvider(key, mdl);
26
+ case 'google': return new GoogleProvider(key, mdl);
27
+ case 'openrouter': return new OpenRouterProvider(key, mdl);
28
+ case 'deepseek': return new DeepSeekProvider(key, mdl);
29
+ case 'mistral': return new MistralProvider(key, mdl);
30
+ case 'groq': return new GroqProvider(key, mdl);
31
+ case 'xai': return new XAIProvider(key, mdl);
32
+ case 'together': return new TogetherProvider(key, mdl);
33
+ case 'ollama': return new OllamaProvider(key || '', mdl, baseUrl);
34
+ case 'opencode': return new OpenCodeProvider(key || '', mdl, baseUrl);
35
+ case 'custom': return new CustomProvider(key || '', mdl, baseUrl);
36
+ default:
37
+ throw new Error(`Unknown provider: ${providerId}. Available: ${PROVIDERS.map((p) => p.id).join(', ')}`);
38
+ }
39
+ }
40
+ export function envVarFor(providerId) {
41
+ const map = {
42
+ openai: 'OPENAI_API_KEY',
43
+ anthropic: 'ANTHROPIC_API_KEY',
44
+ google: 'GEMINI_API_KEY',
45
+ openrouter: 'OPENROUTER_API_KEY',
46
+ deepseek: 'DEEPSEEK_API_KEY',
47
+ mistral: 'MISTRAL_API_KEY',
48
+ groq: 'GROQ_API_KEY',
49
+ xai: 'XAI_API_KEY',
50
+ together: 'TOGETHER_API_KEY',
51
+ ollama: '',
52
+ opencode: '',
53
+ custom: 'CUSTOM_API_KEY',
54
+ };
55
+ return map[providerId] || `${providerId.toUpperCase()}_API_KEY`;
56
+ }
57
+ export async function fetchModelsFromProvider(providerId, apiKey) {
58
+ const prov = createProvider(providerId, apiKey);
59
+ try {
60
+ return await prov.fetchModels();
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ }
66
+ export const CONNECT_PROVIDERS = PROVIDERS.map((p) => ({
67
+ id: p.id,
68
+ name: p.name,
69
+ desc: p.models.length > 0 ? p.models.slice(0, 3).join(', ') + (p.models.length > 3 ? '...' : '') : 'Flexible model selection',
70
+ env: envVarFor(p.id),
71
+ needsKey: p.id !== 'opencode' && p.id !== 'ollama',
72
+ }));
73
+ //# sourceMappingURL=providerFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerFactory.js","sourceRoot":"","sources":["../../src/commands/providerFactory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function encrypt(plaintext: string): string;
2
+ export declare function decrypt(ciphertext: string): string;
3
+ //# sourceMappingURL=encryption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/config/encryption.ts"],"names":[],"mappings":"AA8BA,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAWlD"}
@@ -0,0 +1,47 @@
1
+ import * as crypto from 'node:crypto';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import * as os from 'node:os';
5
+ const ALGORITHM = 'aes-256-gcm';
6
+ const KEY_DIR = path.join(os.homedir(), '.config', 'anya');
7
+ const KEY_FILE = path.join(KEY_DIR, '.key');
8
+ function getOrCreateKey() {
9
+ if (fs.existsSync(KEY_FILE)) {
10
+ return fs.readFileSync(KEY_FILE);
11
+ }
12
+ const key = crypto.randomBytes(32);
13
+ if (!fs.existsSync(KEY_DIR)) {
14
+ fs.mkdirSync(KEY_DIR, { recursive: true });
15
+ }
16
+ fs.writeFileSync(KEY_FILE, key, { mode: 0o600 });
17
+ return key;
18
+ }
19
+ let cachedKey = null;
20
+ function getKey() {
21
+ if (!cachedKey) {
22
+ cachedKey = getOrCreateKey();
23
+ }
24
+ return cachedKey;
25
+ }
26
+ export function encrypt(plaintext) {
27
+ const key = getKey();
28
+ const iv = crypto.randomBytes(16);
29
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
30
+ const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
31
+ const tag = cipher.getAuthTag();
32
+ return iv.toString('hex') + ':' + tag.toString('hex') + ':' + encrypted.toString('hex');
33
+ }
34
+ export function decrypt(ciphertext) {
35
+ const key = getKey();
36
+ const parts = ciphertext.split(':');
37
+ if (parts.length !== 3)
38
+ throw new Error('Invalid encrypted data');
39
+ const iv = Buffer.from(parts[0], 'hex');
40
+ const tag = Buffer.from(parts[1], 'hex');
41
+ const encrypted = Buffer.from(parts[2], 'hex');
42
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
43
+ decipher.setAuthTag(tag);
44
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
45
+ return decrypted.toString('utf8');
46
+ }
47
+ //# sourceMappingURL=encryption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.js","sourceRoot":"","sources":["../../src/config/encryption.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ export declare const ProviderConfigSchema: z.ZodObject<{
3
+ apiKey: z.ZodString;
4
+ model: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ apiKey: string;
7
+ model: string;
8
+ }, {
9
+ apiKey: string;
10
+ model: string;
11
+ }>;
12
+ export declare const AnyaConfigSchema: z.ZodObject<{
13
+ providers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodObject<{
14
+ apiKey: z.ZodString;
15
+ model: z.ZodString;
16
+ }, "strip", z.ZodTypeAny, {
17
+ apiKey: string;
18
+ model: string;
19
+ }, {
20
+ apiKey: string;
21
+ model: string;
22
+ }>>>>;
23
+ activeProvider: z.ZodDefault<z.ZodString>;
24
+ activeModel: z.ZodDefault<z.ZodString>;
25
+ favorites: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
26
+ recent: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
27
+ theme: z.ZodDefault<z.ZodEnum<["pink", "lavender", "mint", "ocean", "sunset"]>>;
28
+ defaultProvider: z.ZodDefault<z.ZodString>;
29
+ defaultModel: z.ZodDefault<z.ZodString>;
30
+ imageVisibility: z.ZodDefault<z.ZodBoolean>;
31
+ telemetry: z.ZodDefault<z.ZodBoolean>;
32
+ updateChannel: z.ZodDefault<z.ZodEnum<["stable", "beta", "nightly"]>>;
33
+ tokenUsage: z.ZodDefault<z.ZodObject<{
34
+ total: z.ZodDefault<z.ZodNumber>;
35
+ requests: z.ZodDefault<z.ZodNumber>;
36
+ successes: z.ZodDefault<z.ZodNumber>;
37
+ failures: z.ZodDefault<z.ZodNumber>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ total: number;
40
+ requests: number;
41
+ successes: number;
42
+ failures: number;
43
+ }, {
44
+ total?: number | undefined;
45
+ requests?: number | undefined;
46
+ successes?: number | undefined;
47
+ failures?: number | undefined;
48
+ }>>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ providers: Record<string, {
51
+ apiKey: string;
52
+ model: string;
53
+ } | undefined>;
54
+ activeProvider: string;
55
+ activeModel: string;
56
+ favorites: string[];
57
+ recent: string[];
58
+ theme: "pink" | "lavender" | "mint" | "ocean" | "sunset";
59
+ defaultProvider: string;
60
+ defaultModel: string;
61
+ imageVisibility: boolean;
62
+ telemetry: boolean;
63
+ updateChannel: "stable" | "beta" | "nightly";
64
+ tokenUsage: {
65
+ total: number;
66
+ requests: number;
67
+ successes: number;
68
+ failures: number;
69
+ };
70
+ }, {
71
+ providers?: Record<string, {
72
+ apiKey: string;
73
+ model: string;
74
+ } | undefined> | undefined;
75
+ activeProvider?: string | undefined;
76
+ activeModel?: string | undefined;
77
+ favorites?: string[] | undefined;
78
+ recent?: string[] | undefined;
79
+ theme?: "pink" | "lavender" | "mint" | "ocean" | "sunset" | undefined;
80
+ defaultProvider?: string | undefined;
81
+ defaultModel?: string | undefined;
82
+ imageVisibility?: boolean | undefined;
83
+ telemetry?: boolean | undefined;
84
+ updateChannel?: "stable" | "beta" | "nightly" | undefined;
85
+ tokenUsage?: {
86
+ total?: number | undefined;
87
+ requests?: number | undefined;
88
+ successes?: number | undefined;
89
+ failures?: number | undefined;
90
+ } | undefined;
91
+ }>;
92
+ export type AnyaConfig = z.infer<typeof AnyaConfigSchema>;
93
+ export declare function validateConfig(data: unknown): AnyaConfig;
94
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,oBAAoB;;;;;;;;;EAG/B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB3B,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAExD"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ export const ProviderConfigSchema = z.object({
3
+ apiKey: z.string().min(1, 'API key is required'),
4
+ model: z.string().min(1, 'Model is required'),
5
+ });
6
+ export const AnyaConfigSchema = z.object({
7
+ providers: z.record(z.string(), ProviderConfigSchema.optional()).default({}),
8
+ activeProvider: z.string().default('openai'),
9
+ activeModel: z.string().default('gpt-4o'),
10
+ favorites: z.array(z.string()).default([]),
11
+ recent: z.array(z.string()).default([]),
12
+ theme: z.enum(['pink', 'lavender', 'mint', 'ocean', 'sunset']).default('pink'),
13
+ defaultProvider: z.string().default('openai'),
14
+ defaultModel: z.string().default('gpt-4o'),
15
+ imageVisibility: z.boolean().default(true),
16
+ telemetry: z.boolean().default(false),
17
+ updateChannel: z.enum(['stable', 'beta', 'nightly']).default('stable'),
18
+ tokenUsage: z.object({
19
+ total: z.number().default(0),
20
+ requests: z.number().default(0),
21
+ successes: z.number().default(0),
22
+ failures: z.number().default(0),
23
+ }).default({}),
24
+ });
25
+ export function validateConfig(data) {
26
+ return AnyaConfigSchema.parse(data);
27
+ }
28
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAAC;CAC9C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5E,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IACzC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9E,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC7C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC1C,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACrC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACtE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;KAChC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACf,CAAC,CAAA;AAIF,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AACrC,CAAC"}
@@ -0,0 +1,40 @@
1
+ export interface ProviderConfig {
2
+ apiKey: string;
3
+ model: string;
4
+ encrypted?: boolean;
5
+ baseUrl?: string;
6
+ }
7
+ export interface AnyaConfig {
8
+ providers: Record<string, ProviderConfig | undefined>;
9
+ activeProvider: string;
10
+ activeModel: string;
11
+ favorites: string[];
12
+ recent: string[];
13
+ theme: string;
14
+ defaultProvider: string;
15
+ defaultModel: string;
16
+ imageVisibility: boolean;
17
+ telemetry: boolean;
18
+ updateChannel: string;
19
+ tokenUsage: {
20
+ total: number;
21
+ requests: number;
22
+ successes: number;
23
+ failures: number;
24
+ };
25
+ }
26
+ export declare function loadConfig(): AnyaConfig;
27
+ export declare function saveConfig(config: AnyaConfig): void;
28
+ export declare function getApiKey(provider: string): string | null;
29
+ export declare function setApiKey(provider: string, key: string): void;
30
+ export declare function getModel(provider: string): string | null;
31
+ export declare function setModel(provider: string, model: string): void;
32
+ export declare function addRecentModel(modelId: string): void;
33
+ export declare function toggleFavorite(modelId: string): boolean;
34
+ export declare function isFavorite(modelId: string): boolean;
35
+ export declare function deleteApiKey(provider: string): void;
36
+ export declare function maskKey(key: string): string;
37
+ export declare function updateTheme(theme: string): void;
38
+ export declare function updateSettings(settings: Partial<AnyaConfig>): void;
39
+ export declare function recordTokenUsage(tokens: number, success: boolean): void;
40
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/config/store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,CAAC,CAAA;IACrD,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,OAAO,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAsBD,wBAAgB,UAAU,IAAI,UAAU,CAcvC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAKnD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+BzD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CA2B7D;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBxD;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAS9D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWvD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMnD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI/C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAIlE;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAOvE"}