@tyvm/knowhow 0.0.82 → 0.0.84

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 (210) hide show
  1. package/package.json +4 -2
  2. package/src/agents/base/base.ts +72 -62
  3. package/src/agents/index.ts +30 -14
  4. package/src/agents/tools/startAgentTask.ts +3 -1
  5. package/src/chat/CliChatService.ts +20 -4
  6. package/src/chat/modules/AgentModule.ts +399 -357
  7. package/src/chat/modules/CustomCommandsModule.ts +0 -1
  8. package/src/chat/modules/InternalChatModule.ts +18 -2
  9. package/src/chat/modules/RendererModule.ts +109 -0
  10. package/src/chat/modules/SessionsModule.ts +854 -0
  11. package/src/chat/modules/SetupModule.ts +6 -8
  12. package/src/chat/modules/index.ts +1 -0
  13. package/src/chat/renderer/CompactRenderer.ts +209 -0
  14. package/src/chat/renderer/ConsoleRenderer.ts +141 -0
  15. package/src/chat/renderer/FancyRenderer.ts +421 -0
  16. package/src/chat/renderer/index.ts +5 -0
  17. package/src/chat/renderer/loadRenderer.ts +314 -0
  18. package/src/chat/renderer/messagesToRenderEvents.ts +96 -0
  19. package/src/chat/renderer/types.ts +88 -0
  20. package/src/chat/types.ts +5 -0
  21. package/src/chat.ts +69 -5
  22. package/src/cli.ts +24 -5
  23. package/src/config.ts +15 -0
  24. package/src/plugins/AgentsMdPlugin.ts +1 -1
  25. package/src/plugins/GitPlugin.ts +20 -20
  26. package/src/plugins/PluginBase.ts +11 -0
  27. package/src/plugins/SkillsPlugin.ts +150 -0
  28. package/src/plugins/asana.ts +4 -4
  29. package/src/plugins/embedding.ts +3 -5
  30. package/src/plugins/exec.ts +3 -3
  31. package/src/plugins/figma.ts +3 -7
  32. package/src/plugins/github.ts +18 -29
  33. package/src/plugins/jira.ts +2 -2
  34. package/src/plugins/language.ts +4 -4
  35. package/src/plugins/linear.ts +4 -4
  36. package/src/plugins/notion.ts +6 -8
  37. package/src/plugins/plugins.ts +30 -4
  38. package/src/plugins/url.ts +2 -2
  39. package/src/plugins/vim.ts +4 -3
  40. package/src/services/AgentService.ts +17 -0
  41. package/src/services/AgentSyncFs.ts +3 -0
  42. package/src/services/EventService.ts +168 -27
  43. package/src/services/KnowhowClient.ts +1 -0
  44. package/src/services/SessionManager.ts +51 -1
  45. package/src/services/SyncedAgentWatcher.ts +397 -0
  46. package/src/services/SyncerService.ts +147 -0
  47. package/src/services/index.ts +2 -0
  48. package/src/services/modules/index.ts +14 -3
  49. package/src/types.ts +25 -0
  50. package/src/worker.ts +80 -2
  51. package/src/workers/auth/PasskeySetup.ts +185 -0
  52. package/src/workers/auth/WorkerPasskeyAuth.ts +190 -0
  53. package/src/workers/auth/types.ts +58 -0
  54. package/src/workers/tools/getChallenge.ts +33 -0
  55. package/src/workers/tools/index.ts +8 -0
  56. package/src/workers/tools/lock.ts +31 -0
  57. package/src/workers/tools/unlock.ts +116 -0
  58. package/tests/unit/modules/moduleLoading.test.ts +226 -0
  59. package/tests/unit/plugins/pluginLoading.test.ts +151 -0
  60. package/ts_build/package.json +4 -2
  61. package/ts_build/src/agents/base/base.d.ts +4 -3
  62. package/ts_build/src/agents/base/base.js +54 -30
  63. package/ts_build/src/agents/base/base.js.map +1 -1
  64. package/ts_build/src/agents/index.d.ts +3 -0
  65. package/ts_build/src/agents/index.js +21 -11
  66. package/ts_build/src/agents/index.js.map +1 -1
  67. package/ts_build/src/agents/tools/startAgentTask.js +2 -1
  68. package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
  69. package/ts_build/src/chat/CliChatService.js +16 -5
  70. package/ts_build/src/chat/CliChatService.js.map +1 -1
  71. package/ts_build/src/chat/modules/AgentModule.d.ts +34 -17
  72. package/ts_build/src/chat/modules/AgentModule.js +248 -258
  73. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  74. package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -1
  75. package/ts_build/src/chat/modules/InternalChatModule.d.ts +3 -0
  76. package/ts_build/src/chat/modules/InternalChatModule.js +16 -1
  77. package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
  78. package/ts_build/src/chat/modules/RendererModule.d.ts +16 -0
  79. package/ts_build/src/chat/modules/RendererModule.js +76 -0
  80. package/ts_build/src/chat/modules/RendererModule.js.map +1 -0
  81. package/ts_build/src/chat/modules/SessionsModule.d.ts +33 -0
  82. package/ts_build/src/chat/modules/SessionsModule.js +582 -0
  83. package/ts_build/src/chat/modules/SessionsModule.js.map +1 -0
  84. package/ts_build/src/chat/modules/SetupModule.d.ts +3 -3
  85. package/ts_build/src/chat/modules/SetupModule.js +4 -6
  86. package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
  87. package/ts_build/src/chat/modules/index.d.ts +1 -0
  88. package/ts_build/src/chat/modules/index.js +3 -1
  89. package/ts_build/src/chat/modules/index.js.map +1 -1
  90. package/ts_build/src/chat/renderer/CompactRenderer.d.ts +23 -0
  91. package/ts_build/src/chat/renderer/CompactRenderer.js +167 -0
  92. package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -0
  93. package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +22 -0
  94. package/ts_build/src/chat/renderer/ConsoleRenderer.js +110 -0
  95. package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -0
  96. package/ts_build/src/chat/renderer/FancyRenderer.d.ts +23 -0
  97. package/ts_build/src/chat/renderer/FancyRenderer.js +328 -0
  98. package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -0
  99. package/ts_build/src/chat/renderer/index.d.ts +5 -0
  100. package/ts_build/src/chat/renderer/index.js +29 -0
  101. package/ts_build/src/chat/renderer/index.js.map +1 -0
  102. package/ts_build/src/chat/renderer/loadRenderer.d.ts +4 -0
  103. package/ts_build/src/chat/renderer/loadRenderer.js +246 -0
  104. package/ts_build/src/chat/renderer/loadRenderer.js.map +1 -0
  105. package/ts_build/src/chat/renderer/messagesToRenderEvents.d.ts +15 -0
  106. package/ts_build/src/chat/renderer/messagesToRenderEvents.js +72 -0
  107. package/ts_build/src/chat/renderer/messagesToRenderEvents.js.map +1 -0
  108. package/ts_build/src/chat/renderer/types.d.ts +75 -0
  109. package/ts_build/src/chat/renderer/types.js +3 -0
  110. package/ts_build/src/chat/renderer/types.js.map +1 -0
  111. package/ts_build/src/chat/types.d.ts +5 -0
  112. package/ts_build/src/chat.js +46 -4
  113. package/ts_build/src/chat.js.map +1 -1
  114. package/ts_build/src/cli.js +18 -5
  115. package/ts_build/src/cli.js.map +1 -1
  116. package/ts_build/src/config.d.ts +1 -0
  117. package/ts_build/src/config.js +17 -1
  118. package/ts_build/src/config.js.map +1 -1
  119. package/ts_build/src/plugins/AgentsMdPlugin.js +1 -1
  120. package/ts_build/src/plugins/AgentsMdPlugin.js.map +1 -1
  121. package/ts_build/src/plugins/GitPlugin.js +20 -20
  122. package/ts_build/src/plugins/GitPlugin.js.map +1 -1
  123. package/ts_build/src/plugins/PluginBase.d.ts +1 -0
  124. package/ts_build/src/plugins/PluginBase.js +13 -0
  125. package/ts_build/src/plugins/PluginBase.js.map +1 -1
  126. package/ts_build/src/plugins/SkillsPlugin.d.ts +13 -0
  127. package/ts_build/src/plugins/SkillsPlugin.js +149 -0
  128. package/ts_build/src/plugins/SkillsPlugin.js.map +1 -0
  129. package/ts_build/src/plugins/asana.js +4 -4
  130. package/ts_build/src/plugins/asana.js.map +1 -1
  131. package/ts_build/src/plugins/embedding.js +3 -3
  132. package/ts_build/src/plugins/embedding.js.map +1 -1
  133. package/ts_build/src/plugins/exec.js +3 -3
  134. package/ts_build/src/plugins/exec.js.map +1 -1
  135. package/ts_build/src/plugins/figma.js +3 -3
  136. package/ts_build/src/plugins/figma.js.map +1 -1
  137. package/ts_build/src/plugins/github.js +18 -18
  138. package/ts_build/src/plugins/github.js.map +1 -1
  139. package/ts_build/src/plugins/jira.js +2 -2
  140. package/ts_build/src/plugins/jira.js.map +1 -1
  141. package/ts_build/src/plugins/language.js +4 -4
  142. package/ts_build/src/plugins/language.js.map +1 -1
  143. package/ts_build/src/plugins/linear.js +4 -4
  144. package/ts_build/src/plugins/linear.js.map +1 -1
  145. package/ts_build/src/plugins/notion.js +6 -6
  146. package/ts_build/src/plugins/notion.js.map +1 -1
  147. package/ts_build/src/plugins/plugins.d.ts +3 -0
  148. package/ts_build/src/plugins/plugins.js +19 -4
  149. package/ts_build/src/plugins/plugins.js.map +1 -1
  150. package/ts_build/src/plugins/url.js +2 -2
  151. package/ts_build/src/plugins/url.js.map +1 -1
  152. package/ts_build/src/plugins/vim.js +2 -2
  153. package/ts_build/src/plugins/vim.js.map +1 -1
  154. package/ts_build/src/services/AgentService.d.ts +3 -0
  155. package/ts_build/src/services/AgentService.js +7 -0
  156. package/ts_build/src/services/AgentService.js.map +1 -1
  157. package/ts_build/src/services/AgentSyncFs.d.ts +1 -0
  158. package/ts_build/src/services/AgentSyncFs.js +2 -0
  159. package/ts_build/src/services/AgentSyncFs.js.map +1 -1
  160. package/ts_build/src/services/EventService.d.ts +25 -2
  161. package/ts_build/src/services/EventService.js +92 -14
  162. package/ts_build/src/services/EventService.js.map +1 -1
  163. package/ts_build/src/services/KnowhowClient.d.ts +1 -0
  164. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  165. package/ts_build/src/services/SessionManager.d.ts +6 -0
  166. package/ts_build/src/services/SessionManager.js +39 -1
  167. package/ts_build/src/services/SessionManager.js.map +1 -1
  168. package/ts_build/src/services/SyncedAgentWatcher.d.ts +101 -0
  169. package/ts_build/src/services/SyncedAgentWatcher.js +312 -0
  170. package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -0
  171. package/ts_build/src/services/SyncerService.d.ts +30 -0
  172. package/ts_build/src/services/SyncerService.js +72 -0
  173. package/ts_build/src/services/SyncerService.js.map +1 -0
  174. package/ts_build/src/services/index.d.ts +2 -0
  175. package/ts_build/src/services/index.js +2 -0
  176. package/ts_build/src/services/index.js.map +1 -1
  177. package/ts_build/src/services/modules/index.js +10 -2
  178. package/ts_build/src/services/modules/index.js.map +1 -1
  179. package/ts_build/src/types.d.ts +19 -0
  180. package/ts_build/src/types.js.map +1 -1
  181. package/ts_build/src/worker.d.ts +2 -0
  182. package/ts_build/src/worker.js +59 -4
  183. package/ts_build/src/worker.js.map +1 -1
  184. package/ts_build/src/workers/auth/PasskeySetup.d.ts +10 -0
  185. package/ts_build/src/workers/auth/PasskeySetup.js +131 -0
  186. package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -0
  187. package/ts_build/src/workers/auth/WorkerPasskeyAuth.d.ts +35 -0
  188. package/ts_build/src/workers/auth/WorkerPasskeyAuth.js +129 -0
  189. package/ts_build/src/workers/auth/WorkerPasskeyAuth.js.map +1 -0
  190. package/ts_build/src/workers/auth/types.d.ts +36 -0
  191. package/ts_build/src/workers/auth/types.js +3 -0
  192. package/ts_build/src/workers/auth/types.js.map +1 -0
  193. package/ts_build/src/workers/tools/getChallenge.d.ts +9 -0
  194. package/ts_build/src/workers/tools/getChallenge.js +27 -0
  195. package/ts_build/src/workers/tools/getChallenge.js.map +1 -0
  196. package/ts_build/src/workers/tools/index.d.ts +6 -0
  197. package/ts_build/src/workers/tools/index.js +10 -0
  198. package/ts_build/src/workers/tools/index.js.map +1 -1
  199. package/ts_build/src/workers/tools/lock.d.ts +9 -0
  200. package/ts_build/src/workers/tools/lock.js +27 -0
  201. package/ts_build/src/workers/tools/lock.js.map +1 -0
  202. package/ts_build/src/workers/tools/unlock.d.ts +18 -0
  203. package/ts_build/src/workers/tools/unlock.js +78 -0
  204. package/ts_build/src/workers/tools/unlock.js.map +1 -0
  205. package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +1 -0
  206. package/ts_build/tests/unit/modules/moduleLoading.test.js +187 -0
  207. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -0
  208. package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +1 -0
  209. package/ts_build/tests/unit/plugins/pluginLoading.test.js +123 -0
  210. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -0
