@witty-ai/skill-insight 0.6.0-beta → 0.7.0-beta

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 (207) hide show
  1. package/.env.example +1 -0
  2. package/.next/standalone/.next/BUILD_ID +1 -1
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  5. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.rsc +4 -4
  15. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  16. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/config/create/route.js +4 -3
  22. package/.next/standalone/.next/server/app/api/config/create/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/config/route.js +3 -2
  24. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/data/route.js +5 -4
  26. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/evaluation/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/otel/v1/logs/route.js +5 -4
  29. package/.next/standalone/.next/server/app/api/otel/v1/logs/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/otel/v1/traces/route.js +3 -2
  31. package/.next/standalone/.next/server/app/api/otel/v1/traces/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/proxy/[taskId]/[...path]/route.js +1 -1
  33. package/.next/standalone/.next/server/app/api/proxy/[taskId]/end/route.js +4 -3
  34. package/.next/standalone/.next/server/app/api/proxy/[taskId]/end/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/rejudge/route.js +5 -4
  36. package/.next/standalone/.next/server/app/api/rejudge/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/session/route.js +4 -4
  38. package/.next/standalone/.next/server/app/api/session/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/skills/[id]/versions/[version]/download/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/skills/[id]/versions/[version]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/skills/[id]/versions/route.js +5 -2
  42. package/.next/standalone/.next/server/app/api/skills/[id]/versions/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/skills/automation/import/route.js +5 -2
  44. package/.next/standalone/.next/server/app/api/skills/automation/import/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/skills/logs/route.js +5 -4
  46. package/.next/standalone/.next/server/app/api/skills/logs/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/skills/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/skills/upload/route.js +5 -2
  50. package/.next/standalone/.next/server/app/api/skills/upload/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/task-stats/route.js +5 -4
  52. package/.next/standalone/.next/server/app/api/task-stats/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/upload/route.js +4 -3
  54. package/.next/standalone/.next/server/app/api/upload/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/details/page/react-loadable-manifest.json +1 -1
  56. package/.next/standalone/.next/server/app/details/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/details/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/details.html +1 -1
  59. package/.next/standalone/.next/server/app/details.rsc +5 -5
  60. package/.next/standalone/.next/server/app/details.segments/_full.segment.rsc +5 -5
  61. package/.next/standalone/.next/server/app/details.segments/_head.segment.rsc +1 -1
  62. package/.next/standalone/.next/server/app/details.segments/_index.segment.rsc +3 -3
  63. package/.next/standalone/.next/server/app/details.segments/_tree.segment.rsc +2 -2
  64. package/.next/standalone/.next/server/app/details.segments/details/__PAGE__.segment.rsc +2 -2
  65. package/.next/standalone/.next/server/app/details.segments/details.segment.rsc +1 -1
  66. package/.next/standalone/.next/server/app/index.html +1 -1
  67. package/.next/standalone/.next/server/app/index.rsc +5 -5
  68. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  69. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  70. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  71. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  72. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  73. package/.next/standalone/.next/server/app/login/page.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/app/login.html +1 -1
  76. package/.next/standalone/.next/server/app/login.rsc +5 -5
  77. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +5 -5
  78. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  79. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +3 -3
  80. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  81. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  82. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  83. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  85. package/.next/standalone/.next/server/app/skills/page.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/app/skills.html +1 -1
  88. package/.next/standalone/.next/server/app/skills.rsc +5 -5
  89. package/.next/standalone/.next/server/app/skills.segments/_full.segment.rsc +5 -5
  90. package/.next/standalone/.next/server/app/skills.segments/_head.segment.rsc +1 -1
  91. package/.next/standalone/.next/server/app/skills.segments/_index.segment.rsc +3 -3
  92. package/.next/standalone/.next/server/app/skills.segments/_tree.segment.rsc +2 -2
  93. package/.next/standalone/.next/server/app/skills.segments/skills/__PAGE__.segment.rsc +2 -2
  94. package/.next/standalone/.next/server/app/skills.segments/skills.segment.rsc +1 -1
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__02ddba88._.js +1 -1
  96. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15dbd1f2._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1c95bcde._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/[root-of-the-server]__23efcd78._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4a6d443b._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/[root-of-the-server]__53775b48._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5444db55._.js +1 -1
  102. package/.next/standalone/.next/server/chunks/[root-of-the-server]__591248f3._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5d8178f6._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6261d672._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6923eecf._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6fc12878._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8402dfd1._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/[root-of-the-server]__863cf6de._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89404730._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/[root-of-the-server]__98b3de5e._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9d551ea2._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a4d3d791._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/[root-of-the-server]__aa3d72e3._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b11acc79._.js +1 -1
  115. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ba01f286._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bd91659b._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c200214a._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c602c518._.js +3 -0
  119. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d7fab946._.js +1 -1
  120. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8c1808b._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d9b9fecc._.js +1 -1
  122. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ddf63a21._.js +1 -1
  123. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e280561d._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e550423c._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/_33c0c729._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/_46f10554._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/_4c806e26._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/_cd3d20ca._.js +1 -1
  129. package/.next/standalone/.next/server/chunks/src_98433cb8._.js +77 -15
  130. package/.next/standalone/.next/server/chunks/src_c8971a2d._.js +57 -8
  131. package/.next/standalone/.next/server/chunks/src_lib_119f6c7b._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__9ab7cc4a._.js → [root-of-the-server]__082c32a2._.js} +2 -2
  133. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__51073007._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/_049876f0._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/_09546b95._.js +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/_8f5379ab._.js +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/_c8c8c083._.js +9 -9
  138. package/.next/standalone/.next/server/chunks/ssr/{_b121f1ae._.js → _e2faf4f5._.js} +2 -2
  139. package/.next/standalone/.next/server/chunks/ssr/_fd46f439._.js +2 -2
  140. package/.next/standalone/.next/server/chunks/ssr/src_66a70595._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/src_app_login_page_tsx_72f58654._.js +1 -1
  142. package/.next/standalone/.next/server/pages/404.html +1 -1
  143. package/.next/standalone/.next/server/pages/500.html +2 -2
  144. package/.next/standalone/.next/static/chunks/{9445b2873a413c58.js → 015467355d3866a3.js} +1 -1
  145. package/.next/standalone/.next/static/chunks/09f192c9b0609ad8.js +1 -0
  146. package/.next/standalone/.next/static/chunks/1945a5514fbc393c.css +1 -0
  147. package/.next/standalone/.next/static/chunks/{07c9f28a269c701a.js → 361e4cf1e9a71ccb.js} +1 -1
  148. package/.next/{static/chunks/5432ce4a494bc74d.js → standalone/.next/static/chunks/60bc50374fd32f20.js} +3 -3
  149. package/.next/standalone/.next/static/chunks/{251551dcdf74a60d.js → 65bac0880a87bff3.js} +1 -1
  150. package/.next/standalone/.next/static/chunks/961f7fa606dd26a8.js +1 -0
  151. package/.next/standalone/.next/static/chunks/bab2ffd4f527acfb.js +1 -0
  152. package/.next/standalone/.next/static/chunks/c513373e5cfedd5b.js +2 -0
  153. package/.next/standalone/.next/static/chunks/ca3017e51e817855.js +1 -0
  154. package/.next/{static/chunks/7e35f4cf2e266022.js → standalone/.next/static/chunks/cb104c3cb4c52833.js} +1 -1
  155. package/.next/standalone/.next/static/chunks/{cd0fde15dc0dfcca.js → f786bb68e17b12b4.js} +1 -1
  156. package/.next/standalone/.next/static/chunks/fc61b990c5ec4ef4.js +109 -0
  157. package/.next/standalone/node_modules/.prisma/client/edge.js +4 -3
  158. package/.next/standalone/node_modules/.prisma/client/index-browser.js +1 -0
  159. package/.next/standalone/node_modules/.prisma/client/index.js +4 -3
  160. package/.next/standalone/node_modules/.prisma/client/package.json +1 -1
  161. package/.next/standalone/node_modules/.prisma/client/schema.prisma +14 -13
  162. package/.next/standalone/node_modules/.prisma/client/wasm.js +1 -0
  163. package/.next/standalone/package.json +1 -1
  164. package/.next/standalone/prisma/schema.prisma +4 -3
  165. package/.next/standalone/scripts/opencode_plugin.ts +135 -45
  166. package/.next/static/chunks/{9445b2873a413c58.js → 015467355d3866a3.js} +1 -1
  167. package/.next/static/chunks/09f192c9b0609ad8.js +1 -0
  168. package/.next/static/chunks/1945a5514fbc393c.css +1 -0
  169. package/.next/static/chunks/{07c9f28a269c701a.js → 361e4cf1e9a71ccb.js} +1 -1
  170. package/.next/{standalone/.next/static/chunks/5432ce4a494bc74d.js → static/chunks/60bc50374fd32f20.js} +3 -3
  171. package/.next/static/chunks/{251551dcdf74a60d.js → 65bac0880a87bff3.js} +1 -1
  172. package/.next/static/chunks/961f7fa606dd26a8.js +1 -0
  173. package/.next/static/chunks/bab2ffd4f527acfb.js +1 -0
  174. package/.next/static/chunks/c513373e5cfedd5b.js +2 -0
  175. package/.next/static/chunks/ca3017e51e817855.js +1 -0
  176. package/.next/{standalone/.next/static/chunks/7e35f4cf2e266022.js → static/chunks/cb104c3cb4c52833.js} +1 -1
  177. package/.next/static/chunks/{cd0fde15dc0dfcca.js → f786bb68e17b12b4.js} +1 -1
  178. package/.next/static/chunks/fc61b990c5ec4ef4.js +109 -0
  179. package/package.json +1 -1
  180. package/prisma/schema.prisma +4 -3
  181. package/scripts/opencode_plugin.ts +135 -45
  182. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1013b265._.js +0 -3
  183. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ce5e3b8._.js +0 -3
  184. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6d8053e2._.js +0 -3
  185. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b835ea7f._.js +0 -3
  186. package/.next/standalone/.next/server/chunks/_41a98bd8._.js +0 -3
  187. package/.next/standalone/.next/server/chunks/src_lib_12408140._.js +0 -3
  188. package/.next/standalone/.next/static/chunks/1e782a49beaf489c.js +0 -1
  189. package/.next/standalone/.next/static/chunks/4ee8dc41c9f15b7b.js +0 -1
  190. package/.next/standalone/.next/static/chunks/67bd1a5de2195779.js +0 -1
  191. package/.next/standalone/.next/static/chunks/94dfb15df65ef720.js +0 -2
  192. package/.next/standalone/.next/static/chunks/9d1c5c3494fa53de.js +0 -109
  193. package/.next/standalone/.next/static/chunks/c6bd2818656b1f20.css +0 -1
  194. package/.next/standalone/.next/static/chunks/dc59a07a8f327b40.js +0 -1
  195. package/.next/static/chunks/1e782a49beaf489c.js +0 -1
  196. package/.next/static/chunks/4ee8dc41c9f15b7b.js +0 -1
  197. package/.next/static/chunks/67bd1a5de2195779.js +0 -1
  198. package/.next/static/chunks/94dfb15df65ef720.js +0 -2
  199. package/.next/static/chunks/9d1c5c3494fa53de.js +0 -109
  200. package/.next/static/chunks/c6bd2818656b1f20.css +0 -1
  201. package/.next/static/chunks/dc59a07a8f327b40.js +0 -1
  202. /package/.next/standalone/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_buildManifest.js +0 -0
  203. /package/.next/standalone/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_clientMiddlewareManifest.json +0 -0
  204. /package/.next/standalone/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_ssgManifest.js +0 -0
  205. /package/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_buildManifest.js +0 -0
  206. /package/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_clientMiddlewareManifest.json +0 -0
  207. /package/.next/static/{0uvhCJooDO_gMNlKOaHwB → iKG72t8Hpebb09DcIpKUJ}/_ssgManifest.js +0 -0
