gibi-bot 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 (43) hide show
  1. package/.context.json +185 -0
  2. package/.env.example +4 -0
  3. package/DISTRIBUTION.md +55 -0
  4. package/GEMINI.md +20 -0
  5. package/LICENSE +21 -0
  6. package/README.md +192 -0
  7. package/assets/gibi_avatar.png +0 -0
  8. package/conductor/code_styleguides/general.md +23 -0
  9. package/conductor/code_styleguides/ts.md +52 -0
  10. package/conductor/product-guidelines.md +28 -0
  11. package/conductor/product.md +20 -0
  12. package/conductor/setup_state.json +1 -0
  13. package/conductor/tech-stack.md +15 -0
  14. package/conductor/tracks/slack_bot_20260107/metadata.json +8 -0
  15. package/conductor/tracks/slack_bot_20260107/plan.md +26 -0
  16. package/conductor/tracks/slack_bot_20260107/spec.md +18 -0
  17. package/conductor/tracks.md +8 -0
  18. package/conductor/workflow.md +338 -0
  19. package/dist/agents.js +90 -0
  20. package/dist/agents.test.js +65 -0
  21. package/dist/app.js +740 -0
  22. package/dist/config.js +102 -0
  23. package/dist/context.js +146 -0
  24. package/dist/context.test.js +95 -0
  25. package/dist/prompts.js +20 -0
  26. package/jest.config.js +11 -0
  27. package/nodemon.json +10 -0
  28. package/package.json +44 -0
  29. package/src/agents.test.ts +85 -0
  30. package/src/agents.ts +112 -0
  31. package/src/app.d.ts +2 -0
  32. package/src/app.d.ts.map +1 -0
  33. package/src/app.js +55 -0
  34. package/src/app.js.map +1 -0
  35. package/src/app.ts +809 -0
  36. package/src/config.ts +72 -0
  37. package/src/context.test.ts +75 -0
  38. package/src/context.ts +130 -0
  39. package/src/prompts.ts +17 -0
  40. package/test_gemini.js +23 -0
  41. package/test_gemini_approval.js +24 -0
  42. package/test_gemini_write.js +23 -0
  43. package/tsconfig.json +13 -0
