@howlil/ez-agents 3.4.2 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +77 -2
  2. package/agents/ez-observer-agent.md +260 -0
  3. package/agents/ez-release-agent.md +333 -0
  4. package/agents/ez-requirements-agent.md +377 -0
  5. package/agents/ez-scrum-master-agent.md +242 -0
  6. package/agents/ez-tech-lead-agent.md +267 -0
  7. package/bin/install.js +3221 -3272
  8. package/commands/ez/arch-review.md +102 -0
  9. package/commands/ez/execute-phase.md +11 -0
  10. package/commands/ez/export-session.md +79 -0
  11. package/commands/ez/gather-requirements.md +117 -0
  12. package/commands/ez/git-workflow.md +72 -0
  13. package/commands/ez/hotfix.md +120 -0
  14. package/commands/ez/import-session.md +82 -0
  15. package/commands/ez/list-sessions.md +96 -0
  16. package/commands/ez/package-manager.md +316 -0
  17. package/commands/ez/plan-phase.md +9 -1
  18. package/commands/ez/preflight.md +79 -0
  19. package/commands/ez/progress.md +13 -1
  20. package/commands/ez/release.md +153 -0
  21. package/commands/ez/resume.md +107 -0
  22. package/commands/ez/standup.md +85 -0
  23. package/ez-agents/bin/ez-tools.cjs +1095 -716
  24. package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
  25. package/ez-agents/bin/lib/content-scanner.cjs +238 -0
  26. package/ez-agents/bin/lib/context-cache.cjs +154 -0
  27. package/ez-agents/bin/lib/context-errors.cjs +71 -0
  28. package/ez-agents/bin/lib/context-manager.cjs +220 -0
  29. package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
  30. package/ez-agents/bin/lib/file-access.cjs +207 -0
  31. package/ez-agents/bin/lib/git-errors.cjs +83 -0
  32. package/ez-agents/bin/lib/git-utils.cjs +321 -203
  33. package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
  34. package/ez-agents/bin/lib/index.cjs +46 -2
  35. package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
  36. package/ez-agents/bin/lib/logger.cjs +124 -154
  37. package/ez-agents/bin/lib/memory-compression.cjs +256 -0
  38. package/ez-agents/bin/lib/metrics-tracker.cjs +406 -0
  39. package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
  40. package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
  41. package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
  42. package/ez-agents/bin/lib/release-validator.cjs +614 -0
  43. package/ez-agents/bin/lib/safe-exec.cjs +128 -214
  44. package/ez-agents/bin/lib/session-chain.cjs +304 -0
  45. package/ez-agents/bin/lib/session-errors.cjs +81 -0
  46. package/ez-agents/bin/lib/session-export.cjs +251 -0
  47. package/ez-agents/bin/lib/session-import.cjs +262 -0
  48. package/ez-agents/bin/lib/session-manager.cjs +280 -0
  49. package/ez-agents/bin/lib/tier-manager.cjs +428 -0
  50. package/ez-agents/bin/lib/url-fetch.cjs +170 -0
  51. package/ez-agents/references/metrics-schema.md +118 -0
  52. package/ez-agents/references/planning-config.md +140 -0
  53. package/ez-agents/references/tier-strategy.md +103 -0
  54. package/ez-agents/templates/bdd-feature.md +173 -0
  55. package/ez-agents/templates/discussion.md +68 -0
  56. package/ez-agents/templates/incident-runbook.md +205 -0
  57. package/ez-agents/templates/release-checklist.md +133 -0
  58. package/ez-agents/templates/rollback-plan.md +201 -0
  59. package/ez-agents/workflows/arch-review.md +54 -0
  60. package/ez-agents/workflows/autonomous.md +844 -743
  61. package/ez-agents/workflows/execute-phase.md +45 -0
  62. package/ez-agents/workflows/export-session.md +255 -0
  63. package/ez-agents/workflows/gather-requirements.md +206 -0
  64. package/ez-agents/workflows/help.md +92 -0
  65. package/ez-agents/workflows/hotfix.md +291 -0
  66. package/ez-agents/workflows/import-session.md +303 -0
  67. package/ez-agents/workflows/new-milestone.md +713 -384
  68. package/ez-agents/workflows/new-project.md +1107 -1113
  69. package/ez-agents/workflows/plan-phase.md +22 -0
  70. package/ez-agents/workflows/progress.md +15 -25
  71. package/ez-agents/workflows/release.md +253 -0
  72. package/ez-agents/workflows/resume-session.md +215 -0
  73. package/ez-agents/workflows/standup.md +64 -0
  74. package/package.json +9 -2
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Session Error Classes
5
+ *
6
+ * Provides structured error handling for session operations
7
+ */
8
+
9
+ class SessionError extends Error {
10
+ constructor(message, options = {}) {
11
+ super(message);
12
+ this.name = 'SessionError';
13
+ this.code = options.code || 'SESSION_ERROR';
14
+ this.details = options.details || {};
15
+ this.timestamp = new Date().toISOString();
16
+ Error.captureStackTrace(this, SessionError);
17
+ }
18
+
19
+ toJSON() {
20
+ return {
21
+ name: this.name,
22
+ code: this.code,
23
+ message: this.message,
24
+ details: this.details,
25
+ timestamp: this.timestamp
26
+ };
27
+ }
28
+ }
29
+
30
+ class SessionNotFoundError extends SessionError {
31
+ constructor(sessionId, options = {}) {
32
+ super(`Session '${sessionId}' not found`, {
33
+ code: 'SESSION_NOT_FOUND',
34
+ details: { sessionId, ...options.details }
35
+ });
36
+ this.name = 'SessionNotFoundError';
37
+ this.sessionId = sessionId;
38
+ }
39
+ }
40
+
41
+ class SessionChainError extends SessionError {
42
+ constructor(message, chain = [], options = {}) {
43
+ super(message, {
44
+ code: 'SESSION_CHAIN_ERROR',
45
+ details: { chain, ...options.details }
46
+ });
47
+ this.name = 'SessionChainError';
48
+ this.chain = chain;
49
+ }
50
+ }
51
+
52
+ class SessionExportError extends SessionError {
53
+ constructor(format, reason, options = {}) {
54
+ super(`Export failed for format '${format}': ${reason}`, {
55
+ code: 'SESSION_EXPORT_ERROR',
56
+ details: { format, reason, ...options.details }
57
+ });
58
+ this.name = 'SessionExportError';
59
+ this.format = format;
60
+ this.reason = reason;
61
+ }
62
+ }
63
+
64
+ class SessionImportError extends SessionError {
65
+ constructor(message, validationErrors = [], options = {}) {
66
+ super(message, {
67
+ code: 'SESSION_IMPORT_ERROR',
68
+ details: { validationErrors, ...options.details }
69
+ });
70
+ this.name = 'SessionImportError';
71
+ this.validationErrors = validationErrors;
72
+ }
73
+ }
74
+
75
+ module.exports = {
76
+ SessionError,
77
+ SessionNotFoundError,
78
+ SessionChainError,
79
+ SessionExportError,
80
+ SessionImportError
81
+ };
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Session Export — Export session data for model handoff
5
+ *
6
+ * Supports markdown and JSON export formats
7
+ */
8
+
9
+ const { SessionExportError, SessionNotFoundError } = require('./session-errors.cjs');
10
+ const { safePlanningWriteSync } = require('./planning-write.cjs');
11
+
12
+ class SessionExport {
13
+ /**
14
+ * Create a SessionExport instance
15
+ * @param {Object} sessionManager - SessionManager instance
16
+ */
17
+ constructor(sessionManager) {
18
+ this.sessionManager = sessionManager;
19
+ }
20
+
21
+ /**
22
+ * Export a session in the specified format
23
+ * @param {string} sessionId - Session ID
24
+ * @param {string} format - Export format ('markdown' or 'json')
25
+ * @returns {Object} Export result with content and path
26
+ */
27
+ export(sessionId, format = 'markdown') {
28
+ const session = this.sessionManager.loadSession(sessionId);
29
+ if (!session) {
30
+ throw new SessionNotFoundError(sessionId);
31
+ }
32
+
33
+ let content;
34
+ switch (format) {
35
+ case 'markdown':
36
+ content = this.toMarkdown(session);
37
+ break;
38
+ case 'json':
39
+ content = this.toJSON(session);
40
+ break;
41
+ default:
42
+ throw new SessionExportError(format, 'Unsupported format');
43
+ }
44
+
45
+ const ext = format === 'markdown' ? 'md' : 'json';
46
+ const outputPath = `.planning/sessions/export-${sessionId}.${ext}`;
47
+
48
+ return {
49
+ success: true,
50
+ format,
51
+ content,
52
+ outputPath
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Convert session to markdown format
58
+ * @param {Object} session - Session object
59
+ * @returns {string} Markdown string
60
+ */
61
+ toMarkdown(session) {
62
+ const { metadata, context, state } = session;
63
+ const exportedAt = new Date().toISOString();
64
+
65
+ // Calculate duration
66
+ let duration = 'N/A';
67
+ if (metadata.started_at && metadata.ended_at) {
68
+ const start = new Date(metadata.started_at);
69
+ const end = new Date(metadata.ended_at);
70
+ const diffMs = end - start;
71
+ const diffHrs = Math.floor(diffMs / (1000 * 60 * 60));
72
+ const diffMins = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
73
+ if (diffHrs > 0) {
74
+ duration = `${diffHrs}h ${diffMins}m`;
75
+ } else {
76
+ duration = `${diffMins}m`;
77
+ }
78
+ }
79
+
80
+ // Build markdown
81
+ let md = `# Session Export: ${metadata.session_id}\n\n`;
82
+ md += `**Exported:** ${exportedAt}\n`;
83
+ md += `**Model:** ${metadata.model || 'Unknown'}\n`;
84
+ md += `**Phase:** ${metadata.phase || 'N/A'}\n`;
85
+ md += `**Plan:** ${metadata.plan || 'N/A'}\n`;
86
+ md += `**Duration:** ${duration}\n\n`;
87
+ md += `---\n\n`;
88
+
89
+ // Session Summary
90
+ md += `## Session Summary\n\n`;
91
+ md += `**Objective:** ${state.next_recommended_action || 'Not specified'}\n\n`;
92
+
93
+ md += `**Completed:**\n`;
94
+ if (context.tasks && context.tasks.length > 0) {
95
+ const completedTasks = context.tasks.filter(t => t.status === 'completed');
96
+ if (completedTasks.length > 0) {
97
+ completedTasks.forEach(t => md += `- ${t.name || t.description || 'Task'}\n`);
98
+ } else {
99
+ md += `- None\n`;
100
+ }
101
+ } else {
102
+ md += `- None\n`;
103
+ }
104
+ md += `\n`;
105
+
106
+ md += `**Incomplete:**\n`;
107
+ if (state.incomplete_tasks && state.incomplete_tasks.length > 0) {
108
+ state.incomplete_tasks.forEach(t => md += `- ${t}\n`);
109
+ } else {
110
+ md += `- None\n`;
111
+ }
112
+ md += `\n`;
113
+
114
+ md += `---\n\n`;
115
+
116
+ // Key Decisions
117
+ md += `## Key Decisions\n\n`;
118
+ if (context.decisions && context.decisions.length > 0) {
119
+ context.decisions.forEach((decision, index) => {
120
+ md += `${index + 1}. **${decision.title || 'Decision'}**\n`;
121
+ if (decision.rationale) {
122
+ md += ` - Rationale: ${decision.rationale}\n`;
123
+ }
124
+ if (decision.status) {
125
+ md += ` - Status: ${decision.status}\n`;
126
+ }
127
+ });
128
+ } else {
129
+ md += `No decisions recorded\n`;
130
+ }
131
+ md += `\n`;
132
+
133
+ md += `---\n\n`;
134
+
135
+ // File Changes
136
+ md += `## File Changes\n\n`;
137
+ if (context.file_changes && context.file_changes.length > 0) {
138
+ md += `| File | Action | Reason |\n`;
139
+ md += `|------|--------|--------|\n`;
140
+ context.file_changes.forEach(change => {
141
+ md += `| ${change.file || 'Unknown'} | ${change.action || 'modified'} | ${change.reason || '-'} |\n`;
142
+ });
143
+ } else {
144
+ md += `No file changes recorded\n`;
145
+ }
146
+ md += `\n`;
147
+
148
+ md += `---\n\n`;
149
+
150
+ // Open Questions
151
+ md += `## Open Questions\n\n`;
152
+ if (context.open_questions && context.open_questions.length > 0) {
153
+ context.open_questions.forEach(q => md += `- ${q}\n`);
154
+ } else {
155
+ md += `None\n`;
156
+ }
157
+ md += `\n`;
158
+
159
+ md += `---\n\n`;
160
+
161
+ // Blockers
162
+ md += `## Blockers/Concerns\n\n`;
163
+ if (context.blockers && context.blockers.length > 0) {
164
+ context.blockers.forEach(b => md += `- ${b}\n`);
165
+ } else {
166
+ md += `None\n`;
167
+ }
168
+ md += `\n`;
169
+
170
+ md += `---\n\n`;
171
+
172
+ // Recommended Next Actions
173
+ md += `## Recommended Next Actions\n\n`;
174
+ if (state.next_recommended_action) {
175
+ md += `- ${state.next_recommended_action}\n`;
176
+ } else {
177
+ md += `None\n`;
178
+ }
179
+ md += `\n`;
180
+
181
+ md += `---\n\n`;
182
+
183
+ // Session Chain
184
+ md += `## Session Chain\n\n`;
185
+ const chain = metadata.session_chain || [];
186
+ const currentIndex = chain.indexOf(metadata.session_id);
187
+
188
+ if (chain.length > 0) {
189
+ md += `- Previous: ${currentIndex > 0 ? chain[currentIndex - 1] : 'none'}\n`;
190
+ md += `- Current: ${metadata.session_id}\n`;
191
+ md += `- Next: ${currentIndex < chain.length - 1 ? chain[currentIndex + 1] : 'none'}\n`;
192
+ } else {
193
+ md += `- Previous: none\n`;
194
+ md += `- Current: ${metadata.session_id}\n`;
195
+ md += `- Next: none\n`;
196
+ }
197
+ md += `\n`;
198
+
199
+ // Token Usage (if available)
200
+ if (metadata.token_usage && (metadata.token_usage.input || metadata.token_usage.output)) {
201
+ md += `---\n\n`;
202
+ md += `## Token Usage\n\n`;
203
+ md += `- Input: ${metadata.token_usage.input || 0}\n`;
204
+ md += `- Output: ${metadata.token_usage.output || 0}\n`;
205
+ md += `- Total: ${metadata.token_usage.total || 0}\n`;
206
+ md += `\n`;
207
+ }
208
+
209
+ return md;
210
+ }
211
+
212
+ /**
213
+ * Convert session to JSON format
214
+ * @param {Object} session - Session object
215
+ * @returns {string} JSON string
216
+ */
217
+ toJSON(session) {
218
+ const exportData = {
219
+ export_version: '1.0',
220
+ exported_at: new Date().toISOString(),
221
+ export_format: 'json',
222
+ session: session
223
+ };
224
+ return JSON.stringify(exportData, null, 2);
225
+ }
226
+
227
+ /**
228
+ * Export session to file
229
+ * @param {string} sessionId - Session ID
230
+ * @param {string} format - Export format
231
+ * @param {string} outputPath - Output file path
232
+ * @returns {Object} Export result with path
233
+ */
234
+ exportToFile(sessionId, format, outputPath) {
235
+ const result = this.export(sessionId, format);
236
+
237
+ if (!outputPath) {
238
+ outputPath = result.outputPath;
239
+ }
240
+
241
+ safePlanningWriteSync(outputPath, result.content);
242
+
243
+ return {
244
+ success: true,
245
+ path: outputPath,
246
+ format
247
+ };
248
+ }
249
+ }
250
+
251
+ module.exports = SessionExport;
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Session Import — Import session data from exported files
5
+ *
6
+ * Validates session structure and chain integrity
7
+ * Supports model-specific adapters
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const { SessionImportError, SessionNotFoundError } = require('./session-errors.cjs');
12
+ const { defaultLogger: logger } = require('./logger.cjs');
13
+
14
+ class SessionImport {
15
+ /**
16
+ * Create a SessionImport instance
17
+ * @param {Object} sessionManager - SessionManager instance
18
+ */
19
+ constructor(sessionManager) {
20
+ this.sessionManager = sessionManager;
21
+ }
22
+
23
+ /**
24
+ * Import a session from file
25
+ * @param {string} sessionFile - Path to session file
26
+ * @param {Object} options - Import options
27
+ * @param {string} [options.sourceModel] - Source model for adapter
28
+ * @returns {Object} Import result with sessionId and warnings
29
+ */
30
+ import(sessionFile, options = {}) {
31
+ const { sourceModel } = options;
32
+ const warnings = [];
33
+
34
+ // Read and parse file
35
+ let importedData;
36
+ try {
37
+ const content = fs.readFileSync(sessionFile, 'utf-8');
38
+ importedData = JSON.parse(content);
39
+ } catch (err) {
40
+ throw new SessionImportError(`Failed to parse JSON: ${err.message}`, [err.message]);
41
+ }
42
+
43
+ // Handle model-specific format conversion
44
+ if (sourceModel) {
45
+ importedData = this.importFromModelSpecificFormat(importedData, sourceModel);
46
+ }
47
+
48
+ // Validate structure
49
+ const structureValidation = this.validateStructure(importedData);
50
+ if (!structureValidation.valid) {
51
+ throw new SessionImportError('Invalid session structure', structureValidation.errors);
52
+ }
53
+
54
+ // Validate session chain
55
+ const chainValidation = this.validateSessionChain(importedData);
56
+ if (!chainValidation.valid) {
57
+ throw new SessionImportError('Invalid session chain', chainValidation.errors);
58
+ }
59
+
60
+ // Validate chain links exist
61
+ const linksValidation = this.validateChainLinksExist(importedData);
62
+ if (linksValidation.warnings && linksValidation.warnings.length > 0) {
63
+ warnings.push(...linksValidation.warnings);
64
+ }
65
+
66
+ // Create new session
67
+ const newSessionId = this.sessionManager.createSession({
68
+ model: importedData.metadata?.model,
69
+ phase: importedData.metadata?.phase,
70
+ plan: importedData.metadata?.plan
71
+ });
72
+
73
+ // Merge imported context and state
74
+ const updates = {
75
+ context: importedData.context || {},
76
+ state: importedData.state || {}
77
+ };
78
+
79
+ // Add previous session to chain
80
+ const previousSessionId = importedData.metadata?.session_id;
81
+ if (previousSessionId) {
82
+ updates.metadata = {
83
+ session_chain: [previousSessionId]
84
+ };
85
+ }
86
+
87
+ this.sessionManager.updateSession(newSessionId, updates);
88
+
89
+ logger.info('Session imported', { sessionId: newSessionId, sourceFile: sessionFile });
90
+
91
+ return {
92
+ success: true,
93
+ sessionId: newSessionId,
94
+ warnings
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Validate session structure
100
+ * @param {Object} session - Session object
101
+ * @returns {Object} Validation result
102
+ */
103
+ validateStructure(session) {
104
+ const errors = [];
105
+
106
+ // Check for export wrapper or direct session
107
+ const sessionData = session.session || session;
108
+
109
+ if (!sessionData.metadata) {
110
+ errors.push('Missing metadata section');
111
+ } else {
112
+ if (!sessionData.metadata.session_id) {
113
+ errors.push('Missing metadata.session_id');
114
+ }
115
+ if (!sessionData.metadata.started_at) {
116
+ errors.push('Missing metadata.started_at');
117
+ }
118
+ if (!sessionData.metadata.session_version) {
119
+ errors.push('Missing metadata.session_version');
120
+ }
121
+ }
122
+
123
+ if (!sessionData.context) {
124
+ errors.push('Missing context section');
125
+ } else {
126
+ if (!Array.isArray(sessionData.context.tasks)) {
127
+ errors.push('context.tasks must be an array');
128
+ }
129
+ if (!Array.isArray(sessionData.context.decisions)) {
130
+ errors.push('context.decisions must be an array');
131
+ }
132
+ }
133
+
134
+ return {
135
+ valid: errors.length === 0,
136
+ errors
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Validate session chain integrity
142
+ * @param {Object} session - Session object
143
+ * @returns {Object} Validation result
144
+ */
145
+ validateSessionChain(session) {
146
+ const errors = [];
147
+ const sessionData = session.session || session;
148
+
149
+ if (sessionData.metadata?.session_chain) {
150
+ const chain = sessionData.metadata.session_chain;
151
+ const sessionId = sessionData.metadata.session_id;
152
+
153
+ if (!Array.isArray(chain)) {
154
+ errors.push('session_chain must be an array');
155
+ } else if (chain.includes(sessionId)) {
156
+ errors.push('Circular reference detected: session_chain includes current session_id');
157
+ }
158
+ }
159
+
160
+ return {
161
+ valid: errors.length === 0,
162
+ errors
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Validate chain links exist in session manager
168
+ * @param {Object} session - Session object
169
+ * @returns {Object} Validation result with warnings
170
+ */
171
+ validateChainLinksExist(session) {
172
+ const warnings = [];
173
+ const sessionData = session.session || session;
174
+
175
+ if (sessionData.metadata?.session_chain) {
176
+ const chain = sessionData.metadata.session_chain;
177
+ const missingLinks = [];
178
+
179
+ for (const id of chain) {
180
+ const linkedSession = this.sessionManager.loadSession(id);
181
+ if (!linkedSession) {
182
+ missingLinks.push(id);
183
+ }
184
+ }
185
+
186
+ if (missingLinks.length > 0) {
187
+ warnings.push(`Missing chain links: ${missingLinks.join(', ')}`);
188
+ }
189
+ }
190
+
191
+ return {
192
+ valid: true,
193
+ warnings
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Import from model-specific format
199
+ * @param {Object} data - Data to convert
200
+ * @param {string} sourceModel - Source model name
201
+ * @returns {Object} Converted session object
202
+ */
203
+ importFromModelSpecificFormat(data, sourceModel) {
204
+ // If data has session wrapper, use it
205
+ if (data.session) {
206
+ return data.session;
207
+ }
208
+
209
+ // Model-specific adapters (can be extended)
210
+ switch (sourceModel.toLowerCase()) {
211
+ case 'claude':
212
+ return this._adaptClaudeFormat(data);
213
+ case 'qwen':
214
+ return this._adaptQwenFormat(data);
215
+ case 'openai':
216
+ return this._adaptOpenAIFormat(data);
217
+ case 'kimi':
218
+ return this._adaptKimiFormat(data);
219
+ default:
220
+ // Assume standard format
221
+ return data;
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Adapt Claude-specific format
227
+ * @private
228
+ */
229
+ _adaptClaudeFormat(data) {
230
+ // Claude format adapter (placeholder)
231
+ return data;
232
+ }
233
+
234
+ /**
235
+ * Adapt Qwen-specific format
236
+ * @private
237
+ */
238
+ _adaptQwenFormat(data) {
239
+ // Qwen format adapter (placeholder)
240
+ return data;
241
+ }
242
+
243
+ /**
244
+ * Adapt OpenAI-specific format
245
+ * @private
246
+ */
247
+ _adaptOpenAIFormat(data) {
248
+ // OpenAI format adapter (placeholder)
249
+ return data;
250
+ }
251
+
252
+ /**
253
+ * Adapt Kimi-specific format
254
+ * @private
255
+ */
256
+ _adaptKimiFormat(data) {
257
+ // Kimi format adapter (placeholder)
258
+ return data;
259
+ }
260
+ }
261
+
262
+ module.exports = SessionImport;