@prismer/runtime 2.0.7 → 2.2.55
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.
- package/CHANGELOG.md +3631 -0
- package/README.md +34 -12
- package/apc/skills/FIELD-DICTIONARY.md +111 -0
- package/apc/skills/bug-reproduce/SKILL.md +150 -0
- package/apc/skills/bug-reproduce/skill.json +96 -0
- package/apc/skills/code-review/SKILL.md +198 -0
- package/apc/skills/code-review/skill.json +124 -0
- package/apc/skills/design-review/SKILL.md +122 -0
- package/apc/skills/design-review/skill.json +88 -0
- package/apc/skills/doc-sync/SKILL.md +168 -0
- package/apc/skills/doc-sync/skill.json +81 -0
- package/apc/skills/env-doctor/SKILL.md +194 -0
- package/apc/skills/env-doctor/skill.json +209 -0
- package/apc/skills/git-ops/SKILL.md +189 -0
- package/apc/skills/git-ops/skill.json +94 -0
- package/apc/skills/impact-trace/SKILL.md +168 -0
- package/apc/skills/impact-trace/skill.json +104 -0
- package/apc/skills/observability/SKILL.md +195 -0
- package/apc/skills/observability/skill.json +116 -0
- package/apc/skills/release-db-config-sync/SKILL.md +186 -0
- package/apc/skills/release-db-config-sync/skill.json +109 -0
- package/apc/skills/release-ota-promote/SKILL.md +195 -0
- package/apc/skills/release-ota-promote/skill.json +176 -0
- package/apc/skills/release-preflight/SKILL.md +174 -0
- package/apc/skills/release-preflight/skill.json +175 -0
- package/apc/skills/release-rollback/SKILL.md +214 -0
- package/apc/skills/release-rollback/skill.json +230 -0
- package/apc/skills/release-tag/SKILL.md +194 -0
- package/apc/skills/release-tag/skill.json +94 -0
- package/apc/skills/releasing-prod/SKILL.md +49 -0
- package/apc/skills/releasing-test/SKILL.md +135 -0
- package/apc/skills/sdk-release/SKILL.md +200 -0
- package/apc/skills/spec-intake/SKILL.md +169 -0
- package/apc/skills/spec-intake/skill.json +93 -0
- package/apc/skills/test-result-feedback/SKILL.md +239 -0
- package/apc/skills/test-result-feedback/skill.json +193 -0
- package/apc/skills/test-runner/SKILL.md +169 -0
- package/apc/skills/test-runner/skill.json +103 -0
- package/apc/skills/ui-align/SKILL.md +209 -0
- package/apc/skills/ui-align/skill.json +114 -0
- package/apc/skills/ui-canvas/SKILL.md +148 -0
- package/apc/skills/ui-canvas/skill.json +127 -0
- package/built-in-skills/agent-coordination/SKILL.md +257 -0
- package/built-in-skills/agent-meta/SKILL.md +53 -0
- package/built-in-skills/assets/SKILL.md +133 -0
- package/built-in-skills/browser-use/SKILL.md +93 -0
- package/built-in-skills/canvas-design/LICENSE.txt +202 -0
- package/built-in-skills/canvas-design/SKILL.md +157 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/built-in-skills/claim-agent-ownership/SKILL.md +255 -0
- package/built-in-skills/claude-api/LICENSE.txt +202 -0
- package/built-in-skills/claude-api/SKILL.md +325 -0
- package/built-in-skills/claude-api/csharp/claude-api.md +402 -0
- package/built-in-skills/claude-api/curl/examples.md +216 -0
- package/built-in-skills/claude-api/curl/managed-agents.md +336 -0
- package/built-in-skills/claude-api/go/claude-api.md +421 -0
- package/built-in-skills/claude-api/go/managed-agents/README.md +561 -0
- package/built-in-skills/claude-api/java/claude-api.md +432 -0
- package/built-in-skills/claude-api/java/managed-agents/README.md +442 -0
- package/built-in-skills/claude-api/php/claude-api.md +375 -0
- package/built-in-skills/claude-api/php/managed-agents/README.md +435 -0
- package/built-in-skills/claude-api/python/claude-api/README.md +420 -0
- package/built-in-skills/claude-api/python/claude-api/batches.md +185 -0
- package/built-in-skills/claude-api/python/claude-api/files-api.md +165 -0
- package/built-in-skills/claude-api/python/claude-api/streaming.md +162 -0
- package/built-in-skills/claude-api/python/claude-api/tool-use.md +590 -0
- package/built-in-skills/claude-api/python/managed-agents/README.md +332 -0
- package/built-in-skills/claude-api/ruby/claude-api.md +113 -0
- package/built-in-skills/claude-api/ruby/managed-agents/README.md +389 -0
- package/built-in-skills/claude-api/shared/agent-design.md +101 -0
- package/built-in-skills/claude-api/shared/error-codes.md +213 -0
- package/built-in-skills/claude-api/shared/live-sources.md +135 -0
- package/built-in-skills/claude-api/shared/managed-agents-api-reference.md +378 -0
- package/built-in-skills/claude-api/shared/managed-agents-client-patterns.md +209 -0
- package/built-in-skills/claude-api/shared/managed-agents-core.md +238 -0
- package/built-in-skills/claude-api/shared/managed-agents-environments.md +215 -0
- package/built-in-skills/claude-api/shared/managed-agents-events.md +195 -0
- package/built-in-skills/claude-api/shared/managed-agents-memory.md +197 -0
- package/built-in-skills/claude-api/shared/managed-agents-multiagent.md +99 -0
- package/built-in-skills/claude-api/shared/managed-agents-onboarding.md +114 -0
- package/built-in-skills/claude-api/shared/managed-agents-outcomes.md +106 -0
- package/built-in-skills/claude-api/shared/managed-agents-overview.md +68 -0
- package/built-in-skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +173 -0
- package/built-in-skills/claude-api/shared/managed-agents-tools.md +321 -0
- package/built-in-skills/claude-api/shared/managed-agents-webhooks.md +110 -0
- package/built-in-skills/claude-api/shared/model-migration.md +779 -0
- package/built-in-skills/claude-api/shared/models.md +121 -0
- package/built-in-skills/claude-api/shared/prompt-caching.md +171 -0
- package/built-in-skills/claude-api/shared/tool-use-concepts.md +327 -0
- package/built-in-skills/claude-api/typescript/claude-api/README.md +333 -0
- package/built-in-skills/claude-api/typescript/claude-api/batches.md +106 -0
- package/built-in-skills/claude-api/typescript/claude-api/files-api.md +98 -0
- package/built-in-skills/claude-api/typescript/claude-api/streaming.md +178 -0
- package/built-in-skills/claude-api/typescript/claude-api/tool-use.md +527 -0
- package/built-in-skills/claude-api/typescript/managed-agents/README.md +359 -0
- package/built-in-skills/codebase-design/DEEPENING.md +37 -0
- package/built-in-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/built-in-skills/codebase-design/LICENSE +21 -0
- package/built-in-skills/codebase-design/SKILL.md +116 -0
- package/built-in-skills/conversation-compaction/SKILL.md +114 -0
- package/built-in-skills/council-creator/SKILL.md +426 -0
- package/built-in-skills/diagnosing-bugs/LICENSE +21 -0
- package/built-in-skills/diagnosing-bugs/SKILL.md +136 -0
- package/built-in-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/built-in-skills/doc-coauthoring/SKILL.md +376 -0
- package/built-in-skills/document-generation/SKILL.md +105 -0
- package/built-in-skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/built-in-skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/built-in-skills/domain-modeling/LICENSE +21 -0
- package/built-in-skills/domain-modeling/SKILL.md +76 -0
- package/built-in-skills/frontend-design/LICENSE.txt +177 -0
- package/built-in-skills/frontend-design/SKILL.md +43 -0
- package/built-in-skills/human-approval/SKILL.md +129 -0
- package/built-in-skills/image-generate/SKILL.md +128 -0
- package/built-in-skills/image-generate/scripts/generate-and-deliver.mjs +289 -0
- package/built-in-skills/ingest/SKILL.md +73 -0
- package/built-in-skills/internal-comms/LICENSE.txt +202 -0
- package/built-in-skills/internal-comms/SKILL.md +33 -0
- package/built-in-skills/internal-comms/examples/3p-updates.md +47 -0
- package/built-in-skills/internal-comms/examples/company-newsletter.md +65 -0
- package/built-in-skills/internal-comms/examples/faq-answers.md +30 -0
- package/built-in-skills/internal-comms/examples/general-comms.md +16 -0
- package/built-in-skills/liteparse/SKILL.md +176 -0
- package/built-in-skills/mcp-builder/LICENSE.txt +202 -0
- package/built-in-skills/mcp-builder/SKILL.md +237 -0
- package/built-in-skills/mcp-builder/reference/evaluation.md +602 -0
- package/built-in-skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/built-in-skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/built-in-skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/built-in-skills/mcp-builder/scripts/connections.py +151 -0
- package/built-in-skills/mcp-builder/scripts/evaluation.py +373 -0
- package/built-in-skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/built-in-skills/mcp-builder/scripts/requirements.txt +2 -0
- package/built-in-skills/memory/SKILL.md +471 -0
- package/built-in-skills/memory-dream/SKILL.md +339 -0
- package/built-in-skills/office-artifacts/SKILL.md +211 -0
- package/built-in-skills/okr/SKILL.md +154 -0
- package/built-in-skills/persona/SKILL.md +81 -0
- package/built-in-skills/persona-generator/SKILL.md +296 -0
- package/built-in-skills/pkf-svg/SKILL.md +253 -0
- package/built-in-skills/pkf-writing/SKILL.md +236 -0
- package/built-in-skills/prismer-im-collab/SKILL.md +168 -0
- package/built-in-skills/proactivity/SKILL.md +84 -0
- package/built-in-skills/remotion/SKILL.md +431 -0
- package/built-in-skills/role-builder/SKILL.md +203 -0
- package/built-in-skills/role-builder/scripts/author-role.mjs +334 -0
- package/built-in-skills/role-builder/scripts/ingest-role.mjs +223 -0
- package/built-in-skills/role-builder/scripts/instantiate-and-run.mjs +290 -0
- package/built-in-skills/role-builder/scripts/operation-harness.mjs +267 -0
- package/built-in-skills/skill-authoring/SKILL.md +134 -0
- package/built-in-skills/skill-authoring/skill.json +74 -0
- package/built-in-skills/skill-builder/SKILL.md +171 -0
- package/built-in-skills/skill-builder/scripts/ingest.mjs +265 -0
- package/built-in-skills/skill-creator/LICENSE.txt +202 -0
- package/built-in-skills/skill-creator/SKILL.md +227 -0
- package/built-in-skills/skill-creator/agents/analyzer.md +274 -0
- package/built-in-skills/skill-creator/agents/comparator.md +202 -0
- package/built-in-skills/skill-creator/agents/grader.md +223 -0
- package/built-in-skills/skill-creator/assets/eval_review.html +146 -0
- package/built-in-skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/built-in-skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/built-in-skills/skill-creator/references/external-library-import.md +110 -0
- package/built-in-skills/skill-creator/references/schemas.md +430 -0
- package/built-in-skills/skill-creator/scripts/__init__.py +0 -0
- package/built-in-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/built-in-skills/skill-creator/scripts/generate_report.py +326 -0
- package/built-in-skills/skill-creator/scripts/import-library.mjs +475 -0
- package/built-in-skills/skill-creator/scripts/improve_description.py +247 -0
- package/built-in-skills/skill-creator/scripts/package_skill.py +136 -0
- package/built-in-skills/skill-creator/scripts/quick_validate.py +103 -0
- package/built-in-skills/skill-creator/scripts/run_eval.py +310 -0
- package/built-in-skills/skill-creator/scripts/run_loop.py +328 -0
- package/built-in-skills/skill-creator/scripts/utils.py +47 -0
- package/built-in-skills/slack-gif-creator/LICENSE.txt +202 -0
- package/built-in-skills/slack-gif-creator/SKILL.md +291 -0
- package/built-in-skills/slack-gif-creator/core/easing.py +234 -0
- package/built-in-skills/slack-gif-creator/core/frame_composer.py +176 -0
- package/built-in-skills/slack-gif-creator/core/gif_builder.py +269 -0
- package/built-in-skills/slack-gif-creator/core/validators.py +136 -0
- package/built-in-skills/slack-gif-creator/requirements.txt +4 -0
- package/built-in-skills/tasks/SKILL.md +413 -0
- package/built-in-skills/tdd/LICENSE +21 -0
- package/built-in-skills/tdd/SKILL.md +110 -0
- package/built-in-skills/tdd/mocking.md +59 -0
- package/built-in-skills/tdd/refactoring.md +10 -0
- package/built-in-skills/tdd/tests.md +61 -0
- package/built-in-skills/team/SKILL.md +77 -0
- package/built-in-skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/built-in-skills/web-artifacts-builder/SKILL.md +105 -0
- package/built-in-skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/built-in-skills/web-artifacts-builder/scripts/init-artifact.sh +334 -0
- package/built-in-skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/built-in-skills/webapp-testing/LICENSE.txt +202 -0
- package/built-in-skills/webapp-testing/SKILL.md +97 -0
- package/built-in-skills/webapp-testing/examples/console_logging.py +35 -0
- package/built-in-skills/webapp-testing/examples/element_discovery.py +40 -0
- package/built-in-skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/built-in-skills/webapp-testing/scripts/with_server.py +106 -0
- package/built-in-skills/wechat-pay/SKILL.md +59 -0
- package/dist/cli.cjs +72577 -16101
- package/dist/cli.js +72752 -16232
- package/dist/index.cjs +72632 -16024
- package/dist/index.d.cts +4956 -640
- package/dist/index.d.ts +4956 -640
- package/dist/index.js +72564 -15963
- package/package.json +39 -6
- package/plugins/memory/prismer/__init__.py +1211 -0
- package/plugins/memory/prismer/plugin.yaml +8 -0
- package/plugins/memory/prismer/tool-schemas.generated.json +249 -0
- package/plugins/tools/prismer-recall/__init__.py +282 -0
- package/plugins/tools/prismer-recall/plugin.yaml +15 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { dirname, relative, resolve, sep } from 'node:path';
|
|
7
|
+
|
|
8
|
+
export class LibraryImportError extends Error {
|
|
9
|
+
constructor(stage, code, message, exitCode = 1, details = undefined) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'LibraryImportError';
|
|
12
|
+
this.stage = stage;
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.exitCode = exitCode;
|
|
15
|
+
this.details = details;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const SECRET_OPTIONS = new Set(['--api-key', '--token', '--jwt', '--secret', '--password']);
|
|
20
|
+
const BOOLEAN_OPTIONS = new Set(['--json', '--preflight-only', '--help']);
|
|
21
|
+
const IGNORED_DIRECTORIES = new Set(['.git', '.prismer', 'node_modules']);
|
|
22
|
+
const BUNDLE_EXCLUDED_FILES = new Set(['.DS_Store', 'Thumbs.db', 'LICENSE', 'LICENSE.txt', 'LICENSE.md']);
|
|
23
|
+
|
|
24
|
+
function optionName(arg) {
|
|
25
|
+
const equalsAt = typeof arg === 'string' ? arg.indexOf('=') : -1;
|
|
26
|
+
return equalsAt === -1 ? arg : arg.slice(0, equalsAt);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isLocalTarget(hostname) {
|
|
30
|
+
return ['localhost', '127.0.0.1', '::1', 'host.docker.internal'].includes(hostname);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseBoolean(value) {
|
|
34
|
+
return ['1', 'true', 'yes'].includes(String(value ?? '').toLowerCase());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeRelative(root, absolute) {
|
|
38
|
+
return relative(root, absolute).split(sep).join('/') || '.';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function sha256(value) {
|
|
42
|
+
return createHash('sha256').update(value).digest('hex');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function defaultLedgerPath(root) {
|
|
46
|
+
return resolve(`.prismer/operations/skill-library-${sha256(root).slice(0, 16)}.json`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function loadLibraryImportConfig(argv, env = process.env) {
|
|
50
|
+
const flags = new Set();
|
|
51
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
52
|
+
const arg = argv[index];
|
|
53
|
+
const name = optionName(arg);
|
|
54
|
+
if (SECRET_OPTIONS.has(name)) {
|
|
55
|
+
throw new LibraryImportError(
|
|
56
|
+
'local_validation',
|
|
57
|
+
'SECRET_ARGUMENT_FORBIDDEN',
|
|
58
|
+
`${name} is forbidden; credentials must come from the injected environment`,
|
|
59
|
+
2,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
if (!BOOLEAN_OPTIONS.has(arg)) {
|
|
63
|
+
throw new LibraryImportError(
|
|
64
|
+
'local_validation',
|
|
65
|
+
'UNKNOWN_ARGUMENT',
|
|
66
|
+
`unknown argument at position ${index + 1}`,
|
|
67
|
+
2,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
flags.add(arg);
|
|
71
|
+
}
|
|
72
|
+
if (flags.has('--help')) return { help: true };
|
|
73
|
+
|
|
74
|
+
const sourceRootRaw = env.PRISMER_SKILL_LIBRARY_ROOT?.trim();
|
|
75
|
+
if (!sourceRootRaw) {
|
|
76
|
+
throw new LibraryImportError('local_validation', 'CONFIG_MISSING', 'PRISMER_SKILL_LIBRARY_ROOT is required', 2);
|
|
77
|
+
}
|
|
78
|
+
const sourceRoot = resolve(sourceRootRaw);
|
|
79
|
+
if (!existsSync(sourceRoot) || !statSync(sourceRoot).isDirectory()) {
|
|
80
|
+
throw new LibraryImportError(
|
|
81
|
+
'local_validation',
|
|
82
|
+
'SOURCE_ROOT_INVALID',
|
|
83
|
+
'PRISMER_SKILL_LIBRARY_ROOT must identify an existing directory',
|
|
84
|
+
2,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let baseUrl;
|
|
89
|
+
try {
|
|
90
|
+
baseUrl = new URL((env.PRISMER_CLOUD_BASE || 'http://127.0.0.1:3000').replace(/\/$/, ''));
|
|
91
|
+
} catch {
|
|
92
|
+
throw new LibraryImportError('local_validation', 'INVALID_BASE_URL', 'PRISMER_CLOUD_BASE must be a valid URL', 2);
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
!['http:', 'https:'].includes(baseUrl.protocol) ||
|
|
96
|
+
baseUrl.username ||
|
|
97
|
+
baseUrl.password ||
|
|
98
|
+
baseUrl.search ||
|
|
99
|
+
baseUrl.hash
|
|
100
|
+
) {
|
|
101
|
+
throw new LibraryImportError(
|
|
102
|
+
'local_validation',
|
|
103
|
+
'UNSAFE_BASE_URL',
|
|
104
|
+
'PRISMER_CLOUD_BASE must be a plain http(s) origin without credentials, query, or hash',
|
|
105
|
+
2,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const preflightOnly = flags.has('--preflight-only');
|
|
110
|
+
if (!preflightOnly && !isLocalTarget(baseUrl.hostname) && !parseBoolean(env.PRISMER_ALLOW_REMOTE_WRITE)) {
|
|
111
|
+
throw new LibraryImportError(
|
|
112
|
+
'local_validation',
|
|
113
|
+
'REMOTE_WRITE_NOT_CONFIRMED',
|
|
114
|
+
'remote mutation is blocked; set PRISMER_ALLOW_REMOTE_WRITE=1 after confirming the target environment',
|
|
115
|
+
2,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const excludes = String(env.PRISMER_SKILL_LIBRARY_EXCLUDE || '')
|
|
120
|
+
.split(/[\n,]/)
|
|
121
|
+
.map((entry) => entry.trim().replace(/^\.\//, '').replace(/\/$/, ''))
|
|
122
|
+
.filter(Boolean);
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
sourceRoot,
|
|
126
|
+
excludes,
|
|
127
|
+
cloudBin: env.PRISMER_CLOUD_BIN?.trim() || 'cloud',
|
|
128
|
+
baseUrl: baseUrl.toString().replace(/\/$/, ''),
|
|
129
|
+
ledgerPath: resolve(env.PRISMER_IMPORT_LEDGER?.trim() || defaultLedgerPath(sourceRoot)),
|
|
130
|
+
preflightOnly,
|
|
131
|
+
json: flags.has('--json'),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function excluded(config, absolute) {
|
|
136
|
+
const path = normalizeRelative(config.sourceRoot, absolute);
|
|
137
|
+
return config.excludes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function discoverSkillDirectories(config) {
|
|
141
|
+
const found = [];
|
|
142
|
+
const visit = (directory) => {
|
|
143
|
+
if (excluded(config, directory)) return;
|
|
144
|
+
const entries = readdirSync(directory, { withFileTypes: true });
|
|
145
|
+
if (entries.some((entry) => entry.isFile() && entry.name === 'SKILL.md')) {
|
|
146
|
+
found.push(directory);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
if (!entry.isDirectory() || IGNORED_DIRECTORIES.has(entry.name) || entry.name.startsWith('.')) continue;
|
|
151
|
+
visit(resolve(directory, entry.name));
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
visit(config.sourceRoot);
|
|
155
|
+
return found.sort((left, right) => left.localeCompare(right));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function sourceRevision(config, directories) {
|
|
159
|
+
const hash = createHash('sha256');
|
|
160
|
+
for (const directory of directories) {
|
|
161
|
+
const files = [];
|
|
162
|
+
const visit = (current) => {
|
|
163
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
164
|
+
if (entry.name.startsWith('.')) continue;
|
|
165
|
+
const absolute = resolve(current, entry.name);
|
|
166
|
+
if (entry.isDirectory()) visit(absolute);
|
|
167
|
+
else files.push(absolute);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
visit(directory);
|
|
171
|
+
for (const file of files.sort((left, right) => left.localeCompare(right))) {
|
|
172
|
+
hash.update(normalizeRelative(config.sourceRoot, file));
|
|
173
|
+
hash.update('\0');
|
|
174
|
+
hash.update(readFileSync(file));
|
|
175
|
+
hash.update('\0');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return hash.digest('hex');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function bundleManifest(directory) {
|
|
182
|
+
const files = [];
|
|
183
|
+
const visit = (current) => {
|
|
184
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
185
|
+
if (entry.name.startsWith('.')) continue;
|
|
186
|
+
const absolute = resolve(current, entry.name);
|
|
187
|
+
if (entry.isDirectory()) visit(absolute);
|
|
188
|
+
else if (!BUNDLE_EXCLUDED_FILES.has(entry.name)) files.push(absolute);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
visit(directory);
|
|
192
|
+
return files
|
|
193
|
+
.sort((left, right) => left.localeCompare(right))
|
|
194
|
+
.map((absolute) => {
|
|
195
|
+
const bytes = readFileSync(absolute);
|
|
196
|
+
return {
|
|
197
|
+
path: normalizeRelative(directory, absolute),
|
|
198
|
+
size: bytes.byteLength,
|
|
199
|
+
sha256: sha256(bytes),
|
|
200
|
+
...(normalizeRelative(directory, absolute) === 'SKILL.md' ? { content: bytes.toString('utf8') } : {}),
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function readbackMatchesBundle(readback, directory) {
|
|
206
|
+
const expected = bundleManifest(directory);
|
|
207
|
+
const actual = Array.isArray(readback?.files) ? readback.files : [];
|
|
208
|
+
if (actual.length !== expected.length) return false;
|
|
209
|
+
const actualByPath = new Map(actual.map((file) => [file?.path, file]));
|
|
210
|
+
for (const file of expected) {
|
|
211
|
+
const remote = actualByPath.get(file.path);
|
|
212
|
+
if (!remote || remote.sha256 !== file.sha256 || Number(remote.size) !== file.size) return false;
|
|
213
|
+
if (file.path === 'SKILL.md' && readback.content !== file.content) return false;
|
|
214
|
+
}
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function readbackOwnedBundle(config, row, directory, runCloud, canonicalSlug) {
|
|
219
|
+
const shown = await runCloud(config, ['skill', 'show', canonicalSlug, '--content', '--json']);
|
|
220
|
+
if (!shown.ok) return { ok: false, error: safeCliFailure(shown) };
|
|
221
|
+
const readback = parseJsonOutput(shown, 'readback');
|
|
222
|
+
if (!readbackMatchesBundle(readback, directory)) {
|
|
223
|
+
return { ok: false, error: 'catalog readback does not match the selected local bundle' };
|
|
224
|
+
}
|
|
225
|
+
row.canonicalSlug = canonicalSlug;
|
|
226
|
+
row.stage = 'verified';
|
|
227
|
+
row.verifiedAt = new Date().toISOString();
|
|
228
|
+
return { ok: true, readback };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function parseJsonOutput(result, stage) {
|
|
232
|
+
const raw = String(result.stdout || '').trim();
|
|
233
|
+
try {
|
|
234
|
+
return JSON.parse(raw);
|
|
235
|
+
} catch {
|
|
236
|
+
const start = raw.indexOf('{');
|
|
237
|
+
const end = raw.lastIndexOf('}');
|
|
238
|
+
if (start >= 0 && end > start) {
|
|
239
|
+
try {
|
|
240
|
+
return JSON.parse(raw.slice(start, end + 1));
|
|
241
|
+
} catch {
|
|
242
|
+
// Fall through to the typed diagnostic below.
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
throw new LibraryImportError(stage, 'INVALID_CLI_JSON', 'cloud CLI did not return valid JSON', 5);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function defaultRunCloud(config, args) {
|
|
250
|
+
const result = spawnSync(config.cloudBin, args, {
|
|
251
|
+
encoding: 'utf8',
|
|
252
|
+
env: { ...process.env, PRISMER_CLOUD_BASE: config.baseUrl },
|
|
253
|
+
shell: false,
|
|
254
|
+
});
|
|
255
|
+
if (result.error) {
|
|
256
|
+
throw new LibraryImportError(
|
|
257
|
+
'local_validation',
|
|
258
|
+
'CLOUD_CLI_UNAVAILABLE',
|
|
259
|
+
`could not execute the configured Cloud CLI: ${result.error.message}`,
|
|
260
|
+
2,
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
ok: result.status === 0,
|
|
265
|
+
status: result.status,
|
|
266
|
+
stdout: result.stdout || '',
|
|
267
|
+
stderr: result.stderr || '',
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function writeLedger(path, ledger) {
|
|
272
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
273
|
+
const temporary = `${path}.tmp`;
|
|
274
|
+
writeFileSync(temporary, `${JSON.stringify(ledger, null, 2)}\n`, { mode: 0o600 });
|
|
275
|
+
renameSync(temporary, path);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function readLedger(path) {
|
|
279
|
+
if (!existsSync(path)) return null;
|
|
280
|
+
try {
|
|
281
|
+
const value = JSON.parse(readFileSync(path, 'utf8'));
|
|
282
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
283
|
+
} catch {
|
|
284
|
+
throw new LibraryImportError(
|
|
285
|
+
'local_validation',
|
|
286
|
+
'INVALID_IMPORT_LEDGER',
|
|
287
|
+
'the import ledger exists but is not valid JSON',
|
|
288
|
+
2,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function safeCliFailure(result) {
|
|
294
|
+
const message = String(result.stderr || '').trim();
|
|
295
|
+
return message ? message.slice(0, 2_000) : `cloud CLI exited ${String(result.status)}`;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export async function runLibraryImport(config, runCloud = defaultRunCloud) {
|
|
299
|
+
const directories = discoverSkillDirectories(config);
|
|
300
|
+
if (directories.length === 0) {
|
|
301
|
+
throw new LibraryImportError('local_validation', 'NO_SKILLS_FOUND', 'no root SKILL.md directories found', 2);
|
|
302
|
+
}
|
|
303
|
+
const revision = sourceRevision(config, directories);
|
|
304
|
+
const previous = readLedger(config.ledgerPath);
|
|
305
|
+
if (previous && (previous.sourceRoot !== config.sourceRoot || previous.sourceRevision !== revision)) {
|
|
306
|
+
throw new LibraryImportError(
|
|
307
|
+
'local_validation',
|
|
308
|
+
'IMPORT_LEDGER_CONFLICT',
|
|
309
|
+
'the import ledger belongs to a different source selection or source revision',
|
|
310
|
+
2,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const rowsByPath = new Map((previous?.rows || []).map((row) => [row.sourcePath, row]));
|
|
315
|
+
const rows = [];
|
|
316
|
+
for (const directory of directories) {
|
|
317
|
+
const sourcePath = normalizeRelative(config.sourceRoot, directory);
|
|
318
|
+
const prior = rowsByPath.get(sourcePath);
|
|
319
|
+
if (prior?.stage === 'verified') {
|
|
320
|
+
rows.push(prior);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const validated = await runCloud(config, ['skill', 'validate', directory, '--json']);
|
|
324
|
+
let validation = null;
|
|
325
|
+
try {
|
|
326
|
+
validation = parseJsonOutput(validated, 'validation');
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (validated.ok) throw error;
|
|
329
|
+
}
|
|
330
|
+
rows.push({
|
|
331
|
+
sourcePath,
|
|
332
|
+
requestedSlug: validation?.slug ?? prior?.requestedSlug ?? null,
|
|
333
|
+
stage: validated.ok && validation?.ok !== false ? 'validated' : 'validation_failed',
|
|
334
|
+
...(validated.ok && validation?.ok !== false
|
|
335
|
+
? {}
|
|
336
|
+
: { error: safeCliFailure(validated), validation: validation ?? undefined }),
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const slugs = rows.map((row) => row.requestedSlug).filter(Boolean);
|
|
341
|
+
const duplicates = [...new Set(slugs.filter((slug, index) => slugs.indexOf(slug) !== index))];
|
|
342
|
+
if (duplicates.length > 0) {
|
|
343
|
+
throw new LibraryImportError(
|
|
344
|
+
'validation',
|
|
345
|
+
'DUPLICATE_SOURCE_SLUGS',
|
|
346
|
+
'the selected source contains duplicate Skill slugs; choose the authoritative tree or exclude mirrors',
|
|
347
|
+
2,
|
|
348
|
+
{ slugs: duplicates },
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const ledger = {
|
|
353
|
+
schemaVersion: 1,
|
|
354
|
+
sourceRoot: config.sourceRoot,
|
|
355
|
+
sourceRevision: revision,
|
|
356
|
+
stage: rows.some((row) => row.stage === 'validation_failed') ? 'validation_failed' : 'validated',
|
|
357
|
+
rows,
|
|
358
|
+
updatedAt: new Date().toISOString(),
|
|
359
|
+
};
|
|
360
|
+
writeLedger(config.ledgerPath, ledger);
|
|
361
|
+
if (ledger.stage === 'validation_failed') {
|
|
362
|
+
throw new LibraryImportError(
|
|
363
|
+
'validation',
|
|
364
|
+
'LIBRARY_VALIDATION_FAILED',
|
|
365
|
+
'one or more Skill bundles failed local validation; no catalog writes were attempted',
|
|
366
|
+
2,
|
|
367
|
+
{ failed: rows.filter((row) => row.stage === 'validation_failed').map((row) => row.sourcePath) },
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
if (config.preflightOnly) return ledger;
|
|
371
|
+
|
|
372
|
+
for (const row of rows) {
|
|
373
|
+
if (row.stage === 'verified') continue;
|
|
374
|
+
const directory = resolve(config.sourceRoot, row.sourcePath);
|
|
375
|
+
const created = await runCloud(config, ['skill', 'create', directory, '--json']);
|
|
376
|
+
if (!created.ok) {
|
|
377
|
+
// A process may die after the server commits but before the ledger records
|
|
378
|
+
// the create response. Community slugs are server-canonical and
|
|
379
|
+
// deterministic; only accept the existing owner-visible row when its
|
|
380
|
+
// complete manifest matches the selected bundle byte-for-byte.
|
|
381
|
+
const recoverySlug = `community-${row.requestedSlug}`;
|
|
382
|
+
const recovered = await readbackOwnedBundle(config, row, directory, runCloud, recoverySlug);
|
|
383
|
+
if (recovered.ok) {
|
|
384
|
+
row.recoveredAfterCreateFailure = true;
|
|
385
|
+
delete row.error;
|
|
386
|
+
} else {
|
|
387
|
+
row.stage = 'create_failed';
|
|
388
|
+
row.error = safeCliFailure(created);
|
|
389
|
+
row.recoveryError = recovered.error;
|
|
390
|
+
}
|
|
391
|
+
ledger.updatedAt = new Date().toISOString();
|
|
392
|
+
writeLedger(config.ledgerPath, ledger);
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const creation = parseJsonOutput(created, 'create');
|
|
396
|
+
row.id = creation.id ?? null;
|
|
397
|
+
row.canonicalSlug = creation.slug ?? null;
|
|
398
|
+
row.publishScope = creation.publishScope ?? null;
|
|
399
|
+
row.status = creation.status ?? null;
|
|
400
|
+
row.stage = 'created';
|
|
401
|
+
delete row.error;
|
|
402
|
+
ledger.updatedAt = new Date().toISOString();
|
|
403
|
+
writeLedger(config.ledgerPath, ledger);
|
|
404
|
+
|
|
405
|
+
if (!row.canonicalSlug) {
|
|
406
|
+
row.stage = 'readback_failed';
|
|
407
|
+
row.error = 'create response did not contain a canonical slug';
|
|
408
|
+
writeLedger(config.ledgerPath, ledger);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const verified = await readbackOwnedBundle(config, row, directory, runCloud, row.canonicalSlug);
|
|
412
|
+
if (!verified.ok) {
|
|
413
|
+
row.stage = 'readback_failed';
|
|
414
|
+
row.error = verified.error;
|
|
415
|
+
writeLedger(config.ledgerPath, ledger);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
writeLedger(config.ledgerPath, ledger);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const failed = rows.filter((row) => row.stage !== 'verified');
|
|
422
|
+
ledger.stage = failed.length === 0 ? 'completed' : 'partial_failure';
|
|
423
|
+
ledger.completedAt = failed.length === 0 ? new Date().toISOString() : undefined;
|
|
424
|
+
ledger.updatedAt = new Date().toISOString();
|
|
425
|
+
ledger.requiredSkills = rows
|
|
426
|
+
.filter((row) => row.stage === 'verified')
|
|
427
|
+
.map((row) => ({ skillSlug: row.canonicalSlug, required: true }));
|
|
428
|
+
writeLedger(config.ledgerPath, ledger);
|
|
429
|
+
if (failed.length > 0) {
|
|
430
|
+
throw new LibraryImportError(
|
|
431
|
+
'import',
|
|
432
|
+
'LIBRARY_IMPORT_PARTIAL_FAILURE',
|
|
433
|
+
'some Skill bundles were not verified; retry with the same ledger after fixing transient failures',
|
|
434
|
+
5,
|
|
435
|
+
{ failed: failed.map((row) => ({ sourcePath: row.sourcePath, stage: row.stage })) },
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
return ledger;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const HELP = `Usage:
|
|
442
|
+
# PRISMER_SKILL_LIBRARY_ROOT and cloud authentication are injected in env
|
|
443
|
+
node scripts/import-library.mjs [--preflight-only] [--json]
|
|
444
|
+
|
|
445
|
+
Optional env: PRISMER_SKILL_LIBRARY_EXCLUDE, PRISMER_IMPORT_LEDGER,
|
|
446
|
+
PRISMER_CLOUD_BIN, PRISMER_CLOUD_BASE, PRISMER_ALLOW_REMOTE_WRITE=1.`;
|
|
447
|
+
|
|
448
|
+
async function main() {
|
|
449
|
+
let config;
|
|
450
|
+
try {
|
|
451
|
+
config = loadLibraryImportConfig(process.argv.slice(2));
|
|
452
|
+
if (config.help) {
|
|
453
|
+
process.stdout.write(`${HELP}\n`);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const result = await runLibraryImport(config);
|
|
457
|
+
if (config.json) process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
458
|
+
else {
|
|
459
|
+
process.stdout.write(
|
|
460
|
+
`[skill-creator] ${result.stage}: verified=${result.rows.filter((row) => row.stage === 'verified').length}/${result.rows.length} ledger=${config.ledgerPath}\n`,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
} catch (error) {
|
|
464
|
+
const failure =
|
|
465
|
+
error instanceof LibraryImportError
|
|
466
|
+
? error
|
|
467
|
+
: new LibraryImportError('internal', 'UNEXPECTED_ERROR', error?.message || String(error), 1);
|
|
468
|
+
process.stderr.write(
|
|
469
|
+
`${JSON.stringify({ ok: false, stage: failure.stage, error: { code: failure.code, message: failure.message, details: failure.details }, ...(config?.ledgerPath ? { ledger: config.ledgerPath } : {}) })}\n`,
|
|
470
|
+
);
|
|
471
|
+
process.exitCode = failure.exitCode;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (import.meta.url === `file://${process.argv[1]}`) await main();
|