@totalreclaw/totalreclaw 3.3.12 → 3.3.13

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 (128) hide show
  1. package/SKILL.md +25 -8
  2. package/{billing-cache.ts → billing/billing-cache.ts} +1 -1
  3. package/{relay-headers.ts → billing/relay-headers.ts} +1 -1
  4. package/{tr-cli-export-helper.ts → cli/tr-cli-export-helper.ts} +5 -5
  5. package/{tr-cli.ts → cli/tr-cli.ts} +20 -20
  6. package/{contradiction-sync.ts → contradiction/contradiction-sync.ts} +13 -13
  7. package/{digest-sync.ts → digest/digest-sync.ts} +32 -2
  8. package/dist/{billing-cache.js → billing/billing-cache.js} +1 -1
  9. package/dist/{relay-headers.js → billing/relay-headers.js} +1 -1
  10. package/dist/{tr-cli-export-helper.js → cli/tr-cli-export-helper.js} +5 -5
  11. package/dist/{tr-cli.js → cli/tr-cli.js} +19 -19
  12. package/dist/{contradiction-sync.js → contradiction/contradiction-sync.js} +13 -13
  13. package/dist/{digest-sync.js → digest/digest-sync.js} +32 -2
  14. package/dist/{download-ux.js → embedding/download-ux.js} +1 -1
  15. package/dist/{reranker.js → embedding/reranker.js} +13 -4
  16. package/dist/{claims-helper.js → extraction/claims-helper.js} +54 -58
  17. package/dist/extraction/consolidation.js +170 -0
  18. package/dist/{extractor.js → extraction/extractor.js} +17 -17
  19. package/dist/extraction/importance-filter.js +38 -0
  20. package/dist/{semantic-dedup.js → extraction/semantic-dedup.js} +2 -2
  21. package/dist/{batch-gate.js → import/batch-gate.js} +1 -1
  22. package/dist/import/import-runtime.js +692 -0
  23. package/dist/import-adapters/chatgpt-adapter.js +7 -7
  24. package/dist/import-adapters/gemini-adapter.js +13 -13
  25. package/dist/import-adapters/mem0-adapter.js +10 -10
  26. package/dist/index.js +111 -1094
  27. package/dist/{llm-client.js → llm/llm-client.js} +2 -2
  28. package/dist/{hot-cache-wrapper.js → memory/hot-cache-wrapper.js} +5 -5
  29. package/dist/{memory-runtime.js → memory/memory-runtime.js} +1 -1
  30. package/dist/{pin.js → memory/pin.js} +18 -18
  31. package/dist/{retype-setscope.js → memory/retype-setscope.js} +19 -19
  32. package/dist/{credential-provider.js → pairing/credential-provider.js} +2 -2
  33. package/dist/{first-run.js → pairing/first-run.js} +1 -1
  34. package/dist/{onboarding-cli.js → pairing/onboarding-cli.js} +20 -20
  35. package/dist/{pair-cli-relay.js → pairing/pair-cli-relay.js} +10 -10
  36. package/dist/{pair-crypto.js → pairing/pair-crypto.js} +1 -1
  37. package/dist/{pair-http.js → pairing/pair-http.js} +3 -3
  38. package/dist/{pair-remote-client.js → pairing/pair-remote-client.js} +10 -10
  39. package/dist/{pair-session-store.js → pairing/pair-session-store.js} +4 -4
  40. package/dist/runtime/config-schema.js +59 -0
  41. package/dist/runtime/format-helpers.js +257 -0
  42. package/dist/runtime/types.js +11 -0
  43. package/dist/{confirm-indexed.js → subgraph/confirm-indexed.js} +1 -1
  44. package/dist/{subgraph-search.js → subgraph/subgraph-search.js} +14 -14
  45. package/dist/{subgraph-store.js → subgraph/subgraph-store.js} +6 -6
  46. package/{download-ux.ts → embedding/download-ux.ts} +1 -1
  47. package/{reranker.ts → embedding/reranker.ts} +13 -4
  48. package/{claims-helper.ts → extraction/claims-helper.ts} +52 -60
  49. package/{consolidation.ts → extraction/consolidation.ts} +63 -154
  50. package/{extractor.ts → extraction/extractor.ts} +18 -17
  51. package/extraction/importance-filter.ts +50 -0
  52. package/{semantic-dedup.ts → extraction/semantic-dedup.ts} +2 -2
  53. package/{batch-gate.ts → import/batch-gate.ts} +1 -1
  54. package/import/import-runtime.ts +853 -0
  55. package/import-adapters/chatgpt-adapter.ts +7 -7
  56. package/import-adapters/gemini-adapter.ts +13 -13
  57. package/import-adapters/mem0-adapter.ts +10 -10
  58. package/index.ts +129 -1377
  59. package/{llm-client.ts → llm/llm-client.ts} +2 -2
  60. package/{hot-cache-wrapper.ts → memory/hot-cache-wrapper.ts} +5 -5
  61. package/{memory-runtime.ts → memory/memory-runtime.ts} +1 -1
  62. package/{pin.ts → memory/pin.ts} +20 -20
  63. package/{retype-setscope.ts → memory/retype-setscope.ts} +21 -21
  64. package/{tool-gating.ts → memory/tool-gating.ts} +1 -1
  65. package/package.json +6 -6
  66. package/{credential-provider.ts → pairing/credential-provider.ts} +2 -2
  67. package/{first-run.ts → pairing/first-run.ts} +1 -1
  68. package/{onboarding-cli.ts → pairing/onboarding-cli.ts} +20 -20
  69. package/{pair-cli-relay.ts → pairing/pair-cli-relay.ts} +10 -10
  70. package/{pair-crypto.ts → pairing/pair-crypto.ts} +1 -1
  71. package/{pair-http.ts → pairing/pair-http.ts} +3 -3
  72. package/{pair-remote-client.ts → pairing/pair-remote-client.ts} +10 -10
  73. package/{pair-session-store.ts → pairing/pair-session-store.ts} +4 -4
  74. package/runtime/config-schema.ts +64 -0
  75. package/runtime/format-helpers.ts +293 -0
  76. package/runtime/types.ts +118 -0
  77. package/skill.json +44 -10
  78. package/{confirm-indexed.ts → subgraph/confirm-indexed.ts} +1 -1
  79. package/{subgraph-search.ts → subgraph/subgraph-search.ts} +14 -14
  80. package/{subgraph-store.ts → subgraph/subgraph-store.ts} +10 -10
  81. package/dist/consolidation.js +0 -249
  82. /package/{api-client.ts → billing/api-client.ts} +0 -0
  83. /package/{gateway-url.ts → billing/gateway-url.ts} +0 -0
  84. /package/{inbound-user-tracker.ts → billing/inbound-user-tracker.ts} +0 -0
  85. /package/{relay.ts → billing/relay.ts} +0 -0
  86. /package/{crypto.ts → crypto/crypto.ts} +0 -0
  87. /package/{vault-crypto.ts → crypto/vault-crypto.ts} +0 -0
  88. /package/dist/{api-client.js → billing/api-client.js} +0 -0
  89. /package/dist/{gateway-url.js → billing/gateway-url.js} +0 -0
  90. /package/dist/{inbound-user-tracker.js → billing/inbound-user-tracker.js} +0 -0
  91. /package/dist/{relay.js → billing/relay.js} +0 -0
  92. /package/dist/{crypto.js → crypto/crypto.js} +0 -0
  93. /package/dist/{vault-crypto.js → crypto/vault-crypto.js} +0 -0
  94. /package/dist/{embedder-cache.js → embedding/embedder-cache.js} +0 -0
  95. /package/dist/{embedder-loader.js → embedding/embedder-loader.js} +0 -0
  96. /package/dist/{embedder-network.js → embedding/embedder-network.js} +0 -0
  97. /package/dist/{embedding.js → embedding/embedding.js} +0 -0
  98. /package/dist/{lsh.js → embedding/lsh.js} +0 -0
  99. /package/dist/{import-state-manager.js → import/import-state-manager.js} +0 -0
  100. /package/dist/{llm-profile-reader.js → llm/llm-profile-reader.js} +0 -0
  101. /package/dist/{native-memory.js → memory/native-memory.js} +0 -0
  102. /package/dist/{tool-gating.js → memory/tool-gating.js} +0 -0
  103. /package/dist/{tools.js → memory/tools.js} +0 -0
  104. /package/dist/{generate-mnemonic.js → pairing/generate-mnemonic.js} +0 -0
  105. /package/dist/{pair-cli.js → pairing/pair-cli.js} +0 -0
  106. /package/dist/{pair-page.js → pairing/pair-page.js} +0 -0
  107. /package/dist/{pair-qr.js → pairing/pair-qr.js} +0 -0
  108. /package/dist/{restart-auth.js → pairing/restart-auth.js} +0 -0
  109. /package/dist/{qa-bug-report.js → setup/qa-bug-report.js} +0 -0
  110. /package/dist/{skill-register.js → setup/skill-register.js} +0 -0
  111. /package/dist/{trajectory-poller.js → subgraph/trajectory-poller.js} +0 -0
  112. /package/{embedder-cache.ts → embedding/embedder-cache.ts} +0 -0
  113. /package/{embedder-loader.ts → embedding/embedder-loader.ts} +0 -0
  114. /package/{embedder-network.ts → embedding/embedder-network.ts} +0 -0
  115. /package/{embedding.ts → embedding/embedding.ts} +0 -0
  116. /package/{lsh.ts → embedding/lsh.ts} +0 -0
  117. /package/{import-state-manager.ts → import/import-state-manager.ts} +0 -0
  118. /package/{llm-profile-reader.ts → llm/llm-profile-reader.ts} +0 -0
  119. /package/{native-memory.ts → memory/native-memory.ts} +0 -0
  120. /package/{tools.ts → memory/tools.ts} +0 -0
  121. /package/{generate-mnemonic.ts → pairing/generate-mnemonic.ts} +0 -0
  122. /package/{pair-cli.ts → pairing/pair-cli.ts} +0 -0
  123. /package/{pair-page.ts → pairing/pair-page.ts} +0 -0
  124. /package/{pair-qr.ts → pairing/pair-qr.ts} +0 -0
  125. /package/{restart-auth.ts → pairing/restart-auth.ts} +0 -0
  126. /package/{qa-bug-report.ts → setup/qa-bug-report.ts} +0 -0
  127. /package/{skill-register.ts → setup/skill-register.ts} +0 -0
  128. /package/{trajectory-poller.ts → subgraph/trajectory-poller.ts} +0 -0