@@ -90,16 +90,17 @@ model Execution {
90
90
  }
91
91
 
92
92
  model Config {
93
- id String @id @default(cuid())
94
- query String
95
- skill String @default("") // Ground truth skill name (Legacy - use expectedSkills instead)
96
- skillVersion Int? // Expected skill version (Legacy - use expectedSkills instead)
97
- expectedSkills String? // JSON array of {skill: string, version: number | null}
98
- standardAnswer String
99
- rootCauses String? // JSON array
100
- keyActions String? // JSON array
101
- user String? // Added for user isolation
102
- parseStatus String @default("completed") // parsing | completed | failed
93
+ id String @id @default(cuid())
94
+ query String
95
+ skill String @default("") // Ground truth skill name (Legacy - use expectedSkills instead)
96
+ skillVersion Int? // Expected skill version (Legacy - use expectedSkills instead)
97
+ expectedSkills String? // JSON array of {skill: string, version: number | null}
98
+ standardAnswer String
99
+ rootCauses String? // JSON array
100
+ keyActions String? // JSON array
101
+ extractedKeyActions String? // JSON array of ExtractedKeyAction (auto-extracted from Skill)
102
+ user String? // Added for user isolation
103
+ parseStatus String @default("completed") // parsing | completed | failed
103
104
 
104
105
  @@unique([query, user]) // Queries are unique per user
105
106
  }
