intent-hub 0.1.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 (214) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.turbo/cache/019f5ae385027cb1-meta.json +1 -0
  3. package/.turbo/cache/019f5ae385027cb1.tar.zst +0 -0
  4. package/.turbo/cache/040af6112a552a64-meta.json +1 -0
  5. package/.turbo/cache/040af6112a552a64.tar.zst +0 -0
  6. package/.turbo/cache/11195eac3ca5c6ce-meta.json +1 -0
  7. package/.turbo/cache/11195eac3ca5c6ce.tar.zst +0 -0
  8. package/.turbo/cache/13d11166efdf11cf-meta.json +1 -0
  9. package/.turbo/cache/13d11166efdf11cf.tar.zst +0 -0
  10. package/.turbo/cache/19af1af3b136706c-meta.json +1 -0
  11. package/.turbo/cache/19af1af3b136706c.tar.zst +0 -0
  12. package/.turbo/cache/1d33efac91c05b50-meta.json +1 -0
  13. package/.turbo/cache/1d33efac91c05b50.tar.zst +0 -0
  14. package/.turbo/cache/200b85a612af2d13-meta.json +1 -0
  15. package/.turbo/cache/200b85a612af2d13.tar.zst +0 -0
  16. package/.turbo/cache/210308c9ea929858-meta.json +1 -0
  17. package/.turbo/cache/210308c9ea929858.tar.zst +0 -0
  18. package/.turbo/cache/38df8e44c617835e-meta.json +1 -0
  19. package/.turbo/cache/38df8e44c617835e.tar.zst +0 -0
  20. package/.turbo/cache/3e449de5ef60a7a0-meta.json +1 -0
  21. package/.turbo/cache/3e449de5ef60a7a0.tar.zst +0 -0
  22. package/.turbo/cache/51ff024a97c2b4f5-meta.json +1 -0
  23. package/.turbo/cache/51ff024a97c2b4f5.tar.zst +0 -0
  24. package/.turbo/cache/54bc756eeebb377a-meta.json +1 -0
  25. package/.turbo/cache/54bc756eeebb377a.tar.zst +0 -0
  26. package/.turbo/cache/5ed6a840acafc873-meta.json +1 -0
  27. package/.turbo/cache/5ed6a840acafc873.tar.zst +0 -0
  28. package/.turbo/cache/6702dc24e5ca3c2e-meta.json +1 -0
  29. package/.turbo/cache/6702dc24e5ca3c2e.tar.zst +0 -0
  30. package/.turbo/cache/725c72cf71ea854f-meta.json +1 -0
  31. package/.turbo/cache/725c72cf71ea854f.tar.zst +0 -0
  32. package/.turbo/cache/7344ca28d348037a-meta.json +1 -0
  33. package/.turbo/cache/7344ca28d348037a.tar.zst +0 -0
  34. package/.turbo/cache/748fb444cdc0b78c-meta.json +1 -0
  35. package/.turbo/cache/748fb444cdc0b78c.tar.zst +0 -0
  36. package/.turbo/cache/789677c36fe7fb98-meta.json +1 -0
  37. package/.turbo/cache/789677c36fe7fb98.tar.zst +0 -0
  38. package/.turbo/cache/89ff6c6f38dd4a18-meta.json +1 -0
  39. package/.turbo/cache/89ff6c6f38dd4a18.tar.zst +0 -0
  40. package/.turbo/cache/8dbc92d00de0c92e-meta.json +1 -0
  41. package/.turbo/cache/8dbc92d00de0c92e.tar.zst +0 -0
  42. package/.turbo/cache/8eb03f40082b9441-meta.json +1 -0
  43. package/.turbo/cache/8eb03f40082b9441.tar.zst +0 -0
  44. package/.turbo/cache/9157134d4b916017-meta.json +1 -0
  45. package/.turbo/cache/9157134d4b916017.tar.zst +0 -0
  46. package/.turbo/cache/94219ffd32b48e93-meta.json +1 -0
  47. package/.turbo/cache/94219ffd32b48e93.tar.zst +0 -0
  48. package/.turbo/cache/95c1d160b4fa84eb-meta.json +1 -0
  49. package/.turbo/cache/95c1d160b4fa84eb.tar.zst +0 -0
  50. package/.turbo/cache/998833ea02dfb225-meta.json +1 -0
  51. package/.turbo/cache/998833ea02dfb225.tar.zst +0 -0
  52. package/.turbo/cache/a5974ef6ade3eb90-meta.json +1 -0
  53. package/.turbo/cache/a5974ef6ade3eb90.tar.zst +0 -0
  54. package/.turbo/cache/aab811809257decb-meta.json +1 -0
  55. package/.turbo/cache/aab811809257decb.tar.zst +0 -0
  56. package/.turbo/cache/ab2f82a54da854fd-meta.json +1 -0
  57. package/.turbo/cache/ab2f82a54da854fd.tar.zst +0 -0
  58. package/.turbo/cache/abbf4d95d62a7303-meta.json +1 -0
  59. package/.turbo/cache/abbf4d95d62a7303.tar.zst +0 -0
  60. package/.turbo/cache/af4441f519f9ce50-meta.json +1 -0
  61. package/.turbo/cache/af4441f519f9ce50.tar.zst +0 -0
  62. package/.turbo/cache/b9b85aaaf03d00a6-meta.json +1 -0
  63. package/.turbo/cache/b9b85aaaf03d00a6.tar.zst +0 -0
  64. package/.turbo/cache/cd58ee8721bbfed7-meta.json +1 -0
  65. package/.turbo/cache/cd58ee8721bbfed7.tar.zst +0 -0
  66. package/.turbo/cache/d285e48b8afa30b5-meta.json +1 -0
  67. package/.turbo/cache/d285e48b8afa30b5.tar.zst +0 -0
  68. package/.turbo/cache/d33e90229142acce-meta.json +1 -0
  69. package/.turbo/cache/d33e90229142acce.tar.zst +0 -0
  70. package/.turbo/cache/d57839a0d3b04540-meta.json +1 -0
  71. package/.turbo/cache/d57839a0d3b04540.tar.zst +0 -0
  72. package/.turbo/cache/d8554ef2c8b6e5eb-meta.json +1 -0
  73. package/.turbo/cache/d8554ef2c8b6e5eb.tar.zst +0 -0
  74. package/.turbo/cache/dc7375b51290e102-meta.json +1 -0
  75. package/.turbo/cache/dc7375b51290e102.tar.zst +0 -0
  76. package/.turbo/cache/e5310fe547fdbf0a-meta.json +1 -0
  77. package/.turbo/cache/e5310fe547fdbf0a.tar.zst +0 -0
  78. package/.turbo/cache/f12bb5f2f188758d-meta.json +1 -0
  79. package/.turbo/cache/f12bb5f2f188758d.tar.zst +0 -0
  80. package/.turbo/cache/f2db5af0c0b4d23f-meta.json +1 -0
  81. package/.turbo/cache/f2db5af0c0b4d23f.tar.zst +0 -0
  82. package/.turbo/cache/f8935ade01a88cd7-meta.json +1 -0
  83. package/.turbo/cache/f8935ade01a88cd7.tar.zst +0 -0
  84. package/.turbo/cache/f982b8dd966f823a-meta.json +1 -0
  85. package/.turbo/cache/f982b8dd966f823a.tar.zst +0 -0
  86. package/.turbo/cache/f9d4036dd350ba1a-meta.json +1 -0
  87. package/.turbo/cache/f9d4036dd350ba1a.tar.zst +0 -0
  88. package/README.md +661 -0
  89. package/README_ko.md +577 -0
  90. package/bun.lock +135 -0
  91. package/package.json +26 -0
  92. package/packages/agent/.turbo/turbo-build.log +5 -0
  93. package/packages/agent/.turbo/turbo-typecheck.log +1 -0
  94. package/packages/agent/dist/connection/hub-client.d.ts +33 -0
  95. package/packages/agent/dist/connection/hub-client.d.ts.map +1 -0
  96. package/packages/agent/dist/connection/index.d.ts +2 -0
  97. package/packages/agent/dist/connection/index.d.ts.map +1 -0
  98. package/packages/agent/dist/hooks/index.d.ts +3 -0
  99. package/packages/agent/dist/hooks/index.d.ts.map +1 -0
  100. package/packages/agent/dist/hooks/intent-hub-hooks.d.ts +47 -0
  101. package/packages/agent/dist/hooks/intent-hub-hooks.d.ts.map +1 -0
  102. package/packages/agent/dist/index.d.ts +6 -0
  103. package/packages/agent/dist/index.d.ts.map +1 -0
  104. package/packages/agent/dist/index.js +3315 -0
  105. package/packages/agent/dist/plugin/index.d.ts +3 -0
  106. package/packages/agent/dist/plugin/index.d.ts.map +1 -0
  107. package/packages/agent/dist/plugin/intent-hub-plugin.d.ts +54 -0
  108. package/packages/agent/dist/plugin/intent-hub-plugin.d.ts.map +1 -0
  109. package/packages/agent/package.json +32 -0
  110. package/packages/agent/src/connection/hub-client.ts +152 -0
  111. package/packages/agent/src/connection/index.ts +1 -0
  112. package/packages/agent/src/hooks/index.ts +2 -0
  113. package/packages/agent/src/hooks/intent-hub-hooks.ts +245 -0
  114. package/packages/agent/src/index.ts +5 -0
  115. package/packages/agent/src/plugin/index.ts +2 -0
  116. package/packages/agent/src/plugin/intent-hub-plugin.ts +153 -0
  117. package/packages/agent/tsconfig.json +9 -0
  118. package/packages/hub/.turbo/turbo-build.log +6 -0
  119. package/packages/hub/.turbo/turbo-typecheck.log +1 -0
  120. package/packages/hub/dist/api/dashboard.d.ts +17 -0
  121. package/packages/hub/dist/api/dashboard.d.ts.map +1 -0
  122. package/packages/hub/dist/cli.d.ts +3 -0
  123. package/packages/hub/dist/cli.d.ts.map +1 -0
  124. package/packages/hub/dist/cli.js +7719 -0
  125. package/packages/hub/dist/core/conflict-detector.d.ts +36 -0
  126. package/packages/hub/dist/core/conflict-detector.d.ts.map +1 -0
  127. package/packages/hub/dist/core/index.d.ts +7 -0
  128. package/packages/hub/dist/core/index.d.ts.map +1 -0
  129. package/packages/hub/dist/core/intent-analyzer.d.ts +8 -0
  130. package/packages/hub/dist/core/intent-analyzer.d.ts.map +1 -0
  131. package/packages/hub/dist/core/lock-manager.d.ts +13 -0
  132. package/packages/hub/dist/core/lock-manager.d.ts.map +1 -0
  133. package/packages/hub/dist/core/orchestrator.d.ts +46 -0
  134. package/packages/hub/dist/core/orchestrator.d.ts.map +1 -0
  135. package/packages/hub/dist/index.d.ts +9 -0
  136. package/packages/hub/dist/index.d.ts.map +1 -0
  137. package/packages/hub/dist/index.js +4686 -0
  138. package/packages/hub/dist/llm/index.d.ts +7 -0
  139. package/packages/hub/dist/llm/index.d.ts.map +1 -0
  140. package/packages/hub/dist/llm/negotiation-engine.d.ts +40 -0
  141. package/packages/hub/dist/llm/negotiation-engine.d.ts.map +1 -0
  142. package/packages/hub/dist/llm/provider.d.ts +46 -0
  143. package/packages/hub/dist/llm/provider.d.ts.map +1 -0
  144. package/packages/hub/dist/llm/smart-analyzer.d.ts +20 -0
  145. package/packages/hub/dist/llm/smart-analyzer.d.ts.map +1 -0
  146. package/packages/hub/dist/server/hub-server.d.ts +35 -0
  147. package/packages/hub/dist/server/hub-server.d.ts.map +1 -0
  148. package/packages/hub/dist/server/index.d.ts +5 -0
  149. package/packages/hub/dist/server/index.d.ts.map +1 -0
  150. package/packages/hub/dist/server/message-handler.d.ts +18 -0
  151. package/packages/hub/dist/server/message-handler.d.ts.map +1 -0
  152. package/packages/hub/dist/server/smart-hub-server.d.ts +43 -0
  153. package/packages/hub/dist/server/smart-hub-server.d.ts.map +1 -0
  154. package/packages/hub/dist/state/index.d.ts +2 -0
  155. package/packages/hub/dist/state/index.d.ts.map +1 -0
  156. package/packages/hub/dist/state/session-manager.d.ts +19 -0
  157. package/packages/hub/dist/state/session-manager.d.ts.map +1 -0
  158. package/packages/hub/dist/tunnel/index.d.ts +14 -0
  159. package/packages/hub/dist/tunnel/index.d.ts.map +1 -0
  160. package/packages/hub/package.json +54 -0
  161. package/packages/hub/src/api/dashboard.ts +261 -0
  162. package/packages/hub/src/cli.ts +193 -0
  163. package/packages/hub/src/core/conflict-detector.ts +138 -0
  164. package/packages/hub/src/core/index.ts +6 -0
  165. package/packages/hub/src/core/intent-analyzer.ts +112 -0
  166. package/packages/hub/src/core/lock-manager.ts +95 -0
  167. package/packages/hub/src/core/orchestrator.ts +255 -0
  168. package/packages/hub/src/index.ts +8 -0
  169. package/packages/hub/src/llm/index.ts +17 -0
  170. package/packages/hub/src/llm/negotiation-engine.ts +297 -0
  171. package/packages/hub/src/llm/provider.ts +175 -0
  172. package/packages/hub/src/llm/smart-analyzer.ts +169 -0
  173. package/packages/hub/src/server/hub-server.ts +219 -0
  174. package/packages/hub/src/server/index.ts +4 -0
  175. package/packages/hub/src/server/message-handler.ts +111 -0
  176. package/packages/hub/src/server/smart-hub-server.ts +374 -0
  177. package/packages/hub/src/state/index.ts +1 -0
  178. package/packages/hub/src/state/session-manager.ts +59 -0
  179. package/packages/hub/src/tunnel/index.ts +153 -0
  180. package/packages/hub/tsconfig.json +9 -0
  181. package/packages/shared/.turbo/turbo-build.log +5 -0
  182. package/packages/shared/.turbo/turbo-typecheck.log +1 -0
  183. package/packages/shared/dist/index.d.ts +3 -0
  184. package/packages/shared/dist/index.d.ts.map +1 -0
  185. package/packages/shared/dist/index.js +50 -0
  186. package/packages/shared/dist/types/domain.d.ts +50 -0
  187. package/packages/shared/dist/types/domain.d.ts.map +1 -0
  188. package/packages/shared/dist/types/index.d.ts +4 -0
  189. package/packages/shared/dist/types/index.d.ts.map +1 -0
  190. package/packages/shared/dist/types/intent.d.ts +24 -0
  191. package/packages/shared/dist/types/intent.d.ts.map +1 -0
  192. package/packages/shared/dist/types/message.d.ts +151 -0
  193. package/packages/shared/dist/types/message.d.ts.map +1 -0
  194. package/packages/shared/dist/utils/id.d.ts +6 -0
  195. package/packages/shared/dist/utils/id.d.ts.map +1 -0
  196. package/packages/shared/dist/utils/index.d.ts +3 -0
  197. package/packages/shared/dist/utils/index.d.ts.map +1 -0
  198. package/packages/shared/dist/utils/message.d.ts +5 -0
  199. package/packages/shared/dist/utils/message.d.ts.map +1 -0
  200. package/packages/shared/package.json +33 -0
  201. package/packages/shared/src/index.ts +2 -0
  202. package/packages/shared/src/types/domain.ts +57 -0
  203. package/packages/shared/src/types/index.ts +3 -0
  204. package/packages/shared/src/types/intent.ts +34 -0
  205. package/packages/shared/src/types/message.ts +188 -0
  206. package/packages/shared/src/utils/id.ts +21 -0
  207. package/packages/shared/src/utils/index.ts +2 -0
  208. package/packages/shared/src/utils/message.ts +30 -0
  209. package/packages/shared/tsconfig.json +9 -0
  210. package/scripts/test-e2e.ts +194 -0
  211. package/scripts/test-mvp2.ts +167 -0
  212. package/scripts/test-mvp3.ts +405 -0
  213. package/tsconfig.json +19 -0
  214. package/turbo.json +22 -0
