@agents-at-scale/ark 0.1.40 → 0.1.42
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/arkServices.js +12 -0
- package/dist/commands/completion/index.js +11 -1
- package/dist/commands/evaluation/index.d.ts +3 -0
- package/dist/commands/evaluation/index.js +60 -0
- package/dist/commands/evaluation/index.spec.d.ts +1 -0
- package/dist/commands/evaluation/index.spec.js +166 -0
- package/dist/commands/memory/index.d.ts +15 -0
- package/dist/commands/memory/index.js +130 -0
- package/dist/commands/memory/index.spec.d.ts +1 -0
- package/dist/commands/memory/index.spec.js +124 -0
- package/dist/commands/models/create.d.ts +5 -6
- package/dist/commands/models/create.js +14 -119
- package/dist/commands/models/create.spec.js +47 -0
- package/dist/commands/models/kubernetes/manifest-builder.d.ts +11 -0
- package/dist/commands/models/kubernetes/manifest-builder.js +109 -0
- package/dist/commands/models/kubernetes/secret-manager.d.ts +7 -0
- package/dist/commands/models/kubernetes/secret-manager.js +20 -0
- package/dist/commands/models/providers/azure.d.ts +31 -0
- package/dist/commands/models/providers/azure.js +82 -0
- package/dist/commands/models/providers/azure.spec.d.ts +1 -0
- package/dist/commands/models/providers/azure.spec.js +230 -0
- package/dist/commands/models/providers/bedrock.d.ts +37 -0
- package/dist/commands/models/providers/bedrock.js +105 -0
- package/dist/commands/models/providers/bedrock.spec.d.ts +1 -0
- package/dist/commands/models/providers/bedrock.spec.js +241 -0
- package/dist/commands/models/providers/factory.d.ts +18 -0
- package/dist/commands/models/providers/factory.js +31 -0
- package/dist/commands/models/providers/index.d.ts +17 -0
- package/dist/commands/models/providers/index.js +9 -0
- package/dist/commands/models/providers/openai.d.ts +28 -0
- package/dist/commands/models/providers/openai.js +68 -0
- package/dist/commands/models/providers/openai.spec.d.ts +1 -0
- package/dist/commands/models/providers/openai.spec.js +180 -0
- package/dist/commands/models/providers/types.d.ts +51 -0
- package/dist/commands/models/providers/types.js +1 -0
- package/dist/commands/queries/index.d.ts +3 -0
- package/dist/commands/queries/index.js +70 -0
- package/dist/commands/query/index.js +3 -1
- package/dist/commands/query/index.spec.js +24 -0
- package/dist/components/ChatUI.js +82 -16
- package/dist/index.js +6 -0
- package/dist/lib/arkApiClient.d.ts +4 -0
- package/dist/lib/arkApiClient.js +55 -0
- package/dist/lib/errors.d.ts +1 -0
- package/dist/lib/errors.js +1 -0
- package/dist/lib/executeEvaluation.d.ts +16 -0
- package/dist/lib/executeEvaluation.js +155 -0
- package/dist/lib/executeQuery.d.ts +1 -0
- package/dist/lib/executeQuery.js +48 -10
- package/dist/lib/executeQuery.spec.js +3 -3
- package/dist/lib/kubectl.d.ts +8 -0
- package/dist/lib/kubectl.js +20 -0
- package/dist/lib/kubectl.spec.d.ts +1 -0
- package/dist/lib/kubectl.spec.js +88 -0
- package/dist/lib/stdin.d.ts +1 -0
- package/dist/lib/stdin.js +16 -0
- package/dist/lib/stdin.spec.d.ts +1 -0
- package/dist/lib/stdin.spec.js +82 -0
- package/dist/lib/types.d.ts +39 -0
- package/dist/ui/TargetSelector.d.ts +19 -0
- package/dist/ui/TargetSelector.js +48 -0
- package/package.json +2 -1
- package/dist/ui/AgentSelector.d.ts +0 -8
- package/dist/ui/AgentSelector.js +0 -53
- package/dist/ui/ModelSelector.d.ts +0 -8
- package/dist/ui/ModelSelector.js +0 -53
- package/dist/ui/TeamSelector.d.ts +0 -8
- package/dist/ui/TeamSelector.js +0 -55
- package/dist/ui/ToolSelector.d.ts +0 -8
- package/dist/ui/ToolSelector.js +0 -53
package/dist/arkServices.js
CHANGED
|
@@ -128,6 +128,18 @@ const defaultArkServices = {
|
|
|
128
128
|
k8sDeploymentName: 'ark-mcp',
|
|
129
129
|
k8sDevDeploymentName: 'ark-mcp-devspace',
|
|
130
130
|
},
|
|
131
|
+
'mcp-filesystem': {
|
|
132
|
+
name: 'mcp-filesystem',
|
|
133
|
+
helmReleaseName: 'mcp-filesystem',
|
|
134
|
+
description: 'Stateful filesystem MCP server with workspace isolation',
|
|
135
|
+
enabled: false,
|
|
136
|
+
category: 'service',
|
|
137
|
+
// namespace: undefined - uses current context namespace
|
|
138
|
+
chartPath: `${REGISTRY_BASE}/mcp-filesystem`,
|
|
139
|
+
installArgs: [],
|
|
140
|
+
k8sDeploymentName: 'mcp-filesystem',
|
|
141
|
+
k8sDevDeploymentName: 'mcp-filesystem-devspace',
|
|
142
|
+
},
|
|
131
143
|
'agents-at-scale': {
|
|
132
144
|
name: 'agents-at-scale',
|
|
133
145
|
helmReleaseName: 'agents-at-scale',
|
|
@@ -28,7 +28,7 @@ _ark_completion() {
|
|
|
28
28
|
|
|
29
29
|
case \${COMP_CWORD} in
|
|
30
30
|
1)
|
|
31
|
-
opts="agents chat cluster completion config dashboard docs generate install models query routes status targets teams tools uninstall help"
|
|
31
|
+
opts="agents chat cluster completion config dashboard docs generate install models queries query routes status targets teams tools uninstall help"
|
|
32
32
|
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
33
33
|
return 0
|
|
34
34
|
;;
|
|
@@ -101,6 +101,11 @@ _ark_completion() {
|
|
|
101
101
|
COMPREPLY=( $(compgen -W "\${targets}" -- \${cur}) )
|
|
102
102
|
return 0
|
|
103
103
|
;;
|
|
104
|
+
queries)
|
|
105
|
+
opts="get"
|
|
106
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
107
|
+
return 0
|
|
108
|
+
;;
|
|
104
109
|
esac
|
|
105
110
|
;;
|
|
106
111
|
esac
|
|
@@ -138,6 +143,7 @@ _ark() {
|
|
|
138
143
|
'generate[Generate ARK resources]' \\
|
|
139
144
|
'install[Install ARK services]' \\
|
|
140
145
|
'models[List available models]' \\
|
|
146
|
+
'queries[Manage query resources]' \\
|
|
141
147
|
'query[Execute a single query]' \\
|
|
142
148
|
'routes[List available routes]' \\
|
|
143
149
|
'status[Check system status]' \\
|
|
@@ -216,6 +222,10 @@ _ark() {
|
|
|
216
222
|
fi
|
|
217
223
|
_values 'available targets' \${targets[@]}
|
|
218
224
|
;;
|
|
225
|
+
queries)
|
|
226
|
+
_values 'queries commands' \\
|
|
227
|
+
'get[Get a specific query]'
|
|
228
|
+
;;
|
|
219
229
|
esac
|
|
220
230
|
;;
|
|
221
231
|
esac
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { executeDirectEvaluation, executeQueryEvaluation, } from '../../lib/executeEvaluation.js';
|
|
4
|
+
import { readStdin } from '../../lib/stdin.js';
|
|
5
|
+
export function createEvaluationCommand(_) {
|
|
6
|
+
const evaluationCommand = new Command('evaluation');
|
|
7
|
+
evaluationCommand
|
|
8
|
+
.description('Execute evaluations against evaluators')
|
|
9
|
+
.argument('<evaluator-name>', 'Name of the evaluator to use')
|
|
10
|
+
.argument('[query-name]', 'Name of the query to evaluate (for query-based evaluation)')
|
|
11
|
+
.option('--input <input>', 'Input text for direct evaluation')
|
|
12
|
+
.option('--output <output>', 'Output text for direct evaluation')
|
|
13
|
+
.option('--response-target <target>', 'Response target for query evaluation (e.g., agent:my-agent)')
|
|
14
|
+
.option('--timeout <timeout>', 'Evaluation timeout (e.g., "30s", "5m")')
|
|
15
|
+
.option('--watch-timeout <timeout>', 'CLI watch timeout')
|
|
16
|
+
.action(async (evaluatorName, queryName, options) => {
|
|
17
|
+
if (options.input && options.output) {
|
|
18
|
+
await executeDirectEvaluation({
|
|
19
|
+
evaluatorName,
|
|
20
|
+
input: options.input,
|
|
21
|
+
output: options.output,
|
|
22
|
+
timeout: options.timeout,
|
|
23
|
+
watchTimeout: options.watchTimeout,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else if (queryName) {
|
|
27
|
+
await executeQueryEvaluation({
|
|
28
|
+
evaluatorName,
|
|
29
|
+
queryName,
|
|
30
|
+
responseTarget: options.responseTarget,
|
|
31
|
+
timeout: options.timeout,
|
|
32
|
+
watchTimeout: options.watchTimeout,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const stdinQueryName = await readStdin();
|
|
37
|
+
if (stdinQueryName) {
|
|
38
|
+
await executeQueryEvaluation({
|
|
39
|
+
evaluatorName,
|
|
40
|
+
queryName: stdinQueryName,
|
|
41
|
+
responseTarget: options.responseTarget,
|
|
42
|
+
timeout: options.timeout,
|
|
43
|
+
watchTimeout: options.watchTimeout,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.error(chalk.red('Error: Must provide either:'));
|
|
48
|
+
console.error(' - --input and --output for direct evaluation');
|
|
49
|
+
console.error(' - <query-name> for query-based evaluation');
|
|
50
|
+
console.error(' - Pipe query name from stdin');
|
|
51
|
+
console.error('\nExamples:');
|
|
52
|
+
console.error(' ark evaluation my-evaluator --input "test" --output "result"');
|
|
53
|
+
console.error(' ark evaluation my-evaluator my-query');
|
|
54
|
+
console.error(' echo "my-query" | ark evaluation my-evaluator');
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return evaluationCommand;
|
|
60
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
const mockExecuteDirectEvaluation = jest.fn();
|
|
4
|
+
const mockExecuteQueryEvaluation = jest.fn();
|
|
5
|
+
jest.unstable_mockModule('../../lib/executeEvaluation.js', () => ({
|
|
6
|
+
executeDirectEvaluation: mockExecuteDirectEvaluation,
|
|
7
|
+
executeQueryEvaluation: mockExecuteQueryEvaluation,
|
|
8
|
+
}));
|
|
9
|
+
const { createEvaluationCommand } = await import('./index.js');
|
|
10
|
+
describe('createEvaluationCommand', () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
it('should create an evaluation command', () => {
|
|
15
|
+
const command = createEvaluationCommand({});
|
|
16
|
+
expect(command).toBeInstanceOf(Command);
|
|
17
|
+
expect(command.name()).toBe('evaluation');
|
|
18
|
+
expect(command.description()).toBe('Execute evaluations against evaluators');
|
|
19
|
+
});
|
|
20
|
+
describe('direct evaluation', () => {
|
|
21
|
+
it('should execute direct evaluation with required options', async () => {
|
|
22
|
+
mockExecuteDirectEvaluation.mockResolvedValue(undefined);
|
|
23
|
+
const command = createEvaluationCommand({});
|
|
24
|
+
await command.parseAsync([
|
|
25
|
+
'node',
|
|
26
|
+
'test',
|
|
27
|
+
'my-evaluator',
|
|
28
|
+
'--input',
|
|
29
|
+
'test-input',
|
|
30
|
+
'--output',
|
|
31
|
+
'test-output',
|
|
32
|
+
]);
|
|
33
|
+
expect(mockExecuteDirectEvaluation).toHaveBeenCalledWith({
|
|
34
|
+
evaluatorName: 'my-evaluator',
|
|
35
|
+
input: 'test-input',
|
|
36
|
+
output: 'test-output',
|
|
37
|
+
timeout: undefined,
|
|
38
|
+
watchTimeout: undefined,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it('should execute direct evaluation with timeout options', async () => {
|
|
42
|
+
mockExecuteDirectEvaluation.mockResolvedValue(undefined);
|
|
43
|
+
const command = createEvaluationCommand({});
|
|
44
|
+
await command.parseAsync([
|
|
45
|
+
'node',
|
|
46
|
+
'test',
|
|
47
|
+
'my-evaluator',
|
|
48
|
+
'--input',
|
|
49
|
+
'test-input',
|
|
50
|
+
'--output',
|
|
51
|
+
'test-output',
|
|
52
|
+
'--timeout',
|
|
53
|
+
'10m',
|
|
54
|
+
'--watch-timeout',
|
|
55
|
+
'11m',
|
|
56
|
+
]);
|
|
57
|
+
expect(mockExecuteDirectEvaluation).toHaveBeenCalledWith({
|
|
58
|
+
evaluatorName: 'my-evaluator',
|
|
59
|
+
input: 'test-input',
|
|
60
|
+
output: 'test-output',
|
|
61
|
+
timeout: '10m',
|
|
62
|
+
watchTimeout: '11m',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('query evaluation', () => {
|
|
67
|
+
it('should execute query evaluation with required arguments', async () => {
|
|
68
|
+
mockExecuteQueryEvaluation.mockResolvedValue(undefined);
|
|
69
|
+
const command = createEvaluationCommand({});
|
|
70
|
+
await command.parseAsync([
|
|
71
|
+
'node',
|
|
72
|
+
'test',
|
|
73
|
+
'my-evaluator',
|
|
74
|
+
'test-query',
|
|
75
|
+
]);
|
|
76
|
+
expect(mockExecuteQueryEvaluation).toHaveBeenCalledWith({
|
|
77
|
+
evaluatorName: 'my-evaluator',
|
|
78
|
+
queryName: 'test-query',
|
|
79
|
+
responseTarget: undefined,
|
|
80
|
+
timeout: undefined,
|
|
81
|
+
watchTimeout: undefined,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it('should execute query evaluation from stdin', async () => {
|
|
85
|
+
mockExecuteQueryEvaluation.mockResolvedValue(undefined);
|
|
86
|
+
const command = createEvaluationCommand({});
|
|
87
|
+
const mockStdin = {
|
|
88
|
+
isTTY: false,
|
|
89
|
+
setEncoding: jest.fn(),
|
|
90
|
+
on: jest.fn((event, callback) => {
|
|
91
|
+
if (event === 'data') {
|
|
92
|
+
callback('piped-query-name');
|
|
93
|
+
}
|
|
94
|
+
else if (event === 'end') {
|
|
95
|
+
callback();
|
|
96
|
+
}
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
const originalStdin = process.stdin;
|
|
100
|
+
Object.defineProperty(process, 'stdin', {
|
|
101
|
+
value: mockStdin,
|
|
102
|
+
writable: true,
|
|
103
|
+
configurable: true,
|
|
104
|
+
});
|
|
105
|
+
try {
|
|
106
|
+
await command.parseAsync(['node', 'test', 'my-evaluator']);
|
|
107
|
+
expect(mockExecuteQueryEvaluation).toHaveBeenCalledWith({
|
|
108
|
+
evaluatorName: 'my-evaluator',
|
|
109
|
+
queryName: 'piped-query-name',
|
|
110
|
+
responseTarget: undefined,
|
|
111
|
+
timeout: undefined,
|
|
112
|
+
watchTimeout: undefined,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
Object.defineProperty(process, 'stdin', {
|
|
117
|
+
value: originalStdin,
|
|
118
|
+
writable: true,
|
|
119
|
+
configurable: true,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
it('should execute query evaluation with response-target option', async () => {
|
|
124
|
+
mockExecuteQueryEvaluation.mockResolvedValue(undefined);
|
|
125
|
+
const command = createEvaluationCommand({});
|
|
126
|
+
await command.parseAsync([
|
|
127
|
+
'node',
|
|
128
|
+
'test',
|
|
129
|
+
'my-evaluator',
|
|
130
|
+
'test-query',
|
|
131
|
+
'--response-target',
|
|
132
|
+
'agent:my-agent',
|
|
133
|
+
]);
|
|
134
|
+
expect(mockExecuteQueryEvaluation).toHaveBeenCalledWith({
|
|
135
|
+
evaluatorName: 'my-evaluator',
|
|
136
|
+
queryName: 'test-query',
|
|
137
|
+
responseTarget: 'agent:my-agent',
|
|
138
|
+
timeout: undefined,
|
|
139
|
+
watchTimeout: undefined,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
it('should execute query evaluation with all options', async () => {
|
|
143
|
+
mockExecuteQueryEvaluation.mockResolvedValue(undefined);
|
|
144
|
+
const command = createEvaluationCommand({});
|
|
145
|
+
await command.parseAsync([
|
|
146
|
+
'node',
|
|
147
|
+
'test',
|
|
148
|
+
'my-evaluator',
|
|
149
|
+
'test-query',
|
|
150
|
+
'--response-target',
|
|
151
|
+
'agent:my-agent',
|
|
152
|
+
'--timeout',
|
|
153
|
+
'10m',
|
|
154
|
+
'--watch-timeout',
|
|
155
|
+
'11m',
|
|
156
|
+
]);
|
|
157
|
+
expect(mockExecuteQueryEvaluation).toHaveBeenCalledWith({
|
|
158
|
+
evaluatorName: 'my-evaluator',
|
|
159
|
+
queryName: 'test-query',
|
|
160
|
+
responseTarget: 'agent:my-agent',
|
|
161
|
+
timeout: '10m',
|
|
162
|
+
watchTimeout: '11m',
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { ArkConfig } from '../../lib/config.js';
|
|
3
|
+
export declare function listSessions(options: {
|
|
4
|
+
output?: string;
|
|
5
|
+
}): Promise<void>;
|
|
6
|
+
export declare function deleteSession(sessionId: string, options: {
|
|
7
|
+
output?: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
export declare function deleteQuery(sessionId: string, queryId: string, options: {
|
|
10
|
+
output?: string;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
export declare function deleteAll(options: {
|
|
13
|
+
output?: string;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare function createMemoryCommand(_: ArkConfig): Command;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import output from '../../lib/output.js';
|
|
3
|
+
import { ArkApiProxy } from '../../lib/arkApiProxy.js';
|
|
4
|
+
export async function listSessions(options) {
|
|
5
|
+
try {
|
|
6
|
+
const proxy = new ArkApiProxy();
|
|
7
|
+
const arkApiClient = await proxy.start();
|
|
8
|
+
const sessions = await arkApiClient.getSessions();
|
|
9
|
+
if (options.output === 'json') {
|
|
10
|
+
output.info(JSON.stringify(sessions, null, 2));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (sessions.length === 0) {
|
|
14
|
+
output.info('No sessions found');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
output.info('Sessions:');
|
|
18
|
+
sessions.forEach((session) => {
|
|
19
|
+
output.info(` ${session.sessionId} (memory: ${session.memoryName})`);
|
|
20
|
+
});
|
|
21
|
+
proxy.stop();
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
output.error('Failed to list sessions:', error);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function deleteSession(sessionId, options) {
|
|
29
|
+
try {
|
|
30
|
+
const proxy = new ArkApiProxy();
|
|
31
|
+
const arkApiClient = await proxy.start();
|
|
32
|
+
const response = await arkApiClient.deleteSession(sessionId);
|
|
33
|
+
if (options.output === 'json') {
|
|
34
|
+
output.info(JSON.stringify(response, null, 2));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
output.success(`Session ${sessionId} deleted successfully`);
|
|
38
|
+
proxy.stop();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
output.error(`Failed to delete session ${sessionId}:`, error);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function deleteQuery(sessionId, queryId, options) {
|
|
46
|
+
try {
|
|
47
|
+
const proxy = new ArkApiProxy();
|
|
48
|
+
const arkApiClient = await proxy.start();
|
|
49
|
+
const response = await arkApiClient.deleteQueryMessages(sessionId, queryId);
|
|
50
|
+
if (options.output === 'json') {
|
|
51
|
+
output.info(JSON.stringify(response, null, 2));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
output.success(`Query ${queryId} messages deleted successfully from session ${sessionId}`);
|
|
55
|
+
proxy.stop();
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
output.error(`Failed to delete query ${queryId} messages:`, error);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function deleteAll(options) {
|
|
63
|
+
try {
|
|
64
|
+
const proxy = new ArkApiProxy();
|
|
65
|
+
const arkApiClient = await proxy.start();
|
|
66
|
+
const response = await arkApiClient.deleteAllSessions();
|
|
67
|
+
if (options.output === 'json') {
|
|
68
|
+
output.info(JSON.stringify(response, null, 2));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
output.success('All sessions deleted successfully');
|
|
72
|
+
proxy.stop();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
output.error('Failed to delete all sessions:', error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function createMemoryCommand(_) {
|
|
80
|
+
const memoryCommand = new Command('memory');
|
|
81
|
+
memoryCommand.description('Manage memory sessions and queries').alias('mem');
|
|
82
|
+
// List sessions command
|
|
83
|
+
memoryCommand
|
|
84
|
+
.command('list')
|
|
85
|
+
.alias('ls')
|
|
86
|
+
.description('List all sessions')
|
|
87
|
+
.option('-o, --output <format>', 'output format (json or text)', 'text')
|
|
88
|
+
.action(async (options) => {
|
|
89
|
+
await listSessions(options);
|
|
90
|
+
});
|
|
91
|
+
// Delete command with subcommands (alias: reset for backward compatibility)
|
|
92
|
+
const deleteCommand = memoryCommand
|
|
93
|
+
.command('delete')
|
|
94
|
+
.alias('reset')
|
|
95
|
+
.description('Delete memory data')
|
|
96
|
+
.option('--all', 'Delete all sessions and their messages');
|
|
97
|
+
// Delete specific session
|
|
98
|
+
deleteCommand
|
|
99
|
+
.command('session')
|
|
100
|
+
.description('Delete a specific session')
|
|
101
|
+
.argument('<sessionId>', 'Session ID to delete')
|
|
102
|
+
.option('-o, --output <format>', 'output format (json or text)', 'text')
|
|
103
|
+
.action(async (sessionId, options) => {
|
|
104
|
+
await deleteSession(sessionId, options);
|
|
105
|
+
});
|
|
106
|
+
// Delete specific query
|
|
107
|
+
deleteCommand
|
|
108
|
+
.command('query')
|
|
109
|
+
.description('Delete messages for a specific query')
|
|
110
|
+
.argument('<sessionId>', 'Session ID')
|
|
111
|
+
.argument('<queryId>', 'Query ID to delete messages for')
|
|
112
|
+
.option('-o, --output <format>', 'output format (json or text)', 'text')
|
|
113
|
+
.action(async (sessionId, queryId, options) => {
|
|
114
|
+
await deleteQuery(sessionId, queryId, options);
|
|
115
|
+
});
|
|
116
|
+
// Handle --all on delete root
|
|
117
|
+
deleteCommand.action(async (options) => {
|
|
118
|
+
if (options.all) {
|
|
119
|
+
await deleteAll(options);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// If no subcommand and no --all, show help
|
|
123
|
+
deleteCommand.help();
|
|
124
|
+
});
|
|
125
|
+
// Default action - list sessions
|
|
126
|
+
memoryCommand.action(async (options) => {
|
|
127
|
+
await listSessions(options);
|
|
128
|
+
});
|
|
129
|
+
return memoryCommand;
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
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,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
apiVersion?: string;
|
|
1
|
+
import { BaseCollectorOptions } from './providers/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Common options for model creation.
|
|
4
|
+
*/
|
|
5
|
+
export interface CreateModelOptions extends BaseCollectorOptions {
|
|
7
6
|
yes?: boolean;
|
|
8
7
|
}
|
|
9
8
|
export declare function createModel(modelName?: string, options?: CreateModelOptions): Promise<boolean>;
|