@@ -130,8 +131,8 @@ model ParsedFlow {
130
131
  version Int
131
132
  user String?
132
133
 
133
- flowJson String // JSON: { steps, branches }
134
- mermaidCode String // Generated Mermaid code
134
+ flowJson String? // JSON: { steps, branches }
135
+ mermaidCode String? // Generated Mermaid code
135
136
 
136
137
  parsedAt DateTime @default(now())
137
138
 
@@ -148,7 +149,7 @@ model ExecutionMatch {
148
149
  mode String @default("compare") // "compare" or "dynamic"
149
150
  matchJson String? // JSON: { matches, summary }
150
151
  staticMermaid String? // Static flow Mermaid code
151
- dynamicMermaid String // Dynamic flow Mermaid code
152
+ dynamicMermaid String? // Dynamic flow Mermaid code
152
153
  analysisText String? // LLM analysis text
153
154
  extractedSteps String? // JSON: extracted steps from interactions
154
155
 
@@ -199,6 +199,7 @@ exports.Prisma.ConfigScalarFieldEnum = {
199
199
  standardAnswer: 'standardAnswer',
200
200
  rootCauses: 'rootCauses',
201
201
  keyActions: 'keyActions',
202
+ extractedKeyActions: 'extractedKeyActions',
202
203
  user: 'user',
203
204
  parseStatus: 'parseStatus'
204
205
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@witty-ai/skill-insight",
3
- "version": "0.6.0-beta",
3
+ "version": "0.7.0-beta",
4
4
  "description": "Agent Skill 评估与观测平台 — 量化评估 Skills 在 Agent 上的实际运行效果",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -99,6 +99,7 @@ model Config {
99
99
  standardAnswer String
100
100
  rootCauses String? // JSON array
101
101
  keyActions String? // JSON array
102
+ extractedKeyActions String? // JSON array of ExtractedKeyAction (auto-extracted from Skill)
102
103
  user String? // Added for user isolation
103
104
  parseStatus String @default("completed") // parsing | completed | failed
104
105
 
@@ -131,8 +132,8 @@ model ParsedFlow {
131
132
  version Int
132
133
  user String?
133
134
 
134
- flowJson String // JSON: { steps, branches }
135
- mermaidCode String // Generated Mermaid code
135
+ flowJson String? // JSON: { steps, branches }
136
+ mermaidCode String? // Generated Mermaid code
136
137
 
137
138
  parsedAt DateTime @default(now())
138
139
 
@@ -149,7 +150,7 @@ model ExecutionMatch {
149
150
  mode String @default("compare") // "compare" or "dynamic"
150
151
  matchJson String? // JSON: { matches, summary }
151
152
  staticMermaid String? // Static flow Mermaid code
152
- dynamicMermaid String // Dynamic flow Mermaid code
153
+ dynamicMermaid String? // Dynamic flow Mermaid code
153
154
  analysisText String? // LLM analysis text
154
155
  extractedSteps String? // JSON: extracted steps from interactions
155
156
 
@@ -22,6 +22,9 @@ let uploadedSessions = new Map(); // sessionId -> uploaded message count
22
22
  let sessionGraph = new Map(); // parent_id -> [child_ids]
23
23
  let pendingChildSessions = new Map(); // child_id -> {parent_id, data}
24
24
  let lastDeltaByPartField = new Map();
25
+ let sessionParentById = new Map();
26
+ let sessionAgentById = new Map();
27
+ let subagentTypeBySessionId = new Map();
25
28
 
26
29
  const STORE_PATH = path.join(os.homedir(), '.opencode', 'witty_plugin_session_store.json');
27
30
 
@@ -131,6 +134,27 @@ function loadStore() {
131
134
  }
132
135
  }
133
136
  }
137
+
138
+ if (data.sessionParentById) {
139
+ const diskParents = new Map(data.sessionParentById);
140
+ for (const [sid, pid] of diskParents.entries()) {
141
+ if (!sessionParentById.has(sid) && pid) sessionParentById.set(sid, pid);
142
+ }
143
+ }
144
+
145
+ if (data.sessionAgentById) {
146
+ const diskAgents = new Map(data.sessionAgentById);
147
+ for (const [sid, agentName] of diskAgents.entries()) {
148
+ if (!sessionAgentById.has(sid) && agentName) sessionAgentById.set(sid, agentName);
149
+ }
150
+ }
151
+
152
+ if (data.subagentTypeBySessionId) {
153
+ const diskTypes = new Map(data.subagentTypeBySessionId);
154
+ for (const [sid, t] of diskTypes.entries()) {
155
+ if (!subagentTypeBySessionId.has(sid) && t) subagentTypeBySessionId.set(sid, t);
156
+ }
157
+ }
134
158
 
135
159
  logDebug(`Loaded store (merged): ${sessionStore.size} messages`);
136
160
  }
@@ -156,6 +180,9 @@ function saveStore() {
156
180
  uploadedSessions: Array.from(uploadedSessions.entries()),
157
181
  sessionGraph: Array.from(sessionGraph.entries()),
158
182
  pendingChildSessions: Array.from(pendingChildSessions.entries()),
183
+ sessionParentById: Array.from(sessionParentById.entries()),
184
+ sessionAgentById: Array.from(sessionAgentById.entries()),
185
+ subagentTypeBySessionId: Array.from(subagentTypeBySessionId.entries()),
159
186
  timestamp: new Date().toISOString()
160
187
  };
161
188
  fs.writeFileSync(STORE_PATH, JSON.stringify(data, null, 2), 'utf8');
@@ -290,7 +317,8 @@ function collectSessionMessages(sessionId) {
290
317
  timeInfo: entry.info.time,
291
318
  partBasedDuration: partBasedDuration,
292
319
  modelID: entry.info.modelID,
293
- model: entry.info.model
320
+ model: entry.info.model,
321
+ agent: entry.info.agent
294
322
  });
295
323
  }
296
324
  }
