bitfab-cli 0.2.473 → 0.2.475
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/dist/index.js +1370 -956
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31126,8 +31126,8 @@ var semver2 = __toESM(require_semver2(), 1);
|
|
|
31126
31126
|
|
|
31127
31127
|
// ../bitfab-plugin-lib/dist/bakedSdkVersions.js
|
|
31128
31128
|
var BAKED_SDK_VERSIONS = {
|
|
31129
|
-
typescript: "0.
|
|
31130
|
-
python: "0.
|
|
31129
|
+
typescript: "0.67.0",
|
|
31130
|
+
python: "0.67.0",
|
|
31131
31131
|
ruby: "0.66.0",
|
|
31132
31132
|
go: "0.66.0"
|
|
31133
31133
|
};
|
|
@@ -31890,7 +31890,7 @@ async function runUpdate(currentVersion, platform2, mode = "all") {
|
|
|
31890
31890
|
}
|
|
31891
31891
|
}
|
|
31892
31892
|
|
|
31893
|
-
// ../
|
|
31893
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/commands.js
|
|
31894
31894
|
function defineCommandCatalog(catalog) {
|
|
31895
31895
|
return {
|
|
31896
31896
|
defineCommands(defs) {
|
|
@@ -31912,239 +31912,12 @@ function defineCommandCatalog(catalog) {
|
|
|
31912
31912
|
};
|
|
31913
31913
|
}
|
|
31914
31914
|
|
|
31915
|
-
// ../
|
|
31916
|
-
var CODEX_RESOLVE_PLUGIN_DIR_BASH = `\`\`\`bash
|
|
31917
|
-
if [ -z "$BITFAB_PLUGIN_DIR" ]; then
|
|
31918
|
-
BITFAB_PLUGIN_DIR=$(
|
|
31919
|
-
hit=$(find "\${CODEX_HOME:-$HOME/.codex}/plugins/cache" -maxdepth 6 -type f -name status.js \\
|
|
31920
|
-
\\( -path '*/bitfab-internal/bitfab/local/dist/commands/*' \\
|
|
31921
|
-
-o -path '*/bitfab/bitfab/*/dist/commands/*' \\) 2>/dev/null | head -1)
|
|
31922
|
-
echo "\${hit%/dist/commands/status.js}"
|
|
31923
|
-
)
|
|
31924
|
-
export BITFAB_PLUGIN_DIR
|
|
31925
|
-
fi
|
|
31926
|
-
test -n "$BITFAB_PLUGIN_DIR" || { echo "ERROR: Bitfab plugin not installed"; exit 1; }
|
|
31927
|
-
\`\`\``;
|
|
31928
|
-
var AMP_RESOLVE_PLUGIN_DIR_BASH = `\`\`\`bash
|
|
31929
|
-
if [ -z "$BITFAB_PLUGIN_DIR" ]; then
|
|
31930
|
-
project_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
31931
|
-
for candidate in "$project_root/.amp/plugins/bitfab" "\${XDG_CONFIG_HOME:-$HOME/.config}/amp/plugins/bitfab"; do
|
|
31932
|
-
if [ -f "$candidate/dist/commands/status.js" ]; then
|
|
31933
|
-
BITFAB_PLUGIN_DIR="$candidate"
|
|
31934
|
-
break
|
|
31935
|
-
fi
|
|
31936
|
-
done
|
|
31937
|
-
export BITFAB_PLUGIN_DIR
|
|
31938
|
-
fi
|
|
31939
|
-
test -n "$BITFAB_PLUGIN_DIR" || { echo "ERROR: Bitfab plugin not installed"; exit 1; }
|
|
31940
|
-
\`\`\``;
|
|
31941
|
-
|
|
31942
|
-
// ../bitfab-flow/dist/targets.js
|
|
31943
|
-
var TARGET_NAMES = ["claude", "cursor", "codex", "amp"];
|
|
31944
|
-
var SECTION_TARGETS = {
|
|
31945
|
-
claude: ["claude"],
|
|
31946
|
-
cursor: ["cursor"],
|
|
31947
|
-
codex: ["codex"],
|
|
31948
|
-
amp: ["amp"],
|
|
31949
|
-
"ask-user-question": ["claude", "cursor"],
|
|
31950
|
-
"plugin-dir-lookup": ["codex", "amp"],
|
|
31951
|
-
"exec-polling": ["codex", "amp"],
|
|
31952
|
-
"no-startup-banner": ["codex", "amp"],
|
|
31953
|
-
"web-fetch-tool": ["claude", "cursor"]
|
|
31954
|
-
};
|
|
31955
|
-
function formatAllowedTools(allowedTools) {
|
|
31956
|
-
return `[${allowedTools.map((t) => JSON.stringify(t)).join(", ")}]`;
|
|
31957
|
-
}
|
|
31958
|
-
var renderClaudeFrontmatter = ({ description, argumentHint, model, allowedTools }) => {
|
|
31959
|
-
const lines = ["---", `description: ${description}`];
|
|
31960
|
-
if (argumentHint !== void 0) {
|
|
31961
|
-
lines.push(`argument-hint: ${JSON.stringify(argumentHint)}`);
|
|
31962
|
-
}
|
|
31963
|
-
if (model !== void 0) {
|
|
31964
|
-
lines.push(`model: ${model}`);
|
|
31965
|
-
}
|
|
31966
|
-
if (allowedTools !== void 0) {
|
|
31967
|
-
lines.push(`allowed-tools: ${formatAllowedTools(allowedTools)}`);
|
|
31968
|
-
}
|
|
31969
|
-
lines.push("---");
|
|
31970
|
-
return lines.join("\n");
|
|
31971
|
-
};
|
|
31972
|
-
var renderClaudeSkillFrontmatter = ({ flowId, description, model, allowedTools }) => {
|
|
31973
|
-
const lines = [
|
|
31974
|
-
"---",
|
|
31975
|
-
`name: ${flowId}`,
|
|
31976
|
-
`description: ${description}`,
|
|
31977
|
-
"user-invocable: false"
|
|
31978
|
-
];
|
|
31979
|
-
if (model !== void 0) {
|
|
31980
|
-
lines.push(`model: ${model}`);
|
|
31981
|
-
}
|
|
31982
|
-
if (allowedTools !== void 0) {
|
|
31983
|
-
lines.push(`allowed-tools: ${formatAllowedTools(allowedTools)}`);
|
|
31984
|
-
}
|
|
31985
|
-
lines.push("---");
|
|
31986
|
-
return lines.join("\n");
|
|
31987
|
-
};
|
|
31988
|
-
function renderNamedFrontmatter(name, description, usage, usageInBody = false) {
|
|
31989
|
-
const frontmatter = [
|
|
31990
|
-
"---",
|
|
31991
|
-
`name: ${name}`,
|
|
31992
|
-
`description: "${description}${usageInBody ? "" : usage}"`,
|
|
31993
|
-
"---"
|
|
31994
|
-
].join("\n");
|
|
31995
|
-
return usageInBody && usage !== "" ? `${frontmatter}
|
|
31996
|
-
|
|
31997
|
-
${usage.slice(2)}` : frontmatter;
|
|
31998
|
-
}
|
|
31999
|
-
var renderCursorFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32000
|
-
const usage = argumentHint !== void 0 ? `. Usage: /bitfab-${flowId} ${argumentHint}` : "";
|
|
32001
|
-
return renderNamedFrontmatter(`bitfab-${flowId}`, description, usage);
|
|
32002
|
-
};
|
|
32003
|
-
var renderCodexFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32004
|
-
const usage = argumentHint !== void 0 ? `. Invoke with $bitfab:${flowId} ${argumentHint}.` : "";
|
|
32005
|
-
return renderNamedFrontmatter(flowId, description, usage);
|
|
32006
|
-
};
|
|
32007
|
-
var renderAmpFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32008
|
-
const usage = argumentHint !== void 0 ? `. Invoke as bitfab:${flowId} ${argumentHint}.` : "";
|
|
32009
|
-
return renderNamedFrontmatter(flowId, description, usage);
|
|
32010
|
-
};
|
|
32011
|
-
var renderCursorDevFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32012
|
-
const usage = argumentHint !== void 0 ? `. Usage: /bitfab-dev-${flowId} ${argumentHint}` : "";
|
|
32013
|
-
return renderNamedFrontmatter(`bitfab-dev-${flowId}`, description, usage, true);
|
|
32014
|
-
};
|
|
32015
|
-
var renderCodexDevFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32016
|
-
const usage = argumentHint !== void 0 ? `. Invoke with $bitfab-dev:${flowId} ${argumentHint}.` : "";
|
|
32017
|
-
return renderNamedFrontmatter(flowId, description, usage, true);
|
|
32018
|
-
};
|
|
32019
|
-
var renderAmpDevFrontmatter = ({ flowId, description, argumentHint }) => {
|
|
32020
|
-
const usage = argumentHint !== void 0 ? `. Invoke as bitfab-dev:${flowId} ${argumentHint}.` : "";
|
|
32021
|
-
return renderNamedFrontmatter(flowId, description, usage, true);
|
|
32022
|
-
};
|
|
32023
|
-
var ASK_USER_QUESTION_TOKENS = {
|
|
32024
|
-
askUser: "with `AskUserQuestion` ",
|
|
32025
|
-
askVerb: "use `AskUserQuestion`",
|
|
32026
|
-
askVerbCap: "Use `AskUserQuestion`",
|
|
32027
|
-
askNoun: "AskUserQuestion"
|
|
32028
|
-
};
|
|
32029
|
-
var PLAIN_PROMPT_TOKENS = {
|
|
32030
|
-
askUser: "",
|
|
32031
|
-
askVerb: "ask the user",
|
|
32032
|
-
askVerbCap: "Ask the user",
|
|
32033
|
-
askNoun: "choice prompt"
|
|
32034
|
-
};
|
|
32035
|
-
var TARGETS = {
|
|
32036
|
-
claude: {
|
|
32037
|
-
name: "claude",
|
|
32038
|
-
tokens: {
|
|
32039
|
-
cmd: "/bitfab:",
|
|
32040
|
-
devCmd: "/bitfab-dev:",
|
|
32041
|
-
editor: "Claude Code",
|
|
32042
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
32043
|
-
pluginRoot: "${CLAUDE_PLUGIN_ROOT}",
|
|
32044
|
-
pluginDirLookup: "",
|
|
32045
|
-
...ASK_USER_QUESTION_TOKENS
|
|
32046
|
-
},
|
|
32047
|
-
mcpPrefix: "mcp__plugin_bitfab_Bitfab__",
|
|
32048
|
-
argsToken: "$ARGUMENTS",
|
|
32049
|
-
frontmatter: renderClaudeFrontmatter,
|
|
32050
|
-
subSkillFrontmatter: renderClaudeSkillFrontmatter,
|
|
32051
|
-
subSkillTool: "Skill"
|
|
32052
|
-
},
|
|
32053
|
-
cursor: {
|
|
32054
|
-
name: "cursor",
|
|
32055
|
-
tokens: {
|
|
32056
|
-
cmd: "/bitfab-",
|
|
32057
|
-
devCmd: "/bitfab-dev-",
|
|
32058
|
-
editor: "Cursor",
|
|
32059
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
32060
|
-
pluginRoot: "${CURSOR_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}",
|
|
32061
|
-
pluginDirLookup: "",
|
|
32062
|
-
...ASK_USER_QUESTION_TOKENS
|
|
32063
|
-
},
|
|
32064
|
-
mcpPrefix: "mcp__Bitfab__",
|
|
32065
|
-
argsToken: "$ARGUMENTS",
|
|
32066
|
-
frontmatter: renderCursorFrontmatter,
|
|
32067
|
-
subSkillFrontmatter: renderCursorFrontmatter
|
|
32068
|
-
},
|
|
32069
|
-
codex: {
|
|
32070
|
-
name: "codex",
|
|
32071
|
-
tokens: {
|
|
32072
|
-
cmd: "$bitfab:",
|
|
32073
|
-
devCmd: "$bitfab-dev:",
|
|
32074
|
-
editor: "Codex",
|
|
32075
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
32076
|
-
pluginRoot: "${BITFAB_PLUGIN_DIR}",
|
|
32077
|
-
pluginDirLookup: CODEX_RESOLVE_PLUGIN_DIR_BASH,
|
|
32078
|
-
...PLAIN_PROMPT_TOKENS
|
|
32079
|
-
},
|
|
32080
|
-
mcpPrefix: "mcp__Bitfab__",
|
|
32081
|
-
argsToken: "$ARGUMENTS",
|
|
32082
|
-
frontmatter: renderCodexFrontmatter,
|
|
32083
|
-
subSkillFrontmatter: renderCodexFrontmatter,
|
|
32084
|
-
dispatchRef: (skillName) => `\`$bitfab:${skillName}\``
|
|
32085
|
-
},
|
|
32086
|
-
amp: {
|
|
32087
|
-
name: "amp",
|
|
32088
|
-
tokens: {
|
|
32089
|
-
cmd: "bitfab:",
|
|
32090
|
-
devCmd: "bitfab-dev:",
|
|
32091
|
-
editor: "Amp",
|
|
32092
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
32093
|
-
pluginRoot: "${BITFAB_PLUGIN_DIR}",
|
|
32094
|
-
pluginDirLookup: AMP_RESOLVE_PLUGIN_DIR_BASH,
|
|
32095
|
-
...PLAIN_PROMPT_TOKENS
|
|
32096
|
-
},
|
|
32097
|
-
mcpPrefix: "",
|
|
32098
|
-
argsToken: "the user's request",
|
|
32099
|
-
frontmatter: renderAmpFrontmatter,
|
|
32100
|
-
subSkillFrontmatter: renderAmpFrontmatter,
|
|
32101
|
-
subSkillTool: "skill",
|
|
32102
|
-
dispatchRef: (skillName) => `\`bitfab:${skillName}\``
|
|
32103
|
-
}
|
|
32104
|
-
};
|
|
32105
|
-
var DEV_TARGETS = {
|
|
32106
|
-
claude: {
|
|
32107
|
-
...TARGETS.claude,
|
|
32108
|
-
frontmatter: renderClaudeFrontmatter,
|
|
32109
|
-
subSkillFrontmatter: renderClaudeSkillFrontmatter
|
|
32110
|
-
},
|
|
32111
|
-
cursor: {
|
|
32112
|
-
...TARGETS.cursor,
|
|
32113
|
-
frontmatter: renderCursorDevFrontmatter,
|
|
32114
|
-
subSkillFrontmatter: renderCursorDevFrontmatter
|
|
32115
|
-
},
|
|
32116
|
-
codex: {
|
|
32117
|
-
...TARGETS.codex,
|
|
32118
|
-
frontmatter: renderCodexDevFrontmatter,
|
|
32119
|
-
subSkillFrontmatter: renderCodexDevFrontmatter,
|
|
32120
|
-
dispatchRef: (skillName) => `\`$bitfab-dev:${skillName}\``
|
|
32121
|
-
},
|
|
32122
|
-
amp: {
|
|
32123
|
-
...TARGETS.amp,
|
|
32124
|
-
frontmatter: renderAmpDevFrontmatter,
|
|
32125
|
-
subSkillFrontmatter: renderAmpDevFrontmatter,
|
|
32126
|
-
dispatchRef: (skillName) => `\`bitfab-dev:${skillName}\``
|
|
32127
|
-
}
|
|
32128
|
-
};
|
|
32129
|
-
|
|
32130
|
-
// ../bitfab-flow/dist/schema.js
|
|
31915
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/schema.js
|
|
32131
31916
|
var StepIdRef = external_exports.string().regex(/^[a-z0-9-]+\/[a-z0-9-]+$/, {
|
|
32132
31917
|
message: "Step references must use the form 'phase-id/step-id'"
|
|
32133
31918
|
});
|
|
32134
31919
|
var StepLocalId = external_exports.string().regex(/^[a-z0-9-]+$/);
|
|
32135
31920
|
var PhaseId = external_exports.string().regex(/^[a-z0-9-]+$/);
|
|
32136
|
-
function PerTarget(inner) {
|
|
32137
|
-
const objectForm = external_exports.object({
|
|
32138
|
-
default: inner.optional(),
|
|
32139
|
-
claude: inner.optional(),
|
|
32140
|
-
cursor: inner.optional(),
|
|
32141
|
-
codex: inner.optional(),
|
|
32142
|
-
amp: inner.optional()
|
|
32143
|
-
}).refine((v) => v.default !== void 0 || TARGET_NAMES.every((target) => v[target] !== void 0), {
|
|
32144
|
-
message: `Per-target object must have \`default\` or define all of ${TARGET_NAMES.join("/")}.`
|
|
32145
|
-
});
|
|
32146
|
-
return external_exports.union([inner, objectForm]);
|
|
32147
|
-
}
|
|
32148
31921
|
function resolvePerTarget(value, target) {
|
|
32149
31922
|
if (typeof value !== "object" || value === null) {
|
|
32150
31923
|
return value;
|
|
@@ -32152,23 +31925,6 @@ function resolvePerTarget(value, target) {
|
|
|
32152
31925
|
const map2 = value;
|
|
32153
31926
|
return map2[target] ?? map2.default;
|
|
32154
31927
|
}
|
|
32155
|
-
var TargetableString = PerTarget(external_exports.string());
|
|
32156
|
-
var TargetableNonEmptyString = PerTarget(external_exports.string().min(1));
|
|
32157
|
-
var RESERVED_TOKEN_NAMES = [
|
|
32158
|
-
"cmd",
|
|
32159
|
-
"devCmd",
|
|
32160
|
-
"editor",
|
|
32161
|
-
"pluginRoot",
|
|
32162
|
-
"pluginDirLookup",
|
|
32163
|
-
"askUser",
|
|
32164
|
-
"askVerb",
|
|
32165
|
-
"askVerbCap",
|
|
32166
|
-
"askNoun",
|
|
32167
|
-
"argsToken"
|
|
32168
|
-
];
|
|
32169
|
-
var MUSTACHE_SECTION_NAMES = Object.keys(SECTION_TARGETS);
|
|
32170
|
-
var MODE_SECTION_RE = /\{\{([#^])mode:([a-z0-9-]+)\}\}/g;
|
|
32171
|
-
var MODE_SECTION_CLOSE_RE = /\{\{\/mode:([a-z0-9-]+)\}\}/g;
|
|
32172
31928
|
function resolveTargetableString(value, target, label) {
|
|
32173
31929
|
const resolved = resolvePerTarget(value, target);
|
|
32174
31930
|
if (resolved === void 0) {
|
|
@@ -32176,6 +31932,11 @@ function resolveTargetableString(value, target, label) {
|
|
|
32176
31932
|
}
|
|
32177
31933
|
return resolved;
|
|
32178
31934
|
}
|
|
31935
|
+
var MODE_SECTION_RE = /\{\{([#^])mode:([a-z0-9-]+)\}\}/g;
|
|
31936
|
+
var MODE_SECTION_CLOSE_RE = /\{\{\/mode:([a-z0-9-]+)\}\}/g;
|
|
31937
|
+
var TOOL_PLACEHOLDER_RE = /\{\{tool:([a-zA-Z][a-zA-Z0-9_-]*)\}\}/g;
|
|
31938
|
+
var COMMAND_PLACEHOLDER_RE = /\{\{command:([a-zA-Z][a-zA-Z0-9_-]*)\}\}/g;
|
|
31939
|
+
var TABLE_PLACEHOLDER_RE = /\{\{(table|list):([a-zA-Z][a-zA-Z0-9_-]*):([a-zA-Z0-9_,-]+)\}\}/g;
|
|
32179
31940
|
var NextRef = StepIdRef.nullable();
|
|
32180
31941
|
var ByModeNext = external_exports.object({
|
|
32181
31942
|
byMode: external_exports.record(external_exports.string(), NextRef)
|
|
@@ -32188,56 +31949,50 @@ var EmitLabel = external_exports.union([
|
|
|
32188
31949
|
action: external_exports.enum(["started", "completed"])
|
|
32189
31950
|
})
|
|
32190
31951
|
]);
|
|
31952
|
+
var BranchOption = external_exports.object({
|
|
31953
|
+
/** Letter shown in the choice prompt, e.g. "A", "B", "C". */
|
|
31954
|
+
letter: external_exports.string().min(1),
|
|
31955
|
+
/** Bolded option name, e.g. "Update all N outdated workspaces". */
|
|
31956
|
+
label: external_exports.string().min(1),
|
|
31957
|
+
/** Optional explanation that follows the label. */
|
|
31958
|
+
description: external_exports.string().optional()
|
|
31959
|
+
});
|
|
31960
|
+
var CompileMode = external_exports.enum(["monolith", "split", "split-chain"]);
|
|
31961
|
+
function PerTarget(inner) {
|
|
31962
|
+
return external_exports.union([inner, external_exports.record(external_exports.string(), inner)]);
|
|
31963
|
+
}
|
|
31964
|
+
var TargetableString = PerTarget(external_exports.string());
|
|
31965
|
+
var TargetableNonEmptyString = PerTarget(external_exports.string().min(1));
|
|
32191
31966
|
var Base = external_exports.object({
|
|
32192
31967
|
id: StepLocalId,
|
|
32193
31968
|
title: TargetableNonEmptyString,
|
|
32194
31969
|
/**
|
|
32195
31970
|
* Concise inline name for cross-phase prose references via
|
|
32196
|
-
* `{{step-ref:phase/id}}`. Falls back to `title` when omitted.
|
|
32197
|
-
* the header `title` reads clumsily mid-sentence (e.g. title "Mark ready,
|
|
32198
|
-
* then merge" -> refName "merge", so a ref renders "the merge step"). Unlike
|
|
31971
|
+
* `{{step-ref:phase/id}}`. Falls back to `title` when omitted. Unlike
|
|
32199
31972
|
* `{{step:...}}` (a file-local number), `{{step-ref:...}}` renders a stable
|
|
32200
31973
|
* name, so it stays meaningful across phases and across split-unit files.
|
|
32201
31974
|
*/
|
|
32202
31975
|
refName: TargetableNonEmptyString.optional(),
|
|
32203
31976
|
body: TargetableString,
|
|
32204
31977
|
/**
|
|
32205
|
-
* Value emitted through the flow-level `emitTemplate` when this step
|
|
32206
|
-
*
|
|
32207
|
-
*
|
|
32208
|
-
* - String shorthand: display name, action defaults to "started".
|
|
32209
|
-
* - Object form: explicit `displayName` + `action`.
|
|
32210
|
-
*
|
|
32211
|
-
* How the value is rendered is determined by `flow.emitTemplate`.
|
|
31978
|
+
* Value emitted through the flow-level `emitTemplate` when this step is
|
|
31979
|
+
* reached. String shorthand = display name with action "started".
|
|
32212
31980
|
* Steps with `emit` but no flow-level template are silently ignored.
|
|
32213
31981
|
*/
|
|
32214
31982
|
emit: EmitLabel.optional(),
|
|
32215
31983
|
/**
|
|
32216
31984
|
* Logical ids of tools this step calls (must exist in `flow.tools`). Used
|
|
32217
|
-
* to auto-derive `frontmatter.allowedTools
|
|
32218
|
-
* placeholders in the body.
|
|
31985
|
+
* to auto-derive `frontmatter.allowedTools`.
|
|
32219
31986
|
*/
|
|
32220
31987
|
toolCalls: external_exports.array(external_exports.string()).optional(),
|
|
32221
|
-
/**
|
|
32222
|
-
* Logical ids of commands this step invokes (must exist in `flow.commands`).
|
|
32223
|
-
* Mirrors `toolCalls` for the command registry so consumers don't need to
|
|
32224
|
-
* regex-scan the body for `{{command:id}}` placeholders.
|
|
32225
|
-
*/
|
|
31988
|
+
/** Logical ids of commands this step invokes (must exist in `flow.commands`). */
|
|
32226
31989
|
commandCalls: external_exports.array(external_exports.string()).optional(),
|
|
32227
31990
|
/**
|
|
32228
|
-
*
|
|
32229
|
-
* 1-indexed
|
|
32230
|
-
* sections like Codex's "Resolve BITFAB_PLUGIN_DIR" that conceptually sit
|
|
32231
|
-
* before step 1 even though they execute first.
|
|
31991
|
+
* In a "headers" phase, number the step "0" instead of joining the
|
|
31992
|
+
* 1-indexed sequence. For setup-style preambles that sit before step 1.
|
|
32232
31993
|
*/
|
|
32233
31994
|
preamble: external_exports.boolean().optional(),
|
|
32234
|
-
/**
|
|
32235
|
-
* Optional list of appendix ids this step consults. Available on every step
|
|
32236
|
-
* kind so that an action or branch step can document its references to
|
|
32237
|
-
* appendices (validated against `flow.appendices` at parse time). The
|
|
32238
|
-
* `kind: "reference"` discriminant carries a stricter `min(1)` requirement
|
|
32239
|
-
* since consulting an appendix is its primary purpose.
|
|
32240
|
-
*/
|
|
31995
|
+
/** Appendix ids this step consults (validated against `flow.appendices`). */
|
|
32241
31996
|
refs: external_exports.array(external_exports.string().min(1)).optional(),
|
|
32242
31997
|
meta: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
|
|
32243
31998
|
});
|
|
@@ -32245,54 +32000,28 @@ var Action = Base.extend({
|
|
|
32245
32000
|
kind: external_exports.literal("action"),
|
|
32246
32001
|
next: Next
|
|
32247
32002
|
});
|
|
32248
|
-
var BranchOption = external_exports.object({
|
|
32249
|
-
/** Letter shown in the AskUserQuestion prompt, e.g. "A", "B", "C". */
|
|
32250
|
-
letter: external_exports.string().min(1),
|
|
32251
|
-
/** Bolded option name, e.g. "Update all N outdated workspaces". */
|
|
32252
|
-
label: external_exports.string().min(1),
|
|
32253
|
-
/** Optional explanation that follows the label after an em dash. */
|
|
32254
|
-
description: external_exports.string().optional()
|
|
32255
|
-
});
|
|
32256
32003
|
var Branch = Base.extend({
|
|
32257
32004
|
kind: external_exports.literal("branch"),
|
|
32258
32005
|
branches: external_exports.array(external_exports.object({
|
|
32259
32006
|
/**
|
|
32260
|
-
*
|
|
32261
|
-
*
|
|
32262
|
-
* branches - when omitted, the diagram label defaults to
|
|
32263
|
-
* `${option.letter} - ${option.label}`.
|
|
32007
|
+
* Runtime condition (agent decides). Required unless the branch
|
|
32008
|
+
* is a user choice (`option`); also the diagram edge label.
|
|
32264
32009
|
*/
|
|
32265
32010
|
when: external_exports.string().optional(),
|
|
32266
|
-
/**
|
|
32267
|
-
* Where this branch goes after the user picks it (or after the
|
|
32268
|
-
* runtime condition resolves). Linear `NextRef` form for the common
|
|
32269
|
-
* case where every mode goes to the same place; `byMode` dispatch
|
|
32270
|
-
* for branches that need per-mode targets - e.g. an "exit" option
|
|
32271
|
-
* that hands off to the next phase in `all` mode but terminates in
|
|
32272
|
-
* sub-modes.
|
|
32273
|
-
*/
|
|
32011
|
+
/** Where this branch goes; linear or `byMode`. */
|
|
32274
32012
|
next: Next,
|
|
32275
32013
|
/** Marks the option the agent should default to. */
|
|
32276
32014
|
recommended: external_exports.boolean().optional(),
|
|
32277
32015
|
/**
|
|
32278
|
-
* Tags the prompt this option belongs to when
|
|
32279
|
-
*
|
|
32280
|
-
* with `{{branches:prompt-name}}`.
|
|
32016
|
+
* Tags the prompt this option belongs to when one step exposes
|
|
32017
|
+
* several user prompts; render a subset with `{{branches:name}}`.
|
|
32281
32018
|
*/
|
|
32282
32019
|
prompt: external_exports.string().optional(),
|
|
32283
|
-
/**
|
|
32284
|
-
* Present on user-choice branches - drives the rendered prompt
|
|
32285
|
-
* block via `{{branches}}` and supersedes `when` as the source of
|
|
32286
|
-
* truth for option text. Absent on runtime branches.
|
|
32287
|
-
*/
|
|
32020
|
+
/** User-choice option rendered by `{{branches}}`. */
|
|
32288
32021
|
option: BranchOption.optional(),
|
|
32289
32022
|
/**
|
|
32290
|
-
*
|
|
32291
|
-
*
|
|
32292
|
-
* `{{whens}}` rendering. When omitted, falls back to "stop the
|
|
32293
|
-
* flow" (for `next: null`) or "continue" (for any step ref). Has
|
|
32294
|
-
* no effect on user-choice (`option`) branches; those use
|
|
32295
|
-
* `option.description`.
|
|
32023
|
+
* Action text for runtime (`when`) branches in `{{whens}}`. Falls
|
|
32024
|
+
* back to "stop the flow" (`next: null`) or "continue".
|
|
32296
32025
|
*/
|
|
32297
32026
|
description: external_exports.string().optional()
|
|
32298
32027
|
}).strict().refine((b) => b.when !== void 0 || b.option !== void 0, {
|
|
@@ -32332,11 +32061,8 @@ var Phase = external_exports.object({
|
|
|
32332
32061
|
steps: external_exports.array(Step).min(1),
|
|
32333
32062
|
outro: TargetableString.optional(),
|
|
32334
32063
|
/**
|
|
32335
|
-
*
|
|
32336
|
-
* - "
|
|
32337
|
-
* - "headers": phase title is hidden; each step renders as its own `## {N}. {title}` H2 section with body below.
|
|
32338
|
-
*
|
|
32339
|
-
* In "headers" mode, steps marked `preamble: true` are numbered "0" instead of joining the 1-indexed sequence.
|
|
32064
|
+
* - "list": `## {title}`, intro, then steps as a numbered markdown list.
|
|
32065
|
+
* - "headers": title hidden; each step is its own `## {N}. {title}` section.
|
|
32340
32066
|
*/
|
|
32341
32067
|
stepStyle: external_exports.enum(["list", "headers"]).default("list")
|
|
32342
32068
|
});
|
|
@@ -32360,143 +32086,83 @@ var Frontmatter = external_exports.object({
|
|
|
32360
32086
|
]).optional(),
|
|
32361
32087
|
model: external_exports.string().optional(),
|
|
32362
32088
|
/**
|
|
32363
|
-
*
|
|
32364
|
-
*
|
|
32089
|
+
* Manual override. When omitted and `flow.tools` is non-empty, the
|
|
32090
|
+
* renderer derives the list from the tools the flow actually calls.
|
|
32365
32091
|
*/
|
|
32366
32092
|
allowedTools: external_exports.array(external_exports.string()).optional()
|
|
32367
32093
|
});
|
|
32368
32094
|
var ToolDef = external_exports.object({
|
|
32369
32095
|
name: PerTarget(external_exports.string()),
|
|
32370
32096
|
kind: external_exports.enum(["builtin", "mcp"]),
|
|
32371
|
-
targets: external_exports.array(external_exports.
|
|
32097
|
+
targets: external_exports.array(external_exports.string()).nonempty().optional()
|
|
32372
32098
|
});
|
|
32373
32099
|
var CommandDef = external_exports.object({
|
|
32374
32100
|
file: external_exports.string().min(1),
|
|
32375
32101
|
description: external_exports.string().min(1),
|
|
32376
32102
|
args: external_exports.string().optional()
|
|
32377
32103
|
});
|
|
32378
|
-
var
|
|
32379
|
-
/**
|
|
32380
|
-
|
|
32381
|
-
/**
|
|
32382
|
-
|
|
32383
|
-
|
|
32384
|
-
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
|
|
32388
|
-
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
});
|
|
32392
|
-
var Flow = external_exports.object({
|
|
32104
|
+
var Table = external_exports.object({
|
|
32105
|
+
/** Header of the leading key column. */
|
|
32106
|
+
keyHeader: external_exports.string().min(1).default("Name"),
|
|
32107
|
+
/** Column header per field; unset fields fall back to the title-cased field name. */
|
|
32108
|
+
columns: external_exports.record(external_exports.string(), external_exports.string()).default({}),
|
|
32109
|
+
rows: external_exports.array(external_exports.object({
|
|
32110
|
+
key: external_exports.string().min(1),
|
|
32111
|
+
/** Display name for `{{list:...}}`; falls back to `key`. */
|
|
32112
|
+
label: external_exports.string().optional(),
|
|
32113
|
+
cells: external_exports.record(external_exports.string(), external_exports.string())
|
|
32114
|
+
})).min(1)
|
|
32115
|
+
});
|
|
32116
|
+
var FlowBase = external_exports.object({
|
|
32393
32117
|
schemaVersion: external_exports.literal(1),
|
|
32394
|
-
id: external_exports.string().
|
|
32118
|
+
id: external_exports.string().regex(/^[a-z0-9-]+$/),
|
|
32395
32119
|
title: TargetableNonEmptyString,
|
|
32396
32120
|
frontmatter: Frontmatter,
|
|
32397
32121
|
intro: TargetableString.optional(),
|
|
32398
32122
|
/**
|
|
32399
|
-
* Entry step per invocation mode
|
|
32400
|
-
*
|
|
32401
|
-
* target can start at a different step than the others - for example,
|
|
32402
|
-
* Codex enters at the `resolve-plugin-dir` preamble while Claude and
|
|
32403
|
-
* Cursor enter directly at `run-update-script`.
|
|
32123
|
+
* Entry step per invocation mode: a bare step id, or a per-target map so a
|
|
32124
|
+
* target can start elsewhere (e.g. at a host-specific preamble).
|
|
32404
32125
|
*/
|
|
32405
32126
|
entries: external_exports.record(external_exports.string(), PerTarget(StepIdRef)),
|
|
32406
|
-
/**
|
|
32127
|
+
/** Mode invoked when the user passes no argument. Must be a key in `entries`. */
|
|
32407
32128
|
defaultMode: external_exports.string().optional(),
|
|
32408
32129
|
/**
|
|
32409
|
-
*
|
|
32410
|
-
*
|
|
32411
|
-
* emits an auto-generated "Modes" dispatch table at the top of the file so
|
|
32412
|
-
* the agent can map `$ARGUMENTS` to the right mode without hand-authored
|
|
32413
|
-
* routing prose. A mode without a hint falls back to its entry phase's
|
|
32414
|
-
* title. Values are `TargetableString`, so a hint can differ per target
|
|
32415
|
-
* (e.g. editor-specific wording) and standard placeholders resolve normally.
|
|
32130
|
+
* One-line description per mode. Declaring any opts a multi-mode flow
|
|
32131
|
+
* into an auto-generated "Modes" routing table.
|
|
32416
32132
|
*/
|
|
32417
32133
|
modeHints: external_exports.record(external_exports.string(), TargetableString).default({}),
|
|
32418
32134
|
/**
|
|
32419
|
-
* Template for
|
|
32420
|
-
*
|
|
32421
|
-
* step's `emit` field. All other placeholders (`{{pluginRoot}}`,
|
|
32422
|
-
* Mustache sections, etc.) are resolved by the normal pipeline.
|
|
32423
|
-
*
|
|
32424
|
-
* If absent, steps with `emit` are silently ignored (no output
|
|
32425
|
-
* rendered). This keeps flows that don't need emission from having
|
|
32426
|
-
* to declare a no-op template.
|
|
32135
|
+
* Template rendered for each step `emit`. `{action}` and `{displayName}`
|
|
32136
|
+
* are substituted; every other placeholder resolves normally.
|
|
32427
32137
|
*/
|
|
32428
32138
|
emitTemplate: TargetableString.optional(),
|
|
32429
32139
|
phases: external_exports.array(Phase).min(1),
|
|
32430
32140
|
appendices: external_exports.array(Appendix).default([]),
|
|
32431
32141
|
invariants: external_exports.array(external_exports.string()).default([]),
|
|
32432
|
-
|
|
32433
|
-
/**
|
|
32434
|
-
* Headers for the columns rendered by `{{languages:FIELD}}` placeholders.
|
|
32435
|
-
* Keyed by Language field name (`imports`, `detection`, `outdated`,
|
|
32436
|
-
* `update`). When unset for a column, the renderer falls back to the
|
|
32437
|
-
* field's title-cased name.
|
|
32438
|
-
*/
|
|
32439
|
-
languageColumnHeaders: external_exports.record(external_exports.string(), external_exports.string()).default({}),
|
|
32440
|
-
/**
|
|
32441
|
-
* Tool registry keyed by logical id. `step.toolCalls` references entries
|
|
32442
|
-
* here; `{{tool:id}}` placeholders render the per-target name.
|
|
32443
|
-
*/
|
|
32142
|
+
tables: external_exports.record(external_exports.string(), Table).default({}),
|
|
32444
32143
|
tools: external_exports.record(external_exports.string(), ToolDef).default({}),
|
|
32445
|
-
/**
|
|
32446
|
-
* CLI command registry keyed by logical id. `{{command:id}}` placeholders
|
|
32447
|
-
* in step/intro/appendix text render as the full invocation path. When
|
|
32448
|
-
* non-empty, the renderer emits a reference table after the flow intro.
|
|
32449
|
-
*/
|
|
32450
32144
|
commands: external_exports.record(external_exports.string(), CommandDef).default({}),
|
|
32451
32145
|
/**
|
|
32452
|
-
* User-defined variables
|
|
32453
|
-
*
|
|
32454
|
-
* in any string field. Must not collide with target-level tokens (cmd,
|
|
32455
|
-
* editor, pluginRoot, askUser).
|
|
32146
|
+
* User-defined `{{name}}` variables (bare or per-target). Must not collide
|
|
32147
|
+
* with target token names.
|
|
32456
32148
|
*/
|
|
32457
32149
|
variables: external_exports.record(external_exports.string(), TargetableString).default({}),
|
|
32458
32150
|
/**
|
|
32459
|
-
* How
|
|
32460
|
-
* - `monolith
|
|
32461
|
-
*
|
|
32462
|
-
* -
|
|
32463
|
-
*
|
|
32464
|
-
*
|
|
32465
|
-
*
|
|
32466
|
-
*
|
|
32467
|
-
* sub-skills.
|
|
32468
|
-
* - `split-chain`: same file layout as `split`, but routing compiles to
|
|
32469
|
-
* tail-call dispatch. The orchestrator never says "return here";
|
|
32470
|
-
* instead every step whose outgoing edge crosses a unit boundary
|
|
32471
|
-
* (orchestrator-with-inline-phases, or a sub-skill) gets a generated
|
|
32472
|
-
* "Next:" annotation with one line per (target phase, mode set) group,
|
|
32473
|
-
* mode literals baked in. Cross-phase loops are legal under
|
|
32474
|
-
* `split-chain` (a dispatch edge back to an earlier sub-skill renders
|
|
32475
|
-
* like any other), which the sequential `split` orchestrator cannot
|
|
32476
|
-
* express.
|
|
32477
|
-
* Codex writes non-inline phases to ordinary `references/<phase>.md`
|
|
32478
|
-
* files and routes by reading them, keeping phase names out of skill
|
|
32479
|
-
* discovery. Other targets emit phase sub-skills.
|
|
32151
|
+
* How the flow compiles to files.
|
|
32152
|
+
* - `monolith`: one skill file per target.
|
|
32153
|
+
* - `split`: an orchestrator plus one sub-skill per non-inline phase,
|
|
32154
|
+
* dispatched call-and-return ("invoke X, then return here").
|
|
32155
|
+
* - `split-chain`: same layout, tail-call routing. Every step whose edge
|
|
32156
|
+
* crosses a file boundary gets a generated "**Next:**" block with mode
|
|
32157
|
+
* literals baked in. Targets with `phaseReferences` emit phases as
|
|
32158
|
+
* reference files instead of discoverable sub-skills.
|
|
32480
32159
|
*
|
|
32481
|
-
* `mode` is per-target
|
|
32482
|
-
*
|
|
32483
|
-
*
|
|
32484
|
-
* `"split"` / `"monolith"` applies to every target.
|
|
32485
|
-
*
|
|
32486
|
-
* `continuousStepNumbers` (monolith only) numbers step headers 1…N
|
|
32487
|
-
* continuously across phases instead of restarting at 1 per phase. Set it
|
|
32488
|
-
* when the phases run **sequentially** in one file (e.g. preflight then a
|
|
32489
|
-
* run phase): restarting would emit duplicate `## 1.` headers with nothing
|
|
32490
|
-
* to disambiguate them. Leave it off (the default) when phases are
|
|
32491
|
-
* **mutually exclusive** alternatives each gated by "Run only when mode is
|
|
32492
|
-
* X" (e.g. subcommands): there the per-phase restart is correct, since only
|
|
32493
|
-
* one phase is ever followed and its own steps read naturally from 1, and
|
|
32494
|
-
* the mode gate, not the number, is what disambiguates. Split modes ignore
|
|
32495
|
-
* this flag entirely: each phase compiles to its own file and always
|
|
32496
|
-
* restarts at 1.
|
|
32160
|
+
* `mode` is per-target, so split can roll out one host at a time.
|
|
32161
|
+
* `continuousStepNumbers` (monolith only) numbers headers 1…N across
|
|
32162
|
+
* sequential phases instead of restarting per phase.
|
|
32497
32163
|
*/
|
|
32498
32164
|
compile: external_exports.object({
|
|
32499
|
-
mode: PerTarget(
|
|
32165
|
+
mode: PerTarget(CompileMode).default("monolith"),
|
|
32500
32166
|
inlinePhases: external_exports.array(external_exports.string()).default([]),
|
|
32501
32167
|
continuousStepNumbers: external_exports.boolean().default(false)
|
|
32502
32168
|
}).default({
|
|
@@ -32504,465 +32170,320 @@ var Flow = external_exports.object({
|
|
|
32504
32170
|
inlinePhases: [],
|
|
32505
32171
|
continuousStepNumbers: false
|
|
32506
32172
|
})
|
|
32507
|
-
})
|
|
32508
|
-
|
|
32509
|
-
const
|
|
32510
|
-
|
|
32511
|
-
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
}
|
|
32518
|
-
|
|
32519
|
-
|
|
32520
|
-
|
|
32521
|
-
|
|
32522
|
-
|
|
32523
|
-
|
|
32524
|
-
|
|
32525
|
-
|
|
32526
|
-
|
|
32173
|
+
});
|
|
32174
|
+
function createFlowSchema(options) {
|
|
32175
|
+
const targetNames = [...options.targetNames];
|
|
32176
|
+
const reservedTokenNames = /* @__PURE__ */ new Set([
|
|
32177
|
+
...options.reservedTokenNames ?? [],
|
|
32178
|
+
"argsToken"
|
|
32179
|
+
]);
|
|
32180
|
+
const allowedKeys = /* @__PURE__ */ new Set(["default", ...targetNames]);
|
|
32181
|
+
return FlowBase.superRefine((flow, ctx) => {
|
|
32182
|
+
const issue2 = (path15, message) => ctx.addIssue({ code: "custom", path: path15, message });
|
|
32183
|
+
for (const { path: path15, value } of targetableFields(flow)) {
|
|
32184
|
+
if (typeof value !== "object" || value === null) {
|
|
32185
|
+
continue;
|
|
32186
|
+
}
|
|
32187
|
+
const map2 = value;
|
|
32188
|
+
for (const key of Object.keys(map2)) {
|
|
32189
|
+
if (!allowedKeys.has(key)) {
|
|
32190
|
+
issue2(path15, `Unknown target "${key}" in per-target object. Known targets: ${targetNames.join(", ")}.`);
|
|
32191
|
+
}
|
|
32192
|
+
}
|
|
32193
|
+
if (map2.default === void 0 && !targetNames.every((target) => map2[target] !== void 0)) {
|
|
32194
|
+
issue2(path15, `Per-target object must have \`default\` or define all of ${targetNames.join("/")}.`);
|
|
32527
32195
|
}
|
|
32528
|
-
localIds.add(step.id);
|
|
32529
|
-
allStepIds.add(`${phase.id}/${step.id}`);
|
|
32530
|
-
}
|
|
32531
|
-
}
|
|
32532
|
-
for (const phaseId of flow.compile.inlinePhases) {
|
|
32533
|
-
if (!phaseIds.has(phaseId)) {
|
|
32534
|
-
ctx.addIssue({
|
|
32535
|
-
code: "custom",
|
|
32536
|
-
path: ["compile", "inlinePhases"],
|
|
32537
|
-
message: `inlinePhases lists unknown phase "${phaseId}"`
|
|
32538
|
-
});
|
|
32539
32196
|
}
|
|
32540
|
-
|
|
32541
|
-
|
|
32542
|
-
|
|
32543
|
-
|
|
32544
|
-
|
|
32545
|
-
|
|
32546
|
-
|
|
32547
|
-
|
|
32548
|
-
|
|
32549
|
-
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32555
|
-
path: ["defaultMode"],
|
|
32556
|
-
message: `defaultMode "${flow.defaultMode}" not declared in entries`
|
|
32557
|
-
});
|
|
32558
|
-
}
|
|
32559
|
-
for (const mode of Object.keys(flow.modeHints)) {
|
|
32560
|
-
if (!declaredModeSet.has(mode)) {
|
|
32561
|
-
ctx.addIssue({
|
|
32562
|
-
code: "custom",
|
|
32563
|
-
path: ["modeHints", mode],
|
|
32564
|
-
message: `modeHints key "${mode}" not declared in entries`
|
|
32565
|
-
});
|
|
32197
|
+
const allStepIds = /* @__PURE__ */ new Set();
|
|
32198
|
+
const phaseIds = /* @__PURE__ */ new Set();
|
|
32199
|
+
for (const phase of flow.phases) {
|
|
32200
|
+
if (phaseIds.has(phase.id)) {
|
|
32201
|
+
issue2(["phases", phase.id], `duplicate phase id "${phase.id}"`);
|
|
32202
|
+
}
|
|
32203
|
+
phaseIds.add(phase.id);
|
|
32204
|
+
const localIds = /* @__PURE__ */ new Set();
|
|
32205
|
+
for (const step of phase.steps) {
|
|
32206
|
+
if (localIds.has(step.id)) {
|
|
32207
|
+
issue2(["phases", phase.id, "steps"], `duplicate step id "${step.id}" in phase "${phase.id}"`);
|
|
32208
|
+
}
|
|
32209
|
+
localIds.add(step.id);
|
|
32210
|
+
allStepIds.add(`${phase.id}/${step.id}`);
|
|
32211
|
+
}
|
|
32566
32212
|
}
|
|
32567
|
-
|
|
32568
|
-
|
|
32569
|
-
|
|
32570
|
-
|
|
32213
|
+
for (const phaseId of flow.compile.inlinePhases) {
|
|
32214
|
+
if (!phaseIds.has(phaseId)) {
|
|
32215
|
+
issue2(["compile", "inlinePhases"], `inlinePhases lists unknown phase "${phaseId}"`);
|
|
32216
|
+
}
|
|
32571
32217
|
}
|
|
32572
|
-
|
|
32573
|
-
|
|
32218
|
+
const declaredModes = Object.keys(flow.entries);
|
|
32219
|
+
const declaredModeSet = new Set(declaredModes);
|
|
32220
|
+
const argumentHint = flow.frontmatter.argumentHint;
|
|
32221
|
+
const argumentHintModes = declaredModes.filter((mode) => mode !== "default" || flow.defaultMode !== "default");
|
|
32222
|
+
if (typeof argumentHint === "object" && "deriveFromModes" in argumentHint && argumentHintModes.length === 0) {
|
|
32223
|
+
issue2(["frontmatter", "argumentHint"], "deriveFromModes requires at least one non-default mode in entries");
|
|
32574
32224
|
}
|
|
32575
|
-
|
|
32576
|
-
|
|
32577
|
-
const refsFromStep = (s2) => {
|
|
32578
|
-
switch (s2.kind) {
|
|
32579
|
-
case "action":
|
|
32580
|
-
case "reference":
|
|
32581
|
-
case "parallel":
|
|
32582
|
-
return refsFromNext(s2.next);
|
|
32583
|
-
case "branch":
|
|
32584
|
-
return s2.branches.flatMap((b) => refsFromNext(b.next));
|
|
32585
|
-
case "loop":
|
|
32586
|
-
return [s2.backTo, s2.onExit];
|
|
32225
|
+
if (flow.defaultMode !== void 0 && !declaredModeSet.has(flow.defaultMode)) {
|
|
32226
|
+
issue2(["defaultMode"], `defaultMode "${flow.defaultMode}" not declared in entries`);
|
|
32587
32227
|
}
|
|
32588
|
-
|
|
32589
|
-
|
|
32590
|
-
|
|
32591
|
-
for (const ref of refsFromStep(step)) {
|
|
32592
|
-
if (!allStepIds.has(ref)) {
|
|
32593
|
-
ctx.addIssue({
|
|
32594
|
-
code: "custom",
|
|
32595
|
-
path: ["phases", phase.id, "steps", step.id],
|
|
32596
|
-
message: `edge \u2192 unknown step "${ref}"`
|
|
32597
|
-
});
|
|
32598
|
-
}
|
|
32228
|
+
for (const mode of Object.keys(flow.modeHints)) {
|
|
32229
|
+
if (!declaredModeSet.has(mode)) {
|
|
32230
|
+
issue2(["modeHints", mode], `modeHints key "${mode}" not declared in entries`);
|
|
32599
32231
|
}
|
|
32600
|
-
|
|
32601
|
-
|
|
32602
|
-
|
|
32603
|
-
|
|
32604
|
-
|
|
32605
|
-
|
|
32606
|
-
message: `${label} lists mode "${mode}" not declared in flow.entries`
|
|
32607
|
-
});
|
|
32232
|
+
}
|
|
32233
|
+
for (const phase of flow.phases) {
|
|
32234
|
+
for (const step of phase.steps) {
|
|
32235
|
+
for (const ref of refsFromStep(step)) {
|
|
32236
|
+
if (!allStepIds.has(ref)) {
|
|
32237
|
+
issue2(["phases", phase.id, "steps", step.id], `edge \u2192 unknown step "${ref}"`);
|
|
32608
32238
|
}
|
|
32609
32239
|
}
|
|
32610
|
-
const
|
|
32611
|
-
|
|
32612
|
-
|
|
32613
|
-
|
|
32614
|
-
|
|
32615
|
-
|
|
32616
|
-
|
|
32240
|
+
const validateByMode = (byMode, path15, label) => {
|
|
32241
|
+
for (const mode of Object.keys(byMode)) {
|
|
32242
|
+
if (!declaredModeSet.has(mode)) {
|
|
32243
|
+
issue2(path15, `${label} lists mode "${mode}" not declared in flow.entries`);
|
|
32244
|
+
}
|
|
32245
|
+
}
|
|
32246
|
+
const missingModes = declaredModes.filter((m) => !(m in byMode));
|
|
32247
|
+
if (missingModes.length > 0) {
|
|
32248
|
+
issue2(path15, `${label} byMode is missing entries for mode(s): ${missingModes.join(", ")}`);
|
|
32249
|
+
}
|
|
32250
|
+
};
|
|
32251
|
+
if ((step.kind === "action" || step.kind === "reference" || step.kind === "parallel") && typeof step.next === "object" && step.next !== null) {
|
|
32252
|
+
validateByMode(step.next.byMode, ["phases", phase.id, "steps", step.id, "next", "byMode"], `step "${step.id}" next`);
|
|
32253
|
+
}
|
|
32254
|
+
if (step.kind === "branch") {
|
|
32255
|
+
for (const [i, branch] of step.branches.entries()) {
|
|
32256
|
+
if (typeof branch.next === "object" && branch.next !== null) {
|
|
32257
|
+
const branchLabelText = branch.option !== void 0 ? `option "${branch.option.letter}"` : branch.when ?? `branch[${i}]`;
|
|
32258
|
+
validateByMode(branch.next.byMode, [
|
|
32259
|
+
"phases",
|
|
32260
|
+
phase.id,
|
|
32261
|
+
"steps",
|
|
32262
|
+
step.id,
|
|
32263
|
+
"branches",
|
|
32264
|
+
i,
|
|
32265
|
+
"next",
|
|
32266
|
+
"byMode"
|
|
32267
|
+
], `step "${step.id}" branch ${branchLabelText}`);
|
|
32268
|
+
}
|
|
32269
|
+
}
|
|
32617
32270
|
}
|
|
32618
|
-
};
|
|
32619
|
-
if ((step.kind === "action" || step.kind === "reference" || step.kind === "parallel") && typeof step.next === "object" && step.next !== null) {
|
|
32620
|
-
validateByMode(step.next.byMode, ["phases", phase.id, "steps", step.id, "next", "byMode"], `step "${step.id}" next`);
|
|
32621
32271
|
}
|
|
32622
|
-
|
|
32623
|
-
|
|
32624
|
-
|
|
32625
|
-
|
|
32626
|
-
|
|
32627
|
-
|
|
32628
|
-
|
|
32629
|
-
|
|
32630
|
-
|
|
32631
|
-
|
|
32632
|
-
|
|
32633
|
-
|
|
32634
|
-
|
|
32635
|
-
], `step "${step.id}" branch ${branchLabelText}`);
|
|
32272
|
+
}
|
|
32273
|
+
for (const phase of flow.phases) {
|
|
32274
|
+
const preambleCount = phase.steps.filter((s2) => s2.preamble === true).length;
|
|
32275
|
+
if (preambleCount > 1) {
|
|
32276
|
+
issue2(["phases", phase.id, "steps"], `phase "${phase.id}" has ${preambleCount} preamble steps; only one is allowed per phase`);
|
|
32277
|
+
}
|
|
32278
|
+
}
|
|
32279
|
+
const appendixIds = new Set(flow.appendices.map((a) => a.id));
|
|
32280
|
+
for (const phase of flow.phases) {
|
|
32281
|
+
for (const step of phase.steps) {
|
|
32282
|
+
for (const r of step.refs ?? []) {
|
|
32283
|
+
if (!appendixIds.has(r)) {
|
|
32284
|
+
issue2(["phases", phase.id, "steps", step.id, "refs"], `unknown appendix "${r}"`);
|
|
32636
32285
|
}
|
|
32637
32286
|
}
|
|
32638
32287
|
}
|
|
32639
32288
|
}
|
|
32640
|
-
|
|
32641
|
-
|
|
32642
|
-
|
|
32643
|
-
|
|
32644
|
-
|
|
32645
|
-
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
|
|
32649
|
-
}
|
|
32650
|
-
}
|
|
32651
|
-
const appendixIds = new Set(flow.appendices.map((a) => a.id));
|
|
32652
|
-
for (const phase of flow.phases) {
|
|
32653
|
-
for (const step of phase.steps) {
|
|
32654
|
-
const refs = step.refs ?? [];
|
|
32655
|
-
for (const r of refs) {
|
|
32656
|
-
if (!appendixIds.has(r)) {
|
|
32657
|
-
ctx.addIssue({
|
|
32658
|
-
code: "custom",
|
|
32659
|
-
path: ["phases", phase.id, "steps", step.id, "refs"],
|
|
32660
|
-
message: `unknown appendix "${r}"`
|
|
32661
|
-
});
|
|
32289
|
+
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32290
|
+
for (const target of targetNames) {
|
|
32291
|
+
const resolved = resolvePerTarget(entry, target);
|
|
32292
|
+
if (resolved === void 0) {
|
|
32293
|
+
issue2(["entries", mode], `entry for mode "${mode}" has no value for target "${target}" (and no default)`);
|
|
32294
|
+
continue;
|
|
32295
|
+
}
|
|
32296
|
+
if (!allStepIds.has(resolved)) {
|
|
32297
|
+
issue2(["entries", mode], `entry "${mode}" \u2192 "${target}" \u2192 unknown step "${resolved}"`);
|
|
32662
32298
|
}
|
|
32663
32299
|
}
|
|
32664
32300
|
}
|
|
32665
|
-
|
|
32666
|
-
const targetNames = ["claude", "cursor", "codex"];
|
|
32667
|
-
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32301
|
+
const reachableUnion = /* @__PURE__ */ new Set();
|
|
32668
32302
|
for (const target of targetNames) {
|
|
32669
|
-
const
|
|
32670
|
-
|
|
32671
|
-
ctx.addIssue({
|
|
32672
|
-
code: "custom",
|
|
32673
|
-
path: ["entries", mode],
|
|
32674
|
-
message: `entry for mode "${mode}" has no value for target "${target}" (and no default)`
|
|
32675
|
-
});
|
|
32676
|
-
continue;
|
|
32303
|
+
for (const id of computeReachableSteps(flow, target)) {
|
|
32304
|
+
reachableUnion.add(id);
|
|
32677
32305
|
}
|
|
32678
|
-
|
|
32679
|
-
|
|
32680
|
-
|
|
32681
|
-
|
|
32682
|
-
message: `entry "${mode}" \u2192 "${target}" \u2192 unknown step "${resolved}"`
|
|
32683
|
-
});
|
|
32306
|
+
}
|
|
32307
|
+
for (const id of allStepIds) {
|
|
32308
|
+
if (!reachableUnion.has(id)) {
|
|
32309
|
+
issue2(["phases"], `unreachable step "${id}" in any (mode, target) combination`);
|
|
32684
32310
|
}
|
|
32685
32311
|
}
|
|
32686
|
-
|
|
32687
|
-
|
|
32688
|
-
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32312
|
+
const inlinePhaseSet = new Set(flow.compile.inlinePhases);
|
|
32313
|
+
const phaseOf = (ref) => ref.split("/")[0];
|
|
32689
32314
|
for (const target of targetNames) {
|
|
32690
|
-
|
|
32691
|
-
if (start === void 0) {
|
|
32315
|
+
if (resolvePerTarget(flow.compile.mode, target) !== "split-chain") {
|
|
32692
32316
|
continue;
|
|
32693
32317
|
}
|
|
32694
|
-
const
|
|
32695
|
-
|
|
32696
|
-
|
|
32697
|
-
const id = queue.shift();
|
|
32698
|
-
if (id === void 0 || seen.has(id)) {
|
|
32318
|
+
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32319
|
+
const resolved = resolvePerTarget(entry, target);
|
|
32320
|
+
if (resolved === void 0 || !allStepIds.has(resolved)) {
|
|
32699
32321
|
continue;
|
|
32700
32322
|
}
|
|
32701
|
-
|
|
32702
|
-
|
|
32703
|
-
const [phaseId, stepId] = id.split("/");
|
|
32704
|
-
const step = flow.phases.find((p9) => p9.id === phaseId)?.steps.find((s2) => s2.id === stepId);
|
|
32705
|
-
if (step === void 0) {
|
|
32323
|
+
const entryPhase = phaseOf(resolved);
|
|
32324
|
+
if (inlinePhaseSet.has(entryPhase)) {
|
|
32706
32325
|
continue;
|
|
32707
32326
|
}
|
|
32708
|
-
|
|
32709
|
-
|
|
32710
|
-
|
|
32711
|
-
}
|
|
32327
|
+
const firstStep = flow.phases.find((p9) => p9.id === entryPhase)?.steps[0];
|
|
32328
|
+
if (firstStep !== void 0 && resolved !== `${entryPhase}/${firstStep.id}`) {
|
|
32329
|
+
issue2(["entries", mode], `split-chain: entry "${mode}" \u2192 "${target}" points mid-phase at "${resolved}"; a sub-skill starts at its first step ("${entryPhase}/${firstStep.id}"). Reorder the phase or inline it.`);
|
|
32712
32330
|
}
|
|
32713
32331
|
}
|
|
32714
|
-
|
|
32715
|
-
|
|
32716
|
-
|
|
32717
|
-
if (reachableUnion.has(id)) {
|
|
32718
|
-
continue;
|
|
32719
|
-
}
|
|
32720
|
-
ctx.addIssue({
|
|
32721
|
-
code: "custom",
|
|
32722
|
-
path: ["phases"],
|
|
32723
|
-
message: `unreachable step "${id}" in any (mode, target) combination`
|
|
32724
|
-
});
|
|
32725
|
-
}
|
|
32726
|
-
const inlinePhaseSet = new Set(flow.compile.inlinePhases);
|
|
32727
|
-
const phaseOf = (ref) => ref.split("/")[0];
|
|
32728
|
-
for (const target of targetNames) {
|
|
32729
|
-
if (resolvePerTarget(flow.compile.mode, target) !== "split-chain") {
|
|
32730
|
-
continue;
|
|
32731
|
-
}
|
|
32732
|
-
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32733
|
-
const resolved = resolvePerTarget(entry, target);
|
|
32734
|
-
if (resolved === void 0 || !allStepIds.has(resolved)) {
|
|
32735
|
-
continue;
|
|
32736
|
-
}
|
|
32737
|
-
const entryPhase = phaseOf(resolved);
|
|
32738
|
-
if (inlinePhaseSet.has(entryPhase)) {
|
|
32739
|
-
continue;
|
|
32740
|
-
}
|
|
32741
|
-
const phase = flow.phases.find((p9) => p9.id === entryPhase);
|
|
32742
|
-
const firstStep = phase?.steps[0];
|
|
32743
|
-
if (firstStep !== void 0 && resolved !== `${entryPhase}/${firstStep.id}`) {
|
|
32744
|
-
ctx.addIssue({
|
|
32745
|
-
code: "custom",
|
|
32746
|
-
path: ["entries", mode],
|
|
32747
|
-
message: `split-chain: entry "${mode}" \u2192 "${target}" points mid-phase at "${resolved}"; a sub-skill starts at its first step ("${entryPhase}/${firstStep.id}"). Reorder the phase or inline it.`
|
|
32748
|
-
});
|
|
32749
|
-
}
|
|
32750
|
-
}
|
|
32751
|
-
const reachable = computeReachableSteps(flow, target);
|
|
32752
|
-
for (const phase of flow.phases) {
|
|
32753
|
-
if (inlinePhaseSet.has(phase.id)) {
|
|
32754
|
-
continue;
|
|
32755
|
-
}
|
|
32756
|
-
for (const step of phase.steps) {
|
|
32757
|
-
if (!reachable.has(`${phase.id}/${step.id}`)) {
|
|
32332
|
+
const reachable = computeReachableSteps(flow, target);
|
|
32333
|
+
for (const phase of flow.phases) {
|
|
32334
|
+
if (inlinePhaseSet.has(phase.id)) {
|
|
32758
32335
|
continue;
|
|
32759
32336
|
}
|
|
32760
|
-
for (const
|
|
32761
|
-
if (
|
|
32762
|
-
|
|
32763
|
-
|
|
32764
|
-
|
|
32765
|
-
|
|
32766
|
-
|
|
32337
|
+
for (const step of phase.steps) {
|
|
32338
|
+
if (!reachable.has(`${phase.id}/${step.id}`)) {
|
|
32339
|
+
continue;
|
|
32340
|
+
}
|
|
32341
|
+
for (const ref of refsFromStep(step)) {
|
|
32342
|
+
if (inlinePhaseSet.has(phaseOf(ref))) {
|
|
32343
|
+
issue2(["phases", phase.id, "steps", step.id], `split-chain: step "${phase.id}/${step.id}" routes to "${ref}" in inline phase "${phaseOf(ref)}" (target "${target}"). Sub-skills may not re-enter the orchestrator; make the shared work its own phase.`);
|
|
32344
|
+
}
|
|
32767
32345
|
}
|
|
32768
32346
|
}
|
|
32769
32347
|
}
|
|
32770
32348
|
}
|
|
32771
|
-
|
|
32772
|
-
|
|
32773
|
-
|
|
32774
|
-
for (const
|
|
32775
|
-
|
|
32776
|
-
|
|
32777
|
-
|
|
32778
|
-
for (const toolId of step.toolCalls) {
|
|
32779
|
-
if (!toolIds.has(toolId)) {
|
|
32780
|
-
ctx.addIssue({
|
|
32781
|
-
code: "custom",
|
|
32782
|
-
path: ["phases", phase.id, "steps", step.id, "toolCalls"],
|
|
32783
|
-
message: `step "${step.id}" calls tool "${toolId}" not declared in flow.tools`
|
|
32784
|
-
});
|
|
32785
|
-
}
|
|
32786
|
-
}
|
|
32787
|
-
}
|
|
32788
|
-
}
|
|
32789
|
-
const commandIds = new Set(Object.keys(flow.commands));
|
|
32790
|
-
for (const phase of flow.phases) {
|
|
32791
|
-
for (const step of phase.steps) {
|
|
32792
|
-
if (step.commandCalls === void 0) {
|
|
32793
|
-
continue;
|
|
32794
|
-
}
|
|
32795
|
-
for (const cmdId of step.commandCalls) {
|
|
32796
|
-
if (!commandIds.has(cmdId)) {
|
|
32797
|
-
ctx.addIssue({
|
|
32798
|
-
code: "custom",
|
|
32799
|
-
path: ["phases", phase.id, "steps", step.id, "commandCalls"],
|
|
32800
|
-
message: `step "${step.id}" calls command "${cmdId}" not declared in flow.commands`
|
|
32801
|
-
});
|
|
32349
|
+
const toolIds = new Set(Object.keys(flow.tools));
|
|
32350
|
+
const commandIds = new Set(Object.keys(flow.commands));
|
|
32351
|
+
const knownTargets = new Set(targetNames);
|
|
32352
|
+
for (const [toolId, tool] of Object.entries(flow.tools)) {
|
|
32353
|
+
for (const t of tool.targets ?? []) {
|
|
32354
|
+
if (!knownTargets.has(t)) {
|
|
32355
|
+
issue2(["tools", toolId, "targets"], `tool "${toolId}" lists unknown target "${t}"`);
|
|
32802
32356
|
}
|
|
32803
32357
|
}
|
|
32804
32358
|
}
|
|
32805
|
-
}
|
|
32806
|
-
const COMMAND_PLACEHOLDER_RE = /\{\{command:([a-zA-Z][a-zA-Z0-9_-]*)\}\}/g;
|
|
32807
|
-
const scanForCommandRefs = (value) => {
|
|
32808
|
-
const refs = [];
|
|
32809
|
-
const scan = (text2) => {
|
|
32810
|
-
if (!text2) {
|
|
32811
|
-
return;
|
|
32812
|
-
}
|
|
32813
|
-
for (const match of text2.matchAll(COMMAND_PLACEHOLDER_RE)) {
|
|
32814
|
-
refs.push(match[1]);
|
|
32815
|
-
}
|
|
32816
|
-
};
|
|
32817
|
-
if (value === void 0) {
|
|
32818
|
-
return refs;
|
|
32819
|
-
}
|
|
32820
|
-
if (typeof value === "string") {
|
|
32821
|
-
scan(value);
|
|
32822
|
-
return refs;
|
|
32823
|
-
}
|
|
32824
|
-
scan(value.default);
|
|
32825
|
-
scan(value.claude);
|
|
32826
|
-
scan(value.cursor);
|
|
32827
|
-
scan(value.codex);
|
|
32828
|
-
return refs;
|
|
32829
|
-
};
|
|
32830
|
-
if (commandIds.size > 0) {
|
|
32831
|
-
const allCommandRefs = [];
|
|
32832
|
-
for (const ref of scanForCommandRefs(flow.intro)) {
|
|
32833
|
-
allCommandRefs.push({ ref, location: "flow.intro" });
|
|
32834
|
-
}
|
|
32835
|
-
for (const ref of scanForCommandRefs(flow.emitTemplate)) {
|
|
32836
|
-
allCommandRefs.push({ ref, location: "flow.emitTemplate" });
|
|
32837
|
-
}
|
|
32838
32359
|
for (const phase of flow.phases) {
|
|
32839
|
-
for (const ref of scanForCommandRefs(phase.intro)) {
|
|
32840
|
-
allCommandRefs.push({ ref, location: `phase "${phase.id}" intro` });
|
|
32841
|
-
}
|
|
32842
32360
|
for (const step of phase.steps) {
|
|
32843
|
-
for (const
|
|
32844
|
-
|
|
32845
|
-
|
|
32846
|
-
|
|
32847
|
-
|
|
32361
|
+
for (const toolId of step.toolCalls ?? []) {
|
|
32362
|
+
if (!toolIds.has(toolId)) {
|
|
32363
|
+
issue2(["phases", phase.id, "steps", step.id, "toolCalls"], `step "${step.id}" calls tool "${toolId}" not declared in flow.tools`);
|
|
32364
|
+
}
|
|
32365
|
+
}
|
|
32366
|
+
for (const cmdId of step.commandCalls ?? []) {
|
|
32367
|
+
if (!commandIds.has(cmdId)) {
|
|
32368
|
+
issue2(["phases", phase.id, "steps", step.id, "commandCalls"], `step "${step.id}" calls command "${cmdId}" not declared in flow.commands`);
|
|
32369
|
+
}
|
|
32848
32370
|
}
|
|
32849
32371
|
}
|
|
32850
32372
|
}
|
|
32851
|
-
for (const
|
|
32852
|
-
for (const
|
|
32853
|
-
|
|
32854
|
-
|
|
32855
|
-
|
|
32856
|
-
});
|
|
32373
|
+
for (const { location, text: text2 } of flowTexts(flow)) {
|
|
32374
|
+
for (const match of text2.matchAll(COMMAND_PLACEHOLDER_RE)) {
|
|
32375
|
+
if (!commandIds.has(match[1])) {
|
|
32376
|
+
issue2(["commands"], `{{command:${match[1]}}} in ${location} not declared in flow.commands`);
|
|
32377
|
+
}
|
|
32857
32378
|
}
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
code: "custom",
|
|
32863
|
-
path: ["commands"],
|
|
32864
|
-
message: `{{command:${ref}}} in ${location} not declared in flow.commands`
|
|
32865
|
-
});
|
|
32379
|
+
for (const match of text2.matchAll(TOOL_PLACEHOLDER_RE)) {
|
|
32380
|
+
if (!toolIds.has(match[1])) {
|
|
32381
|
+
issue2(["tools"], `{{tool:${match[1]}}} in ${location} not declared in flow.tools`);
|
|
32382
|
+
}
|
|
32866
32383
|
}
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
|
|
32870
|
-
|
|
32871
|
-
const scan = (text2) => {
|
|
32872
|
-
if (!text2) {
|
|
32873
|
-
return;
|
|
32384
|
+
for (const match of text2.matchAll(TABLE_PLACEHOLDER_RE)) {
|
|
32385
|
+
if (flow.tables[match[2]] === void 0) {
|
|
32386
|
+
issue2(["tables"], `{{${match[1]}:${match[2]}:\u2026}} in ${location} names an undeclared table`);
|
|
32387
|
+
}
|
|
32874
32388
|
}
|
|
32875
32389
|
for (const match of text2.matchAll(MODE_SECTION_RE)) {
|
|
32876
|
-
|
|
32877
|
-
|
|
32878
|
-
ctx.addIssue({
|
|
32879
|
-
code: "custom",
|
|
32880
|
-
path: ["phases"],
|
|
32881
|
-
message: `{{${match[1]}mode:${mode}}} in ${location} names a mode that does not exist. Declared modes: ${[...modeNames].sort().join(", ")}.`
|
|
32882
|
-
});
|
|
32390
|
+
if (!declaredModeSet.has(match[2])) {
|
|
32391
|
+
issue2(["phases"], `{{${match[1]}mode:${match[2]}}} in ${location} names a mode that does not exist. Declared modes: ${[...declaredModeSet].sort().join(", ")}.`);
|
|
32883
32392
|
}
|
|
32884
32393
|
}
|
|
32885
32394
|
for (const match of text2.matchAll(MODE_SECTION_CLOSE_RE)) {
|
|
32886
|
-
|
|
32887
|
-
|
|
32888
|
-
ctx.addIssue({
|
|
32889
|
-
code: "custom",
|
|
32890
|
-
path: ["phases"],
|
|
32891
|
-
message: `{{/mode:${mode}}} in ${location} closes a mode that does not exist. Declared modes: ${[...modeNames].sort().join(", ")}.`
|
|
32892
|
-
});
|
|
32395
|
+
if (!declaredModeSet.has(match[1])) {
|
|
32396
|
+
issue2(["phases"], `{{/mode:${match[1]}}} in ${location} closes a mode that does not exist. Declared modes: ${[...declaredModeSet].sort().join(", ")}.`);
|
|
32893
32397
|
}
|
|
32894
32398
|
}
|
|
32895
|
-
};
|
|
32896
|
-
if (value === void 0) {
|
|
32897
|
-
return;
|
|
32898
32399
|
}
|
|
32899
|
-
|
|
32900
|
-
|
|
32901
|
-
|
|
32902
|
-
|
|
32903
|
-
scan(value.default);
|
|
32904
|
-
scan(value.claude);
|
|
32905
|
-
scan(value.cursor);
|
|
32906
|
-
scan(value.codex);
|
|
32907
|
-
};
|
|
32908
|
-
scanForModeSections(flow.intro, "flow.intro");
|
|
32909
|
-
for (const phase of flow.phases) {
|
|
32910
|
-
scanForModeSections(phase.intro, `phase "${phase.id}" intro`);
|
|
32911
|
-
for (const step of phase.steps) {
|
|
32912
|
-
scanForModeSections(step.body, `step "${phase.id}/${step.id}"`);
|
|
32400
|
+
for (const name of Object.keys(flow.variables)) {
|
|
32401
|
+
if (reservedTokenNames.has(name)) {
|
|
32402
|
+
issue2(["variables", name], `variable "${name}" collides with the target token of the same name`);
|
|
32403
|
+
}
|
|
32913
32404
|
}
|
|
32405
|
+
});
|
|
32406
|
+
}
|
|
32407
|
+
function refsFromNext(next) {
|
|
32408
|
+
if (next === null) {
|
|
32409
|
+
return [];
|
|
32914
32410
|
}
|
|
32915
|
-
|
|
32916
|
-
|
|
32917
|
-
}
|
|
32918
|
-
const reservedNames = new Set(RESERVED_TOKEN_NAMES);
|
|
32919
|
-
for (const name of Object.keys(flow.variables)) {
|
|
32920
|
-
if (reservedNames.has(name)) {
|
|
32921
|
-
ctx.addIssue({
|
|
32922
|
-
code: "custom",
|
|
32923
|
-
path: ["variables", name],
|
|
32924
|
-
message: `variable "${name}" collides with the target token of the same name`
|
|
32925
|
-
});
|
|
32926
|
-
}
|
|
32411
|
+
if (typeof next === "string") {
|
|
32412
|
+
return [next];
|
|
32927
32413
|
}
|
|
32928
|
-
|
|
32929
|
-
|
|
32930
|
-
function
|
|
32414
|
+
return Object.values(next.byMode).filter((v) => typeof v === "string");
|
|
32415
|
+
}
|
|
32416
|
+
function refsFromStep(s2) {
|
|
32417
|
+
switch (s2.kind) {
|
|
32418
|
+
case "action":
|
|
32419
|
+
case "reference":
|
|
32420
|
+
case "parallel":
|
|
32421
|
+
return refsFromNext(s2.next);
|
|
32422
|
+
case "branch":
|
|
32423
|
+
return s2.branches.flatMap((b) => refsFromNext(b.next));
|
|
32424
|
+
case "loop":
|
|
32425
|
+
return [s2.backTo, s2.onExit];
|
|
32426
|
+
}
|
|
32427
|
+
}
|
|
32428
|
+
function variants(value) {
|
|
32931
32429
|
if (value === void 0) {
|
|
32932
|
-
return;
|
|
32430
|
+
return [];
|
|
32933
32431
|
}
|
|
32934
|
-
|
|
32935
|
-
|
|
32936
|
-
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32432
|
+
if (typeof value === "string") {
|
|
32433
|
+
return [value];
|
|
32434
|
+
}
|
|
32435
|
+
return Object.values(value).filter((v) => v !== void 0);
|
|
32436
|
+
}
|
|
32437
|
+
function flowTexts(flow) {
|
|
32438
|
+
const out = [];
|
|
32439
|
+
const push = (location, value, phaseId) => {
|
|
32440
|
+
for (const text2 of variants(value)) {
|
|
32441
|
+
out.push({ location, text: text2, phaseId });
|
|
32940
32442
|
}
|
|
32941
32443
|
};
|
|
32942
|
-
|
|
32943
|
-
|
|
32944
|
-
|
|
32444
|
+
push("flow.intro", flow.intro);
|
|
32445
|
+
push("flow.emitTemplate", flow.emitTemplate);
|
|
32446
|
+
for (const inv of flow.invariants) {
|
|
32447
|
+
push("flow.invariants", inv);
|
|
32448
|
+
}
|
|
32449
|
+
for (const [name, value] of Object.entries(flow.variables)) {
|
|
32450
|
+
push(`variable "${name}"`, value);
|
|
32451
|
+
}
|
|
32452
|
+
for (const phase of flow.phases) {
|
|
32453
|
+
push(`phase "${phase.id}" intro`, phase.intro, phase.id);
|
|
32454
|
+
push(`phase "${phase.id}" outro`, phase.outro, phase.id);
|
|
32455
|
+
for (const step of phase.steps) {
|
|
32456
|
+
const where = `step "${phase.id}/${step.id}"`;
|
|
32457
|
+
push(where, step.body, phase.id);
|
|
32458
|
+
if (step.kind === "branch") {
|
|
32459
|
+
for (const branch of step.branches) {
|
|
32460
|
+
push(where, branch.description, phase.id);
|
|
32461
|
+
}
|
|
32462
|
+
}
|
|
32463
|
+
if (step.kind === "parallel") {
|
|
32464
|
+
for (const branch of step.branches) {
|
|
32465
|
+
push(where, branch.body, phase.id);
|
|
32466
|
+
}
|
|
32467
|
+
}
|
|
32468
|
+
}
|
|
32469
|
+
}
|
|
32470
|
+
for (const appendix of flow.appendices) {
|
|
32471
|
+
push(`appendix "${appendix.id}"`, appendix.body);
|
|
32945
32472
|
}
|
|
32946
|
-
|
|
32947
|
-
scan(value.claude);
|
|
32948
|
-
scan(value.cursor);
|
|
32949
|
-
scan(value.codex);
|
|
32473
|
+
return out;
|
|
32950
32474
|
}
|
|
32951
32475
|
function collectCalledToolIds(flow) {
|
|
32952
32476
|
const called = /* @__PURE__ */ new Set();
|
|
32953
|
-
harvestToolRefs(flow.intro, called);
|
|
32954
32477
|
for (const phase of flow.phases) {
|
|
32955
|
-
harvestToolRefs(phase.intro, called);
|
|
32956
32478
|
for (const step of phase.steps) {
|
|
32957
32479
|
for (const id of step.toolCalls ?? []) {
|
|
32958
32480
|
called.add(id);
|
|
32959
32481
|
}
|
|
32960
|
-
|
|
32961
|
-
|
|
32962
|
-
|
|
32963
|
-
|
|
32964
|
-
|
|
32965
|
-
}
|
|
32482
|
+
}
|
|
32483
|
+
}
|
|
32484
|
+
for (const { text: text2 } of flowTexts(flow)) {
|
|
32485
|
+
for (const match of text2.matchAll(TOOL_PLACEHOLDER_RE)) {
|
|
32486
|
+
called.add(match[1]);
|
|
32966
32487
|
}
|
|
32967
32488
|
}
|
|
32968
32489
|
return Object.keys(flow.tools).filter((id) => called.has(id));
|
|
@@ -33036,10 +32557,82 @@ function branchLabel(branch) {
|
|
|
33036
32557
|
}
|
|
33037
32558
|
return "(unlabeled branch)";
|
|
33038
32559
|
}
|
|
32560
|
+
function targetableFields(flow) {
|
|
32561
|
+
const out = [];
|
|
32562
|
+
const push = (path15, value) => {
|
|
32563
|
+
if (value !== void 0) {
|
|
32564
|
+
out.push({ path: path15, value });
|
|
32565
|
+
}
|
|
32566
|
+
};
|
|
32567
|
+
push(["title"], flow.title);
|
|
32568
|
+
push(["intro"], flow.intro);
|
|
32569
|
+
push(["emitTemplate"], flow.emitTemplate);
|
|
32570
|
+
push(["frontmatter", "description"], flow.frontmatter.description);
|
|
32571
|
+
const hint = flow.frontmatter.argumentHint;
|
|
32572
|
+
if (typeof hint === "object" && hint !== null && "deriveFromModes" in hint) {
|
|
32573
|
+
push(["frontmatter", "argumentHint", "suffix"], hint.suffix);
|
|
32574
|
+
} else {
|
|
32575
|
+
push(["frontmatter", "argumentHint"], hint);
|
|
32576
|
+
}
|
|
32577
|
+
push(["compile", "mode"], flow.compile.mode);
|
|
32578
|
+
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32579
|
+
push(["entries", mode], entry);
|
|
32580
|
+
}
|
|
32581
|
+
for (const [mode, value] of Object.entries(flow.modeHints)) {
|
|
32582
|
+
push(["modeHints", mode], value);
|
|
32583
|
+
}
|
|
32584
|
+
for (const [name, value] of Object.entries(flow.variables)) {
|
|
32585
|
+
push(["variables", name], value);
|
|
32586
|
+
}
|
|
32587
|
+
for (const [id, tool] of Object.entries(flow.tools)) {
|
|
32588
|
+
push(["tools", id, "name"], tool.name);
|
|
32589
|
+
}
|
|
32590
|
+
for (const phase of flow.phases) {
|
|
32591
|
+
push(["phases", phase.id, "title"], phase.title);
|
|
32592
|
+
push(["phases", phase.id, "intro"], phase.intro);
|
|
32593
|
+
push(["phases", phase.id, "outro"], phase.outro);
|
|
32594
|
+
for (const step of phase.steps) {
|
|
32595
|
+
const base = ["phases", phase.id, "steps", step.id];
|
|
32596
|
+
push([...base, "title"], step.title);
|
|
32597
|
+
push([...base, "refName"], step.refName);
|
|
32598
|
+
push([...base, "body"], step.body);
|
|
32599
|
+
}
|
|
32600
|
+
}
|
|
32601
|
+
for (const appendix of flow.appendices) {
|
|
32602
|
+
push(["appendices", appendix.id, "title"], appendix.title);
|
|
32603
|
+
push(["appendices", appendix.id, "body"], appendix.body);
|
|
32604
|
+
}
|
|
32605
|
+
return out;
|
|
32606
|
+
}
|
|
33039
32607
|
|
|
33040
|
-
// ../
|
|
33041
|
-
|
|
33042
|
-
|
|
32608
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/mermaid.js
|
|
32609
|
+
function diagramValue(value, target) {
|
|
32610
|
+
const resolved = resolvePerTarget(value, target ?? "default");
|
|
32611
|
+
if (resolved !== void 0 || typeof value !== "object" || value === null) {
|
|
32612
|
+
return resolved;
|
|
32613
|
+
}
|
|
32614
|
+
return Object.values(value).find((v) => v !== void 0);
|
|
32615
|
+
}
|
|
32616
|
+
function diagramString(value, target) {
|
|
32617
|
+
return diagramValue(value, target) ?? "";
|
|
32618
|
+
}
|
|
32619
|
+
function reachabilityTarget(flow, target) {
|
|
32620
|
+
if (target !== void 0) {
|
|
32621
|
+
return target;
|
|
32622
|
+
}
|
|
32623
|
+
for (const entry of Object.values(flow.entries)) {
|
|
32624
|
+
if (typeof entry === "object" && entry !== null && entry.default === void 0) {
|
|
32625
|
+
const first = Object.keys(entry)[0];
|
|
32626
|
+
if (first !== void 0) {
|
|
32627
|
+
return first;
|
|
32628
|
+
}
|
|
32629
|
+
}
|
|
32630
|
+
}
|
|
32631
|
+
return "default";
|
|
32632
|
+
}
|
|
32633
|
+
function renderMermaid(flow, options = {}) {
|
|
32634
|
+
const { mode, target } = typeof options === "string" ? { mode: options, target: void 0 } : options;
|
|
32635
|
+
const graphTarget = reachabilityTarget(flow, target);
|
|
33043
32636
|
const lines = ["flowchart TD"];
|
|
33044
32637
|
const stepById = /* @__PURE__ */ new Map();
|
|
33045
32638
|
for (const phase of flow.phases) {
|
|
@@ -33050,19 +32643,19 @@ function renderMermaid(flow, mode) {
|
|
|
33050
32643
|
const nodeId = (key) => key.replace(/[^a-zA-Z0-9]/g, "_");
|
|
33051
32644
|
const allModes = Object.keys(flow.entries);
|
|
33052
32645
|
const activeModes = mode !== void 0 ? [mode] : allModes;
|
|
33053
|
-
const reachable = mode !== void 0 ? new Set([...computeModesPerStep(flow,
|
|
32646
|
+
const reachable = mode !== void 0 ? new Set([...computeModesPerStep(flow, graphTarget).entries()].filter(([, modes]) => modes.has(mode)).map(([key]) => key)) : computeReachableSteps(flow, graphTarget);
|
|
33054
32647
|
for (const phase of flow.phases) {
|
|
33055
32648
|
const phaseSteps = phase.steps.filter((s2) => reachable.has(`${phase.id}/${s2.id}`));
|
|
33056
32649
|
if (phaseSteps.length === 0) {
|
|
33057
32650
|
continue;
|
|
33058
32651
|
}
|
|
33059
|
-
const phaseTitle = escapeMermaidLabel(
|
|
32652
|
+
const phaseTitle = escapeMermaidLabel(diagramString(phase.title, target));
|
|
33060
32653
|
lines.push(` subgraph ${nodeId(phase.id)}["${phaseTitle}"]`);
|
|
33061
32654
|
let counter = 1;
|
|
33062
32655
|
for (const step of phaseSteps) {
|
|
33063
32656
|
const stepKey = `${phase.id}/${step.id}`;
|
|
33064
32657
|
const id = nodeId(stepKey);
|
|
33065
|
-
const baseLabel = escapeMermaidLabel(
|
|
32658
|
+
const baseLabel = escapeMermaidLabel(diagramString(step.title, target));
|
|
33066
32659
|
const num = step.preamble === true ? 0 : counter;
|
|
33067
32660
|
if (step.preamble !== true) {
|
|
33068
32661
|
counter += 1;
|
|
@@ -33093,18 +32686,18 @@ function renderMermaid(flow, mode) {
|
|
|
33093
32686
|
}
|
|
33094
32687
|
} else {
|
|
33095
32688
|
for (const m of activeModes) {
|
|
33096
|
-
const
|
|
33097
|
-
if (
|
|
32689
|
+
const target2 = step.next.byMode[m] ?? null;
|
|
32690
|
+
if (target2 === null || !isReachable(target2)) {
|
|
33098
32691
|
continue;
|
|
33099
32692
|
}
|
|
33100
32693
|
if (mode !== void 0) {
|
|
33101
|
-
const edge = `${src}->${
|
|
32694
|
+
const edge = `${src}->${target2}`;
|
|
33102
32695
|
if (!seenLinearEdges.has(edge)) {
|
|
33103
32696
|
seenLinearEdges.add(edge);
|
|
33104
|
-
lines.push(` ${nodeId(src)} --> ${nodeId(
|
|
32697
|
+
lines.push(` ${nodeId(src)} --> ${nodeId(target2)}`);
|
|
33105
32698
|
}
|
|
33106
32699
|
} else {
|
|
33107
|
-
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(m)}"| ${nodeId(
|
|
32700
|
+
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(m)}"| ${nodeId(target2)}`);
|
|
33108
32701
|
}
|
|
33109
32702
|
}
|
|
33110
32703
|
}
|
|
@@ -33116,20 +32709,20 @@ function renderMermaid(flow, mode) {
|
|
|
33116
32709
|
if (branch.next !== null && !isReachable(branch.next)) {
|
|
33117
32710
|
continue;
|
|
33118
32711
|
}
|
|
33119
|
-
const
|
|
33120
|
-
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(labelWithRec)}"| ${
|
|
32712
|
+
const target2 = branch.next === null ? "flow_end" : nodeId(branch.next);
|
|
32713
|
+
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(labelWithRec)}"| ${target2}`);
|
|
33121
32714
|
} else {
|
|
33122
32715
|
for (const m of activeModes) {
|
|
33123
32716
|
const dest = branch.next.byMode[m] ?? null;
|
|
33124
32717
|
if (dest !== null && !isReachable(dest)) {
|
|
33125
32718
|
continue;
|
|
33126
32719
|
}
|
|
33127
|
-
const
|
|
32720
|
+
const target2 = dest === null ? "flow_end" : nodeId(dest);
|
|
33128
32721
|
if (mode !== void 0) {
|
|
33129
|
-
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(labelWithRec)}"| ${
|
|
32722
|
+
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(labelWithRec)}"| ${target2}`);
|
|
33130
32723
|
} else {
|
|
33131
32724
|
const modeLabel = `${labelWithRec} [${m}]`;
|
|
33132
|
-
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(modeLabel)}"| ${
|
|
32725
|
+
lines.push(` ${nodeId(src)} -->|"${escapeMermaidLabel(modeLabel)}"| ${target2}`);
|
|
33133
32726
|
}
|
|
33134
32727
|
}
|
|
33135
32728
|
}
|
|
@@ -33154,7 +32747,7 @@ function renderMermaid(flow, mode) {
|
|
|
33154
32747
|
if (entry === void 0) {
|
|
33155
32748
|
continue;
|
|
33156
32749
|
}
|
|
33157
|
-
const resolved =
|
|
32750
|
+
const resolved = diagramValue(entry, target);
|
|
33158
32751
|
if (resolved === void 0) {
|
|
33159
32752
|
continue;
|
|
33160
32753
|
}
|
|
@@ -33193,13 +32786,187 @@ function branchForkClass(step) {
|
|
|
33193
32786
|
function escapeMermaidLabel(s2) {
|
|
33194
32787
|
return s2.replace(/"/g, """).replace(/\|/g, "|");
|
|
33195
32788
|
}
|
|
32789
|
+
function describeFlow(flow, target) {
|
|
32790
|
+
const lines = [];
|
|
32791
|
+
const title = diagramString(flow.title, target);
|
|
32792
|
+
lines.push(`Flow: ${flow.id} (${title})`);
|
|
32793
|
+
if (flow.defaultMode !== void 0) {
|
|
32794
|
+
lines.push(`Default mode: ${flow.defaultMode}`);
|
|
32795
|
+
}
|
|
32796
|
+
lines.push("Entries:");
|
|
32797
|
+
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
32798
|
+
const resolved = diagramValue(entry, target);
|
|
32799
|
+
lines.push(` ${mode} \u2192 ${resolved ?? "<no entry for diagram target>"}`);
|
|
32800
|
+
}
|
|
32801
|
+
lines.push("");
|
|
32802
|
+
for (const phase of flow.phases) {
|
|
32803
|
+
lines.push(`Phase: ${phase.id}`);
|
|
32804
|
+
for (const step of phase.steps) {
|
|
32805
|
+
const key = `${phase.id}/${step.id}`;
|
|
32806
|
+
lines.push(` ${key} [${step.kind}]`);
|
|
32807
|
+
const modes = Object.keys(flow.entries);
|
|
32808
|
+
for (const mode of modes) {
|
|
32809
|
+
const targets = nextRefsForMode(step, mode);
|
|
32810
|
+
const desc = targets.map((t) => t ?? "<end>").join(", ");
|
|
32811
|
+
lines.push(` ${mode} \u2192 ${desc}`);
|
|
32812
|
+
}
|
|
32813
|
+
}
|
|
32814
|
+
}
|
|
32815
|
+
return lines.join("\n");
|
|
32816
|
+
}
|
|
33196
32817
|
|
|
33197
|
-
// ../
|
|
32818
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/render.js
|
|
33198
32819
|
function s(value, target, label) {
|
|
33199
32820
|
return resolveTargetableString(value, target, label);
|
|
33200
32821
|
}
|
|
32822
|
+
function renderFlow(flow, target) {
|
|
32823
|
+
const mode = resolvePerTarget(flow.compile.mode, target.name);
|
|
32824
|
+
if (mode === "split" || mode === "split-chain") {
|
|
32825
|
+
return renderSplit(flow, target, mode === "split-chain");
|
|
32826
|
+
}
|
|
32827
|
+
return [{ slug: "", kind: "monolith", content: renderMarkdown(flow, target) }];
|
|
32828
|
+
}
|
|
33201
32829
|
function usesPhaseReferences(flow, target) {
|
|
33202
|
-
return target.
|
|
32830
|
+
return target.phaseReferences === true && resolvePerTarget(flow.compile.mode, target.name) === "split-chain";
|
|
32831
|
+
}
|
|
32832
|
+
function makeRenderContext(flow, target) {
|
|
32833
|
+
return {
|
|
32834
|
+
allModes: Object.keys(flow.entries),
|
|
32835
|
+
modesPerStep: computeModesPerStep(flow, target.name),
|
|
32836
|
+
reachable: computeReachableSteps(flow, target.name),
|
|
32837
|
+
emitTemplate: flow.emitTemplate !== void 0 ? s(flow.emitTemplate, target.name, "flow.emitTemplate") : void 0
|
|
32838
|
+
};
|
|
32839
|
+
}
|
|
32840
|
+
function phaseHasReachableSteps(phase, reachable) {
|
|
32841
|
+
return phase.steps.some((step) => reachable.has(`${phase.id}/${step.id}`));
|
|
32842
|
+
}
|
|
32843
|
+
function renderSplit(flow, target, chain = false) {
|
|
32844
|
+
const ctx = makeRenderContext(flow, target);
|
|
32845
|
+
const inlineSet = new Set(flow.compile.inlinePhases);
|
|
32846
|
+
const subPhases = flow.phases.filter((phase) => !inlineSet.has(phase.id) && phaseHasReachableSteps(phase, ctx.reachable));
|
|
32847
|
+
const files = [
|
|
32848
|
+
{
|
|
32849
|
+
slug: "",
|
|
32850
|
+
kind: "orchestrator",
|
|
32851
|
+
content: renderOrchestrator(flow, target, ctx, inlineSet, subPhases, chain)
|
|
32852
|
+
}
|
|
32853
|
+
];
|
|
32854
|
+
for (const phase of subPhases) {
|
|
32855
|
+
files.push({
|
|
32856
|
+
slug: phase.id,
|
|
32857
|
+
kind: usesPhaseReferences(flow, target) ? "reference" : "phase",
|
|
32858
|
+
content: renderSubSkill(flow, target, ctx, phase, chain)
|
|
32859
|
+
});
|
|
32860
|
+
}
|
|
32861
|
+
return files;
|
|
32862
|
+
}
|
|
32863
|
+
function labeledRefsForMode(step, mode) {
|
|
32864
|
+
switch (step.kind) {
|
|
32865
|
+
case "action":
|
|
32866
|
+
case "reference":
|
|
32867
|
+
case "parallel": {
|
|
32868
|
+
const next = step.next;
|
|
32869
|
+
const ref = next === null || typeof next === "string" ? next : next.byMode[mode] ?? null;
|
|
32870
|
+
return [{ label: null, ref }];
|
|
32871
|
+
}
|
|
32872
|
+
case "branch":
|
|
32873
|
+
return step.branches.map((branch) => {
|
|
32874
|
+
const next = branch.next;
|
|
32875
|
+
const ref = next === null || typeof next === "string" ? next : next.byMode[mode] ?? null;
|
|
32876
|
+
return { label: dispatchBranchLabel(branch), ref };
|
|
32877
|
+
});
|
|
32878
|
+
case "loop":
|
|
32879
|
+
return [
|
|
32880
|
+
{ label: step.exitWhen, ref: step.onExit },
|
|
32881
|
+
{ label: "otherwise", ref: step.backTo }
|
|
32882
|
+
];
|
|
32883
|
+
}
|
|
32884
|
+
}
|
|
32885
|
+
function dispatchBranchLabel(branch) {
|
|
32886
|
+
if (branch.option !== void 0) {
|
|
32887
|
+
return `option ${branch.option.letter} (${branch.option.label})`;
|
|
32888
|
+
}
|
|
32889
|
+
return branch.when ?? "branch";
|
|
32890
|
+
}
|
|
32891
|
+
function computeDispatchEdges(step, stepKey, unitPhases, ctx) {
|
|
32892
|
+
const stepModeSet = modesForStep(stepKey, ctx.modesPerStep, ctx.allModes);
|
|
32893
|
+
const stepModes = ctx.allModes.filter((m) => stepModeSet.has(m));
|
|
32894
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32895
|
+
const order = [];
|
|
32896
|
+
const labelHasDispatch = /* @__PURE__ */ new Set();
|
|
32897
|
+
for (const mode of stepModes) {
|
|
32898
|
+
for (const { label, ref } of labeledRefsForMode(step, mode)) {
|
|
32899
|
+
let kind = "done";
|
|
32900
|
+
let targetPhase = null;
|
|
32901
|
+
if (ref !== null) {
|
|
32902
|
+
const phaseId = ref.split("/")[0];
|
|
32903
|
+
if (unitPhases.has(phaseId)) {
|
|
32904
|
+
kind = "continue";
|
|
32905
|
+
} else {
|
|
32906
|
+
kind = "dispatch";
|
|
32907
|
+
targetPhase = phaseId;
|
|
32908
|
+
}
|
|
32909
|
+
}
|
|
32910
|
+
const key = `${label ?? "\0"}|${kind}|${targetPhase ?? ""}`;
|
|
32911
|
+
const existing = groups.get(key);
|
|
32912
|
+
if (existing !== void 0) {
|
|
32913
|
+
if (!existing.modes.includes(mode)) {
|
|
32914
|
+
existing.modes.push(mode);
|
|
32915
|
+
}
|
|
32916
|
+
} else {
|
|
32917
|
+
groups.set(key, { label, kind, targetPhase, modes: [mode] });
|
|
32918
|
+
order.push(key);
|
|
32919
|
+
}
|
|
32920
|
+
if (kind === "dispatch") {
|
|
32921
|
+
labelHasDispatch.add(label);
|
|
32922
|
+
}
|
|
32923
|
+
}
|
|
32924
|
+
}
|
|
32925
|
+
return order.map((key) => groups.get(key)).filter((edge) => labelHasDispatch.has(edge.label));
|
|
32926
|
+
}
|
|
32927
|
+
function renderDispatchSuffix(flow, target, edges, allModes, unitPhases) {
|
|
32928
|
+
if (edges.length === 0) {
|
|
32929
|
+
return null;
|
|
32930
|
+
}
|
|
32931
|
+
const singleMode = allModes.length === 1;
|
|
32932
|
+
const lines = edges.map((edge) => {
|
|
32933
|
+
const modeList = edge.modes.map((m) => `\`${m}\``).join(" or ");
|
|
32934
|
+
let prefix = "";
|
|
32935
|
+
if (edge.label !== null) {
|
|
32936
|
+
prefix = singleMode ? titleCase(edge.label) : `${titleCase(edge.label)} (mode ${modeList})`;
|
|
32937
|
+
} else if (!singleMode) {
|
|
32938
|
+
prefix = `Mode ${modeList}`;
|
|
32939
|
+
}
|
|
32940
|
+
let action;
|
|
32941
|
+
switch (edge.kind) {
|
|
32942
|
+
case "done":
|
|
32943
|
+
action = "stop here.";
|
|
32944
|
+
break;
|
|
32945
|
+
case "continue":
|
|
32946
|
+
action = usesPhaseReferences(flow, target) ? "continue below in this file." : "continue below in this skill.";
|
|
32947
|
+
break;
|
|
32948
|
+
case "dispatch": {
|
|
32949
|
+
if (edge.targetPhase === null) {
|
|
32950
|
+
throw new Error("Dispatch edge is missing its target phase");
|
|
32951
|
+
}
|
|
32952
|
+
const destination = phaseDestination(flow, target, edge.targetPhase, unitPhases);
|
|
32953
|
+
const actionVerb = usesPhaseReferences(flow, target) ? "read and follow" : "invoke";
|
|
32954
|
+
const fwd = `, forwarding \`${target.argsToken}\` minus the leading mode keyword (if the user typed one).`;
|
|
32955
|
+
if (singleMode) {
|
|
32956
|
+
action = `${actionVerb} ${destination}${fwd}`;
|
|
32957
|
+
} else if (edge.modes.length === 1) {
|
|
32958
|
+
action = `${actionVerb} ${destination} with mode \`${edge.modes[0]}\`${fwd}`;
|
|
32959
|
+
} else {
|
|
32960
|
+
action = `${actionVerb} ${destination} with the current mode (${modeList})${fwd}`;
|
|
32961
|
+
}
|
|
32962
|
+
break;
|
|
32963
|
+
}
|
|
32964
|
+
}
|
|
32965
|
+
return prefix.length > 0 ? `- ${prefix}: ${action}` : `- ${titleCase(action)}`;
|
|
32966
|
+
});
|
|
32967
|
+
return `**Next:**
|
|
32968
|
+
|
|
32969
|
+
${lines.join("\n")}`;
|
|
33203
32970
|
}
|
|
33204
32971
|
function dispatchSkillRef(target, skillName) {
|
|
33205
32972
|
return target.dispatchRef?.(skillName) ?? `\`${skillName}\``;
|
|
@@ -33217,6 +32984,208 @@ function phaseDestination(flow, target, phaseId, unitPhases) {
|
|
|
33217
32984
|
const title = s(phase.title, target.name, `phase[${phaseId}].title`);
|
|
33218
32985
|
return `the [${title}](${prefix}${phaseId}.md) reference`;
|
|
33219
32986
|
}
|
|
32987
|
+
function dispatchSuffixForUnit(flow, target, ctx, unitPhases) {
|
|
32988
|
+
return (step, stepKey) => renderDispatchSuffix(flow, target, computeDispatchEdges(step, stepKey, unitPhases, ctx), ctx.allModes, unitPhases);
|
|
32989
|
+
}
|
|
32990
|
+
function interactiveDefaultDispatchPointer(flow, target) {
|
|
32991
|
+
const action = usesPhaseReferences(flow, target) ? "read and follow that mode's reference" : "invoke that mode's skill";
|
|
32992
|
+
return `**Next:** once the user picks a mode, ${action} from the \`## Dispatch\` section above, forwarding the arguments the user gave with their pick minus the mode keyword. Ignore the dispatch lines' \`${target.argsToken}\` here: this is the no-argument entry, so it is empty and the user's pick is the only source of those arguments.`;
|
|
32993
|
+
}
|
|
32994
|
+
function orchestratorDispatchSuffix(flow, target, ctx, inlineSet, hasEntryDispatch) {
|
|
32995
|
+
const base = dispatchSuffixForUnit(flow, target, ctx, inlineSet);
|
|
32996
|
+
const defaultEntry = flow.entries.default === void 0 ? void 0 : resolvePerTarget(flow.entries.default, target.name);
|
|
32997
|
+
return (step, stepKey) => {
|
|
32998
|
+
if (hasEntryDispatch && defaultEntry !== void 0 && stepKey === defaultEntry && "next" in step && step.next === null) {
|
|
32999
|
+
return interactiveDefaultDispatchPointer(flow, target);
|
|
33000
|
+
}
|
|
33001
|
+
return base(step, stepKey);
|
|
33002
|
+
};
|
|
33003
|
+
}
|
|
33004
|
+
function renderEntryDispatch(flow, target, ctx, inlineSet) {
|
|
33005
|
+
const groups = /* @__PURE__ */ new Map();
|
|
33006
|
+
for (const [mode, entry] of Object.entries(flow.entries)) {
|
|
33007
|
+
const resolved = resolvePerTarget(entry, target.name);
|
|
33008
|
+
if (resolved === void 0) {
|
|
33009
|
+
continue;
|
|
33010
|
+
}
|
|
33011
|
+
const phaseId = resolved.split("/")[0];
|
|
33012
|
+
if (inlineSet.has(phaseId)) {
|
|
33013
|
+
continue;
|
|
33014
|
+
}
|
|
33015
|
+
const modes = groups.get(phaseId) ?? [];
|
|
33016
|
+
modes.push(mode);
|
|
33017
|
+
groups.set(phaseId, modes);
|
|
33018
|
+
}
|
|
33019
|
+
if (groups.size === 0) {
|
|
33020
|
+
return null;
|
|
33021
|
+
}
|
|
33022
|
+
const singleMode = ctx.allModes.length === 1;
|
|
33023
|
+
const lines = [...groups.entries()].map(([phaseId, modes]) => {
|
|
33024
|
+
const destination = phaseDestination(flow, target, phaseId, inlineSet);
|
|
33025
|
+
const action = usesPhaseReferences(flow, target) ? "read and follow" : "invoke";
|
|
33026
|
+
const fwd = `, forwarding \`${target.argsToken}\` minus the leading mode keyword (if the user typed one).`;
|
|
33027
|
+
if (singleMode) {
|
|
33028
|
+
return `- ${titleCase(action)} ${destination}${fwd}`;
|
|
33029
|
+
}
|
|
33030
|
+
const modeList = modes.map((m) => `\`${m}\``).join(" or ");
|
|
33031
|
+
const arg = modes.length === 1 ? `mode \`${modes[0]}\`` : `the current mode (${modeList})`;
|
|
33032
|
+
return `- Mode ${modeList}: ${action} ${destination} with ${arg}${fwd}`;
|
|
33033
|
+
});
|
|
33034
|
+
return `## Dispatch
|
|
33035
|
+
|
|
33036
|
+
${lines.join("\n")}`;
|
|
33037
|
+
}
|
|
33038
|
+
function appendicesForUnit(flow, ctx, unitPhases, includeUnreferenced) {
|
|
33039
|
+
const referencingPhases = /* @__PURE__ */ new Map();
|
|
33040
|
+
for (const phase of flow.phases) {
|
|
33041
|
+
for (const step of phase.steps) {
|
|
33042
|
+
if (!ctx.reachable.has(`${phase.id}/${step.id}`)) {
|
|
33043
|
+
continue;
|
|
33044
|
+
}
|
|
33045
|
+
for (const ref of step.refs ?? []) {
|
|
33046
|
+
const phases = referencingPhases.get(ref) ?? /* @__PURE__ */ new Set();
|
|
33047
|
+
phases.add(phase.id);
|
|
33048
|
+
referencingPhases.set(ref, phases);
|
|
33049
|
+
}
|
|
33050
|
+
}
|
|
33051
|
+
}
|
|
33052
|
+
return flow.appendices.filter((appendix) => {
|
|
33053
|
+
const phases = referencingPhases.get(appendix.id);
|
|
33054
|
+
if (phases === void 0) {
|
|
33055
|
+
return includeUnreferenced;
|
|
33056
|
+
}
|
|
33057
|
+
return [...phases].some((id) => unitPhases.has(id));
|
|
33058
|
+
});
|
|
33059
|
+
}
|
|
33060
|
+
function renderOrchestrator(flow, target, ctx, inlineSet, subPhases, chain) {
|
|
33061
|
+
const inlinePhaseIds = flow.phases.filter((phase) => inlineSet.has(phase.id)).map((phase) => phase.id);
|
|
33062
|
+
const sections = [
|
|
33063
|
+
target.frontmatter({
|
|
33064
|
+
flowId: flow.id,
|
|
33065
|
+
description: s(flow.frontmatter.description, target.name, "flow.frontmatter.description"),
|
|
33066
|
+
argumentHint: resolveArgumentHint(flow, target),
|
|
33067
|
+
model: flow.frontmatter.model,
|
|
33068
|
+
allowedTools: orchestratorAllowedTools(flow, target, inlinePhaseIds, subPhases.length > 0)
|
|
33069
|
+
}),
|
|
33070
|
+
`# ${s(flow.title, target.name, "flow.title")}`
|
|
33071
|
+
];
|
|
33072
|
+
pushIntro(sections, flow, target);
|
|
33073
|
+
if (usesPhaseReferences(flow, target) && subPhases.length > 0) {
|
|
33074
|
+
sections.push("Load phase references only when routing reaches them. Read and follow the linked file in this same session, retaining the current mode, arguments, shared rules, and prior results. Resolve links relative to the file containing them. If an installed shim redirected you here, use this worktree skill's directory, not the shim directory or shell working directory. References are ordinary instruction files, not separately invocable skills.");
|
|
33075
|
+
}
|
|
33076
|
+
if (Object.keys(flow.commands).length > 0) {
|
|
33077
|
+
sections.push(renderCommandsTable(flow, target));
|
|
33078
|
+
}
|
|
33079
|
+
pushInvariants(sections, flow);
|
|
33080
|
+
const modesDispatch = renderModesDispatch(flow, target, true);
|
|
33081
|
+
if (modesDispatch !== null) {
|
|
33082
|
+
sections.push(modesDispatch);
|
|
33083
|
+
}
|
|
33084
|
+
let hasEntryDispatch = false;
|
|
33085
|
+
if (chain) {
|
|
33086
|
+
const entryDispatch = renderEntryDispatch(flow, target, ctx, inlineSet);
|
|
33087
|
+
if (entryDispatch !== null) {
|
|
33088
|
+
sections.push(entryDispatch);
|
|
33089
|
+
hasEntryDispatch = true;
|
|
33090
|
+
}
|
|
33091
|
+
}
|
|
33092
|
+
const subPhaseIds = new Set(subPhases.map((phase) => phase.id));
|
|
33093
|
+
for (const phase of flow.phases) {
|
|
33094
|
+
if (inlineSet.has(phase.id)) {
|
|
33095
|
+
const rendered = renderPhase(
|
|
33096
|
+
phase,
|
|
33097
|
+
target.name,
|
|
33098
|
+
ctx.allModes,
|
|
33099
|
+
ctx.modesPerStep,
|
|
33100
|
+
ctx.reachable,
|
|
33101
|
+
ctx.emitTemplate,
|
|
33102
|
+
true,
|
|
33103
|
+
chain ? orchestratorDispatchSuffix(flow, target, ctx, inlineSet, hasEntryDispatch) : void 0,
|
|
33104
|
+
destinationRenderer(flow, target, inlineSet),
|
|
33105
|
+
0,
|
|
33106
|
+
// Split-chain orchestrators emit a `## Dispatch` block above the inline
|
|
33107
|
+
// phase; fold a single-mode gate under the first step heading so it can't
|
|
33108
|
+
// be misread as gating the dispatch. Non-chain/monolith keep the float.
|
|
33109
|
+
chain
|
|
33110
|
+
);
|
|
33111
|
+
if (rendered.length > 0) {
|
|
33112
|
+
sections.push(rendered);
|
|
33113
|
+
}
|
|
33114
|
+
} else if (!chain && subPhaseIds.has(phase.id)) {
|
|
33115
|
+
sections.push(renderDispatch(flow, target, ctx, phase));
|
|
33116
|
+
}
|
|
33117
|
+
}
|
|
33118
|
+
pushAppendices(sections, flow, target, chain ? appendicesForUnit(flow, ctx, inlineSet, true) : flow.appendices);
|
|
33119
|
+
return finalize2(sections, flow, target, inlineSet);
|
|
33120
|
+
}
|
|
33121
|
+
function renderDispatch(flow, target, ctx, phase) {
|
|
33122
|
+
const title = s(phase.title, target.name, `phase[${phase.id}].title`);
|
|
33123
|
+
const stepKeys = phase.steps.map((step) => `${phase.id}/${step.id}`).filter((key) => ctx.reachable.has(key));
|
|
33124
|
+
const { phaseGate } = precomputePhaseAndStepGates(stepKeys, ctx.modesPerStep, ctx.allModes);
|
|
33125
|
+
const blocks = [`## ${title}`];
|
|
33126
|
+
if (phaseGate !== null) {
|
|
33127
|
+
blocks.push(phaseGate);
|
|
33128
|
+
}
|
|
33129
|
+
blocks.push(`Invoke the \`${flow.id}-${phase.id}\` skill, then return here.`);
|
|
33130
|
+
return blocks.join("\n\n");
|
|
33131
|
+
}
|
|
33132
|
+
function renderSubSkill(flow, target, ctx, phase, chain) {
|
|
33133
|
+
const phaseTitle = s(phase.title, target.name, `phase[${phase.id}].title`);
|
|
33134
|
+
const flowTitle = s(flow.title, target.name, "flow.title");
|
|
33135
|
+
const unitPhases = /* @__PURE__ */ new Set([phase.id]);
|
|
33136
|
+
const reachableSteps = phase.steps.filter((step) => ctx.reachable.has(`${phase.id}/${step.id}`));
|
|
33137
|
+
const hasDispatch = chain && reachableSteps.some((step) => computeDispatchEdges(step, `${phase.id}/${step.id}`, unitPhases, ctx).some((edge) => edge.kind === "dispatch"));
|
|
33138
|
+
const invokedBy = chain ? `Invoked by the ${flow.id} flow; not run directly` : `Invoked by the ${flow.id} orchestrator; not run directly`;
|
|
33139
|
+
const description = `${phaseTitle} phase of the ${flowTitle} flow. ${invokedBy}`;
|
|
33140
|
+
const sections = [];
|
|
33141
|
+
if (!usesPhaseReferences(flow, target)) {
|
|
33142
|
+
sections.push(target.subSkillFrontmatter({
|
|
33143
|
+
flowId: `${flow.id}-${phase.id}`,
|
|
33144
|
+
description,
|
|
33145
|
+
argumentHint: resolveArgumentHint(flow, target),
|
|
33146
|
+
model: flow.frontmatter.model,
|
|
33147
|
+
allowedTools: subSkillAllowedTools(flow, target, phase.id, hasDispatch)
|
|
33148
|
+
}));
|
|
33149
|
+
}
|
|
33150
|
+
sections.push(`# ${flowTitle}: ${phaseTitle}`);
|
|
33151
|
+
if (chain) {
|
|
33152
|
+
const preface = renderModePreface(ctx, phase, reachableSteps);
|
|
33153
|
+
if (preface !== null) {
|
|
33154
|
+
sections.push(preface);
|
|
33155
|
+
}
|
|
33156
|
+
}
|
|
33157
|
+
const rendered = renderPhase(phase, target.name, ctx.allModes, ctx.modesPerStep, ctx.reachable, ctx.emitTemplate, false, chain ? dispatchSuffixForUnit(flow, target, ctx, unitPhases) : void 0, destinationRenderer(flow, target, unitPhases));
|
|
33158
|
+
if (rendered.length > 0) {
|
|
33159
|
+
sections.push(rendered);
|
|
33160
|
+
}
|
|
33161
|
+
if (chain) {
|
|
33162
|
+
pushAppendices(sections, flow, target, appendicesForUnit(flow, ctx, unitPhases, false));
|
|
33163
|
+
}
|
|
33164
|
+
return finalize2(sections, flow, target, unitPhases);
|
|
33165
|
+
}
|
|
33166
|
+
function renderModePreface(ctx, phase, reachableSteps) {
|
|
33167
|
+
const phaseModes = /* @__PURE__ */ new Set();
|
|
33168
|
+
for (const step of reachableSteps) {
|
|
33169
|
+
for (const mode of modesForStep(`${phase.id}/${step.id}`, ctx.modesPerStep, ctx.allModes)) {
|
|
33170
|
+
phaseModes.add(mode);
|
|
33171
|
+
}
|
|
33172
|
+
}
|
|
33173
|
+
if (phaseModes.size < 2) {
|
|
33174
|
+
return null;
|
|
33175
|
+
}
|
|
33176
|
+
const modeList = ctx.allModes.filter((m) => phaseModes.has(m)).map((m) => `\`${m}\``).join(" or ");
|
|
33177
|
+
return `**Mode:** you were dispatched with a mode (${modeList}); which steps apply and where they route below depend on it.`;
|
|
33178
|
+
}
|
|
33179
|
+
function subSkillAllowedTools(flow, target, phaseId, hasDispatch) {
|
|
33180
|
+
const tools = resolveAllowedToolsForPhases(flow, target, [phaseId]);
|
|
33181
|
+
if (tools === void 0 || !hasDispatch) {
|
|
33182
|
+
return tools;
|
|
33183
|
+
}
|
|
33184
|
+
if (target.subSkillTool && !tools.includes(target.subSkillTool)) {
|
|
33185
|
+
return [...tools, target.subSkillTool];
|
|
33186
|
+
}
|
|
33187
|
+
return tools;
|
|
33188
|
+
}
|
|
33220
33189
|
function resolveArgumentHint(flow, target) {
|
|
33221
33190
|
const argumentHint = flow.frontmatter.argumentHint;
|
|
33222
33191
|
if (argumentHint === void 0) {
|
|
@@ -33232,8 +33201,91 @@ function resolveArgumentHint(flow, target) {
|
|
|
33232
33201
|
if (argumentHint.suffix === void 0) {
|
|
33233
33202
|
return modeHint;
|
|
33234
33203
|
}
|
|
33235
|
-
const suffix = s(argumentHint.suffix, target.name, "frontmatter.argumentHint.suffix");
|
|
33236
|
-
return suffix.length > 0 ? `${modeHint} ${suffix}` : modeHint;
|
|
33204
|
+
const suffix = s(argumentHint.suffix, target.name, "frontmatter.argumentHint.suffix");
|
|
33205
|
+
return suffix.length > 0 ? `${modeHint} ${suffix}` : modeHint;
|
|
33206
|
+
}
|
|
33207
|
+
function pushIntro(sections, flow, target) {
|
|
33208
|
+
if (flow.intro === void 0) {
|
|
33209
|
+
return;
|
|
33210
|
+
}
|
|
33211
|
+
const introStr = s(flow.intro, target.name, "flow.intro");
|
|
33212
|
+
if (introStr.length > 0) {
|
|
33213
|
+
sections.push(introStr);
|
|
33214
|
+
}
|
|
33215
|
+
}
|
|
33216
|
+
function pushInvariants(sections, flow) {
|
|
33217
|
+
if (flow.invariants.length > 0) {
|
|
33218
|
+
const items = flow.invariants.map((inv) => `- ${inv}`).join("\n");
|
|
33219
|
+
sections.push(`## Invariants
|
|
33220
|
+
|
|
33221
|
+
${items}`);
|
|
33222
|
+
}
|
|
33223
|
+
}
|
|
33224
|
+
function pushAppendices(sections, flow, target, appendices = flow.appendices) {
|
|
33225
|
+
for (const appendix of appendices) {
|
|
33226
|
+
const title = s(appendix.title, target.name, `appendix[${appendix.id}].title`);
|
|
33227
|
+
const body = s(appendix.body, target.name, `appendix[${appendix.id}].body`);
|
|
33228
|
+
sections.push(`## ${title}
|
|
33229
|
+
|
|
33230
|
+
${body}`);
|
|
33231
|
+
}
|
|
33232
|
+
}
|
|
33233
|
+
function orchestratorAllowedTools(flow, target, inlinePhaseIds, hasSubSkills) {
|
|
33234
|
+
const tools = resolveAllowedToolsForPhases(flow, target, inlinePhaseIds);
|
|
33235
|
+
if (tools === void 0) {
|
|
33236
|
+
return void 0;
|
|
33237
|
+
}
|
|
33238
|
+
if (hasSubSkills && target.subSkillTool && !tools.includes(target.subSkillTool)) {
|
|
33239
|
+
return [...tools, target.subSkillTool];
|
|
33240
|
+
}
|
|
33241
|
+
return tools;
|
|
33242
|
+
}
|
|
33243
|
+
function resolveAllowedToolsForPhases(flow, target, phaseIds) {
|
|
33244
|
+
if (Object.keys(flow.tools).length === 0) {
|
|
33245
|
+
return flow.frontmatter.allowedTools;
|
|
33246
|
+
}
|
|
33247
|
+
const ids = collectPhaseToolIds(flow, target, phaseIds).filter((id) => toolAvailableOnTarget(flow.tools[id], target.name));
|
|
33248
|
+
if (ids.length === 0) {
|
|
33249
|
+
return void 0;
|
|
33250
|
+
}
|
|
33251
|
+
return ids.map((id) => fullToolName(flow, id, target));
|
|
33252
|
+
}
|
|
33253
|
+
var HAS_COMMAND_RE = new RegExp(COMMAND_PLACEHOLDER_RE.source);
|
|
33254
|
+
function collectPhaseToolIds(flow, target, phaseIds) {
|
|
33255
|
+
const wanted = new Set(phaseIds);
|
|
33256
|
+
const called = /* @__PURE__ */ new Set();
|
|
33257
|
+
const runnerId = Object.entries(flow.tools).find(([, tool]) => tool.kind === "builtin" && resolvePerTarget(tool.name, target.name) === target.commandRunnerTool)?.[0];
|
|
33258
|
+
const emitTemplate = flow.emitTemplate !== void 0 ? s(flow.emitTemplate, target.name, "flow.emitTemplate") : void 0;
|
|
33259
|
+
const emitUsesCommand = emitTemplate !== void 0 && HAS_COMMAND_RE.test(emitTemplate);
|
|
33260
|
+
const scan = (text2) => {
|
|
33261
|
+
if (text2 === void 0) {
|
|
33262
|
+
return;
|
|
33263
|
+
}
|
|
33264
|
+
for (const match of text2.matchAll(TOOL_PLACEHOLDER_RE)) {
|
|
33265
|
+
called.add(match[1]);
|
|
33266
|
+
}
|
|
33267
|
+
if (runnerId !== void 0 && HAS_COMMAND_RE.test(text2)) {
|
|
33268
|
+
called.add(runnerId);
|
|
33269
|
+
}
|
|
33270
|
+
};
|
|
33271
|
+
for (const phase of flow.phases) {
|
|
33272
|
+
if (!wanted.has(phase.id)) {
|
|
33273
|
+
continue;
|
|
33274
|
+
}
|
|
33275
|
+
if (phase.intro !== void 0) {
|
|
33276
|
+
scan(s(phase.intro, target.name, `phase[${phase.id}].intro`));
|
|
33277
|
+
}
|
|
33278
|
+
for (const step of phase.steps) {
|
|
33279
|
+
for (const id of step.toolCalls ?? []) {
|
|
33280
|
+
called.add(id);
|
|
33281
|
+
}
|
|
33282
|
+
if (runnerId !== void 0 && ((step.commandCalls?.length ?? 0) > 0 || step.emit !== void 0 && emitUsesCommand)) {
|
|
33283
|
+
called.add(runnerId);
|
|
33284
|
+
}
|
|
33285
|
+
scan(s(step.body, target.name, `step[${step.id}].body`));
|
|
33286
|
+
}
|
|
33287
|
+
}
|
|
33288
|
+
return Object.keys(flow.tools).filter((id) => called.has(id));
|
|
33237
33289
|
}
|
|
33238
33290
|
function renderMarkdown(flow, target) {
|
|
33239
33291
|
const sections = [];
|
|
@@ -33254,7 +33306,7 @@ function renderMarkdown(flow, target) {
|
|
|
33254
33306
|
}
|
|
33255
33307
|
}
|
|
33256
33308
|
if (Object.keys(flow.commands).length > 0) {
|
|
33257
|
-
sections.push(renderCommandsTable(flow));
|
|
33309
|
+
sections.push(renderCommandsTable(flow, target));
|
|
33258
33310
|
}
|
|
33259
33311
|
if (flow.invariants.length > 0) {
|
|
33260
33312
|
const items = flow.invariants.map((inv) => `- ${inv}`).join("\n");
|
|
@@ -33294,7 +33346,7 @@ ${body}`);
|
|
|
33294
33346
|
}
|
|
33295
33347
|
function finalize2(sections, flow, target, unitPhases) {
|
|
33296
33348
|
const joined = sections.join("\n\n");
|
|
33297
|
-
const afterSections = applyModeSections(applyMustacheSections(joined, target
|
|
33349
|
+
const afterSections = applyModeSections(applyMustacheSections(joined, target), flow, target.name, unitPhases);
|
|
33298
33350
|
const withFlowData = applyFlowPlaceholders(afterSections, flow, target, unitPhases);
|
|
33299
33351
|
const substituted = applyTokens(withFlowData, target, flow);
|
|
33300
33352
|
return ensureTrailingNewline(substituted);
|
|
@@ -33353,16 +33405,11 @@ function applyFlowPlaceholders(text2, flow, target, unitPhases) {
|
|
|
33353
33405
|
if (def === void 0) {
|
|
33354
33406
|
throw new Error(`Command "${commandId}" not declared in flow.commands`);
|
|
33355
33407
|
}
|
|
33356
|
-
return
|
|
33408
|
+
return target.invokeCommand(def);
|
|
33357
33409
|
});
|
|
33358
|
-
result = result.replace(/\{\{
|
|
33359
|
-
const block =
|
|
33360
|
-
|
|
33361
|
-
const before = result.slice(lineStart, offset);
|
|
33362
|
-
if (!/^[ \t]*$/.test(before)) {
|
|
33363
|
-
return block;
|
|
33364
|
-
}
|
|
33365
|
-
return block.split("\n").map((line, i) => i === 0 || line.length === 0 ? line : before + line).join("\n");
|
|
33410
|
+
result = result.replace(/\{\{(table|list):([a-zA-Z][a-zA-Z0-9_-]*):([a-zA-Z0-9_,-]+)\}\}/g, (_match, kind, tableName, columnsRaw, offset) => {
|
|
33411
|
+
const block = renderTableBlock(flow, kind, tableName, columnsRaw.split(","));
|
|
33412
|
+
return inheritLineIndent(result, offset, block);
|
|
33366
33413
|
});
|
|
33367
33414
|
return result;
|
|
33368
33415
|
}
|
|
@@ -33448,65 +33495,61 @@ function renderModesDispatch(flow, target, dispatches) {
|
|
|
33448
33495
|
...rows
|
|
33449
33496
|
].join("\n");
|
|
33450
33497
|
}
|
|
33451
|
-
function renderCommandsTable(flow) {
|
|
33498
|
+
function renderCommandsTable(flow, target) {
|
|
33452
33499
|
const rows = [];
|
|
33453
33500
|
for (const def of Object.values(flow.commands)) {
|
|
33454
33501
|
const sig = def.args !== void 0 ? `${def.file} ${def.args}` : def.file;
|
|
33455
33502
|
rows.push(`| \`${sig}\` | ${def.description} |`);
|
|
33456
33503
|
}
|
|
33457
33504
|
return [
|
|
33458
|
-
|
|
33505
|
+
target.commandsTableIntro,
|
|
33459
33506
|
"",
|
|
33460
33507
|
"| Command | Description |",
|
|
33461
33508
|
"|---------|-------------|",
|
|
33462
33509
|
...rows
|
|
33463
33510
|
].join("\n");
|
|
33464
33511
|
}
|
|
33465
|
-
function
|
|
33466
|
-
|
|
33467
|
-
|
|
33512
|
+
function renderTableBlock(flow, kind, tableName, columns) {
|
|
33513
|
+
const table = flow.tables[tableName];
|
|
33514
|
+
if (table === void 0) {
|
|
33515
|
+
throw new Error(`Table "${tableName}" not declared in flow.tables`);
|
|
33468
33516
|
}
|
|
33469
|
-
if (
|
|
33470
|
-
|
|
33471
|
-
|
|
33472
|
-
if (lang.imports !== void 0) {
|
|
33473
|
-
lines2.push(` - ${lang.displayName}: ${lang.imports}`);
|
|
33474
|
-
}
|
|
33517
|
+
if (kind === "list") {
|
|
33518
|
+
if (columns.length !== 1) {
|
|
33519
|
+
throw new Error(`{{list:${tableName}:\u2026}} takes exactly one column, got ${columns.join(",")}`);
|
|
33475
33520
|
}
|
|
33476
|
-
|
|
33521
|
+
const column = columns[0];
|
|
33522
|
+
return table.rows.filter((row) => row.cells[column] !== void 0).map((row) => `- ${row.label ?? row.key}: ${row.cells[column]}`).join("\n");
|
|
33477
33523
|
}
|
|
33478
|
-
const headers = [
|
|
33524
|
+
const headers = [
|
|
33525
|
+
table.keyHeader,
|
|
33526
|
+
...columns.map((c) => table.columns[c] ?? titleCase(c))
|
|
33527
|
+
];
|
|
33479
33528
|
const lines = [
|
|
33480
33529
|
`| ${headers.join(" | ")} |`,
|
|
33481
33530
|
`|${headers.map(() => "---").join("|")}|`
|
|
33482
33531
|
];
|
|
33483
|
-
for (const
|
|
33484
|
-
const cells = columns.map((col) =>
|
|
33532
|
+
for (const row of table.rows) {
|
|
33533
|
+
const cells = columns.map((col) => row.cells[col]);
|
|
33485
33534
|
if (cells.every((c) => c !== void 0)) {
|
|
33486
|
-
lines.push(`| ${
|
|
33535
|
+
lines.push(`| ${row.key} | ${cells.join(" | ")} |`);
|
|
33487
33536
|
}
|
|
33488
33537
|
}
|
|
33489
33538
|
return lines.join("\n");
|
|
33490
33539
|
}
|
|
33491
|
-
function columnHeader(flow, column) {
|
|
33492
|
-
return flow.languageColumnHeaders[column] ?? titleCase(column);
|
|
33493
|
-
}
|
|
33494
33540
|
function titleCase(s2) {
|
|
33495
33541
|
return s2.charAt(0).toUpperCase() + s2.slice(1);
|
|
33496
33542
|
}
|
|
33497
|
-
function
|
|
33498
|
-
|
|
33499
|
-
|
|
33500
|
-
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
|
|
33504
|
-
|
|
33505
|
-
case "update":
|
|
33506
|
-
return lang.update;
|
|
33507
|
-
default:
|
|
33508
|
-
throw new Error(`Unknown languages field "${column}"`);
|
|
33543
|
+
function inheritLineIndent(text2, offset, value) {
|
|
33544
|
+
if (!value.includes("\n")) {
|
|
33545
|
+
return value;
|
|
33546
|
+
}
|
|
33547
|
+
const lineStart = text2.lastIndexOf("\n", offset - 1) + 1;
|
|
33548
|
+
const before = text2.slice(lineStart, offset);
|
|
33549
|
+
if (!/^[ \t]*$/.test(before)) {
|
|
33550
|
+
return value;
|
|
33509
33551
|
}
|
|
33552
|
+
return value.split("\n").map((line, i) => i === 0 || line.length === 0 ? line : before + line).join("\n");
|
|
33510
33553
|
}
|
|
33511
33554
|
function destinationRenderer(flow, target, unitPhases) {
|
|
33512
33555
|
const one = (ref, sourcePhaseId) => {
|
|
@@ -33750,14 +33793,13 @@ function indentBody(body) {
|
|
|
33750
33793
|
const lines = body.split("\n");
|
|
33751
33794
|
return lines.map((line, i) => i === 0 ? line : line.length > 0 ? ` ${line}` : line).join("\n");
|
|
33752
33795
|
}
|
|
33753
|
-
function applyMustacheSections(text2,
|
|
33754
|
-
const sectionRegex = /\{\{([#^])([a-z][a-
|
|
33796
|
+
function applyMustacheSections(text2, target) {
|
|
33797
|
+
const sectionRegex = /\{\{([#^])([a-z][a-z0-9-]*)\}\}([\s\S]*?)\{\{\/\2\}\}/g;
|
|
33755
33798
|
return text2.replace(sectionRegex, (_match, kind, name, inner) => {
|
|
33756
|
-
const
|
|
33757
|
-
if (
|
|
33758
|
-
throw new Error(`Unknown
|
|
33799
|
+
const isMatch = target.sections[name];
|
|
33800
|
+
if (isMatch === void 0) {
|
|
33801
|
+
throw new Error(`Unknown section "${name}". Valid sections: ${Object.keys(target.sections).join(", ")}.`);
|
|
33759
33802
|
}
|
|
33760
|
-
const isMatch = members2.includes(targetName);
|
|
33761
33803
|
const include = kind === "#" ? isMatch : !isMatch;
|
|
33762
33804
|
return include ? inner : "";
|
|
33763
33805
|
});
|
|
@@ -33820,20 +33862,11 @@ function applyTokens(text2, target, flow) {
|
|
|
33820
33862
|
if (!Object.hasOwn(pool, key)) {
|
|
33821
33863
|
throw new Error(`Unresolved placeholder {{${key}}} - not a target token or flow variable. Define it in flow.variables, fix the typo, or remove the placeholder.`);
|
|
33822
33864
|
}
|
|
33823
|
-
|
|
33824
|
-
if (!value.includes("\n")) {
|
|
33825
|
-
return value;
|
|
33826
|
-
}
|
|
33827
|
-
const lineStart = text2.lastIndexOf("\n", offset - 1) + 1;
|
|
33828
|
-
const before = text2.slice(lineStart, offset);
|
|
33829
|
-
if (!/^[ \t]*$/.test(before)) {
|
|
33830
|
-
return value;
|
|
33831
|
-
}
|
|
33832
|
-
return value.split("\n").map((line, i) => i === 0 || line.length === 0 ? line : before + line).join("\n");
|
|
33865
|
+
return inheritLineIndent(text2, offset, pool[key]);
|
|
33833
33866
|
});
|
|
33834
33867
|
const leftovers = result.match(/\{\{[^}]+\}\}/g);
|
|
33835
33868
|
if (leftovers) {
|
|
33836
|
-
throw new Error(`Unresolved placeholder(s): ${leftovers.join(", ")}. Check spelling and namespace (step:, step-ref:, skill-ref:, dispatch-ref:, tool:,
|
|
33869
|
+
throw new Error(`Unresolved placeholder(s): ${leftovers.join(", ")}. Check spelling and namespace (step:, step-ref:, skill-ref:, dispatch-ref:, tool:, command:, table:, list:, branches, branches:).`);
|
|
33837
33870
|
}
|
|
33838
33871
|
return result;
|
|
33839
33872
|
}
|
|
@@ -33842,27 +33875,318 @@ function ensureTrailingNewline(text2) {
|
|
|
33842
33875
|
`;
|
|
33843
33876
|
}
|
|
33844
33877
|
|
|
33845
|
-
// ../
|
|
33846
|
-
var
|
|
33847
|
-
|
|
33848
|
-
|
|
33849
|
-
|
|
33850
|
-
|
|
33851
|
-
|
|
33852
|
-
|
|
33853
|
-
|
|
33854
|
-
|
|
33855
|
-
|
|
33856
|
-
|
|
33857
|
-
|
|
33858
|
-
|
|
33859
|
-
|
|
33860
|
-
|
|
33861
|
-
|
|
33862
|
-
|
|
33863
|
-
|
|
33878
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/kit.js
|
|
33879
|
+
var NAME_RE = /^[a-z][a-z0-9-]*$/;
|
|
33880
|
+
function createFlowKit(config4) {
|
|
33881
|
+
const targetNames = Object.keys(config4.targets);
|
|
33882
|
+
if (targetNames.length === 0) {
|
|
33883
|
+
throw new Error("createFlowKit: at least one target is required");
|
|
33884
|
+
}
|
|
33885
|
+
for (const name of targetNames) {
|
|
33886
|
+
if (!NAME_RE.test(name) || name === "default") {
|
|
33887
|
+
throw new Error(`createFlowKit: invalid target name "${name}" (use lowercase kebab-case; "default" is reserved)`);
|
|
33888
|
+
}
|
|
33889
|
+
}
|
|
33890
|
+
const groups = {};
|
|
33891
|
+
for (const name of targetNames) {
|
|
33892
|
+
groups[name] = [name];
|
|
33893
|
+
}
|
|
33894
|
+
for (const [section, members2] of Object.entries(config4.sections ?? {})) {
|
|
33895
|
+
if (!NAME_RE.test(section)) {
|
|
33896
|
+
throw new Error(`createFlowKit: invalid section name "${section}"`);
|
|
33897
|
+
}
|
|
33898
|
+
if (section in groups) {
|
|
33899
|
+
throw new Error(`createFlowKit: section "${section}" collides with a target name`);
|
|
33900
|
+
}
|
|
33901
|
+
for (const member of members2) {
|
|
33902
|
+
if (!targetNames.includes(member)) {
|
|
33903
|
+
throw new Error(`createFlowKit: section "${section}" lists unknown target "${member}"`);
|
|
33904
|
+
}
|
|
33905
|
+
}
|
|
33906
|
+
groups[section] = members2;
|
|
33907
|
+
}
|
|
33908
|
+
const commands = config4.commands ?? {};
|
|
33909
|
+
const runnerTool = commands.runnerTool ?? "Bash";
|
|
33910
|
+
const targets = {};
|
|
33911
|
+
for (const name of targetNames) {
|
|
33912
|
+
const spec = config4.targets[name];
|
|
33913
|
+
const target = { ...spec, name };
|
|
33914
|
+
const sections = {};
|
|
33915
|
+
for (const [section, members2] of Object.entries(groups)) {
|
|
33916
|
+
sections[section] = members2.includes(name);
|
|
33917
|
+
}
|
|
33918
|
+
const tableIntro = commands.tableIntro;
|
|
33919
|
+
targets[name] = {
|
|
33920
|
+
...target,
|
|
33921
|
+
sections,
|
|
33922
|
+
invokeCommand: (command) => commands.invoke?.(command, target) ?? command.file,
|
|
33923
|
+
commandsTableIntro: typeof tableIntro === "function" ? tableIntro(target) : tableIntro ?? `**CLI commands** available via \`${runnerTool}\`:`,
|
|
33924
|
+
commandRunnerTool: runnerTool
|
|
33925
|
+
};
|
|
33926
|
+
}
|
|
33927
|
+
const reservedTokenNames = /* @__PURE__ */ new Set();
|
|
33928
|
+
for (const name of targetNames) {
|
|
33929
|
+
for (const token of Object.keys(config4.targets[name].tokens)) {
|
|
33930
|
+
reservedTokenNames.add(token);
|
|
33931
|
+
}
|
|
33932
|
+
}
|
|
33933
|
+
const schemaOptions = {
|
|
33934
|
+
targetNames,
|
|
33935
|
+
reservedTokenNames: [...reservedTokenNames]
|
|
33936
|
+
};
|
|
33937
|
+
const schema = createFlowSchema(schemaOptions);
|
|
33938
|
+
const getTarget = (name) => {
|
|
33939
|
+
const target = targets[name];
|
|
33940
|
+
if (target === void 0) {
|
|
33941
|
+
throw new Error(`Unknown target "${name}". Known targets: ${targetNames.join(", ")}.`);
|
|
33942
|
+
}
|
|
33943
|
+
return target;
|
|
33944
|
+
};
|
|
33945
|
+
return {
|
|
33946
|
+
targetNames,
|
|
33947
|
+
targets,
|
|
33948
|
+
schema,
|
|
33949
|
+
defineFlow(input2) {
|
|
33950
|
+
const result = schema.safeParse(input2);
|
|
33951
|
+
if (!result.success) {
|
|
33952
|
+
const id = typeof input2 === "object" && input2 !== null && "id" in input2 ? String(input2.id) : "<unknown>";
|
|
33953
|
+
throw new Error(`Invalid flow "${id}":
|
|
33954
|
+
${external_exports.prettifyError(result.error)}`);
|
|
33955
|
+
}
|
|
33956
|
+
return result.data;
|
|
33957
|
+
},
|
|
33958
|
+
render: (flow, name) => renderFlow(flow, getTarget(name)),
|
|
33959
|
+
renderMarkdown: (flow, name) => renderMarkdown(flow, getTarget(name)),
|
|
33960
|
+
renderProject(projects) {
|
|
33961
|
+
const out = [];
|
|
33962
|
+
for (const { flow, outputs } of projects) {
|
|
33963
|
+
for (const name of targetNames) {
|
|
33964
|
+
const output2 = outputs[name];
|
|
33965
|
+
if (output2 === void 0) {
|
|
33966
|
+
continue;
|
|
33967
|
+
}
|
|
33968
|
+
for (const file2 of renderFlow(flow, getTarget(name))) {
|
|
33969
|
+
out.push({
|
|
33970
|
+
flowId: flow.id,
|
|
33971
|
+
target: name,
|
|
33972
|
+
kind: file2.kind,
|
|
33973
|
+
path: resolveOutputPath(output2, file2),
|
|
33974
|
+
content: file2.content
|
|
33975
|
+
});
|
|
33976
|
+
}
|
|
33977
|
+
}
|
|
33978
|
+
}
|
|
33979
|
+
return out;
|
|
33980
|
+
},
|
|
33981
|
+
renderMermaid,
|
|
33982
|
+
describeFlow
|
|
33983
|
+
};
|
|
33984
|
+
}
|
|
33985
|
+
function dirname(path15) {
|
|
33986
|
+
const i = path15.lastIndexOf("/");
|
|
33987
|
+
return i === -1 ? "." : path15.slice(0, i);
|
|
33988
|
+
}
|
|
33989
|
+
function basename(path15) {
|
|
33990
|
+
return path15.slice(path15.lastIndexOf("/") + 1);
|
|
33991
|
+
}
|
|
33992
|
+
function resolveOutputPath(output2, file2) {
|
|
33993
|
+
const main2 = typeof output2 === "string" ? output2 : output2.main;
|
|
33994
|
+
if (file2.slug === "") {
|
|
33995
|
+
return main2;
|
|
33996
|
+
}
|
|
33997
|
+
if (file2.kind === "reference") {
|
|
33998
|
+
return `${dirname(main2)}/references/${file2.slug}.md`;
|
|
33999
|
+
}
|
|
34000
|
+
if (typeof output2 !== "string") {
|
|
34001
|
+
return output2.phase.replace(/\{phase\}/g, file2.slug);
|
|
34002
|
+
}
|
|
34003
|
+
const skillDir = dirname(main2);
|
|
34004
|
+
if (skillDir === ".") {
|
|
34005
|
+
throw new Error(`Cannot derive a sub-skill path for phase "${file2.slug}" from "${main2}"; use { main, phase } output paths.`);
|
|
34006
|
+
}
|
|
34007
|
+
return `${dirname(skillDir)}/${basename(skillDir)}-${file2.slug}/${basename(main2)}`;
|
|
34008
|
+
}
|
|
34009
|
+
|
|
34010
|
+
// ../node_modules/.pnpm/@agent-flows+core@0.1.1_zod@4.6.7/node_modules/@agent-flows/core/dist/targets.js
|
|
34011
|
+
function formatAllowedTools(allowedTools) {
|
|
34012
|
+
return `[${allowedTools.map((t) => JSON.stringify(t)).join(", ")}]`;
|
|
34013
|
+
}
|
|
34014
|
+
function claudeFrontmatter({ description, argumentHint, model, allowedTools }) {
|
|
34015
|
+
const lines = ["---", `description: ${description}`];
|
|
34016
|
+
if (argumentHint !== void 0) {
|
|
34017
|
+
lines.push(`argument-hint: ${JSON.stringify(argumentHint)}`);
|
|
34018
|
+
}
|
|
34019
|
+
if (model !== void 0) {
|
|
34020
|
+
lines.push(`model: ${model}`);
|
|
34021
|
+
}
|
|
34022
|
+
if (allowedTools !== void 0) {
|
|
34023
|
+
lines.push(`allowed-tools: ${formatAllowedTools(allowedTools)}`);
|
|
34024
|
+
}
|
|
34025
|
+
lines.push("---");
|
|
34026
|
+
return lines.join("\n");
|
|
34027
|
+
}
|
|
34028
|
+
function claudeSubSkillFrontmatter({ flowId, description, model, allowedTools }) {
|
|
34029
|
+
const lines = [
|
|
34030
|
+
"---",
|
|
34031
|
+
`name: ${flowId}`,
|
|
34032
|
+
`description: ${description}`,
|
|
34033
|
+
"user-invocable: false"
|
|
34034
|
+
];
|
|
34035
|
+
if (model !== void 0) {
|
|
34036
|
+
lines.push(`model: ${model}`);
|
|
34037
|
+
}
|
|
34038
|
+
if (allowedTools !== void 0) {
|
|
34039
|
+
lines.push(`allowed-tools: ${formatAllowedTools(allowedTools)}`);
|
|
33864
34040
|
}
|
|
34041
|
+
lines.push("---");
|
|
34042
|
+
return lines.join("\n");
|
|
34043
|
+
}
|
|
34044
|
+
function namedFrontmatter(name, description, usage, usageInBody = false) {
|
|
34045
|
+
const frontmatter = [
|
|
34046
|
+
"---",
|
|
34047
|
+
`name: ${name}`,
|
|
34048
|
+
`description: "${description}${usageInBody ? "" : usage}"`,
|
|
34049
|
+
"---"
|
|
34050
|
+
].join("\n");
|
|
34051
|
+
return usageInBody && usage !== "" ? `${frontmatter}
|
|
34052
|
+
|
|
34053
|
+
${usage.slice(2)}` : frontmatter;
|
|
34054
|
+
}
|
|
34055
|
+
var ASK_USER_QUESTION_TOKENS = {
|
|
34056
|
+
askUser: "with `AskUserQuestion` ",
|
|
34057
|
+
askVerb: "use `AskUserQuestion`",
|
|
34058
|
+
askVerbCap: "Use `AskUserQuestion`",
|
|
34059
|
+
askNoun: "AskUserQuestion"
|
|
33865
34060
|
};
|
|
34061
|
+
var PLAIN_PROMPT_TOKENS = {
|
|
34062
|
+
askUser: "",
|
|
34063
|
+
askVerb: "ask the user",
|
|
34064
|
+
askVerbCap: "Ask the user",
|
|
34065
|
+
askNoun: "choice prompt"
|
|
34066
|
+
};
|
|
34067
|
+
function claudeCode(options) {
|
|
34068
|
+
return {
|
|
34069
|
+
tokens: {
|
|
34070
|
+
cmd: `/${options.plugin}:`,
|
|
34071
|
+
editor: "Claude Code",
|
|
34072
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable rendered into skill markdown
|
|
34073
|
+
pluginRoot: "${CLAUDE_PLUGIN_ROOT}",
|
|
34074
|
+
pluginDirLookup: "",
|
|
34075
|
+
...ASK_USER_QUESTION_TOKENS,
|
|
34076
|
+
...options.tokens
|
|
34077
|
+
},
|
|
34078
|
+
mcpPrefix: options.mcpPrefix ?? (options.mcpServer !== void 0 ? `mcp__plugin_${options.plugin}_${options.mcpServer}__` : ""),
|
|
34079
|
+
argsToken: "$ARGUMENTS",
|
|
34080
|
+
frontmatter: claudeFrontmatter,
|
|
34081
|
+
subSkillFrontmatter: claudeSubSkillFrontmatter,
|
|
34082
|
+
subSkillTool: "Skill"
|
|
34083
|
+
};
|
|
34084
|
+
}
|
|
34085
|
+
function cursor(options) {
|
|
34086
|
+
const render = ({ flowId, description, argumentHint }) => {
|
|
34087
|
+
const name = `${options.plugin}-${flowId}`;
|
|
34088
|
+
const usage = argumentHint !== void 0 ? `. Usage: /${name} ${argumentHint}` : "";
|
|
34089
|
+
return namedFrontmatter(name, description, usage, options.usageInBody);
|
|
34090
|
+
};
|
|
34091
|
+
return {
|
|
34092
|
+
tokens: {
|
|
34093
|
+
cmd: `/${options.plugin}-`,
|
|
34094
|
+
editor: "Cursor",
|
|
34095
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable rendered into skill markdown
|
|
34096
|
+
pluginRoot: "${CURSOR_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}",
|
|
34097
|
+
pluginDirLookup: "",
|
|
34098
|
+
...ASK_USER_QUESTION_TOKENS,
|
|
34099
|
+
...options.tokens
|
|
34100
|
+
},
|
|
34101
|
+
mcpPrefix: options.mcpPrefix ?? (options.mcpServer !== void 0 ? `mcp__${options.mcpServer}__` : ""),
|
|
34102
|
+
argsToken: "$ARGUMENTS",
|
|
34103
|
+
frontmatter: render,
|
|
34104
|
+
subSkillFrontmatter: render
|
|
34105
|
+
};
|
|
34106
|
+
}
|
|
34107
|
+
function defaultEnvVar(plugin) {
|
|
34108
|
+
return `${plugin.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_PLUGIN_DIR`;
|
|
34109
|
+
}
|
|
34110
|
+
function codexPluginDirLookup(plugin, { envVar = defaultEnvVar(plugin), markerFile }) {
|
|
34111
|
+
return `\`\`\`bash
|
|
34112
|
+
if [ -z "$${envVar}" ]; then
|
|
34113
|
+
${envVar}=$(
|
|
34114
|
+
hit=$(find "\${CODEX_HOME:-$HOME/.codex}/plugins/cache" -maxdepth 8 -type f \\
|
|
34115
|
+
-path '*/${plugin}/*/${markerFile}' 2>/dev/null | head -1)
|
|
34116
|
+
echo "\${hit%/${markerFile}}"
|
|
34117
|
+
)
|
|
34118
|
+
export ${envVar}
|
|
34119
|
+
fi
|
|
34120
|
+
test -n "$${envVar}" || { echo "ERROR: ${plugin} plugin not installed"; exit 1; }
|
|
34121
|
+
\`\`\``;
|
|
34122
|
+
}
|
|
34123
|
+
function ampPluginDirLookup(plugin, { envVar = defaultEnvVar(plugin), markerFile }) {
|
|
34124
|
+
return `\`\`\`bash
|
|
34125
|
+
if [ -z "$${envVar}" ]; then
|
|
34126
|
+
project_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
34127
|
+
for candidate in "$project_root/.amp/plugins/${plugin}" "\${XDG_CONFIG_HOME:-$HOME/.config}/amp/plugins/${plugin}"; do
|
|
34128
|
+
if [ -f "$candidate/${markerFile}" ]; then
|
|
34129
|
+
${envVar}="$candidate"
|
|
34130
|
+
break
|
|
34131
|
+
fi
|
|
34132
|
+
done
|
|
34133
|
+
export ${envVar}
|
|
34134
|
+
fi
|
|
34135
|
+
test -n "$${envVar}" || { echo "ERROR: ${plugin} plugin not installed"; exit 1; }
|
|
34136
|
+
\`\`\``;
|
|
34137
|
+
}
|
|
34138
|
+
function pluginDirTokens(plugin, pluginDir, lookup) {
|
|
34139
|
+
if (pluginDir === void 0) {
|
|
34140
|
+
return {};
|
|
34141
|
+
}
|
|
34142
|
+
return {
|
|
34143
|
+
pluginRoot: `\${${pluginDir.envVar ?? defaultEnvVar(plugin)}}`,
|
|
34144
|
+
pluginDirLookup: lookup(plugin, pluginDir)
|
|
34145
|
+
};
|
|
34146
|
+
}
|
|
34147
|
+
function codex(options) {
|
|
34148
|
+
const render = ({ flowId, description, argumentHint }) => {
|
|
34149
|
+
const usage = argumentHint !== void 0 ? `. Invoke with $${options.plugin}:${flowId} ${argumentHint}.` : "";
|
|
34150
|
+
return namedFrontmatter(flowId, description, usage, options.usageInBody);
|
|
34151
|
+
};
|
|
34152
|
+
return {
|
|
34153
|
+
tokens: {
|
|
34154
|
+
cmd: `$${options.plugin}:`,
|
|
34155
|
+
editor: "Codex",
|
|
34156
|
+
...pluginDirTokens(options.plugin, options.pluginDir, codexPluginDirLookup),
|
|
34157
|
+
...PLAIN_PROMPT_TOKENS,
|
|
34158
|
+
...options.tokens
|
|
34159
|
+
},
|
|
34160
|
+
mcpPrefix: options.mcpPrefix ?? (options.mcpServer !== void 0 ? `mcp__${options.mcpServer}__` : ""),
|
|
34161
|
+
argsToken: "$ARGUMENTS",
|
|
34162
|
+
frontmatter: render,
|
|
34163
|
+
subSkillFrontmatter: render,
|
|
34164
|
+
dispatchRef: (skillName) => `\`$${options.plugin}:${skillName}\``,
|
|
34165
|
+
phaseReferences: options.phaseReferences ?? true
|
|
34166
|
+
};
|
|
34167
|
+
}
|
|
34168
|
+
function amp(options) {
|
|
34169
|
+
const render = ({ flowId, description, argumentHint }) => {
|
|
34170
|
+
const usage = argumentHint !== void 0 ? `. Invoke as ${options.plugin}:${flowId} ${argumentHint}.` : "";
|
|
34171
|
+
return namedFrontmatter(flowId, description, usage, options.usageInBody);
|
|
34172
|
+
};
|
|
34173
|
+
return {
|
|
34174
|
+
tokens: {
|
|
34175
|
+
cmd: `${options.plugin}:`,
|
|
34176
|
+
editor: "Amp",
|
|
34177
|
+
...pluginDirTokens(options.plugin, options.pluginDir, ampPluginDirLookup),
|
|
34178
|
+
...PLAIN_PROMPT_TOKENS,
|
|
34179
|
+
...options.tokens
|
|
34180
|
+
},
|
|
34181
|
+
// Amp exposes MCP tools under their bare names.
|
|
34182
|
+
mcpPrefix: options.mcpPrefix ?? "",
|
|
34183
|
+
argsToken: "the user's request",
|
|
34184
|
+
frontmatter: render,
|
|
34185
|
+
subSkillFrontmatter: render,
|
|
34186
|
+
subSkillTool: "skill",
|
|
34187
|
+
dispatchRef: (skillName) => `\`${options.plugin}:${skillName}\``
|
|
34188
|
+
};
|
|
34189
|
+
}
|
|
33866
34190
|
|
|
33867
34191
|
// ../bitfab-plugin-lib/dist/retiredAssistant.js
|
|
33868
34192
|
var RETIRED_ASSISTANT_EXAMPLE_REQUESTS = [
|
|
@@ -33872,9 +34196,84 @@ var RETIRED_ASSISTANT_EXAMPLE_REQUESTS = [
|
|
|
33872
34196
|
"Compare the baseline experiment with the two prompt-variant experiments"
|
|
33873
34197
|
];
|
|
33874
34198
|
|
|
34199
|
+
// ../bitfab-plugin-lib/dist/flows/kit.js
|
|
34200
|
+
var BITFAB_PLUGIN = "bitfab";
|
|
34201
|
+
var MCP_SERVER = "Bitfab";
|
|
34202
|
+
var CODEX_RESOLVE_PLUGIN_DIR_BASH = `\`\`\`bash
|
|
34203
|
+
if [ -z "$BITFAB_PLUGIN_DIR" ]; then
|
|
34204
|
+
BITFAB_PLUGIN_DIR=$(
|
|
34205
|
+
hit=$(find "\${CODEX_HOME:-$HOME/.codex}/plugins/cache" -maxdepth 6 -type f -name status.js \\
|
|
34206
|
+
\\( -path '*/bitfab-internal/bitfab/local/dist/commands/*' \\
|
|
34207
|
+
-o -path '*/bitfab/bitfab/*/dist/commands/*' \\) 2>/dev/null | head -1)
|
|
34208
|
+
echo "\${hit%/dist/commands/status.js}"
|
|
34209
|
+
)
|
|
34210
|
+
export BITFAB_PLUGIN_DIR
|
|
34211
|
+
fi
|
|
34212
|
+
test -n "$BITFAB_PLUGIN_DIR" || { echo "ERROR: Bitfab plugin not installed"; exit 1; }
|
|
34213
|
+
\`\`\``;
|
|
34214
|
+
var AMP_RESOLVE_PLUGIN_DIR_BASH = `\`\`\`bash
|
|
34215
|
+
if [ -z "$BITFAB_PLUGIN_DIR" ]; then
|
|
34216
|
+
project_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
34217
|
+
for candidate in "$project_root/.amp/plugins/bitfab" "\${XDG_CONFIG_HOME:-$HOME/.config}/amp/plugins/bitfab"; do
|
|
34218
|
+
if [ -f "$candidate/dist/commands/status.js" ]; then
|
|
34219
|
+
BITFAB_PLUGIN_DIR="$candidate"
|
|
34220
|
+
break
|
|
34221
|
+
fi
|
|
34222
|
+
done
|
|
34223
|
+
export BITFAB_PLUGIN_DIR
|
|
34224
|
+
fi
|
|
34225
|
+
test -n "$BITFAB_PLUGIN_DIR" || { echo "ERROR: Bitfab plugin not installed"; exit 1; }
|
|
34226
|
+
\`\`\``;
|
|
34227
|
+
var bitfabKit = createFlowKit({
|
|
34228
|
+
targets: {
|
|
34229
|
+
claude: claudeCode({ plugin: BITFAB_PLUGIN, mcpServer: MCP_SERVER }),
|
|
34230
|
+
cursor: cursor({ plugin: BITFAB_PLUGIN, mcpServer: MCP_SERVER }),
|
|
34231
|
+
codex: codex({
|
|
34232
|
+
plugin: BITFAB_PLUGIN,
|
|
34233
|
+
mcpServer: MCP_SERVER,
|
|
34234
|
+
tokens: {
|
|
34235
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
34236
|
+
pluginRoot: "${BITFAB_PLUGIN_DIR}",
|
|
34237
|
+
pluginDirLookup: CODEX_RESOLVE_PLUGIN_DIR_BASH
|
|
34238
|
+
}
|
|
34239
|
+
}),
|
|
34240
|
+
amp: amp({
|
|
34241
|
+
plugin: BITFAB_PLUGIN,
|
|
34242
|
+
tokens: {
|
|
34243
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell variable reference rendered into skill markdown, not a JS template
|
|
34244
|
+
pluginRoot: "${BITFAB_PLUGIN_DIR}",
|
|
34245
|
+
pluginDirLookup: AMP_RESOLVE_PLUGIN_DIR_BASH
|
|
34246
|
+
}
|
|
34247
|
+
})
|
|
34248
|
+
},
|
|
34249
|
+
sections: {
|
|
34250
|
+
"ask-user-question": ["claude", "cursor"],
|
|
34251
|
+
"plugin-dir-lookup": ["codex", "amp"],
|
|
34252
|
+
"exec-polling": ["codex", "amp"],
|
|
34253
|
+
"no-startup-banner": ["codex", "amp"],
|
|
34254
|
+
"web-fetch-tool": ["claude", "cursor"]
|
|
34255
|
+
},
|
|
34256
|
+
commands: {
|
|
34257
|
+
invoke: (command) => `node "{{pluginRoot}}/dist/commands/${command.file}"`,
|
|
34258
|
+
tableIntro: "**CLI commands** available via Bash (all paths relative to `{{pluginRoot}}/dist/commands/`):"
|
|
34259
|
+
}
|
|
34260
|
+
});
|
|
34261
|
+
var TARGET_NAMES = bitfabKit.targetNames;
|
|
34262
|
+
var TARGETS = bitfabKit.targets;
|
|
34263
|
+
var SHARED_VARIABLES = {
|
|
34264
|
+
parallelism: {
|
|
34265
|
+
default: "in parallel with",
|
|
34266
|
+
codex: "in the same cycle as"
|
|
34267
|
+
},
|
|
34268
|
+
togetherness: {
|
|
34269
|
+
default: "in parallel",
|
|
34270
|
+
codex: "together"
|
|
34271
|
+
}
|
|
34272
|
+
};
|
|
34273
|
+
|
|
33875
34274
|
// ../bitfab-plugin-lib/dist/flows/assistant.js
|
|
33876
34275
|
var EXAMPLE_LINES = RETIRED_ASSISTANT_EXAMPLE_REQUESTS.map((request) => `> - "${request}"`).join("\n");
|
|
33877
|
-
var assistantFlow =
|
|
34276
|
+
var assistantFlow = bitfabKit.defineFlow({
|
|
33878
34277
|
schemaVersion: 1,
|
|
33879
34278
|
id: "assistant",
|
|
33880
34279
|
title: "Bitfab Assistant (retired)",
|
|
@@ -34131,6 +34530,7 @@ var FRAMEWORKS = [
|
|
|
34131
34530
|
// The captured span IS the BAML function call (a model call), recorded via a
|
|
34132
34531
|
// BAML Collector (observe), not withSpan. No nested child spans.
|
|
34133
34532
|
autoCapture: { modelCall: "observed" },
|
|
34533
|
+
recordedUnderTraceRoot: true,
|
|
34134
34534
|
signals: {
|
|
34135
34535
|
ts: "`@boundaryml/baml`, `baml_client` import",
|
|
34136
34536
|
py: "`baml-py`, `from baml_client import b`"
|
|
@@ -34193,7 +34593,8 @@ function frameworkReferenceList() {
|
|
|
34193
34593
|
const alias = f.aliasHandler ? `; in a LangChain-only project, prefer the identical aliases ${code(f.aliasHandler.ts)} / ${code(f.aliasHandler.py ?? f.aliasHandler.ts)} so the code reads naturally` : "";
|
|
34194
34594
|
const wrapper = f.rootWrapper ? `, plus the replayable run wrapper ${code(f.rootWrapper.ts)} / ${code(f.rootWrapper.py ?? f.rootWrapper.ts)} (drop-in for the run call)` : "";
|
|
34195
34595
|
const toolReplay = f.experimentalToolReplay ? `; Experimental (alpha) tool replay: ${code(f.experimentalToolReplay.factory.ts)} / ${code(f.experimentalToolReplay.factory.py ?? f.experimentalToolReplay.factory.ts)} with ${code(f.experimentalToolReplay.invoker.ts)} / ${code(f.experimentalToolReplay.invoker.py ?? f.experimentalToolReplay.invoker.ts)}${f.experimentalToolReplay.invoker.pyAsync ? ` / ${code(f.experimentalToolReplay.invoker.pyAsync)}` : ""}` : "";
|
|
34196
|
-
|
|
34596
|
+
const underTraceRoot = f.recordedUnderTraceRoot ? `; beneath an opt-out ${code("withTrace")} / ${code("trace")} root its calls are recorded as ${code("llm")} spans with no ${methods}, so add that ${f.handlerNoun} only under opt-in ${code("withSpan")} / ${code("@span")} code, and configure one call with ${code("withNode")} / ${code("node()")} on the bound method` : "";
|
|
34597
|
+
return `${f.label} \u2192 ${code(docsUrl(f.docsPath))} (${methods}${alias}${wrapper}${toolReplay}${underTraceRoot})`;
|
|
34197
34598
|
}).join("; ");
|
|
34198
34599
|
}
|
|
34199
34600
|
function handlerFrameworksWithMethods() {
|
|
@@ -34302,7 +34703,7 @@ var REPLAY_REGISTRY_VARIABLES = {
|
|
|
34302
34703
|
};
|
|
34303
34704
|
|
|
34304
34705
|
// ../bitfab-plugin-lib/dist/flows/setup.js
|
|
34305
|
-
var setupFlow =
|
|
34706
|
+
var setupFlow = bitfabKit.defineFlow({
|
|
34306
34707
|
schemaVersion: 1,
|
|
34307
34708
|
id: "setup",
|
|
34308
34709
|
title: "Bitfab Setup",
|
|
@@ -35993,7 +36394,7 @@ If **zero** valid candidates remain, skip to step {{step:analyze-repo/report}} a
|
|
|
35993
36394
|
});
|
|
35994
36395
|
|
|
35995
36396
|
// ../bitfab-plugin-lib/dist/flows/update.js
|
|
35996
|
-
var updateFlow =
|
|
36397
|
+
var updateFlow = bitfabKit.defineFlow({
|
|
35997
36398
|
schemaVersion: 1,
|
|
35998
36399
|
id: "update",
|
|
35999
36400
|
title: "Bitfab Update",
|
|
@@ -36045,45 +36446,58 @@ var updateFlow = Flow.parse({
|
|
|
36045
36446
|
plugin: "Update only the Bitfab plugin to the latest version.",
|
|
36046
36447
|
sdk: "Update only the Bitfab SDK to the latest version."
|
|
36047
36448
|
},
|
|
36048
|
-
|
|
36049
|
-
|
|
36050
|
-
|
|
36051
|
-
|
|
36052
|
-
|
|
36053
|
-
|
|
36054
|
-
|
|
36055
|
-
|
|
36056
|
-
|
|
36057
|
-
|
|
36058
|
-
|
|
36059
|
-
|
|
36060
|
-
|
|
36061
|
-
|
|
36062
|
-
|
|
36063
|
-
|
|
36064
|
-
|
|
36065
|
-
|
|
36066
|
-
|
|
36067
|
-
|
|
36068
|
-
|
|
36069
|
-
|
|
36070
|
-
|
|
36071
|
-
|
|
36072
|
-
|
|
36073
|
-
|
|
36074
|
-
|
|
36075
|
-
|
|
36076
|
-
|
|
36077
|
-
|
|
36078
|
-
|
|
36079
|
-
|
|
36080
|
-
|
|
36081
|
-
|
|
36082
|
-
|
|
36083
|
-
|
|
36084
|
-
|
|
36449
|
+
tables: {
|
|
36450
|
+
languages: {
|
|
36451
|
+
keyHeader: "Language",
|
|
36452
|
+
columns: {
|
|
36453
|
+
detection: "Detection (from workspace/repo)",
|
|
36454
|
+
outdated: "Command (run from workspace dir)",
|
|
36455
|
+
update: "Command"
|
|
36456
|
+
},
|
|
36457
|
+
rows: [
|
|
36458
|
+
{
|
|
36459
|
+
key: "typescript",
|
|
36460
|
+
label: "TypeScript",
|
|
36461
|
+
cells: {
|
|
36462
|
+
imports: "`import .* from [\"'](?:@bitfab/sdk|bitfab)[\"']` or `require\\([\"'](?:@bitfab/sdk|bitfab)[\"']\\)`",
|
|
36463
|
+
detection: "`pnpm-lock.yaml` at repo root \u2192 pnpm; `yarn.lock` \u2192 yarn; `bun.lock` \u2192 bun; otherwise npm",
|
|
36464
|
+
outdated: "`pnpm outdated @bitfab/sdk --json` / `npm outdated @bitfab/sdk --json` / `yarn outdated @bitfab/sdk` / `bun outdated @bitfab/sdk`",
|
|
36465
|
+
update: "If `renameFrom` is set (legacy `bitfab` package): remove the old package and add the new one in a single command: `pnpm remove bitfab && pnpm add @bitfab/sdk@latest` / `npm uninstall bitfab && npm install @bitfab/sdk@latest` / `yarn remove bitfab && yarn add @bitfab/sdk@latest` / `bun remove bitfab && bun add @bitfab/sdk@latest`. Then update imports in source files from `bitfab` to `@bitfab/sdk`. If no rename: `pnpm update @bitfab/sdk@latest` / `yarn upgrade @bitfab/sdk@latest` / `bun update @bitfab/sdk` / `npm install @bitfab/sdk@latest`"
|
|
36466
|
+
}
|
|
36467
|
+
},
|
|
36468
|
+
{
|
|
36469
|
+
key: "python",
|
|
36470
|
+
label: "Python",
|
|
36471
|
+
cells: {
|
|
36472
|
+
imports: "`^\\s*(from|import) bitfab\\b`",
|
|
36473
|
+
detection: "`uv.lock` \u2192 uv; `poetry.lock` \u2192 poetry; otherwise pip",
|
|
36474
|
+
outdated: "`uv pip list --outdated --format=json` / `poetry show -o bitfab-py` / `pip list --outdated --format=json`",
|
|
36475
|
+
update: "`uv add bitfab-py@latest` / `poetry add bitfab-py@latest` / `pip install -U bitfab-py` (and bump the pin in `requirements.txt` via Edit)"
|
|
36476
|
+
}
|
|
36477
|
+
},
|
|
36478
|
+
{
|
|
36479
|
+
key: "ruby",
|
|
36480
|
+
label: "Ruby",
|
|
36481
|
+
cells: {
|
|
36482
|
+
imports: "`require ['\"]bitfab['\"]`",
|
|
36483
|
+
detection: "`Gemfile.lock`",
|
|
36484
|
+
outdated: "`bundle outdated bitfab --parseable`",
|
|
36485
|
+
update: "`bundle update bitfab`"
|
|
36486
|
+
}
|
|
36487
|
+
},
|
|
36488
|
+
{
|
|
36489
|
+
key: "go",
|
|
36490
|
+
label: "Go",
|
|
36491
|
+
cells: {
|
|
36492
|
+
imports: '`"github.com/Project-White-Rabbit/bitfab-go"`',
|
|
36493
|
+
detection: "`go.mod`",
|
|
36494
|
+
outdated: "`go list -m -u -json github.com/Project-White-Rabbit/bitfab-go`",
|
|
36495
|
+
update: "`go get github.com/Project-White-Rabbit/bitfab-go@latest && go mod tidy`"
|
|
36496
|
+
}
|
|
36497
|
+
}
|
|
36498
|
+
]
|
|
36085
36499
|
}
|
|
36086
|
-
|
|
36500
|
+
},
|
|
36087
36501
|
phases: [
|
|
36088
36502
|
{
|
|
36089
36503
|
id: "setup",
|
|
@@ -36191,7 +36605,7 @@ If there are **no lines** inside \`<bitfab-sdk-status>\`, the programmatic check
|
|
|
36191
36605
|
body: `The programmatic detection is regex-based and only knows the workspace formats we hand-coded (pnpm/npm/yarn workspaces, uv workspaces, go.work). It can miss unusual monorepo layouts, vendored SDKs, or projects using package managers we don't parse. **Always run this verification** before offering updates.
|
|
36192
36606
|
|
|
36193
36607
|
- Grep the project for SDK imports (run these in parallel):
|
|
36194
|
-
{{languages:imports}}
|
|
36608
|
+
{{list:languages:imports}}
|
|
36195
36609
|
- For each import, find its workspace directory by walking up to the nearest \`package.json\` / \`pyproject.toml\` / \`Gemfile\` / \`go.mod\`.
|
|
36196
36610
|
- Compare that set against the \`workspacePath\` values in \`<bitfab-sdk-status>\`.
|
|
36197
36611
|
- For each workspace that has imports but **no** corresponding status entry, treat it as a missed detection: ask the user which package manager that workspace uses, then go to step {{step:sdk/agent-fallback}} for it (same flow as \`remoteCheckFailed: true\`).
|
|
@@ -36205,7 +36619,7 @@ If there are **no lines** inside \`<bitfab-sdk-status>\`, the programmatic check
|
|
|
36205
36619
|
title: "Agent fallback for `remoteCheckFailed` or detection gaps",
|
|
36206
36620
|
body: `For each entry where \`remoteCheckFailed: true\`, or any workspace discovered only in step {{step:sdk/verify-with-agent}}, run the package manager's native outdated command from the workspace directory. The command is authoritative, it respects private registries, mirrors, and offline caches.
|
|
36207
36621
|
|
|
36208
|
-
{{languages:detection,outdated}}
|
|
36622
|
+
{{table:languages:detection,outdated}}
|
|
36209
36623
|
|
|
36210
36624
|
Use the real latest from the command's output in place of \`latest\` when deciding whether to offer an upgrade.`,
|
|
36211
36625
|
next: "sdk/ask-batch"
|
|
@@ -36289,7 +36703,7 @@ When no outdated workspaces remain, exit and acknowledge.`,
|
|
|
36289
36703
|
title: "Run the update for the chosen workspace",
|
|
36290
36704
|
body: `Detect the package manager from the lockfiles and run the update **from the workspace directory** (not repo root, matters in monorepos):
|
|
36291
36705
|
|
|
36292
|
-
{{languages:update}}
|
|
36706
|
+
{{table:languages:update}}
|
|
36293
36707
|
|
|
36294
36708
|
After the update, Read the manifest to verify the new version and confirm to the user. If a rename was performed (\`renameFrom\` was set), also grep the workspace for old import paths and update them (e.g. \`from "bitfab"\` to \`from "@bitfab/sdk"\`). Then return to the per-workspace prompt for the next workspace.`,
|
|
36295
36709
|
next: "sdk/ask-per-workspace"
|
|
@@ -36301,7 +36715,7 @@ After the update, Read the manifest to verify the new version and confirm to the
|
|
|
36301
36715
|
title: "Run updates for every outdated workspace",
|
|
36302
36716
|
body: `For every workspace with \`updateAvailable: true\`, detect the package manager from the lockfiles and run the update **from each workspace directory** (not repo root):
|
|
36303
36717
|
|
|
36304
|
-
{{languages:update}}
|
|
36718
|
+
{{table:languages:update}}
|
|
36305
36719
|
|
|
36306
36720
|
After each update, Read the manifest to verify the new version and confirm to the user. If a rename was performed (\`renameFrom\` was set), also grep the workspace for old import paths and update them (e.g. \`from "bitfab"\` to \`from "@bitfab/sdk"\`).`,
|
|
36307
36721
|
next: null
|
|
@@ -36511,7 +36925,7 @@ var SUPPORTED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
36511
36925
|
"switchOrg",
|
|
36512
36926
|
"update"
|
|
36513
36927
|
]);
|
|
36514
|
-
var setupV2Flow =
|
|
36928
|
+
var setupV2Flow = bitfabKit.defineFlow({
|
|
36515
36929
|
...setupFlow,
|
|
36516
36930
|
id: "setup-v2",
|
|
36517
36931
|
title: "Bitfab Terminal Setup",
|
|
@@ -44573,8 +44987,8 @@ var Protocol = class {
|
|
|
44573
44987
|
}
|
|
44574
44988
|
}
|
|
44575
44989
|
},
|
|
44576
|
-
listTasks: (
|
|
44577
|
-
return taskStore.listTasks(
|
|
44990
|
+
listTasks: (cursor2) => {
|
|
44991
|
+
return taskStore.listTasks(cursor2, sessionId);
|
|
44578
44992
|
}
|
|
44579
44993
|
};
|
|
44580
44994
|
}
|
|
@@ -44864,8 +45278,8 @@ var ExperimentalServerTasks = class {
|
|
|
44864
45278
|
*
|
|
44865
45279
|
* @experimental
|
|
44866
45280
|
*/
|
|
44867
|
-
async listTasks(
|
|
44868
|
-
return this._server.listTasks(
|
|
45281
|
+
async listTasks(cursor2, options) {
|
|
45282
|
+
return this._server.listTasks(cursor2 ? { cursor: cursor2 } : void 0, options);
|
|
44869
45283
|
}
|
|
44870
45284
|
/**
|
|
44871
45285
|
* Cancels a running task.
|
|
@@ -48664,7 +49078,7 @@ import * as p8 from "@clack/prompts";
|
|
|
48664
49078
|
// src/setupV2Verification.ts
|
|
48665
49079
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
48666
49080
|
import { existsSync, readFileSync } from "fs";
|
|
48667
|
-
import { basename, relative, resolve as resolve2 } from "path";
|
|
49081
|
+
import { basename as basename2, relative, resolve as resolve2 } from "path";
|
|
48668
49082
|
var MUTATING_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
48669
49083
|
var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
48670
49084
|
".cjs",
|
|
@@ -48726,7 +49140,7 @@ function isReplayRuntimeCommand(command, registryPath) {
|
|
|
48726
49140
|
return false;
|
|
48727
49141
|
}
|
|
48728
49142
|
const displayedPath = registryPath.replaceAll("\\", "/");
|
|
48729
|
-
const registryName =
|
|
49143
|
+
const registryName = basename2(registryPath);
|
|
48730
49144
|
return /(?:^|\s)(?:[^\s]+\s+)*bitfab-replay(?:\s|$)/i.test(command) && /(?:^|\s)--registry(?:\s|=)/.test(command) && (command.includes(displayedPath) || command.includes(registryName));
|
|
48731
49145
|
}
|
|
48732
49146
|
function isWorkflowRuntimeCommand(command) {
|
|
@@ -48934,7 +49348,7 @@ var SetupV2VerificationGate = class {
|
|
|
48934
49348
|
message: "Edited text files must end with exactly one newline."
|
|
48935
49349
|
});
|
|
48936
49350
|
}
|
|
48937
|
-
if (/BITFAB_API_KEY\s*=/.test(source) &&
|
|
49351
|
+
if (/BITFAB_API_KEY\s*=/.test(source) && basename2(path15).startsWith(".env") && !/BITFAB_SERVICE_URL\s*=/.test(source)) {
|
|
48938
49352
|
issues.push({
|
|
48939
49353
|
code: "missing-service-url",
|
|
48940
49354
|
path: displayPath(this.cwd, path15),
|
|
@@ -49017,7 +49431,7 @@ var SetupV2VerificationGate = class {
|
|
|
49017
49431
|
}
|
|
49018
49432
|
}
|
|
49019
49433
|
const registryRevision = this.touchedPaths.get(registryPath) ?? 0;
|
|
49020
|
-
const registryName =
|
|
49434
|
+
const registryName = basename2(registryPath);
|
|
49021
49435
|
const registryVerified = this.verificationCommands.some(
|
|
49022
49436
|
({ command, revision }) => revision >= registryRevision && (command.includes(registryPath) || command.includes(displayPath(this.cwd, registryPath)) || command.includes(registryName) || /\btsc\b/.test(command) && projectTypecheckCoversRegistry(this.cwd, registryPath))
|
|
49023
49437
|
);
|