@cogcoin/client 0.5.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +80 -25
  2. package/dist/app-paths.d.ts +5 -6
  3. package/dist/app-paths.js +8 -16
  4. package/dist/art/balance.txt +10 -0
  5. package/dist/art/welcome.txt +16 -0
  6. package/dist/bitcoind/bootstrap/controller.d.ts +1 -0
  7. package/dist/bitcoind/bootstrap/controller.js +53 -1
  8. package/dist/bitcoind/client/follow-block-times.d.ts +1 -0
  9. package/dist/bitcoind/client/follow-block-times.js +1 -1
  10. package/dist/bitcoind/client/internal-types.d.ts +7 -3
  11. package/dist/bitcoind/client/managed-client.d.ts +4 -2
  12. package/dist/bitcoind/client/managed-client.js +14 -0
  13. package/dist/bitcoind/client/sync-engine.js +72 -11
  14. package/dist/bitcoind/hash-order.d.ts +4 -0
  15. package/dist/bitcoind/hash-order.js +13 -0
  16. package/dist/bitcoind/indexer-daemon-main.js +11 -3
  17. package/dist/bitcoind/normalize.js +3 -2
  18. package/dist/bitcoind/processing-start-height.d.ts +5 -0
  19. package/dist/bitcoind/processing-start-height.js +7 -0
  20. package/dist/bitcoind/progress/constants.d.ts +4 -0
  21. package/dist/bitcoind/progress/constants.js +4 -0
  22. package/dist/bitcoind/progress/controller.d.ts +2 -1
  23. package/dist/bitcoind/progress/controller.js +3 -3
  24. package/dist/bitcoind/progress/follow-scene.d.ts +6 -2
  25. package/dist/bitcoind/progress/follow-scene.js +29 -6
  26. package/dist/bitcoind/progress/formatting.d.ts +1 -0
  27. package/dist/bitcoind/progress/formatting.js +6 -0
  28. package/dist/bitcoind/progress/train-scene.js +37 -18
  29. package/dist/bitcoind/progress/tty-renderer.d.ts +6 -1
  30. package/dist/bitcoind/progress/tty-renderer.js +8 -4
  31. package/dist/bitcoind/rpc.d.ts +2 -1
  32. package/dist/bitcoind/rpc.js +3 -0
  33. package/dist/bitcoind/types.d.ts +16 -0
  34. package/dist/bytes.d.ts +1 -0
  35. package/dist/bytes.js +3 -0
  36. package/dist/cli/art.d.ts +2 -0
  37. package/dist/cli/art.js +37 -0
  38. package/dist/cli/commands/client-admin.d.ts +2 -0
  39. package/dist/cli/commands/client-admin.js +91 -0
  40. package/dist/cli/commands/follow.js +0 -2
  41. package/dist/cli/commands/mining-admin.js +6 -47
  42. package/dist/cli/commands/mining-read.js +11 -50
  43. package/dist/cli/commands/mining-runtime.js +38 -3
  44. package/dist/cli/commands/service-runtime.js +0 -2
  45. package/dist/cli/commands/status.js +8 -2
  46. package/dist/cli/commands/sync.js +51 -4
  47. package/dist/cli/commands/wallet-admin.js +142 -136
  48. package/dist/cli/commands/wallet-mutation.js +91 -79
  49. package/dist/cli/commands/wallet-read.js +15 -18
  50. package/dist/cli/context.js +4 -14
  51. package/dist/cli/mining-format.d.ts +0 -1
  52. package/dist/cli/mining-format.js +5 -37
  53. package/dist/cli/mining-json.d.ts +0 -18
  54. package/dist/cli/mining-json.js +0 -35
  55. package/dist/cli/mutation-command-groups.d.ts +1 -2
  56. package/dist/cli/mutation-command-groups.js +0 -5
  57. package/dist/cli/mutation-json.d.ts +24 -145
  58. package/dist/cli/mutation-json.js +30 -136
  59. package/dist/cli/mutation-resolved-json.d.ts +0 -7
  60. package/dist/cli/mutation-resolved-json.js +4 -10
  61. package/dist/cli/mutation-success.d.ts +2 -0
  62. package/dist/cli/mutation-success.js +11 -1
  63. package/dist/cli/mutation-text-format.js +1 -3
  64. package/dist/cli/output.d.ts +1 -1
  65. package/dist/cli/output.js +254 -231
  66. package/dist/cli/parse.d.ts +1 -1
  67. package/dist/cli/parse.js +93 -122
  68. package/dist/cli/preview-json.d.ts +17 -120
  69. package/dist/cli/preview-json.js +14 -97
  70. package/dist/cli/prompt.js +8 -13
  71. package/dist/cli/read-json.d.ts +15 -37
  72. package/dist/cli/read-json.js +44 -140
  73. package/dist/cli/runner.js +10 -13
  74. package/dist/cli/types.d.ts +8 -17
  75. package/dist/cli/types.js +0 -2
  76. package/dist/cli/wallet-format.d.ts +1 -0
  77. package/dist/cli/wallet-format.js +205 -144
  78. package/dist/cli/workflow-hints.d.ts +3 -3
  79. package/dist/cli/workflow-hints.js +11 -8
  80. package/dist/client/default-client.d.ts +3 -1
  81. package/dist/client/default-client.js +45 -2
  82. package/dist/client/factory.js +1 -1
  83. package/dist/client/initialization.js +23 -0
  84. package/dist/client/persistence.js +5 -5
  85. package/dist/client/store-adapter.js +1 -0
  86. package/dist/sqlite/checkpoints.d.ts +1 -0
  87. package/dist/sqlite/checkpoints.js +7 -0
  88. package/dist/sqlite/store.js +14 -1
  89. package/dist/types.d.ts +1 -0
  90. package/dist/wallet/coin-control.d.ts +41 -11
  91. package/dist/wallet/coin-control.js +100 -357
  92. package/dist/wallet/descriptor-normalization.d.ts +1 -3
  93. package/dist/wallet/descriptor-normalization.js +0 -16
  94. package/dist/wallet/lifecycle.d.ts +7 -99
  95. package/dist/wallet/lifecycle.js +513 -968
  96. package/dist/wallet/managed-core-wallet.d.ts +13 -0
  97. package/dist/wallet/managed-core-wallet.js +20 -0
  98. package/dist/wallet/mining/constants.d.ts +5 -12
  99. package/dist/wallet/mining/constants.js +5 -12
  100. package/dist/wallet/mining/control.d.ts +1 -13
  101. package/dist/wallet/mining/control.js +45 -349
  102. package/dist/wallet/mining/index.d.ts +3 -4
  103. package/dist/wallet/mining/index.js +1 -2
  104. package/dist/wallet/mining/runner.d.ts +179 -6
  105. package/dist/wallet/mining/runner.js +891 -501
  106. package/dist/wallet/mining/runtime-artifacts.js +23 -3
  107. package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
  108. package/dist/wallet/mining/sentence-protocol.js +123 -0
  109. package/dist/wallet/mining/sentences.d.ts +4 -8
  110. package/dist/wallet/mining/sentences.js +3 -52
  111. package/dist/wallet/mining/state.d.ts +11 -6
  112. package/dist/wallet/mining/state.js +7 -6
  113. package/dist/wallet/mining/types.d.ts +2 -30
  114. package/dist/wallet/mining/visualizer.d.ts +31 -3
  115. package/dist/wallet/mining/visualizer.js +135 -13
  116. package/dist/wallet/read/context.d.ts +0 -2
  117. package/dist/wallet/read/context.js +119 -140
  118. package/dist/wallet/read/filter.js +2 -11
  119. package/dist/wallet/read/index.d.ts +1 -1
  120. package/dist/wallet/read/project.js +24 -77
  121. package/dist/wallet/read/types.d.ts +10 -25
  122. package/dist/wallet/reset.d.ts +0 -1
  123. package/dist/wallet/reset.js +60 -138
  124. package/dist/wallet/root-resolution.d.ts +1 -5
  125. package/dist/wallet/root-resolution.js +0 -18
  126. package/dist/wallet/runtime.d.ts +0 -6
  127. package/dist/wallet/runtime.js +0 -8
  128. package/dist/wallet/state/client-password-agent.js +208 -0
  129. package/dist/wallet/state/client-password.d.ts +65 -0
  130. package/dist/wallet/state/client-password.js +952 -0
  131. package/dist/wallet/state/crypto.d.ts +1 -20
  132. package/dist/wallet/state/crypto.js +0 -63
  133. package/dist/wallet/state/provider.d.ts +23 -11
  134. package/dist/wallet/state/provider.js +248 -290
  135. package/dist/wallet/state/storage.d.ts +2 -2
  136. package/dist/wallet/state/storage.js +48 -16
  137. package/dist/wallet/tx/anchor.d.ts +3 -28
  138. package/dist/wallet/tx/anchor.js +349 -1240
  139. package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
  140. package/dist/wallet/tx/bitcoin-transfer.js +200 -0
  141. package/dist/wallet/tx/cog.d.ts +5 -1
  142. package/dist/wallet/tx/cog.js +149 -185
  143. package/dist/wallet/tx/common.d.ts +74 -10
  144. package/dist/wallet/tx/common.js +315 -138
  145. package/dist/wallet/tx/domain-admin.d.ts +3 -1
  146. package/dist/wallet/tx/domain-admin.js +61 -99
  147. package/dist/wallet/tx/domain-market.d.ts +5 -1
  148. package/dist/wallet/tx/domain-market.js +221 -228
  149. package/dist/wallet/tx/field.d.ts +4 -10
  150. package/dist/wallet/tx/field.js +84 -914
  151. package/dist/wallet/tx/identity-selector.d.ts +9 -3
  152. package/dist/wallet/tx/identity-selector.js +17 -35
  153. package/dist/wallet/tx/index.d.ts +3 -1
  154. package/dist/wallet/tx/index.js +2 -1
  155. package/dist/wallet/tx/register.d.ts +3 -1
  156. package/dist/wallet/tx/register.js +62 -220
  157. package/dist/wallet/tx/reputation.d.ts +3 -1
  158. package/dist/wallet/tx/reputation.js +58 -95
  159. package/dist/wallet/types.d.ts +8 -122
  160. package/package.json +5 -5
  161. package/dist/wallet/archive.d.ts +0 -4
  162. package/dist/wallet/archive.js +0 -41
  163. package/dist/wallet/mining/hook-protocol.d.ts +0 -47
  164. package/dist/wallet/mining/hook-protocol.js +0 -161
  165. package/dist/wallet/mining/hook-runner.js +0 -52
  166. package/dist/wallet/mining/hooks.d.ts +0 -38
  167. package/dist/wallet/mining/hooks.js +0 -520
  168. package/dist/wallet/state/explicit-lock.d.ts +0 -4
  169. package/dist/wallet/state/explicit-lock.js +0 -19
  170. package/dist/wallet/state/session.d.ts +0 -12
  171. package/dist/wallet/state/session.js +0 -23
  172. /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { mkdir, open, readFile, rename, rm, stat } from "node:fs/promises";
