snow-flow 4.1.0 → 4.1.2

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 (44) hide show
  1. package/README.md +15 -40
  2. package/dist/cli.js +0 -81
  3. package/dist/dynamic-version.js +1 -1
  4. package/dist/index.js +3 -1
  5. package/dist/intelligence/performance-recommendations-engine.js +1 -0
  6. package/dist/mcp/advanced/servicenow-advanced-features-mcp.js +12 -12
  7. package/dist/mcp/servicenow-development-assistant-mcp.js +1 -1
  8. package/dist/mcp/servicenow-local-development-mcp.d.ts +0 -3
  9. package/dist/mcp/servicenow-local-development-mcp.js +7 -204
  10. package/dist/mcp/servicenow-machine-learning-mcp.js +2 -2
  11. package/dist/mcp/servicenow-reporting-analytics-mcp.js +1 -1
  12. package/dist/mcp/shared/response-limiter.js +1 -1
  13. package/dist/memory/snow-flow-memory-patterns.d.ts +29 -30
  14. package/dist/memory/snow-flow-memory-patterns.js +26 -37
  15. package/dist/snow-flow-system.js +1 -0
  16. package/dist/testing/integration-test-suite.js +1 -0
  17. package/dist/utils/artifact-local-sync.js +0 -17
  18. package/dist/utils/artifact-sync/artifact-registry.js +11 -11
  19. package/dist/utils/smart-field-fetcher.js +9 -11
  20. package/package.json +2 -2
  21. package/dist/agent/interactive.d.ts +0 -11
  22. package/dist/agent/interactive.js +0 -190
  23. package/dist/agent/session.d.ts +0 -12
  24. package/dist/agent/session.js +0 -106
  25. package/dist/cli/auth.d.ts +0 -3
  26. package/dist/cli/auth.js +0 -59
  27. package/dist/cli/session.d.ts +0 -3
  28. package/dist/cli/session.js +0 -46
  29. package/dist/llm/keys.d.ts +0 -5
  30. package/dist/llm/keys.js +0 -29
  31. package/dist/llm/providers.d.ts +0 -11
  32. package/dist/llm/providers.js +0 -77
  33. package/dist/mcp/bridge.d.ts +0 -10
  34. package/dist/mcp/bridge.js +0 -31
  35. package/dist/mcp/shared/mcp-types.d.ts +0 -37
  36. package/dist/mcp/shared/mcp-types.js +0 -7
  37. package/dist/memory/hierarchical-memory-system.d.ts +0 -32
  38. package/dist/memory/hierarchical-memory-system.js +0 -60
  39. package/dist/memory/memory-system.d.ts +0 -25
  40. package/dist/memory/memory-system.js +0 -36
  41. package/dist/session/store.d.ts +0 -47
  42. package/dist/session/store.js +0 -74
  43. package/dist/utils/chunking-manager.d.ts +0 -39
  44. package/dist/utils/chunking-manager.js +0 -143
@@ -112,5 +112,5 @@ exports.ResponseLimiter = ResponseLimiter;
112
112
  // Configurable via environment variable, default to 500KB (reasonable for widgets/flows)
113
113
  ResponseLimiter.MAX_RESPONSE_SIZE = parseInt(process.env.MCP_MAX_RESPONSE_SIZE || '500000'); // 500KB default
114
114
  ResponseLimiter.MAX_ARRAY_ITEMS = parseInt(process.env.MCP_MAX_ARRAY_ITEMS || '500'); // 500 items default
115
- ResponseLimiter.MAX_TOKEN_ESTIMATE = 200000; // Claude's actual 200k context window
115
+ ResponseLimiter.MAX_TOKEN_ESTIMATE = 125000; // ~500KB / 4 chars per token
116
116
  //# sourceMappingURL=response-limiter.js.map
@@ -1,34 +1,33 @@
1
1
  /**
2
- * Snow-Flow Memory Patterns
3
- * Common memory patterns and utilities for Snow-Flow
2
+ * Snow-Flow Memory Patterns - Stub Implementation
3
+ * Minimal implementation to support Queen Memory System
4
4
  */
