log-llm-config-staging 1.3.96 → 1.3.97

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.
@@ -7,6 +7,7 @@ import { enrichRawFromRecipe } from './enrichment_helpers.js';
7
7
  import { collectDirectoryEntries, collectDirectoryMetadata } from './directory_collector.js';
8
8
  import { collectVscdbEntries } from '../readers/vscdb_config_builder.js';
9
9
  import { pushDerivedFilesFromRecipe } from './openclaw_helpers.js';
10
+ import { collapseMetadataByFileType } from './metadata_merge.js';
10
11
  function buildCollectionContext(patterns, projectRoot, home, homeRecurseSkipDirs = [], absolutePathPrefixes = [], mcpToolGlobSpec = null, clientPathConstants = null, pathResolutionSpecs = null) {
11
12
  const seenPaths = new Set();
12
13
  const targets = [];
@@ -148,7 +149,7 @@ function collectConfigFilesFromPatterns(patterns, projectRoot, onProgress, optio
148
149
  pushDerivedFilesFromRecipe(entry.raw_content, configFiles, recipe);
149
150
  }
150
151
  }
151
- return configFiles;
152
+ return collapseMetadataByFileType(configFiles);
152
153
  }
153
154
  // ─── Re-exports (barrel for public API) ──────────────────────────────────────
154
155
  export { collectConfigFilesFromPatterns };
