Download scripts/generate-env-help-registry.js from tostido/Champion_Council_private: direct link, hf CLI and curl.
- Browser
- Download file 56.3 kB
-
https://huggingface.co/spaces/tostido/Champion_Council_private/resolve/main/scripts/generate-env-help-registry.js
- Command line
-
hf download hf://spaces/tostido/Champion_Council_private/scripts/generate-env-help-registry.js
-
curl -L -o generate-env-help-registry.js https://huggingface.co/spaces/tostido/Champion_Council_private/resolve/main/scripts/generate-env-help-registry.js
56.3 kB
| const fs = require('fs'); | |
| const path = require('path'); | |
| function parseArgs(argv) { | |
| const out = {}; | |
| for (let i = 0; i < argv.length; i += 1) { | |
| const token = String(argv[i] || ''); | |
| if (!token.startsWith('--')) continue; | |
| const key = token.slice(2); | |
| const next = argv[i + 1]; | |
| if (next === undefined || String(next).startsWith('--')) out[key] = true; | |
| else { | |
| out[key] = next; | |
| i += 1; | |
| } | |
| } | |
| return out; | |
| } | |
| function titleCase(value) { | |
| return String(value || '') | |
| .replace(/[_-]+/g, ' ') | |
| .replace(/\s+/g, ' ') | |
| .trim() | |
| .split(' ') | |
| .filter(Boolean) | |
| .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) | |
| .join(' '); | |
| } | |
| function nounPhrase(value) { | |
| return String(value || '') | |
| .replace(/[_-]+/g, ' ') | |
| .replace(/\s+/g, ' ') | |
| .trim() | |
| .toLowerCase(); | |
| } | |
| function extractQuotedStrings(block) { | |
| const out = []; | |
| const regex = /'([^']+)'|"([^"]+)"/g; | |
| let match = regex.exec(block); | |
| while (match) { | |
| out.push(String(match[1] || match[2] || '').trim()); | |
| match = regex.exec(block); | |
| } | |
| return out.filter(Boolean); | |
| } | |
| function extractFrozenset(text, symbolName) { | |
| const regex = new RegExp(`${symbolName}\\s*=\\s*frozenset\\(\\{([\\s\\S]*?)\\}\\)`, 'm'); | |
| const match = text.match(regex); | |
| return match ? extractQuotedStrings(match[1]) : []; | |
| } | |
| function extractJsArray(text, propertyName, nextPropertyName) { | |
| const escapedProperty = propertyName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| const escapedNext = nextPropertyName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| const regex = new RegExp(`${escapedProperty}\\s*:\\s*\\[([\\s\\S]*?)\\]\\s*,\\s*${escapedNext}`, 'm'); | |
| const match = text.match(regex); | |
| return match ? extractQuotedStrings(match[1]) : []; | |
| } | |
| function findCommandAnchors(text, filePath) { | |
| const anchors = new Map(); | |
| const lines = text.split(/\r?\n/); | |
| const patterns = [ | |
| { kind: 'handler', regex: /if\s*\(\s*command\s*===\s*'([^']+)'\s*\)/ }, | |
| { kind: 'handler', regex: /if\s*\(\s*command\s*===\s*"([^"]+)"\s*\)/ }, | |
| { kind: 'bridge', regex: /_envQueueControl\(\s*'([^']+)'/ }, | |
| { kind: 'bridge', regex: /_envQueueControl\(\s*"([^"]+)"/ }, | |
| ]; | |
| lines.forEach((line, index) => { | |
| patterns.forEach((pattern) => { | |
| const match = line.match(pattern.regex); | |
| if (!match) return; | |
| const command = String(match[1] || '').trim(); | |
| if (!command) return; | |
| if (!anchors.has(command)) anchors.set(command, []); | |
| const rows = anchors.get(command); | |
| if (rows.some((row) => row.line === index + 1 && row.kind === pattern.kind)) return; | |
| rows.push({ | |
| file: filePath, | |
| line: index + 1, | |
| kind: pattern.kind, | |
| }); | |
| }); | |
| }); | |
| return anchors; | |
| } | |
| function findActionAnchors(text, filePath) { | |
| const anchors = new Map(); | |
| const lines = text.split(/\r?\n/); | |
| const patterns = [ | |
| { kind: 'ui_action', regex: /if\s*\(\s*action\s*===\s*'([^']+)'\s*\)/ }, | |
| { kind: 'ui_action', regex: /if\s*\(\s*action\s*===\s*"([^"]+)"\s*\)/ }, | |
| { kind: 'ui_entrypoint', regex: /data-env-action="([^"]+)"/ }, | |
| { kind: 'ui_entrypoint', regex: /data-env-action='([^']+)'/ }, | |
| ]; | |
| lines.forEach((line, index) => { | |
| patterns.forEach((pattern) => { | |
| const match = line.match(pattern.regex); | |
| if (!match) return; | |
| const action = String(match[1] || '').trim(); | |
| if (!action) return; | |
| if (!anchors.has(action)) anchors.set(action, []); | |
| const rows = anchors.get(action); | |
| if (rows.some((row) => row.line === index + 1 && row.kind === pattern.kind)) return; | |
| rows.push({ | |
| file: filePath, | |
| line: index + 1, | |
| kind: pattern.kind, | |
| }); | |
| }); | |
| }); | |
| return anchors; | |
| } | |
| function mergeObjects(base, override) { | |
| if (override === undefined) return base; | |
| if (Array.isArray(base) || Array.isArray(override)) return override; | |
| if (!base || typeof base !== 'object' || !override || typeof override !== 'object') return override; | |
| const out = { ...base }; | |
| Object.keys(override).forEach((key) => { | |
| out[key] = key in out ? mergeObjects(out[key], override[key]) : override[key]; | |
| }); | |
| return out; | |
| } | |
| function normalizeActionToCommand(action) { | |
| return String(action || '').trim().replace(/-/g, '_'); | |
| } | |
| function dedupeList(values) { | |
| return Array.from(new Set((values || []).filter(Boolean).map((item) => String(item).trim()).filter(Boolean))); | |
| } | |
| function familyForCommand(command) { | |
| if (command.startsWith('camera_')) return 'camera_pose'; | |
| if (command.startsWith('capture_')) return 'capture_observer'; | |
| if (command.startsWith('surface_') || ['focus_surface', 'inspect_surface', 'open_surface', 'close_surface', 'close_inspector', 'open_doc_memory'].includes(command)) { | |
| return 'surface_bridge'; | |
| } | |
| if (command.startsWith('character_') || ['spawn_inhabitant', 'despawn_inhabitant', 'focus_inhabitant', 'toggle_inhabitant_fov_debug'].includes(command)) { | |
| return 'character_runtime'; | |
| } | |
| if ( | |
| command === 'workbench_play_authored_clip' | |
| || command === 'workbench_compile_clip' | |
| || command === 'workbench_set_timeline_cursor' | |
| || command === 'workbench_assert_balance' | |
| || command === 'workbench_capture_pose' | |
| || command === 'workbench_delete_pose' | |
| || command === 'workbench_apply_pose' | |
| ) return 'builder_motion'; | |
| if (command.startsWith('workbench_')) return 'builder_workbench'; | |
| if ( | |
| command.startsWith('focus_') | |
| || command.startsWith('replay_') | |
| || ['follow_failed', 'sample_now', 'toggle_stream', 'toggle_replay', 'branch_snapshot'].includes(command) | |
| ) return 'focus_navigation'; | |
| if (['activate_profile', 'run_recipe', 'scan_docs', 'set_theater_mode', 'set_camera_mode', 'set_replay_mode'].includes(command)) { | |
| return 'theater_profile_recipe'; | |
| } | |
| return 'environment_misc'; | |
| } | |
| const FAMILY_DEFAULTS = { | |
| focus_navigation: { | |
| title: 'Focus And Navigation', | |
| description: 'Focus changes, replay/sample navigation, and shell steering commands.', | |
| when_to_use: [ | |
| 'Use these when the theater focus, replay cursor, or live sample stream is pointed at the wrong thing.', | |
| 'These are the safest navigation controls when you want state changes without manual UI guessing.', | |
| ], | |
| mode_notes: [ | |
| 'Most focus targets only work when matching items exist in the current ledger, replay state, or scene context.', | |
| 'Read the text theater first after navigation changes so the new focus is interpreted visually before consulting mirror metadata.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'env_read(query=\'text_theater_snapshot\')', 'capture_supercam'], | |
| }, | |
| camera_pose: { | |
| title: 'Camera And Pose', | |
| description: 'Camera framing, orbit, pan, tilt, dolly, and pose controls for the theater view.', | |
| when_to_use: [ | |
| 'Use these before capture when you need repeatable framing instead of mouse navigation.', | |
| 'They are also the cleanest recovery path after focus or scene-shell changes leave the camera in a bad state.', | |
| ], | |
| mode_notes: [ | |
| 'Camera commands change viewer state, not embodiment or workbench data.', | |
| 'Framing commands depend on there being a meaningful focus, replay target, or overview context.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'capture_supercam', 'capture_probe'], | |
| }, | |
| capture_observer: { | |
| title: 'Capture And Observer', | |
| description: 'Observer capture commands used to corroborate scene, subject, and motion truth.', | |
| when_to_use: [ | |
| 'Use these when viewport impression is not enough and you need saved evidence.', | |
| 'Capture commands are the main corroboration path for scale, floor truth, motion, and scene layout.', | |
| ], | |
| mode_notes: [ | |
| 'A dispatched capture is not proven complete until the file exists or the text-theater/capture ledger reports the latest artifact.', | |
| 'Different capture modes emphasize different truths: local detail, overview context, or motion across time.', | |
| ], | |
| verification: ['static/captures/', 'env_read(query=\'text_theater_snapshot\')', 'probe_compare'], | |
| }, | |
| surface_bridge: { | |
| title: 'Surface Bridge', | |
| description: 'Owned-surface inspection and input commands for browser-side panels and surfaces.', | |
| when_to_use: [ | |
| 'Use these when you need to drive a browser-owned panel without relying on a pointer.', | |
| 'They are especially useful for opening, focusing, and inspecting surfaces across agent sessions.', | |
| ], | |
| mode_notes: [ | |
| 'Surface bridge commands usually need a valid owned surface id first.', | |
| 'Success is easiest to confirm from visible browser behavior plus feed, with text-theater or snapshot reads before raw shared_state.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'feed(n=20)', 'visible browser surface behavior'], | |
| }, | |
| theater_profile_recipe: { | |
| title: 'Theater / Profile / Recipe', | |
| description: 'Theater mode, profile, recipe, and environment-shell steering commands.', | |
| when_to_use: [ | |
| 'Use these when you are changing the shell itself rather than moving a single camera, subject, or panel.', | |
| 'These are the top-level steering controls for how the theater is organized right now.', | |
| ], | |
| mode_notes: [ | |
| 'A mode or profile change can invalidate assumptions about focus, camera, and visible inspectors.', | |
| 'These commands often affect multiple panels or shell affordances at once.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'capture_supercam', 'feed(n=20)'], | |
| }, | |
| character_runtime: { | |
| title: 'Character Runtime', | |
| description: 'Mounted runtime commands for character presence, model, movement, and playback.', | |
| when_to_use: [ | |
| 'Use these to operate the mounted asset/runtime embodiment rather than the builder skeleton.', | |
| 'These are the commands for imported asset inspection, runtime animation, and inhabitant presence.', | |
| ], | |
| mode_notes: [ | |
| 'Some commands assume a mounted subject already exists.', | |
| 'Builder-subject mode and mounted-asset inspection can share the theater, but they are not the same runtime state.', | |
| ], | |
| verification: ['capture_probe', 'capture_supercam', 'env_read(query=\'text_theater_snapshot\')'], | |
| }, | |
| builder_workbench: { | |
| title: 'Builder Workbench', | |
| description: 'Builder subject, pose, selection, display, and workbench control commands.', | |
| when_to_use: [ | |
| 'Use these when editing or inspecting the builder subject instead of the mounted imported asset.', | |
| 'This is the main family for scaffold truth, selection, pose editing, and blueprint state.', | |
| ], | |
| mode_notes: [ | |
| 'Most builder workbench commands assume builder_subject mode is active.', | |
| 'If builder mode is not active, expect partial responses or no visible effect until a builder subject is created.', | |
| 'When the question is about route/support/blocker truth, prefer env_report(route_stability_diagnosis) after the theater and snapshot reads instead of jumping straight to shared_state.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'env_read(query=\'text_theater_snapshot\')', 'workbench_get_blueprint'], | |
| }, | |
| builder_motion: { | |
| title: 'Builder Motion', | |
| description: 'Timeline, preset, authored clip, and scrub commands for builder-side motion work.', | |
| when_to_use: [ | |
| 'Use these for staged motion inspection, authored clip work, or pose sequencing on the builder subject.', | |
| 'They are the core path for motion validation before live runtime playback is trustworthy.', | |
| ], | |
| mode_notes: [ | |
| 'Builder motion commands assume a builder subject and an active timeline or pose store.', | |
| 'Preset apply does not imply autoplay; staged motion and live playback are different surfaces.', | |
| ], | |
| verification: ['capture_time_strip', 'capture_probe', 'env_read(query=\'text_theater_snapshot\')'], | |
| }, | |
| environment_misc: { | |
| title: 'Environment Misc', | |
| description: 'Remaining environment commands that do not fit the main families.', | |
| when_to_use: [ | |
| 'Use these for shell helpers, profile kits, world profile changes, and scene-side toggles that cut across families.', | |
| 'This family usually holds useful edge operations rather than the main command lanes.', | |
| ], | |
| mode_notes: [ | |
| 'Misc commands often affect shell state more than a single subject.', | |
| 'Read the individual entry carefully because the name alone is not always enough to infer scope.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_snapshot\')', 'feed(n=20)'], | |
| }, | |
| observation_query: { | |
| title: 'Observation Queries', | |
| description: 'Read-only environment query surfaces that return live browser state or derived observation views.', | |
| when_to_use: [ | |
| 'Use these when you need fast readback from the live theater without dispatching a new control command.', | |
| 'These are the observation-bus surfaces for shared state, text theater, captures, and similar diagnostics.', | |
| ], | |
| mode_notes: [ | |
| 'Observation queries do not mutate runtime state by themselves.', | |
| 'Freshness still matters: mirror lag or stale browser state can make a read truthful about old state rather than current intent.', | |
| ], | |
| verification: ['env_read(query=\'text_theater_embodiment\')', 'env_read(query=\'text_theater_snapshot\')'], | |
| }, | |
| }; | |
| const STANDALONE_UI_ACTIONS = new Set([ | |
| 'workbench-play-clip', | |
| 'workbench-toggle-pause', | |
| 'workbench-set-speed', | |
| 'workbench-toggle-loop', | |
| 'workbench-set-locomotion', | |
| 'workbench-shot-preset', | |
| 'workbench-toggle-skeleton', | |
| 'workbench-toggle-attachments', | |
| 'workbench-toggle-turntable', | |
| 'workbench-toggle-scaffold', | |
| 'workbench-toggle-load-field', | |
| 'toggle-overlay-panel', | |
| 'restore-overlay-panel', | |
| 'reset-overlay-panel', | |
| 'set-label-mode', | |
| 'toggle-kind-panel', | |
| 'toggle-kind', | |
| 'kind-show-all', | |
| 'kind-hide-all', | |
| 'reset-camera', | |
| 'toggle-inhabitant', | |
| ]); | |
| const UI_ACTION_BRIDGES = { | |
| 'workbench-play-clip': ['character_play_clip'], | |
| 'workbench-set-speed': ['character_set_speed'], | |
| 'workbench-toggle-loop': ['character_set_loop'], | |
| 'workbench-toggle-scaffold': ['workbench_set_scaffold'], | |
| 'workbench-toggle-load-field': ['workbench_set_load_field'], | |
| 'reset-camera': ['camera_reset_pose'], | |
| 'toggle-inhabitant': ['character_mount', 'character_unmount'], | |
| }; | |
| function summaryForCommand(command, family) { | |
| if (command === 'workbench_set_timeline_cursor') return 'Scrub the active builder timeline to a given normalized, time, or index position and apply that staged pose.'; | |
| if (command === 'character_set_model') return 'Swap the mounted runtime to a direct asset ref and leave builder-subject mode for mesh-asset inspection.'; | |
| if (command === 'workbench_new_builder') return 'Instantiate a fresh builder subject, clear the mounted asset clone, and enter builder-subject mode.'; | |
| if (command === 'workbench_get_blueprint') return 'Return the serialized builder blueprint describing the active builder subject.'; | |
| if (command === 'workbench_get_part_surface') return 'Return the surface and slot metadata for a selected builder part.'; | |
| if (command === 'workbench_frame_part') return 'Frame the camera around a selected builder part or supplied part id.'; | |
| if (command === 'workbench_set_load_field') return 'Enable or disable the builder load-field mechanics lane used by scaffold-side diagnostics.'; | |
| if (command === 'workbench_set_scaffold') return 'Enable or disable scaffold presentation for the current builder subject.'; | |
| if (command === 'workbench_capture_pose') return 'Capture the current builder pose into the workbench pose store.'; | |
| if (command === 'workbench_delete_pose') return 'Delete a stored builder pose from the workbench pose store.'; | |
| if (command === 'workbench_apply_pose') return 'Apply a stored builder pose to the current builder subject.'; | |
| if (command === 'workbench_compile_clip') return 'Compile the current builder pose and timeline data into an authored clip.'; | |
| if (command === 'workbench_play_authored_clip') return 'Play the current authored builder clip through the workbench runtime.'; | |
| if (command === 'workbench_save_blueprint') return 'Serialize and save the current builder blueprint.'; | |
| if (command === 'workbench_load_blueprint') return 'Load a serialized builder blueprint into the active workbench session.'; | |
| if (command === 'workbench_reset_angles') return 'Reset the selected builder bone, a supplied target bone, or all bones back toward neutral angles.'; | |
| if (command === 'workbench_clear_pose') return 'Clear the current staged builder pose offsets.'; | |
| if (command === 'workbench_set_pose') return 'Apply or stage an explicit pose payload on the builder subject.'; | |
| if (command === 'workbench_set_pose_batch') return 'Apply multiple pose changes in a single builder operation.'; | |
| if (command === 'workbench_select_bone') return 'Replace the current builder selection with one named bone.'; | |
| if (command === 'workbench_select_bones') return 'Replace the current builder selection with multiple named bones.'; | |
| if (command === 'workbench_set_bone') return 'Apply an explicit bone transform payload to the builder subject.'; | |
| if (command === 'workbench_set_display_scope') return 'Change how much of the builder subject the workbench displays.'; | |
| if (command === 'workbench_set_editing_mode') return 'Switch the builder between pose and structure editing modes.'; | |
| if (command === 'workbench_set_gizmo_mode') return 'Change the active workbench gizmo mode.'; | |
| if (command === 'workbench_set_gizmo_space') return 'Change whether the gizmo works in local or world space.'; | |
| if (command === 'workbench_isolate_chain') return 'Limit the builder display and edit scope to a selected chain or restore the full body.'; | |
| if (command === 'capture_probe') return 'Capture the multi-angle local probe view for the focused subject or runtime target.'; | |
| if (command === 'capture_supercam') return 'Capture the broader overview observer montage for scene-scale corroboration.'; | |
| if (command === 'capture_time_strip') return 'Capture sampled frames across the current builder timeline so staged motion can be inspected without autoplay.'; | |
| if (command === 'capture_focus') return 'Capture the current focus target with the observer pipeline.'; | |
| if (command === 'capture_frame') return 'Capture a single observer frame from the current scene or subject context.'; | |
| if (command === 'capture_frame_overview') return 'Capture a single observer frame using overview framing.'; | |
| if (command === 'capture_strip') return 'Capture a strip of observer frames for quick comparative inspection.'; | |
| if (command === 'character_mount') return 'Mount the runtime character surface so the theater has an active character subject.'; | |
| if (command === 'character_unmount') return 'Unmount the current runtime character surface.'; | |
| if (command === 'character_focus') return 'Move focus onto the mounted runtime character subject.'; | |
| if (command === 'character_move_to') return 'Command the mounted runtime character toward a supplied world-space destination.'; | |
| if (command === 'character_look_at') return 'Command the mounted runtime character to orient toward a supplied point.'; | |
| if (command === 'character_play_clip') return 'Play a named animation clip on the mounted runtime subject.'; | |
| if (command === 'character_queue_clips') return 'Queue one or more animation clips on the mounted runtime subject.'; | |
| if (command === 'character_stop_clip') return 'Stop the currently forced or queued animation clip.'; | |
| if (command === 'character_stop') return 'Stop the mounted runtime subject and clear immediate movement intent.'; | |
| if (command === 'character_set_loop') return 'Set clip loop behavior for mounted runtime playback.'; | |
| if (command === 'character_set_speed') return 'Set clip playback speed for the mounted runtime subject.'; | |
| if (command === 'character_get_animation_state') return 'Read the mounted runtime animation state for the active subject.'; | |
| if (command === 'character_play_reaction') return 'Trigger a named reaction or gesture on the mounted runtime subject.'; | |
| if (command === 'spawn_inhabitant') return 'Spawn a fresh inhabitant/runtime subject into the current theater context.'; | |
| if (command === 'despawn_inhabitant') return 'Remove the active inhabitant/runtime subject from the theater context.'; | |
| if (command === 'focus_inhabitant') return 'Move theater focus onto the active inhabitant/runtime subject.'; | |
| if (command === 'toggle_inhabitant_fov_debug') return 'Toggle the inhabitant field-of-view debug overlay.'; | |
| if (command === 'branch_snapshot') return 'Create a replay/sample snapshot from the current branch context.'; | |
| if (command === 'follow_failed') return 'Jump focus to the latest failed execution or failed branch target.'; | |
| if (command === 'sample_now') return 'Force an immediate sample capture from the current focus context.'; | |
| if (command === 'toggle_stream') return 'Toggle the live sample and activity stream used by the theater shell.'; | |
| if (command === 'toggle_replay') return 'Toggle replay mode inside the theater shell.'; | |
| if (command === 'replay_next') return 'Advance the replay cursor to the next replay entry.'; | |
| if (command === 'replay_prev') return 'Move the replay cursor back to the previous replay entry.'; | |
| if (command.startsWith('focus_')) return `Move theater focus to the current ${nounPhrase(command.replace(/^focus_/, ''))} target.`; | |
| if (command === 'open_surface') return 'Open an owned browser surface inside the theater shell.'; | |
| if (command === 'close_surface') return 'Close an owned browser surface.'; | |
| if (command === 'focus_surface') return 'Move shell focus onto a named owned surface.'; | |
| if (command === 'inspect_surface') return 'Open the inspector for a named owned surface.'; | |
| if (command === 'close_inspector') return 'Close the current inspector surface.'; | |
| if (command === 'open_doc_memory') return 'Open the doc-memory surface from the theater shell.'; | |
| if (command === 'surface_click') return 'Send a synthetic click to an owned browser surface.'; | |
| if (command === 'surface_input') return 'Send text or value input to an owned browser surface.'; | |
| if (command === 'surface_scroll') return 'Send a synthetic scroll event to an owned browser surface.'; | |
| if (command === 'surface_submit') return 'Submit a form or action target inside an owned browser surface.'; | |
| if (command === 'surface_tab') return 'Switch tabs inside an owned browser surface.'; | |
| if (command === 'surface_action') return 'Dispatch a generic action payload to an owned browser surface.'; | |
| if (command === 'activate_profile') return 'Activate a named theater/profile preset.'; | |
| if (command === 'run_recipe') return 'Run a named recipe through the environment shell.'; | |
| if (command === 'scan_docs') return 'Scan docs into the theater shell context.'; | |
| if (command === 'set_camera_mode') return 'Switch the camera mode used by the theater shell.'; | |
| if (command === 'set_replay_mode') return 'Switch the replay presentation mode used by the theater shell.'; | |
| if (command === 'set_theater_mode') return 'Switch the theater shell between major presentation modes.'; | |
| if (command === 'apply_profile_kit') return 'Apply a prepared profile-kit payload to the current shell state.'; | |
| if (command === 'clear_profile_kit') return 'Clear the currently applied profile-kit payload.'; | |
| if (command === 'set_camera_preset') return 'Apply a named camera preset to the theater shell.'; | |
| if (command === 'set_world_profile') return 'Apply a named world-profile preset to the current scene shell.'; | |
| if (command.startsWith('camera_frame_')) return `Frame the camera around the current ${nounPhrase(command.replace(/^camera_frame_/, ''))} context.`; | |
| if (command.startsWith('camera_dolly_')) return `Move the camera ${nounPhrase(command.replace(/^camera_dolly_/, ''))} along its current view axis.`; | |
| if (command.startsWith('camera_orbit_')) return `Orbit the camera ${nounPhrase(command.replace(/^camera_orbit_/, ''))} around the current focus anchor.`; | |
| if (command.startsWith('camera_pan_')) return `Pan the camera ${nounPhrase(command.replace(/^camera_pan_/, ''))} without changing focus.`; | |
| if (command.startsWith('camera_tilt_')) return `Tilt the camera ${nounPhrase(command.replace(/^camera_tilt_/, ''))} around its current pivot.`; | |
| if (command === 'camera_pose') return 'Apply or serialize a camera pose payload for the current theater view.'; | |
| if (command === 'camera_reset_pose') return 'Reset the camera to the theater-mode default pose.'; | |
| if (command.startsWith('camera_')) return `Adjust the theater camera using ${command}.`; | |
| return `Dispatch the environment command ${command}.`; | |
| } | |
| function targetContractForCommand(command, family) { | |
| if (command === 'workbench_set_timeline_cursor') { | |
| return { | |
| shape: 'json', | |
| description: 'Timeline cursor payload using normalized, time, or index.', | |
| examples: ['{"normalized":0.5}', '{"time":0.8}', '{"index":2}'], | |
| }; | |
| } | |
| if (command === 'character_set_model') { | |
| return { | |
| shape: 'string', | |
| description: 'Direct asset ref or URL for the mounted character model.', | |
| examples: ['/static/assets/packs/os3a-tomb-chaser/GhostArmature.glb'], | |
| }; | |
| } | |
| if (command === 'workbench_new_builder') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Builder family id or JSON payload describing family, subject mode, and anchor choices.', | |
| examples: ['humanoid_biped', '{"family":"humanoid_biped"}'], | |
| }; | |
| } | |
| if (command === 'character_move_to' || command === 'character_look_at') { | |
| return { | |
| shape: 'json_or_string', | |
| description: 'World-space destination or look-target payload understood by the runtime handler.', | |
| examples: ['{"x":0,"y":0,"z":0}'], | |
| }; | |
| } | |
| if (command === 'character_play_clip') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Clip name or JSON payload controlling which clip to play and whether it overrides current playback.', | |
| examples: ['walk', '{"clip":"walk","override":true}'], | |
| }; | |
| } | |
| if (command === 'character_queue_clips') { | |
| return { | |
| shape: 'json', | |
| description: 'Queue payload describing one or more clips and their sequencing metadata.', | |
| examples: ['{"clips":["walk","idle"]}'], | |
| }; | |
| } | |
| if (command === 'character_set_loop') { | |
| return { | |
| shape: 'string', | |
| description: 'Loop mode name such as repeat or once.', | |
| examples: ['repeat', 'once'], | |
| }; | |
| } | |
| if (command === 'character_set_speed') { | |
| return { | |
| shape: 'number_or_string', | |
| description: 'Positive playback speed multiplier.', | |
| examples: ['0.5', '1', '2'], | |
| }; | |
| } | |
| if (command === 'workbench_select_bone') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Single bone id or selection payload.', | |
| examples: ['hips', '{"bone":"hips"}'], | |
| }; | |
| } | |
| if (command === 'workbench_select_bones') { | |
| return { | |
| shape: 'json', | |
| description: 'Bone selection payload containing multiple bone ids.', | |
| examples: ['{"bones":["hips","spine","head"]}'], | |
| }; | |
| } | |
| if (command === 'workbench_set_bone' || command === 'workbench_set_pose' || command === 'workbench_set_pose_batch') { | |
| return { | |
| shape: 'json', | |
| description: 'Explicit builder transform or pose payload.', | |
| examples: ['{"bone":"hips","rotation":{"x":0,"y":0.1,"z":0}}'], | |
| }; | |
| } | |
| if (command === 'workbench_capture_pose' || command === 'workbench_delete_pose' || command === 'workbench_apply_pose') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Pose name or payload naming the stored pose entry.', | |
| examples: ['neutral_standing', '{"name":"neutral_standing"}'], | |
| }; | |
| } | |
| if (command === 'workbench_set_editing_mode') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Builder editing mode. Valid modes are pose and structure; JSON payloads may use an editing_mode field.', | |
| examples: ['pose', 'structure', '{"editing_mode":"pose"}', '{"editing_mode":"structure"}'], | |
| }; | |
| } | |
| if (command === 'workbench_reset_angles') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Reset target for the builder angle reset path. Accepts one bone id, all, or JSON payloads naming bone/all.', | |
| examples: ['hips', 'all', '{"bone":"hips"}', '{"all":true}'], | |
| }; | |
| } | |
| if (command === 'workbench_set_display_scope' || command === 'workbench_set_gizmo_mode' || command === 'workbench_set_gizmo_space') { | |
| return { | |
| shape: 'string', | |
| description: 'Workbench enum value understood by the builder UI/runtime handler.', | |
| examples: ['rotate', 'translate', 'local', 'world'], | |
| }; | |
| } | |
| if (command === 'workbench_set_load_field' || command === 'workbench_set_scaffold') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'On/off/toggle style control or JSON payload carrying the target boolean.', | |
| examples: ['toggle', '{"enabled":true}'], | |
| }; | |
| } | |
| if (command.startsWith('capture_')) { | |
| return { | |
| shape: 'string_optional', | |
| description: 'Optional target hint for the observer capture flow.', | |
| examples: ['character_runtime::mounted_primary'], | |
| }; | |
| } | |
| if (family === 'surface_bridge') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Surface id or structured payload describing which owned surface to act on.', | |
| examples: ['memory', '{"surface":"memory"}'], | |
| }; | |
| } | |
| if (family === 'character_runtime' || family === 'builder_workbench' || family === 'builder_motion') { | |
| return { | |
| shape: 'string_or_json', | |
| description: 'Runtime or workbench payload interpreted by the active browser handler.', | |
| examples: [], | |
| }; | |
| } | |
| return { | |
| shape: 'string_optional', | |
| description: 'Command-specific target id interpreted by the browser/runtime handler.', | |
| examples: [], | |
| }; | |
| } | |
| function availabilityForCommand(command, family) { | |
| const base = { | |
| theater_modes: [], | |
| visual_modes: [], | |
| requires_focus_kind: [], | |
| requires_builder_subject: false, | |
| }; | |
| if (family === 'character_runtime' || family === 'builder_workbench' || family === 'builder_motion') { | |
| base.theater_modes = ['character']; | |
| base.requires_focus_kind = ['character_runtime']; | |
| } | |
| if (family === 'builder_workbench' || family === 'builder_motion') { | |
| base.visual_modes = ['builder_subject']; | |
| base.requires_builder_subject = true; | |
| } else if (family === 'character_runtime') { | |
| base.visual_modes = ['mesh_asset', 'builder_subject']; | |
| } | |
| if (family === 'camera_pose' || family === 'capture_observer' || family === 'focus_navigation' || family === 'theater_profile_recipe') { | |
| base.theater_modes = ['scene', 'character']; | |
| } | |
| if (command === 'character_set_model') { | |
| base.visual_modes = ['mesh_asset', 'builder_subject']; | |
| base.requires_builder_subject = false; | |
| } | |
| if (command === 'workbench_new_builder') { | |
| base.visual_modes = ['mesh_asset', 'builder_subject']; | |
| base.requires_builder_subject = false; | |
| } | |
| if (command === 'workbench_set_editing_mode') { | |
| base.valid_editing_modes = ['pose', 'structure']; | |
| } | |
| if (command === 'workbench_reset_angles') { | |
| base.required_editing_mode = ['structure']; | |
| } | |
| return base; | |
| } | |
| function familyForUiAction(action) { | |
| if (action.startsWith('workbench-')) { | |
| if ([ | |
| 'workbench-play-clip', | |
| 'workbench-toggle-pause', | |
| 'workbench-set-speed', | |
| 'workbench-toggle-loop', | |
| 'workbench-set-locomotion', | |
| ].includes(action)) return 'builder_motion'; | |
| return 'builder_workbench'; | |
| } | |
| if (action === 'reset-camera') return 'camera_pose'; | |
| if (action === 'toggle-inhabitant') return 'character_runtime'; | |
| if (['toggle-overlay-panel', 'restore-overlay-panel', 'reset-overlay-panel'].includes(action)) return 'surface_bridge'; | |
| return 'environment_misc'; | |
| } | |
| function summaryForUiAction(action) { | |
| if (action === 'workbench-play-clip') return 'Play a named loaded clip from the local workbench clip strip.'; | |
| if (action === 'workbench-toggle-pause') return 'Pause or resume the current local preview action without changing staged builder timeline data.'; | |
| if (action === 'workbench-set-speed') return 'Set local playback speed from the helper chips and forward that value through the runtime speed command.'; | |
| if (action === 'workbench-toggle-loop') return 'Toggle loop mode from the helper chips and forward that loop choice through the runtime loop command.'; | |
| if (action === 'workbench-set-locomotion') return 'Set the browser-side locomotion preview lane for the current workbench clip and refresh the animation UI.'; | |
| if (action === 'workbench-shot-preset') return 'Apply a browser-local workbench camera shot preset such as front, side, or face.'; | |
| if (action === 'workbench-toggle-skeleton') return 'Toggle the browser-local skeleton helper for the current workbench subject.'; | |
| if (action === 'workbench-toggle-attachments') return 'Toggle browser-local attachment gizmos for the current workbench subject.'; | |
| if (action === 'workbench-toggle-turntable') return 'Flip the browser-local workbench turntable on or off for the current builder view.'; | |
| if (action === 'workbench-toggle-scaffold') return 'Flip scaffold visibility from the local helper strip and then dispatch the persistent scaffold command.'; | |
| if (action === 'workbench-toggle-load-field') return 'Flip the helper-strip load toggle immediately in the browser and then dispatch the persistent load-field command.'; | |
| if (action === 'toggle-overlay-panel') return 'Minimize or restore an overlay panel without leaving the current theater view.'; | |
| if (action === 'restore-overlay-panel') return 'Restore a minimized overlay panel to its visible state.'; | |
| if (action === 'reset-overlay-panel') return 'Restore an overlay panel and clear its staged local position.'; | |
| if (action === 'set-label-mode') return 'Change the browser-local label rendering mode for scene annotations.'; | |
| if (action === 'toggle-kind-panel') return 'Open or close the local kind-filter panel.'; | |
| if (action === 'toggle-kind') return 'Toggle visibility for one object-kind filter in the current scene view.'; | |
| if (action === 'kind-show-all') return 'Show all currently filterable scene kinds.'; | |
| if (action === 'kind-hide-all') return 'Hide all currently filterable scene kinds.'; | |
| if (action === 'reset-camera') return 'Use the local shell control to reset the camera through the standard camera-reset command.'; | |
| if (action === 'toggle-inhabitant') return 'Use the local shell toggle to mount or unmount the inhabitant runtime.'; | |
| return `Trigger the local browser action ${action}.`; | |
| } | |
| function targetContractForUiAction(action) { | |
| if (action === 'workbench-shot-preset') { | |
| return { | |
| shape: 'ui_chip', | |
| description: 'Triggered by the local shot-preset chips; not directly callable through env_control.', | |
| examples: ['front', 'three_q', 'side'], | |
| }; | |
| } | |
| if (action === 'workbench-set-speed') { | |
| return { | |
| shape: 'ui_chip', | |
| description: 'Triggered by speed chips carrying a numeric speed multiplier.', | |
| examples: ['0.25', '0.5', '1', '2'], | |
| }; | |
| } | |
| if (action === 'workbench-set-locomotion') { | |
| return { | |
| shape: 'ui_chip', | |
| description: 'Triggered by local locomotion chips such as auto, idle, walk, or run.', | |
| examples: ['auto', 'idle', 'walk', 'run'], | |
| }; | |
| } | |
| if (['toggle-overlay-panel', 'restore-overlay-panel', 'reset-overlay-panel'].includes(action)) { | |
| return { | |
| shape: 'ui_payload', | |
| description: 'Triggered by an overlay panel control carrying an overlay id.', | |
| examples: ['overlay:inspector'], | |
| }; | |
| } | |
| if (action === 'toggle-kind') { | |
| return { | |
| shape: 'ui_payload', | |
| description: 'Triggered by a kind-filter chip carrying the scene-kind name.', | |
| examples: ['lights', 'characters'], | |
| }; | |
| } | |
| return { | |
| shape: 'ui_local', | |
| description: 'Browser-local control; use the named UI affordance rather than env_control.', | |
| examples: [], | |
| }; | |
| } | |
| function whenToUseForEntry(command, family, entryKind) { | |
| const base = (FAMILY_DEFAULTS[family] && FAMILY_DEFAULTS[family].when_to_use) || []; | |
| const extra = []; | |
| if (command === 'workbench_set_timeline_cursor') extra.push('Use this when a preset or authored clip is loaded and you need a specific moment without autoplay.'); | |
| if (command === 'character_set_model') extra.push('Use this when validating a mounted imported asset or leaving builder-subject mode on purpose.'); | |
| if (command === 'workbench_get_blueprint') extra.push('Use this when you need the exact serialized builder truth instead of relying on the viewport alone.'); | |
| if (command === 'workbench_set_load_field') extra.push('Use this when testing scaffold-side load mechanics or verifying helper-strip synchronization.'); | |
| if (command === 'capture_probe') extra.push('Use this for close-range corroboration of scale, scaffold state, support planting, and local pose truth.'); | |
| if (entryKind === 'ui_action' && command === 'workbench-toggle-turntable') extra.push('Use this when you need the builder subject to rotate continuously for local visual inspection.'); | |
| return dedupeList([...base, ...extra]); | |
| } | |
| function whatItChangesForEntry(command, family, entryKind) { | |
| const out = []; | |
| if (family === 'camera_pose') out.push('Camera transform, framing, or stored camera pose state.'); | |
| if (family === 'capture_observer') out.push('Writes new capture output and updates latest capture context.'); | |
| if (family === 'focus_navigation') out.push('Current focus, replay cursor, or sample-stream state.'); | |
| if (family === 'surface_bridge') out.push('Owned browser surfaces, their focus, or input state.'); | |
| if (family === 'theater_profile_recipe') out.push('Scene-shell mode, profile, recipe, or replay/camera presentation state.'); | |
| if (family === 'character_runtime') out.push('Mounted runtime subject, animation state, playback, or inhabitant presence.'); | |
| if (family === 'builder_workbench') out.push('Builder selection, scaffold state, workbench editing settings, or serialized blueprint data.'); | |
| if (family === 'builder_motion') out.push('Builder pose store, staged timeline state, or authored motion data.'); | |
| if (family === 'environment_misc') out.push('Cross-cutting shell state such as profile kits, world profile, or scene filters.'); | |
| if (entryKind === 'ui_action') out.unshift('Browser-local UI state that may or may not dispatch a persistent runtime command.'); | |
| if (command === 'workbench_set_timeline_cursor') out.push('Repositions the staged builder timeline and updates the visible pose.'); | |
| if (command === 'workbench-toggle-turntable') out.push('Local workbench turntable flag stored in the theater session.'); | |
| return dedupeList(out); | |
| } | |
| function modeNotesForEntry(command, family, entryKind) { | |
| const base = (FAMILY_DEFAULTS[family] && FAMILY_DEFAULTS[family].mode_notes) || []; | |
| const extra = []; | |
| if (command === 'workbench_set_timeline_cursor') extra.push('Works only when a builder timeline is currently loaded.'); | |
| if (command === 'character_set_model') extra.push('Mounted-asset inspection and builder-subject mode are separate visual regimes.'); | |
| if (entryKind === 'ui_action') extra.push('UI-local actions are discovered from browser source and are not guaranteed to be callable through env_control.'); | |
| return dedupeList([...base, ...extra]); | |
| } | |
| function gotchasForCommand(command, family, transports, bridgesTo, entryKind) { | |
| const out = []; | |
| if (entryKind === 'env_command' && transports && transports.env_control) { | |
| out.push('env_control results attach paired text_theater observation so agents can inspect current mirrored scene state without a separate env_read round-trip.'); | |
| out.push('Attached payload shape is text_theater.current_compact, text_theater.snapshot, and text_theater.freshness; include_full=true also returns current_full with theater plus embodiment.'); | |
| out.push('Check text_theater.freshness.cache_advanced_after_command and text_theater.freshness.matched_command_sync before trusting the attached frame as post-command truth; when false, you are looking at the newest mirrored state, but not a confirmed fresh sync for that command yet.'); | |
| out.push('Use env_read(query=\'text_theater_view\') only when you need the richer consult renderer on demand; the hot path should prefer the attached browser-authored text_theater payload.'); | |
| } | |
| if (command === 'workbench_set_timeline_cursor') { | |
| out.push('Builder-only; timeline scrub will fail when no builder subject is active.'); | |
| } | |
| if (command === 'workbench_set_editing_mode') { | |
| out.push('Valid builder editing modes are pose and structure.'); | |
| out.push('Local gizmo modes such as rotate/translate and spaces such as local/world are separate controls; use workbench_set_gizmo_mode or workbench_set_gizmo_space for those.'); | |
| } | |
| if (command === 'workbench_reset_angles') { | |
| out.push('workbench_reset_angles is gated to structure mode; pose mode rejects the reset.'); | |
| out.push('Without an explicit target, the reset falls back to the currently selected bone.'); | |
| } | |
| if (command === 'character_set_model') { | |
| out.push('Uses direct asset refs/URLs, not manifest aliases.'); | |
| } | |
| if (command.startsWith('capture_')) { | |
| out.push('Capture dispatch does not guarantee the browser completed the capture until corroborated via files or shared_state.'); | |
| } | |
| if (!transports.env_control && transports.browser_surface) { | |
| out.push('Browser-visible, but not proxied through env_control.'); | |
| } | |
| if (family === 'surface_bridge') { | |
| out.push('Surface commands often depend on an owned/browser surface being active first.'); | |
| } | |
| if (family === 'builder_workbench' || family === 'builder_motion') { | |
| out.push('Most builder commands require builder_subject mode; mounted-asset inspection is not enough.'); | |
| } | |
| if (entryKind === 'ui_action') { | |
| out.push('UI-local action; do not assume there is an equivalent direct env_control command.'); | |
| } | |
| if (entryKind === 'ui_action' && command === 'workbench-toggle-turntable') { | |
| out.push('Turntable is session-local browser behavior; remote env_control callers cannot flip it directly.'); | |
| } | |
| if (entryKind === 'ui_action' && command === 'workbench-toggle-pause') { | |
| out.push('Pause acts on the local preview action object; it is not the same surface as builder preset staging.'); | |
| } | |
| if (entryKind === 'ui_action' && command === 'workbench-set-locomotion') { | |
| out.push('Locomotion preview is a browser-side preview lane; it can clear clip overrides in some cases.'); | |
| } | |
| if (bridgesTo.length) { | |
| out.push(`This UI action bridges into ${bridgesTo.join(', ')} after local browser-side work.`); | |
| } | |
| return out; | |
| } | |
| function failureModesForEntry(command, family, entryKind, bridgesTo) { | |
| const out = []; | |
| if (family === 'builder_workbench' || family === 'builder_motion') out.push('No builder subject active.'); | |
| if (family === 'character_runtime') out.push('No mounted runtime character is active.'); | |
| if (family === 'surface_bridge') out.push('Owned surface id or selector is missing or stale.'); | |
| if (family === 'focus_navigation') out.push('Requested target is not present in the current ledger, replay state, or scene context.'); | |
| if (family === 'capture_observer') out.push('Browser capture was queued but no saved output appeared yet.'); | |
| if (entryKind === 'ui_action') out.push('The expected browser panel, helper strip, or workbench context is not currently visible.'); | |
| if (command === 'workbench_set_timeline_cursor') out.push('No active timeline is loaded, so scrub has nothing to apply.'); | |
| if (command === 'character_set_model') out.push('The asset ref could not be loaded or produced an empty mounted runtime.'); | |
| if (bridgesTo.includes('workbench_set_load_field')) out.push('Local helper chip flipped but persistent load-field readback stayed stale until sync completed.'); | |
| return dedupeList(out); | |
| } | |
| function verificationForEntry(command, family, entryKind) { | |
| const base = (FAMILY_DEFAULTS[family] && FAMILY_DEFAULTS[family].verification) || []; | |
| const extra = []; | |
| if (entryKind === 'env_command') extra.push('env_read(query=\'text_theater_view\')'); | |
| if (command === 'character_get_animation_state') extra.push('character_get_animation_state'); | |
| if (command === 'workbench_get_blueprint') extra.push('workbench_get_blueprint'); | |
| if (command === 'workbench_set_timeline_cursor') extra.push('capture_time_strip'); | |
| if (command === 'workbench_set_load_field' || command === 'workbench-toggle-load-field') extra.push('capture_probe'); | |
| if (entryKind === 'ui_action') extra.push('visible browser surface behavior'); | |
| return dedupeList([...base, ...extra]); | |
| } | |
| function relatedCommands(command, family, bridgesTo) { | |
| if (command === 'workbench_set_timeline_cursor') return ['workbench_compile_clip', 'capture_probe', 'capture_time_strip']; | |
| if (command === 'character_set_model') return ['workbench_new_builder', 'capture_probe', 'capture_supercam']; | |
| if (command === 'workbench_get_blueprint') return ['workbench_save_blueprint', 'workbench_load_blueprint', 'capture_probe']; | |
| if (command === 'workbench-toggle-turntable') return ['capture_probe', 'workbench-shot-preset']; | |
| if (bridgesTo.length) return dedupeList([...bridgesTo, 'capture_probe']); | |
| const familyCommands = { | |
| camera_pose: ['capture_supercam', 'capture_probe'], | |
| capture_observer: ['capture_probe', 'capture_supercam', 'capture_time_strip'], | |
| character_runtime: ['character_focus', 'character_set_model', 'capture_probe'], | |
| builder_workbench: ['workbench_get_blueprint', 'workbench_frame_part', 'capture_probe'], | |
| builder_motion: ['workbench_set_timeline_cursor', 'workbench_compile_clip', 'capture_time_strip'], | |
| focus_navigation: ['capture_supercam', 'sample_now', 'toggle_stream'], | |
| surface_bridge: ['open_surface', 'inspect_surface', 'focus_surface'], | |
| theater_profile_recipe: ['set_theater_mode', 'set_camera_mode', 'set_replay_mode'], | |
| environment_misc: ['set_world_profile', 'set_camera_preset'], | |
| }; | |
| return familyCommands[family] || []; | |
| } | |
| function surfaceEntrypointsForCommand(command, actionAnchors, commandNames) { | |
| const aliases = []; | |
| actionAnchors.forEach((_rows, action) => { | |
| if (STANDALONE_UI_ACTIONS.has(action)) return; | |
| if (normalizeActionToCommand(action) === command && commandNames.includes(command)) aliases.push(action); | |
| }); | |
| return aliases.sort((a, b) => a.localeCompare(b)); | |
| } | |
| function commandSourceAnchors(command, serverLines, mainAnchors, actionAnchors, surfaceEntrypoints) { | |
| const anchors = []; | |
| const serverNeedle = `"${command}"`; | |
| const lineIndex = serverLines.findIndex((line) => line.includes(serverNeedle)); | |
| if (lineIndex >= 0) { | |
| anchors.push({ | |
| file: 'server.py', | |
| line: lineIndex + 1, | |
| kind: 'proxy_list', | |
| }); | |
| } | |
| const rows = mainAnchors.get(command) || []; | |
| rows.slice(0, 4).forEach((row) => anchors.push(row)); | |
| (surfaceEntrypoints || []).forEach((action) => { | |
| const actionRows = actionAnchors.get(action) || []; | |
| actionRows.slice(0, 2).forEach((row) => anchors.push(row)); | |
| }); | |
| return anchors; | |
| } | |
| const args = parseArgs(process.argv.slice(2)); | |
| const cwd = process.cwd(); | |
| const serverPath = path.resolve(cwd, 'server.py'); | |
| const mainPath = path.resolve(cwd, 'static', 'main.js'); | |
| const outputPath = path.resolve(cwd, String(args.output || path.join('static', 'data', 'help', 'environment_command_registry.json'))); | |
| const overridesPath = path.resolve(cwd, String(args.overrides || path.join('static', 'data', 'help', 'environment_command_overrides.json'))); | |
| const serverText = fs.readFileSync(serverPath, 'utf8'); | |
| const mainText = fs.readFileSync(mainPath, 'utf8'); | |
| const serverLines = serverText.split(/\r?\n/); | |
| const mainAnchors = findCommandAnchors(mainText, 'static/main.js'); | |
| const actionAnchors = findActionAnchors(mainText, 'static/main.js'); | |
| const proxyCommands = new Set(extractFrozenset(serverText, '_ENV_CONTROL_PROXY_COMMANDS')); | |
| const hostCommands = new Set(extractJsArray(mainText, 'host_commands', 'legacy_host_commands')); | |
| const implementedVerbs = new Set(extractJsArray(mainText, 'implemented_verbs', 'agent_bearing')); | |
| const commandNames = Array.from(new Set([...proxyCommands, ...hostCommands])).sort((a, b) => a.localeCompare(b)); | |
| let overrides = {}; | |
| if (fs.existsSync(overridesPath)) { | |
| overrides = JSON.parse(fs.readFileSync(overridesPath, 'utf8')); | |
| } | |
| const commandOverrides = (overrides && overrides.commands && typeof overrides.commands === 'object') ? overrides.commands : {}; | |
| const familyOverrides = (overrides && overrides.families && typeof overrides.families === 'object') ? overrides.families : {}; | |
| const uiActionOverrides = (overrides && overrides.ui_actions && typeof overrides.ui_actions === 'object') ? overrides.ui_actions : {}; | |
| const queryOverrides = (overrides && overrides.queries && typeof overrides.queries === 'object') ? overrides.queries : {}; | |
| const playbooks = (overrides && overrides.playbooks && typeof overrides.playbooks === 'object') ? overrides.playbooks : {}; | |
| const commands = {}; | |
| const queries = {}; | |
| const familyBuckets = new Map(); | |
| commandNames.forEach((command) => { | |
| const family = familyForCommand(command); | |
| if (!familyBuckets.has(family)) familyBuckets.set(family, []); | |
| familyBuckets.get(family).push(command); | |
| const surfaceEntrypoints = surfaceEntrypointsForCommand(command, actionAnchors, commandNames); | |
| const bridgesTo = []; | |
| const transports = { | |
| env_control: proxyCommands.has(command), | |
| browser_surface: hostCommands.has(command) || (mainAnchors.get(command) || []).length > 0 || surfaceEntrypoints.length > 0, | |
| ui_local_only: false, | |
| implemented_verb: implementedVerbs.has(command.replace(/^workbench_/, '').replace(/^character_/, '').replace(/^focus_/, 'focus')), | |
| }; | |
| const baseEntry = { | |
| command, | |
| entry_kind: 'env_command', | |
| title: titleCase(command), | |
| category: family, | |
| status: 'live', | |
| transport: transports, | |
| availability: availabilityForCommand(command, family), | |
| target_contract: targetContractForCommand(command, family), | |
| summary: summaryForCommand(command, family), | |
| when_to_use: whenToUseForEntry(command, family, 'env_command'), | |
| what_it_changes: whatItChangesForEntry(command, family, 'env_command'), | |
| mode_notes: modeNotesForEntry(command, family, 'env_command'), | |
| verification: verificationForEntry(command, family, 'env_command'), | |
| gotchas: gotchasForCommand(command, family, transports, bridgesTo, 'env_command'), | |
| failure_modes: failureModesForEntry(command, family, 'env_command', bridgesTo), | |
| aliases: surfaceEntrypoints, | |
| surface_entrypoints: surfaceEntrypoints, | |
| bridges_to: bridgesTo, | |
| related_commands: relatedCommands(command, family, bridgesTo), | |
| source_anchors: commandSourceAnchors(command, serverLines, mainAnchors, actionAnchors, surfaceEntrypoints), | |
| }; | |
| commands[command] = mergeObjects(baseEntry, commandOverrides[command] || {}); | |
| }); | |
| Array.from(STANDALONE_UI_ACTIONS).sort((a, b) => a.localeCompare(b)).forEach((action) => { | |
| if (!actionAnchors.has(action)) return; | |
| const family = familyForUiAction(action); | |
| if (!familyBuckets.has(family)) familyBuckets.set(family, []); | |
| familyBuckets.get(family).push(action); | |
| const bridgesTo = dedupeList(UI_ACTION_BRIDGES[action] || []); | |
| const transports = { | |
| env_control: false, | |
| browser_surface: true, | |
| ui_local_only: true, | |
| implemented_verb: false, | |
| }; | |
| const baseEntry = { | |
| command: action, | |
| entry_kind: 'ui_action', | |
| title: titleCase(action), | |
| category: family, | |
| status: 'live', | |
| transport: transports, | |
| availability: availabilityForCommand(action, family), | |
| target_contract: targetContractForUiAction(action), | |
| summary: summaryForUiAction(action), | |
| when_to_use: whenToUseForEntry(action, family, 'ui_action'), | |
| what_it_changes: whatItChangesForEntry(action, family, 'ui_action'), | |
| mode_notes: modeNotesForEntry(action, family, 'ui_action'), | |
| verification: verificationForEntry(action, family, 'ui_action'), | |
| gotchas: gotchasForCommand(action, family, transports, bridgesTo, 'ui_action'), | |
| failure_modes: failureModesForEntry(action, family, 'ui_action', bridgesTo), | |
| aliases: [], | |
| surface_entrypoints: [action], | |
| bridges_to: bridgesTo, | |
| related_commands: relatedCommands(action, family, bridgesTo), | |
| source_anchors: (actionAnchors.get(action) || []).slice(0, 4), | |
| }; | |
| commands[action] = mergeObjects(baseEntry, uiActionOverrides[action] || {}); | |
| }); | |
| Object.keys(queryOverrides).sort((a, b) => a.localeCompare(b)).forEach((query) => { | |
| const override = queryOverrides[query] || {}; | |
| const family = String(override.category || override.family || 'observation_query'); | |
| if (!familyBuckets.has(family)) familyBuckets.set(family, []); | |
| familyBuckets.get(family).push(query); | |
| const baseEntry = { | |
| query, | |
| entry_kind: 'env_read_query', | |
| title: titleCase(query), | |
| category: family, | |
| status: 'live', | |
| transport: { | |
| env_read: true, | |
| env_control: false, | |
| browser_surface: false, | |
| ui_local_only: false, | |
| implemented_verb: false, | |
| }, | |
| summary: `Read ${query} from the live environment/browser state.`, | |
| when_to_use: whenToUseForEntry(query, family, 'env_read_query'), | |
| what_it_changes: [], | |
| mode_notes: modeNotesForEntry(query, family, 'env_read_query'), | |
| verification: verificationForEntry(query, family, 'env_read_query'), | |
| gotchas: gotchasForCommand(query, family, { env_control: false, browser_surface: false, ui_local_only: false, implemented_verb: false }, [], 'env_read_query'), | |
| failure_modes: failureModesForEntry(query, family, 'env_read_query', []), | |
| aliases: [], | |
| related_commands: [], | |
| source_anchors: [], | |
| }; | |
| queries[query] = mergeObjects(baseEntry, override); | |
| }); | |
| const families = {}; | |
| Array.from(familyBuckets.keys()).sort((a, b) => a.localeCompare(b)).forEach((family) => { | |
| const base = { | |
| category: family, | |
| title: FAMILY_DEFAULTS[family].title, | |
| description: FAMILY_DEFAULTS[family].description, | |
| count: familyBuckets.get(family).length, | |
| commands: familyBuckets.get(family).slice().sort((a, b) => a.localeCompare(b)), | |
| when_to_use: FAMILY_DEFAULTS[family].when_to_use, | |
| mode_notes: FAMILY_DEFAULTS[family].mode_notes, | |
| verification: FAMILY_DEFAULTS[family].verification, | |
| }; | |
| families[family] = mergeObjects(base, familyOverrides[family] || {}); | |
| }); | |
| const commandEntryCount = Object.keys(commands).length; | |
| const queryCount = Object.keys(queries).length; | |
| const entryCount = commandEntryCount + queryCount; | |
| const uiActionCount = Object.values(commands).filter((entry) => entry && entry.entry_kind === 'ui_action').length; | |
| const envCommandCount = commandEntryCount - uiActionCount; | |
| const registry = { | |
| meta: { | |
| generated_at: new Date().toISOString(), | |
| generated_by: 'scripts/generate-env-help-registry.js', | |
| update_commands: [ | |
| 'node scripts/generate-env-help-registry.js', | |
| 'npm run build:env-help', | |
| ], | |
| sources: [ | |
| 'server.py::_ENV_CONTROL_PROXY_COMMANDS', | |
| 'static/main.js::command_surface.host_commands', | |
| 'static/main.js::command handlers and _envQueueControl callsites', | |
| 'static/main.js::ui action handlers and data-env-action entrypoints', | |
| 'static/data/help/environment_command_overrides.json', | |
| ], | |
| counts: { | |
| entries: entryCount, | |
| env_commands: envCommandCount, | |
| ui_actions: uiActionCount, | |
| queries: queryCount, | |
| proxied_commands: proxyCommands.size, | |
| host_commands: hostCommands.size, | |
| families: Object.keys(families).length, | |
| playbooks: Object.keys(playbooks).length, | |
| }, | |
| }, | |
| families, | |
| commands, | |
| queries, | |
| playbooks, | |
| }; | |
| fs.mkdirSync(path.dirname(outputPath), { recursive: true }); | |
| fs.writeFileSync(outputPath, `${JSON.stringify(registry, null, 2)}\n`, 'utf8'); | |
| console.log(`Wrote ${outputPath}`); | |
| console.log(`Entries: ${entryCount}`); | |
| console.log(`Env commands: ${envCommandCount}`); | |
| console.log(`UI actions: ${uiActionCount}`); | |
| console.log(`Queries: ${queryCount}`); | |
| console.log(`Families: ${Object.keys(families).length}`); | |
| console.log(`Playbooks: ${Object.keys(playbooks).length}`); | |