@claude-flow/cli 3.0.0-alpha.2 → 3.0.0-alpha.20
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/README.md +172 -6
- package/bin/cli.js +0 -0
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +43 -27
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.d.ts +19 -0
- package/dist/src/commands/analyze.d.ts.map +1 -0
- package/dist/src/commands/analyze.js +1823 -0
- package/dist/src/commands/analyze.js.map +1 -0
- package/dist/src/commands/claims.d.ts +10 -0
- package/dist/src/commands/claims.d.ts.map +1 -0
- package/dist/src/commands/claims.js +288 -0
- package/dist/src/commands/claims.js.map +1 -0
- package/dist/src/commands/completions.d.ts +10 -0
- package/dist/src/commands/completions.d.ts.map +1 -0
- package/dist/src/commands/completions.js +539 -0
- package/dist/src/commands/completions.js.map +1 -0
- package/dist/src/commands/config.js +2 -2
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/daemon.d.ts +8 -0
- package/dist/src/commands/daemon.d.ts.map +1 -0
- package/dist/src/commands/daemon.js +545 -0
- package/dist/src/commands/daemon.js.map +1 -0
- package/dist/src/commands/deployment.d.ts +10 -0
- package/dist/src/commands/deployment.d.ts.map +1 -0
- package/dist/src/commands/deployment.js +289 -0
- package/dist/src/commands/deployment.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +10 -0
- package/dist/src/commands/doctor.d.ts.map +1 -0
- package/dist/src/commands/doctor.js +429 -0
- package/dist/src/commands/doctor.js.map +1 -0
- package/dist/src/commands/embeddings.d.ts +18 -0
- package/dist/src/commands/embeddings.d.ts.map +1 -0
- package/dist/src/commands/embeddings.js +616 -0
- package/dist/src/commands/embeddings.js.map +1 -0
- package/dist/src/commands/hive-mind.d.ts.map +1 -1
- package/dist/src/commands/hive-mind.js +252 -35
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +326 -2
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +13 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +52 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/mcp.js +4 -4
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.d.ts.map +1 -1
- package/dist/src/commands/memory.js +236 -170
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/migrate.js +1 -1
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/neural.d.ts +10 -0
- package/dist/src/commands/neural.d.ts.map +1 -0
- package/dist/src/commands/neural.js +224 -0
- package/dist/src/commands/neural.js.map +1 -0
- package/dist/src/commands/performance.d.ts +10 -0
- package/dist/src/commands/performance.d.ts.map +1 -0
- package/dist/src/commands/performance.js +262 -0
- package/dist/src/commands/performance.js.map +1 -0
- package/dist/src/commands/plugins.d.ts +10 -0
- package/dist/src/commands/plugins.d.ts.map +1 -0
- package/dist/src/commands/plugins.js +280 -0
- package/dist/src/commands/plugins.js.map +1 -0
- package/dist/src/commands/process.d.ts.map +1 -1
- package/dist/src/commands/process.js +95 -20
- package/dist/src/commands/process.js.map +1 -1
- package/dist/src/commands/providers.d.ts +10 -0
- package/dist/src/commands/providers.d.ts.map +1 -0
- package/dist/src/commands/providers.js +232 -0
- package/dist/src/commands/providers.js.map +1 -0
- package/dist/src/commands/route.d.ts +16 -0
- package/dist/src/commands/route.d.ts.map +1 -0
- package/dist/src/commands/route.js +603 -0
- package/dist/src/commands/route.js.map +1 -0
- package/dist/src/commands/security.d.ts +10 -0
- package/dist/src/commands/security.d.ts.map +1 -0
- package/dist/src/commands/security.js +261 -0
- package/dist/src/commands/security.js.map +1 -0
- package/dist/src/commands/start.js +2 -2
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/status.d.ts.map +1 -1
- package/dist/src/commands/status.js +26 -2
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.js +6 -6
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +63 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +218 -362
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +5 -0
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +22 -12
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +17 -1
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +5 -0
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +350 -14
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
- package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/analyze-tools.js +317 -0
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -0
- package/dist/src/mcp-tools/config-tools.d.ts +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +262 -15
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/hive-mind-tools.js +447 -0
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +80 -15
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +6 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +6 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +157 -9
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts +8 -0
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/session-tools.js +315 -0
- package/dist/src/mcp-tools/session-tools.js.map +1 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +37 -2
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts +8 -0
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/task-tools.js +302 -0
- package/dist/src/mcp-tools/task-tools.js.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.js +481 -0
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -0
- package/dist/src/output.d.ts +16 -0
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +42 -0
- package/dist/src/output.js.map +1 -1
- package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
- package/dist/src/ruvector/ast-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/ast-analyzer.js +277 -0
- package/dist/src/ruvector/ast-analyzer.js.map +1 -0
- package/dist/src/ruvector/coverage-router.d.ts +145 -0
- package/dist/src/ruvector/coverage-router.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-router.js +451 -0
- package/dist/src/ruvector/coverage-router.js.map +1 -0
- package/dist/src/ruvector/coverage-tools.d.ts +33 -0
- package/dist/src/ruvector/coverage-tools.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-tools.js +157 -0
- package/dist/src/ruvector/coverage-tools.js.map +1 -0
- package/dist/src/ruvector/diff-classifier.d.ts +154 -0
- package/dist/src/ruvector/diff-classifier.d.ts.map +1 -0
- package/dist/src/ruvector/diff-classifier.js +508 -0
- package/dist/src/ruvector/diff-classifier.js.map +1 -0
- package/dist/src/ruvector/graph-analyzer.d.ts +174 -0
- package/dist/src/ruvector/graph-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/graph-analyzer.js +878 -0
- package/dist/src/ruvector/graph-analyzer.js.map +1 -0
- package/dist/src/ruvector/index.d.ts +27 -0
- package/dist/src/ruvector/index.d.ts.map +1 -0
- package/dist/src/ruvector/index.js +47 -0
- package/dist/src/ruvector/index.js.map +1 -0
- package/dist/src/ruvector/q-learning-router.d.ts +211 -0
- package/dist/src/ruvector/q-learning-router.d.ts.map +1 -0
- package/dist/src/ruvector/q-learning-router.js +681 -0
- package/dist/src/ruvector/q-learning-router.js.map +1 -0
- package/dist/src/ruvector/vector-db.d.ts +69 -0
- package/dist/src/ruvector/vector-db.d.ts.map +1 -0
- package/dist/src/ruvector/vector-db.js +243 -0
- package/dist/src/ruvector/vector-db.js.map +1 -0
- package/dist/src/services/index.d.ts +7 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +6 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/worker-daemon.d.ts +153 -0
- package/dist/src/services/worker-daemon.d.ts.map +1 -0
- package/dist/src/services/worker-daemon.js +567 -0
- package/dist/src/services/worker-daemon.js.map +1 -0
- package/dist/src/suggest.d.ts +53 -0
- package/dist/src/suggest.d.ts.map +1 -0
- package/dist/src/suggest.js +200 -0
- package/dist/src/suggest.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +28 -6
- package/.agentic-flow/intelligence.json +0 -16
- package/.claude-flow/metrics/agent-metrics.json +0 -1
- package/.claude-flow/metrics/performance.json +0 -87
- package/.claude-flow/metrics/task-metrics.json +0 -10
- package/__tests__/README.md +0 -140
- package/__tests__/TEST_SUMMARY.md +0 -144
- package/__tests__/cli.test.ts +0 -558
- package/__tests__/commands.test.ts +0 -726
- package/__tests__/config-adapter.test.ts +0 -362
- package/__tests__/config-loading.test.ts +0 -106
- package/__tests__/coverage/.tmp/coverage-0.json +0 -1
- package/__tests__/coverage/.tmp/coverage-1.json +0 -1
- package/__tests__/coverage/.tmp/coverage-2.json +0 -1
- package/__tests__/coverage/.tmp/coverage-3.json +0 -1
- package/__tests__/coverage/.tmp/coverage-4.json +0 -1
- package/__tests__/coverage/.tmp/coverage-5.json +0 -1
- package/__tests__/mcp-client.test.ts +0 -480
- package/__tests__/p1-commands.test.ts +0 -1064
- package/docs/CONFIG_LOADING.md +0 -236
- package/docs/IMPLEMENTATION_COMPLETE.md +0 -421
- package/docs/MCP_CLIENT_GUIDE.md +0 -620
- package/docs/REFACTORING_SUMMARY.md +0 -247
- package/src/commands/agent.ts +0 -941
- package/src/commands/config.ts +0 -452
- package/src/commands/hive-mind.ts +0 -762
- package/src/commands/hooks.ts +0 -2603
- package/src/commands/index.ts +0 -115
- package/src/commands/init.ts +0 -597
- package/src/commands/mcp.ts +0 -753
- package/src/commands/memory.ts +0 -1063
- package/src/commands/migrate.ts +0 -447
- package/src/commands/process.ts +0 -617
- package/src/commands/session.ts +0 -891
- package/src/commands/start.ts +0 -457
- package/src/commands/status.ts +0 -705
- package/src/commands/swarm.ts +0 -648
- package/src/commands/task.ts +0 -792
- package/src/commands/workflow.ts +0 -742
- package/src/config-adapter.ts +0 -210
- package/src/index.ts +0 -383
- package/src/infrastructure/in-memory-repositories.ts +0 -310
- package/src/init/claudemd-generator.ts +0 -631
- package/src/init/executor.ts +0 -756
- package/src/init/helpers-generator.ts +0 -628
- package/src/init/index.ts +0 -60
- package/src/init/mcp-generator.ts +0 -83
- package/src/init/settings-generator.ts +0 -274
- package/src/init/statusline-generator.ts +0 -211
- package/src/init/types.ts +0 -447
- package/src/mcp-client.ts +0 -227
- package/src/mcp-server.ts +0 -571
- package/src/mcp-tools/agent-tools.ts +0 -92
- package/src/mcp-tools/config-tools.ts +0 -88
- package/src/mcp-tools/hooks-tools.ts +0 -1819
- package/src/mcp-tools/index.ts +0 -12
- package/src/mcp-tools/memory-tools.ts +0 -89
- package/src/mcp-tools/swarm-tools.ts +0 -69
- package/src/mcp-tools/types.ts +0 -33
- package/src/output.ts +0 -593
- package/src/parser.ts +0 -417
- package/src/prompt.ts +0 -619
- package/src/types.ts +0 -287
- package/tmp.json +0 -0
- package/tsconfig.json +0 -16
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -13
package/src/commands/session.ts
DELETED
|
@@ -1,891 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* V3 CLI Session Command
|
|
3
|
-
* Session management for Claude Flow
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Command, CommandContext, CommandResult } from '../types.js';
|
|
7
|
-
import { output } from '../output.js';
|
|
8
|
-
import { confirm, input, select } from '../prompt.js';
|
|
9
|
-
import { callMCPTool, MCPClientError } from '../mcp-client.js';
|
|
10
|
-
import * as fs from 'fs';
|
|
11
|
-
import * as path from 'path';
|
|
12
|
-
|
|
13
|
-
// Format date for display
|
|
14
|
-
function formatDate(dateStr: string): string {
|
|
15
|
-
const date = new Date(dateStr);
|
|
16
|
-
const now = new Date();
|
|
17
|
-
const diff = now.getTime() - date.getTime();
|
|
18
|
-
|
|
19
|
-
// Less than 24 hours - show relative time
|
|
20
|
-
if (diff < 24 * 60 * 60 * 1000) {
|
|
21
|
-
const hours = Math.floor(diff / (60 * 60 * 1000));
|
|
22
|
-
const minutes = Math.floor((diff % (60 * 60 * 1000)) / (60 * 1000));
|
|
23
|
-
|
|
24
|
-
if (hours > 0) {
|
|
25
|
-
return `${hours}h ${minutes}m ago`;
|
|
26
|
-
}
|
|
27
|
-
return `${minutes}m ago`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Otherwise show date
|
|
31
|
-
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Format session status
|
|
35
|
-
function formatStatus(status: string): string {
|
|
36
|
-
switch (status) {
|
|
37
|
-
case 'active':
|
|
38
|
-
return output.success(status);
|
|
39
|
-
case 'saved':
|
|
40
|
-
return output.info(status);
|
|
41
|
-
case 'archived':
|
|
42
|
-
return output.dim(status);
|
|
43
|
-
default:
|
|
44
|
-
return status;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// List subcommand
|
|
49
|
-
const listCommand: Command = {
|
|
50
|
-
name: 'list',
|
|
51
|
-
aliases: ['ls'],
|
|
52
|
-
description: 'List all sessions',
|
|
53
|
-
options: [
|
|
54
|
-
{
|
|
55
|
-
name: 'active',
|
|
56
|
-
short: 'a',
|
|
57
|
-
description: 'Show only active sessions',
|
|
58
|
-
type: 'boolean',
|
|
59
|
-
default: false
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: 'all',
|
|
63
|
-
description: 'Include archived sessions',
|
|
64
|
-
type: 'boolean',
|
|
65
|
-
default: false
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
name: 'limit',
|
|
69
|
-
short: 'l',
|
|
70
|
-
description: 'Maximum sessions to show',
|
|
71
|
-
type: 'number',
|
|
72
|
-
default: 20
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
76
|
-
const activeOnly = ctx.flags.active as boolean;
|
|
77
|
-
const includeArchived = ctx.flags.all as boolean;
|
|
78
|
-
const limit = ctx.flags.limit as number;
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
const result = await callMCPTool<{
|
|
82
|
-
sessions: Array<{
|
|
83
|
-
id: string;
|
|
84
|
-
name?: string;
|
|
85
|
-
description?: string;
|
|
86
|
-
status: 'active' | 'saved' | 'archived';
|
|
87
|
-
createdAt: string;
|
|
88
|
-
updatedAt: string;
|
|
89
|
-
agentCount: number;
|
|
90
|
-
taskCount: number;
|
|
91
|
-
memorySize: number;
|
|
92
|
-
}>;
|
|
93
|
-
total: number;
|
|
94
|
-
}>('session/list', {
|
|
95
|
-
status: activeOnly ? 'active' : includeArchived ? 'all' : 'active,saved',
|
|
96
|
-
limit
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (ctx.flags.format === 'json') {
|
|
100
|
-
output.printJson(result);
|
|
101
|
-
return { success: true, data: result };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
output.writeln();
|
|
105
|
-
output.writeln(output.bold('Sessions'));
|
|
106
|
-
output.writeln();
|
|
107
|
-
|
|
108
|
-
if (result.sessions.length === 0) {
|
|
109
|
-
output.printInfo('No sessions found');
|
|
110
|
-
output.printInfo('Run "claude-flow session save" to create a session');
|
|
111
|
-
return { success: true, data: result };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
output.printTable({
|
|
115
|
-
columns: [
|
|
116
|
-
{ key: 'id', header: 'ID', width: 20 },
|
|
117
|
-
{ key: 'name', header: 'Name', width: 20 },
|
|
118
|
-
{ key: 'status', header: 'Status', width: 10 },
|
|
119
|
-
{ key: 'agents', header: 'Agents', width: 8, align: 'right' },
|
|
120
|
-
{ key: 'tasks', header: 'Tasks', width: 8, align: 'right' },
|
|
121
|
-
{ key: 'updated', header: 'Last Updated', width: 18 }
|
|
122
|
-
],
|
|
123
|
-
data: result.sessions.map(s => ({
|
|
124
|
-
id: s.id,
|
|
125
|
-
name: s.name || '-',
|
|
126
|
-
status: formatStatus(s.status),
|
|
127
|
-
agents: s.agentCount,
|
|
128
|
-
tasks: s.taskCount,
|
|
129
|
-
updated: formatDate(s.updatedAt)
|
|
130
|
-
}))
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
output.writeln();
|
|
134
|
-
output.printInfo(`Showing ${result.sessions.length} of ${result.total} sessions`);
|
|
135
|
-
|
|
136
|
-
return { success: true, data: result };
|
|
137
|
-
} catch (error) {
|
|
138
|
-
if (error instanceof MCPClientError) {
|
|
139
|
-
output.printError(`Failed to list sessions: ${error.message}`);
|
|
140
|
-
} else {
|
|
141
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
142
|
-
}
|
|
143
|
-
return { success: false, exitCode: 1 };
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// Save subcommand
|
|
149
|
-
const saveCommand: Command = {
|
|
150
|
-
name: 'save',
|
|
151
|
-
aliases: ['create', 'checkpoint'],
|
|
152
|
-
description: 'Save current session state',
|
|
153
|
-
options: [
|
|
154
|
-
{
|
|
155
|
-
name: 'name',
|
|
156
|
-
short: 'n',
|
|
157
|
-
description: 'Session name',
|
|
158
|
-
type: 'string'
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
name: 'description',
|
|
162
|
-
short: 'd',
|
|
163
|
-
description: 'Session description',
|
|
164
|
-
type: 'string'
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: 'include-memory',
|
|
168
|
-
description: 'Include memory state in session',
|
|
169
|
-
type: 'boolean',
|
|
170
|
-
default: true
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
name: 'include-agents',
|
|
174
|
-
description: 'Include agent state in session',
|
|
175
|
-
type: 'boolean',
|
|
176
|
-
default: true
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
name: 'include-tasks',
|
|
180
|
-
description: 'Include task state in session',
|
|
181
|
-
type: 'boolean',
|
|
182
|
-
default: true
|
|
183
|
-
}
|
|
184
|
-
],
|
|
185
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
186
|
-
let sessionName = ctx.flags.name as string;
|
|
187
|
-
let description = ctx.flags.description as string;
|
|
188
|
-
|
|
189
|
-
// Interactive mode
|
|
190
|
-
if (!sessionName && ctx.interactive) {
|
|
191
|
-
sessionName = await input({
|
|
192
|
-
message: 'Session name:',
|
|
193
|
-
default: `session-${Date.now().toString(36)}`,
|
|
194
|
-
validate: (v) => v.length > 0 || 'Name is required'
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (!description && ctx.interactive) {
|
|
199
|
-
description = await input({
|
|
200
|
-
message: 'Session description (optional):',
|
|
201
|
-
default: ''
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const spinner = output.createSpinner({ text: 'Saving session...' });
|
|
206
|
-
spinner.start();
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
const result = await callMCPTool<{
|
|
210
|
-
sessionId: string;
|
|
211
|
-
name: string;
|
|
212
|
-
description?: string;
|
|
213
|
-
savedAt: string;
|
|
214
|
-
includes: {
|
|
215
|
-
memory: boolean;
|
|
216
|
-
agents: boolean;
|
|
217
|
-
tasks: boolean;
|
|
218
|
-
};
|
|
219
|
-
stats: {
|
|
220
|
-
agentCount: number;
|
|
221
|
-
taskCount: number;
|
|
222
|
-
memoryEntries: number;
|
|
223
|
-
totalSize: number;
|
|
224
|
-
};
|
|
225
|
-
}>('session/save', {
|
|
226
|
-
name: sessionName,
|
|
227
|
-
description,
|
|
228
|
-
includeMemory: ctx.flags['include-memory'] !== false,
|
|
229
|
-
includeAgents: ctx.flags['include-agents'] !== false,
|
|
230
|
-
includeTasks: ctx.flags['include-tasks'] !== false
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
spinner.succeed('Session saved');
|
|
234
|
-
output.writeln();
|
|
235
|
-
|
|
236
|
-
output.printTable({
|
|
237
|
-
columns: [
|
|
238
|
-
{ key: 'property', header: 'Property', width: 18 },
|
|
239
|
-
{ key: 'value', header: 'Value', width: 35 }
|
|
240
|
-
],
|
|
241
|
-
data: [
|
|
242
|
-
{ property: 'Session ID', value: result.sessionId },
|
|
243
|
-
{ property: 'Name', value: result.name },
|
|
244
|
-
{ property: 'Description', value: result.description || '-' },
|
|
245
|
-
{ property: 'Saved At', value: new Date(result.savedAt).toLocaleString() },
|
|
246
|
-
{ property: 'Agents', value: result.stats.agentCount },
|
|
247
|
-
{ property: 'Tasks', value: result.stats.taskCount },
|
|
248
|
-
{ property: 'Memory Entries', value: result.stats.memoryEntries },
|
|
249
|
-
{ property: 'Total Size', value: formatSize(result.stats.totalSize) }
|
|
250
|
-
]
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
output.writeln();
|
|
254
|
-
output.printSuccess(`Session saved: ${result.sessionId}`);
|
|
255
|
-
output.printInfo(`Restore with: claude-flow session restore ${result.sessionId}`);
|
|
256
|
-
|
|
257
|
-
if (ctx.flags.format === 'json') {
|
|
258
|
-
output.printJson(result);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return { success: true, data: result };
|
|
262
|
-
} catch (error) {
|
|
263
|
-
spinner.fail('Failed to save session');
|
|
264
|
-
if (error instanceof MCPClientError) {
|
|
265
|
-
output.printError(`Error: ${error.message}`);
|
|
266
|
-
} else {
|
|
267
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
268
|
-
}
|
|
269
|
-
return { success: false, exitCode: 1 };
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
// Restore subcommand
|
|
275
|
-
const restoreCommand: Command = {
|
|
276
|
-
name: 'restore',
|
|
277
|
-
aliases: ['load'],
|
|
278
|
-
description: 'Restore a saved session',
|
|
279
|
-
options: [
|
|
280
|
-
{
|
|
281
|
-
name: 'force',
|
|
282
|
-
short: 'f',
|
|
283
|
-
description: 'Overwrite current state without confirmation',
|
|
284
|
-
type: 'boolean',
|
|
285
|
-
default: false
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
name: 'memory-only',
|
|
289
|
-
description: 'Only restore memory state',
|
|
290
|
-
type: 'boolean',
|
|
291
|
-
default: false
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
name: 'agents-only',
|
|
295
|
-
description: 'Only restore agent state',
|
|
296
|
-
type: 'boolean',
|
|
297
|
-
default: false
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
name: 'tasks-only',
|
|
301
|
-
description: 'Only restore task state',
|
|
302
|
-
type: 'boolean',
|
|
303
|
-
default: false
|
|
304
|
-
}
|
|
305
|
-
],
|
|
306
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
307
|
-
let sessionId = ctx.args[0];
|
|
308
|
-
const force = ctx.flags.force as boolean;
|
|
309
|
-
|
|
310
|
-
if (!sessionId && ctx.interactive) {
|
|
311
|
-
// Show list to select from
|
|
312
|
-
try {
|
|
313
|
-
const sessions = await callMCPTool<{
|
|
314
|
-
sessions: Array<{ id: string; name?: string; status: string; updatedAt: string }>;
|
|
315
|
-
}>('session/list', { status: 'saved', limit: 20 });
|
|
316
|
-
|
|
317
|
-
if (sessions.sessions.length === 0) {
|
|
318
|
-
output.printWarning('No saved sessions found');
|
|
319
|
-
return { success: false, exitCode: 1 };
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
sessionId = await select({
|
|
323
|
-
message: 'Select session to restore:',
|
|
324
|
-
options: sessions.sessions.map(s => ({
|
|
325
|
-
value: s.id,
|
|
326
|
-
label: s.name || s.id,
|
|
327
|
-
hint: formatDate(s.updatedAt)
|
|
328
|
-
}))
|
|
329
|
-
});
|
|
330
|
-
} catch (error) {
|
|
331
|
-
if (error instanceof Error && error.message === 'User cancelled') {
|
|
332
|
-
output.printInfo('Operation cancelled');
|
|
333
|
-
return { success: true };
|
|
334
|
-
}
|
|
335
|
-
throw error;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (!sessionId) {
|
|
340
|
-
output.printError('Session ID is required');
|
|
341
|
-
return { success: false, exitCode: 1 };
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Confirm unless forced
|
|
345
|
-
if (!force && ctx.interactive) {
|
|
346
|
-
const confirmed = await confirm({
|
|
347
|
-
message: 'This will overwrite current state. Continue?',
|
|
348
|
-
default: false
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
if (!confirmed) {
|
|
352
|
-
output.printInfo('Operation cancelled');
|
|
353
|
-
return { success: true };
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const spinner = output.createSpinner({ text: 'Restoring session...' });
|
|
358
|
-
spinner.start();
|
|
359
|
-
|
|
360
|
-
try {
|
|
361
|
-
// Determine what to restore
|
|
362
|
-
const restoreMemory = !ctx.flags['agents-only'] && !ctx.flags['tasks-only'];
|
|
363
|
-
const restoreAgents = !ctx.flags['memory-only'] && !ctx.flags['tasks-only'];
|
|
364
|
-
const restoreTasks = !ctx.flags['memory-only'] && !ctx.flags['agents-only'];
|
|
365
|
-
|
|
366
|
-
const result = await callMCPTool<{
|
|
367
|
-
sessionId: string;
|
|
368
|
-
restoredAt: string;
|
|
369
|
-
restored: {
|
|
370
|
-
memory: boolean;
|
|
371
|
-
agents: boolean;
|
|
372
|
-
tasks: boolean;
|
|
373
|
-
};
|
|
374
|
-
stats: {
|
|
375
|
-
agentsRestored: number;
|
|
376
|
-
tasksRestored: number;
|
|
377
|
-
memoryEntriesRestored: number;
|
|
378
|
-
};
|
|
379
|
-
}>('session/restore', {
|
|
380
|
-
sessionId,
|
|
381
|
-
restoreMemory,
|
|
382
|
-
restoreAgents,
|
|
383
|
-
restoreTasks
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
spinner.succeed('Session restored');
|
|
387
|
-
output.writeln();
|
|
388
|
-
|
|
389
|
-
output.printTable({
|
|
390
|
-
columns: [
|
|
391
|
-
{ key: 'component', header: 'Component', width: 20 },
|
|
392
|
-
{ key: 'status', header: 'Status', width: 15 },
|
|
393
|
-
{ key: 'count', header: 'Items', width: 10, align: 'right' }
|
|
394
|
-
],
|
|
395
|
-
data: [
|
|
396
|
-
{
|
|
397
|
-
component: 'Memory',
|
|
398
|
-
status: result.restored.memory ? output.success('Restored') : output.dim('Skipped'),
|
|
399
|
-
count: result.stats.memoryEntriesRestored
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
component: 'Agents',
|
|
403
|
-
status: result.restored.agents ? output.success('Restored') : output.dim('Skipped'),
|
|
404
|
-
count: result.stats.agentsRestored
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
component: 'Tasks',
|
|
408
|
-
status: result.restored.tasks ? output.success('Restored') : output.dim('Skipped'),
|
|
409
|
-
count: result.stats.tasksRestored
|
|
410
|
-
}
|
|
411
|
-
]
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
output.writeln();
|
|
415
|
-
output.printSuccess(`Session ${sessionId} restored successfully`);
|
|
416
|
-
|
|
417
|
-
if (ctx.flags.format === 'json') {
|
|
418
|
-
output.printJson(result);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return { success: true, data: result };
|
|
422
|
-
} catch (error) {
|
|
423
|
-
spinner.fail('Failed to restore session');
|
|
424
|
-
if (error instanceof MCPClientError) {
|
|
425
|
-
output.printError(`Error: ${error.message}`);
|
|
426
|
-
} else {
|
|
427
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
428
|
-
}
|
|
429
|
-
return { success: false, exitCode: 1 };
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
// Delete subcommand
|
|
435
|
-
const deleteCommand: Command = {
|
|
436
|
-
name: 'delete',
|
|
437
|
-
aliases: ['rm', 'remove'],
|
|
438
|
-
description: 'Delete a saved session',
|
|
439
|
-
options: [
|
|
440
|
-
{
|
|
441
|
-
name: 'force',
|
|
442
|
-
short: 'f',
|
|
443
|
-
description: 'Delete without confirmation',
|
|
444
|
-
type: 'boolean',
|
|
445
|
-
default: false
|
|
446
|
-
}
|
|
447
|
-
],
|
|
448
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
449
|
-
const sessionId = ctx.args[0];
|
|
450
|
-
const force = ctx.flags.force as boolean;
|
|
451
|
-
|
|
452
|
-
if (!sessionId) {
|
|
453
|
-
output.printError('Session ID is required');
|
|
454
|
-
return { success: false, exitCode: 1 };
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (!force && ctx.interactive) {
|
|
458
|
-
const confirmed = await confirm({
|
|
459
|
-
message: `Delete session ${sessionId}? This cannot be undone.`,
|
|
460
|
-
default: false
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
if (!confirmed) {
|
|
464
|
-
output.printInfo('Operation cancelled');
|
|
465
|
-
return { success: true };
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
try {
|
|
470
|
-
const result = await callMCPTool<{
|
|
471
|
-
sessionId: string;
|
|
472
|
-
deleted: boolean;
|
|
473
|
-
deletedAt: string;
|
|
474
|
-
}>('session/delete', { sessionId });
|
|
475
|
-
|
|
476
|
-
output.writeln();
|
|
477
|
-
output.printSuccess(`Session ${sessionId} deleted`);
|
|
478
|
-
|
|
479
|
-
if (ctx.flags.format === 'json') {
|
|
480
|
-
output.printJson(result);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
return { success: true, data: result };
|
|
484
|
-
} catch (error) {
|
|
485
|
-
if (error instanceof MCPClientError) {
|
|
486
|
-
output.printError(`Failed to delete session: ${error.message}`);
|
|
487
|
-
} else {
|
|
488
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
489
|
-
}
|
|
490
|
-
return { success: false, exitCode: 1 };
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
// Export subcommand
|
|
496
|
-
const exportCommand: Command = {
|
|
497
|
-
name: 'export',
|
|
498
|
-
description: 'Export session to file',
|
|
499
|
-
options: [
|
|
500
|
-
{
|
|
501
|
-
name: 'output',
|
|
502
|
-
short: 'o',
|
|
503
|
-
description: 'Output file path',
|
|
504
|
-
type: 'string'
|
|
505
|
-
},
|
|
506
|
-
{
|
|
507
|
-
name: 'format',
|
|
508
|
-
short: 'f',
|
|
509
|
-
description: 'Export format (json, yaml)',
|
|
510
|
-
type: 'string',
|
|
511
|
-
choices: ['json', 'yaml'],
|
|
512
|
-
default: 'json'
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
name: 'include-memory',
|
|
516
|
-
description: 'Include memory data',
|
|
517
|
-
type: 'boolean',
|
|
518
|
-
default: true
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
name: 'compress',
|
|
522
|
-
description: 'Compress output',
|
|
523
|
-
type: 'boolean',
|
|
524
|
-
default: false
|
|
525
|
-
}
|
|
526
|
-
],
|
|
527
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
528
|
-
let sessionId = ctx.args[0];
|
|
529
|
-
let outputPath = ctx.flags.output as string;
|
|
530
|
-
const exportFormat = ctx.flags.format as string;
|
|
531
|
-
const compress = ctx.flags.compress as boolean;
|
|
532
|
-
|
|
533
|
-
// Get current session if no ID provided
|
|
534
|
-
if (!sessionId) {
|
|
535
|
-
try {
|
|
536
|
-
const current = await callMCPTool<{ sessionId: string }>('session/current', {});
|
|
537
|
-
sessionId = current.sessionId;
|
|
538
|
-
} catch {
|
|
539
|
-
output.printError('No active session. Provide a session ID to export.');
|
|
540
|
-
return { success: false, exitCode: 1 };
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// Generate output path if not provided
|
|
545
|
-
if (!outputPath) {
|
|
546
|
-
const ext = compress ? '.gz' : '';
|
|
547
|
-
outputPath = `session-${sessionId}.${exportFormat}${ext}`;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
const spinner = output.createSpinner({ text: 'Exporting session...' });
|
|
551
|
-
spinner.start();
|
|
552
|
-
|
|
553
|
-
try {
|
|
554
|
-
const result = await callMCPTool<{
|
|
555
|
-
sessionId: string;
|
|
556
|
-
data: unknown;
|
|
557
|
-
stats: {
|
|
558
|
-
agentCount: number;
|
|
559
|
-
taskCount: number;
|
|
560
|
-
memoryEntries: number;
|
|
561
|
-
};
|
|
562
|
-
}>('session/export', {
|
|
563
|
-
sessionId,
|
|
564
|
-
includeMemory: ctx.flags['include-memory'] !== false
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
// Format output
|
|
568
|
-
let content: string;
|
|
569
|
-
if (exportFormat === 'yaml') {
|
|
570
|
-
content = toSimpleYaml(result.data);
|
|
571
|
-
} else {
|
|
572
|
-
content = JSON.stringify(result.data, null, 2);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Write to file
|
|
576
|
-
const absolutePath = path.isAbsolute(outputPath)
|
|
577
|
-
? outputPath
|
|
578
|
-
: path.join(ctx.cwd, outputPath);
|
|
579
|
-
|
|
580
|
-
fs.writeFileSync(absolutePath, content, 'utf-8');
|
|
581
|
-
|
|
582
|
-
spinner.succeed('Session exported');
|
|
583
|
-
output.writeln();
|
|
584
|
-
|
|
585
|
-
output.printTable({
|
|
586
|
-
columns: [
|
|
587
|
-
{ key: 'property', header: 'Property', width: 18 },
|
|
588
|
-
{ key: 'value', header: 'Value', width: 40 }
|
|
589
|
-
],
|
|
590
|
-
data: [
|
|
591
|
-
{ property: 'Session ID', value: sessionId },
|
|
592
|
-
{ property: 'Output File', value: absolutePath },
|
|
593
|
-
{ property: 'Format', value: exportFormat.toUpperCase() },
|
|
594
|
-
{ property: 'Agents', value: result.stats.agentCount },
|
|
595
|
-
{ property: 'Tasks', value: result.stats.taskCount },
|
|
596
|
-
{ property: 'Memory Entries', value: result.stats.memoryEntries },
|
|
597
|
-
{ property: 'File Size', value: formatSize(content.length) }
|
|
598
|
-
]
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
output.writeln();
|
|
602
|
-
output.printSuccess(`Session exported to ${outputPath}`);
|
|
603
|
-
|
|
604
|
-
return {
|
|
605
|
-
success: true,
|
|
606
|
-
data: { sessionId, outputPath, format: exportFormat, size: content.length }
|
|
607
|
-
};
|
|
608
|
-
} catch (error) {
|
|
609
|
-
spinner.fail('Failed to export session');
|
|
610
|
-
if (error instanceof MCPClientError) {
|
|
611
|
-
output.printError(`Error: ${error.message}`);
|
|
612
|
-
} else {
|
|
613
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
614
|
-
}
|
|
615
|
-
return { success: false, exitCode: 1 };
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
// Import subcommand
|
|
621
|
-
const importCommand: Command = {
|
|
622
|
-
name: 'import',
|
|
623
|
-
description: 'Import session from file',
|
|
624
|
-
options: [
|
|
625
|
-
{
|
|
626
|
-
name: 'name',
|
|
627
|
-
short: 'n',
|
|
628
|
-
description: 'Session name for imported session',
|
|
629
|
-
type: 'string'
|
|
630
|
-
},
|
|
631
|
-
{
|
|
632
|
-
name: 'activate',
|
|
633
|
-
description: 'Activate session after import',
|
|
634
|
-
type: 'boolean',
|
|
635
|
-
default: false
|
|
636
|
-
}
|
|
637
|
-
],
|
|
638
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
639
|
-
const filePath = ctx.args[0];
|
|
640
|
-
const sessionName = ctx.flags.name as string;
|
|
641
|
-
const activate = ctx.flags.activate as boolean;
|
|
642
|
-
|
|
643
|
-
if (!filePath) {
|
|
644
|
-
output.printError('File path is required');
|
|
645
|
-
return { success: false, exitCode: 1 };
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
const absolutePath = path.isAbsolute(filePath)
|
|
649
|
-
? filePath
|
|
650
|
-
: path.join(ctx.cwd, filePath);
|
|
651
|
-
|
|
652
|
-
if (!fs.existsSync(absolutePath)) {
|
|
653
|
-
output.printError(`File not found: ${absolutePath}`);
|
|
654
|
-
return { success: false, exitCode: 1 };
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
const spinner = output.createSpinner({ text: 'Importing session...' });
|
|
658
|
-
spinner.start();
|
|
659
|
-
|
|
660
|
-
try {
|
|
661
|
-
const content = fs.readFileSync(absolutePath, 'utf-8');
|
|
662
|
-
let data: unknown;
|
|
663
|
-
|
|
664
|
-
// Parse based on extension
|
|
665
|
-
if (absolutePath.endsWith('.yaml') || absolutePath.endsWith('.yml')) {
|
|
666
|
-
// Simple YAML parsing (basic implementation)
|
|
667
|
-
data = JSON.parse(content); // Would need proper YAML parser
|
|
668
|
-
} else {
|
|
669
|
-
data = JSON.parse(content);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
const result = await callMCPTool<{
|
|
673
|
-
sessionId: string;
|
|
674
|
-
name: string;
|
|
675
|
-
importedAt: string;
|
|
676
|
-
stats: {
|
|
677
|
-
agentsImported: number;
|
|
678
|
-
tasksImported: number;
|
|
679
|
-
memoryEntriesImported: number;
|
|
680
|
-
};
|
|
681
|
-
activated: boolean;
|
|
682
|
-
}>('session/import', {
|
|
683
|
-
data,
|
|
684
|
-
name: sessionName,
|
|
685
|
-
activate
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
spinner.succeed('Session imported');
|
|
689
|
-
output.writeln();
|
|
690
|
-
|
|
691
|
-
output.printTable({
|
|
692
|
-
columns: [
|
|
693
|
-
{ key: 'property', header: 'Property', width: 20 },
|
|
694
|
-
{ key: 'value', header: 'Value', width: 35 }
|
|
695
|
-
],
|
|
696
|
-
data: [
|
|
697
|
-
{ property: 'Session ID', value: result.sessionId },
|
|
698
|
-
{ property: 'Name', value: result.name },
|
|
699
|
-
{ property: 'Source File', value: path.basename(absolutePath) },
|
|
700
|
-
{ property: 'Agents Imported', value: result.stats.agentsImported },
|
|
701
|
-
{ property: 'Tasks Imported', value: result.stats.tasksImported },
|
|
702
|
-
{ property: 'Memory Entries', value: result.stats.memoryEntriesImported },
|
|
703
|
-
{ property: 'Activated', value: result.activated ? 'Yes' : 'No' }
|
|
704
|
-
]
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
output.writeln();
|
|
708
|
-
output.printSuccess(`Session imported: ${result.sessionId}`);
|
|
709
|
-
|
|
710
|
-
if (!result.activated) {
|
|
711
|
-
output.printInfo(`Restore with: claude-flow session restore ${result.sessionId}`);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
if (ctx.flags.format === 'json') {
|
|
715
|
-
output.printJson(result);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
return { success: true, data: result };
|
|
719
|
-
} catch (error) {
|
|
720
|
-
spinner.fail('Failed to import session');
|
|
721
|
-
if (error instanceof MCPClientError) {
|
|
722
|
-
output.printError(`Error: ${error.message}`);
|
|
723
|
-
} else if (error instanceof SyntaxError) {
|
|
724
|
-
output.printError('Invalid file format. Expected JSON or YAML.');
|
|
725
|
-
} else {
|
|
726
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
727
|
-
}
|
|
728
|
-
return { success: false, exitCode: 1 };
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
|
|
733
|
-
// Current subcommand
|
|
734
|
-
const currentCommand: Command = {
|
|
735
|
-
name: 'current',
|
|
736
|
-
description: 'Show current active session',
|
|
737
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
738
|
-
try {
|
|
739
|
-
const result = await callMCPTool<{
|
|
740
|
-
sessionId: string;
|
|
741
|
-
name?: string;
|
|
742
|
-
status: string;
|
|
743
|
-
startedAt: string;
|
|
744
|
-
stats: {
|
|
745
|
-
agentCount: number;
|
|
746
|
-
taskCount: number;
|
|
747
|
-
memoryEntries: number;
|
|
748
|
-
duration: number;
|
|
749
|
-
};
|
|
750
|
-
}>('session/current', { includeStats: true });
|
|
751
|
-
|
|
752
|
-
if (ctx.flags.format === 'json') {
|
|
753
|
-
output.printJson(result);
|
|
754
|
-
return { success: true, data: result };
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
output.writeln();
|
|
758
|
-
output.writeln(output.bold('Current Session'));
|
|
759
|
-
output.writeln();
|
|
760
|
-
|
|
761
|
-
output.printTable({
|
|
762
|
-
columns: [
|
|
763
|
-
{ key: 'property', header: 'Property', width: 18 },
|
|
764
|
-
{ key: 'value', header: 'Value', width: 35 }
|
|
765
|
-
],
|
|
766
|
-
data: [
|
|
767
|
-
{ property: 'Session ID', value: result.sessionId },
|
|
768
|
-
{ property: 'Name', value: result.name || '-' },
|
|
769
|
-
{ property: 'Status', value: formatStatus(result.status) },
|
|
770
|
-
{ property: 'Started', value: new Date(result.startedAt).toLocaleString() },
|
|
771
|
-
{ property: 'Duration', value: formatDuration(result.stats.duration) },
|
|
772
|
-
{ property: 'Agents', value: result.stats.agentCount },
|
|
773
|
-
{ property: 'Tasks', value: result.stats.taskCount },
|
|
774
|
-
{ property: 'Memory Entries', value: result.stats.memoryEntries }
|
|
775
|
-
]
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
return { success: true, data: result };
|
|
779
|
-
} catch (error) {
|
|
780
|
-
if (error instanceof MCPClientError) {
|
|
781
|
-
output.printWarning('No active session');
|
|
782
|
-
output.printInfo('Start a session with "claude-flow start"');
|
|
783
|
-
return { success: true, data: { active: false } };
|
|
784
|
-
}
|
|
785
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
786
|
-
return { success: false, exitCode: 1 };
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
// Helper functions
|
|
792
|
-
function formatSize(bytes: number): string {
|
|
793
|
-
if (bytes === 0) return '0 B';
|
|
794
|
-
const k = 1024;
|
|
795
|
-
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
796
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
797
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
function formatDuration(ms: number): string {
|
|
801
|
-
const seconds = Math.floor(ms / 1000);
|
|
802
|
-
const minutes = Math.floor(seconds / 60);
|
|
803
|
-
const hours = Math.floor(minutes / 60);
|
|
804
|
-
|
|
805
|
-
if (hours > 0) {
|
|
806
|
-
return `${hours}h ${minutes % 60}m`;
|
|
807
|
-
} else if (minutes > 0) {
|
|
808
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
809
|
-
}
|
|
810
|
-
return `${seconds}s`;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function toSimpleYaml(obj: unknown, indent: number = 0): string {
|
|
814
|
-
// Simple YAML serializer (for basic types)
|
|
815
|
-
if (obj === null) return 'null';
|
|
816
|
-
if (typeof obj === 'boolean') return String(obj);
|
|
817
|
-
if (typeof obj === 'number') return String(obj);
|
|
818
|
-
if (typeof obj === 'string') return obj.includes(':') ? `"${obj}"` : obj;
|
|
819
|
-
|
|
820
|
-
const spaces = ' '.repeat(indent);
|
|
821
|
-
let result = '';
|
|
822
|
-
|
|
823
|
-
if (Array.isArray(obj)) {
|
|
824
|
-
for (const item of obj) {
|
|
825
|
-
result += `${spaces}- ${toSimpleYaml(item, indent + 1).trim()}\n`;
|
|
826
|
-
}
|
|
827
|
-
return result;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if (typeof obj === 'object') {
|
|
831
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
832
|
-
if (typeof value === 'object' && value !== null) {
|
|
833
|
-
result += `${spaces}${key}:\n${toSimpleYaml(value, indent + 1)}`;
|
|
834
|
-
} else {
|
|
835
|
-
result += `${spaces}${key}: ${toSimpleYaml(value, indent)}\n`;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return result;
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
return String(obj);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// Main session command
|
|
845
|
-
export const sessionCommand: Command = {
|
|
846
|
-
name: 'session',
|
|
847
|
-
description: 'Session management commands',
|
|
848
|
-
subcommands: [
|
|
849
|
-
listCommand,
|
|
850
|
-
saveCommand,
|
|
851
|
-
restoreCommand,
|
|
852
|
-
deleteCommand,
|
|
853
|
-
exportCommand,
|
|
854
|
-
importCommand,
|
|
855
|
-
currentCommand
|
|
856
|
-
],
|
|
857
|
-
options: [],
|
|
858
|
-
examples: [
|
|
859
|
-
{ command: 'claude-flow session list', description: 'List all sessions' },
|
|
860
|
-
{ command: 'claude-flow session save -n "checkpoint-1"', description: 'Save current session' },
|
|
861
|
-
{ command: 'claude-flow session restore session-123', description: 'Restore a session' },
|
|
862
|
-
{ command: 'claude-flow session delete session-123', description: 'Delete a session' },
|
|
863
|
-
{ command: 'claude-flow session export -o backup.json', description: 'Export session to file' },
|
|
864
|
-
{ command: 'claude-flow session import backup.json', description: 'Import session from file' },
|
|
865
|
-
{ command: 'claude-flow session current', description: 'Show current session' }
|
|
866
|
-
],
|
|
867
|
-
action: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
868
|
-
// Show help if no subcommand
|
|
869
|
-
output.writeln();
|
|
870
|
-
output.writeln(output.bold('Session Management Commands'));
|
|
871
|
-
output.writeln();
|
|
872
|
-
output.writeln('Usage: claude-flow session <subcommand> [options]');
|
|
873
|
-
output.writeln();
|
|
874
|
-
output.writeln('Subcommands:');
|
|
875
|
-
output.printList([
|
|
876
|
-
`${output.highlight('list')} - List all sessions`,
|
|
877
|
-
`${output.highlight('save')} - Save current session state`,
|
|
878
|
-
`${output.highlight('restore')} - Restore a saved session`,
|
|
879
|
-
`${output.highlight('delete')} - Delete a saved session`,
|
|
880
|
-
`${output.highlight('export')} - Export session to file`,
|
|
881
|
-
`${output.highlight('import')} - Import session from file`,
|
|
882
|
-
`${output.highlight('current')} - Show current active session`
|
|
883
|
-
]);
|
|
884
|
-
output.writeln();
|
|
885
|
-
output.writeln('Run "claude-flow session <subcommand> --help" for subcommand help');
|
|
886
|
-
|
|
887
|
-
return { success: true };
|
|
888
|
-
}
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
export default sessionCommand;
|