5
- export interface MemoryPattern {
6
- pattern: string;
7
- namespace: string;
8
- type: string;
5
+ export declare class SnowFlowMemoryOrganizer {
6
+ static getWidgetMemoryStructure(name: string): {
7
+ key: string;
8
+ patterns: string[];
9
+ context: {
10
+ type: string;
11
+ name: string;
12
+ };
13
+ };
14
+ static getFlowMemoryStructure(name: string): {
15
+ key: string;
16
+ patterns: string[];
17
+ context: {
18
+ type: string;
19
+ name: string;
20
+ };
21
+ };
22
+ static getScriptMemoryStructure(name: string, scriptType?: string): {
23
+ key: string;
24
+ patterns: string[];
25
+ context: {
26
+ type: string;
27
+ name: string;
28
+ scriptType: string;
29
+ };
30
+ };
31
+ static generateKey(category: string, type: string, name: string): string;
9
32
  }
10
- export declare const MEMORY_PATTERNS: {
11
- readonly AGENT: "agent/*";
12
- readonly TASK: "task/*";
13
- readonly SESSION: "session/*";
14
- readonly ARTIFACT: "artifact/*";
15
- readonly CONFIG: "config/*";
16
- readonly TEMP: "temp/*";
17
- };
18
- export declare const MEMORY_NAMESPACES: {
19
- readonly QUEEN: "queen";
20
- readonly AGENTS: "agents";
21
- readonly TASKS: "tasks";
22
- readonly SESSIONS: "sessions";
23
- readonly ARTIFACTS: "artifacts";
24
- readonly CONFIG: "config";
25
- readonly TEMP: "temp";
26
- };
27
- export declare function createMemoryKey(namespace: string, type: string, id: string): string;
28
- export declare function parseMemoryKey(key: string): {
29
- namespace: string;
30
- type: string;
31
- id: string;
32
- } | null;
33
- export declare function matchesPattern(key: string, pattern: string): boolean;
34
33
  //# sourceMappingURL=snow-flow-memory-patterns.d.ts.map
@@ -1,46 +1,35 @@
1
1
  "use strict";
2
2
  /**
3
- * Snow-Flow Memory Patterns
4
- * Common memory patterns and utilities for Snow-Flow
3
+ * Snow-Flow Memory Patterns - Stub Implementation
4
+ * Minimal implementation to support Queen Memory System
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.MEMORY_NAMESPACES = exports.MEMORY_PATTERNS = void 0;
8
- exports.createMemoryKey = createMemoryKey;
9
- exports.parseMemoryKey = parseMemoryKey;
10
- exports.matchesPattern = matchesPattern;
11
- exports.MEMORY_PATTERNS = {
12
- AGENT: 'agent/*',
13
- TASK: 'task/*',
14
- SESSION: 'session/*',
15
- ARTIFACT: 'artifact/*',
16
- CONFIG: 'config/*',
17
- TEMP: 'temp/*'
18
- };
19
- exports.MEMORY_NAMESPACES = {
20
- QUEEN: 'queen',
21
- AGENTS: 'agents',
22
- TASKS: 'tasks',
23
- SESSIONS: 'sessions',
24
- ARTIFACTS: 'artifacts',
25
- CONFIG: 'config',
26
- TEMP: 'temp'
27
- };
28
- function createMemoryKey(namespace, type, id) {
29
- return `${namespace}/${type}/${id}`;
30
- }
31
- function parseMemoryKey(key) {
32
- const parts = key.split('/');
33
- if (parts.length >= 3) {
7
+ exports.SnowFlowMemoryOrganizer = void 0;
8
+ class SnowFlowMemoryOrganizer {
9
+ static getWidgetMemoryStructure(name) {
34
10
  return {
35
- namespace: parts[0],
36
- type: parts[1],
37
- id: parts.slice(2).join('/')
11
+ key: this.generateKey('artifacts', 'widget', name),
12
+ patterns: ['template', 'script', 'client_script'],
13
+ context: { type: 'widget', name }
38
14
  };
39
15
  }
40
- return null;
41
- }
42
- function matchesPattern(key, pattern) {
43
- const regex = new RegExp(pattern.replace('*', '.*'));
44
- return regex.test(key);
16
+ static getFlowMemoryStructure(name) {
17
+ return {
18
+ key: this.generateKey('artifacts', 'flow', name),
19
+ patterns: ['actions', 'conditions', 'variables'],
20
+ context: { type: 'flow', name }
21
+ };
22
+ }
23
+ static getScriptMemoryStructure(name, scriptType = 'server') {
24
+ return {
25
+ key: this.generateKey('artifacts', 'script', name),
26
+ patterns: ['functions', 'variables', 'dependencies'],
27
+ context: { type: 'script', name, scriptType }
28
+ };
29
+ }
30
+ static generateKey(category, type, name) {
31
+ return `${category}:${type}:${name}`;
32
+ }
45
33
  }
34
+ exports.SnowFlowMemoryOrganizer = SnowFlowMemoryOrganizer;
46
35
  //# sourceMappingURL=snow-flow-memory-patterns.js.map
@@ -11,6 +11,7 @@ exports.snowFlowSystem = exports.SnowFlowSystem = void 0;
11
11
  const events_1 = require("events");
12
12
  const snow_flow_config_1 = require("./config/snow-flow-config");
13
13
  const servicenow_queen_1 = require("./queen/servicenow-queen");
14
+ const memory_system_1 = require("./memory/memory-system");
14
15
  const mcp_server_manager_1 = require("./utils/mcp-server-manager");
15
16
  const performance_tracker_1 = require("./monitoring/performance-tracker");
16
17
  const system_health_1 = require("./health/system-health");
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.IntegrationTestSuite = void 0;
11
11
  const logger_js_1 = require("../utils/logger.js");
12
12
  const servicenow_client_js_1 = require("../utils/servicenow-client.js");
13
+ const memory_system_js_1 = require("../memory/memory-system.js");
13
14
  class IntegrationTestSuite {
14
15
  constructor() {
15
16
  // Flow-related systems removed in v1.4.0
@@ -47,7 +47,6 @@ const fs = __importStar(require("fs"));
47
47
  const path = __importStar(require("path"));
48
48
  const smart_field_fetcher_js_1 = require("./smart-field-fetcher.js");
49
49
  const mcp_timeout_config_js_1 = require("./mcp-timeout-config.js");
50
- const chunking_manager_js_1 = require("./chunking-manager.js");
51
50
  const artifact_registry_1 = require("./artifact-sync/artifact-registry");
52
51
  class ArtifactLocalSync {
53
52
  constructor(client, customBaseDir) {
@@ -286,22 +285,6 @@ class ArtifactLocalSync {
286
285
  }
287
286
  // Map back to ServiceNow field
288
287
  if (file.field && file.field !== 'documentation' && file.field !== 'metadata') {
289
- // Check if field needs chunking (large server scripts)
290
- if (chunking_manager_js_1.ChunkingManager.needsChunking(processedContent)) {
291
- console.log(` ⚠️ Large field detected: ${file.field} (${processedContent.length} chars)`);
292
- // Attempt chunked update
293
- const chunkResult = await chunking_manager_js_1.ChunkingManager.attemptChunkedUpdate(this.client, config.tableName, sys_id, file.field, processedContent);
294
- if (!chunkResult.success) {
295
- // Add to validation results as a manual instruction
296
- validationResults.push({
297
- valid: false,
298
- errors: [],
299
- warnings: [`Large ${file.field} requires manual update`],
300
- hints: [chunkResult.message]
301
- });
302
- continue; // Skip adding to updates
303
- }
304
- }
305
288
  updates[file.field] = processedContent;
306
289
  console.log(` 📝 Changed: ${file.filename} (${file.field})`);
307
290
  // Validate ES5 if required
@@ -33,7 +33,7 @@ exports.ARTIFACT_REGISTRY = {
33
33
  fileExtension: 'html',
34
34
  description: 'HTML template with Angular bindings',
35
35
  wrapperHeader: '<!-- ServiceNow Widget Template: {name} -->\n<!-- Angular bindings: {{data.x}}, ng-click="method()" -->\n\n',
36
- maxTokens: 200000, // Claude's context window is 200k tokens
36
+ maxTokens: 20000,
37
37
  isRequired: true
38
38
  },
39
39
  {
@@ -43,7 +43,7 @@ exports.ARTIFACT_REGISTRY = {
43
43
  description: 'Server-side script (ES5 ONLY)',
44
44
  wrapperHeader: '/**\n * Server Script for Widget: {name}\n * ES5 ONLY - No arrow functions, const/let, template literals\n * Available: data, input, options, gs, $sp\n */\n\n(function() {\n',
45
45
  wrapperFooter: '\n})();',
46
- maxTokens: 200000, // Claude's context window is 200k tokens
46
+ maxTokens: 20000,
47
47
  isRequired: false,
48
48
  validateES5: true
49
49
  },
@@ -54,7 +54,7 @@ exports.ARTIFACT_REGISTRY = {
54
54
  description: 'Client-side AngularJS controller',
55
55
  wrapperHeader: '/**\n * Client Controller for Widget: {name}\n * AngularJS 1.x\n * Available: c (this), c.data, c.server, $scope\n */\n\nfunction(',
56
56
  wrapperFooter: ')',
57
- maxTokens: 200000, // Claude's context window is 200k tokens
57
+ maxTokens: 20000,
58
58
  isRequired: false
59
59
  },
60
60
  {
@@ -63,7 +63,7 @@ exports.ARTIFACT_REGISTRY = {
63
63
  fileExtension: 'css',
64
64
  description: 'Widget-specific CSS styles',
65
65
  wrapperHeader: '/* Styles for Widget: {name} */\n/* Prefix classes to avoid conflicts */\n\n',
66
- maxTokens: 200000, // Claude's context window is 200k tokens
66
+ maxTokens: 20000,
67
67
  isRequired: false
68
68
  },
69
69
  {
@@ -153,7 +153,7 @@ exports.ARTIFACT_REGISTRY = {
153
153
  localFileName: '{name}.flow',
154
154
  fileExtension: 'json',
155
155
  description: 'Complete flow definition with all steps and actions',
156
- maxTokens: 200000, // Claude's context window is 200k tokens // Flows can be huge
156
+ maxTokens: 50000, // Flows can be huge
157
157
  isRequired: true,
158
158
  preprocessor: (content) => {
159
159
  try {
@@ -243,7 +243,7 @@ exports.ARTIFACT_REGISTRY = {
243
243
  description: 'Business rule script',
244
244
  wrapperHeader: '/**\n * Business Rule: {name}\n * Table: {collection}\n * When: {when}\n * Order: {order}\n * Available: current, previous, gs, g_scratchpad\n */\n\n(function executeRule(current, previous /*null when async*/) {\n',
245
245
  wrapperFooter: '\n})(current, previous);',
246
- maxTokens: 200000, // Claude's context window is 200k tokens
246
+ maxTokens: 20000,
247
247
  isRequired: true,
248
248
  validateES5: true
249
249
  },
@@ -281,7 +281,7 @@ exports.ARTIFACT_REGISTRY = {
281
281
  localFileName: '{name}.client',
282
282
  fileExtension: 'js',
283
283
  description: 'Client-side JavaScript',
284
- maxTokens: 200000, // Claude's context window is 200k tokens
284
+ maxTokens: 20000,
285
285
  isRequired: false
286
286
  },
287
287
  {
@@ -289,7 +289,7 @@ exports.ARTIFACT_REGISTRY = {
289
289
  localFileName: '{name}.server',
290
290
  fileExtension: 'js',
291
291
  description: 'Server-side processing script (ES5)',
292
- maxTokens: 200000, // Claude's context window is 200k tokens
292
+ maxTokens: 20000,
293
293
  isRequired: false,
294
294
  validateES5: true
295
295
  }
@@ -310,7 +310,7 @@ exports.ARTIFACT_REGISTRY = {
310
310
  fileExtension: 'js',
311
311
  description: 'Client-side form script',
312
312
  wrapperHeader: '/**\n * Client Script: {name}\n * Table: {table}\n * Type: {type}\n * Available: g_form, g_user, g_list\n */\n\n',
313
- maxTokens: 200000, // Claude's context window is 200k tokens
313
+ maxTokens: 20000,
314
314
  isRequired: true
315
315
  }
316
316
  ]
@@ -375,7 +375,7 @@ exports.ARTIFACT_REGISTRY = {
375
375
  localFileName: '{name}',
376
376
  fileExtension: 'js',
377
377
  description: 'Transform map script',
378
- maxTokens: 200000, // Claude's context window is 200k tokens
378
+ maxTokens: 20000,
379
379
  isRequired: false,
380
380
  validateES5: true
381
381
  }
@@ -396,7 +396,7 @@ exports.ARTIFACT_REGISTRY = {
396
396
  fileExtension: 'js',
397
397
  description: 'Scheduled job script (ES5)',
398
398
  wrapperHeader: '/**\n * Scheduled Job: {name}\n * Run as: {run_as}\n * Time zone: {time_zone}\n */\n\n',
399
- maxTokens: 200000, // Claude's context window is 200k tokens
399
+ maxTokens: 20000,
400
400
  isRequired: true,
401
401
  validateES5: true
402
402
  }
@@ -22,25 +22,25 @@ const WIDGET_FIELD_GROUPS = [
22
22
  groupName: 'template',
23
23
  fields: ['template'],
24
24
  description: 'HTML template - defines UI structure and Angular bindings (ng-click, {{data.x}})',
25
- maxTokens: 200000 // Claude's full context window
25
+ maxTokens: 20000 // Increased to 20K
26
26
  },
27
27
  {
28
28
  groupName: 'server_script',
29
29
  fields: ['script'], // Note: 'script' is the actual field name, not 'server_script'
30
30
  description: 'Server-side script (ES5 only) - initializes data object and handles input.action requests',
31
- maxTokens: 200000 // Claude's full context window
31
+ maxTokens: 20000 // Increased to 20K
32
32
  },
33
33
  {
34
34
  groupName: 'client_script',
35
35
  fields: ['client_script'],
36
36
  description: 'Client-side AngularJS controller - implements methods called by template ng-click and calls c.server.get()',
37
- maxTokens: 200000 // Claude's full context window
37
+ maxTokens: 20000 // Increased to 20K
38
38
  },
39
39
  {
40
40
  groupName: 'styling',
41
41
  fields: ['css'],
42
42
  description: 'Widget-specific CSS styles - classes used in template',
43
- maxTokens: 200000 // Claude's full context window
43
+ maxTokens: 20000 // Increased to 20K
44
44
  },
45
45
  {
46
46
  groupName: 'configuration',
@@ -130,8 +130,8 @@ class SmartFieldFetcher {
130
130
  description: group.description,
131
131
  fields: group.fields
132
132
  };
133
- // FIX: getRecord returns direct object, not response.result[0]
134
- Object.assign(results, response);
133
+ // Add to flat structure for easy access
134
+ Object.assign(results, response.result[0]);
135
135
  }
136
136
  }
137
137
  catch (error) {
@@ -232,9 +232,8 @@ class SmartFieldFetcher {
232
232
  // Try using getRecord instead of searchRecords with short timeout
233
233
  const directResponse = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.getRecord('sp_widget', sys_id), 5000, // 5 second timeout for direct fetch
234
234
  `Direct widget fetch ${sys_id}`);
235
- if (directResponse) {
236
- // FIX: getRecord returns direct object, not nested structure
237
- const directData = directResponse;
235
+ if (directResponse && directResponse.success && directResponse.data && directResponse.data.result) {
236
+ const directData = directResponse.data.result;
238
237
  // Merge any new data we got
239
238
  Object.assign(results, directData);
240
239
  console.log(`📊 Direct API retrieved:`);
@@ -293,7 +292,6 @@ class SmartFieldFetcher {
293
292
  console.log(` 📄 Fetching field: ${field}`);
294
293
  const response = await this.client.getRecord(table, sys_id);
295
294
  if (response) {
296
- // FIX: getRecord returns direct object
297
295
  result.data[field] = response[field];
298
296
  result._field_status[field] = 'success';
299
297
  }
@@ -505,7 +503,7 @@ function createFetchStrategyHint(table, sys_id) {
505
503
  return `
506
504
  🔍 SMART FETCH STRATEGY for ${table} (${sys_id}):
507
505
 
508
- When the artifact is too large (>200000 tokens), I'll fetch fields in intelligent groups:
506
+ When the artifact is too large (>25000 tokens), I'll fetch fields in intelligent groups:
509
507
  1. First fetch metadata (name, title, sys_id)
510
508
  2. Then fetch each content field separately (template, script, client_script, css)
511
509
  3. Maintain context: These fields work together!
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "4.1.0",
4
- "description": "ENTERPRISE SCALE - v4.1.0 removes ALL artificial limits! Now supports widgets with 5MB+ server scripts, 200k token fields, and 100k record queries. Built for real enterprise ServiceNow environments.",
3
+ "version": "4.1.2",
4
+ "description": "ENTERPRISE SCALE - v4.1.0 removes ALL artificial limits! Built on stable v3.6.25 with enterprise-grade support for massive widgets (5MB+ scripts), 200k token fields, and 100k record queries.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {
@@ -1,11 +0,0 @@
1
- import type { SnowFlowConfig } from '../config/llm-config-loader';
2
- import type { ProviderOptions } from '../llm/providers';
3
- export interface InteractiveOptions extends ProviderOptions {
4
- system?: string;
5
- mcp: SnowFlowConfig['mcp'];
6
- maxSteps?: number;
7
- showReasoning?: boolean;
8
- resumeId?: string;
9
- }
10
- export declare function runInteractive(opts: InteractiveOptions): Promise<void>;
11
- //# sourceMappingURL=interactive.d.ts.map
@@ -1,190 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.runInteractive = runInteractive;
7
- const bridge_1 = require("../mcp/bridge");
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const boxen_1 = __importDefault(require("boxen"));
10
- const node_readline_1 = __importDefault(require("node:readline"));
11
- const store_js_1 = require("../session/store.js");
12
- const ora_1 = __importDefault(require("ora"));
13
- async function runInteractive(opts) {
14
- const { provider, model, baseURL, apiKeyEnv, system, mcp, maxSteps = 40, showReasoning = true, resumeId } = opts;
15
- // Resolve model
16
- // eslint-disable-next-line @typescript-eslint/no-var-requires
17
- const prov = require('../llm/providers.js');
18
- const llm = prov.getModel({ provider, model, baseURL, apiKeyEnv });
19
- const sessionId = resumeId || (0, store_js_1.createSessionId)();
20
- (0, store_js_1.startSession)({
21
- id: sessionId,
22
- startedAt: new Date().toISOString(),
23
- objective: '(interactive)',
24
- provider: { id: String(provider), model: String(model), baseURL },
25
- mcp: { cmd: mcp.cmd, args: mcp.args },
26
- });
27
- process.stdout.write(chalk_1.default.bold(`\nSnow-Flow Interactive (${provider}:${model})`) + "\n");
28
- process.stdout.write(chalk_1.default.gray('Tips: ESC ESC = vorige assistant-antwoord | /quit om te stoppen') + "\n\n");
29
- // Load tools once with spinner
30
- const spinner = (0, ora_1.default)('MCP-tools laden...').start();
31
- const { tools, close } = await (0, bridge_1.loadMCPTools)(mcp).finally(() => spinner.stop());
32
- const messages = [];
33
- if (system)
34
- messages.push({ role: 'system', content: system });
35
- // Preload previous messages if resuming
36
- if (resumeId) {
37
- try {
38
- const { readSession } = require('../session/store.js');
39
- const rec = readSession(resumeId);
40
- if (rec?.messages?.length) {
41
- const recent = rec.messages.filter((m) => m.role === 'user' || m.role === 'assistant').slice(-20);
42
- for (const m of recent)
43
- messages.push({ role: m.role, content: m.content });
44
- }
45
- }
46
- catch { }
47
- }
48
- // Key handling for ESC ESC
49
- node_readline_1.default.emitKeypressEvents(process.stdin);
50
- if (process.stdin.isTTY)
51
- process.stdin.setRawMode(true);
52
- let lastEsc = 0;
53
- let lastAssistant = null;
54
- let showTools = true;
55
- const onKeypress = (_str, key) => {
56
- if (!key)
57
- return;
58
- if (key.name === 'escape') {
59
- const now = Date.now();
60
- if (now - lastEsc < 500) {
61
- // double ESC
62
- if (lastAssistant) {
63
- const box = (0, boxen_1.default)(lastAssistant.slice(0, 1200) + (lastAssistant.length > 1200 ? '…' : ''), { padding: 1, borderColor: 'yellow', title: 'Vorige assistant', titleAlignment: 'center' });
64
- process.stdout.write('\n' + box + '\n');
65
- }
66
- else {
67
- process.stdout.write(chalk_1.default.gray('\nGeen vorige assistant-respons beschikbaar.') + '\n');
68
- }
69
- }
70
- lastEsc = now;
71
- }
72
- if (key.name === 't') {
73
- showTools = !showTools;
74
- process.stdout.write('\n' + (showTools ? chalk_1.default.gray('Tool events: ON') : chalk_1.default.gray('Tool events: OFF')) + '\n');
75
- }
76
- if (key.name === 'h') {
77
- const last = messages.slice(-6);
78
- const text = last.map(m => `${m.role}> ${m.content}`).join('\n');
79
- const panel = (0, boxen_1.default)(text, { padding: 1, borderColor: 'blue', title: 'History (tail)', titleAlignment: 'center' });
80
- process.stdout.write('\n' + panel + '\n');
81
- }
82
- if (key.name === 's') {
83
- const fs = require('fs');
84
- const out = (lastAssistant || '').toString();
85
- const outPath = `${process.env.HOME || ''}/.snow-flow/sessions/${sessionId}.txt`;
86
- try {
87
- fs.writeFileSync(outPath, out, 'utf8');
88
- }
89
- catch { }
90
- process.stdout.write(chalk_1.default.gray(`Saved assistant output to ${outPath}`) + '\n');
91
- }
92
- };
93
- process.stdin.on('keypress', onKeypress);
94
- // eslint-disable-next-line @typescript-eslint/no-var-requires
95
- const { streamText } = require('ai');
96
- const rl = node_readline_1.default.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
97
- const ask = (q) => new Promise(resolve => rl.question(q, resolve));
98
- try {
99
- const onSignal = async () => {
100
- try {
101
- await close();
102
- }
103
- catch { }
104
- (0, store_js_1.endSession)(sessionId);
105
- process.stdout.write('\n' + chalk_1.default.gray('Session ended.') + '\n');
106
- process.exit(0);
107
- };
108
- process.on('SIGINT', onSignal);
109
- process.on('SIGTERM', onSignal);
110
- // loop
111
- while (true) {
112
- const input = await ask(chalk_1.default.cyan('You: '));
113
- if (!input)
114
- continue;
115
- if (input.trim() === '/quit')
116
- break;
117
- const long = input.length > 1200;
118
- if (long) {
119
- const preview = input.slice(0, 1200) + '…';
120
- const box = (0, boxen_1.default)(preview, { padding: 1, borderColor: 'green', title: 'Preview (truncated)', titleAlignment: 'center' });
121
- process.stdout.write('\n' + box + '\n');
122
- const confirm = await ask(chalk_1.default.gray('Doorgaan met verzenden? [y/N] '));
123
- if (!/^y(es)?$/i.test(confirm.trim()))
124
- continue;
125
- }
126
- messages.push({ role: 'user', content: input });
127
- (0, store_js_1.appendMessage)(sessionId, { role: 'user', content: input, timestamp: new Date().toISOString() });
128
- const result = await streamText({
129
- model: llm,
130
- system,
131
- messages,
132
- tools,
133
- maxSteps,
134
- });
135
- let buffer = '';
136
- let inReasoning = false;
137
- const write = (s) => {
138
- buffer += s;
139
- const out = inReasoning && showReasoning ? chalk_1.default.yellow.dim(s) : s;
140
- process.stdout.write(out);
141
- };
142
- if (result.toolCallStream && typeof result.toolCallStream[Symbol.asyncIterator] === 'function') {
143
- (async () => {
144
- for await (const ev of result.toolCallStream) {
145
- const name = ev?.toolName || ev?.name || 'tool';
146
- const args = ev?.args ? JSON.stringify(ev.args).slice(0, 180) : '';
147
- if (showTools)
148
- process.stdout.write('\n' + chalk_1.default.cyan(`🔧 Tool → ${name} ${args}`) + '\n');
149
- (0, store_js_1.appendToolEvent)(sessionId, { name, argsPreview: args });
150
- }
151
- })().catch(() => { });
152
- }
153
- if (result.toolResultStream && typeof result.toolResultStream[Symbol.asyncIterator] === 'function') {
154
- (async () => {
155
- for await (const ev of result.toolResultStream) {
156
- const name = ev?.toolName || ev?.name || 'tool';
157
- const out = ev?.result ? JSON.stringify(ev.result).slice(0, 180) : '';
158
- if (showTools)
159
- process.stdout.write(chalk_1.default.magenta(`📦 Result ← ${name} ${out}`) + '\n');
160
- (0, store_js_1.appendToolEvent)(sessionId, { name, resultPreview: out });
161
- }
162
- })().catch(() => { });
163
- }
164
- process.stdout.write(chalk_1.default.green('\nAssistant: '));
165
- for await (const chunk of result.textStream) {
166
- const s = String(chunk);
167
- if (showReasoning) {
168
- if (s.includes('```reasoning') || s.toLowerCase().includes('<thinking>') || /\[\s*reasoning\s*\]/i.test(s))
169
- inReasoning = true;
170
- if (s.includes('```') || s.toLowerCase().includes('</thinking>'))
171
- inReasoning = false;
172
- }
173
- write(s);
174
- }
175
- process.stdout.write('\n');
176
- lastAssistant = buffer;
177
- messages.push({ role: 'assistant', content: buffer });
178
- (0, store_js_1.appendMessage)(sessionId, { role: 'assistant', content: buffer, timestamp: new Date().toISOString() });
179
- }
180
- }
181
- finally {
182
- rl.close();
183
- process.stdin.off('keypress', onKeypress);
184
- if (process.stdin.isTTY)
185
- process.stdin.setRawMode(false);
186
- await close();
187
- (0, store_js_1.endSession)(sessionId);
188
- }
189
- }
190
- //# sourceMappingURL=interactive.js.map
@@ -1,12 +0,0 @@
1
- import type { SnowFlowConfig } from '../config/llm-config-loader';
2
- import type { ProviderOptions } from '../llm/providers';
3
- export interface AgentRunOptions extends ProviderOptions {
4
- system?: string;
5
- user: string;
6
- mcp: SnowFlowConfig['mcp'];
7
- maxSteps?: number;
8
- showReasoning?: boolean;
9
- saveOutputPath?: string;
10
- }
11
- export declare function runAgent(opts: AgentRunOptions): Promise<void>;
12
- //# sourceMappingURL=session.d.ts.map