log-llm-config-staging 1.3.44

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 (51) hide show
  1. package/README.md +46 -0
  2. package/dist/apply_deferred_vscdb.js +8 -0
  3. package/dist/bootstrap_constants.js +5 -0
  4. package/dist/cli/bash_script_generator.js +95 -0
  5. package/dist/cli.js +103 -0
  6. package/dist/cli_invocation_match.js +28 -0
  7. package/dist/compliance_check_runner.js +17 -0
  8. package/dist/compliance_prompt_gate.js +197 -0
  9. package/dist/endpoint_client/http_transport.js +88 -0
  10. package/dist/endpoint_client/index.js +3 -0
  11. package/dist/endpoint_client/registry_api.js +41 -0
  12. package/dist/endpoint_client/startup_api.js +43 -0
  13. package/dist/endpoint_client/types.js +4 -0
  14. package/dist/execute_trusted_restarts.js +54 -0
  15. package/dist/log_config_files/auth/auth_flow.js +22 -0
  16. package/dist/log_config_files/auth/auth_key_store.js +14 -0
  17. package/dist/log_config_files/collection/config_collector.js +160 -0
  18. package/dist/log_config_files/collection/directory_collector.js +96 -0
  19. package/dist/log_config_files/collection/enrichment_helpers.js +53 -0
  20. package/dist/log_config_files/collection/file_type_rules.js +47 -0
  21. package/dist/log_config_files/collection/mcp_tool_collector.js +37 -0
  22. package/dist/log_config_files/collection/openclaw_helpers.js +55 -0
  23. package/dist/log_config_files/collection/plugin_collector.js +89 -0
  24. package/dist/log_config_files/collection/plugin_version_helpers.js +37 -0
  25. package/dist/log_config_files/index.js +19 -0
  26. package/dist/log_config_files/paths/path_constants_helpers.js +71 -0
  27. package/dist/log_config_files/paths/pattern_resolver.js +227 -0
  28. package/dist/log_config_files/readers/file_readers.js +69 -0
  29. package/dist/log_config_files/readers/vscdb_config_builder.js +146 -0
  30. package/dist/log_config_files/readers/vscdb_reader.js +247 -0
  31. package/dist/log_config_files/runtime/compliance_check.js +518 -0
  32. package/dist/log_config_files/runtime/hardware_uuid.js +36 -0
  33. package/dist/log_config_files/runtime/hook_logger.js +197 -0
  34. package/dist/log_config_files/runtime/main_runner.js +192 -0
  35. package/dist/log_config_files/runtime/management_storage.js +82 -0
  36. package/dist/log_config_files/runtime/remediation_config_path.js +90 -0
  37. package/dist/log_config_files/runtime/remediation_sync.js +1290 -0
  38. package/dist/log_config_files/runtime/sqlite_binary.js +92 -0
  39. package/dist/log_config_files/runtime/trusted_restarts.js +52 -0
  40. package/dist/log_config_files/sender/batch_sender.js +220 -0
  41. package/dist/log_config_files/sender/endpoint_config.js +24 -0
  42. package/dist/log_config_files/sender/signing.js +1 -0
  43. package/dist/log_sensitive_paths_audit.js +97 -0
  44. package/dist/log_uuid/auth_key_store.js +71 -0
  45. package/dist/log_uuid/hardware_uuid.js +35 -0
  46. package/dist/log_uuid/index.js +11 -0
  47. package/dist/log_uuid/log_uuid_helper.js +30 -0
  48. package/dist/log_uuid/startup_sender.js +74 -0
  49. package/dist/log_uuid/user_profile.js +178 -0
  50. package/dist/types/config_file_types.js +1 -0
  51. package/package.json +62 -0
