mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
Orchestration commands print small flat fields in text and --json by default; --full prints the previous output. Failures exit non-zero with error: <code>: <message> on stderr.
87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
// Keep executable resolution and command-discovery guidance consistent across stubs.
|
|
const SHARED_STUB_SOURCE = 'skill-stubs/_shared/cli-resolution.md'
|
|
const BLOCK_DEFINITION_PATTERN = /^<!-- block: (?<id>[a-z][a-z0-9-]*) -->$/u
|
|
// `shared-omit` takes a block's place for a stub whose own text replaces it.
|
|
const INSERTION_MARKER_PATTERN = /^<!-- shared(?<omit>-omit)?: (?<id>\S+) -->$/u
|
|
|
|
// Skip fragment header before first block marker; require LF-normalized input.
|
|
function parseSharedStubBlocks(markdown, sourcePath) {
|
|
const blocks = new Map()
|
|
let open = null
|
|
const close = () => {
|
|
if (!open) {
|
|
return
|
|
}
|
|
const text = open.lines.join('\n').replace(/^\n+/u, '').replace(/\n+$/u, '')
|
|
if (!text) {
|
|
throw new Error(`Shared stub block is empty: ${sourcePath} (${open.id})`)
|
|
}
|
|
blocks.set(open.id, { text })
|
|
}
|
|
for (const line of markdown.split('\n')) {
|
|
const definition = BLOCK_DEFINITION_PATTERN.exec(line)
|
|
if (!definition) {
|
|
if (open) {
|
|
open.lines.push(line)
|
|
}
|
|
continue
|
|
}
|
|
close()
|
|
const { id } = definition.groups
|
|
if (blocks.has(id)) {
|
|
throw new Error(`Shared stub block is defined twice: ${sourcePath} (${id})`)
|
|
}
|
|
open = { id, lines: [] }
|
|
}
|
|
close()
|
|
if (blocks.size === 0) {
|
|
throw new Error(`Shared stub source defines no blocks: ${sourcePath}`)
|
|
}
|
|
return blocks
|
|
}
|
|
|
|
// Throw on unknown marker or missing/duplicate insertion: silent drop could remove safety ladder while generator stays green.
|
|
function renderSharedStubBody(stubBody, { blocks, sourcePath }) {
|
|
const insertions = new Map()
|
|
const composed = stubBody
|
|
.split('\n')
|
|
.map((line) => {
|
|
const marker = INSERTION_MARKER_PATTERN.exec(line)
|
|
if (!marker) {
|
|
return line
|
|
}
|
|
const { id } = marker.groups
|
|
const block = blocks.get(id)
|
|
if (!block) {
|
|
throw new Error(
|
|
`Unknown shared stub block "${id}" in ${sourcePath}. Known blocks: ${[...blocks.keys()].join(', ')}`
|
|
)
|
|
}
|
|
insertions.set(id, (insertions.get(id) ?? 0) + 1)
|
|
return marker.groups.omit ? null : block.text
|
|
})
|
|
.filter((line) => line !== null)
|
|
.join('\n')
|
|
// An omitted marker leaves its paragraph gap behind; keep one blank line, as the formatter would.
|
|
.replace(/\n{3,}/gu, '\n\n')
|
|
|
|
for (const [id, block] of blocks) {
|
|
const count = insertions.get(id) ?? 0
|
|
if (count !== 1) {
|
|
throw new Error(
|
|
`${sourcePath} must insert or omit <!-- shared: ${id} --> exactly once; found ${count}.`
|
|
)
|
|
}
|
|
// Why: re-inlining a copy beside the marker is exactly the drift this fragment ends.
|
|
const [firstLine] = block.text.split('\n')
|
|
if (stubBody.includes(firstLine)) {
|
|
throw new Error(
|
|
`${sourcePath} re-inlines shared block "${id}"; insert it with a marker instead.`
|
|
)
|
|
}
|
|
}
|
|
return composed
|
|
}
|
|
|
|
export { SHARED_STUB_SOURCE, parseSharedStubBlocks, renderSharedStubBody }
|