@tyvm/knowhow 0.0.21 → 0.0.23

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/package.json +3 -1
  2. package/src/agents/base/base.ts +16 -7
  3. package/src/agents/configurable/ConfigAgent.ts +5 -3
  4. package/src/agents/developer/developer.ts +3 -4
  5. package/src/agents/index.ts +26 -2
  6. package/src/agents/patcher/patcher.ts +3 -5
  7. package/src/agents/researcher/researcher.ts +3 -4
  8. package/src/agents/tools/agentCall.ts +5 -2
  9. package/src/agents/tools/executeScript/README.md +78 -0
  10. package/src/agents/tools/executeScript/definition.ts +73 -0
  11. package/src/agents/tools/executeScript/examples/dependency-injection-validation.ts +272 -0
  12. package/src/agents/tools/executeScript/examples/quick-test.ts +74 -0
  13. package/src/agents/tools/executeScript/examples/serialization-test.ts +321 -0
  14. package/src/agents/tools/executeScript/examples/test-runner.ts +197 -0
  15. package/src/agents/tools/executeScript/index.ts +93 -0
  16. package/src/agents/tools/index.ts +1 -0
  17. package/src/agents/tools/list.ts +2 -1
  18. package/src/agents/vim/vim.ts +3 -4
  19. package/src/ai.ts +2 -1
  20. package/src/chat.ts +4 -2
  21. package/src/cli.ts +7 -15
  22. package/src/clients/index.ts +23 -9
  23. package/src/dataset/diffs/test.ts +2 -1
  24. package/src/index.ts +3 -3
  25. package/src/services/AgentService.ts +9 -10
  26. package/src/services/EventService.ts +0 -2
  27. package/src/services/GitHub.ts +0 -1
  28. package/src/services/KnowhowClient.ts +0 -3
  29. package/src/services/Mcp.ts +0 -2
  30. package/src/services/S3.ts +0 -1
  31. package/src/services/Tools.ts +63 -8
  32. package/src/services/flags.ts +0 -1
  33. package/src/services/index.ts +56 -0
  34. package/src/services/modules/index.ts +53 -0
  35. package/src/{modules → services/modules}/types.ts +16 -5
  36. package/src/services/script-execution/SandboxContext.ts +278 -0
  37. package/src/services/script-execution/ScriptExecutor.ts +339 -0
  38. package/src/services/script-execution/ScriptPolicy.ts +236 -0
  39. package/src/services/script-execution/ScriptTracer.ts +249 -0
  40. package/src/services/script-execution/types.ts +134 -0
  41. package/src/worker.ts +3 -3
  42. package/tests/integration/fileblocks/readwrite.test.ts +2 -1
  43. package/tests/integration/patching.test.ts +5 -5
  44. package/ts_build/src/agents/base/base.d.ts +9 -4
  45. package/ts_build/src/agents/base/base.js +7 -10
  46. package/ts_build/src/agents/base/base.js.map +1 -1
  47. package/ts_build/src/agents/configurable/ConfigAgent.d.ts +2 -2
  48. package/ts_build/src/agents/configurable/ConfigAgent.js +2 -2
  49. package/ts_build/src/agents/configurable/ConfigAgent.js.map +1 -1
  50. package/ts_build/src/agents/developer/developer.d.ts +2 -3
  51. package/ts_build/src/agents/developer/developer.js +3 -4
  52. package/ts_build/src/agents/developer/developer.js.map +1 -1
  53. package/ts_build/src/agents/index.d.ts +11 -2
  54. package/ts_build/src/agents/index.js +19 -3
  55. package/ts_build/src/agents/index.js.map +1 -1
  56. package/ts_build/src/agents/patcher/patcher.d.ts +2 -3
  57. package/ts_build/src/agents/patcher/patcher.js +3 -4
  58. package/ts_build/src/agents/patcher/patcher.js.map +1 -1
  59. package/ts_build/src/agents/researcher/researcher.d.ts +2 -3
  60. package/ts_build/src/agents/researcher/researcher.js +3 -4
  61. package/ts_build/src/agents/researcher/researcher.js.map +1 -1
  62. package/ts_build/src/agents/tools/agentCall.js +4 -4
  63. package/ts_build/src/agents/tools/agentCall.js.map +1 -1
  64. package/ts_build/src/agents/tools/executeScript/definition.d.ts +2 -0
  65. package/ts_build/src/agents/tools/executeScript/definition.js +70 -0
  66. package/ts_build/src/agents/tools/executeScript/definition.js.map +1 -0
  67. package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.d.ts +18 -0
  68. package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js +192 -0
  69. package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js.map +1 -0
  70. package/ts_build/src/agents/tools/executeScript/examples/quick-test.d.ts +3 -0
  71. package/ts_build/src/agents/tools/executeScript/examples/quick-test.js +65 -0
  72. package/ts_build/src/agents/tools/executeScript/examples/quick-test.js.map +1 -0
  73. package/ts_build/src/agents/tools/executeScript/examples/serialization-test.d.ts +15 -0
  74. package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js +266 -0
  75. package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js.map +1 -0
  76. package/ts_build/src/agents/tools/executeScript/examples/simple-example.d.ts +20 -0
  77. package/ts_build/src/agents/tools/executeScript/examples/simple-example.js +35 -0
  78. package/ts_build/src/agents/tools/executeScript/examples/simple-example.js.map +1 -0
  79. package/ts_build/src/agents/tools/executeScript/examples/test-runner.d.ts +4 -0
  80. package/ts_build/src/agents/tools/executeScript/examples/test-runner.js +198 -0
  81. package/ts_build/src/agents/tools/executeScript/examples/test-runner.js.map +1 -0
  82. package/ts_build/src/agents/tools/executeScript/handler.d.ts +27 -0
  83. package/ts_build/src/agents/tools/executeScript/handler.js +64 -0
  84. package/ts_build/src/agents/tools/executeScript/handler.js.map +1 -0
  85. package/ts_build/src/agents/tools/executeScript/index.d.ts +27 -0
  86. package/ts_build/src/agents/tools/executeScript/index.js +70 -0
  87. package/ts_build/src/agents/tools/executeScript/index.js.map +1 -0
  88. package/ts_build/src/agents/tools/executeScript.d.ts +29 -0
  89. package/ts_build/src/agents/tools/executeScript.js +124 -0
  90. package/ts_build/src/agents/tools/executeScript.js.map +1 -0
  91. package/ts_build/src/agents/tools/index.d.ts +1 -0
  92. package/ts_build/src/agents/tools/index.js +1 -0
  93. package/ts_build/src/agents/tools/index.js.map +1 -1
  94. package/ts_build/src/agents/tools/list.js +2 -0
  95. package/ts_build/src/agents/tools/list.js.map +1 -1
  96. package/ts_build/src/agents/vim/vim.d.ts +2 -3
  97. package/ts_build/src/agents/vim/vim.js +3 -4
  98. package/ts_build/src/agents/vim/vim.js.map +1 -1
  99. package/ts_build/src/ai.js +2 -1
  100. package/ts_build/src/ai.js.map +1 -1
  101. package/ts_build/src/chat.js +10 -9
  102. package/ts_build/src/chat.js.map +1 -1
  103. package/ts_build/src/cli.js +12 -19
  104. package/ts_build/src/cli.js.map +1 -1
  105. package/ts_build/src/clients/index.d.ts +9 -2
  106. package/ts_build/src/clients/index.js +17 -4
  107. package/ts_build/src/clients/index.js.map +1 -1
  108. package/ts_build/src/dataset/diffs/test.js +2 -1
  109. package/ts_build/src/dataset/diffs/test.js.map +1 -1
  110. package/ts_build/src/index.js +10 -10
  111. package/ts_build/src/index.js.map +1 -1
  112. package/ts_build/src/services/AgentService.d.ts +7 -3
  113. package/ts_build/src/services/AgentService.js +11 -10
  114. package/ts_build/src/services/AgentService.js.map +1 -1
  115. package/ts_build/src/services/EventService.d.ts +0 -1
  116. package/ts_build/src/services/EventService.js +1 -2
  117. package/ts_build/src/services/EventService.js.map +1 -1
  118. package/ts_build/src/services/GitHub.d.ts +0 -1
  119. package/ts_build/src/services/GitHub.js +1 -2
  120. package/ts_build/src/services/GitHub.js.map +1 -1
  121. package/ts_build/src/services/KnowhowClient.d.ts +0 -1
  122. package/ts_build/src/services/KnowhowClient.js +1 -2
  123. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  124. package/ts_build/src/services/Mcp.d.ts +0 -1
  125. package/ts_build/src/services/Mcp.js +1 -2
  126. package/ts_build/src/services/Mcp.js.map +1 -1
  127. package/ts_build/src/services/S3.d.ts +0 -1
  128. package/ts_build/src/services/S3.js +1 -2
  129. package/ts_build/src/services/S3.js.map +1 -1
  130. package/ts_build/src/services/Tools.d.ts +22 -1
  131. package/ts_build/src/services/Tools.js +32 -6
  132. package/ts_build/src/services/Tools.js.map +1 -1
  133. package/ts_build/src/services/flags.d.ts +0 -1
  134. package/ts_build/src/services/flags.js +1 -2
  135. package/ts_build/src/services/flags.js.map +1 -1
  136. package/ts_build/src/services/index.d.ts +25 -0
  137. package/ts_build/src/services/index.js +42 -1
  138. package/ts_build/src/services/index.js.map +1 -1
  139. package/ts_build/src/services/modules/example-usage.d.ts +11 -0
  140. package/ts_build/src/services/modules/example-usage.js +43 -0
  141. package/ts_build/src/services/modules/example-usage.js.map +1 -0
  142. package/ts_build/src/services/modules/index.d.ts +4 -0
  143. package/ts_build/src/services/modules/index.js +44 -0
  144. package/ts_build/src/services/modules/index.js.map +1 -0
  145. package/ts_build/src/services/modules/types.d.ts +47 -0
  146. package/ts_build/src/services/modules/types.js +3 -0
  147. package/ts_build/src/services/modules/types.js.map +1 -0
  148. package/ts_build/src/services/script-execution/SandboxContext.d.ts +34 -0
  149. package/ts_build/src/services/script-execution/SandboxContext.js +186 -0
  150. package/ts_build/src/services/script-execution/SandboxContext.js.map +1 -0
  151. package/ts_build/src/services/script-execution/ScriptExecutor.d.ts +17 -0
  152. package/ts_build/src/services/script-execution/ScriptExecutor.js +211 -0
  153. package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -0
  154. package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +27 -0
  155. package/ts_build/src/services/script-execution/ScriptPolicy.js +150 -0
  156. package/ts_build/src/services/script-execution/ScriptPolicy.js.map +1 -0
  157. package/ts_build/src/services/script-execution/ScriptTracer.d.ts +19 -0
  158. package/ts_build/src/services/script-execution/ScriptTracer.js +186 -0
  159. package/ts_build/src/services/script-execution/ScriptTracer.js.map +1 -0
  160. package/ts_build/src/services/script-execution/types.d.ts +108 -0
  161. package/ts_build/src/services/script-execution/types.js +3 -0
  162. package/ts_build/src/services/script-execution/types.js.map +1 -0
  163. package/ts_build/src/services/singletons.d.ts +17 -0
  164. package/ts_build/src/services/singletons.js +28 -0
  165. package/ts_build/src/services/singletons.js.map +1 -0
  166. package/ts_build/src/worker.js +4 -3
  167. package/ts_build/src/worker.js.map +1 -1
  168. package/ts_build/tests/integration/fileblocks/readwrite.test.js +10 -9
  169. package/ts_build/tests/integration/fileblocks/readwrite.test.js.map +1 -1
  170. package/ts_build/tests/integration/patching.test.js +9 -10
  171. package/ts_build/tests/integration/patching.test.js.map +1 -1
  172. package/src/modules/index.ts +0 -37
