@asermax/tachikoma 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/README.md +64 -0
  2. package/dist/agent/adapter.d.ts +8 -0
  3. package/dist/agent/adapter.js +86 -0
  4. package/dist/agent/adapter.js.map +1 -0
  5. package/dist/agent/manager.d.ts +35 -0
  6. package/dist/agent/manager.js +76 -0
  7. package/dist/agent/manager.js.map +1 -0
  8. package/dist/agent/models.d.ts +46 -0
  9. package/dist/agent/models.js +96 -0
  10. package/dist/agent/models.js.map +1 -0
  11. package/dist/agent/side-run.d.ts +42 -0
  12. package/dist/agent/side-run.js +83 -0
  13. package/dist/agent/side-run.js.map +1 -0
  14. package/dist/app.d.ts +5 -0
  15. package/dist/app.js +79 -0
  16. package/dist/app.js.map +1 -0
  17. package/dist/channels/types.d.ts +37 -0
  18. package/dist/channels/types.js +5 -0
  19. package/dist/channels/types.js.map +1 -0
  20. package/dist/config/default-template.d.ts +1 -0
  21. package/dist/config/default-template.js +49 -0
  22. package/dist/config/default-template.js.map +1 -0
  23. package/dist/config/load.d.ts +8 -0
  24. package/dist/config/load.js +28 -0
  25. package/dist/config/load.js.map +1 -0
  26. package/dist/config/parse.d.ts +5 -0
  27. package/dist/config/parse.js +18 -0
  28. package/dist/config/parse.js.map +1 -0
  29. package/dist/config/schema.d.ts +29 -0
  30. package/dist/config/schema.js +35 -0
  31. package/dist/config/schema.js.map +1 -0
  32. package/dist/coordinator.d.ts +54 -0
  33. package/dist/coordinator.js +344 -0
  34. package/dist/coordinator.js.map +1 -0
  35. package/dist/db/core-schema.d.ts +250 -0
  36. package/dist/db/core-schema.js +19 -0
  37. package/dist/db/core-schema.js.map +1 -0
  38. package/dist/db/index.d.ts +8 -0
  39. package/dist/db/index.js +16 -0
  40. package/dist/db/index.js.map +1 -0
  41. package/dist/db/schema.d.ts +4 -0
  42. package/dist/db/schema.js +7 -0
  43. package/dist/db/schema.js.map +1 -0
  44. package/dist/db/state.d.ts +10 -0
  45. package/dist/db/state.js +36 -0
  46. package/dist/db/state.js.map +1 -0
  47. package/dist/domain/agent-events.d.ts +26 -0
  48. package/dist/domain/agent-events.js +2 -0
  49. package/dist/domain/agent-events.js.map +1 -0
  50. package/dist/domain/message.d.ts +25 -0
  51. package/dist/domain/message.js +17 -0
  52. package/dist/domain/message.js.map +1 -0
  53. package/dist/events.d.ts +9 -0
  54. package/dist/events.js +27 -0
  55. package/dist/events.js.map +1 -0
  56. package/dist/extensions/api.d.ts +118 -0
  57. package/dist/extensions/api.js +7 -0
  58. package/dist/extensions/api.js.map +1 -0
  59. package/dist/extensions/boundary/detector.d.ts +20 -0
  60. package/dist/extensions/boundary/detector.js +57 -0
  61. package/dist/extensions/boundary/detector.js.map +1 -0
  62. package/dist/extensions/boundary/idle.d.ts +10 -0
  63. package/dist/extensions/boundary/idle.js +28 -0
  64. package/dist/extensions/boundary/idle.js.map +1 -0
  65. package/dist/extensions/boundary/index.d.ts +12 -0
  66. package/dist/extensions/boundary/index.js +65 -0
  67. package/dist/extensions/boundary/index.js.map +1 -0
  68. package/dist/extensions/boundary/summary.d.ts +5 -0
  69. package/dist/extensions/boundary/summary.js +33 -0
  70. package/dist/extensions/boundary/summary.js.map +1 -0
  71. package/dist/extensions/commands/index.d.ts +7 -0
  72. package/dist/extensions/commands/index.js +21 -0
  73. package/dist/extensions/commands/index.js.map +1 -0
  74. package/dist/extensions/context/index.d.ts +7 -0
  75. package/dist/extensions/context/index.js +65 -0
  76. package/dist/extensions/context/index.js.map +1 -0
  77. package/dist/extensions/context/processor.d.ts +27 -0
  78. package/dist/extensions/context/processor.js +228 -0
  79. package/dist/extensions/context/processor.js.map +1 -0
  80. package/dist/extensions/detached-processes/index.d.ts +12 -0
  81. package/dist/extensions/detached-processes/index.js +51 -0
  82. package/dist/extensions/detached-processes/index.js.map +1 -0
  83. package/dist/extensions/detached-processes/limits.d.ts +27 -0
  84. package/dist/extensions/detached-processes/limits.js +55 -0
  85. package/dist/extensions/detached-processes/limits.js.map +1 -0
  86. package/dist/extensions/detached-processes/output.d.ts +2 -0
  87. package/dist/extensions/detached-processes/output.js +26 -0
  88. package/dist/extensions/detached-processes/output.js.map +1 -0
  89. package/dist/extensions/detached-processes/reconcile.d.ts +31 -0
  90. package/dist/extensions/detached-processes/reconcile.js +71 -0
  91. package/dist/extensions/detached-processes/reconcile.js.map +1 -0
  92. package/dist/extensions/detached-processes/repository.d.ts +33 -0
  93. package/dist/extensions/detached-processes/repository.js +62 -0
  94. package/dist/extensions/detached-processes/repository.js.map +1 -0
  95. package/dist/extensions/detached-processes/schema.d.ts +252 -0
  96. package/dist/extensions/detached-processes/schema.js +23 -0
  97. package/dist/extensions/detached-processes/schema.js.map +1 -0
  98. package/dist/extensions/detached-processes/spawn.d.ts +40 -0
  99. package/dist/extensions/detached-processes/spawn.js +137 -0
  100. package/dist/extensions/detached-processes/spawn.js.map +1 -0
  101. package/dist/extensions/detached-processes/tools.d.ts +41 -0
  102. package/dist/extensions/detached-processes/tools.js +243 -0
  103. package/dist/extensions/detached-processes/tools.js.map +1 -0
  104. package/dist/extensions/detached-processes/watcher.d.ts +7 -0
  105. package/dist/extensions/detached-processes/watcher.js +19 -0
  106. package/dist/extensions/detached-processes/watcher.js.map +1 -0
  107. package/dist/extensions/external/index.d.ts +11 -0
  108. package/dist/extensions/external/index.js +40 -0
  109. package/dist/extensions/external/index.js.map +1 -0
  110. package/dist/extensions/external/installs.d.ts +39 -0
  111. package/dist/extensions/external/installs.js +98 -0
  112. package/dist/extensions/external/installs.js.map +1 -0
  113. package/dist/extensions/external/loader.d.ts +19 -0
  114. package/dist/extensions/external/loader.js +70 -0
  115. package/dist/extensions/external/loader.js.map +1 -0
  116. package/dist/extensions/external/tools.d.ts +17 -0
  117. package/dist/extensions/external/tools.js +112 -0
  118. package/dist/extensions/external/tools.js.map +1 -0
  119. package/dist/extensions/git/commit.d.ts +19 -0
  120. package/dist/extensions/git/commit.js +44 -0
  121. package/dist/extensions/git/commit.js.map +1 -0
  122. package/dist/extensions/git/git.d.ts +11 -0
  123. package/dist/extensions/git/git.js +29 -0
  124. package/dist/extensions/git/git.js.map +1 -0
  125. package/dist/extensions/git/hooks.d.ts +10 -0
  126. package/dist/extensions/git/hooks.js +88 -0
  127. package/dist/extensions/git/hooks.js.map +1 -0
  128. package/dist/extensions/git/index.d.ts +11 -0
  129. package/dist/extensions/git/index.js +28 -0
  130. package/dist/extensions/git/index.js.map +1 -0
  131. package/dist/extensions/git/processor.d.ts +13 -0
  132. package/dist/extensions/git/processor.js +52 -0
  133. package/dist/extensions/git/processor.js.map +1 -0
  134. package/dist/extensions/git/sync.d.ts +44 -0
  135. package/dist/extensions/git/sync.js +189 -0
  136. package/dist/extensions/git/sync.js.map +1 -0
  137. package/dist/extensions/git/tools.d.ts +21 -0
  138. package/dist/extensions/git/tools.js +101 -0
  139. package/dist/extensions/git/tools.js.map +1 -0
  140. package/dist/extensions/host.d.ts +31 -0
  141. package/dist/extensions/host.js +75 -0
  142. package/dist/extensions/host.js.map +1 -0
  143. package/dist/extensions/index.d.ts +3 -0
  144. package/dist/extensions/index.js +32 -0
  145. package/dist/extensions/index.js.map +1 -0
  146. package/dist/extensions/memory/archive.d.ts +8 -0
  147. package/dist/extensions/memory/archive.js +46 -0
  148. package/dist/extensions/memory/archive.js.map +1 -0
  149. package/dist/extensions/memory/dates.d.ts +2 -0
  150. package/dist/extensions/memory/dates.js +7 -0
  151. package/dist/extensions/memory/dates.js.map +1 -0
  152. package/dist/extensions/memory/extraction.d.ts +17 -0
  153. package/dist/extensions/memory/extraction.js +218 -0
  154. package/dist/extensions/memory/extraction.js.map +1 -0
  155. package/dist/extensions/memory/index.d.ts +20 -0
  156. package/dist/extensions/memory/index.js +67 -0
  157. package/dist/extensions/memory/index.js.map +1 -0
  158. package/dist/extensions/memory/indexes.d.ts +14 -0
  159. package/dist/extensions/memory/indexes.js +64 -0
  160. package/dist/extensions/memory/indexes.js.map +1 -0
  161. package/dist/extensions/memory/layout.d.ts +20 -0
  162. package/dist/extensions/memory/layout.js +79 -0
  163. package/dist/extensions/memory/layout.js.map +1 -0
  164. package/dist/extensions/memory/maintenance.d.ts +21 -0
  165. package/dist/extensions/memory/maintenance.js +357 -0
  166. package/dist/extensions/memory/maintenance.js.map +1 -0
  167. package/dist/extensions/memory/prompts.d.ts +8 -0
  168. package/dist/extensions/memory/prompts.js +125 -0
  169. package/dist/extensions/memory/prompts.js.map +1 -0
  170. package/dist/extensions/memory/transcript.d.ts +18 -0
  171. package/dist/extensions/memory/transcript.js +79 -0
  172. package/dist/extensions/memory/transcript.js.map +1 -0
  173. package/dist/extensions/notifications/format.d.ts +5 -0
  174. package/dist/extensions/notifications/format.js +17 -0
  175. package/dist/extensions/notifications/format.js.map +1 -0
  176. package/dist/extensions/notifications/index.d.ts +13 -0
  177. package/dist/extensions/notifications/index.js +29 -0
  178. package/dist/extensions/notifications/index.js.map +1 -0
  179. package/dist/extensions/notifications/payload.d.ts +22 -0
  180. package/dist/extensions/notifications/payload.js +29 -0
  181. package/dist/extensions/notifications/payload.js.map +1 -0
  182. package/dist/extensions/notifications/router.d.ts +29 -0
  183. package/dist/extensions/notifications/router.js +55 -0
  184. package/dist/extensions/notifications/router.js.map +1 -0
  185. package/dist/extensions/notifications/tools.d.ts +12 -0
  186. package/dist/extensions/notifications/tools.js +41 -0
  187. package/dist/extensions/notifications/tools.js.map +1 -0
  188. package/dist/extensions/projects/context-provider.d.ts +9 -0
  189. package/dist/extensions/projects/context-provider.js +37 -0
  190. package/dist/extensions/projects/context-provider.js.map +1 -0
  191. package/dist/extensions/projects/git.d.ts +28 -0
  192. package/dist/extensions/projects/git.js +91 -0
  193. package/dist/extensions/projects/git.js.map +1 -0
  194. package/dist/extensions/projects/hooks.d.ts +7 -0
  195. package/dist/extensions/projects/hooks.js +42 -0
  196. package/dist/extensions/projects/hooks.js.map +1 -0
  197. package/dist/extensions/projects/index.d.ts +11 -0
  198. package/dist/extensions/projects/index.js +30 -0
  199. package/dist/extensions/projects/index.js.map +1 -0
  200. package/dist/extensions/projects/processor.d.ts +13 -0
  201. package/dist/extensions/projects/processor.js +63 -0
  202. package/dist/extensions/projects/processor.js.map +1 -0
  203. package/dist/extensions/projects/tools.d.ts +21 -0
  204. package/dist/extensions/projects/tools.js +118 -0
  205. package/dist/extensions/projects/tools.js.map +1 -0
  206. package/dist/extensions/registrations.d.ts +21 -0
  207. package/dist/extensions/registrations.js +12 -0
  208. package/dist/extensions/registrations.js.map +1 -0
  209. package/dist/extensions/repl/index.d.ts +2 -0
  210. package/dist/extensions/repl/index.js +85 -0
  211. package/dist/extensions/repl/index.js.map +1 -0
  212. package/dist/extensions/skills/agents.d.ts +17 -0
  213. package/dist/extensions/skills/agents.js +77 -0
  214. package/dist/extensions/skills/agents.js.map +1 -0
  215. package/dist/extensions/skills/delegate.d.ts +22 -0
  216. package/dist/extensions/skills/delegate.js +54 -0
  217. package/dist/extensions/skills/delegate.js.map +1 -0
  218. package/dist/extensions/skills/index.d.ts +11 -0
  219. package/dist/extensions/skills/index.js +43 -0
  220. package/dist/extensions/skills/index.js.map +1 -0
  221. package/dist/extensions/skills/reload.d.ts +8 -0
  222. package/dist/extensions/skills/reload.js +38 -0
  223. package/dist/extensions/skills/reload.js.map +1 -0
  224. package/dist/extensions/tasks/executor.d.ts +43 -0
  225. package/dist/extensions/tasks/executor.js +179 -0
  226. package/dist/extensions/tasks/executor.js.map +1 -0
  227. package/dist/extensions/tasks/expiration.d.ts +12 -0
  228. package/dist/extensions/tasks/expiration.js +17 -0
  229. package/dist/extensions/tasks/expiration.js.map +1 -0
  230. package/dist/extensions/tasks/generation.d.ts +14 -0
  231. package/dist/extensions/tasks/generation.js +70 -0
  232. package/dist/extensions/tasks/generation.js.map +1 -0
  233. package/dist/extensions/tasks/index.d.ts +14 -0
  234. package/dist/extensions/tasks/index.js +75 -0
  235. package/dist/extensions/tasks/index.js.map +1 -0
  236. package/dist/extensions/tasks/repository.d.ts +53 -0
  237. package/dist/extensions/tasks/repository.js +147 -0
  238. package/dist/extensions/tasks/repository.js.map +1 -0
  239. package/dist/extensions/tasks/schedule.d.ts +13 -0
  240. package/dist/extensions/tasks/schedule.js +32 -0
  241. package/dist/extensions/tasks/schedule.js.map +1 -0
  242. package/dist/extensions/tasks/schema.d.ts +423 -0
  243. package/dist/extensions/tasks/schema.js +45 -0
  244. package/dist/extensions/tasks/schema.js.map +1 -0
  245. package/dist/extensions/tasks/session-delivery.d.ts +18 -0
  246. package/dist/extensions/tasks/session-delivery.js +39 -0
  247. package/dist/extensions/tasks/session-delivery.js.map +1 -0
  248. package/dist/extensions/tasks/tools.d.ts +38 -0
  249. package/dist/extensions/tasks/tools.js +181 -0
  250. package/dist/extensions/tasks/tools.js.map +1 -0
  251. package/dist/extensions/telegram/buttons.d.ts +14 -0
  252. package/dist/extensions/telegram/buttons.js +49 -0
  253. package/dist/extensions/telegram/buttons.js.map +1 -0
  254. package/dist/extensions/telegram/channel.d.ts +39 -0
  255. package/dist/extensions/telegram/channel.js +201 -0
  256. package/dist/extensions/telegram/channel.js.map +1 -0
  257. package/dist/extensions/telegram/chunking.d.ts +7 -0
  258. package/dist/extensions/telegram/chunking.js +67 -0
  259. package/dist/extensions/telegram/chunking.js.map +1 -0
  260. package/dist/extensions/telegram/inbound.d.ts +7 -0
  261. package/dist/extensions/telegram/inbound.js +29 -0
  262. package/dist/extensions/telegram/inbound.js.map +1 -0
  263. package/dist/extensions/telegram/index.d.ts +13 -0
  264. package/dist/extensions/telegram/index.js +67 -0
  265. package/dist/extensions/telegram/index.js.map +1 -0
  266. package/dist/extensions/telegram/media.d.ts +39 -0
  267. package/dist/extensions/telegram/media.js +223 -0
  268. package/dist/extensions/telegram/media.js.map +1 -0
  269. package/dist/extensions/telegram/mutex.d.ts +9 -0
  270. package/dist/extensions/telegram/mutex.js +14 -0
  271. package/dist/extensions/telegram/mutex.js.map +1 -0
  272. package/dist/extensions/telegram/sending.d.ts +48 -0
  273. package/dist/extensions/telegram/sending.js +119 -0
  274. package/dist/extensions/telegram/sending.js.map +1 -0
  275. package/dist/extensions/telegram/streaming.d.ts +46 -0
  276. package/dist/extensions/telegram/streaming.js +140 -0
  277. package/dist/extensions/telegram/streaming.js.map +1 -0
  278. package/dist/extensions/telegram/tools.d.ts +80 -0
  279. package/dist/extensions/telegram/tools.js +232 -0
  280. package/dist/extensions/telegram/tools.js.map +1 -0
  281. package/dist/extensions/workflows/cleanup.d.ts +10 -0
  282. package/dist/extensions/workflows/cleanup.js +38 -0
  283. package/dist/extensions/workflows/cleanup.js.map +1 -0
  284. package/dist/extensions/workflows/index.d.ts +11 -0
  285. package/dist/extensions/workflows/index.js +42 -0
  286. package/dist/extensions/workflows/index.js.map +1 -0
  287. package/dist/extensions/workflows/loader.d.ts +27 -0
  288. package/dist/extensions/workflows/loader.js +90 -0
  289. package/dist/extensions/workflows/loader.js.map +1 -0
  290. package/dist/extensions/workflows/model.d.ts +19 -0
  291. package/dist/extensions/workflows/model.js +7 -0
  292. package/dist/extensions/workflows/model.js.map +1 -0
  293. package/dist/extensions/workflows/repository.d.ts +24 -0
  294. package/dist/extensions/workflows/repository.js +61 -0
  295. package/dist/extensions/workflows/repository.js.map +1 -0
  296. package/dist/extensions/workflows/schema.d.ts +193 -0
  297. package/dist/extensions/workflows/schema.js +20 -0
  298. package/dist/extensions/workflows/schema.js.map +1 -0
  299. package/dist/extensions/workflows/tools.d.ts +27 -0
  300. package/dist/extensions/workflows/tools.js +285 -0
  301. package/dist/extensions/workflows/tools.js.map +1 -0
  302. package/dist/log.d.ts +8 -0
  303. package/dist/log.js +15 -0
  304. package/dist/log.js.map +1 -0
  305. package/dist/main.d.ts +2 -0
  306. package/dist/main.js +27 -0
  307. package/dist/main.js.map +1 -0
  308. package/dist/migration/ask.d.ts +8 -0
  309. package/dist/migration/ask.js +24 -0
  310. package/dist/migration/ask.js.map +1 -0
  311. package/dist/migration/config.d.ts +10 -0
  312. package/dist/migration/config.js +122 -0
  313. package/dist/migration/config.js.map +1 -0
  314. package/dist/migration/context.d.ts +3 -0
  315. package/dist/migration/context.js +24 -0
  316. package/dist/migration/context.js.map +1 -0
  317. package/dist/migration/database.d.ts +8 -0
  318. package/dist/migration/database.js +51 -0
  319. package/dist/migration/database.js.map +1 -0
  320. package/dist/migration/fs.d.ts +1 -0
  321. package/dist/migration/fs.js +11 -0
  322. package/dist/migration/fs.js.map +1 -0
  323. package/dist/migration/index.d.ts +11 -0
  324. package/dist/migration/index.js +28 -0
  325. package/dist/migration/index.js.map +1 -0
  326. package/dist/migration/skills.d.ts +19 -0
  327. package/dist/migration/skills.js +77 -0
  328. package/dist/migration/skills.js.map +1 -0
  329. package/dist/scheduler.d.ts +17 -0
  330. package/dist/scheduler.js +53 -0
  331. package/dist/scheduler.js.map +1 -0
  332. package/dist/sessions/registry.d.ts +15 -0
  333. package/dist/sessions/registry.js +42 -0
  334. package/dist/sessions/registry.js.map +1 -0
  335. package/dist/workspace.d.ts +13 -0
  336. package/dist/workspace.js +32 -0
  337. package/dist/workspace.js.map +1 -0
  338. package/drizzle/0000_init.sql +19 -0
  339. package/drizzle/0001_extensions.sql +63 -0
  340. package/drizzle/meta/0000_snapshot.json +134 -0
  341. package/drizzle/meta/0001_snapshot.json +526 -0
  342. package/drizzle/meta/_journal.json +20 -0
  343. package/package.json +63 -0
  344. package/skills/skill-authoring/SKILL.md +168 -0
  345. package/skills/workflow-authoring/SKILL.md +251 -0
