@xgent-ai/skills 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1043) hide show
  1. package/README.md +124 -4
  2. package/bin/xgent-skills.js +561 -4
  3. package/package.json +7 -3
  4. package/skills/agi-mode/SKILL.md +225 -0
  5. package/skills/agi-mode/evals/baseline-coverage.md +96 -0
  6. package/skills/agi-mode/evals/scenarios.md +331 -0
  7. package/skills/agi-mode/evals/test_check_evidence.py +141 -0
  8. package/skills/agi-mode/playbooks/arena.md +47 -0
  9. package/skills/agi-mode/playbooks/authoring-a-skill.md +26 -0
  10. package/skills/agi-mode/playbooks/autonomous-run.md +39 -0
  11. package/skills/agi-mode/playbooks/bug-fix.md +27 -0
  12. package/skills/agi-mode/playbooks/design-prototype.md +41 -0
  13. package/skills/agi-mode/playbooks/eval.md +72 -0
  14. package/skills/agi-mode/playbooks/feature.md +26 -0
  15. package/skills/agi-mode/playbooks/forensics.md +31 -0
  16. package/skills/agi-mode/playbooks/hillclimb.md +73 -0
  17. package/skills/agi-mode/playbooks/investigation.md +29 -0
  18. package/skills/agi-mode/playbooks/migration-refactoring.md +27 -0
  19. package/skills/agi-mode/playbooks/optimization.md +27 -0
  20. package/skills/agi-mode/playbooks/pr-lifecycle.md +38 -0
  21. package/skills/agi-mode/playbooks/program.md +57 -0
  22. package/skills/agi-mode/playbooks/reflection.md +41 -0
  23. package/skills/agi-mode/playbooks/resource-cleanup.md +24 -0
  24. package/skills/agi-mode/playbooks/review.md +27 -0
  25. package/skills/agi-mode/playbooks/session-handoff.md +37 -0
  26. package/skills/agi-mode/playbooks/shipping.md +35 -0
  27. package/skills/agi-mode/playbooks/ui-delivery.md +34 -0
  28. package/skills/agi-mode/playbooks/unblock.md +54 -0
  29. package/skills/agi-mode/principles/autonomous-decisions.md +21 -0
  30. package/skills/agi-mode/principles/behavioral-tests.md +21 -0
  31. package/skills/agi-mode/principles/boundary-discipline.md +21 -0
  32. package/skills/agi-mode/principles/bounded-convergence.md +21 -0
  33. package/skills/agi-mode/principles/build-leverage.md +21 -0
  34. package/skills/agi-mode/principles/challenge-premises.md +21 -0
  35. package/skills/agi-mode/principles/complete-migrations.md +21 -0
  36. package/skills/agi-mode/principles/context-as-state.md +21 -0
  37. package/skills/agi-mode/principles/critical-path-throughput.md +21 -0
  38. package/skills/agi-mode/principles/domain-models-and-types.md +23 -0
  39. package/skills/agi-mode/principles/evidence-lifetime.md +21 -0
  40. package/skills/agi-mode/principles/experience-first.md +21 -0
  41. package/skills/agi-mode/principles/explore-alternatives.md +21 -0
  42. package/skills/agi-mode/principles/falsifiable-verification.md +21 -0
  43. package/skills/agi-mode/principles/foundations-first.md +21 -0
  44. package/skills/agi-mode/principles/idempotent-effects.md +21 -0
  45. package/skills/agi-mode/principles/information-first.md +21 -0
  46. package/skills/agi-mode/principles/minimize-complexity.md +21 -0
  47. package/skills/agi-mode/principles/outcome-ownership.md +21 -0
  48. package/skills/agi-mode/principles/prove-real-outcomes.md +21 -0
  49. package/skills/agi-mode/principles/redesign-from-constraints.md +21 -0
  50. package/skills/agi-mode/principles/root-cause.md +21 -0
  51. package/skills/agi-mode/principles/state-ownership.md +21 -0
  52. package/skills/agi-mode/principles/structural-learning.md +21 -0
  53. package/skills/agi-mode/principles/verifiable-units.md +21 -0
  54. package/skills/agi-mode/references/continuity.md +75 -0
  55. package/skills/agi-mode/references/eval-protocol.md +71 -0
  56. package/skills/agi-mode/references/evidence-contract.md +57 -0
  57. package/skills/agi-mode/references/evolution-evidence.md +71 -0
  58. package/skills/agi-mode/references/experiments.md +82 -0
  59. package/skills/agi-mode/references/reflection/divergent-reviewer.md +45 -0
  60. package/skills/agi-mode/references/reflection/judgment-reviewer.md +44 -0
  61. package/skills/agi-mode/references/reflection/synthesizer.md +39 -0
  62. package/skills/agi-mode/references/reflection/tooling-reviewer.md +57 -0
  63. package/skills/agi-mode/references/skill-evolution.md +50 -0
  64. package/skills/agi-mode/scripts/check_evidence.py +147 -0
  65. package/skills/apply-code-review/SKILL.md +53 -0
  66. package/skills/apply-code-review/agents/openai.yaml +4 -0
  67. package/skills/apply-code-review/references/record-contract.md +77 -0
  68. package/skills/apply-doc-review/SKILL.md +79 -0
  69. package/skills/apply-doc-review/agents/openai.yaml +4 -0
  70. package/skills/apply-doc-review/references/disposition-contract.md +57 -0
  71. package/skills/archify/LICENSE +22 -0
  72. package/skills/archify/SKILL.md +137 -0
  73. package/skills/archify/THIRD_PARTY_NOTICES.md +69 -0
  74. package/skills/archify/assets/JetBrainsMono-OFL.txt +93 -0
  75. package/skills/archify/assets/template.html +14937 -0
  76. package/skills/archify/bin/archify.mjs +2139 -0
  77. package/skills/archify/bin/open-artifact.mjs +86 -0
  78. package/skills/archify/bin/preview.mjs +653 -0
  79. package/skills/archify/bin/visual-check.mjs +829 -0
  80. package/skills/archify/brand-marks/README.md +31 -0
  81. package/skills/archify/brand-marks/catalog.json +131 -0
  82. package/skills/archify/delta/architecture-delta.mjs +1232 -0
  83. package/skills/archify/examples/agent-run.lifecycle.json +60 -0
  84. package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
  85. package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
  86. package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
  87. package/skills/archify/examples/cache-miss-request.sequence.json +82 -0
  88. package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
  89. package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
  90. package/skills/archify/examples/dataflow-product-analytics.html +15048 -0
  91. package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
  92. package/skills/archify/examples/event-stream.dataflow.json +57 -0
  93. package/skills/archify/examples/incident-response.workflow.json +64 -0
  94. package/skills/archify/examples/lifecycle-agent-run.html +14983 -0
  95. package/skills/archify/examples/product-analytics.dataflow.json +76 -0
  96. package/skills/archify/examples/production-deployment.architecture.json +71 -0
  97. package/skills/archify/examples/release-delivery.workflow.json +62 -0
  98. package/skills/archify/examples/sequence-cache-miss-request.html +15063 -0
  99. package/skills/archify/examples/web-app-rendered.html +15012 -0
  100. package/skills/archify/examples/web-app.architecture.json +46 -0
  101. package/skills/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
  102. package/skills/archify/migrations/workflow-v2.mjs +279 -0
  103. package/skills/archify/package-lock.json +149 -0
  104. package/skills/archify/package.json +39 -0
  105. package/skills/archify/recipes/scenarios.mjs +391 -0
  106. package/skills/archify/references/authoring-contract.md +247 -0
  107. package/skills/archify/references/brand-marks.md +65 -0
  108. package/skills/archify/references/delivery-contract.md +138 -0
  109. package/skills/archify/references/viewer-runtime.md +45 -0
  110. package/skills/archify/renderers/architecture/grid.mjs +62 -0
  111. package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
  112. package/skills/archify/renderers/dataflow/README.md +104 -0
  113. package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  114. package/skills/archify/renderers/lifecycle/README.md +115 -0
  115. package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  116. package/skills/archify/renderers/sequence/README.md +114 -0
  117. package/skills/archify/renderers/sequence/render-sequence.mjs +464 -0
  118. package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
  119. package/skills/archify/renderers/shared/cli.mjs +218 -0
  120. package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
  121. package/skills/archify/renderers/shared/diagnostics.mjs +160 -0
  122. package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
  123. package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  124. package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
  125. package/skills/archify/renderers/shared/geometry.mjs +1423 -0
  126. package/skills/archify/renderers/shared/i18n.mjs +595 -0
  127. package/skills/archify/renderers/shared/layout-report.mjs +40 -0
  128. package/skills/archify/renderers/shared/legend.mjs +217 -0
  129. package/skills/archify/renderers/shared/output-path.mjs +340 -0
  130. package/skills/archify/renderers/shared/repository-evidence.mjs +239 -0
  131. package/skills/archify/renderers/shared/repository-location.mjs +58 -0
  132. package/skills/archify/renderers/shared/text-fit.mjs +49 -0
  133. package/skills/archify/renderers/shared/utils.mjs +232 -0
  134. package/skills/archify/renderers/shared/validator.mjs +86 -0
  135. package/skills/archify/renderers/workflow/README.md +223 -0
  136. package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
  137. package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  138. package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  139. package/skills/archify/schemas/README.md +211 -0
  140. package/skills/archify/schemas/architecture.schema.json +178 -0
  141. package/skills/archify/schemas/common.schema.json +115 -0
  142. package/skills/archify/schemas/dataflow.schema.json +243 -0
  143. package/skills/archify/schemas/lifecycle.schema.json +266 -0
  144. package/skills/archify/schemas/sequence.schema.json +223 -0
  145. package/skills/archify/schemas/workflow.schema.json +428 -0
  146. package/skills/archify/scripts/check-render-output.mjs +916 -0
  147. package/skills/archify/scripts/check-update.mjs +1667 -0
  148. package/skills/archify/scripts/generate-brand-marks.mjs +141 -0
  149. package/skills/archify/scripts/generate-validators.mjs +66 -0
  150. package/skills/archify/scripts/render-examples.mjs +26 -0
  151. package/skills/archify/scripts/update-contract.mjs +182 -0
  152. package/skills/archify/skill-release.json +10 -0
  153. package/skills/archify/test/adaptive-reader-layout.test.mjs +86 -0
  154. package/skills/archify/test/animation.test.mjs +179 -0
  155. package/skills/archify/test/architecture-compare-recovery.test.mjs +157 -0
  156. package/skills/archify/test/architecture-delta-markers.test.mjs +137 -0
  157. package/skills/archify/test/architecture-delta.test.mjs +705 -0
  158. package/skills/archify/test/artifact-receipt-flush.test.mjs +126 -0
  159. package/skills/archify/test/authored-reachability.test.mjs +95 -0
  160. package/skills/archify/test/authoring-safety-contract.test.mjs +54 -0
  161. package/skills/archify/test/automatic-port-spread.test.mjs +376 -0
  162. package/skills/archify/test/base-input-compatibility.test.mjs +42 -0
  163. package/skills/archify/test/brand-marks.test.mjs +678 -0
  164. package/skills/archify/test/chapter-delta-preview.test.mjs +157 -0
  165. package/skills/archify/test/chapter-handoff.test.mjs +97 -0
  166. package/skills/archify/test/chapter-rail.test.mjs +86 -0
  167. package/skills/archify/test/checkout-line-endings.test.mjs +72 -0
  168. package/skills/archify/test/ci-scope.test.mjs +59 -0
  169. package/skills/archify/test/clean-skill-staging.test.mjs +440 -0
  170. package/skills/archify/test/cli-output-types.test.mjs +201 -0
  171. package/skills/archify/test/cli.test.mjs +986 -0
  172. package/skills/archify/test/community-proof-intake.test.mjs +125 -0
  173. package/skills/archify/test/cursor-onboarding.test.mjs +74 -0
  174. package/skills/archify/test/degraded.test.mjs +161 -0
  175. package/skills/archify/test/delivery-contract.test.mjs +52 -0
  176. package/skills/archify/test/desktop-reader-browser.test.mjs +80 -0
  177. package/skills/archify/test/diagram-guide.test.mjs +92 -0
  178. package/skills/archify/test/engineering-profile.test.mjs +209 -0
  179. package/skills/archify/test/export-browser.test.mjs +305 -0
  180. package/skills/archify/test/export-cleanup-browser.test.mjs +294 -0
  181. package/skills/archify/test/finder-browser.test.mjs +274 -0
  182. package/skills/archify/test/finder.test.mjs +104 -0
  183. package/skills/archify/test/fixtures/automatic-routing-node-border-clearance.workflow.json +40 -0
  184. package/skills/archify/test/fixtures/fail-migration-cleanup.mjs +17 -0
  185. package/skills/archify/test/fixtures/issue-126/custom-widths.workflow.json +18 -0
  186. package/skills/archify/test/fixtures/issue-126/explicit-route.workflow.json +28 -0
  187. package/skills/archify/test/fixtures/issue-126/explicit-viewbox.workflow.json +19 -0
  188. package/skills/archify/test/fixtures/issue-126/labels.workflow.json +18 -0
  189. package/skills/archify/test/fixtures/v1-baseline/agent-run.lifecycle.json +64 -0
  190. package/skills/archify/test/fixtures/v1-baseline/agent-tool-call.workflow.json +88 -0
  191. package/skills/archify/test/fixtures/v1-baseline/cache-miss-request.sequence.json +75 -0
  192. package/skills/archify/test/fixtures/v1-baseline/event-stream.dataflow.json +57 -0
  193. package/skills/archify/test/fixtures/v1-baseline/product-analytics.dataflow.json +70 -0
  194. package/skills/archify/test/fixtures/v1-baseline/production-deployment.architecture.json +71 -0
  195. package/skills/archify/test/fixtures/v1-baseline/web-app.architecture.json +41 -0
  196. package/skills/archify/test/fixtures/v1-workflow-700x400.workflow.json +22 -0
  197. package/skills/archify/test/fixtures/v1-workflow-explicit-coordinates.workflow.json +47 -0
  198. package/skills/archify/test/focus-browser.test.mjs +226 -0
  199. package/skills/archify/test/gallery.test.mjs +130 -0
  200. package/skills/archify/test/generate-validators.test.mjs +59 -0
  201. package/skills/archify/test/generate-viewer.test.mjs +165 -0
  202. package/skills/archify/test/generated-artifact-xml.test.mjs +88 -0
  203. package/skills/archify/test/geometry.test.mjs +739 -0
  204. package/skills/archify/test/golden.mjs +207 -0
  205. package/skills/archify/test/grid.test.mjs +47 -0
  206. package/skills/archify/test/guide-page.test.mjs +85 -0
  207. package/skills/archify/test/guide.test.mjs +81 -0
  208. package/skills/archify/test/guided-views-browser.test.mjs +460 -0
  209. package/skills/archify/test/guided-views.test.mjs +144 -0
  210. package/skills/archify/test/helpers/desktop-browser.mjs +48 -0
  211. package/skills/archify/test/helpers/offline-fonts.mjs +76 -0
  212. package/skills/archify/test/helpers/viewer-click.mjs +72 -0
  213. package/skills/archify/test/helpers/xml.mjs +37 -0
  214. package/skills/archify/test/i18n.test.mjs +422 -0
  215. package/skills/archify/test/intent-trace-browser.test.mjs +284 -0
  216. package/skills/archify/test/intent-trace.test.mjs +111 -0
  217. package/skills/archify/test/landing.test.mjs +97 -0
  218. package/skills/archify/test/layout-rules.test.mjs +1498 -0
  219. package/skills/archify/test/legend-contract.test.mjs +404 -0
  220. package/skills/archify/test/motion-governor-browser.test.mjs +342 -0
  221. package/skills/archify/test/motion-governor.test.mjs +111 -0
  222. package/skills/archify/test/offline-font-browser.test.mjs +210 -0
  223. package/skills/archify/test/offline-self-containment.test.mjs +80 -0
  224. package/skills/archify/test/open-artifact.test.mjs +118 -0
  225. package/skills/archify/test/ordinary-model-floor.test.mjs +1052 -0
  226. package/skills/archify/test/output-path.test.mjs +587 -0
  227. package/skills/archify/test/presentation.test.mjs +71 -0
  228. package/skills/archify/test/preset-tryon.test.mjs +113 -0
  229. package/skills/archify/test/preview-contract.test.mjs +40 -0
  230. package/skills/archify/test/preview.test.mjs +530 -0
  231. package/skills/archify/test/proof-aperture.test.mjs +78 -0
  232. package/skills/archify/test/reach-share-card.test.mjs +149 -0
  233. package/skills/archify/test/reader-layout-browser.test.mjs +320 -0
  234. package/skills/archify/test/readme-showcase.test.mjs +319 -0
  235. package/skills/archify/test/real-repository-proof.test.mjs +209 -0
  236. package/skills/archify/test/relationship-direct-explorer.test.mjs +115 -0
  237. package/skills/archify/test/relationship-lens.test.mjs +128 -0
  238. package/skills/archify/test/relationship-permalink.test.mjs +130 -0
  239. package/skills/archify/test/relationship-pulse.test.mjs +122 -0
  240. package/skills/archify/test/release-identity.test.mjs +476 -0
  241. package/skills/archify/test/release-package-gates.test.mjs +750 -0
  242. package/skills/archify/test/render-output-checks.test.mjs +588 -0
  243. package/skills/archify/test/renderer-diagnostic-boundary.test.mjs +107 -0
  244. package/skills/archify/test/repair-receipt.test.mjs +181 -0
  245. package/skills/archify/test/repository-evidence-replacement.test.mjs +136 -0
  246. package/skills/archify/test/repository-evidence.test.mjs +605 -0
  247. package/skills/archify/test/repository-language-metadata.test.mjs +67 -0
  248. package/skills/archify/test/route-journey.test.mjs +125 -0
  249. package/skills/archify/test/route-probe-browser.test.mjs +363 -0
  250. package/skills/archify/test/route-probe.test.mjs +114 -0
  251. package/skills/archify/test/route-share-card.test.mjs +163 -0
  252. package/skills/archify/test/semantic-camera.test.mjs +88 -0
  253. package/skills/archify/test/semantic-flow.test.mjs +90 -0
  254. package/skills/archify/test/semantic-legend-gateway.test.mjs +156 -0
  255. package/skills/archify/test/semantic-lens-browser.test.mjs +372 -0
  256. package/skills/archify/test/semantic-lens.test.mjs +103 -0
  257. package/skills/archify/test/semantic-passport.test.mjs +99 -0
  258. package/skills/archify/test/semantic-radar.test.mjs +735 -0
  259. package/skills/archify/test/semantic-zoom.test.mjs +86 -0
  260. package/skills/archify/test/sequence-column-fit.test.mjs +137 -0
  261. package/skills/archify/test/settled-flow.test.mjs +97 -0
  262. package/skills/archify/test/share-card-export.test.mjs +132 -0
  263. package/skills/archify/test/site-language-continuity.test.mjs +569 -0
  264. package/skills/archify/test/site-language-integration.mjs +9 -0
  265. package/skills/archify/test/skill-metadata.test.mjs +84 -0
  266. package/skills/archify/test/stable-update-manifest.test.mjs +167 -0
  267. package/skills/archify/test/start-page.test.mjs +312 -0
  268. package/skills/archify/test/story-beat-navigator.test.mjs +103 -0
  269. package/skills/archify/test/story-carrier.test.mjs +90 -0
  270. package/skills/archify/test/story-director-strip.test.mjs +91 -0
  271. package/skills/archify/test/story-follow-camera.test.mjs +103 -0
  272. package/skills/archify/test/story-horizon.test.mjs +91 -0
  273. package/skills/archify/test/story-moment-link.test.mjs +93 -0
  274. package/skills/archify/test/story-shelf.test.mjs +84 -0
  275. package/skills/archify/test/story-trail.test.mjs +81 -0
  276. package/skills/archify/test/toolbar-polish.test.mjs +57 -0
  277. package/skills/archify/test/update-contract.test.mjs +133 -0
  278. package/skills/archify/test/update-notifier.test.mjs +3317 -0
  279. package/skills/archify/test/v1-compatibility.test.mjs +329 -0
  280. package/skills/archify/test/vertical-edge.test.mjs +68 -0
  281. package/skills/archify/test/viewer-camera-browser.test.mjs +395 -0
  282. package/skills/archify/test/viewer-chrome-layout.test.mjs +1104 -0
  283. package/skills/archify/test/viewer-identifiers-browser.test.mjs +135 -0
  284. package/skills/archify/test/visual-check.test.mjs +400 -0
  285. package/skills/archify/test/webm-artifact.smoke.mjs +1855 -0
  286. package/skills/archify/test/workflow-compiler-hard-contract.test.mjs +2136 -0
  287. package/skills/archify/test/workflow-compiler.test.mjs +1163 -0
  288. package/skills/archify/test/workflow-migration.test.mjs +620 -0
  289. package/skills/archify/test/workflow-semantic-contract.test.mjs +131 -0
  290. package/skills/architect/SKILL.md +83 -0
  291. package/skills/architect/references/design-red-flags.md +33 -0
  292. package/skills/architect/references/rationale-template.md +35 -0
  293. package/skills/architect/references/runner-prompt.md +20 -0
  294. package/skills/arena/SKILL.md +13 -0
  295. package/skills/automate-me/SKILL.md +104 -0
  296. package/skills/autoresearch/SKILL.md +14 -0
  297. package/skills/debugging/SKILL.md +279 -0
  298. package/skills/dev-plan/SKILL.md +117 -92
  299. package/skills/dev-plan/references/architecture-quality.md +141 -0
  300. package/skills/dev-plan/references/execution-workflow.md +25 -0
  301. package/skills/dev-plan/references/plan-skeleton.md +252 -77
  302. package/skills/dev-plan/scripts/check_progress.sh +162 -0
  303. package/skills/documentation-writer/SKILL.md +204 -0
  304. package/skills/documentation-writer/assets/templates/ARCHITECTURE.md +49 -0
  305. package/skills/documentation-writer/assets/templates/CONCERNS.md +56 -0
  306. package/skills/documentation-writer/assets/templates/CONVENTIONS.md +52 -0
  307. package/skills/documentation-writer/assets/templates/FEATURES.md +43 -0
  308. package/skills/documentation-writer/assets/templates/INTEGRATIONS.md +48 -0
  309. package/skills/documentation-writer/assets/templates/STACK.md +56 -0
  310. package/skills/documentation-writer/assets/templates/STRUCTURE.md +44 -0
  311. package/skills/documentation-writer/assets/templates/TESTING.md +57 -0
  312. package/skills/documentation-writer/references/api-docs.md +185 -0
  313. package/skills/documentation-writer/references/architecture.md +134 -0
  314. package/skills/documentation-writer/references/codebase-map.md +113 -0
  315. package/skills/documentation-writer/references/inquiry-checkpoints.md +78 -0
  316. package/skills/documentation-writer/references/readme.md +89 -0
  317. package/skills/documentation-writer/references/stack-detection.md +134 -0
  318. package/skills/documentation-writer/references/user-manual.md +103 -0
  319. package/skills/documentation-writer/references/writing-style.md +220 -0
  320. package/skills/documentation-writer/scripts/check_doc.py +273 -0
  321. package/skills/documentation-writer/scripts/scan.py +712 -0
  322. package/skills/elintp/SKILL.md +155 -0
  323. package/skills/figure-it-out/SKILL.md +53 -0
  324. package/skills/gdpr-compliant/SKILL.md +283 -0
  325. package/skills/gdpr-compliant/references/Security.md +266 -0
  326. package/skills/gdpr-compliant/references/data-rights.md +177 -0
  327. package/skills/how/SKILL.md +58 -0
  328. package/skills/how/references/explainer-prompt.md +55 -0
  329. package/skills/how/references/explorer-prompt.md +52 -0
  330. package/skills/humanize-writing/SKILL.md +417 -0
  331. package/skills/humanize-writing/references/ai-tells.md +291 -0
  332. package/skills/kpi-dashboard-design/SKILL.md +103 -0
  333. package/skills/landing-page-conversion-audit/SKILL.md +122 -0
  334. package/skills/meeting-minutes/SKILL.md +235 -0
  335. package/skills/pardon/SKILL.md +30 -0
  336. package/skills/portal-app-exchange/SKILL.md +97 -0
  337. package/skills/portal-dev-setup/SKILL.md +610 -0
  338. package/skills/portal-dev-setup/puller.env.example +75 -0
  339. package/skills/portal-dev-setup/references/kafka.md +140 -0
  340. package/skills/portal-dev-setup/references/troubleshooting.md +163 -0
  341. package/skills/portal-dev-setup/scripts/onebox.sh +1420 -0
  342. package/skills/portal-external-app/SKILL.md +309 -0
  343. package/skills/portal-external-app/references/contract-doc-template.md +96 -0
  344. package/skills/portal-external-app/references/health-contract.md +80 -0
  345. package/skills/portal-external-app/references/integration-contract.md +130 -0
  346. package/skills/portal-external-app/references/public-entrypoints.md +100 -0
  347. package/skills/portal-external-app/references/quota-and-seats.md +194 -0
  348. package/skills/portal-external-app/references/registration-and-onebox.md +315 -0
  349. package/skills/portal-external-app/scripts/health-verdict.ts +22 -0
  350. package/skills/portal-external-app/scripts/verify-health.ts +27 -0
  351. package/skills/portal-logging/SKILL.md +139 -0
  352. package/skills/portal-logging/references/collectors.md +285 -0
  353. package/skills/portal-logging/references/contract.md +95 -0
  354. package/skills/portal-logging/scripts/smoke-ingest.sh +72 -0
  355. package/skills/portal-micro-app/SKILL.md +73 -0
  356. package/skills/portal-micro-app/references/manifest-and-acl.md +97 -0
  357. package/skills/portal-micro-app/references/open-api-and-extensions.md +86 -0
  358. package/skills/portal-micro-app/references/sdk-reference.md +208 -0
  359. package/skills/prd/SKILL.md +230 -0
  360. package/skills/prd/references/prd-skeleton.md +282 -0
  361. package/skills/prd/references/product-quality.md +89 -0
  362. package/skills/prd/references/spms-mapping.md +150 -0
  363. package/skills/react/SKILL.md +125 -0
  364. package/skills/react/references/actions.md +251 -0
  365. package/skills/react/references/component-patterns.md +275 -0
  366. package/skills/react/references/data-fetching.md +279 -0
  367. package/skills/react/references/effect-patterns.md +407 -0
  368. package/skills/react/references/js-performance.md +432 -0
  369. package/skills/react/references/react19-migration.md +407 -0
  370. package/skills/react/references/rendering-performance.md +351 -0
  371. package/skills/react/references/rerender-optimization.md +578 -0
  372. package/skills/reflect/SKILL.md +13 -0
  373. package/skills/review-code/SKILL.md +63 -0
  374. package/skills/review-code/agents/openai.yaml +4 -0
  375. package/skills/review-code/references/git-scopes.md +38 -0
  376. package/skills/review-code/references/report-contract.md +56 -0
  377. package/skills/review-code/references/review-lenses.md +33 -0
  378. package/skills/review-dev-plan/SKILL.md +88 -0
  379. package/skills/review-dev-plan/agents/openai.yaml +4 -0
  380. package/skills/review-dev-plan/references/report-contract.md +59 -0
  381. package/skills/review-dev-plan/references/review-lenses.md +82 -0
  382. package/skills/review-prd/SKILL.md +84 -0
  383. package/skills/review-prd/agents/openai.yaml +4 -0
  384. package/skills/review-prd/references/report-contract.md +64 -0
  385. package/skills/review-prd/references/review-lenses.md +82 -0
  386. package/skills/review-prd-dev-gaps/SKILL.md +84 -0
  387. package/skills/review-prd-dev-gaps/agents/openai.yaml +4 -0
  388. package/skills/review-prd-dev-gaps/references/report-contract.md +72 -0
  389. package/skills/rust/SKILL.md +103 -0
  390. package/skills/rust/references/chapter_01.md +564 -0
  391. package/skills/rust/references/chapter_02.md +117 -0
  392. package/skills/rust/references/chapter_03.md +209 -0
  393. package/skills/rust/references/chapter_04.md +183 -0
  394. package/skills/rust/references/chapter_05.md +390 -0
  395. package/skills/rust/references/chapter_06.md +142 -0
  396. package/skills/rust/references/chapter_07.md +226 -0
  397. package/skills/rust/references/chapter_08.md +257 -0
  398. package/skills/rust/references/chapter_09.md +261 -0
  399. package/skills/rust/references/chapter_10.md +554 -0
  400. package/skills/security-audit/SKILL.md +191 -0
  401. package/skills/security-audit/references/language-patterns.md +221 -0
  402. package/skills/security-audit/references/report-format.md +194 -0
  403. package/skills/security-audit/references/secret-patterns.md +178 -0
  404. package/skills/security-audit/references/vuln-categories.md +288 -0
  405. package/skills/security-audit/references/vulnerable-packages.md +111 -0
  406. package/skills/sql-optimization/SKILL.md +296 -0
  407. package/skills/story-points/SKILL.md +219 -0
  408. package/skills/story-points/references/factors.md +367 -0
  409. package/skills/summarize/SKILL.md +80 -0
  410. package/skills/swarm/SKILL.md +263 -0
  411. package/skills/swarm/evals/evals.json +55 -0
  412. package/skills/swarm/references/agent-types.md +260 -0
  413. package/skills/swarm/references/teams/code-audit.md +81 -0
  414. package/skills/swarm/references/teams/debug-race.md +70 -0
  415. package/skills/swarm/references/teams/feature-dev.md +71 -0
  416. package/skills/swarm/references/teams/product.md +114 -0
  417. package/skills/swarm/references/teams/refactor-migration.md +73 -0
  418. package/skills/swarm/references/teams/research-debate.md +73 -0
  419. package/skills/tdd/SKILL.md +42 -0
  420. package/skills/teach/SKILL.md +21 -0
  421. package/skills/test-plan/SKILL.md +137 -0
  422. package/skills/test-plan/references/case-taxonomy.md +142 -0
  423. package/skills/why/SKILL.md +158 -0
  424. package/skills/why/references/epistemics.md +144 -0
  425. package/skills/why/references/investigator-prompt.md +103 -0
  426. package/skills/why/references/source-playbook.md +17 -0
  427. package/skills/why/references/sources/code-archaeology.md +88 -0
  428. package/skills/why/references/sources/databricks.md +70 -0
  429. package/skills/why/references/sources/datadog.md +99 -0
  430. package/skills/why/references/sources/incident-postmortem.md +15 -0
  431. package/skills/why/references/sources/linear.md +48 -0
  432. package/skills/why/references/sources/notion.md +55 -0
  433. package/skills/why/references/sources/sentry.md +100 -0
  434. package/skills/why/references/sources/slack.md +54 -0
  435. package/skills/why/references/synthesizer-prompt.md +135 -0
  436. package/skills/working-with-mbx/SKILL.md +343 -0
  437. package/skills/working-with-mbx/references/acknowledgements.md +37 -0
  438. package/skills/working-with-mbx/references/benchmarks.md +140 -0
  439. package/skills/working-with-mbx/references/cache-results.md +153 -0
  440. package/skills/working-with-mbx/references/cache-server.md +151 -0
  441. package/skills/working-with-mbx/references/cli/adopt.md +29 -0
  442. package/skills/working-with-mbx/references/cli/cache/dir.md +24 -0
  443. package/skills/working-with-mbx/references/cli/cache/export.md +31 -0
  444. package/skills/working-with-mbx/references/cli/cache/import.md +27 -0
  445. package/skills/working-with-mbx/references/cli/cache/largest.md +26 -0
  446. package/skills/working-with-mbx/references/cli/cache/projects.md +23 -0
  447. package/skills/working-with-mbx/references/cli/cache/remove.md +30 -0
  448. package/skills/working-with-mbx/references/cli/cache/stats.md +24 -0
  449. package/skills/working-with-mbx/references/cli/cache/trace.md +27 -0
  450. package/skills/working-with-mbx/references/cli/cache/verify.md +23 -0
  451. package/skills/working-with-mbx/references/cli/cache.md +35 -0
  452. package/skills/working-with-mbx/references/cli/clean.md +27 -0
  453. package/skills/working-with-mbx/references/cli/completion.md +27 -0
  454. package/skills/working-with-mbx/references/cli/doctor.md +24 -0
  455. package/skills/working-with-mbx/references/cli/exec.md +28 -0
  456. package/skills/working-with-mbx/references/cli/explain.md +29 -0
  457. package/skills/working-with-mbx/references/cli/gc.md +28 -0
  458. package/skills/working-with-mbx/references/cli/prefetch.md +27 -0
  459. package/skills/working-with-mbx/references/cli/setup.md +28 -0
  460. package/skills/working-with-mbx/references/cli/stats.md +24 -0
  461. package/skills/working-with-mbx/references/cli/tui.md +24 -0
  462. package/skills/working-with-mbx/references/cli.md +58 -0
  463. package/skills/working-with-mbx/references/compared.md +67 -0
  464. package/skills/working-with-mbx/references/configuration.md +724 -0
  465. package/skills/working-with-mbx/references/cookbook/fork-prs.md +82 -0
  466. package/skills/working-with-mbx/references/cookbook/local-development.md +127 -0
  467. package/skills/working-with-mbx/references/cookbook/migrate.md +67 -0
  468. package/skills/working-with-mbx/references/dashboard.md +89 -0
  469. package/skills/working-with-mbx/references/faq.md +75 -0
  470. package/skills/working-with-mbx/references/getting-started.md +147 -0
  471. package/skills/working-with-mbx/references/github-action.md +254 -0
  472. package/skills/working-with-mbx/references/guide.md +59 -0
  473. package/skills/working-with-mbx/references/how-it-works.md +86 -0
  474. package/skills/working-with-mbx/references/incremental.md +78 -0
  475. package/skills/working-with-mbx/references/index.md +57 -0
  476. package/skills/working-with-mbx/references/installation.md +101 -0
  477. package/skills/working-with-mbx/references/limits.md +182 -0
  478. package/skills/working-with-mbx/references/linkers.md +75 -0
  479. package/skills/working-with-mbx/references/managed-targets.md +197 -0
  480. package/skills/working-with-mbx/references/protocol-compatibility.md +103 -0
  481. package/skills/working-with-mbx/references/remote-cache.md +190 -0
  482. package/skills/working-with-mbx/references/scheduling.md +65 -0
  483. package/skills/working-with-mbx/references/setup.md +157 -0
  484. package/skills/working-with-mbx/references/stability.md +43 -0
  485. package/skills/working-with-mbx/references/standalone-builds.md +102 -0
  486. package/skills/working-with-mbx/references/stats.md +49 -0
  487. package/skills/working-with-mbx/references/troubleshooting.md +136 -0
  488. package/skills/working-with-mbx/references/tui.md +163 -0
  489. package/skills/working-with-mbx/update-docs.sh +49 -0
  490. package/skills/working-with-mise/SKILL.md +297 -0
  491. package/skills/working-with-mise/references/cli/activate-html.md +90 -0
  492. package/skills/working-with-mise/references/cli/alias-html.md +30 -0
  493. package/skills/working-with-mise/references/cli/backends-html.md +40 -0
  494. package/skills/working-with-mise/references/cli/bin-paths-html.md +37 -0
  495. package/skills/working-with-mise/references/cli/bootstrap-html.md +109 -0
  496. package/skills/working-with-mise/references/cli/cache-html.md +40 -0
  497. package/skills/working-with-mise/references/cli/completion-html.md +76 -0
  498. package/skills/working-with-mise/references/cli/config-html.md +44 -0
  499. package/skills/working-with-mise/references/cli/daemons-html.md +48 -0
  500. package/skills/working-with-mise/references/cli/deactivate-html.md +47 -0
  501. package/skills/working-with-mise/references/cli/deps-html.md +89 -0
  502. package/skills/working-with-mise/references/cli/doctor-html.md +46 -0
  503. package/skills/working-with-mise/references/cli/dotfiles-html.md +57 -0
  504. package/skills/working-with-mise/references/cli/edit-html.md +48 -0
  505. package/skills/working-with-mise/references/cli/en-html.md +62 -0
  506. package/skills/working-with-mise/references/cli/env-html.md +57 -0
  507. package/skills/working-with-mise/references/cli/exec-html.md +79 -0
  508. package/skills/working-with-mise/references/cli/exec.md +79 -0
  509. package/skills/working-with-mise/references/cli/fmt-html.md +44 -0
  510. package/skills/working-with-mise/references/cli/generate-html.md +43 -0
  511. package/skills/working-with-mise/references/cli/implode-html.md +35 -0
  512. package/skills/working-with-mise/references/cli/install-html.md +83 -0
  513. package/skills/working-with-mise/references/cli/install-into-html.md +47 -0
  514. package/skills/working-with-mise/references/cli/latest-html.md +62 -0
  515. package/skills/working-with-mise/references/cli/link-html.md +57 -0
  516. package/skills/working-with-mise/references/cli/lock-html.md +114 -0
  517. package/skills/working-with-mise/references/cli/ls-html.md +95 -0
  518. package/skills/working-with-mise/references/cli/ls-remote-html.md +61 -0
  519. package/skills/working-with-mise/references/cli/mcp-html.md +57 -0
  520. package/skills/working-with-mise/references/cli/oci-html.md +41 -0
  521. package/skills/working-with-mise/references/cli/outdated-html.md +79 -0
  522. package/skills/working-with-mise/references/cli/packslip-html.md +38 -0
  523. package/skills/working-with-mise/references/cli/patrons-html.md +45 -0
  524. package/skills/working-with-mise/references/cli/plugins-html.md +46 -0
  525. package/skills/working-with-mise/references/cli/prune-html.md +56 -0
  526. package/skills/working-with-mise/references/cli/registry-html.md +59 -0
  527. package/skills/working-with-mise/references/cli/reshim-html.md +46 -0
  528. package/skills/working-with-mise/references/cli/run-html.md +152 -0
  529. package/skills/working-with-mise/references/cli/search-html.md +69 -0
  530. package/skills/working-with-mise/references/cli/self-update-html.md +42 -0
  531. package/skills/working-with-mise/references/cli/set-html.md +116 -0
  532. package/skills/working-with-mise/references/cli/settings-html.md +78 -0
  533. package/skills/working-with-mise/references/cli/shell-alias-html.md +39 -0
  534. package/skills/working-with-mise/references/cli/shell-html.md +53 -0
  535. package/skills/working-with-mise/references/cli/skills-html.md +39 -0
  536. package/skills/working-with-mise/references/cli/sponsors-html.md +31 -0
  537. package/skills/working-with-mise/references/cli/ssh-html.md +45 -0
  538. package/skills/working-with-mise/references/cli/sync-html.md +37 -0
  539. package/skills/working-with-mise/references/cli/tasks-html.md +61 -0
  540. package/skills/working-with-mise/references/cli/test-tool-html.md +49 -0
  541. package/skills/working-with-mise/references/cli/token-html.md +37 -0
  542. package/skills/working-with-mise/references/cli/tool-alias-html.md +41 -0
  543. package/skills/working-with-mise/references/cli/tool-html.md +55 -0
  544. package/skills/working-with-mise/references/cli/tool-stub-html.md +60 -0
  545. package/skills/working-with-mise/references/cli/trust-html.md +63 -0
  546. package/skills/working-with-mise/references/cli/uninstall-html.md +62 -0
  547. package/skills/working-with-mise/references/cli/unset-html.md +59 -0
  548. package/skills/working-with-mise/references/cli/untrust-html.md +35 -0
  549. package/skills/working-with-mise/references/cli/unuse-html.md +74 -0
  550. package/skills/working-with-mise/references/cli/upgrade-html.md +133 -0
  551. package/skills/working-with-mise/references/cli/use-html.md +130 -0
  552. package/skills/working-with-mise/references/cli/use.md +130 -0
  553. package/skills/working-with-mise/references/cli/version-html.md +46 -0
  554. package/skills/working-with-mise/references/cli/watch-html.md +465 -0
  555. package/skills/working-with-mise/references/cli/where-html.md +53 -0
  556. package/skills/working-with-mise/references/cli/which-html.md +55 -0
  557. package/skills/working-with-mise/references/configuration/environments-html.md +171 -0
  558. package/skills/working-with-mise/references/configuration/project-diagnostics-html.md +93 -0
  559. package/skills/working-with-mise/references/configuration/settings-html.md +3062 -0
  560. package/skills/working-with-mise/references/configuration/vars-html.md +167 -0
  561. package/skills/working-with-mise/references/dev-tools/aliases-html.md +97 -0
  562. package/skills/working-with-mise/references/dev-tools/backend_architecture-html.md +198 -0
  563. package/skills/working-with-mise/references/dev-tools/backends/aqua-html.md +274 -0
  564. package/skills/working-with-mise/references/dev-tools/backends/aqua.md +274 -0
  565. package/skills/working-with-mise/references/dev-tools/backends/asdf-html.md +98 -0
  566. package/skills/working-with-mise/references/dev-tools/backends/asdf.md +98 -0
  567. package/skills/working-with-mise/references/dev-tools/backends/cargo-html.md +240 -0
  568. package/skills/working-with-mise/references/dev-tools/backends/cargo.md +240 -0
  569. package/skills/working-with-mise/references/dev-tools/backends/conda-html.md +125 -0
  570. package/skills/working-with-mise/references/dev-tools/backends/dotnet-html.md +142 -0
  571. package/skills/working-with-mise/references/dev-tools/backends/forgejo-html.md +533 -0
  572. package/skills/working-with-mise/references/dev-tools/backends/gem-html.md +77 -0
  573. package/skills/working-with-mise/references/dev-tools/backends/gem.md +77 -0
  574. package/skills/working-with-mise/references/dev-tools/backends/github-html.md +622 -0
  575. package/skills/working-with-mise/references/dev-tools/backends/github.md +622 -0
  576. package/skills/working-with-mise/references/dev-tools/backends/gitlab-html.md +546 -0
  577. package/skills/working-with-mise/references/dev-tools/backends/go-html.md +115 -0
  578. package/skills/working-with-mise/references/dev-tools/backends/go.md +115 -0
  579. package/skills/working-with-mise/references/dev-tools/backends/http-html.md +644 -0
  580. package/skills/working-with-mise/references/dev-tools/backends/http.md +644 -0
  581. package/skills/working-with-mise/references/dev-tools/backends/npm-html.md +436 -0
  582. package/skills/working-with-mise/references/dev-tools/backends/npm.md +436 -0
  583. package/skills/working-with-mise/references/dev-tools/backends/packslip-html.md +310 -0
  584. package/skills/working-with-mise/references/dev-tools/backends/pipx-html.md +329 -0
  585. package/skills/working-with-mise/references/dev-tools/backends/pipx.md +329 -0
  586. package/skills/working-with-mise/references/dev-tools/backends/pkgx-html.md +73 -0
  587. package/skills/working-with-mise/references/dev-tools/backends/pypi-html.md +331 -0
  588. package/skills/working-with-mise/references/dev-tools/backends/s3-html.md +346 -0
  589. package/skills/working-with-mise/references/dev-tools/backends/spm-html.md +201 -0
  590. package/skills/working-with-mise/references/dev-tools/backends/ubi-html.md +232 -0
  591. package/skills/working-with-mise/references/dev-tools/backends/vfox-html.md +173 -0
  592. package/skills/working-with-mise/references/dev-tools/backends/vfox.md +173 -0
  593. package/skills/working-with-mise/references/dev-tools/backends.md +32 -0
  594. package/skills/working-with-mise/references/dev-tools/comparison-to-asdf-html.md +112 -0
  595. package/skills/working-with-mise/references/dev-tools/deps-html.md +390 -0
  596. package/skills/working-with-mise/references/dev-tools/github-tokens-html.md +390 -0
  597. package/skills/working-with-mise/references/dev-tools/index-html.md +420 -0
  598. package/skills/working-with-mise/references/dev-tools/mise-lock-html.md +660 -0
  599. package/skills/working-with-mise/references/dev-tools/mise-oci-html.md +418 -0
  600. package/skills/working-with-mise/references/dev-tools/packslip-resources-html.md +203 -0
  601. package/skills/working-with-mise/references/dev-tools/packslip-verification-html.md +178 -0
  602. package/skills/working-with-mise/references/dev-tools/shims-html.md +397 -0
  603. package/skills/working-with-mise/references/dev-tools/tool-stubs-html.md +416 -0
  604. package/skills/working-with-mise/references/guides/getting-started.md +268 -0
  605. package/skills/working-with-mise/references/index.md +37 -0
  606. package/skills/working-with-mise/update-docs.sh +111 -0
  607. package/skills/xgent-app-release/SKILL.md +507 -0
  608. package/skills/xgent-app-release/references/build-and-package.md +70 -0
  609. package/skills/xgent-app-release/references/embed-csp.mjs +126 -0
  610. package/skills/xgent-app-release/references/frontend-archive.md +67 -0
  611. package/skills/xgent-app-release/references/public-delivery.md +75 -0
  612. package/skills/xgent-app-release/references/publish-api.md +321 -0
  613. package/skills/xgent-app-release/references/troubleshooting.md +124 -0
  614. package/skills/xgent-app-release/references/verify-preflight.mjs +50 -0
  615. package/skills/xgent-app-release/scripts/npm-token.mjs +99 -0
  616. package/skills/xgent-app-release/scripts/preflight.mjs +351 -0
  617. package/skills/xgent-app-release/scripts/registry-config.mjs +88 -0
  618. package/skills/xgent-image-push/SKILL.md +239 -0
  619. package/skills/xgent-image-push/registry.env.example +51 -0
  620. package/skills/xgent-image-push/scripts/push-image.sh +576 -0
  621. package/skills/xgent-init/SKILL.md +37 -0
  622. package/skills/xgent-init/references/external-app-AGENTS.template.md +149 -0
  623. package/skills/xgent-init/references/external-app-DESIGN.template.md +317 -0
  624. package/skills/xgent-init/references/external-app-PRODUCT.template.md +87 -0
  625. package/skills/xgent-init/references/fill-guide.md +66 -0
  626. package/skills/xgent-init/scripts/check-docs.mjs +232 -0
  627. package/vendor/impeccable/LICENSE +191 -0
  628. package/vendor/impeccable/NOTICE.md +11 -0
  629. package/vendor/impeccable/VERSION.json +22 -0
  630. package/vendor/impeccable/bundle/blobs/00c067253d37cd20a41dbe9c806d6a72cbff983ad1418b3c3e447998f577b9c2 +152 -0
  631. package/vendor/impeccable/bundle/blobs/00d167d9183c8d0c6c0682055107382e6672bacf7a712de0abc8f157c2cb2210 +86 -0
  632. package/vendor/impeccable/bundle/blobs/00f053b877a92a9847d69eec2403e40c757152f30a5ca807c5033c58d7c297f1 +33 -0
  633. package/vendor/impeccable/bundle/blobs/012f548547fae48ebdd22a3c3af8a01032641fddd530e3783bd73b7358ab2c49 +80 -0
  634. package/vendor/impeccable/bundle/blobs/016c082dcd2aa8f3c080a757c8ed335c6070a904bd2f39668bb9d3e6f95929c1 +24 -0
  635. package/vendor/impeccable/bundle/blobs/0221a193d111a9de33a785706a603e55dd974a115f549dbdf74e0f9ec72bde7d +101 -0
  636. package/vendor/impeccable/bundle/blobs/03b30331c176a248a3b3bd17abdff1a1fd658f09ffb2a412b36ae9627dd3f33b +105 -0
  637. package/vendor/impeccable/bundle/blobs/055c571f2960b8f929d6a8d3806a4d32dfcb9750b3ef8b60adc8930fff34b559 +101 -0
  638. package/vendor/impeccable/bundle/blobs/058f81f256134841875fd3183e06b37a023de0c877fd2b9eecd97011640791fe +46 -0
  639. package/vendor/impeccable/bundle/blobs/05aa836a190f4ff62e5d4619738bdb891d83d85e35d81c2e6e322d1dc084d802 +80 -0
  640. package/vendor/impeccable/bundle/blobs/05e86f37d7fa381c5e8a04b6212490a27904d3be3e9384862a0764d3daba6d78 +54 -0
  641. package/vendor/impeccable/bundle/blobs/0605c8729dc638a46798e90ab12486fe3ae3372a869757cfb387a08e23b3c84a +152 -0
  642. package/vendor/impeccable/bundle/blobs/0617b37a905f0486c1ab4e91a287c8ef8292e253095c340f452d591206272f73 +104 -0
  643. package/vendor/impeccable/bundle/blobs/0648e4e06d01cabc91fa7dc19256ceedeeeea213b9265e9d36b0918370e16fb2 +318 -0
  644. package/vendor/impeccable/bundle/blobs/06b20bd42e5682a42c5d6fbfaad4c55e66ff9b9d99a604bd31d3545af120fc2d +101 -0
  645. package/vendor/impeccable/bundle/blobs/076a31941acbaa81013c8c511e146ed4138128eb5e9895dae3e9a27a25ac4f04 +13 -0
  646. package/vendor/impeccable/bundle/blobs/08346755b13f1a3f7c6fb4e512387884b80467aaeff109fd41f5521d2a95635a +113 -0
  647. package/vendor/impeccable/bundle/blobs/08398fa2d8e2b06b849f1c0f032e1e93b832e9294aed35c1c7f62b938d62ee80 +43 -0
  648. package/vendor/impeccable/bundle/blobs/087f6715114e901c2ce00b438e75b82fd48978c020a782f3dc361d39eb7198a6 +26 -0
  649. package/vendor/impeccable/bundle/blobs/08812a8618de7bd2f63a51298e9c2558031237e8efba280062ccb636101e25e1 +80 -0
  650. package/vendor/impeccable/bundle/blobs/08a2980eae0bfea1f00229899defc28ec92c7ecb875bf5fb02e4ba80dad6c394 +806 -0
  651. package/vendor/impeccable/bundle/blobs/08d78eb31c561256f83baa0afa742a660f1467aa2c81be2f60c2b7f9c770d66e +54 -0
  652. package/vendor/impeccable/bundle/blobs/09310582ed23393b171eb99ad4a288cc422ac53c26d76311586ce54c6df77b22 +113 -0
  653. package/vendor/impeccable/bundle/blobs/098a891028ce59c212b747d3c70468dd750aff7053a703d1336045ed31e0da7c +70 -0
  654. package/vendor/impeccable/bundle/blobs/0a151a54959a15eb32fa338890d5d64ac48a9d54d2d5442c3c7708a4c27c1858 +104 -0
  655. package/vendor/impeccable/bundle/blobs/0bb4085f6dda702846e0e56bd4f797aa1b046ab48eca02644448e368f3820f88 +104 -0
  656. package/vendor/impeccable/bundle/blobs/0bc2bc36ca6e74f9f610392f1a4fb8f57b2676238ba1f9c65cd8714f5d27e8a2 +42 -0
  657. package/vendor/impeccable/bundle/blobs/0bc7d7971b3edf2acd0580e847458dc6d84129d90715b452799ace3bed815c7c +84 -0
  658. package/vendor/impeccable/bundle/blobs/0bf6f08bf34d24cd88a78d544add9e4d71478bcf939926cde32f4e164882c775 +105 -0
  659. package/vendor/impeccable/bundle/blobs/0c064c9975f25f6eb5cf7911c2eeafd3e695d729f8c86a49a24ff2d76cb3cd94 +63 -0
  660. package/vendor/impeccable/bundle/blobs/0ccf57f758eb0d53bc32c5c77156f016e528d20fe2c2740662bf19964dfbb00b +152 -0
  661. package/vendor/impeccable/bundle/blobs/0dd1e6ccf053cb80e057caf7bf2fef30fd0197a41d907a1a8d2d2d02f6978674 +63 -0
  662. package/vendor/impeccable/bundle/blobs/0e081d496eba4bd77aca81723d59120c10177a71c9551a60ab923c356fb3cf38 +104 -0
  663. package/vendor/impeccable/bundle/blobs/0e18ac33b7e6a247b658fcaf926d9eac028399597dbaba366f1d2f2b884a383b +325 -0
  664. package/vendor/impeccable/bundle/blobs/0ed5986d1503399f48c11104df5e523a63be2d6558770ebfbbeb2323ca3f2ad3 +46 -0
  665. package/vendor/impeccable/bundle/blobs/11f75834c26ecd8a5b0afdf696e838953b235dc4835b7293bbc6b1bc27dd3106 +84 -0
  666. package/vendor/impeccable/bundle/blobs/14c9c9a7816026dd77494d06b8d1777c8d64785126b0c9ac8db5ebd996dfd6b6 +101 -0
  667. package/vendor/impeccable/bundle/blobs/14ef0ab84c10331f8af6b4124387a3f80b493175a04a3f89200719b4b5aea221 +152 -0
  668. package/vendor/impeccable/bundle/blobs/1547005438784032de3254cb35bff393e8187d7a459d0c20a693d9bfb0b5c1a4 +42 -0
  669. package/vendor/impeccable/bundle/blobs/162b814ddd1133923b9584bb95f85959e64844c94341d6bf10a81c06ab7cc02c +101 -0
  670. package/vendor/impeccable/bundle/blobs/1640c70b984a43e729d72d046109f87243ae84ecd64d2600a007d140558123cc +80 -0
  671. package/vendor/impeccable/bundle/blobs/16498466a97a5b19a593d5b3f245468c71784bea069d7fc8aa9690db5ac1d968 +29 -0
  672. package/vendor/impeccable/bundle/blobs/1652d639d91889a08bda7f351456c43ee30e5677aa4866a90f375e1e4be15deb +80 -0
  673. package/vendor/impeccable/bundle/blobs/16ba7fca1973c5faf53dd2ca523559129c0fe9e5f8d50b645f527afa78186cd2 +345 -0
  674. package/vendor/impeccable/bundle/blobs/16d99e9fe8e75d69042bc4fda12e93daa7e10f9fa6c00b12b0f0580b119a4cfd +105 -0
  675. package/vendor/impeccable/bundle/blobs/171777f8a8596d2ffdb43f4b935a7c6c12859ace233967f868a566390a59708e +325 -0
  676. package/vendor/impeccable/bundle/blobs/1725ca4aa546a34770f29191b58bf8dc14957d4258fb9e7d02f7b1c59c412ea4 +63 -0
  677. package/vendor/impeccable/bundle/blobs/173dd66abe65633910dcb04a51f40d6ff2a793f87088f022a02fc4cad24dd133 +94 -0
  678. package/vendor/impeccable/bundle/blobs/17c583cf8ad41266ea1e787b666b9d91fe13469d3d0f6af57c08e0146f9b17ac +58 -0
  679. package/vendor/impeccable/bundle/blobs/1898529e994bf0a31ee9ff3f87c343caea3d8a7e0986f404e129fbf89078ade0 +90 -0
  680. package/vendor/impeccable/bundle/blobs/190a4e642ca362d7499f3c3ab123e21f18f75457d11f072b545a183f296e6495 +99 -0
  681. package/vendor/impeccable/bundle/blobs/1971edc3784273bd8da7b1980779c6159471e857992faa6637178109cb130503 +806 -0
  682. package/vendor/impeccable/bundle/blobs/199d5d3db1197e053a2eb9c3cb927d44cbaaaeb57745c1ada3fd775ba50d9291 +104 -0
  683. package/vendor/impeccable/bundle/blobs/19b439d7d16e139357459d3874f739ea94dbdffeb2a0e201df1620ed1e40574d +24 -0
  684. package/vendor/impeccable/bundle/blobs/19c5bfce570a0e2bddd4d9c788936ff9070c90299363c4853ba77bfd37306e20 +416 -0
  685. package/vendor/impeccable/bundle/blobs/1b289c8c09de9d4442109ada91b1fa3a190e113a310cab7aa26a3633c5df0bb0 +24 -0
  686. package/vendor/impeccable/bundle/blobs/1bb3bdce54386e96e21b5956713a80583e6b3b9d1170f3bb8dec3819fa341bc3 +46 -0
  687. package/vendor/impeccable/bundle/blobs/1c11cb8ea42536c7a51e197f1aa32198960bb89262da2eaf32e0feb03c70792c +152 -0
  688. package/vendor/impeccable/bundle/blobs/1c6258015ed02c522948f8f1a3b6457395a8f7954497b87c1cd83f1791f9f819 +24 -0
  689. package/vendor/impeccable/bundle/blobs/1d7145fd5bf65282b2e05cf42faf41766d68e83e2b75f460b3b62d81ada5e5d7 +152 -0
  690. package/vendor/impeccable/bundle/blobs/1d72b494f46a60e6c9c06e89bab79789dd85e11f62fb4286a03abf26d352dc1f +80 -0
  691. package/vendor/impeccable/bundle/blobs/1e2f696760ee55fb154bdcc302c7d7b0fbb807e0308130594bd892dae14dc9ea +42 -0
  692. package/vendor/impeccable/bundle/blobs/1f6c3a1d7344f44eaa88b6f38334ad7d7b60201709589039a58cee73de486f5d +24 -0
  693. package/vendor/impeccable/bundle/blobs/207d443cabe4e6fe1351f91785748957f757bf1e7aeca405433c0329dad46a15 +63 -0
  694. package/vendor/impeccable/bundle/blobs/20e2111b3e065e8e8054f715ea3902e64b77886b30d2bddee723558f22942620 +90 -0
  695. package/vendor/impeccable/bundle/blobs/21e78c8a77badb3f83290cd4577ed3b24bd4dd3b57136d7da75733d4f3ee9ac0 +19 -0
  696. package/vendor/impeccable/bundle/blobs/223f08673b267f81d7586f686afe05d7cd7529a8e11ac37d979f95c2ceaae8ce +24 -0
  697. package/vendor/impeccable/bundle/blobs/238e1967d933ca5739db708f7ad9f72ca8b34bc4c9b9e1c07b0a06dcf9d00681 +806 -0
  698. package/vendor/impeccable/bundle/blobs/244e5b7bca6d22a51b4e22104a52a36e477056b03d257b56d1d4e319cd6167a8 +80 -0
  699. package/vendor/impeccable/bundle/blobs/2499b18f26639694344ca95682f47c65494f730cfff88aa9bd2aa83a22e5926d +101 -0
  700. package/vendor/impeccable/bundle/blobs/26cd88d10f8a14ed0ddb6e6b21e5e2c981f410eac93afa179202c354d7d1c0d5 +113 -0
  701. package/vendor/impeccable/bundle/blobs/275dd1b6e63bbd30d2713227c4f79b880a8bc4e01cc48d392068bb86939d3afa +38 -0
  702. package/vendor/impeccable/bundle/blobs/28f65b42c1ce9aaea35dc37a51257d7c703bb7f6553ebe3b8ca238a1007251e0 +113 -0
  703. package/vendor/impeccable/bundle/blobs/29f741b71e75fd39c65ca6df4b01b5f6c4f3c4c7adf23b47a3220ce2c0251f24 +104 -0
  704. package/vendor/impeccable/bundle/blobs/2ac1624b1253f3b6fcf2da54d54293624176539b2e9609a49245e7e46c65ca5f +42 -0
  705. package/vendor/impeccable/bundle/blobs/2b58041cd82d819d12762b10becb95f8253c661bf6a9de40f61fc01c1204b743 +806 -0
  706. package/vendor/impeccable/bundle/blobs/2b5b2fbf5f658f34ea1997fb1aeebe01604d05187f75c6a4f1f55a5bc78520a4 +104 -0
  707. package/vendor/impeccable/bundle/blobs/2b9379cdb329890eebe2384fbaa23f771745f30d8cfc43e180ebd092e69bcd2f +87 -0
  708. package/vendor/impeccable/bundle/blobs/2bc5d62463cc83d6417df7b8f4a02b4135e2b1bb654aa7727890662496f86e3d +42 -0
  709. package/vendor/impeccable/bundle/blobs/2c2ed6286bd74adef4f24ef442e2e1bc0780d44bc060aa2a4c03a03988dbafd5 +325 -0
  710. package/vendor/impeccable/bundle/blobs/2ce1722bd1a9f366182d9357d629796b1448f7a0126a854df507eb044d891cab +26 -0
  711. package/vendor/impeccable/bundle/blobs/2e4846117a2fcdc1e4bc9570a5333da839649cb8ccdac6a30a87591ca05b4bb0 +54 -0
  712. package/vendor/impeccable/bundle/blobs/2f02f96f889e0c8e0e90806af1ef17e0c162a6cc402068f434d3f7608d9deda3 +54 -0
  713. package/vendor/impeccable/bundle/blobs/2feb3768125ba6469c92a50d516727e6d42f44579165ddfd33409948e2a3803d +27 -0
  714. package/vendor/impeccable/bundle/blobs/3149a87bbed84bffe3558d5eaf1dc596b2e84d3c1be290fc7b1c13e481ae0803 +90 -0
  715. package/vendor/impeccable/bundle/blobs/31b90048c0b540daec46762a10c2b6b6434737a89af005054d8b848d829d003b +69 -0
  716. package/vendor/impeccable/bundle/blobs/3253eab02b62efa80abc74a5c85da08f3e2c6c20dff8dec38f4d236cbbfa0f3c +63 -0
  717. package/vendor/impeccable/bundle/blobs/3565d038a2eeab88a8b18ff52e6630008ab30f867f9df922a38ce8980440b2e3 +80 -0
  718. package/vendor/impeccable/bundle/blobs/3673248740bcdd1122ccc610093ba2fe52f3943a61ce0b7170b74dc49e5b6098 +416 -0
  719. package/vendor/impeccable/bundle/blobs/3753448bca49da76dd8b12d5a8b4264414673f26e49028d37616faa8beb210b7 +127 -0
  720. package/vendor/impeccable/bundle/blobs/37565671b09d983ea1ad83a9e9190bc37255d93c68445958c6facecc7e0f7c4f +33 -0
  721. package/vendor/impeccable/bundle/blobs/37680abf9a8e446619fcd33862718f483d197bf2652f966adca8dc54d2909b9d +85 -0
  722. package/vendor/impeccable/bundle/blobs/37aeddc0f2031fa89d72519ae2e7542c267872f81786fb8288fca0a49118be11 +27 -0
  723. package/vendor/impeccable/bundle/blobs/37c9a2122efa64dc8789eb47d196150b0bc635e0ba95042fd381ff157002ed50 +111 -0
  724. package/vendor/impeccable/bundle/blobs/385a0efe833bd4afe4a257e7159590de0cf1b7fd8f7b213b732f1e537c62dab7 +21 -0
  725. package/vendor/impeccable/bundle/blobs/3898bd9b56a042e860a0db4fb4dd81ac81126fa218b604702e2ac0c2287ae09b +345 -0
  726. package/vendor/impeccable/bundle/blobs/3970c8e24615610b0246585e49146f6762d5082b3c8fddc08a00940d6e72d394 +80 -0
  727. package/vendor/impeccable/bundle/blobs/39ac044f2e45a9e7eed8eb68fe91d32938160eb7f8fa93d2afc42fc80a0c3c10 +54 -0
  728. package/vendor/impeccable/bundle/blobs/39d9600489073e227e4f4d55c451ce4252a6632ed7ae37923efbbcbc91f16d07 +206 -0
  729. package/vendor/impeccable/bundle/blobs/3af7c46309f748ff3845f16455a431ec0e9e807e5e3a965e96e9ee75a1198eb8 +95 -0
  730. package/vendor/impeccable/bundle/blobs/3b2b60f23fa8ed9d73e721e17142c3933dc5318fa9a251742a76fee890ac81a8 +26 -0
  731. package/vendor/impeccable/bundle/blobs/3bcf81b938a0f0309e9ed6616f4bd18d82f07e2801411ee4cce51220d417eb95 +80 -0
  732. package/vendor/impeccable/bundle/blobs/3bd55b35c253f7841ca4e6e1a855a4b477d59aa2daf6e61e93fd685caaaff131 +63 -0
  733. package/vendor/impeccable/bundle/blobs/3bed76a0d528e2d73da8acae4dc63702bdb5baca5ab11600d70e75fc9f2ba90b +42 -0
  734. package/vendor/impeccable/bundle/blobs/3e3b6fdc6afbc2c2a734d08d6a18b393b7139c56f28f91f82e13e5555b98018a +84 -0
  735. package/vendor/impeccable/bundle/blobs/3ef9a43006bc68d83bc958fc8401e59f9beb6379048f5ced047747fdad05b895 +46 -0
  736. package/vendor/impeccable/bundle/blobs/3f2c351303b74e217907006fb9c55ada2ef596e9710c13d631e20506d17b9ee8 +325 -0
  737. package/vendor/impeccable/bundle/blobs/400419aaa20f710e1a7e5ca1fce9e8bc995c4db84053f40cf778d987619e0210 +24 -0
  738. package/vendor/impeccable/bundle/blobs/402373ef95962ecb81dd3d7cf70ecb3bd3e22a2bd2aabb4c0d76f7f4f9447870 +105 -0
  739. package/vendor/impeccable/bundle/blobs/40c87038b5f75147a5952a96237acf312a327bf70c1bcd8e0a5f064625ae9668 +51 -0
  740. package/vendor/impeccable/bundle/blobs/40cd6024312a1339aa66801df533afa543e60c36e708f0f9659dd8d558f83dce +63 -0
  741. package/vendor/impeccable/bundle/blobs/412dd9a5238aee223397591fe49b3bd27b6b53d649a0e67ed8570f3e199cebb9 +24 -0
  742. package/vendor/impeccable/bundle/blobs/41ef23c048ab739f48afdce26a2678d36ee40bcced34ef4b969d1d8ffafca64c +113 -0
  743. package/vendor/impeccable/bundle/blobs/420d82fe41884b7aa8c28750520146d8160c91396ac332a96b2d82a90b017fb2 +80 -0
  744. package/vendor/impeccable/bundle/blobs/424ff273e7ab283d6695d127bb502675627193f5b752d7b43b7524bcfc42f43f +84 -0
  745. package/vendor/impeccable/bundle/blobs/42831c3cd874346d8e7f120808d91e6ed3cda5c3eca6eefd76b126659536bc87 +148 -0
  746. package/vendor/impeccable/bundle/blobs/42a71df98075f66e6eb396b69ef3d6b1c3db46d1c1d24b4edc9d15f53d193ecb +111 -0
  747. package/vendor/impeccable/bundle/blobs/43dbfcb7c2e54c9cca9fce66024f17c06a2f2be645547b718b75c8828a463de2 +24 -0
  748. package/vendor/impeccable/bundle/blobs/442749aed338f51c1a3ccfb182c6ade9b74b90590b67984062ac94a5b100e914 +80 -0
  749. package/vendor/impeccable/bundle/blobs/4435529820c3fc2eceae8b1ee35c906a34c7612fb860117e896152b45aee0770 +26 -0
  750. package/vendor/impeccable/bundle/blobs/44a60aedcc350c2d7d501d0f830a31a586a6511a9ff9b4e361cb328bb747339d +101 -0
  751. package/vendor/impeccable/bundle/blobs/45dcea8da47cc21f447041daa942cf5d92cddde9a5a02c196cedbd159c829304 +47 -0
  752. package/vendor/impeccable/bundle/blobs/464c0c2b33d278375aec66caf95518f5e7ccd0aad1bea3f9dd553ed47815daa1 +325 -0
  753. package/vendor/impeccable/bundle/blobs/4700adf4542874f204c680ebad8317a97bf7169dbc04147082618ab59ce70c7d +85 -0
  754. package/vendor/impeccable/bundle/blobs/4777bbeaff2efcd6a2a66b07aacaaf57cd32f3fab1c1da5a0513937fafb48bd1 +63 -0
  755. package/vendor/impeccable/bundle/blobs/47b3461f6f76db80fdc49fc7542552d65fed24edc8d30d903cb76aefbad0ed05 +84 -0
  756. package/vendor/impeccable/bundle/blobs/47edbdfaf27073c47033d1ac7dfee881be49e2dcbda7671d1157300481dde6da +1 -0
  757. package/vendor/impeccable/bundle/blobs/484ea165f6d49ecc15b7a5c5623e377f2e203f4dad366df23eae99255ecf4572 +152 -0
  758. package/vendor/impeccable/bundle/blobs/485774d58dfd5796956024cdd9c12f05e692a3703f70b12a02ab43918885c3fd +101 -0
  759. package/vendor/impeccable/bundle/blobs/4879f38b23d0a251a63cbb0327e660296194cd2e71eb4da3236c6ebfe5807746 +33 -0
  760. package/vendor/impeccable/bundle/blobs/488da2e7406c6b4b5c92d7bc8cbd370cdaafc82a5f3ab5adbcffb21d1d1c4df4 +113 -0
  761. package/vendor/impeccable/bundle/blobs/48bb7c3b738f57fa4f3f714d7e3e919879036f3e751135a9acc1c5ede1850ea6 +54 -0
  762. package/vendor/impeccable/bundle/blobs/492a8030d11e2f4908d934bd817bd6d16a3164056c74a7172f60e2cec5ff3055 +42 -0
  763. package/vendor/impeccable/bundle/blobs/494d6fcb4701c437597c2ed16a9595af92f3d9ad53c944c96a2fb563bd766af5 +99 -0
  764. package/vendor/impeccable/bundle/blobs/4972f28d96897c8dec891f0de7a0d9d51f36030ff780ed9d960241c75413da2b +46 -0
  765. package/vendor/impeccable/bundle/blobs/49a7b37b98fb6e3ef68154174677ff4b9f1715efcffdbf6b30c3535b3e4e302c +54 -0
  766. package/vendor/impeccable/bundle/blobs/4a6f0386bff78bb42efa285df2919e75209ec336672cf5fff91ba66ffb352eaa +63 -0
  767. package/vendor/impeccable/bundle/blobs/4a8a45a46b79948a64b484edf389aa0b00fc80de855470cbabe3c7c71268f345 +828 -0
  768. package/vendor/impeccable/bundle/blobs/4ad7c5d5821f85c2311ff91746d9b9cf272dbe0a9a5b61687f77681f5a13f812 +69 -0
  769. package/vendor/impeccable/bundle/blobs/4b0e2eea17f297daa06b17578131775be099ef43addf91007f4b7e295454f64f +105 -0
  770. package/vendor/impeccable/bundle/blobs/4bceaf3346b6f5100b5a54deaae49a38b975dd134df2836675848f06ff1e7e11 +806 -0
  771. package/vendor/impeccable/bundle/blobs/4df48b7a86d525ad12e7889a1fd16b06ed4b25a9470c359c7193a6d82649262f +54 -0
  772. package/vendor/impeccable/bundle/blobs/4e3cc4d0e229ca96dd2e28fb2da0478a7f0bb64e447d07a652c425d8fbc57573 +113 -0
  773. package/vendor/impeccable/bundle/blobs/4ea8e05d0f88d24f182ad554da84317f90b9730e29fad262143ddf423a1f8645 +26 -0
  774. package/vendor/impeccable/bundle/blobs/4fb6d2fcc8afaf827a7377ddd604725264fd83be871e2d35062e9d1939144404 +25 -0
  775. package/vendor/impeccable/bundle/blobs/50d4b14134fc06daeac0aab6960800f171ef85250d3bcce6f246cf81e824463f +88 -0
  776. package/vendor/impeccable/bundle/blobs/50f3b5714ca3e2c1bcf070003733407935ee050609d3123c2c065489fbc9950b +43 -0
  777. package/vendor/impeccable/bundle/blobs/51032bb883137007127d30189b44b516d0e6140271bf5881da7eca76f8bd282c +113 -0
  778. package/vendor/impeccable/bundle/blobs/511ecde67e6bd976c9bdfa8d92f0dba359621344f8135c2a5ce5a66b385a4cb5 +42 -0
  779. package/vendor/impeccable/bundle/blobs/514a27fc9830455828d337cfc2fa95fa86be8e5464501bbabb9aca09a66b40ad +63 -0
  780. package/vendor/impeccable/bundle/blobs/521391d55814fdef6cd648ed62154a14d77b324004a0fc2d06c0a4e97857eab2 +806 -0
  781. package/vendor/impeccable/bundle/blobs/529cb2ace696ec11a86f4b010c9b137acf282072e483932181be1871df2aa690 +152 -0
  782. package/vendor/impeccable/bundle/blobs/52e861ac390a62c4473ae0cf87ff18dd6d721afa6557910492dd8ed28bd9970d +84 -0
  783. package/vendor/impeccable/bundle/blobs/532d6387db6f5da1a59dc7d29ce4d8ba6ca044626c367dc16e1cb8b981eb2d9a +104 -0
  784. package/vendor/impeccable/bundle/blobs/53628d05b7eff0d4f48b95e48fad40266452fe1b42f398bd88dd9328353e0dd8 +101 -0
  785. package/vendor/impeccable/bundle/blobs/53de37260c4f1c37e467557e9b038faa0f285b056bb2b95f435e0a7d1b69b0de +89 -0
  786. package/vendor/impeccable/bundle/blobs/5415103ca4422ea1422e23bfe9f9bae181f5d6d6407442f7fba31856ada58d12 +113 -0
  787. package/vendor/impeccable/bundle/blobs/54e71283cbd5646021fcd8eaa28d85852ec5288109c306aca9db9e2e4832338e +69 -0
  788. package/vendor/impeccable/bundle/blobs/5515d5210fbe2ef64e611ef2827a7204b7cea2f9df059f3ea499931f45065d93 +104 -0
  789. package/vendor/impeccable/bundle/blobs/56285b28b0ffe471761c2ad062d3f933ed2346ca1b617f1323a30fed99a1a852 +24 -0
  790. package/vendor/impeccable/bundle/blobs/56500b1f9d2fcec8324d7f448d813048b5831a46d3feeb1055bd3eb17ec3660f +70 -0
  791. package/vendor/impeccable/bundle/blobs/56cc1bba51e6805de370160ce4a9399fef3740571204f13c3c751725870305e5 +113 -0
  792. package/vendor/impeccable/bundle/blobs/571526fd5c60a586ff65bdb3f8333f26c36ae227f5f5ece826f4a43b4d4aee0f +325 -0
  793. package/vendor/impeccable/bundle/blobs/571f5c3bcf01c9b1bd02ab853a54db3f88375c4b8f39dd67d53e983a33e08bb7 +26 -0
  794. package/vendor/impeccable/bundle/blobs/57e28934208e3eac653ab59c5c6a5e4eace44906d8ac86472988242d777ca5a1 +54 -0
  795. package/vendor/impeccable/bundle/blobs/5855d7595b0212bb8d521e0265378d437df8d2343d5f8a30408c3edde0a14d96 +85 -0
  796. package/vendor/impeccable/bundle/blobs/599afc25c1d6d083e4d4e60e1617ab05f6c5ecd52be75473f3788063219aa174 +31 -0
  797. package/vendor/impeccable/bundle/blobs/5a07d4769a741cd00fdf8c95b943ef072eb12cd0c9e2c2d2622d5fe0a4fa3894 +46 -0
  798. package/vendor/impeccable/bundle/blobs/5a9626fb8c1e9051155c68626fe7c765a55be325113245d44b4991fc3d3b014e +44 -0
  799. package/vendor/impeccable/bundle/blobs/5b5dcf7029376ee6fbcf13e5975eb828dd1dbf41736c1bd5017dcda8173b1ebc +325 -0
  800. package/vendor/impeccable/bundle/blobs/5be952da521a2d5fb799c834d14ce5388284374bc23c5efcec737a05aa65d878 +84 -0
  801. package/vendor/impeccable/bundle/blobs/5c036648951d555e73be63161e5c9edcba146d8e9f64b1604ffdea765cde5d9d +131 -0
  802. package/vendor/impeccable/bundle/blobs/5c4cd151c97dae824a039211d7ccfba4c572b76d8f079c6186ba1dd5dae7732b +54 -0
  803. package/vendor/impeccable/bundle/blobs/5ce0631eacaae6d9fbb23ade26a774a20142cb40d3a8d5608a3fb9dbc4116b60 +806 -0
  804. package/vendor/impeccable/bundle/blobs/5db17cd013c10dca0012bc18aee7276280941579aa50757682e9ce60c4f7a006 +104 -0
  805. package/vendor/impeccable/bundle/blobs/5e354ae11913d5846faa3681a9ed98b68d1881fbbb1ecebf0769e3010bb0a426 +42 -0
  806. package/vendor/impeccable/bundle/blobs/5e6eea05456108b8766cf354dda998e90b6a5ecca7f15d807e28659ee78c306f +42 -0
  807. package/vendor/impeccable/bundle/blobs/5fae7f8a2fc3ddd49ad0a413446dc44daedef5b6b7de5eb935bd2fbfad646d58 +92 -0
  808. package/vendor/impeccable/bundle/blobs/634257e766b1fecacd25e27dbfc7e21ef3b440b01e94e92b8b17711018d8a661 +152 -0
  809. package/vendor/impeccable/bundle/blobs/6428239079f98fd6500e9fd032dd289b52052da7a4364ff357b0a5341b6444db +63 -0
  810. package/vendor/impeccable/bundle/blobs/647bab2f5cf6279d58d808f4df05d1ac63c1c86c6df9d13406ae776458653995 +42 -0
  811. package/vendor/impeccable/bundle/blobs/64802d14087fc96b38ef3881fef8098b36068d07f3b942031637b18eef3dd2af +84 -0
  812. package/vendor/impeccable/bundle/blobs/64807d8f43267f4ed879e997834bbf793bd4605ba1dc65f4b545324b660a7063 +80 -0
  813. package/vendor/impeccable/bundle/blobs/6528f2aebe4a425b724de293c8f6dc8a42ca80c7f1ed3039b8b9a813b004956a +87 -0
  814. package/vendor/impeccable/bundle/blobs/6575a657642ccdab42d0743ceaee06621c77811b4dc4f21c616e28aabf5e28ef +42 -0
  815. package/vendor/impeccable/bundle/blobs/66d60356172ccafdd334fca9bf33243c8409216a733dcde0d66a24fd70ee8132 +1 -0
  816. package/vendor/impeccable/bundle/blobs/68c5636a7858dd0b5137a9229c15e25fdc2ee40a0f8a4e9d809f78e809256262 +327 -0
  817. package/vendor/impeccable/bundle/blobs/696c15f96d49a03091b71a408151a3297521f7a8231b98ca9b1103667a0b5f89 +80 -0
  818. package/vendor/impeccable/bundle/blobs/69be9bb887f4d8ba4ead24928f9b97d122c796e731652fc0c08f195ab8ec2815 +105 -0
  819. package/vendor/impeccable/bundle/blobs/69cad1ae7355825ef320ac9638a1c9675ba9fda01c9a0fa12244cc4a1973e550 +214 -0
  820. package/vendor/impeccable/bundle/blobs/6acc0bf221a4ddc6e5c6438348920b2ca2393b29c4314dbde2cdc23f2b1a9639 +58 -0
  821. package/vendor/impeccable/bundle/blobs/6bc62a59f6fef0b749927c8d10e9849ab2411199d86d70772a86f8e83ac309f5 +29 -0
  822. package/vendor/impeccable/bundle/blobs/6c382f8283756e8a693d832b750f7e4cbff1ca5bdcc3825b2b4ef4da9f21876a +94 -0
  823. package/vendor/impeccable/bundle/blobs/6c9ce3e27ec4520ead001da3aad2a2ebba481c4e5cd22873db8890259ee579fe +95 -0
  824. package/vendor/impeccable/bundle/blobs/6d21d8e2729effaecc5b6239dadbcffb1ec8d51e8bdadeb47a39827266a61c5e +26 -0
  825. package/vendor/impeccable/bundle/blobs/6d368b679a0ed1815812815de65863b5840d419589dfbda06224c01149240287 +258 -0
  826. package/vendor/impeccable/bundle/blobs/6d9258a49c0b0583ec255eeb1092554298d5eea676fb9391f5a5a1377c3fd770 +87 -0
  827. package/vendor/impeccable/bundle/blobs/6e7e3b7c4cf331cdb43f4546c164acd6c45a267ce3289dcfa87e13202d98c747 +104 -0
  828. package/vendor/impeccable/bundle/blobs/6f4dfe968f47302ea64dca0e02f8c6d81497d93e4f436d09236e305456cbcc02 +87 -0
  829. package/vendor/impeccable/bundle/blobs/6f7f1639a933ed88e116aa8ab0cfb951096930d14f413349ae22ed04e28d2358 +46 -0
  830. package/vendor/impeccable/bundle/blobs/706c68612a7c6b899a0abf0b407eca7cabcd371deae60f830aa38aa86947694e +84 -0
  831. package/vendor/impeccable/bundle/blobs/713a942482531ef8ef103adf48d9decd7327697450e444289aa0479458e4ee1f +101 -0
  832. package/vendor/impeccable/bundle/blobs/713cac92a71ef45e8b700180d881f830096cfe2b0615e79b276ccc4a12c051e0 +80 -0
  833. package/vendor/impeccable/bundle/blobs/7212014fb2477d1d54aedaa79cdb861071a58afb2ae6d4dc5a495fa4810c6f8a +46 -0
  834. package/vendor/impeccable/bundle/blobs/73549b5536699c915156339976192fb38534bb43158cf9262ff5b89090388c64 +806 -0
  835. package/vendor/impeccable/bundle/blobs/73bd60faec1d8360753595f1ee9e970b44933448202767d7b0e87c275d399396 +6 -0
  836. package/vendor/impeccable/bundle/blobs/73f8bdec7d9a97476fd7d7e0b4114b5c3e9c7b84c22cbb876cd18c3e64a9b8c5 +42 -0
  837. package/vendor/impeccable/bundle/blobs/745b1f74877f6b3445da48af65dc45c66c3daa7738cb9a928aaa900889c2a204 +104 -0
  838. package/vendor/impeccable/bundle/blobs/74e20b26c29242bbebf79760315f7f0788e001566695618cfc70805484c6f92a +111 -0
  839. package/vendor/impeccable/bundle/blobs/754e9f0aa2101245a83cb17d8cc5bc49cf87997b29a83dedbfff283dbd0a8c4f +44 -0
  840. package/vendor/impeccable/bundle/blobs/765d3e890cd7f58ca94b6834181052166e9c4f9ef06278dc241da4d64da2d595 +113 -0
  841. package/vendor/impeccable/bundle/blobs/778cedc9199b407d3e23fa1041e38d548b00b1101a33517aa2a2eb299f9d0edc +26 -0
  842. package/vendor/impeccable/bundle/blobs/77ae09542fbc10aa4e8b119d6fd19359908a47c13c30068d6a150bfdb50e3e10 +24 -0
  843. package/vendor/impeccable/bundle/blobs/7848f40e224cf520bd8554943c9816a1ff8c97b1db57af0844e3b1ebb223d91f +416 -0
  844. package/vendor/impeccable/bundle/blobs/78c236dadb7e70337dc9dfa67e65fc15b7abed137ad320c16410ddfa7aec34f9 +131 -0
  845. package/vendor/impeccable/bundle/blobs/79114c6bf78b5a1838fe19bf033f3be85b232560eebf190ff8586aaec34ea170 +105 -0
  846. package/vendor/impeccable/bundle/blobs/796bbd8231413fcbf22eb7e6f40c402842aa4b10b1894545a7b05d9201ca7c4a +152 -0
  847. package/vendor/impeccable/bundle/blobs/79f85e381d1d6fdc8d39f54e1c8753fccf19b4ba3abb9827b6a7cc61eb376d1f +416 -0
  848. package/vendor/impeccable/bundle/blobs/7ad26830c7399a118cdbd4465a5426bc1919015aba99fd15959dc6deb8edc8d6 +80 -0
  849. package/vendor/impeccable/bundle/blobs/7af7fcc09c6b14f26ba78734460a2f9dddd2dcd2e2fa0c47c682f539e2f4cad5 +24 -0
  850. package/vendor/impeccable/bundle/blobs/7b1a4cc5ce94837c8309962a204c47361927e442b7a1c3cc472f90276eca8b8c +63 -0
  851. package/vendor/impeccable/bundle/blobs/7c417abe75f0ce4341b6f5acbadcafbbeabcc32cdb13c930aecc5cabda9f9242 +26 -0
  852. package/vendor/impeccable/bundle/blobs/7e36403ed58e0e82c0e42bf2fbea1c066b8e63276978647a6f1e44bf1edb23fb +63 -0
  853. package/vendor/impeccable/bundle/blobs/7fd1617d5a86b7a1a0bf9d6e291b334ac41a3efce31031eeaef11de7cd7e75b4 +325 -0
  854. package/vendor/impeccable/bundle/blobs/80191b3580a996a2045105976f728e0f46de22c412fc7640741add9767b2d8f4 +101 -0
  855. package/vendor/impeccable/bundle/blobs/808291e15746c9a64d9ede3ad3f06664b0a72970aa95052e064a96f1bfbed361 +54 -0
  856. package/vendor/impeccable/bundle/blobs/814610dee1081abc4213476ff0c4ae3e8f457909550d250ea0f89953687c85c6 +63 -0
  857. package/vendor/impeccable/bundle/blobs/8157b5a376e46980117f1ad6d08b24ee7be966f5de64b041bd213d486ea8c077 +26 -0
  858. package/vendor/impeccable/bundle/blobs/81666fc7f783b4e3514db6554e713dc0479bd9cdedb06e93d15f8b579aae869a +105 -0
  859. package/vendor/impeccable/bundle/blobs/835f19a0a3812f3652dd6979a2ce5597f654fd01f26e1b420b92d5f42b997ce4 +121 -0
  860. package/vendor/impeccable/bundle/blobs/8373668da1aa37c39888809ed9e834a7edfcb884af12f74934c270d004fba626 +85 -0
  861. package/vendor/impeccable/bundle/blobs/83d614fec61078175383012a088f49a9c0bb08b9ebd2b651c77cb94a323474ab +42 -0
  862. package/vendor/impeccable/bundle/blobs/8449781319a33d4a10a7fab9bfa4812241c303b95f33703b300b097dba51089a +152 -0
  863. package/vendor/impeccable/bundle/blobs/84a06415956986cb215139b3efda7b3c7a5bb6f502a3b3d9300f0744a970e620 +99 -0
  864. package/vendor/impeccable/bundle/blobs/857c4a0db5859f1fa91152db684528299dfc552525f50f416d1625a270e12671 +46 -0
  865. package/vendor/impeccable/bundle/blobs/86d10faab62da852aa1f4304157871545c853da708b6fe61c80aefb552c1f300 +84 -0
  866. package/vendor/impeccable/bundle/blobs/871a8e4d749b807c693ebabd83defbd6c76e1bd2a0f53a28a460cb1308ba8634 +318 -0
  867. package/vendor/impeccable/bundle/blobs/87b3db688c7963898bda8096f7868fed05ec5a0a80d14298e8b906b70cdf9c42 +416 -0
  868. package/vendor/impeccable/bundle/blobs/881a58aadf300bcc8f4947243e82192ae8dd7f14822a70fabc84fc74a5f9199c +46 -0
  869. package/vendor/impeccable/bundle/blobs/88549c11ea55d5dfc9f551db9a9c270d7362a9d42aa83db7747c9a7f020e1255 +46 -0
  870. package/vendor/impeccable/bundle/blobs/88749ebbe9bc87250765a07c2b959508262bd0e276ad60baa53e6e48c3579143 +806 -0
  871. package/vendor/impeccable/bundle/blobs/8a2d316593a631579bbb2f3fcb90d4488f85e97f69698dd2dd4fb50766f537d3 +325 -0
  872. package/vendor/impeccable/bundle/blobs/8c06daf096984cf71cf4133ea284dd6eaf503208da828816836ea41dfb69a234 +80 -0
  873. package/vendor/impeccable/bundle/blobs/8c34f78d71ac02c99303c7e0ca9ef30341aa9ecdeb75804dcba7e36a127914c1 +84 -0
  874. package/vendor/impeccable/bundle/blobs/8eb39a13e3d3650d4261f8fb06e91d6c0b888ca12ddbd3a5610cd8f0b05ad176 +69 -0
  875. package/vendor/impeccable/bundle/blobs/8ff60b8b5369d364f732f8de10479a39294e65341b3e0b6497b21de5c8e34b2d +806 -0
  876. package/vendor/impeccable/bundle/blobs/904859c8160b02330b04db23a8eeeb4ef55bcaa10f5208b8d73a1718334633e7 +84 -0
  877. package/vendor/impeccable/bundle/blobs/9205e222bc6565b37fb504ceec93233c2d2a456802b69d16e6b1c44723907c4c +5 -0
  878. package/vendor/impeccable/bundle/blobs/9287af96048c58ed0e72493cf7eb90c3957d4ba8b19e70ecf5d1f54264e9e597 +101 -0
  879. package/vendor/impeccable/bundle/blobs/92b7ab84c828fa888f4882c417c3d7f8fde2e5445b40f96f4fc8181a3e058afc +101 -0
  880. package/vendor/impeccable/bundle/blobs/93c53421c3376f695fe9dad5c82102f74bb5dd15e4ced81bb4ad50a71e5f1027 +24 -0
  881. package/vendor/impeccable/bundle/blobs/93eda27117930692a20f668f1cb0a80b7e14ab865998faba567cd721116081d4 +84 -0
  882. package/vendor/impeccable/bundle/blobs/94b4ce6299fea93d9f256b2d25705961a76bc5ea940c56db4145686ebc99df1b +89 -0
  883. package/vendor/impeccable/bundle/blobs/95b07450ad1ea0b7adc369587b06e52404945bbaa5d87f7491fac7ffd0e6e2ae +11 -0
  884. package/vendor/impeccable/bundle/blobs/95f0c7935a6d0375e09ae67ae0066c0ce7b583bf1d445d268cc4d2f4f900b1bb +113 -0
  885. package/vendor/impeccable/bundle/blobs/960cb922bc934adbf9192e9428ff6bec1f382038166f02a785939c93b7391067 +139 -0
  886. package/vendor/impeccable/bundle/blobs/96e2e6bd4fcf9a2c6da65fb029f96d9176308fae2efd9d8653d3b8d838960e07 +44 -0
  887. package/vendor/impeccable/bundle/blobs/96e508039c719c0815701c36b8418b18baee1967f915fa29b23b84861ae8ea94 +127 -0
  888. package/vendor/impeccable/bundle/blobs/98384b78af087855dbb526ec1e870a676ecd87f57237643dfea815317dad8a07 +26 -0
  889. package/vendor/impeccable/bundle/blobs/98afc4c6da252e90c6b783079b6f157bf94a13dd4351392e881edd2a100edf6a +105 -0
  890. package/vendor/impeccable/bundle/blobs/99e4a6facdb07986aa721bda8a4e35466b30091f32e38d7a71d9fcbe3591f65a +45 -0
  891. package/vendor/impeccable/bundle/blobs/9a2c08ee2516d2ee87129e7ebe6a0895f9990c9852d1f6fa7e70be9a6a88a659 +234 -0
  892. package/vendor/impeccable/bundle/blobs/9a4aa0d4903eabee987fdc92053466ff7f6eb0604797aee0efe67d67999b3eae +46 -0
  893. package/vendor/impeccable/bundle/blobs/9d45e5f6c082de6df4a2cfff11deb969715c49b5d9891d100dd1b2252c5bdcdd +152 -0
  894. package/vendor/impeccable/bundle/blobs/9db3c0857f4c2c8877b1fe24a47a229fee0de76ec9057bd8ee95f0677fb58d74 +26 -0
  895. package/vendor/impeccable/bundle/blobs/9e161532dc6731581d7a5f35bda5a2865e5248df7aff90e6dfc9221409893e35 +54 -0
  896. package/vendor/impeccable/bundle/blobs/9e82126a2e08aa365f9c430d383cf6e1921e04d1e0a1b5777716ff97828cfad8 +46 -0
  897. package/vendor/impeccable/bundle/blobs/9eb03b319ce7a2b281bc85ed1b0a437eb05ab2f765fc267354f9f9e6cbfadc25 +806 -0
  898. package/vendor/impeccable/bundle/blobs/9f1151faffbaadba0ddf5c09a4b2a82c9a12c900a2c1a9dac9863ba9ba0f420e +54 -0
  899. package/vendor/impeccable/bundle/blobs/9f2993499adadfdef4065a9a7fb69c75f888d892d4ee6bdbe62619bc772f495c +24 -0
  900. package/vendor/impeccable/bundle/blobs/a1a56df5fd51be403ca85a2f8054bb6f2bfeee443556c7798c2482e412fb6a09 +54 -0
  901. package/vendor/impeccable/bundle/blobs/a1af8b8a97665a3692eb39872c235796684a387a0b83785872f81aebd9dab046 +152 -0
  902. package/vendor/impeccable/bundle/blobs/a27399e3056c77a28ddd310fb5b4dee6e8e440dfa1737f7e38815097bec4c3a9 +46 -0
  903. package/vendor/impeccable/bundle/blobs/a423108e7e31a54564e2e0794186394f842625fd9f7d7ce6e6615362511503a2 +93 -0
  904. package/vendor/impeccable/bundle/blobs/a4cfd2330c8cca94b62986679b3f9e3bb9ada0cb30c2c63c5d19c6039f5a45ae +104 -0
  905. package/vendor/impeccable/bundle/blobs/a55f016c046cb6a27c55bd7f346375aeb506a755c4fbca19a5f92dbd42309c23 +59 -0
  906. package/vendor/impeccable/bundle/blobs/a569989e6a3d6453b4c45e9474e162a15cc54e11732ac6baa7990a6e7cccc0b5 +21 -0
  907. package/vendor/impeccable/bundle/blobs/a7045711a1f0dd2cd5bd98e57ff615f638d7e29738bdd618cf15e83fea5993b9 +325 -0
  908. package/vendor/impeccable/bundle/blobs/a75b892696469e3ccd2af33c9eef793e635efc3c5ac45336b0c1373d90c856b0 +63 -0
  909. package/vendor/impeccable/bundle/blobs/a7e8e60df83c6f47590467094ab2a13f1fe28ce45959a4e69dd89575a4208646 +47 -0
  910. package/vendor/impeccable/bundle/blobs/a7f036f4217933db8a96cf2f0ba251b15f388839d62bcf95720ce0b7152dd185 +806 -0
  911. package/vendor/impeccable/bundle/blobs/a892e337eee548d53252abb72ba5aa85cbcf556ffd8dc74e05534652c010d574 +24 -0
  912. package/vendor/impeccable/bundle/blobs/a93397adc906e245c69b42d4b25931fc92dc75baa60ca9a3749ba23b52ba01a0 +88 -0
  913. package/vendor/impeccable/bundle/blobs/a9856cb40da6519b1334bcfc75a4fbe83bef39ca86ee6f3effcb2a96794c627c +127 -0
  914. package/vendor/impeccable/bundle/blobs/a98b397cedeeaa1da57f3395b3d9b6c1fc477f4247fb9dc13e4da3da588283ff +54 -0
  915. package/vendor/impeccable/bundle/blobs/a9d2203acd45ca33a13d5c68b02b23ed512425ac15f0e8438318ed124b43729d +61 -0
  916. package/vendor/impeccable/bundle/blobs/a9e63b2df611805e845e0bb1cca1a0c27e83640a78185c9fd9de90d53a539cdc +42 -0
  917. package/vendor/impeccable/bundle/blobs/ab80e6a971baa66342548a846ce3fb69824ef9ef4e0f26c6f02685f225d00bbd +26 -0
  918. package/vendor/impeccable/bundle/blobs/ac695dd89d5f1261004cfa966526f5d5e913c92fa0640d4d71cb42493effad08 +131 -0
  919. package/vendor/impeccable/bundle/blobs/add1bee76f897f989166a5b9ad1b38d9173248e29d668d5c885ae9a0eff73861 +105 -0
  920. package/vendor/impeccable/bundle/blobs/af35b5fb6e45acb6483a5fbb864c3eaa9c57bacc43857f48183c836041c670ae +101 -0
  921. package/vendor/impeccable/bundle/blobs/af5842c4844b692b817319d5375611d4211dc7f459fb12da358baefc3a6cd373 +63 -0
  922. package/vendor/impeccable/bundle/blobs/b0e1a0721a1e47675a8750cfb608138743dd9fa9c047146e5cc8f82b9041be7a +806 -0
  923. package/vendor/impeccable/bundle/blobs/b14dc725606717be881a058bb691c0af1860cc8ad98d48e5a4789fe1a7de5458 +806 -0
  924. package/vendor/impeccable/bundle/blobs/b2732083f8f1d1924d38f84f179491430aebda8e0fd1f1d0785e3f883bcf3a40 +63 -0
  925. package/vendor/impeccable/bundle/blobs/b29e10f4506af2277739ad2373bc91c9fff41dbe76c9907f45152b4178cc6b6c +105 -0
  926. package/vendor/impeccable/bundle/blobs/b2d71ff0df7ed49e06dfc4acfce3d3f7eb48afa68be04763ee8c08354df50a07 +97 -0
  927. package/vendor/impeccable/bundle/blobs/b2f60e0154bf0e687badc46d8c8420e2118a9a6e21162050722be779dc02cb6d +111 -0
  928. package/vendor/impeccable/bundle/blobs/b314a0c5bd844f6471ea3031aeb9299674d972fbdd1615d99d16478de437d26d +84 -0
  929. package/vendor/impeccable/bundle/blobs/b3b1d5a4c80ce279d88896601deee9ccfeacdae0d0cd433600985a5f7ac93c72 +26 -0
  930. package/vendor/impeccable/bundle/blobs/b4be5499f404a926cdd2c55d8fb7409ba74a56b3d0c7d865594cc0254d3e499a +42 -0
  931. package/vendor/impeccable/bundle/blobs/b4def5b57733b6ba233570bd5691a536901f8b15479fc0111a2cde56224d0e1a +325 -0
  932. package/vendor/impeccable/bundle/blobs/b5f4fbb4a044c3f5ec14adc847222488f00fccabbf79ecd0b21084c8d319d616 +105 -0
  933. package/vendor/impeccable/bundle/blobs/b626e0677288a1660e9ce80c4f0454b527010239681f6b8dcc0f36b4a4d6bcb2 +113 -0
  934. package/vendor/impeccable/bundle/blobs/b6a2ef031313d3848ab2928875298550836f0f9ff7bdf5772e918c5c610ea448 +806 -0
  935. package/vendor/impeccable/bundle/blobs/b6dfd3df9a371e7d179d365cc1d72c11d4ed91b6507c0e1dbec0843419542f66 +84 -0
  936. package/vendor/impeccable/bundle/blobs/b719be9c5d4ced5d649ec6c0c90630196e7ee513d0da482aef13c705fdc23ab6 +113 -0
  937. package/vendor/impeccable/bundle/blobs/b7fcd2b03539d1029c8774fa806e6f4c677448e9e97e15f69b066022536c5491 +80 -0
  938. package/vendor/impeccable/bundle/blobs/b824bb76a657d3edd65e89807dcb21a3679eab39292423066e11368b35afba79 +325 -0
  939. package/vendor/impeccable/bundle/blobs/b8938fea3399aa639b4c873248035c219658069eef7be62672254e2f72c056f4 +42 -0
  940. package/vendor/impeccable/bundle/blobs/b8d49a3cab3428d9f351502e9c2c5802cef187e0d2af626ef3e1cd1837fd06bf +105 -0
  941. package/vendor/impeccable/bundle/blobs/ba0d96d88ab40fad1cb522e60b11affc568cfe9d340110ac5e71f834ac3d0f4a +42 -0
  942. package/vendor/impeccable/bundle/blobs/bb069b43c09109d7031b0374e31955749fec657b252d39782f11e8985aca2b51 +131 -0
  943. package/vendor/impeccable/bundle/blobs/bb36665889124a0b6e15f16045265737449c3bdcf2712cdb08af3cfa01563e2b +14 -0
  944. package/vendor/impeccable/bundle/blobs/bb59a1f78f3d2aa78e4b024fe203117155f50946a9e4bbe65c1b3b3abdcee356 +104 -0
  945. package/vendor/impeccable/bundle/blobs/bb9d4bb369216e892eea25adeaefc5a3e09bb4abd31e3475b79e47b3aee2a6af +806 -0
  946. package/vendor/impeccable/bundle/blobs/bc48bca63dff44e1f0205bafb64e16b2d6fb294ace405dbc9ae06a3bc6107154 +113 -0
  947. package/vendor/impeccable/bundle/blobs/bc5f71f1129d0f2c310d913d07c8dc609a1d25644121bd78c308f42d52a0b9e9 +86 -0
  948. package/vendor/impeccable/bundle/blobs/bcc05ea92faebb5c74037a9d4263a5ce9a56f5ab07c8ab3c59ee704d8cade745 +24 -0
  949. package/vendor/impeccable/bundle/blobs/bdd676c8f29295addfdbceaab285bb1184ec3ef7ff60501908b97ea8269580c4 +85 -0
  950. package/vendor/impeccable/bundle/blobs/bdf9a59beea111ac6f98f5624854feb5a5a1d60b1989edbbfabf3dc6f357a7e6 +105 -0
  951. package/vendor/impeccable/bundle/blobs/bdfd2a879ca65e437481eac5309f2283da225121630935d89ed902cfdf470c8e +105 -0
  952. package/vendor/impeccable/bundle/blobs/bea6ebfda78c51b9cf372097a1d77431d0f6bcd96eadec13a2ac95afbb87fb6d +104 -0
  953. package/vendor/impeccable/bundle/blobs/bf3b8883f8550744e08754af82a78939ab8b1237e5fad6f38d819e2f17e8a389 +104 -0
  954. package/vendor/impeccable/bundle/blobs/bf92a4a51b29de9661c5fa82f3d79244718a67d385ef661990f0c4a5b367e843 +104 -0
  955. package/vendor/impeccable/bundle/blobs/bfc51972fbf387566dc9e29c8b1af479a66ab401fdbce659fae9e6a5a9d85316 +69 -0
  956. package/vendor/impeccable/bundle/blobs/c06effcdc60859157208d3b7ee23d56160f2386f6a2dfa2514ba82fe21828ae0 +24 -0
  957. package/vendor/impeccable/bundle/blobs/c100b67a4ae248ad564182b181acb1ee2fe64c00049aeef62d4e7a3213726f37 +26 -0
  958. package/vendor/impeccable/bundle/blobs/c1cb6877ca99a0c1b38ba0c7d59f32702d3022f6821d8045f7133f7c40b6362f +242 -0
  959. package/vendor/impeccable/bundle/blobs/c1f3766091019b6f9183bc1d11b1e0fe03d44c168dc05a682c55df32f904dcfd +33 -0
  960. package/vendor/impeccable/bundle/blobs/c2dfc965319745c403b99e00e9e97de15f1300ea721bd3f708f0ac47aadc537b +101 -0
  961. package/vendor/impeccable/bundle/blobs/c327bf17f2af186f87164dee5fb5468746a9b137f0b604365d531ac9387f3712 +325 -0
  962. package/vendor/impeccable/bundle/blobs/c6b3bc811eb23d90ff9add1e0e5b40999a0bbbab364f5e6d08061f36d30429a5 +39 -0
  963. package/vendor/impeccable/bundle/blobs/c6f15d20d8d8748c4c475ff70cdb0ee426f2e6c9e7eab6169311f4dffd279ea1 +54 -0
  964. package/vendor/impeccable/bundle/blobs/c83d6a13fdfb58835c845f61aed3fc6dca17b5569d33387ced840bc13424f354 +84 -0
  965. package/vendor/impeccable/bundle/blobs/c9284892cb1f21aaeaf93fdf2e9e7a679d05e0baa8ddf309a79a9790d262ad38 +806 -0
  966. package/vendor/impeccable/bundle/blobs/cb8caddbb3919e5bf7f252143b519fb16db28a244642d937b186cb89962d9201 +828 -0
  967. package/vendor/impeccable/bundle/blobs/cbd8bd68fa00935dd0f179adb169252629cf7ee443ea9dc7db77e7ef2cf77446 +4 -0
  968. package/vendor/impeccable/bundle/blobs/cdf8a88b9865599c58fe285041d2d46eea7d9bd2d4075d82de358191742b20ad +46 -0
  969. package/vendor/impeccable/bundle/blobs/cf3d3a296890ac1ee363fee930f252e20d0935cd575367ad017b3cdc2dc5a50d +26 -0
  970. package/vendor/impeccable/bundle/blobs/d1366aa4802b364893c2a14b16fe95c3b7fab79f9f69eb272fd1538f7cb1ce2c +105 -0
  971. package/vendor/impeccable/bundle/blobs/d1fbd55074abb2251bdaa03749d34acc42c38e46e47549f18f5848df57d43c42 +86 -0
  972. package/vendor/impeccable/bundle/blobs/d2455359baf5f9e75360c7094e28a16937c8674619e07d58f30d2b5abfd31e53 +105 -0
  973. package/vendor/impeccable/bundle/blobs/d2e16da9bb6b33c931378d1bf57dcfff5dc426a71434bc352cec6aece715a66f +152 -0
  974. package/vendor/impeccable/bundle/blobs/d4a9e18a879bbb92aa0a56e16b45481090dffa4470efdecf52fb0da8c900be5d +46 -0
  975. package/vendor/impeccable/bundle/blobs/d57c3e0453f601ad688911fca4471057c7b46b561fcd42a1e12a581101c5186c +41 -0
  976. package/vendor/impeccable/bundle/blobs/d5f83912eda93d42f93522bb74aeff0ea04d9c559577ec52fcccc130dd03166d +137 -0
  977. package/vendor/impeccable/bundle/blobs/d6489d7f3e607ce3f8514a7a7d3a0eb5e8f1ac55859eaf7d5c31b53de8fab9f3 +152 -0
  978. package/vendor/impeccable/bundle/blobs/d658c48ffbe0031e8e3b318996cad6ceafe29e40aa50d5bb25e4bf1d6839dc7c +89 -0
  979. package/vendor/impeccable/bundle/blobs/d6a1fa1689642a6db9027493747d7ed54f9e0cae660472022c0a0a8dfdead3f4 +54 -0
  980. package/vendor/impeccable/bundle/blobs/d6a51f4df6d76f16b95ab81268a689f4c5936d505c5bb25c80ad7423f927bbc6 +47 -0
  981. package/vendor/impeccable/bundle/blobs/d7211a816aa8ca1111701930f7cdab82b4c8caa94c9a37522c1d7945209b01c2 +84 -0
  982. package/vendor/impeccable/bundle/blobs/d7b99a57652cb8741d57a15ba7e06de4707fac02a97e5e001179da007272f2b8 +113 -0
  983. package/vendor/impeccable/bundle/blobs/d87879329982d608866e4babd31c61438ec34c68483e529761fbf420203eeebd +104 -0
  984. package/vendor/impeccable/bundle/blobs/d9963fd73bf6129fe0c8ec25c5148f50617ec85683b8eeae7e411c9a42e2db33 +137 -0
  985. package/vendor/impeccable/bundle/blobs/da3b2399814db89d67959268c646601957d3e8c641b09a5bdbce84217c1c2cfe +46 -0
  986. package/vendor/impeccable/bundle/blobs/dc3aeccbea3e997704ce8b170f56b0eaf343a14ad4fedb22a6dbee0f205aa37f +47 -0
  987. package/vendor/impeccable/bundle/blobs/dcc1572e739cdabcbf084f276b447cb686aa18459896e6d8fe29f4d7d807bd1d +46 -0
  988. package/vendor/impeccable/bundle/blobs/dcf7340da023e64144af5768b8bf44ecf45b1bfdec12d3b1c9e6618f17f8c60a +131 -0
  989. package/vendor/impeccable/bundle/blobs/dd66761b291c7dbca6e9efd22023e38f8c53ad310f3a6cdab5dc7ecd7ae8f31f +84 -0
  990. package/vendor/impeccable/bundle/blobs/dd953992625c240fd1842aaf533a865aabd09487cbc16fa01fe8bb4b4365b843 +101 -0
  991. package/vendor/impeccable/bundle/blobs/de1b7404f4cdfd7b515196afb17b74b1980f0bc88cb8681ae93a76ca48ec7bdb +167 -0
  992. package/vendor/impeccable/bundle/blobs/de70398719140e4951aa111e9625de5ed916ad1ef0877e4ab6f6b4a7e3cc5f8f +154 -0
  993. package/vendor/impeccable/bundle/blobs/deaaa533475b6a9f7dd52e01a1f1997aa3af146694334981650f8c846f939559 +113 -0
  994. package/vendor/impeccable/bundle/blobs/df23e9ee5b689a05ed88f42e9a36aaffa2e6e28b1d56e2832acaa1d3603fd363 +105 -0
  995. package/vendor/impeccable/bundle/blobs/dfd6f341b156bc604e7556b27cba437d5870fbc82d4c673d0127cf18151b2226 +99 -0
  996. package/vendor/impeccable/bundle/blobs/e02ba7f4417e84b3bd5ec65287c4a14cf163ca3ac6f8ee37d8f709d0c8b0b6d2 +84 -0
  997. package/vendor/impeccable/bundle/blobs/e07176229b8a330970ca3c9c5e3dd68c2aaeb726285e30f471e91053d7f8e798 +24 -0
  998. package/vendor/impeccable/bundle/blobs/e1075ea5b34ac9c60f7c5bda97356eeaf1b683b599592d324fd3704f0852ad7a +152 -0
  999. package/vendor/impeccable/bundle/blobs/e26ddd48211aae08fe6debf2a7a4308aa081ed224668cde528e451888db0e3e3 +325 -0
  1000. package/vendor/impeccable/bundle/blobs/e2e275495354eeccb7e59af7d74e2ff1f371839bd6aaec1266428760995fb24c +104 -0
  1001. package/vendor/impeccable/bundle/blobs/e3af212117e0c552b0976687200fe8f95846a01725a482e8e4dbfd75e40dbfa6 +26 -0
  1002. package/vendor/impeccable/bundle/blobs/e3c2031978cd670d7150ff3140f12cf8b6882ef638ea9a9985caffa9a80c8713 +63 -0
  1003. package/vendor/impeccable/bundle/blobs/e44ca51f24c4736f9aee6024182b0409aa12ec94812b7ec94745e0999ed06a70 +29 -0
  1004. package/vendor/impeccable/bundle/blobs/e68467ba99684d8c975a8a2725145d29db41d70659c7544ea54cc6632660cea3 +127 -0
  1005. package/vendor/impeccable/bundle/blobs/e6e18e7c23cfe82961d90b9714cb466c20bd83f222ac63e9339b6b2c304e1787 +26 -0
  1006. package/vendor/impeccable/bundle/blobs/e71524578eb2bda3b8d2da3d8b8371239a2179c5fa866f9f7e48bcac45a8cd6f +84 -0
  1007. package/vendor/impeccable/bundle/blobs/e7af7ad18b307a3171fcf49421df2a557f93289d27af2430f10ee74e2a2fc2d3 +101 -0
  1008. package/vendor/impeccable/bundle/blobs/e7dd10af2c3c18c60dc20734d55ff870c323a10dadd337600f7bb980fc6b53c8 +327 -0
  1009. package/vendor/impeccable/bundle/blobs/e802e4f7bdc89050a9c0f2ca506e1d493a2316e6e810c0336c57aa073717ef3e +50 -0
  1010. package/vendor/impeccable/bundle/blobs/e85da3098368807689009184eca2bb09a91bdb6cb1be3e7a61f91f1ae31cd69b +152 -0
  1011. package/vendor/impeccable/bundle/blobs/e8720f3aa41135211cc58cc299a39eeda86c75651f4279cc1ede8db10dcc0584 +98 -0
  1012. package/vendor/impeccable/bundle/blobs/e8ee6c08e94b80324173d89d6f4cdc5b4829ea6858b3a11fc186588a490cada4 +46 -0
  1013. package/vendor/impeccable/bundle/blobs/e9861052457cc1ddc42c687bb8c33a877834ced94fed74af2a4f00f6bae50795 +101 -0
  1014. package/vendor/impeccable/bundle/blobs/ea8432c90c30ecb0426662a681ead5c0941113079704e1a766cda09e85b15b4f +111 -0
  1015. package/vendor/impeccable/bundle/blobs/eaa50e8cd95e00a94a257db2bff4eafd820696ba75a08a384a00517c3402924e +325 -0
  1016. package/vendor/impeccable/bundle/blobs/eb3e86876c20f1cfc443dcbe48d8f41fea6e815082a304610be432272429a06d +42 -0
  1017. package/vendor/impeccable/bundle/blobs/eba472f6190541c28e2e647ed019f43564ba5b92d629963f34c899175b25b31e +46 -0
  1018. package/vendor/impeccable/bundle/blobs/eba609589a5a051643a7bae60b7cceef7cfe44d0f8bd9229e61473ac75910fb3 +24 -0
  1019. package/vendor/impeccable/bundle/blobs/ec6338b20047099601e4bac8b2efcd597f800d5e437259f6c15d23090400621b +325 -0
  1020. package/vendor/impeccable/bundle/blobs/ec81b008d2641402e3352b09b1a90562ef7a24598d7c5aded475038cce63aca0 +24 -0
  1021. package/vendor/impeccable/bundle/blobs/ec86b8633fbeb14ef2272f220fdd98089972b03b99da83e49eeb6a8b73b00617 +113 -0
  1022. package/vendor/impeccable/bundle/blobs/ee6d6d127c1c2ab3526d529a8e3698be2185b5e346ac617f37501de2c0698b97 +99 -0
  1023. package/vendor/impeccable/bundle/blobs/ef2dde00030580ed2765cbf7be9b2ea4a6f64cb915b804fd6f6abcf38051c7b9 +234 -0
  1024. package/vendor/impeccable/bundle/blobs/ef2e97cd690baf6fe5c895dd2d8844aff9fcc4a8bc04973402678a739c81d712 +90 -0
  1025. package/vendor/impeccable/bundle/blobs/f0fbe529f63961a027bada2e6a3cbe86f4af0dba4b8e1010da22b007f9002f66 +63 -0
  1026. package/vendor/impeccable/bundle/blobs/f1601095679d7d8cf6fef6845598c70d8734190709c1404fa0026e28fef2faaa +325 -0
  1027. package/vendor/impeccable/bundle/blobs/f254d59ff973e907cacdc2c34b8b4de075437d292de31dac30e10a9d7035086c +85 -0
  1028. package/vendor/impeccable/bundle/blobs/f5efb1b1dd4cd18e1d4789d7c8e0188f4342b25fffd53af6088ba8b67774fb99 +26 -0
  1029. package/vendor/impeccable/bundle/blobs/f672ef8251a3ed4051a053d30819664951b17540b2899acd27d20e500c234abc +258 -0
  1030. package/vendor/impeccable/bundle/blobs/f68a3d68ac92606e91aa8878e003d9432ddd09aa97ca01c6b3ce46c937dca316 +13510 -0
  1031. package/vendor/impeccable/bundle/blobs/f7a9e3f30fe07b0d98351730e9895d50bba96dd42fe91c0d9b9a76ef62e53322 +80 -0
  1032. package/vendor/impeccable/bundle/blobs/f7b854effc55c8f07e40a415e0d6b5c333f4042fbc849fac73d52619c8d053a1 +54 -0
  1033. package/vendor/impeccable/bundle/blobs/f84b653ede0804d21e6210c6d21fd5352023914fedceae6ff14e20f1e93b06e7 +46 -0
  1034. package/vendor/impeccable/bundle/blobs/f964506c0fae87b3c2c1db7016ddc9be9ef970bbcf5548d684b997b5d5991586 +33 -0
  1035. package/vendor/impeccable/bundle/blobs/f9cbbad0cc08fb9bd69d4d3046067c6cf820b89cdaf7af8c81c671fb0a62b6ae +54 -0
  1036. package/vendor/impeccable/bundle/blobs/fb32d99751c5fc24493ff4460be1767bd5236dc820fd337775067c0620d1a7a6 +113 -0
  1037. package/vendor/impeccable/bundle/blobs/fb5fec24adafa48df43eece6907c1c986a4772cbdc64142c881f00c3b312e9ca +152 -0
  1038. package/vendor/impeccable/bundle/blobs/fc149b5bc7a8d0cc9b9bf86e5013793f3857c1c302212e9aaf101cb95427386b +101 -0
  1039. package/vendor/impeccable/bundle/blobs/fce6688138d2ceb1e3d2cde5231f54b1d8dc8748b4c95a7919aa83b6f924cf96 +127 -0
  1040. package/vendor/impeccable/bundle/blobs/fe91fcf28638f95577af481a50edaf339d6c9a3ad3b9fa477bc81c116b8bc392 +139 -0
  1041. package/vendor/impeccable/bundle/blobs/ff0ab1361f52d70d3ff0d23090d78794a75afdfa2f8c1cee5491dee69215faaa +105 -0
  1042. package/vendor/impeccable/bundle/manifest.json +1254 -0
  1043. package/skills/dev-plan/evals/evals.json +0 -72
