stageflow 0.27.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/builtin-skills/browser/SKILL.md +42 -0
- package/dist/agent/claudeAdapter.js +2 -2
- package/dist/agent/cursorProvider.d.ts +10 -0
- package/dist/agent/cursorProvider.js +83 -8
- package/dist/agent/fakeAgent.d.ts +1 -0
- package/dist/agent/fakeAgent.js +13 -0
- package/dist/agent/piAdapter.d.ts +3 -24
- package/dist/agent/piAdapter.js +49 -47
- package/dist/agent/piSessionFactory.d.ts +38 -0
- package/dist/agent/piSessionFactory.js +60 -0
- package/dist/agent/port.d.ts +2 -0
- package/dist/agent/providerAuth.d.ts +7 -3
- package/dist/agent/providerAuth.js +5 -3
- package/dist/agent/streamLogRedact.d.ts +6 -0
- package/dist/agent/streamLogRedact.js +23 -1
- package/dist/browser/anchor.d.ts +27 -0
- package/dist/browser/anchor.js +127 -0
- package/dist/browser/auditSink.d.ts +38 -0
- package/dist/browser/auditSink.js +34 -0
- package/dist/browser/browserHost.d.ts +86 -0
- package/dist/browser/browserHost.js +7 -0
- package/dist/browser/browserSweep.d.ts +14 -0
- package/dist/browser/browserSweep.js +54 -0
- package/dist/browser/browserTeardown.d.ts +56 -0
- package/dist/browser/browserTeardown.js +235 -0
- package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -0
- package/dist/browser/fakeRemoteBrowserHost.js +34 -0
- package/dist/browser/gateHandoff.d.ts +25 -0
- package/dist/browser/gateHandoff.js +83 -0
- package/dist/browser/humanLogin.d.ts +18 -0
- package/dist/browser/humanLogin.js +34 -0
- package/dist/browser/keyProvider.d.ts +10 -0
- package/dist/browser/keyProvider.js +39 -0
- package/dist/browser/localBrowserHost.d.ts +10 -0
- package/dist/browser/localBrowserHost.js +152 -0
- package/dist/browser/localProfileLock.d.ts +2 -0
- package/dist/browser/localProfileLock.js +218 -0
- package/dist/browser/localProfileStore.d.ts +5 -0
- package/dist/browser/localProfileStore.js +91 -0
- package/dist/browser/loginCheck.d.ts +53 -0
- package/dist/browser/loginCheck.js +147 -0
- package/dist/browser/memoryProfileLock.d.ts +2 -0
- package/dist/browser/memoryProfileLock.js +53 -0
- package/dist/browser/memoryProfileStore.d.ts +2 -0
- package/dist/browser/memoryProfileStore.js +31 -0
- package/dist/browser/navigationAudit.d.ts +16 -0
- package/dist/browser/navigationAudit.js +53 -0
- package/dist/browser/persistedEnv.d.ts +3 -0
- package/dist/browser/persistedEnv.js +15 -0
- package/dist/browser/profileLock.d.ts +40 -0
- package/dist/browser/profileLock.js +10 -0
- package/dist/browser/profileStore.d.ts +23 -0
- package/dist/browser/profileStore.js +39 -0
- package/dist/browser/runLiveness.d.ts +13 -0
- package/dist/browser/runLiveness.js +39 -0
- package/dist/browser/sitePolicy.d.ts +10 -0
- package/dist/browser/sitePolicy.js +61 -0
- package/dist/browser/stageBrowserEnv.d.ts +22 -0
- package/dist/browser/stageBrowserEnv.js +147 -0
- package/dist/browser/stageProfileLock.d.ts +17 -0
- package/dist/browser/stageProfileLock.js +39 -0
- package/dist/cli/browserCommand.d.ts +44 -0
- package/dist/cli/browserCommand.js +472 -0
- package/dist/cli/doctorCommand.js +7 -0
- package/dist/cli/hostClient.d.ts +20 -0
- package/dist/cli/hostClient.js +36 -2
- package/dist/cli/initCommand.d.ts +1 -0
- package/dist/cli/initCommand.js +23 -7
- package/dist/cli/initTemplates.d.ts +5 -2
- package/dist/cli/initTemplates.js +25 -2
- package/dist/cli/providersCommand.d.ts +1 -1
- package/dist/cli/providersCommand.js +4 -4
- package/dist/cli/runsCommand.js +6 -2
- package/dist/cli/triggerCommand.d.ts +12 -0
- package/dist/cli/triggerCommand.js +183 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +23 -6
- package/dist/cli.js +32 -3
- package/dist/config/browseCatalog.d.ts +1 -0
- package/dist/config/browseCatalog.js +5 -4
- package/dist/config/builtinSkills.d.ts +4 -0
- package/dist/config/builtinSkills.js +23 -0
- package/dist/config/catalogRelativePath.d.ts +1 -0
- package/dist/config/catalogRelativePath.js +10 -2
- package/dist/config/createTrigger.d.ts +27 -0
- package/dist/config/createTrigger.js +232 -0
- package/dist/config/draftPackage.d.ts +117 -0
- package/dist/config/draftPackage.js +550 -0
- package/dist/config/ensureCatalogScanRoot.d.ts +16 -0
- package/dist/config/ensureCatalogScanRoot.js +73 -0
- package/dist/config/hostConfig.d.ts +2 -0
- package/dist/config/hostConfig.js +27 -0
- package/dist/config/listSkills.d.ts +2 -2
- package/dist/config/listSkills.js +17 -3
- package/dist/config/loadOutcome.d.ts +6 -0
- package/dist/config/loadPipeline.js +16 -0
- package/dist/config/loadStage.js +7 -0
- package/dist/config/loadStageflowManifest.js +25 -0
- package/dist/config/loadTrigger.d.ts +9 -0
- package/dist/config/loadTrigger.js +120 -0
- package/dist/config/multiProjectCatalog.d.ts +2 -0
- package/dist/config/multiProjectCatalog.js +26 -18
- package/dist/config/normalizePipelineStageEntry.js +8 -1
- package/dist/config/parseCompletionContract.js +6 -0
- package/dist/config/pipelineStageKeys.js +1 -0
- package/dist/config/publishDraftPackage.d.ts +7 -0
- package/dist/config/publishDraftPackage.js +25 -0
- package/dist/config/resolveCatalogContext.js +1 -1
- package/dist/config/resolvePipelineDag.js +1 -1
- package/dist/config/scanCatalogPaths.d.ts +1 -1
- package/dist/config/scanCatalogPaths.js +6 -2
- package/dist/config/stageBrowser.d.ts +12 -0
- package/dist/config/stageBrowser.js +118 -0
- package/dist/config/triggerCatalog.d.ts +10 -0
- package/dist/config/triggerCatalog.js +37 -0
- package/dist/config/validateCatalog.d.ts +13 -3
- package/dist/config/validateCatalog.js +83 -2
- package/dist/config/validateCompletionContract.js +8 -0
- package/dist/envelope/preEmitChecks.d.ts +1 -1
- package/dist/envelope/preEmitChecks.js +8 -0
- package/dist/logging/redact.d.ts +4 -0
- package/dist/logging/redact.js +17 -0
- package/dist/mcp/catalogTools.js +43 -8
- package/dist/mcp/controlTools.js +3 -1
- package/dist/mcp/deps.d.ts +2 -0
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/tools.js +2 -0
- package/dist/mcp/triggerTools.d.ts +3 -0
- package/dist/mcp/triggerTools.js +176 -0
- package/dist/operatorAgent/docsRetrieval.d.ts +40 -0
- package/dist/operatorAgent/docsRetrieval.js +269 -0
- package/dist/operatorAgent/draftContext.d.ts +16 -0
- package/dist/operatorAgent/draftContext.js +68 -0
- package/dist/operatorAgent/fakeHost.d.ts +39 -0
- package/dist/operatorAgent/fakeHost.js +92 -0
- package/dist/operatorAgent/host.d.ts +40 -0
- package/dist/operatorAgent/host.js +179 -0
- package/dist/operatorAgent/index.d.ts +9 -0
- package/dist/operatorAgent/index.js +8 -0
- package/dist/operatorAgent/piModel.d.ts +80 -0
- package/dist/operatorAgent/piModel.js +528 -0
- package/dist/operatorAgent/profiles/workshopAuthor.d.ts +23 -0
- package/dist/operatorAgent/profiles/workshopAuthor.js +338 -0
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +6 -0
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +103 -0
- package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +57 -0
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +623 -0
- package/dist/operatorAgent/proposals.d.ts +32 -0
- package/dist/operatorAgent/proposals.js +144 -0
- package/dist/operatorAgent/types.d.ts +128 -0
- package/dist/operatorAgent/types.js +1 -0
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/project/findManifestRoot.d.ts +3 -0
- package/dist/project/findManifestRoot.js +35 -0
- package/dist/project/resolveStageflowContext.d.ts +7 -0
- package/dist/project/resolveStageflowContext.js +44 -28
- package/dist/runstore/assertTmpdir.js +6 -2
- package/dist/runstore/diskUsage.d.ts +1 -1
- package/dist/runstore/diskUsage.js +2 -7
- package/dist/runstore/port.d.ts +28 -0
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -1
- package/dist/runstore/sqlite/SqliteRunStore.js +90 -0
- package/dist/runstore/sqlite/migrations/008-triggers-table.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/008-triggers-table.js +19 -0
- package/dist/runstore/sqlite/migrations/009-trigger-next-run.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/009-trigger-next-run.js +19 -0
- package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.js +17 -0
- package/dist/runstore/sqlite/migrations/index.js +6 -0
- package/dist/runtime/answerResume.d.ts +1 -0
- package/dist/runtime/answerResume.js +3 -1
- package/dist/runtime/completionCheckRunner.d.ts +12 -1
- package/dist/runtime/completionCheckRunner.js +22 -0
- package/dist/runtime/credentialBinding.d.ts +7 -2
- package/dist/runtime/credentialBinding.js +20 -28
- package/dist/runtime/emailSource.d.ts +72 -0
- package/dist/runtime/emailSource.js +304 -0
- package/dist/runtime/githubPollSource.d.ts +86 -0
- package/dist/runtime/githubPollSource.js +284 -0
- package/dist/runtime/pipelineRunner.d.ts +4 -0
- package/dist/runtime/pipelineRunner.js +3 -0
- package/dist/runtime/pipelineScheduler.d.ts +2 -0
- package/dist/runtime/pipelineScheduler.js +86 -1
- package/dist/runtime/repositoryMaterialize.d.ts +1 -1
- package/dist/runtime/runManager.d.ts +11 -0
- package/dist/runtime/runManager.js +161 -3
- package/dist/runtime/runRetryCoordinator.d.ts +2 -0
- package/dist/runtime/runRetryCoordinator.js +1 -0
- package/dist/runtime/scheduleSource.d.ts +38 -0
- package/dist/runtime/scheduleSource.js +119 -0
- package/dist/runtime/settingsFile.d.ts +7 -2
- package/dist/runtime/settingsFile.js +66 -56
- package/dist/runtime/stageAttemptBootstrap.js +55 -3
- package/dist/runtime/stageEnvironment.js +1 -0
- package/dist/runtime/stageHitl.d.ts +1 -0
- package/dist/runtime/stageHitl.js +5 -1
- package/dist/runtime/stageProcessLauncher.d.ts +3 -0
- package/dist/runtime/stageProcessLauncher.js +52 -5
- package/dist/runtime/stageRunner.d.ts +5 -0
- package/dist/runtime/stageRunner.js +30 -6
- package/dist/runtime/stageStreamLog.d.ts +1 -0
- package/dist/runtime/stageStreamLog.js +2 -1
- package/dist/runtime/triggerCatalog.d.ts +6 -0
- package/dist/runtime/triggerCatalog.js +24 -0
- package/dist/runtime/triggerEventMatch.d.ts +2 -0
- package/dist/runtime/triggerEventMatch.js +6 -0
- package/dist/runtime/triggerPort.d.ts +14 -0
- package/dist/runtime/triggerPort.js +1 -0
- package/dist/runtime/triggerRunner.d.ts +17 -0
- package/dist/runtime/triggerRunner.js +89 -0
- package/dist/runtime/verifiedStageExecution.d.ts +7 -0
- package/dist/runtime/verifiedStageExecution.js +14 -0
- package/dist/runtime/webhookSignature.d.ts +1 -0
- package/dist/runtime/webhookSignature.js +12 -0
- package/dist/server/bootstrap.d.ts +6 -0
- package/dist/server/bootstrap.js +70 -0
- package/dist/server/controlToken.js +13 -0
- package/dist/server/createHttpHost.js +3 -0
- package/dist/server/healthSurfaces.js +31 -6
- package/dist/server/http.d.ts +15 -0
- package/dist/server/http.js +1251 -74
- package/dist/server/requestAuthContext.d.ts +1 -1
- package/dist/server/triggerRoutes.d.ts +15 -0
- package/dist/server/triggerRoutes.js +268 -0
- package/dist/tools/askOperator.d.ts +3 -2
- package/dist/types/completion.d.ts +3 -0
- package/dist/types/pipeline.d.ts +3 -1
- package/dist/types/preEmitCheck.d.ts +7 -0
- package/dist/types/stage.d.ts +14 -0
- package/dist/types/stageflowManifest.d.ts +3 -0
- package/dist/types/trigger.d.ts +18 -0
- package/dist/types/trigger.js +1 -0
- package/dist/ui/assets/{index-CSsDued1.css → index-Bv4p1aPK.css} +1 -1
- package/dist/ui/assets/index-p8Iou3zk.js +133 -0
- package/dist/ui/index.html +2 -2
- package/dist/workshop/autosave.d.ts +58 -0
- package/dist/workshop/autosave.js +222 -0
- package/dist/workshop/buildStore.d.ts +79 -0
- package/dist/workshop/buildStore.js +326 -0
- package/dist/workshop/chatTurn.d.ts +232 -0
- package/dist/workshop/chatTurn.js +475 -0
- package/dist/workshop/modelSettings.d.ts +18 -0
- package/dist/workshop/modelSettings.js +44 -0
- package/dist/workshop/sessionStore.d.ts +61 -0
- package/dist/workshop/sessionStore.js +254 -0
- package/dist/workshop/workshopPin.d.ts +72 -0
- package/dist/workshop/workshopPin.js +193 -0
- package/examples/README.md +2 -1
- package/examples/browser-session/README.md +77 -0
- package/examples/browser-session/browser-session.pipeline.yaml +50 -0
- package/examples/browser-session/browser-session.task.yaml +6 -0
- package/examples/browser-session/check-login.yaml +22 -0
- package/examples/browser-session/fixture-server.mjs +64 -0
- package/examples/browser-session/human-login.yaml +31 -0
- package/examples/browser-session/merge.yaml +36 -0
- package/examples/browser-session/work-a.yaml +41 -0
- package/examples/browser-session/work-b.yaml +41 -0
- package/examples/conditional-fork/decide.yaml +1 -1
- package/examples/github-release/README.md +17 -3
- package/examples/stage-mcp/README.md +3 -2
- package/examples/stageflow.yaml +51 -0
- package/package.json +9 -4
- package/skills/stageflow/references/control-surface.md +3 -1
- package/skills/stageflow-author/references/stage-prompt-template.md +4 -4
- package/skills/stageflow-run/SKILL.md +2 -0
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +3 -1
- package/skills/stageflow-setup/SKILL.md +11 -0
- package/dist/ui/assets/index-B6hlSXXn.js +0 -120
|
@@ -2,16 +2,37 @@ export const STAGEFLOW_YAML = `version: 1
|
|
|
2
2
|
catalog:
|
|
3
3
|
pipelines:
|
|
4
4
|
- pipelines
|
|
5
|
+
- workshop
|
|
5
6
|
tasks:
|
|
6
7
|
- tasks
|
|
8
|
+
- workshop
|
|
7
9
|
patterns:
|
|
8
10
|
pipeline: "*.pipeline.yaml"
|
|
9
11
|
task: "*.task.yaml"
|
|
10
12
|
`;
|
|
11
|
-
export const
|
|
13
|
+
export const LOUD_MODEL_PLACEHOLDER = "CHANGE_ME/<provider-model>";
|
|
14
|
+
const PROVIDER_DEFAULT_MODELS = {
|
|
15
|
+
anthropic: "anthropic/claude-sonnet-4-5",
|
|
16
|
+
openrouter: "openrouter/auto",
|
|
17
|
+
cursor: "cursor/auto",
|
|
18
|
+
};
|
|
19
|
+
export function resolveInitDefaultModel(configuredProviderIds) {
|
|
20
|
+
const ids = [
|
|
21
|
+
...new Set(configuredProviderIds
|
|
22
|
+
.map((id) => id.trim().toLowerCase())
|
|
23
|
+
.filter((id) => id.length > 0)),
|
|
24
|
+
].sort((a, b) => a.localeCompare(b));
|
|
25
|
+
if (ids.length === 1) {
|
|
26
|
+
const id = ids[0];
|
|
27
|
+
return PROVIDER_DEFAULT_MODELS[id] ?? `CHANGE_ME/${id}-model`;
|
|
28
|
+
}
|
|
29
|
+
return LOUD_MODEL_PLACEHOLDER;
|
|
30
|
+
}
|
|
31
|
+
export function helloPipelineYaml(model) {
|
|
32
|
+
return `id: hello
|
|
12
33
|
stages:
|
|
13
34
|
- id: hello
|
|
14
|
-
model:
|
|
35
|
+
model: "${model}"
|
|
15
36
|
system_prompt: Say hello and emit a success envelope.
|
|
16
37
|
io:
|
|
17
38
|
input:
|
|
@@ -21,6 +42,8 @@ stages:
|
|
|
21
42
|
schema:
|
|
22
43
|
type: object
|
|
23
44
|
`;
|
|
45
|
+
}
|
|
46
|
+
export const HELLO_PIPELINE_YAML = helloPipelineYaml("anthropic/claude-sonnet-4-5");
|
|
24
47
|
export const HELLO_TASK_YAML = `id: hello
|
|
25
48
|
goal: Run the hello pipeline scaffold.
|
|
26
49
|
`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AuthInteraction } from "@earendil-works/pi-ai";
|
|
2
2
|
import { type ProviderAuthContext } from "../agent/providerAuth.js";
|
|
3
|
-
export declare const PROVIDERS_USAGE = "Usage:\n sf providers list\n sf providers status [--provider <id>]\n sf providers detect\n sf providers source [get | set
|
|
3
|
+
export declare const PROVIDERS_USAGE = "Usage:\n sf providers list\n sf providers status [--provider <id>]\n sf providers detect\n sf providers source [get | set sf_owned]\n sf providers login <providerId> [--type api_key|oauth] [--api-key-env <VAR>]\n sf providers logout <providerId>";
|
|
4
4
|
export type ProvidersCommandIo = {
|
|
5
5
|
log: (line: string) => void;
|
|
6
6
|
error: (line: string) => void;
|
|
@@ -6,7 +6,7 @@ export const PROVIDERS_USAGE = `Usage:
|
|
|
6
6
|
sf providers list
|
|
7
7
|
sf providers status [--provider <id>]
|
|
8
8
|
sf providers detect
|
|
9
|
-
sf providers source [get | set
|
|
9
|
+
sf providers source [get | set sf_owned]
|
|
10
10
|
sf providers login <providerId> [--type api_key|oauth] [--api-key-env <VAR>]
|
|
11
11
|
sf providers logout <providerId>`;
|
|
12
12
|
const defaultIo = {
|
|
@@ -167,7 +167,7 @@ export async function runProvidersCommand(args, cwd, io = {}, ctx = defaultConte
|
|
|
167
167
|
? `credentialSource=${detected.credentialSource}`
|
|
168
168
|
: "credentialSource=(unset)";
|
|
169
169
|
out.log([
|
|
170
|
-
`
|
|
170
|
+
`authConfigured=${detected.authConfigured}`,
|
|
171
171
|
sourceLine,
|
|
172
172
|
`provisional=${detected.provisional}`,
|
|
173
173
|
`bindingSource=${detected.source}`,
|
|
@@ -188,8 +188,8 @@ export async function runProvidersCommand(args, cwd, io = {}, ctx = defaultConte
|
|
|
188
188
|
}
|
|
189
189
|
if (action === "set") {
|
|
190
190
|
const value = parsed.positionals[1];
|
|
191
|
-
if (value !== "
|
|
192
|
-
out.error('source set requires
|
|
191
|
+
if (value !== "sf_owned") {
|
|
192
|
+
out.error('source set requires sf_owned');
|
|
193
193
|
out.error(PROVIDERS_USAGE);
|
|
194
194
|
return 1;
|
|
195
195
|
}
|
package/dist/cli/runsCommand.js
CHANGED
|
@@ -616,10 +616,14 @@ export async function runRunsCommand(args, options = {}) {
|
|
|
616
616
|
return 1;
|
|
617
617
|
}
|
|
618
618
|
if (parsed.json) {
|
|
619
|
-
printJson(out,
|
|
619
|
+
printJson(out, result.verification !== undefined
|
|
620
|
+
? { ok: true, verification: result.verification }
|
|
621
|
+
: { ok: true });
|
|
620
622
|
}
|
|
621
623
|
else {
|
|
622
|
-
out.log(
|
|
624
|
+
out.log(result.verification !== undefined
|
|
625
|
+
? `ok (${result.verification})`
|
|
626
|
+
: "ok");
|
|
623
627
|
}
|
|
624
628
|
return 0;
|
|
625
629
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type EnsureGlobalServiceResult } from "../server/ensureGlobalService.js";
|
|
2
|
+
export declare const TRIGGER_USAGE = "Usage:\n sf trigger list [--json]\n sf trigger show <id> [--json]\n sf trigger fire <id> [--task-inline '<json>'] [--json]";
|
|
3
|
+
export type TriggerCommandIo = {
|
|
4
|
+
log: (line: string) => void;
|
|
5
|
+
error: (line: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function runTriggerCommand(args: string[], options?: {
|
|
8
|
+
cwd?: string;
|
|
9
|
+
io?: Partial<TriggerCommandIo>;
|
|
10
|
+
hostBaseUrl?: string;
|
|
11
|
+
ensureService?: () => Promise<EnsureGlobalServiceResult>;
|
|
12
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { completeCliRun } from "./runCommand.js";
|
|
2
|
+
import { reportCliRun, writeQueuedAdmissionLine } from "./runOutput.js";
|
|
3
|
+
import { ensureGlobalService, hostBaseUrl, } from "../server/ensureGlobalService.js";
|
|
4
|
+
import { httpFireTrigger, httpGetTrigger, httpListTriggers, } from "./hostClient.js";
|
|
5
|
+
export const TRIGGER_USAGE = `Usage:
|
|
6
|
+
sf trigger list [--json]
|
|
7
|
+
sf trigger show <id> [--json]
|
|
8
|
+
sf trigger fire <id> [--task-inline '<json>'] [--json]`;
|
|
9
|
+
const defaultIo = {
|
|
10
|
+
log: (line) => console.log(line),
|
|
11
|
+
error: (line) => console.error(line),
|
|
12
|
+
};
|
|
13
|
+
function parseTriggerArgs(args) {
|
|
14
|
+
if (args.length === 0) {
|
|
15
|
+
return { help: false, json: false };
|
|
16
|
+
}
|
|
17
|
+
if (args[0] === "--help" || args[0] === "-h") {
|
|
18
|
+
return { help: true, json: false };
|
|
19
|
+
}
|
|
20
|
+
const subcommand = args[0];
|
|
21
|
+
let help = false;
|
|
22
|
+
let json = false;
|
|
23
|
+
let id;
|
|
24
|
+
let taskInline;
|
|
25
|
+
for (let i = 1; i < args.length; i++) {
|
|
26
|
+
const arg = args[i];
|
|
27
|
+
if (arg === "--help" || arg === "-h") {
|
|
28
|
+
help = true;
|
|
29
|
+
}
|
|
30
|
+
else if (arg === "--json") {
|
|
31
|
+
json = true;
|
|
32
|
+
}
|
|
33
|
+
else if (arg === "--task-inline") {
|
|
34
|
+
const value = args[++i];
|
|
35
|
+
if (value === undefined || value.length === 0) {
|
|
36
|
+
throw new Error("Missing value for --task-inline");
|
|
37
|
+
}
|
|
38
|
+
taskInline = value;
|
|
39
|
+
}
|
|
40
|
+
else if (arg.startsWith("-")) {
|
|
41
|
+
throw new Error(`Unknown flag: ${arg}`);
|
|
42
|
+
}
|
|
43
|
+
else if (id === undefined) {
|
|
44
|
+
id = arg;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { help, json, subcommand, id, taskInline };
|
|
51
|
+
}
|
|
52
|
+
function parseJsonFlag(raw, flagName) {
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
parsed = JSON.parse(raw);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new Error(`${flagName} must be valid JSON`);
|
|
59
|
+
}
|
|
60
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
61
|
+
throw new Error(`${flagName} must be a JSON object`);
|
|
62
|
+
}
|
|
63
|
+
return parsed;
|
|
64
|
+
}
|
|
65
|
+
function printJson(io, payload) {
|
|
66
|
+
io.log(JSON.stringify(payload, null, 2));
|
|
67
|
+
}
|
|
68
|
+
function usageError(io, message) {
|
|
69
|
+
if (message !== undefined)
|
|
70
|
+
io.error(message);
|
|
71
|
+
io.error(TRIGGER_USAGE);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
export async function runTriggerCommand(args, options = {}) {
|
|
75
|
+
const out = { ...defaultIo, ...options.io };
|
|
76
|
+
const base = options.hostBaseUrl ?? hostBaseUrl();
|
|
77
|
+
const ensureService = options.ensureService ?? (() => ensureGlobalService());
|
|
78
|
+
let parsed;
|
|
79
|
+
try {
|
|
80
|
+
parsed = parseTriggerArgs(args);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
84
|
+
return usageError(out, message);
|
|
85
|
+
}
|
|
86
|
+
if (parsed.help) {
|
|
87
|
+
out.error(TRIGGER_USAGE);
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
if (!parsed.subcommand) {
|
|
91
|
+
return usageError(out);
|
|
92
|
+
}
|
|
93
|
+
if (parsed.subcommand !== "list" &&
|
|
94
|
+
parsed.subcommand !== "show" &&
|
|
95
|
+
parsed.subcommand !== "fire") {
|
|
96
|
+
return usageError(out, `Unknown trigger subcommand: ${parsed.subcommand}`);
|
|
97
|
+
}
|
|
98
|
+
const ensured = await ensureService();
|
|
99
|
+
if (!ensured.ok) {
|
|
100
|
+
if (parsed.json) {
|
|
101
|
+
printJson(out, { error: ensured.message, reason: ensured.reason });
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
out.error(ensured.message);
|
|
105
|
+
}
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
const mutatingIo = out;
|
|
109
|
+
switch (parsed.subcommand) {
|
|
110
|
+
case "list": {
|
|
111
|
+
const result = await httpListTriggers(base);
|
|
112
|
+
if (!result.ok) {
|
|
113
|
+
const payload = { error: result.reason };
|
|
114
|
+
if (result.status !== undefined)
|
|
115
|
+
payload.status = result.status;
|
|
116
|
+
if (parsed.json) {
|
|
117
|
+
printJson(out, payload);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
out.error(result.reason);
|
|
121
|
+
}
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
if (parsed.json) {
|
|
125
|
+
printJson(out, { triggers: result.triggers });
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
for (const trigger of result.triggers) {
|
|
129
|
+
out.log(`${trigger.id}\t${trigger.kind}\t${trigger.enabled}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
case "show": {
|
|
135
|
+
if (!parsed.id) {
|
|
136
|
+
return usageError(out, "Missing <id>");
|
|
137
|
+
}
|
|
138
|
+
const result = await httpGetTrigger(base, parsed.id);
|
|
139
|
+
if (!result.ok) {
|
|
140
|
+
const payload = { error: result.reason };
|
|
141
|
+
if (result.status !== undefined)
|
|
142
|
+
payload.status = result.status;
|
|
143
|
+
if (parsed.json) {
|
|
144
|
+
printJson(out, payload);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
out.error(result.reason);
|
|
148
|
+
}
|
|
149
|
+
return 1;
|
|
150
|
+
}
|
|
151
|
+
if (parsed.json) {
|
|
152
|
+
printJson(out, result.trigger);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
out.log(`${result.trigger.id}\t${result.trigger.kind}\t${result.trigger.enabled}`);
|
|
156
|
+
}
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
case "fire": {
|
|
160
|
+
if (!parsed.id) {
|
|
161
|
+
return usageError(out, "Missing <id>");
|
|
162
|
+
}
|
|
163
|
+
let task;
|
|
164
|
+
if (parsed.taskInline !== undefined) {
|
|
165
|
+
try {
|
|
166
|
+
task = parseJsonFlag(parsed.taskInline, "--task-inline");
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const started = await httpFireTrigger(base, parsed.id, task);
|
|
174
|
+
if (!started.ok) {
|
|
175
|
+
return reportCliRun({ kind: "start-failure", started }, { json: parsed.json, io: mutatingIo });
|
|
176
|
+
}
|
|
177
|
+
writeQueuedAdmissionLine(started, mutatingIo);
|
|
178
|
+
return completeCliRun(started, mutatingIo, { json: parsed.json });
|
|
179
|
+
}
|
|
180
|
+
default:
|
|
181
|
+
return usageError(out, `Unknown trigger subcommand: ${parsed.subcommand}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { validateCatalog as defaultValidateCatalog, type ValidationResult } from "../config/validateCatalog.js";
|
|
2
|
-
export declare const VALIDATE_USAGE = "Usage:\n sf validate [--pipeline <path>] [--task <path>] [--strict] [--json]\n\n With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).\n --pipeline validates one pipeline file (includes uses:/include: transitively).\n --task validates one task file.";
|
|
2
|
+
export declare const VALIDATE_USAGE = "Usage:\n sf validate [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]\n\n With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).\n --pipeline validates one pipeline file (includes uses:/include: transitively).\n --task validates one task file.\n --trigger validates one trigger file, including its pipeline/task refs.";
|
|
3
3
|
export type ValidateCommandIo = {
|
|
4
4
|
log: (line: string) => void;
|
|
5
5
|
error: (line: string) => void;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { validateCatalog as defaultValidateCatalog, } from "../config/validateCatalog.js";
|
|
2
2
|
import { exitCodeForValidation, formatValidationHuman, formatValidationJson, } from "./validateOutput.js";
|
|
3
3
|
export const VALIDATE_USAGE = `Usage:
|
|
4
|
-
sf validate [--pipeline <path>] [--task <path>] [--strict] [--json]
|
|
4
|
+
sf validate [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]
|
|
5
5
|
|
|
6
6
|
With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).
|
|
7
7
|
--pipeline validates one pipeline file (includes uses:/include: transitively).
|
|
8
|
-
--task validates one task file
|
|
8
|
+
--task validates one task file.
|
|
9
|
+
--trigger validates one trigger file, including its pipeline/task refs.`;
|
|
9
10
|
const defaultIo = {
|
|
10
11
|
log: (line) => console.log(line),
|
|
11
12
|
error: (line) => console.error(line),
|
|
@@ -19,6 +20,7 @@ function parseValidateArgs(args) {
|
|
|
19
20
|
}
|
|
20
21
|
let pipeline;
|
|
21
22
|
let task;
|
|
23
|
+
let trigger;
|
|
22
24
|
let strict = false;
|
|
23
25
|
let json = false;
|
|
24
26
|
let help = false;
|
|
@@ -41,6 +43,13 @@ function parseValidateArgs(args) {
|
|
|
41
43
|
}
|
|
42
44
|
task = value;
|
|
43
45
|
}
|
|
46
|
+
else if (arg === "--trigger") {
|
|
47
|
+
const value = args[++i];
|
|
48
|
+
if (value === undefined || value.length === 0) {
|
|
49
|
+
throw new Error("Missing value for --trigger");
|
|
50
|
+
}
|
|
51
|
+
trigger = value;
|
|
52
|
+
}
|
|
44
53
|
else if (arg === "--strict") {
|
|
45
54
|
strict = true;
|
|
46
55
|
}
|
|
@@ -54,10 +63,11 @@ function parseValidateArgs(args) {
|
|
|
54
63
|
throw new Error(`Unexpected argument: ${arg}`);
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
const scopedFlagCount = [pipeline, task, trigger].filter((v) => v !== undefined).length;
|
|
67
|
+
if (scopedFlagCount > 1) {
|
|
68
|
+
throw new Error("Use at most one of --pipeline, --task, or --trigger");
|
|
59
69
|
}
|
|
60
|
-
return { help, pipeline, task, strict, json };
|
|
70
|
+
return { help, pipeline, task, trigger, strict, json };
|
|
61
71
|
}
|
|
62
72
|
export async function runValidateCommand(args, options = {}) {
|
|
63
73
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -70,13 +80,20 @@ export async function runValidateCommand(args, options = {}) {
|
|
|
70
80
|
out.error(VALIDATE_USAGE);
|
|
71
81
|
return 0;
|
|
72
82
|
}
|
|
73
|
-
const scope = parsed.pipeline
|
|
83
|
+
const scope = parsed.pipeline
|
|
84
|
+
? "pipeline"
|
|
85
|
+
: parsed.task
|
|
86
|
+
? "task"
|
|
87
|
+
: parsed.trigger
|
|
88
|
+
? "trigger"
|
|
89
|
+
: "full";
|
|
74
90
|
const result = await validateCatalogFn({
|
|
75
91
|
scope,
|
|
76
92
|
cwd,
|
|
77
93
|
projectRoot,
|
|
78
94
|
pipeline: parsed.pipeline,
|
|
79
95
|
task: parsed.task,
|
|
96
|
+
trigger: parsed.trigger,
|
|
80
97
|
strict: parsed.strict,
|
|
81
98
|
});
|
|
82
99
|
if (parsed.json) {
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { realpathSync } from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { globalAgentBackendFromManifest, resolveAgentPort } from "./agent/resolveAgentPort.js";
|
|
8
|
+
import { BROWSER_USAGE, runBrowserCommand } from "./cli/browserCommand.js";
|
|
8
9
|
import { ARTIFACT_USAGE, runArtifactCommand } from "./cli/artifactCommand.js";
|
|
9
10
|
import { ENVELOPE_USAGE, runEnvelopeCommand, } from "./cli/envelopeCommand.js";
|
|
10
11
|
import { EXPORT_RUN_USAGE, runExportRunCommand, } from "./cli/exportRunCommand.js";
|
|
@@ -17,6 +18,7 @@ import { PROVIDERS_USAGE, runProvidersCommand } from "./cli/providersCommand.js"
|
|
|
17
18
|
import { RUN_USAGE, runRunCommand } from "./cli/runCommand.js";
|
|
18
19
|
import { RUN_STAGE_USAGE, runRunStageCommand } from "./cli/runStageCommand.js";
|
|
19
20
|
import { RUNS_USAGE, runRunsCommand } from "./cli/runsCommand.js";
|
|
21
|
+
import { TRIGGER_USAGE, runTriggerCommand } from "./cli/triggerCommand.js";
|
|
20
22
|
import { resolveOperatorCatalog } from "./cli/operatorCatalog.js";
|
|
21
23
|
import { SKILLS_USAGE, runSkillsCommand } from "./cli/skillsCommand.js";
|
|
22
24
|
import { VALIDATE_USAGE, runValidateCommand } from "./cli/validateCommand.js";
|
|
@@ -67,12 +69,17 @@ const USAGE = `Usage:
|
|
|
67
69
|
sf providers list
|
|
68
70
|
sf providers status [--provider <id>]
|
|
69
71
|
sf providers detect
|
|
70
|
-
sf providers source [get | set
|
|
72
|
+
sf providers source [get | set sf_owned]
|
|
71
73
|
sf providers login <providerId> [--type api_key|oauth] [--api-key-env <VAR>]
|
|
72
74
|
sf providers logout <providerId>
|
|
73
75
|
sf skills list
|
|
74
76
|
sf skills install --from-path <dir> [--skill-name <name>]
|
|
75
77
|
sf skills install --from-zip <url-or-path> [--skill-name <name>] [--checksum sha256:<hex>]
|
|
78
|
+
sf browser profiles [--json]
|
|
79
|
+
sf browser status <name> [--json]
|
|
80
|
+
sf browser check <name> --url <url> --logged-in <glob> [--logged-out <glob>]... [--headless] [--json]
|
|
81
|
+
sf browser login <name> --url <login-url> --logged-in <glob> [--timeout-sec <n>]
|
|
82
|
+
sf browser clear <name> [--yes]
|
|
76
83
|
sf --version
|
|
77
84
|
sf -V
|
|
78
85
|
sf --help
|
|
@@ -115,9 +122,13 @@ ${EXPORT_ALL_USAGE}
|
|
|
115
122
|
|
|
116
123
|
${RUNS_USAGE}
|
|
117
124
|
|
|
125
|
+
${TRIGGER_USAGE}
|
|
126
|
+
|
|
118
127
|
${PROVIDERS_USAGE}
|
|
119
128
|
|
|
120
|
-
${SKILLS_USAGE}
|
|
129
|
+
${SKILLS_USAGE}
|
|
130
|
+
|
|
131
|
+
${BROWSER_USAGE}`;
|
|
121
132
|
function parseArgs(argv) {
|
|
122
133
|
const args = argv.slice(2);
|
|
123
134
|
if (args.length === 0) {
|
|
@@ -153,7 +164,9 @@ function parseArgs(argv) {
|
|
|
153
164
|
command === "restore" ||
|
|
154
165
|
command === "export" ||
|
|
155
166
|
command === "runs" ||
|
|
156
|
-
command === "
|
|
167
|
+
command === "trigger" ||
|
|
168
|
+
command === "skills" ||
|
|
169
|
+
command === "browser") {
|
|
157
170
|
return { help: false, command };
|
|
158
171
|
}
|
|
159
172
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -473,6 +486,11 @@ async function main(argv) {
|
|
|
473
486
|
cwd: ctx.invocationCwd,
|
|
474
487
|
});
|
|
475
488
|
}
|
|
489
|
+
if (parsed.command === "trigger") {
|
|
490
|
+
return runTriggerCommand(argv.slice(3), {
|
|
491
|
+
cwd: ctx.invocationCwd,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
476
494
|
if (parsed.command === "providers") {
|
|
477
495
|
return runProvidersCommand(argv.slice(3), ctx.invocationCwd);
|
|
478
496
|
}
|
|
@@ -482,6 +500,9 @@ async function main(argv) {
|
|
|
482
500
|
projectRoot: ctx.projectRoot,
|
|
483
501
|
});
|
|
484
502
|
}
|
|
503
|
+
if (parsed.command === "browser") {
|
|
504
|
+
return runBrowserCommand(argv.slice(3));
|
|
505
|
+
}
|
|
485
506
|
const globalAgent = globalAgentBackendFromManifest(ctx.manifest);
|
|
486
507
|
if (parsed.command === "ui") {
|
|
487
508
|
const listenHost = resolveListenHost({ flag: parsed.host });
|
|
@@ -499,6 +520,14 @@ async function main(argv) {
|
|
|
499
520
|
mcpStateless,
|
|
500
521
|
controlTokens: tokens,
|
|
501
522
|
});
|
|
523
|
+
if (host.store) {
|
|
524
|
+
try {
|
|
525
|
+
await host.store.ensureProject(ctx.projectRoot);
|
|
526
|
+
}
|
|
527
|
+
catch {
|
|
528
|
+
// The console still serves seeded catalogs when this project cannot be registered.
|
|
529
|
+
}
|
|
530
|
+
}
|
|
502
531
|
console.log(`Operator console: ${host.url}`);
|
|
503
532
|
console.log(`MCP endpoint: ${host.mcpUrl}`);
|
|
504
533
|
if (!isNoOpenEnabled(parsed.noOpen)) {
|
|
@@ -37,6 +37,7 @@ export type CatalogBrowseResult = {
|
|
|
37
37
|
export type CatalogScanPaths = {
|
|
38
38
|
pipelinePaths: string[];
|
|
39
39
|
taskPaths: string[];
|
|
40
|
+
triggerPaths: string[];
|
|
40
41
|
};
|
|
41
42
|
export declare function getCatalogScanPaths(ctx: CatalogContext): Promise<CatalogScanPaths | null>;
|
|
42
43
|
export declare function browseCatalog(invocationCwd: string | StageflowContext): Promise<CatalogBrowseResult>;
|
|
@@ -28,7 +28,7 @@ function bakedModels() {
|
|
|
28
28
|
return [...BAKED_MODEL_IDS].sort((a, b) => a.localeCompare(b));
|
|
29
29
|
}
|
|
30
30
|
function catalogReadyFromStageflow(ctx) {
|
|
31
|
-
return ctx.
|
|
31
|
+
return ctx.manifestStatus === "ok" && ctx.manifest !== null;
|
|
32
32
|
}
|
|
33
33
|
function catalogReady(ctx) {
|
|
34
34
|
return ctx.manifestStatus === "ok" && ctx.projectRoot !== null && ctx.manifest !== null;
|
|
@@ -37,11 +37,12 @@ export async function getCatalogScanPaths(ctx) {
|
|
|
37
37
|
if (!catalogReady(ctx)) {
|
|
38
38
|
return null;
|
|
39
39
|
}
|
|
40
|
-
const [pipelinePaths, taskPaths] = await Promise.all([
|
|
40
|
+
const [pipelinePaths, taskPaths, triggerPaths] = await Promise.all([
|
|
41
41
|
scanCatalogPaths(ctx.manifest, "pipeline"),
|
|
42
42
|
scanCatalogPaths(ctx.manifest, "task"),
|
|
43
|
+
scanCatalogPaths(ctx.manifest, "trigger"),
|
|
43
44
|
]);
|
|
44
|
-
return { pipelinePaths, taskPaths };
|
|
45
|
+
return { pipelinePaths, taskPaths, triggerPaths };
|
|
45
46
|
}
|
|
46
47
|
async function listTasksFromManifest(projectRoot, manifest, warnings) {
|
|
47
48
|
const filePaths = await scanCatalogPaths(manifest, "task");
|
|
@@ -122,7 +123,7 @@ export async function browseCatalog(invocationCwd) {
|
|
|
122
123
|
? await resolveStageflowContext(invocationCwd)
|
|
123
124
|
: invocationCwd;
|
|
124
125
|
const base = {
|
|
125
|
-
projectRoot: ctx.
|
|
126
|
+
projectRoot: ctx.manifestStatus === "not_git" ? null : ctx.projectRoot,
|
|
126
127
|
manifest: ctx.manifest,
|
|
127
128
|
manifestStatus: ctx.manifestStatus,
|
|
128
129
|
issues: ctx.manifestIssues,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const BROWSER_SKILL_NAME = "browser";
|
|
2
|
+
export declare function isBuiltinSkillName(name: string): boolean;
|
|
3
|
+
/** Absolute SKILL.md of a skill shipped inside the package, if present on disk. */
|
|
4
|
+
export declare function resolveBuiltinSkillFile(name: string, fromUrl?: string): string | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
export const BROWSER_SKILL_NAME = "browser";
|
|
5
|
+
const BUILTIN_SKILL_NAMES = new Set([BROWSER_SKILL_NAME]);
|
|
6
|
+
export function isBuiltinSkillName(name) {
|
|
7
|
+
return BUILTIN_SKILL_NAMES.has(name);
|
|
8
|
+
}
|
|
9
|
+
/** Absolute SKILL.md of a skill shipped inside the package, if present on disk. */
|
|
10
|
+
export function resolveBuiltinSkillFile(name, fromUrl = import.meta.url) {
|
|
11
|
+
if (!isBuiltinSkillName(name))
|
|
12
|
+
return undefined;
|
|
13
|
+
const here = path.dirname(fileURLToPath(fromUrl));
|
|
14
|
+
for (const root of [
|
|
15
|
+
path.resolve(here, "../../builtin-skills"),
|
|
16
|
+
path.resolve(here, "../../../builtin-skills"),
|
|
17
|
+
]) {
|
|
18
|
+
const file = path.join(root, name, "SKILL.md");
|
|
19
|
+
if (existsSync(file))
|
|
20
|
+
return file;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
@@ -33,7 +33,10 @@ export function resolveCatalogRelativePath(input) {
|
|
|
33
33
|
const field = input.fieldName ?? "path";
|
|
34
34
|
const registered = input.roots.map((r) => r.project_root);
|
|
35
35
|
if (path.isAbsolute(input.inputPath)) {
|
|
36
|
-
|
|
36
|
+
const rootsList = registered.length > 0
|
|
37
|
+
? registered.join(", ")
|
|
38
|
+
: "(none — register a project or use seeded examples)";
|
|
39
|
+
throw new CatalogPathError(`Absolute ${field} is not allowed on network surfaces. Use a catalog-relative path under project_root (registered or seeded roots: ${rootsList}). Local CLI may pass absolute paths and auto-registers the project folder.`, "absolute_path_not_allowed", registered);
|
|
37
40
|
}
|
|
38
41
|
const root = selectCatalogRootForStart(input.roots, input.projectRoot);
|
|
39
42
|
const absolutePath = path.resolve(root.path, input.inputPath);
|
|
@@ -47,11 +50,16 @@ export function resolveCatalogRelativePath(input) {
|
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
export function catalogPathErrorBody(err) {
|
|
50
|
-
|
|
53
|
+
const body = {
|
|
51
54
|
error: err.message,
|
|
52
55
|
code: err.code,
|
|
53
56
|
registered_roots: err.registered_roots,
|
|
54
57
|
};
|
|
58
|
+
if (err.code === "absolute_path_not_allowed") {
|
|
59
|
+
body.hint =
|
|
60
|
+
"MCP/HTTP: relative path under project_root; CLI may pass absolute paths and auto-register.";
|
|
61
|
+
}
|
|
62
|
+
return body;
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Pick the catalog root for start_run / POST /api/runs.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TriggerEvent, TriggerSchedule } from "../types/trigger.js";
|
|
2
|
+
import type { TriggerListItem } from "./triggerCatalog.js";
|
|
3
|
+
export type CreateTriggerInput = {
|
|
4
|
+
directory: string;
|
|
5
|
+
id: string;
|
|
6
|
+
pipeline: string;
|
|
7
|
+
task?: string;
|
|
8
|
+
kind: "manual" | "schedule" | "event";
|
|
9
|
+
schedule?: TriggerSchedule;
|
|
10
|
+
event?: TriggerEvent;
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type CreateTriggerParseError = {
|
|
14
|
+
ok: false;
|
|
15
|
+
status: 400;
|
|
16
|
+
error: string;
|
|
17
|
+
};
|
|
18
|
+
export type CreateTriggerResult = {
|
|
19
|
+
ok: true;
|
|
20
|
+
trigger: TriggerListItem;
|
|
21
|
+
} | {
|
|
22
|
+
ok: false;
|
|
23
|
+
status: 400 | 409 | 422 | 500;
|
|
24
|
+
error: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function parseCreateTriggerBody(body: unknown): CreateTriggerInput | CreateTriggerParseError;
|
|
27
|
+
export declare function createTrigger(rawProjectRoot: string, input: CreateTriggerInput): Promise<CreateTriggerResult>;
|