@@ -315,32 +343,53 @@ function cleanupOrphanedSessions() {
315
343
  }
316
344
  }
317
345
 
318
- function collectSessionWithChildren(sessionId) {
319
- const messages = collectSessionMessages(sessionId);
320
- const childSessionIds = sessionGraph.get(sessionId) || [];
321
-
322
- logDebug(`Collecting ${childSessionIds.length} child sessions for ${sessionId}`);
323
-
324
- for (const childId of childSessionIds) {
325
- const childData = pendingChildSessions.get(childId);
346
+ function findRootSessionId(sessionId) {
347
+ let cur = sessionId;
348
+ const visited = new Set();
349
+ while (cur && cur.startsWith('ses') && !visited.has(cur)) {
350
+ visited.add(cur);
351
+ const p = sessionParentById.get(cur);
352
+ if (!p || !p.startsWith('ses')) break;
353
+ cur = p;
354
+ }
355
+ return cur;
356
+ }
357
+
358
+ function collectSessionWithDescendants(rootSessionId) {
359
+ const messages = collectSessionMessages(rootSessionId);
360
+ const mergedSessionIds = [];
361
+ const visited = new Set();
362
+ const stack = Array.isArray(sessionGraph.get(rootSessionId)) ? [...sessionGraph.get(rootSessionId)] : [];
363
+
364
+ while (stack.length > 0) {
365
+ const sid = stack.pop();
366
+ if (!sid || visited.has(sid)) continue;
367
+ visited.add(sid);
368
+
369
+ const childData = pendingChildSessions.get(sid);
326
370
  if (childData && childData.messages) {
327
- logDebug(`Merging ${childData.messages.length} messages from child ${childId}`);
328
-
329
- // Convert roles in child sessions
371
+ logDebug(`Merging ${childData.messages.length} messages from child ${sid}`);
372
+ const name =
373
+ sessionAgentById.get(sid) ||
374
+ subagentTypeBySessionId.get(sid) ||
375
+ null;
330
376
  const subagentMessages = childData.messages.map(msg => {
331
377
  if (msg.role === 'assistant') {
332
- return { ...msg, role: 'subagent' };
378
+ return { ...msg, role: 'subagent', subagent_name: name || msg.agent, subagent_session_id: sid };
333
379
  } else if (msg.role === 'user') {
334
380
  return { ...msg, role: 'opencode' };
335
381
  }
336
382
  return msg;
337
383
  });
338
-
339
384
  messages.push(...subagentMessages);
385
+ mergedSessionIds.push(sid);
340
386
  }
387
+
388
+ const next = sessionGraph.get(sid) || [];
389
+ for (const x of next) stack.push(x);
341
390
  }
342
-
343
- return { messages, childSessionIds };
391
+
392
+ return { messages, mergedSessionIds };
344
393
  }
345
394
 
346
395
  export default async function WittySkillInsightPlugin(input) {
@@ -404,6 +453,22 @@ export default async function WittySkillInsightPlugin(input) {
404
453
  let sessionId = event.session_id || event.properties?.sessionID || event.payload?.session_id;
405
454
  let eagerFlush = false;
406
455
 
456
+ if (event.type === 'session.created' || event.type === 'session.updated') {
457
+ const sessionInfo = event.properties?.info || event.payload?.info;
458
+ if (sessionInfo && sessionInfo.id) {
459
+ const sid = sessionInfo.id;
460
+ const pid = sessionInfo.parentID || sessionInfo.parentId || sessionInfo.parent_id;
461
+ if (pid && pid.startsWith('ses')) {
462
+ sessionParentById.set(sid, pid);
463
+ if (!sessionGraph.has(pid)) sessionGraph.set(pid, []);
464
+ if (!sessionGraph.get(pid).includes(sid)) {
465
+ sessionGraph.get(pid).push(sid);
466
+ logDebug(`Session created: ${sid} is child of ${pid}`);
467
+ }
468
+ }
469
+ }
470
+ }
471
+
407
472
  // 1. Accumulate Message Metadata
408
473
  if (event.type === 'message.created' || event.type === 'message.updated') {
409
474
  let info = (event.payload && event.payload.message) || (event.properties && event.properties.info);
@@ -424,6 +489,12 @@ export default async function WittySkillInsightPlugin(input) {
424
489
  if (info.tool_calls || info.toolCalls) entry.info.tool_calls = info.tool_calls || info.toolCalls;
425
490
  if (info.function_call || info.functionCall) entry.info.function_call = info.function_call || info.functionCall;
426
491
 
492
+ if (entry.info?.sessionID && entry.info?.agent) {
493
+ if (!sessionAgentById.has(entry.info.sessionID)) {
494
+ sessionAgentById.set(entry.info.sessionID, entry.info.agent);
495
+ }
496
+ }
497
+
427
498
  if (entry.info?.role === 'assistant' && (entry.info.finish || entry.info.time?.completed != null)) {
428
499
  eagerFlush = true;
429
500
  }
@@ -522,21 +593,30 @@ export default async function WittySkillInsightPlugin(input) {
522
593
  if (tp.tool === 'task' && tp.state.output) {
523
594
  try {
524
595
  const taskOutput = tp.state.output;
525
- const taskIdMatch = taskOutput.match(/task_id:\s*(\w+)/);
526
- if (taskIdMatch && taskIdMatch[1]) {
527
- const subagentSessionId = taskIdMatch[1];
528
- if (subagentSessionId.startsWith('ses')) {
529
- // Establish parent-child relationship
530
- const parentSessionId = entry.info.sessionID || sessionId;
531
- if (parentSessionId) {
532
- if (!sessionGraph.has(parentSessionId)) {
533
- sessionGraph.set(parentSessionId, []);
534
- }
535
- if (!sessionGraph.get(parentSessionId).includes(subagentSessionId)) {
536
- sessionGraph.get(parentSessionId).push(subagentSessionId);
537
- logDebug(`Task detected: ${subagentSessionId} is child of ${parentSessionId}`);
538
- }
596
+ let subagentSessionId = null;
597
+ const m1 = taskOutput.match(/<task_metadata>[\s\S]*?session_id:\s*(ses_[A-Za-z0-9]+)[\s\S]*?<\/task_metadata>/i);
598
+ const m2 = taskOutput.match(/session_id:\s*(ses_[A-Za-z0-9]+)/i);
599
+ const m3 = taskOutput.match(/task\(\s*session_id\s*=\s*\"(ses_[A-Za-z0-9]+)\"/i);
600
+ const m4 = taskOutput.match(/task_id:\s*(\w+)/i);
601
+ const candidate = (m1 && m1[1]) || (m2 && m2[1]) || (m3 && m3[1]) || (m4 && m4[1]) || null;
602
+ if (candidate && String(candidate).startsWith('ses')) subagentSessionId = String(candidate);
603
+
604
+ if (subagentSessionId) {
605
+ const parentSessionId = entry.info.sessionID || sessionId;
606
+ if (parentSessionId) {
607
+ if (!sessionGraph.has(parentSessionId)) sessionGraph.set(parentSessionId, []);
608
+ if (!sessionGraph.get(parentSessionId).includes(subagentSessionId)) {
609
+ sessionGraph.get(parentSessionId).push(subagentSessionId);
610
+ logDebug(`Task detected: ${subagentSessionId} is child of ${parentSessionId}`);
539
611
  }
612
+ if (!sessionParentById.has(subagentSessionId)) {
613
+ sessionParentById.set(subagentSessionId, parentSessionId);
614
+ }
615
+ }
616
+
617
+ const t = tp.state?.input?.subagent_type;
618
+ if (t && !subagentTypeBySessionId.has(subagentSessionId)) {
619
+ subagentTypeBySessionId.set(subagentSessionId, t);
540
620
  }
541
621
  }
542
622
  } catch (e) {
@@ -622,15 +702,18 @@ export default async function WittySkillInsightPlugin(input) {
622
702
  // from within the opencode interactive interface).
623
703
  loadStore();
624
704
 
625
- // Only treat a session as "child" when it was detected via Task tool
626
- // (i.e. registered in sessionGraph). Do NOT rely on event.parentID because
627
- // nested `opencode run ...` can also set parentID and we want both sessions uploaded.
628
705
  let foundParentId = null;
629
- for (const [potentialParent, childIds] of sessionGraph.entries()) {
630
- if (childIds.includes(sessionId)) {
631
- foundParentId = potentialParent;
632
- logDebug(`Found parent ${foundParentId} for for child ${sessionId} from sessionGraph`);
633
- break;
706
+ const directParent = sessionParentById.get(sessionId);
707
+ if (directParent && Array.isArray(sessionGraph.get(directParent)) && sessionGraph.get(directParent).includes(sessionId)) {
708
+ foundParentId = directParent;
709
+ logDebug(`Found parent ${foundParentId} for for child ${sessionId} from sessionParentById`);
710
+ } else {
711
+ for (const [potentialParent, childIds] of sessionGraph.entries()) {
712
+ if (childIds.includes(sessionId)) {
713
+ foundParentId = potentialParent;
714
+ logDebug(`Found parent ${foundParentId} for for child ${sessionId} from sessionGraph`);
715
+ break;
716
+ }
634
717
  }
635
718
  }
636
719
 
@@ -655,14 +738,16 @@ export default async function WittySkillInsightPlugin(input) {
655
738
  });
656
739
  logDebug(`Stored ${childMessages.length} messages for child session ${sessionId}`);
657
740
  }
658
-
659
- return; // Don't upload child session separately
741
+
742
+ const rootId = findRootSessionId(foundParentId) || foundParentId;
743
+ if (!rootId || rootId === sessionId) return;
744
+ sessionId = rootId;
660
745
  }
661
746
 
662
747
  logDebug(`Session Idle: ${sessionId}. Messages in store: ${sessionStore.size}`);
663
748
 
664
749
  // This is a parent session, collect all messages including children
665
- const { messages, childSessionIds } = collectSessionWithChildren(sessionId);
750
+ const { messages, mergedSessionIds } = collectSessionWithDescendants(sessionId);
666
751
 
667
752
  if (messages.length === 0) {
668
753
  logDebug(`No messages found for session ${sessionId}, skipping upload.`);
@@ -670,11 +755,10 @@ export default async function WittySkillInsightPlugin(input) {
670
755
  }
671
756
 
672
757
  // Cleanup child session data after successful upload
673
- for (const childId of childSessionIds) {
758
+ for (const childId of mergedSessionIds) {
674
759
  pendingChildSessions.delete(childId);
675
760
  logDebug(`Cleaned up child session ${childId}`);
676
761
  }
677
- sessionGraph.delete(sessionId);
678
762
 
679
763
  // Cleanup orphaned child sessions (older than 1 hour)
680
764
  cleanupOrphanedSessions();
@@ -704,11 +788,14 @@ export default async function WittySkillInsightPlugin(input) {
704
788
 
705
789
  for (const m of messages) {
706
790
  if (m.role === 'user' && !firstUserQuery) firstUserQuery = m.content;
791
+ const isCompletion = m.role === 'assistant' || m.role === 'subagent';
707
792
  if (m.role === 'assistant') {
708
- llmCallCount++;
709
793
  lastAssistantContent = m.content;
710
794
  if (m.model) model = m.model;
711
795
  else if (m.modelID) model = m.modelID;
796
+ }
797
+ if (isCompletion) {
798
+ llmCallCount++;
712
799
 
713
800
  // Token logic
714
801
  const u = m.usage;
@@ -792,7 +879,10 @@ export default async function WittySkillInsightPlugin(input) {
792
879
  function_call: m.function_call || m.functionCall,
793
880
  usage: m.usage,
794
881
  timestamp: m.timestamp,
795
- timeInfo: m.timeInfo
882
+ timeInfo: m.timeInfo,
883
+ agent: m.agent,
884
+ subagent_name: m.subagent_name,
885
+ subagent_session_id: m.subagent_session_id
796
886
  })),
797
887
  timestamp: new Date().toISOString()
798
888
  };