@agents-at-scale/ark 0.1.52 → 0.1.55

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 (116) hide show
  1. package/dist/arkServices.js +11 -7
  2. package/dist/commands/export/index.js +6 -4
  3. package/dist/commands/generate/generators/agent.js +2 -0
  4. package/dist/commands/generate/generators/marketplace.js +2 -0
  5. package/dist/commands/generate/generators/mcpserver.js +2 -0
  6. package/dist/commands/generate/generators/project.js +9 -2
  7. package/dist/commands/generate/generators/query.js +2 -0
  8. package/dist/commands/generate/generators/team.js +2 -0
  9. package/dist/commands/generate/templateDiscovery.js +1 -0
  10. package/dist/commands/generate/templateEngine.js +1 -3
  11. package/dist/commands/import/index.js +1 -1
  12. package/dist/commands/install/index.js +2 -1
  13. package/dist/commands/models/kubernetes/manifest-builder.js +27 -10
  14. package/dist/commands/models/providers/azure.d.ts +10 -7
  15. package/dist/commands/models/providers/azure.js +83 -21
  16. package/dist/commands/uninstall/index.js +1 -1
  17. package/dist/components/ChatUI.js +17 -16
  18. package/dist/components/statusChecker.js +3 -3
  19. package/dist/lib/arkApiClient.js +11 -9
  20. package/dist/lib/arkApiProxy.js +1 -0
  21. package/dist/lib/arkServiceProxy.js +5 -1
  22. package/dist/lib/chatClient.js +9 -0
  23. package/dist/lib/config.js +8 -3
  24. package/dist/lib/errors.js +3 -0
  25. package/dist/ui/asyncOperations/connectingToArk.js +2 -2
  26. package/package.json +17 -13
  27. package/dist/arkServices.spec.d.ts +0 -1
  28. package/dist/arkServices.spec.js +0 -138
  29. package/dist/commands/agents/index.spec.d.ts +0 -1
  30. package/dist/commands/agents/index.spec.js +0 -67
  31. package/dist/commands/cluster/get.spec.d.ts +0 -1
  32. package/dist/commands/cluster/get.spec.js +0 -92
  33. package/dist/commands/cluster/index.spec.d.ts +0 -1
  34. package/dist/commands/cluster/index.spec.js +0 -24
  35. package/dist/commands/completion/index.spec.d.ts +0 -1
  36. package/dist/commands/completion/index.spec.js +0 -34
  37. package/dist/commands/config/index.spec.d.ts +0 -1
  38. package/dist/commands/config/index.spec.js +0 -78
  39. package/dist/commands/evaluation/index.spec.d.ts +0 -1
  40. package/dist/commands/evaluation/index.spec.js +0 -161
  41. package/dist/commands/export/index.spec.d.ts +0 -1
  42. package/dist/commands/export/index.spec.js +0 -145
  43. package/dist/commands/import/index.spec.d.ts +0 -1
  44. package/dist/commands/import/index.spec.js +0 -46
  45. package/dist/commands/install/index.spec.d.ts +0 -1
  46. package/dist/commands/install/index.spec.js +0 -286
  47. package/dist/commands/marketplace/index.spec.d.ts +0 -1
  48. package/dist/commands/marketplace/index.spec.js +0 -88
  49. package/dist/commands/memory/index.spec.d.ts +0 -1
  50. package/dist/commands/memory/index.spec.js +0 -124
  51. package/dist/commands/models/create.spec.d.ts +0 -1
  52. package/dist/commands/models/create.spec.js +0 -167
  53. package/dist/commands/models/index.spec.d.ts +0 -1
  54. package/dist/commands/models/index.spec.js +0 -96
  55. package/dist/commands/models/providers/azure.spec.d.ts +0 -1
  56. package/dist/commands/models/providers/azure.spec.js +0 -232
  57. package/dist/commands/models/providers/bedrock.spec.d.ts +0 -1
  58. package/dist/commands/models/providers/bedrock.spec.js +0 -241
  59. package/dist/commands/models/providers/openai.spec.d.ts +0 -1
  60. package/dist/commands/models/providers/openai.spec.js +0 -180
  61. package/dist/commands/queries/delete.spec.d.ts +0 -1
  62. package/dist/commands/queries/delete.spec.js +0 -74
  63. package/dist/commands/queries/index.spec.d.ts +0 -1
  64. package/dist/commands/queries/index.spec.js +0 -167
  65. package/dist/commands/queries/list.spec.d.ts +0 -1
  66. package/dist/commands/queries/list.spec.js +0 -170
  67. package/dist/commands/queries/validation.spec.d.ts +0 -1
  68. package/dist/commands/queries/validation.spec.js +0 -27
  69. package/dist/commands/query/index.spec.d.ts +0 -1
  70. package/dist/commands/query/index.spec.js +0 -104
  71. package/dist/commands/targets/index.spec.d.ts +0 -1
  72. package/dist/commands/targets/index.spec.js +0 -154
  73. package/dist/commands/teams/index.spec.d.ts +0 -1
  74. package/dist/commands/teams/index.spec.js +0 -70
  75. package/dist/commands/tools/index.spec.d.ts +0 -1
  76. package/dist/commands/tools/index.spec.js +0 -70
  77. package/dist/commands/uninstall/index.spec.d.ts +0 -1
  78. package/dist/commands/uninstall/index.spec.js +0 -125
  79. package/dist/lib/arkServiceProxy.spec.d.ts +0 -1
  80. package/dist/lib/arkServiceProxy.spec.js +0 -100
  81. package/dist/lib/arkStatus.spec.d.ts +0 -1
  82. package/dist/lib/arkStatus.spec.js +0 -49
  83. package/dist/lib/chatClient.spec.d.ts +0 -1
  84. package/dist/lib/chatClient.spec.js +0 -108
  85. package/dist/lib/cluster.spec.d.ts +0 -1
  86. package/dist/lib/cluster.spec.js +0 -338
  87. package/dist/lib/commands.spec.d.ts +0 -1
  88. package/dist/lib/commands.spec.js +0 -146
  89. package/dist/lib/config.spec.d.ts +0 -1
  90. package/dist/lib/config.spec.js +0 -202
  91. package/dist/lib/duration.spec.d.ts +0 -1
  92. package/dist/lib/duration.spec.js +0 -13
  93. package/dist/lib/errors.spec.d.ts +0 -1
  94. package/dist/lib/errors.spec.js +0 -221
  95. package/dist/lib/executeQuery.spec.d.ts +0 -1
  96. package/dist/lib/executeQuery.spec.js +0 -325
  97. package/dist/lib/kubectl.spec.d.ts +0 -1
  98. package/dist/lib/kubectl.spec.js +0 -192
  99. package/dist/lib/marketplaceFetcher.spec.d.ts +0 -1
  100. package/dist/lib/marketplaceFetcher.spec.js +0 -225
  101. package/dist/lib/nextSteps.spec.d.ts +0 -1
  102. package/dist/lib/nextSteps.spec.js +0 -59
  103. package/dist/lib/output.spec.d.ts +0 -1
  104. package/dist/lib/output.spec.js +0 -123
  105. package/dist/lib/startup.spec.d.ts +0 -1
  106. package/dist/lib/startup.spec.js +0 -152
  107. package/dist/lib/stdin.spec.d.ts +0 -1
  108. package/dist/lib/stdin.spec.js +0 -82
  109. package/dist/lib/timeout.spec.d.ts +0 -1
  110. package/dist/lib/timeout.spec.js +0 -14
  111. package/dist/lib/waitForReady.spec.d.ts +0 -1
  112. package/dist/lib/waitForReady.spec.js +0 -104
  113. package/dist/marketplaceServices.spec.d.ts +0 -1
  114. package/dist/marketplaceServices.spec.js +0 -74
  115. package/dist/ui/statusFormatter.spec.d.ts +0 -1
  116. package/dist/ui/statusFormatter.spec.js +0 -58
