@bernierllc/braingrid-cli-wrapper 0.3.1 → 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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { BrainGridProject, BrainGridRequirement, BrainGridTask, RequirementStatus, TaskStatus, BrainGridProjectSchema, BrainGridRequirementSchema, BrainGridTaskSchema, BrainGridCliError } from './models';
2
+ export type { BrainGridCliErrorCode, BrainGridCliErrorOptions } from './models';
2
3
  export { createIdea } from './commands/createIdea';
3
4
  export { listProjects } from './commands/listProjects';
4
5
  export { createProject } from './commands/createProject';
package/dist/models.d.ts CHANGED
@@ -81,9 +81,17 @@ export declare const BrainGridTaskSchema: z.ZodObject<{
81
81
  metadata?: Record<string, unknown> | undefined;
82
82
  }>;
83
83
  export type BrainGridTask = z.infer<typeof BrainGridTaskSchema>;
84
+ export type BrainGridCliErrorCode = 'BRAINGRID_CLI_ERROR' | 'BRAINGRID_CLI_NOT_FOUND' | 'BRAINGRID_CLI_INVALID_OUTPUT' | 'BRAINGRID_CLI_NONZERO_EXIT';
85
+ export interface BrainGridCliErrorOptions {
86
+ cause?: Error;
87
+ code?: BrainGridCliErrorCode;
88
+ context?: Record<string, unknown>;
89
+ }
84
90
  export declare class BrainGridCliError extends Error {
85
91
  command: string;
86
92
  exitCode: number;
87
93
  stderr: string;
88
- constructor(message: string, command: string, exitCode: number, stderr: string);
94
+ readonly code: BrainGridCliErrorCode;
95
+ readonly context?: Record<string, unknown>;
96
+ constructor(message: string, command: string, exitCode: number, stderr: string, options?: BrainGridCliErrorOptions);
89
97
  }
package/dist/models.js CHANGED
@@ -58,17 +58,23 @@ exports.BrainGridTaskSchema = zod_1.z.object({
58
58
  updatedAt: zod_1.z.string().optional(),
59
59
  metadata: zod_1.z.record(zod_1.z.unknown()).optional()
60
60
  });