@@ -0,0 +1,1420 @@
1
+ #!/usr/bin/env bash
2
+ # portal-dev-setup — 在【你自己 App 的 repo 里】起一个真实门户(一盒 / one-box)用于本地联调。
3
+ #
4
+ # onebox.sh init --key <你的listingKey> [--image <门户镜像tag>]
5
+ # 首次用:登录仓库并拉门户镜像 → 从镜像里取出 compose 资产 →
6
+ # 生成 compose.env(挑空闲端口、随机密钥),落在 ./portal-onebox/。
7
+ # 已存在的 compose.env 不覆盖(要整份重来加 --force)。
8
+ # 不给 --image 就用 <REGISTRY>/<PROJECT>/one-box:latest —— 一盒
9
+ # 和它的反代都挂了 latest,开新项目不用先去问 tag。
10
+ # onebox.sh up ★ 按顺序把整套铺起来(迁移→种子→各库→注册→起栈),幂等可重跑。
11
+ # 顺序本身是契约(种子会 truncate、反代启动时才读 /svc map),
12
+ # 这条命令就是为了不让人自己记它。
13
+ # onebox.sh upgrade [--image <ref>] [--proxy-image <ref>]
14
+ # 换部署资产并追加版本信息;保留现有配置、端口、密钥与数据,再跑 up。
15
+ # onebox.sh doctor ★ 体检:把排查表里能自动判的都判一遍,每条给一行可直接粘的修法。
16
+ # 跑不通先跑它,别翻文档。
17
+ # onebox.sh add <key> ★ 把一个平台侧 App 拉进来陪调(如 omni-parser 多模态解析):
18
+ # 注册清单 + 建库 + 起容器。非破坏性、幂等。
19
+ # onebox.sh pull 只(重)拉门户镜像 —— 换版本、或 latest 移动过之后用
20
+ # onebox.sh env 生效的关键 env + 配置告警(同键多值、端口、NODE_ENV…)
21
+ # onebox.sh status env 摘要 + 容器状态 + 宿主侧健康探测
22
+ # onebox.sh smoke 只跑宿主侧健康探测
23
+ # onebox.sh chain 打印它将要用的那串 compose 参数
24
+ # onebox.sh dc <args...> docker compose <拼好的参数> <args...>
25
+ #
26
+ # 【拉取凭证】镜像仓库不开放匿名拉取,需要一份只读 puller 凭证。按顺序找第一个存在的:
27
+ # $XGENT_REGISTRY_CONFIG → ./.xgent-registry.env → ${XDG_CONFIG_HOME:-~/.config}/xgent/registry.env
28
+ # → ~/.xgent-registry.env → <skill 目录>/registry.env
29
+ # KEY=value 三项:REGISTRY(域名,不带协议)· PULLER_AUTH(base64 的「用户名:口令」)·
30
+ # ONEBOX_PROJECT(【门户一盒镜像】所在的项目名 —— 省掉 --image 时用它拼
31
+ # <REGISTRY>/<ONEBOX_PROJECT>/one-box:latest)。⚠️ 它多半【不等于】PROJECT:后者是
32
+ # xgent-image-push 用来推【你自己 App 镜像】的项目,两者同仓不同项目。缺 ONEBOX_PROJECT
33
+ # 时才回退到 PROJECT(老配置兼容),拿它拼出来的引用十有八九 not found。
34
+ # 同名环境变量优先,CI 里注入即可不必落盘。模板:<skill 目录>/puller.env.example
35
+ # 两个镜像本地都已有(比如 docker load 的离线 tar)时会跳过登录与拉取。
36
+ #
37
+ # 【一套就够】一台机器只跑一套一盒,compose 项目名固定 xgent-onebox —— 它不属于某个 App,
38
+ # 本机要联调的 App 都接进这同一套(add 拉平台侧 App / XGENT_ONEBOX_HOME 复用栈 /
39
+ # 宿主进程直连它的 pg/redis/minio,见 SKILL.md §5)。init 发现本机已有别的一盒会停下。
40
+ #
41
+ # 【一盒目录】放 docker-compose.yml 与 compose.env 的那个,按序查找:
42
+ # $XGENT_ONEBOX_HOME → ./portal-onebox → ./deploy → <git 根>/portal-onebox → <git 根>/deploy
43
+ # 判据是同时有 docker-compose.yml 与 onebox/docker-compose.onebox.yml —— 你自己 repo 里
44
+ # 那个装别的东西的 deploy/ 不会被误认。
45
+ set -euo pipefail
46
+
47
+ c_red=$'\033[31m'; c_grn=$'\033[32m'; c_ylw=$'\033[33m'; c_dim=$'\033[2m'; c_off=$'\033[0m'
48
+ warn() { printf '%s! %s%s\n' "$c_ylw" "$*" "$c_off"; }
49
+ info() { printf '%s>%s %s\n' "$c_dim" "$c_off" "$*"; }
50
+ die() { printf '%sERROR: %s%s\n' "$c_red" "$*" "$c_off" >&2; exit 1; }
51
+
52
+ SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
53
+
54
+ # --- 镜像仓库凭证 -------------------------------------------------------------
55
+ # 仓库域名与口令都不写在这个 skill 里(域名属内部信息,口令是密钥)。与仓内推镜像那套
56
+ # 用同一份 .xgent-registry.env,只是这里读的是【只读】的 puller 那两项。
57
+ load_registry_config() {
58
+ local c f key val
59
+ if [ -z "${REGISTRY_CONFIG:-}" ]; then
60
+ for c in "${XGENT_REGISTRY_CONFIG:-}" "$PWD/.xgent-registry.env" \
61
+ "${XDG_CONFIG_HOME:-$HOME/.config}/xgent/registry.env" \
62
+ "$HOME/.xgent-registry.env" "$SKILL_DIR/registry.env"; do
63
+ [ -n "$c" ] && [ -f "$c" ] && { REGISTRY_CONFIG="$c"; break; }
64
+ done
65
+ fi
66
+ f="${REGISTRY_CONFIG:-}"
67
+ [ -n "$f" ] && [ -f "$f" ] || return 0
68
+ while IFS= read -r line || [ -n "$line" ]; do
69
+ case "$line" in ''|'#'*) continue ;; esac
70
+ key="${line%%=*}"; val="${line#*=}"
71
+ case "$key" in *[!A-Za-z0-9_]*|"") continue ;; esac
72
+ val="${val%\"}"; val="${val#\"}"; val="${val%\'}"; val="${val#\'}"
73
+ case "$key" in
74
+ REGISTRY|PROJECT|ONEBOX_PROJECT|PULLER_AUTH|MANIFEST_STORE|MANIFEST_STORE_READ_TOKEN) [ -n "${!key:-}" ] || printf -v "$key" '%s' "$val" ;;
75
+ esac
76
+ done < "$f"
77
+ # base64 不是加密,同组可读就等于把口令摊在那儿
78
+ if [ -n "${PULLER_AUTH:-}" ]; then
79
+ # Only the permission field is read; the filename is never parsed.
80
+ # shellcheck disable=SC2012
81
+ case "$(ls -l "$f" | cut -c1-10)" in ??????---*) ;; *) warn "$f 含 PULLER_AUTH 且同组/其他人可读 —— chmod 600 $f";; esac
82
+ fi
83
+ }
84
+
85
+ require_puller() {
86
+ load_registry_config
87
+ if [ -z "${REGISTRY:-}" ] || [ -z "${PULLER_AUTH:-}" ]; then
88
+ die "$(cat <<MSG
89
+ 没有 puller 凭证,拉不到门户镜像 —— 仓库不开放匿名拉取,一盒起不来。
90
+
91
+ 先找【你们自己的开发团队】要一份 puller key:这是一对只读拉取凭证,按团队发放,
92
+ 不是谁的个人密码(一个团队共用一份,有人离职要找他们轮换)。拿到后:
93
+
94
+ cp "$SKILL_DIR/puller.env.example" ./.xgent-registry.env
95
+ chmod 600 ./.xgent-registry.env
96
+
97
+ 填两项:
98
+ REGISTRY=<仓库域名> # 不带 https://、不带端口、无尾斜杠
99
+ PULLER_AUTH=<base64> # base64 的「用户名:口令」
100
+
101
+ PULLER_AUTH 就是 ~/.docker/config.json 里 auths.<REGISTRY>.auth 那个值;
102
+ 自己算: printf '%s' '<用户名>:<口令>' | base64
103
+
104
+ 查找顺序:\$XGENT_REGISTRY_CONFIG → ./.xgent-registry.env →
105
+ \${XDG_CONFIG_HOME:-~/.config}/xgent/registry.env → ~/.xgent-registry.env →
106
+ $SKILL_DIR/registry.env
107
+ 同名环境变量优先,CI 里注入 REGISTRY / PULLER_AUTH 即可,不必落盘。
108
+
109
+ ⚠️ base64 不是加密,base64 -d 一条命令就还原成明文:别提交进 git,别转发出团队。
110
+ 已经拿到离线镜像 tar 的,先 docker load 两个镜像,本脚本会跳过拉取这一步。
111
+ MSG
112
+ )"
113
+ fi
114
+ case "$REGISTRY" in *://*) die "REGISTRY 不要带协议(去掉 http:// 或 https://):$REGISTRY";; esac
115
+ case "$REGISTRY" in */*) die "REGISTRY 只写域名,别带项目名:$REGISTRY";; esac
116
+ local dec
117
+ dec="$(printf '%s' "$PULLER_AUTH" | base64 -d 2>/dev/null || printf '%s' "$PULLER_AUTH" | base64 -D 2>/dev/null || true)"
118
+ case "$dec" in
119
+ *:*) PULLER_USER="${dec%%:*}"; PULLER_SECRET="${dec#*:}" ;;
120
+ *) die "PULLER_AUTH 不是 base64 的「用户名:口令」。自己算一遍:printf '%s' '<用户名>:<口令>' | base64" ;;
121
+ esac
122
+ }
123
+
124
+ registry_login() {
125
+ info "登录 ${REGISTRY}(用户 ${PULLER_USER},只读)…"
126
+ printf '%s' "$PULLER_SECRET" | docker login "$REGISTRY" -u "$PULLER_USER" --password-stdin >/dev/null 2>&1 \
127
+ || die "docker login $REGISTRY 失败。口令可能已被轮换 —— 先 docker logout $REGISTRY 再让开发团队补一份新的 PULLER_AUTH。(陈旧凭证不会提示你去登录,只会一直 401。)"
128
+ }
129
+
130
+ # do_pull REF HINT [PLATFORM] —— docker pull 的 "What's Next" 提示走 stderr,>/dev/null 挡不住;
131
+ # 但 2>&1 会把真错误一起吞掉,所以收进临时文件、只在失败时回显。
132
+ do_pull() {
133
+ local ref="$1" hint="$2" errf; errf="$(mktemp)"
134
+ local -a pf=(); [ -n "${3:-}" ] && pf=(--platform "$3")
135
+ info "拉 ${ref}${3:+(${3})} …"
136
+ if ! docker pull ${pf[@]+"${pf[@]}"} "$ref" >/dev/null 2>"$errf"; then
137
+ local msg; msg="$(tail -3 "$errf")"; rm -f "$errf"
138
+ die "docker pull $ref 失败。${hint:+$hint
139
+ }$msg"
140
+ fi
141
+ rm -f "$errf"
142
+ }
143
+
144
+ # pull_images RUNTIME PROXY —— 两个镜像本地都在就跳过(离线 docker load 的场合)
145
+ pull_images() {
146
+ local rt="$1" px="$2"
147
+ if docker image inspect "$rt" >/dev/null 2>&1 && docker image inspect "$px" >/dev/null 2>&1; then
148
+ info "两个镜像本地已有,跳过拉取(要强制重拉用 $0 pull --image ${rt})"
149
+ return 0
150
+ fi
151
+ local host="${rt%%/*}"
152
+ case "$host" in
153
+ *.*|*:*) ;; # 带域名的私有仓
154
+ *) host="" ;; # 没有域名段 = docker hub
155
+ esac
156
+ require_puller
157
+ if [ -n "$host" ] && [ "$host" != "$REGISTRY" ]; then
158
+ die "镜像域名(${host})与配置里的 REGISTRY(${REGISTRY})对不上 —— 登录 A 却去 B 拉,必然 401。对齐这两个再来。"
159
+ fi
160
+ registry_login
161
+ do_pull "$rt" "两种可能,按顺序查:① 项目名不对 —— 一盒镜像与你自己 App 的镜像【不在同一个项目】下(配 ONEBOX_PROJECT,或直接 --image 给全);② tag 写错 —— 一盒只有 :latest(可变指针)和 :v<版本>-<7位sha>(钉住某一版)两种。"
162
+ do_pull "$px" "代理镜像名是从 runtime 镜像推出来的(同仓同版本、仓库名 proxy),有的部署不叫这个 —— 用 --proxy-image 显式指定。"
163
+ }
164
+
165
+ # 不给 --image 时用的默认镜像。一盒与它的反代都挂了 latest 指针 —— 这类镜像是【给人手工
166
+ # docker pull】的调试件,没有"部署侧按镜像引用触发重建"那条链,可变 tag 的代价不成立,
167
+ # 而"新人不知道该用哪个 tag"这个洞是真的。要钉住某一版就显式 --image <...>:v<版本>-<sha>。
168
+ default_image() {
169
+ load_registry_config
170
+ # ⚠️ 一盒镜像与【你自己 App 的镜像】不在同一个项目下。ONEBOX_PROJECT 是前者;
171
+ # PROJECT 是后者(xgent-image-push 推镜像用的那个)。只有 ONEBOX_PROJECT 缺席时才
172
+ # 回退到 PROJECT —— 那是老配置的兼容路径,拼出来的引用多半 not found,所以回退时
173
+ # 明说一句,别让人对着一个指错方向的 404 猜 tag。
174
+ local proj="${ONEBOX_PROJECT:-}"
175
+ if [ -z "$proj" ] && [ -n "${PROJECT:-}" ]; then
176
+ proj="$PROJECT"
177
+ warn "配置里没有 ONEBOX_PROJECT,回退用 PROJECT=${PROJECT} 拼一盒镜像 —— 那通常是【推你自己 App 镜像】的项目,不是一盒所在的项目。拉不到就去问开发团队要一盒的项目名,填进 ONEBOX_PROJECT。"
178
+ fi
179
+ [ -n "${REGISTRY:-}" ] && [ -n "$proj" ] || return 1
180
+ printf '%s/%s/one-box:latest' "$REGISTRY" "$proj"
181
+ }
182
+
183
+ # --- 定位一盒目录 -------------------------------------------------------------
184
+ find_home() {
185
+ local d git_root
186
+ if [ -n "${XGENT_ONEBOX_HOME:-}" ]; then printf '%s' "$XGENT_ONEBOX_HOME"; return; fi
187
+ git_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
188
+ for d in ./portal-onebox ./deploy ${git_root:+"$git_root/portal-onebox" "$git_root/deploy"}; do
189
+ [ -f "$d/docker-compose.yml" ] && [ -f "$d/onebox/docker-compose.onebox.yml" ] && { (cd "$d" && pwd); return; }
190
+ done
191
+ printf ''
192
+ }
193
+
194
+ require_home() {
195
+ HOME_DIR="$(find_home)"
196
+ [ -n "$HOME_DIR" ] || die "没找到一盒目录(要有 docker-compose.yml + onebox/docker-compose.onebox.yml)。首次用先跑: $0 init --image <门户镜像tag> --key <你的listingKey>"
197
+ ENV_FILE="$HOME_DIR/compose.env"
198
+ [ -f "$ENV_FILE" ] || die "$HOME_DIR 里没有 compose.env。跑 $0 init 生成,或手工按 compose.env.example 拼。"
199
+ }
200
+
201
+ # --- env-file 解析(docker compose 是「后定义者胜」,这份文件是拼装出来的)--------
202
+ _assignments() {
203
+ awk '/^[A-Za-z_][A-Za-z0-9_]*=/ {
204
+ k = $0; sub(/=.*/, "", k)
205
+ v = $0; sub(/^[^=]*=/, "", v)
206
+ sub(/^"(.*)"$/, "\\1", v); sub(/^'"'"'(.*)'"'"'$/, "\\1", v)
207
+ printf "%d\t%s\t%s\n", NR, k, v
208
+ }' "$ENV_FILE"
209
+ }
210
+ _eff() { # _eff KEY [default]
211
+ local v; v="$(_assignments | awk -F'\t' -v k="$1" '$2==k{v=$3} END{print v}')"
212
+ [ -n "$v" ] && printf '%s' "$v" || printf '%s' "${2-}"
213
+ }
214
+
215
+ load_env() {
216
+ APP_KEY="$(_eff APP_KEY)"; APP_IMAGE="$(_eff APP_IMAGE)"; APP_FRONTEND_DIST="$(_eff APP_FRONTEND_DIST)"
217
+ CATALOG="$(_eff XGENT_APP_CATALOG files,llm-gateway,git,org,observability,user-center)"
218
+ HTTP_PORT="$(_eff HTTP_PORT 80)"; COMPOSE_PROJECT="$(_eff COMPOSE_PROJECT_NAME xgent)"
219
+ BASE_URL="http://localhost"; [ "$HTTP_PORT" = "80" ] || BASE_URL="http://localhost:$HTTP_PORT"
220
+ }
221
+
222
+ # --- compose 参数拼装 ---------------------------------------------------------
223
+ # app-dev.yml 里的 ${APP_IMAGE:?} / ${APP_KEY:?} 是【解析期】求值的(与 profile 无关),
224
+ # 所以还没填自己 App 那两行时必须整层不带,否则连 ps 都跑不了。
225
+ compose_args() {
226
+ printf '%s\0' --env-file "$ENV_FILE" \
227
+ -f "$HOME_DIR/docker-compose.yml" \
228
+ -f "$HOME_DIR/onebox/docker-compose.onebox.yml"
229
+ if [ -n "$APP_KEY" ] && [ -n "$APP_IMAGE" ]; then
230
+ printf '%s\0' -f "$HOME_DIR/app-devkit/docker-compose.app-dev.yml"
231
+ [ -n "$APP_FRONTEND_DIST" ] && printf '%s\0' -f "$HOME_DIR/app-devkit/docker-compose.app-frontend.yml"
232
+ printf '%s\0' --profile app-external
233
+ fi
234
+ printf '%s\0' --profile local-infra
235
+ local k; for k in ${CATALOG//,/ }; do
236
+ _is_portal_hosted "$k" && continue
237
+ printf '%s\0' --profile "app-$k"
238
+ # 清单型 App(onebox.sh add 生成过片段的)也归 dc 管:这样 up/ps/logs/down 都看得见它们,
239
+ # 而不是只有 add 那一次 -f 才带上。
240
+ [ -f "$HOME_DIR/generated/$k.yml" ] && printf '%s\0' -f "$HOME_DIR/generated/$k.yml"
241
+ [ -f "$SKILL_DIR/services/$k.extra.yml" ] && printf '%s\0' -f "$SKILL_DIR/services/$k.extra.yml"
242
+ done
243
+ # 门户日志采集段已并入 docker-compose.onebox.yml。这行只为【老抽取资产】的家目录兜底:
244
+ # 那些 portal-onebox/ 里还有独立的 portal-logs.yml(旧镜像取出的),照老规矩叠加;
245
+ # 新资产里文件不存在,[ -f ] 自动跳过。
246
+ _has_catalog observability && [ -f "$HOME_DIR/onebox/docker-compose.portal-logs.yml" ] \
247
+ && printf '%s\0' -f "$HOME_DIR/onebox/docker-compose.portal-logs.yml"
248
+ return 0
249
+ }
250
+ _has_catalog() { case ",$CATALOG," in *",$1,"*) return 0;; *) return 1;; esac; }
251
+ # 用户中心只有身份 owner 清单,运行时由 portal-api 承载,无独立库、容器与 /svc。
252
+ _is_portal_hosted() { [ "$1" = "user-center" ]; }
253
+ # 目录里「清单型」的 key = 一盒镜像/目录里有 app-devkit/manifests/<key>.manifest.json 且不是门户内置 workspace
254
+ _is_manifest_app() { [ -f "$HOME_DIR/app-devkit/manifests/$1.manifest.json" ]; }
255
+ dc() { local a=(); while IFS= read -r -d '' x; do a+=("$x"); done < <(compose_args); docker compose "${a[@]}" "$@"; }
256
+
257
+ # --- init ---------------------------------------------------------------------
258
+ port_free() { ! (exec 3<>"/dev/tcp/127.0.0.1/$1") >/dev/null 2>&1; }
259
+ pick_port() { local p; for p in "$@"; do port_free "$p" && { printf '%s' "$p"; return; }; done; printf '%s' "$1"; }
260
+ rand_hex() { openssl rand -hex 32 2>/dev/null || head -c32 /dev/urandom | od -An -tx1 | tr -d ' \n'; }
261
+
262
+ _image_version() {
263
+ local image="$1" id created
264
+ id="$(docker image inspect "$image" --format '{{.Id}}' 2>/dev/null | cut -c8-14 || true)"
265
+ created="$(docker image inspect "$image" --format '{{.Created}}' 2>/dev/null | cut -c1-10 || true)"
266
+ [ -z "$id" ] || printf 'onebox %s %s%s' "${image##*:}" "$id" "${created:+ built ${created}}"
267
+ }
268
+
269
+ # Shared by init and upgrade. Machine-owned state must never come from an image.
270
+ _extract_assets() {
271
+ local image="$1" home="$2" postgres_volume="${3:-}" tmp cid
272
+ info "从 ${image} 取出 compose 资产…"
273
+ tmp="$(mktemp -d)"
274
+ cid="$(docker create "$image")" || { rm -rf "$tmp"; die "docker create 失败,请确认镜像已就位。"; }
275
+ if ! docker cp "$cid:/app/deploy" "$tmp/deploy" >/dev/null; then
276
+ docker rm -f "$cid" >/dev/null; rm -rf "$tmp"
277
+ die "镜像里没有 /app/deploy,请使用门户一盒镜像。"
278
+ fi
279
+ docker rm -f "$cid" >/dev/null
280
+ if ! grep -qE '^ rustfs:' "$tmp/deploy/docker-compose.yml" \
281
+ || [ ! -f "$tmp/deploy/scripts/objectstore-cutover.sh" ] \
282
+ || [ ! -f "$tmp/deploy/scripts/objectstore-manifest.ts" ]; then
283
+ rm -rf "$tmp"; die "镜像里的对象存储资产还是旧版,请 upgrade --image <新版一盒镜像>。"
284
+ fi
285
+ ( cd "$tmp/deploy" && rm -rf .DS_Store k8s oauth pm2 caddy knowledge-devkit onebox/Dockerfile \
286
+ compose.env generated backup scripts/tests \
287
+ app-devkit/manifests/pagebuilder.manifest.json app-devkit/manifests/task-gateway.manifest.json )
288
+ # Persist volume identity in staging before replacing assets. If a later version
289
+ # check refuses an unknown layout, the next run must still find the same data.
290
+ if [ -n "$postgres_volume" ]; then
291
+ if ! awk -v volume="$postgres_volume" '
292
+ /^volumes:/{volumes=1}
293
+ volumes && /^ pg-data:/{print " pg-data:"; print " name: " volume; pg=1; count++; next}
294
+ volumes && /^ [A-Za-z0-9_-]+:/{pg=0}
295
+ pg && /^ name:/{next}
296
+ {print}
297
+ END{if(count!=1)exit 1}
298
+ ' "$tmp/deploy/docker-compose.yml" > "$tmp/compose-pinned.yml"; then
299
+ rm -rf "$tmp"; die "新版资产缺少唯一 pg-data 卷定义,未替换现有资产。"
300
+ fi
301
+ mv "$tmp/compose-pinned.yml" "$tmp/deploy/docker-compose.yml" \
302
+ || { rm -rf "$tmp"; die "无法保留 PostgreSQL 卷名,未替换现有资产。"; }
303
+ fi
304
+ # This retired overlay otherwise survives extraction and duplicates logging mounts.
305
+ [ -f "$tmp/deploy/onebox/docker-compose.portal-logs.yml" ] \
306
+ || rm -f "$home/onebox/docker-compose.portal-logs.yml"
307
+ ( cd "$tmp/deploy" && tar -cf - . ) | ( cd "$home" && tar -xf - )
308
+ rm -rf "$tmp"
309
+ }
310
+
311
+ cmd_upgrade() {
312
+ local image="" proxy=""
313
+ while [ $# -gt 0 ]; do
314
+ case "$1" in
315
+ --image) image="${2:?}"; shift 2 ;;
316
+ --proxy-image) proxy="${2:?}"; shift 2 ;;
317
+ *) die "upgrade: 不认识的参数 '$1'" ;;
318
+ esac
319
+ done
320
+ if [ -z "$image" ]; then
321
+ image="$(_eff XGENT_IMAGE)"
322
+ [ -n "$proxy" ] || proxy="$(_eff XGENT_PROXY_IMAGE)"
323
+ fi
324
+ [ -n "$image" ] || die "compose.env 缺 XGENT_IMAGE,请 upgrade --image <新版一盒镜像>。"
325
+ [ -n "$proxy" ] || proxy="${image%/*}/proxy:${image##*:}"
326
+ pull_images "$image" "$proxy"
327
+ # Retain the old volume identity even after down and with a custom volume name.
328
+ local postgres_volume; postgres_volume="$(_postgres_volume)" || die "无法确认升级前的 PostgreSQL 数据卷。"
329
+ _extract_assets "$image" "$HOME_DIR" "$postgres_volume"
330
+ _env_set XGENT_IMAGE "$image"
331
+ _env_set XGENT_PROXY_IMAGE "$proxy"
332
+ local version; version="$(_image_version "$image")"
333
+ [ -z "$version" ] || _env_set APP_VERSION "$version"
334
+ _objectstore_image
335
+ _pin_postgres "$postgres_volume"
336
+ _kafka_defaults
337
+ info "部署资产已升级;现有配置、generated/、backup/、端口与数据卷保留。"
338
+ info "下一步:$0 up(仍会重种门户库;App 自己的库不重置)。"
339
+ }
340
+
341
+ cmd_init() {
342
+ local image="${XGENT_IMAGE:-}" proxy="" key="" home="./portal-onebox" force=0
343
+ while [ $# -gt 0 ]; do
344
+ case "$1" in
345
+ --image) image="${2:?}"; shift 2 ;;
346
+ --proxy-image) proxy="${2:?}"; shift 2 ;;
347
+ --key) key="${2:?}"; shift 2 ;;
348
+ --home) home="${2:?}"; shift 2 ;;
349
+ --force) force=1; shift ;;
350
+ *) die "init: 不认识的参数 '$1'" ;;
351
+ esac
352
+ done
353
+ [ -n "$image" ] || image="$(default_image || true)"
354
+ [ -n "$image" ] || die "init 不知道该拉哪个镜像:给 --image <registry>/<一盒项目>/one-box:<版本>,或在 puller 配置里补上 REGISTRY 与 ONEBOX_PROJECT(补了就默认用 <REGISTRY>/<ONEBOX_PROJECT>/one-box:latest,不必再去问 tag)。⚠️ ONEBOX_PROJECT 是【一盒镜像】的项目,不是你推自己 App 镜像的那个 PROJECT。"
355
+ case "$image" in *:latest) info "用 ${image}(可变指针)—— 它跟着最新一版走,开工前 $0 pull 一次就是最新;要钉住某一版改用 --image <...>:v<版本>-<sha>。";; esac
356
+ [ -n "$proxy" ] || proxy="${image%/*}/proxy:${image##*:}" # 代理镜像同仓同版本
357
+ [ -n "$key" ] || warn "没给 --key,先用占位 your-app —— 起 app-backend 之前必须把 compose.env 里的 APP_KEY 改成你的 listingKey(它同时是 /svc/<key>、iframe 路径、scope 命名空间和令牌 aud)。"
358
+ key="${key:-your-app}"
359
+
360
+ # 先把路径算出来但【不建目录】—— 下面任何一步停下时都不该留一个空壳
361
+ home="$(cd "$(dirname "$home")" 2>/dev/null && pwd || printf '%s' "$PWD")/$(basename "$home")"
362
+ local envf="$home/compose.env"
363
+ if [ -f "$envf" ] && [ "$force" = 0 ]; then
364
+ die "$envf 已存在(里面是这台机器的密钥)。要整份重来加 --force;只想补配置就直接往它末尾加。"
365
+ fi
366
+
367
+ # 一台机器一套一盒(SKILL.md 文首「一套就够」):本机已有【别的】一盒在跑/跑过时停下,
368
+ # 而不是再铺第二套 —— 两套之间只有端口退让、没有数据互通,要调的 App 应该接进现有那套。
369
+ # 自己这套(容器 config_files 落在本 home 下)不算;--force 时降级为提醒。
370
+ local other
371
+ other="$(docker ps -a --filter 'label=com.docker.compose.project' \
372
+ --format '{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.project.config_files"}}' 2>/dev/null \
373
+ | awk -F'\t' -v h="$home/" '($1=="xgent-onebox" || $1 ~ /^onebox-/) && index($2, h)!=1 { print $1; exit }' || true)"
374
+ if [ -n "$other" ]; then
375
+ [ "$force" = 1 ] || die "本机已有一套一盒(compose 项目 ${other})—— 一台机器只共用一套,别再铺第二套。
376
+ 要调你的 App:XGENT_ONEBOX_HOME=<那套 portal-onebox/ 的路径> 复用它的栈跑 register-app / dc;
377
+ 宿主上的 dev 后端直连它的 pg/redis/minio(SKILL.md §5)。那套的路径查看:docker compose ls。
378
+ 确需整份重来(--force 会连 compose.env 一起重建):$0 init --force …"
379
+ warn "本机已有另一套一盒(${other})—— --force 放行,但请确认那套已 down 掉,别长期并存。"
380
+ fi
381
+
382
+ # 1) 备齐镜像 —— 没有 puller 凭证就在这里停下,而不是让人跑到一半才发现
383
+ pull_images "$image" "$proxy"
384
+ mkdir -p "$home"
385
+
386
+ # 门户的 /health 报的 version 取自 APP_VERSION 环境变量,compose 缺省填 "dev" ——
387
+ # 于是一盒对使用者【完全不自报版本】。而「照文档做但行为不符」十有八九就是镜像比文档旧
388
+ # (CR-4:自动授予租户那段代码比某一版镜像新一天,症状是市场里没有卡片且零报错)。
389
+ # 这里把 tag + 镜像 ID + 构建日期钉进 compose.env,`/health` 与 `status` 立刻能回答
390
+ # 「我跑的是哪一版」。取不到就留空,不编。
391
+ local ver; ver="$(_image_version "$image")"
392
+
393
+ # 2) 从镜像里取 compose 资产 —— 版本天然与镜像对齐,不需要门户仓
394
+ _extract_assets "$image" "$home"
395
+
396
+ # 3) 挑空闲端口 —— 首次用最常见的翻车就是 80/5432/6379/9000 已被别的东西占着
397
+ local hp hsp pgp rdp mnp mncp kfp base kafka_cluster_id kafka_password
398
+ hp="$(pick_port 80 8080 8090 18080)"; hsp="$(pick_port 443 8443 18443)"
399
+ pgp="$(pick_port 5432 15432 25432)"; rdp="$(pick_port 6379 16379 26379)"
400
+ mnp="$(pick_port 9000 19000 29000)"; mncp="$(pick_port 9001 19001 29001)"
401
+ kfp="$(pick_port 9092 19092 29092)"
402
+ kafka_cluster_id="$(_kafka_cluster_id)" || die "无法生成 Kafka 集群 ID,初始化中止。"
403
+ kafka_password="$(_kafka_admin_password)" || die "无法生成 Kafka 管理密码,初始化中止。"
404
+ base="http://localhost"; [ "$hp" = "80" ] || base="http://localhost:$hp"
405
+
406
+ # 4) 三段模板 + 本机覆盖块(覆盖块必须在最末尾)
407
+ cat "$home/compose.env.example" "$home/onebox/compose.env.onebox.example" \
408
+ "$home/app-devkit/compose.env.app.example" > "$envf"
409
+ cat >> "$envf" <<EOF
410
+
411
+ # ============================================================================
412
+ # 本机覆盖 —— 由 onebox.sh init 生成。docker compose 是【后定义者胜】,所以这一段
413
+ # 必须留在文件最末尾;以后要改配置,也往这下面加,别回上面改。
414
+ # ============================================================================
415
+ # 全机一套共用这个名字(不带 App 名;init 的撞栈检测也认它),别改名来「并存」两套。
416
+ COMPOSE_PROJECT_NAME=xgent-onebox
417
+ NODE_ENV=development
418
+ DEV_MOCK_OAUTH=true
419
+
420
+ XGENT_IMAGE=$image
421
+ XGENT_PROXY_IMAGE=$proxy
422
+ # 这台一盒的身份(/health 的 version 字段读它)。换镜像后重跑 init,或自己改这一行。
423
+ APP_VERSION=$ver
424
+
425
+ # 宿主发布端口(init 挑的是当时空闲的口)。改了 HTTP_PORT 要同步下面两行。
426
+ HTTP_PORT=$hp
427
+ HTTPS_PORT=$hsp
428
+ POSTGRES_PORT=$pgp
429
+ REDIS_PORT=$rdp
430
+ MINIO_PORT=$mnp
431
+ MINIO_CONSOLE_PORT=$mncp
432
+ KAFKA_PORT=$kfp
433
+ KAFKA_CLUSTER_ID=$kafka_cluster_id
434
+ KAFKA_ADMIN_PASSWORD=$kafka_password
435
+ PORTAL_BASE_URL=$base
436
+ FILES_APP_URL=$base
437
+
438
+ # 门户自身密钥(本机随机,只在这台机器上有意义)
439
+ SESSION_SECRET=$(rand_hex)
440
+ TDT_SIGNING_KEY=$(rand_hex)
441
+ PLATFORM_ADMIN_KEY=$(rand_hex)
442
+ FILES_ENC_KEY=$(rand_hex)
443
+ LLM_GATEWAY_SECRET_ENC_KEY=$(rand_hex)
444
+
445
+ # files 的服务账号:种子把这里的值种进库,files-server 也读这里 —— 同源即一致。
446
+ # 用已知的 dev 明文,这样重跑种子/换机器都能对上(一盒是调试底座,不是门户)。
447
+ FILES_SA_CLIENT_SECRET=files-dev-resource-key
448
+ FILES_RESOURCE_KEY=files-dev-resource-key
449
+
450
+ # 一盒不装 ffmpeg:这一项必须留空,填 auto 会让每次转换去 exec 一个不存在的二进制。
451
+ PREVIEW_MEDIA_CONVERTER_URL=
452
+
453
+ # ---- 你的 App(填完 APP_IMAGE 才会起 app-backend)----
454
+ APP_KEY=$key
455
+ APP_IMAGE=
456
+ # micro(有前端、iframe 嵌入)才要,且必须是【绝对路径】、目录里有 index.html:
457
+ #APP_FRONTEND_DIST=/abs/path/to/your/frontend/dist
458
+ EOF
459
+ chmod 600 "$envf" || die "无法保护 compose.env 权限,初始化中止。"
460
+
461
+ # 5) 别让它进版本库:里面是密钥,且随时能从镜像重新生成
462
+ local root; root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
463
+ if [ -n "$root" ] && [ -f "$root/.gitignore" ] && ! grep -qx "$(basename "$home")/" "$root/.gitignore" 2>/dev/null; then
464
+ printf '\n# 门户一盒本地联调栈(含密钥,可用 onebox.sh init 重新生成)\n%s/\n' "$(basename "$home")" >> "$root/.gitignore"
465
+ info "已把 $(basename "$home")/ 加进 .gitignore"
466
+ fi
467
+
468
+ echo
469
+ printf '%s一盒资产就位:%s%s\n' "$c_grn" "$home" "$c_off"
470
+ printf ' 门户地址 %s\n' "$base"
471
+ printf ' 端口 http=%s pg=%s redis=%s minio=%s/%s kafka=%s\n' "$hp" "$pgp" "$rdp" "$mnp" "$mncp" "$kfp"
472
+ printf ' 项目名 xgent-onebox(全机一套共用,别改名)\n'
473
+ echo
474
+ echo "下一步(顺序本身是契约,见 SKILL.md §3)。先记一个短名:"
475
+ echo " S=$0"
476
+ echo
477
+ echo " 1. 编辑 $envf 末尾:填 APP_IMAGE(micro 再加 APP_FRONTEND_DIST)"
478
+ echo " 2. \$S up"
479
+ echo " 3. \$S doctor"
480
+ }
481
+
482
+ cmd_pull() {
483
+ local image="${XGENT_IMAGE:-}" proxy=""
484
+ while [ $# -gt 0 ]; do
485
+ case "$1" in
486
+ --image) image="${2:?}"; shift 2 ;;
487
+ --proxy-image) proxy="${2:?}"; shift 2 ;;
488
+ *) die "pull: 不认识的参数 '$1'" ;;
489
+ esac
490
+ done
491
+ if [ -z "$image" ] && [ -n "$(find_home)" ]; then # 已 init 过就从 compose.env 取
492
+ ENV_FILE="$(find_home)/compose.env"
493
+ [ -f "$ENV_FILE" ] && { image="$(_eff XGENT_IMAGE)"; [ -n "$proxy" ] || proxy="$(_eff XGENT_PROXY_IMAGE)"; }
494
+ fi
495
+ [ -n "$image" ] || image="$(default_image || true)"
496
+ [ -n "$image" ] || die "pull 不知道该拉哪个镜像:给 --image <门户镜像tag>,或先 init(之后它会从 compose.env 里读),或在 puller 配置里补上 REGISTRY 与 ONEBOX_PROJECT(默认 one-box:latest)。"
497
+ [ -n "$proxy" ] || proxy="${image%/*}/proxy:${image##*:}"
498
+ require_puller; registry_login
499
+ do_pull "$image" "tag 写错了?一盒只有两种::latest(可变指针,跟着最新一版走)和 :v<版本>-<7位sha>(钉住某一版)。"
500
+ do_pull "$proxy" "代理镜像名是从 runtime 镜像推出来的,有的部署不叫 proxy —— 用 --proxy-image 指定。"
501
+ printf '%s两个镜像就位%s\n' "$c_grn" "$c_off"
502
+ echo "镜像就位后跑 $0 upgrade --image ${image} --proxy-image ${proxy},再跑 $0 up。"
503
+ }
504
+
505
+ # --- 其余子命令 ---------------------------------------------------------------
506
+ cmd_env() {
507
+ echo "一盒目录: $HOME_DIR"
508
+ echo "compose.env: $ENV_FILE"
509
+ echo
510
+ local k v n
511
+ for k in COMPOSE_PROJECT_NAME XGENT_IMAGE XGENT_PROXY_IMAGE XGENT_APP_CATALOG NODE_ENV DEV_MOCK_OAUTH \
512
+ HTTP_PORT HTTPS_PORT POSTGRES_PORT REDIS_PORT MINIO_PORT MINIO_CONSOLE_PORT KAFKA_PORT PORTAL_BASE_URL \
513
+ APP_KEY APP_IMAGE APP_FRONTEND_DIST PREVIEW_MEDIA_CONVERTER_URL; do
514
+ v="$(_eff "$k")"
515
+ n="$(_assignments | awk -F'\t' -v k="$k" '$2==k{seen[$3]=1} END{print length(seen)}')"
516
+ printf ' %-28s %s' "$k" "${v:-${c_dim}(空)${c_off}}"
517
+ [ "$n" -gt 1 ] && printf ' %s← 同键 %s 个不同值,取最后一个%s' "$c_ylw" "$n" "$c_off"
518
+ printf '\n'
519
+ done
520
+ echo
521
+ [ "$COMPOSE_PROJECT" = "xgent" ] && warn "COMPOSE_PROJECT_NAME 还是模板默认的 xgent —— 同机另一套 compose 会被当成同一项目(容器被接管、命名卷共享)。改成 xgent-onebox(全机一套共用这个名字,init 现在就是这么设的)。"
522
+ [ "$(_eff NODE_ENV)" = "development" ] || warn "NODE_ENV 不是 development —— 镜像烘的是 production,不覆盖则 portal-api 拒绝在 DEV_MOCK_OAUTH=true 下启动,register-app 也拒跑。"
523
+ [ "$(_eff DEV_MOCK_OAUTH)" = "true" ] || warn "DEV_MOCK_OAUTH 不是 true —— 没有 dev 登录门,浏览器进不去。"
524
+ [ -n "$(_eff PREVIEW_MEDIA_CONVERTER_URL)" ] && warn "PREVIEW_MEDIA_CONVERTER_URL 非空 —— 一盒不装 ffmpeg,非空会让每次转换 exec 一个不存在的二进制。留空。"
525
+ case "$(_eff XGENT_IMAGE)" in *:latest) info "XGENT_IMAGE 是 latest(可变指针)—— 本地已经有同名镜像时 compose 不会回仓库看一眼,开工前先 $0 pull;要钉住某一版就写成 :v<版本>-<sha>。";; esac
526
+ [ -z "$APP_IMAGE" ] && warn "APP_IMAGE 还没填 —— 你的 app-backend 不会被拉起。(门户本身照常可用;先把门户跑通本来也是对的第一步。)"
527
+ case "$(_eff PORTAL_BASE_URL)" in
528
+ ""|"http://localhost:$HTTP_PORT") ;;
529
+ "http://localhost") [ "$HTTP_PORT" = "80" ] || warn "PORTAL_BASE_URL 是 http://localhost 但 HTTP_PORT=$HTTP_PORT —— 浏览器侧的绝对链接会指错端口。";;
530
+ *) warn "PORTAL_BASE_URL($(_eff PORTAL_BASE_URL))与 HTTP_PORT(${HTTP_PORT})对不上。";;
531
+ esac
532
+ if [ -n "$APP_FRONTEND_DIST" ]; then
533
+ [ -f "$APP_FRONTEND_DIST/index.html" ] || warn "APP_FRONTEND_DIST 下没有 index.html(${APP_FRONTEND_DIST})—— iframe 会 404。要绝对路径、且指向构建产物目录。"
534
+ fi
535
+ return 0
536
+ }
537
+
538
+ cmd_smoke() {
539
+ echo "宿主侧健康探测(${BASE_URL})"
540
+ local k keys="$CATALOG" tmp; tmp="$(mktemp)"
541
+ case ",$CATALOG," in *",$APP_KEY,"*) ;; *) [ -n "$APP_KEY" ] && keys="$CATALOG,$APP_KEY";; esac
542
+ _probe() { # _probe LABEL PATH
543
+ local code body
544
+ # curl 自己在失败时就打印 000;再 || echo 000 会拼成 000000
545
+ code="$(curl -s -m 8 -o "$tmp" -w '%{http_code}' "$BASE_URL$2" 2>/dev/null || true)"
546
+ code="${code:-000}"
547
+ body="$(head -c 160 "$tmp" 2>/dev/null || true)"
548
+ if [ "$code" = "200" ]; then printf ' %s✓%s %-22s %s\n' "$c_grn" "$c_off" "$1" "$body"
549
+ else printf ' %s✗%s %-22s HTTP %s %s\n' "$c_red" "$c_off" "$1" "$code" "$body"; fi
550
+ }
551
+ _probe "/health" /health
552
+ for k in ${keys//,/ }; do
553
+ _is_portal_hosted "$k" && continue
554
+ _probe "/svc/$k/health" "/svc/$k/health"
555
+ done
556
+
557
+ # dev 登录入口。登录页那枚「本地开发账号」按钮由 /auth/providers 的 dev 字段驱动 ——
558
+ # 字段在而按钮不在,就是这版镜像的前端与 API 对不齐(换镜像,或直接走 /auth/dev/start);
559
+ # 字段不在就是 DEV_MOCK_OAUTH 没生效。此前这一步只能靠读门户源码才知道(CR-4 #4)。
560
+ curl -s -m 8 -o "$tmp" "$BASE_URL/auth/providers" 2>/dev/null || true
561
+ if grep -q '"dev"' "$tmp" 2>/dev/null; then
562
+ printf ' %s✓%s %-22s %s\n' "$c_grn" "$c_off" "dev 登录" "登录页的「本地开发账号」按钮;按钮没出现就直接开 ${BASE_URL}/auth/dev/start"
563
+ else
564
+ printf ' %s✗%s %-22s %s\n' "$c_red" "$c_off" "dev 登录" "/auth/providers 里没有 dev —— DEV_MOCK_OAUTH 没生效(compose.env 末尾要有 NODE_ENV=development + DEV_MOCK_OAUTH=true,改完 dc up -d portal-api)"
565
+ fi
566
+ rm -f "$tmp"
567
+ echo
568
+ echo "${c_dim}404 = /svc 放行 map 没写成,或反代在写 map 之前就起了(跑 register-app,再 dc exec reverse-proxy caddy reload)${c_off}"
569
+ echo "${c_dim}502 = 后端容器没起/崩了/没听 8080/网络别名 <key>-server 没命中(dc logs <key>-server 或 app-backend)${c_off}"
570
+ echo "${c_dim}000 = 反代本身没起,或你探的端口不是 HTTP_PORT(dc ps / dc logs reverse-proxy)${c_off}"
571
+ return 0
572
+ }
573
+
574
+ cmd_status() {
575
+ cmd_env
576
+ echo "容器(project: ${COMPOSE_PROJECT})"
577
+ dc ps || true
578
+ echo
579
+ # 「unhealthy 是假红」这句必须按【容器里实际生效的那条探针】给,不能无条件打印:旧镜像的
580
+ # 基础层 compose 有两条永远失败的探针 —— `curl -fsS …/health`(精简镜像没装 curl)与反代的
581
+ # `wget … http://127.0.0.1:80/`(站点地址是主机名时被 308 到 https://IP/,IP 不能作 SNI,
582
+ # 回 SSL alert 80)。新镜像两条都换掉了,那之后 unhealthy 就是真的;照旧提示「假红不用查」
583
+ # 会让人放过真的配置漂移(典型:只用 -f docker-compose.yml 重建了一个服务,overlay 的
584
+ # logging.driver 一起丢了,日志静默不再进 observability)。
585
+ local cid nm tst stale=""
586
+ for cid in $(dc ps -q 2>/dev/null || true); do
587
+ tst="$(docker inspect "$cid" --format '{{json .Config.Healthcheck.Test}}' 2>/dev/null || true)"
588
+ case "$tst" in
589
+ *"curl -fsS http://127.0.0.1:8080/health"*|*"wget -q -O /dev/null http://127.0.0.1:80/"*)
590
+ nm="$(docker inspect "$cid" --format '{{.Name}}' 2>/dev/null | sed 's#^/##')"
591
+ stale="$stale ${nm:-$cid}" ;;
592
+ esac
593
+ done
594
+ if [ -n "$stale" ]; then
595
+ warn "这些容器的 healthcheck 还是旧镜像里那条永远失败的探针,它们的 unhealthy 是假红(判活只看下面的探测):$stale"
596
+ _note "新镜像已换成 bun / 不跟随重定向的 curl。$0 pull 后跑 $0 upgrade,再跑 $0 up;upgrade 保留配置与数据。"
597
+ else
598
+ _note "healthcheck 都是新探针 —— 这里的 unhealthy 就是真红,别当假红放过去(先看 $0 dc logs <服务>)。"
599
+ fi
600
+ echo
601
+ cmd_smoke
602
+ }
603
+
604
+ # --- 小工具 -------------------------------------------------------------------
605
+ _env_set() { # _env_set KEY VALUE —— 追加到 compose.env 末尾(后定义者胜),已是同值则跳过
606
+ local k="$1" v="$2"
607
+ [ "$(_eff "$k")" = "$v" ] && return 0
608
+ printf '%s=%s\n' "$k" "$v" >> "$ENV_FILE" || die "无法写入 compose.env,操作中止。"
609
+ info "compose.env += ${k}=${v}"
610
+ }
611
+ _env_append_secret() {
612
+ printf '%s=%s\n' "$1" "$2" >> "$ENV_FILE" || die "无法写入 compose.env,操作中止。"
613
+ info "compose.env += ${1}=***"
614
+ }
615
+ _kafka_cluster_id() {
616
+ local value
617
+ value="$(openssl rand -base64 16 | tr '+/' '-_' | tr -d '=')" || return 1
618
+ [ "${#value}" = 22 ] || return 1
619
+ printf '%s' "$value"
620
+ }
621
+ _kafka_admin_password() {
622
+ local value
623
+ value="$(openssl rand -hex 24)" || return 1
624
+ [ "${#value}" = 48 ] || return 1
625
+ printf '%s' "$value"
626
+ }
627
+ _kafka_defaults() {
628
+ # Only absent keys are filled. An existing cluster ID/password must never rotate.
629
+ local value
630
+ if ! grep -q '^KAFKA_CLUSTER_ID=' "$ENV_FILE"; then
631
+ value="$(_kafka_cluster_id)" || die "无法生成 Kafka 集群 ID,升级中止。"
632
+ _env_set KAFKA_CLUSTER_ID "$value"
633
+ fi
634
+ if ! grep -q '^KAFKA_ADMIN_PASSWORD=' "$ENV_FILE"; then
635
+ value="$(_kafka_admin_password)" || die "无法生成 Kafka 管理密码,升级中止。"
636
+ _env_append_secret KAFKA_ADMIN_PASSWORD "$value"
637
+ fi
638
+ if ! grep -q '^KAFKA_PORT=' "$ENV_FILE"; then _env_set KAFKA_PORT "$(pick_port 9092 19092 29092)"; fi
639
+ chmod 600 "$ENV_FILE" || die "无法保护 compose.env 权限,升级中止。"
640
+ }
641
+ _kafka_assets_current() {
642
+ grep -qE '^ kafka:' "$HOME_DIR/docker-compose.yml" \
643
+ && grep -q '^KAFKA_CLUSTER_ID=' "$ENV_FILE" \
644
+ && grep -q '^KAFKA_ADMIN_PASSWORD=' "$ENV_FILE" \
645
+ && grep -q '^KAFKA_PORT=' "$ENV_FILE"
646
+ }
647
+ _require_kafka_assets() {
648
+ _kafka_assets_current || die "一盒 Kafka 资产或配置是旧版,先跑 $0 upgrade --image <新版一盒镜像>,再跑 $0 up。"
649
+ }
650
+ _kafka_up() {
651
+ local deadline cid state
652
+ if ! dc up -d kafka </dev/null; then
653
+ warn "Kafka 启动失败,门户继续;查看下方日志。"
654
+ dc logs --tail 50 kafka </dev/null || true
655
+ return 0
656
+ fi
657
+ deadline=$((SECONDS+60))
658
+ while [ "$SECONDS" -lt "$deadline" ]; do
659
+ cid="$(dc ps -q kafka </dev/null 2>/dev/null || true)"; state=''
660
+ [ -z "$cid" ] || state="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{end}}' "$cid" </dev/null 2>/dev/null || true)"
661
+ if [ "$state" = healthy ]; then info "Kafka: healthy"; return 0; fi
662
+ [ "$SECONDS" -ge "$deadline" ] || sleep 1
663
+ done
664
+ warn "Kafka 60s 内未健康,门户继续;依赖 Kafka 的应用需等服务恢复。"
665
+ dc logs --tail 50 kafka </dev/null || true
666
+ return 0
667
+ }
668
+ _ensure_kafka() { # _ensure_kafka LISTING_KEY ENV_PREFIX
669
+ local key="$1" prefix="$2" username password admin deadline
670
+ [[ "$key" =~ ^[a-z0-9][a-z0-9-]*$ ]] || return 1
671
+ _kafka_assets_current || return 1
672
+ dc up -d kafka </dev/null >/dev/null 2>&1 || return 1
673
+ deadline=$((SECONDS+60))
674
+ until dc exec -T kafka nc -z 127.0.0.1 9092 </dev/null >/dev/null 2>&1; do
675
+ [ "$SECONDS" -lt "$deadline" ] || return 1
676
+ sleep 1
677
+ done
678
+ username="app_${key//-/_}"
679
+ password="$(_eff "${prefix}_KAFKA_PASSWORD")"
680
+ if [ -z "$password" ]; then
681
+ password="$(_kafka_admin_password)" || return 1
682
+ # Persist before contacting the broker: a partial ACL failure must reuse this password.
683
+ _env_append_secret "${prefix}_KAFKA_PASSWORD" "$password"
684
+ fi
685
+ admin="$(_eff KAFKA_ADMIN_PASSWORD)"
686
+ [ -n "$admin" ] || return 1
687
+ case "$admin" in *$'\n'*|*$'\r'*) return 1 ;; esac
688
+ # Generated passwords are hex; preserve existing safe base64/url-safe passwords too.
689
+ [[ "$password" =~ ^[A-Za-z0-9_+/=-]+$ ]] || return 1
690
+ chmod 600 "$ENV_FILE" || return 1
691
+ # Secrets enter through stdin, never command arguments or raw CLI output. The temporary
692
+ # properties live only inside the broker and are removed on success, failure or signal.
693
+ # shellcheck disable=SC2016
694
+ if ! printf '%s\n%s\n' "$admin" "$password" | dc exec -T kafka bash -ec '
695
+ umask 077
696
+ IFS= read -r admin
697
+ IFS= read -r password
698
+ dir=$(mktemp -d /tmp/xgent-kafka-admin.XXXXXX)
699
+ trap '\''rm -rf "$dir"'\'' EXIT
700
+ trap '\''exit 1'\'' HUP INT TERM
701
+ escaped=${admin//\\/\\\\}; escaped=${escaped//\"/\\\"}
702
+ jaas="org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"$escaped\";"
703
+ printf "security.protocol=SASL_PLAINTEXT\nsasl.mechanism=PLAIN\nsasl.jaas.config=%s\nrequest.timeout.ms=10000\ndefault.api.timeout.ms=15000\n" "${jaas//\\/\\\\}" > "$dir/admin.properties"
704
+ printf "SCRAM-SHA-512=iterations=8192,password=%s\n" "$password" > "$dir/scram.properties"
705
+ /opt/kafka/bin/kafka-configs.sh --bootstrap-server kafka:9092 --command-config "$dir/admin.properties" --alter --add-config-file "$dir/scram.properties" --entity-type users --entity-name "$1"
706
+ acl=(--bootstrap-server kafka:9092 --command-config "$dir/admin.properties" --add --allow-principal "User:$1" --allow-host "*" --resource-pattern-type prefixed)
707
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --topic "$2" --operation Create --operation Delete --operation Describe --operation DescribeConfigs --operation Read --operation Write
708
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --group "$2" --operation Read --operation Describe --operation Delete
709
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --transactional-id "$2" --operation Write --operation Describe
710
+ ' bash "$username" "app.${key}." >/dev/null 2>&1; then return 1; fi
711
+ _env_set "${prefix}_KAFKA_BROKERS" kafka:9092
712
+ _env_set "${prefix}_KAFKA_USERNAME" "$username"
713
+ _env_set "${prefix}_KAFKA_SASL_MECHANISM" SCRAM-SHA-512
714
+ _env_set "${prefix}_KAFKA_TOPIC_PREFIX" "app.${key}."
715
+ info "Kafka 用户 ${username} 与前缀 app.${key}. 就绪"
716
+ }
717
+ _kafka_add_warning() {
718
+ warn "Kafka 供给失败;门户与应用初始化继续。已保存的密码保持不变,检查 Kafka 日志后重试:"
719
+ printf ' XGENT_ONEBOX_HOME=%q bash %q add %q' "$HOME_DIR" "$0" "$1"
720
+ [ -z "${ADD_MANIFEST:-}" ] || printf ' --manifest %q' "$ADD_MANIFEST"
721
+ [ -z "${ADD_FROM:-}" ] || printf ' --from %q' "$ADD_FROM"
722
+ printf '\n'
723
+ _note "手工修复命令见《平台 Kafka 接入指引》的一盒故障恢复;不要把管理员密码填进 App requiredEnv。"
724
+ }
725
+ _portal_services_up() {
726
+ # Kafka has its own non-blocking startup; do not retry it in the hard-fail group.
727
+ local enabled svc services=()
728
+ enabled="$(dc config --services)" || die "无法读取一盒服务清单。"
729
+ while IFS= read -r svc; do
730
+ [ -z "$svc" ] || [ "$svc" = kafka ] || services+=("$svc")
731
+ done <<< "$enabled"
732
+ [ "${#services[@]}" -gt 0 ] || die "一盒服务清单为空。"
733
+ dc up -d "${services[@]}"
734
+ }
735
+ _svc_running() { [ -n "$(dc ps -q "$1" 2>/dev/null || true)" ]; }
736
+ # v1 的放行表只在 Caddy load 时读取;v2 由唯一发布器生成、验证并应用整代配置。
737
+ # 必须先询问镜像的受管 selector;模式损坏时不能按旧镜像降级,更不能重读兼容模板。
738
+ _reload_proxy() {
739
+ _svc_running reverse-proxy || return 0
740
+ local selected out
741
+ if ! selected="$(dc exec -T reverse-proxy sh -c '
742
+ selector=/usr/local/libexec/xgent-gateway-config
743
+ if [ -e "$selector" ] || [ -L "$selector" ]; then
744
+ [ -f "$selector" ] && [ -x "$selector" ] || exit 1
745
+ exec "$selector"
746
+ fi
747
+ # 旧镜像只有完全没有受管状态时才允许兼容 reload。
748
+ for path in /etc/caddy/sites/gateway-v2.enabled /etc/caddy/sites/current /etc/caddy/gateway-operation.conf; do
749
+ if [ -e "$path" ] || [ -L "$path" ]; then exit 1; fi
750
+ done
751
+ printf "/etc/caddy/Caddyfile\n"
752
+ ' 2>/dev/null)"; then
753
+ die "无法确认反代模式;已停止 reload。请检查受管模式与 current 快照,再按网关维护文档恢复。"
754
+ fi
755
+ case "$selected" in
756
+ /etc/caddy/Caddyfile) ;;
757
+ /*/current/Caddyfile)
758
+ info " 反代为 v2,路由变更由唯一发布器应用;请查看发布状态确认结果"
759
+ return 0 ;;
760
+ *) die "反代模式返回无效;已停止 reload,不会回退到兼容模板。" ;;
761
+ esac
762
+ if out="$(dc exec -T reverse-proxy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1)"; then
763
+ info " 反代已重读 /svc 放行表"
764
+ else
765
+ warn "反代重读失败,/svc 仍是改动前那份:$(printf '%s' "$out" | tail -2 | tr '\n' ' ')"
766
+ fi
767
+ }
768
+ _ok() { printf ' %s✓%s %s\n' "$c_grn" "$c_off" "$*"; }
769
+ _bad() { printf ' %s✗%s %s\n' "$c_red" "$c_off" "$1"; shift; [ $# -gt 0 ] && printf ' %s↳ %s%s\n' "$c_dim" "$*" "$c_off"; DOCTOR_BAD=$((DOCTOR_BAD+1)); return 0; }
770
+ _note() { printf ' %s↳ %s%s\n' "$c_dim" "$*" "$c_off"; }
771
+
772
+ # --- up:按顺序铺一遍(幂等)---------------------------------------------------
773
+ _objectstore_assets_current() {
774
+ grep -qE '^ rustfs:' "$HOME_DIR/docker-compose.yml" \
775
+ && [ -f "$HOME_DIR/scripts/objectstore-cutover.sh" ] \
776
+ && [ -f "$HOME_DIR/scripts/objectstore-manifest.ts" ]
777
+ }
778
+ _require_objectstore_assets() {
779
+ _objectstore_assets_current || die "一盒资产是旧版,先跑 $0 upgrade --image <新版一盒镜像>,再跑 $0 up。"
780
+ }
781
+ _objectstore_image() {
782
+ local image
783
+ image="$(dc config --images rustfs)" || die "无法读取 RustFS 镜像配置;旧对象存储未切换。"
784
+ [ -n "$image" ] || die "Compose 配置里没有 RustFS 镜像;旧对象存储未切换。"
785
+ docker image inspect "$image" >/dev/null 2>&1 && return 0
786
+ dc pull rustfs </dev/null || die "RustFS 镜像尚未就位;拉取失败,旧对象存储未切换。修复镜像拉取后重跑。"
787
+ }
788
+
789
+ # An asset upgrade must not upgrade/downgrade an existing PostgreSQL data directory.
790
+ # Inspect only this project's real mount, then read it through a read-only container.
791
+ _postgres_volume() {
792
+ local project ids cid volume volumes configured
793
+ project="$(_eff COMPOSE_PROJECT_NAME xgent-onebox)"
794
+ ids="$(docker ps -aq --filter "label=com.docker.compose.project=$project" --filter label=com.docker.compose.service=postgres)" \
795
+ || die "无法检查本项目 PostgreSQL 容器;未启动服务。"
796
+ if [ -n "$ids" ]; then
797
+ [ "$(printf '%s\n' "$ids" | wc -l | tr -d ' ')" = 1 ] || die "本项目有多个 PostgreSQL 容器,无法确定权威数据卷;请人工确认,勿删卷。"
798
+ cid="$ids"
799
+ volume="$(docker inspect "$cid" --format '{{range .Mounts}}{{if eq .Type "volume"}}{{if or (eq .Destination "/var/lib/postgresql") (eq .Destination "/var/lib/postgresql/data")}}{{println .Name}}{{end}}{{end}}{{end}}')" \
800
+ || die "无法读取 PostgreSQL 挂载,勿删卷。"
801
+ [ -n "$volume" ] && [ "$(printf '%s\n' "$volume" | wc -l | tr -d ' ')" = 1 ] \
802
+ || die "PostgreSQL 挂载不是唯一命名卷;请人工确认,勿删卷。"
803
+ else
804
+ volume="$(docker volume ls --filter "label=com.docker.compose.project=$project" --filter label=com.docker.compose.volume=pg-data --format '{{.Name}}')" \
805
+ || die "无法查询 PostgreSQL 数据卷;未启动服务。"
806
+ if [ -n "$volume" ]; then
807
+ [ "$(printf '%s\n' "$volume" | wc -l | tr -d ' ')" = 1 ] || die "本项目有多个 pg-data 卷,拒绝自动选择。"
808
+ else
809
+ configured="$(awk '
810
+ /^volumes:/{volumes=1; next}
811
+ volumes && /^ pg-data:/{pg=1; next}
812
+ volumes && /^ [A-Za-z0-9_-]+:/{pg=0}
813
+ pg && /^ name:/{sub(/^ name:[[:space:]]*/, ""); print}
814
+ ' "$HOME_DIR/docker-compose.yml" | sed "s/^[\"']//; s/[\"']$//")"
815
+ volume="${configured:-${project}_pg-data}"
816
+ [[ "$volume" =~ ^[A-Za-z0-9][A-Za-z0-9_.-]*$ ]] || die "pg-data 自定义卷名无法确定;请人工确认,勿删卷。"
817
+ volumes="$(docker volume ls --format '{{.Name}}')" || die "无法查询 Docker 数据卷;未启动服务。"
818
+ printf '%s\n' "$volumes" | grep -qxF "$volume" || return 0
819
+ fi
820
+ fi
821
+ printf '%s' "$volume"
822
+ }
823
+ _pin_postgres() {
824
+ local volume state major layout file next
825
+ if [ $# -gt 0 ]; then volume="$1"
826
+ else volume="$(_postgres_volume)" || die "无法确认 PostgreSQL 数据卷;未启动服务。"; fi
827
+ [ -n "$volume" ] || return 0
828
+ state="$(docker run --rm --network none -u 0 --entrypoint sh -v "$volume:/probe:ro" rustfs/rustfs:1.0.0 -c '
829
+ set -eu
830
+ count=0
831
+ for f in /probe/PG_VERSION /probe/[0-9]*/docker/PG_VERSION; do
832
+ [ -f "$f" ] || continue
833
+ count=$((count+1)); major=$(cat "$f")
834
+ if [ "$f" = /probe/PG_VERSION ]; then layout=legacy
835
+ elif [ "$f" = "/probe/$major/docker/PG_VERSION" ]; then layout=parent
836
+ else echo unknown; exit 1; fi
837
+ printf "%s %s\n" "$major" "$layout"
838
+ done
839
+ if [ "$count" = 0 ]; then
840
+ if [ -z "$(ls -A /probe)" ]; then echo empty; else echo unknown; fi
841
+ fi
842
+ ' </dev/null)" || die "PostgreSQL 只读卷检查失败;未启动服务,勿删卷。"
843
+ [ "$state" = empty ] && return 0
844
+ [ "$(printf '%s\n' "$state" | wc -l | tr -d ' ')" = 1 ] \
845
+ || die "PostgreSQL 卷内有多个版本目录,拒绝自动选择;勿删卷。"
846
+ major="${state%% *}"; layout="${state#* }"
847
+ [[ "$major" =~ ^[1-9][0-9]$ ]] || die "PostgreSQL 卷布局或版本未知;拒绝启动,勿删卷。"
848
+ if [ "$layout" = legacy ] && [ "$major" -lt 18 ]; then
849
+ layout=/var/lib/postgresql/data
850
+ elif [ "$layout" = parent ] && [ "$major" -ge 18 ]; then
851
+ layout=/var/lib/postgresql
852
+ else
853
+ die "PostgreSQL 版本与目录布局不一致;拒绝启动,勿删卷。"
854
+ fi
855
+ file="$HOME_DIR/docker-compose.yml"; next="$(mktemp "$HOME_DIR/.postgres-compose.XXXXXX")"
856
+ if ! awk -v major="$major" -v mount="$layout" -v volume="$volume" '
857
+ /^ postgres:/{svc=1; print; next}
858
+ svc && /^ [A-Za-z0-9_-]+:/{svc=0}
859
+ /^volumes:/{svc=0; volumes=1}
860
+ svc && /^ image:/{print " image: postgres:" major "-alpine"; images++; next}
861
+ svc && /^[[:space:]]*- pg-data:\/var\/lib\/postgresql(\/data)?[[:space:]]*$/{print " - pg-data:" mount; mounts++; next}
862
+ volumes && /^ pg-data:/{print " pg-data:"; print " name: " volume; named=1; names++; next}
863
+ volumes && /^ [A-Za-z0-9_-]+:/{named=0}
864
+ named && /^ name:/{next}
865
+ {print}
866
+ END{if(images!=1 || mounts!=1 || names!=1)exit 1}
867
+ ' "$file" > "$next"; then
868
+ rm -f "$next"; die "PostgreSQL compose 布局不符合预期,未覆盖文件;请人工确认,勿删卷。"
869
+ fi
870
+ # 运行中的 portal-api / controller 按 inode 单文件挂载它;内容没变就不换文件,免得它们读到已删除的旧文件。
871
+ if cmp -s "$next" "$file"; then rm -f "$next"
872
+ else mv "$next" "$file" || { rm -f "$next"; die "无法保存 PostgreSQL 版本保护;未启动服务。"; }; fi
873
+ info "PostgreSQL 存量卷保持 PG${major} 与 ${layout} 挂载;大版本迁移需另行安排。"
874
+ }
875
+
876
+ _objectstore_up() {
877
+ _require_objectstore_assets
878
+ _objectstore_image
879
+ local code deadline
880
+ if "$HOME_DIR/scripts/objectstore-cutover.sh" \
881
+ --project "$(_eff COMPOSE_PROJECT_NAME xgent-onebox)" --env-file "$ENV_FILE" \
882
+ --backup-dir "$HOME_DIR/backup" </dev/null; then
883
+ :
884
+ else
885
+ code=$?
886
+ die "对象存储切换中止(退出 ${code});按上方提示处理,未启动正式 RustFS。"
887
+ fi
888
+ dc up -d rustfs </dev/null || die "RustFS 启动失败;已过提交点,rustfs-data 是权威,勿删。看 $0 dc logs rustfs;回退只执行 $HOME_DIR/backup/rollback-minio.sh。"
889
+ deadline=$((SECONDS+60))
890
+ while [ "$SECONDS" -lt "$deadline" ]; do
891
+ if dc exec -T rustfs curl -fsS --max-time 1 http://127.0.0.1:9000/health </dev/null >/dev/null 2>&1; then return 0; fi
892
+ [ "$SECONDS" -ge "$deadline" ] || sleep 1
893
+ done
894
+ die "RustFS 60s 未就绪;已过提交点,rustfs-data 是权威,勿删。看 $0 dc logs rustfs;回退只执行 $HOME_DIR/backup/rollback-minio.sh。"
895
+ }
896
+
897
+ cmd_up() {
898
+ _require_objectstore_assets
899
+ _require_kafka_assets
900
+ [ -n "$APP_KEY" ] || die "compose.env 里还没有 APP_KEY —— 先跑 $0 init --key <你的listingKey>。"
901
+ info "① 基础设施(postgres / redis / RustFS / Kafka)"
902
+ _objectstore_image
903
+ _pin_postgres
904
+ _objectstore_up
905
+ dc up -d postgres redis
906
+ _kafka_up
907
+ info " 等 postgres 就绪…"
908
+ # 首次初始化时 initdb 会先起一个临时实例再重启,单次 pg_isready 会在那个窗口里误判就绪,
909
+ # 紧接着的 db:migrate 就撞 ECONNREFUSED(实测)。要求连续 3 秒都就绪才算。
910
+ local i=0 okc=0; until [ "$okc" -ge 3 ]; do
911
+ if dc exec -T postgres pg_isready -U postgres >/dev/null 2>&1; then okc=$((okc+1)); else okc=0; fi
912
+ i=$((i+1)); [ "$i" -gt 90 ] && die "postgres 90s 还没就绪,看 $0 dc logs postgres"
913
+ sleep 1
914
+ done
915
+ info "② 门户库 + 目录里各服务自己的库(迁移)"
916
+ dc run --rm portal-api bun run db:migrate
917
+ # ⚠️ 必须在种子之前:种子要替 deploy-controller(一盒里它启动即拒)跑各 App 的
918
+ # 逐租户基线(org 的预置档案字段就是这么来的),表还没建就只能眼看着它失败。
919
+ local k
920
+ for k in ${CATALOG//,/ }; do
921
+ case "$k" in files|llm-gateway|git|org) dc run --rm portal-api bun run "db:$k:migrate" || warn "db:$k:migrate 失败,继续";; esac
922
+ done
923
+ info "②b 你自己的库 xgent-${APP_KEY}"
924
+ _ensure_db "xgent-${APP_KEY}"
925
+ info "③ 一盒种子(★ 破坏性:truncate cascade)"
926
+ dc run --rm portal-api bun run db:seed:onebox
927
+ if [ -n "${ONEBOX_MANIFEST:-}" ] || [ -f "app.manifest.json" ]; then
928
+ local mf="${ONEBOX_MANIFEST:-app.manifest.json}"
929
+ info "④ 注册你的 App(${mf})"
930
+ dc run --rm -v "$(cd "$(dirname "$mf")" && pwd):/devkit:ro" portal-api bun run register-app "/devkit/$(basename "$mf")" \
931
+ || warn "register-app 失败 —— 看上面的报错;改完重跑 $0 up 即可(幂等)"
932
+ else
933
+ warn "④ 跳过 register-app:当前目录没有 app.manifest.json。有的话设 ONEBOX_MANIFEST=<路径> 再跑一次 $0 up。"
934
+ fi
935
+ # ④b 目录里的清单型 App(如 observability 日志与监控):按 add 的流程拉镜像 → 注册 → 建库 →
936
+ # migrate → 生成片段。非破坏性、幂等;失败只告警,不挡门户三件套。
937
+ local mk
938
+ for mk in ${CATALOG//,/ }; do
939
+ _is_manifest_app "$mk" || continue
940
+ info "④b 目录里的清单型 App:${mk}"
941
+ ADD_QUIET=1 cmd_add "$mk" || warn "add ${mk} 失败 —— 看上面的报错;修完重跑 $0 up(幂等)"
942
+ done
943
+ info "⑤ 起门户三件套 + 基础服务" ; _portal_services_up
944
+ _reload_proxy
945
+ _has_catalog observability && _portal_logs_up
946
+ echo; info "跑一次体检:"; cmd_doctor
947
+ }
948
+
949
+ # 门户自身控制台日志 → 日志与监控(采集段在 onebox/docker-compose.onebox.yml 内,
950
+ # portal-logs 服务挂 onebox-logs profile,这里签密钥后【显式】起):
951
+ # 用 portal-self 签一把只带 observability.ingest 的 xsak_ 写进 compose.env,再起 portal-logs。
952
+ # 前提(observability 已注册 + 已登记为平台基础服务应用 + portal-self 在)由 portal-logs-key.ts 判,
953
+ # 不成立 ⇒ 退出码 3 ⇒ 这里只告警。密钥只签一次:已有 OBS_ACCESS_KEY 就不动。
954
+ _portal_logs_up() {
955
+ info "⑥ 门户控制台日志采集(portal-api → portal-logs → observability)"
956
+ if [ -z "$(_eff OBS_ACCESS_KEY)" ]; then
957
+ local sec rc=0 err; err="$(mktemp)"
958
+ # 容器的 workdir 是 /app(monorepo 根),脚本在 apps/api 下;不走 package script 是因为它带 --env-file=../../.env,镜像里没有那份文件。
959
+ sec="$(dc run --rm --no-deps -T -w /app/apps/api portal-api bun run scripts/portal-logs-key.ts 2>"$err")" || rc=$?
960
+ if [ "$rc" -eq 0 ] && [ -n "$sec" ]; then
961
+ _env_append_secret OBS_ACCESS_KEY "$sec"
962
+ else
963
+ warn "采集密钥没签成(rc=${rc}):$(grep -v xsak_ "$err" | tail -3 | tr '\n' ' ')"; rm -f "$err"; return 0
964
+ fi
965
+ rm -f "$err"
966
+ fi
967
+ dc up -d portal-logs portal-api
968
+ _ok "portal-logs 已起;portal-api 的 stdout/stderr 经 fluentd 驱动进 app_portal_console(观测:$0 dc logs portal-logs)"
969
+ }
970
+
971
+ # 使用 RustFS 自带 curl 与容器内凭据建桶;不依赖已停止分发的 mc。
972
+ _ensure_bucket() { # _ensure_bucket <bucket>
973
+ local bucket="$1"
974
+ [[ "$bucket" =~ ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ ]] || die "对象存储桶名不合法。"
975
+ _objectstore_up
976
+ # Credentials and bucket positional argument expand in the container shell.
977
+ # shellcheck disable=SC2016
978
+ if dc exec -T rustfs sh -c 'exec curl -fsS --max-time 10 --retry 10 --retry-delay 1 --retry-all-errors \
979
+ --aws-sigv4 "aws:amz:us-east-1:s3" --user "$RUSTFS_ACCESS_KEY:$RUSTFS_SECRET_KEY" \
980
+ -X PUT "http://127.0.0.1:9000/$1"' sh "$bucket" </dev/null >/dev/null; then
981
+ info "桶 ${bucket} 就绪"
982
+ else die "桶 ${bucket} 没建成;检查 $0 dc logs rustfs,修复后重跑原命令。"; fi
983
+ }
984
+ _ensure_db() { # _ensure_db <dbname>
985
+ if dc exec -T postgres psql -U postgres -lqt 2>/dev/null | cut -d'|' -f1 | grep -qw "$1"; then
986
+ info " 库 $1 已存在"
987
+ else
988
+ dc exec -T postgres psql -U postgres -c "CREATE DATABASE \"$1\"" >/dev/null && info " 建库 $1"
989
+ fi
990
+ }
991
+
992
+ # --- add:把一个平台侧 App 拉进来陪调 ------------------------------------------
993
+ # 关键设计:compose 片段【从 manifest 生成】,不是每个 App 在 skill 里写一份 YAML —— 那样
994
+ # 每接一个新 App 就得改一次 skill,等于把问题搬了个地方。manifest 里已经有全部所需:
995
+ # deployDescriptor.image → 镜像(相对名按 <REGISTRY>/<ONEBOX_PROJECT>/ 补全,版本由清单钉住)
996
+ # deployDescriptor.port → 容器内端口 listingKey → 网络别名 <key>-server + 库名 xgent-<key>
997
+ # serviceAccount.clientId→ 自省身份 type → micro 要不要前端
998
+ # 密钥【不从 manifest 来】:一盒现生成一个,同时写进本地门户 DB 与容器 env。所以清单里
999
+ # 有没有明文密钥都无所谓(release 提交的那份本来就被 prod 模式拒收)。
1000
+ #
1001
+ # 少数 App 有 manifest 描述不了的自带 infra(knowledge 要一个 Chroma 边车)。那种情况下
1002
+ # skill 的 services/<key>.extra.yml 补一层——只有例外才需要文件,不是每个 App 都要。
1003
+ _manifest_json() { # _manifest_json KEY → 把 manifest JSON 打到 stdout
1004
+ local key="$1"
1005
+ if [ -n "${ADD_MANIFEST:-}" ]; then cat "$ADD_MANIFEST"; return; fi
1006
+ if [ -n "${ADD_FROM:-}" ]; then
1007
+ # ⚠️ 门户【所有】200 都是信封 {ok,data} —— manifest 在 data.manifest,不在响应根。
1008
+ # 把响应体直接当 manifest 解,症状是「字段全 undefined」而不是「解析失败」,更难查。
1009
+ # 头必须走数组:`${X:+-H "a: b"}` 不加引号会按空白拆成四个参数(连引号一起)。
1010
+ local http body; local -a hdr=()
1011
+ if [ -n "${MANIFEST_STORE_READ_TOKEN:-}" ]; then hdr=(-H "Authorization: Bearer ${MANIFEST_STORE_READ_TOKEN}"); fi
1012
+ # 刻意不加 -f:4xx 的响应体正是要读的那一份(业务失败走 200 + 错误体,闸走 4xx)。
1013
+ body="$(curl -sS -m 20 -w $'\n%{http_code}' ${hdr[@]+"${hdr[@]}"} \
1014
+ "${ADD_FROM%/}/api/market/catalog/${key}" 2>/dev/null)" \
1015
+ || die "连不上 ${ADD_FROM} —— 检查地址与网络,或用 --manifest <本地文件> 顶上。"
1016
+ http="${body##*$'\n'}"; body="${body%$'\n'*}"
1017
+ case "$http" in
1018
+ 404) die "${ADD_FROM} 没有目录接口(那个门户没开目录能力,或地址不对)。出路:--manifest <本地文件>,或不带 --from 用镜像自带的样例清单。" ;;
1019
+ 401) die "目录读取令牌无效或已失效 —— 在 .xgent-registry.env 里更新 MANIFEST_STORE_READ_TOKEN(找门户团队要新的)。" ;;
1020
+ 200) ;;
1021
+ *) die "目录返回 HTTP ${http}。出路:--manifest <本地文件>,或不带 --from 用镜像自带的样例清单。" ;;
1022
+ esac
1023
+ # data:null = 目录里还没有这个 key;ok:false = 业务失败。
1024
+ # 出错信息走【stdout】:`dc run` 的 stderr 混着 compose 自己的噪音,捞不干净。
1025
+ local mout rc
1026
+ mout="$(printf '%s' "$body" | dc run --rm --no-deps -T portal-api bun -e '
1027
+ let raw=""; for await (const c of Bun.stdin.stream()) raw += new TextDecoder().decode(c);
1028
+ let r; try { r = JSON.parse(raw); } catch { console.log("目录返回的不是 JSON"); process.exit(3); }
1029
+ if (r?.ok === false) { console.log(r?.error?.message ?? "目录拒绝了这次请求"); process.exit(4); }
1030
+ if (r?.data == null) process.exit(5);
1031
+ if (!r?.data?.manifest) { console.log("目录条目里没有 manifest 字段"); process.exit(3); }
1032
+ console.log(JSON.stringify(r.data.manifest));
1033
+ ' 2>/dev/null)"; rc=$?
1034
+ local outs="出路:--manifest <本地文件>,或不带 --from 用镜像自带的样例清单。"
1035
+ case "$rc" in
1036
+ 0) printf '%s' "$mout"; return ;;
1037
+ 5) die "目录里还没有 ${key}(那个 App 还没发过版?)。${outs}" ;;
1038
+ 4) die "目录拒绝了这次请求:${mout}。${outs}" ;;
1039
+ *) die "读取目录条目失败:${mout:-未知错误}。${outs}" ;;
1040
+ esac
1041
+ fi
1042
+ # 默认:一盒镜像自带的那批样例清单
1043
+ dc run --rm --no-deps -T portal-api cat "/app/deploy/app-devkit/manifests/${key}.manifest.json" 2>/dev/null \
1044
+ || die "这版一盒镜像里没有 ${key} 的清单。三条出路:① ${0} pull 换新镜像;② --manifest <你手上那份 app.manifest.json>;③ --from <在线门户地址> 从平台目录拉。"
1045
+ }
1046
+
1047
+ cmd_add() {
1048
+ _require_objectstore_assets
1049
+ _objectstore_image
1050
+ _pin_postgres
1051
+ local key="" want_image=""
1052
+ ADD_MANIFEST=""; ADD_FROM=""
1053
+ while [ $# -gt 0 ]; do
1054
+ case "$1" in
1055
+ --image) want_image="${2:-}"; shift 2 ;;
1056
+ --manifest) ADD_MANIFEST="${2:-}"; shift 2 ;;
1057
+ --from) ADD_FROM="${2:-}"; shift 2 ;;
1058
+ -*) die "未知参数 $1(支持 --image <ref> / --manifest <文件> / --from <门户地址>)" ;;
1059
+ *) key="$1"; shift ;;
1060
+ esac
1061
+ done
1062
+ [ -n "$key" ] || die "用法:${0} add <key> [--image <ref>] [--manifest <文件>] [--from <门户地址>]"
1063
+ # 清单来源优先级:--manifest <文件> > --from / MANIFEST_STORE > 镜像自带样例。
1064
+ # 配了 MANIFEST_STORE 就不必每次敲 --from(地址与只读令牌都在 .xgent-registry.env 里)。
1065
+ load_registry_config || true
1066
+ [ -n "${ADD_FROM:-}" ] || ADD_FROM="${MANIFEST_STORE:-}"
1067
+
1068
+ info "① 取清单"
1069
+ local mj; mj="$(_manifest_json "$key")"
1070
+ [ -n "$mj" ] || die "清单是空的。"
1071
+
1072
+ # 用 portal-api 里的 bun 解析(不对宿主机的 python/jq 做任何假设)
1073
+ local fields
1074
+ # JavaScript template expressions must reach Bun without shell expansion.
1075
+ # shellcheck disable=SC2016
1076
+ fields="$(printf '%s' "$mj" | dc run --rm --no-deps -T portal-api bun -e '
1077
+ let raw=""; for await (const c of Bun.stdin.stream()) raw += new TextDecoder().decode(c);
1078
+ const m = JSON.parse(raw); const d = m.deployDescriptor ?? {};
1079
+ const q = (v) => String(v ?? "").replace(/\n/g, " ");
1080
+ console.log(`M_KEY=${q(m.listingKey)}`);
1081
+ console.log(`M_TYPE=${q(m.type)}`);
1082
+ console.log(`M_IMAGE=${q(d.image)}`);
1083
+ console.log(`M_PORT=${q(d.port ?? 8080)}`);
1084
+ console.log(`M_HEALTH=${q(d.healthPath ?? "/health")}`);
1085
+ console.log(`M_SA=${q((m.serviceAccount ?? {}).clientId)}`);
1086
+ console.log(`M_ENV=${(m.requiredEnv ?? []).map((e) => (typeof e === "string" ? e : e.key)).join(" ")}`);
1087
+ console.log(`M_KAFKA=${(m.requiredServices ?? []).some((s) => s.kind === "kafka") ? "1" : "0"}`);
1088
+ // 非空 ⇒ 它是跨应用交换的【发起方】,需要一把 App Secret(下面与 SA 密钥同源生成注入)。
1089
+ console.log(`M_XTARGETS=${(m.exchangeTargets ?? []).join(" ")}`);
1090
+ console.log(`M_MIGRATE=${(d.migrateArgs ?? []).join(" ")}`);
1091
+ console.log(`M_DEPS=${(m.dependencies ?? []).join(" ")}`);
1092
+ ' 2>/dev/null)" || die "解析清单失败 —— 它可能不是一份合法的 app.manifest.json。"
1093
+ local M_KEY="" M_TYPE="" M_IMAGE="" M_PORT="" M_HEALTH="" M_SA="" M_ENV="" M_KAFKA="" M_XTARGETS="" M_MIGRATE="" M_DEPS=""
1094
+ eval "$(printf '%s' "$fields" | sed 's/^\([A-Z_]*\)=\(.*\)$/\1="\2"/')"
1095
+ [ "$M_KEY" = "$key" ] || die "清单里的 listingKey 是「${M_KEY}」,与你要加的「${key}」对不上。"
1096
+ info " ${M_KEY} type=${M_TYPE} port=${M_PORT} sa=${M_SA}"
1097
+
1098
+ # 依赖预检:register-app 要求 dependencies 里每个 key 在【这台门户】已有清单,否则
1099
+ # DEPENDENCY_UNAVAILABLE —— 而且只报第一个、带一屏堆栈。拉镜像之前一次点名全部缺的。
1100
+ # 只卡「有没有清单」:装不装由「应用管理 → 应用市场」安装时按依赖一并装上,不归这里。
1101
+ if [ -n "$M_DEPS" ]; then
1102
+ dc up -d postgres >/dev/null 2>&1 || true
1103
+ local rows dep dmiss=""
1104
+ if rows="$(dc exec -T postgres psql -U postgres -d "$(_eff POSTGRES_DB xgent-portal)" -tAc 'select listing_key from marketplace_listings' 2>/dev/null)"; then
1105
+ rows=" $(printf '%s' "$rows" | tr -d '\r' | tr '\n' ' ') "
1106
+ for dep in $M_DEPS; do
1107
+ _is_portal_hosted "$dep" && continue
1108
+ case "$rows" in *" $dep "*) ;; *) dmiss="${dmiss:+$dmiss }$dep" ;; esac
1109
+ done
1110
+ else
1111
+ warn "读不到本地门户的清单表(postgres 还没就绪或还没 migrate),跳过依赖预检,交给 register-app 判。"
1112
+ fi
1113
+ [ -z "$dmiss" ] || die "「${key}」依赖 ${dmiss},这台一盒里还没有它们的清单 —— 直接注册会被拒(DEPENDENCY_UNAVAILABLE)。
1114
+ 先逐个 ${0} add <依赖>(配了 MANIFEST_STORE 就从目录取清单;镜像在 <REGISTRY>/<ONEBOX_PROJECT>/ 下,清单没写 deployDescriptor.image 时加 --image <全引用>),再重跑 ${0} add ${key}。
1115
+ 之后在「应用管理 → 应用市场」里安装 ${key},依赖会被一并装上、自动授予。"
1116
+ fi
1117
+
1118
+ # ② 镜像:清单里的相对名按 <REGISTRY>/<ONEBOX_PROJECT>/ 补全(版本由清单钉住,可复现)
1119
+ local ivar ref; ivar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_IMAGE"
1120
+ ref="${want_image:-$(_eff "$ivar")}"
1121
+ if [ -z "$ref" ]; then
1122
+ [ -n "$M_IMAGE" ] || die "清单里没有 deployDescriptor.image,也没给 --image。
1123
+ 陪调用的平台侧 App 镜像在 ${REGISTRY:-<REGISTRY>}/${ONEBOX_PROJECT:-${PROJECT:-<ONEBOX_PROJECT>}}/${key}:<tag> 下 —— 用 --image 给全引用(tag 找门户团队确认),并请该 App 在清单里补上 deployDescriptor.image。"
1124
+ case "$M_IMAGE" in
1125
+ */*) ref="$M_IMAGE" ;; # 已经带项目/域名,原样用
1126
+ *) load_registry_config || true
1127
+ [ -n "${REGISTRY:-}" ] || die "还没配拉取凭证 —— 先按 SKILL.md §0 放一份 .xgent-registry.env。"
1128
+ ref="${REGISTRY}/${ONEBOX_PROJECT:-${PROJECT:-}}/${M_IMAGE}" ;;
1129
+ esac
1130
+ fi
1131
+ info "② 镜像 ${ref}"
1132
+ if docker image inspect "$ref" >/dev/null 2>&1; then info " 本地已有,跳过拉取"
1133
+ else
1134
+ require_puller; registry_login
1135
+ # 只发了 amd64 的镜像(buildx 默认带 attestation,推上去是个 index)在 Apple Silicon 上裸 pull
1136
+ # 报 no matching manifest。本机没指定平台、裸 pull 又失败时,看它有没有 amd64 那一份:有就按
1137
+ # amd64 拉(走仿真),并把 <PREFIX>_PLATFORM 记进 compose.env —— 生成片段的 platform: 读它。
1138
+ # 其它失败原因(项目 / tag 不对、没权限)由 do_pull 原样报。
1139
+ local pvar plat; pvar="${ivar%_IMAGE}_PLATFORM"; plat="$(_eff "$pvar" "$(_eff APP_PLATFORM)")"
1140
+ [ -n "$plat" ] || info "拉 ${ref} …"
1141
+ if [ -n "$plat" ] || ! docker pull "$ref" >/dev/null 2>&1; then
1142
+ if [ -z "$plat" ] && docker manifest inspect "$ref" 2>/dev/null | grep -Eq '"architecture": *"amd64"'; then
1143
+ plat="linux/amd64"; warn "${ref} 没有本机架构的版本,改按 ${plat} 拉(仿真运行,冷启动慢)"
1144
+ _env_set "$pvar" "$plat"
1145
+ fi
1146
+ do_pull "$ref" "配合调试用的 App 都发在一盒同一个项目(ONEBOX_PROJECT=${ONEBOX_PROJECT:-未配})下;确实不在就用 --image 给全引用。" "$plat"
1147
+ fi
1148
+ fi
1149
+ _env_set "$ivar" "$ref"
1150
+
1151
+ # ③ 密钥:一盒现生成,两侧同源(清单里有没有明文都不影响)
1152
+ local svar sec; svar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_SA_SECRET"
1153
+ sec="$(_eff "$svar")"; [ -n "$sec" ] || { sec="$(rand_hex | cut -c1-32)"; _env_append_secret "$svar" "$sec"; }
1154
+ # 声明了 exchangeTargets 的 App 是跨应用交换的【发起方】,它在 /oauth/token 上用
1155
+ # `sk_<key>` + App Secret 换对方的令牌。目录里的清单按红线剥掉了 exchangeInitiatorSecret,
1156
+ # 而 register-app 的 dev 模式只在【清单里有这个字段】时才 wireInitiatorSecret ——
1157
+ # 不补这一把,该 App 的跨应用交换会稳定 401,且症状出现在「发起方」而不是这里。
1158
+ local avar asec=""; avar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_APP_SECRET"
1159
+ if [ -n "$M_XTARGETS" ]; then
1160
+ asec="$(_eff "$avar")"; [ -n "$asec" ] || { asec="$(rand_hex | cut -c1-32)"; _env_append_secret "$avar" "$asec"; }
1161
+ fi
1162
+
1163
+ info "④ 注册清单(非破坏性、幂等)"
1164
+ # register-app 不带 --prod 是 dev 模式,而 dev 模式【强制要求】serviceAccount.secret;
1165
+ # 目录里的清单按红线只留 clientId。把③那把注进去 —— 于是门户库里那把与容器 env 里那把
1166
+ # 才真的是同一把(这一条对镜像自带样例同样生效:它们自带的明文 dev secret 与容器 env
1167
+ # 里那把本来就不是同一把,只是没人验过自省)。临时文件用完即删。
1168
+ # 两把密钥走 stdin 的前两行,不走 `-e`:命令行参数同机 `ps` 可见。
1169
+ printf '%s\n%s\n%s' "$sec" "$asec" "$mj" | dc run --rm --no-deps -T portal-api bun -e '
1170
+ let raw=""; for await (const c of Bun.stdin.stream()) raw += new TextDecoder().decode(c);
1171
+ const a = raw.indexOf("\n"); const b = raw.indexOf("\n", a + 1);
1172
+ const secret = raw.slice(0, a);
1173
+ const appSecret = raw.slice(a + 1, b);
1174
+ const m = JSON.parse(raw.slice(b + 1));
1175
+ m.serviceAccount = { ...(m.serviceAccount ?? {}), secret };
1176
+ // 空 = 这个 App 不是交换发起方;写进去反而会让 register-app 白跑一次 wire。
1177
+ if (appSecret) m.exchangeInitiatorSecret = appSecret;
1178
+ console.log(JSON.stringify(m, null, 2));
1179
+ ' > "$HOME_DIR/.add-$key.manifest.json" || die "注入 dev 密钥失败。"
1180
+ dc run --rm --no-deps -v "$HOME_DIR:/devkit:ro" portal-api bun run register-app "/devkit/.add-$key.manifest.json" \
1181
+ || { rm -f "$HOME_DIR/.add-$key.manifest.json"; die "注册失败 —— 看上面的报错。"; }
1182
+ rm -f "$HOME_DIR/.add-$key.manifest.json"
1183
+ _reload_proxy
1184
+
1185
+ info "⑤ 建库 xgent-${key}"
1186
+ dc up -d postgres >/dev/null 2>&1 || true
1187
+ _ensure_db "xgent-${key}"
1188
+
1189
+ # ⑥ 从 manifest 生成 compose 片段
1190
+ local gen="$HOME_DIR/generated"; mkdir -p "$gen"
1191
+ local out="$gen/${key}.yml" PREFIX; PREFIX="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')"
1192
+ case " $M_ENV " in *" ${PREFIX}_KAFKA_USERNAME "*) M_KAFKA=1 ;; esac
1193
+ if [ "$M_KAFKA" = 1 ]; then
1194
+ if ! _ensure_kafka "$key" "$PREFIX"; then _kafka_add_warning "$key"; fi
1195
+ fi
1196
+ {
1197
+ echo "# 由 onebox.sh add ${key} 从 manifest 生成 —— 不要手改,重跑 add 会覆盖。"
1198
+ echo "services:"
1199
+ echo " ${key}-server:"
1200
+ echo " image: \${${ivar}:?}"
1201
+ echo " platform: \${${PREFIX}_PLATFORM:-\${APP_PLATFORM:-}}"
1202
+ echo " restart: unless-stopped"
1203
+ # ⚠️ 绝对路径。compose 里的相对路径按【第一个 -f】的目录解析(= 一盒根),不是按本文件
1204
+ # 所在目录 —— 写 ../compose.env 会解析到一盒根的上一级,报 env file not found(实测)。
1205
+ # 这是生成文件、随机器走、已被 .gitignore 挡住,绝对路径没有副作用。
1206
+ echo " env_file: [\"${ENV_FILE}\"]"
1207
+ echo " environment:"
1208
+ # 一盒反代的通用规则只反代 <key>-server:8080;镜像不听 8080 的(如 observability 8081)
1209
+ # 在 compose.env 里用 <PREFIX>_PORT 改成 8080(值归平台,与生产注入 PORT 同语义)。
1210
+ echo " PORT: \"\${${PREFIX}_PORT:-${M_PORT}}\""
1211
+ echo " PORTAL_INTROSPECT_URL: http://portal-api:3000/api/tokens/introspect"
1212
+ echo " ${PREFIX}_SA_CLIENT_ID: ${M_SA}"
1213
+ echo " ${PREFIX}_SA_CLIENT_SECRET: \${${svar}}"
1214
+ # 发起方才有:门户库里那把(register-app 从清单读)与容器里这把必须同源,否则
1215
+ # 跨应用交换在【发起方】上 401,而错看起来像是被调方的问题。
1216
+ [ -n "$M_XTARGETS" ] && echo " ${PREFIX}_APP_SECRET: \${${avar}}"
1217
+ # 库连接串:<PREFIX>_DATABASE_URL 是生产的约定名(批准时按它建库并注入,发版 preflight 也要求它);
1218
+ # 后两个是旧名,留给还没改名的镜像。三个都指向同一个库。
1219
+ echo " ${PREFIX}_DATABASE_URL: postgres://postgres:postgres@postgres:5432/xgent-${key}"
1220
+ echo " ${PREFIX}_PG_DSN: postgres://postgres:postgres@postgres:5432/xgent-${key}"
1221
+ echo " DATABASE_URL: postgres://postgres:postgres@postgres:5432/xgent-${key}"
1222
+ echo " expose: [\"\${${PREFIX}_PORT:-${M_PORT}}\"]"
1223
+ echo " networks: { default: { aliases: [${key}-server] } }"
1224
+ } > "$out"
1225
+ info "⑥ 生成 ${out#"$HOME_DIR"/}"
1226
+ # requiredEnv 里【既不在上面生成的片段、也不在 compose.env】的键 —— 一盒版的 REQUIRED_ENV_MISSING
1227
+ # (生产还会把平台代为供给的键算作已提供,一盒只有这两处来源)。在这里点名,而不是等容器缺变量退出。
1228
+ if [ -n "$M_ENV" ]; then
1229
+ local gen_keys="PORT PORTAL_INTROSPECT_URL ${PREFIX}_SA_CLIENT_ID ${PREFIX}_SA_CLIENT_SECRET ${PREFIX}_DATABASE_URL ${PREFIX}_PG_DSN DATABASE_URL"
1230
+ [ -n "$M_XTARGETS" ] && gen_keys="$gen_keys ${PREFIX}_APP_SECRET"
1231
+ local ek missing=""
1232
+ for ek in $M_ENV; do
1233
+ case " $gen_keys " in *" $ek "*) continue ;; esac
1234
+ [ -n "$(_eff "$ek")" ] && continue
1235
+ missing="${missing:+$missing }$ek"
1236
+ done
1237
+ if [ -n "$missing" ]; then
1238
+ warn "requiredEnv 里这些键既不在生成的片段里、也不在 compose.env 里:${missing}"
1239
+ _note "值归平台(生产由审批屏填),这里补进 compose.env 末尾,再重跑 ${0} add ${key}。"
1240
+ else
1241
+ _note "requiredEnv 的键都已到位(生成的片段 + compose.env)。"
1242
+ fi
1243
+ fi
1244
+
1245
+ # 例外:manifest 描述不了的自带 infra(如 knowledge 的 Chroma)
1246
+ local extra_args=() extra="$SKILL_DIR/services/${key}.extra.yml"
1247
+ [ -f "$extra" ] && { extra_args=(-f "$extra"); info " 叠加自带依赖 services/${key}.extra.yml"; }
1248
+
1249
+ # 对象存储桶:清单 requiredEnv 里带 *_S3_BUCKET_NAME / ZO_S3_BUCKET_NAME 的,按 compose.env 在 RustFS 建桶
1250
+ local bvar bname
1251
+ # M_ENV is a validated whitespace-delimited list of environment key names.
1252
+ # shellcheck disable=SC2086
1253
+ for bvar in $(printf '%s\n' $M_ENV | grep -E '_S3_BUCKET(_NAME)?$' || true); do
1254
+ bname="$(_eff "$bvar")"; [ -n "$bname" ] && _ensure_bucket "$bname"
1255
+ done
1256
+
1257
+ # 清单声明了 deployDescriptor.migrateArgs(生产由 deploy-controller 在换容器前跑):起容器前先跑一次
1258
+ if [ -n "$M_MIGRATE" ]; then
1259
+ info "⑥b 迁移:${key}-server ${M_MIGRATE}"
1260
+ _objectstore_up
1261
+ dc up -d postgres >/dev/null
1262
+ # shellcheck disable=SC2086
1263
+ XGENT_ONEBOX_HOME="$HOME_DIR" dc -f "$out" ${extra_args[@]+"${extra_args[@]}"} run --rm --no-deps "${key}-server" $M_MIGRATE \
1264
+ || warn "${key}-server ${M_MIGRATE} 失败 —— 看上面的报错(多半是 env 值没到位)"
1265
+ fi
1266
+
1267
+ info "⑦ 起容器"
1268
+ XGENT_ONEBOX_HOME="$HOME_DIR" dc -f "$out" ${extra_args[@]+"${extra_args[@]}"} up -d "${key}-server"
1269
+
1270
+ echo; info "⑧ 冒烟"
1271
+ # amd64 镜像在 Apple Silicon 上走仿真,冷启动能到两分钟(observability 实测 ~100s):等 120s。
1272
+ local i=0 code=""
1273
+ while [ "$i" -lt 60 ]; do
1274
+ code="$(curl -s -m 5 -o /dev/null -w '%{http_code}' "${BASE_URL}/svc/${key}${M_HEALTH}" || true)"
1275
+ [ "$code" = "200" ] && break; i=$((i+1)); sleep 2
1276
+ done
1277
+ if [ "$code" = "200" ]; then _ok "/svc/${key}${M_HEALTH} 200"
1278
+ else _bad "/svc/${key}${M_HEALTH} HTTP ${code:-000}(等了 120s)" "${0} dc logs ${key}-server —— 多半是镜像认的 env 变量名与上面生成的那几个不同名,补进 compose.env 末尾即可"; fi
1279
+
1280
+ [ -n "${ADD_QUIET:-}" ] && return 0
1281
+ echo
1282
+ info "还差最后一步(浏览器里点一下):rockie@xgent.ai 登控制台 → 租户 → 可用应用 → 勾上「${key}」保存。"
1283
+ _note "service 型 App 的勾选【就是】安装;不装的话跨应用交换拿不到它的 scope。"
1284
+ # wireInitiatorSecret 只能写【已安装】的 apps 行 —— 先勾选安装、再重跑一次 add 才落得下去。
1285
+ [ -n "$M_XTARGETS" ] && _note "它声明了 exchangeTargets(${M_XTARGETS})—— 勾选安装【之后】再跑一次 ${0} add ${key},那把 App Secret 才写得进已安装的行(幂等,不会重复建东西)。"
1286
+ echo
1287
+ info "然后在【你自己】的 manifest 里两处一起加,再 ${0} up:"
1288
+ printf ' "scopes": […, "%s.read", …]\n' "$(printf '%s' "$key" | tr '-' '_')"
1289
+ printf ' "exchangeTargets": ["%s"]\n' "$key"
1290
+ }
1291
+
1292
+ # --- doctor:把排查表能自动判的都判一遍 ----------------------------------------
1293
+ DOCTOR_BAD=0
1294
+ cmd_doctor() {
1295
+ DOCTOR_BAD=0
1296
+ echo "一盒体检(${BASE_URL})"
1297
+ echo
1298
+
1299
+ echo "对象存储"
1300
+ if ! _objectstore_assets_current; then
1301
+ _bad "对象存储部署资产是旧版" "$0 upgrade --image <新版一盒镜像> && $0 up"
1302
+ elif dc exec -T rustfs curl -fsS --max-time 5 http://127.0.0.1:9000/health </dev/null >/dev/null 2>&1; then
1303
+ _ok "RustFS /health 正常"
1304
+ else
1305
+ _bad "RustFS 未就绪" "$0 up;失败时保留 rustfs-data,查看 $0 dc logs rustfs。"
1306
+ fi
1307
+
1308
+ echo "Kafka"
1309
+ if ! _kafka_assets_current; then
1310
+ _bad "Kafka 部署资产或配置是旧版" "$0 upgrade --image <新版一盒镜像> && $0 up"
1311
+ elif dc exec -T kafka nc -z 127.0.0.1 9092 </dev/null >/dev/null 2>&1; then
1312
+ _ok "Kafka INTERNAL 监听正常(SASL 认证由服务探测验证)"
1313
+ else
1314
+ _bad "Kafka 未就绪;门户与现有应用可继续运行" "$0 dc logs --tail 50 kafka;修复后重跑 $0 up。"
1315
+ fi
1316
+
1317
+ echo "① 镜像版本"
1318
+ local iv; iv="$(_eff XGENT_IMAGE)"
1319
+ if docker image inspect "$iv" >/dev/null 2>&1; then
1320
+ if docker run --rm --entrypoint sh "$iv" -c '[ -d /srv/www/apps ]' >/dev/null 2>&1; then
1321
+ _ok "门户镜像带有共享目录预建(v1.2.0+)"
1322
+ else
1323
+ _bad "门户镜像是旧版(缺 /srv/www/apps 等预建目录)" "$0 pull && $0 dc down -v && $0 up —— 顺序是【先换镜像、再删卷】,只做一半都不解决"
1324
+ fi
1325
+ else _note "本地没有 ${iv},跳过($0 pull)"; fi
1326
+
1327
+ echo "② 命名卷属主(EACCES 一族的根因)"
1328
+ if _svc_running reverse-proxy; then
1329
+ local bad_dirs=""
1330
+ local d
1331
+ for d in /srv/www/apps /etc/caddy/svc-allow /etc/caddy/apps-csp; do
1332
+ local owner; owner="$(dc exec -T -u root reverse-proxy stat -c '%u' "$d" 2>/dev/null | tr -d '\r' || echo "")"
1333
+ [ "$owner" = "1000" ] || bad_dirs="$bad_dirs $d"
1334
+ done
1335
+ if [ -z "$bad_dirs" ]; then _ok "三个共享卷都归 bun(1000)"
1336
+ else _bad "这些卷不归 portal-api:$bad_dirs" "$0 dc exec -u root reverse-proxy chown -R 1000:1000$bad_dirs"; fi
1337
+ # 内联 key 却存在 map 文件 ⇒ duplicate input ⇒ 反代整个起不来
1338
+ local dup; dup="$(dc exec -T reverse-proxy sh -c 'ls /etc/caddy/svc-allow/ 2>/dev/null' 2>/dev/null | tr -d '\r' | grep -E '^(knowledge|omni-parser|task-gateway|pagebuilder)\.map$' | tr '\n' ' ' || true)"
1339
+ if [ -n "$dup" ]; then _bad "内联 key 又写了 map:$dup" "这会让 Caddy 拒绝整份配置(全站 502)。$0 dc exec -u root reverse-proxy sh -c 'cd /etc/caddy/svc-allow && rm -f $dup' && $0 dc restart reverse-proxy"
1340
+ else _ok "没有与内联 key 撞车的 map 文件"; fi
1341
+ else _note "reverse-proxy 没在跑,跳过($0 up)"; fi
1342
+
1343
+ echo "③ 架构匹配"
1344
+ local host_arch img_arch; host_arch="$(docker version --format '{{.Server.Arch}}' 2>/dev/null || echo '?')"
1345
+ if [ -n "$APP_IMAGE" ] && docker image inspect "$APP_IMAGE" >/dev/null 2>&1; then
1346
+ img_arch="$(docker image inspect --format '{{.Architecture}}' "$APP_IMAGE" 2>/dev/null || echo '?')"
1347
+ if [ "$img_arch" = "$host_arch" ] || [ -n "$(_eff APP_PLATFORM)" ]; then _ok "APP_IMAGE ($img_arch) 与本机 ($host_arch) 兼容"
1348
+ else _bad "APP_IMAGE 是 ${img_arch},本机是 $host_arch" "compose.env 末尾加:APP_PLATFORM=linux/${img_arch}(Apple Silicon 走 Rosetta,慢但能跑)"; fi
1349
+ else _note "APP_IMAGE 未填或本地没有,跳过"; fi
1350
+
1351
+ echo "④ 数据库"
1352
+ if _svc_running postgres; then
1353
+ local want="$CATALOG"; [ -n "$APP_KEY" ] && want="$CATALOG,$APP_KEY"
1354
+ local dbs; dbs="$(dc exec -T postgres psql -U postgres -lqt 2>/dev/null | cut -d'|' -f1 | tr -d ' \r' || true)"
1355
+ local miss=""
1356
+ for k in ${want//,/ }; do
1357
+ _is_portal_hosted "$k" && continue
1358
+ printf '%s\n' "$dbs" | grep -qx "xgent-$k" || miss="$miss xgent-$k"
1359
+ done
1360
+ if [ -z "$miss" ]; then _ok "目录里每个 App 的库都在"
1361
+ else _bad "缺库:$miss" "$0 dc exec postgres psql -U postgres -c 'CREATE DATABASE \"<库名>\"'($0 add <key> 会顺手建)"; fi
1362
+ else _note "postgres 没在跑,跳过"; fi
1363
+
1364
+ # 栈没起的时候,⑤⑥ 每一格都会红,而真正的下一步只有一个 —— 别拿 8 行红字淹掉它。
1365
+ if ! _svc_running portal-api; then
1366
+ echo "⑤⑥ 目录/路由"
1367
+ _bad "栈还没起来(portal-api 没在跑)" "${0} up —— 它会按顺序铺完再自动跑一次体检"
1368
+ echo; printf '%s先把栈起来,其余的判断才有意义。%s\n' "$c_ylw" "$c_off"
1369
+ return 0
1370
+ fi
1371
+
1372
+ echo "⑤ 目录 vs 容器"
1373
+ for k in ${CATALOG//,/ }; do
1374
+ _is_portal_hosted "$k" && continue
1375
+ case "$k" in files|llm-gateway|git|org) continue;; esac
1376
+ if _svc_running "${k}-server"; then _ok "$k 的容器在跑"
1377
+ else _bad "$k 在 XGENT_APP_CATALOG 里但容器没起" "$0 add ${k}(清单已注册的话它只会补建库+起容器)"; fi
1378
+ done
1379
+
1380
+ echo "⑥ 路由与健康"
1381
+ cmd_smoke >/dev/null 2>&1 || true
1382
+ local keys="$CATALOG"; [ -n "$APP_KEY" ] && keys="$CATALOG,$APP_KEY"
1383
+ local code
1384
+ code="$(curl -s -m 8 -o /dev/null -w '%{http_code}' "$BASE_URL/health" || true)"
1385
+ if [ "$code" = "200" ]; then _ok "门户 /health 200"
1386
+ else _bad "门户 /health HTTP ${code:-000}" "000=反代没起或端口不对($0 dc ps);其它看 $0 dc logs portal-api"; fi
1387
+ for k in ${keys//,/ }; do
1388
+ _is_portal_hosted "$k" && continue
1389
+ code="$(curl -s -m 8 -o /dev/null -w '%{http_code}' "$BASE_URL/svc/$k/health" || true)"
1390
+ case "$code" in
1391
+ 200) _ok "/svc/$k 200";;
1392
+ 404) _bad "/svc/$k 404" "放行尚未应用:检查发布状态及 $0 dc logs portal-api,勿手工 reload 兼容模板";;
1393
+ 502) _bad "/svc/$k 502" "后端不在/没听 8080/别名没命中:$0 dc logs ${k}-server";;
1394
+ *) _bad "/svc/$k HTTP ${code:-000}" "$0 dc ps";;
1395
+ esac
1396
+ done
1397
+
1398
+ echo
1399
+ if [ "$DOCTOR_BAD" -eq 0 ]; then printf '%s一切正常。%s\n' "$c_grn" "$c_off"
1400
+ else printf '%s%s 项要处理 —— 每条下面那行可以直接粘。%s\n' "$c_ylw" "$DOCTOR_BAD" "$c_off"
1401
+ printf '%s还有判不了的?排查表按「你看到什么」编排:references/troubleshooting.md%s\n' "$c_dim" "$c_off"; fi
1402
+ return 0
1403
+ }
1404
+
1405
+ case "${1-status}" in
1406
+ init) shift; cmd_init "$@" ;;
1407
+ upgrade) require_home; load_env; shift; cmd_upgrade "$@" ;;
1408
+ pull) shift; cmd_pull "$@" ;;
1409
+ env) require_home; load_env; cmd_env ;;
1410
+ smoke) require_home; load_env; cmd_smoke ;;
1411
+ status) require_home; load_env; cmd_status ;;
1412
+ chain) require_home; load_env; { while IFS= read -r -d '' x; do printf '%s ' "$x"; done < <(compose_args); echo; } ;;
1413
+ up) require_home; load_env; cmd_up ;;
1414
+ doctor) require_home; load_env; cmd_doctor ;;
1415
+ add) require_home; load_env; shift; cmd_add "$@" ;;
1416
+ dc) require_home; load_env; shift; dc "$@" ;;
1417
+ # 打印开头那段注释直到第一条非注释行 —— 别写死行号,加一条子命令就会截断(踩过)。
1418
+ -h|--help|help) awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "${BASH_SOURCE[0]}" ;;
1419
+ *) die "未知子命令 '$1'。用 init | upgrade | up | doctor | add <key> | pull | env | status | smoke | chain | dc <args...>" ;;
1420
+ esac