@@ -35,10 +35,7 @@ export class GitHubPlugin extends PluginBase {
35
35
  }
36
36
  return false;
37
37
  } catch (error) {
38
- console.error(
39
- "GITHUB PLUGIN: Failed to initialize Octokit client",
40
- error
41
- );
38
+ this.log(`Failed to initialize Octokit client: ${error}`, "error");
42
39
  return false;
43
40
  }
44
41
  }
@@ -76,9 +73,7 @@ export class GitHubPlugin extends PluginBase {
76
73
  async getDiff(url: string) {
77
74
  try {
78
75
  const { owner, repo, pullNumber } = this.parseUrl(url);
79
- console.log(
80
- `GITHUB PLUGIN: Loading diff for ${owner}/${repo}#${pullNumber}`
81
- );
76
+ this.log(`Loading diff for ${owner}/${repo}#${pullNumber}`);
82
77
  const { data: diff } = await this.octokit.rest.pulls.get({
83
78
  owner,
84
79
  repo,
@@ -90,9 +85,9 @@ export class GitHubPlugin extends PluginBase {
90
85
 
91
86
  return diff;
92
87
  } catch (error) {
93
- console.error(`GITHUB PLUGIN: Failed to get diff for ${url}:`, error.message);
88
+ this.log(`Failed to get diff for ${url}: ${error.message}`, "error");
94
89
  if (error.status === 401) {
95
- console.error("GITHUB PLUGIN: Authentication failed. Please check your GITHUB_TOKEN.");
90
+ this.log("Authentication failed. Please check your GITHUB_TOKEN.", "error");
96
91
  }
97
92
  return null;
98
93
  }
@@ -107,9 +102,9 @@ export class GitHubPlugin extends PluginBase {
107
102
  pull_number: parseInt(pullNumber, 10),
108
103
  });
109
104
  } catch (error) {
110
- console.error(`GITHUB PLUGIN: Failed to get PR for ${url}:`, error.message);
105
+ this.log(`Failed to get PR for ${url}: ${error.message}`, "error");
111
106
  if (error.status === 401) {
112
- console.error("GITHUB PLUGIN: Authentication failed. Please check your GITHUB_TOKEN.");
107
+ this.log("Authentication failed. Please check your GITHUB_TOKEN.", "error");
113
108
  }
114
109
  return null;
115
110
  }
@@ -119,7 +114,7 @@ export class GitHubPlugin extends PluginBase {
119
114
  const length = hunks
120
115
  .flatMap((hunk) => [...hunk.additions, ...hunk.subtractions])
121
116
  .reduce((acc, line) => acc + line.length, 0);
122
- console.log(`GITHUB PLUGIN: Length of hunks: ${length}`);
117
+ this.log(`Length of hunks: ${length}`);
123
118
  return length;
124
119
  }
125
120
 
@@ -131,13 +126,13 @@ export class GitHubPlugin extends PluginBase {
131
126
 
132
127
  // If getDiff returned null (auth error), skip this URL
133
128
  if (!diff) {
134
- console.log(`GITHUB PLUGIN: Skipping ${url} due to error`);
129
+ this.log(`Skipping ${url} due to error`);
135
130
  return null;
136
131
  }
137
132
 
138
133
  let parsed = parseHunks(diff.toString());
139
134
 
140
- console.log(`GITHUB PLUGIN: Parsed ${parsed.length} hunks`);
135
+ this.log(`Parsed ${parsed.length} hunks`);
141
136
 
142
137
  const averageHunkSize =
143
138
  parsed.reduce((acc, hunk) => acc + hunk.lines.length, 0) /
@@ -147,9 +142,7 @@ export class GitHubPlugin extends PluginBase {
147
142
  .flatMap((hunk) => [...hunk.additions, ...hunk.subtractions])
148
143
  .reduce((acc, line) => acc + line.length, 0);
149
144
 
150
- console.log(
151
- `GITHUB PLUGIN: Average hunk size: ${averageHunkSize}, total characters: ${totalCharacters}`
152
- );
145
+ this.log(`Average hunk size: ${averageHunkSize}, total characters: ${totalCharacters}`);
153
146
 
154
147
  const MAX_CHARACTERS = 10000;
155
148
  const average = MAX_CHARACTERS / averageHunkSize;
@@ -159,14 +152,10 @@ export class GitHubPlugin extends PluginBase {
159
152
  return this.getLengthOfHunks([hunk]) <= PER_HUNK_LIMIT;
160
153
  });
161
154
 
162
- console.log(
163
- `GITHUB PLUGIN: Filtered to ${
164
- parsed.length
165
- } hunks. ${this.getLengthOfHunks(parsed)} characters`
166
- );
155
+ this.log(`Filtered to ${parsed.length} hunks. ${this.getLengthOfHunks(parsed)} characters`);
167
156
  return parsed;
168
157
  } catch (error) {
169
- console.error(`GITHUB PLUGIN: Error parsing diff for ${url}:`, error.message);
158
+ this.log(`Error parsing diff for ${url}: ${error.message}`, "error");
170
159
  return null;
171
160
  }
172
161
  })
@@ -188,7 +177,7 @@ export class GitHubPlugin extends PluginBase {
188
177
 
189
178
  // Skip this PR if we couldn't get its data
190
179
  if (!prResponse) {
191
- console.log(`GITHUB PLUGIN: Skipping ${url} - could not fetch PR data`);
180
+ this.log(`Skipping ${url} - could not fetch PR data`);
192
181
  continue;
193
182
  }
194
183
 
@@ -210,21 +199,21 @@ export class GitHubPlugin extends PluginBase {
210
199
  }
211
200
 
212
201
  if (prs.length === 0) {
213
- return "GITHUB PLUGIN: Could not fetch any pull request data. Please check your GITHUB_TOKEN and permissions.";
202
+ return "Could not fetch any pull request data. Please check your GITHUB_TOKEN and permissions.";
214
203
  }
215
204
 
216
- const context = `GITHUB PLUGIN: These ${urls} have automatically been expanded to include the changes:\n\n${JSON.stringify(
205
+ const context = `These ${urls} have automatically been expanded to include the changes:\n\n${JSON.stringify(
217
206
  prs,
218
207
  null,
219
208
  2
220
209
  )}`;
221
- console.log(context);
210
+ this.log(context);
222
211
  return context;
223
212
  } catch (error) {
224
- return `GITHUB PLUGIN: Error fetching pull request data: ${error.message}`;
213
+ return `Error fetching pull request data: ${error.message}`;
225
214
  }
226
215
  }
227
216
 
228
- return "GITHUB PLUGIN: No pull request URLs detected.";
217
+ return "No pull request URLs detected.";
229
218
  }
230
219
  }
@@ -53,7 +53,7 @@ export class JiraPlugin extends PluginBase {
53
53
  async getTaskFromUrl(url: string) {
54
54
  const issueId = this.extractIdFromUrl(url);
55
55
  if (issueId) {
56
- console.log(`Fetching Jira issue ${issueId}`);
56
+ this.log(`Fetching Jira issue ${issueId}`);
57
57
  return await this.getIssueData(issueId);
58
58
  }
59
59
  return null;
@@ -64,7 +64,7 @@ export class JiraPlugin extends PluginBase {
64
64
  const issue = await this.jiraClient.findIssue(issueId);
65
65
  return issue;
66
66
  } catch (error) {
67
- console.error("Error fetching Jira issue:", error);
67
+ this.log(`Error fetching Jira issue: ${error}`, "error");
68
68
  return null;
69
69
  }
70
70
  }
@@ -67,7 +67,7 @@ export class LanguagePlugin extends PluginBase implements Plugin {
67
67
  });
68
68
  });
69
69
  } catch (error) {
70
- console.error("LANGUAGE PLUGIN: Error setting up event handlers:", error);
70
+ this.log("LANGUAGE PLUGIN: Error setting up event handlers: " + error, "error");
71
71
  }
72
72
  }
73
73
 
@@ -184,7 +184,7 @@ export class LanguagePlugin extends PluginBase implements Plugin {
184
184
  );
185
185
  }
186
186
  } catch (error) {
187
- console.error("LANGUAGE PLUGIN: Error handling file event:", error);
187
+ this.log("LANGUAGE PLUGIN: Error handling file event: " + error, "error");
188
188
  }
189
189
  }
190
190
 
@@ -245,7 +245,7 @@ export class LanguagePlugin extends PluginBase implements Plugin {
245
245
  );
246
246
  }
247
247
  } catch (error) {
248
- console.error("LANGUAGE PLUGIN: Error handling agent event:", error);
248
+ this.log("LANGUAGE PLUGIN: Error handling agent event: " + error, "error");
249
249
  }
250
250
  }
251
251
 
@@ -282,7 +282,7 @@ export class LanguagePlugin extends PluginBase implements Plugin {
282
282
  // Use the extracted resolveSources method
283
283
  const contexts = await this.resolveSources(matchingTerms);
284
284
 
285
- console.log("LANGUAGE PLUGIN: Matching terms found:", matchingTerms);
285
+ this.log("LANGUAGE PLUGIN: Matching terms found: " + matchingTerms);
286
286
 
287
287
  const output = contexts.every((c) => typeof c === "string")
288
288
  ? contexts.join("")
@@ -79,7 +79,7 @@ export class LinearPlugin extends PluginBase {
79
79
  const issue = await this.linearClient.issue(issueId);
80
80
  return issue;
81
81
  } catch (error) {
82
- console.error("Error fetching Linear issue:", error);
82
+ this.log(`Error fetching Linear issue: ${error}`, "error");
83
83
  return null;
84
84
  }
85
85
  }
@@ -87,7 +87,7 @@ export class LinearPlugin extends PluginBase {
87
87
  async getTaskFromUrl(url: string) {
88
88
  const issueId = this.getIdFromUrl(url);
89
89
  if (issueId) {
90
- console.log(`Fetching Linear issue ${issueId}`);
90
+ this.log(`Fetching Linear issue ${issueId}`);
91
91
  return await this.getIssueData(issueId);
92
92
  }
93
93
  return null;
@@ -135,7 +135,7 @@ export class LinearPlugin extends PluginBase {
135
135
  }
136
136
 
137
137
  async getTasksForProject(projectId: string) {
138
- console.log({ projectId });
138
+ this.log(`Project ID: ${projectId}`);
139
139
  let tasks = await this.linearClient.issues({
140
140
  filter: {
141
141
  project: { slugId: { eq: projectId } },
@@ -161,7 +161,7 @@ export class LinearPlugin extends PluginBase {
161
161
  }
162
162
 
163
163
  async getTasksForTeam(teamId: string) {
164
- console.log({ teamId });
164
+ this.log(`Team ID: ${teamId}`);
165
165
  let tasks = await this.linearClient.issues({
166
166
  filter: {
167
167
  team: { key: { eq: teamId } },
@@ -58,9 +58,7 @@ export class NotionPlugin extends PluginBase {
58
58
  if (processed[pageId] || currentDepth > maxDepth) {
59
59
  return { results: [] };
60
60
  }
61
- console.log(
62
- `Notion Plugin: Fetching all blocks for page ${pageId} at depth ${currentDepth}`
63
- );
61
+ this.log(`Fetching all blocks for page ${pageId} at depth ${currentDepth}`);
64
62
  processed[pageId] = true;
65
63
  const response = await this.notionClient.blocks.children.list({
66
64
  block_id: pageId,
@@ -68,7 +66,7 @@ export class NotionPlugin extends PluginBase {
68
66
 
69
67
  let cursor = response.next_cursor;
70
68
  while (cursor) {
71
- console.log("Fetching more blocks");
69
+ this.log("Fetching more blocks");
72
70
  const childResponse = await this.notionClient.blocks.children.list({
73
71
  block_id: pageId,
74
72
  start_cursor: cursor,
@@ -109,7 +107,7 @@ export class NotionPlugin extends PluginBase {
109
107
  (b) => "has_children" in b && b.has_children
110
108
  );
111
109
 
112
- console.log(JSON.stringify(results, null, 2));
110
+ this.log(JSON.stringify(results, null, 2));
113
111
 
114
112
  const childBlocks = await Promise.all(
115
113
  childPages.map(async (childPage) => {
@@ -133,7 +131,7 @@ export class NotionPlugin extends PluginBase {
133
131
  }
134
132
  }
135
133
 
136
- console.log(JSON.stringify(embeddings, null, 2));
134
+ this.log(JSON.stringify(embeddings, null, 2));
137
135
  return embeddings;
138
136
  }
139
137
 
@@ -147,7 +145,7 @@ export class NotionPlugin extends PluginBase {
147
145
  async getPageFromUrl(url: string) {
148
146
  const pageId = url.split("-").pop();
149
147
  if (pageId) {
150
- console.log(`Fetching Notion page ${pageId}`);
148
+ this.log(`Fetching Notion page ${pageId}`);
151
149
  const page = await this.notionClient.pages.retrieve({ page_id: pageId });
152
150
  const blocks = await this.getAllChildBlocks(page.id);
153
151
  return { page, blocks };
@@ -175,7 +173,7 @@ export class NotionPlugin extends PluginBase {
175
173
  const markdownPages = pagesDataFiltered
176
174
  .map((page) => `### Page: ${JSON.stringify(page, null, 2)}\n-`)
177
175
  .join("\n\n");
178
- console.log(markdownPages);
176
+ this.log(markdownPages);
179
177
  return `NOTION PLUGIN: The following pages were loaded:\n\n${markdownPages}`;
180
178
  }
181
179
  }