@@ -0,0 +1,236 @@
1
+ import {
2
+ ResourceQuotas,
3
+ SecurityPolicy,
4
+ QuotaUsage,
5
+ PolicyViolation
6
+ } from './types';
7
+
8
+ /**
9
+ * Enforces security policies and resource quotas for script execution
10
+ */
11
+ export class ScriptPolicyEnforcer {
12
+ private usage: QuotaUsage;
13
+ private violations: PolicyViolation[] = [];
14
+
15
+ constructor(
16
+ private quotas: ResourceQuotas,
17
+ private policy: SecurityPolicy
18
+ ) {
19
+ this.usage = {
20
+ toolCalls: 0,
21
+ tokens: 0,
22
+ executionTimeMs: 0,
23
+ costUsd: 0
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Check if a tool call is allowed
29
+ */
30
+ checkToolCall(toolName: string): boolean {
31
+ // Check if tool is in denylist
32
+ if (this.policy.denylistedTools && this.policy.denylistedTools.includes(toolName)) {
33
+ this.recordViolation('tool_denied', `Tool '${toolName}' is in denylist`);
34
+ return false;
35
+ }
36
+
37
+ // Check if tool is in allowlist (if allowlist is defined and not empty)
38
+ if (this.policy.allowlistedTools && this.policy.allowlistedTools.length > 0 &&
39
+ !this.policy.allowlistedTools.includes(toolName)) {
40
+ this.recordViolation('tool_not_allowed', `Tool '${toolName}' is not in allowlist`);
41
+ return false;
42
+ }
43
+
44
+ // Check quota
45
+ if (this.usage.toolCalls >= this.quotas.maxToolCalls) {
46
+ this.recordViolation('quota_exceeded', 'Maximum tool calls exceeded');
47
+ return false;
48
+ }
49
+
50
+ return true;
51
+ }
52
+
53
+ /**
54
+ * Record a tool call
55
+ */
56
+ recordToolCall(): void {
57
+ this.usage.toolCalls++;
58
+ }
59
+
60
+ /**
61
+ * Check if token usage is allowed
62
+ */
63
+ checkTokenUsage(tokens: number): boolean {
64
+ if (this.usage.tokens + tokens > this.quotas.maxTokens) {
65
+ this.recordViolation('quota_exceeded', 'Maximum tokens would be exceeded');
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+
71
+ /**
72
+ * Record token usage
73
+ */
74
+ recordTokenUsage(tokens: number): void {
75
+ this.usage.tokens += tokens;
76
+ }
77
+
78
+ /**
79
+ * Check if execution time limit is exceeded
80
+ */
81
+ checkExecutionTime(currentTimeMs: number): boolean {
82
+ if (currentTimeMs > this.quotas.maxExecutionTimeMs) {
83
+ this.recordViolation('quota_exceeded', 'Maximum execution time exceeded');
84
+ return false;
85
+ }
86
+ this.usage.executionTimeMs = currentTimeMs;
87
+ return true;
88
+ }
89
+
90
+ /**
91
+ * Check if cost limit is exceeded
92
+ */
93
+ checkCost(additionalCost: number): boolean {
94
+ if (this.usage.costUsd + additionalCost > this.quotas.maxCostUsd) {
95
+ this.recordViolation('quota_exceeded', 'Maximum cost would be exceeded');
96
+ return false;
97
+ }
98
+ return true;
99
+ }
100
+
101
+ /**
102
+ * Record cost usage
103
+ */
104
+ recordCost(cost: number): void {
105
+ this.usage.costUsd += cost;
106
+ }
107
+
108
+ /**
109
+ * Get current usage
110
+ */
111
+ getUsage(): QuotaUsage {
112
+ return { ...this.usage };
113
+ }
114
+
115
+ /**
116
+ * Get current quotas
117
+ */
118
+ getQuotas(): ResourceQuotas {
119
+ return { ...this.quotas };
120
+ }
121
+
122
+ /**
123
+ * Get all policy violations
124
+ */
125
+ getViolations(): PolicyViolation[] {
126
+ return [...this.violations];
127
+ }
128
+
129
+ /**
130
+ * Check if there are any violations
131
+ */
132
+ hasViolations(): boolean {
133
+ return this.violations.length > 0;
134
+ }
135
+
136
+ /**
137
+ * Get the most recent violation
138
+ */
139
+ getLastViolation(): PolicyViolation | undefined {
140
+ return this.violations[this.violations.length - 1];
141
+ }
142
+
143
+ /**
144
+ * Reset usage counters
145
+ */
146
+ resetUsage(): void {
147
+ this.usage = {
148
+ toolCalls: 0,
149
+ tokens: 0,
150
+ executionTimeMs: 0,
151
+ costUsd: 0
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Reset violations
157
+ */
158
+ resetViolations(): void {
159
+ this.violations = [];
160
+ }
161
+
162
+ /**
163
+ * Validate script content for security issues
164
+ */
165
+ validateScript(scriptContent: string): { valid: boolean; issues: string[] } {
166
+ const issues: string[] = [];
167
+
168
+ // Check for dangerous patterns
169
+ const dangerousPatterns = [
170
+ /require\s*\(/gi, // Node.js require
171
+ /import\s+.*\s+from/gi, // ES6 imports (should be handled by bundler)
172
+ /process\./gi, // Process access
173
+ /global\./gi, // Global object access
174
+ /eval\s*\(/gi, // eval calls
175
+ /Function\s*\(/gi, // Function constructor
176
+ /setTimeout/gi, // setTimeout
177
+ /setInterval/gi, // setInterval
178
+ /fetch\s*\(/gi, // Direct fetch calls
179
+ /XMLHttpRequest/gi, // XHR
180
+ /WebSocket/gi, // WebSocket
181
+ /location\./gi, // Location object
182
+ /document\./gi, // Document object
183
+ /window\./gi, // Window object
184
+ ];
185
+
186
+ for (const pattern of dangerousPatterns) {
187
+ if (pattern.test(scriptContent)) {
188
+ issues.push(`Potentially dangerous pattern detected: ${pattern.source}`);
189
+ }
190
+ }
191
+
192
+ // Check script length
193
+ if (scriptContent.length > this.policy.maxScriptLength) {
194
+ issues.push(`Script too long: ${scriptContent.length} > ${this.policy.maxScriptLength}`);
195
+ }
196
+
197
+ // Check for excessive complexity (rough heuristic)
198
+ const complexityIndicators = [
199
+ /for\s*\(/gi,
200
+ /while\s*\(/gi,
201
+ /function\s+\w+/gi,
202
+ /=>\s*{/gi,
203
+ /if\s*\(/gi,
204
+ ];
205
+
206
+ let complexityScore = 0;
207
+ for (const indicator of complexityIndicators) {
208
+ const matches = scriptContent.match(indicator);
209
+ complexityScore += matches ? matches.length : 0;
210
+ }
211
+
212
+ if (complexityScore > 50) {
213
+ issues.push(`Script complexity too high: ${complexityScore} constructs detected`);
214
+ }
215
+
216
+ return {
217
+ valid: issues.length === 0,
218
+ issues
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Record a policy violation
224
+ */
225
+ private recordViolation(type: 'quota_exceeded' | 'tool_denied' | 'tool_not_allowed' | 'script_validation', message: string): void {
226
+ const violation: PolicyViolation = {
227
+ id: `violation-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
228
+ type,
229
+ message,
230
+ timestamp: Date.now(),
231
+ usage: { ...this.usage }
232
+ };
233
+
234
+ this.violations.push(violation);
235
+ }
236
+ }
@@ -0,0 +1,249 @@
1
+ import { TraceEvent, TraceMetrics, ExecutionTrace, QuotaUsage } from "./types";
2
+
3
+ /**
4
+ * Handles tracing and monitoring of script execution
5
+ */
6
+ export class ScriptTracer {
7
+ private events: TraceEvent[] = [];
8
+ private metrics: TraceMetrics;
9
+ private startTime: number;
10
+
11
+ constructor() {
12
+ this.startTime = Date.now();
13
+ this.metrics = {
14
+ executionTimeMs: 0,
15
+ toolCallCount: 0,
16
+ llmCallCount: 0,
17
+ tokenUsage: {
18
+ prompt: 0,
19
+ completion: 0,
20
+ total: 0,
21
+ },
22
+ memoryUsage: {
23
+ heapUsed: 0,
24
+ heapTotal: 0,
25
+ },
26
+ costUsd: 0,
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Emit a trace event
32
+ */
33
+ emitEvent(type: string, data: any): void {
34
+ const event: TraceEvent = {
35
+ id: `evt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
36
+ type,
37
+ timestamp: Date.now(),
38
+ data: this.sanitizeEventData(data),
39
+ };
40
+
41
+ this.events.push(event);
42
+ this.updateMetrics(event);
43
+ }
44
+
45
+ /**
46
+ * Record cost for tracking
47
+ */
48
+ recordCost(costUsd: number): void {
49
+ this.metrics.costUsd += costUsd;
50
+ this.emitEvent("cost_recorded", {
51
+ costUsd,
52
+ totalCost: this.metrics.costUsd,
53
+ });
54
+ }
55
+
56
+ /**
57
+ * Get current quota usage
58
+ */
59
+ getCurrentQuota(): QuotaUsage {
60
+ return {
61
+ toolCalls: this.metrics.toolCallCount,
62
+ tokens: this.metrics.tokenUsage.total,
63
+ executionTimeMs: Date.now() - this.startTime,
64
+ costUsd: this.metrics.costUsd,
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Get all trace events
70
+ */
71
+ getEvents(): TraceEvent[] {
72
+ return [...this.events];
73
+ }
74
+
75
+ /**
76
+ * Get current metrics
77
+ */
78
+ getMetrics(): TraceMetrics {
79
+ return {
80
+ ...this.metrics,
81
+ executionTimeMs: Date.now() - this.startTime,
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Generate execution trace
87
+ */
88
+ getTrace(): ExecutionTrace {
89
+ return {
90
+ id: `trace-${Date.now()}`,
91
+ startTime: this.startTime,
92
+ endTime: Date.now(),
93
+ events: this.getEvents(),
94
+ metrics: this.getMetrics(),
95
+ success: !this.events.some((e) => e.type.includes("error")),
96
+ error: this.getLastError(),
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Clear all events and reset metrics
102
+ */
103
+ reset(): void {
104
+ this.events = [];
105
+ this.startTime = Date.now();
106
+ this.metrics = {
107
+ executionTimeMs: 0,
108
+ toolCallCount: 0,
109
+ llmCallCount: 0,
110
+ tokenUsage: {
111
+ prompt: 0,
112
+ completion: 0,
113
+ total: 0,
114
+ },
115
+ memoryUsage: {
116
+ heapUsed: 0,
117
+ heapTotal: 0,
118
+ },
119
+ costUsd: 0,
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Update metrics based on events
125
+ */
126
+ private updateMetrics(event: TraceEvent): void {
127
+ switch (event.type) {
128
+ case "tool_call_start":
129
+ this.metrics.toolCallCount++;
130
+ break;
131
+
132
+ case "llm_call_start":
133
+ this.metrics.llmCallCount++;
134
+ break;
135
+
136
+ case "llm_call_success":
137
+ if (event.data && event.data.usage) {
138
+ const usage = event.data.usage;
139
+ this.metrics.tokenUsage.prompt += usage.prompt_tokens || 0;
140
+ this.metrics.tokenUsage.completion += usage.completion_tokens || 0;
141
+ this.metrics.tokenUsage.total += usage.total_tokens || 0;
142
+ }
143
+ break;
144
+ }
145
+
146
+ // Update memory usage if available
147
+ if (typeof process !== "undefined" && process.memoryUsage) {
148
+ const memUsage = process.memoryUsage();
149
+ this.metrics.memoryUsage.heapUsed = memUsage.heapUsed;
150
+ this.metrics.memoryUsage.heapTotal = memUsage.heapTotal;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Get the last error from events
156
+ */
157
+ private getLastError(): string | undefined {
158
+ const errorEvents = this.events
159
+ .filter((e) => e.type.includes("error"))
160
+ .reverse();
161
+
162
+ if (errorEvents.length > 0) {
163
+ const lastError = errorEvents[0];
164
+ return (
165
+ lastError.data?.error || lastError.data?.message || "Unknown error"
166
+ );
167
+ }
168
+
169
+ return undefined;
170
+ }
171
+
172
+ /**
173
+ * Sanitize event data to prevent sensitive information leaks
174
+ */
175
+ private sanitizeEventData(data: any): any {
176
+ if (data === null || data === undefined) {
177
+ return data;
178
+ }
179
+
180
+ if (typeof data === "string") {
181
+ // Truncate very long strings
182
+ return data.length > 1000
183
+ ? data.substring(0, 1000) + "...[TRUNCATED]"
184
+ : data;
185
+ }
186
+
187
+ if (Array.isArray(data)) {
188
+ return data.map((item) => this.sanitizeEventData(item));
189
+ }
190
+
191
+ if (typeof data === "object") {
192
+ const sanitized: any = {};
193
+ for (const [key, value] of Object.entries(data)) {
194
+ // Redact sensitive keys
195
+ if (this.isSensitiveKey(key)) {
196
+ sanitized[key] = "[REDACTED]";
197
+ } else if (key === "parameters" && typeof value === "object") {
198
+ // Special handling for tool parameters
199
+ sanitized[key] = this.sanitizeParameters(value);
200
+ } else {
201
+ sanitized[key] = this.sanitizeEventData(value);
202
+ }
203
+ }
204
+ return sanitized;
205
+ }
206
+
207
+ return data;
208
+ }
209
+
210
+ /**
211
+ * Check if a key contains sensitive information
212
+ */
213
+ private isSensitiveKey(key: string): boolean {
214
+ const lowerKey = key.toLowerCase();
215
+ const sensitivePatterns = [
216
+ "password",
217
+ "secret",
218
+ "token",
219
+ "key",
220
+ "auth",
221
+ "credential",
222
+ "private",
223
+ "confidential",
224
+ ];
225
+
226
+ return sensitivePatterns.some((pattern) => lowerKey.includes(pattern));
227
+ }
228
+
229
+ /**
230
+ * Sanitize tool parameters
231
+ */
232
+ private sanitizeParameters(params: any): any {
233
+ if (!params || typeof params !== "object") {
234
+ return params;
235
+ }
236
+
237
+ const sanitized: any = {};
238
+ for (const [key, value] of Object.entries(params)) {
239
+ if (this.isSensitiveKey(key)) {
240
+ sanitized[key] = "[REDACTED]";
241
+ } else if (typeof value === "string" && value.length > 500) {
242
+ sanitized[key] = value.substring(0, 500) + "...[TRUNCATED]";
243
+ } else {
244
+ sanitized[key] = this.sanitizeEventData(value);
245
+ }
246
+ }
247
+ return sanitized;
248
+ }
249
+ }
@@ -0,0 +1,134 @@
1
+ import { Message } from '../../clients/types';
2
+
3
+ // Basic trace event interface
4
+ export interface TraceEvent {
5
+ id: string;
6
+ type: string;
7
+ timestamp: number;
8
+ data: any;
9
+ }
10
+
11
+ // Trace metrics for performance monitoring
12
+ export interface TraceMetrics {
13
+ executionTimeMs: number;
14
+ toolCallCount: number;
15
+ llmCallCount: number;
16
+ tokenUsage: {
17
+ prompt: number;
18
+ completion: number;
19
+ total: number;
20
+ };
21
+ memoryUsage: {
22
+ heapUsed: number;
23
+ heapTotal: number;
24
+ };
25
+ costUsd: number;
26
+ }
27
+
28
+ // Complete execution trace
29
+ export interface ExecutionTrace {
30
+ id: string;
31
+ startTime: number;
32
+ endTime: number;
33
+ events: TraceEvent[];
34
+ metrics: TraceMetrics;
35
+ success: boolean;
36
+ error?: string;
37
+ }
38
+
39
+ // Resource quotas for script execution
40
+ export interface ResourceQuotas {
41
+ maxToolCalls: number;
42
+ maxTokens: number;
43
+ maxExecutionTimeMs: number;
44
+ maxCostUsd: number;
45
+ maxMemoryMb: number;
46
+ }
47
+
48
+ // Security policy configuration
49
+ export interface SecurityPolicy {
50
+ allowlistedTools: string[];
51
+ denylistedTools: string[];
52
+ maxScriptLength: number;
53
+ allowNetworkAccess: boolean;
54
+ allowFileSystemAccess: boolean;
55
+ }
56
+
57
+ // Current quota usage tracking
58
+ export interface QuotaUsage {
59
+ toolCalls: number;
60
+ tokens: number;
61
+ executionTimeMs: number;
62
+ costUsd: number;
63
+ }
64
+
65
+ // Policy violation record
66
+ export interface PolicyViolation {
67
+ id: string;
68
+ type: 'quota_exceeded' | 'tool_denied' | 'tool_not_allowed' | 'script_validation';
69
+ message: string;
70
+ timestamp: number;
71
+ usage: QuotaUsage;
72
+ }
73
+
74
+ // Script execution request
75
+ export interface ExecutionRequest {
76
+ script: string;
77
+ context?: Record<string, any>;
78
+ quotas?: Partial<ResourceQuotas>;
79
+ policy?: Partial<SecurityPolicy>;
80
+ }
81
+
82
+ // Script execution result
83
+ export interface ExecutionResult {
84
+ success: boolean;
85
+ error: string | null;
86
+ result: any;
87
+ trace: ExecutionTrace;
88
+ artifacts: Artifact[];
89
+ consoleOutput: string[];
90
+ }
91
+
92
+ // Artifact created by script
93
+ export interface Artifact {
94
+ id: string;
95
+ name: string;
96
+ type: 'text' | 'json' | 'csv' | 'html' | 'markdown';
97
+ content: string;
98
+ createdAt: string;
99
+ }
100
+
101
+ // Tool execution result
102
+ export interface ToolResult {
103
+ success: boolean;
104
+ result?: any;
105
+ error?: string;
106
+ }
107
+
108
+ // Tool call record
109
+ export interface ToolCall {
110
+ id: string;
111
+ name: string;
112
+ args: Record<string, any>;
113
+ result?: any;
114
+ error?: string;
115
+ timestamp: number;
116
+ duration?: number;
117
+ }
118
+
119
+ // LLM call record
120
+ export interface LLMCall {
121
+ id: string;
122
+ model: string;
123
+ messages: Message[];
124
+ response?: any;
125
+ error?: string;
126
+ timestamp: number;
127
+ duration?: number;
128
+ tokenUsage?: {
129
+ prompt: number;
130
+ completion: number;
131
+ total: number;
132
+ };
133
+ cost?: number;
134
+ }
package/src/worker.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import os from "os";
2
2
  import { WebSocket } from "ws";
3
- import { Developer, Patcher, Researcher } from "./agents";
4
3
  import { includedTools } from "./agents/tools/list";
5
4
  import { loadJwt } from "./login";
6
- import { Agents, Tools } from "./services";
7
- import { Mcp, McpServerService } from "./services/Mcp";
5
+ import { services } from "./services";
6
+ import { McpServerService } from "./services/Mcp";
8
7
  import * as allTools from "./agents/tools";
9
8
  import { wait } from "./utils";
10
9
  import { getConfig, updateConfig } from "./config";
@@ -12,6 +11,7 @@ import { getConfig, updateConfig } from "./config";
12
11
  const API_URL = process.env.KNOWHOW_API_URL;
13
12
 
14
13
  export async function worker() {
14
+ const { Tools } = services();
15
15
  const mcpServer = new McpServerService(Tools);
16
16
  const clientName = "knowhow-worker";
17
17
  const clientVersion = "1.1.1";
@@ -1,9 +1,10 @@
1
1
  import * as fs from "fs";
2
2
  import { readFile, writeFile } from "../../../src/utils";
3
- import { Patcher } from "../../../src/agents/patcher/patcher";
3
+ import { agents } from "../../../src/agents";
4
4
  import { FlagsService } from "../../../src/services/flags";
5
5
 
6
6
  describe("Developer", () => {
7
+ const { Patcher } = agents();
7
8
  beforeAll(() => {
8
9
  Patcher.disableTool("searchFiles");
9
10
  Patcher.disableTool("execCommand");
@@ -2,9 +2,8 @@ import { readFile, writeFile } from "../../src/utils";
2
2
  import { createPatch, applyPatch } from "diff";
3
3
  import { scanFile } from "../../src/agents/tools";
4
4
  import { patchFile } from "../../src/agents/tools/patch";
5
- import { Agents } from "../../src/services/AgentService";
6
- import { Patcher } from "../../src/agents";
7
- import { Tools } from "../../src/services";
5
+ import { agents } from "../../src/agents";
6
+ import { services } from "../../src/services";
8
7
  import { includedTools } from "../../src/agents/tools/list";
9
8
  import * as allTools from "../../src/agents/tools";
10
9
 
@@ -29,11 +28,12 @@ const brokenPatch = `Index: tests/integration/patching/input.txt
29
28
  }\n`;
30
29
 
31
30
  describe("Patcher", () => {
32
- beforeAll(async () => {
31
+ const { Agents, Tools } = beforeAll(async () => {
32
+ const { Patcher } = agents();
33
33
  Agents.registerAgent(Patcher);
34
34
  Tools.addTools(includedTools);
35
35
  const toolFunctions = Object.entries(allTools)
36
- .filter(([_, value]) => typeof value === 'function')
36
+ .filter(([_, value]) => typeof value === "function")
37
37
  .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
38
38
  Tools.addFunctions(toolFunctions);
39
39
  });
@@ -11,10 +11,12 @@ export interface ModelPreference {
11
11
  model: string;
12
12
  provider: keyof typeof Clients.clients;
13
13
  }
14
+ export interface AgentContext {
15
+ Tools?: ToolsService;
16
+ Events?: EventService;
17
+ messageProcessor?: MessageProcessor;
18
+ }
14
19
  export declare abstract class BaseAgent implements IAgent {
15
- tools: ToolsService;
16
- events: EventService;
17
- messageProcessor: MessageProcessor;
18
20
  abstract name: string;
19
21
  abstract description: string;
20
22
  private status;
@@ -43,8 +45,11 @@ export declare abstract class BaseAgent implements IAgent {
43
45
  kill: string;
44
46
  unpause: string;
45
47
  };
48
+ tools: ToolsService;
49
+ events: EventService;
50
+ messageProcessor: MessageProcessor;
46
51
  disabledTools: any[];
47
- constructor(tools?: ToolsService, events?: EventService, messageProcessor?: MessageProcessor);
52
+ constructor(context: AgentContext);
48
53
  newTask(): void;
49
54
  register(): void;
50
55
  setModelPreferences(value: ModelPreference[]): void;