@@ -57,6 +57,8 @@ function matchesDirGlob(name, glob) {
57
57
  // **/*.jsonl → match any extension suffix after **/
58
58
  if (glob.startsWith('**/')) {
59
59
  const suffix = glob.slice(3);
60
+ if (suffix === '*' || suffix === '**')
61
+ return true;
60
62
  if (suffix.startsWith('*.'))
61
63
  return name.endsWith(suffix.slice(1));
62
64
  return name === suffix;
@@ -0,0 +1,43 @@
1
+ /** When several install/log paths exist for one agent, keep a single metadata row (newest mtime). */
2
+ const METADATA_COLLAPSE_BY_FILE_TYPE = new Set(['opencode_presence', 'opencode_log']);
3
+ function metadataLastModifiedMs(entry) {
4
+ const raw = entry.raw_content;
5
+ if (!raw || typeof raw !== 'object')
6
+ return 0;
7
+ const lm = raw.last_modified;
8
+ if (typeof lm !== 'string')
9
+ return 0;
10
+ const ms = Date.parse(lm);
11
+ return Number.isFinite(ms) ? ms : 0;
12
+ }
13
+ /**
14
+ * Collapse multiple metadata uploads of the same file_type to one row: highest last_modified wins.
15
+ */
16
+ function collapseMetadataByFileType(files) {
17
+ const passthrough = [];
18
+ const groups = new Map();
19
+ for (const f of files) {
20
+ if (f.collect_style === 'metadata' && METADATA_COLLAPSE_BY_FILE_TYPE.has(f.file_type)) {
21
+ const list = groups.get(f.file_type) ?? [];
22
+ list.push(f);
23
+ groups.set(f.file_type, list);
24
+ }
25
+ else {
26
+ passthrough.push(f);
27
+ }
28
+ }
29
+ const merged = [...passthrough];
30
+ for (const [, list] of groups) {
31
+ if (list.length === 0)
32
+ continue;
33
+ let best = list[0];
34
+ for (let i = 1; i < list.length; i++) {
35
+ if (metadataLastModifiedMs(list[i]) > metadataLastModifiedMs(best)) {
36
+ best = list[i];
37
+ }
38
+ }
39
+ merged.push(best);
40
+ }
41
+ return merged;
42
+ }
43
+ export { collapseMetadataByFileType, METADATA_COLLAPSE_BY_FILE_TYPE };
@@ -41,6 +41,8 @@ export function normalizeAgentToken(raw) {
41
41
  return 'cursor';
42
42
  if (s === 'copilot')
43
43
  return 'copilot';
44
+ if (s === 'opencode')
45
+ return 'opencode';
44
46
  return '';
45
47
  }
46
48
  function currentAgentFromEnv() {
@@ -48,12 +50,14 @@ function currentAgentFromEnv() {
48
50
  const override = normalizeAgentToken(process.env.OPTIMUS_AGENT);
49
51
  if (override)
50
52
  return override;
51
- // Backwards-compatible: hook wrappers set OPTIMUS_HOOK_TYPE to cursor|claude|copilot.
53
+ // Backwards-compatible: hook wrappers set OPTIMUS_HOOK_TYPE to cursor|claude|copilot|opencode.
52
54
  const hookType = normalizeAgentToken(process.env.OPTIMUS_HOOK_TYPE);
53
55
  if (hookType === 'cursor')
54
56
  return 'cursor';
55
57
  if (hookType === 'copilot')
56
58
  return 'copilot';
59
+ if (hookType === 'opencode')
60
+ return 'opencode';
57
61
  return 'claude';
58
62
  }
59
63
  function targetsCurrentAgent(entry, agent) {
@@ -0,0 +1,28 @@
1
+ function normalizeToken(raw) {
2
+ if (!raw?.trim())
3
+ return '';
4
+ const s = raw.trim().toLowerCase().replace(/-/g, '_');
5
+ if (s === 'claude_desktop')
6
+ return 'claude';
7
+ if (s === 'github_copilot')
8
+ return 'copilot';
9
+ if (s === 'cursor' || s === 'claude' || s === 'copilot' || s === 'opencode')
10
+ return s;
11
+ // Legacy hooks set OPTIMUS_AGENT=Cursor (display casing)
12
+ if (raw.trim() === 'Cursor')
13
+ return 'cursor';
14
+ return s;
15
+ }
16
+ /** Resolve hook_request.hook_type from hook wrapper env (OPTIMUS_HOOK_TYPE, then OPTIMUS_AGENT). */
17
+ export function resolveHookTypeFromEnv(env = process.env) {
18
+ const fromHook = normalizeToken(env.OPTIMUS_HOOK_TYPE);
19
+ const fromAgent = normalizeToken(env.OPTIMUS_AGENT);
20
+ const token = fromHook || fromAgent || 'claude';
21
+ if (token === 'cursor')
22
+ return 'cursor';
23
+ if (token === 'copilot')
24
+ return 'copilot';
25
+ if (token === 'opencode')
26
+ return 'opencode';
27
+ return 'claude';
28
+ }
@@ -7,6 +7,7 @@ import { OPT_AI_SEC_MANAGEMENT_REL } from '../../bootstrap_constants.js';
7
7
  import { runSensitivePathsAudit } from '../../log_sensitive_paths_audit.js';
8
8
  import { loadEndpointBase, getEndpointSource } from '../sender/endpoint_config.js';
9
9
  import { hookLogReplace, hookRunLog } from './hook_logger.js';
10
+ import { resolveHookTypeFromEnv } from './hook_type_for_request.js';
10
11
  import { resolveHardwareUuid } from './hardware_uuid.js';
11
12
  import { ensureAuthentication } from '../auth/auth_flow.js';
12
13
  import { readJSONFile, readMarkdownFile } from '../readers/file_readers.js';
@@ -128,8 +129,7 @@ async function addSensitivePathsAudit(endpointBase, configFiles) {
128
129
  }
129
130
  }
130
131
  async function sendAllConfigFiles(configFiles, worktreeReport, hardwareUuid, authKey) {
131
- const hookTypeRaw = (process.env.OPTIMUS_HOOK_TYPE || 'claude').toLowerCase();
132
- const hookType = hookTypeRaw === 'cursor' ? 'cursor' : hookTypeRaw === 'copilot' ? 'copilot' : 'claude';
132
+ const hookType = resolveHookTypeFromEnv();
133
133
  const manifest = configFiles.map((c) => canonicalCursorUserStateVscdbPath(c.file_path));
134
134
  const workspaceRepo = ensureWorkspaceRepoEnv(manifest);
135
135
  const hookRequestId = await sendHookRequestCreate(hardwareUuid, authKey, hookType, workspaceRepo);
@@ -34,6 +34,8 @@ function currentAgentFromEnv() {
34
34
  return 'cursor';
35
35
  if (override === 'copilot')
36
36
  return 'copilot';
37
+ if (override === 'opencode')
38
+ return 'opencode';
37
39
  if (override === 'claude' || override === 'claude_desktop')
38
40
  return 'claude';
39
41
  const hookType = normalizeAgentToken(process.env.OPTIMUS_HOOK_TYPE);
@@ -41,6 +43,8 @@ function currentAgentFromEnv() {
41
43
  return 'cursor';
42
44
  if (hookType === 'copilot')
43
45
  return 'copilot';
46
+ if (hookType === 'opencode')
47
+ return 'opencode';
44
48
  return 'claude';
45
49
  }
46
50
  /** Spawn each trusted command detached (same pattern as former compliance_prompt_gate fireRestartCommands). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "log-llm-config-staging",
3
- "version": "1.3.96",
3
+ "version": "1.3.97",
4
4
  "description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
5
5
  "type": "module",
6
6
  "bin": {