@jinn-network/client 0.1.6 → 0.1.7
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 +33 -0
- package/deployments/deployment-jinn-mvi-l1-sepolia-fast.json +23 -4
- package/deployments/deployment-jinn-mvi-l1-sepolia.json +23 -4
- package/deployments/deployment-jinn-mvi-l2-baseSepolia.json +5 -4
- package/dist/adapters/mech/adapter.d.ts +38 -1
- package/dist/adapters/mech/adapter.js +241 -54
- package/dist/adapters/mech/adapter.js.map +1 -1
- package/dist/adapters/mech/contracts.d.ts +17 -4
- package/dist/adapters/mech/contracts.js +8 -2
- package/dist/adapters/mech/contracts.js.map +1 -1
- package/dist/adapters/mech/safe-revert.d.ts +20 -0
- package/dist/adapters/mech/safe-revert.js +12 -4
- package/dist/adapters/mech/safe-revert.js.map +1 -1
- package/dist/adapters/mech/safe.d.ts +5 -1
- package/dist/adapters/mech/safe.js +27 -8
- package/dist/adapters/mech/safe.js.map +1 -1
- package/dist/adapters/mech/verdict-code.d.ts +1 -0
- package/dist/adapters/mech/verdict-code.js +18 -0
- package/dist/adapters/mech/verdict-code.js.map +1 -1
- package/dist/api/admin-endpoint.d.ts +15 -3
- package/dist/api/admin-endpoint.js +24 -2
- package/dist/api/admin-endpoint.js.map +1 -1
- package/dist/api/bootstrap-endpoint.js +49 -0
- package/dist/api/bootstrap-endpoint.js.map +1 -1
- package/dist/api/codex-doctor-endpoint.d.ts +73 -0
- package/dist/api/codex-doctor-endpoint.js +177 -0
- package/dist/api/codex-doctor-endpoint.js.map +1 -0
- package/dist/api/discovery-endpoint.d.ts +1 -0
- package/dist/api/discovery-endpoint.js +26 -0
- package/dist/api/discovery-endpoint.js.map +1 -1
- package/dist/api/fleet-build.d.ts +1 -0
- package/dist/api/fleet-build.js +2 -1
- package/dist/api/fleet-build.js.map +1 -1
- package/dist/api/gather-status.d.ts +11 -0
- package/dist/api/gather-status.js +400 -4
- package/dist/api/gather-status.js.map +1 -1
- package/dist/api/hermes-doctor-endpoint.d.ts +117 -0
- package/dist/api/hermes-doctor-endpoint.js +229 -23
- package/dist/api/hermes-doctor-endpoint.js.map +1 -1
- package/dist/api/launcher-status.d.ts +21 -16
- package/dist/api/launcher-status.js +2 -1
- package/dist/api/launcher-status.js.map +1 -1
- package/dist/api/portfolio-v0-build.d.ts +10 -0
- package/dist/api/portfolio-v0-build.js +24 -5
- package/dist/api/portfolio-v0-build.js.map +1 -1
- package/dist/api/prediction-v1-build.d.ts +10 -0
- package/dist/api/prediction-v1-build.js +7 -1
- package/dist/api/prediction-v1-build.js.map +1 -1
- package/dist/api/server.d.ts +31 -1
- package/dist/api/server.js +68 -1
- package/dist/api/server.js.map +1 -1
- package/dist/api/setup-endpoints.d.ts +16 -0
- package/dist/api/setup-endpoints.js +78 -4
- package/dist/api/setup-endpoints.js.map +1 -1
- package/dist/api/setup-retry-endpoint.d.ts +19 -0
- package/dist/api/setup-retry-endpoint.js +32 -0
- package/dist/api/setup-retry-endpoint.js.map +1 -0
- package/dist/api/solvernets-endpoints.d.ts +8 -0
- package/dist/api/solvernets-endpoints.js +71 -43
- package/dist/api/solvernets-endpoints.js.map +1 -1
- package/dist/api/status-build.d.ts +72 -0
- package/dist/api/status-build.js +73 -18
- package/dist/api/status-build.js.map +1 -1
- package/dist/api/task-run-routing.d.ts +7 -0
- package/dist/api/task-run-routing.js +12 -0
- package/dist/api/task-run-routing.js.map +1 -0
- package/dist/api/task-runs-build.d.ts +21 -0
- package/dist/api/task-runs-build.js +14 -1
- package/dist/api/task-runs-build.js.map +1 -1
- package/dist/build-info.json +4 -4
- package/dist/build-meta.json +1 -1
- package/dist/chain-read-errors.d.ts +10 -0
- package/dist/chain-read-errors.js +15 -0
- package/dist/chain-read-errors.js.map +1 -1
- package/dist/cli/commands/auth.js +1 -1
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/create.js +3 -2
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +2 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/rewards.js +11 -7
- package/dist/cli/commands/rewards.js.map +1 -1
- package/dist/cli/commands/solver-nets.js +24 -9
- package/dist/cli/commands/solver-nets.js.map +1 -1
- package/dist/cli/commands/status.js +1 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/tasks.js +86 -9
- package/dist/cli/commands/tasks.js.map +1 -1
- package/dist/cli/commands/update.d.ts +10 -0
- package/dist/cli/commands/update.js +36 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/introspection-context.js +5 -0
- package/dist/cli/introspection-context.js.map +1 -1
- package/dist/cli/task-native-readiness.d.ts +3 -1
- package/dist/cli/task-native-readiness.js +28 -6
- package/dist/cli/task-native-readiness.js.map +1 -1
- package/dist/config.d.ts +106 -5
- package/dist/config.js +97 -18
- package/dist/config.js.map +1 -1
- package/dist/daemon/checkpoint-loop.d.ts +48 -0
- package/dist/daemon/checkpoint-loop.js +76 -0
- package/dist/daemon/checkpoint-loop.js.map +1 -0
- package/dist/daemon/creator.d.ts +1 -1
- package/dist/daemon/creator.js +7 -3
- package/dist/daemon/creator.js.map +1 -1
- package/dist/daemon/daemon.d.ts +19 -0
- package/dist/daemon/daemon.js +68 -1
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/eviction-loop.d.ts +40 -0
- package/dist/daemon/eviction-loop.js +67 -0
- package/dist/daemon/eviction-loop.js.map +1 -0
- package/dist/daemon/jinn-claim-loop-wiring.d.ts +33 -0
- package/dist/daemon/jinn-claim-loop-wiring.js +40 -0
- package/dist/daemon/jinn-claim-loop-wiring.js.map +1 -0
- package/dist/daemon/jinn-claim-loop.d.ts +24 -17
- package/dist/daemon/jinn-claim-loop.js +77 -23
- package/dist/daemon/jinn-claim-loop.js.map +1 -1
- package/dist/daemon/skip-log-dedup.d.ts +69 -0
- package/dist/daemon/skip-log-dedup.js +106 -0
- package/dist/daemon/skip-log-dedup.js.map +1 -0
- package/dist/dashboard/assets/index-BUlE8F3Y.js +330 -0
- package/dist/dashboard/assets/index-blqc7eqq.css +32 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/discovery/factory.d.ts +17 -5
- package/dist/discovery/factory.js +46 -18
- package/dist/discovery/factory.js.map +1 -1
- package/dist/discovery/http.js +142 -3
- package/dist/discovery/http.js.map +1 -1
- package/dist/discovery/onchain.d.ts +5 -0
- package/dist/discovery/onchain.js +407 -15
- package/dist/discovery/onchain.js.map +1 -1
- package/dist/discovery/types.d.ts +45 -1
- package/dist/discovery/types.js +8 -10
- package/dist/discovery/types.js.map +1 -1
- package/dist/discovery/with-fallback.d.ts +7 -0
- package/dist/discovery/with-fallback.js +10 -0
- package/dist/discovery/with-fallback.js.map +1 -1
- package/dist/earning/bootstrap.d.ts +92 -1
- package/dist/earning/bootstrap.js +203 -63
- package/dist/earning/bootstrap.js.map +1 -1
- package/dist/earning/contracts.d.ts +14 -0
- package/dist/earning/contracts.js +17 -5
- package/dist/earning/contracts.js.map +1 -1
- package/dist/earning/funding-plan.js +27 -18
- package/dist/earning/funding-plan.js.map +1 -1
- package/dist/earning/jinn-rewards.d.ts +46 -0
- package/dist/earning/jinn-rewards.js +32 -0
- package/dist/earning/jinn-rewards.js.map +1 -1
- package/dist/earning/safe-adapter.d.ts +2 -0
- package/dist/earning/safe-adapter.js +26 -12
- package/dist/earning/safe-adapter.js.map +1 -1
- package/dist/earning/store.d.ts +8 -0
- package/dist/earning/store.js.map +1 -1
- package/dist/earning/testnet-setup-migration.d.ts +12 -0
- package/dist/earning/testnet-setup-migration.js +27 -1
- package/dist/earning/testnet-setup-migration.js.map +1 -1
- package/dist/earning/types.d.ts +15 -0
- package/dist/erc8004/reputation.d.ts +8 -0
- package/dist/erc8004/reputation.js +22 -3
- package/dist/erc8004/reputation.js.map +1 -1
- package/dist/harnesses/cost-estimates.d.ts +145 -0
- package/dist/harnesses/cost-estimates.js +297 -0
- package/dist/harnesses/cost-estimates.js.map +1 -0
- package/dist/harnesses/engine/engine.d.ts +72 -0
- package/dist/harnesses/engine/engine.js +105 -8
- package/dist/harnesses/engine/engine.js.map +1 -1
- package/dist/harnesses/engine/persistence.d.ts +51 -1
- package/dist/harnesses/engine/persistence.js +118 -5
- package/dist/harnesses/engine/persistence.js.map +1 -1
- package/dist/harnesses/engine/work-dir-reaper.d.ts +65 -0
- package/dist/harnesses/engine/work-dir-reaper.js +100 -0
- package/dist/harnesses/engine/work-dir-reaper.js.map +1 -0
- package/dist/harnesses/impls/hermes-agent/adapter.js +40 -0
- package/dist/harnesses/impls/hermes-agent/adapter.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/bootstrap.d.ts +20 -0
- package/dist/harnesses/impls/hermes-agent/bootstrap.js +40 -6
- package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/harness.d.ts +59 -1
- package/dist/harnesses/impls/hermes-agent/harness.js +104 -0
- package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -1
- package/dist/harnesses/impls/index.d.ts +7 -0
- package/dist/harnesses/impls/index.js +16 -1
- package/dist/harnesses/impls/index.js.map +1 -1
- package/dist/harnesses/impls/learner/harness.d.ts +38 -4
- package/dist/harnesses/impls/learner/harness.js +96 -2
- package/dist/harnesses/impls/learner/harness.js.map +1 -1
- package/dist/harnesses/impls/learner/plugin-path.d.ts +0 -13
- package/dist/harnesses/impls/learner/plugin-path.js +35 -15
- package/dist/harnesses/impls/learner/plugin-path.js.map +1 -1
- package/dist/harnesses/impls/learner/types.d.ts +11 -0
- package/dist/harnesses/impls/stub.d.ts +58 -0
- package/dist/harnesses/impls/stub.js +89 -0
- package/dist/harnesses/impls/stub.js.map +1 -0
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.d.ts +69 -50
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +178 -93
- 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 +12 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js +121 -7
- 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 +15 -0
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +54 -4
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.d.ts +6 -0
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.js +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.js.map +1 -1
- package/dist/harnesses/readiness-registry.js +9 -1
- package/dist/harnesses/readiness-registry.js.map +1 -1
- package/dist/main.js +371 -82
- package/dist/main.js.map +1 -1
- package/dist/observability/emit-event.d.ts +1 -1
- package/dist/observability/emit-event.js.map +1 -1
- package/dist/operator-errors.d.ts +7 -0
- package/dist/operator-errors.js +13 -1
- package/dist/operator-errors.js.map +1 -1
- package/dist/plugins/learner/.claude-plugin/plugin.json +9 -0
- package/dist/plugins/learner/.codex-plugin/plugin.json +39 -0
- package/dist/plugins/learner/AGENTS.md +40 -0
- package/dist/plugins/learner/CLAUDE.md +33 -0
- package/dist/plugins/learner/README.md +59 -0
- package/dist/plugins/learner/hooks/hooks.json +16 -0
- package/dist/plugins/learner/hooks/session-start +38 -0
- package/dist/plugins/learner/skills/learn/SKILL.md +412 -0
- package/dist/plugins/learner/skills/learn/analyst-prompt.md +68 -0
- package/dist/plugins/learner/skills/learn/consolidator-prompt.md +94 -0
- package/dist/plugins/learner/skills/learn/explorer-prompt.md +53 -0
- package/dist/plugins/learner/skills/learn/planner-prompt.md +87 -0
- package/dist/plugins/learner/skills/learn/promoter-prompt.md +113 -0
- package/dist/plugins/learner/skills/learn/step-worker-prompt.md +47 -0
- package/dist/plugins/learner/skills/learn/strategist-prompt.md +85 -0
- package/dist/restart-daemon.d.ts +90 -0
- package/dist/restart-daemon.js +95 -0
- package/dist/restart-daemon.js.map +1 -0
- package/dist/setup/halt-mode.d.ts +14 -0
- package/dist/setup/halt-mode.js +17 -0
- package/dist/setup/halt-mode.js.map +1 -0
- package/dist/solver-nets/prediction-operator-ux.js +43 -3
- package/dist/solver-nets/prediction-operator-ux.js.map +1 -1
- package/dist/solver-nets/registry.d.ts +1 -0
- package/dist/solver-nets/registry.js +1 -1
- package/dist/solver-nets/registry.js.map +1 -1
- package/dist/solver-types/_swe-rebench-v2-pool-cache.d.ts +58 -0
- package/dist/solver-types/_swe-rebench-v2-pool-cache.js +87 -0
- package/dist/solver-types/_swe-rebench-v2-pool-cache.js.map +1 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.d.ts +1 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.js +10 -0
- package/dist/solver-types/_swe-rebench-v2-substrate.js.map +1 -1
- package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +65 -0
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js +243 -26
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2-auto.d.ts +22 -7
- package/dist/solver-types/swe-rebench-v2-auto.js +45 -20
- package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2.d.ts +13 -2
- package/dist/solver-types/swe-rebench-v2.js +233 -94
- package/dist/solver-types/swe-rebench-v2.js.map +1 -1
- package/dist/solvernets/daemon-init.d.ts +10 -2
- package/dist/solvernets/daemon-init.js +22 -2
- package/dist/solvernets/daemon-init.js.map +1 -1
- package/dist/solvernets/launched-record-dispatcher.js +35 -7
- package/dist/solvernets/launched-record-dispatcher.js.map +1 -1
- package/dist/solvernets/store.d.ts +5 -0
- package/dist/solvernets/store.js +1 -0
- package/dist/solvernets/store.js.map +1 -1
- package/dist/store/store.d.ts +15 -0
- package/dist/store/store.js +118 -3
- package/dist/store/store.js.map +1 -1
- package/dist/tasks/sources.d.ts +18 -1
- package/dist/tasks/sources.js +33 -5
- package/dist/tasks/sources.js.map +1 -1
- package/dist/tx-retry.d.ts +151 -19
- package/dist/tx-retry.js +286 -32
- package/dist/tx-retry.js.map +1 -1
- package/dist/types/payloads/prediction-apy-v0.d.ts +5 -5
- package/dist/types/payloads/prediction-v0.d.ts +5 -5
- package/dist/types/task-document.d.ts +392 -0
- package/dist/types/task-document.js +10 -0
- package/dist/types/task-document.js.map +1 -1
- package/dist/types/task.d.ts +28 -0
- package/dist/util/extract-tx-hash.d.ts +14 -0
- package/dist/util/extract-tx-hash.js +19 -0
- package/dist/util/extract-tx-hash.js.map +1 -0
- package/dist/vendor/@jinn-network/sdk/dist/contracts.js +1 -1
- package/dist/vendor/@jinn-network/sdk/dist/solvernets/manifest-schema.d.ts +3 -0
- package/dist/vendor/@jinn-network/sdk/dist/solvernets/manifest-schema.js +1 -0
- package/package.json +29 -12
- package/dist/dashboard/assets/index-DOlzFN8a.css +0 -32
- package/dist/dashboard/assets/index-NkZ7CTAT.js +0 -140
package/dist/main.js
CHANGED
|
@@ -26,7 +26,8 @@ import { dirname, join } from 'node:path';
|
|
|
26
26
|
import { fileURLToPath } from 'node:url';
|
|
27
27
|
import { loadConfig, getConfigPathFromArgs, DEFAULT_CONFIG_PATH } from './config.js';
|
|
28
28
|
import { Store } from './store/store.js';
|
|
29
|
-
import { startApiServer } from './api/server.js';
|
|
29
|
+
import { startApiServer, isEmbeddedAgentEnabled } from './api/server.js';
|
|
30
|
+
import { setDefaultTxSubmissionLedger } from './tx-retry.js';
|
|
30
31
|
// addHarnessReadinessRoutes is wired through startApiServer's holder ref now
|
|
31
32
|
// (jinn-mono-u34i). No direct import needed.
|
|
32
33
|
import { CapturePublishUnavailableError } from './api/captures.js';
|
|
@@ -36,10 +37,11 @@ import { hashImplStateDir } from './harnesses/freeze.js';
|
|
|
36
37
|
import { readModeState } from './harnesses/mode-state.js';
|
|
37
38
|
import { attachAgentWs, updateAgentClaudePath } from './agent/agent-ws.js';
|
|
38
39
|
import { createSetupModeController } from './setup-mode.js';
|
|
40
|
+
import { requestDaemonRestart } from './restart-daemon.js';
|
|
39
41
|
import { buildEnvelope, emitEnvelope } from './errors/envelope.js';
|
|
40
42
|
import { clearBootstrapError, persistBootstrapError, } from './errors/persisted-bootstrap-error.js';
|
|
41
43
|
import { emitStructured } from './events/emitter.js';
|
|
42
|
-
import { FleetBootstrapper } from './earning/bootstrap.js';
|
|
44
|
+
import { FleetBootstrapper, recoverEvictedService as recoverEvictedServiceFn } from './earning/bootstrap.js';
|
|
43
45
|
import { DEFAULT_TESTNET_ARTIFACTS, applyChainGasOverrides, getChainConfig, loadJinnMviConfig } from './earning/contracts.js';
|
|
44
46
|
import { runLegacyAgentIdMigration } from './earning/migrate-agent-id.js';
|
|
45
47
|
import { FleetStateStore } from './earning/store.js';
|
|
@@ -48,6 +50,7 @@ import { decryptMnemonic, deriveMasterSigner, walletPrivateKeyAtIndex } from './
|
|
|
48
50
|
import { MechAdapter } from './adapters/mech/adapter.js';
|
|
49
51
|
import { ClaudeRunner } from './runner/claude.js';
|
|
50
52
|
import { Daemon } from './daemon/daemon.js';
|
|
53
|
+
import { buildJinnClaimLoopConfig, shouldWireJinnClaimL1Signer, } from './daemon/jinn-claim-loop-wiring.js';
|
|
51
54
|
import { createJinnPublicClient, createJinnWalletClient, createJinnL1PublicClient, createJinnL1WalletClient } from './earning/viem-clients.js';
|
|
52
55
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
53
56
|
import { getAddress } from 'viem';
|
|
@@ -56,6 +59,7 @@ import { joinedSolverNetsViewFromConfig } from './harnesses/engine/engine.js';
|
|
|
56
59
|
import { buildHarnesses } from './harnesses/impls/index.js';
|
|
57
60
|
import { loadExternalImpl } from './harnesses/external-impls/index.js';
|
|
58
61
|
import { CLAUDE_CODE_HARNESS, CODEX_HARNESS, HERMES_AGENT_HARNESS, harnessStateDirName } from './harnesses/names.js';
|
|
62
|
+
import { resolveContractFromSolverNetId } from './solvernets/launched-record-dispatcher.js';
|
|
59
63
|
import { HarnessReadinessRegistry } from './harnesses/readiness-registry.js';
|
|
60
64
|
import { createClients } from './adapters/mech/safe.js';
|
|
61
65
|
import { loadSolverNets } from './solver-nets/registry.js';
|
|
@@ -76,10 +80,11 @@ import { GeminiSessionParser } from './trajectory/transcript-parsers/gemini-sess
|
|
|
76
80
|
import { CursorSqliteParser } from './trajectory/transcript-parsers/cursor-sqlite.js';
|
|
77
81
|
import { buildInfo } from './build-info.js';
|
|
78
82
|
import { BASE_FEEDS } from './venues/chainlink/feeds.js';
|
|
79
|
-
import { GeneratedTaskSource, StaticConfiguredTaskSource } from './tasks/sources.js';
|
|
83
|
+
import { GeneratedTaskSource, StaticConfiguredTaskSource, filterBindableTasks } from './tasks/sources.js';
|
|
80
84
|
import { checkRpcNetwork, logRpcLocalDevToStderr, rpcNetworkFailureHint } from './preflight/rpc-network.js';
|
|
81
85
|
import { apiPortFailureMessage, checkApiPortAvailable } from './preflight/api-port.js';
|
|
82
86
|
import { openBrowser } from './cli/open-browser.js';
|
|
87
|
+
import { keepSetupUiOnBootstrapError } from './setup/halt-mode.js';
|
|
83
88
|
if (process.env['JINN_LOAD_DEV_ENV'] === '1' || process.env['NODE_ENV'] === 'development') {
|
|
84
89
|
dotenvConfig({ path: join(dirname(fileURLToPath(import.meta.url)), '..', '.env') });
|
|
85
90
|
}
|
|
@@ -132,8 +137,19 @@ const config = loadConfig(CONFIG_PATH);
|
|
|
132
137
|
if (config.network === 'mainnet' && process.env['JINN_ENABLE_MAINNET'] !== '1') {
|
|
133
138
|
console.warn('[main] Mainnet is disabled before launch; using testnet defaults.');
|
|
134
139
|
config.network = 'testnet';
|
|
135
|
-
config.rpcUrl = 'https://base-sepolia.
|
|
140
|
+
config.rpcUrl = 'https://base-sepolia-rpc.publicnode.com';
|
|
136
141
|
}
|
|
142
|
+
// Issue #326: the embedded Claude agent chat surface (right rail + onboarding
|
|
143
|
+
// "Ask Claude" panel + /api/agent/ws bridge) is hidden by default while its
|
|
144
|
+
// action-authority / plugin-scope shape is still in design. Set
|
|
145
|
+
// `JINN_ENABLE_EMBEDDED_AGENT=1` to re-enable it for development. This does
|
|
146
|
+
// NOT affect Claude-Code-as-a-solver-harness — that path is independent.
|
|
147
|
+
//
|
|
148
|
+
// Issue #367: the SPA reads this flag via the injected `window.__JINN_FEATURES__`
|
|
149
|
+
// (`resolveFeatureFlags` in api/server.ts) like every other operator-app flag.
|
|
150
|
+
// This `embeddedAgentEnabled` const is the daemon-side consumer only — it gates
|
|
151
|
+
// whether the `/api/agent/ws` bridge is mounted below.
|
|
152
|
+
const embeddedAgentEnabled = isEmbeddedAgentEnabled();
|
|
137
153
|
let activeClaudePath = config.claudePath ?? 'claude';
|
|
138
154
|
const selectClaudePath = (claudePath) => {
|
|
139
155
|
activeClaudePath = claudePath;
|
|
@@ -484,11 +500,17 @@ async function bootstrap() {
|
|
|
484
500
|
hint: 'Fund the listed address and re-run this command.',
|
|
485
501
|
exampleCli: 'jinn fund-requirements --json',
|
|
486
502
|
details: {
|
|
487
|
-
|
|
503
|
+
// jinn-mono-hjex.6: structured envelope so SPA can render the
|
|
504
|
+
// specific address + amount instead of a prose disjunction.
|
|
505
|
+
category: 'insufficient_funds',
|
|
506
|
+
step: 'awaiting_funding',
|
|
488
507
|
address: result.funding.master_address,
|
|
508
|
+
requiredWei: result.funding.eth_required,
|
|
509
|
+
haveWei: result.funding.eth_balance,
|
|
510
|
+
// Legacy aliases kept for any external consumers that read these.
|
|
511
|
+
role: 'master',
|
|
489
512
|
asset: 'native',
|
|
490
513
|
needWei: result.funding.eth_required,
|
|
491
|
-
haveWei: result.funding.eth_balance,
|
|
492
514
|
},
|
|
493
515
|
});
|
|
494
516
|
}
|
|
@@ -503,11 +525,17 @@ async function bootstrap() {
|
|
|
503
525
|
hint: 'Bootstrap failed before the fleet reached a runnable state.',
|
|
504
526
|
details: {
|
|
505
527
|
cause: result.message,
|
|
528
|
+
// jinn-mono-hjex.6: propagate structured category from the bootstrapper
|
|
529
|
+
// so the SPA can render category-specific UI (e.g. funding shortfall).
|
|
530
|
+
...(result.errorCategory !== undefined ? { category: result.errorCategory } : {}),
|
|
506
531
|
// Preserve the raw underlying error so a misclassified summary can
|
|
507
532
|
// be diagnosed without re-running with JINN_DEBUG. See jinn-mono-jz9f.
|
|
508
533
|
...(result.rawErrorMessage && result.rawErrorMessage !== result.message
|
|
509
534
|
? { rawErrorMessage: result.rawErrorMessage }
|
|
510
535
|
: {}),
|
|
536
|
+
// jinn-mono-hjex reviewer fix: propagate tx hash so the SPA can render
|
|
537
|
+
// a block-explorer link for failed on-chain revert transactions.
|
|
538
|
+
...(result.txHash != null ? { txHash: result.txHash } : {}),
|
|
511
539
|
},
|
|
512
540
|
});
|
|
513
541
|
}
|
|
@@ -592,7 +620,9 @@ class SetupBootstrapHalted extends Error {
|
|
|
592
620
|
this.name = 'SetupBootstrapHalted';
|
|
593
621
|
}
|
|
594
622
|
}
|
|
595
|
-
|
|
623
|
+
// hjex.6: gate for the halt-and-resume loop. Lives in ./setup/halt-mode.ts
|
|
624
|
+
// so it can be unit-tested without dragging main.ts's top-level side
|
|
625
|
+
// effects (password resolution, config load) into the test.
|
|
596
626
|
// ── Main ────────────────────────────────────────────────────────────────────
|
|
597
627
|
/**
|
|
598
628
|
* --json-progress: emit NDJSON progress envelopes on stdout during long
|
|
@@ -679,6 +709,7 @@ export async function main() {
|
|
|
679
709
|
// /v1/bootstrap + /v1/events + /v1/status here. The same Store instance is
|
|
680
710
|
// later passed into Daemon so we don't double-open the SQLite file.
|
|
681
711
|
const sharedStore = new Store(config.dbPath);
|
|
712
|
+
setDefaultTxSubmissionLedger(sharedStore);
|
|
682
713
|
const capturesStore = new CapturesStore(sharedStore);
|
|
683
714
|
let captureReceiver;
|
|
684
715
|
try {
|
|
@@ -759,6 +790,18 @@ export async function main() {
|
|
|
759
790
|
// builder-artifacts. Holder ref lets the routes register eagerly and
|
|
760
791
|
// start returning real data the moment main.ts assigns holder.current.
|
|
761
792
|
const discoveryApiHolder = { current: undefined };
|
|
793
|
+
// hjex.3: holder for the restake callback. Populated in running mode after
|
|
794
|
+
// bootstrap completes (when mnemonic + distributorAddress are available).
|
|
795
|
+
const restakeCallbackRef = {
|
|
796
|
+
current: undefined,
|
|
797
|
+
};
|
|
798
|
+
// hjex.6: retry signal for the bootstrap halt-and-resume loop.
|
|
799
|
+
// When a SetupBootstrapHalted is caught (fatal non-funding error or funding
|
|
800
|
+
// timeout), main() waits on this promise instead of returning, so the setup
|
|
801
|
+
// API stays alive and the operator can click Retry in the SPA.
|
|
802
|
+
// The retry endpoint resolves this promise to trigger a re-run.
|
|
803
|
+
let retryBootstrapResolve = null;
|
|
804
|
+
let retryBootstrapReject = null;
|
|
762
805
|
let setupApiServer;
|
|
763
806
|
try {
|
|
764
807
|
setupApiServer = await startApiServer({
|
|
@@ -772,11 +815,32 @@ export async function main() {
|
|
|
772
815
|
hermesPath: config.hermesPath,
|
|
773
816
|
hermesDoctorTimeoutMs: config.hermesDoctorTimeoutMs,
|
|
774
817
|
},
|
|
818
|
+
codexDoctor: {
|
|
819
|
+
codexPath: config.codexPath,
|
|
820
|
+
codexDoctorTimeoutMs: config.codexDoctorTimeoutMs,
|
|
821
|
+
},
|
|
775
822
|
admin: {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
823
|
+
// jinn-mono #289: in interactive mode (the dashboard SPA case),
|
|
824
|
+
// spawn a detached replacement before exiting so the panel reconnects
|
|
825
|
+
// to a live daemon instead of seeing a 502 + terminal prompt. In
|
|
826
|
+
// headless mode (`JINN_NO_UI=1`), exit without respawning so the
|
|
827
|
+
// supervisor / systemd / docker entrypoint decides what to do.
|
|
828
|
+
// Stop: pure exit, never respawn. The operator clicked Stop; they
|
|
829
|
+
// want the daemon down until they explicitly start it again.
|
|
830
|
+
onStopRequested: () => process.exit(0),
|
|
831
|
+
onRestartRequested: (opts) => requestDaemonRestart({
|
|
832
|
+
forceRespawn: opts.forceRespawn,
|
|
833
|
+
// jinn-mono #561: close the API + OTLP listeners before the
|
|
834
|
+
// replacement spawns, so the child binds without an
|
|
835
|
+
// EADDRINUSE race. Errors are swallowed inside
|
|
836
|
+
// requestDaemonRestart so the operator is never stranded.
|
|
837
|
+
preSpawnCleanup: async () => {
|
|
838
|
+
await setupApiServer.close().catch(() => undefined);
|
|
839
|
+
if (captureReceiver) {
|
|
840
|
+
await captureReceiver.shutdown().catch(() => undefined);
|
|
841
|
+
}
|
|
842
|
+
},
|
|
843
|
+
}),
|
|
780
844
|
},
|
|
781
845
|
harnessStatus: {
|
|
782
846
|
getStatus: async () => {
|
|
@@ -962,10 +1026,40 @@ export async function main() {
|
|
|
962
1026
|
// toggle immediately. (jinn-mono-l2zl.15.4.12)
|
|
963
1027
|
invalidatePredictionOperatorStatusCache(config);
|
|
964
1028
|
},
|
|
1029
|
+
// hjex.3: delegate to the live callback populated once running mode starts.
|
|
1030
|
+
restake: (serviceId) => {
|
|
1031
|
+
if (!restakeCallbackRef.current) {
|
|
1032
|
+
return Promise.resolve({ ok: false, error: 'restake_not_available_in_setup_mode' });
|
|
1033
|
+
}
|
|
1034
|
+
return restakeCallbackRef.current(serviceId);
|
|
1035
|
+
},
|
|
1036
|
+
// hjex.6: re-trigger the bootstrap state machine from the SPA Retry button.
|
|
1037
|
+
// Resolves the halt-and-resume promise; main() will loop back and call
|
|
1038
|
+
// bootstrap() again. Rejects if the daemon is not currently halted.
|
|
1039
|
+
retryBootstrap: () => {
|
|
1040
|
+
return new Promise((resolve, reject) => {
|
|
1041
|
+
if (!retryBootstrapResolve) {
|
|
1042
|
+
reject(new Error('daemon_not_halted'));
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const prevResolve = retryBootstrapResolve;
|
|
1046
|
+
// The resolve will unblock the main loop's await. When bootstrap
|
|
1047
|
+
// completes (success or new halt), the caller receives the result
|
|
1048
|
+
// via the /v1/bootstrap polling endpoint.
|
|
1049
|
+
prevResolve();
|
|
1050
|
+
resolve();
|
|
1051
|
+
});
|
|
1052
|
+
},
|
|
965
1053
|
},
|
|
966
1054
|
status: {
|
|
967
1055
|
earningDir: config.earningDir,
|
|
968
1056
|
rpcUrl: config.rpcUrl,
|
|
1057
|
+
// tJINN identity comes from the bundled JINN MVI L1 artifact
|
|
1058
|
+
// (`JINN_MVI_CONFIG`) — one source of truth. The Sepolia RPC endpoint
|
|
1059
|
+
// is read from `config.ethereumRpcUrl` via the threaded `config`.
|
|
1060
|
+
tjinnTokenAddress: JINN_MVI_CONFIG.jinn,
|
|
1061
|
+
tjinnChainId: JINN_MVI_CONFIG.l1ChainId,
|
|
1062
|
+
tjinnDistributorAddress: JINN_MVI_CONFIG.distributor,
|
|
969
1063
|
network: config.network,
|
|
970
1064
|
pollIntervalMs: config.pollIntervalMs,
|
|
971
1065
|
masterEthDailyEstimateWei: config.masterEthDailyEstimateWei,
|
|
@@ -1114,30 +1208,41 @@ export async function main() {
|
|
|
1114
1208
|
// can attach to a long-lived embedded `claude` subprocess. The embedded
|
|
1115
1209
|
// session reads MCP config we materialise to disk so it can reach the
|
|
1116
1210
|
// operator MCP server (`jinn mcp`) for tool calls.
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1211
|
+
//
|
|
1212
|
+
// Issue #326: the embedded agent chat surface is hidden by default. The WS
|
|
1213
|
+
// bridge mounts only when `JINN_ENABLE_EMBEDDED_AGENT=1` so the dev-time
|
|
1214
|
+
// path stays end-to-end; with the flag off there is no /api/agent/ws route
|
|
1215
|
+
// and the SPA never renders the chat panel. Claude-Code-as-solver-harness
|
|
1216
|
+
// is independent of this bridge and unaffected.
|
|
1217
|
+
if (embeddedAgentEnabled) {
|
|
1218
|
+
const operatorMcpConfigPath = join(homedir(), '.jinn-client', 'operator-mcp-config.json');
|
|
1219
|
+
try {
|
|
1220
|
+
mkdirSync(dirname(operatorMcpConfigPath), { recursive: true });
|
|
1221
|
+
writeFileSyncMain(operatorMcpConfigPath, JSON.stringify({
|
|
1222
|
+
mcpServers: {
|
|
1223
|
+
'jinn-operator': {
|
|
1224
|
+
command: 'jinn',
|
|
1225
|
+
args: ['mcp'],
|
|
1226
|
+
},
|
|
1125
1227
|
},
|
|
1126
|
-
},
|
|
1127
|
-
}
|
|
1228
|
+
}, null, 2));
|
|
1229
|
+
}
|
|
1230
|
+
catch (err) {
|
|
1231
|
+
console.warn(`[main] Failed to write operator MCP config at ${operatorMcpConfigPath}: ` +
|
|
1232
|
+
(err instanceof Error ? err.message : String(err)));
|
|
1233
|
+
}
|
|
1234
|
+
attachAgentWs({
|
|
1235
|
+
httpServer: setupApiServer.server,
|
|
1236
|
+
uiToken,
|
|
1237
|
+
claudePath: activeClaudePath,
|
|
1238
|
+
cwd: process.cwd(),
|
|
1239
|
+
mcpConfigPath: operatorMcpConfigPath,
|
|
1240
|
+
});
|
|
1241
|
+
console.log(`[main] Agent WS bridge mounted at ws://127.0.0.1:${setupApiServer.port}/api/agent/ws`);
|
|
1128
1242
|
}
|
|
1129
|
-
|
|
1130
|
-
console.
|
|
1131
|
-
(err instanceof Error ? err.message : String(err)));
|
|
1243
|
+
else {
|
|
1244
|
+
console.log('[main] Embedded agent surface disabled (set JINN_ENABLE_EMBEDDED_AGENT=1 to enable).');
|
|
1132
1245
|
}
|
|
1133
|
-
attachAgentWs({
|
|
1134
|
-
httpServer: setupApiServer.server,
|
|
1135
|
-
uiToken,
|
|
1136
|
-
claudePath: activeClaudePath,
|
|
1137
|
-
cwd: process.cwd(),
|
|
1138
|
-
mcpConfigPath: operatorMcpConfigPath,
|
|
1139
|
-
});
|
|
1140
|
-
console.log(`[main] Agent WS bridge mounted at ws://127.0.0.1:${setupApiServer.port}/api/agent/ws`);
|
|
1141
1246
|
// ── Init-if-missing ──────────────────────────────────────────────────────
|
|
1142
1247
|
// If the keystore is missing but we have a password, run `jinn init` now so
|
|
1143
1248
|
// bootstrap has something to decrypt. Idempotent: init is a no-op when the
|
|
@@ -1178,30 +1283,96 @@ export async function main() {
|
|
|
1178
1283
|
// keystore is on disk and we're transitioning into bootstrap.
|
|
1179
1284
|
setupController.refresh({ keystoreExists: true, allComplete: false });
|
|
1180
1285
|
}
|
|
1286
|
+
// hjex.6: halt-and-resume loop for bootstrap retries.
|
|
1287
|
+
// When failBootstrap() throws SetupBootstrapHalted, we wait for the operator
|
|
1288
|
+
// to click Retry in the SPA (which resolves retryBootstrapResolve) rather
|
|
1289
|
+
// than returning and exiting. On each retry, we loop back and call bootstrap()
|
|
1290
|
+
// again. bootstrap() is idempotent — completed steps are no-ops.
|
|
1181
1291
|
let bootstrapResult;
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1292
|
+
// eslint-disable-next-line no-constant-condition
|
|
1293
|
+
while (true) {
|
|
1294
|
+
try {
|
|
1295
|
+
bootstrapResult = await bootstrap();
|
|
1296
|
+
break; // success — exit the retry loop
|
|
1297
|
+
}
|
|
1298
|
+
catch (err) {
|
|
1299
|
+
if (err instanceof SetupBootstrapHalted) {
|
|
1300
|
+
// Install the retry signal so the endpoint can unblock us.
|
|
1301
|
+
const retrySignal = new Promise((resolve, reject) => {
|
|
1302
|
+
retryBootstrapResolve = resolve;
|
|
1303
|
+
retryBootstrapReject = reject;
|
|
1304
|
+
});
|
|
1305
|
+
console.log('[main] Bootstrap halted. Waiting for retry signal from the dashboard...');
|
|
1306
|
+
// hjex.6: Auto-resume funding poller.
|
|
1307
|
+
// When the halt is a funding shortfall, poll the master EOA balance
|
|
1308
|
+
// every JINN_FUNDING_POLL_INTERVAL_MS (default 15s). When the balance
|
|
1309
|
+
// meets or exceeds the required amount, auto-signal the retry loop.
|
|
1310
|
+
// Only runs while the halt signal is pending; stops on any signal.
|
|
1311
|
+
let fundingPollHandle = null;
|
|
1312
|
+
const isHaltedOnFunding = err.envelope.code === 'funding_required';
|
|
1313
|
+
const haltDetails = err.envelope.details;
|
|
1314
|
+
const haltAddress = typeof haltDetails?.['address'] === 'string'
|
|
1315
|
+
? haltDetails['address']
|
|
1316
|
+
: null;
|
|
1317
|
+
const haltRequired = typeof haltDetails?.['requiredWei'] === 'string'
|
|
1318
|
+
? BigInt(haltDetails['requiredWei'])
|
|
1319
|
+
: typeof haltDetails?.['needWei'] === 'string'
|
|
1320
|
+
? BigInt(haltDetails['needWei'])
|
|
1321
|
+
: null;
|
|
1322
|
+
const fundingPollIntervalMs = (() => {
|
|
1323
|
+
const raw = process.env['JINN_FUNDING_POLL_INTERVAL_MS'];
|
|
1324
|
+
if (!raw)
|
|
1325
|
+
return 15_000;
|
|
1326
|
+
const n = Number.parseInt(raw, 10);
|
|
1327
|
+
return Number.isFinite(n) && n > 0 ? n : 15_000;
|
|
1328
|
+
})();
|
|
1329
|
+
if (isHaltedOnFunding && haltAddress && haltRequired !== null) {
|
|
1330
|
+
const publicClient = createJinnPublicClient(config.rpcUrl, NETWORK_CHAIN);
|
|
1331
|
+
const schedulePoll = () => {
|
|
1332
|
+
fundingPollHandle = setTimeout(async () => {
|
|
1333
|
+
// Guard: if the signal was already fired, stop polling.
|
|
1334
|
+
if (!retryBootstrapResolve)
|
|
1335
|
+
return;
|
|
1336
|
+
try {
|
|
1337
|
+
const balance = await publicClient.getBalance({ address: haltAddress });
|
|
1338
|
+
if (balance >= haltRequired) {
|
|
1339
|
+
console.log(`[main] Funding shortfall cleared (have ${balance}, required ${haltRequired}). ` +
|
|
1340
|
+
`Auto-resuming bootstrap...`);
|
|
1341
|
+
retryBootstrapResolve?.();
|
|
1342
|
+
return; // don't schedule the next poll
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
catch (pollErr) {
|
|
1346
|
+
// Balance read failed — not fatal, just skip this tick.
|
|
1347
|
+
const msg = pollErr instanceof Error ? pollErr.message : String(pollErr);
|
|
1348
|
+
console.log(`[main] Funding poller balance read failed (will retry): ${msg}`);
|
|
1349
|
+
}
|
|
1350
|
+
schedulePoll(); // reschedule
|
|
1351
|
+
}, fundingPollIntervalMs);
|
|
1352
|
+
};
|
|
1353
|
+
schedulePoll();
|
|
1354
|
+
}
|
|
1355
|
+
try {
|
|
1356
|
+
await retrySignal;
|
|
1357
|
+
}
|
|
1358
|
+
finally {
|
|
1359
|
+
retryBootstrapResolve = null;
|
|
1360
|
+
retryBootstrapReject = null;
|
|
1361
|
+
if (fundingPollHandle !== null) {
|
|
1362
|
+
clearTimeout(fundingPollHandle);
|
|
1363
|
+
fundingPollHandle = null;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
console.log('[main] Retry triggered — re-running bootstrap...');
|
|
1367
|
+
continue; // loop back to the bootstrap() call
|
|
1368
|
+
}
|
|
1369
|
+
// If bootstrap throws an unexpected error (vs. SetupBootstrapHalted),
|
|
1370
|
+
// tear down the API we just started so we don't leave a dangling listener.
|
|
1371
|
+
await setupApiServer.close().catch(() => undefined);
|
|
1372
|
+
await closeCaptureReceiver();
|
|
1373
|
+
sharedStore.close();
|
|
1374
|
+
throw err;
|
|
1198
1375
|
}
|
|
1199
|
-
// If bootstrap throws (vs. emitEnvelope-exits), tear down the API we
|
|
1200
|
-
// just started so we don't leave a dangling listener on the port.
|
|
1201
|
-
await setupApiServer.close().catch(() => undefined);
|
|
1202
|
-
await closeCaptureReceiver();
|
|
1203
|
-
sharedStore.close();
|
|
1204
|
-
throw err;
|
|
1205
1376
|
}
|
|
1206
1377
|
// Bootstrap completed — flip the controller into 'running' so any waiters
|
|
1207
1378
|
// (future loops gated on this) unblock.
|
|
@@ -1257,6 +1428,33 @@ export async function main() {
|
|
|
1257
1428
|
const publicClient = createJinnPublicClient(config.rpcUrl, NETWORK_CHAIN);
|
|
1258
1429
|
publicClientForLauncher = publicClient;
|
|
1259
1430
|
const masterWallet = createJinnWalletClient(config.rpcUrl, NETWORK_CHAIN, masterAccount);
|
|
1431
|
+
// hjex.3: populate the restake callback now that mnemonic is available.
|
|
1432
|
+
if (config.stakingMode === 'standard' && CHAIN_CONFIG.distributorAddress) {
|
|
1433
|
+
const fleetStore = earningStore;
|
|
1434
|
+
restakeCallbackRef.current = async (serviceId) => {
|
|
1435
|
+
try {
|
|
1436
|
+
const state = await fleetStore.load(NETWORK_CHAIN);
|
|
1437
|
+
const svc = state.services.find(s => s.service_id === serviceId);
|
|
1438
|
+
if (!svc)
|
|
1439
|
+
return { ok: false, error: `service_not_found:${serviceId}` };
|
|
1440
|
+
if (!svc.staking_address)
|
|
1441
|
+
return { ok: false, error: 'staking_address_missing' };
|
|
1442
|
+
await recoverEvictedServiceFn({
|
|
1443
|
+
serviceDisplayIndex: Math.max(0, svc.index - 1),
|
|
1444
|
+
serviceId,
|
|
1445
|
+
stakingAddress: svc.staking_address,
|
|
1446
|
+
distributorAddress: CHAIN_CONFIG.distributorAddress,
|
|
1447
|
+
rpcUrl: config.rpcUrl,
|
|
1448
|
+
chain: NETWORK_CHAIN,
|
|
1449
|
+
mnemonic: mnemonicForMaster,
|
|
1450
|
+
});
|
|
1451
|
+
return { ok: true };
|
|
1452
|
+
}
|
|
1453
|
+
catch (err) {
|
|
1454
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1260
1458
|
const evictionRecovery = config.stakingMode === 'standard' &&
|
|
1261
1459
|
serviceId !== null &&
|
|
1262
1460
|
stakingAddress &&
|
|
@@ -1360,19 +1558,45 @@ export async function main() {
|
|
|
1360
1558
|
// ── L1 (Sepolia / Ethereum mainnet) clients for cross-chain JINN claim loop ──
|
|
1361
1559
|
// Uses the agent EOA because MockMessenger.owner is the agent on testnet.
|
|
1362
1560
|
// Same key as L2; only the chain differs.
|
|
1363
|
-
const
|
|
1561
|
+
const shouldWireJinnClaimL1 = shouldWireJinnClaimL1Signer({
|
|
1562
|
+
enabled: config.jinnClaimLoopEnabled,
|
|
1563
|
+
intervalMs: config.jinnClaimLoopIntervalMs,
|
|
1564
|
+
submissionMode: config.jinnClaimSubmissionMode,
|
|
1565
|
+
distributorAddress: JINN_MVI_CONFIG.distributor,
|
|
1566
|
+
ethereumRpcUrl: config.ethereumRpcUrl,
|
|
1567
|
+
});
|
|
1568
|
+
const l1ClientsForJinnClaim = shouldWireJinnClaimL1 && config.ethereumRpcUrl
|
|
1364
1569
|
? {
|
|
1365
1570
|
public: createJinnL1PublicClient(config.ethereumRpcUrl, config.jinnL1Network),
|
|
1366
1571
|
wallet: createJinnL1WalletClient(config.ethereumRpcUrl, config.jinnL1Network, privateKeyToAccount(agentPrivateKey)),
|
|
1367
1572
|
}
|
|
1368
1573
|
: undefined;
|
|
1369
|
-
|
|
1370
|
-
|
|
1574
|
+
const jinnClaimLoopConfig = buildJinnClaimLoopConfig({
|
|
1575
|
+
enabled: config.jinnClaimLoopEnabled,
|
|
1576
|
+
intervalMs: config.jinnClaimLoopIntervalMs,
|
|
1577
|
+
submissionMode: config.jinnClaimSubmissionMode,
|
|
1578
|
+
messengerMode: JINN_CLAIM_MESSENGER_MODE,
|
|
1579
|
+
mvi: JINN_MVI_CONFIG,
|
|
1580
|
+
l2Client: agentClients.publicClient,
|
|
1581
|
+
l2ProofClient,
|
|
1582
|
+
l2Wallet: agentClients.walletClient,
|
|
1583
|
+
l1Clients: l1ClientsForJinnClaim,
|
|
1584
|
+
store: earningStore,
|
|
1585
|
+
chain: NETWORK_CHAIN,
|
|
1586
|
+
optimismPortalAddress,
|
|
1587
|
+
disputeGameFactoryAddress,
|
|
1588
|
+
});
|
|
1589
|
+
if (jinnClaimLoopConfig) {
|
|
1590
|
+
console.log(`[main] JinnClaimLoop: enabled (submission=${config.jinnClaimSubmissionMode}, ` +
|
|
1591
|
+
`mode=${JINN_CLAIM_MESSENGER_MODE}, ` +
|
|
1371
1592
|
`interval=${config.jinnClaimLoopIntervalMs}ms, distributor=${JINN_MVI_CONFIG.distributor}, ` +
|
|
1372
1593
|
`emitter=${JINN_MVI_CONFIG.claimEmitter})`);
|
|
1373
1594
|
}
|
|
1595
|
+
else if (!config.jinnClaimLoopEnabled) {
|
|
1596
|
+
console.log('[main] JinnClaimLoop: disabled (jinnClaimLoopEnabled=false)');
|
|
1597
|
+
}
|
|
1374
1598
|
else {
|
|
1375
|
-
console.log(`[main] JinnClaimLoop: disabled (
|
|
1599
|
+
console.log(`[main] JinnClaimLoop: disabled (missing claim-loop artifacts, interval disabled, or L1 submit wiring)`);
|
|
1376
1600
|
}
|
|
1377
1601
|
// ── Harness registry ─────────────────────────────────────────────────────────
|
|
1378
1602
|
const solverNetRegistry = await loadSolverNets(config);
|
|
@@ -1464,6 +1688,9 @@ export async function main() {
|
|
|
1464
1688
|
hermesPath: config.hermesPath,
|
|
1465
1689
|
hermesModel: config.hermesModel,
|
|
1466
1690
|
hermesProvider: config.hermesProvider,
|
|
1691
|
+
hermesDoctorTimeoutMs: config.hermesDoctorTimeoutMs,
|
|
1692
|
+
codexPath: config.codexPath,
|
|
1693
|
+
codexDoctorTimeoutMs: config.codexDoctorTimeoutMs,
|
|
1467
1694
|
})) {
|
|
1468
1695
|
implRegistry.register(impl);
|
|
1469
1696
|
}
|
|
@@ -1733,11 +1960,19 @@ export async function main() {
|
|
|
1733
1960
|
if (!safeAddressForLauncher) {
|
|
1734
1961
|
throw new Error('[main] safeAddressForLauncher missing at SolverNet endpoints registration');
|
|
1735
1962
|
}
|
|
1963
|
+
const getGeneratorState = (solverNetId) => {
|
|
1964
|
+
const entry = pendingGeneratorsRef.current.find((g) => g.recordRef.current.solverNetId === solverNetId);
|
|
1965
|
+
const resolved = resolveContractFromSolverNetId(entry?.recordRef.current.solverNetId ?? solverNetId);
|
|
1966
|
+
if (!resolved)
|
|
1967
|
+
return undefined;
|
|
1968
|
+
return launchedGeneratorStateBySolverType.get(resolved.solverType)?.();
|
|
1969
|
+
};
|
|
1736
1970
|
solverNetEndpointsDepsHolder.current = {
|
|
1737
1971
|
store: solverNetStore,
|
|
1738
1972
|
launch: {
|
|
1739
1973
|
launchAction,
|
|
1740
1974
|
lifecycleTransition,
|
|
1975
|
+
getGeneratorState,
|
|
1741
1976
|
pendingGenerators: pendingGeneratorsRef,
|
|
1742
1977
|
signer: launcherSigner,
|
|
1743
1978
|
network: 'base-sepolia',
|
|
@@ -1812,9 +2047,23 @@ export async function main() {
|
|
|
1812
2047
|
if (config.network === 'mainnet' && !autoTasksDisabled && BASE_FEEDS['ETH / USD']) {
|
|
1813
2048
|
// Mainnet auto-task opt-in only; default is OFF. Reserved for a future flag.
|
|
1814
2049
|
}
|
|
2050
|
+
// filterBindableTasks (issue #415): drop config-level tasks[] entries without
|
|
2051
|
+
// solverNetManifestCid before they enter the creator loop. Such entries would
|
|
2052
|
+
// throw a PermanentError on every attempt and retry every 30 min indefinitely.
|
|
2053
|
+
const bindableConfigTasks = filterBindableTasks(config.tasks);
|
|
1815
2054
|
const taskSources = [
|
|
1816
|
-
new StaticConfiguredTaskSource(
|
|
1817
|
-
...launchedRecordGenerators.map(({ solverType, generator }, idx) => new GeneratedTaskSource(`launched:${solverType}:${idx}`, generator
|
|
2055
|
+
new StaticConfiguredTaskSource(bindableConfigTasks),
|
|
2056
|
+
...launchedRecordGenerators.map(({ solverType, generator }, idx) => new GeneratedTaskSource(`launched:${solverType}:${idx}`, generator, {
|
|
2057
|
+
bucketKeyForTask: (task) => {
|
|
2058
|
+
if (task.solverType !== 'swe-rebench-v2.v1')
|
|
2059
|
+
return undefined;
|
|
2060
|
+
const instanceId = task.spec?.['instance_id'];
|
|
2061
|
+
const postedCount = task.eligibility?.['posted_count_after_record'];
|
|
2062
|
+
if (typeof instanceId !== 'string' || typeof postedCount !== 'number')
|
|
2063
|
+
return undefined;
|
|
2064
|
+
return `swe-rebench-v2:${instanceId}:${postedCount}`;
|
|
2065
|
+
},
|
|
2066
|
+
})),
|
|
1818
2067
|
];
|
|
1819
2068
|
// ── Corpus (daemon-side, jinn-mono-vy37.1.6) ─────────────────────────────
|
|
1820
2069
|
//
|
|
@@ -1866,6 +2115,12 @@ export async function main() {
|
|
|
1866
2115
|
status: {
|
|
1867
2116
|
earningDir: config.earningDir,
|
|
1868
2117
|
rpcUrl: config.rpcUrl,
|
|
2118
|
+
// tJINN identity comes from the bundled JINN MVI L1 artifact
|
|
2119
|
+
// (`JINN_MVI_CONFIG`) — one source of truth. The Sepolia RPC endpoint
|
|
2120
|
+
// is read from `config.ethereumRpcUrl` via the threaded `config`.
|
|
2121
|
+
tjinnTokenAddress: JINN_MVI_CONFIG.jinn,
|
|
2122
|
+
tjinnChainId: JINN_MVI_CONFIG.l1ChainId,
|
|
2123
|
+
tjinnDistributorAddress: JINN_MVI_CONFIG.distributor,
|
|
1869
2124
|
network: config.network,
|
|
1870
2125
|
pollIntervalMs: config.pollIntervalMs,
|
|
1871
2126
|
masterEthDailyEstimateWei: config.masterEthDailyEstimateWei,
|
|
@@ -1888,28 +2143,7 @@ export async function main() {
|
|
|
1888
2143
|
distributorAddress: CHAIN_CONFIG.distributorAddress,
|
|
1889
2144
|
}
|
|
1890
2145
|
: undefined,
|
|
1891
|
-
jinnClaim:
|
|
1892
|
-
JINN_MVI_CONFIG.claimEmitter &&
|
|
1893
|
-
JINN_MVI_CONFIG.messenger &&
|
|
1894
|
-
JINN_MVI_CONFIG.distributor &&
|
|
1895
|
-
config.jinnClaimLoopIntervalMs > 0
|
|
1896
|
-
? {
|
|
1897
|
-
intervalMs: config.jinnClaimLoopIntervalMs,
|
|
1898
|
-
l2Client: agentClients.publicClient,
|
|
1899
|
-
l2ProofClient,
|
|
1900
|
-
l2Wallet: agentClients.walletClient,
|
|
1901
|
-
l1Client: l1ClientsForJinnClaim.public,
|
|
1902
|
-
l1Wallet: l1ClientsForJinnClaim.wallet,
|
|
1903
|
-
store: earningStore,
|
|
1904
|
-
chain: NETWORK_CHAIN,
|
|
1905
|
-
claimEmitterAddress: JINN_MVI_CONFIG.claimEmitter,
|
|
1906
|
-
distributorAddress: JINN_MVI_CONFIG.distributor,
|
|
1907
|
-
messengerAddress: JINN_MVI_CONFIG.messenger,
|
|
1908
|
-
messengerMode: JINN_CLAIM_MESSENGER_MODE,
|
|
1909
|
-
optimismPortalAddress,
|
|
1910
|
-
disputeGameFactoryAddress,
|
|
1911
|
-
}
|
|
1912
|
-
: undefined,
|
|
2146
|
+
jinnClaim: jinnClaimLoopConfig,
|
|
1913
2147
|
restorationEngine: {
|
|
1914
2148
|
paths: {
|
|
1915
2149
|
workingDirRoot: config.engine.workingDirRoot,
|
|
@@ -1954,6 +2188,61 @@ export async function main() {
|
|
|
1954
2188
|
safeTopupTarget: CHAIN_CONFIG.minSafeEth,
|
|
1955
2189
|
}
|
|
1956
2190
|
: undefined,
|
|
2191
|
+
// Eviction-check loop — only in standard staking mode (requires distributorAddress).
|
|
2192
|
+
// Running mode only: setup-halted daemons must not try to restake services that
|
|
2193
|
+
// haven't been staked yet (hjex.3).
|
|
2194
|
+
evictionCheck: config.evictionCheckIntervalMs > 0 &&
|
|
2195
|
+
config.stakingMode === 'standard' &&
|
|
2196
|
+
CHAIN_CONFIG.distributorAddress
|
|
2197
|
+
? {
|
|
2198
|
+
intervalMs: config.evictionCheckIntervalMs,
|
|
2199
|
+
store: earningStore,
|
|
2200
|
+
chain: NETWORK_CHAIN,
|
|
2201
|
+
readContract: (opts) => publicClient.readContract(opts),
|
|
2202
|
+
recoverEvictedService: async (svc) => {
|
|
2203
|
+
if (!svc.service_id || !svc.staking_address)
|
|
2204
|
+
return;
|
|
2205
|
+
await recoverEvictedServiceFn({
|
|
2206
|
+
serviceDisplayIndex: Math.max(0, svc.index - 1),
|
|
2207
|
+
serviceId: svc.service_id,
|
|
2208
|
+
stakingAddress: svc.staking_address,
|
|
2209
|
+
distributorAddress: CHAIN_CONFIG.distributorAddress,
|
|
2210
|
+
rpcUrl: config.rpcUrl,
|
|
2211
|
+
chain: NETWORK_CHAIN,
|
|
2212
|
+
mnemonic: mnemonicForMaster,
|
|
2213
|
+
});
|
|
2214
|
+
},
|
|
2215
|
+
}
|
|
2216
|
+
: undefined,
|
|
2217
|
+
// Checkpoint loop — proactively advances `tsCheckpoint` on each staked
|
|
2218
|
+
// proxy so the activity-rate window stays narrow (issue #505).
|
|
2219
|
+
// `checkpoint()` is permissionless; master EOA pays gas. No-op for
|
|
2220
|
+
// non-standard staking modes.
|
|
2221
|
+
checkpoint: config.checkpointIntervalMs > 0 && config.stakingMode === 'standard'
|
|
2222
|
+
? {
|
|
2223
|
+
intervalMs: config.checkpointIntervalMs,
|
|
2224
|
+
store: earningStore,
|
|
2225
|
+
chain: NETWORK_CHAIN,
|
|
2226
|
+
writeCheckpoint: async ({ stakingProxy }) => {
|
|
2227
|
+
const txHash = await masterWallet.writeContract({
|
|
2228
|
+
address: stakingProxy,
|
|
2229
|
+
abi: [
|
|
2230
|
+
{
|
|
2231
|
+
type: 'function',
|
|
2232
|
+
name: 'checkpoint',
|
|
2233
|
+
stateMutability: 'nonpayable',
|
|
2234
|
+
inputs: [],
|
|
2235
|
+
outputs: [],
|
|
2236
|
+
},
|
|
2237
|
+
],
|
|
2238
|
+
functionName: 'checkpoint',
|
|
2239
|
+
account: masterAccount,
|
|
2240
|
+
chain: null,
|
|
2241
|
+
});
|
|
2242
|
+
return { txHash };
|
|
2243
|
+
},
|
|
2244
|
+
}
|
|
2245
|
+
: undefined,
|
|
1957
2246
|
});
|
|
1958
2247
|
// Write pidfile so `jinn stop` can find us.
|
|
1959
2248
|
const pidPath = join(config.earningDir, 'daemon.pid');
|