@@ -0,0 +1,112 @@
1
+ import { Type } from "typebox";
2
+ import { isGitSource } from "./installs.js";
3
+ const RESTART_NOTE = "The change takes effect after Tachikoma restarts.";
4
+ export const InstallPluginParams = Type.Object({
5
+ source: Type.String({
6
+ description: "Git URL to clone (https://, git@, ssh://, file:// or ending in .git) or a local path to a directory/file containing the extension module",
7
+ }),
8
+ alias: Type.String({
9
+ description: "Install alias — lowercase letters, digits, and hyphens",
10
+ }),
11
+ });
12
+ export const PluginAliasParams = Type.Object({
13
+ alias: Type.String({
14
+ description: "Alias of an installed extension (see list_installed_extensions)",
15
+ }),
16
+ });
17
+ export const ListInstalledPluginsParams = Type.Object({});
18
+ export const handleInstallExternalExtension = async (manager, args) => {
19
+ const record = await manager.install(args.source, args.alias);
20
+ return [
21
+ `ExternalExtension '${args.alias}' installed successfully.`,
22
+ `- Source: ${record.source}`,
23
+ `- Path: ${record.path}`,
24
+ RESTART_NOTE,
25
+ ].join("\n");
26
+ };
27
+ export const handleUpdateExternalExtension = async (manager, args) => {
28
+ const result = await manager.update(args.alias);
29
+ if (result.status === "skipped")
30
+ return `ExternalExtension '${args.alias}' skipped: ${result.detail}`;
31
+ return [`ExternalExtension '${args.alias}' updated.`, result.detail, RESTART_NOTE].join("\n");
32
+ };
33
+ export const handleListInstalledPlugins = (manager) => {
34
+ const entries = Object.entries(manager.list());
35
+ if (entries.length === 0)
36
+ return "No external extensions installed.";
37
+ return [
38
+ "# Installed Plugins",
39
+ "",
40
+ ...entries.flatMap(([alias, record]) => [
41
+ `- **${alias}** (${isGitSource(record.source) ? "git" : "local"})`,
42
+ ` Source: ${record.source}`,
43
+ ` Path: ${record.path}`,
44
+ ` Installed: ${record.installedAt}`,
45
+ "",
46
+ ]),
47
+ ].join("\n");
48
+ };
49
+ export const handleUninstallExtension = async (manager, args) => {
50
+ await manager.uninstall(args.alias);
51
+ return [`ExternalExtension '${args.alias}' uninstalled.`, RESTART_NOTE].join("\n");
52
+ };
53
+ const textResult = (text) => ({
54
+ content: [{ type: "text", text }],
55
+ details: undefined,
56
+ });
57
+ /** pi extension factory exposing the extension install management tools to the agent. */
58
+ export const createExternalToolsFactory = (manager) => (pi) => {
59
+ pi.registerTool({
60
+ name: "install_extension",
61
+ label: "Install ExternalExtension",
62
+ description: "Install a third-party Tachikoman extension from a git URL (cloned into the data dir) or a local path (loaded in place). The external extension is loaded on the next restart.",
63
+ promptSnippet: "Install third-party Tachikoman extensions from git URLs or local paths",
64
+ promptGuidelines: [
65
+ "Use install_extension when the user asks to add a Tachikoman extension; tell them it activates after a restart.",
66
+ ],
67
+ parameters: InstallPluginParams,
68
+ async execute(_toolCallId, params) {
69
+ return textResult(await handleInstallExternalExtension(manager, params));
70
+ },
71
+ });
72
+ pi.registerTool({
73
+ name: "update_extension",
74
+ label: "Update ExternalExtension",
75
+ description: "Update an installed extension: git installs are pulled from their source; local installs are always current. Updates apply on the next restart.",
76
+ promptSnippet: "Update an installed extension to its latest version",
77
+ promptGuidelines: [
78
+ "Use update_extension with the alias from list_installed_extensions when the user wants a newer extension version.",
79
+ ],
80
+ parameters: PluginAliasParams,
81
+ async execute(_toolCallId, params) {
82
+ return textResult(await handleUpdateExternalExtension(manager, params));
83
+ },
84
+ });
85
+ pi.registerTool({
86
+ name: "list_installed_extensions",
87
+ label: "List Installed Plugins",
88
+ description: "List external extensions installed through install_extension, with their alias, source, install path, and install time.",
89
+ promptSnippet: "List installed third-party extensions",
90
+ promptGuidelines: [
91
+ "Check list_installed_extensions before install_extension to avoid alias collisions.",
92
+ ],
93
+ parameters: ListInstalledPluginsParams,
94
+ async execute() {
95
+ return textResult(handleListInstalledPlugins(manager));
96
+ },
97
+ });
98
+ pi.registerTool({
99
+ name: "uninstall_extension",
100
+ label: "Uninstall ExternalExtension",
101
+ description: "Uninstall an extension by alias: removes its install record and deletes cloned files (local sources are left untouched). The external extension stays active until restart.",
102
+ promptSnippet: "Uninstall a third-party extension by alias",
103
+ promptGuidelines: [
104
+ "Use uninstall_extension when the user wants an extension gone; mention it unloads fully on restart.",
105
+ ],
106
+ parameters: PluginAliasParams,
107
+ async execute(_toolCallId, params) {
108
+ return textResult(await handleUninstallExtension(manager, params));
109
+ },
110
+ });
111
+ };
112
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/extensions/external/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SideRunner } from "../../agent/side-run.ts";
2
+ import type { Logger } from "../../log.ts";
3
+ export type Completer = Pick<SideRunner, "complete">;
4
+ export declare const generateCommitMessage: (side: Completer, diffStat: string, fallback: string, log: Logger) => Promise<string>;
5
+ export interface CommitAllOptions {
6
+ cwd: string;
7
+ side: Completer;
8
+ /** Deterministic message used when generation fails or produces nothing usable. */
9
+ fallbackMessage: string;
10
+ /** Explicit message — skips generation entirely. */
11
+ message?: string;
12
+ log: Logger;
13
+ }
14
+ /**
15
+ * Stage everything and commit with a descriptive message generated from the
16
+ * staged diffstat. Returns the commit message, or null when there was nothing
17
+ * to commit.
18
+ */
19
+ export declare const commitAll: ({ cwd, side, fallbackMessage, message, log, }: CommitAllOptions) => Promise<string | null>;
@@ -0,0 +1,44 @@
1
+ import { runGit, runGitCapture } from "./git.js";
2
+ const COMMIT_MESSAGE_SYSTEM = `You write git commit messages for an automated workspace-versioning agent.
3
+
4
+ Given the staged diffstat of a commit, respond with a single descriptive commit
5
+ message line: imperative mood, under 72 characters, mentioning what changed.
6
+ Output only the message — no quotes, no prose, no trailing punctuation.`;
7
+ const MAX_MESSAGE_CHARS = 100;
8
+ const sanitizeMessage = (raw) => {
9
+ const line = raw
10
+ .split("\n")
11
+ .map((candidate) => candidate.trim())
12
+ .find((candidate) => candidate !== "");
13
+ if (line == null)
14
+ return null;
15
+ const cleaned = line.replaceAll(/^["'`]+|["'`]+$/g, "").trim();
16
+ if (cleaned === "")
17
+ return null;
18
+ return cleaned.length <= MAX_MESSAGE_CHARS ? cleaned : `${cleaned.slice(0, MAX_MESSAGE_CHARS)}…`;
19
+ };
20
+ export const generateCommitMessage = async (side, diffStat, fallback, log) => {
21
+ try {
22
+ const generated = sanitizeMessage(await side.complete({ system: COMMIT_MESSAGE_SYSTEM, user: diffStat, tier: "processor" }));
23
+ return generated ?? fallback;
24
+ }
25
+ catch (error) {
26
+ log.warn({ err: error }, "commit message generation failed — using fallback");
27
+ return fallback;
28
+ }
29
+ };
30
+ /**
31
+ * Stage everything and commit with a descriptive message generated from the
32
+ * staged diffstat. Returns the commit message, or null when there was nothing
33
+ * to commit.
34
+ */
35
+ export const commitAll = async ({ cwd, side, fallbackMessage, message, log, }) => {
36
+ await runGit(cwd, ["add", "-A"]);
37
+ const { stdout: diffStat } = await runGitCapture(cwd, ["diff", "--cached", "--stat"]);
38
+ if (diffStat === "")
39
+ return null;
40
+ const resolved = message ?? (await generateCommitMessage(side, diffStat, fallbackMessage, log));
41
+ await runGit(cwd, ["commit", "-m", resolved]);
42
+ return resolved;
43
+ };
44
+ //# sourceMappingURL=commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../src/extensions/git/commit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIjD,MAAM,qBAAqB,GAAG;;;;wEAI0C,CAAC;AAEzE,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,MAAM,eAAe,GAAG,CAAC,GAAW,EAAiB,EAAE;IACrD,MAAM,IAAI,GAAG,GAAG;SACb,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;SACpC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IAEzC,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE/D,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEhC,OAAO,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,GAAG,CAAC;AACnG,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,IAAe,EACf,QAAgB,EAChB,QAAgB,EAChB,GAAW,EACM,EAAE;IACnB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,eAAe,CAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAC1F,CAAC;QAEF,OAAO,SAAS,IAAI,QAAQ,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,mDAAmD,CAAC,CAAC;QAC9E,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAYF;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,EAC9B,GAAG,EACH,IAAI,EACJ,eAAe,EACf,OAAO,EACP,GAAG,GACc,EAA0B,EAAE;IAC7C,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtF,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEjC,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC,CAAC;IAChG,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE9C,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface GitResult {
2
+ code: number;
3
+ stdout: string;
4
+ stderr: string;
5
+ }
6
+ /** Run a git command and return exit code + trimmed output, never throwing on non-zero exit. */
7
+ export declare const runGitCapture: (cwd: string, args: string[]) => Promise<GitResult>;
8
+ /** Run a git command and throw on failure. Returns trimmed stdout. */
9
+ export declare const runGit: (cwd: string, args: string[]) => Promise<string>;
10
+ export declare const hasUncommittedChanges: (cwd: string) => Promise<boolean>;
11
+ export declare const hasRemote: (cwd: string, remote: string) => Promise<boolean>;
@@ -0,0 +1,29 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ /** Run a git command and return exit code + trimmed output, never throwing on non-zero exit. */
5
+ export const runGitCapture = async (cwd, args) => {
6
+ try {
7
+ const { stdout, stderr } = await execFileAsync("git", args, { cwd });
8
+ return { code: 0, stdout: stdout.trim(), stderr: stderr.trim() };
9
+ }
10
+ catch (error) {
11
+ const failure = error;
12
+ return {
13
+ code: typeof failure.code === "number" ? failure.code : 1,
14
+ stdout: (failure.stdout ?? "").trim(),
15
+ stderr: (failure.stderr ?? "").trim(),
16
+ };
17
+ }
18
+ };
19
+ /** Run a git command and throw on failure. Returns trimmed stdout. */
20
+ export const runGit = async (cwd, args) => {
21
+ const result = await runGitCapture(cwd, args);
22
+ if (result.code !== 0) {
23
+ throw new Error(`git ${args.join(" ")} failed: ${result.stderr || `exit code ${result.code}`}`);
24
+ }
25
+ return result.stdout;
26
+ };
27
+ export const hasUncommittedChanges = async (cwd) => (await runGitCapture(cwd, ["status", "--porcelain"])).stdout !== "";
28
+ export const hasRemote = async (cwd, remote) => (await runGitCapture(cwd, ["remote", "get-url", remote])).code === 0;
29
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/extensions/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAQ1C,gGAAgG;AAChG,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,GAAW,EAAE,IAAc,EAAsB,EAAE;IACrF,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACrE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IACnE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAqE,CAAC;QAEtF,OAAO;YACL,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;SACtC,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,GAAW,EAAE,IAAc,EAAmB,EAAE;IAC3E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAE9C,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,IAAI,aAAa,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,GAAW,EAAoB,EAAE,CAC3E,CAAC,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC;AAEtE,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,GAAW,EAAE,MAAc,EAAoB,EAAE,CAC/E,CAAC,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Logger } from "../../log.ts";
2
+ export declare const COMMITTER_NAME = "Tachikoma";
3
+ export declare const COMMITTER_EMAIL = "tachikoma@local";
4
+ export declare const GITIGNORE_ENTRIES: string[];
5
+ /**
6
+ * Bootstrap hook: initialize the workspace as a git repo with a fixed
7
+ * committer identity (idempotent), ensure internal state stays gitignored,
8
+ * and sync with the origin remote when one is configured.
9
+ */
10
+ export declare const initializeWorkspaceRepo: (workspaceRoot: string, log: Logger) => Promise<void>;
@@ -0,0 +1,88 @@
1
+ import { access, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { hasRemote, runGit } from "./git.js";
4
+ import { SYNC_RESULT, smartPull } from "./sync.js";
5
+ export const COMMITTER_NAME = "Tachikoma";
6
+ export const COMMITTER_EMAIL = "tachikoma@local";
7
+ export const GITIGNORE_ENTRIES = [".tachikoma/\n"];
8
+ const readGitignore = async (workspaceRoot) => {
9
+ try {
10
+ return await readFile(join(workspaceRoot, ".gitignore"), "utf8");
11
+ }
12
+ catch {
13
+ return "";
14
+ }
15
+ };
16
+ const appendMissingEntries = (existing) => {
17
+ let content = existing;
18
+ for (const entry of GITIGNORE_ENTRIES) {
19
+ if (!content.includes(entry)) {
20
+ const separator = content === "" || content.endsWith("\n") ? "" : "\n";
21
+ content += separator + entry;
22
+ }
23
+ }
24
+ return content;
25
+ };
26
+ /**
27
+ * Ensure the gitignore entries exist without committing — called on every
28
+ * startup so existing workspaces receive new entries; the commit processor
29
+ * picks the change up at the next session close.
30
+ */
31
+ const ensureGitignoreEntries = async (workspaceRoot) => {
32
+ const existing = await readGitignore(workspaceRoot);
33
+ const updated = appendMissingEntries(existing);
34
+ if (updated !== existing) {
35
+ await writeFile(join(workspaceRoot, ".gitignore"), updated, "utf8");
36
+ }
37
+ };
38
+ const initializeRepo = async (workspaceRoot, log) => {
39
+ log.info({ path: workspaceRoot }, "initializing workspace git repo");
40
+ await runGit(workspaceRoot, ["init"]);
41
+ await runGit(workspaceRoot, ["config", "user.name", COMMITTER_NAME]);
42
+ await runGit(workspaceRoot, ["config", "user.email", COMMITTER_EMAIL]);
43
+ // The agent commits unattended — never block on a missing GPG setup.
44
+ await runGit(workspaceRoot, ["config", "commit.gpgsign", "false"]);
45
+ await runGit(workspaceRoot, ["commit", "--allow-empty", "-m", "Initial commit"]);
46
+ await ensureGitignoreEntries(workspaceRoot);
47
+ await runGit(workspaceRoot, ["add", ".gitignore"]);
48
+ await runGit(workspaceRoot, ["commit", "-m", "Add gitignore for workspace exclusions"]);
49
+ log.info("workspace git repo initialized");
50
+ };
51
+ const syncWorkspace = async (workspaceRoot, log) => {
52
+ try {
53
+ if (!(await hasRemote(workspaceRoot, "origin"))) {
54
+ log.debug("no origin remote configured — skipping workspace sync");
55
+ return;
56
+ }
57
+ const result = await smartPull(workspaceRoot, "origin", "HEAD", log);
58
+ if (result === SYNC_RESULT.dirtySkipped) {
59
+ log.warn("workspace has uncommitted changes — skipping sync");
60
+ }
61
+ else if (result === SYNC_RESULT.upToDate) {
62
+ log.debug("workspace already up to date");
63
+ }
64
+ else if (result === SYNC_RESULT.syncFailed) {
65
+ log.warn("workspace sync failed — continuing with local state");
66
+ }
67
+ else {
68
+ log.info({ result }, "workspace synced");
69
+ }
70
+ }
71
+ catch (error) {
72
+ log.warn({ err: error }, "workspace sync failed");
73
+ }
74
+ };
75
+ /**
76
+ * Bootstrap hook: initialize the workspace as a git repo with a fixed
77
+ * committer identity (idempotent), ensure internal state stays gitignored,
78
+ * and sync with the origin remote when one is configured.
79
+ */
80
+ export const initializeWorkspaceRepo = async (workspaceRoot, log) => {
81
+ const gitDirMissing = await access(join(workspaceRoot, ".git")).then(() => false, () => true);
82
+ if (gitDirMissing) {
83
+ await initializeRepo(workspaceRoot, log);
84
+ }
85
+ await ensureGitignoreEntries(workspaceRoot);
86
+ await syncWorkspace(workspaceRoot, log);
87
+ };
88
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/extensions/git/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ interface GitConfig {
2
+ enabled: boolean;
3
+ }
4
+ /**
5
+ * Workspace versioning: initializes the workspace as a git repo on startup
6
+ * (syncing with origin when configured), commits and pushes all workspace
7
+ * changes at session close, and exposes git inspection/commit tools to the
8
+ * agent.
9
+ */
10
+ declare const _default: import("../api.ts").TachikomaExtension<GitConfig>;
11
+ export default _default;
@@ -0,0 +1,28 @@
1
+ import { Type } from "typebox";
2
+ import { defineExtension } from "../api.js";
3
+ import { initializeWorkspaceRepo } from "./hooks.js";
4
+ import { createGitProcessor } from "./processor.js";
5
+ import { createGitToolsFactory } from "./tools.js";
6
+ /**
7
+ * Workspace versioning: initializes the workspace as a git repo on startup
8
+ * (syncing with origin when configured), commits and pushes all workspace
9
+ * changes at session close, and exposes git inspection/commit tools to the
10
+ * agent.
11
+ */
12
+ export default defineExtension({
13
+ name: "git",
14
+ configSchema: Type.Object({
15
+ enabled: Type.Boolean({ default: true }),
16
+ }),
17
+ setup(app) {
18
+ if (!app.extensionConfig.enabled) {
19
+ app.log.info("git extension disabled by configuration");
20
+ return;
21
+ }
22
+ const workspaceRoot = app.workspace.root;
23
+ app.bootstrap("init-workspace-repo", () => initializeWorkspaceRepo(workspaceRoot, app.log));
24
+ app.agent.use(createGitToolsFactory({ workspaceRoot, side: app.agent.side, log: app.log }));
25
+ app.sessions.registerProcessor(createGitProcessor({ workspaceRoot, side: app.agent.side }));
26
+ },
27
+ });
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/git/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAMnD;;;;;GAKG;AACH,eAAe,eAAe,CAAY;IACxC,IAAI,EAAE,KAAK;IAEX,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC;QACxB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;KACzC,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;YACjC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;QAEzC,GAAG,CAAC,SAAS,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAE5F,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { PostProcessor } from "../api.ts";
2
+ import { type Completer } from "./commit.ts";
3
+ export interface GitProcessorDeps {
4
+ workspaceRoot: string;
5
+ side: Completer;
6
+ }
7
+ export declare const workspaceFallbackMessage: (now?: Date) => string;
8
+ /**
9
+ * Finalize-phase post-processor: stages and commits all workspace changes after
10
+ * each session with a message generated from the staged diffstat, then pushes
11
+ * to origin when a remote is configured.
12
+ */
13
+ export declare const createGitProcessor: ({ workspaceRoot, side }: GitProcessorDeps) => PostProcessor;
@@ -0,0 +1,52 @@
1
+ import { commitAll } from "./commit.js";
2
+ import { hasRemote, hasUncommittedChanges } from "./git.js";
3
+ import { PUSH_RESULT, PUSH_SUCCESS, smartPush } from "./sync.js";
4
+ export const workspaceFallbackMessage = (now = new Date()) => `Update workspace files (${now.toISOString().slice(0, 10)})`;
5
+ /**
6
+ * Finalize-phase post-processor: stages and commits all workspace changes after
7
+ * each session with a message generated from the staged diffstat, then pushes
8
+ * to origin when a remote is configured.
9
+ */
10
+ export const createGitProcessor = ({ workspaceRoot, side }) => ({
11
+ name: "git-commit",
12
+ phase: "finalize",
13
+ async process({ log }) {
14
+ if (!(await hasUncommittedChanges(workspaceRoot))) {
15
+ log.debug("workspace is clean — no commits needed");
16
+ return;
17
+ }
18
+ const message = await commitAll({
19
+ cwd: workspaceRoot,
20
+ side,
21
+ fallbackMessage: workspaceFallbackMessage(),
22
+ log,
23
+ });
24
+ if (message != null)
25
+ log.info({ message }, "committed workspace changes");
26
+ if (await hasRemote(workspaceRoot, "origin")) {
27
+ const result = await smartPush(workspaceRoot, "origin", "HEAD", log);
28
+ if (PUSH_SUCCESS.has(result)) {
29
+ log.info({ result }, "pushed workspace changes");
30
+ }
31
+ else if (result === PUSH_RESULT.nothingToPush) {
32
+ log.debug("nothing to push");
33
+ }
34
+ else {
35
+ log.warn({ result }, "push failed — changes remain committed locally");
36
+ }
37
+ }
38
+ if (await hasUncommittedChanges(workspaceRoot)) {
39
+ log.warn("uncommitted changes remain after commit pass — retrying");
40
+ await commitAll({
41
+ cwd: workspaceRoot,
42
+ side,
43
+ fallbackMessage: workspaceFallbackMessage(),
44
+ log,
45
+ });
46
+ if (await hasUncommittedChanges(workspaceRoot)) {
47
+ log.warn("uncommitted changes remain after git processor retry");
48
+ }
49
+ }
50
+ },
51
+ });
52
+ //# sourceMappingURL=processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processor.js","sourceRoot":"","sources":["../../../src/extensions/git/processor.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOjE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,EAAU,EAAE,CACnE,2BAA2B,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,aAAa,EAAE,IAAI,EAAoB,EAAiB,EAAE,CAAC,CAAC;IAC/F,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,UAAU;IAEjB,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE;QACnB,IAAI,CAAC,CAAC,MAAM,qBAAqB,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC;YAC9B,GAAG,EAAE,aAAa;YAClB,IAAI;YACJ,eAAe,EAAE,wBAAwB,EAAE;YAC3C,GAAG;SACJ,CAAC,CAAC;QAEH,IAAI,OAAO,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B,CAAC,CAAC;QAE1E,IAAI,MAAM,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAErE,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC;YACnD,CAAC;iBAAM,IAAI,MAAM,KAAK,WAAW,CAAC,aAAa,EAAE,CAAC;gBAChD,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,gDAAgD,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,qBAAqB,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;YAEpE,MAAM,SAAS,CAAC;gBACd,GAAG,EAAE,aAAa;gBAClB,IAAI;gBACJ,eAAe,EAAE,wBAAwB,EAAE;gBAC3C,GAAG;aACJ,CAAC,CAAC;YAEH,IAAI,MAAM,qBAAqB,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { Logger } from "../../log.ts";
2
+ export declare const DIVERGENCE_STATUS: {
3
+ readonly upToDate: "UP_TO_DATE";
4
+ readonly ahead: "AHEAD";
5
+ readonly behind: "BEHIND";
6
+ readonly diverged: "DIVERGED";
7
+ };
8
+ export type DivergenceStatus = (typeof DIVERGENCE_STATUS)[keyof typeof DIVERGENCE_STATUS];
9
+ export declare const PUSH_RESULT: {
10
+ readonly pushed: "PUSHED";
11
+ readonly nothingToPush: "NOTHING_TO_PUSH";
12
+ readonly rebaseSucceeded: "REBASE_SUCCEEDED";
13
+ readonly pushFailed: "PUSH_FAILED";
14
+ readonly rebaseFailed: "REBASE_FAILED";
15
+ };
16
+ export type PushResult = (typeof PUSH_RESULT)[keyof typeof PUSH_RESULT];
17
+ export declare const SYNC_RESULT: {
18
+ readonly upToDate: "UP_TO_DATE";
19
+ readonly fastForwarded: "FAST_FORWARDED";
20
+ readonly rebaseSucceeded: "REBASE_SUCCEEDED";
21
+ readonly syncFailed: "SYNC_FAILED";
22
+ readonly dirtySkipped: "DIRTY_SKIPPED";
23
+ };
24
+ export type SyncResult = (typeof SYNC_RESULT)[keyof typeof SYNC_RESULT];
25
+ export declare const PUSH_SUCCESS: ReadonlySet<PushResult>;
26
+ /**
27
+ * Classify the relationship between local HEAD and `<remote>/<branch>`.
28
+ * Precondition: `git fetch <remote>` has already run.
29
+ */
30
+ export declare const detectDivergence: (cwd: string, remote?: string, branch?: string) => Promise<DivergenceStatus>;
31
+ /**
32
+ * Push local commits with divergence recovery: abort stale rebase → fetch →
33
+ * detect divergence → push directly when ahead, or rebase-then-push when
34
+ * diverged. Conflicting rebases are aborted (local commits preserved) and
35
+ * surface as REBASE_FAILED.
36
+ */
37
+ export declare const smartPush: (cwd: string, remote: string, branch: string, log: Logger) => Promise<PushResult>;
38
+ /**
39
+ * Pull remote changes with divergence recovery: skip when dirty, abort stale
40
+ * rebase → fetch → detect divergence → fast-forward when behind, or naive
41
+ * rebase when diverged. Conflicting rebases are aborted and surface as
42
+ * SYNC_FAILED.
43
+ */
44
+ export declare const smartPull: (cwd: string, remote: string, branch: string, log: Logger) => Promise<SyncResult>;