@@ -1,88 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockGetAllMarketplaceServices = jest.fn();
4
- const mockGetAllMarketplaceAgents = jest.fn();
5
- const mockFetchMarketplaceManifest = jest.fn();
6
- const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
7
- jest.unstable_mockModule('../../marketplaceServices.js', () => ({
8
- getAllMarketplaceServices: mockGetAllMarketplaceServices,
9
- getAllMarketplaceAgents: mockGetAllMarketplaceAgents,
10
- }));
11
- jest.unstable_mockModule('../../lib/marketplaceFetcher.js', () => ({
12
- fetchMarketplaceManifest: mockFetchMarketplaceManifest,
13
- }));
14
- const { createMarketplaceCommand } = await import('./index.js');
15
- describe('marketplace command', () => {
16
- beforeEach(() => {
17
- jest.clearAllMocks();
18
- });
19
- it('creates marketplace command with correct structure', () => {
20
- const command = createMarketplaceCommand({});
21
- expect(command).toBeInstanceOf(Command);
22
- expect(command.name()).toBe('marketplace');
23
- });
24
- it('lists services and agents from manifest', async () => {
25
- const mockServices = {
26
- 'test-service': {
27
- name: 'test-service',
28
- helmReleaseName: 'test-service',
29
- description: 'Test service description',
30
- enabled: true,
31
- category: 'marketplace',
32
- namespace: 'test-ns',
33
- },
34
- };
35
- const mockAgents = {
36
- 'test-agent': {
37
- name: 'test-agent',
38
- helmReleaseName: 'test-agent',
39
- description: 'Test agent description',
40
- enabled: true,
41
- category: 'marketplace',
42
- namespace: 'test-ns',
43
- },
44
- };
45
- const mockManifest = {
46
- version: '1.0.0',
47
- marketplace: 'ARK Marketplace',
48
- items: [
49
- {
50
- name: 'test-service',
51
- description: 'Test service',
52
- type: 'service',
53
- ark: {
54
- chartPath: 'oci://registry/test-service',
55
- namespace: 'test',
56
- },
57
- },
58
- {
59
- name: 'test-agent',
60
- description: 'Test agent',
61
- type: 'agent',
62
- ark: {
63
- chartPath: 'oci://registry/test-agent',
64
- namespace: 'test',
65
- },
66
- },
67
- ],
68
- };
69
- mockGetAllMarketplaceServices.mockResolvedValue(mockServices);
70
- mockGetAllMarketplaceAgents.mockResolvedValue(mockAgents);
71
- mockFetchMarketplaceManifest.mockResolvedValue(mockManifest);
72
- const command = createMarketplaceCommand({});
73
- await command.parseAsync(['node', 'test', 'list']);
74
- expect(mockGetAllMarketplaceServices).toHaveBeenCalled();
75
- expect(mockGetAllMarketplaceAgents).toHaveBeenCalled();
76
- expect(mockConsoleLog).toHaveBeenCalled();
77
- });
78
- it('shows unavailable message when marketplace unavailable', async () => {
79
- mockGetAllMarketplaceServices.mockResolvedValue(null);
80
- mockGetAllMarketplaceAgents.mockResolvedValue(null);
81
- mockFetchMarketplaceManifest.mockResolvedValue(null);
82
- const command = createMarketplaceCommand({});
83
- await command.parseAsync(['node', 'test', 'list']);
84
- expect(mockConsoleLog).toHaveBeenCalled();
85
- const logCalls = mockConsoleLog.mock.calls.map((c) => c[0]).join(' ');
86
- expect(logCalls).toContain('unavailable');
87
- });
88
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,124 +0,0 @@
1
- import { describe, it, expect, jest, beforeEach, afterEach, beforeAll, } from '@jest/globals';
2
- // ESM-safe mocking: declare variables to hold dynamically imported modules
3
- let createMemoryCommand;
4
- let deleteSession;
5
- let deleteQuery;
6
- let deleteAll;
7
- let ArkApiProxy;
8
- let output;
9
- // Mock dependencies
10
- jest.unstable_mockModule('../../lib/output.js', () => ({
11
- default: {
12
- info: jest.fn(),
13
- success: jest.fn(),
14
- error: jest.fn(),
15
- },
16
- }));
17
- // Mock ArkApiProxy with a simpler approach
18
- jest.unstable_mockModule('../../lib/arkApiProxy.js', () => ({
19
- __esModule: true,
20
- ArkApiProxy: jest.fn().mockImplementation(() => ({
21
- start: jest.fn(),
22
- stop: jest.fn(),
23
- })),
24
- }));
25
- beforeAll(async () => {
26
- // After mocks are registered, dynamically import modules
27
- ({ ArkApiProxy } = await import('../../lib/arkApiProxy.js'));
28
- ({ default: output } = await import('../../lib/output.js'));
29
- ({ createMemoryCommand, deleteSession, deleteQuery, deleteAll } = await import('./index.js'));
30
- });
31
- describe('Memory Command', () => {
32
- let mockConfig;
33
- beforeEach(() => {
34
- jest.clearAllMocks();
35
- mockConfig = {};
36
- });
37
- afterEach(() => {
38
- jest.restoreAllMocks();
39
- });
40
- describe('Command Structure', () => {
41
- it('should create memory command with correct structure', () => {
42
- const command = createMemoryCommand(mockConfig);
43
- expect(command.name()).toBe('memory');
44
- expect(command.alias()).toBe('mem');
45
- expect(command.description()).toBe('Manage memory sessions and queries');
46
- });
47
- it('should have list subcommand', () => {
48
- const command = createMemoryCommand(mockConfig);
49
- const subcommands = command.commands.map((cmd) => cmd.name());
50
- expect(subcommands).toContain('list');
51
- });
52
- it('should have delete subcommand with nested commands and flags', () => {
53
- const command = createMemoryCommand(mockConfig);
54
- const deleteCommand = command.commands.find((cmd) => cmd.name() === 'delete');
55
- expect(deleteCommand).toBeDefined();
56
- expect(deleteCommand?.description()).toBe('Delete memory data');
57
- const deleteSubcommands = deleteCommand?.commands.map((cmd) => cmd.name()) || [];
58
- expect(deleteSubcommands).toContain('session');
59
- expect(deleteSubcommands).toContain('query');
60
- // --all flag is supported on the delete root instead of an 'all' subcommand
61
- });
62
- });
63
- describe('Command Creation', () => {
64
- it('should create command without errors', () => {
65
- expect(() => createMemoryCommand(mockConfig)).not.toThrow();
66
- });
67
- it('should return a command object', () => {
68
- const command = createMemoryCommand(mockConfig);
69
- expect(command).toBeDefined();
70
- expect(typeof command.name).toBe('function');
71
- expect(typeof command.description).toBe('function');
72
- });
73
- });
74
- describe('Error Scenarios', () => {
75
- let exitSpy;
76
- beforeEach(async () => {
77
- exitSpy = jest
78
- .spyOn(process, 'exit')
79
- .mockImplementation(((..._args) => undefined));
80
- });
81
- afterEach(() => {
82
- exitSpy.mockRestore();
83
- });
84
- it('deleteSession handles 500 error', async () => {
85
- const err = new Error('Internal Server Error');
86
- const fakeClient = {
87
- deleteSession: jest.fn().mockRejectedValue(err),
88
- };
89
- ArkApiProxy.mockImplementation(() => ({
90
- start: jest.fn().mockResolvedValue(fakeClient),
91
- stop: jest.fn(),
92
- }));
93
- await deleteSession('sess-1', { output: 'text' }).catch(() => { });
94
- expect(output.error).toHaveBeenCalled();
95
- expect(process.exit).toHaveBeenCalledWith(1);
96
- });
97
- it('deleteQuery handles network timeout', async () => {
98
- const err = new Error('Network timeout');
99
- const fakeClient = {
100
- deleteQueryMessages: jest.fn().mockRejectedValue(err),
101
- };
102
- ArkApiProxy.mockImplementation(() => ({
103
- start: jest.fn().mockResolvedValue(fakeClient),
104
- stop: jest.fn(),
105
- }));
106
- await deleteQuery('sess-2', 'query-9', { output: 'text' }).catch(() => { });
107
- expect(output.error).toHaveBeenCalled();
108
- expect(process.exit).toHaveBeenCalledWith(1);
109
- });
110
- it('deleteAll handles no memory services reachable', async () => {
111
- const err = new Error('No memory services reachable');
112
- const fakeClient = {
113
- deleteAllSessions: jest.fn().mockRejectedValue(err),
114
- };
115
- ArkApiProxy.mockImplementation(() => ({
116
- start: jest.fn().mockResolvedValue(fakeClient),
117
- stop: jest.fn(),
118
- }));
119
- await deleteAll({ output: 'text' }).catch(() => { });
120
- expect(output.error).toHaveBeenCalled();
121
- expect(process.exit).toHaveBeenCalledWith(1);
122
- });
123
- });
124
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,167 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- const mockExeca = jest.fn();
3
- jest.unstable_mockModule('execa', () => ({
4
- execa: mockExeca,
5
- }));
6
- const mockInquirer = {
7
- prompt: jest.fn(),
8
- };
9
- jest.unstable_mockModule('inquirer', () => ({
10
- default: mockInquirer,
11
- }));
12
- const mockOutput = {
13
- info: jest.fn(),
14
- warning: jest.fn(),
15
- error: jest.fn(),
16
- success: jest.fn(),
17
- };
18
- jest.unstable_mockModule('../../lib/output.js', () => ({
19
- default: mockOutput,
20
- }));
21
- jest.spyOn(console, 'log').mockImplementation(() => { });
22
- jest.spyOn(console, 'error').mockImplementation(() => { });
23
- const { createModel } = await import('./create.js');
24
- describe('createModel', () => {
25
- beforeEach(() => {
26
- jest.clearAllMocks();
27
- });
28
- it('creates new model for type aws bedrock', async () => {
29
- mockExeca.mockRejectedValueOnce(new Error('not found')); // model doesn't exist
30
- mockInquirer.prompt
31
- .mockResolvedValueOnce({ modelType: 'bedrock' }) // user selects from list
32
- .mockResolvedValueOnce({ model: 'anthropic.claude-3-sonnet-20240229-v1:0' })
33
- .mockResolvedValueOnce({ region: 'us-east-1' })
34
- .mockResolvedValueOnce({ accessKeyId: 'AKIAIOSFODNN7EXAMPLE' })
35
- .mockResolvedValueOnce({
36
- secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
37
- })
38
- .mockResolvedValueOnce({ sessionToken: 'optional-session-token' })
39
- .mockResolvedValueOnce({
40
- modelArn: 'arn:aws:bedrock:us-east-1:123456789012:model/anthropic.claude-3-sonnet-20240229-v1:0',
41
- });
42
- mockExeca.mockResolvedValue({}); // kubectl ops succeed
43
- await createModel('test-model');
44
- // Verify that model type prompt was called
45
- expect(mockInquirer.prompt).toHaveBeenCalledWith([
46
- expect.objectContaining({
47
- type: 'list',
48
- name: 'modelType',
49
- message: 'select model provider:',
50
- choices: expect.arrayContaining([
51
- { name: 'Azure OpenAI', value: 'azure' },
52
- { name: 'OpenAI', value: 'openai' },
53
- { name: 'AWS Bedrock', value: 'bedrock' },
54
- ]),
55
- }),
56
- ]);
57
- // Verify Bedrock-specific prompts were called
58
- expect(mockInquirer.prompt).toHaveBeenCalledWith([
59
- expect.objectContaining({
60
- name: 'region',
61
- message: 'AWS region:',
62
- }),
63
- ]);
64
- expect(mockInquirer.prompt).toHaveBeenCalledWith([
65
- expect.objectContaining({
66
- name: 'accessKeyId',
67
- message: 'AWS access key ID:',
68
- }),
69
- ]);
70
- expect(mockInquirer.prompt).toHaveBeenCalledWith([
71
- expect.objectContaining({
72
- name: 'secretAccessKey',
73
- message: 'AWS secret access key:',
74
- type: 'password',
75
- }),
76
- ]);
77
- expect(mockOutput.success).toHaveBeenCalledWith('model test-model created');
78
- });
79
- it('creates new model with provided name', async () => {
80
- // Model doesn't exist
81
- mockExeca.mockRejectedValueOnce(new Error('not found'));
82
- // Prompts for model details
83
- mockInquirer.prompt
84
- .mockResolvedValueOnce({ modelType: 'openai' })
85
- .mockResolvedValueOnce({ model: 'gpt-4' })
86
- .mockResolvedValueOnce({ baseUrl: 'https://api.openai.com/' })
87
- .mockResolvedValueOnce({ apiKey: 'secret-key' });
88
- // Secret operations succeed
89
- mockExeca.mockResolvedValueOnce({}); // create secret
90
- mockExeca.mockResolvedValueOnce({}); // apply model
91
- const result = await createModel('test-model');
92
- expect(result).toBe(true);
93
- expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'model', 'test-model'], { stdio: 'pipe' });
94
- expect(mockOutput.success).toHaveBeenCalledWith('model test-model created');
95
- });
96
- it('prompts for name when not provided', async () => {
97
- mockInquirer.prompt
98
- .mockResolvedValueOnce({ modelName: 'prompted-model' })
99
- .mockResolvedValueOnce({ modelType: 'azure' })
100
- .mockResolvedValueOnce({ model: 'gpt-4' })
101
- .mockResolvedValueOnce({ baseUrl: 'https://azure.com' })
102
- .mockResolvedValueOnce({ apiVersion: '2024-12-01' })
103
- .mockResolvedValueOnce({ apiKey: 'secret' });
104
- mockExeca.mockRejectedValueOnce(new Error('not found')); // model doesn't exist
105
- mockExeca.mockResolvedValue({}); // all kubectl ops succeed
106
- const result = await createModel();
107
- expect(result).toBe(true);
108
- expect(mockInquirer.prompt).toHaveBeenCalledWith([
109
- expect.objectContaining({
110
- name: 'modelName',
111
- message: 'model name:',
112
- }),
113
- ]);
114
- });
115
- it('handles overwrite confirmation when model exists', async () => {
116
- // Model exists
117
- mockExeca.mockResolvedValueOnce({});
118
- mockInquirer.prompt
119
- .mockResolvedValueOnce({ overwrite: true })
120
- .mockResolvedValueOnce({ modelType: 'openai' })
121
- .mockResolvedValueOnce({ model: 'gpt-4' })
122
- .mockResolvedValueOnce({ baseUrl: 'https://api.openai.com' })
123
- .mockResolvedValueOnce({ apiKey: 'secret' });
124
- mockExeca.mockResolvedValue({}); // remaining kubectl ops
125
- const result = await createModel('existing-model');
126
- expect(result).toBe(true);
127
- expect(mockOutput.warning).toHaveBeenCalledWith('model existing-model already exists');
128
- });
129
- it('cancels when user declines overwrite', async () => {
130
- mockExeca.mockResolvedValueOnce({}); // model exists
131
- mockInquirer.prompt.mockResolvedValueOnce({ overwrite: false });
132
- const result = await createModel('existing-model');
133
- expect(result).toBe(false);
134
- expect(mockOutput.info).toHaveBeenCalledWith('model creation cancelled');
135
- });
136
- it('handles secret creation failure', async () => {
137
- mockExeca
138
- .mockRejectedValueOnce(new Error('not found')); // model doesn't exist
139
- mockInquirer.prompt
140
- .mockResolvedValueOnce({ modelType: 'openai' })
141
- .mockResolvedValueOnce({ model: 'gpt-4' })
142
- .mockResolvedValueOnce({ baseUrl: 'https://api.openai.com' })
143
- .mockResolvedValueOnce({ apiKey: 'secret' });
144
- mockExeca
145
- .mockRejectedValueOnce(new Error('not found')); // secret doesn't exist check
146
- mockExeca.mockRejectedValueOnce(new Error('secret creation failed')); // create secret fails
147
- const result = await createModel('test-model');
148
- expect(result).toBe(false);
149
- expect(mockOutput.error).toHaveBeenCalledWith('failed to create secret');
150
- });
151
- it('updates existing secret when secret already exists', async () => {
152
- mockExeca.mockRejectedValueOnce(new Error('not found')); // model doesn't exist
153
- mockInquirer.prompt
154
- .mockResolvedValueOnce({ modelType: 'openai' })
155
- .mockResolvedValueOnce({ model: 'gpt-4' })
156
- .mockResolvedValueOnce({ baseUrl: 'https://api.openai.com' })
157
- .mockResolvedValueOnce({ apiKey: 'new-secret-key' });
158
- mockExeca.mockResolvedValueOnce({}); // secret exists check
159
- mockExeca.mockResolvedValueOnce({ stdout: 'secret yaml' }); // dry-run output
160
- mockExeca.mockResolvedValueOnce({}); // kubectl apply
161
- mockExeca.mockResolvedValueOnce({}); // apply model
162
- const result = await createModel('test-model');
163
- expect(result).toBe(true);
164
- expect(mockOutput.success).toHaveBeenCalledWith('updated secret test-model-model-secret');
165
- expect(mockOutput.success).toHaveBeenCalledWith('model test-model created');
166
- });
167
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,96 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockExeca = jest.fn();
4
- jest.unstable_mockModule('execa', () => ({
5
- execa: mockExeca,
6
- }));
7
- const mockOutput = {
8
- info: jest.fn(),
9
- error: jest.fn(),
10
- };
11
- jest.unstable_mockModule('../../lib/output.js', () => ({
12
- default: mockOutput,
13
- }));
14
- const mockCreateModel = jest.fn();
15
- jest.unstable_mockModule('./create.js', () => ({
16
- createModel: mockCreateModel,
17
- }));
18
- const mockExecuteQuery = jest.fn();
19
- jest.unstable_mockModule('../../lib/executeQuery.js', () => ({
20
- executeQuery: mockExecuteQuery,
21
- parseTarget: jest.fn(),
22
- }));
23
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
24
- throw new Error('process.exit called');
25
- }));
26
- const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
27
- const { createModelsCommand } = await import('./index.js');
28
- describe('models command', () => {
29
- beforeEach(() => {
30
- jest.clearAllMocks();
31
- });
32
- it('creates command with correct structure', () => {
33
- const command = createModelsCommand({});
34
- expect(command).toBeInstanceOf(Command);
35
- expect(command.name()).toBe('models');
36
- });
37
- it('lists models in text format', async () => {
38
- const mockModels = {
39
- items: [{ metadata: { name: 'gpt-4' } }, { metadata: { name: 'claude-3' } }],
40
- };
41
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockModels) });
42
- const command = createModelsCommand({});
43
- await command.parseAsync(['node', 'test']);
44
- expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'models', '-o', 'json'], { stdio: 'pipe' });
45
- expect(mockConsoleLog).toHaveBeenCalledWith('gpt-4');
46
- expect(mockConsoleLog).toHaveBeenCalledWith('claude-3');
47
- });
48
- it('lists models in json format', async () => {
49
- const mockModels = {
50
- items: [{ metadata: { name: 'gpt-4' } }],
51
- };
52
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockModels) });
53
- const command = createModelsCommand({});
54
- await command.parseAsync(['node', 'test', '-o', 'json']);
55
- expect(mockConsoleLog).toHaveBeenCalledWith(JSON.stringify(mockModels.items, null, 2));
56
- });
57
- it('shows info when no models', async () => {
58
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
59
- const command = createModelsCommand({});
60
- await command.parseAsync(['node', 'test']);
61
- expect(mockOutput.info).toHaveBeenCalledWith('No models found');
62
- });
63
- it('handles errors', async () => {
64
- mockExeca.mockRejectedValue(new Error('kubectl failed'));
65
- const command = createModelsCommand({});
66
- await expect(command.parseAsync(['node', 'test'])).rejects.toThrow('process.exit called');
67
- expect(mockOutput.error).toHaveBeenCalledWith('fetching models:', 'kubectl failed');
68
- expect(mockExit).toHaveBeenCalledWith(1);
69
- });
70
- it('list subcommand works', async () => {
71
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
72
- const command = createModelsCommand({});
73
- await command.parseAsync(['node', 'test', 'list']);
74
- expect(mockExeca).toHaveBeenCalled();
75
- });
76
- it('create subcommand works', async () => {
77
- const command = createModelsCommand({});
78
- await command.parseAsync(['node', 'test', 'create', 'my-model']);
79
- expect(mockCreateModel).toHaveBeenCalledWith('my-model', expect.objectContaining({}));
80
- });
81
- it('query subcommand works', async () => {
82
- const command = createModelsCommand({});
83
- await command.parseAsync([
84
- 'node',
85
- 'test',
86
- 'query',
87
- 'default',
88
- 'Hello world',
89
- ]);
90
- expect(mockExecuteQuery).toHaveBeenCalledWith({
91
- targetType: 'model',
92
- targetName: 'default',
93
- message: 'Hello world',
94
- });
95
- });
96
- });
@@ -1 +0,0 @@
1
- export {};