@intrect/openswarm 0.2.2 → 0.4.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 (176) hide show
  1. package/README.md +236 -331
  2. package/config.example.yaml +36 -13
  3. package/dist/adapters/agenticLoop.d.ts +90 -0
  4. package/dist/adapters/agenticLoop.d.ts.map +1 -0
  5. package/dist/adapters/agenticLoop.js +141 -0
  6. package/dist/adapters/agenticLoop.js.map +1 -0
  7. package/dist/adapters/base.d.ts.map +1 -1
  8. package/dist/adapters/base.js +4 -0
  9. package/dist/adapters/base.js.map +1 -1
  10. package/dist/adapters/cryptoQuantAdapter.js +1 -1
  11. package/dist/adapters/cryptoQuantAdapter.js.map +1 -1
  12. package/dist/adapters/gpt.d.ts +19 -0
  13. package/dist/adapters/gpt.d.ts.map +1 -0
  14. package/dist/adapters/gpt.js +251 -0
  15. package/dist/adapters/gpt.js.map +1 -0
  16. package/dist/adapters/index.d.ts +2 -0
  17. package/dist/adapters/index.d.ts.map +1 -1
  18. package/dist/adapters/index.js +6 -0
  19. package/dist/adapters/index.js.map +1 -1
  20. package/dist/adapters/local.d.ts +31 -0
  21. package/dist/adapters/local.d.ts.map +1 -0
  22. package/dist/adapters/local.js +320 -0
  23. package/dist/adapters/local.js.map +1 -0
  24. package/dist/adapters/tools.d.ts +30 -0
  25. package/dist/adapters/tools.d.ts.map +1 -0
  26. package/dist/adapters/tools.js +219 -0
  27. package/dist/adapters/tools.js.map +1 -0
  28. package/dist/adapters/types.d.ts +6 -1
  29. package/dist/adapters/types.d.ts.map +1 -1
  30. package/dist/agents/pairPipeline.d.ts +7 -0
  31. package/dist/agents/pairPipeline.d.ts.map +1 -1
  32. package/dist/agents/pairPipeline.js +99 -7
  33. package/dist/agents/pairPipeline.js.map +1 -1
  34. package/dist/agents/pipelineGuards.d.ts.map +1 -1
  35. package/dist/agents/pipelineGuards.js +84 -2
  36. package/dist/agents/pipelineGuards.js.map +1 -1
  37. package/dist/agents/worker.d.ts +3 -0
  38. package/dist/agents/worker.d.ts.map +1 -1
  39. package/dist/agents/worker.js +1 -0
  40. package/dist/agents/worker.js.map +1 -1
  41. package/dist/auth/index.d.ts +3 -0
  42. package/dist/auth/index.d.ts.map +1 -0
  43. package/dist/auth/index.js +6 -0
  44. package/dist/auth/index.js.map +1 -0
  45. package/dist/auth/oauthPkce.d.ts +21 -0
  46. package/dist/auth/oauthPkce.d.ts.map +1 -0
  47. package/dist/auth/oauthPkce.js +212 -0
  48. package/dist/auth/oauthPkce.js.map +1 -0
  49. package/dist/auth/oauthStore.d.ts +24 -0
  50. package/dist/auth/oauthStore.d.ts.map +1 -0
  51. package/dist/auth/oauthStore.js +96 -0
  52. package/dist/auth/oauthStore.js.map +1 -0
  53. package/dist/automation/autonomousRunner.d.ts +5 -5
  54. package/dist/automation/runnerTypes.d.ts +1 -1
  55. package/dist/automation/runnerTypes.d.ts.map +1 -1
  56. package/dist/cli/authHandler.d.ts +16 -0
  57. package/dist/cli/authHandler.d.ts.map +1 -0
  58. package/dist/cli/authHandler.js +93 -0
  59. package/dist/cli/authHandler.js.map +1 -0
  60. package/dist/cli/checkHandler.d.ts +25 -0
  61. package/dist/cli/checkHandler.d.ts.map +1 -0
  62. package/dist/cli/checkHandler.js +465 -0
  63. package/dist/cli/checkHandler.js.map +1 -0
  64. package/dist/cli.js +64 -0
  65. package/dist/cli.js.map +1 -1
  66. package/dist/core/config.d.ts +17 -4
  67. package/dist/core/config.d.ts.map +1 -1
  68. package/dist/core/config.js +21 -8
  69. package/dist/core/config.js.map +1 -1
  70. package/dist/core/service.d.ts.map +1 -1
  71. package/dist/core/service.js +18 -8
  72. package/dist/core/service.js.map +1 -1
  73. package/dist/core/types.d.ts +4 -2
  74. package/dist/core/types.d.ts.map +1 -1
  75. package/dist/issues/graphql/resolvers.d.ts +252 -0
  76. package/dist/issues/graphql/resolvers.d.ts.map +1 -0
  77. package/dist/issues/graphql/resolvers.js +88 -0
  78. package/dist/issues/graphql/resolvers.js.map +1 -0
  79. package/dist/issues/graphql/server.d.ts +13 -0
  80. package/dist/issues/graphql/server.d.ts.map +1 -0
  81. package/dist/issues/graphql/server.js +56 -0
  82. package/dist/issues/graphql/server.js.map +1 -0
  83. package/dist/issues/graphql/typeDefs.d.ts +2 -0
  84. package/dist/issues/graphql/typeDefs.d.ts.map +1 -0
  85. package/dist/issues/graphql/typeDefs.js +251 -0
  86. package/dist/issues/graphql/typeDefs.js.map +1 -0
  87. package/dist/issues/index.d.ts +8 -0
  88. package/dist/issues/index.d.ts.map +1 -0
  89. package/dist/issues/index.js +11 -0
  90. package/dist/issues/index.js.map +1 -0
  91. package/dist/issues/issueBoardHtml.d.ts +2 -0
  92. package/dist/issues/issueBoardHtml.d.ts.map +1 -0
  93. package/dist/issues/issueBoardHtml.js +677 -0
  94. package/dist/issues/issueBoardHtml.js.map +1 -0
  95. package/dist/issues/linearBridge.d.ts +27 -0
  96. package/dist/issues/linearBridge.d.ts.map +1 -0
  97. package/dist/issues/linearBridge.js +211 -0
  98. package/dist/issues/linearBridge.js.map +1 -0
  99. package/dist/issues/memoryBridge.d.ts +35 -0
  100. package/dist/issues/memoryBridge.d.ts.map +1 -0
  101. package/dist/issues/memoryBridge.js +184 -0
  102. package/dist/issues/memoryBridge.js.map +1 -0
  103. package/dist/issues/schema.d.ts +162 -0
  104. package/dist/issues/schema.d.ts.map +1 -0
  105. package/dist/issues/schema.js +121 -0
  106. package/dist/issues/schema.js.map +1 -0
  107. package/dist/issues/sqliteStore.d.ts +90 -0
  108. package/dist/issues/sqliteStore.d.ts.map +1 -0
  109. package/dist/issues/sqliteStore.js +488 -0
  110. package/dist/issues/sqliteStore.js.map +1 -0
  111. package/dist/knowledge/index.d.ts.map +1 -1
  112. package/dist/knowledge/index.js +9 -3
  113. package/dist/knowledge/index.js.map +1 -1
  114. package/dist/linear/linear.d.ts +4 -0
  115. package/dist/linear/linear.d.ts.map +1 -1
  116. package/dist/linear/linear.js +27 -0
  117. package/dist/linear/linear.js.map +1 -1
  118. package/dist/locale/prompts/en.d.ts.map +1 -1
  119. package/dist/locale/prompts/en.js +32 -2
  120. package/dist/locale/prompts/en.js.map +1 -1
  121. package/dist/locale/prompts/ko.d.ts.map +1 -1
  122. package/dist/locale/prompts/ko.js +32 -2
  123. package/dist/locale/prompts/ko.js.map +1 -1
  124. package/dist/locale/types.d.ts +17 -0
  125. package/dist/locale/types.d.ts.map +1 -1
  126. package/dist/registry/bsDetector.d.ts +24 -0
  127. package/dist/registry/bsDetector.d.ts.map +1 -0
  128. package/dist/registry/bsDetector.js +276 -0
  129. package/dist/registry/bsDetector.js.map +1 -0
  130. package/dist/registry/entityScanner.d.ts +36 -0
  131. package/dist/registry/entityScanner.d.ts.map +1 -0
  132. package/dist/registry/entityScanner.js +693 -0
  133. package/dist/registry/entityScanner.js.map +1 -0
  134. package/dist/registry/graphql/resolvers.d.ts +778 -0
  135. package/dist/registry/graphql/resolvers.d.ts.map +1 -0
  136. package/dist/registry/graphql/resolvers.js +127 -0
  137. package/dist/registry/graphql/resolvers.js.map +1 -0
  138. package/dist/registry/graphql/typeDefs.d.ts +2 -0
  139. package/dist/registry/graphql/typeDefs.d.ts.map +1 -0
  140. package/dist/registry/graphql/typeDefs.js +276 -0
  141. package/dist/registry/graphql/typeDefs.js.map +1 -0
  142. package/dist/registry/index.d.ts +12 -0
  143. package/dist/registry/index.d.ts.map +1 -0
  144. package/dist/registry/index.js +18 -0
  145. package/dist/registry/index.js.map +1 -0
  146. package/dist/registry/issueBridge.d.ts +8 -0
  147. package/dist/registry/issueBridge.d.ts.map +1 -0
  148. package/dist/registry/issueBridge.js +30 -0
  149. package/dist/registry/issueBridge.js.map +1 -0
  150. package/dist/registry/memoryBridge.d.ts +13 -0
  151. package/dist/registry/memoryBridge.d.ts.map +1 -0
  152. package/dist/registry/memoryBridge.js +60 -0
  153. package/dist/registry/memoryBridge.js.map +1 -0
  154. package/dist/registry/schema.d.ts +307 -0
  155. package/dist/registry/schema.d.ts.map +1 -0
  156. package/dist/registry/schema.js +139 -0
  157. package/dist/registry/schema.js.map +1 -0
  158. package/dist/registry/sqliteStore.d.ts +101 -0
  159. package/dist/registry/sqliteStore.d.ts.map +1 -0
  160. package/dist/registry/sqliteStore.js +688 -0
  161. package/dist/registry/sqliteStore.js.map +1 -0
  162. package/dist/support/chatBackend.d.ts.map +1 -1
  163. package/dist/support/chatBackend.js +35 -4
  164. package/dist/support/chatBackend.js.map +1 -1
  165. package/dist/support/chatTui.d.ts.map +1 -1
  166. package/dist/support/chatTui.js +109 -3
  167. package/dist/support/chatTui.js.map +1 -1
  168. package/dist/support/dashboardHtml.d.ts +1 -1
  169. package/dist/support/dashboardHtml.d.ts.map +1 -1
  170. package/dist/support/dashboardHtml.js +1 -0
  171. package/dist/support/dashboardHtml.js.map +1 -1
  172. package/dist/support/web.d.ts.map +1 -1
  173. package/dist/support/web.js +16 -3
  174. package/dist/support/web.js.map +1 -1
  175. package/package.json +8 -2
  176. package/templates/TOOLS.md +2 -2