61
- // CLI Error
62
61
  class BrainGridCliError extends Error {
63
62
  command;
64
63
  exitCode;
65
64
  stderr;
66
- constructor(message, command, exitCode, stderr) {
67
- super(message);
65
+ code;
66
+ context;
67
+ constructor(message, command, exitCode, stderr, options) {
68
+ super(message, options?.cause ? { cause: options.cause } : undefined);
68
69
  this.name = 'BrainGridCliError';
69
70
  this.command = command;
70
71
  this.exitCode = exitCode;
71
72
  this.stderr = stderr;
73
+ this.code = options?.code ?? 'BRAINGRID_CLI_ERROR';
74
+ if (options?.context !== undefined) {
75
+ this.context = options.context;
76
+ }
77
+ Error.captureStackTrace?.(this, this.constructor);
72
78
  }
73
79
  }
74
80
  exports.BrainGridCliError = BrainGridCliError;
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@bernierllc/braingrid-cli-wrapper",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Type-safe wrapper for BrainGrid CLI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
7
12
  "keywords": [
8
13
  "braingrid",
9
14
  "cli",
package/.eslintrc.cjs DELETED
@@ -1,29 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- module.exports = {
10
- parser: '@typescript-eslint/parser',
11
- extends: [
12
- 'eslint:recommended',
13
- 'plugin:@typescript-eslint/recommended',
14
- ],
15
- parserOptions: {
16
- ecmaVersion: 2020,
17
- sourceType: 'module',
18
- },
19
- rules: {
20
- '@typescript-eslint/no-explicit-any': 'warn',
21
- '@typescript-eslint/explicit-module-boundary-types': 'off',
22
- '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
23
- },
24
- env: {
25
- node: true,
26
- jest: true,
27
- },
28
- };
29
-
package/CHANGELOG.md DELETED
@@ -1,43 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ## [0.3.1](https://github.com/bernier-llc/tools/compare/@bernierllc/braingrid-cli-wrapper@0.3.0...@bernierllc/braingrid-cli-wrapper@0.3.1) (2026-03-03)
7
-
8
- **Note:** Version bump only for package @bernierllc/braingrid-cli-wrapper
9
-
10
-
11
-
12
-
13
-
14
- # 0.3.0 (2025-12-25)
15
-
16
-
17
- ### Bug Fixes
18
-
19
- * **ci:** add lerna version step before publish ([3d20300](https://github.com/bernier-llc/tools/commit/3d203002143bf353fffafe4f8a78a99009567347))
20
- * **jest:** move global options to root config and fix typos ([c14710c](https://github.com/bernier-llc/tools/commit/c14710c11e8fc34dd7f773edf01328151564323a))
21
- * update neverhub-adapter deps to workspace:* and publish 0.1.2 ([f0e3d04](https://github.com/bernier-llc/tools/commit/f0e3d04d8d4f094e3bb899ddf81e93243d16e2c2))
22
-
23
-
24
- ### Features
25
-
26
- * add 4 more core/integration packages ([dd05b81](https://github.com/bernier-llc/tools/commit/dd05b816c94adcbd99556afbd9e316146654f44c))
27
-
28
-
29
-
30
-
31
-
32
- # 0.2.0 (2025-12-25)
33
-
34
-
35
- ### Bug Fixes
36
-
37
- * **jest:** move global options to root config and fix typos ([c14710c](https://github.com/bernier-llc/tools/commit/c14710c11e8fc34dd7f773edf01328151564323a))
38
- * update neverhub-adapter deps to workspace:* and publish 0.1.2 ([f0e3d04](https://github.com/bernier-llc/tools/commit/f0e3d04d8d4f094e3bb899ddf81e93243d16e2c2))
39
-
40
-
41
- ### Features
42
-
43
- * add 4 more core/integration packages ([dd05b81](https://github.com/bernier-llc/tools/commit/dd05b816c94adcbd99556afbd9e316146654f44c))
package/jest.config.cjs DELETED
@@ -1,21 +0,0 @@
1
- module.exports = {
2
- preset: 'ts-jest',
3
- // Use fixed environment to handle Node.js v25+ localStorage issue
4
- testEnvironment: '<rootDir>/../../../jest-environment-node-fixed.cjs',
5
- roots: ['<rootDir>/src'],
6
- testMatch: [
7
- '**/__tests__/**/*.ts',
8
- '**/?(*.)+(spec|test).ts'
9
- ],
10
- transform: {
11
- '^.+\\.ts$': 'ts-jest',
12
- },
13
- collectCoverageFrom: [
14
- 'src/**/*.ts',
15
- '!src/**/*.d.ts',
16
- ],
17
- coverageDirectory: 'coverage',
18
- moduleFileExtensions: ['ts', 'js', 'json'],
19
- setupFilesAfterEnv: [],
20
- };
21
-
@@ -1,34 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- /**
10
- * Mock Validation Tests
11
- *
12
- * Per CLAUDE.md requirement: "mocks used in tests must always be validated!"
13
- * These tests verify our execa mock matches the real execa library behavior.
14
- *
15
- * NOTE: This test is skipped because execa is an ESM module and Jest requires
16
- * additional configuration to handle ESM imports. The mock structure is validated
17
- * through integration with the actual CLI wrapper functions in other test files.
18
- */
19
- describe.skip('Execa Mock Validation', () => {
20
- it('should match real execa return structure for successful commands', async () => {
21
- // Skipped - execa is ESM and requires additional Jest configuration
22
- // Mock structure is validated through CLI wrapper function tests
23
- });
24
-
25
- it('should match real execa error structure for failed commands', async () => {
26
- // Skipped - execa is ESM and requires additional Jest configuration
27
- // Error handling is validated through CLI wrapper function tests
28
- });
29
-
30
- it('should handle JSON output correctly', async () => {
31
- // Skipped - execa is ESM and requires additional Jest configuration
32
- // JSON parsing is validated through CLI wrapper function tests
33
- });
34
- });
@@ -1,77 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- // Mock CLI module before importing index
10
- jest.mock('../cli', () => ({
11
- runBrainGridCommand: jest.fn()
12
- }));
13
-
14
- // Mock all command modules to avoid loading real execa
15
- jest.mock('../commands/createIdea', () => ({
16
- createIdea: jest.fn()
17
- }));
18
- jest.mock('../commands/listProjects', () => ({
19
- listProjects: jest.fn()
20
- }));
21
- jest.mock('../commands/createProject', () => ({
22
- createProject: jest.fn()
23
- }));
24
- jest.mock('../commands/listRequirements', () => ({
25
- listRequirements: jest.fn()
26
- }));
27
- jest.mock('../commands/updateRequirementStatus', () => ({
28
- updateRequirementStatus: jest.fn()
29
- }));
30
- jest.mock('../commands/createTask', () => ({
31
- createTask: jest.fn()
32
- }));
33
- jest.mock('../commands/updateTaskStatus', () => ({
34
- updateTaskStatus: jest.fn()
35
- }));
36
- jest.mock('../commands/listTasks', () => ({
37
- listTasks: jest.fn()
38
- }));
39
-
40
- import * as BrainGridWrapper from '../index';
41
-
42
- describe('BrainGrid CLI Wrapper - Index Exports', () => {
43
- it('should export all type definitions', () => {
44
- expect(BrainGridWrapper.BrainGridProjectSchema).toBeDefined();
45
- expect(BrainGridWrapper.BrainGridRequirementSchema).toBeDefined();
46
- expect(BrainGridWrapper.BrainGridTaskSchema).toBeDefined();
47
- expect(BrainGridWrapper.BrainGridCliError).toBeDefined();
48
- });
49
-
50
- it('should export all command functions', () => {
51
- expect(typeof BrainGridWrapper.createIdea).toBe('function');
52
- expect(typeof BrainGridWrapper.listProjects).toBe('function');
53
- expect(typeof BrainGridWrapper.createProject).toBe('function');
54
- expect(typeof BrainGridWrapper.listRequirements).toBe('function');
55
- expect(typeof BrainGridWrapper.updateRequirementStatus).toBe('function');
56
- expect(typeof BrainGridWrapper.createTask).toBe('function');
57
- expect(typeof BrainGridWrapper.updateTaskStatus).toBe('function');
58
- expect(typeof BrainGridWrapper.listTasks).toBe('function');
59
- });
60
-
61
- it('should export BrainGridCliError as a class', () => {
62
- const error = new BrainGridWrapper.BrainGridCliError(
63
- 'Test error',
64
- 'braingrid test',
65
- 1,
66
- 'test stderr'
67
- );
68
-
69
- expect(error).toBeInstanceOf(Error);
70
- expect(error).toBeInstanceOf(BrainGridWrapper.BrainGridCliError);
71
- expect(error.name).toBe('BrainGridCliError');
72
- expect(error.message).toBe('Test error');
73
- expect(error.command).toBe('braingrid test');
74
- expect(error.exitCode).toBe(1);
75
- expect(error.stderr).toBe('test stderr');
76
- });
77
- });
package/src/cli.test.ts DELETED
@@ -1,86 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { runBrainGridCommand } from './cli';
10
- import { BrainGridCliError } from './models';
11
-
12
- // Mock execa
13
- jest.mock('execa', () => ({
14
- execa: jest.fn()
15
- }));
16
-
17
- import { execa } from 'execa';
18
-
19
- describe('CLI Helper', () => {
20
- beforeEach(() => {
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should run command successfully', async () => {
25
- const mockOutput = { id: 'proj-123', name: 'Test' };
26
- (execa as jest.MockedFunction<typeof execa>).mockResolvedValue({
27
- stdout: JSON.stringify(mockOutput),
28
- stderr: '',
29
- exitCode: 0
30
- } as any);
31
-
32
- const result = await runBrainGridCommand(['projects', 'list', '--format', 'json']);
33
-
34
- expect(result).toEqual(mockOutput);
35
- expect(execa).toHaveBeenCalledWith(
36
- 'braingrid',
37
- ['projects', 'list', '--format', 'json'],
38
- expect.any(Object)
39
- );
40
- });
41
-
42
- it('should handle command with no JSON output', async () => {
43
- (execa as jest.MockedFunction<typeof execa>).mockResolvedValue({
44
- stdout: 'Success',
45
- stderr: '',
46
- exitCode: 0
47
- } as any);
48
-
49
- const result = await runBrainGridCommand(['task', 'update', 'task-123']);
50
-
51
- expect(result).toBeNull();
52
- });
53
-
54
- it('should throw BrainGridCliError on failure', async () => {
55
- (execa as jest.MockedFunction<typeof execa>).mockRejectedValue({
56
- exitCode: 1,
57
- stderr: 'Invalid command',
58
- stdout: ''
59
- });
60
-
61
- await expect(
62
- runBrainGridCommand(['invalid'])
63
- ).rejects.toThrow(BrainGridCliError);
64
- });
65
-
66
- it('should use custom CLI path from env', async () => {
67
- const originalEnv = process.env.BRAINGRID_CLI_PATH;
68
- process.env.BRAINGRID_CLI_PATH = '/custom/path/braingrid';
69
-
70
- (execa as jest.MockedFunction<typeof execa>).mockResolvedValue({
71
- stdout: '{}',
72
- stderr: '',
73
- exitCode: 0
74
- } as any);
75
-
76
- await runBrainGridCommand(['projects', 'list']);
77
-
78
- expect(execa).toHaveBeenCalledWith(
79
- '/custom/path/braingrid',
80
- expect.any(Array),
81
- expect.any(Object)
82
- );
83
-
84
- process.env.BRAINGRID_CLI_PATH = originalEnv;
85
- });
86
- });
package/src/cli.ts DELETED
@@ -1,71 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { execa } from 'execa';
10
- import { BrainGridCliError } from './models';
11
-
12
- /**
13
- * Run a BrainGrid CLI command and return parsed JSON output
14
- */
15
- export async function runBrainGridCommand(
16
- args: string[],
17
- options?: {
18
- cwd?: string;
19
- env?: Record<string, string>;
20
- }
21
- ): Promise<unknown> {
22
- const cliPath = process.env.BRAINGRID_CLI_PATH || 'braingrid';
23
-
24
- try {
25
- const result = await execa(cliPath, args, {
26
- cwd: options?.cwd,
27
- env: {
28
- ...process.env,
29
- ...options?.env
30
- },
31
- timeout: 30000, // 30 second timeout
32
- reject: false // Don't throw on non-zero exit
33
- });
34
-
35
- // Check for errors
36
- if (result.exitCode !== 0) {
37
- throw new BrainGridCliError(
38
- `BrainGrid CLI command failed: ${args.join(' ')}`,
39
- cliPath,
40
- result.exitCode,
41
- result.stderr
42
- );
43
- }
44
-
45
- // Try to parse JSON output
46
- const stdout = result.stdout.trim();
47
- if (!stdout) {
48
- return null;
49
- }
50
-
51
- try {
52
- return JSON.parse(stdout);
53
- } catch (e) {
54
- // Not JSON output, return as-is
55
- return null;
56
- }
57
- } catch (error) {
58
- if (error instanceof BrainGridCliError) {
59
- throw error;
60
- }
61
-
62
- // Handle execa errors
63
- const execaError = error as Error & { exitCode?: number; stderr?: string };
64
- throw new BrainGridCliError(
65
- `Failed to execute BrainGrid CLI: ${execaError.message}`,
66
- cliPath,
67
- execaError.exitCode || -1,
68
- execaError.stderr || ''
69
- );
70
- }
71
- }
@@ -1,77 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { createIdea } from './createIdea';
10
-
11
- jest.mock('../cli', () => ({
12
- runBrainGridCommand: jest.fn()
13
- }));
14
-
15
- import { runBrainGridCommand } from '../cli';
16
-
17
- describe('createIdea', () => {
18
- beforeEach(() => {
19
- jest.clearAllMocks();
20
- });
21
-
22
- it('should create idea with prompt only', async () => {
23
- const mockReq = {
24
- id: 'req-123',
25
- projectId: 'proj-456',
26
- title: 'Add OAuth2',
27
- status: 'IDEA'
28
- };
29
-
30
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue(mockReq);
31
-
32
- const result = await createIdea('Add OAuth2 authentication');
33
-
34
- expect(runBrainGridCommand).toHaveBeenCalledWith([
35
- 'specify',
36
- 'Add OAuth2 authentication',
37
- '--format',
38
- 'json'
39
- ]);
40
-
41
- expect(result.id).toBe('req-123');
42
- expect(result.status).toBe('IDEA');
43
- });
44
-
45
- it('should create idea with project ID', async () => {
46
- const mockReq = {
47
- id: 'req-123',
48
- projectId: 'proj-456',
49
- title: 'Add OAuth2',
50
- status: 'IDEA'
51
- };
52
-
53
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue(mockReq);
54
-
55
- await createIdea('Add OAuth2 authentication', 'proj-456');
56
-
57
- expect(runBrainGridCommand).toHaveBeenCalledWith([
58
- 'specify',
59
- 'Add OAuth2 authentication',
60
- '--project',
61
- 'proj-456',
62
- '--format',
63
- 'json'
64
- ]);
65
- });
66
-
67
- it('should validate response schema', async () => {
68
- const invalidReq = {
69
- id: 123, // Should be string
70
- title: 'Test'
71
- };
72
-
73
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue(invalidReq);
74
-
75
- await expect(createIdea('Test')).rejects.toThrow();
76
- });
77
- });
@@ -1,36 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { runBrainGridCommand } from '../cli';
10
- import { BrainGridRequirement, BrainGridRequirementSchema } from '../models';
11
-
12
- /**
13
- * Create a new requirement (IDEA) in BrainGrid
14
- */
15
- export async function createIdea(
16
- prompt: string,
17
- projectId?: string
18
- ): Promise<BrainGridRequirement> {
19
- const args = ['specify', prompt];
20
-
21
- if (projectId) {
22
- args.push('--project', projectId);
23
- }
24
-
25
- args.push('--format', 'json');
26
-
27
- const result = await runBrainGridCommand(args);
28
-
29
- // Validate response
30
- const parsed = BrainGridRequirementSchema.safeParse(result);
31
- if (!parsed.success) {
32
- throw new Error(`Invalid BrainGrid response: ${parsed.error.message}`);
33
- }
34
-
35
- return parsed.data;
36
- }
@@ -1,75 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { createProject } from './createProject';
10
-
11
- jest.mock('../cli', () => ({
12
- runBrainGridCommand: jest.fn()
13
- }));
14
-
15
- import { runBrainGridCommand } from '../cli';
16
-
17
- describe('createProject', () => {
18
- beforeEach(() => {
19
- jest.clearAllMocks();
20
- });
21
-
22
- it('should create project with name only', async () => {
23
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue({
24
- id: 'proj-123',
25
- name: 'Test Project'
26
- });
27
-
28
- const result = await createProject('Test Project');
29
-
30
- expect(runBrainGridCommand).toHaveBeenCalledWith([
31
- 'project',
32
- 'create',
33
- '--name',
34
- 'Test Project',
35
- '--format',
36
- 'json'
37
- ]);
38
- expect(result).toEqual({
39
- id: 'proj-123',
40
- name: 'Test Project'
41
- });
42
- });
43
-
44
- it('should create project with name and description', async () => {
45
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue({
46
- id: 'proj-456',
47
- name: 'My Project',
48
- description: 'Project description'
49
- });
50
-
51
- const result = await createProject('My Project', 'Project description');
52
-
53
- expect(runBrainGridCommand).toHaveBeenCalledWith([
54
- 'project',
55
- 'create',
56
- '--name',
57
- 'My Project',
58
- '--format',
59
- 'json',
60
- '--description',
61
- 'Project description'
62
- ]);
63
- expect(result).toEqual({
64
- id: 'proj-456',
65
- name: 'My Project',
66
- description: 'Project description'
67
- });
68
- });
69
-
70
- it('should throw on invalid response', async () => {
71
- (runBrainGridCommand as jest.MockedFunction<typeof runBrainGridCommand>).mockResolvedValue({ invalid: 'data' });
72
-
73
- await expect(createProject('Test')).rejects.toThrow();
74
- });
75
- });
@@ -1,37 +0,0 @@
1
- /*
2
- Copyright (c) 2025 Bernier LLC
3
-
4
- This file is licensed to the client under a limited-use license.
5
- The client may use and modify this code *only within the scope of the project it was delivered for*.
6
- Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
- */
8
-
9
- import { runBrainGridCommand } from '../cli';
10
- import { BrainGridProject, BrainGridProjectSchema } from '../models';
11
-
12
- /**
13
- * Creates a new BrainGrid project
14
- * @param name - Project name (required)
15
- * @param description - Project description (optional)
16
- * @returns Promise resolving to the created project
17
- */
18
- export async function createProject(
19
- name: string,
20
- description?: string
21
- ): Promise<BrainGridProject> {
22
- const args = ['project', 'create', '--name', name, '--format', 'json'];
23
-
24
- if (description) {
25
- args.push('--description', description);
26
- }
27
-
28
- const result = await runBrainGridCommand(args);
29
-
30
- // Validate response
31
- const parsed = BrainGridProjectSchema.safeParse(result);
32
- if (!parsed.success) {
33
- throw new Error(`Invalid BrainGrid response: ${parsed.error.message}`);
34
- }
35
-
36
- return parsed.data;
37
- }