gibi-bot 1.0.0 → 1.1.1

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 (48) hide show
  1. package/.context.json +47 -3
  2. package/.github/workflows/npm-publish.yml +33 -0
  3. package/.github/workflows/release.yml +45 -0
  4. package/.husky/commit-msg +1 -0
  5. package/.husky/pre-commit +2 -0
  6. package/.prettierignore +3 -0
  7. package/.prettierrc +7 -0
  8. package/CHANGELOG.md +45 -0
  9. package/DISTRIBUTION.md +9 -1
  10. package/GEMINI.md +28 -9
  11. package/README.md +55 -28
  12. package/commitlint.config.js +3 -0
  13. package/conductor/code_styleguides/general.md +6 -1
  14. package/conductor/code_styleguides/ts.md +42 -35
  15. package/conductor/product-guidelines.md +16 -12
  16. package/conductor/product.md +12 -7
  17. package/conductor/setup_state.json +1 -1
  18. package/conductor/tech-stack.md +4 -1
  19. package/conductor/tracks/slack_bot_20260107/metadata.json +1 -1
  20. package/conductor/tracks/slack_bot_20260107/plan.md +6 -1
  21. package/conductor/tracks/slack_bot_20260107/spec.md +9 -6
  22. package/conductor/tracks.md +2 -1
  23. package/conductor/workflow.md +74 -53
  24. package/dist/agents.js +7 -10
  25. package/dist/agents.test.js +17 -12
  26. package/dist/app.js +212 -135
  27. package/dist/config.js +5 -5
  28. package/dist/context.js +4 -3
  29. package/dist/context.test.js +2 -4
  30. package/eslint.config.mjs +17 -0
  31. package/jest.config.js +4 -3
  32. package/nodemon.json +5 -9
  33. package/package.json +34 -4
  34. package/release.config.js +22 -0
  35. package/src/agents.test.ts +62 -57
  36. package/src/agents.ts +94 -82
  37. package/src/app.d.ts +1 -1
  38. package/src/app.ts +298 -178
  39. package/src/config.ts +48 -48
  40. package/src/context.test.ts +54 -56
  41. package/src/context.ts +123 -114
  42. package/test_gemini.js +13 -9
  43. package/test_gemini_approval.js +13 -9
  44. package/test_gemini_write.js +19 -9
  45. package/tests/context.test.ts +145 -0
  46. package/tsconfig.json +1 -1
  47. package/src/app.js +0 -55
  48. package/src/app.js.map +0 -1
package/dist/config.js CHANGED
@@ -46,7 +46,7 @@ const SERVICE_NAME = 'gibi-slack-bot';
46
46
  const REQUIRED_VARS = [
47
47
  { name: 'SLACK_BOT_TOKEN', message: 'Enter your Slack Bot Token (xoxb-...):' },
48
48
  { name: 'SLACK_SIGNING_SECRET', message: 'Enter your Slack Signing Secret:' },
49
- { name: 'SLACK_APP_TOKEN', message: 'Enter your Slack App Token (xapp-...):' }
49
+ { name: 'SLACK_APP_TOKEN', message: 'Enter your Slack App Token (xapp-...):' },
50
50
  ];
51
51
  async function loadConfig() {
52
52
  let updated = false;
@@ -72,8 +72,8 @@ async function loadConfig() {
72
72
  type: 'password',
73
73
  name: 'value',
74
74
  message: message,
75
- mask: '*'
76
- }
75
+ mask: '*',
76
+ },
77
77
  ]);
78
78
  const value = response.value;
