@cdoing/cli 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 (118) hide show
  1. package/.cdoing/permissions.json +8 -0
  2. package/dist/callbacks.d.ts +17 -0
  3. package/dist/callbacks.d.ts.map +1 -0
  4. package/dist/callbacks.js +265 -0
  5. package/dist/callbacks.js.map +1 -0
  6. package/dist/chat.d.ts +27 -0
  7. package/dist/chat.d.ts.map +1 -0
  8. package/dist/chat.js +57 -0
  9. package/dist/chat.js.map +1 -0
  10. package/dist/commands.d.ts +22 -0
  11. package/dist/commands.d.ts.map +1 -0
  12. package/dist/commands.js +452 -0
  13. package/dist/commands.js.map +1 -0
  14. package/dist/config.d.ts +84 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +427 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/help.d.ts +9 -0
  19. package/dist/help.d.ts.map +1 -0
  20. package/dist/help.js +167 -0
  21. package/dist/help.js.map +1 -0
  22. package/dist/history.d.ts +51 -0
  23. package/dist/history.d.ts.map +1 -0
  24. package/dist/history.js +207 -0
  25. package/dist/history.js.map +1 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +220 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/oauth.d.ts +13 -0
  31. package/dist/oauth.d.ts.map +1 -0
  32. package/dist/oauth.js +182 -0
  33. package/dist/oauth.js.map +1 -0
  34. package/dist/review.d.ts +26 -0
  35. package/dist/review.d.ts.map +1 -0
  36. package/dist/review.js +198 -0
  37. package/dist/review.js.map +1 -0
  38. package/dist/serve.d.ts +23 -0
  39. package/dist/serve.d.ts.map +1 -0
  40. package/dist/serve.js +293 -0
  41. package/dist/serve.js.map +1 -0
  42. package/dist/tools.d.ts +14 -0
  43. package/dist/tools.d.ts.map +1 -0
  44. package/dist/tools.js +57 -0
  45. package/dist/tools.js.map +1 -0
  46. package/dist/ui/App.d.ts +24 -0
  47. package/dist/ui/App.d.ts.map +1 -0
  48. package/dist/ui/App.js +321 -0
  49. package/dist/ui/App.js.map +1 -0
  50. package/dist/ui/MessageList.d.ts +14 -0
  51. package/dist/ui/MessageList.d.ts.map +1 -0
  52. package/dist/ui/MessageList.js +147 -0
  53. package/dist/ui/MessageList.js.map +1 -0
  54. package/dist/ui/SessionBrowser.d.ts +18 -0
  55. package/dist/ui/SessionBrowser.d.ts.map +1 -0
  56. package/dist/ui/SessionBrowser.js +149 -0
  57. package/dist/ui/SessionBrowser.js.map +1 -0
  58. package/dist/ui/SetupWizard.d.ts +23 -0
  59. package/dist/ui/SetupWizard.d.ts.map +1 -0
  60. package/dist/ui/SetupWizard.js +402 -0
  61. package/dist/ui/SetupWizard.js.map +1 -0
  62. package/dist/ui/Spinner.d.ts +15 -0
  63. package/dist/ui/Spinner.d.ts.map +1 -0
  64. package/dist/ui/Spinner.js +111 -0
  65. package/dist/ui/Spinner.js.map +1 -0
  66. package/dist/ui/StatusBar.d.ts +16 -0
  67. package/dist/ui/StatusBar.d.ts.map +1 -0
  68. package/dist/ui/StatusBar.js +56 -0
  69. package/dist/ui/StatusBar.js.map +1 -0
  70. package/dist/ui/UserInput.d.ts +13 -0
  71. package/dist/ui/UserInput.d.ts.map +1 -0
  72. package/dist/ui/UserInput.js +872 -0
  73. package/dist/ui/UserInput.js.map +1 -0
  74. package/dist/ui/hooks/helpers.d.ts +55 -0
  75. package/dist/ui/hooks/helpers.d.ts.map +1 -0
  76. package/dist/ui/hooks/helpers.js +304 -0
  77. package/dist/ui/hooks/helpers.js.map +1 -0
  78. package/dist/ui/hooks/useAgent.d.ts +60 -0
  79. package/dist/ui/hooks/useAgent.d.ts.map +1 -0
  80. package/dist/ui/hooks/useAgent.js +213 -0
  81. package/dist/ui/hooks/useAgent.js.map +1 -0
  82. package/dist/ui/hooks/useChat.d.ts +74 -0
  83. package/dist/ui/hooks/useChat.d.ts.map +1 -0
  84. package/dist/ui/hooks/useChat.js +819 -0
  85. package/dist/ui/hooks/useChat.js.map +1 -0
  86. package/dist/ui/theme.d.ts +73 -0
  87. package/dist/ui/theme.d.ts.map +1 -0
  88. package/dist/ui/theme.js +214 -0
  89. package/dist/ui/theme.js.map +1 -0
  90. package/dist/ui/types.d.ts +37 -0
  91. package/dist/ui/types.d.ts.map +1 -0
  92. package/dist/ui/types.js +3 -0
  93. package/dist/ui/types.js.map +1 -0
  94. package/package.json +33 -0
  95. package/src/callbacks.ts +294 -0
  96. package/src/chat.ts +72 -0
  97. package/src/commands.ts +425 -0
  98. package/src/config.ts +462 -0
  99. package/src/help.ts +182 -0
  100. package/src/history.ts +205 -0
  101. package/src/index.ts +248 -0
  102. package/src/oauth.ts +164 -0
  103. package/src/review.ts +233 -0
  104. package/src/serve.ts +290 -0
  105. package/src/tools.ts +104 -0
  106. package/src/ui/App.tsx +426 -0
  107. package/src/ui/MessageList.tsx +222 -0
  108. package/src/ui/SessionBrowser.tsx +161 -0
  109. package/src/ui/SetupWizard.tsx +412 -0
  110. package/src/ui/Spinner.tsx +103 -0
  111. package/src/ui/StatusBar.tsx +106 -0
  112. package/src/ui/UserInput.tsx +954 -0
  113. package/src/ui/hooks/helpers.ts +271 -0
  114. package/src/ui/hooks/useAgent.ts +270 -0
  115. package/src/ui/hooks/useChat.ts +943 -0
  116. package/src/ui/theme.ts +326 -0
  117. package/src/ui/types.ts +41 -0
  118. package/tsconfig.json +18 -0
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * useAgent.ts — React hook that owns the AgentRunner lifecycle.
4
+ *
5
+ * Single responsibility: build, rebuild, and run the AI agent.
6
+ * It knows nothing about conversations, sessions, slash commands, or UI
7
+ * messages — those live in useChat.ts.
8
+ *
9
+ * Why a separate hook?
10
+ * - The agent can be rebuilt (e.g. when the user changes the model) without
11
+ * touching any message or session state.
12
+ * - The streaming callbacks (onToken, onToolCall…) are pure side-effects of
13
+ * the agent run. Keeping them here makes them easy to read end-to-end.
14
+ * - useChat.ts can stay focused on slash commands and message history.
15
+ *
16
+ * What this hook exposes:
17
+ * - agentRef — the live AgentRunner instance
18
+ * - modelConfigRef — mutable model settings (mutated by /model, /provider)
19
+ * - toolRegistryRef — mutable tool list (mutated by /dir)
20
+ * - workingDirRef — current working directory as a ref
21
+ * - planManagerRef — manages plan-mode state
22
+ * - rulesManagerRef — loads .cdoing/rules.md
23
+ * - effortManagerRef — tracks effort level
24
+ * - mcpManagerRef — MCP server configuration
25
+ * - contextProvidersRef — @mention context providers
26
+ * - rebuildAgent() — recreate the agent after config changes
27
+ * - resolveContextProviders() — expand @mentions in a message
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.useAgent = useAgent;
31
+ const react_1 = require("react");
32
+ const ai_1 = require("@cdoing/ai");
33
+ const core_1 = require("@cdoing/core");
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // Hook
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+ /**
38
+ * Manages the AgentRunner and all mutable config references.
39
+ *
40
+ * All returned refs are intentionally mutable — slash commands in useChat.ts
41
+ * mutate them (e.g. modelConfigRef.current.model = "gpt-4o") and then call
42
+ * rebuildAgent() to create a fresh AgentRunner with the new settings.
43
+ */
44
+ function useAgent(opts) {
45
+ // ── Mutable config refs ───────────────────────────────────────────────────
46
+ // These use useRef (not useState) because changing them should NOT trigger
47
+ // a re-render. Re-renders are triggered by state variables in useChat.ts.
48
+ /** Current working directory — changes when the user runs /dir */
49
+ const workingDirRef = (0, react_1.useRef)(process.cwd());
50
+ /** Model + provider + API key settings — changes on /model, /provider, /config set */
51
+ const modelConfigRef = (0, react_1.useRef)({ ...opts.modelConfig });
52
+ /** The set of tools available to the agent — swapped on /dir to match the new cwd */
53
+ const toolRegistryRef = (0, react_1.useRef)(opts.toolRegistry);
54
+ // ── Feature-manager refs ─────────────────────────────────────────────────
55
+ // Each manager encapsulates one feature. They are ref-stored so the agent
56
+ // can query them synchronously inside buildAgent() without going through state.
57
+ /** Plan mode: the agent proposes a plan before executing */
58
+ const planManagerRef = (0, react_1.useRef)(new core_1.PlanManager());
59
+ /** Project-specific rules loaded from .cdoing/rules.md */
60
+ const rulesManagerRef = (0, react_1.useRef)(new core_1.RulesManager(process.cwd()));
61
+ /** Effort level — low / medium / high / max — affects the system prompt */
62
+ const effortManagerRef = (0, react_1.useRef)(new core_1.EffortManager());
63
+ /** MCP (Model Context Protocol) server configuration */
64
+ const mcpManagerRef = (0, react_1.useRef)(new core_1.McpManager(process.cwd()));
65
+ /**
66
+ * Registry of @mention context providers.
67
+ * Each provider has a trigger (e.g. "@file") and a resolve() function that
68
+ * returns context to inject into the user's message before it reaches the LLM.
69
+ */
70
+ const contextProvidersRef = (0, react_1.useRef)(buildContextProviders());
71
+ // ── Agent ref ────────────────────────────────────────────────────────────
72
+ /**
73
+ * The live AgentRunner instance. Wrapped in a ref so the same object is
74
+ * accessible inside async callbacks without capturing a stale closure.
75
+ *
76
+ * Initialized with buildAgentInternal() immediately, then replaced via
77
+ * rebuildAgent() whenever settings change.
78
+ */
79
+ const agentRef = (0, react_1.useRef)((() => {
80
+ try {
81
+ return buildAgentInternal();
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ })());
87
+ // ─────────────────────────────────────────────────────────────────────────
88
+ // Agent builder
89
+ // ─────────────────────────────────────────────────────────────────────────
90
+ /**
91
+ * Construct a new AgentRunner from the current refs.
92
+ *
93
+ * Called once on mount and again via rebuildAgent() after any config change.
94
+ * Combines project config, rules, and effort hints into a single system prompt.
95
+ */
96
+ function buildAgentInternal() {
97
+ const dir = workingDirRef.current;
98
+ const projectConfig = (0, core_1.loadProjectConfig)(dir); // .cdoing/config.md
99
+ const rulesText = rulesManagerRef.current?.formatForPrompt() || "";
100
+ const effortHint = effortManagerRef.current?.getSystemPromptAddition() || "";
101
+ // Merge all system-prompt additions, filtering out empty strings
102
+ const systemPrompt = [projectConfig || "", rulesText, effortHint]
103
+ .filter(Boolean)
104
+ .join("\n\n");
105
+ return new ai_1.AgentRunner(modelConfigRef.current, toolRegistryRef.current, opts.permissionManager, opts.hookManager, {
106
+ workingDir: dir,
107
+ projectConfig: systemPrompt || undefined,
108
+ memory: opts.memoryStore.formatForPrompt() || undefined,
109
+ });
110
+ }
111
+ /**
112
+ * Replace the live agent with a freshly built one.
113
+ * Call this any time you mutate modelConfigRef, toolRegistryRef, or workingDirRef.
114
+ */
115
+ function rebuildAgent() {
116
+ try {
117
+ agentRef.current = buildAgentInternal();
118
+ }
119
+ catch (err) {
120
+ // Don't crash — agentRef keeps the previous agent (or null).
121
+ // The error will surface as a friendly message on the next send.
122
+ }
123
+ }
124
+ // ─────────────────────────────────────────────────────────────────────────
125
+ // Context provider resolver
126
+ // ─────────────────────────────────────────────────────────────────────────
127
+ /**
128
+ * Expand any @mention triggers in the user's message.
129
+ *
130
+ * Example: "@file src/main.ts tell me what this does"
131
+ * → strips "@file src/main.ts"
132
+ * → reads the file
133
+ * → returns "tell me what this does\n\n---\n\n<file path="src/main.ts">…</file>"
134
+ *
135
+ * @param message Raw message as typed by the user
136
+ * @param workingDir Current working directory (for relative file paths)
137
+ * @param lastTerminalOutput Last captured terminal output (for @terminal)
138
+ */
139
+ async function resolveContextProviders(message, workingDir, lastTerminalOutput) {
140
+ const providers = contextProvidersRef.current.getAll();
141
+ if (!providers.length)
142
+ return message;
143
+ const injected = [];
144
+ let clean = message;
145
+ for (const provider of providers) {
146
+ const idx = message.indexOf(provider.trigger);
147
+ if (idx < 0)
148
+ continue; // trigger not present
149
+ // Extract the argument (text after the trigger on the same line)
150
+ const after = message.substring(idx + provider.trigger.length);
151
+ let arg;
152
+ if (provider.requiresArg) {
153
+ const end = after.indexOf("\n");
154
+ arg = (end >= 0 ? after.substring(0, end) : after).trim();
155
+ }
156
+ // Remove the trigger (+ optional arg) from the clean message
157
+ const fullTrigger = provider.requiresArg && arg
158
+ ? `${provider.trigger} ${arg}`
159
+ : provider.trigger;
160
+ clean = clean.replace(fullTrigger, "").trim();
161
+ try {
162
+ const result = await provider.resolve(arg, { workingDir, terminalOutput: lastTerminalOutput });
163
+ if (result.content)
164
+ injected.push(result.content);
165
+ }
166
+ catch {
167
+ // If a provider fails, skip it silently — the message still goes through
168
+ }
169
+ }
170
+ // Append all injected context blocks separated by a horizontal rule
171
+ return injected.length
172
+ ? `${clean}\n\n---\n\n${injected.join("\n\n---\n\n")}`
173
+ : clean;
174
+ }
175
+ // ─────────────────────────────────────────────────────────────────────────
176
+ // Public API
177
+ // ─────────────────────────────────────────────────────────────────────────
178
+ return {
179
+ // Refs exposed so slash commands in useChat.ts can mutate them
180
+ agentRef,
181
+ modelConfigRef,
182
+ toolRegistryRef,
183
+ workingDirRef,
184
+ planManagerRef,
185
+ rulesManagerRef,
186
+ effortManagerRef,
187
+ mcpManagerRef,
188
+ contextProvidersRef,
189
+ // Actions
190
+ rebuildAgent,
191
+ resolveContextProviders,
192
+ };
193
+ }
194
+ // ─────────────────────────────────────────────────────────────────────────────
195
+ // Private helpers (module-level, not exported)
196
+ // ─────────────────────────────────────────────────────────────────────────────
197
+ /**
198
+ * Register all built-in @mention context providers.
199
+ *
200
+ * The Strategy pattern: each provider is interchangeable and can be added or
201
+ * removed without changing the chat hook.
202
+ */
203
+ function buildContextProviders() {
204
+ const reg = new core_1.ContextProviderRegistry();
205
+ reg.register(new core_1.TerminalContextProvider()); // @terminal — recent shell output
206
+ reg.register(new core_1.UrlContextProvider()); // @url <link> — fetch a webpage
207
+ reg.register(new core_1.TreeContextProvider()); // @tree — project file tree
208
+ reg.register(new core_1.CodebaseContextProvider()); // @codebase — full codebase
209
+ reg.register(new core_1.ClipboardContextProvider()); // @clip — clipboard content
210
+ reg.register(new core_1.FileIncludeContextProvider()); // @file <path> — include a file
211
+ return reg;
212
+ }
213
+ //# sourceMappingURL=useAgent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgent.js","sourceRoot":"","sources":["../../../src/ui/hooks/useAgent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * useChat.ts — Main chat state hook.
3
+ *
4
+ * This is the top-level hook consumed by App.tsx. It wires together three
5
+ * concerns that intentionally live in separate modules:
6
+ *
7
+ * 1. Agent lifecycle → ./useAgent.ts
8
+ * Build / rebuild the AgentRunner when settings change.
9
+ *
10
+ * 2. Pure utilities → ./helpers.ts
11
+ * Terminal output, diff printing, help text — no React.
12
+ *
13
+ * 3. This file (useChat.ts)
14
+ * - Message history (what's displayed in the chat window)
15
+ * - Session / conversation persistence
16
+ * - Background jobs (/bg, /jobs)
17
+ * - Slash command dispatch (/model, /dir, /clear, …)
18
+ * - The sendMessage() function that runs the agent and streams tokens
19
+ *
20
+ * Learning note — why split at all?
21
+ * A single 1000-line file works but becomes hard to navigate. Splitting by
22
+ * responsibility means you can read useAgent.ts to understand "how is the
23
+ * AI agent built?" without wading through session management, and vice versa.
24
+ *
25
+ * Data flow:
26
+ * User types → UserInput.tsx → onSubmit → App.tsx → sendMessage()
27
+ * ↓
28
+ * agentRef.current.run()
29
+ * ↓
30
+ * onToken / onToolCall / onComplete
31
+ * ↓
32
+ * setStreamingContent / setMessages
33
+ */
34
+ import type { ModelConfig } from "@cdoing/ai";
35
+ import type { ToolRegistry, PermissionManager, HookManager, MemoryStore, TodoStore } from "@cdoing/core";
36
+ import { listConversations } from "../../history";
37
+ import type { ChatMessage, ToolActivity, UsageInfo, ContextUsage, BackgroundJob } from "../types";
38
+ /** Props passed by the parent component (App.tsx → chat.ts → here) */
39
+ export interface UseChatOptions {
40
+ modelConfig: Partial<ModelConfig>;
41
+ toolRegistry: ToolRegistry;
42
+ permissionManager: PermissionManager;
43
+ hookManager: HookManager;
44
+ memoryStore: MemoryStore;
45
+ todoStore?: TodoStore;
46
+ }
47
+ export declare function useChat(opts: UseChatOptions): {
48
+ messages: ChatMessage[];
49
+ setMessages: import("react").Dispatch<import("react").SetStateAction<ChatMessage[]>>;
50
+ streamingContent: string;
51
+ isProcessing: boolean;
52
+ toolActivity: ToolActivity | null;
53
+ lastUsage: UsageInfo | null;
54
+ contextUsage: ContextUsage | null;
55
+ workingDir: string;
56
+ backgroundJobs: BackgroundJob[];
57
+ showSessionBrowser: boolean;
58
+ setShowSessionBrowser: import("react").Dispatch<import("react").SetStateAction<boolean>>;
59
+ conversations: typeof listConversations;
60
+ modelConfig: {
61
+ provider?: string | undefined;
62
+ model?: string | undefined;
63
+ apiKey?: string | undefined;
64
+ oauthToken?: string | undefined;
65
+ temperature?: number | undefined;
66
+ maxTokens?: number | undefined;
67
+ baseURL?: string | undefined;
68
+ };
69
+ sendMessage: (text: string) => Promise<void>;
70
+ handleSlashCommand: (command: string) => Promise<string | null>;
71
+ cancelCurrent: () => void;
72
+ addSystemMessage: (content: string) => void;
73
+ };
74
+ //# sourceMappingURL=useChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../../src/ui/hooks/useChat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAEjB,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,cAAc,CAAC;AAItB,OAAO,EAIL,iBAAiB,EAKlB,MAAM,eAAe,CAAC;AAsBvB,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiBlG,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAQ,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,YAAY,EAAO,YAAY,CAAC;IAChC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAQ,WAAW,CAAC;IAC/B,WAAW,EAAQ,WAAW,CAAC;IAC/B,SAAS,CAAC,EAAS,SAAS,CAAC;CAC9B;AAMD,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc;;;;;;;;;;;;;;;;;;;;;;wBAwL3B,MAAM;kCA2JH,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;;gCA/Od,MAAM,KAAG,IAAI;EAytBjD"}