@@ -8,7 +8,7 @@
8
8
  * Embedding generation has been moved to embedding.ts (local ONNX model via
9
9
  * @huggingface/transformers). No API key needed for embeddings.
10
10
  */
11
- import { CONFIG } from './config.js';
11
+ import { CONFIG } from '../config.js';
12
12
  // ---------------------------------------------------------------------------
13
13
  // Provider mappings
14
14
  // ---------------------------------------------------------------------------
@@ -754,4 +754,4 @@ async function chatCompletionAnthropic(config, messages, maxTokens, temperature,
754
754
  // see embedding.ts + embedder-loader.ts.
755
755
  export { generateEmbedding, getEmbeddingDims, getEmbeddingModelId, configureEmbedder,
756
756
  // 3.3.3-rc.1 (#187): pre-pair bundle prefetch
757
- prefetchEmbedderBundle, } from './embedding.js';
757
+ prefetchEmbedderBundle, } from '../embedding/embedding.js';
@@ -72,12 +72,12 @@ export class PluginHotCache {
72
72
  if (!fs.existsSync(this.cachePath))
73
73
  return;
74
74
  try {
75
- const data = fs.readFileSync(this.cachePath);
76
- if (data.length < IV_LENGTH + TAG_LENGTH)
75
+ const encryptedFile = fs.readFileSync(this.cachePath);
76
+ if (encryptedFile.length < IV_LENGTH + TAG_LENGTH)
77
77
  return;
78
- const iv = data.subarray(0, IV_LENGTH);
79
- const tag = data.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
80
- const ciphertext = data.subarray(IV_LENGTH + TAG_LENGTH);
78
+ const iv = encryptedFile.subarray(0, IV_LENGTH);
79
+ const tag = encryptedFile.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
80
+ const ciphertext = encryptedFile.subarray(IV_LENGTH + TAG_LENGTH);
81
81
  const decipher = crypto.createDecipheriv('aes-256-gcm', this.key, iv);
82
82
  decipher.setAuthTag(tag);
83
83
  const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
@@ -64,7 +64,7 @@
64
64
  // (no OpenClaw type import) so the plugin compiles without depending on
65
65
  // OpenClaw's type package.
66
66
  // ---------------------------------------------------------------------------
67
- import { EXTRACTION_SYSTEM_PROMPT } from './extractor.js';
67
+ import { EXTRACTION_SYSTEM_PROMPT } from '../extraction/extractor.js';
68
68
  // ---------------------------------------------------------------------------
69
69
  // Constants
70
70
  // ---------------------------------------------------------------------------
@@ -10,11 +10,11 @@
10
10
  */
11
11
  import crypto from 'node:crypto';
12
12
  import { createRequire } from 'node:module';
13
- import { buildV1ClaimBlob, mapTypeToCategory, readV1Blob, } from './claims-helper.js';
14
- import { findLoserClaimInDecisionLog, maybeWriteFeedbackForPin, } from './contradiction-sync.js';
15
- import { isValidMemoryType, V0_TO_V1_TYPE } from './extractor.js';
16
- import { PROTOBUF_VERSION_V4 } from './subgraph-store.js';
17
- import { confirmIndexed } from './confirm-indexed.js';
13
+ import { buildV1ClaimBlob, mapTypeToCategory, readV1Blob, } from '../extraction/claims-helper.js';
14
+ import { findLoserClaimInDecisionLog, maybeWriteFeedbackForPin, } from '../contradiction/contradiction-sync.js';
15
+ import { isValidMemoryType, V0_TO_V1_TYPE } from '../extraction/extractor.js';
16
+ import { PROTOBUF_VERSION_V4 } from '../subgraph/subgraph-store.js';
17
+ import { confirmIndexed } from '../subgraph/confirm-indexed.js';
18
18
  // Lazy-load WASM core (mirrors claims-helper.ts pattern — plays nicely under
19
19
  // both the OpenClaw runtime (CJS-ish tsx) and bare Node ESM used by tests).
20
20
  const requireWasm = createRequire(import.meta.url);
@@ -64,9 +64,9 @@ const HUMAN_TO_SHORT = {
64
64
  };
65
65
  /** Parse a decrypted blob into a canonical mutable Claim + current human status. */
66
66
  export function parseBlobForPin(decrypted) {
67
- let obj;
67
+ let parsed;
68
68
  try {
69
- obj = JSON.parse(decrypted);
69
+ parsed = JSON.parse(decrypted);
70
70
  }
71
71
  catch {
72
72
  const shortClaim = buildCanonicalObjectFromLegacy(decrypted, {});
@@ -79,15 +79,15 @@ export function parseBlobForPin(decrypted) {
79
79
  }
80
80
  // v1 payload (plugin v3.0.0+): long-form fields + schema_version "1.x".
81
81
  // Preserve the v1 structure so the pin path can emit v1 on output.
82
- if (typeof obj.text === 'string' &&
83
- typeof obj.type === 'string' &&
84
- typeof obj.schema_version === 'string' &&
85
- obj.schema_version.startsWith('1.')) {
82
+ if (typeof parsed.text === 'string' &&
83
+ typeof parsed.type === 'string' &&
84
+ typeof parsed.schema_version === 'string' &&
85
+ parsed.schema_version.startsWith('1.')) {
86
86
  const v1 = readV1Blob(decrypted);
87
87
  if (v1) {
88
88
  // Current status = pinStatus if present, else active.
89
89
  const human = v1.pinStatus === 'pinned' ? 'pinned' : 'active';
90
- const shortProjection = v1ToShortKeyClaim(obj);
90
+ const shortProjection = v1ToShortKeyClaim(parsed);
91
91
  return {
92
92
  source: {
93
93
  kind: 'v1',
@@ -114,10 +114,10 @@ export function parseBlobForPin(decrypted) {
114
114
  // readV1Blob returned null — fall through to v0 path.
115
115
  }
116
116
  // v0 canonical Claim — short keys present.
117
- if (typeof obj.t === 'string' && typeof obj.c === 'string') {
118
- const st = typeof obj.st === 'string' ? obj.st : 'a';
117
+ if (typeof parsed.t === 'string' && typeof parsed.c === 'string') {
118
+ const st = typeof parsed.st === 'string' ? parsed.st : 'a';
119
119
  const human = SHORT_TO_HUMAN[st] ?? 'active';
120
- const cloned = JSON.parse(JSON.stringify(obj));
120
+ const cloned = JSON.parse(JSON.stringify(parsed));
121
121
  return {
122
122
  source: { kind: 'v0', claim: cloned },
123
123
  claim: cloned,
@@ -126,9 +126,9 @@ export function parseBlobForPin(decrypted) {
126
126
  };
127
127
  }
128
128
  // Legacy {text, metadata: {importance: 0-1}} shape.
129
- if (typeof obj.text === 'string') {
130
- const meta = obj.metadata ?? {};
131
- const shortClaim = buildCanonicalObjectFromLegacy(obj.text, meta);
129
+ if (typeof parsed.text === 'string') {
130
+ const meta = parsed.metadata ?? {};
131
+ const shortClaim = buildCanonicalObjectFromLegacy(parsed.text, meta);
132
132
  return {
133
133
  source: { kind: 'v0', claim: shortClaim },
134
134
  claim: shortClaim,
@@ -29,10 +29,10 @@
29
29
  */
30
30
  import crypto from 'node:crypto';
31
31
  import { createRequire } from 'node:module';
32
- import { buildV1ClaimBlob, mapTypeToCategory, readV1Blob, } from './claims-helper.js';
33
- import { isValidMemoryType, VALID_MEMORY_SCOPES, V0_TO_V1_TYPE, } from './extractor.js';
34
- import { PROTOBUF_VERSION_V4 } from './subgraph-store.js';
35
- import { confirmIndexed } from './confirm-indexed.js';
32
+ import { buildV1ClaimBlob, mapTypeToCategory, readV1Blob, } from '../extraction/claims-helper.js';
33
+ import { isValidMemoryType, VALID_MEMORY_SCOPES, V0_TO_V1_TYPE, } from '../extraction/extractor.js';
34
+ import { PROTOBUF_VERSION_V4 } from '../subgraph/subgraph-store.js';
35
+ import { confirmIndexed } from '../subgraph/confirm-indexed.js';
36
36
  // Lazy-load WASM core — mirrors pin.ts pattern.
37
37
  const requireWasm = createRequire(import.meta.url);
38
38
  let _wasm = null;
@@ -58,18 +58,18 @@ function encodeFactProtobufLocal(fact, version) {
58
58
  return Buffer.from(getWasm().encodeFactProtobuf(json));
59
59
  }
60
60
  function projectFromDecrypted(decrypted) {
61
- let obj;
61
+ let parsed;
62
62
  try {
63
- obj = JSON.parse(decrypted);
63
+ parsed = JSON.parse(decrypted);
64
64
  }
65
65
  catch {
66
66
  return null;
67
67
  }
68
68
  // v1 blob (schema_version "1.x")
69
- if (typeof obj.text === 'string' &&
70
- typeof obj.type === 'string' &&
71
- typeof obj.schema_version === 'string' &&
72
- obj.schema_version.startsWith('1.')) {
69
+ if (typeof parsed.text === 'string' &&
70
+ typeof parsed.type === 'string' &&
71
+ typeof parsed.schema_version === 'string' &&
72
+ parsed.schema_version.startsWith('1.')) {
73
73
  const v1 = readV1Blob(decrypted);
74
74
  if (v1) {
75
75
  return {
@@ -90,18 +90,18 @@ function projectFromDecrypted(decrypted) {
90
90
  }
91
91
  }
92
92
  // v0 short-key blob — upgrade to v1 shape.
93
- if (typeof obj.t === 'string' && typeof obj.c === 'string') {
94
- const v0Type = typeof obj.c === 'string' ? obj.c : 'fact';
93
+ if (typeof parsed.t === 'string' && typeof parsed.c === 'string') {
94
+ const v0Type = typeof parsed.c === 'string' ? parsed.c : 'fact';
95
95
  const v1Type = V0_TO_V1_TYPE[v0Type] ?? 'claim';
96
- const imp = typeof obj.i === 'number' ? obj.i : 5;
97
- const conf = typeof obj.cf === 'number' ? obj.cf : 0.85;
98
- const sa = typeof obj.sa === 'string' ? obj.sa : 'user';
96
+ const imp = typeof parsed.i === 'number' ? parsed.i : 5;
97
+ const conf = typeof parsed.cf === 'number' ? parsed.cf : 0.85;
98
+ const sa = typeof parsed.sa === 'string' ? parsed.sa : 'user';
99
99
  const validSource = ['user', 'user-inferred', 'assistant', 'external', 'derived'].includes(sa)
100
100
  ? sa
101
101
  : 'user';
102
- const ea = typeof obj.ea === 'string' ? obj.ea : new Date().toISOString();
103
- const entities = Array.isArray(obj.e)
104
- ? obj.e
102
+ const ea = typeof parsed.ea === 'string' ? parsed.ea : new Date().toISOString();
103
+ const entities = Array.isArray(parsed.e)
104
+ ? parsed.e
105
105
  .map((e) => {
106
106
  if (!e || typeof e !== 'object')
107
107
  return null;
@@ -116,7 +116,7 @@ function projectFromDecrypted(decrypted) {
116
116
  .filter((e) => e !== null)
117
117
  : undefined;
118
118
  return {
119
- text: typeof obj.t === 'string' ? obj.t : '',
119
+ text: typeof parsed.t === 'string' ? parsed.t : '',
120
120
  type: v1Type,
121
121
  source: validSource,
122
122
  scope: undefined,
@@ -34,8 +34,8 @@
34
34
  * the source of truth; writing back would split it.
35
35
  */
36
36
  import fs from 'node:fs';
37
- import { CONFIG } from './config.js';
38
- import { loadCredentialsJson, writeCredentialsJson, deleteCredentialsFile, } from './fs-helpers.js';
37
+ import { CONFIG } from '../config.js';
38
+ import { loadCredentialsJson, writeCredentialsJson, deleteCredentialsFile, } from '../fs-helpers.js';
39
39
  /**
40
40
  * Default provider — delegates to the existing fs-helpers functions.
41
41
  * Behavior is identical to direct `loadCredentialsJson` / `writeCredentialsJson`
@@ -36,7 +36,7 @@
36
36
  * (`mnemonic`, etc.) are intentionally kept so we do not churn the
37
37
  * crypto code for a copy change.
38
38
  */
39
- import { loadCredentialsJson, extractBootstrapMnemonic } from './fs-helpers.js';
39
+ import { loadCredentialsJson, extractBootstrapMnemonic } from '../fs-helpers.js';
40
40
  // ---------------------------------------------------------------------------
41
41
  // Canonical copy — single source of truth for the welcome-on-first-run UX.
42
42
  // Tests import these constants and assert on exact-match substrings; the
@@ -43,7 +43,7 @@ import path from 'node:path';
43
43
  import readline from 'node:readline/promises';
44
44
  import { generateMnemonic, validateMnemonic } from '@scure/bip39';
45
45
  import { wordlist } from '@scure/bip39/wordlists/english.js';
46
- import { writeCredentialsJson, loadCredentialsJson, writeOnboardingState, loadOnboardingState, } from './fs-helpers.js';
46
+ import { writeCredentialsJson, loadCredentialsJson, writeOnboardingState, loadOnboardingState, } from '../fs-helpers.js';
47
47
  // ---------------------------------------------------------------------------
48
48
  // User-facing strings (centralised so tests can assert on them + localisation
49
49
  // has one place to grow into later).
@@ -499,17 +499,17 @@ export async function runNonInteractiveOnboard(inputs) {
499
499
  scopeAddress = undefined;
500
500
  }
501
501
  }
502
- const result = {
502
+ const onboardResult = {
503
503
  ok: true,
504
504
  action,
505
505
  credentials_path: inputs.credentialsPath,
506
506
  };
507
507
  if (scopeAddress)
508
- result.scope_address = scopeAddress;
508
+ onboardResult.scope_address = scopeAddress;
509
509
  if (inputs.emitPhrase)
510
- result.mnemonic = mnemonic;
510
+ onboardResult.mnemonic = mnemonic;
511
511
  void state; // Touch for clarity — state is persisted via writeCredsAndState.
512
- return result;
512
+ return onboardResult;
513
513
  }
514
514
  // ---------------------------------------------------------------------------
515
515
  // CLI registration
@@ -642,7 +642,7 @@ export function registerOnboardingCli(program, opts) {
642
642
  if (phrase === '-') {
643
643
  phrase = await readAllStdin();
644
644
  }
645
- const result = await runNonInteractiveOnboard({
645
+ const onboardResult = await runNonInteractiveOnboard({
646
646
  credentialsPath: opts.credentialsPath,
647
647
  statePath: opts.statePath,
648
648
  mode,
@@ -655,28 +655,28 @@ export function registerOnboardingCli(program, opts) {
655
655
  // the JSON payload is about to include the plaintext phrase.
656
656
  // stderr is intentional: stdout must remain a single
657
657
  // machine-parseable JSON line.
658
- if (cliOpts.emitPhrase && result.ok && result.mnemonic) {
658
+ if (cliOpts.emitPhrase && onboardResult.ok && onboardResult.mnemonic) {
659
659
  process.stderr.write(PHRASE_PRINT_DEPRECATION_WARNING);
660
660
  }
661
- process.stdout.write(JSON.stringify(result) + '\n');
661
+ process.stdout.write(JSON.stringify(onboardResult) + '\n');
662
662
  }
663
663
  else {
664
- if (result.ok) {
665
- if (result.mnemonic) {
664
+ if (onboardResult.ok) {
665
+ if (onboardResult.mnemonic) {
666
666
  process.stderr.write(PHRASE_PRINT_DEPRECATION_WARNING);
667
667
  process.stderr.write('WARNING: --emit-phrase was set. The plaintext recovery phrase was returned.\n' +
668
668
  'For agent-driven flows, prefer reading ~/.totalreclaw/credentials.json directly ' +
669
669
  'in the user\'s terminal instead of echoing the phrase.\n');
670
670
  }
671
- process.stdout.write(`onboarding: ok action=${result.action} ` +
672
- (result.scope_address ? `scope_address=${result.scope_address} ` : '') +
673
- `credentials=${result.credentials_path}\n`);
671
+ process.stdout.write(`onboarding: ok action=${onboardResult.action} ` +
672
+ (onboardResult.scope_address ? `scope_address=${onboardResult.scope_address} ` : '') +
673
+ `credentials=${onboardResult.credentials_path}\n`);
674
674
  }
675
675
  else {
676
- process.stderr.write(`onboarding: ${result.error}: ${result.error_detail ?? ''}\n`);
676
+ process.stderr.write(`onboarding: ${onboardResult.error}: ${onboardResult.error_detail ?? ''}\n`);
677
677
  }
678
678
  }
679
- process.exit(result.ok ? 0 : 1);
679
+ process.exit(onboardResult.ok ? 0 : 1);
680
680
  }
681
681
  if (cliOpts.json) {
682
682
  process.stderr.write('--json requires --non-interactive. Use: openclaw totalreclaw onboard --non-interactive --json --mode generate\n');
@@ -685,18 +685,18 @@ export function registerOnboardingCli(program, opts) {
685
685
  // Interactive path — original 3.2.0 behaviour preserved in full.
686
686
  const io = buildDefaultIo();
687
687
  try {
688
- const result = await runOnboardingWizard({
688
+ const wizardResult = await runOnboardingWizard({
689
689
  credentialsPath: opts.credentialsPath,
690
690
  statePath: opts.statePath,
691
691
  io,
692
692
  });
693
- if (result.error) {
694
- opts.logger.warn(`onboarding wizard exited with error: ${result.error}`);
693
+ if (wizardResult.error) {
694
+ opts.logger.warn(`onboarding wizard exited with error: ${wizardResult.error}`);
695
695
  io.close();
696
696
  process.exit(1);
697
697
  }
698
- if (result.choice === 'generate' || result.choice === 'import') {
699
- opts.logger.info(`onboarding: state=active createdBy=${result.state?.createdBy}`);
698
+ if (wizardResult.choice === 'generate' || wizardResult.choice === 'import') {
699
+ opts.logger.info(`onboarding: state=active createdBy=${wizardResult.state?.createdBy}`);
700
700
  }
701
701
  }
702
702
  catch (err) {
@@ -45,12 +45,12 @@
45
45
  */
46
46
  import { validateMnemonic } from '@scure/bip39';
47
47
  import { wordlist } from '@scure/bip39/wordlists/english.js';
48
- import { loadCredentialsJson, writeCredentialsJson, writeOnboardingState, } from './fs-helpers.js';
48
+ import { loadCredentialsJson, writeCredentialsJson, writeOnboardingState, } from '../fs-helpers.js';
49
49
  import { awaitPhraseUpload, openRemotePairSession, } from './pair-remote-client.js';
50
- import { setRecoveryPhraseOverride } from './config.js';
50
+ import { setRecoveryPhraseOverride } from '../config.js';
51
51
  import { encodePng, encodeUnicode } from './pair-qr.js';
52
- import { deriveKeys, computeAuthKeyHash } from './crypto.js';
53
- import { createApiClient } from './api-client.js';
52
+ import { deriveKeys, computeAuthKeyHash } from '../crypto/crypto.js';
53
+ import { createApiClient } from '../billing/api-client.js';
54
54
  /**
55
55
  * Run the relay-mode pair CLI. Mirrors `runPairCli`'s exit-code semantics:
56
56
  * - `completed` (status 0)
@@ -214,7 +214,7 @@ export async function runRelayPairCli(mode, opts) {
214
214
  stdout.write(text);
215
215
  };
216
216
  try {
217
- const result = await awaitPhraseUpload(session, {
217
+ const completion = await awaitPhraseUpload(session, {
218
218
  phraseValidator: (p) => validateMnemonic(p, wordlist),
219
219
  completePairing: async ({ mnemonic }) => {
220
220
  try {
@@ -239,8 +239,8 @@ export async function runRelayPairCli(mode, opts) {
239
239
  // serves both protocols on the same host.
240
240
  const httpsBase = opts.relayBaseUrl.replace(/^ws/, 'http').replace(/\/+$/, '');
241
241
  const apiClient = createApiClient(httpsBase);
242
- const result = await apiClient.register(authKeyHash, saltHex);
243
- registeredUserId = result.user_id;
242
+ const registerResult = await apiClient.register(authKeyHash, saltHex);
243
+ registeredUserId = registerResult.user_id;
244
244
  opts.logger.info(`pair-cli (relay): registered user_id=${registeredUserId} (salt + auth-key persisted)`);
245
245
  }
246
246
  catch (regErr) {
@@ -296,12 +296,12 @@ export async function runRelayPairCli(mode, opts) {
296
296
  emitStatus('\nCanceled. Pairing session invalidated.\n');
297
297
  return { status: 'canceled', sid: session.token };
298
298
  }
299
- if (result.state === 'active') {
299
+ if (completion.state === 'active') {
300
300
  emitStatus('\nPairing complete. Account is active.\n');
301
301
  return { status: 'completed', sid: session.token };
302
302
  }
303
- emitStatus(`\nPairing failed: ${result.error ?? 'unknown_error'}\n`);
304
- return { status: 'error', sid: session.token, error: result.error ?? 'unknown_error' };
303
+ emitStatus(`\nPairing failed: ${completion.error ?? 'unknown_error'}\n`);
304
+ return { status: 'error', sid: session.token, error: completion.error ?? 'unknown_error' };
305
305
  }
306
306
  catch (err) {
307
307
  if (canceled) {
@@ -14,4 +14,4 @@
14
14
  * material and nonces are passed in by callers. See vault-crypto.ts for
15
15
  * the implementation.
16
16
  */
17
- export { HKDF_INFO, AEAD_KEY_BYTES, AEAD_NONCE_BYTES, AEAD_TAG_BYTES, X25519_KEY_BYTES, generateGatewayKeypair, derivePublicFromPrivate, computeSharedSecret, deriveSessionKeys, deriveAeadKeyFromEcdh, aeadDecrypt, decryptPairingPayload, aeadEncryptWithSessionKey, encryptPairingPayload, compareSecondaryCodesCT, } from './vault-crypto.js';
17
+ export { HKDF_INFO, AEAD_KEY_BYTES, AEAD_NONCE_BYTES, AEAD_TAG_BYTES, X25519_KEY_BYTES, generateGatewayKeypair, derivePublicFromPrivate, computeSharedSecret, deriveSessionKeys, deriveAeadKeyFromEcdh, aeadDecrypt, decryptPairingPayload, aeadEncryptWithSessionKey, encryptPairingPayload, compareSecondaryCodesCT, } from '../crypto/vault-crypto.js';
@@ -381,7 +381,7 @@ export function buildPairRoutes(cfg) {
381
381
  // sid/mode for log correlation.
382
382
  void (async () => {
383
383
  try {
384
- const result = await awaitPhraseUpload(session, {
384
+ const completion = await awaitPhraseUpload(session, {
385
385
  phraseValidator: validate,
386
386
  timeoutMs: cfg.initAwaitTimeoutMs,
387
387
  completePairing: async ({ mnemonic }) => {
@@ -396,11 +396,11 @@ export function buildPairRoutes(cfg) {
396
396
  return cfg.completePairing({ mnemonic, session: sessionLike });
397
397
  },
398
398
  });
399
- if (result.state === 'active') {
399
+ if (completion.state === 'active') {
400
400
  cfg.logger.info(`pair-http /init: session ${redactSid(session.token)} completed in-process; onboarding active`);
401
401
  }
402
402
  else {
403
- cfg.logger.warn(`pair-http /init: session ${redactSid(session.token)} completion non-active: ${result.error ?? 'unknown'}`);
403
+ cfg.logger.warn(`pair-http /init: session ${redactSid(session.token)} completion non-active: ${completion.error ?? 'unknown'}`);
404
404
  }
405
405
  }
406
406
  catch (err) {
@@ -158,9 +158,9 @@ export async function openRemotePairSession(opts = {}) {
158
158
  const text = typeof raw === 'string' ? raw : Buffer.from(raw).toString('utf-8');
159
159
  msg = JSON.parse(text);
160
160
  }
161
- catch {
161
+ catch (err) {
162
162
  safeClose(ws);
163
- throw new Error('pair-remote-client: opened frame not valid JSON');
163
+ throw new Error('pair-remote-client: opened frame not valid JSON', { cause: err });
164
164
  }
165
165
  if (msg.type === 'error') {
166
166
  const errStr = typeof msg.error === 'string' ? msg.error : 'relay_error';
@@ -220,10 +220,10 @@ export async function awaitPhraseUpload(session, opts) {
220
220
  const text = typeof raw === 'string' ? raw : Buffer.from(raw).toString('utf-8');
221
221
  msg = JSON.parse(text);
222
222
  }
223
- catch {
223
+ catch (err) {
224
224
  safeSend(ws, { type: 'nack', error: 'bad_json' });
225
225
  safeClose(ws);
226
- throw new Error('pair-remote-client: forward frame not valid JSON');
226
+ throw new Error('pair-remote-client: forward frame not valid JSON', { cause: err });
227
227
  }
228
228
  if (msg.type !== 'forward') {
229
229
  safeSend(ws, { type: 'nack', error: 'expected_forward' });
@@ -281,9 +281,9 @@ export async function awaitPhraseUpload(session, opts) {
281
281
  }
282
282
  // Hand off to the caller-supplied completion handler. Wrapped in try/finally
283
283
  // so we always drop our own reference to the mnemonic.
284
- let result;
284
+ let completion;
285
285
  try {
286
- result = await opts.completePairing({ mnemonic, session });
286
+ completion = await opts.completePairing({ mnemonic, session });
287
287
  }
288
288
  catch (err) {
289
289
  safeSend(ws, { type: 'nack', error: 'completion_failed' });
@@ -295,14 +295,14 @@ export async function awaitPhraseUpload(session, opts) {
295
295
  // rebinding at least drops the reference from this closure.
296
296
  mnemonic = '';
297
297
  }
298
- if (result.state !== 'active') {
299
- safeSend(ws, { type: 'nack', error: result.error ?? 'completion_failed' });
298
+ if (completion.state !== 'active') {
299
+ safeSend(ws, { type: 'nack', error: completion.error ?? 'completion_failed' });
300
300
  safeClose(ws);
301
- return result;
301
+ return completion;
302
302
  }
303
303
  safeSend(ws, { type: 'ack' });
304
304
  safeClose(ws);
305
- return result;
305
+ return completion;
306
306
  }
307
307
  /**
308
308
  * One-shot convenience: open session + await phrase upload + run completion.
@@ -428,17 +428,17 @@ export async function updatePairSession(sessionsPath, sid, mutate, now = Date.no
428
428
  }
429
429
  const current = pruned.file.sessions[idx];
430
430
  const next = mutate(current);
431
- let result;
431
+ let mutatedSession;
432
432
  if (next === null) {
433
433
  pruned.file.sessions.splice(idx, 1);
434
- result = null;
434
+ mutatedSession = null;
435
435
  }
436
436
  else {
437
437
  pruned.file.sessions[idx] = next;
438
- result = next;
438
+ mutatedSession = next;
439
439
  }
440
440
  writePairSessionsFileSync(sessionsPath, pruned.file);
441
- return result;
441
+ return mutatedSession;
442
442
  }
443
443
  finally {
444
444
  release();
@@ -0,0 +1,59 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Plugin configSchema — static JSON-schema for the OpenClaw plugin config.
3
+ // Extracted from index.ts; pure data, no runtime state.
4
+ // ---------------------------------------------------------------------------
5
+ export const CONFIG_SCHEMA = {
6
+ type: 'object',
7
+ additionalProperties: false,
8
+ properties: {
9
+ publicUrl: {
10
+ type: 'string',
11
+ description: "Public gateway URL for QR pairing (e.g. 'https://gateway.example.com:18789'). Overrides the auto-resolution cascade in buildPairingUrl.",
12
+ },
13
+ extraction: {
14
+ type: 'object',
15
+ additionalProperties: false,
16
+ properties: {
17
+ enabled: {
18
+ type: 'boolean',
19
+ description: 'Enable/disable auto-extraction (default: true)',
20
+ },
21
+ model: {
22
+ type: 'string',
23
+ description: "Shorthand: override just the extraction model (e.g., 'glm-4.5-flash', 'gpt-4.1-mini'). For a full provider override use extraction.llm.",
24
+ },
25
+ interval: {
26
+ type: 'number',
27
+ description: 'Number of turns between automatic extractions (default: 3)',
28
+ },
29
+ maxFactsPerExtraction: {
30
+ type: 'number',
31
+ description: 'Hard cap on facts extracted per turn (default: 15)',
32
+ },
33
+ llm: {
34
+ type: 'object',
35
+ additionalProperties: false,
36
+ description: 'Explicit LLM override block. Highest-priority tier in the extraction-provider cascade. Any subset of provider+apiKey is enough to pin a provider.',
37
+ properties: {
38
+ provider: {
39
+ type: 'string',
40
+ description: "Provider name: zai | openai | anthropic | gemini | google | mistral | groq | deepseek | openrouter | xai | together | cerebras.",
41
+ },
42
+ model: {
43
+ type: 'string',
44
+ description: 'Explicit model id. If omitted, deriveCheapModel(provider) picks a sensible default.',
45
+ },
46
+ apiKey: {
47
+ type: 'string',
48
+ description: 'API key for the selected provider. Required for the override to take effect.',
49
+ },
50
+ baseUrl: {
51
+ type: 'string',
52
+ description: 'Override the provider base URL (self-hosted / custom gateway setups).',
53
+ },
54
+ },
55
+ },
56
+ },
57
+ },
58
+ },
59
+ };