@@ -0,0 +1,247 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { execFileSync } from 'node:child_process';
3
+ import { resolveSqlite3Binary } from '../runtime/sqlite_binary.js';
4
+ import { readFileCollectionVscdbContract, writeFileCollectionVscdbContract, } from '../runtime/management_storage.js';
5
+ /**
6
+ * ItemTable keys that store a bare JSON boolean; compliance paths use `${key}.${field}`.
7
+ * Kept in sync with `coerceItemTableValueToObjectRoot` / `serializeItemTableValueForWrite` in remediation_sync.
8
+ */
9
+ export const CURSOR_SCALAR_ITEMTABLE_FIELDS = {
10
+ 'cursor/thirdPartyExtensibilityEnabled': 'thirdPartyExtensibilityEnabled',
11
+ 'cursorai/donotchange/privacyMode': 'privacyMode',
12
+ 'cursor/autoOpenLocalhostUrls': 'autoOpenLocalhostUrls',
13
+ };
14
+ function querySqlite(dbPath, key) {
15
+ const bin = resolveSqlite3Binary();
16
+ if (!bin)
17
+ throw new Error('sqlite3 not found');
18
+ const safe = key.replace(/'/g, "''");
19
+ const script = `.timeout 60000\nSELECT value FROM ItemTable WHERE key='${safe}';\n`;
20
+ return execFileSync(bin, ['-noheader', dbPath], {
21
+ input: script,
22
+ encoding: 'utf8',
23
+ stdio: ['pipe', 'pipe', 'pipe'],
24
+ }).trim();
25
+ }
26
+ /**
27
+ * Fallback if the API omits vscdb_composer_contract (older server): derive from vscdb_read_queries.
28
+ */
29
+ export function parseVscdbComposerContractFromReadQueries(queries) {
30
+ const empty = {
31
+ version: 1,
32
+ reactive_storage_item_key: undefined,
33
+ composer_shadow_keys: [],
34
+ };
35
+ if (!queries?.length)
36
+ return empty;
37
+ for (const step of queries) {
38
+ if (step.value_kind === 'composer_with_include' && step.state_key === 'composerState') {
39
+ const keys = step.item_table_keys ?? [];
40
+ return {
41
+ version: 1,
42
+ reactive_storage_item_key: keys[0],
43
+ composer_shadow_keys: [...(step.include_keys ?? [])],
44
+ };
45
+ }
46
+ }
47
+ return empty;
48
+ }
49
+ export function normalizeVscdbComposerContractFromPatternsResponse(resp) {
50
+ const c = resp.vscdb_composer_contract;
51
+ const hasKey = c != null &&
52
+ ((typeof c.reactive_storage_item_key === 'string' && c.reactive_storage_item_key.trim() !== '') ||
53
+ (c.composer_shadow_keys?.length ?? 0) > 0);
54
+ if (hasKey && c) {
55
+ return {
56
+ version: 1,
57
+ reactive_storage_item_key: c.reactive_storage_item_key ?? undefined,
58
+ composer_shadow_keys: [...(c.composer_shadow_keys ?? [])],
59
+ };
60
+ }
61
+ return parseVscdbComposerContractFromReadQueries(resp.vscdb_read_queries);
62
+ }
63
+ /** Persist backend-derived contract next to remediation_instructions.json. */
64
+ export function persistVscdbComposerContractFromPatternsResponse(resp) {
65
+ const norm = normalizeVscdbComposerContractFromPatternsResponse(resp);
66
+ if (norm.reactive_storage_item_key || norm.composer_shadow_keys.length > 0) {
67
+ writeFileCollectionVscdbContract(norm);
68
+ }
69
+ }
70
+ /**
71
+ * Read one ItemTable JSON blob (e.g. key `composerState`) and return `{ [itemKey]: object }` so
72
+ * dot-paths like `composerState.modes4.agent.autoRun` (or legacy numeric `modes4.0`) work in compliance checks. Empty / missing value
73
+ * yields `{ [itemKey]: {} }`. Returns null if the DB is missing, sqlite3 is unavailable, or JSON parse fails.
74
+ *
75
+ * When `file_collection_vscdb_contract.json` lists `reactive_storage_item_key`, a missing legacy `composerState` row
76
+ * falls back to nested `composerState` inside that reactive blob (paths from the backend API only).
77
+ */
78
+ export function readVscdbItemTableJson(dbPath, itemKey) {
79
+ try {
80
+ if (!dbPath || !existsSync(dbPath))
81
+ return null;
82
+ if (!resolveSqlite3Binary())
83
+ return null;
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ try {
89
+ const raw = querySqlite(dbPath, itemKey);
90
+ const contract = readFileCollectionVscdbContract();
91
+ const reactiveKey = typeof contract?.reactive_storage_item_key === 'string' ? contract.reactive_storage_item_key.trim() : '';
92
+ if (itemKey === 'composerState' && (!raw || raw === '{}') && reactiveKey) {
93
+ const reactive = querySqlite(dbPath, reactiveKey);
94
+ if (reactive) {
95
+ const root = JSON.parse(reactive);
96
+ const cs = root.composerState;
97
+ if (cs !== null && typeof cs === 'object' && !Array.isArray(cs)) {
98
+ return { composerState: cs };
99
+ }
100
+ }
101
+ }
102
+ if (!raw) {
103
+ return { [itemKey]: {} };
104
+ }
105
+ const parsed = JSON.parse(raw);
106
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
107
+ return { [itemKey]: parsed };
108
+ }
109
+ // Bare JSON primitives. Scalar toggles must be wrapped so getByPath(key.field) works in compliance checks.
110
+ // Match coerceScalarForItemTableField in remediation_sync: Cursor may store toggles as JSON 0/1, not only booleans.
111
+ if (typeof parsed === 'boolean' || typeof parsed === 'number' || typeof parsed === 'string') {
112
+ const field = CURSOR_SCALAR_ITEMTABLE_FIELDS[itemKey];
113
+ if (field) {
114
+ if (typeof parsed === 'boolean') {
115
+ return { [itemKey]: { [field]: parsed } };
116
+ }
117
+ if (typeof parsed === 'number' && !Number.isNaN(parsed)) {
118
+ return { [itemKey]: { [field]: parsed !== 0 } };
119
+ }
120
+ if (typeof parsed === 'string') {
121
+ const lower = parsed.trim().toLowerCase();
122
+ return {
123
+ [itemKey]: { [field]: lower === 'true' || lower === '1' || lower === 'yes' },
124
+ };
125
+ }
126
+ }
127
+ return { [itemKey]: parsed };
128
+ }
129
+ return { [itemKey]: {} };
130
+ }
131
+ catch {
132
+ return null;
133
+ }
134
+ }
135
+ function setNested(obj, dotPath, value) {
136
+ const parts = dotPath.split('.');
137
+ const safe = (k) => k !== '__proto__' && k !== 'constructor' && k !== 'prototype';
138
+ if (!parts.every(safe))
139
+ return;
140
+ let cur = obj;
141
+ for (let i = 0; i < parts.length - 1; i++) {
142
+ const p = parts[i];
143
+ if (!(p in cur) || typeof cur[p] !== 'object')
144
+ cur[p] = Object.create(null);
145
+ cur = cur[p];
146
+ }
147
+ cur[parts[parts.length - 1]] = value;
148
+ }
149
+ function runOneStep(dbPath, stateData, step) {
150
+ for (const key of step.item_table_keys) {
151
+ try {
152
+ const result = querySqlite(dbPath, key);
153
+ if (!result)
154
+ continue;
155
+ if (step.value_kind === 'boolean') {
156
+ const lower = result.toLowerCase();
157
+ setNested(stateData, step.state_key, lower === 'true' || lower === '1' || lower === 'yes');
158
+ return;
159
+ }
160
+ const parsed = JSON.parse(result);
161
+ if (step.value_kind === 'composer_with_include') {
162
+ if (!parsed || typeof parsed !== 'object')
163
+ continue;
164
+ const obj = parsed;
165
+ const composerState = (obj.composerState ?? obj);
166
+ if (composerState && typeof composerState === 'object') {
167
+ stateData.composerState = composerState;
168
+ }
169
+ if (step.include_keys?.length) {
170
+ const nested = composerState && typeof composerState === 'object'
171
+ ? composerState
172
+ : undefined;
173
+ for (const k of step.include_keys) {
174
+ // Prefer the value inside composerState when present; blob root can be stale vs the UI.
175
+ if (nested && k in nested && nested[k] !== undefined) {
176
+ stateData[k] = nested[k];
177
+ }
178
+ else if (k in obj && obj[k] !== undefined) {
179
+ stateData[k] = obj[k];
180
+ }
181
+ }
182
+ }
183
+ return;
184
+ }
185
+ if (step.value_kind === 'json_array_or_object') {
186
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
187
+ setNested(stateData, step.state_key, Object.keys(parsed));
188
+ }
189
+ else if (Array.isArray(parsed)) {
190
+ setNested(stateData, step.state_key, parsed);
191
+ }
192
+ return;
193
+ }
194
+ if (step.value_kind === 'json') {
195
+ if (parsed !== null && typeof parsed === 'object') {
196
+ setNested(stateData, step.state_key, parsed);
197
+ }
198
+ return;
199
+ }
200
+ }
201
+ catch {
202
+ continue;
203
+ }
204
+ }
205
+ }
206
+ function mergeFromComposerState(stateData, mergeKeys) {
207
+ const composer = stateData.composerState;
208
+ if (!composer || typeof composer !== 'object')
209
+ return;
210
+ const composerState = composer;
211
+ for (const key of mergeKeys) {
212
+ if (key in stateData && stateData[key] !== undefined)
213
+ continue;
214
+ if (key in composerState && composerState[key] !== undefined) {
215
+ stateData[key] = composerState[key];
216
+ }
217
+ }
218
+ }
219
+ /**
220
+ * Read state from a vscdb file using backend-driven queries only (no hardcoded keys).
221
+ * dbPath must be provided (e.g. from API client_path_constants via getVscdbPath); no default path.
222
+ * Constants come from API vscdb_read_queries and vscdb_merge_from_composer_state (backend utils/queries.py).
223
+ */
224
+ export function readVSCDBState(dbPath, readQueries, mergeFromComposerStateKeys) {
225
+ try {
226
+ if (!dbPath || !existsSync(dbPath))
227
+ return null;
228
+ if (!resolveSqlite3Binary()) {
229
+ console.warn('sqlite3 command not found; skipping vscdb reading');
230
+ return null;
231
+ }
232
+ if (!readQueries?.length)
233
+ return null;
234
+ const stateData = {};
235
+ for (const step of readQueries) {
236
+ runOneStep(dbPath, stateData, step);
237
+ }
238
+ if (mergeFromComposerStateKeys?.length) {
239
+ mergeFromComposerState(stateData, mergeFromComposerStateKeys);
240
+ }
241
+ return Object.keys(stateData).length > 0 ? stateData : null;
242
+ }
243
+ catch (error) {
244
+ console.error(`Error reading vscdb:`, error instanceof Error ? error.message : String(error));
245
+ return null;
246
+ }
247
+ }