wave-agent-sdk 0.0.7 → 0.0.8

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 (172) hide show
  1. package/dist/agent.d.ts +32 -20
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +202 -20
  4. package/dist/constants/events.d.ts +28 -0
  5. package/dist/constants/events.d.ts.map +1 -0
  6. package/dist/constants/events.js +27 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/managers/aiManager.d.ts +34 -1
  11. package/dist/managers/aiManager.d.ts.map +1 -1
  12. package/dist/managers/aiManager.js +243 -128
  13. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  14. package/dist/managers/backgroundBashManager.js +7 -6
  15. package/dist/managers/hookManager.d.ts +9 -4
  16. package/dist/managers/hookManager.d.ts.map +1 -1
  17. package/dist/managers/hookManager.js +62 -30
  18. package/dist/managers/liveConfigManager.d.ts +58 -0
  19. package/dist/managers/liveConfigManager.d.ts.map +1 -0
  20. package/dist/managers/liveConfigManager.js +160 -0
  21. package/dist/managers/messageManager.d.ts +38 -13
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +163 -30
  24. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  25. package/dist/managers/slashCommandManager.js +4 -1
  26. package/dist/managers/subagentManager.d.ts +51 -0
  27. package/dist/managers/subagentManager.d.ts.map +1 -1
  28. package/dist/managers/subagentManager.js +189 -18
  29. package/dist/services/aiService.d.ts +13 -5
  30. package/dist/services/aiService.d.ts.map +1 -1
  31. package/dist/services/aiService.js +350 -74
  32. package/dist/services/configurationWatcher.d.ts +120 -0
  33. package/dist/services/configurationWatcher.d.ts.map +1 -0
  34. package/dist/services/configurationWatcher.js +439 -0
  35. package/dist/services/fileWatcher.d.ts +69 -0
  36. package/dist/services/fileWatcher.d.ts.map +1 -0
  37. package/dist/services/fileWatcher.js +213 -0
  38. package/dist/services/hook.d.ts +91 -9
  39. package/dist/services/hook.d.ts.map +1 -1
  40. package/dist/services/hook.js +393 -43
  41. package/dist/services/jsonlHandler.d.ts +62 -0
  42. package/dist/services/jsonlHandler.d.ts.map +1 -0
  43. package/dist/services/jsonlHandler.js +257 -0
  44. package/dist/services/memory.d.ts +9 -0
  45. package/dist/services/memory.d.ts.map +1 -1
  46. package/dist/services/memory.js +81 -12
  47. package/dist/services/memoryStore.d.ts +81 -0
  48. package/dist/services/memoryStore.d.ts.map +1 -0
  49. package/dist/services/memoryStore.js +200 -0
  50. package/dist/services/session.d.ts +64 -49
  51. package/dist/services/session.d.ts.map +1 -1
  52. package/dist/services/session.js +310 -132
  53. package/dist/tools/bashTool.d.ts.map +1 -1
  54. package/dist/tools/bashTool.js +5 -4
  55. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  56. package/dist/tools/deleteFileTool.js +2 -1
  57. package/dist/tools/editTool.d.ts.map +1 -1
  58. package/dist/tools/editTool.js +3 -2
  59. package/dist/tools/multiEditTool.d.ts.map +1 -1
  60. package/dist/tools/multiEditTool.js +4 -3
  61. package/dist/tools/readTool.d.ts.map +1 -1
  62. package/dist/tools/readTool.js +2 -1
  63. package/dist/tools/writeTool.d.ts.map +1 -1
  64. package/dist/tools/writeTool.js +5 -6
  65. package/dist/types/commands.d.ts +4 -0
  66. package/dist/types/commands.d.ts.map +1 -1
  67. package/dist/types/core.d.ts +35 -0
  68. package/dist/types/core.d.ts.map +1 -1
  69. package/dist/types/environment.d.ts +42 -0
  70. package/dist/types/environment.d.ts.map +1 -0
  71. package/dist/types/environment.js +21 -0
  72. package/dist/types/hooks.d.ts +8 -2
  73. package/dist/types/hooks.d.ts.map +1 -1
  74. package/dist/types/hooks.js +8 -2
  75. package/dist/types/index.d.ts +2 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/dist/types/index.js +2 -0
  78. package/dist/types/memoryStore.d.ts +82 -0
  79. package/dist/types/memoryStore.d.ts.map +1 -0
  80. package/dist/types/memoryStore.js +7 -0
  81. package/dist/types/messaging.d.ts +14 -2
  82. package/dist/types/messaging.d.ts.map +1 -1
  83. package/dist/types/session.d.ts +20 -0
  84. package/dist/types/session.d.ts.map +1 -0
  85. package/dist/types/session.js +7 -0
  86. package/dist/utils/bashHistory.d.ts.map +1 -1
  87. package/dist/utils/bashHistory.js +27 -26
  88. package/dist/utils/cacheControlUtils.d.ts +121 -0
  89. package/dist/utils/cacheControlUtils.d.ts.map +1 -0
  90. package/dist/utils/cacheControlUtils.js +367 -0
  91. package/dist/utils/commandPathResolver.d.ts +52 -0
  92. package/dist/utils/commandPathResolver.d.ts.map +1 -0
  93. package/dist/utils/commandPathResolver.js +145 -0
  94. package/dist/utils/configPaths.d.ts +85 -0
  95. package/dist/utils/configPaths.d.ts.map +1 -0
  96. package/dist/utils/configPaths.js +121 -0
  97. package/dist/utils/configResolver.d.ts +37 -10
  98. package/dist/utils/configResolver.d.ts.map +1 -1
  99. package/dist/utils/configResolver.js +127 -23
  100. package/dist/utils/constants.d.ts +1 -1
  101. package/dist/utils/constants.js +1 -1
  102. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  103. package/dist/utils/convertMessagesForAPI.js +7 -5
  104. package/dist/utils/customCommands.d.ts.map +1 -1
  105. package/dist/utils/customCommands.js +66 -21
  106. package/dist/utils/fileUtils.d.ts +15 -0
  107. package/dist/utils/fileUtils.d.ts.map +1 -0
  108. package/dist/utils/fileUtils.js +61 -0
  109. package/dist/utils/globalLogger.d.ts +102 -0
  110. package/dist/utils/globalLogger.d.ts.map +1 -0
  111. package/dist/utils/globalLogger.js +136 -0
  112. package/dist/utils/mcpUtils.d.ts.map +1 -1
  113. package/dist/utils/mcpUtils.js +25 -3
  114. package/dist/utils/messageOperations.d.ts +20 -8
  115. package/dist/utils/messageOperations.d.ts.map +1 -1
  116. package/dist/utils/messageOperations.js +25 -16
  117. package/dist/utils/pathEncoder.d.ts +104 -0
  118. package/dist/utils/pathEncoder.d.ts.map +1 -0
  119. package/dist/utils/pathEncoder.js +272 -0
  120. package/dist/utils/subagentParser.d.ts.map +1 -1
  121. package/dist/utils/subagentParser.js +2 -1
  122. package/dist/utils/tokenCalculation.d.ts +26 -0
  123. package/dist/utils/tokenCalculation.d.ts.map +1 -0
  124. package/dist/utils/tokenCalculation.js +36 -0
  125. package/package.json +6 -3
  126. package/src/agent.ts +298 -34
  127. package/src/constants/events.ts +38 -0
  128. package/src/index.ts +2 -0
  129. package/src/managers/aiManager.ts +323 -170
  130. package/src/managers/backgroundBashManager.ts +7 -6
  131. package/src/managers/hookManager.ts +83 -40
  132. package/src/managers/liveConfigManager.ts +248 -0
  133. package/src/managers/messageManager.ts +230 -63
  134. package/src/managers/slashCommandManager.ts +4 -1
  135. package/src/managers/subagentManager.ts +283 -21
  136. package/src/services/aiService.ts +474 -83
  137. package/src/services/configurationWatcher.ts +622 -0
  138. package/src/services/fileWatcher.ts +301 -0
  139. package/src/services/hook.ts +538 -47
  140. package/src/services/jsonlHandler.ts +319 -0
  141. package/src/services/memory.ts +92 -12
  142. package/src/services/memoryStore.ts +279 -0
  143. package/src/services/session.ts +381 -157
  144. package/src/tools/bashTool.ts +5 -4
  145. package/src/tools/deleteFileTool.ts +2 -1
  146. package/src/tools/editTool.ts +3 -2
  147. package/src/tools/multiEditTool.ts +4 -3
  148. package/src/tools/readTool.ts +2 -1
  149. package/src/tools/writeTool.ts +7 -6
  150. package/src/types/commands.ts +6 -0
  151. package/src/types/core.ts +44 -0
  152. package/src/types/environment.ts +60 -0
  153. package/src/types/hooks.ts +21 -8
  154. package/src/types/index.ts +2 -0
  155. package/src/types/memoryStore.ts +94 -0
  156. package/src/types/messaging.ts +14 -2
  157. package/src/types/session.ts +25 -0
  158. package/src/utils/bashHistory.ts +27 -27
  159. package/src/utils/cacheControlUtils.ts +540 -0
  160. package/src/utils/commandPathResolver.ts +189 -0
  161. package/src/utils/configPaths.ts +163 -0
  162. package/src/utils/configResolver.ts +182 -22
  163. package/src/utils/constants.ts +1 -1
  164. package/src/utils/convertMessagesForAPI.ts +7 -5
  165. package/src/utils/customCommands.ts +90 -22
  166. package/src/utils/fileUtils.ts +65 -0
  167. package/src/utils/globalLogger.ts +145 -0
  168. package/src/utils/mcpUtils.ts +34 -3
  169. package/src/utils/messageOperations.ts +42 -20
  170. package/src/utils/pathEncoder.ts +379 -0
  171. package/src/utils/subagentParser.ts +2 -1
  172. package/src/utils/tokenCalculation.ts +43 -0
