@givolt/i3-composer-agent 2.2.3 → 2.3.1

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 (439) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude/commands/i3-prototype.md +23 -0
  3. package/.claude/commands/i3-review.md +1 -1
  4. package/.claude/commands/i3-ship.md +1 -1
  5. package/.claude-plugin/marketplace.json +1 -1
  6. package/.claude-plugin/plugin.json +1 -1
  7. package/.codex-plugin/plugin.json +2 -2
  8. package/.gemini/commands/i3-prototype.toml +23 -0
  9. package/.gemini/commands/i3-review.toml +1 -1
  10. package/.gemini/commands/i3-ship.toml +1 -1
  11. package/README.md +15 -5
  12. package/agents/code-reviewer.md +1 -1
  13. package/agents/test-engineer.md +1 -1
  14. package/bin/native-layout.cjs +2 -0
  15. package/commands/i3-prototype.toml +23 -0
  16. package/commands/i3-review.toml +1 -1
  17. package/commands/i3-ship.toml +1 -1
  18. package/docs/agents.md +2 -2
  19. package/docs/codebuddy-setup.md +2 -2
  20. package/docs/codex-setup.md +1 -1
  21. package/docs/copilot-setup.md +4 -0
  22. package/docs/cursor-setup.md +3 -0
  23. package/docs/other-hosts.md +44 -9
  24. package/docs/workbuddy-setup.md +2 -2
  25. package/evals/README.md +2 -0
  26. package/evals/cases/i3-documentation-and-adrs.json +18 -0
  27. package/evals/cases/i3-test-driven-development.json +8 -0
  28. package/evals/cases/i3-ui-prototype.json +49 -0
  29. package/evals/fixtures/i3-documentation-and-adrs/prose-review/README.md +19 -0
  30. package/evals/fixtures/i3-documentation-and-adrs/prose-review/queue.js +32 -0
  31. package/evals/fixtures/i3-ui-prototype/business-brief.md +7 -0
  32. package/evals/plugin/tdd-fires-on-pasted-bug/graders/failing-test-first.md +7 -0
  33. package/evals/plugin/tdd-fires-on-pasted-bug/graders/skill-fired.md +5 -0
  34. package/evals/plugin/tdd-fires-on-pasted-bug/prompt.md +15 -0
  35. package/evals/plugin/tdd-stays-quiet-on-debug/graders/not-fired.md +8 -0
  36. package/evals/plugin/tdd-stays-quiet-on-debug/prompt.md +25 -0
  37. package/evals/zh-CN/cases/i3-documentation-and-adrs.json +19 -0
  38. package/evals/zh-CN/cases/i3-test-driven-development.json +4 -0
  39. package/evals/zh-CN/cases/i3-ui-prototype.json +50 -0
  40. package/hooks/SIMPLIFY-IGNORE.md +3 -2
  41. package/hooks/simplify-ignore-test.sh +93 -1
  42. package/hooks/simplify-ignore.sh +94 -11
  43. package/package.json +31 -1
  44. package/plugin.json +1 -1
  45. package/references/performance-checklist.md +4 -2
  46. package/scripts/design-provider-discovery-test.js +190 -0
  47. package/scripts/design-provider-test.js +68 -0
  48. package/scripts/enterprise-template-test.js +179 -0
  49. package/scripts/lib/skill-lint-test.js +113 -1
  50. package/scripts/lib/skill-lint.js +62 -8
  51. package/scripts/run-evals-test.js +207 -0
  52. package/scripts/run-evals.js +47 -9
  53. package/scripts/template-adapter-test.js +155 -0
  54. package/scripts/ui-prototype-test.js +114 -0
  55. package/scripts/validate-commands-test.js +30 -0
  56. package/scripts/validate-commands.js +6 -16
  57. package/scripts/validate-reference-links-test.js +18 -0
  58. package/scripts/validate-reference-links.js +4 -2
  59. package/scripts/validate-skills.js +26 -3
  60. package/skills/i3-documentation-and-adrs/SKILL.md +9 -0
  61. package/skills/i3-frontend-ui-engineering/SKILL.md +5 -1
  62. package/skills/i3-idea-refine/SKILL.md +20 -5
  63. package/skills/i3-incremental-implementation/SKILL.md +4 -0
  64. package/skills/i3-performance-optimization/SKILL.md +10 -10
  65. package/skills/i3-security-and-hardening/references/hardening-patterns.md +1 -1
  66. package/skills/i3-shipping-and-launch/SKILL.md +6 -0
  67. package/skills/i3-test-driven-development/SKILL.md +3 -3
  68. package/skills/i3-ui-prototype/SKILL.md +119 -0
  69. package/skills/i3-ui-prototype/assets/templates/catalog.json +148 -0
  70. package/skills/i3-ui-prototype/assets/templates/classic-admin/manifest.json +9 -0
  71. package/skills/i3-ui-prototype/assets/templates/classic-admin/preset.json +6 -0
  72. package/skills/i3-ui-prototype/assets/templates/common/app/app.mjs +89 -0
  73. package/skills/i3-ui-prototype/assets/templates/common/app/config.json +1 -0
  74. package/skills/i3-ui-prototype/assets/templates/common/app/domain.mjs +20 -0
  75. package/skills/i3-ui-prototype/assets/templates/common/app/index.html +17 -0
  76. package/skills/i3-ui-prototype/assets/templates/common/app/serve.cjs +16 -0
  77. package/skills/i3-ui-prototype/assets/templates/common/app/styles.css +670 -0
  78. package/skills/i3-ui-prototype/assets/templates/common/app/tokens.css +19 -0
  79. package/skills/i3-ui-prototype/assets/templates/common/design-system/master.md +20 -0
  80. package/skills/i3-ui-prototype/assets/templates/common/gallery.html +2 -0
  81. package/skills/i3-ui-prototype/assets/templates/common/mocks/applications.json +5 -0
  82. package/skills/i3-ui-prototype/assets/templates/common/requirements-map.json +8 -0
  83. package/skills/i3-ui-prototype/assets/templates/common/serve-gallery.cjs +16 -0
  84. package/skills/i3-ui-prototype/assets/templates/credits.md +17 -0
  85. package/skills/i3-ui-prototype/assets/templates/data-operations/manifest.json +9 -0
  86. package/skills/i3-ui-prototype/assets/templates/data-operations/preset.json +6 -0
  87. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/design-system.md +32 -0
  88. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/index.html +29 -0
  89. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/manifest.json +9 -0
  90. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/origin.json +344 -0
  91. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/preset.json +928 -0
  92. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/app.js +22 -0
  93. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/empty.svg +1 -0
  94. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/reference-styles.json +1 -0
  95. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/result-403.svg +1 -0
  96. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/result-404.svg +1 -0
  97. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets-manifest.json +334 -0
  98. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/baseline.json +173 -0
  99. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/conversion.md +30 -0
  100. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/credits.md +17 -0
  101. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/design-tokens.json +881 -0
  102. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/index.html +28 -0
  103. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/@qin-ui-antdv-next-pro.txt +9 -0
  104. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/ant-design-icons.txt +22 -0
  105. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/antdv-next.txt +21 -0
  106. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/package.json +12 -0
  107. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/browser-routes.json +298 -0
  108. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/coverage.json +180 -0
  109. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/integrity.json +13 -0
  110. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/keyboard.json +11 -0
  111. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/responsive.json +125 -0
  112. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/review.md +51 -0
  113. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/rules.log +150 -0
  114. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-html.png +0 -0
  115. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-original.png +0 -0
  116. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-html.png +0 -0
  117. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-original.png +0 -0
  118. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/models-html.png +0 -0
  119. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/models-original.png +0 -0
  120. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-html.png +0 -0
  121. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-original.png +0 -0
  122. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/selection.json +9 -0
  123. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/visual-comparison.json +342 -0
  124. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/readme.md +73 -0
  125. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/reference.md +59 -0
  126. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/routes.json +178 -0
  127. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/controls.js +99 -0
  128. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/dialogs.js +54 -0
  129. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/dom.js +264 -0
  130. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/forms.js +47 -0
  131. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/icons.js +41 -0
  132. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/layout.js +47 -0
  133. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/router.js +63 -0
  134. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/state.js +90 -0
  135. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/table.js +41 -0
  136. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/widgets.js +8 -0
  137. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.html +3 -0
  138. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.js +36 -0
  139. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.html +2 -0
  140. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.js +51 -0
  141. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.html +3 -0
  142. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.js +48 -0
  143. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/CheckResults.html +2 -0
  144. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/CheckResults.js +6 -0
  145. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.html +2 -0
  146. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.js +13 -0
  147. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/data.js +24 -0
  148. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/domain.js +32 -0
  149. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/registry.js +25 -0
  150. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/store.js +85 -0
  151. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentClose.html +2 -0
  152. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentClose.js +17 -0
  153. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.html +2 -0
  154. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.js +66 -0
  155. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.html +3 -0
  156. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.js +38 -0
  157. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.html +2 -0
  158. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.js +66 -0
  159. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.html +2 -0
  160. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.js +5 -0
  161. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.html +2 -0
  162. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.js +12 -0
  163. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.html +2 -0
  164. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.js +11 -0
  165. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentList.html +2 -0
  166. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentList.js +116 -0
  167. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.html +2 -0
  168. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.js +32 -0
  169. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.html +2 -0
  170. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.js +49 -0
  171. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.html +2 -0
  172. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.js +10 -0
  173. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.html +2 -0
  174. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.js +77 -0
  175. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/data.js +60 -0
  176. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/domain.js +105 -0
  177. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/store.js +212 -0
  178. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/AuditPanel.html +2 -0
  179. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/AuditPanel.js +18 -0
  180. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelDetail.html +2 -0
  181. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelDetail.js +23 -0
  182. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelEditor.html +2 -0
  183. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelEditor.js +78 -0
  184. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelGrant.html +2 -0
  185. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelGrant.js +55 -0
  186. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelReferences.html +2 -0
  187. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelReferences.js +26 -0
  188. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelRelease.html +2 -0
  189. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelRelease.js +38 -0
  190. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelStatus.html +2 -0
  191. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelStatus.js +7 -0
  192. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTable.html +2 -0
  193. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTable.js +72 -0
  194. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTester.html +2 -0
  195. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTester.js +46 -0
  196. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelsPage.html +2 -0
  197. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelsPage.js +52 -0
  198. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/RowActions.html +2 -0
  199. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/RowActions.js +19 -0
  200. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/UsagePanel.html +2 -0
  201. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/UsagePanel.js +30 -0
  202. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/data.js +48 -0
  203. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/domain.js +39 -0
  204. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/store.js +129 -0
  205. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.html +4 -0
  206. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.js +21 -0
  207. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IntentSource.html +2 -0
  208. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IntentSource.js +8 -0
  209. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.html +2 -0
  210. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.js +37 -0
  211. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.html +2 -0
  212. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.js +10 -0
  213. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.html +2 -0
  214. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.js +37 -0
  215. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.html +2 -0
  216. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.js +49 -0
  217. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RunDetail.html +4 -0
  218. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RunDetail.js +22 -0
  219. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.html +2 -0
  220. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.js +9 -0
  221. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/commands.js +82 -0
  222. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/examples.js +47 -0
  223. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/model.js +61 -0
  224. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/repair.js +68 -0
  225. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/store.js +55 -0
  226. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/types.js +1 -0
  227. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/workbench.js +18 -0
  228. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.html +3 -0
  229. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.js +28 -0
  230. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.html +2 -0
  231. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.js +18 -0
  232. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.html +2 -0
  233. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.js +31 -0
  234. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.html +2 -0
  235. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.js +27 -0
  236. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.html +2 -0
  237. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.js +16 -0
  238. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.html +2 -0
  239. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.js +43 -0
  240. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.html +4 -0
  241. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.js +34 -0
  242. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.html +2 -0
  243. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.js +30 -0
  244. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.html +3 -0
  245. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.js +67 -0
  246. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.html +2 -0
  247. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.js +41 -0
  248. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.html +2 -0
  249. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.js +31 -0
  250. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.html +2 -0
  251. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.js +26 -0
  252. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.html +2 -0
  253. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.js +70 -0
  254. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/data.js +8 -0
  255. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/domain.js +62 -0
  256. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/management.js +36 -0
  257. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/managementStore.js +49 -0
  258. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/store.js +132 -0
  259. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/AdminList.html +2 -0
  260. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/AdminList.js +38 -0
  261. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.html +2 -0
  262. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.js +11 -0
  263. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.html +2 -0
  264. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.js +45 -0
  265. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.html +2 -0
  266. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.js +54 -0
  267. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.html +3 -0
  268. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.js +27 -0
  269. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.html +2 -0
  270. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.js +12 -0
  271. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.html +2 -0
  272. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.js +45 -0
  273. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.html +3 -0
  274. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.js +38 -0
  275. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/domain.js +61 -0
  276. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/state.js +51 -0
  277. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/store.js +116 -0
  278. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.html +2 -0
  279. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.js +45 -0
  280. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.html +4 -0
  281. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.js +30 -0
  282. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.html +2 -0
  283. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.js +67 -0
  284. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.html +2 -0
  285. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.js +5 -0
  286. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.html +4 -0
  287. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.js +60 -0
  288. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/commands.js +157 -0
  289. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/model.js +136 -0
  290. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/store.js +76 -0
  291. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.html +3 -0
  292. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.js +26 -0
  293. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.html +2 -0
  294. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.js +14 -0
  295. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.html +2 -0
  296. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.js +113 -0
  297. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.html +3 -0
  298. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.js +62 -0
  299. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/commands.js +97 -0
  300. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/model.js +147 -0
  301. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/store.js +13 -0
  302. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.html +2 -0
  303. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.js +9 -0
  304. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.html +2 -0
  305. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.js +8 -0
  306. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.html +2 -0
  307. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.js +37 -0
  308. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListMore.html +2 -0
  309. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListMore.js +8 -0
  310. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.html +2 -0
  311. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.js +17 -0
  312. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/columns.js +32 -0
  313. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/deliveryGuide.js +49 -0
  314. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/deliveryView.js +12 -0
  315. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/listBatch.js +15 -0
  316. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/listSelection.js +37 -0
  317. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/policy.js +68 -0
  318. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/session.js +44 -0
  319. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.html +2 -0
  320. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.js +25 -0
  321. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.html +2 -0
  322. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.js +53 -0
  323. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.html +10 -0
  324. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.js +30 -0
  325. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ScopePage.html +2 -0
  326. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ScopePage.js +10 -0
  327. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.html +2 -0
  328. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.js +9 -0
  329. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/confirmation.js +3 -0
  330. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/navigation.js +19 -0
  331. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.html +2 -0
  332. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.js +8 -0
  333. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.html +2 -0
  334. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.js +32 -0
  335. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.html +2 -0
  336. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.js +15 -0
  337. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.html +2 -0
  338. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.js +11 -0
  339. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecReview.html +2 -0
  340. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecReview.js +57 -0
  341. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.html +2 -0
  342. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.js +37 -0
  343. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/data.js +20 -0
  344. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/domain.js +55 -0
  345. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/store.js +151 -0
  346. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.html +3 -0
  347. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.js +18 -0
  348. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.html +2 -0
  349. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.js +40 -0
  350. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.html +2 -0
  351. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.js +51 -0
  352. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.html +2 -0
  353. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.js +9 -0
  354. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.html +5 -0
  355. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.js +48 -0
  356. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/domain.js +204 -0
  357. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/exampleSource.js +22 -0
  358. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/registry.js +135 -0
  359. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/store.js +137 -0
  360. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.html +3 -0
  361. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.js +36 -0
  362. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/model.js +56 -0
  363. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/store.js +15 -0
  364. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.html +2 -0
  365. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.js +27 -0
  366. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.html +4 -0
  367. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.js +31 -0
  368. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.html +2 -0
  369. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.js +68 -0
  370. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.html +5 -0
  371. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.js +55 -0
  372. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/data.js +16 -0
  373. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/domain.js +83 -0
  374. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/registry.js +18 -0
  375. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/store.js +61 -0
  376. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/admin.css +60 -0
  377. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/agents.css +46 -0
  378. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/antdv.css +295 -0
  379. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/app.css +102 -0
  380. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/delivery.css +4 -0
  381. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/intents.css +37 -0
  382. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/native.css +22 -0
  383. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/operations.css +2 -0
  384. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/pbc.css +3 -0
  385. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/permissions.css +22 -0
  386. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/pro.css +1 -0
  387. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/releases.css +4 -0
  388. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/reset.css +246 -0
  389. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/reviews.css +8 -0
  390. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/tasks.css +6 -0
  391. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/tokens.css +15 -0
  392. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/workbench.css +61 -0
  393. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/workflows.css +1 -0
  394. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/admin-rules.test.js +96 -0
  395. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/agents.test.js +14 -0
  396. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/intent-state.test.js +37 -0
  397. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/list-batch.test.js +44 -0
  398. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operation-fixtures.js +19 -0
  399. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operation-repair.test.js +14 -0
  400. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operations.test.js +25 -0
  401. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/pbc-management.test.js +17 -0
  402. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/pbc-state.test.js +24 -0
  403. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/permission-config.test.js +23 -0
  404. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/permissions.test.js +24 -0
  405. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/releases.test.js +50 -0
  406. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/reviews.test.js +36 -0
  407. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-forms-router.test.js +28 -0
  408. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-state.test.js +42 -0
  409. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-stores.test.js +16 -0
  410. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/spec-state.test.js +11 -0
  411. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/tasks.test.js +27 -0
  412. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/workbench.test.js +34 -0
  413. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/workflows.test.js +16 -0
  414. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/convert.mjs +168 -0
  415. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/serve.mjs +7 -0
  416. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/styles.mjs +11 -0
  417. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/verify.mjs +24 -0
  418. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/serve.cjs +16 -0
  419. package/skills/i3-ui-prototype/assets/templates/enterprise-admin/usability.css +44 -0
  420. package/skills/i3-ui-prototype/assets/templates/gallery/index.html +40 -0
  421. package/skills/i3-ui-prototype/assets/templates/modern-workspace/manifest.json +9 -0
  422. package/skills/i3-ui-prototype/assets/templates/modern-workspace/preset.json +6 -0
  423. package/skills/i3-ui-prototype/assets/templates/serve-gallery.cjs +23 -0
  424. package/skills/i3-ui-prototype/references/artifact-contract.md +41 -0
  425. package/skills/i3-ui-prototype/references/enterprise-admin.md +38 -0
  426. package/skills/i3-ui-prototype/references/expert-adapter.md +48 -0
  427. package/skills/i3-ui-prototype/references/template-adapters.md +57 -0
  428. package/skills/i3-ui-prototype/references/workflow-contract.md +19 -0
  429. package/skills/i3-ui-prototype/scripts/adapters/easel-html.cjs +30 -0
  430. package/skills/i3-ui-prototype/scripts/adapters/legacy-html.cjs +28 -0
  431. package/skills/i3-ui-prototype/scripts/check-design-provider.cjs +9 -0
  432. package/skills/i3-ui-prototype/scripts/check-prototype.cjs +14 -0
  433. package/skills/i3-ui-prototype/scripts/design-provider-discovery.cjs +128 -0
  434. package/skills/i3-ui-prototype/scripts/enterprise-template.cjs +97 -0
  435. package/skills/i3-ui-prototype/scripts/init-prototype.cjs +8 -0
  436. package/skills/i3-ui-prototype/scripts/manage-baseline.cjs +11 -0
  437. package/skills/i3-ui-prototype/scripts/prototype-lib.cjs +259 -0
  438. package/skills/i3-ui-prototype/scripts/template-adapters.cjs +89 -0
  439. package/skills/i3-using-agent-skills/SKILL.md +5 -0
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelDetail.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" title="模型详情" data-bind-size="(760)" data-on-close="(emit('close'))"><div class="detail-heading"><div><h2>{{ (model.name) }}</h2><p class="mono muted">{{ (model.alias) }}</p></div><template data-component="ModelStatus" data-bind-model="(model)"></template></div><template data-component="Space" wrap="" class="detail-tags"><template data-component="Tag">平台统一接入</template><template data-component="Tag" data-each="cap in (model.capabilities)" data-bind-key="(cap)">{{ (cap) }}</template></template><template data-component="Descriptions" data-bind-items="(items)" data-bind-column="({ xs: 1, sm: 2, md: 2, lg: 2, xl: 2, xxl: 2 })" size="middle" bordered=""></template><section data-if="(session.readable('model:view', 'platform'))" class="drawer-section"><div class="section-heading"><h2>配置发布</h2><template data-component="Button" type="link" data-on-click="(emit('action', 'release', model))">查看发布</template></div><template data-component="Alert" show-icon="" data-bind-type="(model.publishState === 'failed' ? 'error' : 'info')" data-bind-title="('配置 v' + model.version + ' · ' + ({ draft: '待测试或发布', review: '评审中', published: '已发布', failed: '发布失败' }[model.publishState]))" data-bind-description="(model.liveVersion !== model.version ? '当前生效配置与草稿分别保留,新草稿不会自动覆盖当前运行版本。' : '当前配置已经发布,启停状态单独管理。')"></template></section><section class="drawer-section"><div class="section-heading"><h2>使用授权</h2><template data-component="Button" type="link" data-bind-disabled="(!session.can('model:grant', 'platform'))" data-on-click="(emit('action', 'grant', model))">管理授权</template></div><div data-each="g in (model.grants)" data-bind-key="(g.tenantId)" class="grant-scope"><h3>{{ (tenantLabel(g.tenantId)) }}</h3><p><template data-component="Tag" data-each="project in (g.projects)" data-bind-key="(project)">{{ (project) }}</template></p><p class="muted">Agent:{{ (g.agents.map(modelAgentLabel).join('、') || '未授权') }}</p></div><p data-if="(!model.grants.length)" class="muted">尚未分配使用授权</p><p>共享月额度:{{ (fmtNumber(model.quota)) }} Token</p></section><section data-if="(session.readable('model:view', 'platform'))" class="drawer-section"><div class="section-heading"><h2>资源引用 · {{ (model.references.length) }}</h2><template data-component="Button" type="link" data-on-click="(emit('action', 'references', model))">查看引用</template></div><p class="muted">{{ (model.references.length ? '被引用的模型不能直接删除,请先调整关联资源。' : '当前没有资源引用。') }}</p></section><template data-component="RecordMetadata" data-bind-record="(model)"></template><template data-slot="footer"><div class="drawer-footer"><template data-component="Button" data-on-click="(emit('close'))">关闭</template><template data-component="Space"><template data-component="Button" data-bind-disabled="(!session.can('model:edit', 'platform') || model.publishState === 'review')" data-on-click="(emit('action', 'edit', model))">编辑配置</template><template data-component="Button" type="primary" data-bind-disabled="(!session.can('model:test', 'platform') || model.publishState === 'review')" data-on-click="(emit('action', 'test', model))">连接测试</template></template></div></template></template>
@@ -0,0 +1,23 @@
1
+ import { modelAgentLabel } from "../agents/registry.js";
2
+ import { Drawer, Descriptions, Tag, Button, Space, Alert } from "../../runtime/widgets.js";
3
+ import { computed } from '../../runtime/state.js';
4
+ import { h } from '../../runtime/dom.js';
5
+ import { fmtNumber } from "./data.js";
6
+ import { useSession } from "../shared/session.js";
7
+ import { tenantLabel } from "../shared/policy.js";
8
+ import RecordMetadata from "../shared/RecordMetadata.js";
9
+ import ModelStatus from "./ModelStatus.js";
10
+ import { createComponent } from '../../runtime/dom.js';
11
+ export default createComponent({ name: 'ModelDetail', propKeys: ["model"], template: new URL('./ModelDetail.html', import.meta.url).href, setup(__props, __emit) {
12
+ const props = __props, emit = __emit, session = useSession();
13
+ const items = computed(() => [
14
+ { key: 'alias', label: '模型标识', content: props.model.alias }, { key: 'provider', label: '供应商', content: props.model.provider },
15
+ { key: 'type', label: '模型类型', content: props.model.kind === 'chat' ? '对话模型' : '向量模型' },
16
+ { key: 'version', label: '生效版本', content: props.model.liveVersion ? 'v' + props.model.liveVersion : '尚未发布' },
17
+ { key: 'endpoint', label: '服务地址', content: h('span', { class: 'mono wrap-anywhere' }, props.model.endpoint), span: 'filled' },
18
+ { key: 'credential', label: '凭据引用', content: h('span', { class: 'mono wrap-anywhere' }, props.model.credential), span: 'filled' },
19
+ { key: 'price', label: '演示单价', content: '输入 ¥' + props.model.inputPrice + ' / 输出 ¥' + props.model.outputPrice + '(每百万 Token)', span: 'filled' },
20
+ ...(props.model.kind === 'embedding' ? [{ key: 'dimension', label: '向量维度', content: props.model.dimension + ' 维' }] : []),
21
+ ]);
22
+ return { modelAgentLabel, Drawer, Descriptions, Tag, Button, Space, Alert, computed, h, fmtNumber, useSession, tenantLabel, RecordMetadata, ModelStatus, props, emit, session, items };
23
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelEditor.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" data-bind-title="(model ? '编辑模型' : '接入模型')" data-bind-size="(720)" data-bind-mask="({ closable: false })" data-bind-keyboard="(!saving)" data-bind-closable="(!saving)" data-on-close="(close)"><template data-slot="extra"><template data-component="Button" size="small" type="text" data-bind-disabled="(saving)" data-on-click="(session.state = 'expired')">模拟登录失效</template></template><template data-component="Alert" class="form-intro" type="info" show-icon="" title="平台统一管理接入配置" data-bind-description="(model ? '保存生成新草稿;当前生效版本继续保留。新配置需测试并通过发布评审后生效。' : '保存为平台配置草稿,完成测试与发布评审后再启用并分配使用授权。')"></template><template data-component="Alert" data-if="(error)" class="form-intro" type="error" show-icon="" data-bind-title="(error)"></template><template data-component="ProForm" name="model-editor" data-bind-form="(form)" data-bind-grid="({ gutter: 24 })" data-bind-disabled="(saving || !store.canEdit)" data-bind-label-col="({ style: { width: '88px' } })" data-bind-wrapper-col="({ flex: 'auto' })" class="editor-form"></template><template data-component="RecordMetadata" data-if="(model)" data-bind-record="(model)"></template><template data-slot="footer"><div class="drawer-footer"><span class="muted">保存草稿不会直接发布</span><template data-component="Space"><template data-component="Button" data-bind-disabled="(saving)" data-on-click="(close)">取消</template><template data-component="Button" type="primary" data-bind-loading="(saving)" data-bind-disabled="(!store.canEdit)" data-on-click="(save)">保存草稿</template></template></div></template></template>
@@ -0,0 +1,78 @@
1
+ import { confirmAction } from "../shell/confirmation.js";
2
+ import { computed, ref } from '../../runtime/state.js';
3
+ import { Alert, Button, Drawer, Space, message } from "../../runtime/widgets.js";
4
+ import { ProForm, useForm } from "../../runtime/widgets.js";
5
+ import { clone, credentials, providers } from "./data.js";
6
+ import { useModels } from "./store.js";
7
+ import { useSession } from "../shared/session.js";
8
+ import { metadata } from "../shared/policy.js";
9
+ import RecordMetadata from "../shared/RecordMetadata.js";
10
+ import { createComponent } from '../../runtime/dom.js';
11
+ export default createComponent({ name: 'ModelEditor', propKeys: ["model"], template: new URL('./ModelEditor.html', import.meta.url).href, setup(__props, __emit) {
12
+ const props = __props;
13
+ const emit = __emit;
14
+ const store = useModels(), session = useSession(), saving = ref(false), error = ref('');
15
+ const initial = props.model ? clone(props.model) : {
16
+ ...metadata(session.actor, '', 'platform'), grants: [], references: [], publishState: 'draft',
17
+ id: crypto.randomUUID(), name: '', alias: '', provider: '', kind: 'chat', endpoint: '', credential: '', capabilities: ['文本'],
18
+ inputPrice: 0, outputPrice: 0, enabled: false, health: 'untested', projects: [], agents: [], quota: 1000000, version: 1, updatedAt: '',
19
+ };
20
+ const form = useForm(clone(initial));
21
+ const required = (label) => [{ required: true, whitespace: true, message: `请输入${label}` }];
22
+ form.fields.value = [
23
+ { path: 'name', label: '模型名称', component: 'input', placeholder: '例如:报修分诊模型', span: 12, xs: 24, sm: 12, rules: required('模型名称') },
24
+ { path: 'alias', label: '模型标识', component: 'input', placeholder: '例如:triage-chat', span: 12, xs: 24, sm: 12, extra: '小写字母、数字、短横线,2–64 位', rules: [...required('模型标识'), { pattern: /^[a-z][a-z0-9-]{1,63}$/, message: '请输入 2–64 位有效模型标识' }, { validator: async (_rule, value) => { if (store.models.some(m => m.id !== initial.id && m.alias === value?.trim()))
25
+ throw new Error('模型标识已存在,请更换'); } }] },
26
+ { path: 'provider', label: '供应商', component: 'select', placeholder: '请选择供应商', options: providers.map(x => ({ label: x, value: x })), span: 12, xs: 24, sm: 12, rules: [{ required: true, message: '请选择供应商' }] },
27
+ { path: 'kind', label: '模型类型', component: 'select', options: [{ label: '对话模型', value: 'chat' }, { label: '向量模型', value: 'embedding' }], allowClear: false, span: 12, xs: 24, sm: 12 },
28
+ { path: 'endpoint', label: '服务地址', component: 'input', placeholder: 'https://models.example.invalid/v1', span: 24, extra: '填写服务端点;原型不会向该地址发送请求。', rules: [...required('服务地址'), { type: 'url', message: '请输入完整有效的 HTTP 或 HTTPS 地址' }, { pattern: /^https?:\/\//, message: '请输入 HTTP 或 HTTPS 地址' }] },
29
+ { path: 'credential', label: '凭据引用', component: 'select', options: credentials, placeholder: '请选择受管凭据', span: 24, extra: '仅选择演示凭据引用,不填写真实 API Key。', rules: [{ required: true, message: '请选择凭据引用' }] },
30
+ { path: 'capabilities', label: '声明能力', component: 'select', mode: 'multiple', options: ['文本', '工具调用', '推理', '视觉'].map(x => ({ label: x, value: x })), span: 24, hidden: computed(() => form.formData.kind === 'embedding'), rules: computed(() => form.formData.kind === 'chat' ? [{ required: true, type: 'array', min: 1, message: '请选择至少一项能力' }] : []) },
31
+ { path: 'dimension', label: '向量维度', component: 'input-number', min: 1, max: 65536, precision: 0, span: 24, hidden: computed(() => form.formData.kind !== 'embedding'), rules: computed(() => form.formData.kind === 'embedding' ? [{ required: true, message: '请输入向量维度' }] : []) },
32
+ { path: 'inputPrice', label: '输入单价', component: 'input-number', min: 0, precision: 4, span: 12, xs: 24, sm: 12, extra: '元 / 百万 Token(演示)', rules: [{ required: true, type: 'number', min: 0, message: '请输入有效的非负输入单价' }] },
33
+ { path: 'outputPrice', label: '输出单价', component: 'input-number', min: 0, precision: 4, span: 12, xs: 24, sm: 12, extra: '元 / 百万 Token(演示)', hidden: computed(() => form.formData.kind === 'embedding'), rules: computed(() => form.formData.kind === 'chat' ? [{ required: true, type: 'number', min: 0, message: '请输入有效的非负输出单价' }] : []) },
34
+ ];
35
+ function close() {
36
+ if (saving.value)
37
+ return;
38
+ if (JSON.stringify(form.formData) !== JSON.stringify(initial))
39
+ confirmAction({ title: '放弃未保存的修改?', content: '关闭后本次输入不会保存。', okText: '放弃修改', cancelText: '继续编辑', onOk: () => emit('close') });
40
+ else
41
+ emit('close');
42
+ }
43
+ async function save() {
44
+ if (!store.canEdit)
45
+ return;
46
+ try {
47
+ await form.formRef.value?.validate();
48
+ }
49
+ catch {
50
+ return;
51
+ }
52
+ saving.value = true;
53
+ await new Promise(resolve => setTimeout(resolve, 400));
54
+ const value = clone(form.formData);
55
+ value.name = value.name.trim();
56
+ value.alias = value.alias.trim();
57
+ value.endpoint = value.endpoint.trim();
58
+ value.version = props.model ? props.model.version + 1 : 1;
59
+ if (value.kind === 'embedding') {
60
+ value.capabilities = ['向量'];
61
+ value.outputPrice = 0;
62
+ }
63
+ else
64
+ delete value.dimension;
65
+ try {
66
+ error.value = '';
67
+ if (store.save(value, !props.model))
68
+ emit('saved', value.id);
69
+ }
70
+ catch (e) {
71
+ error.value = e.message;
72
+ }
73
+ finally {
74
+ saving.value = false;
75
+ }
76
+ }
77
+ return { confirmAction, computed, ref, Alert, Button, Drawer, Space, message, ProForm, useForm, clone, credentials, providers, useModels, useSession, metadata, RecordMetadata, props, emit, store, session, saving, error, initial, form, required, close, save };
78
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelGrant.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" title="管理模型使用授权" data-bind-size="(660)" data-bind-mask="({ closable: false })" data-on-close="(!saving &amp;&amp; emit('close'))"><h2>{{ (model.name) }}</h2><template data-component="Alert" class="form-intro" type="info" show-icon="" title="模型配置由平台维护" description="所选 Agent 会获准在该租户的全部所选项目中使用此模型,候选项随项目联动。调用须同时匹配租户、项目和 Agent。使用授权不包含编辑源配置或转授权;全部留空表示撤销使用授权。"></template><template data-component="ProForm" name="model-grant" data-bind-form="(form)" data-bind-disabled="(saving || !session.can('model:grant', 'platform'))" data-bind-grid="({ gutter: 24 })" data-bind-label-col="({ style: { width: '104px' } })" data-bind-wrapper-col="({ flex: 'auto' })"></template><template data-component="Alert" data-if="(error)" type="error" show-icon="" data-bind-title="(error)"></template><template data-slot="footer"><div class="drawer-footer"><span class="muted">授权关系与资源引用分别管理</span><template data-component="Space"><template data-component="Button" data-bind-disabled="(saving)" data-on-click="(emit('close'))">取消</template><template data-component="Button" type="primary" data-bind-loading="(saving)" data-bind-disabled="(!session.can('model:grant', 'platform'))" data-on-click="(save)">保存授权</template></template></div></template></template>
@@ -0,0 +1,55 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { Alert, Button, Drawer, Space } from "../../runtime/widgets.js";
3
+ import { ProForm, useForm } from "../../runtime/widgets.js";
4
+ import { agentCatalog, projectCatalog } from "./data.js";
5
+ import { useModels } from "./store.js";
6
+ import { modelAgentEntries, modelProjectEntries } from "../agents/registry.js";
7
+ import { useSession } from "../shared/session.js";
8
+ import { createComponent } from '../../runtime/dom.js';
9
+ export default createComponent({ name: 'ModelGrant', propKeys: ["model"], template: new URL('./ModelGrant.html', import.meta.url).href, setup(__props, __emit) {
10
+ const props = __props, emit = __emit;
11
+ const store = useModels(), session = useSession(), saving = ref(false), error = ref(''), expected = props.model.recordVersion;
12
+ const group = (tenant) => props.model.grants.find(g => g.tenantId === tenant);
13
+ const form = useForm({ heatingProjects: [...(group('heating')?.projects || [])], heatingAgents: [...(group('heating')?.agents || [])], northProjects: [...(group('north')?.projects || [])], northAgents: [...(group('north')?.agents || [])], quota: props.model.quota });
14
+ const catalog = computed(() => { const entries = new Map(agentCatalog.map(a => [a.value, { ...a, label: a.value }])); for (const a of modelAgentEntries()) {
15
+ const old = entries.get(a.value);
16
+ entries.set(a.value, { ...a, projects: [...new Set([...(old?.projects || []), ...a.projects])] });
17
+ } return [...entries.values()]; });
18
+ const projects = computed(() => [...projectCatalog, ...modelProjectEntries()].filter((a, i, all) => all.findIndex(b => b.value === a.value && b.tenantId === a.tenantId) === i));
19
+ const options = (p) => catalog.value.filter(a => p.length && p.every(v => a.projects.includes(v))).map(a => ({ label: a.label, value: a.value }));
20
+ form.fields.value = [
21
+ { path: 'heatingProjects', label: '供热 · 项目', component: 'select', mode: 'multiple', span: 24, options: computed(() => projects.value.filter(p => p.tenantId === 'heating').map(p => ({ label: p.value, value: p.value }))), placeholder: '选择供热事业部项目' },
22
+ { path: 'heatingAgents', label: '供热 · Agent', component: 'select', mode: 'multiple', span: 24, options: computed(() => options(form.formData.heatingProjects)), disabled: computed(() => !form.formData.heatingProjects.length), placeholder: '选择在上述项目中允许使用的 Agent' },
23
+ { path: 'northProjects', label: '北方 · 项目', component: 'select', mode: 'multiple', span: 24, options: computed(() => projects.value.filter(p => p.tenantId === 'north').map(p => ({ label: p.value, value: p.value }))), placeholder: '选择北方能源项目' },
24
+ { path: 'northAgents', label: '北方 · Agent', component: 'select', mode: 'multiple', span: 24, options: computed(() => options(form.formData.northProjects)), disabled: computed(() => !form.formData.northProjects.length), placeholder: '选择在上述项目中允许使用的 Agent' },
25
+ { path: 'quota', label: '共享月额度', component: 'input-number', span: 24, min: 1, max: 10000000000, precision: 0, extra: 'Token;沿用所选范围共享额度的演示口径,正式扣减规则待 spec。', rules: [{ required: true, message: '请输入额度' }] },
26
+ ];
27
+ watch(() => form.formData.heatingProjects, p => { form.formData.heatingAgents = form.formData.heatingAgents.filter(a => options(p).some(o => o.value === a)); }, { deep: true });
28
+ watch(() => form.formData.northProjects, p => { form.formData.northAgents = form.formData.northAgents.filter(a => options(p).some(o => o.value === a)); }, { deep: true });
29
+ async function save() {
30
+ if (saving.value)
31
+ return;
32
+ try {
33
+ await form.formRef.value?.validate();
34
+ }
35
+ catch {
36
+ return;
37
+ }
38
+ saving.value = true;
39
+ error.value = '';
40
+ try {
41
+ await new Promise(r => setTimeout(r, 350));
42
+ const d = form.formData;
43
+ const grants = [{ tenantId: 'heating', projects: d.heatingProjects, agents: d.heatingAgents }, { tenantId: 'north', projects: d.northProjects, agents: d.northAgents }].filter(g => g.projects.length || g.agents.length);
44
+ store.grant(props.model.id, grants, Number(d.quota), expected);
45
+ emit('close');
46
+ }
47
+ catch (e) {
48
+ error.value = e.message;
49
+ }
50
+ finally {
51
+ saving.value = false;
52
+ }
53
+ }
54
+ return { computed, ref, watch, Alert, Button, Drawer, Space, ProForm, useForm, agentCatalog, projectCatalog, useModels, modelAgentEntries, modelProjectEntries, useSession, props, emit, store, session, saving, error, expected, group, form, catalog, projects, options, save };
55
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelReferences.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" data-bind-title="(deleting ? '删除模型' : '资源引用')" data-bind-size="(600)" data-on-close="(emit('close'))"><h2>{{ (model.name) }}</h2><template data-component="Alert" data-if="(deleting)" class="form-intro" data-bind-type="(reason ? 'warning' : 'info')" show-icon="" data-bind-title="(reason || '确认删除此模型?')" description="删除后从可用列表移除,基础信息和操作记录仍保留。提交时会再次检查资源引用。"></template><section class="drawer-section"><h2>引用此模型的资源 · {{ (model.references.length) }}</h2><div data-each="item in (model.references)" data-bind-key="(item.name)" class="reference-row"><div><strong>{{ (item.name) }}</strong><p class="muted">{{ (item.kind) }} · {{ (item.version) }}</p></div><template data-component="Tag">正在引用</template></div><p data-if="(!model.references.length)" class="muted">当前没有资源引用。授权关系不等同于资源引用。</p></section><template data-component="Alert" data-if="(error)" type="error" data-bind-title="(error)"></template><template data-slot="footer"><div class="drawer-footer"><template data-component="Button" data-on-click="(emit('close'))">返回</template><template data-component="Button" data-if="(deleting)" danger="" type="primary" data-bind-disabled="(!!reason || !session.can('model:delete', 'platform'))" data-on-click="(remove)">确认删除</template></div></template></template>
@@ -0,0 +1,26 @@
1
+ import { ref, computed } from '../../runtime/state.js';
2
+ import { Alert, Button, Drawer, Tag } from "../../runtime/widgets.js";
3
+ import { useModels } from "./store.js";
4
+ import { useSession } from "../shared/session.js";
5
+ import { assertDelete } from "./domain.js";
6
+ import { createComponent } from '../../runtime/dom.js';
7
+ export default createComponent({ name: 'ModelReferences', propKeys: ["model", "deleting"], template: new URL('./ModelReferences.html', import.meta.url).href, setup(__props, __emit) {
8
+ const props = __props, emit = __emit;
9
+ const store = useModels(), session = useSession(), error = ref('');
10
+ const expected = props.model.recordVersion;
11
+ const reason = computed(() => { try {
12
+ assertDelete(props.model);
13
+ return '';
14
+ }
15
+ catch (e) {
16
+ return e.message;
17
+ } });
18
+ function remove() { try {
19
+ store.remove(props.model.id, expected);
20
+ emit('close');
21
+ }
22
+ catch (e) {
23
+ error.value = e.message;
24
+ } }
25
+ return { ref, computed, Alert, Button, Drawer, Tag, useModels, useSession, assertDelete, props, emit, store, session, error, expected, reason, remove };
26
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelRelease.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" title="配置发布" data-bind-size="(640)" data-bind-mask="({ closable: false })" data-on-close="(!busy &amp;&amp; emit('close'))"><div class="detail-heading"><div><h2>{{ (model.name) }}</h2><p class="mono muted">{{ (model.alias) }}</p></div><template data-component="Tag" data-bind-color="(model.publishState === 'published' ? 'green' : 'blue')">{{ ({ draft: '待发布', review: '评审中', published: '已发布', failed: '发布失败' }[model.publishState]) }}</template></div><div class="version-comparison"><div><span>当前生效版本</span><strong>{{ (model.liveVersion ? 'v' + model.liveVersion : '尚未发布') }}</strong><small>{{ (model.publishedBy || '平台初始配置') }} {{ (model.publishedAt ? formatDate(model.publishedAt) : '') }}</small></div><div><span>本次配置</span><strong>v{{ (model.version) }}</strong><small>{{ (model.testedVersion === model.version ? '本版本模拟测试通过' : '等待本版本测试') }}</small></div></div><section class="drawer-section"><h2>变更内容</h2><p data-if="(!changes.length)">与当前发布版本一致</p><div data-else="" class="config-diff"><table><thead><tr><th>字段</th><th>当前生效</th><th>待发布</th></tr></thead><tbody><tr data-each="d in (diff)" data-bind-key="(d.key)"><th>{{ (d.label) }}</th><td>{{ (d.before) }}</td><td>{{ (d.after) }}</td></tr></tbody></table></div><p class="muted">配置草稿、测试结果和发布结果分别记录。发布成功前,当前生效配置保持不变。</p></section><template data-component="Alert" data-if="(model.requestId)" class="form-intro" type="info" show-icon="" title="发布申请(演示)" data-bind-description="(model.requestId + ' · 申请人:' + model.requestName)"></template><template data-component="Alert" data-if="(model.publishState === 'review' &amp;&amp; !session.can('model:publish', 'platform'))" class="form-intro" type="info" show-icon="" title="等待配置审核员评审" description="可在页头切换到配置审核员,查看同一申请并给出评审结果。"></template><section data-if="(model.publishState === 'review' &amp;&amp; session.can('model:publish', 'platform'))" class="drawer-section"><label for="release-note" class="answer-label">评审意见</label><template data-component="Input.TextArea" id="release-note" data-model-value="(note)" data-bind-rows="(3)" data-bind-maxlength="(500)" placeholder="请说明发布或退回的理由"></template></section><template data-component="Alert" data-if="(model.publishNote)" class="form-intro" data-bind-type="(model.publishState === 'failed' ? 'error' : model.publishState === 'published' ? 'success' : 'warning')" show-icon="" data-bind-title="(model.publishNote)"></template><template data-component="Alert" data-if="(error)" type="error" show-icon="" data-bind-title="(error)"></template><p class="muted">本页模拟配置评审与发布,不提交真实 GitLab PR 或修改运行环境。</p><template data-slot="footer"><div class="drawer-footer"><template data-component="Button" data-bind-disabled="(busy)" data-on-click="(emit('close'))">关闭</template><template data-component="Space" data-if="(model.publishState === 'review' &amp;&amp; session.can('model:publish', 'platform'))"><template data-component="Button" danger="" data-bind-disabled="(busy)" data-on-click="(act('reject'))">退回修改</template><template data-component="Button" type="primary" data-bind-loading="(busy)" data-on-click="(act('approve'))">同意并发布</template></template><template data-component="Button" data-else="" type="primary" data-bind-loading="(busy)" data-bind-disabled="(!session.can('model:edit', 'platform') || model.publishState === 'review' || model.liveVersion === model.version || model.testedVersion !== model.version)" data-on-click="(act('submit'))">提交发布申请</template></div></template></template>
@@ -0,0 +1,38 @@
1
+ import { ref, computed } from '../../runtime/state.js';
2
+ import { Alert, Button, Drawer, Input, Space, Tag } from "../../runtime/widgets.js";
3
+ import { useModels } from "./store.js";
4
+ import { useSession } from "../shared/session.js";
5
+ import { formatDate } from "../shared/policy.js";
6
+ import { modelConfigKeys } from "./domain.js";
7
+ import { createComponent } from '../../runtime/dom.js';
8
+ export default createComponent({ name: 'ModelRelease', propKeys: ["model"], template: new URL('./ModelRelease.html', import.meta.url).href, setup(__props, __emit) {
9
+ const props = __props, emit = __emit;
10
+ const store = useModels(), session = useSession(), note = ref(''), error = ref(''), busy = ref(false);
11
+ const labels = { name: '名称', alias: '标识', provider: '供应商', kind: '类型', endpoint: '服务地址', credential: '凭据引用', capabilities: '能力', inputPrice: '输入价格', outputPrice: '输出价格', dimension: '向量维度' };
12
+ const changes = computed(() => modelConfigKeys.filter(k => JSON.stringify(props.model[k]) !== JSON.stringify(props.model.liveConfig?.[k])).map(k => labels[k]));
13
+ const diff = computed(() => modelConfigKeys.filter(k => JSON.stringify(props.model[k]) !== JSON.stringify(props.model.liveConfig?.[k])).map(k => ({ key: k, label: labels[k], before: display(props.model.liveConfig?.[k]), after: display(props.model[k]) })));
14
+ function display(value) { return value === undefined || value === '' ? '未设置' : Array.isArray(value) ? value.join('、') : String(value); }
15
+ async function act(action) {
16
+ if (busy.value)
17
+ return;
18
+ const expected = props.model.recordVersion, actor = session.actor.id;
19
+ busy.value = true;
20
+ error.value = '';
21
+ try {
22
+ await new Promise(r => setTimeout(r, 500));
23
+ if (actor !== session.actor.id)
24
+ throw new Error('身份已改变,请重新核对。');
25
+ if (action === 'submit')
26
+ store.submit(props.model.id, expected);
27
+ else
28
+ store.review(props.model.id, expected, action === 'approve', note.value);
29
+ }
30
+ catch (e) {
31
+ error.value = e.message;
32
+ }
33
+ finally {
34
+ busy.value = false;
35
+ }
36
+ }
37
+ return { ref, computed, Alert, Button, Drawer, Input, Space, Tag, useModels, useSession, formatDate, modelConfigKeys, props, emit, store, session, note, error, busy, labels, changes, diff, display, act };
38
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelStatus.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="model-status"><div><span class="status-dot" data-bind-class="(model.enabled ? (model.health === 'error' ? 'error' : 'success') : 'neutral')"></span><span>{{ (model.enabled ? '已启用' : '已停用') }}</span></div><span class="health-text" data-bind-class="(model.health)">{{ (healthText) }}</span></div>
@@ -0,0 +1,7 @@
1
+ import { computed } from '../../runtime/state.js';
2
+ import { createComponent } from '../../runtime/dom.js';
3
+ export default createComponent({ name: 'ModelStatus', propKeys: ["model"], template: new URL('./ModelStatus.html', import.meta.url).href, setup(__props, __emit) {
4
+ const props = __props;
5
+ const healthText = computed(() => ({ normal: '连接正常', error: '连接异常', untested: '未测试' })[props.model.health]);
6
+ return { computed, props, healthText };
7
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelTable.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <section class="filter-panel panel" aria-label="模型筛选"><template data-component="ProForm" name="model-search" data-bind-form="(filters)" data-bind-grid="({ gutter: 24 })" class="filter-form" data-on-keydown.enter.prevent="(search)"></template><div class="filter-actions"><template data-component="Button" data-on-click="(search)">查询</template><template data-component="Button" data-on-click="(reset)">重置</template></div></section><section class="panel model-table-panel" aria-label="已接入模型列表"><template data-component="Result" data-if="(store.scene === 'error')" status="warning" title="模型列表加载失败"><template data-slot="extra"><template data-component="Button" type="primary" data-on-click="(retry)">重试</template></template></template><template data-component="ProTable" data-else="" data-bind-table="(table)" data-bind-search="(async () =&gt; { })" data-bind-control="(false)" data-bind-table-container="(false)" data-bind-loading="(loading)" data-bind-row-selection="(selection.rowSelection.value)" row-key="id" size="middle" data-bind-scroll="({ x: 'max-content' })" data-bind-pagination="({ showTotal: (n) =&gt; '共 ' + n + ' 条', showSizeChanger: true, pageSizeOptions: [10, 20, 50, 100] })" data-bind-locale="({ emptyText: h(Empty, { description: store.scene === 'empty' ? '还没有接入模型' : '没有符合条件的模型' }, { default: () =&gt; h(Button, { onClick: store.scene === 'empty' ? () =&gt; emit('create') : reset, disabled: store.scene === 'empty' &amp;&amp; !store.canEdit }, () =&gt; store.scene === 'empty' ? '接入第一个模型' : '清除筛选') }) })"><template data-slot="button-bar"><div class="list-heading"><h2>已接入模型 · {{ (filtered.length) }}</h2><template data-component="ListBatchBar" data-bind-count="(selection.keys.value.length)" data-bind-allowed="(session.can('model:delete', 'platform'))" data-on-remove="(batchDelete)" data-on-clear="(selection.clear)"></template></div></template><template data-slot="toolbar"><div class="table-tools"><template data-component="Select" data-model-value="(sort)" aria-label="模型排序" data-bind-options="([{ label: '创建时间倒序', value: 'created' }, { label: '修改时间倒序', value: 'updated' }, { label: '名称排序', value: 'name' }])"></template><template data-component="ColumnSettings" data-bind-preferences="(prefs)"></template><template data-component="Button" aria-label="刷新模型列表" data-bind-loading="(loading)" data-on-click="(refresh)"><template data-component="ReloadOutlined"></template></template></div></template></template></section><template data-component="ListDeleteDialog" data-if="(deleteTargets.length)" data-model-targets="(deleteTargets)" label="模型" data-bind-check="(store.checkRemove)" data-bind-submit="(store.removeMany)" data-on-close="(deleteTargets = [])" data-on-deleted="(deleted)"></template>
@@ -0,0 +1,72 @@
1
+ import { computed, onMounted, ref, watch } from '../../runtime/state.js';
2
+ import { h } from '../../runtime/dom.js';
3
+ import { Button, Empty, Result, Tag, Select } from "../../runtime/widgets.js";
4
+ import { ReloadOutlined } from "../../runtime/icons.js";
5
+ import { ProForm, ProTable, useForm, useTable } from "../../runtime/widgets.js";
6
+ import { providers } from "./data.js";
7
+ import { useModels } from "./store.js";
8
+ import { useSession } from "../shared/session.js";
9
+ import { formatDate } from "../shared/policy.js";
10
+ import { useColumns } from "../shared/columns.js";
11
+ import ColumnSettings from "../shared/ColumnSettings.js";
12
+ import { useListSelection } from "../shared/listSelection.js";
13
+ import ListBatchBar from "../shared/ListBatchBar.js";
14
+ import ListDeleteDialog from "../shared/ListDeleteDialog.js";
15
+ import ModelStatus from "./ModelStatus.js";
16
+ import RowActions from "./RowActions.js";
17
+ import { createComponent } from '../../runtime/dom.js';
18
+ export default createComponent({ name: 'ModelTable', propKeys: [], template: new URL('./ModelTable.html', import.meta.url).href, setup(__props, __emit) {
19
+ const emit = __emit, store = useModels(), session = useSession(), loading = ref(false), sort = ref('created');
20
+ const applied = ref({ keyword: '', provider: '', status: '' });
21
+ const filters = useForm({ ...applied.value }, [
22
+ { path: 'keyword', label: '模型名称', component: 'input', placeholder: '搜索名称或标识', span: 9, xs: 24, md: 9 },
23
+ { path: 'provider', label: '供应商', component: 'select', placeholder: '全部供应商', options: providers.map(p => ({ label: p, value: p })), span: 8, xs: 24, md: 8 },
24
+ { path: 'status', label: '状态', component: 'select', placeholder: '全部状态', options: [{ label: '已启用', value: 'enabled' }, { label: '已停用', value: 'disabled' }, { label: '待发布', value: 'draft' }, { label: '评审中', value: 'review' }, { label: '连接异常', value: 'error' }], span: 7, xs: 24, md: 7 },
25
+ ]);
26
+ const filtered = computed(() => {
27
+ if (store.scene !== 'normal')
28
+ return [];
29
+ const q = applied.value.keyword.trim().toLowerCase(), status = applied.value.status;
30
+ return store.models.filter(m => (!q || (m.name + ' ' + m.alias).toLowerCase().includes(q)) && (!applied.value.provider || m.provider === applied.value.provider) &&
31
+ (!status || status === 'enabled' && m.enabled || status === 'disabled' && !m.enabled || status === 'error' && m.health === 'error' || status === m.publishState))
32
+ .sort((a, b) => sort.value === 'name' ? a.name.localeCompare(b.name, 'zh-CN') : ((sort.value === 'updated' ? b.updatedAt : b.createdAt).localeCompare(sort.value === 'updated' ? a.updatedAt : a.createdAt) || a.id.localeCompare(b.id)));
33
+ });
34
+ const render = (fn) => (_, m) => fn(m);
35
+ const prefs = useColumns('models', [
36
+ { key: 'name', label: '模型', locked: true }, { key: 'provider', label: '供应商', defaultVisible: true }, { key: 'capabilities', label: '能力', defaultVisible: true },
37
+ { key: 'scope', label: '授权范围', defaultVisible: true }, { key: 'status', label: '状态', defaultVisible: true }, { key: 'version', label: '生效 / 草稿', defaultVisible: true },
38
+ { key: 'createdBy', label: '创建人' }, { key: 'createdAt', label: '创建时间' }, { key: 'createdDept', label: '创建部门' }, { key: 'updatedBy', label: '修改人' }, { key: 'updatedAt', label: '修改时间' }, { key: 'actions', label: '操作', locked: true },
39
+ ]);
40
+ const table = useTable({ pageParam: { current: 1, pageSize: 10, total: 0 }, columns: [
41
+ { key: 'name', title: '模型', dataIndex: 'name', width: 215, render: render(m => h('div', { class: 'model-name-cell' }, [h('button', { class: 'text-button model-link', onClick: () => emit('action', 'detail', m) }, m.name), h('span', { class: 'mono muted' }, m.alias)])) },
42
+ { key: 'provider', title: '供应商', dataIndex: 'provider', width: 145 },
43
+ { key: 'capabilities', title: '能力', width: 155, render: render(m => h('div', { class: 'capabilities' }, m.capabilities.map(c => h(Tag, { bordered: false }, () => c)))) },
44
+ { key: 'scope', title: '授权范围', width: 130, render: render(m => h('button', { class: 'text-button scope-link', onClick: () => emit('action', session.can('model:grant', 'platform') ? 'grant' : 'detail', m) }, m.grants.length ? m.grants.length + ' 个租户 · ' + m.projects.length + ' 个项目' : '暂未授权')) },
45
+ { key: 'status', title: '状态', width: 130, render: render(m => h(ModelStatus, { model: m })) },
46
+ { key: 'version', title: '生效 / 草稿', width: 140, render: render(m => h('div', { class: 'model-name-cell' }, [h('span', m.liveVersion ? '生效 v' + m.liveVersion : '尚未发布'), h('span', { class: 'muted' }, m.liveVersion === m.version ? '无待发布变更' : 'v' + m.version + ' · ' + ({ draft: '待发布', review: '评审中', failed: '发布失败', published: '已发布' }[m.publishState]))])) },
47
+ { key: 'createdBy', title: '创建人', dataIndex: 'createdBy', width: 105 }, { key: 'createdAt', title: '创建时间', dataIndex: 'createdAt', width: 180, render: (v) => formatDate(String(v)) },
48
+ { key: 'createdDept', title: '创建部门', dataIndex: 'createdDept', width: 140 }, { key: 'updatedBy', title: '修改人', dataIndex: 'updatedBy', width: 105 },
49
+ { key: 'updatedAt', title: '修改时间', dataIndex: 'updatedAt', width: 180, render: (v) => formatDate(String(v)) },
50
+ { key: 'actions', title: '操作', fixed: 'right', width: 120, render: render(m => h(RowActions, { model: m, onAction: (a, x) => emit('action', a, x) })) },
51
+ ] });
52
+ const deleteTargets = ref([]);
53
+ const selection = useListSelection(table.dataSource, computed(() => JSON.stringify([applied.value, sort.value, session.key, store.scene, table.pageParam.current, table.pageParam.pageSize])), computed(() => session.can('model:delete', 'platform')), m => m.name);
54
+ function batchDelete() { deleteTargets.value = selection.selected.value.map(m => ({ id: m.id, name: m.name, recordVersion: m.recordVersion })); }
55
+ function deleted() { deleteTargets.value = []; selection.clear(); }
56
+ const catalog = new Map(table.columns.value.map(c => [c.key, c]));
57
+ watch(prefs.keys, keys => { table.columns.value = keys.map(k => catalog.get(k)).filter(Boolean); }, { immediate: true });
58
+ watch([filtered, () => table.pageParam.current, () => table.pageParam.pageSize], () => {
59
+ const size = table.pageParam.pageSize || 10, max = Math.max(1, Math.ceil(filtered.value.length / size));
60
+ if ((table.pageParam.current || 1) > max)
61
+ table.setPageParam({ current: max });
62
+ const start = ((table.pageParam.current || 1) - 1) * size;
63
+ table.dataSource.value = filtered.value.slice(start, start + size);
64
+ table.setPageParam({ total: filtered.value.length });
65
+ }, { immediate: true });
66
+ async function refresh() { selection.clear(); loading.value = true; await new Promise(r => setTimeout(r, 300)); loading.value = false; }
67
+ function search() { applied.value = { keyword: filters.formData.keyword || '', provider: filters.formData.provider || '', status: filters.formData.status || '' }; table.setPageParam({ current: 1 }); }
68
+ function reset() { filters.setFormData({ keyword: '', provider: '', status: '' }); search(); }
69
+ function retry() { store.scene = 'normal'; refresh(); }
70
+ onMounted(refresh);
71
+ return { computed, onMounted, ref, watch, h, Button, Empty, Result, Tag, Select, ReloadOutlined, ProForm, ProTable, useForm, useTable, providers, useModels, useSession, formatDate, useColumns, ColumnSettings, useListSelection, ListBatchBar, ListDeleteDialog, ModelStatus, RowActions, emit, store, session, loading, sort, applied, filters, filtered, render, prefs, table, deleteTargets, selection, batchDelete, deleted, catalog, refresh, search, reset, retry };
72
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelTester.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" title="模型连接测试" data-bind-size="(640)" data-on-close="(close)"><div class="detail-heading"><div><h2>{{ (model.name) }}</h2><p class="mono muted">{{ (model.alias) }} · v{{ (model.version) }}</p></div><template data-component="Tag">模拟测试</template></div><template data-component="Alert" type="info" show-icon="" title="本次测试仅演示交互,不会调用真实模型。" description="可切换成功与失败场景,观察结果和后续操作。"></template><section class="drawer-section"><h2>模拟结果</h2><template data-component="RadioGroup" data-model-value="(outcome)" data-bind-disabled="(running)" data-bind-options="([{ label: '连接成功', value: 'success' }, { label: '连接超时', value: 'failure' }])"></template></section><section class="drawer-section"><template data-component="Steps" data-bind-current="(result === 'success' ? 3 : stage)" data-bind-status="(result === 'failure' ? 'error' : 'process')" data-bind-items="(stages)" size="small"></template></section><div data-if="(running)" class="test-wait" role="status"><template data-component="LoadingOutlined" spin=""></template><h2>正在验证模型接入</h2><p>正在模拟{{ (stages[stage]?.title) }}…</p></div><div data-else-if="(result)" class="test-result" data-bind-class="(result)" role="status"><template data-component="CheckCircleOutlined" data-if="(result === 'success')"></template><template data-component="CloseCircleOutlined" data-else=""></template><h2>{{ (result === 'success' ? '模型连接测试通过' : '模型连接超时') }}</h2><p>{{ (result === 'success' ? '配置与声明能力已通过模拟检查。' : '请检查服务地址、凭据引用及供应商服务状态。') }}</p><p data-if="(result === 'success')" class="muted">模拟响应耗时:480 ms · 此数值不代表真实性能</p><p data-else="" class="mono muted">DEMO_CONNECTION_TIMEOUT · 模拟错误</p></div><div data-else="" class="test-wait"><p class="muted">开始测试后,这里将显示各项检查结果。</p></div><template data-component="Alert" data-if="(error)" type="error" show-icon="" data-bind-title="(error)"></template><template data-component="Alert" data-if="(result === 'success')" type="info" show-icon="" title="测试通过后,请前往“配置发布”提交评审。" description="本地测试不代表真实协议兼容或发布成功;正式验证需要分别覆盖工具调用、结构化输出、流式、usage 和错误语义。"></template><template data-slot="footer"><div class="drawer-footer"><template data-component="Button" data-on-click="(close)">{{ (running ? '取消测试并关闭' : '关闭') }}</template><template data-component="Button" type="primary" data-bind-loading="(running)" data-bind-disabled="(!session.can('model:test', 'platform'))" data-on-click="(run)">{{ (result ? '重新测试' : '开始测试') }}</template></div></template></template>
@@ -0,0 +1,46 @@
1
+ import { computed, onBeforeUnmount, ref } from '../../runtime/state.js';
2
+ import { Alert, Button, Drawer, RadioGroup, Steps, Tag, Space, message } from "../../runtime/widgets.js";
3
+ import { CheckCircleOutlined, CloseCircleOutlined, LoadingOutlined } from "../../runtime/icons.js";
4
+ import { useModels } from "./store.js";
5
+ import { useSession } from "../shared/session.js";
6
+ import { createComponent } from '../../runtime/dom.js';
7
+ export default createComponent({ name: 'ModelTester', propKeys: ["model"], template: new URL('./ModelTester.html', import.meta.url).href, setup(__props, __emit) {
8
+ const props = __props;
9
+ const emit = __emit;
10
+ const store = useModels(), running = ref(false), stage = ref(0), outcome = ref(props.model.health === 'error' ? 'failure' : 'success');
11
+ const session = useSession(), error = ref('');
12
+ const result = ref(null);
13
+ let timer;
14
+ const stages = computed(() => [{ title: '检查配置' }, { title: '验证连接' }, { title: props.model.kind === 'embedding' ? '向量能力' : '声明能力' }]);
15
+ function run() {
16
+ if (!session.can('model:test', 'platform') || running.value)
17
+ return;
18
+ running.value = true;
19
+ stage.value = 0;
20
+ result.value = null;
21
+ const version = props.model.version, id = props.model.id, chosen = outcome.value;
22
+ timer = setInterval(() => {
23
+ if (stage.value < 2)
24
+ stage.value++;
25
+ else {
26
+ clearInterval(timer);
27
+ timer = undefined;
28
+ running.value = false;
29
+ try {
30
+ store.test(id, version, chosen === 'success');
31
+ result.value = chosen;
32
+ error.value = '';
33
+ }
34
+ catch (e) {
35
+ result.value = null;
36
+ error.value = e.message;
37
+ }
38
+ }
39
+ }, 450);
40
+ }
41
+ function close() { if (timer)
42
+ clearInterval(timer); timer = undefined; emit('close'); }
43
+ onBeforeUnmount(() => { if (timer)
44
+ clearInterval(timer); });
45
+ return { computed, onBeforeUnmount, ref, Alert, Button, Drawer, RadioGroup, Steps, Tag, Space, message, CheckCircleOutlined, CloseCircleOutlined, LoadingOutlined, useModels, useSession, props, emit, store, running, stage, outcome, session, error, result, timer, stages, run, close };
46
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/ModelsPage.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="page-heading"><div><h1>模型管理</h1><p>平台统一接入,按租户、项目与 Agent 分配使用授权。</p></div><template data-component="Button" type="primary" data-bind-disabled="(!session.can('model:edit', 'platform'))" data-on-click="(create)"><template data-component="PlusOutlined"></template>接入模型</template></div><template data-component="Alert" data-if="(!session.readable('model:view', 'platform'))" class="page-alert" type="info" show-icon="" title="当前展示本租户已获授权的模型" description="接入配置由平台维护;使用授权不包含编辑或转授权权限。"></template><template data-component="Alert" data-if="(store.persistenceError)" class="page-alert" type="warning" show-icon="" title="浏览器暂时无法保存演示数据,请保留当前输入后重试。"></template><template data-component="Tabs" data-model-active-key="(tab)" data-bind-items="(tabs)" class="model-tabs"></template><template data-component="ModelTable" data-if="(tab === 'list')" data-on-action="(action)" data-on-create="(create)"></template><template data-component="UsagePanel" data-else-if="(tab === 'usage')"></template><template data-component="AuditPanel" data-else-if="(session.can('model:audit', 'platform'))"></template><template data-component="ModelEditor" data-if="(overlay === 'edit')" data-bind-model="(selected)" data-on-close="(close)" data-on-saved="(saved)"></template><template data-component="ModelDetail" data-if="(overlay === 'detail' &amp;&amp; selected)" data-bind-model="(selected)" data-on-close="(close)" data-on-action="(action)"></template><template data-component="ModelTester" data-if="(overlay === 'test' &amp;&amp; selected)" data-bind-model="(selected)" data-on-close="(close)"></template><template data-component="ModelGrant" data-if="(overlay === 'grant' &amp;&amp; selected)" data-bind-model="(selected)" data-on-close="(close)"></template><template data-component="ModelRelease" data-if="(overlay === 'release' &amp;&amp; selected)" data-bind-model="(selected)" data-on-close="(close)"></template><template data-component="ModelReferences" data-if="((overlay === 'references' || overlay === 'delete') &amp;&amp; selected)" data-bind-model="(selected)" data-bind-deleting="(overlay === 'delete')" data-on-close="(close)"></template><template data-component="Drawer" data-if="(overlay === 'detail' &amp;&amp; !selected)" data-bind-open="(true)" title="模型访问" data-bind-size="(600)" data-on-close="(close)"><template data-component="Result" status="403" title="无法访问此模型" sub-title="记录不存在、已被删除或不在当前授权范围。"><template data-slot="extra"><template data-component="Button" data-on-click="(close)">返回列表</template></template></template></template>
@@ -0,0 +1,52 @@
1
+ import { confirmAction } from "../shell/confirmation.js";
2
+ import { computed, ref, watch } from '../../runtime/state.js';
3
+ import { useRoute, useRouter } from "../../runtime/router.js";
4
+ import { Alert, Button, Tabs, Result, Drawer, message } from "../../runtime/widgets.js";
5
+ import { PlusOutlined } from "../../runtime/icons.js";
6
+ import { useModels } from "./store.js";
7
+ import { useSession } from "../shared/session.js";
8
+ import ModelTable from "./ModelTable.js";
9
+ import ModelEditor from "./ModelEditor.js";
10
+ import ModelDetail from "./ModelDetail.js";
11
+ import ModelTester from "./ModelTester.js";
12
+ import ModelGrant from "./ModelGrant.js";
13
+ import ModelRelease from "./ModelRelease.js";
14
+ import ModelReferences from "./ModelReferences.js";
15
+ import UsagePanel from "./UsagePanel.js";
16
+ import AuditPanel from "./AuditPanel.js";
17
+ import { createComponent } from '../../runtime/dom.js';
18
+ export default createComponent({ name: 'ModelsPage', propKeys: [], template: new URL('./ModelsPage.html', import.meta.url).href, setup(__props, __emit) {
19
+ const store = useModels(), session = useSession(), route = useRoute(), router = useRouter(), tab = ref('list'), selectedId = ref(null);
20
+ const overlay = ref(null), selected = computed(() => store.models.find(m => m.id === selectedId.value));
21
+ const tabs = computed(() => [{ key: 'list', label: '模型列表' }, { key: 'usage', label: '用量概览' }, ...(session.can('model:audit', 'platform') ? [{ key: 'audit', label: '操作记录' }] : [])]);
22
+ function close() { overlay.value = null; selectedId.value = null; if (route.query.model)
23
+ router.replace('/models'); }
24
+ watch(() => session.actorId, () => { close(); tab.value = 'list'; });
25
+ watch(() => route.query.model, id => { if (typeof id === 'string') {
26
+ selectedId.value = id;
27
+ overlay.value = 'detail';
28
+ } }, { immediate: true });
29
+ function create() { if (session.can('model:edit', 'platform')) {
30
+ selectedId.value = null;
31
+ overlay.value = 'edit';
32
+ } }
33
+ function action(name, model) {
34
+ selectedId.value = model.id;
35
+ if (name === 'toggle') {
36
+ confirmAction({ title: model.enabled ? '停用' + model.name : '启用' + model.name, content: model.enabled ? '停用后阻止新调用。当前生效版本与历史记录保留;在途任务策略仍待运行契约验证。' : '启用已发布的配置。草稿保存或测试成功不能替代发布。', okText: model.enabled ? '确认停用' : '确认启用', cancelText: '取消', okButtonProps: { danger: model.enabled }, onOk: () => { try {
37
+ store.toggle(model.id, model.recordVersion);
38
+ message.success('状态已更新(演示)');
39
+ }
40
+ catch (e) {
41
+ message.error(e.message);
42
+ return Promise.reject(e);
43
+ } } });
44
+ return;
45
+ }
46
+ overlay.value = name;
47
+ if (name === 'detail')
48
+ router.replace({ path: '/models', query: { model: model.id } });
49
+ }
50
+ function saved(id) { selectedId.value = id; overlay.value = 'detail'; message.success('草稿已保存,当前生效版本保持不变'); }
51
+ return { confirmAction, computed, ref, watch, useRoute, useRouter, Alert, Button, Tabs, Result, Drawer, message, PlusOutlined, useModels, useSession, ModelTable, ModelEditor, ModelDetail, ModelTester, ModelGrant, ModelRelease, ModelReferences, UsagePanel, AuditPanel, store, session, route, router, tab, selectedId, overlay, selected, tabs, close, create, action, saved };
52
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/RowActions.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="row-actions"><template data-component="Button" type="text" class="link-button" data-bind-disabled="(!session.can('model:test', 'platform') || model.publishState === 'review')" data-bind-aria-label="('测试' + model.name)" data-on-click="(emit('action', 'test', model))">测试</template><template data-component="ListMore" data-bind-name="(model.name)" data-bind-items="(items)" data-on-action="(emit('action', $event, model))"></template></div>
@@ -0,0 +1,19 @@
1
+ import { computed } from '../../runtime/state.js';
2
+ import { Button } from "../../runtime/widgets.js";
3
+ import ListMore from "../shared/ListMore.js";
4
+ import { useSession } from "../shared/session.js";
5
+ import { createComponent } from '../../runtime/dom.js';
6
+ export default createComponent({ name: 'RowActions', propKeys: ["model"], template: new URL('./RowActions.html', import.meta.url).href, setup(__props, __emit) {
7
+ const props = __props, emit = __emit, session = useSession();
8
+ const items = computed(() => [
9
+ { key: 'detail', label: '查看详情' },
10
+ { key: 'edit', label: '编辑配置', disabled: !session.can('model:edit', 'platform') || props.model.publishState === 'review' },
11
+ { key: 'release', label: props.model.publishState === 'review' ? '查看发布申请' : '配置发布', disabled: !session.readable('model:view', 'platform') },
12
+ { key: 'grant', label: '使用授权', disabled: !session.can('model:grant', 'platform') },
13
+ { key: 'references', label: '资源引用', disabled: !session.readable('model:view', 'platform') },
14
+ { type: 'divider' },
15
+ { key: 'toggle', label: props.model.enabled ? '停用模型' : '启用模型', disabled: !session.can('model:status', 'platform') },
16
+ { key: 'delete', label: '删除模型', danger: true, disabled: !session.can('model:delete', 'platform') },
17
+ ]);
18
+ return { computed, Button, ListMore, useSession, props, emit, session, items };
19
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/models/UsagePanel.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <section class="panel usage-panel"><div class="section-heading"><h2>模型用量</h2><div class="usage-filters"><template data-component="Select" data-model-value="(period)" aria-label="用量周期" data-bind-options="([{ label: '最近 7 天', value: 7 }, { label: '最近 30 天', value: 30 }])"></template><template data-component="Select" data-model-value="(project)" aria-label="用量项目" data-bind-options="([{ label: '全部项目', value: 'all' }, ...projects.map(p =&gt; ({ label: p, value: p }))])"></template></div></div><template data-component="Alert" type="info" show-icon="" title="演示用量与价格,仅用于确认展示口径;不代表真实账单。"></template><div class="usage-metrics"><div><span>Token 总量</span><strong>{{ (fmtNumber(totals.tokens)) }}</strong><small>输入 + 输出</small></div><div><span>模型调用</span><strong>{{ (fmtNumber(totals.requests)) }}</strong><small>次 · 所选周期</small></div><div><span>估算费用</span><strong>{{ (money(totals.cost)) }}</strong><small>人民币 · 按演示单价计算</small></div></div><template data-component="ProTable" data-bind-table="(table)" data-bind-table-container="(false)" data-bind-control="(false)" row-key="id" data-bind-scroll="({ x: 780 })" data-bind-pagination="({ showTotal: (t) =&gt; `共 ${t} 条`, hideOnSinglePage: false })"></template><p class="muted">估算公式:输入 Token × 输入单价 + 输出 Token × 输出单价;单价以每百万 Token 计。</p></section>
@@ -0,0 +1,30 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { h } from '../../runtime/dom.js';
3
+ import { Alert, Select } from "../../runtime/widgets.js";
4
+ import { ProTable, useTable } from "../../runtime/widgets.js";
5
+ import { fmtNumber } from "./data.js";
6
+ import { useModels } from "./store.js";
7
+ import { createComponent } from '../../runtime/dom.js';
8
+ export default createComponent({ name: 'UsagePanel', propKeys: [], template: new URL('./UsagePanel.html', import.meta.url).href, setup(__props, __emit) {
9
+ const store = useModels(), period = ref(7), project = ref('all');
10
+ const projects = computed(() => [...new Set(store.models.flatMap(m => m.projects))]);
11
+ const rows = computed(() => store.models.map(m => {
12
+ const i = Number(m.id.replace('demo-', '')) - 1;
13
+ const included = project.value === 'all' || m.projects.includes(project.value);
14
+ const factor = (period.value === 7 ? 1 : 4) * (project.value === 'all' ? Math.max(1, m.projects.length) : 1);
15
+ const requests = m.id.startsWith('demo-') && m.projects.length && included ? (680 + (5 - i) * 147) * factor : 0;
16
+ const input = requests * 1120, output = m.kind === 'embedding' ? 0 : requests * 360;
17
+ return { id: m.id, name: m.name, requests, input, output, cost: (input * m.inputPrice + output * m.outputPrice) / 1000000 };
18
+ }).filter(r => project.value === 'all' || r.requests > 0));
19
+ const totals = computed(() => rows.value.reduce((a, x) => ({ tokens: a.tokens + x.input + x.output, requests: a.requests + x.requests, cost: a.cost + x.cost }), { tokens: 0, requests: 0, cost: 0 }));
20
+ const money = (n) => `¥${n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
21
+ const table = useTable({ columns: [
22
+ { title: '模型', dataIndex: 'name', width: 210 },
23
+ { title: '调用次数', dataIndex: 'requests', align: 'right', render: (text) => fmtNumber(Number(text)) },
24
+ { title: '输入 Token', dataIndex: 'input', align: 'right', render: (text) => fmtNumber(Number(text)) },
25
+ { title: '输出 Token', dataIndex: 'output', align: 'right', render: (text) => fmtNumber(Number(text)) },
26
+ { title: '估算费用(元)', dataIndex: 'cost', align: 'right', width: 180, render: (text) => h('strong', money(Number(text))) },
27
+ ] });
28
+ watch(rows, () => { table.dataSource.value = rows.value; table.setPageParam({ total: rows.value.length }); }, { immediate: true });
29
+ return { computed, ref, watch, h, Alert, Select, ProTable, useTable, fmtNumber, useModels, store, period, project, projects, rows, totals, money, table };
30
+ } });