@@ -0,0 +1,251 @@
1
+ // ============================================
2
+ // OpenSwarm - Issue Tracker GraphQL Type Definitions
3
+ // Created: 2026-04-03
4
+ // Purpose: GraphQL 스키마 정의
5
+ // ============================================
6
+ export const typeDefs = /* GraphQL */ `
7
+ type Query {
8
+ # 이슈
9
+ issue(id: ID!): Issue
10
+ issues(filter: IssueFilterInput): IssueConnection!
11
+
12
+ # 라벨 & 마일스톤
13
+ labels: [Label!]!
14
+ milestones: [Milestone!]!
15
+
16
+ # 이벤트 로그
17
+ issueEvents(issueId: ID!, limit: Int): [IssueEvent!]!
18
+ recentEvents(limit: Int): [IssueEvent!]!
19
+
20
+ # 통계
21
+ issueStats(projectId: String): IssueStats!
22
+
23
+ # 메모리 연동
24
+ linkedMemories(issueId: ID!): [String!]!
25
+ issueContext(issueId: ID!): IssueContext!
26
+ }
27
+
28
+ type Mutation {
29
+ # 이슈 CRUD
30
+ createIssue(input: CreateIssueInput!): Issue!
31
+ updateIssue(id: ID!, input: UpdateIssueInput!): Issue
32
+ deleteIssue(id: ID!): Boolean!
33
+
34
+ # 상태 전이
35
+ changeIssueStatus(id: ID!, status: IssueStatus!, actor: String): Issue
36
+
37
+ # 이벤트
38
+ addComment(issueId: ID!, content: String!, actor: String): IssueEvent!
39
+
40
+ # 라벨
41
+ createLabel(name: String!, color: String, description: String): Label!
42
+ deleteLabel(id: ID!): Boolean!
43
+
44
+ # 마일스톤
45
+ createMilestone(name: String!, description: String, dueDate: String): Milestone!
46
+
47
+ # 메모리 연동
48
+ linkMemory(issueId: ID!, memoryId: String!): Boolean!
49
+ autoLinkMemories(issueId: ID!): [String!]!
50
+ }
51
+
52
+ type Subscription {
53
+ issueUpdated(projectId: String): Issue!
54
+ issueEventAdded(issueId: ID): IssueEvent!
55
+ }
56
+
57
+ # ---- Types ----
58
+
59
+ type Issue {
60
+ id: ID!
61
+ projectId: String!
62
+ title: String!
63
+ description: String!
64
+ status: IssueStatus!
65
+ priority: IssuePriority!
66
+ source: IssueSource!
67
+ labels: [String!]!
68
+ assignee: String
69
+ milestone: String
70
+ relevantFiles: [String!]!
71
+ acceptanceCriteria: [String!]!
72
+ estimateMinutes: Int
73
+ complexity: Complexity
74
+ dependencies: [String!]!
75
+ parentId: String
76
+ childIds: [String!]!
77
+ linearId: String
78
+ linearIdentifier: String
79
+ linearUrl: String
80
+ memoryIds: [String!]!
81
+ createdAt: String!
82
+ updatedAt: String!
83
+ closedAt: String
84
+ }
85
+
86
+ type IssueConnection {
87
+ issues: [Issue!]!
88
+ total: Int!
89
+ }
90
+
91
+ type IssueEvent {
92
+ id: ID!
93
+ issueId: String!
94
+ type: IssueEventType!
95
+ oldValue: String
96
+ newValue: String
97
+ content: String
98
+ memoryId: String
99
+ actor: String!
100
+ createdAt: String!
101
+ }
102
+
103
+ type Label {
104
+ id: ID!
105
+ name: String!
106
+ color: String!
107
+ description: String
108
+ }
109
+
110
+ type Milestone {
111
+ id: ID!
112
+ name: String!
113
+ description: String
114
+ dueDate: String
115
+ status: String!
116
+ createdAt: String!
117
+ }
118
+
119
+ type IssueStats {
120
+ total: Int!
121
+ byStatus: [StatusCount!]!
122
+ byPriority: [PriorityCount!]!
123
+ byProject: [ProjectCount!]!
124
+ recentlyCreated: Int!
125
+ recentlyClosed: Int!
126
+ }
127
+
128
+ type StatusCount {
129
+ status: String!
130
+ count: Int!
131
+ }
132
+
133
+ type PriorityCount {
134
+ priority: String!
135
+ count: Int!
136
+ }
137
+
138
+ type ProjectCount {
139
+ projectId: String!
140
+ count: Int!
141
+ }
142
+
143
+ type IssueContext {
144
+ linkedMemories: [MemoryRef!]!
145
+ similarIssues: [Issue!]!
146
+ }
147
+
148
+ type MemoryRef {
149
+ id: String!
150
+ content: String!
151
+ score: Float!
152
+ }
153
+
154
+ # ---- Enums ----
155
+
156
+ enum IssueStatus {
157
+ backlog
158
+ todo
159
+ in_progress
160
+ in_review
161
+ done
162
+ cancelled
163
+ }
164
+
165
+ enum IssuePriority {
166
+ urgent
167
+ high
168
+ medium
169
+ low
170
+ none
171
+ }
172
+
173
+ enum IssueSource {
174
+ local
175
+ linear
176
+ github
177
+ discord
178
+ }
179
+
180
+ enum Complexity {
181
+ simple
182
+ moderate
183
+ complex
184
+ very_complex
185
+ }
186
+
187
+ enum IssueEventType {
188
+ created
189
+ status_changed
190
+ priority_changed
191
+ assigned
192
+ commented
193
+ labeled
194
+ linked
195
+ memory_linked
196
+ closed
197
+ reopened
198
+ }
199
+
200
+ # ---- Inputs ----
201
+
202
+ input CreateIssueInput {
203
+ projectId: String!
204
+ title: String!
205
+ description: String
206
+ status: IssueStatus
207
+ priority: IssuePriority
208
+ source: IssueSource
209
+ labels: [String!]
210
+ assignee: String
211
+ milestone: String
212
+ relevantFiles: [String!]
213
+ acceptanceCriteria: [String!]
214
+ estimateMinutes: Int
215
+ complexity: Complexity
216
+ dependencies: [String!]
217
+ parentId: String
218
+ linearId: String
219
+ linearIdentifier: String
220
+ linearUrl: String
221
+ }
222
+
223
+ input UpdateIssueInput {
224
+ title: String
225
+ description: String
226
+ priority: IssuePriority
227
+ labels: [String!]
228
+ assignee: String
229
+ milestone: String
230
+ relevantFiles: [String!]
231
+ acceptanceCriteria: [String!]
232
+ estimateMinutes: Int
233
+ complexity: Complexity
234
+ dependencies: [String!]
235
+ parentId: String
236
+ }
237
+
238
+ input IssueFilterInput {
239
+ projectId: String
240
+ status: [IssueStatus!]
241
+ priority: [IssuePriority!]
242
+ labels: [String!]
243
+ assignee: String
244
+ source: IssueSource
245
+ parentId: String
246
+ search: String
247
+ limit: Int
248
+ offset: Int
249
+ }
250
+ `;
251
+ //# sourceMappingURL=typeDefs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeDefs.js","sourceRoot":"","sources":["../../../src/issues/graphql/typeDefs.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,qDAAqD;AACrD,sBAAsB;AACtB,0BAA0B;AAC1B,+CAA+C;AAE/C,MAAM,CAAC,MAAM,QAAQ,GAAG,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoPrC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { getIssueStore, closeIssueStore, SqliteIssueStore } from './sqliteStore.js';
2
+ export type { IIssueStore, CreateIssueInput, EventData, IssueStats } from './sqliteStore.js';
3
+ export type { Issue, IssueEvent, IssueFilter, IssueStatus, IssuePriority, IssueSource, IssueEventType, Label, Milestone, } from './schema.js';
4
+ export { IssueSchema, IssueEventSchema, IssueFilterSchema, IssueStatusSchema, IssuePrioritySchema, LabelSchema, MilestoneSchema, } from './schema.js';
5
+ export { autoLinkMemories, saveCompletionInsight, saveBlockingConstraint, enrichIssueContext, digestRecentEvents, } from './memoryBridge.js';
6
+ export { handleGraphQL, isGraphQLRequest } from './graphql/server.js';
7
+ export { initLinearBridge, syncFromLinear, pushToLinear, syncStatusToLinear, isLinearBridgeReady, } from './linearBridge.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/issues/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC7F,YAAY,EACV,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAC1D,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,GAC9C,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAChD,iBAAiB,EAAE,mBAAmB,EAAE,WAAW,EAAE,eAAe,GACrE,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAAE,qBAAqB,EACvC,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,GAC/D,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAC9C,kBAAkB,EAAE,mBAAmB,GACxC,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,11 @@
1
+ // ============================================
2
+ // OpenSwarm - Issue Tracker Module Index
3
+ // Created: 2026-04-03
4
+ // Purpose: 이슈 트래커 퍼블릭 API
5
+ // ============================================
6
+ export { getIssueStore, closeIssueStore, SqliteIssueStore } from './sqliteStore.js';
7
+ export { IssueSchema, IssueEventSchema, IssueFilterSchema, IssueStatusSchema, IssuePrioritySchema, LabelSchema, MilestoneSchema, } from './schema.js';
8
+ export { autoLinkMemories, saveCompletionInsight, saveBlockingConstraint, enrichIssueContext, digestRecentEvents, } from './memoryBridge.js';
9
+ export { handleGraphQL, isGraphQLRequest } from './graphql/server.js';
10
+ export { initLinearBridge, syncFromLinear, pushToLinear, syncStatusToLinear, isLinearBridgeReady, } from './linearBridge.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/issues/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,yCAAyC;AACzC,sBAAsB;AACtB,0BAA0B;AAC1B,+CAA+C;AAE/C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMpF,OAAO,EACL,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAChD,iBAAiB,EAAE,mBAAmB,EAAE,WAAW,EAAE,eAAe,GACrE,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAAE,qBAAqB,EACvC,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,GAC/D,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAC9C,kBAAkB,EAAE,mBAAmB,GACxC,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const ISSUE_BOARD_HTML = "<!DOCTYPE html>\n<html lang=\"ko\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>OpenSwarm :: Issues</title>\n <style>\n :root {\n --bg: #0a0c0a;\n --bg2: #0d100d;\n --bg3: #111411;\n --green: #00ff41;\n --green-dim: #003a00;\n --green-mid: #00aa00;\n --green-lo: #005500;\n --cyan: #00ccdd;\n --cyan-dim: #003344;\n --amber: #ffaa00;\n --red: #ff3333;\n --white: #ccddcc;\n --dim: #445544;\n --border: #1a2a1a;\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: 'Cascadia Code', 'JetBrains Mono', 'Fira Code', monospace;\n background: var(--bg);\n color: var(--white);\n font-size: 13px;\n line-height: 1.4;\n height: 100vh;\n display: flex;\n flex-direction: column;\n }\n\n /* Header */\n header {\n height: 38px;\n background: var(--bg2);\n border-bottom: 1px solid var(--border);\n display: flex;\n align-items: center;\n padding: 0 1rem;\n gap: 0.75rem;\n flex-shrink: 0;\n }\n .hdr-logo { color: var(--green); font-weight: bold; font-size: 14px; letter-spacing: 0.15em; text-decoration: none; }\n .hdr-sep { color: var(--dim); margin: 0 0.5rem; }\n .hdr-sub { color: var(--cyan); font-size: 12px; letter-spacing: 0.1em; }\n .hdr-right { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }\n\n /* Toolbar */\n .toolbar {\n background: var(--bg2);\n border-bottom: 1px solid var(--border);\n padding: 6px 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n }\n .btn {\n background: var(--bg3);\n color: var(--green);\n border: 1px solid var(--green-dim);\n padding: 3px 10px;\n font-family: inherit;\n font-size: 11px;\n cursor: pointer;\n border-radius: 3px;\n }\n .btn:hover { background: var(--green-dim); }\n .btn-primary { color: var(--cyan); border-color: var(--cyan-dim); }\n .btn-primary:hover { background: var(--cyan-dim); }\n .filter-select {\n background: var(--bg3);\n color: var(--white);\n border: 1px solid var(--border);\n padding: 3px 6px;\n font-family: inherit;\n font-size: 11px;\n border-radius: 3px;\n }\n .search-input {\n background: var(--bg3);\n color: var(--white);\n border: 1px solid var(--border);\n padding: 3px 8px;\n font-family: inherit;\n font-size: 11px;\n width: 200px;\n border-radius: 3px;\n }\n .search-input::placeholder { color: var(--dim); }\n .stats-bar { margin-left: auto; color: var(--dim); font-size: 11px; }\n .stats-bar span { margin: 0 0.5rem; }\n .stats-val { color: var(--green); }\n\n /* Kanban Board */\n .board {\n flex: 1;\n display: flex;\n gap: 2px;\n padding: 8px;\n overflow-x: auto;\n min-height: 0;\n }\n .column {\n flex: 1;\n min-width: 220px;\n max-width: 320px;\n background: var(--bg2);\n border: 1px solid var(--border);\n border-radius: 4px;\n display: flex;\n flex-direction: column;\n }\n .col-header {\n padding: 6px 10px;\n background: var(--bg3);\n border-bottom: 1px solid var(--border);\n font-size: 11px;\n letter-spacing: 0.1em;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .col-header .count {\n background: var(--green-dim);\n color: var(--green);\n padding: 1px 6px;\n border-radius: 8px;\n font-size: 10px;\n }\n .col-body {\n flex: 1;\n overflow-y: auto;\n padding: 4px;\n }\n\n /* Issue Card */\n .card {\n background: var(--bg3);\n border: 1px solid var(--border);\n border-radius: 3px;\n padding: 8px;\n margin-bottom: 4px;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .card:hover { border-color: var(--green-lo); }\n .card-title { font-size: 12px; color: var(--white); margin-bottom: 4px; }\n .card-meta { font-size: 10px; color: var(--dim); display: flex; gap: 6px; flex-wrap: wrap; }\n .card-priority {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n margin-right: 4px;\n }\n .p-urgent { background: var(--red); }\n .p-high { background: var(--amber); }\n .p-medium { background: var(--cyan); }\n .p-low { background: var(--dim); }\n .p-none { background: transparent; border: 1px solid var(--dim); }\n .card-label {\n font-size: 9px;\n padding: 1px 4px;\n border-radius: 2px;\n background: var(--green-dim);\n color: var(--green-mid);\n }\n .card-id { color: var(--dim); font-size: 9px; }\n\n /* Modal */\n .modal-overlay {\n display: none;\n position: fixed;\n inset: 0;\n background: rgba(0,0,0,0.7);\n z-index: 100;\n justify-content: center;\n align-items: center;\n }\n .modal-overlay.active { display: flex; }\n .modal {\n background: var(--bg2);\n border: 1px solid var(--green-dim);\n border-radius: 6px;\n width: 90%;\n max-width: 600px;\n max-height: 85vh;\n overflow-y: auto;\n padding: 1.5rem;\n }\n .modal h3 { color: var(--green); font-size: 14px; margin-bottom: 1rem; letter-spacing: 0.1em; }\n .form-group { margin-bottom: 0.75rem; }\n .form-group label { display: block; color: var(--dim); font-size: 10px; margin-bottom: 3px; letter-spacing: 0.05em; }\n .form-group input, .form-group textarea, .form-group select {\n width: 100%;\n background: var(--bg3);\n color: var(--white);\n border: 1px solid var(--border);\n padding: 6px 8px;\n font-family: inherit;\n font-size: 12px;\n border-radius: 3px;\n }\n .form-group textarea { min-height: 80px; resize: vertical; }\n .form-actions { display: flex; gap: 0.5rem; margin-top: 1rem; justify-content: flex-end; }\n .form-actions .btn { padding: 5px 16px; }\n\n /* Detail panel */\n .detail-panel {\n display: none;\n position: fixed;\n top: 0;\n right: 0;\n width: 420px;\n height: 100%;\n background: var(--bg2);\n border-left: 1px solid var(--green-dim);\n z-index: 90;\n overflow-y: auto;\n padding: 1rem;\n }\n .detail-panel.active { display: block; }\n .detail-close { float: right; cursor: pointer; color: var(--dim); font-size: 16px; }\n .detail-title { color: var(--green); font-size: 14px; margin-bottom: 0.5rem; margin-right: 2rem; }\n .detail-section { margin-top: 1rem; }\n .detail-section h4 { color: var(--cyan); font-size: 11px; letter-spacing: 0.05em; margin-bottom: 0.25rem; }\n .detail-section p, .detail-section ul { color: var(--white); font-size: 12px; }\n .detail-section ul { padding-left: 1rem; }\n .event-item { font-size: 11px; color: var(--dim); padding: 3px 0; border-bottom: 1px solid var(--border); }\n .event-item .ev-type { color: var(--amber); }\n </style>\n</head>\n<body>\n <header>\n <a href=\"/\" class=\"hdr-logo\">OpenSwarm</a>\n <span class=\"hdr-sep\">::</span>\n <span class=\"hdr-sub\">ISSUE TRACKER</span>\n <div class=\"hdr-right\">\n <span id=\"stats-summary\" style=\"color:var(--dim);font-size:11px\"></span>\n </div>\n </header>\n\n <div class=\"toolbar\">\n <button class=\"btn btn-primary\" onclick=\"openCreateModal()\">+ NEW ISSUE</button>\n <select class=\"filter-select\" id=\"filter-project\" onchange=\"applyFilter()\">\n <option value=\"\">all projects</option>\n </select>\n <select class=\"filter-select\" id=\"filter-priority\" onchange=\"applyFilter()\">\n <option value=\"\">all priorities</option>\n <option value=\"urgent\">urgent</option>\n <option value=\"high\">high</option>\n <option value=\"medium\">medium</option>\n <option value=\"low\">low</option>\n </select>\n <input type=\"text\" class=\"search-input\" id=\"search-input\" placeholder=\"search issues...\" oninput=\"debounceSearch()\">\n <div class=\"stats-bar\">\n <span>total: <span class=\"stats-val\" id=\"stat-total\">0</span></span>\n <span>open: <span class=\"stats-val\" id=\"stat-open\">0</span></span>\n <span>done: <span class=\"stats-val\" id=\"stat-done\">0</span></span>\n </div>\n </div>\n\n <div class=\"board\" id=\"board\">\n <!-- \uCE78\uBC18 \uCE7C\uB7FC\uC740 JS\uC5D0\uC11C \uB3D9\uC801 \uC0DD\uC131 -->\n </div>\n\n <!-- \uC774\uC288 \uC0DD\uC131 \uBAA8\uB2EC -->\n <div class=\"modal-overlay\" id=\"create-modal\">\n <div class=\"modal\">\n <h3>NEW ISSUE</h3>\n <div class=\"form-group\">\n <label>PROJECT</label>\n <select id=\"new-project\"></select>\n </div>\n <div class=\"form-group\">\n <label>TITLE</label>\n <input type=\"text\" id=\"new-title\" placeholder=\"\uC774\uC288 \uC81C\uBAA9\">\n </div>\n <div class=\"form-group\">\n <label>DESCRIPTION</label>\n <textarea id=\"new-desc\" placeholder=\"\uC0C1\uC138 \uC124\uBA85...\"></textarea>\n </div>\n <div style=\"display:flex;gap:0.75rem\">\n <div class=\"form-group\" style=\"flex:1\">\n <label>PRIORITY</label>\n <select id=\"new-priority\">\n <option value=\"medium\">medium</option>\n <option value=\"urgent\">urgent</option>\n <option value=\"high\">high</option>\n <option value=\"low\">low</option>\n <option value=\"none\">none</option>\n </select>\n </div>\n <div class=\"form-group\" style=\"flex:1\">\n <label>STATUS</label>\n <select id=\"new-status\">\n <option value=\"backlog\">backlog</option>\n <option value=\"todo\">todo</option>\n <option value=\"in_progress\">in_progress</option>\n </select>\n </div>\n </div>\n <div class=\"form-group\">\n <label>LABELS (comma separated)</label>\n <input type=\"text\" id=\"new-labels\" placeholder=\"bug, feature, ...\">\n </div>\n <div class=\"form-group\">\n <label>RELEVANT FILES (comma separated)</label>\n <input type=\"text\" id=\"new-files\" placeholder=\"src/foo.ts, src/bar.ts\">\n </div>\n <div class=\"form-actions\">\n <button class=\"btn\" onclick=\"closeCreateModal()\">CANCEL</button>\n <button class=\"btn btn-primary\" onclick=\"createIssue()\">CREATE</button>\n </div>\n </div>\n </div>\n\n <!-- \uC774\uC288 \uC0C1\uC138 \uD328\uB110 -->\n <div class=\"detail-panel\" id=\"detail-panel\">\n <span class=\"detail-close\" onclick=\"closeDetail()\">&times;</span>\n <div id=\"detail-content\"></div>\n </div>\n\n <script>\n const COLUMNS = [\n { status: 'backlog', label: 'BACKLOG', color: 'var(--dim)' },\n { status: 'todo', label: 'TODO', color: 'var(--white)' },\n { status: 'in_progress', label: 'IN PROGRESS', color: 'var(--amber)' },\n { status: 'in_review', label: 'IN REVIEW', color: 'var(--cyan)' },\n { status: 'done', label: 'DONE', color: 'var(--green)' },\n ];\n\n let allIssues = [];\n let projects = new Set();\n\n // GraphQL helper\n async function gql(query, variables = {}) {\n const res = await fetch('/graphql', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ query, variables }),\n });\n const json = await res.json();\n if (json.errors) {\n console.error('GraphQL errors:', json.errors);\n throw new Error(json.errors[0].message);\n }\n return json.data;\n }\n\n // \uC774\uC288 \uBAA9\uB85D \uB85C\uB4DC\n async function loadIssues() {\n const projectId = document.getElementById('filter-project').value || undefined;\n const priority = document.getElementById('filter-priority').value || undefined;\n const search = document.getElementById('search-input').value || undefined;\n\n const filter = {};\n if (projectId) filter.projectId = projectId;\n if (priority) filter.priority = [priority];\n if (search) filter.search = search;\n\n const data = await gql(`\n query ListIssues($filter: IssueFilterInput) {\n issues(filter: $filter) {\n issues {\n id projectId title description status priority source\n labels assignee relevantFiles dependencies childIds\n linearIdentifier memoryIds createdAt updatedAt closedAt\n }\n total\n }\n issueStats {\n total\n byStatus { status count }\n }\n }\n `, { filter: Object.keys(filter).length > 0 ? filter : null });\n\n allIssues = data.issues.issues;\n\n // \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uAC31\uC2E0\n for (const iss of allIssues) projects.add(iss.projectId);\n updateProjectFilter();\n\n // \uD1B5\uACC4 \uAC31\uC2E0\n const stats = data.issueStats;\n document.getElementById('stat-total').textContent = stats.total;\n const openCount = stats.byStatus\n .filter(s => !['done', 'cancelled'].includes(s.status))\n .reduce((a, s) => a + s.count, 0);\n const doneCount = stats.byStatus.find(s => s.status === 'done')?.count || 0;\n document.getElementById('stat-open').textContent = openCount;\n document.getElementById('stat-done').textContent = doneCount;\n\n renderBoard();\n }\n\n function updateProjectFilter() {\n const sel = document.getElementById('filter-project');\n const current = sel.value;\n const opts = ['<option value=\"\">all projects</option>'];\n for (const p of projects) {\n opts.push('<option value=\"' + p + '\"' + (p === current ? ' selected' : '') + '>' + p + '</option>');\n }\n sel.innerHTML = opts.join('');\n }\n\n // \uCE78\uBC18 \uBCF4\uB4DC \uB80C\uB354\uB9C1\n function renderBoard() {\n const board = document.getElementById('board');\n board.innerHTML = '';\n\n for (const col of COLUMNS) {\n const issues = allIssues.filter(i => i.status === col.status);\n const colEl = document.createElement('div');\n colEl.className = 'column';\n colEl.innerHTML = `\n <div class=\"col-header\">\n <span style=\"color:${col.color}\">${col.label}</span>\n <span class=\"count\">${issues.length}</span>\n </div>\n <div class=\"col-body\" data-status=\"${col.status}\"></div>\n `;\n\n const body = colEl.querySelector('.col-body');\n for (const iss of issues) {\n body.appendChild(createCard(iss));\n }\n\n // \uB4DC\uB798\uADF8 \uB4DC\uB86D \uC218\uC2E0\n body.addEventListener('dragover', e => { e.preventDefault(); body.style.background = 'var(--green-dim)'; });\n body.addEventListener('dragleave', () => { body.style.background = ''; });\n body.addEventListener('drop', async e => {\n e.preventDefault();\n body.style.background = '';\n const issueId = e.dataTransfer.getData('text/plain');\n if (issueId && col.status) {\n await gql(`mutation($id:ID!,$s:IssueStatus!){changeIssueStatus(id:$id,status:$s){id}}`,\n { id: issueId, s: col.status });\n loadIssues();\n }\n });\n\n board.appendChild(colEl);\n }\n }\n\n function createCard(iss) {\n const card = document.createElement('div');\n card.className = 'card';\n card.draggable = true;\n card.addEventListener('dragstart', e => { e.dataTransfer.setData('text/plain', iss.id); });\n card.addEventListener('click', () => openDetail(iss.id));\n\n const priorityClass = 'p-' + iss.priority;\n const labels = (iss.labels || []).map(l => '<span class=\"card-label\">' + l + '</span>').join('');\n const timeAgo = formatTimeAgo(iss.updatedAt);\n\n card.innerHTML = `\n <div class=\"card-title\"><span class=\"card-priority ${priorityClass}\"></span>${escHtml(iss.title)}</div>\n <div class=\"card-meta\">\n <span class=\"card-id\">${iss.id.slice(0, 6)}</span>\n <span>${iss.projectId}</span>\n ${iss.assignee ? '<span>' + iss.assignee + '</span>' : ''}\n <span>${timeAgo}</span>\n </div>\n ${labels ? '<div class=\"card-meta\" style=\"margin-top:3px\">' + labels + '</div>' : ''}\n `;\n return card;\n }\n\n // \uC774\uC288 \uC0C1\uC138 \uD328\uB110\n async function openDetail(id) {\n const data = await gql(`\n query IssueDetail($id:ID!) {\n issue(id:$id) {\n id projectId title description status priority source\n labels assignee relevantFiles acceptanceCriteria\n dependencies childIds memoryIds createdAt updatedAt closedAt\n linearIdentifier linearUrl\n }\n issueEvents(issueId:$id, limit:20) {\n id type oldValue newValue content actor createdAt\n }\n }\n `, { id });\n\n const iss = data.issue;\n if (!iss) return;\n const events = data.issueEvents;\n\n const panel = document.getElementById('detail-panel');\n const content = document.getElementById('detail-content');\n\n const statusOptions = COLUMNS.map(c =>\n '<option value=\"' + c.status + '\"' + (c.status === iss.status ? ' selected' : '') + '>' + c.label + '</option>'\n ).join('');\n\n content.innerHTML = `\n <div class=\"detail-title\">${escHtml(iss.title)}</div>\n <div style=\"color:var(--dim);font-size:10px;margin-bottom:1rem\">\n ${iss.id} | ${iss.projectId}\n ${iss.linearIdentifier ? ' | <a href=\"' + iss.linearUrl + '\" style=\"color:var(--cyan)\" target=\"_blank\">' + iss.linearIdentifier + '</a>' : ''}\n </div>\n\n <div class=\"detail-section\">\n <h4>STATUS</h4>\n <select class=\"filter-select\" onchange=\"changeStatus('${iss.id}', this.value)\" style=\"width:100%\">\n ${statusOptions}\n <option value=\"cancelled\"${iss.status==='cancelled'?' selected':''}>CANCELLED</option>\n </select>\n </div>\n\n <div class=\"detail-section\">\n <h4>DESCRIPTION</h4>\n <p style=\"white-space:pre-wrap\">${escHtml(iss.description) || '<span style=\"color:var(--dim)\">no description</span>'}</p>\n </div>\n\n ${iss.relevantFiles.length ? '<div class=\"detail-section\"><h4>RELEVANT FILES</h4><ul>' + iss.relevantFiles.map(f => '<li>' + escHtml(f) + '</li>').join('') + '</ul></div>' : ''}\n\n ${iss.acceptanceCriteria.length ? '<div class=\"detail-section\"><h4>ACCEPTANCE CRITERIA</h4><ul>' + iss.acceptanceCriteria.map(c => '<li>' + escHtml(c) + '</li>').join('') + '</ul></div>' : ''}\n\n ${iss.dependencies.length ? '<div class=\"detail-section\"><h4>DEPENDENCIES</h4><p>' + iss.dependencies.join(', ') + '</p></div>' : ''}\n\n <div class=\"detail-section\">\n <h4>ACTIVITY (${events.length})</h4>\n ${events.map(ev => `\n <div class=\"event-item\">\n <span class=\"ev-type\">${ev.type}</span>\n ${ev.content ? ': ' + escHtml(ev.content).slice(0, 100) : ''}\n ${ev.oldValue && ev.newValue ? ': ' + ev.oldValue + ' \u2192 ' + ev.newValue : ''}\n <span style=\"float:right\">${formatTimeAgo(ev.createdAt)}</span>\n </div>\n `).join('')}\n </div>\n\n <div class=\"detail-section\" style=\"margin-top:1.5rem\">\n <h4>ADD COMMENT</h4>\n <textarea id=\"comment-input\" style=\"width:100%;background:var(--bg3);color:var(--white);border:1px solid var(--border);padding:6px;font-family:inherit;font-size:12px;min-height:60px;border-radius:3px\" placeholder=\"\uCF54\uBA58\uD2B8 \uC785\uB825...\"></textarea>\n <button class=\"btn btn-primary\" style=\"margin-top:4px\" onclick=\"addComment('${iss.id}')\">COMMENT</button>\n </div>\n\n <div class=\"form-actions\" style=\"margin-top:1.5rem;justify-content:flex-start\">\n <button class=\"btn\" style=\"color:var(--red);border-color:var(--red)\" onclick=\"deleteIssue('${iss.id}')\">DELETE</button>\n </div>\n `;\n\n panel.classList.add('active');\n }\n\n function closeDetail() {\n document.getElementById('detail-panel').classList.remove('active');\n }\n\n async function changeStatus(id, status) {\n await gql(`mutation($id:ID!,$s:IssueStatus!){changeIssueStatus(id:$id,status:$s){id}}`, { id, s: status });\n loadIssues();\n }\n\n async function addComment(id) {\n const input = document.getElementById('comment-input');\n const content = input.value.trim();\n if (!content) return;\n await gql(`mutation($id:ID!,$c:String!){addComment(issueId:$id,content:$c){id}}`, { id, c: content });\n input.value = '';\n openDetail(id);\n }\n\n async function deleteIssue(id) {\n if (!confirm('Delete this issue?')) return;\n await gql(`mutation($id:ID!){deleteIssue(id:$id)}`, { id });\n closeDetail();\n loadIssues();\n }\n\n // \uC774\uC288 \uC0DD\uC131\n function openCreateModal() {\n const sel = document.getElementById('new-project');\n sel.innerHTML = [...projects].map(p => '<option value=\"' + p + '\">' + p + '</option>').join('');\n if (sel.options.length === 0) {\n sel.innerHTML = '<option value=\"default\">default</option>';\n }\n document.getElementById('create-modal').classList.add('active');\n document.getElementById('new-title').focus();\n }\n\n function closeCreateModal() {\n document.getElementById('create-modal').classList.remove('active');\n }\n\n async function createIssue() {\n const title = document.getElementById('new-title').value.trim();\n if (!title) { alert('Title required'); return; }\n\n const input = {\n projectId: document.getElementById('new-project').value || 'default',\n title,\n description: document.getElementById('new-desc').value,\n priority: document.getElementById('new-priority').value,\n status: document.getElementById('new-status').value,\n labels: document.getElementById('new-labels').value.split(',').map(s => s.trim()).filter(Boolean),\n relevantFiles: document.getElementById('new-files').value.split(',').map(s => s.trim()).filter(Boolean),\n };\n\n await gql(`\n mutation CreateIssue($input: CreateIssueInput!) {\n createIssue(input: $input) { id }\n }\n `, { input });\n\n closeCreateModal();\n // \uD3FC \uCD08\uAE30\uD654\n document.getElementById('new-title').value = '';\n document.getElementById('new-desc').value = '';\n document.getElementById('new-labels').value = '';\n document.getElementById('new-files').value = '';\n loadIssues();\n }\n\n // \uC720\uD2F8\n function escHtml(s) {\n if (!s) return '';\n return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;');\n }\n\n function formatTimeAgo(iso) {\n if (!iso) return '';\n const diff = Date.now() - new Date(iso).getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'just now';\n if (mins < 60) return mins + 'm ago';\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return hrs + 'h ago';\n const days = Math.floor(hrs / 24);\n return days + 'd ago';\n }\n\n let searchTimer;\n function debounceSearch() {\n clearTimeout(searchTimer);\n searchTimer = setTimeout(loadIssues, 300);\n }\n\n function applyFilter() {\n loadIssues();\n }\n\n // \uD0A4\uBCF4\uB4DC \uB2E8\uCD95\uD0A4\n document.addEventListener('keydown', e => {\n if (e.key === 'Escape') {\n closeCreateModal();\n closeDetail();\n }\n if (e.key === 'n' && !e.target.closest('input,textarea,select')) {\n e.preventDefault();\n openCreateModal();\n }\n });\n\n // \uCD08\uAE30 \uB85C\uB4DC\n loadIssues();\n // 30\uCD08 \uAC04\uACA9 \uC790\uB3D9 \uC0C8\uB85C\uACE0\uCE68\n setInterval(loadIssues, 30000);\n </script>\n</body>\n</html>";
2
+ //# sourceMappingURL=issueBoardHtml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issueBoardHtml.d.ts","sourceRoot":"","sources":["../../src/issues/issueBoardHtml.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,gBAAgB,+nwBA8pBrB,CAAC"}