@llblab/pi-kit 0.38.3 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-actors/AGENTS.md +108 -20
- package/node_modules/@llblab/pi-actors/BACKLOG.md +207 -4
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +13 -0
- package/node_modules/@llblab/pi-actors/README.md +31 -1
- package/node_modules/@llblab/pi-actors/dist/index.js +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +131 -62
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.js +3 -2
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.js +263 -129
- package/node_modules/@llblab/pi-actors/dist/lib/execution-files.d.ts +32 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-files.js +128 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-output.js +5 -4
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.d.ts +19 -1
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.js +62 -26
- package/node_modules/@llblab/pi-actors/dist/lib/execution.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/execution.js +6 -1
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +9 -2
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +92 -14
- package/node_modules/@llblab/pi-actors/dist/lib/file-state.js +21 -2
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.js +2 -2
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.d.ts +25 -7
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +562 -262
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.d.ts +20 -10
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.js +80 -91
- package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.js +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +15 -1
- package/node_modules/@llblab/pi-actors/dist/lib/observability.js +216 -99
- package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +5 -4
- package/node_modules/@llblab/pi-actors/dist/lib/pi.js +64 -10
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.js +220 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.js +30 -6
- package/node_modules/@llblab/pi-actors/dist/lib/registry.js +270 -36
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +213 -5
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +1909 -40
- package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.d.ts +107 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.js +412 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +9 -2
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +283 -60
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.d.ts +26 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.js +68 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.d.ts +451 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.js +2315 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.d.ts +97 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.js +368 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.js +46 -7
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.d.ts +78 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.js +334 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.js +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.d.ts +80 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.js +287 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.d.ts +110 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.js +282 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.d.ts +66 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.js +349 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.d.ts +73 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.js +227 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.d.ts +141 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.js +292 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.d.ts +10 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.js +36 -4
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.d.ts +46 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.js +114 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.d.ts +34 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.js +158 -26
- package/node_modules/@llblab/pi-actors/dist/lib/runs-results.d.ts +116 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-results.js +518 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.d.ts +15 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.js +148 -9
- package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.d.ts +95 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.js +470 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.d.ts +58 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.js +92 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.js +44 -3
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.d.ts +15 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.js +337 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.d.ts +105 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.js +501 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +14 -3
- package/node_modules/@llblab/pi-actors/dist/lib/runtime.js +22 -3
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +59 -3
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.js +14 -8
- package/node_modules/@llblab/pi-actors/dist/lib/temp.d.ts +2 -4
- package/node_modules/@llblab/pi-actors/dist/lib/temp.js +4 -56
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.js +13 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +110 -43
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.js +18 -6
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.js +126 -31
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.d.ts +31 -3
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.js +311 -47
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.js +29 -7
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +192 -43
- package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +272 -194
- package/node_modules/@llblab/pi-actors/dist/scripts/conformance.mjs +14 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +46 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/diagnostics.md +40 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +55 -1
- package/node_modules/@llblab/pi-actors/docs/README.md +9 -1
- package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +84 -15
- package/node_modules/@llblab/pi-actors/docs/agent-experience.md +216 -0
- package/node_modules/@llblab/pi-actors/docs/async-runs.md +18 -2
- package/node_modules/@llblab/pi-actors/docs/composition-transport.md +103 -0
- package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +204 -4
- package/node_modules/@llblab/pi-actors/docs/inspection.md +38 -2
- package/node_modules/@llblab/pi-actors/docs/output-projection-map.md +130 -0
- package/node_modules/@llblab/pi-actors/docs/releasing.md +19 -2
- package/node_modules/@llblab/pi-actors/docs/run-supervision.md +1622 -0
- package/node_modules/@llblab/pi-actors/docs/template-recipes.md +4 -0
- package/node_modules/@llblab/pi-actors/docs/windows-process-observation.md +248 -0
- package/node_modules/@llblab/pi-actors/index.ts +1 -1
- package/node_modules/@llblab/pi-actors/lib/async-runs.ts +164 -73
- package/node_modules/@llblab/pi-actors/lib/automatic-review-runtime.ts +4 -2
- package/node_modules/@llblab/pi-actors/lib/command-templates.ts +287 -138
- package/node_modules/@llblab/pi-actors/lib/execution-files.ts +118 -0
- package/node_modules/@llblab/pi-actors/lib/execution-output.ts +4 -4
- package/node_modules/@llblab/pi-actors/lib/execution-sessions.ts +57 -27
- package/node_modules/@llblab/pi-actors/lib/execution.ts +8 -0
- package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +102 -12
- package/node_modules/@llblab/pi-actors/lib/file-state.ts +16 -2
- package/node_modules/@llblab/pi-actors/lib/inspector-command.ts +2 -2
- package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +524 -261
- package/node_modules/@llblab/pi-actors/lib/inspector.ts +101 -130
- package/node_modules/@llblab/pi-actors/lib/limits.ts +1 -0
- package/node_modules/@llblab/pi-actors/lib/observability.ts +235 -116
- package/node_modules/@llblab/pi-actors/lib/pi.ts +59 -11
- package/node_modules/@llblab/pi-actors/lib/recipe-projection.ts +232 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-context.ts +27 -6
- package/node_modules/@llblab/pi-actors/lib/registry.ts +266 -36
- package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +1737 -49
- package/node_modules/@llblab/pi-actors/lib/run-supervision.ts +411 -0
- package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +237 -73
- package/node_modules/@llblab/pi-actors/lib/runs-artifacts.ts +73 -1
- package/node_modules/@llblab/pi-actors/lib/runs-context-exports.ts +1871 -0
- package/node_modules/@llblab/pi-actors/lib/runs-context-index.ts +372 -0
- package/node_modules/@llblab/pi-actors/lib/runs-control-delivery.ts +36 -18
- package/node_modules/@llblab/pi-actors/lib/runs-control.ts +297 -1
- package/node_modules/@llblab/pi-actors/lib/runs-controls.ts +3 -1
- package/node_modules/@llblab/pi-actors/lib/runs-descendant-launches.ts +338 -0
- package/node_modules/@llblab/pi-actors/lib/runs-execution-evidence.ts +302 -0
- package/node_modules/@llblab/pi-actors/lib/runs-index.ts +345 -17
- package/node_modules/@llblab/pi-actors/lib/runs-native-launches.ts +270 -0
- package/node_modules/@llblab/pi-actors/lib/runs-outcomes.ts +377 -0
- package/node_modules/@llblab/pi-actors/lib/runs-ownership.ts +37 -4
- package/node_modules/@llblab/pi-actors/lib/runs-process-windows-mi.ts +113 -0
- package/node_modules/@llblab/pi-actors/lib/runs-process.ts +210 -34
- package/node_modules/@llblab/pi-actors/lib/runs-results.ts +601 -0
- package/node_modules/@llblab/pi-actors/lib/runs-retention.ts +134 -10
- package/node_modules/@llblab/pi-actors/lib/runs-session-exports.ts +406 -0
- package/node_modules/@llblab/pi-actors/lib/runs-snapshot.ts +143 -0
- package/node_modules/@llblab/pi-actors/lib/runs-start.ts +44 -2
- package/node_modules/@llblab/pi-actors/lib/runs-status.ts +252 -10
- package/node_modules/@llblab/pi-actors/lib/runs-supervision.ts +394 -0
- package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +14 -3
- package/node_modules/@llblab/pi-actors/lib/runtime.ts +22 -3
- package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +76 -4
- package/node_modules/@llblab/pi-actors/lib/state-readers.ts +16 -7
- package/node_modules/@llblab/pi-actors/lib/temp.ts +3 -56
- package/node_modules/@llblab/pi-actors/lib/tools-access.ts +13 -0
- package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +110 -51
- package/node_modules/@llblab/pi-actors/lib/tools-local.ts +37 -24
- package/node_modules/@llblab/pi-actors/lib/tools-message.ts +120 -37
- package/node_modules/@llblab/pi-actors/lib/tools-response.ts +273 -50
- package/node_modules/@llblab/pi-actors/lib/tools-spawn.ts +31 -10
- package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +165 -42
- package/node_modules/@llblab/pi-actors/package.json +10 -6
- package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +272 -194
- package/node_modules/@llblab/pi-actors/scripts/conformance.mjs +14 -2
- package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +46 -2
- package/node_modules/@llblab/pi-actors/skills/actors/references/diagnostics.md +40 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +55 -1
- package/node_modules/@llblab/pi-codex-usage/AGENTS.md +2 -2
- package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +6 -0
- package/node_modules/@llblab/pi-codex-usage/README.md +9 -5
- package/node_modules/@llblab/pi-codex-usage/lib/query.ts +229 -50
- package/node_modules/@llblab/pi-codex-usage/lib/usage.ts +9 -1
- package/node_modules/@llblab/pi-codex-usage/package.json +1 -1
- package/node_modules/yaml/LICENSE +13 -0
- package/node_modules/yaml/README.md +172 -0
- package/node_modules/yaml/bin.mjs +11 -0
- package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
- package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
- package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
- package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
- package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
- package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
- package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
- package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
- package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
- package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
- package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
- package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
- package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
- package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
- package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
- package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
- package/node_modules/yaml/browser/dist/errors.js +57 -0
- package/node_modules/yaml/browser/dist/index.js +17 -0
- package/node_modules/yaml/browser/dist/log.js +11 -0
- package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
- package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
- package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
- package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
- package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
- package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
- package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
- package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
- package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
- package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
- package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
- package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
- package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
- package/node_modules/yaml/browser/dist/public-api.js +102 -0
- package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
- package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
- package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
- package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
- package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
- package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
- package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
- package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
- package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
- package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
- package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
- package/node_modules/yaml/browser/dist/util.js +11 -0
- package/node_modules/yaml/browser/dist/visit.js +233 -0
- package/node_modules/yaml/browser/index.js +5 -0
- package/node_modules/yaml/browser/package.json +3 -0
- package/node_modules/yaml/dist/cli.d.ts +8 -0
- package/node_modules/yaml/dist/cli.mjs +201 -0
- package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
- package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
- package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
- package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
- package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
- package/node_modules/yaml/dist/compose/compose-node.js +112 -0
- package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
- package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
- package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
- package/node_modules/yaml/dist/compose/composer.js +224 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
- package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
- package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
- package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
- package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
- package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
- package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
- package/node_modules/yaml/dist/doc/Document.js +337 -0
- package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
- package/node_modules/yaml/dist/doc/anchors.js +76 -0
- package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
- package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
- package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
- package/node_modules/yaml/dist/doc/createNode.js +90 -0
- package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
- package/node_modules/yaml/dist/doc/directives.js +178 -0
- package/node_modules/yaml/dist/errors.d.ts +21 -0
- package/node_modules/yaml/dist/errors.js +62 -0
- package/node_modules/yaml/dist/index.d.ts +25 -0
- package/node_modules/yaml/dist/index.js +50 -0
- package/node_modules/yaml/dist/log.d.ts +3 -0
- package/node_modules/yaml/dist/log.js +19 -0
- package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/Alias.js +118 -0
- package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
- package/node_modules/yaml/dist/nodes/Collection.js +151 -0
- package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/Node.js +40 -0
- package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
- package/node_modules/yaml/dist/nodes/Pair.js +39 -0
- package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
- package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
- package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
- package/node_modules/yaml/dist/nodes/identity.js +53 -0
- package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/toJS.js +39 -0
- package/node_modules/yaml/dist/options.d.ts +350 -0
- package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
- package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
- package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
- package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
- package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
- package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
- package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
- package/node_modules/yaml/dist/parse/cst.js +112 -0
- package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
- package/node_modules/yaml/dist/parse/lexer.js +723 -0
- package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
- package/node_modules/yaml/dist/parse/line-counter.js +41 -0
- package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
- package/node_modules/yaml/dist/parse/parser.js +980 -0
- package/node_modules/yaml/dist/public-api.d.ts +44 -0
- package/node_modules/yaml/dist/public-api.js +107 -0
- package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
- package/node_modules/yaml/dist/schema/Schema.js +39 -0
- package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/map.js +19 -0
- package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
- package/node_modules/yaml/dist/schema/common/null.js +17 -0
- package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/seq.js +19 -0
- package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/string.js +16 -0
- package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/bool.js +21 -0
- package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/float.js +47 -0
- package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/int.js +42 -0
- package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/core/schema.js +25 -0
- package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
- package/node_modules/yaml/dist/schema/json/schema.js +64 -0
- package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
- package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
- package/node_modules/yaml/dist/schema/tags.js +99 -0
- package/node_modules/yaml/dist/schema/types.d.ts +92 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
- package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
- package/node_modules/yaml/dist/stringify/stringify.js +132 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
- package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
- package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
- package/node_modules/yaml/dist/test-events.d.ts +4 -0
- package/node_modules/yaml/dist/test-events.js +134 -0
- package/node_modules/yaml/dist/util.d.ts +16 -0
- package/node_modules/yaml/dist/util.js +28 -0
- package/node_modules/yaml/dist/visit.d.ts +102 -0
- package/node_modules/yaml/dist/visit.js +236 -0
- package/node_modules/yaml/package.json +97 -0
- package/node_modules/yaml/util.js +2 -0
- package/package.json +3 -3
- package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +0 -16
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +0 -57
- package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +0 -79
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
import { readFileSync, statSync } from "node:fs";
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
|
|
10
|
-
import type
|
|
10
|
+
import { getMarkdownTheme, type Theme } from "@earendil-works/pi-coding-agent";
|
|
11
|
+
import { Document, isScalar, visit } from "yaml";
|
|
11
12
|
import {
|
|
12
13
|
matchesKey,
|
|
14
|
+
Markdown,
|
|
13
15
|
sliceByColumn,
|
|
14
16
|
truncateToWidth,
|
|
15
17
|
visibleWidth,
|
|
@@ -22,8 +24,9 @@ import * as RunsControls from "./runs-controls.ts";
|
|
|
22
24
|
import * as RunControlDelivery from "./runs-control-delivery.ts";
|
|
23
25
|
import * as RunsTrace from "./runs-trace.ts";
|
|
24
26
|
import * as Limits from "./limits.ts";
|
|
25
|
-
import { computeRunControlCapacity } from "./run-evidence-policy.ts";
|
|
27
|
+
import { computeRunControlCapacity, runControlStatusTimestamp } from "./run-evidence-policy.ts";
|
|
26
28
|
import * as RuntimeTriage from "./runtime-triage.ts";
|
|
29
|
+
import { normalizeRecipeControl } from "./recipe-control.ts";
|
|
27
30
|
import * as TraceProjection from "./trace-projection.ts";
|
|
28
31
|
|
|
29
32
|
export type ActorInspectorTab = "recipe" | "trace" | "control";
|
|
@@ -52,6 +55,21 @@ export interface ActorInspectorOverlayOptions {
|
|
|
52
55
|
tui: TUI;
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// Per-render provenance, not parsed from authored text or retained as source metadata.
|
|
59
|
+
interface InspectorDocumentLine {
|
|
60
|
+
text: string;
|
|
61
|
+
label?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type AgentDetailSegment = { kind: "metadata"; value: unknown } | { kind: "body"; text: string };
|
|
65
|
+
|
|
66
|
+
interface ControlObservation {
|
|
67
|
+
run: string;
|
|
68
|
+
generation?: string;
|
|
69
|
+
document: Record<string, unknown>;
|
|
70
|
+
rows: Array<{ id: string; value: ControlProjection.ProjectedRunControl; age: number; reason?: string }>;
|
|
71
|
+
}
|
|
72
|
+
|
|
55
73
|
interface KillConfirmation {
|
|
56
74
|
run: string;
|
|
57
75
|
runInstanceId: string;
|
|
@@ -84,12 +102,20 @@ export class ActorInspectorOverlay {
|
|
|
84
102
|
private documentScroll = 0;
|
|
85
103
|
private detailScroll = 0;
|
|
86
104
|
private feedback?: ActorInspectorActionResult;
|
|
105
|
+
private feedbackFromAction = false;
|
|
106
|
+
private feedbackScroll = 0;
|
|
107
|
+
private feedbackPageRows = 1;
|
|
108
|
+
private inspectorFrame?: { width: number; lines: string[] };
|
|
87
109
|
private focus: InspectorFocus = "runs";
|
|
88
110
|
private killConfirmation?: KillConfirmation;
|
|
89
111
|
private killDialogChoice: "cancel" | "kill" = "cancel";
|
|
112
|
+
private killDialogScroll = 0;
|
|
113
|
+
private killDialogPageRows = 1;
|
|
90
114
|
private rowIndex = 0;
|
|
91
115
|
private runCache?: ActorInspector.ActorInspectorRunItem[];
|
|
92
116
|
private selectedTraceId?: string;
|
|
117
|
+
private controlCache?: ControlObservation;
|
|
118
|
+
private controlSelection?: { run: string; generation?: string; id: string };
|
|
93
119
|
private runIndex = 0;
|
|
94
120
|
private selectorIndex = 0;
|
|
95
121
|
private selectorMode?: SelectorMode;
|
|
@@ -98,6 +124,7 @@ export class ActorInspectorOverlay {
|
|
|
98
124
|
run: string;
|
|
99
125
|
runInstanceId?: string;
|
|
100
126
|
items: TraceProjection.TraceItem[];
|
|
127
|
+
journalSummary?: ReturnType<typeof RunsTrace.summarizeRunTraceJournal>;
|
|
101
128
|
};
|
|
102
129
|
private traceDetail?: TraceProjection.TraceItem;
|
|
103
130
|
private traceSourceIndex = 0;
|
|
@@ -125,11 +152,10 @@ export class ActorInspectorOverlay {
|
|
|
125
152
|
invalidate(): void {
|
|
126
153
|
this.runCache = undefined;
|
|
127
154
|
this.traceCache = undefined;
|
|
155
|
+
this.controlCache = undefined;
|
|
128
156
|
}
|
|
129
157
|
|
|
130
158
|
handleInput(data: string): void {
|
|
131
|
-
const runs = this.runs();
|
|
132
|
-
this.runIndex = Math.min(this.runIndex, Math.max(0, runs.length - 1));
|
|
133
159
|
if (matchesKey(data, "ctrl+c")) {
|
|
134
160
|
this.done();
|
|
135
161
|
return;
|
|
@@ -139,11 +165,30 @@ export class ActorInspectorOverlay {
|
|
|
139
165
|
this.tui.requestRender();
|
|
140
166
|
return;
|
|
141
167
|
}
|
|
168
|
+
if (this.feedback) {
|
|
169
|
+
if (matchesKey(data, "escape")) {
|
|
170
|
+
this.feedback = undefined;
|
|
171
|
+
this.feedbackFromAction = false;
|
|
172
|
+
this.feedbackScroll = 0;
|
|
173
|
+
} else if (matchesKey(data, "up")) this.feedbackScroll = Math.max(0, this.feedbackScroll - 1);
|
|
174
|
+
else if (matchesKey(data, "down")) this.feedbackScroll++;
|
|
175
|
+
else if (matchesKey(data, "pageUp")) this.feedbackScroll = Math.max(0, this.feedbackScroll - this.feedbackPageRows);
|
|
176
|
+
else if (matchesKey(data, "pageDown")) this.feedbackScroll += this.feedbackPageRows;
|
|
177
|
+
this.tui.requestRender();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const runs = this.runs();
|
|
181
|
+
this.runIndex = Math.min(this.runIndex, Math.max(0, runs.length - 1));
|
|
142
182
|
if (data.toLowerCase() === "k") {
|
|
143
183
|
this.requestKill(runs[this.runIndex]);
|
|
144
184
|
this.tui.requestRender();
|
|
145
185
|
return;
|
|
146
186
|
}
|
|
187
|
+
if (this.tab === "control" && (this.focus === "list" || this.focus === "detail")) {
|
|
188
|
+
this.handleControlInput(data, runs[this.runIndex]);
|
|
189
|
+
this.tui.requestRender();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
147
192
|
if (matchesKey(data, "escape")) {
|
|
148
193
|
if (this.focus === "select") {
|
|
149
194
|
this.selectorMode = undefined;
|
|
@@ -173,7 +218,8 @@ export class ActorInspectorOverlay {
|
|
|
173
218
|
return;
|
|
174
219
|
}
|
|
175
220
|
if (this.focus === "document") {
|
|
176
|
-
if (matchesKey(data, "
|
|
221
|
+
if (this.tab === "control" && matchesKey(data, "return")) this.openControlList(runs[this.runIndex]);
|
|
222
|
+
else if (matchesKey(data, "left")) this.focus = "tabs";
|
|
177
223
|
else if (matchesKey(data, "up") && this.documentScroll === 0) this.focus = "tabs";
|
|
178
224
|
else this.handleScrollableInput(data, "document");
|
|
179
225
|
this.tui.requestRender();
|
|
@@ -204,6 +250,7 @@ export class ActorInspectorOverlay {
|
|
|
204
250
|
}
|
|
205
251
|
} else if (matchesKey(data, "return")) {
|
|
206
252
|
if (this.tab === "trace") this.openSourceSelector(runs[this.runIndex]);
|
|
253
|
+
else if (this.tab === "control") this.openControlList(runs[this.runIndex]);
|
|
207
254
|
else this.focus = "document";
|
|
208
255
|
}
|
|
209
256
|
} else if (this.focus === "list") {
|
|
@@ -244,32 +291,27 @@ export class ActorInspectorOverlay {
|
|
|
244
291
|
|
|
245
292
|
render(width: number): string[] {
|
|
246
293
|
const safeWidth = Math.max(24, width);
|
|
294
|
+
const modal = !!(this.killConfirmation || this.feedback);
|
|
295
|
+
if (!modal || !this.inspectorFrame) this.inspectorFrame = { width: safeWidth, lines: this.renderInspector(safeWidth) };
|
|
296
|
+
const lines = this.modalUnderlay(safeWidth);
|
|
297
|
+
if (this.killConfirmation) this.compositePopup(lines, this.renderKillDialog(safeWidth - 2, lines.length), safeWidth);
|
|
298
|
+
else if (this.feedback) this.compositePopup(lines, this.renderFeedbackPopup(safeWidth, lines.length), safeWidth);
|
|
299
|
+
return lines;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private renderInspector(safeWidth: number): string[] {
|
|
247
303
|
const innerWidth = safeWidth - 2;
|
|
248
304
|
const runs = this.runs();
|
|
249
305
|
this.runIndex = Math.min(this.runIndex, Math.max(0, runs.length - 1));
|
|
250
306
|
const run = runs[this.runIndex];
|
|
251
|
-
if (this.killConfirmation) return this.renderKillDialog(innerWidth);
|
|
252
|
-
|
|
253
307
|
const lines = [this.border("╭", " Actor Inspector ", "╮", innerWidth)];
|
|
254
|
-
lines.push(this.row(this.renderRunControl(run, runs.length - this.runIndex - 1), innerWidth));
|
|
308
|
+
lines.push(this.row(this.renderRunControl(run, runs.length - this.runIndex - 1, innerWidth), innerWidth));
|
|
255
309
|
lines.push(this.row(this.renderTabs(run), innerWidth));
|
|
256
310
|
lines.push(this.border("├", "", "┤", innerWidth));
|
|
257
311
|
|
|
258
312
|
this.contentSelectedRows.clear();
|
|
259
313
|
this.contentStripeIndices = [];
|
|
260
314
|
let content = this.renderContent(run, innerWidth);
|
|
261
|
-
if (this.feedback) {
|
|
262
|
-
const color = this.feedback.ok
|
|
263
|
-
? "success"
|
|
264
|
-
: /^Kill (failed|rejected)/u.test(this.feedback.message)
|
|
265
|
-
? "error"
|
|
266
|
-
: "warning";
|
|
267
|
-
content = [this.theme.fg(color, ` ${this.feedback.message}`), ...content];
|
|
268
|
-
this.contentSelectedRows = new Set(
|
|
269
|
-
[...this.contentSelectedRows].map((index) => index + 1),
|
|
270
|
-
);
|
|
271
|
-
this.contentStripeIndices = [0, ...this.contentStripeIndices];
|
|
272
|
-
}
|
|
273
315
|
const viewportRows = this.contentViewportRows();
|
|
274
316
|
content = content.slice(0, viewportRows);
|
|
275
317
|
for (let index = 0; index < viewportRows; index += 1) {
|
|
@@ -284,9 +326,9 @@ export class ActorInspectorOverlay {
|
|
|
284
326
|
if (this.focus === "select") {
|
|
285
327
|
const runSelector = this.selectorMode === "run";
|
|
286
328
|
const startRow = runSelector ? 2 : 3;
|
|
287
|
-
const horizontalOffset = runSelector ?
|
|
329
|
+
const horizontalOffset = runSelector ? 5 : 12;
|
|
288
330
|
const availableRows = Math.max(3, lines.length - startRow - 1);
|
|
289
|
-
const menu = this.renderSelector(run, availableRows);
|
|
331
|
+
const menu = this.renderSelector(run, availableRows, innerWidth);
|
|
290
332
|
for (const [offset, menuLine] of menu.entries()) {
|
|
291
333
|
const target = startRow + offset;
|
|
292
334
|
if (target >= lines.length - 1) break;
|
|
@@ -333,12 +375,13 @@ export class ActorInspectorOverlay {
|
|
|
333
375
|
|
|
334
376
|
private handleScrollableInput(data: string, target: "detail" | "document"): void {
|
|
335
377
|
const key = target === "detail" ? "detailScroll" : "documentScroll";
|
|
378
|
+
const pageRows = () => this.contentViewportRows();
|
|
336
379
|
if (matchesKey(data, "up")) this[key] = Math.max(0, this[key] - 1);
|
|
337
380
|
else if (matchesKey(data, "down")) this[key] += 1;
|
|
338
381
|
else if (matchesKey(data, "pageUp")) {
|
|
339
|
-
this[key] = Math.max(0, this[key] -
|
|
382
|
+
this[key] = Math.max(0, this[key] - pageRows());
|
|
340
383
|
} else if (matchesKey(data, "pageDown")) {
|
|
341
|
-
this[key] +=
|
|
384
|
+
this[key] += pageRows();
|
|
342
385
|
} else if (matchesKey(data, "left") && target === "detail") {
|
|
343
386
|
this.selectedTraceId = this.traceDetail?.id;
|
|
344
387
|
this.traceDetail = undefined;
|
|
@@ -389,6 +432,8 @@ export class ActorInspectorOverlay {
|
|
|
389
432
|
|
|
390
433
|
private requestKill(run?: ActorInspector.ActorInspectorRunItem): void {
|
|
391
434
|
this.feedback = undefined;
|
|
435
|
+
this.feedbackFromAction = false;
|
|
436
|
+
this.feedbackScroll = 0;
|
|
392
437
|
if (this.focus !== "runs") {
|
|
393
438
|
this.feedback = { ok: false, message: "Focus Run before using Kill." };
|
|
394
439
|
return;
|
|
@@ -415,12 +460,17 @@ export class ActorInspectorOverlay {
|
|
|
415
460
|
status: run.status,
|
|
416
461
|
};
|
|
417
462
|
this.killDialogChoice = "cancel";
|
|
463
|
+
this.killDialogScroll = 0;
|
|
418
464
|
}
|
|
419
465
|
|
|
420
466
|
private handleKillInput(data: string): void {
|
|
421
467
|
const key = data.toLowerCase();
|
|
422
|
-
if (matchesKey(data, "
|
|
423
|
-
this.
|
|
468
|
+
if (matchesKey(data, "pageUp")) {
|
|
469
|
+
this.killDialogScroll = Math.max(0, this.killDialogScroll - this.killDialogPageRows);
|
|
470
|
+
} else if (matchesKey(data, "pageDown")) {
|
|
471
|
+
this.killDialogScroll += this.killDialogPageRows;
|
|
472
|
+
} else if (matchesKey(data, "escape") || key === "n") {
|
|
473
|
+
this.feedback = undefined;
|
|
424
474
|
this.killConfirmation = undefined;
|
|
425
475
|
this.killDialogChoice = "cancel";
|
|
426
476
|
} else if (matchesKey(data, "left") || matchesKey(data, "right") || matchesKey(data, "tab")) {
|
|
@@ -430,7 +480,7 @@ export class ActorInspectorOverlay {
|
|
|
430
480
|
} else if (matchesKey(data, "return")) {
|
|
431
481
|
if (this.killDialogChoice === "kill") this.confirmKill();
|
|
432
482
|
else {
|
|
433
|
-
this.feedback =
|
|
483
|
+
this.feedback = undefined;
|
|
434
484
|
this.killConfirmation = undefined;
|
|
435
485
|
}
|
|
436
486
|
}
|
|
@@ -441,52 +491,63 @@ export class ActorInspectorOverlay {
|
|
|
441
491
|
this.killConfirmation = undefined;
|
|
442
492
|
this.killDialogChoice = "cancel";
|
|
443
493
|
if (!confirmation || !this.killRun) return;
|
|
494
|
+
this.feedbackFromAction = true;
|
|
444
495
|
try {
|
|
445
496
|
const result = this.killRun(confirmation.run, confirmation.runInstanceId);
|
|
446
497
|
this.feedback = result.ok ? undefined : result;
|
|
447
498
|
if (result.ok) this.invalidate();
|
|
448
499
|
} catch (error) {
|
|
449
500
|
const message = error instanceof Error ? error.message : String(error);
|
|
501
|
+
const normalized = message.replaceAll(/\s+/g, " ");
|
|
502
|
+
let selected = normalized.slice(0, 160);
|
|
503
|
+
const clipped = typeof normalized === "string" && normalized.length > 160;
|
|
504
|
+
if (clipped && typeof selected === "string" && /[\uD800-\uDBFF]/u.test(selected.at(-1) ?? "") && /[\uDC00-\uDFFF]/u.test(normalized[160]!)) selected = selected.slice(0, -1);
|
|
450
505
|
this.feedback = {
|
|
451
506
|
ok: false,
|
|
452
|
-
message:
|
|
507
|
+
message: ActorInspector.formatActorInspectorKillFeedback("failed", `${selected}`, { clipped }),
|
|
453
508
|
};
|
|
454
509
|
}
|
|
455
510
|
}
|
|
456
511
|
|
|
457
|
-
private renderKillDialog(
|
|
512
|
+
private renderKillDialog(width: number, maxRows: number): string[] {
|
|
513
|
+
const innerWidth = Math.min(width, 70), textWidth = innerWidth - 2;
|
|
458
514
|
const confirmation = this.killConfirmation!;
|
|
459
515
|
const cancel = this.killDialogChoice === "cancel"
|
|
460
|
-
? this.theme.bg("selectedBg", this.theme.fg("accent", "
|
|
461
|
-
: this.theme.fg("muted", "
|
|
516
|
+
? this.theme.bg("selectedBg", this.theme.fg("accent", " Cancel "))
|
|
517
|
+
: this.theme.fg("muted", " Cancel ");
|
|
462
518
|
const kill = this.killDialogChoice === "kill"
|
|
463
|
-
? this.theme.bg("selectedBg", this.theme.fg("error", "
|
|
464
|
-
: this.theme.fg("error", "
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
"",
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this.
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
519
|
+
? this.theme.bg("selectedBg", this.theme.fg("error", " Kill actor "))
|
|
520
|
+
: this.theme.fg("error", " Kill actor ");
|
|
521
|
+
const details = this.documentProjection({
|
|
522
|
+
run: confirmation.run,
|
|
523
|
+
state: confirmation.status,
|
|
524
|
+
action: "generation-fenced runtime kill",
|
|
525
|
+
}, textWidth).lines;
|
|
526
|
+
const safety = this.closureWarning(textWidth).map(line => this.theme.fg("warning", line));
|
|
527
|
+
const choices = visibleWidth(cancel) + 2 + visibleWidth(kill) <= textWidth
|
|
528
|
+
? [this.center(`${cancel} ${kill}`, textWidth)]
|
|
529
|
+
: [this.center(cancel, textWidth), this.center(kill, textWidth)];
|
|
530
|
+
const layout = this.popupLayout(maxRows, safety.length + 1 + choices.length, details.length);
|
|
531
|
+
this.killDialogPageRows = layout.pageRows;
|
|
532
|
+
this.killDialogScroll = Math.min(this.killDialogScroll, Math.max(0, details.length - this.killDialogPageRows));
|
|
533
|
+
const visible = details.slice(this.killDialogScroll, this.killDialogScroll + this.killDialogPageRows);
|
|
534
|
+
const hints = innerWidth < 30 ? this.keyHints(["↵", "pick"], ["esc", "back"])
|
|
535
|
+
: innerWidth < 60 ? this.keyHints(["←→/tab", "choose"], ["↵", "pick"], ["esc", "back"]) : this.renderKeyHints(true);
|
|
536
|
+
return [
|
|
537
|
+
this.border("╭", " Confirm Actor Kill ", "╮", innerWidth),
|
|
538
|
+
...(layout.top ? [this.row("", innerWidth)] : []),
|
|
539
|
+
...visible.map(line => this.row(" " + line, innerWidth)),
|
|
540
|
+
...(layout.paged ? [this.row(" " + this.theme.fg("muted", `${this.killDialogScroll + 1}-${this.killDialogScroll + visible.length}/${details.length} pgup/pgdn`), innerWidth)] : []),
|
|
541
|
+
...[...safety, "", ...choices].map(line => this.row(" " + line, innerWidth)),
|
|
542
|
+
...(layout.bottom ? [this.row("", innerWidth)] : []),
|
|
543
|
+
this.footerBorder(hints, innerWidth),
|
|
476
544
|
];
|
|
477
|
-
const lines = [this.border("╭", " Confirm Actor Kill ", "╮", innerWidth)];
|
|
478
|
-
const availableRows = this.contentViewportRows() + 3;
|
|
479
|
-
const topPadding = Math.max(0, Math.floor((availableRows - body.length) / 2));
|
|
480
|
-
const rows = [...Array.from({ length: topPadding }, () => ""), ...body].slice(0, availableRows);
|
|
481
|
-
while (rows.length < availableRows) rows.push("");
|
|
482
|
-
for (const line of rows) lines.push(this.row(this.center(line, innerWidth), innerWidth));
|
|
483
|
-
lines.push(this.footerBorder(this.renderKeyHints(), innerWidth));
|
|
484
|
-
return lines;
|
|
485
545
|
}
|
|
486
546
|
|
|
487
547
|
private renderRunControl(
|
|
488
548
|
run: ActorInspector.ActorInspectorRunItem | undefined,
|
|
489
549
|
sequence: number,
|
|
550
|
+
width: number,
|
|
490
551
|
): string {
|
|
491
552
|
const active = this.focus === "runs" || (this.focus === "select" && this.selectorMode === "run");
|
|
492
553
|
const prefix = active ? this.theme.fg("accent", " ← ") : " ";
|
|
@@ -496,11 +557,12 @@ export class ActorInspectorOverlay {
|
|
|
496
557
|
return active ? this.theme.bg("selectedBg", empty) : empty;
|
|
497
558
|
}
|
|
498
559
|
const value = `${prefix}${this.theme.fg("muted", "Run: ")}${this.theme.fg("text", `#${sequence}`)} ${this.theme.fg("accent", run.run)} ${this.theme.fg(this.statusColor(run.status), run.status)}${suffix}`;
|
|
499
|
-
|
|
560
|
+
const bounded = truncateToWidth(value, width, "…");
|
|
561
|
+
return active ? this.theme.bg("selectedBg", bounded) : bounded;
|
|
500
562
|
}
|
|
501
563
|
|
|
502
564
|
private renderTabs(run?: ActorInspector.ActorInspectorRunItem): string {
|
|
503
|
-
const source = this.traceSource(run);
|
|
565
|
+
const source = this.tab === "trace" ? this.traceSource(run) : "all";
|
|
504
566
|
return TABS.map((tab, index) => {
|
|
505
567
|
const base = `${tab[0]!.toUpperCase()}${tab.slice(1)}`;
|
|
506
568
|
const label = tab === "trace" && source !== "all" ? `${base}: ${source}` : base;
|
|
@@ -527,13 +589,20 @@ export class ActorInspectorOverlay {
|
|
|
527
589
|
width: number,
|
|
528
590
|
): string[] {
|
|
529
591
|
if (!run) return [this.theme.fg("muted", " No owned actor runs")];
|
|
592
|
+
if (this.tab === "control" && (this.focus === "list" || this.focus === "detail")) return this.renderControlContent(run, width);
|
|
530
593
|
if (this.focus === "detail") return this.renderTraceDetail(width);
|
|
531
|
-
if (this.tab === "trace") return this.renderTraceList(run);
|
|
532
|
-
const
|
|
594
|
+
if (this.tab === "trace") return this.renderTraceList(run, width);
|
|
595
|
+
const selectedRun = run.run;
|
|
596
|
+
const stateDir = path.join(this.stateRoot, selectedRun);
|
|
533
597
|
const value = this.tab === "recipe"
|
|
534
598
|
? ActorInspector.readActorInspectorRecipe(stateDir)
|
|
535
599
|
: this.controlDocument(run, stateDir);
|
|
536
|
-
const
|
|
600
|
+
const body = this.documentProjection(value, width);
|
|
601
|
+
const identity = this.documentProjection({ selected_run_id: selectedRun }, width);
|
|
602
|
+
const projection = {
|
|
603
|
+
lines: [...identity.lines, ...body.lines],
|
|
604
|
+
stripes: [...identity.stripes, ...body.stripes.map(index => index + 1)],
|
|
605
|
+
};
|
|
537
606
|
const maxStart = Math.max(0, projection.lines.length - this.contentViewportRows());
|
|
538
607
|
this.documentScroll = Math.min(this.documentScroll, maxStart);
|
|
539
608
|
this.contentStripeIndices = projection.stripes.slice(
|
|
@@ -546,12 +615,83 @@ export class ActorInspectorOverlay {
|
|
|
546
615
|
);
|
|
547
616
|
}
|
|
548
617
|
|
|
618
|
+
private modalUnderlay(width: number): string[] {
|
|
619
|
+
const frame = this.inspectorFrame!;
|
|
620
|
+
const height = this.contentViewportRows() + 5;
|
|
621
|
+
if (frame.width === width && frame.lines.length === height) return frame.lines.slice();
|
|
622
|
+
// Resize the frozen underlay without refreshing evidence behind an open modal.
|
|
623
|
+
const innerWidth = width - 2;
|
|
624
|
+
const content = (index: number) => sliceByColumn(frame.lines[index] ?? "", 1, frame.width - 2, true);
|
|
625
|
+
return [
|
|
626
|
+
this.border("╭", " Actor Inspector ", "╮", innerWidth),
|
|
627
|
+
this.row(content(1), innerWidth),
|
|
628
|
+
this.row(content(2), innerWidth),
|
|
629
|
+
this.border("├", "", "┤", innerWidth),
|
|
630
|
+
...Array.from({ length: height - 5 }, (_, index) =>
|
|
631
|
+
this.row(index < frame.lines.length - 5 ? content(index + 4) : "", innerWidth)),
|
|
632
|
+
this.footerBorder(content(frame.lines.length - 1), innerWidth),
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
private compositePopup(lines: string[], popup: string[], width: number): void {
|
|
637
|
+
const popupWidth = visibleWidth(popup[0]!);
|
|
638
|
+
const left = Math.floor((width - popupWidth) / 2);
|
|
639
|
+
const top = Math.floor((lines.length - popup.length) / 2);
|
|
640
|
+
for (const [offset, line] of popup.entries()) {
|
|
641
|
+
const base = lines[top + offset]!;
|
|
642
|
+
const right = left + popupWidth;
|
|
643
|
+
// Terminal-default background masks underlying stripes; selected buttons keep their own fill.
|
|
644
|
+
lines[top + offset] = `${sliceByColumn(base, 0, left, true)}\u001b[49m${line}\u001b[49m${sliceByColumn(base, right, width - right, true)}`;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
private popupLayout(maxRows: number, fixedRows: number, detailRows: number): { top: boolean; bottom: boolean; pageRows: number; paged: boolean } {
|
|
649
|
+
// Reserve readable text, pinned safety and choices before decorative blank rows.
|
|
650
|
+
const minimum = 2 + fixedRows + Math.min(2, detailRows);
|
|
651
|
+
const paddingRows = Math.min(2, Math.max(0, maxRows - minimum));
|
|
652
|
+
const height = Math.min(maxRows, Math.max(maxRows - 2, minimum + paddingRows));
|
|
653
|
+
const slots = height - 2 - fixedRows - paddingRows;
|
|
654
|
+
const paged = detailRows > slots;
|
|
655
|
+
return { top: paddingRows > 0, bottom: paddingRows > 1, pageRows: Math.min(detailRows, slots - Number(paged)), paged };
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private renderFeedbackPopup(width: number, maxRows: number): string[] {
|
|
659
|
+
const feedback = this.feedback!;
|
|
660
|
+
const innerWidth = Math.min(70, width - 2), textWidth = innerWidth - 2;
|
|
661
|
+
const color = feedback.ok
|
|
662
|
+
? "success"
|
|
663
|
+
: /^(?:Kill (?:failed|rejected)|- action: kill\n- result: (?:failed|rejected)\n)/u.test(feedback.message) ? "error" : "warning";
|
|
664
|
+
const message = `${feedback.message}`;
|
|
665
|
+
const details = this.wrapDocument(message.split(/\r\n|\r|\n/u).map(text => ({ text })), textWidth).map(line => line.text);
|
|
666
|
+
const safety = this.feedbackFromAction ? [...this.closureWarning(textWidth), "No automatic retry."] : [];
|
|
667
|
+
const layout = this.popupLayout(maxRows, safety.length, details.length);
|
|
668
|
+
this.feedbackPageRows = layout.pageRows;
|
|
669
|
+
this.feedbackScroll = Math.min(this.feedbackScroll, Math.max(0, details.length - this.feedbackPageRows));
|
|
670
|
+
const visible = details.slice(this.feedbackScroll, this.feedbackScroll + this.feedbackPageRows);
|
|
671
|
+
return [
|
|
672
|
+
this.border("╭", " Notice ", "╮", innerWidth),
|
|
673
|
+
...(layout.top ? [this.row("", innerWidth)] : []),
|
|
674
|
+
...visible.map(line => this.row(" " + this.theme.fg(color, line), innerWidth)),
|
|
675
|
+
...(layout.paged ? [this.row(" " + this.theme.fg("muted", `${this.feedbackScroll + 1}-${this.feedbackScroll + visible.length}/${details.length} ↑↓ pgup/pgdn`), innerWidth)] : []),
|
|
676
|
+
...safety.map(line => this.row(" " + this.theme.fg("warning", line), innerWidth)),
|
|
677
|
+
...(layout.bottom ? [this.row("", innerWidth)] : []),
|
|
678
|
+
this.footerBorder(this.keyHints(["esc", "close"]), innerWidth),
|
|
679
|
+
];
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
private closureWarning(width: number): string[] {
|
|
683
|
+
return width >= visibleWidth("- closure: unconfirmed")
|
|
684
|
+
? ["- closure: unconfirmed"] : ["- closure:", " unconfirmed"];
|
|
685
|
+
}
|
|
686
|
+
|
|
549
687
|
private renderSelector(
|
|
550
688
|
run: ActorInspector.ActorInspectorRunItem,
|
|
551
689
|
availableRows: number,
|
|
690
|
+
width: number,
|
|
552
691
|
): string[] {
|
|
692
|
+
// Run menu reserves five offset columns, two markers, two borders and one right-padding column.
|
|
553
693
|
const options = this.selectorMode === "run"
|
|
554
|
-
? this.runSelectorOptions()
|
|
694
|
+
? this.runSelectorOptions(Math.max(0, width - 10))
|
|
555
695
|
: this.traceSources(run).map((source) => ({
|
|
556
696
|
content: `${this.theme.fg("accent", "Trace:")} ${this.theme.fg("text", source)}`,
|
|
557
697
|
preserveColors: true,
|
|
@@ -559,7 +699,7 @@ export class ActorInspectorOverlay {
|
|
|
559
699
|
return this.renderMenuBox(options, this.selectorIndex, availableRows);
|
|
560
700
|
}
|
|
561
701
|
|
|
562
|
-
private runSelectorOptions(): SelectorOption[] {
|
|
702
|
+
private runSelectorOptions(width: number): SelectorOption[] {
|
|
563
703
|
const runs = this.runs();
|
|
564
704
|
const sequenceWidth = Math.max(
|
|
565
705
|
2,
|
|
@@ -567,11 +707,11 @@ export class ActorInspectorOverlay {
|
|
|
567
707
|
);
|
|
568
708
|
const runWidth = Math.max(1, ...runs.map((item) => visibleWidth(item.run)));
|
|
569
709
|
return runs.map((item, index) => ({
|
|
570
|
-
content: [
|
|
710
|
+
content: truncateToWidth([
|
|
571
711
|
this.theme.fg("text", this.fit(`#${runs.length - index - 1}`, sequenceWidth)),
|
|
572
712
|
this.theme.fg("accent", this.fit(item.run, runWidth)),
|
|
573
713
|
this.theme.fg(this.statusColor(item.status), item.status),
|
|
574
|
-
].join(" "),
|
|
714
|
+
].join(" "), width, "…"),
|
|
575
715
|
preserveColors: true,
|
|
576
716
|
}));
|
|
577
717
|
}
|
|
@@ -589,33 +729,46 @@ export class ActorInspectorOverlay {
|
|
|
589
729
|
const maxStart = Math.max(0, options.length - visibleLimit);
|
|
590
730
|
const start = Math.max(0, Math.min(focusedIndex - Math.floor(visibleLimit / 2), maxStart));
|
|
591
731
|
const visible = options.slice(start, start + visibleLimit);
|
|
592
|
-
const
|
|
593
|
-
const
|
|
594
|
-
|
|
732
|
+
const runMenu = this.selectorMode === "run";
|
|
733
|
+
const width = Math.max(8, ...options.map((option) => visibleWidth(option.content) + (runMenu ? 3 : 4)));
|
|
734
|
+
// Reset both menu edges so sliced document backgrounds cannot bleed through.
|
|
735
|
+
const ownBackground = (line: string) => runMenu ? `\u001b[49m${line}\u001b[49m` : line;
|
|
736
|
+
const border = (left: string, right: string, marker = "") => ownBackground(
|
|
737
|
+
this.theme.fg("borderAccent", `${left}${marker}${"─".repeat(Math.max(0, width - visibleWidth(marker)))}${right}`));
|
|
595
738
|
return [
|
|
596
739
|
border("╭", "╮", start > 0 ? "↑" : ""),
|
|
597
740
|
...visible.map((option, offset) => {
|
|
598
741
|
const index = start + offset;
|
|
599
742
|
const marker = index === focusedIndex
|
|
600
|
-
? this.theme.fg("accent", " ▶ ")
|
|
601
|
-
: " ";
|
|
602
|
-
const row = this.fit(`${marker}${option.content}`, width);
|
|
743
|
+
? this.theme.fg("accent", runMenu ? "▶ " : " ▶ ")
|
|
744
|
+
: runMenu ? " " : " ";
|
|
745
|
+
const row = this.fit(`${marker}${option.content}`, width - Number(runMenu)) + (runMenu ? " " : "");
|
|
603
746
|
const colored = index === focusedIndex && !option.preserveColors
|
|
604
747
|
? this.theme.fg("accent", row)
|
|
605
748
|
: row;
|
|
606
|
-
const
|
|
607
|
-
|
|
749
|
+
const background = index === focusedIndex ? "selectedBg" : runMenu && index % 2 ? "customMessageBg" : undefined;
|
|
750
|
+
// Native truncation emits full SGR resets; repaint each resulting segment.
|
|
751
|
+
const styled = background === undefined ? colored : runMenu
|
|
752
|
+
? colored.split("\u001b[0m").map(part => this.theme.bg(background, part)).join("\u001b[0m")
|
|
753
|
+
: this.theme.bg(background, colored);
|
|
754
|
+
return ownBackground(`${this.theme.fg("borderAccent", "│")}${styled}${this.theme.fg("borderAccent", "│")}`);
|
|
608
755
|
}),
|
|
609
756
|
border("╰", "╯", start + visible.length < options.length ? "↓" : ""),
|
|
610
757
|
];
|
|
611
758
|
}
|
|
612
759
|
|
|
613
|
-
private
|
|
760
|
+
private traceTableLine(text: string, width: number): string {
|
|
761
|
+
const [first = "", ...rest] = text.split(/\r\n|\r|\n/u);
|
|
762
|
+
return truncateToWidth(first + (rest.length ? "…" : ""), width, "…");
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
private renderTraceList(run: ActorInspector.ActorInspectorRunItem, width: number): string[] {
|
|
614
766
|
const items = this.traceItems(run);
|
|
615
|
-
const summary = RunsTrace.summarizeRunTraceJournal(
|
|
767
|
+
const summary = this.traceCache!.journalSummary ??= RunsTrace.summarizeRunTraceJournal(
|
|
616
768
|
RunsTrace.readRunTraceJournal(path.join(this.stateRoot, run.run)));
|
|
617
769
|
const banner = summary.history_complete ? [] : [this.theme.fg("warning",
|
|
618
|
-
|
|
770
|
+
width < visibleWidth(" ! Trace history incomplete:") ? " ! Trace incomplete…" : this.traceTableLine(
|
|
771
|
+
` ! Trace history incomplete: ${summary.compacted ? `${summary.compactions_total} compaction(s), ` : ""}${summary.dropped_event_count_exact ? summary.dropped_events : "unknown"} dropped event(s), ${summary.dropped_bytes} bytes`, width))];
|
|
619
772
|
if (items.length === 0) return [...banner, this.theme.fg("muted", " No Trace evidence")];
|
|
620
773
|
if (this.selectedTraceId) {
|
|
621
774
|
const selectedIndex = items.findIndex((item) => item.id === this.selectedTraceId);
|
|
@@ -645,25 +798,32 @@ export class ActorInspectorOverlay {
|
|
|
645
798
|
const detail = item.detail && typeof item.detail === "object"
|
|
646
799
|
? item.detail as Record<string, unknown>
|
|
647
800
|
: {};
|
|
648
|
-
const
|
|
649
|
-
? this.theme.fg("
|
|
650
|
-
:
|
|
651
|
-
? this.theme.fg("warning", "A")
|
|
652
|
-
: " ";
|
|
801
|
+
const attention = item.level !== "error" && detail.attention
|
|
802
|
+
? this.theme.fg("warning", "A") + " "
|
|
803
|
+
: "";
|
|
653
804
|
const prefix = this.focus === "list" && index === this.rowIndex
|
|
654
|
-
? this.theme.fg("accent", "
|
|
655
|
-
: "
|
|
656
|
-
const
|
|
657
|
-
const
|
|
805
|
+
? this.theme.fg("accent", "▶ ")
|
|
806
|
+
: " ";
|
|
807
|
+
const chronology = item[TraceProjection.TRACE_ITEM_CHRONOLOGY];
|
|
808
|
+
const sequence = chronology?.state === "available" ? chronology.ordinal : "?";
|
|
809
|
+
const row = `${prefix}${this.theme.fg("text", `#${sequence}`)} ${attention}${this.theme.fg("muted", item.source)}/${this.theme.fg(item.level === "error" ? "error" : "accent", item.kind)} ${this.theme.fg("text", item.summary)}`;
|
|
810
|
+
const preview = this.traceTableLine(row, width);
|
|
658
811
|
return this.focus === "list" && index === this.rowIndex
|
|
659
|
-
? this.theme.fg("accent",
|
|
660
|
-
:
|
|
812
|
+
? this.theme.fg("accent", preview)
|
|
813
|
+
: preview;
|
|
661
814
|
})];
|
|
662
815
|
}
|
|
663
816
|
|
|
664
817
|
private renderTraceDetail(width: number): string[] {
|
|
665
818
|
if (!this.traceDetail) return [this.theme.fg("warning", " Trace row is no longer available")];
|
|
666
|
-
const
|
|
819
|
+
const sequence = this.traceDetail[TraceProjection.TRACE_ITEM_SEQUENCE];
|
|
820
|
+
const value = {
|
|
821
|
+
...(sequence !== undefined ? { projection_sequence: sequence } : {}),
|
|
822
|
+
...this.traceDetail,
|
|
823
|
+
chronology: this.traceDetail[TraceProjection.TRACE_ITEM_CHRONOLOGY] ?? { state: "unavailable", reason: "metadata_unavailable" },
|
|
824
|
+
};
|
|
825
|
+
const projection = this.traceDetail.source === "agent" && this.traceDetail.kind === "agent.turn"
|
|
826
|
+
? this.agentDetailProjection(value, width) : this.documentProjection(value, width);
|
|
667
827
|
const maxStart = Math.max(0, projection.lines.length - this.contentViewportRows());
|
|
668
828
|
this.detailScroll = Math.min(this.detailScroll, maxStart);
|
|
669
829
|
this.contentStripeIndices = projection.stripes.slice(
|
|
@@ -676,37 +836,240 @@ export class ActorInspectorOverlay {
|
|
|
676
836
|
);
|
|
677
837
|
}
|
|
678
838
|
|
|
839
|
+
private agentDetailSegments(value: unknown): AgentDetailSegment[] {
|
|
840
|
+
const extractedBody = Symbol("extracted-body");
|
|
841
|
+
const bodies: Array<{ field: Array<string | number>; text: string }> = [];
|
|
842
|
+
// Only typed SessionEvidenceTurn slots are bodies. Never inspect authored text for framing.
|
|
843
|
+
const select = (item: unknown, field: Array<string | number>): unknown => {
|
|
844
|
+
if (typeof item === "string") { bodies.push({ field, text: item }); return extractedBody; }
|
|
845
|
+
return item;
|
|
846
|
+
};
|
|
847
|
+
const record = value as Record<string, unknown>;
|
|
848
|
+
const detail = record.detail;
|
|
849
|
+
let metadata = value;
|
|
850
|
+
if (detail && typeof detail === "object" && !Array.isArray(detail)) {
|
|
851
|
+
const retained = Object.fromEntries(Object.entries(detail).map(([key, item]) => {
|
|
852
|
+
if (["assistantText", "userText", "thinking"].includes(key) && typeof item === "string") {
|
|
853
|
+
return [key, select(item, ["detail", key])];
|
|
854
|
+
}
|
|
855
|
+
if (key !== "toolCalls" || !Array.isArray(item)) return [key, item];
|
|
856
|
+
return [key, item.map((call, callIndex) => {
|
|
857
|
+
if (!call || typeof call !== "object" || Array.isArray(call)) return call;
|
|
858
|
+
// Action-first display order only; retained tool-call data and body rendering stay unchanged.
|
|
859
|
+
const rank = (key: string) => key === "name" ? 0 : key === "arguments" ? 1 : key === "result" ? 3 : 2;
|
|
860
|
+
return Object.fromEntries(Object.entries(call).sort(([left], [right]) => rank(left) - rank(right)).map(([name, result]) => {
|
|
861
|
+
if (name !== "result") return [name, result];
|
|
862
|
+
const field = ["detail", key, callIndex, name];
|
|
863
|
+
if (typeof result === "string") return [name, select(result, field)];
|
|
864
|
+
if (!Array.isArray(result)) return [name, result];
|
|
865
|
+
return [name, result.map((block, blockIndex) => {
|
|
866
|
+
if (!block || typeof block !== "object" || block.type !== "text" || typeof block.text !== "string") return block;
|
|
867
|
+
select(block.text, [...field, blockIndex, "text"]);
|
|
868
|
+
return Object.fromEntries(Object.entries(block).filter(([slot]) => slot !== "text"));
|
|
869
|
+
})];
|
|
870
|
+
}).filter(([, item]) => item !== extractedBody));
|
|
871
|
+
})];
|
|
872
|
+
}).filter(([, item]) => item !== extractedBody));
|
|
873
|
+
metadata = { ...record, detail: retained };
|
|
874
|
+
}
|
|
875
|
+
return [{ kind: "metadata", value: metadata }, ...bodies.flatMap<AgentDetailSegment>(({ field, text }) => [
|
|
876
|
+
{ kind: "metadata", value: { field } }, { kind: "body", text },
|
|
877
|
+
])];
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
private metadataText(value: unknown): string {
|
|
881
|
+
// Copy own selected data, so the library cannot invoke an object's toJSON hook.
|
|
882
|
+
const copy = (item: unknown): unknown => {
|
|
883
|
+
// UI-only value state: keep an own undefined slot visible, distinct from null or literal text.
|
|
884
|
+
if (item === undefined) return { value_state: "undefined" };
|
|
885
|
+
if (typeof item === "function") throw new TypeError("Inspector metadata must be selected own data");
|
|
886
|
+
if (!item || typeof item !== "object") return item;
|
|
887
|
+
if (Array.isArray(item)) return Array.from({ length: item.length }, (_, index) => {
|
|
888
|
+
const descriptor = Object.getOwnPropertyDescriptor(item, String(index));
|
|
889
|
+
if (descriptor && !Object.hasOwn(descriptor, "value")) throw new TypeError("Inspector metadata must be selected own data");
|
|
890
|
+
return copy(descriptor?.value);
|
|
891
|
+
});
|
|
892
|
+
const result = Object.create(null) as Record<string, unknown>;
|
|
893
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(item))) {
|
|
894
|
+
if (!descriptor.enumerable) continue;
|
|
895
|
+
if (!Object.hasOwn(descriptor, "value")) throw new TypeError("Inspector metadata must be selected own data");
|
|
896
|
+
result[key] = copy(descriptor.value);
|
|
897
|
+
}
|
|
898
|
+
return result;
|
|
899
|
+
};
|
|
900
|
+
const document = new Document(copy(value), { version: "1.2", schema: "core", aliasDuplicateObjects: false });
|
|
901
|
+
visit(document, { Pair(_key, pair) {
|
|
902
|
+
if (isScalar(pair.key) && typeof pair.key.value === "string" && pair.key.value.includes("\uFEFF")) pair.key.type = "QUOTE_DOUBLE";
|
|
903
|
+
} });
|
|
904
|
+
return document.toString({ collectionStyle: "block", indent: 2, lineWidth: 0, directives: false,
|
|
905
|
+
defaultStringType: "PLAIN", doubleQuotedAsJSON: true });
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
private agentDetailProjection(value: unknown, width: number): { lines: string[]; stripes: number[] } {
|
|
909
|
+
const segments = this.agentDetailSegments(value);
|
|
910
|
+
const lines: string[] = [], stripes: number[] = [];
|
|
911
|
+
const markdownTheme = { ...getMarkdownTheme(), codeBlockIndent: "" };
|
|
912
|
+
const detailStripe = Object.keys(value as object).indexOf("detail");
|
|
913
|
+
const append = (rendered: string[], stripe: number) => {
|
|
914
|
+
lines.push(...rendered); stripes.push(...rendered.map(() => stripe));
|
|
915
|
+
};
|
|
916
|
+
const metadata = (selected: unknown, stripe: number) => {
|
|
917
|
+
// yaml's standard serializer has no completion-wire budget/depth ceiling. Data is already admitted upstream.
|
|
918
|
+
const yaml = this.metadataText(selected).replace(/\n$/u, "");
|
|
919
|
+
append(this.wrapDocument(yaml.split("\n").map(text => ({ text })), width).map(line => this.theme.fg("muted", line.text)), stripe);
|
|
920
|
+
};
|
|
921
|
+
segments.forEach((segment, index) => {
|
|
922
|
+
if (index) append([""], detailStripe);
|
|
923
|
+
if (segment.kind === "body") {
|
|
924
|
+
append(new Markdown(segment.text, 0, 0, markdownTheme, { color: text => this.theme.fg("text", text) }).render(width), detailStripe);
|
|
925
|
+
} else if (index === 0) {
|
|
926
|
+
// Serialize root entries separately to retain root-field stripe provenance without parsing YAML rows.
|
|
927
|
+
Object.entries(segment.value as object).forEach(([key, item], stripe) => metadata({ [key]: item }, stripe));
|
|
928
|
+
} else {
|
|
929
|
+
if (segments[index + 1]?.kind === "body") append([this.theme.fg("muted", "---")], detailStripe);
|
|
930
|
+
metadata(segment.value, detailStripe);
|
|
931
|
+
if (segments[index + 1]?.kind === "body") append([this.theme.fg("muted", "---")], detailStripe);
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
return { lines, stripes };
|
|
935
|
+
}
|
|
936
|
+
|
|
679
937
|
private controlDocument(
|
|
680
938
|
run: ActorInspector.ActorInspectorRunItem,
|
|
681
939
|
stateDir: string,
|
|
682
940
|
): Record<string, unknown> {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
941
|
+
return this.controlObservation(run, stateDir).document;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
private controlObservation(run: ActorInspector.ActorInspectorRunItem, stateDir = path.join(this.stateRoot, run.run)): ControlObservation {
|
|
945
|
+
if (this.controlCache?.run === run.run && this.controlCache.generation === run.runInstanceId) return this.controlCache;
|
|
686
946
|
const meta = this.readRunMeta(stateDir);
|
|
687
|
-
const
|
|
947
|
+
const bound = Boolean(meta && !Array.isArray(meta) && run.runInstanceId && meta.run === run.run
|
|
948
|
+
&& meta.run_instance_id === run.runInstanceId && meta.ownerId === this.ownerId);
|
|
949
|
+
const diagnostics: Array<{ reason: string; line?: number }> = [];
|
|
950
|
+
let actions: string[] = [];
|
|
951
|
+
if (!bound) diagnostics.push({ reason: "metadata_binding_unavailable" });
|
|
952
|
+
else {
|
|
953
|
+
try { actions = normalizeRecipeControl(meta.control) ?? []; }
|
|
954
|
+
catch { diagnostics.push({ reason: "invalid_action_declarations" }); }
|
|
955
|
+
}
|
|
956
|
+
const endpoint = bound ? RunControlDelivery.readRunControlEndpoint(stateDir, run.runInstanceId!) : undefined;
|
|
957
|
+
const journal = bound ? RunsControls.readRunControlJournalFromStateDir(stateDir) : { records: [], diagnostics: [] };
|
|
958
|
+
diagnostics.push(...journal.diagnostics.map(item => item.line === undefined
|
|
959
|
+
? { reason: "unreadable_control_journal" } : { reason: "invalid_control_json", line: item.line }));
|
|
960
|
+
const now = Date.now();
|
|
961
|
+
const ids = new Map<string, number>();
|
|
962
|
+
for (const value of journal.records) {
|
|
963
|
+
if (value && typeof value === "object" && typeof (value as Record<string, unknown>).id === "string") {
|
|
964
|
+
const id = (value as Record<string, unknown>).id as string;
|
|
965
|
+
ids.set(id, (ids.get(id) ?? 0) + 1);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
const accepted: Array<{ id: string; value: ControlProjection.ProjectedRunControl; age: number; reason?: string; parsedIndex: number }> = [];
|
|
969
|
+
for (const [parsedIndex, value] of journal.records.entries()) {
|
|
970
|
+
const classification = RuntimeTriage.classifyRuntimeControl(run, value, now);
|
|
971
|
+
if (classification.diagnostic) { diagnostics.push({ reason: classification.diagnostic.reason }); continue; }
|
|
972
|
+
const record = value as RunsControls.RunControlRecord;
|
|
973
|
+
if (record.run_instance_id !== run.runInstanceId) { diagnostics.push({ reason: "foreign_generation" }); continue; }
|
|
974
|
+
if (ids.get(record.id) !== 1) { diagnostics.push({ reason: "duplicate_control_id" }); continue; }
|
|
975
|
+
if (["queued_at", "delivered_at", "claimed_at", "handled_at", "failed_at"].some(field => {
|
|
976
|
+
const timestamp = (record as unknown as Record<string, unknown>)[field];
|
|
977
|
+
return (field === "queued_at" || timestamp !== undefined) && (typeof timestamp !== "string" || !Number.isFinite(Date.parse(timestamp)));
|
|
978
|
+
})) {
|
|
979
|
+
diagnostics.push({ reason: "invalid_record_timestamp" }); continue;
|
|
980
|
+
}
|
|
981
|
+
accepted.push({ id: record.id, value: ControlProjection.projectRunControl(record), parsedIndex,
|
|
982
|
+
age: Math.max(0, now - Date.parse(runControlStatusTimestamp(record as unknown as Record<string, unknown>, record.status) as string)),
|
|
983
|
+
reason: classification.stale?.reason });
|
|
984
|
+
}
|
|
688
985
|
const capacity = computeRunControlCapacity(journal.records);
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
986
|
+
const partial = diagnostics.length > 0;
|
|
987
|
+
const rows = accepted.filter(row => row.parsedIndex >= journal.records.length - 20).reverse();
|
|
988
|
+
const readiness = partial ? "data_unavailable" : run.status !== "running" ? "not_ready"
|
|
989
|
+
: !actions.length ? "unsupported" : capacity.backpressured ? "backpressure" : endpoint ? "ready_recorded_endpoint" : "not_ready";
|
|
990
|
+
const reason = partial ? "partial_observation" : run.status !== "running" ? "run_terminal"
|
|
991
|
+
: !actions.length ? "no_declared_actor_actions" : capacity.backpressured ? "pending_limit_reached"
|
|
992
|
+
: endpoint ? "recorded_endpoint_only_not_connection_proof" : "recorded_endpoint_unavailable";
|
|
993
|
+
this.controlCache = { run: run.run, generation: run.runInstanceId, rows, document: {
|
|
994
|
+
actor_control_readiness: readiness, reason, actor_actions: actions,
|
|
995
|
+
data_state: partial ? "partial" : "available", pending: bound ? capacity.pending : null,
|
|
996
|
+
pending_limit: capacity.limit, available: partial ? null : capacity.available,
|
|
997
|
+
backpressured: bound ? capacity.backpressured : null,
|
|
998
|
+
runtime_actions: bound ? run.status === "running" ? this.killRun && run.runInstanceId ? ["kill"] : [] : ["archive", "prune"] : [],
|
|
999
|
+
runtime_actions_note: "API capabilities; only existing Run-focus Kill is interactive",
|
|
1000
|
+
request_history: { shown: rows.length, retained: journal.records.length, parsed_suffix_limit: 20,
|
|
1001
|
+
partial: partial || journal.records.length > 20, coverage: "recent parsed journal records; malformed-line coverage unavailable; not complete lifetime history" },
|
|
1002
|
+
request_navigation: "Enter opens requests; Down scrolls overview",
|
|
1003
|
+
evidence: "Saved non-atomic observation; delivered != handled; handled != Run completion; stale never expires requests",
|
|
1004
|
+
status: run.status, run_instance_id: run.runInstanceId,
|
|
1005
|
+
journal_bytes: (() => { try { return statSync(RunsControls.runControlsFile(stateDir)).size; } catch { return null; } })(),
|
|
698
1006
|
journal_limit: Limits.RUN_CONTROL_JOURNAL_MAX_BYTES,
|
|
699
|
-
stale_pending:
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1007
|
+
stale_pending: accepted.filter(row => row.reason).length, diagnostics,
|
|
1008
|
+
endpoint, recent_controls: rows.map(row => row.value),
|
|
1009
|
+
} };
|
|
1010
|
+
return this.controlCache;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
private selectedControl(observation: ControlObservation) {
|
|
1014
|
+
const selection = this.controlSelection;
|
|
1015
|
+
return selection?.run === observation.run && selection.generation === observation.generation
|
|
1016
|
+
? observation.rows.find(row => row.id === selection.id) : undefined;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
private openControlList(run?: ActorInspector.ActorInspectorRunItem): void {
|
|
1020
|
+
this.focus = "list";
|
|
1021
|
+
this.rowIndex = 0;
|
|
1022
|
+
const observation = run ? this.controlObservation(run) : undefined;
|
|
1023
|
+
const first = observation?.rows[0];
|
|
1024
|
+
this.controlSelection = first ? { run: observation!.run, generation: observation!.generation, id: first.id } : undefined;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
private handleControlInput(data: string, run?: ActorInspector.ActorInspectorRunItem): void {
|
|
1028
|
+
if (matchesKey(data, "escape") || matchesKey(data, "left")) {
|
|
1029
|
+
this.focus = this.focus === "detail" ? "list" : "tabs";
|
|
1030
|
+
this.detailScroll = 0;
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
if (!run) return;
|
|
1034
|
+
const observation = this.controlObservation(run);
|
|
1035
|
+
const selected = this.selectedControl(observation);
|
|
1036
|
+
if (this.focus === "detail") { this.handleScrollableInput(data, "detail"); return; }
|
|
1037
|
+
const index = selected ? observation.rows.indexOf(selected) : -1;
|
|
1038
|
+
let next = index;
|
|
1039
|
+
if (matchesKey(data, "up")) next = Math.max(0, index - 1);
|
|
1040
|
+
else if (matchesKey(data, "down")) next = Math.min(observation.rows.length - 1, index + 1);
|
|
1041
|
+
else if (matchesKey(data, "pageUp")) next = Math.max(0, index - this.contentViewportRows());
|
|
1042
|
+
else if (matchesKey(data, "pageDown")) next = Math.min(observation.rows.length - 1, index + this.contentViewportRows());
|
|
1043
|
+
else if ((matchesKey(data, "return") || matchesKey(data, "right")) && selected) {
|
|
1044
|
+
this.focus = "detail"; this.detailScroll = 0; return;
|
|
1045
|
+
}
|
|
1046
|
+
if (next !== index && observation.rows[next]) this.controlSelection = {
|
|
1047
|
+
run: observation.run, generation: observation.generation, id: observation.rows[next]!.id,
|
|
707
1048
|
};
|
|
708
1049
|
}
|
|
709
1050
|
|
|
1051
|
+
private renderControlContent(run: ActorInspector.ActorInspectorRunItem, width: number): string[] {
|
|
1052
|
+
const observation = this.controlObservation(run);
|
|
1053
|
+
const selected = this.selectedControl(observation);
|
|
1054
|
+
if (this.focus === "detail") {
|
|
1055
|
+
const projection = this.documentProjection(selected ? selected.value : { request: "unavailable", reason: "selected Run/generation/id no longer available" }, width);
|
|
1056
|
+
this.detailScroll = Math.min(this.detailScroll, Math.max(0, projection.lines.length - this.contentViewportRows()));
|
|
1057
|
+
this.contentStripeIndices = projection.stripes.slice(this.detailScroll, this.detailScroll + this.contentViewportRows());
|
|
1058
|
+
return projection.lines.slice(this.detailScroll, this.detailScroll + this.contentViewportRows());
|
|
1059
|
+
}
|
|
1060
|
+
const coverage = observation.document.request_history as { shown: number; retained: number; partial: boolean };
|
|
1061
|
+
const banner = this.traceTableLine(` Requests ${coverage.shown}/${coverage.retained} parsed; recent20${coverage.partial ? "; partial" : ""}`, width);
|
|
1062
|
+
if (!observation.rows.length) return [banner, " No requests", this.traceTableLine(" Saved observation; history may be partial", width)];
|
|
1063
|
+
const index = selected ? observation.rows.indexOf(selected) : -1;
|
|
1064
|
+
const count = Math.max(1, this.contentViewportRows() - 2);
|
|
1065
|
+
const start = Math.max(0, index - Math.floor(count / 2));
|
|
1066
|
+
const rows = observation.rows.slice(start, start + count);
|
|
1067
|
+
this.contentStripeIndices = [0, 0, ...rows.map((_row, offset) => start + offset + 1)];
|
|
1068
|
+
if (index >= start) this.contentSelectedRows.add(index - start + 2);
|
|
1069
|
+
return [banner, this.traceTableLine(index < 0 ? " Selection unavailable; arrows select a request" : " Status | action | status age | error/stale", width),
|
|
1070
|
+
...rows.map(row => this.traceTableLine(`${row === selected ? "▶" : " "} ${row.value.status} | ${row.value.action} | ${Math.floor(row.age / 1000)}s | ${row.value.error ?? row.reason ?? ""}`, width))];
|
|
1071
|
+
}
|
|
1072
|
+
|
|
710
1073
|
private allTraceItems(run?: ActorInspector.ActorInspectorRunItem): TraceProjection.TraceItem[] {
|
|
711
1074
|
if (!run) return [];
|
|
712
1075
|
if (
|
|
@@ -752,195 +1115,95 @@ export class ActorInspectorOverlay {
|
|
|
752
1115
|
value: unknown,
|
|
753
1116
|
width: number,
|
|
754
1117
|
): { lines: string[]; stripes: number[] } {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1118
|
+
// Copy before enumerating roots: accessors and hooks must never run during projection.
|
|
1119
|
+
const selected = this.metadataText(value);
|
|
1120
|
+
const descriptors = value && typeof value === "object" && !Array.isArray(value)
|
|
1121
|
+
? Object.entries(Object.getOwnPropertyDescriptors(value)).filter(([, descriptor]) => descriptor.enumerable) : [];
|
|
1122
|
+
const sections = descriptors.length
|
|
1123
|
+
? descriptors.map(([key, descriptor]) => this.metadataText({ [key]: descriptor.value }))
|
|
1124
|
+
: [selected];
|
|
760
1125
|
const lines: string[] = [];
|
|
761
1126
|
const stripes: number[] = [];
|
|
762
1127
|
sections.forEach((section, sectionIndex) => {
|
|
763
|
-
const wrapped = this.wrapDocument(section, width);
|
|
764
|
-
lines.push(...wrapped.map((line) => this.
|
|
1128
|
+
const wrapped = this.wrapDocument(section.replace(/\n$/u, "").split("\n").map(text => ({ text })), width);
|
|
1129
|
+
lines.push(...wrapped.map((line) => this.theme.fg("muted", line.text)));
|
|
765
1130
|
stripes.push(...wrapped.map(() => sectionIndex));
|
|
766
1131
|
});
|
|
767
1132
|
return { lines, stripes };
|
|
768
1133
|
}
|
|
769
1134
|
|
|
770
|
-
private
|
|
771
|
-
if (Array.isArray(value)) {
|
|
772
|
-
if (value.length === 0) return "[]";
|
|
773
|
-
if (value.every((item) =>
|
|
774
|
-
(item === null || typeof item !== "object") &&
|
|
775
|
-
!(typeof item === "string" && /[\r\n]/u.test(item))
|
|
776
|
-
)) {
|
|
777
|
-
return `[${value.map((item) => String(item ?? "none")).join(", ")}]`;
|
|
778
|
-
}
|
|
779
|
-
return undefined;
|
|
780
|
-
}
|
|
781
|
-
if (value && typeof value === "object") {
|
|
782
|
-
if (Object.keys(value as Record<string, unknown>).length === 0) return "{}";
|
|
783
|
-
}
|
|
784
|
-
return undefined;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
private labeledDocumentLines(key: string, value: unknown, depth = 0): string[] {
|
|
788
|
-
const inline = this.inlineDocumentValue(value);
|
|
789
|
-
if (inline !== undefined) return [`${" ".repeat(depth)}${key}: ${inline}`];
|
|
790
|
-
if (value && typeof value === "object") {
|
|
791
|
-
const indent = " ".repeat(depth);
|
|
792
|
-
const nested = this.document(value, depth);
|
|
793
|
-
return [`${indent}${key}: ${nested[0]!.slice(indent.length)}`, ...nested.slice(1)];
|
|
794
|
-
}
|
|
795
|
-
return this.labeledScalarLines(key, value, depth);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
private labeledScalarLines(key: string, value: unknown, depth = 0): string[] {
|
|
799
|
-
const indent = " ".repeat(depth);
|
|
800
|
-
const [first = "", ...rest] = String(value ?? "none").split(/\r?\n/u);
|
|
801
|
-
return [
|
|
802
|
-
`${indent}${key}: ${first}`,
|
|
803
|
-
...rest.map((line) => `${indent} ${line}`),
|
|
804
|
-
];
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
private document(value: unknown, depth = 0): string[] {
|
|
808
|
-
if (value === null || value === undefined) return [`${" ".repeat(depth)}none`];
|
|
809
|
-
const inline = this.inlineDocumentValue(value);
|
|
810
|
-
if (inline !== undefined) return [`${" ".repeat(depth)}${inline}`];
|
|
811
|
-
if (Array.isArray(value)) {
|
|
812
|
-
const indent = " ".repeat(depth);
|
|
813
|
-
return [
|
|
814
|
-
`${indent}[`,
|
|
815
|
-
...value.flatMap((item, index) => {
|
|
816
|
-
const itemDepth = depth + 1;
|
|
817
|
-
const itemIndent = " ".repeat(itemDepth);
|
|
818
|
-
const marker = `#${index}`;
|
|
819
|
-
const itemInline = this.inlineDocumentValue(item);
|
|
820
|
-
let lines: string[];
|
|
821
|
-
if (itemInline !== undefined) {
|
|
822
|
-
lines = [`${itemIndent}${marker}: ${itemInline}`];
|
|
823
|
-
} else if (item && typeof item === "object") {
|
|
824
|
-
const nested = this.document(item, itemDepth);
|
|
825
|
-
lines = [
|
|
826
|
-
`${itemIndent}${marker}: ${nested[0]!.slice(itemIndent.length)}`,
|
|
827
|
-
...nested.slice(1),
|
|
828
|
-
];
|
|
829
|
-
} else {
|
|
830
|
-
lines = this.labeledScalarLines(marker, item, itemDepth);
|
|
831
|
-
}
|
|
832
|
-
if (index < value.length - 1) lines[lines.length - 1] += ",";
|
|
833
|
-
return lines;
|
|
834
|
-
}),
|
|
835
|
-
`${indent}]`,
|
|
836
|
-
];
|
|
837
|
-
}
|
|
838
|
-
if (typeof value === "object") {
|
|
839
|
-
const indent = " ".repeat(depth);
|
|
840
|
-
const entries = Object.entries(value as Record<string, unknown>);
|
|
841
|
-
return [
|
|
842
|
-
`${indent}{`,
|
|
843
|
-
...entries.flatMap(([key, item], index) => {
|
|
844
|
-
const lines = this.labeledDocumentLines(key, item, depth + 1);
|
|
845
|
-
if (index < entries.length - 1) lines[lines.length - 1] += ",";
|
|
846
|
-
return lines;
|
|
847
|
-
}),
|
|
848
|
-
`${indent}}`,
|
|
849
|
-
];
|
|
850
|
-
}
|
|
851
|
-
return String(value)
|
|
852
|
-
.split(/\r?\n/u)
|
|
853
|
-
.map((line) => `${" ".repeat(depth)}${line}`);
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
private wrapDocument(lines: string[], width: number): string[] {
|
|
1135
|
+
private wrapDocument(lines: InspectorDocumentLine[], width: number): InspectorDocumentLine[] {
|
|
857
1136
|
return lines.flatMap((line) => {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
);
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1137
|
+
// Keep the existing terminal tab display policy; never alter the source value.
|
|
1138
|
+
const text = line.text.replaceAll("\t", " ");
|
|
1139
|
+
const label = line.label?.replaceAll("\t", " ");
|
|
1140
|
+
if (visibleWidth(text) <= width) return [{ text, label }];
|
|
1141
|
+
const leading = text.match(/^ */u)?.[0] ?? "";
|
|
1142
|
+
const hanging = label === undefined ? leading : `${leading} `;
|
|
1143
|
+
const continuation = hanging.length <= width - 2 ? hanging : "";
|
|
1144
|
+
const wrapped: InspectorDocumentLine[] = [];
|
|
1145
|
+
const columns = visibleWidth(text);
|
|
1146
|
+
let offset = 0;
|
|
1147
|
+
while (offset < columns) {
|
|
1148
|
+
const prefix = offset === 0 ? "" : continuation;
|
|
1149
|
+
const available = width - visibleWidth(prefix);
|
|
1150
|
+
// Native cell slicing keeps graphemes; retain separators instead of trimming authored spaces.
|
|
1151
|
+
let part = sliceByColumn(text, offset, available, true);
|
|
1152
|
+
const preferred = Math.max(part.lastIndexOf(" "), part.lastIndexOf("/"), part.lastIndexOf(","));
|
|
1153
|
+
if (offset + visibleWidth(part) < columns && preferred >= Math.floor(part.length * 0.6)) {
|
|
1154
|
+
part = sliceByColumn(text, offset, visibleWidth(part.slice(0, preferred + 1)), true);
|
|
1155
|
+
}
|
|
1156
|
+
const consumed = visibleWidth(part);
|
|
1157
|
+
const labelPart = label === undefined ? "" : sliceByColumn(label, offset, consumed, true);
|
|
1158
|
+
wrapped.push({ text: prefix + part, ...(labelPart ? { label: prefix + labelPart } : {}) });
|
|
1159
|
+
offset += consumed;
|
|
878
1160
|
}
|
|
879
|
-
if (rest) wrapped.push(`${prefix}${rest}`);
|
|
880
1161
|
return wrapped;
|
|
881
1162
|
});
|
|
882
1163
|
}
|
|
883
1164
|
|
|
884
|
-
private
|
|
885
|
-
const indent = line.match(/^ */u)?.[0] ?? "";
|
|
886
|
-
const content = line.slice(indent.length);
|
|
887
|
-
if (content.endsWith(":")) {
|
|
888
|
-
return `${indent}${this.theme.fg("accent", content)}`;
|
|
889
|
-
}
|
|
890
|
-
const indexed = /^(#\d+:)(.*)$/u.exec(content);
|
|
891
|
-
if (indexed) {
|
|
892
|
-
return `${indent}${this.theme.fg("accent", indexed[1])}${this.theme.fg("text", indexed[2])}`;
|
|
893
|
-
}
|
|
894
|
-
const labeled = /^([^:]+:)(.*)$/u.exec(content);
|
|
895
|
-
if (labeled) {
|
|
896
|
-
return `${indent}${this.theme.fg("muted", labeled[1])}${this.theme.fg("text", labeled[2])}`;
|
|
897
|
-
}
|
|
898
|
-
return `${indent}${this.theme.fg(content === "none" || content === "[]" ? "muted" : "text", content)}`;
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
private visiblePrefix(value: string, width: number): string {
|
|
902
|
-
let consumed = 0;
|
|
903
|
-
let result = "";
|
|
904
|
-
for (const character of value) {
|
|
905
|
-
const characterWidth = visibleWidth(character);
|
|
906
|
-
if (consumed + characterWidth > width) break;
|
|
907
|
-
result += character;
|
|
908
|
-
consumed += characterWidth;
|
|
909
|
-
}
|
|
910
|
-
return result;
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
private renderKeyHints(): string {
|
|
1165
|
+
private keyHints(...items: Array<[string, string]>): string {
|
|
914
1166
|
const hint = (keys: string, description: string) =>
|
|
915
1167
|
`${this.theme.fg("accent", keys)}${this.theme.fg("borderAccent", ` ${description}`)}`;
|
|
916
1168
|
const divider = this.theme.fg("borderAccent", " ─ ");
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1169
|
+
return items.map(([keys, description]) => hint(keys, description)).join(divider);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
private renderKeyHints(killConfirmation = false): string {
|
|
1173
|
+
if (killConfirmation) {
|
|
1174
|
+
return this.keyHints(["←→/tab", "choose"], ["enter", "pick"], ["y", "kill"], ["esc/n", "cancel"]);
|
|
921
1175
|
}
|
|
922
1176
|
if (this.focus === "select") {
|
|
923
|
-
return
|
|
1177
|
+
return this.keyHints(["↑↓", "option"], ["enter/→", "apply"], ["←/esc", "back"]);
|
|
924
1178
|
}
|
|
925
1179
|
if (this.focus === "detail") {
|
|
926
|
-
return
|
|
1180
|
+
return this.keyHints(["↑↓/pgup/pgdn", "scroll"], ["←/esc", "back"]);
|
|
1181
|
+
}
|
|
1182
|
+
if (this.tab === "control" && this.focus === "document") {
|
|
1183
|
+
return this.keyHints(["↑↓/pgup/pgdn", "scroll"], ["enter", "requests"], ["←/esc", "tabs"]);
|
|
1184
|
+
}
|
|
1185
|
+
if (this.tab === "control" && this.focus === "list") {
|
|
1186
|
+
return this.keyHints(["↑↓/pgup/pgdn", "row"], ["→/enter", "YAML"], ["←/esc", "tabs"]);
|
|
1187
|
+
}
|
|
1188
|
+
if (this.tab === "control" && this.focus === "tabs") {
|
|
1189
|
+
return this.keyHints(["←→", "tabs"], ["↓", "overview"], ["enter", "requests"], ["esc", "close"]);
|
|
927
1190
|
}
|
|
928
1191
|
if (this.focus === "document") {
|
|
929
|
-
return
|
|
1192
|
+
return this.keyHints(["↑↓/pgup/pgdn", "scroll"], ["↑ at top", "tabs"], ["←/esc", "tabs"]);
|
|
930
1193
|
}
|
|
931
1194
|
if (this.focus === "list") {
|
|
932
|
-
return
|
|
1195
|
+
return this.keyHints(["↑↓/pgup/pgdn", "row"], ["→/enter", "open"], ["←", "tabs"], ["esc", "close"]);
|
|
933
1196
|
}
|
|
934
1197
|
if (this.focus === "runs") {
|
|
935
1198
|
const items: Array<[string, string]> = [["←→", "run"], ["↓", "tabs"], ["enter", "list"]];
|
|
936
1199
|
const run = this.runs()[this.runIndex];
|
|
937
1200
|
if (this.killRun && run?.status === "running" && run.runInstanceId) items.push(["k", "kill"]);
|
|
938
1201
|
items.push(["esc", "close"]);
|
|
939
|
-
return
|
|
1202
|
+
return this.keyHints(...items);
|
|
940
1203
|
}
|
|
941
1204
|
return this.tab === "trace"
|
|
942
|
-
?
|
|
943
|
-
:
|
|
1205
|
+
? this.keyHints(["←→", "tabs"], ["↑↓", "focus"], ["enter/f", "source"], ["esc", "close"])
|
|
1206
|
+
: this.keyHints(["←→", "tabs"], ["↑↓", "focus"], ["enter", "open"], ["esc", "close"]);
|
|
944
1207
|
}
|
|
945
1208
|
|
|
946
1209
|
private statusColor(status: string): "error" | "warning" | "success" | "muted" {
|