@@ -0,0 +1,3 @@
1
+ export { IntentHubPlugin, intentHub } from './intent-hub-plugin.js';
2
+ export type { IntentHubPluginConfig, LockInfo, BlockedInfo } from './intent-hub-plugin.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { HubMessage, BroadcastMessage } from '@anthropic-for-korea/intent-hub-shared';
2
+ export interface IntentHubPluginConfig {
3
+ hubUrl: string;
4
+ userId: string;
5
+ username: string;
6
+ projectPath: string;
7
+ }
8
+ export interface LockInfo {
9
+ domain: string;
10
+ username: string;
11
+ intentSummary: string;
12
+ }
13
+ export interface BlockedInfo {
14
+ intentId: string;
15
+ blockedBy: Array<{
16
+ domain: string;
17
+ username: string;
18
+ intentSummary: string;
19
+ }>;
20
+ }
21
+ type MessageCallback = (message: HubMessage | BroadcastMessage) => void;
22
+ type ConnectedCallback = (sessionId: string) => void;
23
+ type DisconnectedCallback = () => void;
24
+ type LockAcquiredCallback = (intentId: string, domains: string[]) => void;
25
+ type LockBlockedCallback = (info: BlockedInfo) => void;
26
+ type LockUpdateCallback = (locks: LockInfo[]) => void;
27
+ export declare class IntentHubPlugin {
28
+ private client;
29
+ private config;
30
+ private currentLocks;
31
+ private messageCallbacks;
32
+ private connectedCallbacks;
33
+ private disconnectedCallbacks;
34
+ private lockAcquiredCallbacks;
35
+ private lockBlockedCallbacks;
36
+ private lockUpdateCallbacks;
37
+ initialize(config: IntentHubPluginConfig): void;
38
+ connect(): void;
39
+ disconnect(): void;
40
+ submitIntent(prompt: string): void;
41
+ isConnected(): boolean;
42
+ getSessionId(): string | null;
43
+ getCurrentLocks(): LockInfo[];
44
+ onMessage(callback: MessageCallback): () => void;
45
+ onConnected(callback: ConnectedCallback): () => void;
46
+ onDisconnected(callback: DisconnectedCallback): () => void;
47
+ onLockAcquired(callback: LockAcquiredCallback): () => void;
48
+ onLockBlocked(callback: LockBlockedCallback): () => void;
49
+ onLockUpdate(callback: LockUpdateCallback): () => void;
50
+ private handleMessage;
51
+ }
52
+ export declare const intentHub: IntentHubPlugin;
53
+ export {};
54
+ //# sourceMappingURL=intent-hub-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-hub-plugin.d.ts","sourceRoot":"","sources":["../../src/plugin/intent-hub-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAG3F,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;CACJ;AAED,KAAK,eAAe,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,gBAAgB,KAAK,IAAI,CAAC;AACxE,KAAK,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AACrD,KAAK,oBAAoB,GAAG,MAAM,IAAI,CAAC;AACvC,KAAK,oBAAoB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAC1E,KAAK,mBAAmB,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;AACvD,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;AAEtD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,YAAY,CAAkB;IAEtC,OAAO,CAAC,gBAAgB,CAAmC;IAC3D,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,qBAAqB,CAAwC;IACrE,OAAO,CAAC,qBAAqB,CAAwC;IACrE,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,mBAAmB,CAAsC;IAEjE,UAAU,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI;IAuB/C,OAAO,IAAI,IAAI;IAOf,UAAU,IAAI,IAAI;IAIlB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOlC,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,eAAe,IAAI,QAAQ,EAAE;IAI7B,SAAS,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IAKhD,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAKpD,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAK1D,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAK1D,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAKxD,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI;IAKtD,OAAO,CAAC,aAAa;CAuBtB;AAED,eAAO,MAAM,SAAS,iBAAwB,CAAC"}
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@anthropic-for-korea/intent-hub-agent",
3
+ "version": "0.1.0",
4
+ "description": "Client library for Intent Hub - connect AI agents to the coordination hub",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "bun build ./src/index.ts --outdir ./dist --target node && tsc --emitDeclarationOnly",
13
+ "dev": "bun build ./src/index.ts --outdir ./dist --target node --watch",
14
+ "typecheck": "tsc --noEmit",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "dependencies": {
18
+ "@anthropic-for-korea/intent-hub-shared": "^0.1.0",
19
+ "ws": "^8.18.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/ws": "^8.5.13",
23
+ "typescript": "^5.7.0"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/anthropic-for-korea/intent-hub.git",
28
+ "directory": "packages/agent"
29
+ },
30
+ "license": "MIT",
31
+ "keywords": ["intent-hub", "llm", "ai", "agent", "coordination", "claude", "opencode"]
32
+ }
@@ -0,0 +1,152 @@
1
+ import WebSocket from 'ws';
2
+ import type {
3
+ AgentConnectMessage,
4
+ AgentIntentSubmitMessage,
5
+ AgentHeartbeatMessage,
6
+ HubMessage,
7
+ BroadcastMessage,
8
+ } from '@anthropic-for-korea/intent-hub-shared';
9
+ import { createMessage, parseMessage, serializeMessage } from '@anthropic-for-korea/intent-hub-shared';
10
+
11
+ export interface HubClientOptions {
12
+ hubUrl: string;
13
+ userId: string;
14
+ username: string;
15
+ projectPath: string;
16
+ onConnected?: (sessionId: string) => void;
17
+ onDisconnected?: () => void;
18
+ onMessage?: (message: HubMessage | BroadcastMessage) => void;
19
+ onError?: (error: Error) => void;
20
+ reconnectInterval?: number;
21
+ }
22
+
23
+ export class HubClient {
24
+ private ws: WebSocket | null = null;
25
+ private sessionId: string | null = null;
26
+ private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
27
+ private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
28
+ private isConnecting = false;
29
+ private shouldReconnect = true;
30
+
31
+ constructor(private options: HubClientOptions) {}
32
+
33
+ connect(): void {
34
+ if (this.ws || this.isConnecting) return;
35
+
36
+ this.isConnecting = true;
37
+ this.shouldReconnect = true;
38
+
39
+ try {
40
+ this.ws = new WebSocket(this.options.hubUrl);
41
+
42
+ this.ws.on('open', () => {
43
+ this.isConnecting = false;
44
+ this.sendConnect();
45
+ this.startHeartbeat();
46
+ });
47
+
48
+ this.ws.on('message', (data) => {
49
+ const message = parseMessage(data.toString());
50
+ if (message) {
51
+ this.handleMessage(message as HubMessage | BroadcastMessage);
52
+ }
53
+ });
54
+
55
+ this.ws.on('close', () => {
56
+ this.cleanup();
57
+ this.options.onDisconnected?.();
58
+ this.scheduleReconnect();
59
+ });
60
+
61
+ this.ws.on('error', (error) => {
62
+ this.options.onError?.(error);
63
+ });
64
+ } catch (error) {
65
+ this.isConnecting = false;
66
+ this.options.onError?.(error as Error);
67
+ this.scheduleReconnect();
68
+ }
69
+ }
70
+
71
+ disconnect(): void {
72
+ this.shouldReconnect = false;
73
+ this.cleanup();
74
+ if (this.ws) {
75
+ this.ws.close();
76
+ this.ws = null;
77
+ }
78
+ }
79
+
80
+ submitIntent(prompt: string): void {
81
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
82
+ throw new Error('Not connected to hub');
83
+ }
84
+
85
+ const message = createMessage<AgentIntentSubmitMessage>('agent:intent:submit', {
86
+ payload: { prompt },
87
+ });
88
+ this.ws.send(serializeMessage(message));
89
+ }
90
+
91
+ isConnected(): boolean {
92
+ return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
93
+ }
94
+
95
+ getSessionId(): string | null {
96
+ return this.sessionId;
97
+ }
98
+
99
+ private sendConnect(): void {
100
+ if (!this.ws) return;
101
+
102
+ const message = createMessage<AgentConnectMessage>('agent:connect', {
103
+ payload: {
104
+ userId: this.options.userId,
105
+ username: this.options.username,
106
+ projectPath: this.options.projectPath,
107
+ },
108
+ });
109
+ this.ws.send(serializeMessage(message));
110
+ }
111
+
112
+ private handleMessage(message: HubMessage | BroadcastMessage): void {
113
+ if (message.type === 'hub:connected') {
114
+ this.sessionId = (message as any).payload.sessionId;
115
+ this.options.onConnected?.(this.sessionId!);
116
+ }
117
+
118
+ this.options.onMessage?.(message);
119
+ }
120
+
121
+ private startHeartbeat(): void {
122
+ this.heartbeatTimer = setInterval(() => {
123
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
124
+ const message = createMessage<AgentHeartbeatMessage>('agent:heartbeat', {});
125
+ this.ws.send(serializeMessage(message));
126
+ }
127
+ }, 30000);
128
+ }
129
+
130
+ private cleanup(): void {
131
+ if (this.heartbeatTimer) {
132
+ clearInterval(this.heartbeatTimer);
133
+ this.heartbeatTimer = null;
134
+ }
135
+ if (this.reconnectTimer) {
136
+ clearTimeout(this.reconnectTimer);
137
+ this.reconnectTimer = null;
138
+ }
139
+ this.sessionId = null;
140
+ this.isConnecting = false;
141
+ }
142
+
143
+ private scheduleReconnect(): void {
144
+ if (!this.shouldReconnect) return;
145
+
146
+ const interval = this.options.reconnectInterval ?? 5000;
147
+ this.reconnectTimer = setTimeout(() => {
148
+ this.ws = null;
149
+ this.connect();
150
+ }, interval);
151
+ }
152
+ }
@@ -0,0 +1 @@
1
+ export { HubClient } from './hub-client.js';
@@ -0,0 +1,2 @@
1
+ export { IntentHubHooks, createIntentHubHooks } from './intent-hub-hooks.js';
2
+ export type { HookContext, HookResult, IntentHubHooksConfig } from './intent-hub-hooks.js';
@@ -0,0 +1,245 @@
1
+ import type { HubMessage, BroadcastMessage } from '@anthropic-for-korea/intent-hub-shared';
2
+ import { HubClient } from '../connection/hub-client.js';
3
+
4
+ export interface HookContext {
5
+ toolName: string;
6
+ toolInput: Record<string, unknown>;
7
+ sessionId: string;
8
+ userId: string;
9
+ username: string;
10
+ }
11
+
12
+ export interface HookResult {
13
+ allow: boolean;
14
+ message?: string;
15
+ modifiedInput?: Record<string, unknown>;
16
+ }
17
+
18
+ export interface IntentHubHooksConfig {
19
+ hubUrl: string;
20
+ userId: string;
21
+ username: string;
22
+ projectPath: string;
23
+ autoConnect?: boolean;
24
+ onNotification?: (event: string, data: unknown) => void;
25
+ }
26
+
27
+ export class IntentHubHooks {
28
+ private client: HubClient | null = null;
29
+ private config: IntentHubHooksConfig;
30
+ private currentIntent: string | null = null;
31
+ private blockedDomains: Set<string> = new Set();
32
+ private pendingDecisions: Map<string, {
33
+ resolve: (value: string) => void;
34
+ options: Array<{ id: string; description: string }>;
35
+ }> = new Map();
36
+
37
+ constructor(config: IntentHubHooksConfig) {
38
+ this.config = config;
39
+ if (config.autoConnect !== false) {
40
+ this.connect();
41
+ }
42
+ }
43
+
44
+ connect(): void {
45
+ this.client = new HubClient({
46
+ hubUrl: this.config.hubUrl,
47
+ userId: this.config.userId,
48
+ username: this.config.username,
49
+ projectPath: this.config.projectPath,
50
+ onConnected: (sessionId) => {
51
+ console.log(`[IntentHub] Connected to hub (session: ${sessionId})`);
52
+ },
53
+ onDisconnected: () => {
54
+ console.log('[IntentHub] Disconnected from hub');
55
+ },
56
+ onMessage: (message) => this.handleMessage(message),
57
+ onError: (error) => {
58
+ console.error('[IntentHub] Connection error:', error.message);
59
+ },
60
+ });
61
+ this.client.connect();
62
+ }
63
+
64
+ disconnect(): void {
65
+ this.client?.disconnect();
66
+ this.client = null;
67
+ }
68
+
69
+ async preToolUse(context: HookContext): Promise<HookResult> {
70
+ const editTools = ['edit', 'write', 'Edit', 'Write', 'MultiEdit'];
71
+
72
+ if (!editTools.includes(context.toolName)) {
73
+ return { allow: true };
74
+ }
75
+
76
+ const filePath = context.toolInput['filePath'] as string | undefined;
77
+ if (!filePath) {
78
+ return { allow: true };
79
+ }
80
+
81
+ const domain = this.inferDomainFromPath(filePath);
82
+
83
+ if (this.blockedDomains.has(domain)) {
84
+ return {
85
+ allow: false,
86
+ message: `⚠️ [IntentHub] This domain (${domain}) is currently being worked on by another team member. Please wait or work on a different area.`,
87
+ };
88
+ }
89
+
90
+ if (!this.currentIntent && this.client?.isConnected()) {
91
+ const prompt = `Editing file: ${filePath}`;
92
+ this.client.submitIntent(prompt);
93
+ }
94
+
95
+ return { allow: true };
96
+ }
97
+
98
+ async postToolUse(context: HookContext, result: unknown): Promise<void> {
99
+ const editTools = ['edit', 'write', 'Edit', 'Write', 'MultiEdit'];
100
+
101
+ if (!editTools.includes(context.toolName)) {
102
+ return;
103
+ }
104
+ }
105
+
106
+ async onUserPromptSubmit(prompt: string): Promise<{
107
+ modifiedPrompt?: string;
108
+ cancel?: boolean;
109
+ message?: string;
110
+ }> {
111
+ if (!this.client?.isConnected()) {
112
+ return {};
113
+ }
114
+
115
+ this.client.submitIntent(prompt);
116
+
117
+ await this.waitForResponse(1000);
118
+
119
+ if (this.blockedDomains.size > 0) {
120
+ const domains = Array.from(this.blockedDomains).join(', ');
121
+ return {
122
+ message: `⚠️ [IntentHub] Note: The following domains are currently locked by other team members: ${domains}. Your work may be queued.`,
123
+ };
124
+ }
125
+
126
+ return {};
127
+ }
128
+
129
+ async onStop(): Promise<void> {
130
+ if (this.currentIntent) {
131
+ this.currentIntent = null;
132
+ }
133
+ this.blockedDomains.clear();
134
+ }
135
+
136
+ submitDecision(conflictId: string, choice: string): void {
137
+ const pending = this.pendingDecisions.get(conflictId);
138
+ if (pending) {
139
+ pending.resolve(choice);
140
+ this.pendingDecisions.delete(conflictId);
141
+ }
142
+ }
143
+
144
+ private handleMessage(message: HubMessage | BroadcastMessage): void {
145
+ switch (message.type) {
146
+ case 'hub:lock:acquired': {
147
+ const payload = (message as any).payload;
148
+ this.currentIntent = payload.intentId;
149
+ this.config.onNotification?.('lock:acquired', {
150
+ domains: payload.domains,
151
+ });
152
+ break;
153
+ }
154
+
155
+ case 'hub:lock:blocked': {
156
+ const payload = (message as any).payload;
157
+ for (const block of payload.blockedBy) {
158
+ this.blockedDomains.add(block.domain);
159
+ }
160
+ this.config.onNotification?.('lock:blocked', {
161
+ blockedBy: payload.blockedBy,
162
+ });
163
+ break;
164
+ }
165
+
166
+ case 'hub:negotiation:start': {
167
+ const payload = (message as any).payload;
168
+ this.config.onNotification?.('negotiation:start', payload);
169
+ break;
170
+ }
171
+
172
+ case 'hub:negotiation:resolved': {
173
+ const payload = (message as any).payload;
174
+ this.blockedDomains.clear();
175
+ this.config.onNotification?.('negotiation:resolved', payload);
176
+ break;
177
+ }
178
+
179
+ case 'hub:decision:required': {
180
+ const payload = (message as any).payload;
181
+ this.config.onNotification?.('decision:required', payload);
182
+ break;
183
+ }
184
+
185
+ case 'broadcast:lock:update': {
186
+ const payload = (message as any).payload;
187
+ this.blockedDomains.clear();
188
+ for (const lock of payload.locks) {
189
+ if (lock.username !== this.config.username) {
190
+ this.blockedDomains.add(lock.domainId);
191
+ }
192
+ }
193
+ this.config.onNotification?.('locks:updated', { locks: payload.locks });
194
+ break;
195
+ }
196
+
197
+ case 'broadcast:user:joined': {
198
+ const payload = (message as any).payload;
199
+ this.config.onNotification?.('user:joined', payload);
200
+ break;
201
+ }
202
+
203
+ case 'broadcast:user:left': {
204
+ const payload = (message as any).payload;
205
+ this.config.onNotification?.('user:left', payload);
206
+ break;
207
+ }
208
+ }
209
+ }
210
+
211
+ private inferDomainFromPath(filePath: string): string {
212
+ const lower = filePath.toLowerCase();
213
+
214
+ if (lower.includes('/auth/') || lower.includes('auth.')) return 'auth';
215
+ if (lower.includes('/user/') || lower.includes('user.')) return 'user';
216
+ if (lower.includes('/payment/') || lower.includes('payment.')) return 'payment';
217
+ if (lower.includes('/api/') || lower.includes('route')) return 'api';
218
+ if (lower.includes('/component') || lower.includes('.tsx') || lower.includes('.jsx')) return 'ui';
219
+ if (lower.includes('/test/') || lower.includes('.test.') || lower.includes('.spec.')) return 'test';
220
+ if (lower.includes('config') || lower.includes('.env')) return 'config';
221
+ if (lower.includes('/db/') || lower.includes('database') || lower.includes('migration')) return 'database';
222
+
223
+ return 'general';
224
+ }
225
+
226
+ private waitForResponse(ms: number): Promise<void> {
227
+ return new Promise(resolve => setTimeout(resolve, ms));
228
+ }
229
+
230
+ isConnected(): boolean {
231
+ return this.client?.isConnected() ?? false;
232
+ }
233
+
234
+ getBlockedDomains(): string[] {
235
+ return Array.from(this.blockedDomains);
236
+ }
237
+
238
+ getCurrentIntent(): string | null {
239
+ return this.currentIntent;
240
+ }
241
+ }
242
+
243
+ export function createIntentHubHooks(config: IntentHubHooksConfig): IntentHubHooks {
244
+ return new IntentHubHooks(config);
245
+ }
@@ -0,0 +1,5 @@
1
+ export { HubClient } from './connection/index.js';
2
+ export { IntentHubPlugin, intentHub } from './plugin/index.js';
3
+ export type { IntentHubPluginConfig, LockInfo, BlockedInfo } from './plugin/index.js';
4
+ export { IntentHubHooks, createIntentHubHooks } from './hooks/index.js';
5
+ export type { HookContext, HookResult, IntentHubHooksConfig } from './hooks/index.js';
@@ -0,0 +1,2 @@
1
+ export { IntentHubPlugin, intentHub } from './intent-hub-plugin.js';
2
+ export type { IntentHubPluginConfig, LockInfo, BlockedInfo } from './intent-hub-plugin.js';
@@ -0,0 +1,153 @@
1
+ import type { HubMessage, BroadcastMessage } from '@anthropic-for-korea/intent-hub-shared';
2
+ import { HubClient } from '../connection/hub-client.js';
3
+
4
+ export interface IntentHubPluginConfig {
5
+ hubUrl: string;
6
+ userId: string;
7
+ username: string;
8
+ projectPath: string;
9
+ }
10
+
11
+ export interface LockInfo {
12
+ domain: string;
13
+ username: string;
14
+ intentSummary: string;
15
+ }
16
+
17
+ export interface BlockedInfo {
18
+ intentId: string;
19
+ blockedBy: Array<{
20
+ domain: string;
21
+ username: string;
22
+ intentSummary: string;
23
+ }>;
24
+ }
25
+
26
+ type MessageCallback = (message: HubMessage | BroadcastMessage) => void;
27
+ type ConnectedCallback = (sessionId: string) => void;
28
+ type DisconnectedCallback = () => void;
29
+ type LockAcquiredCallback = (intentId: string, domains: string[]) => void;
30
+ type LockBlockedCallback = (info: BlockedInfo) => void;
31
+ type LockUpdateCallback = (locks: LockInfo[]) => void;
32
+
33
+ export class IntentHubPlugin {
34
+ private client: HubClient | null = null;
35
+ private config: IntentHubPluginConfig | null = null;
36
+ private currentLocks: LockInfo[] = [];
37
+
38
+ private messageCallbacks: Set<MessageCallback> = new Set();
39
+ private connectedCallbacks: Set<ConnectedCallback> = new Set();
40
+ private disconnectedCallbacks: Set<DisconnectedCallback> = new Set();
41
+ private lockAcquiredCallbacks: Set<LockAcquiredCallback> = new Set();
42
+ private lockBlockedCallbacks: Set<LockBlockedCallback> = new Set();
43
+ private lockUpdateCallbacks: Set<LockUpdateCallback> = new Set();
44
+
45
+ initialize(config: IntentHubPluginConfig): void {
46
+ this.config = config;
47
+ this.client = new HubClient({
48
+ hubUrl: config.hubUrl,
49
+ userId: config.userId,
50
+ username: config.username,
51
+ projectPath: config.projectPath,
52
+ onConnected: (sessionId) => {
53
+ this.connectedCallbacks.forEach(cb => cb(sessionId));
54
+ },
55
+ onDisconnected: () => {
56
+ this.disconnectedCallbacks.forEach(cb => cb());
57
+ },
58
+ onMessage: (message) => {
59
+ this.handleMessage(message);
60
+ this.messageCallbacks.forEach(cb => cb(message));
61
+ },
62
+ onError: (error) => {
63
+ console.error('[IntentHub] Connection error:', error.message);
64
+ },
65
+ });
66
+ }
67
+
68
+ connect(): void {
69
+ if (!this.client) {
70
+ throw new Error('Plugin not initialized. Call initialize() first.');
71
+ }
72
+ this.client.connect();
73
+ }
74
+
75
+ disconnect(): void {
76
+ this.client?.disconnect();
77
+ }
78
+
79
+ submitIntent(prompt: string): void {
80
+ if (!this.client) {
81
+ throw new Error('Plugin not initialized');
82
+ }
83
+ this.client.submitIntent(prompt);
84
+ }
85
+
86
+ isConnected(): boolean {
87
+ return this.client?.isConnected() ?? false;
88
+ }
89
+
90
+ getSessionId(): string | null {
91
+ return this.client?.getSessionId() ?? null;
92
+ }
93
+
94
+ getCurrentLocks(): LockInfo[] {
95
+ return [...this.currentLocks];
96
+ }
97
+
98
+ onMessage(callback: MessageCallback): () => void {
99
+ this.messageCallbacks.add(callback);
100
+ return () => this.messageCallbacks.delete(callback);
101
+ }
102
+
103
+ onConnected(callback: ConnectedCallback): () => void {
104
+ this.connectedCallbacks.add(callback);
105
+ return () => this.connectedCallbacks.delete(callback);
106
+ }
107
+
108
+ onDisconnected(callback: DisconnectedCallback): () => void {
109
+ this.disconnectedCallbacks.add(callback);
110
+ return () => this.disconnectedCallbacks.delete(callback);
111
+ }
112
+
113
+ onLockAcquired(callback: LockAcquiredCallback): () => void {
114
+ this.lockAcquiredCallbacks.add(callback);
115
+ return () => this.lockAcquiredCallbacks.delete(callback);
116
+ }
117
+
118
+ onLockBlocked(callback: LockBlockedCallback): () => void {
119
+ this.lockBlockedCallbacks.add(callback);
120
+ return () => this.lockBlockedCallbacks.delete(callback);
121
+ }
122
+
123
+ onLockUpdate(callback: LockUpdateCallback): () => void {
124
+ this.lockUpdateCallbacks.add(callback);
125
+ return () => this.lockUpdateCallbacks.delete(callback);
126
+ }
127
+
128
+ private handleMessage(message: HubMessage | BroadcastMessage): void {
129
+ switch (message.type) {
130
+ case 'hub:lock:acquired': {
131
+ const payload = (message as any).payload;
132
+ this.lockAcquiredCallbacks.forEach(cb => cb(payload.intentId, payload.domains));
133
+ break;
134
+ }
135
+ case 'hub:lock:blocked': {
136
+ const payload = (message as any).payload;
137
+ this.lockBlockedCallbacks.forEach(cb => cb({
138
+ intentId: payload.intentId,
139
+ blockedBy: payload.blockedBy,
140
+ }));
141
+ break;
142
+ }
143
+ case 'broadcast:lock:update': {
144
+ const payload = (message as any).payload;
145
+ this.currentLocks = payload.locks;
146
+ this.lockUpdateCallbacks.forEach(cb => cb(this.currentLocks));
147
+ break;
148
+ }
149
+ }
150
+ }
151
+ }
152
+
153
+ export const intentHub = new IntentHubPlugin();
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
@@ -0,0 +1,6 @@
1
+ $ bun build ./src/index.ts ./src/cli.ts --outdir ./dist --target node && tsc --emitDeclarationOnly
2
+ Bundled 74 modules in 5ms
3
+
4
+ index.js 151.96 KB (entry point)
5
+ cli.js 253.21 KB (entry point)
6
+
@@ -0,0 +1 @@
1
+ $ tsc --noEmit