@@ -0,0 +1,145 @@
1
+ import { relative, basename } from "path";
2
+ /**
3
+ * Generate command ID from file path
4
+ * @param filePath - Absolute path to markdown file
5
+ * @param rootDir - Root commands directory path
6
+ * @returns Command identifier string (e.g., "openspec:apply")
7
+ * @throws Error on invalid path structure
8
+ */
9
+ export function generateCommandId(filePath, rootDir) {
10
+ // Handle null/undefined inputs
11
+ if (filePath == null || rootDir == null) {
12
+ throw new Error("File path and root directory must be provided");
13
+ }
14
+ // Handle empty root directory (for root level commands)
15
+ const relativePath = rootDir === "" ? filePath : relative(rootDir, filePath);
16
+ // Handle edge cases
17
+ if (!relativePath || relativePath === ".") {
18
+ throw new Error("Command filename cannot be empty");
19
+ }
20
+ const segments = relativePath.split("/").filter((segment) => segment !== "");
21
+ // Remove .md extension from the last segment
22
+ const lastSegment = segments[segments.length - 1];
23
+ if (!lastSegment.endsWith(".md")) {
24
+ throw new Error(`Command files must have .md extension`);
25
+ }
26
+ segments[segments.length - 1] = basename(lastSegment, ".md");
27
+ // Handle empty filename after removing extension
28
+ if (segments[segments.length - 1] === "") {
29
+ throw new Error("Command filename cannot be empty");
30
+ }
31
+ // Validate depth (max 1 level of nesting)
32
+ if (segments.length > 2) {
33
+ throw new Error(`Command nesting too deep: ${relativePath}. Maximum depth is 1 level.`);
34
+ }
35
+ // Validate segments
36
+ for (const segment of segments) {
37
+ if (!validateSegment(segment)) {
38
+ throw new Error(`Invalid command path segment: "${segment}" in ${relativePath}. Must match pattern /^[a-zA-Z][a-zA-Z0-9_.-]*$/`);
39
+ }
40
+ }
41
+ // Generate command ID
42
+ if (segments.length === 1) {
43
+ return segments[0]; // Flat command
44
+ }
45
+ else {
46
+ return segments.join(":"); // Nested command with colon syntax
47
+ }
48
+ }
49
+ /**
50
+ * Parse command ID into components
51
+ * @param commandId - Command identifier (e.g., "openspec:apply")
52
+ * @returns Object with namespace and command name
53
+ * @throws Error on malformed command ID
54
+ */
55
+ export function parseCommandId(commandId) {
56
+ // Handle null/undefined inputs
57
+ if (commandId == null) {
58
+ throw new Error("Command ID cannot be null or undefined");
59
+ }
60
+ if (commandId === "") {
61
+ throw new Error("Command ID cannot be empty");
62
+ }
63
+ if (!validateCommandId(commandId)) {
64
+ throw new Error(`Invalid command ID format: "${commandId}". Must match pattern /^[a-zA-Z0-9_-]+(?::[a-zA-Z0-9_-]+)?$/`);
65
+ }
66
+ const parts = commandId.split(":");
67
+ if (parts.length === 1) {
68
+ // Flat command
69
+ return {
70
+ namespace: undefined,
71
+ commandName: parts[0],
72
+ isNested: false,
73
+ depth: 0,
74
+ segments: [parts[0]],
75
+ };
76
+ }
77
+ else if (parts.length === 2) {
78
+ // Nested command
79
+ return {
80
+ namespace: parts[0],
81
+ commandName: parts[1],
82
+ isNested: true,
83
+ depth: 1,
84
+ segments: [parts[0], parts[1]],
85
+ };
86
+ }
87
+ else {
88
+ throw new Error(`Invalid command ID format: "${commandId}". Too many colon separators.`);
89
+ }
90
+ }
91
+ /**
92
+ * Validate command ID format
93
+ * @param commandId - Command identifier to validate
94
+ * @returns Boolean indicating validity
95
+ */
96
+ export function validateCommandId(commandId) {
97
+ // Handle null/undefined inputs
98
+ if (commandId == null) {
99
+ return false;
100
+ }
101
+ // Command ID can have multiple colons (though generateCommandId enforces max 1 level)
102
+ // This validates the format but doesn't enforce depth limits
103
+ const pattern = /^[a-zA-Z][a-zA-Z0-9_-]*(?::[a-zA-Z][a-zA-Z0-9_-]*)*$/;
104
+ return pattern.test(commandId);
105
+ }
106
+ /**
107
+ * Validate individual path segment
108
+ * @param segment - Path segment to validate
109
+ * @returns Boolean indicating validity
110
+ */
111
+ function validateSegment(segment) {
112
+ // Segments should start with letters and can contain letters, numbers, dashes, underscores, dots
113
+ const pattern = /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
114
+ return pattern.test(segment);
115
+ }
116
+ /**
117
+ * Convert file path to command segments array
118
+ * @param filePath - Absolute path to markdown file
119
+ * @param rootDir - Root commands directory path
120
+ * @returns Array of path segments
121
+ */
122
+ export function getCommandSegments(filePath, rootDir) {
123
+ const relativePath = relative(rootDir, filePath);
124
+ const segments = relativePath.split("/").filter((segment) => segment !== "");
125
+ // Remove .md extension from the last segment
126
+ const lastSegment = segments[segments.length - 1];
127
+ segments[segments.length - 1] = basename(lastSegment, ".md");
128
+ return segments;
129
+ }
130
+ /**
131
+ * Get namespace from command segments
132
+ * @param segments - Command path segments
133
+ * @returns Namespace string or undefined for flat commands
134
+ */
135
+ export function getNamespace(segments) {
136
+ return segments.length > 1 ? segments[0] : undefined;
137
+ }
138
+ /**
139
+ * Get command depth from segments
140
+ * @param segments - Command path segments
141
+ * @returns Depth number (0 for root, 1 for nested)
142
+ */
143
+ export function getDepth(segments) {
144
+ return Math.max(0, segments.length - 1);
145
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Configuration Path Utilities
3
+ *
4
+ * Centralized utilities for resolving Wave configuration file paths.
5
+ * Supports both regular settings.json and settings.local.json with proper priority.
6
+ *
7
+ * Priority system:
8
+ * - User configs: ~/.wave/settings.local.json > ~/.wave/settings.json
9
+ * - Project configs: {workdir}/.wave/settings.local.json > {workdir}/.wave/settings.json
10
+ * - Project configs override user configs (existing behavior)
11
+ */
12
+ /**
13
+ * Get the user-specific configuration file path (legacy function)
14
+ * @deprecated Use getUserConfigPaths() for better priority support
15
+ */
16
+ export declare function getUserConfigPath(): string;
17
+ /**
18
+ * Get the project-specific configuration file path (legacy function)
19
+ * @deprecated Use getProjectConfigPaths() for better priority support
20
+ */
21
+ export declare function getProjectConfigPath(workdir: string): string;
22
+ /**
23
+ * Get the user-specific configuration file paths in priority order
24
+ * Returns array with .local.json first, then .json
25
+ */
26
+ export declare function getUserConfigPaths(): string[];
27
+ /**
28
+ * Get the project-specific configuration file paths in priority order
29
+ * Returns array with .local.json first, then .json
30
+ */
31
+ export declare function getProjectConfigPaths(workdir: string): string[];
32
+ /**
33
+ * Get all configuration file paths (user and project) in priority order
34
+ * Useful for comprehensive configuration detection
35
+ */
36
+ export declare function getAllConfigPaths(workdir: string): {
37
+ userPaths: string[];
38
+ projectPaths: string[];
39
+ allPaths: string[];
40
+ };
41
+ /**
42
+ * Get existing configuration file paths
43
+ * Returns only the paths that actually exist on the filesystem
44
+ */
45
+ export declare function getExistingConfigPaths(workdir: string): {
46
+ userPaths: string[];
47
+ projectPaths: string[];
48
+ existingPaths: string[];
49
+ };
50
+ /**
51
+ * Get the first existing configuration file path with the specified priority
52
+ * @param paths Array of paths in priority order
53
+ * @returns The first path that exists, or undefined if none exist
54
+ */
55
+ export declare function getFirstExistingPath(paths: string[]): string | undefined;
56
+ /**
57
+ * Get effective configuration paths (the ones that would actually be used)
58
+ * Returns the highest priority existing path for each category
59
+ */
60
+ export declare function getEffectiveConfigPaths(workdir: string): {
61
+ userPath?: string;
62
+ projectPath?: string;
63
+ effectivePath?: string;
64
+ };
65
+ /**
66
+ * Check if any configuration files exist
67
+ */
68
+ export declare function hasAnyConfig(workdir: string): boolean;
69
+ /**
70
+ * Get configuration information for debugging and monitoring
71
+ */
72
+ export declare function getConfigurationInfo(workdir: string): {
73
+ hasUser: boolean;
74
+ hasProject: boolean;
75
+ paths: string[];
76
+ userPaths: string[];
77
+ projectPaths: string[];
78
+ existingPaths: string[];
79
+ effectivePaths: {
80
+ userPath?: string;
81
+ projectPath?: string;
82
+ effectivePath?: string;
83
+ };
84
+ };
85
+ //# sourceMappingURL=configPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configPaths.d.ts","sourceRoot":"","sources":["../../src/utils/configPaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAG7C;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAClD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CASA;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG;IACvD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAYA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAExE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAeA;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,CAcA"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Configuration Path Utilities
3
+ *
4
+ * Centralized utilities for resolving Wave configuration file paths.
5
+ * Supports both regular settings.json and settings.local.json with proper priority.
6
+ *
7
+ * Priority system:
8
+ * - User configs: ~/.wave/settings.local.json > ~/.wave/settings.json
9
+ * - Project configs: {workdir}/.wave/settings.local.json > {workdir}/.wave/settings.json
10
+ * - Project configs override user configs (existing behavior)
11
+ */
12
+ import { join } from "path";
13
+ import { homedir } from "os";
14
+ import { existsSync } from "fs";
15
+ /**
16
+ * Get the user-specific configuration file path (legacy function)
17
+ * @deprecated Use getUserConfigPaths() for better priority support
18
+ */
19
+ export function getUserConfigPath() {
20
+ return join(homedir(), ".wave", "settings.json");
21
+ }
22
+ /**
23
+ * Get the project-specific configuration file path (legacy function)
24
+ * @deprecated Use getProjectConfigPaths() for better priority support
25
+ */
26
+ export function getProjectConfigPath(workdir) {
27
+ return join(workdir, ".wave", "settings.json");
28
+ }
29
+ /**
30
+ * Get the user-specific configuration file paths in priority order
31
+ * Returns array with .local.json first, then .json
32
+ */
33
+ export function getUserConfigPaths() {
34
+ const baseDir = join(homedir(), ".wave");
35
+ return [join(baseDir, "settings.local.json"), join(baseDir, "settings.json")];
36
+ }
37
+ /**
38
+ * Get the project-specific configuration file paths in priority order
39
+ * Returns array with .local.json first, then .json
40
+ */
41
+ export function getProjectConfigPaths(workdir) {
42
+ const baseDir = join(workdir, ".wave");
43
+ return [join(baseDir, "settings.local.json"), join(baseDir, "settings.json")];
44
+ }
45
+ /**
46
+ * Get all configuration file paths (user and project) in priority order
47
+ * Useful for comprehensive configuration detection
48
+ */
49
+ export function getAllConfigPaths(workdir) {
50
+ const userPaths = getUserConfigPaths();
51
+ const projectPaths = getProjectConfigPaths(workdir);
52
+ return {
53
+ userPaths,
54
+ projectPaths,
55
+ allPaths: [...userPaths, ...projectPaths],
56
+ };
57
+ }
58
+ /**
59
+ * Get existing configuration file paths
60
+ * Returns only the paths that actually exist on the filesystem
61
+ */
62
+ export function getExistingConfigPaths(workdir) {
63
+ const allPaths = getAllConfigPaths(workdir);
64
+ const existingUserPaths = allPaths.userPaths.filter(existsSync);
65
+ const existingProjectPaths = allPaths.projectPaths.filter(existsSync);
66
+ const allExistingPaths = allPaths.allPaths.filter(existsSync);
67
+ return {
68
+ userPaths: existingUserPaths,
69
+ projectPaths: existingProjectPaths,
70
+ existingPaths: allExistingPaths,
71
+ };
72
+ }
73
+ /**
74
+ * Get the first existing configuration file path with the specified priority
75
+ * @param paths Array of paths in priority order
76
+ * @returns The first path that exists, or undefined if none exist
77
+ */
78
+ export function getFirstExistingPath(paths) {
79
+ return paths.find((path) => existsSync(path));
80
+ }
81
+ /**
82
+ * Get effective configuration paths (the ones that would actually be used)
83
+ * Returns the highest priority existing path for each category
84
+ */
85
+ export function getEffectiveConfigPaths(workdir) {
86
+ const userPaths = getUserConfigPaths();
87
+ const projectPaths = getProjectConfigPaths(workdir);
88
+ const userPath = getFirstExistingPath(userPaths);
89
+ const projectPath = getFirstExistingPath(projectPaths);
90
+ // Project path takes precedence over user path if both exist
91
+ const effectivePath = projectPath || userPath;
92
+ return {
93
+ userPath,
94
+ projectPath,
95
+ effectivePath,
96
+ };
97
+ }
98
+ /**
99
+ * Check if any configuration files exist
100
+ */
101
+ export function hasAnyConfig(workdir) {
102
+ const { existingPaths } = getExistingConfigPaths(workdir);
103
+ return existingPaths.length > 0;
104
+ }
105
+ /**
106
+ * Get configuration information for debugging and monitoring
107
+ */
108
+ export function getConfigurationInfo(workdir) {
109
+ const allPaths = getAllConfigPaths(workdir);
110
+ const existingPaths = getExistingConfigPaths(workdir);
111
+ const effectivePaths = getEffectiveConfigPaths(workdir);
112
+ return {
113
+ hasUser: existingPaths.userPaths.length > 0,
114
+ hasProject: existingPaths.projectPaths.length > 0,
115
+ paths: allPaths.allPaths,
116
+ userPaths: allPaths.userPaths,
117
+ projectPaths: allPaths.projectPaths,
118
+ existingPaths: existingPaths.existingPaths,
119
+ effectivePaths,
120
+ };
121
+ }
@@ -1,38 +1,65 @@
1
1
  /**
2
2
  * Configuration resolver utilities for Agent Constructor Configuration
3
3
  * Resolves configuration from constructor arguments with environment fallbacks
4
+ * Supports live configuration updates and cache invalidation
4
5
  */
5
6
  import { GatewayConfig, ModelConfig } from "../types/index.js";
6
7
  export declare class ConfigResolver {
7
8
  /**
8
- * Resolves gateway configuration from constructor args and environment
9
+ * Resolves gateway configuration from constructor args and environment with live config support
9
10
  * @param apiKey - API key from constructor (optional)
10
11
  * @param baseURL - Base URL from constructor (optional)
12
+ * @param workdir - Working directory for loading live configuration (optional)
11
13
  * @returns Resolved gateway configuration
12
14
  * @throws ConfigurationError if required configuration is missing after fallbacks
13
15
  */
14
- static resolveGatewayConfig(apiKey?: string, baseURL?: string): GatewayConfig;
16
+ static resolveGatewayConfig(apiKey?: string, baseURL?: string, workdir?: string): GatewayConfig;
15
17
  /**
16
- * Resolves model configuration with fallbacks
18
+ * Resolves model configuration with fallbacks and live config support
17
19
  * @param agentModel - Agent model from constructor (optional)
18
20
  * @param fastModel - Fast model from constructor (optional)
21
+ * @param workdir - Working directory for loading live configuration (optional)
19
22
  * @returns Resolved model configuration with defaults
20
23
  */
21
- static resolveModelConfig(agentModel?: string, fastModel?: string): ModelConfig;
24
+ static resolveModelConfig(agentModel?: string, fastModel?: string, workdir?: string): ModelConfig;
22
25
  /**
23
- * Resolves token limit with fallbacks
26
+ * Resolves token limit with fallbacks and live config support
24
27
  * @param constructorLimit - Token limit from constructor (optional)
28
+ * @param workdir - Working directory for loading live configuration (optional)
25
29
  * @returns Resolved token limit
26
30
  */
27
- static resolveTokenLimit(constructorLimit?: number): number;
31
+ static resolveTokenLimit(constructorLimit?: number, workdir?: string): number;
32
+ /**
33
+ * Invalidate configuration cache to force reload from settings.json
34
+ * @param workdir - Working directory to invalidate cache for (optional)
35
+ */
36
+ static invalidateCache(workdir?: string): void;
37
+ /**
38
+ * Refresh configuration cache by reloading from settings.json
39
+ * @param workdir - Working directory to refresh cache for (optional)
40
+ */
41
+ static refreshCache(workdir?: string): void;
42
+ /**
43
+ * Get current cache status for monitoring
44
+ * @returns Cache information or null if no cache
45
+ */
46
+ static getCacheStatus(): {
47
+ workdir?: string;
48
+ lastUpdated: number;
49
+ envVarCount: number;
50
+ isValid: boolean;
51
+ } | null;
28
52
  }
29
53
  /**
30
54
  * Static configuration resolver instance
31
- * Implements ConfigurationResolver interface from types.ts
55
+ * Implements ConfigurationResolver interface from types.ts with backward compatibility
32
56
  */
33
57
  export declare const configResolver: {
34
- resolveGatewayConfig: typeof ConfigResolver.resolveGatewayConfig;
35
- resolveModelConfig: typeof ConfigResolver.resolveModelConfig;
36
- resolveTokenLimit: typeof ConfigResolver.resolveTokenLimit;
58
+ resolveGatewayConfig: (apiKey?: string, baseURL?: string, workdir?: string) => GatewayConfig;
59
+ resolveModelConfig: (agentModel?: string, fastModel?: string, workdir?: string) => ModelConfig;
60
+ resolveTokenLimit: (constructorLimit?: number, workdir?: string) => number;
61
+ invalidateCache: typeof ConfigResolver.invalidateCache;
62
+ refreshCache: typeof ConfigResolver.refreshCache;
63
+ getCacheStatus: typeof ConfigResolver.getCacheStatus;
37
64
  };
38
65
  //# sourceMappingURL=configResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configResolver.d.ts","sourceRoot":"","sources":["../../src/utils/configResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,aAAa,EACb,WAAW,EAGZ,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,cAAc;IACzB;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CACzB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,aAAa;IAuDhB;;;;;OAKG;IACH,MAAM,CAAC,kBAAkB,CACvB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW;IAmBd;;;;OAIG;IACH,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;CAoB5D;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;CAI1B,CAAC"}
1
+ {"version":3,"file":"configResolver.d.ts","sourceRoot":"","sources":["../../src/utils/configResolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,WAAW,EAGZ,MAAM,mBAAmB,CAAC;AA8E3B,qBAAa,cAAc;IACzB;;;;;;;OAOG;IACH,MAAM,CAAC,oBAAoB,CACzB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,aAAa;IAyDhB;;;;;;OAMG;IACH,MAAM,CAAC,kBAAkB,CACvB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,WAAW;IA4Bd;;;;;OAKG;IACH,MAAM,CAAC,iBAAiB,CACtB,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM;IAuBT;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAa9C;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3C;;;OAGG;IACH,MAAM,CAAC,cAAc,IAAI;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,OAAO,CAAC;KAClB,GAAG,IAAI;CAYT;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;oCACO,MAAM,YAAY,MAAM,YAAY,MAAM;sCAG3D,MAAM,cACP,MAAM,YACR,MAAM;2CAEqB,MAAM,YAAY,MAAM;;;;CAOhE,CAAC"}
@@ -1,48 +1,103 @@
1
1
  /**
2
2
  * Configuration resolver utilities for Agent Constructor Configuration
3
3
  * Resolves configuration from constructor arguments with environment fallbacks
4
+ * Supports live configuration updates and cache invalidation
4
5
  */
5
6
  import { ConfigurationError, CONFIG_ERRORS, } from "../types/index.js";
7
+ import { DEFAULT_TOKEN_LIMIT } from "./constants.js";
8
+ import { loadMergedWaveConfig } from "../services/hook.js";
9
+ import { getGlobalLogger } from "./globalLogger.js";
10
+ let configCache = null;
11
+ /**
12
+ * Initialize configuration cache with current environment variables from settings.json
13
+ */
14
+ function initializeConfigurationCache(workdir) {
15
+ try {
16
+ const waveConfig = workdir ? loadMergedWaveConfig(workdir) : null;
17
+ const envVars = waveConfig?.env || {};
18
+ configCache = {
19
+ workdir,
20
+ lastUpdated: Date.now(),
21
+ environmentVars: envVars,
22
+ isValid: true,
23
+ };
24
+ const logger = getGlobalLogger();
25
+ logger?.debug(`Live Config: Configuration cache initialized with ${Object.keys(envVars).length} environment variables`);
26
+ }
27
+ catch (error) {
28
+ const logger = getGlobalLogger();
29
+ logger?.error(`Live Config: Failed to initialize configuration cache: ${error.message}`);
30
+ configCache = {
31
+ workdir,
32
+ lastUpdated: Date.now(),
33
+ environmentVars: {},
34
+ isValid: false,
35
+ };
36
+ }
37
+ }
38
+ /**
39
+ * Get current environment variable value with live configuration support
40
+ */
41
+ function getCurrentEnvironmentValue(key, workdir) {
42
+ // Initialize cache if not present or workdir changed
43
+ if (!configCache || configCache.workdir !== workdir) {
44
+ initializeConfigurationCache(workdir);
45
+ }
46
+ // Use cached environment variables if available and valid
47
+ if (configCache && configCache.isValid) {
48
+ const cachedValue = configCache.environmentVars[key];
49
+ if (cachedValue !== undefined) {
50
+ const logger = getGlobalLogger();
51
+ logger?.debug(`Live Config: Using cached environment variable ${key}=${cachedValue}`);
52
+ return cachedValue;
53
+ }
54
+ }
55
+ // Fallback to process environment
56
+ return process.env[key];
57
+ }
6
58
  export class ConfigResolver {
7
59
  /**
8
- * Resolves gateway configuration from constructor args and environment
60
+ * Resolves gateway configuration from constructor args and environment with live config support
9
61
  * @param apiKey - API key from constructor (optional)
10
62
  * @param baseURL - Base URL from constructor (optional)
63
+ * @param workdir - Working directory for loading live configuration (optional)
11
64
  * @returns Resolved gateway configuration
12
65
  * @throws ConfigurationError if required configuration is missing after fallbacks
13
66
  */
14
- static resolveGatewayConfig(apiKey, baseURL) {
15
- // Resolve API key: constructor > environment variable
67
+ static resolveGatewayConfig(apiKey, baseURL, workdir) {
68
+ // Resolve API key: constructor > live configuration > environment variable
16
69
  // Note: Explicitly provided empty strings should be treated as invalid, not fall back to env
17
70
  let resolvedApiKey;
18
71
  if (apiKey !== undefined) {
19
72
  resolvedApiKey = apiKey;
20
73
  }
21
74
  else {
22
- resolvedApiKey = process.env.AIGW_TOKEN || "";
75
+ resolvedApiKey = getCurrentEnvironmentValue("AIGW_TOKEN", workdir) || "";
23
76
  }
24
77
  if (!resolvedApiKey && apiKey === undefined) {
78
+ const envValue = getCurrentEnvironmentValue("AIGW_TOKEN", workdir);
25
79
  throw new ConfigurationError(CONFIG_ERRORS.MISSING_API_KEY, "apiKey", {
26
80
  constructor: apiKey,
27
- environment: process.env.AIGW_TOKEN,
81
+ environment: envValue,
28
82
  });
29
83
  }
30
84
  if (resolvedApiKey.trim() === "") {
31
85
  throw new ConfigurationError(CONFIG_ERRORS.EMPTY_API_KEY, "apiKey", resolvedApiKey);
32
86
  }
33
- // Resolve base URL: constructor > environment variable
87
+ // Resolve base URL: constructor > live configuration > environment variable
34
88
  // Note: Explicitly provided empty strings should be treated as invalid, not fall back to env
35
89
  let resolvedBaseURL;
36
90
  if (baseURL !== undefined) {
37
91
  resolvedBaseURL = baseURL;
38
92
  }
39
93
  else {
40
- resolvedBaseURL = process.env.AIGW_URL || "";
94
+ resolvedBaseURL = getCurrentEnvironmentValue("AIGW_URL", workdir) || "";
41
95
  }
42
96
  if (!resolvedBaseURL && baseURL === undefined) {
97
+ const envValue = getCurrentEnvironmentValue("AIGW_URL", workdir);
43
98
  throw new ConfigurationError(CONFIG_ERRORS.MISSING_BASE_URL, "baseURL", {
44
99
  constructor: baseURL,
45
- environment: process.env.AIGW_URL,
100
+ environment: envValue,
46
101
  });
47
102
  }
48
103
  if (resolvedBaseURL.trim() === "") {
@@ -54,53 +109,102 @@ export class ConfigResolver {
54
109
  };
55
110
  }
56
111
  /**
57
- * Resolves model configuration with fallbacks
112
+ * Resolves model configuration with fallbacks and live config support
58
113
  * @param agentModel - Agent model from constructor (optional)
59
114
  * @param fastModel - Fast model from constructor (optional)
115
+ * @param workdir - Working directory for loading live configuration (optional)
60
116
  * @returns Resolved model configuration with defaults
61
117
  */
62
- static resolveModelConfig(agentModel, fastModel) {
118
+ static resolveModelConfig(agentModel, fastModel, workdir) {
63
119
  // Default values as per data-model.md
64
120
  const DEFAULT_AGENT_MODEL = "claude-sonnet-4-20250514";
65
121
  const DEFAULT_FAST_MODEL = "gemini-2.5-flash";
66
- // Resolve agent model: constructor > environment > default
67
- const resolvedAgentModel = agentModel || process.env.AIGW_MODEL || DEFAULT_AGENT_MODEL;
68
- // Resolve fast model: constructor > environment > default
69
- const resolvedFastModel = fastModel || process.env.AIGW_FAST_MODEL || DEFAULT_FAST_MODEL;
122
+ // Resolve agent model: constructor > live configuration > environment > default
123
+ const resolvedAgentModel = agentModel ||
124
+ getCurrentEnvironmentValue("AIGW_MODEL", workdir) ||
125
+ DEFAULT_AGENT_MODEL;
126
+ // Resolve fast model: constructor > live configuration > environment > default
127
+ const resolvedFastModel = fastModel ||
128
+ getCurrentEnvironmentValue("AIGW_FAST_MODEL", workdir) ||
129
+ DEFAULT_FAST_MODEL;
130
+ const logger = getGlobalLogger();
131
+ logger?.debug(`Live Config: Resolved models - agent: ${resolvedAgentModel}, fast: ${resolvedFastModel}`);
70
132
  return {
71
133
  agentModel: resolvedAgentModel,
72
134
  fastModel: resolvedFastModel,
73
135
  };
74
136
  }
75
137
  /**
76
- * Resolves token limit with fallbacks
138
+ * Resolves token limit with fallbacks and live config support
77
139
  * @param constructorLimit - Token limit from constructor (optional)
140
+ * @param workdir - Working directory for loading live configuration (optional)
78
141
  * @returns Resolved token limit
79
142
  */
80
- static resolveTokenLimit(constructorLimit) {
81
- const DEFAULT_TOKEN_LIMIT = 64000;
143
+ static resolveTokenLimit(constructorLimit, workdir) {
82
144
  // If constructor value provided, use it
83
145
  if (constructorLimit !== undefined) {
84
146
  return constructorLimit;
85
147
  }
86
- // Try environment variable
87
- const envTokenLimit = process.env.TOKEN_LIMIT;
148
+ // Try live configuration then environment variable
149
+ const envTokenLimit = getCurrentEnvironmentValue("TOKEN_LIMIT", workdir);
88
150
  if (envTokenLimit) {
89
151
  const parsed = parseInt(envTokenLimit, 10);
90
152
  if (!isNaN(parsed)) {
153
+ const logger = getGlobalLogger();
154
+ logger?.debug(`Live Config: Resolved token limit from configuration: ${parsed}`);
91
155
  return parsed;
92
156
  }
93
157
  }
94
158
  // Use default
95
159
  return DEFAULT_TOKEN_LIMIT;
96
160
  }
161
+ /**
162
+ * Invalidate configuration cache to force reload from settings.json
163
+ * @param workdir - Working directory to invalidate cache for (optional)
164
+ */
165
+ static invalidateCache(workdir) {
166
+ if (configCache &&
167
+ (workdir === undefined || configCache.workdir === workdir)) {
168
+ const logger = getGlobalLogger();
169
+ logger?.info(`Live Config: Configuration cache invalidated for workdir: ${workdir || "global"}`);
170
+ configCache = null;
171
+ }
172
+ }
173
+ /**
174
+ * Refresh configuration cache by reloading from settings.json
175
+ * @param workdir - Working directory to refresh cache for (optional)
176
+ */
177
+ static refreshCache(workdir) {
178
+ const logger = getGlobalLogger();
179
+ logger?.info(`Live Config: Refreshing configuration cache for workdir: ${workdir || "global"}`);
180
+ initializeConfigurationCache(workdir);
181
+ }
182
+ /**
183
+ * Get current cache status for monitoring
184
+ * @returns Cache information or null if no cache
185
+ */
186
+ static getCacheStatus() {
187
+ if (!configCache) {
188
+ return null;
189
+ }
190
+ return {
191
+ workdir: configCache.workdir,
192
+ lastUpdated: configCache.lastUpdated,
193
+ envVarCount: Object.keys(configCache.environmentVars).length,
194
+ isValid: configCache.isValid,
195
+ };
196
+ }
97
197
  }
98
198
  /**
99
199
  * Static configuration resolver instance
100
- * Implements ConfigurationResolver interface from types.ts
200
+ * Implements ConfigurationResolver interface from types.ts with backward compatibility
101
201
  */
102
202
  export const configResolver = {
103
- resolveGatewayConfig: ConfigResolver.resolveGatewayConfig,
104
- resolveModelConfig: ConfigResolver.resolveModelConfig,
105
- resolveTokenLimit: ConfigResolver.resolveTokenLimit,
203
+ resolveGatewayConfig: (apiKey, baseURL, workdir) => ConfigResolver.resolveGatewayConfig(apiKey, baseURL, workdir),
204
+ resolveModelConfig: (agentModel, fastModel, workdir) => ConfigResolver.resolveModelConfig(agentModel, fastModel, workdir),
205
+ resolveTokenLimit: (constructorLimit, workdir) => ConfigResolver.resolveTokenLimit(constructorLimit, workdir),
206
+ // Live configuration management methods
207
+ invalidateCache: ConfigResolver.invalidateCache,
208
+ refreshCache: ConfigResolver.refreshCache,
209
+ getCacheStatus: ConfigResolver.getCacheStatus,
106
210
  };
@@ -21,7 +21,7 @@ export declare const USER_MEMORY_FILE: string;
21
21
  /**
22
22
  * AI related constants
23
23
  */
24
- export declare const DEFAULT_TOKEN_LIMIT = 64000;
24
+ export declare const DEFAULT_TOKEN_LIMIT = 96000;
25
25
  /**
26
26
  * @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
27
27
  * They are maintained for backward compatibility with existing code that might still reference them,