79
79
  if (value) {
@@ -92,11 +92,11 @@ async function loadConfig() {
92
92
  }
93
93
  async function clearConfig(keysToClear) {
94
94
  const varsToProcess = keysToClear
95
- ? REQUIRED_VARS.filter(v => keysToClear.includes(v.name))
95
+ ? REQUIRED_VARS.filter((v) => keysToClear.includes(v.name))
96
96
  : REQUIRED_VARS;
97
97
  for (const { name } of varsToProcess) {
98
98
  await keytar.deletePassword(SERVICE_NAME, name);
99
99
  delete process.env[name];
100
100
  }
101
- console.log(`Cleared stored configuration for: ${varsToProcess.map(v => v.name).join(', ')}`);
101
+ console.log(`Cleared stored configuration for: ${varsToProcess.map((v) => v.name).join(', ')}`);
102
102
  }
package/dist/context.js CHANGED
@@ -50,12 +50,13 @@ class ContextManager {
50
50
  const rawData = fs.readFileSync(this.storagePath, 'utf8');
51
51
  const parsed = JSON.parse(rawData);
52
52
  // Convert plain objects back to GibiContext with Dates
53
- Object.values(parsed).forEach((ctx) => {
53
+ Object.values(parsed).forEach((c) => {
54
+ const ctx = c;
54
55
  this.contexts.set(ctx.id, {
55
56
  ...ctx,
56
57
  createdAt: new Date(ctx.createdAt),
57
58
  lastActiveAt: new Date(ctx.lastActiveAt),
58
- messages: ctx.messages || [] // Ensure messages exists for old contexts
59
+ messages: ctx.messages || [], // Ensure messages exists for old contexts
59
60
  });
60
61
  });
61
62
  console.log(`[ContextManager] Loaded ${this.contexts.size} contexts from disk`);
@@ -98,7 +99,7 @@ class ContextManager {
98
99
  createdAt: new Date(),
99
100
  lastActiveAt: new Date(),
100
101
  data: {},
101
- messages: []
102
+ messages: [],
102
103
  };
103
104
  this.contexts.set(id, context);
104
105
  console.log(`[ContextManager] Created new context: ${id}`);
@@ -35,11 +35,9 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const context_1 = require("./context");
37
37
  const fs = __importStar(require("fs"));
38
- const path = __importStar(require("path"));
39
38
  jest.mock('fs');
40
39
  describe('ContextManager', () => {
41
40
  let contextManager;
42
- const mockStoragePath = path.join(process.cwd(), '.context.json');
43
41
  beforeEach(() => {
44
42
  jest.clearAllMocks();
45
43
  fs.existsSync.mockReturnValue(false);
@@ -73,8 +71,8 @@ describe('ContextManager', () => {
73
71
  createdAt: new Date().toISOString(),
74
72
  lastActiveAt: new Date().toISOString(),
75
73
  data: { foo: 'bar' },
76
- messages: [{ role: 'user', content: 'hello' }]
77
- }
74
+ messages: [{ role: 'user', content: 'hello' }],
75
+ },
78
76
  };
79
77
  fs.existsSync.mockReturnValue(true);
80
78
  fs.readFileSync.mockReturnValue(JSON.stringify(mockData));
@@ -0,0 +1,17 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+ import eslintConfigPrettier from 'eslint-config-prettier';
4
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
5
+
6
+ export default tseslint.config(
7
+ eslint.configs.recommended,
8
+ ...tseslint.configs.recommended,
9
+ eslintPluginPrettierRecommended,
10
+ {
11
+ rules: {
12
+ '@typescript-eslint/no-explicit-any': 'warn',
13
+ '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
14
+ },
15
+ ignores: ['dist/', 'node_modules/', 'coverage/'],
16
+ },
17
+ );
package/jest.config.js CHANGED
@@ -1,11 +1,12 @@
1
- const { createDefaultPreset } = require("ts-jest");
1
+ const { createDefaultPreset } = require('ts-jest');
2
2
 
3
3
  const tsJestTransformCfg = createDefaultPreset().transform;
4
4
 
5
5
  /** @type {import("jest").Config} **/
6
6
  module.exports = {
7
- testEnvironment: "node",
7
+ testEnvironment: 'node',
8
8
  transform: {
9
9
  ...tsJestTransformCfg,
10
10
  },
11
- };
11
+ testPathIgnorePatterns: ['/node_modules/', '/dist/'],
12
+ };
package/nodemon.json CHANGED
@@ -1,10 +1,6 @@
1
1
  {
2
- "watch": [
3
- "src"
4
- ],
5
- "ext": "ts",
6
- "exec": "ts-node src/app.ts",
7
- "ignore": [
8
- "src/**/*.test.ts"
9
- ]
10
- }
2
+ "watch": ["src"],
3
+ "ext": "ts",
4
+ "exec": "ts-node src/app.ts",
5
+ "ignore": ["src/**/*.test.ts"]
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gibi-bot",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "",
5
5
  "main": "dist/app.js",
6
6
  "bin": {
@@ -10,7 +10,13 @@
10
10
  "start": "ts-node src/app.ts",
11
11
  "dev": "nodemon",
12
12
  "build": "tsc",
13
- "test": "jest"
13
+ "test": "jest",
14
+ "lint": "eslint 'src/**/*.{ts,js}'",
15
+ "lint:fix": "eslint 'src/**/*.{ts,js}' --fix",
16
+ "format": "prettier --write .",
17
+ "format:check": "prettier --check .",
18
+ "release": "semantic-release",
19
+ "prepare": "husky"
14
20
  },
15
21
  "repository": {
16
22
  "type": "git",
@@ -33,12 +39,36 @@
33
39
  "ts-node": "^10.9.2",
34
40
  "typescript": "^5.9.3"
35
41
  },
42
+ "lint-staged": {
43
+ "src/**/*.{ts,js}": [
44
+ "eslint --fix",
45
+ "prettier --write"
46
+ ]
47
+ },
36
48
  "devDependencies": {
49
+ "@commitlint/cli": "^20.3.0",
50
+ "@commitlint/config-conventional": "^20.3.0",
51
+ "@semantic-release/changelog": "^6.0.3",
52
+ "@semantic-release/commit-analyzer": "^13.0.1",
53
+ "@semantic-release/git": "^10.0.1",
54
+ "@semantic-release/github": "^12.0.2",
55
+ "@semantic-release/npm": "^13.1.3",
56
+ "@semantic-release/release-notes-generator": "^14.1.0",
37
57
  "@types/inquirer": "^9.0.9",
38
58
  "@types/jest": "^30.0.0",
39
59
  "@types/keytar": "^4.4.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
61
+ "@typescript-eslint/parser": "^8.52.0",
62
+ "eslint": "^9.39.2",
63
+ "eslint-config-prettier": "^10.1.8",
64
+ "eslint-plugin-prettier": "^5.5.4",
65
+ "husky": "^9.1.7",
40
66
  "jest": "^30.2.0",
67
+ "lint-staged": "^16.2.7",
41
68
  "nodemon": "^3.1.11",
42
- "ts-jest": "^29.4.6"
69
+ "prettier": "^3.7.4",
70
+ "semantic-release": "^25.0.2",
71
+ "ts-jest": "^29.4.6",
72
+ "typescript-eslint": "^8.52.0"
43
73
  }
44
- }
74
+ }
@@ -0,0 +1,22 @@
1
+ module.exports = {
2
+ branches: ['main'],
3
+ plugins: [
4
+ '@semantic-release/commit-analyzer',
5
+ '@semantic-release/release-notes-generator',
6
+ '@semantic-release/changelog',
7
+ [
8
+ '@semantic-release/npm',
9
+ {
10
+ provenance: true,
11
+ },
12
+ ],
13
+ [
14
+ '@semantic-release/git',
15
+ {
16
+ assets: ['package.json', 'CHANGELOG.md'],
17
+ message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
18
+ },
19
+ ],
20
+ '@semantic-release/github',
21
+ ],
22
+ };
@@ -5,81 +5,86 @@ import { EventEmitter } from 'events';
5
5
  jest.mock('child_process');
6
6
 
7
7
  describe('GeminiAgent', () => {
8
- let agent: GeminiAgent;
8
+ let agent: GeminiAgent;
9
9
 
10
- beforeEach(() => {
11
- jest.clearAllMocks();
12
- agent = new GeminiAgent();
10
+ beforeEach(() => {
11
+ jest.clearAllMocks();
12
+ agent = new GeminiAgent();
13
+ });
14
+
15
+ it('should run gemini with the correct arguments', async () => {
16
+ const mockChild = Object.assign(new EventEmitter(), {
17
+ stdout: new EventEmitter(),
18
+ stderr: new EventEmitter(),
13
19
  });
14
20
 
15
- it('should run gemini with the correct arguments', async () => {
16
- const mockChild = new EventEmitter() as any;
17
- mockChild.stdout = new EventEmitter();
18
- mockChild.stderr = new EventEmitter();
19
-
20
- (spawn as jest.Mock).mockReturnValue(mockChild);
21
+ (spawn as jest.Mock).mockReturnValue(mockChild);
22
+
23
+ const messages = [{ role: 'user', content: 'hello' }];
24
+ const options = { model: 'test-model' };
21
25
 
22
- const messages = [{ role: 'user', content: 'hello' }];
23
- const options = { model: 'test-model' };
26
+ const promise = agent.run(messages, options);
24
27
 
25
- const promise = agent.run(messages, options);
28
+ // Simulate CLI output
29
+ setTimeout(() => {
30
+ mockChild.stdout.emit('data', Buffer.from('hi there'));
31
+ mockChild.emit('close', 0);
32
+ }, 10);
26
33
 
27
- // Simulate CLI output
28
- setTimeout(() => {
29
- mockChild.stdout.emit('data', Buffer.from('hi there'));
30
- mockChild.emit('close', 0);
31
- }, 10);
34
+ const result = await promise;
32
35
 
33
- const result = await promise;
36
+ expect(result).toBe('hi there');
37
+ expect(spawn).toHaveBeenCalledWith('gemini', [
38
+ '-m',
39
+ 'test-model',
40
+ '--approval-mode',
41
+ 'yolo',
42
+ 'User: hello\nAssistant:',
43
+ ]);
44
+ });
34
45
 
35
- expect(result).toBe('hi there');
36
- expect(spawn).toHaveBeenCalledWith('gemini', [
37
- '-m', 'test-model',
38
- '--approval-mode', 'yolo',
39
- 'User: hello\nAssistant:'
40
- ]);
46
+ it('should handle errors from the CLI', async () => {
47
+ const mockChild = Object.assign(new EventEmitter(), {
48
+ stdout: new EventEmitter(),
49
+ stderr: new EventEmitter(),
41
50
  });
42
51
 
43
- it('should handle errors from the CLI', async () => {
44
- const mockChild = new EventEmitter() as any;
45
- mockChild.stdout = new EventEmitter();
46
- mockChild.stderr = new EventEmitter();
47
-
48
- (spawn as jest.Mock).mockReturnValue(mockChild);
52
+ (spawn as jest.Mock).mockReturnValue(mockChild);
49
53
 
50
- const messages = [{ role: 'user', content: 'hello' }];
51
- const promise = agent.run(messages);
54
+ const messages = [{ role: 'user', content: 'hello' }];
55
+ const promise = agent.run(messages);
52
56
 
53
- setTimeout(() => {
54
- mockChild.stderr.emit('data', Buffer.from('something went wrong'));
55
- mockChild.emit('close', 1);
56
- }, 10);
57
+ setTimeout(() => {
58
+ mockChild.stderr.emit('data', Buffer.from('something went wrong'));
59
+ mockChild.emit('close', 1);
60
+ }, 10);
57
61
 
58
- await expect(promise).rejects.toThrow('gemini CLI exited with code 1: something went wrong');
62
+ await expect(promise).rejects.toThrow('gemini CLI exited with code 1: something went wrong');
63
+ });
64
+
65
+ it('should include PLAN_MODE_PROMPT in plan mode', async () => {
66
+ const mockChild = Object.assign(new EventEmitter(), {
67
+ stdout: new EventEmitter(),
68
+ stderr: new EventEmitter(),
59
69
  });
60
70
 
61
- it('should include PLAN_MODE_PROMPT in plan mode', async () => {
62
- const mockChild = new EventEmitter() as any;
63
- mockChild.stdout = new EventEmitter();
64
- mockChild.stderr = new EventEmitter();
65
-
66
- (spawn as jest.Mock).mockReturnValue(mockChild);
71
+ (spawn as jest.Mock).mockReturnValue(mockChild);
67
72
 
68
- const messages = [{ role: 'user', content: 'plan this' }];
69
- const options = { mode: 'plan' };
73
+ const messages = [{ role: 'user', content: 'plan this' }];
74
+ const options = { mode: 'plan' };
70
75
 
71
- const promise = agent.run(messages, options);
76
+ const promise = agent.run(messages, options);
72
77
 
73
- setTimeout(() => {
74
- mockChild.stdout.emit('data', Buffer.from('here is the plan'));
75
- mockChild.emit('close', 0);
76
- }, 10);
78
+ setTimeout(() => {
79
+ mockChild.stdout.emit('data', Buffer.from('here is the plan'));
80
+ mockChild.emit('close', 0);
81
+ }, 10);
77
82
 
78
- await promise;
83
+ await promise;
79
84
 
80
- const callArgs = (spawn as jest.Mock).mock.calls[0][1];
81
- const lastArg = callArgs[callArgs.length - 1];
82
- expect(lastArg).toContain('expert software architect');
83
- expect(lastArg).toContain('User: plan this');
84
- });
85
+ const callArgs = (spawn as jest.Mock).mock.calls[0][1];
86
+ const lastArg = callArgs[callArgs.length - 1];
87
+ expect(lastArg).toContain('expert software architect');
88
+ expect(lastArg).toContain('User: plan this');
89
+ });
85
90
  });
package/src/agents.ts CHANGED
@@ -2,111 +2,123 @@ import { spawn } from 'child_process';
2
2
  import { PLAN_MODE_PROMPT } from './prompts';
3
3
 
4
4
  export interface Agent {
5
- name: string;
6
- run(messages: Array<{ role: string; content: string }>, options?: any): Promise<string>;
5
+ name: string;
6
+ run(
7
+ messages: Array<{ role: string; content: string }>,
8
+ options?: Record<string, unknown>,
9
+ ): Promise<string>;
7
10
  }
8
11
 
9
12
  export class GeminiAgent implements Agent {
10
- name = 'gemini';
13
+ name = 'gemini';
11
14
 
12
- async run(messages: Array<{ role: string; content: string }>, options: any = {}): Promise<string> {
13
- const { model, mode } = options;
15
+ async run(
16
+ messages: Array<{ role: string; content: string }>,
17
+ options: Record<string, unknown> = {},
18
+ ): Promise<string> {
19
+ const { model, mode } = options as { model?: string; mode?: string };
14
20
 
15
- let prompt = messages
16
- .map((m: any) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
17
- .join('\n') + '\nAssistant:';
21
+ let prompt =
22
+ messages.map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`).join('\n') +
23
+ '\nAssistant:';
18
24
 
19
- if (mode === 'plan') {
20
- prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
21
- }
22
-
23
- const args = [];
24
- if (model) {
25
- args.push('-m', model);
26
- }
27
- args.push('--approval-mode', 'yolo');
28
- args.push(prompt);
29
-
30
- console.log(`[GeminiAgent] Spawning gemini with args: ${JSON.stringify(args)}`);
31
- return this.spawnProcess('gemini', args);
25
+ if (mode === 'plan') {
26
+ prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
32
27
  }
33
28
 
34
- protected spawnProcess(command: string, args: string[]): Promise<string> {
35
- return new Promise((resolve, reject) => {
36
- const child = spawn(command, args);
37
- let responseText = '';
38
- let errorText = '';
39
-
40
- child.stdout.on('data', (data: any) => {
41
- responseText += data.toString();
42
- });
43
-
44
- child.stderr.on('data', (data: any) => {
45
- errorText += data.toString();
46
- });
47
-
48
- child.on('close', (code: number) => {
49
- if (code !== 0) {
50
- reject(new Error(`${command} CLI exited with code ${code}: ${errorText}`));
51
- } else {
52
- resolve(responseText.trim());
53
- }
54
- });
55
-
56
- child.on('error', (err: any) => reject(err));
57
- });
29
+ const args = [];
30
+ if (model) {
31
+ args.push('-m', model);
58
32
  }
33
+ args.push('--approval-mode', 'yolo');
34
+ args.push(prompt);
35
+
36
+ console.log(`[GeminiAgent] Spawning gemini with args: ${JSON.stringify(args)}`);
37
+ return this.spawnProcess('gemini', args);
38
+ }
39
+
40
+ protected spawnProcess(command: string, args: string[]): Promise<string> {
41
+ return new Promise((resolve, reject) => {
42
+ const child = spawn(command, args);
43
+ let responseText = '';
44
+ let errorText = '';
45
+
46
+ child.stdout.on('data', (data: Buffer) => {
47
+ responseText += data.toString();
48
+ });
49
+
50
+ child.stderr.on('data', (data: Buffer) => {
51
+ errorText += data.toString();
52
+ });
53
+
54
+ child.on('close', (code: number) => {
55
+ if (code !== 0) {
56
+ reject(new Error(`${command} CLI exited with code ${code}: ${errorText}`));
57
+ } else {
58
+ resolve(responseText.trim());
59
+ }
60
+ });
61
+
62
+ child.on('error', (err: Error) => reject(err));
63
+ });
64
+ }
59
65
  }
60
66
 
61
67
  export class ClaudeAgent extends GeminiAgent {
62
- name = 'claude';
63
-
64
- async run(messages: Array<{ role: string; content: string }>, options: any = {}): Promise<string> {
65
- // Basic implementation for Claude - similar structure, different CLI
66
- // Assuming 'claude' CLI accepts similar prompt structure or just a string
67
- const { mode } = options;
68
-
69
- let prompt = messages
70
- .map((m: any) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
71
- .join('\n') + '\nAssistant:';
72
-
73
- if (mode === 'plan') {
74
- prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
75
- }
68
+ name = 'claude';
69
+
70
+ async run(
71
+ messages: Array<{ role: string; content: string }>,
72
+ options: Record<string, unknown> = {},
73
+ ): Promise<string> {
74
+ // Basic implementation for Claude - similar structure, different CLI
75
+ // Assuming 'claude' CLI accepts similar prompt structure or just a string
76
+ const { mode } = options as { mode?: string };
77
+
78
+ let prompt =
79
+ messages.map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`).join('\n') +
80
+ '\nAssistant:';
81
+
82
+ if (mode === 'plan') {
83
+ prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
84
+ }
76
85
 
77
- const args = [prompt];
78
- // Add specific arguments if Claude CLI requires them, e.g. -p or similar.
79
- // logic here assumes usage: claude "prompt"
86
+ const args = [prompt];
87
+ // Add specific arguments if Claude CLI requires them, e.g. -p or similar.
88
+ // logic here assumes usage: claude "prompt"
80
89
 
81
- console.log(`[ClaudeAgent] Spawning claude with args length: ${args.length}`);
82
- return this.spawnProcess('claude', args);
83
- }
90
+ console.log(`[ClaudeAgent] Spawning claude with args length: ${args.length}`);
91
+ return this.spawnProcess('claude', args);
92
+ }
84
93
  }
85
94
 
86
95
  export class CursorAgent extends GeminiAgent {
87
- name = 'cursor';
96
+ name = 'cursor';
88
97
 
89
- async run(messages: Array<{ role: string; content: string }>, options: any = {}): Promise<string> {
90
- const { mode } = options;
98
+ async run(
99
+ messages: Array<{ role: string; content: string }>,
100
+ options: Record<string, unknown> = {},
101
+ ): Promise<string> {
102
+ const { mode } = options as { mode?: string };
91
103
 
92
- let prompt = messages
93
- .map((m: any) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)
94
- .join('\n') + '\nAssistant:';
104
+ let prompt =
105
+ messages.map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`).join('\n') +
106
+ '\nAssistant:';
95
107
 
96
- if (mode === 'plan') {
97
- prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
98
- }
108
+ if (mode === 'plan') {
109
+ prompt = `${PLAN_MODE_PROMPT}\n\n${prompt}`;
110
+ }
99
111
 
100
- const args = [prompt];
101
- // Logic assumes usage: cursor "prompt" - this is hypothetical as 'cursor' CLI might differ
112
+ const args = [prompt];
113
+ // Logic assumes usage: cursor "prompt" - this is hypothetical as 'cursor' CLI might differ
102
114
 
103
- console.log(`[CursorAgent] Spawning cursor with args length: ${args.length}`);
104
- return this.spawnProcess('cursor', args);
105
- }
115
+ console.log(`[CursorAgent] Spawning cursor with args length: ${args.length}`);
116
+ return this.spawnProcess('cursor', args);
117
+ }
106
118
  }
107
119
 
108
120
  export const agentRegistry: Record<string, Agent> = {
109
- gemini: new GeminiAgent(),
110
- claude: new ClaudeAgent(),
111
- cursor: new CursorAgent(),
121
+ gemini: new GeminiAgent(),
122
+ claude: new ClaudeAgent(),
123
+ cursor: new CursorAgent(),
112
124
  };
package/src/app.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export {};
2
- //# sourceMappingURL=app.d.ts.map
2
+ //# sourceMappingURL=app.d.ts.map