@@ -0,0 +1,18 @@
1
+ # Feature Spec: Basic Slack Bot (TS)
2
+
3
+ ## Overview
4
+ A simple Slack bot built with TypeScript and Bolt that proves connectivity.
5
+
6
+ ## Requirements
7
+ 1. **Language:** TypeScript.
8
+ 2. **Framework:** `@slack/bolt`.
9
+ 3. **Commands:**
10
+ - When a user types "ping" in a channel the bot is in, it should reply "pong".
11
+ 4. **Configuration:**
12
+ - `SLACK_BOT_TOKEN`
13
+ - `SLACK_SIGNING_SECRET`
14
+ - `SLACK_APP_TOKEN` (if using Socket Mode, which is recommended for local dev).
15
+
16
+ ## Implementation Details
17
+ - Entry point: `src/app.ts`.
18
+ - Use Socket Mode for easier local development (requires `SLACK_APP_TOKEN`).
@@ -0,0 +1,8 @@
1
+ # Project Tracks
2
+
3
+ This file tracks all major tracks for the project. Each track has its own detailed plan in its respective folder.
4
+
5
+ ---
6
+
7
+ ## [x] Track: Initialize TypeScript project and create a basic Slack bot
8
+ *Link: [./conductor/tracks/slack_bot_20260107/](./conductor/tracks/slack_bot_20260107/)*
@@ -0,0 +1,338 @@
1
+ # Project Workflow
2
+
3
+ ## Guiding Principles
4
+
5
+ 1. **The Plan is the Source of Truth:** All work must be tracked in `plan.md`
6
+ 2. **The Tech Stack is Deliberate:** Changes to the tech stack must be documented in `tech-stack.md` *before* implementation
7
+ 3. **Test-Driven Development:** Write unit tests before implementing functionality
8
+ 4. **High Code Coverage:** Aim for >80% code coverage for all modules
9
+ 5. **User Experience First:** Every decision should prioritize user experience
10
+ 6. **Non-Interactive & CI-Aware:** Prefer non-interactive commands. Use `CI=true` for watch-mode tools (tests, linters) to ensure single execution.
11
+
12
+ ## Task Workflow
13
+
14
+ All tasks follow a strict lifecycle:
15
+
16
+ ### Standard Task Workflow
17
+
18
+ 1. **Select Task:** Choose the next available task from `plan.md` in sequential order
19
+
20
+ 2. **Mark In Progress:** Before beginning work, edit `plan.md` and change the task from `[ ]` to `[~]`
21
+
22
+ 3. **Write Failing Tests (Red Phase):**
23
+ - Create a new test file for the feature or bug fix.
24
+ - Write one or more unit tests that clearly define the expected behavior and acceptance criteria for the task.
25
+ - **CRITICAL:** Run the tests and confirm that they fail as expected. This is the "Red" phase of TDD. Do not proceed until you have failing tests.
26
+
27
+ 4. **Implement to Pass Tests (Green Phase):**
28
+ - Write the minimum amount of application code necessary to make the failing tests pass.
29
+ - Run the test suite again and confirm that all tests now pass. This is the "Green" phase.
30
+
31
+ 5. **Refactor (Optional but Recommended):**
32
+ - With the safety of passing tests, refactor the implementation code and the test code to improve clarity, remove duplication, and enhance performance without changing the external behavior.
33
+ - Rerun tests to ensure they still pass after refactoring.
34
+
35
+ 6. **Verify Coverage:** Run coverage reports using the project's chosen tools. For example, in a Python project, this might look like:
36
+ ```bash
37
+ pytest --cov=app --cov-report=html
38
+ ```
39
+ Target: >80% coverage for new code. The specific tools and commands will vary by language and framework.
40
+
41
+ 7. **Document Deviations:** If implementation differs from tech stack:
42
+ - **STOP** implementation
43
+ - Update `tech-stack.md` with new design
44
+ - Add dated note explaining the change
45
+ - Resume implementation
46
+
47
+ 8. **Lint and Format:**
48
+ - Run the project's linting and formatting tools (e.g., `go fmt`, `golangci-lint`, `eslint`, `prettier`).
49
+ - Fix any errors or style violations.
50
+ - Ensure the code is clean and consistent before committing.
51
+
52
+ 9. **Commit Code Changes:**
53
+ - Stage all code changes related to the task.
54
+ - Propose a clear, concise commit message e.g, `feat(ui): Create basic HTML structure for calculator`.
55
+ - Perform the commit.
56
+
57
+ 10. **Attach Task Summary with Git Notes:**
58
+ - **Step 10.1: Get Commit Hash:** Obtain the hash of the *just-completed commit* (`git log -1 --format="%H"`).
59
+ - **Step 10.2: Draft Note Content:** Create a detailed summary for the completed task. This should include the task name, a summary of changes, a list of all created/modified files, and the core "why" for the change.
60
+ - **Step 10.3: Attach Note:** Use the `git notes` command to attach the summary to the commit.
61
+ ```bash
62
+ # The note content from the previous step is passed via the -m flag.
63
+ git notes add -m "<note content>" <commit_hash>
64
+ ```
65
+
66
+ 11. **Get and Record Task Commit SHA:**
67
+ - **Step 11.1: Update Plan:** Read `plan.md`, find the line for the completed task, update its status from `[~]` to `[x]`, and append the first 7 characters of the *just-completed commit's* commit hash.
68
+ - **Step 11.2: Write Plan:** Write the updated content back to `plan.md`.
69
+
70
+ 12. **Commit Plan Update:**
71
+ - **Action:** Stage the modified `plan.md` file.
72
+ - **Action:** Commit this change with a descriptive message (e.g., `conductor(plan): Mark task 'Create user model' as complete`).
73
+
74
+ ### Phase Completion Verification and Checkpointing Protocol
75
+
76
+ **Trigger:** This protocol is executed immediately after a task is completed that also concludes a phase in `plan.md`.
77
+
78
+ 1. **Announce Protocol Start:** Inform the user that the phase is complete and the verification and checkpointing protocol has begun.
79
+
80
+ 2. **Ensure Test Coverage for Phase Changes:**
81
+ - **Step 2.1: Determine Phase Scope:** To identify the files changed in this phase, you must first find the starting point. Read `plan.md` to find the Git commit SHA of the *previous* phase's checkpoint. If no previous checkpoint exists, the scope is all changes since the first commit.
82
+ - **Step 2.2: List Changed Files:** Execute `git diff --name-only <previous_checkpoint_sha> HEAD` to get a precise list of all files modified during this phase.
83
+ - **Step 2.3: Verify and Create Tests:** For each file in the list:
84
+ - **CRITICAL:** First, check its extension. Exclude non-code files (e.g., `.json`, `.md`, `.yaml`).
85
+ - For each remaining code file, verify a corresponding test file exists.
86
+ - If a test file is missing, you **must** create one. Before writing the test, **first, analyze other test files in the repository to determine the correct naming convention and testing style.** The new tests **must** validate the functionality described in this phase's tasks (`plan.md`).
87
+
88
+ 3. **Execute Automated Tests with Proactive Debugging:**
89
+ - Before execution, you **must** announce the exact shell command you will use to run the tests.
90
+ - **Example Announcement:** "I will now run the automated test suite to verify the phase. **Command:** `CI=true npm test`"
91
+ - Execute the announced command.
92
+ - If tests fail, you **must** inform the user and begin debugging. You may attempt to propose a fix a **maximum of two times**. If the tests still fail after your second proposed fix, you **must stop**, report the persistent failure, and ask the user for guidance.
93
+
94
+ 4. **Propose a Detailed, Actionable Manual Verification Plan:**
95
+ - **CRITICAL:** To generate the plan, first analyze `product.md`, `product-guidelines.md`, and `plan.md` to determine the user-facing goals of the completed phase.
96
+ - You **must** generate a step-by-step plan that walks the user through the verification process, including any necessary commands and specific, expected outcomes.
97
+ - The plan you present to the user **must** follow this format:
98
+
99
+ **For a Frontend Change:**
100
+ ```
101
+ The automated tests have passed. For manual verification, please follow these steps:
102
+
103
+ **Manual Verification Steps:**
104
+ 1. **Start the development server with the command:** `npm run dev`
105
+ 2. **Open your browser to:** `http://localhost:3000`
106
+ 3. **Confirm that you see:** The new user profile page, with the user's name and email displayed correctly.
107
+ ```
108
+
109
+ **For a Backend Change:**
110
+ ```
111
+ The automated tests have passed. For manual verification, please follow these steps:
112
+
113
+ **Manual Verification Steps:**
114
+ 1. **Ensure the server is running.**
115
+ 2. **Execute the following command in your terminal:** `curl -X POST http://localhost:8080/api/v1/users -d '{"name": "test"}'`
116
+ 3. **Confirm that you receive:** A JSON response with a status of `201 Created`.
117
+ ```
118
+
119
+ 5. **Await Explicit User Feedback:**
120
+ - After presenting the detailed plan, ask the user for confirmation: "**Does this meet your expectations? Please confirm with yes or provide feedback on what needs to be changed.**"
121
+ - **PAUSE** and await the user's response. Do not proceed without an explicit yes or confirmation.
122
+
123
+ 6. **Create Checkpoint Commit:**
124
+ - Stage all changes. If no changes occurred in this step, proceed with an empty commit.
125
+ - Perform the commit with a clear and concise message (e.g., `conductor(checkpoint): Checkpoint end of Phase X`).
126
+
127
+ 7. **Attach Auditable Verification Report using Git Notes:**
128
+ - **Step 8.1: Draft Note Content:** Create a detailed verification report including the automated test command, the manual verification steps, and the user's confirmation.
129
+ - **Step 8.2: Attach Note:** Use the `git notes` command and the full commit hash from the previous step to attach the full report to the checkpoint commit.
130
+
131
+ 8. **Get and Record Phase Checkpoint SHA:**
132
+ - **Step 7.1: Get Commit Hash:** Obtain the hash of the *just-created checkpoint commit* (`git log -1 --format="%H"`).
133
+ - **Step 7.2: Update Plan:** Read `plan.md`, find the heading for the completed phase, and append the first 7 characters of the commit hash in the format `[checkpoint: <sha>]`.
134
+ - **Step 7.3: Write Plan:** Write the updated content back to `plan.md`.
135
+
136
+ 9. **Commit Plan Update:**
137
+ - **Action:** Stage the modified `plan.md` file.
138
+ - **Action:** Commit this change with a descriptive message following the format `conductor(plan): Mark phase '<PHASE NAME>' as complete`.
139
+
140
+ 10. **Announce Completion:** Inform the user that the phase is complete and the checkpoint has been created, with the detailed verification report attached as a git note.
141
+
142
+ ### Quality Gates
143
+
144
+ Before marking any task complete, verify:
145
+
146
+ - [ ] All tests pass
147
+ - [ ] Code coverage meets requirements (>80%)
148
+ - [ ] Code follows project's code style guidelines (as defined in `code_styleguides/`)
149
+ - [ ] All public functions/methods are documented (e.g., docstrings, JSDoc, GoDoc)
150
+ - [ ] Type safety is enforced (e.g., type hints, TypeScript types, Go types)
151
+ - [ ] No linting or static analysis errors (using the project's configured tools)
152
+ - [ ] Works correctly on mobile (if applicable)
153
+ - [ ] Documentation updated if needed
154
+ - [ ] No security vulnerabilities introduced
155
+
156
+ ## Development Commands
157
+
158
+ **AI AGENT INSTRUCTION: This section should be adapted to the project's specific language, framework, and build tools.**
159
+
160
+ ### Setup
161
+ ```bash
162
+ # Example: Commands to set up the development environment (e.g., install dependencies, configure database)
163
+ # e.g., for a Node.js project: npm install
164
+ # e.g., for a Go project: go mod tidy
165
+ ```
166
+
167
+ ### Daily Development
168
+ ```bash
169
+ # Example: Commands for common daily tasks (e.g., start dev server, run tests, lint, format)
170
+ # e.g., for a Node.js project: npm run dev, npm test, npm run lint
171
+ # e.g., for a Go project: go run main.go, go test ./..., go fmt ./...
172
+ ```
173
+
174
+ ### Before Committing
175
+ ```bash
176
+ # Example: Commands to run all pre-commit checks (e.g., format, lint, type check, run tests)
177
+ # e.g., for a Node.js project: npm run check
178
+ # e.g., for a Go project: make check (if a Makefile exists)
179
+ ```
180
+
181
+ ## Testing Requirements
182
+
183
+ ### Unit Testing
184
+ - Every module must have corresponding tests.
185
+ - Use appropriate test setup/teardown mechanisms (e.g., fixtures, beforeEach/afterEach).
186
+ - Mock external dependencies.
187
+ - Test both success and failure cases.
188
+
189
+ ### Integration Testing
190
+ - Test complete user flows
191
+ - Verify database transactions
192
+ - Test authentication and authorization
193
+ - Check form submissions
194
+
195
+ ### Mobile Testing
196
+ - Test on actual iPhone when possible
197
+ - Use Safari developer tools
198
+ - Test touch interactions
199
+ - Verify responsive layouts
200
+ - Check performance on 3G/4G
201
+
202
+ ## Code Review Process
203
+
204
+ ### Self-Review Checklist
205
+ Before requesting review:
206
+
207
+ 1. **Functionality**
208
+ - Feature works as specified
209
+ - Edge cases handled
210
+ - Error messages are user-friendly
211
+
212
+ 2. **Code Quality**
213
+ - Follows style guide
214
+ - DRY principle applied
215
+ - Clear variable/function names
216
+ - Appropriate comments
217
+
218
+ 3. **Testing**
219
+ - Unit tests comprehensive
220
+ - Integration tests pass
221
+ - Coverage adequate (>80%)
222
+
223
+ 4. **Security**
224
+ - No hardcoded secrets
225
+ - Input validation present
226
+ - SQL injection prevented
227
+ - XSS protection in place
228
+
229
+ 5. **Performance**
230
+ - Database queries optimized
231
+ - Images optimized
232
+ - Caching implemented where needed
233
+
234
+ 6. **Mobile Experience**
235
+ - Touch targets adequate (44x44px)
236
+ - Text readable without zooming
237
+ - Performance acceptable on mobile
238
+ - Interactions feel native
239
+
240
+ ## Commit Guidelines
241
+
242
+ ### Message Format
243
+ ```
244
+ <type>(<scope>): <description>
245
+
246
+ [optional body]
247
+
248
+ [optional footer]
249
+ ```
250
+
251
+ ### Types
252
+ - `feat`: New feature
253
+ - `fix`: Bug fix
254
+ - `docs`: Documentation only
255
+ - `style`: Formatting, missing semicolons, etc.
256
+ - `refactor`: Code change that neither fixes a bug nor adds a feature
257
+ - `test`: Adding missing tests
258
+ - `chore`: Maintenance tasks
259
+
260
+ ### Examples
261
+ ```bash
262
+ git commit -m "feat(auth): Add remember me functionality"
263
+ git commit -m "fix(posts): Correct excerpt generation for short posts"
264
+ git commit -m "test(comments): Add tests for emoji reaction limits"
265
+ git commit -m "style(mobile): Improve button touch targets"
266
+ ```
267
+
268
+ ## Definition of Done
269
+
270
+ A task is complete when:
271
+
272
+ 1. All code implemented to specification
273
+ 2. Unit tests written and passing
274
+ 3. Code coverage meets project requirements
275
+ 4. Documentation complete (if applicable)
276
+ 5. Code passes all configured linting and static analysis checks
277
+ 6. Works beautifully on mobile (if applicable)
278
+ 7. Implementation notes added to `plan.md`
279
+ 8. Changes committed with proper message
280
+ 9. Git note with task summary attached to the commit
281
+
282
+ ## Emergency Procedures
283
+
284
+ ### Critical Bug in Production
285
+ 1. Create hotfix branch from main
286
+ 2. Write failing test for bug
287
+ 3. Implement minimal fix
288
+ 4. Test thoroughly including mobile
289
+ 5. Deploy immediately
290
+ 6. Document in plan.md
291
+
292
+ ### Data Loss
293
+ 1. Stop all write operations
294
+ 2. Restore from latest backup
295
+ 3. Verify data integrity
296
+ 4. Document incident
297
+ 5. Update backup procedures
298
+
299
+ ### Security Breach
300
+ 1. Rotate all secrets immediately
301
+ 2. Review access logs
302
+ 3. Patch vulnerability
303
+ 4. Notify affected users (if any)
304
+ 5. Document and update security procedures
305
+
306
+ ## Deployment Workflow
307
+
308
+ ### Pre-Deployment Checklist
309
+ - [ ] All tests passing
310
+ - [ ] Coverage >80%
311
+ - [ ] No linting errors
312
+ - [ ] Mobile testing complete
313
+ - [ ] Environment variables configured
314
+ - [ ] Database migrations ready
315
+ - [ ] Backup created
316
+
317
+ ### Deployment Steps
318
+ 1. Merge feature branch to main
319
+ 2. Tag release with version
320
+ 3. Push to deployment service
321
+ 4. Run database migrations
322
+ 5. Verify deployment
323
+ 6. Test critical paths
324
+ 7. Monitor for errors
325
+
326
+ ### Post-Deployment
327
+ 1. Monitor analytics
328
+ 2. Check error logs
329
+ 3. Gather user feedback
330
+ 4. Plan next iteration
331
+
332
+ ## Continuous Improvement
333
+
334
+ - Review workflow weekly
335
+ - Update based on pain points
336
+ - Document lessons learned
337
+ - Optimize for user happiness
338
+ - Keep things simple and maintainable
package/dist/agents.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agentRegistry = exports.CursorAgent = exports.ClaudeAgent = exports.GeminiAgent = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const prompts_1 = require("./prompts");
6
+ class GeminiAgent {
7
+ name = 'gemini';
8
+ async run(messages, options = {}) {
9
+ const { model, mode } = options;
10
+ let prompt = messages
11
+ .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
12
+ .join('\n') + '\nAssistant:';
13
+ if (mode === 'plan') {
14
+ prompt = `${prompts_1.PLAN_MODE_PROMPT}\n\n${prompt}`;
15
+ }
16
+ const args = [];
17
+ if (model) {
18
+ args.push('-m', model);
19
+ }
20
+ args.push('--approval-mode', 'yolo');
21
+ args.push(prompt);
22
+ console.log(`[GeminiAgent] Spawning gemini with args: ${JSON.stringify(args)}`);
23
+ return this.spawnProcess('gemini', args);
24
+ }
25
+ spawnProcess(command, args) {
26
+ return new Promise((resolve, reject) => {
27
+ const child = (0, child_process_1.spawn)(command, args);
28
+ let responseText = '';
29
+ let errorText = '';
30
+ child.stdout.on('data', (data) => {
31
+ responseText += data.toString();
32
+ });
33
+ child.stderr.on('data', (data) => {
34
+ errorText += data.toString();
35
+ });
36
+ child.on('close', (code) => {
37
+ if (code !== 0) {
38
+ reject(new Error(`${command} CLI exited with code ${code}: ${errorText}`));
39
+ }
40
+ else {
41
+ resolve(responseText.trim());
42
+ }
43
+ });
44
+ child.on('error', (err) => reject(err));
45
+ });
46
+ }
47
+ }
48
+ exports.GeminiAgent = GeminiAgent;
49
+ class ClaudeAgent extends GeminiAgent {
50
+ name = 'claude';
51
+ async run(messages, options = {}) {
52
+ // Basic implementation for Claude - similar structure, different CLI
53
+ // Assuming 'claude' CLI accepts similar prompt structure or just a string
54
+ const { mode } = options;
55
+ let prompt = messages
56
+ .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
57
+ .join('\n') + '\nAssistant:';
58
+ if (mode === 'plan') {
59
+ prompt = `${prompts_1.PLAN_MODE_PROMPT}\n\n${prompt}`;
60
+ }
61
+ const args = [prompt];
62
+ // Add specific arguments if Claude CLI requires them, e.g. -p or similar.
63
+ // logic here assumes usage: claude "prompt"
64
+ console.log(`[ClaudeAgent] Spawning claude with args length: ${args.length}`);
65
+ return this.spawnProcess('claude', args);
66
+ }
67
+ }
68
+ exports.ClaudeAgent = ClaudeAgent;
69
+ class CursorAgent extends GeminiAgent {
70
+ name = 'cursor';
71
+ async run(messages, options = {}) {
72
+ const { mode } = options;
73
+ let prompt = messages
74
+ .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
75
+ .join('\n') + '\nAssistant:';
76
+ if (mode === 'plan') {
77
+ prompt = `${prompts_1.PLAN_MODE_PROMPT}\n\n${prompt}`;
78
+ }
79
+ const args = [prompt];
80
+ // Logic assumes usage: cursor "prompt" - this is hypothetical as 'cursor' CLI might differ
81
+ console.log(`[CursorAgent] Spawning cursor with args length: ${args.length}`);
82
+ return this.spawnProcess('cursor', args);
83
+ }
84
+ }
85
+ exports.CursorAgent = CursorAgent;
86
+ exports.agentRegistry = {
87
+ gemini: new GeminiAgent(),
88
+ claude: new ClaudeAgent(),
89
+ cursor: new CursorAgent(),
90
+ };
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const agents_1 = require("./agents");
4
+ const child_process_1 = require("child_process");
5
+ const events_1 = require("events");
6
+ jest.mock('child_process');
7
+ describe('GeminiAgent', () => {
8
+ let agent;
9
+ beforeEach(() => {
10
+ jest.clearAllMocks();
11
+ agent = new agents_1.GeminiAgent();
12
+ });
13
+ it('should run gemini with the correct arguments', async () => {
14
+ const mockChild = new events_1.EventEmitter();
15
+ mockChild.stdout = new events_1.EventEmitter();
16
+ mockChild.stderr = new events_1.EventEmitter();
17
+ child_process_1.spawn.mockReturnValue(mockChild);
18
+ const messages = [{ role: 'user', content: 'hello' }];
19
+ const options = { model: 'test-model' };
20
+ const promise = agent.run(messages, options);
21
+ // Simulate CLI output
22
+ setTimeout(() => {
23
+ mockChild.stdout.emit('data', Buffer.from('hi there'));
24
+ mockChild.emit('close', 0);
25
+ }, 10);
26
+ const result = await promise;
27
+ expect(result).toBe('hi there');
28
+ expect(child_process_1.spawn).toHaveBeenCalledWith('gemini', [
29
+ '-m', 'test-model',
30
+ '--approval-mode', 'yolo',
31
+ 'User: hello\nAssistant:'
32
+ ]);
33
+ });
34
+ it('should handle errors from the CLI', async () => {
35
+ const mockChild = new events_1.EventEmitter();
36
+ mockChild.stdout = new events_1.EventEmitter();
37
+ mockChild.stderr = new events_1.EventEmitter();
38
+ child_process_1.spawn.mockReturnValue(mockChild);
39
+ const messages = [{ role: 'user', content: 'hello' }];
40
+ const promise = agent.run(messages);
41
+ setTimeout(() => {
42
+ mockChild.stderr.emit('data', Buffer.from('something went wrong'));
43
+ mockChild.emit('close', 1);
44
+ }, 10);
45
+ await expect(promise).rejects.toThrow('gemini CLI exited with code 1: something went wrong');
46
+ });
47
+ it('should include PLAN_MODE_PROMPT in plan mode', async () => {
48
+ const mockChild = new events_1.EventEmitter();
49
+ mockChild.stdout = new events_1.EventEmitter();
50
+ mockChild.stderr = new events_1.EventEmitter();
51
+ child_process_1.spawn.mockReturnValue(mockChild);
52
+ const messages = [{ role: 'user', content: 'plan this' }];
53
+ const options = { mode: 'plan' };
54
+ const promise = agent.run(messages, options);
55
+ setTimeout(() => {
56
+ mockChild.stdout.emit('data', Buffer.from('here is the plan'));
57
+ mockChild.emit('close', 0);
58
+ }, 10);
59
+ await promise;
60
+ const callArgs = child_process_1.spawn.mock.calls[0][1];
61
+ const lastArg = callArgs[callArgs.length - 1];
62
+ expect(lastArg).toContain('expert software architect');
63
+ expect(lastArg).toContain('User: plan this');
64
+ });
65
+ });