@jinn-network/client 0.1.5 → 0.1.6-canary.118cd4d0
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 +98 -0
- package/dist/adapters/mech/adapter.js +7 -7
- package/dist/adapters/mech/adapter.js.map +1 -1
- package/dist/adapters/mech/ipfs-pinfile.d.ts +22 -0
- package/dist/adapters/mech/ipfs-pinfile.js +54 -0
- package/dist/adapters/mech/ipfs-pinfile.js.map +1 -0
- package/dist/adapters/mech/ipfs.d.ts +1 -0
- package/dist/adapters/mech/ipfs.js +24 -1
- package/dist/adapters/mech/ipfs.js.map +1 -1
- package/dist/api/bootstrap-endpoint.js +14 -1
- package/dist/api/bootstrap-endpoint.js.map +1 -1
- package/dist/api/discovery-endpoint.d.ts +31 -0
- package/dist/api/discovery-endpoint.js +78 -0
- package/dist/api/discovery-endpoint.js.map +1 -0
- package/dist/api/fleet-build.d.ts +7 -0
- package/dist/api/fleet-build.js +6 -1
- package/dist/api/fleet-build.js.map +1 -1
- package/dist/api/gather-status.js +20 -3
- package/dist/api/gather-status.js.map +1 -1
- package/dist/api/harness-readiness-endpoint.d.ts +25 -0
- package/dist/api/harness-readiness-endpoint.js +24 -0
- package/dist/api/harness-readiness-endpoint.js.map +1 -0
- package/dist/api/hermes-doctor-endpoint.d.ts +26 -0
- package/dist/api/hermes-doctor-endpoint.js +29 -0
- package/dist/api/hermes-doctor-endpoint.js.map +1 -0
- package/dist/api/server.d.ts +43 -0
- package/dist/api/server.js +39 -0
- package/dist/api/server.js.map +1 -1
- package/dist/api/setup-endpoints.d.ts +5 -0
- package/dist/api/setup-endpoints.js +24 -5
- package/dist/api/setup-endpoints.js.map +1 -1
- package/dist/build-info.json +4 -4
- package/dist/build-meta.json +1 -1
- package/dist/cli/commands/auth.js +3 -1
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/create.d.ts +5 -3
- package/dist/cli/commands/create.js +101 -36
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/solver-nets.d.ts +19 -0
- package/dist/cli/commands/solver-nets.js +140 -2
- package/dist/cli/commands/solver-nets.js.map +1 -1
- package/dist/cli/commands/solver-plugins-publish.d.ts +31 -0
- package/dist/cli/commands/solver-plugins-publish.js +169 -0
- package/dist/cli/commands/solver-plugins-publish.js.map +1 -0
- package/dist/cli/commands/solver-plugins-revoke.d.ts +15 -0
- package/dist/cli/commands/solver-plugins-revoke.js +91 -0
- package/dist/cli/commands/solver-plugins-revoke.js.map +1 -0
- package/dist/cli/commands/solver-plugins.d.ts +50 -6
- package/dist/cli/commands/solver-plugins.js +205 -68
- package/dist/cli/commands/solver-plugins.js.map +1 -1
- package/dist/config.d.ts +27 -0
- package/dist/config.js +30 -2
- package/dist/config.js.map +1 -1
- package/dist/conformance/checks/hash-signature.js +6 -2
- package/dist/conformance/checks/hash-signature.js.map +1 -1
- package/dist/conformance/checks/payload.js +4 -2
- package/dist/conformance/checks/payload.js.map +1 -1
- package/dist/conformance/checks/verdict.d.ts +10 -10
- package/dist/conformance/checks/verdict.js +16 -15
- package/dist/conformance/checks/verdict.js.map +1 -1
- package/dist/conformance/harness.d.ts +1 -1
- package/dist/conformance/harness.js +16 -9
- package/dist/conformance/harness.js.map +1 -1
- package/dist/conformance/types.d.ts +10 -3
- package/dist/conformance/types.js.map +1 -1
- package/dist/corpus/acquire.d.ts +1 -3
- package/dist/corpus/acquire.js.map +1 -1
- package/dist/corpus/envelope-projection.d.ts +1 -1
- package/dist/corpus/envelope-projection.js +14 -7
- package/dist/corpus/envelope-projection.js.map +1 -1
- package/dist/corpus/index.d.ts +2 -1
- package/dist/corpus/index.js.map +1 -1
- package/dist/corpus/prediction-brier-scoreboard-report.js +1 -1
- package/dist/corpus/prediction-brier-scoreboard-report.js.map +1 -1
- package/dist/corpus/prediction-brier-scoreboard.js +3 -1
- package/dist/corpus/prediction-brier-scoreboard.js.map +1 -1
- package/dist/corpus/types.d.ts +2 -2
- package/dist/daemon/daemon.d.ts +17 -1
- package/dist/daemon/daemon.js +15 -0
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/freeze-fence.js +6 -3
- package/dist/daemon/freeze-fence.js.map +1 -1
- package/dist/daemon/readiness-gate.d.ts +30 -0
- package/dist/daemon/readiness-gate.js +31 -0
- package/dist/daemon/readiness-gate.js.map +1 -0
- package/dist/dashboard/assets/{index-D_NMfDfV.css → index-DOlzFN8a.css} +1 -1
- package/dist/dashboard/assets/index-NkZ7CTAT.js +140 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/discovery/http.js +121 -0
- package/dist/discovery/http.js.map +1 -1
- package/dist/discovery/onchain.js +11 -0
- package/dist/discovery/onchain.js.map +1 -1
- package/dist/discovery/types.d.ts +112 -0
- package/dist/discovery/types.js.map +1 -1
- package/dist/discovery/with-fallback.js +9 -0
- package/dist/discovery/with-fallback.js.map +1 -1
- package/dist/earning/agent-wallet-binding.d.ts +20 -1
- package/dist/earning/agent-wallet-binding.js +54 -16
- package/dist/earning/agent-wallet-binding.js.map +1 -1
- package/dist/earning/bootstrap.d.ts +119 -0
- package/dist/earning/bootstrap.js +482 -16
- package/dist/earning/bootstrap.js.map +1 -1
- package/dist/earning/contracts.js +9 -1
- package/dist/earning/contracts.js.map +1 -1
- package/dist/earning/funding-plan.js +15 -2
- package/dist/earning/funding-plan.js.map +1 -1
- package/dist/earning/store.js +48 -1
- package/dist/earning/store.js.map +1 -1
- package/dist/earning/types.d.ts +30 -0
- package/dist/earning/types.js +37 -0
- package/dist/earning/types.js.map +1 -1
- package/dist/erc8004/abis.d.ts +64 -0
- package/dist/erc8004/abis.js +48 -0
- package/dist/erc8004/abis.js.map +1 -1
- package/dist/erc8004/plugin-registry.d.ts +102 -0
- package/dist/erc8004/plugin-registry.js +165 -0
- package/dist/erc8004/plugin-registry.js.map +1 -0
- package/dist/events/types.d.ts +2 -2
- package/dist/harnesses/engine/engine.js +15 -3
- package/dist/harnesses/engine/engine.js.map +1 -1
- package/dist/harnesses/engine/envelope-assembly.d.ts +2 -2
- package/dist/harnesses/engine/envelope-assembly.js +4 -2
- package/dist/harnesses/engine/envelope-assembly.js.map +1 -1
- package/dist/harnesses/freeze.d.ts +4 -1
- package/dist/harnesses/freeze.js +12 -2
- package/dist/harnesses/freeze.js.map +1 -1
- package/dist/harnesses/impls/claude-mcp-prediction/index.d.ts +4 -1
- package/dist/harnesses/impls/claude-mcp-prediction/index.js +7 -2
- package/dist/harnesses/impls/claude-mcp-prediction/index.js.map +1 -1
- package/dist/harnesses/impls/claude-mcp-prediction-apy/index.d.ts +4 -1
- package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js +7 -2
- package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js.map +1 -1
- package/dist/harnesses/impls/evaluation-context.d.ts +15 -4
- package/dist/harnesses/impls/evaluation-context.js +24 -8
- package/dist/harnesses/impls/evaluation-context.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/adapter.d.ts +34 -0
- package/dist/harnesses/impls/hermes-agent/adapter.js +205 -0
- package/dist/harnesses/impls/hermes-agent/adapter.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/bootstrap.d.ts +18 -0
- package/dist/harnesses/impls/hermes-agent/bootstrap.js +231 -0
- package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/config-builder.d.ts +49 -0
- package/dist/harnesses/impls/hermes-agent/config-builder.js +104 -0
- package/dist/harnesses/impls/hermes-agent/config-builder.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/harness.d.ts +30 -0
- package/dist/harnesses/impls/hermes-agent/harness.js +52 -0
- package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/index.d.ts +5 -0
- package/dist/harnesses/impls/hermes-agent/index.js +7 -0
- package/dist/harnesses/impls/hermes-agent/index.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/prompt.d.ts +15 -0
- package/dist/harnesses/impls/hermes-agent/prompt.js +37 -0
- package/dist/harnesses/impls/hermes-agent/prompt.js.map +1 -0
- package/dist/harnesses/impls/index.d.ts +6 -0
- package/dist/harnesses/impls/index.js +17 -4
- package/dist/harnesses/impls/index.js.map +1 -1
- package/dist/harnesses/impls/learner/adapters/claude-code.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.js +13 -34
- package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -0
- package/dist/harnesses/impls/learner/adapters/codex-workspace.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/harness.d.ts +9 -3
- package/dist/harnesses/impls/{claude-code-learner → learner}/harness.js +24 -1
- package/dist/harnesses/impls/learner/harness.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.js +15 -3
- package/dist/harnesses/impls/learner/harvest.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/index.d.ts +5 -5
- package/dist/harnesses/impls/{claude-code-learner → learner}/index.js +4 -4
- package/dist/harnesses/impls/learner/index.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.d.ts +4 -4
- package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.js +7 -7
- package/dist/harnesses/impls/learner/plugin-path.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.js +3 -1
- package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -0
- package/dist/harnesses/impls/learner/test-utils/fake-plugin-outputs.js.map +1 -0
- package/dist/harnesses/impls/learner/test-utils/noop-adapter.js.map +1 -0
- package/dist/harnesses/impls/{claude-code-learner → learner}/types.d.ts +12 -2
- package/dist/harnesses/impls/learner/types.js.map +1 -0
- package/dist/harnesses/impls/portfolio-v0-evaluator/index.js +13 -12
- package/dist/harnesses/impls/portfolio-v0-evaluator/index.js.map +1 -1
- package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js +7 -7
- package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js.map +1 -1
- package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.d.ts +3 -3
- package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js +7 -6
- package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js.map +1 -1
- package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js +1 -1
- package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js.map +1 -1
- package/dist/harnesses/impls/prediction-v0-evaluator/index.js +11 -10
- package/dist/harnesses/impls/prediction-v0-evaluator/index.js.map +1 -1
- package/dist/harnesses/impls/prediction-v1-evaluator/index.js +11 -10
- package/dist/harnesses/impls/prediction-v1-evaluator/index.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.d.ts +1 -0
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +10 -2
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.d.ts +24 -5
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js +104 -4
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +9 -0
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +25 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
- package/dist/harnesses/names.d.ts +1 -0
- package/dist/harnesses/names.js +3 -0
- package/dist/harnesses/names.js.map +1 -1
- package/dist/harnesses/readiness-registry.d.ts +48 -0
- package/dist/harnesses/readiness-registry.js +136 -0
- package/dist/harnesses/readiness-registry.js.map +1 -0
- package/dist/harnesses/types.d.ts +7 -0
- package/dist/main.d.ts +14 -0
- package/dist/main.js +112 -37
- package/dist/main.js.map +1 -1
- package/dist/mcp/server.js +14 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/operator-errors.js +13 -1
- package/dist/operator-errors.js.map +1 -1
- package/dist/preflight/claude-auth.d.ts +18 -0
- package/dist/preflight/claude-auth.js +38 -0
- package/dist/preflight/claude-auth.js.map +1 -1
- package/dist/scripts/donation-consumption-acceptance.js +1 -1
- package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
- package/dist/scripts/swe-rebench-v2-known-bad.json +12 -0
- package/dist/scripts/swe-rebench-v2-seed-pool.json +26 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.d.ts +52 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.js +76 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.js.map +1 -0
- package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +38 -12
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js +136 -27
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2-auto.d.ts +6 -0
- package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2.d.ts +1 -0
- package/dist/solver-types/swe-rebench-v2.js +19 -6
- package/dist/solver-types/swe-rebench-v2.js.map +1 -1
- package/dist/store/store.js +12 -4
- package/dist/store/store.js.map +1 -1
- package/dist/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
- package/dist/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
- package/dist/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
- package/dist/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
- package/dist/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
- package/dist/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
- package/dist/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
- package/dist/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
- package/dist/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
- package/dist/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
- package/dist/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
- package/dist/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
- package/dist/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
- package/dist/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
- package/dist/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
- package/dist/tx-retry.d.ts +13 -0
- package/dist/tx-retry.js +22 -0
- package/dist/tx-retry.js.map +1 -1
- package/dist/types/envelope.d.ts +28 -21
- package/dist/types/envelope.js +8 -3
- package/dist/types/envelope.js.map +1 -1
- package/dist/types/payloads/index.d.ts +2 -2
- package/dist/types/payloads/index.js +13 -12
- package/dist/types/payloads/index.js.map +1 -1
- package/dist/types/payloads/portfolio-v0.d.ts +60 -10
- package/dist/types/payloads/portfolio-v0.js +16 -6
- package/dist/types/payloads/portfolio-v0.js.map +1 -1
- package/dist/types/payloads/prediction-apy-v0.d.ts +52 -10
- package/dist/types/payloads/prediction-apy-v0.js +16 -6
- package/dist/types/payloads/prediction-apy-v0.js.map +1 -1
- package/dist/types/payloads/prediction-v0.d.ts +49 -10
- package/dist/types/payloads/prediction-v0.js +16 -6
- package/dist/types/payloads/prediction-v0.js.map +1 -1
- package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.d.ts +45 -6
- package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.js +16 -6
- package/dist/x402/handler.js +51 -20
- package/dist/x402/handler.js.map +1 -1
- package/package.json +11 -3
- package/plugins/swe-rebench-v2-diffmin/.claude-plugin/plugin.json +5 -0
- package/plugins/swe-rebench-v2-diffmin/.mcp.json +8 -0
- package/plugins/swe-rebench-v2-diffmin/README.md +69 -0
- package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +12 -0
- package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats-server.mjs +72 -0
- package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats.mjs +48 -0
- package/plugins/swe-rebench-v2-diffmin/package.json +19 -0
- package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +116 -0
- package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +126 -0
- package/plugins/swe-rebench-v2-diffmin/test/diff-stats.test.ts +62 -0
- package/plugins/swe-rebench-v2-diffmin/test/manifest.test.ts +53 -0
- package/plugins/swe-rebench-v2-diffmin/tsconfig.json +12 -0
- package/plugins/swe-rebench-v2-runtime/README.md +13 -0
- package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +7 -3
- package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +6 -17
- package/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
- package/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
- package/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
- package/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
- package/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
- package/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
- package/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
- package/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
- package/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
- package/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
- package/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
- package/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
- package/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
- package/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
- package/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
- package/dist/dashboard/assets/index-BjtltOGc.js +0 -76
- package/dist/harnesses/impls/claude-code-learner/adapters/claude-code.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/adapters/codex-code.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/adapters/codex-workspace.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/harness.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/harvest.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/index.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/plugin-path.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/restoration-patch.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/test-utils/fake-plugin-outputs.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/test-utils/noop-adapter.js.map +0 -1
- package/dist/harnesses/impls/claude-code-learner/types.js.map +0 -1
- package/dist/preflight/claude-required.d.ts +0 -8
- package/dist/preflight/claude-required.js +0 -17
- package/dist/preflight/claude-required.js.map +0 -1
- /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.js +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.js +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.js +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.d.ts +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.js +0 -0
- /package/dist/harnesses/impls/{claude-code-learner → learner}/types.js +0 -0
- /package/plugins/{claude-code-learner → learner}/.claude-plugin/plugin.json +0 -0
- /package/plugins/{claude-code-learner → learner}/.codex-plugin/plugin.json +0 -0
- /package/plugins/{claude-code-learner → learner}/AGENTS.md +0 -0
- /package/plugins/{claude-code-learner → learner}/CLAUDE.md +0 -0
- /package/plugins/{claude-code-learner → learner}/README.md +0 -0
- /package/plugins/{claude-code-learner → learner}/hooks/hooks.json +0 -0
- /package/plugins/{claude-code-learner → learner}/hooks/session-start +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/SKILL.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/analyst-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/consolidator-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/explorer-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/planner-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/promoter-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/step-worker-prompt.md +0 -0
- /package/plugins/{claude-code-learner → learner}/skills/learn/strategist-prompt.md +0 -0
|
@@ -15,7 +15,7 @@ import { formatBootstrapOperatorMessage, isJinnDebug, } from '../operator-errors
|
|
|
15
15
|
import { reconcileServiceAgainstChain, } from './reconcile.js';
|
|
16
16
|
import { previousSafeBeingAbandoned, sweepOrphanedServiceFunds, } from './orphan-sweep.js';
|
|
17
17
|
import { DEFAULT_FAUCET_LOOP_TIMEOUT_MS, computeFaucetDripCap, requestTestnetFunding, } from './faucet.js';
|
|
18
|
-
import { flattenErrorMessage, viemSendTransactionWithRetry, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
|
|
18
|
+
import { flattenErrorMessage, sleep, viemSendTransactionWithRetry, waitForContractCode, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
|
|
19
19
|
import { isUnauthorizedAccountError } from '../errors/unauthorized-account.js';
|
|
20
20
|
import { createJinnPublicClient, createJinnWalletClient } from './viem-clients.js';
|
|
21
21
|
import { isTransientEthReadError } from '../chain-read-errors.js';
|
|
@@ -25,10 +25,71 @@ import { detectDeprecatedTestnetSetup, migrateDeprecatedTestnetSetup, } from './
|
|
|
25
25
|
const addr = (value) => getAddress(value);
|
|
26
26
|
const SAFE_TOKEN_BOOTSTRAP_MULTIPLIER = 2n;
|
|
27
27
|
const STANDARD_MASTER_BOOTSTRAP_MULTIPLIER = 2n;
|
|
28
|
+
/** Master ETH required to FINISH the whole bootstrap from a fresh start (not
|
|
29
|
+
* just to enter Stage 1). Centralized so the daemon's ensureStage1 gate,
|
|
30
|
+
* the read-side funding-plan, gather-status, and the panel faucet target
|
|
31
|
+
* all agree on a single "one-shot fund the operator" number.
|
|
32
|
+
*
|
|
33
|
+
* Components for a 1-service standard-mode bootstrap:
|
|
34
|
+
* - STAGE1_AGENT_ETH (0.010 ETH): master → HD-1 fleet-agent transfer.
|
|
35
|
+
* HD-1 pays for its own Safe deploy + register + setAgentWallet out
|
|
36
|
+
* of this; leftover covers service 1's Stage 2 work (mech deploy +
|
|
37
|
+
* rebind). May get a conditional minEoaGasEth top-up from master if
|
|
38
|
+
* Stage 1's gas eats too much of the original transfer.
|
|
39
|
+
* - minEoaGasEth × STANDARD_MASTER_BOOTSTRAP_MULTIPLIER (0.010 ETH):
|
|
40
|
+
* master gas budget across both stages. Real spend (~0.0025 ETH at
|
|
41
|
+
* typical 6 gwei Base Sepolia) leaves room for ~4× gas-spike margin
|
|
42
|
+
* plus the conditional HD-1 top-up.
|
|
43
|
+
* - minEoaGasEth × (targetServices - 1): per-extra-service top-up for
|
|
44
|
+
* services 2..N. Service 1 piggybacks on HD-1's Stage 1 funding.
|
|
45
|
+
*
|
|
46
|
+
* Total for N=1: 0.010 + 0.010 = 0.020 ETH.
|
|
47
|
+
* Total for N=2: 0.025 ETH.
|
|
48
|
+
* Total for N=3: 0.030 ETH.
|
|
49
|
+
*
|
|
50
|
+
* This number works ONLY when Stage 2's internal gate is `minEoaGasEth ×
|
|
51
|
+
* 1n` (0.005 ETH) — not the historic `× 2n`. After Stage 1 transfers 0.010
|
|
52
|
+
* out, master sits at ~0.0099 ETH (0.020 minus transfer minus Stage 1
|
|
53
|
+
* funding-tx gas). The 0.005 gate clears that with margin; the 0.010 gate
|
|
54
|
+
* did not. See the Stage 2 gate at ensureStage1And2 line ~484.
|
|
55
|
+
*
|
|
56
|
+
* Operator may see a "low runway" warning after bootstrap — that's
|
|
57
|
+
* intentional. The operator-facing 0.020 ETH covers bootstrap completion,
|
|
58
|
+
* not multi-week post-bootstrap runway. Top-up is a separate concern.
|
|
59
|
+
*/
|
|
60
|
+
export const STAGE1_AGENT_ETH = 10000000000000000n; // 0.01 ETH (moved out of stepFleetSafeDeploy)
|
|
61
|
+
export function stage1MinMasterEth(config, targetServices = 1) {
|
|
62
|
+
const extraServiceTransfers = config.minEoaGasEth * BigInt(Math.max(0, targetServices - 1));
|
|
63
|
+
return (STAGE1_AGENT_ETH +
|
|
64
|
+
config.minEoaGasEth * STANDARD_MASTER_BOOTSTRAP_MULTIPLIER +
|
|
65
|
+
extraServiceTransfers);
|
|
66
|
+
}
|
|
28
67
|
/** Conservative default: ~0.001 ETH/day master gas if not configured. */
|
|
29
68
|
const DEFAULT_MASTER_ETH_DAILY_WEI = 1000000000000000n;
|
|
30
69
|
/** Warn when ETH above the minimum would last fewer than this many days at the daily estimate. */
|
|
31
70
|
const MASTER_ETH_RUNWAY_WARN_DAYS = 7n;
|
|
71
|
+
/**
|
|
72
|
+
* Safe → ERC-8004 agent NFT binding retry (jinn-mono-h74p).
|
|
73
|
+
*
|
|
74
|
+
* Empirical observation against fresh Base Sepolia 1/1 Safes: the first
|
|
75
|
+
* `IdentityRegistry.setAgentWallet` attempt reverts with a generic
|
|
76
|
+
* "Execution reverted for an unknown reason" — but the same Safe + same
|
|
77
|
+
* agentId + a freshly-signed message a few seconds later succeeds. The
|
|
78
|
+
* race window is likely freshly-deployed-Safe state lag on the public RPC
|
|
79
|
+
* (the simulator can't read the Safe's storage yet in the same block /
|
|
80
|
+
* eventual-consistency between sibling RPC nodes). A short bounded retry
|
|
81
|
+
* makes the operator-visible behaviour deterministic instead of relying on
|
|
82
|
+
* the "daemon exits → operator restarts → resume at safe_binding_pending"
|
|
83
|
+
* accidental safety net (which goes away when jinn-mono-vh74.2 removes the
|
|
84
|
+
* Claude-auth post-bootstrap exit gate).
|
|
85
|
+
*
|
|
86
|
+
* Defaults: 3 attempts × 3 s delay = at most ~6 s of in-process retry budget
|
|
87
|
+
* before falling through to the existing `safe_binding_pending` persisted
|
|
88
|
+
* state. Real (non-transient) failures still surface — just with a slightly
|
|
89
|
+
* higher latency tax for the diagnostic.
|
|
90
|
+
*/
|
|
91
|
+
const DEFAULT_SAFE_BINDING_MAX_ATTEMPTS = 3;
|
|
92
|
+
const DEFAULT_SAFE_BINDING_RETRY_DELAY_MS = 3_000;
|
|
32
93
|
export class FleetBootstrapper {
|
|
33
94
|
store;
|
|
34
95
|
config;
|
|
@@ -43,6 +104,8 @@ export class FleetBootstrapper {
|
|
|
43
104
|
faucetLoopTimeoutMs;
|
|
44
105
|
now;
|
|
45
106
|
autoTestnetFaucet;
|
|
107
|
+
safeBindingMaxAttempts;
|
|
108
|
+
safeBindingRetryDelayMs;
|
|
46
109
|
constructor(options = {}) {
|
|
47
110
|
this.store = new FleetStateStore(options.earningDir);
|
|
48
111
|
this.chain = options.chain ?? 'base';
|
|
@@ -55,6 +118,10 @@ export class FleetBootstrapper {
|
|
|
55
118
|
this.now = options.now ?? Date.now;
|
|
56
119
|
this.autoTestnetFaucet =
|
|
57
120
|
options.autoTestnetFaucet ?? this.env['JINN_DISABLE_TESTNET_FAUCET'] !== '1';
|
|
121
|
+
this.safeBindingMaxAttempts =
|
|
122
|
+
options.safeBindingMaxAttempts ?? DEFAULT_SAFE_BINDING_MAX_ATTEMPTS;
|
|
123
|
+
this.safeBindingRetryDelayMs =
|
|
124
|
+
options.safeBindingRetryDelayMs ?? DEFAULT_SAFE_BINDING_RETRY_DELAY_MS;
|
|
58
125
|
const dailyOpt = options.masterEthDailyEstimateWei;
|
|
59
126
|
this.masterEthDailyEstimateWei =
|
|
60
127
|
dailyOpt !== undefined
|
|
@@ -77,6 +144,71 @@ export class FleetBootstrapper {
|
|
|
77
144
|
async getStatus() {
|
|
78
145
|
return this.store.load(this.chain);
|
|
79
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Run `bindAgentWalletToSafe` with the freshly-deployed-Safe race retry
|
|
149
|
+
* (jinn-mono-h74p, corrected in jinn-mono-k1ng).
|
|
150
|
+
*
|
|
151
|
+
* The race: against a fresh 1/1 Safe on Base Sepolia, the first
|
|
152
|
+
* setAgentWallet attempt reverts with "Execution reverted for an unknown
|
|
153
|
+
* reason"; the same Safe + same agentId a few seconds later succeeds.
|
|
154
|
+
*
|
|
155
|
+
* The h74p version of the retry only wrapped the call in a try/catch.
|
|
156
|
+
* In production, `bindAgentWalletToSafe` doesn't throw on revert — it
|
|
157
|
+
* returns a `{ ok: false, error }` outcome — so the catch never fired
|
|
158
|
+
* and the retry was dead code. The per-service path "worked" anyway
|
|
159
|
+
* because it persists `safe_binding_pending` and the next bootstrap
|
|
160
|
+
* resumes the bind. Stage 1 had no equivalent safety net, so a single
|
|
161
|
+
* `ok: false` halted bootstrap (the 2026-05-18 canary failure).
|
|
162
|
+
*
|
|
163
|
+
* This wrapper:
|
|
164
|
+
* - Retries on returned `ok: false` (the way the race actually
|
|
165
|
+
* manifests in production).
|
|
166
|
+
* - Also retries on thrown exceptions (defense-in-depth in case viem
|
|
167
|
+
* error handling changes).
|
|
168
|
+
* - Returns the final outcome; callers decide whether to throw, mark
|
|
169
|
+
* pending, or proceed.
|
|
170
|
+
*
|
|
171
|
+
* Single attempt budget: `safeBindingMaxAttempts` × `safeBindingRetryDelayMs`
|
|
172
|
+
* (defaults: 3 × 3 s = ~9 s).
|
|
173
|
+
*/
|
|
174
|
+
async bindAgentWalletWithRetry(args, label) {
|
|
175
|
+
const maxAttempts = Math.max(1, this.safeBindingMaxAttempts);
|
|
176
|
+
let lastResult;
|
|
177
|
+
let lastThrowError;
|
|
178
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
179
|
+
try {
|
|
180
|
+
lastResult = await bindAgentWalletToSafe(args);
|
|
181
|
+
if (lastResult.ok)
|
|
182
|
+
return lastResult;
|
|
183
|
+
if (attempt < maxAttempts) {
|
|
184
|
+
console.error(`[fleet-bootstrap] ${label}: setAgentWallet attempt ` +
|
|
185
|
+
`${attempt}/${maxAttempts} returned ok=false (${lastResult.error.shortMessage}); ` +
|
|
186
|
+
`retrying in ${this.safeBindingRetryDelayMs}ms...`);
|
|
187
|
+
if (this.safeBindingRetryDelayMs > 0) {
|
|
188
|
+
await sleep(this.safeBindingRetryDelayMs);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
lastThrowError = err;
|
|
194
|
+
if (attempt < maxAttempts) {
|
|
195
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
196
|
+
console.error(`[fleet-bootstrap] ${label}: setAgentWallet attempt ` +
|
|
197
|
+
`${attempt}/${maxAttempts} threw (${reason}); retrying in ` +
|
|
198
|
+
`${this.safeBindingRetryDelayMs}ms...`);
|
|
199
|
+
if (this.safeBindingRetryDelayMs > 0) {
|
|
200
|
+
await sleep(this.safeBindingRetryDelayMs);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (lastResult)
|
|
206
|
+
return lastResult; // final ok:false propagated to caller
|
|
207
|
+
// Only thrown all the way through — no successful response or returned outcome.
|
|
208
|
+
throw lastThrowError instanceof Error
|
|
209
|
+
? lastThrowError
|
|
210
|
+
: new Error(String(lastThrowError));
|
|
211
|
+
}
|
|
80
212
|
/**
|
|
81
213
|
* Conservative daily master gas (wei): max(DEFAULT, rough tx count from poll interval × cost).
|
|
82
214
|
*/
|
|
@@ -112,16 +244,149 @@ export class FleetBootstrapper {
|
|
|
112
244
|
const mnemonic = await this.loadExistingMnemonic(state, password);
|
|
113
245
|
return this.stepRegisterAgent(state, mnemonic, serviceIndex);
|
|
114
246
|
}
|
|
115
|
-
|
|
116
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Stage 1 — Identity (universal). Walks: wallet → predict Safe (from
|
|
249
|
+
* HD-index-1 agent EOA) → ETH funding gate → deploy Safe → mint agentId
|
|
250
|
+
* + setAgentWallet via ERC-1271. Idempotent and re-entrant. Does NOT
|
|
251
|
+
* touch service rows or staking — those belong to Stage 2.
|
|
252
|
+
*
|
|
253
|
+
* Fleet-level fields written:
|
|
254
|
+
* - fleet_safe_address (after predict)
|
|
255
|
+
* - fleet_agent_id, fleet_identity_registry, fleet_stage='stage1'
|
|
256
|
+
* (after mint + bind)
|
|
257
|
+
*
|
|
258
|
+
* Funding gate: requires ETH on the master EOA only (no OLAS). On testnet,
|
|
259
|
+
* the existing CDP faucet loop drains as usual when `autoTestnetFaucet`
|
|
260
|
+
* is enabled.
|
|
261
|
+
*
|
|
262
|
+
* See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
|
|
263
|
+
*/
|
|
264
|
+
async ensureStage1(password) {
|
|
265
|
+
// Legacy keystore migration (same as bootstrap()).
|
|
117
266
|
if (!this.store.hasMnemonicKeystore() && this.store.hasLegacyKeystore()) {
|
|
118
267
|
await this.store.migrateLegacyFiles();
|
|
119
268
|
}
|
|
120
269
|
let state = await this.store.load(this.chain);
|
|
270
|
+
// Short-circuit if Stage 1 is already complete (or beyond).
|
|
271
|
+
if (state.fleet_stage === 'stage1' || state.fleet_stage === 'stage1_and_2') {
|
|
272
|
+
// Even when stage marker says complete, fleet identity may be empty for
|
|
273
|
+
// pre-j07 operators (`stage1_and_2` is set by the migration for
|
|
274
|
+
// services-complete-but-no-agent_id operators). In that case we leave
|
|
275
|
+
// Stage 1 alone — the legacy backfill in main.ts handles those rows
|
|
276
|
+
// and a future ensureStage1 call after backfill will promote.
|
|
277
|
+
return {
|
|
278
|
+
ok: true,
|
|
279
|
+
fleet_state: state,
|
|
280
|
+
message: state.fleet_agent_id !== null
|
|
281
|
+
? `Stage 1 already complete (fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}).`
|
|
282
|
+
: 'Stage 1 marker present but fleet identity is empty (legacy operator). Skipping.',
|
|
283
|
+
};
|
|
284
|
+
}
|
|
121
285
|
try {
|
|
122
|
-
// Phase 1: Master wallet setup
|
|
123
286
|
state = await this.ensureMasterWallet(state, password);
|
|
124
|
-
//
|
|
287
|
+
// Stage 1 funding gate — ETH only (no OLAS). Stage 1 needs
|
|
288
|
+
// STAGE1_AGENT_ETH (0.01) for the master → agent transfer plus
|
|
289
|
+
// minEoaGasEth (0.005) reserved for the master's own gas to send that
|
|
290
|
+
// transfer. The agent EOA then pays for Safe deploy + ERC-8004 register
|
|
291
|
+
// + setAgentWallet out of the funds it just received.
|
|
292
|
+
// See jinn-mono-u34i: pre-fix this gate was 2×minEoaGasEth (= 0.01 ETH),
|
|
293
|
+
// which equaled the transfer amount and left no gas headroom, so a
|
|
294
|
+
// master holding the gate's minimum would fail eth_estimateGas with
|
|
295
|
+
// "gas required exceeds allowance (0)".
|
|
296
|
+
const requiredMasterEth = stage1MinMasterEth(this.config, this.targetServices);
|
|
297
|
+
const masterAddress = state.master_address;
|
|
298
|
+
const masterBalance = await this.publicClient.getBalance({
|
|
299
|
+
address: masterAddress,
|
|
300
|
+
});
|
|
301
|
+
if (masterBalance < requiredMasterEth) {
|
|
302
|
+
const shortfall = requiredMasterEth - masterBalance;
|
|
303
|
+
return {
|
|
304
|
+
ok: false,
|
|
305
|
+
fleet_state: state,
|
|
306
|
+
message: `Your master wallet needs more ETH (currently ${formatEther(masterBalance)} ETH, need ${formatEther(shortfall)} ETH more) to complete Stage 1. Please send ETH to: ${masterAddress}`,
|
|
307
|
+
funding: {
|
|
308
|
+
master_address: masterAddress,
|
|
309
|
+
eth_required: shortfall.toString(),
|
|
310
|
+
eth_balance: masterBalance.toString(),
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const mnemonic = await this.loadExistingMnemonic(state, password);
|
|
315
|
+
// Step 1: predict fleet Safe from HD-index-1 agent EOA.
|
|
316
|
+
if (!state.fleet_safe_address) {
|
|
317
|
+
state = await this.stepFleetSafePredict(state, mnemonic);
|
|
318
|
+
}
|
|
319
|
+
// Step 2: deploy fleet Safe if bytecode absent.
|
|
320
|
+
const safeCode = await this.publicClient.getCode({
|
|
321
|
+
address: getAddress(state.fleet_safe_address),
|
|
322
|
+
});
|
|
323
|
+
if (safeCode === undefined || safeCode === '0x') {
|
|
324
|
+
state = await this.stepFleetSafeDeploy(state, mnemonic);
|
|
325
|
+
}
|
|
326
|
+
// Step 3: mint agentId + bind Safe via setAgentWallet.
|
|
327
|
+
if (!state.fleet_agent_id) {
|
|
328
|
+
state = await this.stepFleetIdentityRegister(state, mnemonic);
|
|
329
|
+
}
|
|
330
|
+
else if (state.fleet_stage !== 'stage1' && state.fleet_stage !== 'stage1_and_2') {
|
|
331
|
+
// Identity was minted but stage marker is stale; advance it.
|
|
332
|
+
state = await this.store.patchFleet({ fleet_stage: 'stage1' });
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
ok: true,
|
|
336
|
+
fleet_state: state,
|
|
337
|
+
message: `Stage 1 complete. fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}.`,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
const { summary, hint, rawMessage } = formatBootstrapOperatorMessage(error);
|
|
342
|
+
const userMessage = hint !== undefined ? `${summary}\nHint: ${hint}` : summary;
|
|
343
|
+
if (this.debug) {
|
|
344
|
+
console.error(`[fleet-bootstrap] ensureStage1 failed:`, error);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
console.error(`[fleet-bootstrap] ${summary}`);
|
|
348
|
+
if (hint !== undefined)
|
|
349
|
+
console.error(`Hint: ${hint}`);
|
|
350
|
+
if (rawMessage && rawMessage !== summary) {
|
|
351
|
+
console.error(`[fleet-bootstrap] raw: ${rawMessage.split('\n')[0]}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
ok: false,
|
|
356
|
+
fleet_state: state,
|
|
357
|
+
message: userMessage,
|
|
358
|
+
rawErrorMessage: rawMessage,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Stage 1 + Stage 2 — full operator bootstrap. Calls `ensureStage1`
|
|
364
|
+
* first; on success, walks Stage 2 per service. Builder-only users who
|
|
365
|
+
* have completed Stage 1 and call this method later begin Stage 2 from
|
|
366
|
+
* `awaiting_stake` for the first service row (created lazily here).
|
|
367
|
+
*
|
|
368
|
+
* Two-Safe topology in standard mode: `fleet_safe_address !==
|
|
369
|
+
* services[0].safe_address` because Stage 2's `distributor.stake()`
|
|
370
|
+
* creates its own Safe. In self-bond mode the two converge (both
|
|
371
|
+
* derived from HD-index-1).
|
|
372
|
+
*
|
|
373
|
+
* See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
|
|
374
|
+
*/
|
|
375
|
+
async ensureStage1And2(password) {
|
|
376
|
+
// Stage 1 first — establishes fleet identity. Short-circuits if already done.
|
|
377
|
+
const stage1Result = await this.ensureStage1(password);
|
|
378
|
+
if (!stage1Result.ok) {
|
|
379
|
+
return stage1Result;
|
|
380
|
+
}
|
|
381
|
+
// Original bootstrap body — copied verbatim from the previous bootstrap()
|
|
382
|
+
// method, with two changes:
|
|
383
|
+
// (a) the legacy-keystore migration and master-wallet-ensure are no-ops
|
|
384
|
+
// because ensureStage1 already ran them.
|
|
385
|
+
// (b) at the end, if any service reached `complete`/`safe_binding_pending`
|
|
386
|
+
// we advance `fleet_stage` to `'stage1_and_2'`.
|
|
387
|
+
let state = stage1Result.fleet_state;
|
|
388
|
+
try {
|
|
389
|
+
// Phase 1b: Check master funding for the full operator path.
|
|
125
390
|
const masterAddress = state.master_address;
|
|
126
391
|
let masterBalance = await this.publicClient.getBalance({ address: masterAddress });
|
|
127
392
|
// Self-bond mode needs much more ETH than standard mode because the master
|
|
@@ -159,7 +424,17 @@ export class FleetBootstrapper {
|
|
|
159
424
|
const requiredMasterEth = this.stakingMode === 'standard'
|
|
160
425
|
? (standardFleetAlreadyComplete
|
|
161
426
|
? 0n
|
|
162
|
-
|
|
427
|
+
// Stage 2 master gas budget — covers distributor.stake() (~0.003
|
|
428
|
+
// ETH at typical 6 gwei Base Sepolia) plus per-extra-service
|
|
429
|
+
// top-up transfers. Previously this was `× 2` for fresh fleets,
|
|
430
|
+
// which double-counted a service-1 transfer that doesn't actually
|
|
431
|
+
// fire (HD-1 carries Stage 1 leftover, gets a conditional top-up
|
|
432
|
+
// only if needed). See jinn-mono-u34i: the `× 2` figure also
|
|
433
|
+
// exceeded the post-Stage-1 master balance at the operator-facing
|
|
434
|
+
// 0.020 ETH budget by ~127k gwei of Stage 1 gas burn, causing a
|
|
435
|
+
// second funding prompt.
|
|
436
|
+
: this.config.minEoaGasEth +
|
|
437
|
+
this.config.minEoaGasEth * BigInt(Math.max(0, this.targetServices - 1)))
|
|
163
438
|
: SELF_BOND_ETH_PER_SERVICE * BigInt(this.targetServices);
|
|
164
439
|
const autoFaucetEnabled = this.autoTestnetFaucet;
|
|
165
440
|
// Re-sum system ETH (master + agent/safe balances for self-bond mode).
|
|
@@ -291,6 +566,11 @@ export class FleetBootstrapper {
|
|
|
291
566
|
const nextIndex = nextFleetServiceIndex(state.services);
|
|
292
567
|
state = await this.bootstrapService(state, mnemonic, nextIndex);
|
|
293
568
|
}
|
|
569
|
+
// Advance fleet_stage to 'stage1_and_2' if any service is operational.
|
|
570
|
+
const anyOperationalAfter = state.services.some(s => isOperationalServiceStep(s.step));
|
|
571
|
+
if (anyOperationalAfter && state.fleet_stage !== 'stage1_and_2') {
|
|
572
|
+
state = await this.store.patchFleet({ fleet_stage: 'stage1_and_2' });
|
|
573
|
+
}
|
|
294
574
|
return {
|
|
295
575
|
ok: true,
|
|
296
576
|
fleet_state: state,
|
|
@@ -322,6 +602,14 @@ export class FleetBootstrapper {
|
|
|
322
602
|
};
|
|
323
603
|
}
|
|
324
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Back-compat alias. Existing call sites in `client/src/cli/commands/bootstrap.ts`
|
|
607
|
+
* and `client/src/cli/commands/fleet-scale.ts` continue to call `bootstrap()`;
|
|
608
|
+
* forwarding to `ensureStage1And2` preserves their semantics without churn.
|
|
609
|
+
*/
|
|
610
|
+
async bootstrap(password) {
|
|
611
|
+
return this.ensureStage1And2(password);
|
|
612
|
+
}
|
|
325
613
|
/**
|
|
326
614
|
* If the master is only slightly above the minimum, warn about gas runway (heuristic days).
|
|
327
615
|
*/
|
|
@@ -382,6 +670,133 @@ export class FleetBootstrapper {
|
|
|
382
670
|
return freshMnemonic;
|
|
383
671
|
}
|
|
384
672
|
}
|
|
673
|
+
// ── Stage 1: fleet-level identity steps (nghf) ────────────────────────
|
|
674
|
+
/** Deterministic Safe predict from the HD-index-1 agent EOA. */
|
|
675
|
+
async stepFleetSafePredict(state, mnemonic) {
|
|
676
|
+
const agentAddress = deriveAgentAddress(mnemonic, 1);
|
|
677
|
+
const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
|
|
678
|
+
console.error(`[fleet-bootstrap] Stage 1: predicting fleet Safe (owner=${agentAddress})`);
|
|
679
|
+
const { address } = await initPredictedSafe({
|
|
680
|
+
rpcUrl: this.config.rpcUrl,
|
|
681
|
+
signerKey: agentKey,
|
|
682
|
+
owners: [agentAddress],
|
|
683
|
+
threshold: 1,
|
|
684
|
+
});
|
|
685
|
+
void state;
|
|
686
|
+
return this.store.patchFleet({ fleet_safe_address: getAddress(address) });
|
|
687
|
+
}
|
|
688
|
+
/** Deploy the predicted fleet Safe. Funds the agent EOA from master if needed. */
|
|
689
|
+
async stepFleetSafeDeploy(state, mnemonic) {
|
|
690
|
+
const agentAddress = deriveAgentAddress(mnemonic, 1);
|
|
691
|
+
const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
|
|
692
|
+
const agentSigner = deriveAgentSigner(mnemonic, 1);
|
|
693
|
+
const fleetSafe = state.fleet_safe_address;
|
|
694
|
+
// Fund agent EOA so it can pay for Safe deploy + setAgentWallet gas.
|
|
695
|
+
// 0.01 ETH covers Safe deploy (~250k gas) + register (~80k) + setAgentWallet
|
|
696
|
+
// (~200k) at testnet gas prices comfortably. STAGE1_AGENT_ETH is the
|
|
697
|
+
// module-level constant used both here and in `stage1MinMasterEth` so the
|
|
698
|
+
// gate and the transfer agree (jinn-mono-u34i).
|
|
699
|
+
const masterAccount = deriveMasterSigner(mnemonic);
|
|
700
|
+
const masterWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, masterAccount);
|
|
701
|
+
const agentBalance = await this.publicClient.getBalance({
|
|
702
|
+
address: getAddress(agentAddress),
|
|
703
|
+
});
|
|
704
|
+
if (agentBalance < STAGE1_AGENT_ETH) {
|
|
705
|
+
const fundAmount = STAGE1_AGENT_ETH - agentBalance;
|
|
706
|
+
console.error(`[fleet-bootstrap] Stage 1: funding fleet agent EOA with ${fundAmount} wei from master`);
|
|
707
|
+
const fundHash = await viemSendTransactionWithRetry(masterWallet, this.publicClient, {
|
|
708
|
+
account: masterAccount,
|
|
709
|
+
to: addr(agentAddress),
|
|
710
|
+
value: fundAmount,
|
|
711
|
+
});
|
|
712
|
+
await waitForTransactionReceiptWithRetry(this.publicClient, fundHash);
|
|
713
|
+
}
|
|
714
|
+
console.error(`[fleet-bootstrap] Stage 1: deploying fleet Safe at ${fleetSafe}`);
|
|
715
|
+
const { safe } = await initPredictedSafe({
|
|
716
|
+
rpcUrl: this.config.rpcUrl,
|
|
717
|
+
signerKey: agentKey,
|
|
718
|
+
owners: [agentAddress],
|
|
719
|
+
threshold: 1,
|
|
720
|
+
});
|
|
721
|
+
const deployTx = await safe.createSafeDeploymentTransaction();
|
|
722
|
+
const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
|
|
723
|
+
const deployHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
|
|
724
|
+
account: agentSigner,
|
|
725
|
+
to: deployTx.to,
|
|
726
|
+
value: BigInt(deployTx.value),
|
|
727
|
+
data: deployTx.data,
|
|
728
|
+
});
|
|
729
|
+
const receipt = await waitForTransactionReceiptWithRetry(this.publicClient, deployHash);
|
|
730
|
+
if (receipt.status !== 'success') {
|
|
731
|
+
throw new Error(`Fleet Safe deployment tx failed: ${deployHash}`);
|
|
732
|
+
}
|
|
733
|
+
try {
|
|
734
|
+
await waitForContractCode(this.publicClient, getAddress(fleetSafe));
|
|
735
|
+
}
|
|
736
|
+
catch {
|
|
737
|
+
throw new Error(`Fleet Safe deployment succeeded but no code at ${fleetSafe}`);
|
|
738
|
+
}
|
|
739
|
+
console.error(`[fleet-bootstrap] Stage 1: fleet Safe deployed (tx=${deployHash})`);
|
|
740
|
+
return this.store.load(this.chain);
|
|
741
|
+
}
|
|
742
|
+
/** Mint the fleet agentId + bind Safe via setAgentWallet (ERC-1271). */
|
|
743
|
+
async stepFleetIdentityRegister(state, mnemonic) {
|
|
744
|
+
const identityRegistry = this.config.identityRegistry ?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
|
|
745
|
+
if (!identityRegistry) {
|
|
746
|
+
throw new Error(`IdentityRegistry address not configured for chainId=${this.config.chainId}.`);
|
|
747
|
+
}
|
|
748
|
+
const fleetSafe = state.fleet_safe_address;
|
|
749
|
+
const agentSigner = deriveAgentSigner(mnemonic, 1);
|
|
750
|
+
const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
|
|
751
|
+
// Mint agentId — empty agent URI for v0 (matches stepRegisterAgent §6.1 in spec).
|
|
752
|
+
const registerData = encodeFunctionData({
|
|
753
|
+
abi: IDENTITY_REGISTRY_ABI,
|
|
754
|
+
functionName: 'register',
|
|
755
|
+
args: [''],
|
|
756
|
+
});
|
|
757
|
+
console.error(`[fleet-bootstrap] Stage 1: minting fleet agentId ` +
|
|
758
|
+
`(IdentityRegistry=${identityRegistry}, agentEOA=${agentSigner.address})`);
|
|
759
|
+
const mintTxHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
|
|
760
|
+
account: agentSigner,
|
|
761
|
+
to: addr(identityRegistry),
|
|
762
|
+
data: registerData,
|
|
763
|
+
});
|
|
764
|
+
const mintReceipt = await waitForTransactionReceiptWithRetry(this.publicClient, mintTxHash);
|
|
765
|
+
if (mintReceipt.status !== 'success') {
|
|
766
|
+
throw new Error(`Fleet IdentityRegistry.register() failed: ${mintTxHash}`);
|
|
767
|
+
}
|
|
768
|
+
const fleetAgentId = this.parseAgentIdFromReceipt(mintReceipt, identityRegistry);
|
|
769
|
+
if (fleetAgentId === null) {
|
|
770
|
+
throw new Error(`Fleet IdentityRegistry.register() succeeded but Registered event missing (tx=${mintTxHash})`);
|
|
771
|
+
}
|
|
772
|
+
// Persist agentId IMMEDIATELY so a crash between mint and bind doesn't lose it.
|
|
773
|
+
await this.store.patchFleet({
|
|
774
|
+
fleet_agent_id: fleetAgentId,
|
|
775
|
+
fleet_identity_registry: getAddress(identityRegistry),
|
|
776
|
+
});
|
|
777
|
+
// Bind the Safe via setAgentWallet (ERC-1271).
|
|
778
|
+
// Wrapped in the freshly-deployed-Safe retry (jinn-mono-k1ng). The
|
|
779
|
+
// pre-k1ng single-attempt version halted bootstrap when the documented
|
|
780
|
+
// race fired on the first attempt — exactly the 2026-05-18 canary's
|
|
781
|
+
// second-time-around failure mode.
|
|
782
|
+
console.error(`[fleet-bootstrap] Stage 1: binding fleet Safe ${fleetSafe} to agentId=${fleetAgentId}`);
|
|
783
|
+
const bindResult = await this.bindAgentWalletWithRetry({
|
|
784
|
+
identityRegistryAddress: addr(identityRegistry),
|
|
785
|
+
agentId: BigInt(fleetAgentId),
|
|
786
|
+
safeAddress: addr(fleetSafe),
|
|
787
|
+
agentEoaAccount: agentSigner,
|
|
788
|
+
agentEoaWalletClient: agentWallet,
|
|
789
|
+
publicClient: this.publicClient,
|
|
790
|
+
chainId: this.config.chainId,
|
|
791
|
+
}, 'Stage 1');
|
|
792
|
+
if (!bindResult.ok) {
|
|
793
|
+
const bindErr = bindResult.error;
|
|
794
|
+
throw new Error(`Fleet setAgentWallet failed after ${this.safeBindingMaxAttempts} attempts: ${bindErr.shortMessage}` +
|
|
795
|
+
(bindErr.revertReason ? ` (revert: ${bindErr.revertReason})` : ''));
|
|
796
|
+
}
|
|
797
|
+
console.error(`[fleet-bootstrap] Stage 1: setAgentWallet succeeded (tx=${bindResult.txHash})`);
|
|
798
|
+
return this.store.patchFleet({ fleet_stage: 'stage1' });
|
|
799
|
+
}
|
|
385
800
|
// ── Phase 2: Per-service bootstrap ───────────────────────────────────
|
|
386
801
|
async bootstrapService(state, mnemonic, index) {
|
|
387
802
|
const agentAddress = deriveAgentAddress(mnemonic, index);
|
|
@@ -837,6 +1252,7 @@ export class FleetBootstrapper {
|
|
|
837
1252
|
let svc = (await this.store.load(this.chain)).services.find(s => s.index === index);
|
|
838
1253
|
if (!svc)
|
|
839
1254
|
throw new Error(`Service ${index} not found in state`);
|
|
1255
|
+
const fleetSnapshot = await this.store.load(this.chain);
|
|
840
1256
|
const identityRegistry = this.config.identityRegistry
|
|
841
1257
|
?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
|
|
842
1258
|
if (!identityRegistry) {
|
|
@@ -845,7 +1261,7 @@ export class FleetBootstrapper {
|
|
|
845
1261
|
}
|
|
846
1262
|
const agentSigner = deriveAgentSigner(mnemonic, index);
|
|
847
1263
|
const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
|
|
848
|
-
// ── Sub-step A: mint NFT (skip if agent_id is already set).
|
|
1264
|
+
// ── Sub-step A: mint NFT (skip if agent_id is already set OR fleet identity exists). ─
|
|
849
1265
|
let agentId;
|
|
850
1266
|
if (svc.agent_id) {
|
|
851
1267
|
console.error(`[fleet-bootstrap] Service ${index}: ERC-8004 agent already registered ` +
|
|
@@ -856,6 +1272,22 @@ export class FleetBootstrapper {
|
|
|
856
1272
|
step: svc.step === 'safe_binding_pending' ? 'safe_binding_pending' : 'agent_registered',
|
|
857
1273
|
});
|
|
858
1274
|
}
|
|
1275
|
+
else if (fleetSnapshot.fleet_agent_id) {
|
|
1276
|
+
// nghf: reuse the fleet-level agentId minted by ensureStage1 instead of
|
|
1277
|
+
// minting a second one. This collapses the "one agentId per user"
|
|
1278
|
+
// invariant in spec §5.1 for the standard-mode two-Safe topology.
|
|
1279
|
+
console.error(`[fleet-bootstrap] Service ${index}: reusing fleet agentId=${fleetSnapshot.fleet_agent_id} ` +
|
|
1280
|
+
`(no second mint needed).`);
|
|
1281
|
+
agentId = fleetSnapshot.fleet_agent_id;
|
|
1282
|
+
svc = await this.firstServiceUpdate(index, {
|
|
1283
|
+
agent_id: fleetSnapshot.fleet_agent_id,
|
|
1284
|
+
agent_uri: '',
|
|
1285
|
+
identity_registry_address: fleetSnapshot.fleet_identity_registry ?? getAddress(identityRegistry),
|
|
1286
|
+
agent_registered_tx: null,
|
|
1287
|
+
step: 'agent_registered',
|
|
1288
|
+
error: null,
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
859
1291
|
else {
|
|
860
1292
|
// v0: empty agentURI. The richer agent card (per §6 of the spec) is
|
|
861
1293
|
// future work — operators may later call `setAgentURI`.
|
|
@@ -924,8 +1356,18 @@ export class FleetBootstrapper {
|
|
|
924
1356
|
step: 'safe_binding_pending',
|
|
925
1357
|
error: null,
|
|
926
1358
|
});
|
|
1359
|
+
// Unified retry policy (jinn-mono-k1ng — supersedes h74p's throw-only
|
|
1360
|
+
// retry): retry on `ok: false` and on thrown exceptions. The h74p
|
|
1361
|
+
// version only caught throws, but `bindAgentWalletToSafe` returns
|
|
1362
|
+
// `ok: false` for the documented freshly-deployed-Safe revert race —
|
|
1363
|
+
// so the retry was dead code under real RPC. Per-service "worked"
|
|
1364
|
+
// anyway because the next bootstrap resumes from `safe_binding_pending`;
|
|
1365
|
+
// k1ng makes the in-process retry actually do its job so we don't
|
|
1366
|
+
// depend on the operator restarting the daemon.
|
|
1367
|
+
let bindResult;
|
|
1368
|
+
let lastBindError;
|
|
927
1369
|
try {
|
|
928
|
-
|
|
1370
|
+
bindResult = await this.bindAgentWalletWithRetry({
|
|
929
1371
|
identityRegistryAddress: addr(identityRegistry),
|
|
930
1372
|
agentId: BigInt(agentId),
|
|
931
1373
|
safeAddress: addr(safeAddress),
|
|
@@ -933,23 +1375,45 @@ export class FleetBootstrapper {
|
|
|
933
1375
|
agentEoaWalletClient: agentWallet,
|
|
934
1376
|
publicClient: this.publicClient,
|
|
935
1377
|
chainId: this.config.chainId,
|
|
936
|
-
});
|
|
1378
|
+
}, `Service ${index}`);
|
|
1379
|
+
}
|
|
1380
|
+
catch (err) {
|
|
1381
|
+
lastBindError = err;
|
|
1382
|
+
}
|
|
1383
|
+
if (bindResult?.ok === true) {
|
|
937
1384
|
console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet succeeded ` +
|
|
938
|
-
`(tx=${
|
|
1385
|
+
`(tx=${bindResult.txHash}, safe=${safeAddress}).`);
|
|
939
1386
|
svc = await this.firstServiceUpdate(index, {
|
|
940
1387
|
safe_bound_to_agent: true,
|
|
941
1388
|
step: 'complete',
|
|
942
1389
|
error: null,
|
|
1390
|
+
error_revert_reason: null,
|
|
1391
|
+
error_short_message: null,
|
|
943
1392
|
});
|
|
944
1393
|
}
|
|
945
|
-
|
|
946
|
-
const
|
|
947
|
-
console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed
|
|
948
|
-
`safe_bound_to_agent=false (${
|
|
1394
|
+
else if (bindResult && !bindResult.ok) {
|
|
1395
|
+
const bindErr = bindResult.error;
|
|
1396
|
+
console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed after retries; ` +
|
|
1397
|
+
`continuing with safe_bound_to_agent=false (${bindErr.shortMessage}` +
|
|
1398
|
+
`${bindErr.revertReason ? `, revert: ${bindErr.revertReason}` : ''}).`);
|
|
1399
|
+
svc = await this.firstServiceUpdate(index, {
|
|
1400
|
+
safe_bound_to_agent: false,
|
|
1401
|
+
step: 'safe_binding_pending',
|
|
1402
|
+
error: `safe_binding_failed: ${bindErr.shortMessage}`,
|
|
1403
|
+
error_revert_reason: bindErr.revertReason,
|
|
1404
|
+
error_short_message: bindErr.shortMessage,
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
else {
|
|
1408
|
+
const reason = lastBindError instanceof Error ? lastBindError.message : String(lastBindError);
|
|
1409
|
+
console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet threw on every attempt; ` +
|
|
1410
|
+
`continuing with safe_bound_to_agent=false (${reason}).`);
|
|
949
1411
|
svc = await this.firstServiceUpdate(index, {
|
|
950
1412
|
safe_bound_to_agent: false,
|
|
951
1413
|
step: 'safe_binding_pending',
|
|
952
1414
|
error: `safe_binding_failed: ${reason}`,
|
|
1415
|
+
error_revert_reason: null,
|
|
1416
|
+
error_short_message: null,
|
|
953
1417
|
});
|
|
954
1418
|
}
|
|
955
1419
|
}
|
|
@@ -1066,8 +1530,10 @@ export class FleetBootstrapper {
|
|
|
1066
1530
|
if (receipt.status !== 'success') {
|
|
1067
1531
|
throw new Error(`Safe deployment tx failed for service ${index}: ${deployHash}`);
|
|
1068
1532
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1533
|
+
try {
|
|
1534
|
+
await waitForContractCode(this.publicClient, getAddress(safeAddress));
|
|
1535
|
+
}
|
|
1536
|
+
catch {
|
|
1071
1537
|
throw new Error(`Safe deployment succeeded but no code at ${safeAddress}`);
|
|
1072
1538
|
}
|
|
1073
1539
|
console.error(`[fleet-bootstrap] Service ${index}: Safe deployed (tx: ${deployHash})`);
|