@@ -1,4 +1,5 @@
1
1
  import { Plugin, PluginContext } from "./types";
2
+ import { Config } from "../types";
2
3
  import { VimPlugin } from "./vim";
3
4
  import { LinterPlugin } from "./LinterPlugin";
4
5
  import { LanguagePlugin } from "./language";
@@ -17,11 +18,15 @@ import { AgentsMdPlugin } from "./AgentsMdPlugin";
17
18
  import { ExecPlugin } from "./exec";
18
19
  import { getConfig } from "../config";
19
20
  import { getDisabledPlugins } from "../types";
21
+ import { SkillsPlugin } from "./SkillsPlugin";
22
+ import { EventService } from "../services/EventService";
20
23
 
21
24
  export class PluginService {
22
25
  private pluginMap = new Map<string, Plugin>();
26
+ private events?: EventService;
23
27
 
24
28
  constructor(context: PluginContext) {
29
+ this.events = context.Events;
25
30
  context.Plugins = this;
26
31
 
27
32
  // Register migrated PluginBase plugins
@@ -41,6 +46,7 @@ export class PluginService {
41
46
  this.pluginMap.set("tmux", new TmuxPlugin(context));
42
47
  this.pluginMap.set("agents-md", new AgentsMdPlugin(context));
43
48
  this.pluginMap.set("exec", new ExecPlugin(context));
49
+ this.pluginMap.set("skills", new SkillsPlugin(context));
44
50
  }
45
51
 
46
52
  /* -------- lifecycle helpers ------------------------------------ */
@@ -57,6 +63,26 @@ export class PluginService {
57
63
  return instance.meta.key;
58
64
  }
59
65
 
66
+ /**
67
+ * Load plugins from config's pluginPackages map.
68
+ * Each entry maps a plugin key to an npm package name or file path.
69
+ * Errors are caught and logged as warnings without crashing.
70
+ */
71
+ async loadPluginsFromConfig(config: Config): Promise<void> {
72
+ const pluginPackages = config.pluginPackages || {};
73
+ for (const [key, spec] of Object.entries(pluginPackages)) {
74
+ try {
75
+ await this.loadPlugin(spec);
76
+ } catch (error) {
77
+ this.events?.log(
78
+ "PluginService",
79
+ `Failed to load plugin "${key}" from "${spec}": ${error instanceof Error ? error.message : error}`,
80
+ "warn"
81
+ );
82
+ }
83
+ }
84
+ }
85
+
60
86
  /** Disable a plugin by its key; returns `true` if found. */
61
87
  disablePlugin(key: string): boolean {
62
88
  const p = this.pluginMap.get(key);
@@ -101,7 +127,7 @@ export class PluginService {
101
127
  return "";
102
128
  }
103
129
  const calls = plugins.map(async (p) => {
104
- return this.callManyForPlugin(p, userInput).catch();
130
+ return this.callManyForPlugin(p, userInput).catch(() => "");
105
131
  });
106
132
 
107
133
  const results = await Promise.all(calls);
@@ -118,7 +144,7 @@ export class PluginService {
118
144
 
119
145
  const enabled = await newPlugin.isEnabled();
120
146
  if (!enabled) {
121
- console.log(`Plugin ${kind} is disabled, skipping`);
147
+ this.events?.log("PluginService", `Plugin ${kind} is disabled, skipping`);
122
148
  return "";
123
149
  }
124
150
  return newPlugin.call(userInput);
@@ -134,7 +160,7 @@ export class PluginService {
134
160
 
135
161
  const enabled = await newPlugin.isEnabled();
136
162
  if (!enabled) {
137
- console.log(`Plugin ${kind} is disabled, skipping`);
163
+ this.events?.log("PluginService", `Plugin ${kind} is disabled, skipping`);
138
164
  return "";
139
165
  }
140
166
  return newPlugin.callMany(userInput);
@@ -149,7 +175,7 @@ export class PluginService {
149
175
 
150
176
  const enabled = await newPlugin.isEnabled();
151
177
  if (!enabled) {
152
- console.log(`Plugin ${kind} is disabled, skipping`);
178
+ this.events?.log("PluginService", `Plugin ${kind} is disabled, skipping`);
153
179
  return [];
154
180
  }
155
181
  return newPlugin.embed ? newPlugin.embed(userInput) : [];
@@ -35,7 +35,7 @@ export class UrlPlugin extends PluginBase implements Plugin {
35
35
  try {
36
36
  const text = await loadWebpage(url);
37
37
 
38
- console.log(`URL PLUGIN: Fetched content from ${url}:`, text);
38
+ this.log(`URL PLUGIN: Fetched content from ${url}: ${text}`);
39
39
 
40
40
  return {
41
41
  id: url + "-url",
@@ -43,7 +43,7 @@ export class UrlPlugin extends PluginBase implements Plugin {
43
43
  metadata: { url },
44
44
  };
45
45
  } catch (error) {
46
- console.error(`Error fetching or parsing URL ${url}:`, error);
46
+ this.log(`Error fetching or parsing URL ${url}: ${error}`, "error");
47
47
  return null;
48
48
  }
49
49
  }
@@ -59,13 +59,14 @@ export class VimPlugin extends PluginBase {
59
59
  return { filePath, content: "DIRECTORY" };
60
60
  }
61
61
  if (stat.size > 32000) {
62
- console.error(
63
- `VIM PLUGIN: File ${filePath} is too large with size ${stat.size}`
62
+ this.log(
63
+ `VIM PLUGIN: File ${filePath} is too large with size ${stat.size}`,
64
+ "error"
64
65
  );
65
66
  return { filePath, content: "FILE TOO LARGE" };
66
67
  }
67
68
 
68
- console.log(`VIM PLUGIN: Reading file ${filePath}`);
69
+ this.log(`VIM PLUGIN: Reading file ${filePath}`);
69
70
  const content = await readFile(filePath, "utf8");
70
71
  return { filePath, content };
71
72
  }
@@ -7,6 +7,7 @@ import { AgentContext } from "../agents/base/base";
7
7
 
8
8
  export class AgentService {
9
9
  private agents: Map<string, IAgent> = new Map();
10
+ private agentContext: AgentContext | null = null;
10
11
 
11
12
  constructor(private tools: ToolsService, private events: EventService) {
12
13
  this.wireUp();
@@ -57,6 +58,22 @@ export class AgentService {
57
58
  this.agents.set(name, agent);
58
59
  }
59
60
 
61
+ /**
62
+ * Set the AgentContext that will be used when creating new agent instances.
63
+ * Should be called from cli.ts after all services are wired up (including LazyToolsService).
64
+ */
65
+ public setAgentContext(context: AgentContext): void {
66
+ this.agentContext = context;
67
+ }
68
+
69
+ /**
70
+ * Get the current AgentContext. Falls back to a minimal context using this service's
71
+ * own tools/events if none has been explicitly set.
72
+ */
73
+ public getAgentContext(): AgentContext {
74
+ return this.agentContext ?? { Tools: this.tools, Events: this.events };
75
+ }
76
+
60
77
  public getAgent(name: string): IAgent {
61
78
  const agent = this.agents.get(name);
62
79
  if (!agent) {
@@ -10,6 +10,7 @@ import { watch } from "fs";
10
10
  export interface FsSyncOptions {
11
11
  taskId: string;
12
12
  prompt: string;
13
+ agentName?: string;
13
14
  }
14
15
 
15
16
  /**
@@ -51,6 +52,7 @@ export class AgentSyncFs {
51
52
  await this.writeMetadata({
52
53
  taskId: this.taskId,
53
54
  prompt: options.prompt,
55
+ agentName: options.agentName || "unknown",
54
56
  startTime: new Date().toISOString(),
55
57
  status: "running",
56
58
  });
@@ -125,6 +127,7 @@ export class AgentSyncFs {
125
127
 
126
128
  metadata.threads = agent.getThreads();
127
129
  metadata.totalCostUsd = agent.getTotalCostUsd();
130
+ metadata.agentName = agent.name;
128
131
  metadata.inProgress = inProgress;
129
132
  metadata.lastUpdate = new Date().toISOString();
130
133