3
3
  import { dirname } from "node:path";
4
4
  import { writeRuntimeStatusFile } from "../fs/status-file.js";
5
- import { normalizeMiningFamilyStatus, normalizeMiningPublishState } from "./state.js";
5
+ import { normalizeMiningLifecycleStatus, normalizeMiningPublishState } from "./state.js";
6
6
  const MAX_EVENT_LOG_BYTES = 10 * 1024 * 1024;
7
7
  const MAX_EVENT_LOG_ROTATIONS = 4;
8
8
  export function resolveRotatedMiningEventsPath(eventsPath) {
@@ -11,14 +11,31 @@ export function resolveRotatedMiningEventsPath(eventsPath) {
11
11
  function resolveIndexedRotatedMiningEventsPath(eventsPath, index) {
12
12
  return `${eventsPath}.${index}`;
13
13
  }
14
+ function normalizeLegacyMiningProviderState(raw) {
15
+ switch (raw) {
16
+ case "ready":
17
+ case "backoff":
18
+ case "unavailable":
19
+ case "rate-limited":
20
+ case "auth-error":
21
+ return raw;
22
+ case "hook-error":
23
+ case "n/a":
24
+ return "unavailable";
25
+ default:
26
+ return null;
27
+ }
28
+ }
14
29
  export async function loadMiningRuntimeStatus(statusPath) {
15
30
  try {
16
31
  const raw = await readFile(statusPath, "utf8");
17
32
  const parsed = JSON.parse(raw);
18
33
  return {
19
34
  ...parsed,
20
- miningState: normalizeMiningFamilyStatus(parsed.miningState),
35
+ miningState: normalizeMiningLifecycleStatus(parsed.miningState),
36
+ providerState: normalizeLegacyMiningProviderState(parsed.providerState),
21
37
  currentPublishState: normalizeMiningPublishState(parsed.currentPublishState),
38
+ livePublishInMempool: parsed.livePublishInMempool ?? parsed.liveMiningFamilyInMempool ?? null,
22
39
  indexerReorgDepth: parsed.indexerReorgDepth ?? null,
23
40
  sameDomainCompetitorSuppressed: parsed.sameDomainCompetitorSuppressed ?? null,
24
41
  dedupedCompetitorDomainCount: parsed.dedupedCompetitorDomainCount ?? null,
@@ -34,7 +51,10 @@ export async function loadMiningRuntimeStatus(statusPath) {
34
51
  }
35
52
  }
36
53
  export async function saveMiningRuntimeStatus(statusPath, snapshot) {
37
- await writeRuntimeStatusFile(statusPath, snapshot);
54
+ await writeRuntimeStatusFile(statusPath, {
55
+ ...snapshot,
56
+ providerState: normalizeLegacyMiningProviderState(snapshot.providerState),
57
+ });
38
58
  }
39
59
  async function rotateMiningEventsIfNeeded(eventsPath, nextEntryBytes) {
40
60
  try {
@@ -0,0 +1,44 @@
1
+ import { MINING_SENTENCE_SCHEMA_VERSION } from "./constants.js";
2
+ export interface MiningSentenceGenerationRequestV1 {
3
+ schemaVersion: typeof MINING_SENTENCE_SCHEMA_VERSION;
4
+ requestId: string;
5
+ targetBlockHeight: number;
6
+ referencedBlockHashDisplay: string;
7
+ generatedAtUnixMs: number;
8
+ extraPrompt: string | null;
9
+ limits: {
10
+ maxCandidatesPerRootDomain: number;
11
+ maxCandidatesTotal: number;
12
+ timeoutMs: number;
13
+ maxCandidateSentenceUtf8Bytes: number;
14
+ };
15
+ rootDomains: Array<{
16
+ domainId: number;
17
+ domainName: string;
18
+ requiredWords: [string, string, string, string, string];
19
+ }>;
20
+ }
21
+ export interface MiningSentenceCandidateV1 {
22
+ domainId: number;
23
+ sentence: string;
24
+ attribution?: {
25
+ provider?: string;
26
+ model?: string;
27
+ promptLabel?: string;
28
+ };
29
+ }
30
+ export interface MiningSentenceGenerationResponseV1 {
31
+ schemaVersion: typeof MINING_SENTENCE_SCHEMA_VERSION;
32
+ requestId: string;
33
+ candidates: MiningSentenceCandidateV1[];
34
+ }
35
+ export declare function createMiningSentenceRequestLimits(): MiningSentenceGenerationRequestV1["limits"];
36
+ export declare function parseStrictJsonValue(raw: string, invalidMessage: string): unknown;
37
+ export declare function stripMarkdownCodeFence(raw: string): string;
38
+ export declare function normalizeMiningSentenceResponse(options: {
39
+ request: MiningSentenceGenerationRequestV1;
40
+ response: unknown;
41
+ }): {
42
+ response: MiningSentenceGenerationResponseV1;
43
+ candidates: MiningSentenceCandidateV1[];
44
+ };
@@ -0,0 +1,123 @@
1
+ import { MINING_SENTENCE_MAX_CANDIDATES_PER_ROOT_DOMAIN, MINING_SENTENCE_MAX_CANDIDATES_TOTAL, MINING_SENTENCE_MAX_CANDIDATE_SENTENCE_UTF8_BYTES, MINING_SENTENCE_SCHEMA_VERSION, MINING_SENTENCE_TIMEOUT_MS, } from "./constants.js";
2
+ export function createMiningSentenceRequestLimits() {
3
+ return {
4
+ maxCandidateSentenceUtf8Bytes: MINING_SENTENCE_MAX_CANDIDATE_SENTENCE_UTF8_BYTES,
5
+ maxCandidatesPerRootDomain: MINING_SENTENCE_MAX_CANDIDATES_PER_ROOT_DOMAIN,
6
+ maxCandidatesTotal: MINING_SENTENCE_MAX_CANDIDATES_TOTAL,
7
+ timeoutMs: MINING_SENTENCE_TIMEOUT_MS,
8
+ };
9
+ }
10
+ function normalizeAttribution(raw) {
11
+ if (raw === null || typeof raw !== "object") {
12
+ return undefined;
13
+ }
14
+ const attribution = raw;
15
+ const normalized = {};
16
+ for (const key of ["provider", "model", "promptLabel"]) {
17
+ const value = attribution[key];
18
+ if (typeof value === "string" && value.length > 0) {
19
+ normalized[key] = value;
20
+ }
21
+ }
22
+ return Object.keys(normalized).length === 0
23
+ ? undefined
24
+ : normalized;
25
+ }
26
+ export function parseStrictJsonValue(raw, invalidMessage) {
27
+ const trimmed = raw.trim();
28
+ if (trimmed.length === 0) {
29
+ throw new Error(invalidMessage);
30
+ }
31
+ try {
32
+ return JSON.parse(trimmed);
33
+ }
34
+ catch {
35
+ throw new Error(invalidMessage);
36
+ }
37
+ }
38
+ export function stripMarkdownCodeFence(raw) {
39
+ const trimmed = raw.trim();
40
+ if (!trimmed.startsWith("```")) {
41
+ return raw;
42
+ }
43
+ const lines = trimmed.split(/\r?\n/);
44
+ if (lines.length < 3) {
45
+ return raw;
46
+ }
47
+ const first = lines[0].trim();
48
+ const last = lines.at(-1)?.trim();
49
+ if (!first.startsWith("```") || last !== "```") {
50
+ return raw;
51
+ }
52
+ return lines.slice(1, -1).join("\n");
53
+ }
54
+ export function normalizeMiningSentenceResponse(options) {
55
+ const raw = options.response;
56
+ if (raw === null || typeof raw !== "object") {
57
+ throw new Error("Mining sentence generation returned an invalid JSON response.");
58
+ }
59
+ const response = raw;
60
+ if (response.schemaVersion !== MINING_SENTENCE_SCHEMA_VERSION) {
61
+ throw new Error("Mining sentence generation returned an unsupported schema version.");
62
+ }
63
+ if (response.requestId !== options.request.requestId) {
64
+ throw new Error("Mining sentence generation returned a mismatched requestId.");
65
+ }
66
+ if (!Array.isArray(response.candidates)) {
67
+ throw new Error("Mining sentence generation response must include a candidates array.");
68
+ }
69
+ if (response.candidates.length > options.request.limits.maxCandidatesTotal) {
70
+ throw new Error("Mining sentence generation returned too many total candidates.");
71
+ }
72
+ const allowedDomainIds = new Set(options.request.rootDomains.map((domain) => domain.domainId));
73
+ const perDomainCounts = new Map();
74
+ const dedupe = new Set();
75
+ const candidates = [];
76
+ for (const rawCandidate of response.candidates) {
77
+ if (rawCandidate === null || typeof rawCandidate !== "object") {
78
+ throw new Error("Mining sentence generation returned an invalid candidate entry.");
79
+ }
80
+ const candidate = rawCandidate;
81
+ const domainId = candidate.domainId;
82
+ const sentence = candidate.sentence;
83
+ if (!Number.isInteger(domainId)) {
84
+ throw new Error("Mining sentence generation candidate is missing a valid domainId.");
85
+ }
86
+ if (!allowedDomainIds.has(domainId)) {
87
+ throw new Error("Mining sentence generation candidate referenced an unknown domainId.");
88
+ }
89
+ if (typeof sentence !== "string") {
90
+ throw new Error("Mining sentence generation candidate is missing a valid sentence.");
91
+ }
92
+ const trimmedSentence = sentence.trim();
93
+ if (trimmedSentence.length === 0) {
94
+ throw new Error("Mining sentence generation candidate sentence was empty after trimming.");
95
+ }
96
+ if (Buffer.byteLength(trimmedSentence, "utf8") > options.request.limits.maxCandidateSentenceUtf8Bytes) {
97
+ throw new Error("Mining sentence generation candidate sentence exceeded the UTF-8 byte limit.");
98
+ }
99
+ const nextCount = (perDomainCounts.get(domainId) ?? 0) + 1;
100
+ perDomainCounts.set(domainId, nextCount);
101
+ if (nextCount > options.request.limits.maxCandidatesPerRootDomain) {
102
+ throw new Error("Mining sentence generation returned too many candidates for one domain.");
103
+ }
104
+ const dedupeKey = `${domainId}:${trimmedSentence}`;
105
+ if (dedupe.has(dedupeKey)) {
106
+ continue;
107
+ }
108
+ dedupe.add(dedupeKey);
109
+ candidates.push({
110
+ domainId: domainId,
111
+ sentence: trimmedSentence,
112
+ attribution: normalizeAttribution(candidate.attribution),
113
+ });
114
+ }
115
+ return {
116
+ response: {
117
+ schemaVersion: MINING_SENTENCE_SCHEMA_VERSION,
118
+ requestId: options.request.requestId,
119
+ candidates,
120
+ },
121
+ candidates,
122
+ };
123
+ }
@@ -1,13 +1,11 @@
1
- import type { GenerateSentencesHookCandidateV1, GenerateSentencesHookRequestV1 } from "./hook-protocol.js";
1
+ import type { MiningSentenceCandidateV1, MiningSentenceGenerationRequestV1 } from "./sentence-protocol.js";
2
2
  import type { WalletRuntimePaths } from "../runtime.js";
3
- import type { HookClientStateRecord } from "../types.js";
4
3
  import type { WalletSecretProvider } from "../state/provider.js";
5
- export type MiningSentenceGenerationRequest = GenerateSentencesHookRequestV1;
6
- export type MiningSentenceGenerationCandidate = GenerateSentencesHookCandidateV1;
4
+ export type MiningSentenceGenerationRequest = MiningSentenceGenerationRequestV1;
5
+ export type MiningSentenceGenerationCandidate = MiningSentenceCandidateV1;
7
6
  export interface MiningSentenceSourceOptions {
8
7
  paths: WalletRuntimePaths;
9
8
  provider: WalletSecretProvider;
10
- hookState: HookClientStateRecord | null;
11
9
  signal?: AbortSignal;
12
10
  fetchImpl?: typeof fetch;
13
11
  }
@@ -16,8 +14,6 @@ declare class MiningProviderRequestError extends Error {
16
14
  constructor(providerState: "unavailable" | "rate-limited" | "auth-error", message: string);
17
15
  }
18
16
  export declare function generateMiningSentences(request: MiningSentenceGenerationRequest, options: MiningSentenceSourceOptions): Promise<{
19
- hookMode: "builtin" | "custom";
20
- candidates: GenerateSentencesHookCandidateV1[];
21
- providerState: "ready" | "n/a";
17
+ candidates: MiningSentenceCandidateV1[];
22
18
  }>;
23
19
  export { MiningProviderRequestError, };
@@ -1,7 +1,6 @@
1
1
  import { loadClientConfig } from "./config.js";
2
- import { inspectMiningHookState, runGenerateSentencesHookRequest } from "./hooks.js";
3
2
  import { MINING_BUILTIN_TIMEOUT_MS, } from "./constants.js";
4
- import { normalizeHookResponse, parseStrictJsonValue, stripMarkdownCodeFence, } from "./hook-protocol.js";
3
+ import { normalizeMiningSentenceResponse, parseStrictJsonValue, stripMarkdownCodeFence, } from "./sentence-protocol.js";
5
4
  class MiningProviderRequestError extends Error {
6
5
  providerState;
7
6
  constructor(providerState, message) {
@@ -48,15 +47,13 @@ function annotateProviderCandidates(options) {
48
47
  function parseProviderJsonResponse(options) {
49
48
  const response = parseStrictJsonValue(stripMarkdownCodeFence(options.raw), `${options.providerLabel} returned invalid JSON.`);
50
49
  try {
51
- return normalizeHookResponse({
50
+ return normalizeMiningSentenceResponse({
52
51
  request: options.request,
53
52
  response,
54
53
  }).candidates;
55
54
  }
56
55
  catch (error) {
57
- throw new Error(error instanceof Error
58
- ? error.message.replace(/^Custom mining hook /, `${options.providerLabel} `)
59
- : `${options.providerLabel} returned an invalid response.`);
56
+ throw new Error(error instanceof Error ? error.message : `${options.providerLabel} returned an invalid response.`);
60
57
  }
61
58
  }
62
59
  function createProviderSignal(signal, timeoutMs) {
@@ -211,51 +208,7 @@ function extractAnthropicText(payload) {
211
208
  }
212
209
  throw new Error("The built-in Anthropic mining provider returned an empty response.");
213
210
  }
214
- async function requestCustomHookSentences(options) {
215
- const inspection = await inspectMiningHookState({
216
- hookRootPath: options.paths.hooksMiningDir,
217
- entrypointPath: options.paths.hooksMiningEntrypointPath,
218
- packagePath: options.paths.hooksMiningPackageJsonPath,
219
- localState: options.hookState,
220
- verify: false,
221
- nowUnixMs: Date.now(),
222
- });
223
- if (inspection.mode !== "custom") {
224
- throw new Error("Custom mining hooks are not enabled.");
225
- }
226
- if (inspection.cooldownActive) {
227
- throw new Error("Custom mining hook is cooling down after repeated failures. Wait for the cooldown to expire or rerun `cogcoin hooks enable mining`.");
228
- }
229
- if (inspection.operatorValidationState === "failed"
230
- || inspection.operatorValidationState === "stale"
231
- || inspection.operatorValidationState === "never") {
232
- throw new Error("Custom mining hook validation is stale or failed. Rerun `cogcoin hooks enable mining`.");
233
- }
234
- if (inspection.trustStatus !== "trusted") {
235
- throw new Error(inspection.trustMessage ?? "Custom mining hook trust checks failed.");
236
- }
237
- return runGenerateSentencesHookRequest({
238
- hookRootPath: options.paths.hooksMiningDir,
239
- entrypointPath: options.paths.hooksMiningEntrypointPath,
240
- request: options.request,
241
- signal: options.signal,
242
- timeoutMs: options.request.limits.timeoutMs,
243
- }).then((result) => result.candidates);
244
- }
245
211
  export async function generateMiningSentences(request, options) {
246
- const hookMode = options.hookState?.mode === "custom" ? "custom" : "builtin";
247
- if (hookMode === "custom") {
248
- return {
249
- hookMode,
250
- candidates: await requestCustomHookSentences({
251
- paths: options.paths,
252
- hookState: options.hookState,
253
- request,
254
- signal: options.signal,
255
- }),
256
- providerState: "n/a",
257
- };
258
- }
259
212
  const config = await loadClientConfig({
260
213
  path: options.paths.clientConfigPath,
261
214
  provider: options.provider,
@@ -265,7 +218,6 @@ export async function generateMiningSentences(request, options) {
265
218
  throw new MiningProviderRequestError("unavailable", "Mining is not configured. Run `cogcoin mine setup`.");
266
219
  }
267
220
  return {
268
- hookMode,
269
221
  candidates: await requestBuiltInSentences({
270
222
  provider: builtIn.provider,
271
223
  apiKey: builtIn.apiKey,
@@ -275,7 +227,6 @@ export async function generateMiningSentences(request, options) {
275
227
  fetchImpl: options.fetchImpl,
276
228
  signal: options.signal,
277
229
  }),
278
- providerState: "ready",
279
230
  };
280
231
  }
281
232
  export { MiningProviderRequestError, };
@@ -1,9 +1,14 @@
1
1
  import type { MiningStateRecord } from "../types.js";
2
- export type MiningFamilyStatus = MiningStateRecord["state"];
2
+ type LegacyMiningStateRecord = MiningStateRecord & {
3
+ livePublishInMempool?: boolean | null;
4
+ liveMiningFamilyInMempool?: boolean | null;
5
+ };
6
+ export type MiningLifecycleStatus = MiningStateRecord["state"];
3
7
  export type MiningPublishState = MiningStateRecord["currentPublishState"];
4
- export declare function normalizeMiningFamilyStatus(raw: string | null | undefined): MiningFamilyStatus;
8
+ export declare function normalizeMiningLifecycleStatus(raw: string | null | undefined): MiningLifecycleStatus;
5
9
  export declare function normalizeMiningPublishState(raw: string | null | undefined): MiningPublishState;
6
- export declare function normalizeMiningStateRecord(state: MiningStateRecord): MiningStateRecord;
7
- export declare function clearMiningFamilyState(state: MiningStateRecord): MiningStateRecord;
8
- export declare function miningFamilyMayStillExist(state: MiningStateRecord): boolean;
9
- export declare function miningFamilyIsInMempool(state: MiningStateRecord): boolean;
10
+ export declare function normalizeMiningStateRecord(state: LegacyMiningStateRecord): MiningStateRecord;
11
+ export declare function clearMiningPublishState(state: MiningStateRecord): MiningStateRecord;
12
+ export declare function miningPublishMayStillExist(state: MiningStateRecord): boolean;
13
+ export declare function miningPublishIsInMempool(state: MiningStateRecord): boolean;
14
+ export {};
@@ -1,4 +1,4 @@
1
- export function normalizeMiningFamilyStatus(raw) {
1
+ export function normalizeMiningLifecycleStatus(raw) {
2
2
  switch (raw) {
3
3
  case "live":
4
4
  case "paused":
@@ -33,11 +33,12 @@ export function normalizeMiningPublishState(raw) {
33
33
  export function normalizeMiningStateRecord(state) {
34
34
  return {
35
35
  ...state,
36
- state: normalizeMiningFamilyStatus(state.state),
36
+ state: normalizeMiningLifecycleStatus(state.state),
37
37
  currentPublishState: normalizeMiningPublishState(state.currentPublishState),
38
+ livePublishInMempool: state.livePublishInMempool ?? state.liveMiningFamilyInMempool ?? false,
38
39
  };
39
40
  }
40
- export function clearMiningFamilyState(state) {
41
+ export function clearMiningPublishState(state) {
41
42
  return {
42
43
  ...normalizeMiningStateRecord(state),
43
44
  state: "idle",
@@ -59,17 +60,17 @@ export function clearMiningFamilyState(state) {
59
60
  currentBlockTargetHeight: null,
60
61
  currentReferencedBlockHashDisplay: null,
61
62
  currentIntentFingerprintHex: null,
62
- liveMiningFamilyInMempool: false,
63
+ livePublishInMempool: false,
63
64
  currentPublishDecision: null,
64
65
  replacementCount: 0,
65
66
  sharedMiningConflictOutpoint: null,
66
67
  };
67
68
  }
68
- export function miningFamilyMayStillExist(state) {
69
+ export function miningPublishMayStillExist(state) {
69
70
  const normalized = normalizeMiningStateRecord(state);
70
71
  return normalized.currentTxid !== null
71
72
  && normalized.currentPublishState !== "none";
72
73
  }
73
- export function miningFamilyIsInMempool(state) {
74
+ export function miningPublishIsInMempool(state) {
74
75
  return normalizeMiningStateRecord(state).currentPublishState === "in-mempool";
75
76
  }
@@ -1,5 +1,4 @@
1
1
  import type { ManagedBitcoindHealth, ManagedIndexerTruthSource } from "../../bitcoind/types.js";
2
- import type { MiningHookOperatorValidationState } from "./hook-protocol.js";
3
2
  export type MiningServiceHealth = "synced" | "catching-up" | "reorging" | "starting" | "stale-heartbeat" | "failed" | "schema-mismatch" | "service-version-mismatch" | "wallet-root-mismatch" | "unavailable";
4
3
  export type MiningProviderKind = "openai" | "anthropic";
5
4
  export interface MiningProviderConfigRecord {
@@ -57,7 +56,7 @@ export interface MiningRuntimeStatusV1 {
57
56
  indexerReorgDepth: number | null;
58
57
  indexerTipAligned: boolean | null;
59
58
  corePublishState: "unknown" | "network-inactive" | "no-outbound-peers" | "ibd" | "mempool-loading" | "healthy" | null;
60
- providerState: "n/a" | "ready" | "backoff" | "unavailable" | "rate-limited" | "auth-error" | "hook-error" | null;
59
+ providerState: "ready" | "backoff" | "unavailable" | "rate-limited" | "auth-error" | null;
61
60
  lastSuspendDetectedAtUnixMs: number | null;
62
61
  reconnectSettledUntilUnixMs: number | null;
63
62
  tipSettledUntilUnixMs: number | null;
@@ -72,7 +71,7 @@ export interface MiningRuntimeStatusV1 {
72
71
  currentCanonicalBlend: string | null;
73
72
  currentTxid: string | null;
74
73
  currentWtxid: string | null;
75
- liveMiningFamilyInMempool: boolean | null;
74
+ livePublishInMempool: boolean | null;
76
75
  currentFeeRateSatVb: number | null;
77
76
  currentAbsoluteFeeSats: number | null;
78
77
  currentBlockFeeSpentSats: string;
@@ -87,7 +86,6 @@ export interface MiningRuntimeStatusV1 {
87
86
  lastMempoolSequence: string | null;
88
87
  lastCompetitivenessGateAtUnixMs: number | null;
89
88
  pauseReason: string | null;
90
- hookMode: "builtin" | "custom";
91
89
  providerConfigured: boolean;
92
90
  providerKind: MiningProviderKind | null;
93
91
  bitcoindHealth: ManagedBitcoindHealth;
@@ -96,35 +94,10 @@ export interface MiningRuntimeStatusV1 {
96
94
  nodeHealth: MiningServiceHealth;
97
95
  indexerHealth: MiningServiceHealth;
98
96
  tipsAligned: boolean | null;
99
- lastValidationState: "unknown" | "validated" | "stale" | "failed" | null;
100
- lastOperatorValidationState: MiningHookOperatorValidationState | null;
101
- lastValidationAtUnixMs: number | null;
102
97
  lastEventAtUnixMs: number | null;
103
98
  lastError: string | null;
104
99
  note: string | null;
105
100
  }
106
- export interface MiningHookInspection {
107
- mode: "builtin" | "custom" | "disabled" | "unavailable";
108
- entrypointPath: string;
109
- packagePath: string;
110
- entrypointExists: boolean;
111
- packageStatus: "valid" | "missing" | "invalid";
112
- packageMessage: string | null;
113
- trustStatus: "trusted" | "untrusted" | "missing";
114
- trustMessage: string | null;
115
- validationState: "unknown" | "validated" | "stale" | "failed" | "unavailable";
116
- operatorValidationState: MiningHookOperatorValidationState;
117
- validationError: string | null;
118
- validatedAtUnixMs: number | null;
119
- validatedLaunchFingerprint: string | null;
120
- validatedFullFingerprint: string | null;
121
- currentLaunchFingerprint: string | null;
122
- currentFullFingerprint: string | null;
123
- verifyUsed: boolean;
124
- cooldownUntilUnixMs: number | null;
125
- cooldownActive: boolean;
126
- consecutiveFailureCount: number;
127
- }
128
101
  export interface MiningProviderInspection {
129
102
  configured: boolean;
130
103
  provider: MiningProviderKind | null;
@@ -135,7 +108,6 @@ export interface MiningProviderInspection {
135
108
  }
136
109
  export interface MiningControlPlaneView {
137
110
  runtime: MiningRuntimeStatusV1;
138
- hook: MiningHookInspection;
139
111
  provider: MiningProviderInspection;
140
112
  lastEventAtUnixMs: number | null;
141
113
  }
@@ -1,12 +1,40 @@
1
1
  import type { BootstrapProgress, ProgressOutputMode } from "../../bitcoind/types.js";
2
2
  import { createFollowSceneState } from "../../bitcoind/progress/follow-scene.js";
3
3
  import { type RenderClock, type TtyRenderStream } from "../../bitcoind/progress/render-policy.js";
4
+ import { type FollowSceneRenderOptions } from "../../bitcoind/progress/tty-renderer.js";
4
5
  import type { MiningRuntimeStatusV1 } from "./types.js";
5
6
  interface VisualizerRendererLike {
6
- renderFollowScene(progress: BootstrapProgress, cogcoinSyncHeight: number | null, cogcoinSyncTargetHeight: number | null, followScene: ReturnType<typeof createFollowSceneState>, statusFieldText?: string): void;
7
+ renderFollowScene(progress: BootstrapProgress, cogcoinSyncHeight: number | null, cogcoinSyncTargetHeight: number | null, followScene: ReturnType<typeof createFollowSceneState>, statusFieldText?: string, renderOptions?: FollowSceneRenderOptions): void;
7
8
  close(): void;
8
9
  }
9
- export declare function describeMiningVisualizerStatus(snapshot: MiningRuntimeStatusV1): string;
10
+ export interface MiningSentenceBoardEntry {
11
+ rank: number;
12
+ domainName: string;
13
+ sentence: string;
14
+ }
15
+ export interface MiningProvisionalSentenceEntry {
16
+ domainName: string | null;
17
+ sentence: string | null;
18
+ }
19
+ export interface MiningRecentWinSummary {
20
+ rank: number;
21
+ rewardCogtoshi: bigint;
22
+ blockHeight: number;
23
+ }
24
+ export interface MiningFollowVisualizerState {
25
+ balanceCogtoshi: bigint | null;
26
+ balanceSats: bigint | null;
27
+ visibleBlockTimesByHeight: Record<number, number>;
28
+ settledBlockHeight: number | null;
29
+ settledBoardEntries: MiningSentenceBoardEntry[];
30
+ provisionalRequiredWords: readonly string[];
31
+ provisionalEntry: MiningProvisionalSentenceEntry;
32
+ latestSentence: string | null;
33
+ latestTxid: string | null;
34
+ recentWin: MiningRecentWinSummary | null;
35
+ }
36
+ export declare function createEmptyMiningFollowVisualizerState(): MiningFollowVisualizerState;
37
+ export declare function describeMiningVisualizerStatus(snapshot: MiningRuntimeStatusV1, ui?: MiningFollowVisualizerState): string;
10
38
  export declare function describeMiningVisualizerProgress(snapshot: MiningRuntimeStatusV1): string;
11
39
  export declare class MiningFollowVisualizer {
12
40
  #private;
@@ -18,7 +46,7 @@ export declare class MiningFollowVisualizer {
18
46
  clock?: RenderClock;
19
47
  rendererFactory?: (stream: TtyRenderStream) => VisualizerRendererLike;
20
48
  });
21
- update(snapshot: MiningRuntimeStatusV1): void;
49
+ update(snapshot: MiningRuntimeStatusV1, uiState?: MiningFollowVisualizerState): void;
22
50
  close(): void;
23
51
  }
24
52
  export {};