stageflow 0.2.0 → 0.8.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 +179 -14
- package/dist/agent/activity.d.ts +12 -1
- package/dist/agent/activity.js +37 -2
- package/dist/agent/activityObserver.d.ts +5 -1
- package/dist/agent/activityObserver.js +174 -11
- package/dist/agent/cursorProvider.d.ts +1 -10
- package/dist/agent/cursorProvider.js +18 -10
- package/dist/agent/fakeAgent.js +15 -7
- package/dist/agent/piAdapter.d.ts +18 -1
- package/dist/agent/piAdapter.js +115 -45
- package/dist/agent/port.d.ts +7 -0
- package/dist/agent/port.js +3 -0
- package/dist/agent/providerAuth.js +12 -7
- package/dist/catalog/displayCatalogPath.d.ts +12 -0
- package/dist/catalog/displayCatalogPath.js +28 -0
- package/dist/cli/artifactCommand.d.ts +10 -0
- package/dist/cli/artifactCommand.js +120 -0
- package/dist/cli/envelopeCommand.d.ts +32 -0
- package/dist/cli/envelopeCommand.js +285 -0
- package/dist/cli/exportRunCommand.d.ts +10 -0
- package/dist/cli/exportRunCommand.js +150 -0
- package/dist/cli/handoffFormat.d.ts +22 -0
- package/dist/cli/handoffFormat.js +61 -0
- package/dist/cli/initCommand.d.ts +9 -0
- package/dist/cli/initCommand.js +71 -0
- package/dist/cli/initTemplates.d.ts +3 -0
- package/dist/cli/initTemplates.js +19 -0
- package/dist/cli/operatorCatalog.d.ts +10 -0
- package/dist/cli/operatorCatalog.js +16 -0
- package/dist/cli/runCommand.d.ts +7 -1
- package/dist/cli/runCommand.js +83 -11
- package/dist/cli/runOutput.d.ts +4 -1
- package/dist/cli/runOutput.js +36 -8
- package/dist/cli/skillsCommand.d.ts +16 -0
- package/dist/cli/skillsCommand.js +459 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +20 -3
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +128 -22
- package/dist/config/browseCatalog.d.ts +45 -0
- package/dist/config/browseCatalog.js +170 -0
- package/dist/config/createPipeline.d.ts +12 -3
- package/dist/config/createPipeline.js +292 -100
- package/dist/config/createStage.d.ts +10 -4
- package/dist/config/createStage.js +44 -14
- package/dist/config/listConfig.d.ts +14 -19
- package/dist/config/listConfig.js +26 -191
- package/dist/config/listModelsFromManifest.d.ts +2 -0
- package/dist/config/listModelsFromManifest.js +4 -0
- package/dist/config/loadOutcome.d.ts +4 -0
- package/dist/config/loadPipeline.d.ts +1 -15
- package/dist/config/loadPipeline.js +88 -142
- package/dist/config/loadStage.d.ts +4 -0
- package/dist/config/loadStage.js +60 -32
- package/dist/config/loadStageflowManifest.d.ts +5 -0
- package/dist/config/loadStageflowManifest.js +157 -0
- package/dist/config/mergePipelineIncludes.d.ts +9 -0
- package/dist/config/mergePipelineIncludes.js +141 -0
- package/dist/config/normalizePipelineStageEntry.d.ts +18 -0
- package/dist/config/normalizePipelineStageEntry.js +210 -0
- package/dist/config/pipelineStageKeys.d.ts +4 -0
- package/dist/config/pipelineStageKeys.js +14 -0
- package/dist/config/resolveCatalogContext.d.ts +13 -0
- package/dist/config/resolveCatalogContext.js +13 -0
- package/dist/config/resolveForkEmitContext.d.ts +4 -0
- package/dist/config/resolveForkEmitContext.js +34 -0
- package/dist/config/resolvePipelineDag.d.ts +5 -1
- package/dist/config/resolvePipelineDag.js +86 -36
- package/dist/config/scanCatalogPaths.d.ts +4 -0
- package/dist/config/scanCatalogPaths.js +83 -0
- package/dist/config/validateCatalog.d.ts +22 -4
- package/dist/config/validateCatalog.js +169 -132
- package/dist/envelope/check.d.ts +2 -0
- package/dist/envelope/check.js +58 -0
- package/dist/envelope/cloneForks.d.ts +2 -0
- package/dist/envelope/cloneForks.js +62 -0
- package/dist/envelope/forkChoice.d.ts +3 -0
- package/dist/envelope/forkChoice.js +47 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/mcp/catalogTools.d.ts +3 -0
- package/dist/mcp/catalogTools.js +187 -0
- package/dist/mcp/controlTools.d.ts +3 -0
- package/dist/mcp/controlTools.js +147 -0
- package/dist/mcp/deps.d.ts +11 -0
- package/dist/mcp/deps.js +1 -0
- package/dist/mcp/projectRun.d.ts +1 -37
- package/dist/mcp/projectRun.js +1 -57
- package/dist/mcp/resources.d.ts +5 -0
- package/dist/mcp/resources.js +45 -0
- package/dist/mcp/server.d.ts +16 -3
- package/dist/mcp/server.js +159 -3
- package/dist/mcp/toolResults.d.ts +7 -0
- package/dist/mcp/toolResults.js +6 -0
- package/dist/mcp/tools.d.ts +2 -7
- package/dist/mcp/tools.js +52 -86
- package/dist/mcp/waitRun.d.ts +46 -0
- package/dist/mcp/waitRun.js +146 -0
- package/dist/mcp/waitingGates.d.ts +12 -0
- package/dist/mcp/waitingGates.js +83 -0
- package/dist/project/findProjectRoot.d.ts +2 -0
- package/dist/project/findProjectRoot.js +51 -0
- package/dist/project/globalHome.d.ts +2 -0
- package/dist/project/globalHome.js +19 -0
- package/dist/project/resolveProjectContext.d.ts +9 -0
- package/dist/project/resolveProjectContext.js +38 -0
- package/dist/project/resolveStageflowContext.d.ts +11 -0
- package/dist/project/resolveStageflowContext.js +66 -0
- package/dist/projection/projectRun.d.ts +44 -0
- package/dist/projection/projectRun.js +71 -0
- package/dist/prompt/priorEnvelope.d.ts +1 -1
- package/dist/prompt/priorEnvelope.js +4 -1
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +4 -0
- package/dist/runstore/paths.js +2 -0
- package/dist/runstore/pipelineDagSnapshot.d.ts +9 -0
- package/dist/runstore/pipelineDagSnapshot.js +90 -1
- package/dist/runstore/port.d.ts +22 -2
- package/dist/runstore/port.js +4 -1
- package/dist/runstore/runProjection.d.ts +1 -1
- package/dist/runstore/runProjection.js +25 -4
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +3 -2
- package/dist/runstore/sqlite/SqliteRunStore.js +65 -7
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +4 -1
- package/dist/runstore/stageInstanceId.d.ts +4 -0
- package/dist/runstore/stageInstanceId.js +23 -0
- package/dist/runstore/syntheticStageSnapshot.d.ts +1 -1
- package/dist/runstore/syntheticStageSnapshot.js +2 -1
- package/dist/runstore/trackProjection.js +28 -12
- package/dist/runstore/workspaceLayout.d.ts +1 -0
- package/dist/runstore/workspaceLayout.js +1 -1
- package/dist/runtime/cloneSchedule.d.ts +18 -0
- package/dist/runtime/cloneSchedule.js +233 -0
- package/dist/runtime/credentialBinding.d.ts +8 -6
- package/dist/runtime/credentialBinding.js +18 -24
- package/dist/runtime/envelopeRouting.d.ts +2 -1
- package/dist/runtime/envelopeRouting.js +80 -13
- package/dist/runtime/pipelineRunner.d.ts +3 -0
- package/dist/runtime/pipelineRunner.js +15 -1
- package/dist/runtime/pipelineScheduler.d.ts +8 -2
- package/dist/runtime/pipelineScheduler.js +215 -39
- package/dist/runtime/reloadRunCatalog.d.ts +5 -0
- package/dist/runtime/reloadRunCatalog.js +44 -0
- package/dist/runtime/resumeReconstruct.d.ts +1 -0
- package/dist/runtime/resumeReconstruct.js +31 -10
- package/dist/runtime/runChangeBus.d.ts +18 -0
- package/dist/runtime/runChangeBus.js +83 -0
- package/dist/runtime/runManager.d.ts +4 -0
- package/dist/runtime/runManager.js +36 -16
- package/dist/runtime/settingsFile.d.ts +12 -0
- package/dist/runtime/settingsFile.js +87 -6
- package/dist/runtime/stageAttemptBootstrap.d.ts +1 -0
- package/dist/runtime/stageAttemptBootstrap.js +18 -7
- package/dist/runtime/stageProcessLauncher.js +3 -0
- package/dist/runtime/stageRecovery.js +3 -1
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +17 -15
- package/dist/runtime/stageWorker.js +13 -10
- package/dist/server/bootstrap.d.ts +32 -0
- package/dist/server/bootstrap.js +56 -0
- package/dist/server/createHttpHost.d.ts +34 -0
- package/dist/server/createHttpHost.js +70 -0
- package/dist/server/http.d.ts +6 -13
- package/dist/server/http.js +297 -352
- package/dist/server/mcpHost.d.ts +22 -0
- package/dist/server/mcpHost.js +21 -0
- package/dist/server/operatorResults.d.ts +13 -0
- package/dist/server/operatorResults.js +22 -0
- package/dist/tools/emitStageEnvelope.d.ts +12 -1
- package/dist/tools/emitStageEnvelope.js +27 -1
- package/dist/types/envelope.d.ts +3 -0
- package/dist/types/forkChoice.d.ts +30 -0
- package/dist/types/forkChoice.js +1 -0
- package/dist/types/pipeline.d.ts +59 -2
- package/dist/types/stageflowManifest.d.ts +23 -0
- package/dist/types/stageflowManifest.js +1 -0
- package/dist/ui/assets/{index-DCsDopak.css → index-C3N7MXAC.css} +1 -1
- package/dist/ui/assets/index-CSoGDA3A.js +118 -0
- package/dist/ui/index.html +3 -2
- package/dist/ui/stageflow-icon.svg +12 -0
- package/package.json +8 -5
- package/skills/install-suite.sh +107 -0
- package/skills/stageflow/SKILL.md +26 -0
- package/skills/stageflow/references/control-surface.md +26 -0
- package/skills/stageflow/scripts/detect-host.mjs +54 -0
- package/skills/stageflow/scripts/detect-host.test.mjs +97 -0
- package/skills/stageflow-author/SKILL.md +58 -0
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -0
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -0
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +13 -0
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +9 -0
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +15 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -0
- package/skills/stageflow-author/references/catalog-mapping.md +131 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +29 -0
- package/skills/stageflow-author/references/stage-prompt-template.md +55 -0
- package/skills/stageflow-author/references/validate-and-report.md +38 -0
- package/skills/stageflow-delegate/SKILL.md +18 -0
- package/skills/stageflow-delegate/references/authoring-or-run.md +15 -0
- package/skills/stageflow-delegate/references/example-walkthrough.md +30 -0
- package/skills/stageflow-delegate/references/pattern-detection.md +44 -0
- package/skills/stageflow-run/SKILL.md +151 -0
- package/skills/stageflow-run/references/mcp-call.md +17 -0
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +52 -0
- package/skills/stageflow-run/scripts/mcp-call.mjs +299 -0
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +271 -0
- package/skills/stageflow-session-capture/SKILL.md +94 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +7 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +8 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +8 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +40 -0
- package/skills/stageflow-session-capture/references/transcript-sources.md +25 -0
- package/skills/stageflow-session-capture/scripts/check-provider-gate.mjs +43 -0
- package/skills/stageflow-session-capture/scripts/locate-session-transcript.mjs +141 -0
- package/skills/stageflow-session-capture/scripts/resolve-catalog-id.mjs +119 -0
- package/skills/stageflow-setup/SKILL.md +110 -0
- package/dist/ui/assets/index-Cry0Tpfx.js +0 -118
package/dist/agent/fakeAgent.js
CHANGED
|
@@ -2,9 +2,11 @@ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { assertRequiredEnvelope, isAdvancingEnvelope, } from "../envelope/check.js";
|
|
4
4
|
import { assertEnvelopePayload } from "../envelope/payloadSchema.js";
|
|
5
|
+
import { assertCloneForks } from "../envelope/cloneForks.js";
|
|
6
|
+
import { assertForkEnvelope } from "../envelope/forkChoice.js";
|
|
5
7
|
import { assertAnswerMatchesPrompt, parseAskOperatorAnswer, } from "../tools/askOperator.js";
|
|
6
8
|
import { tryParsePendingPrompt } from "../runtime/stageHitl.js";
|
|
7
|
-
import { runStageViaOpen } from "./port.js";
|
|
9
|
+
import { runtimeStageId, runStageViaOpen } from "./port.js";
|
|
8
10
|
function opaqueEqual(a, b) {
|
|
9
11
|
if (Object.is(a, b))
|
|
10
12
|
return true;
|
|
@@ -82,7 +84,7 @@ export class FakeAgent {
|
|
|
82
84
|
return answer;
|
|
83
85
|
};
|
|
84
86
|
if (behavior.type === "wait_then_emit") {
|
|
85
|
-
const loaded = loadFakeHitlResume(input.roots, input
|
|
87
|
+
const loaded = loadFakeHitlResume(input.roots, runtimeStageId(input));
|
|
86
88
|
if (loaded === "corrupt") {
|
|
87
89
|
resumeCorrupt = true;
|
|
88
90
|
}
|
|
@@ -115,7 +117,7 @@ export class FakeAgent {
|
|
|
115
117
|
});
|
|
116
118
|
};
|
|
117
119
|
const finishEmit = () => {
|
|
118
|
-
clearFakeHitlResume(input.roots, input
|
|
120
|
+
clearFakeHitlResume(input.roots, runtimeStageId(input));
|
|
119
121
|
if (behavior.type === "throw") {
|
|
120
122
|
input.onActivity?.({ event: "agent_end" });
|
|
121
123
|
return {
|
|
@@ -135,6 +137,12 @@ export class FakeAgent {
|
|
|
135
137
|
: undefined;
|
|
136
138
|
try {
|
|
137
139
|
const envelope = assertRequiredEnvelope(envelopeValue);
|
|
140
|
+
if (input.forkEmitContext !== undefined) {
|
|
141
|
+
assertForkEnvelope(envelope, input.forkEmitContext);
|
|
142
|
+
}
|
|
143
|
+
if (input.cloneEmitContext !== undefined) {
|
|
144
|
+
assertCloneForks(envelope, input.cloneEmitContext);
|
|
145
|
+
}
|
|
138
146
|
assertEnvelopePayload(envelope, input.stage.payload_schema);
|
|
139
147
|
if (!isAdvancingEnvelope(envelope)) {
|
|
140
148
|
input.onActivity?.({ event: "agent_end" });
|
|
@@ -167,7 +175,7 @@ export class FakeAgent {
|
|
|
167
175
|
}
|
|
168
176
|
};
|
|
169
177
|
return {
|
|
170
|
-
stageId: input
|
|
178
|
+
stageId: runtimeStageId(input),
|
|
171
179
|
async next() {
|
|
172
180
|
if (closed) {
|
|
173
181
|
return {
|
|
@@ -206,7 +214,7 @@ export class FakeAgent {
|
|
|
206
214
|
}
|
|
207
215
|
catch (err) {
|
|
208
216
|
input.onActivity?.({ event: "agent_end" });
|
|
209
|
-
clearFakeHitlResume(input.roots, input
|
|
217
|
+
clearFakeHitlResume(input.roots, runtimeStageId(input));
|
|
210
218
|
return {
|
|
211
219
|
status: "completed",
|
|
212
220
|
result: {
|
|
@@ -223,7 +231,7 @@ export class FakeAgent {
|
|
|
223
231
|
answer !== undefined &&
|
|
224
232
|
!opaqueEqual(answer, expected)) {
|
|
225
233
|
input.onActivity?.({ event: "agent_end" });
|
|
226
|
-
clearFakeHitlResume(input.roots, input
|
|
234
|
+
clearFakeHitlResume(input.roots, runtimeStageId(input));
|
|
227
235
|
return {
|
|
228
236
|
status: "completed",
|
|
229
237
|
result: {
|
|
@@ -237,7 +245,7 @@ export class FakeAgent {
|
|
|
237
245
|
const request = behavior.waitRequests[waitIndex];
|
|
238
246
|
waitIndex += 1;
|
|
239
247
|
armWait();
|
|
240
|
-
writeFakeHitlResume(input.roots, input
|
|
248
|
+
writeFakeHitlResume(input.roots, runtimeStageId(input), {
|
|
241
249
|
waitRequests: behavior.waitRequests,
|
|
242
250
|
expectedAnswers: behavior.expectedAnswers,
|
|
243
251
|
envelope: behavior.envelope,
|
|
@@ -2,6 +2,7 @@ import { type AgentSession, DefaultResourceLoader, SessionManager, SettingsManag
|
|
|
2
2
|
import type { StageRoots } from "../runtime/stageRoots.js";
|
|
3
3
|
import { type AskOperatorPrompt, type AskOperatorWaitBridge } from "../tools/askOperator.js";
|
|
4
4
|
import "./cursorProvider.js";
|
|
5
|
+
import { type StageActivityObserver } from "./activityObserver.js";
|
|
5
6
|
import type { AgentPort, OpaqueAnswer, StageHandle, StageHandleCloseOptions, StageRunInput, StageRunResult } from "./port.js";
|
|
6
7
|
/**
|
|
7
8
|
* Stage tool allowlist for sealed Pi sessions.
|
|
@@ -45,6 +46,21 @@ export type ConnectedAskWaitStageHandleOptions = {
|
|
|
45
46
|
* runtime never imports the channel.
|
|
46
47
|
*/
|
|
47
48
|
export declare function createConnectedAskWaitStageHandle(options: ConnectedAskWaitStageHandleOptions): StageHandle;
|
|
49
|
+
/**
|
|
50
|
+
* Extract display text from a Pi tool_execution_update partialResult.
|
|
51
|
+
* Prefers content[].text blocks; otherwise JSON-stringifies.
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractPartialResultText(partialResult: unknown): string;
|
|
54
|
+
export type RouteSessionEventToProgressOptions = {
|
|
55
|
+
observer: StageActivityObserver;
|
|
56
|
+
verbose: boolean;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Adapter-edge routing: stream deltas to the observer, map milestones to
|
|
60
|
+
* StageActivityEvent. Verbose thinking / live tool partials go to observer
|
|
61
|
+
* hooks (stderr streams + coalesced/throttled persist via onActivity).
|
|
62
|
+
*/
|
|
63
|
+
export declare function routeSessionEventToProgress(event: Record<string, unknown>, options: RouteSessionEventToProgressOptions): void;
|
|
48
64
|
export declare function composeStageUserPrompt(input: StageRunInput, emitToolName: string, emitHintOverride?: string, artifactToolName?: string): string;
|
|
49
65
|
/**
|
|
50
66
|
* DefaultResourceLoader with host/global discovery turned off.
|
|
@@ -68,6 +84,7 @@ export declare function createSealedResourceLoader(options: {
|
|
|
68
84
|
}): DefaultResourceLoader;
|
|
69
85
|
/** Stable Pi session JSONL path under the run workspace stage dir. */
|
|
70
86
|
export declare function stageSessionFilePath(roots: Pick<StageRoots, "runWorkspaceDir" | "attempt">, stageId: string): string;
|
|
87
|
+
export declare function resolveStageSessionFile(input: StageRunInput): string;
|
|
71
88
|
export declare class StageSessionReconstructError extends Error {
|
|
72
89
|
readonly stageId: string;
|
|
73
90
|
readonly sessionFile: string;
|
|
@@ -81,7 +98,7 @@ export declare class StageSessionReconstructError extends Error {
|
|
|
81
98
|
* Create or reopen the durable stage session file under the run workspace.
|
|
82
99
|
* Touches an empty file first so Pi flushes the session header immediately.
|
|
83
100
|
*/
|
|
84
|
-
export declare function createStageSessionManager(roots: StageRoots, stageId: string): Promise<SessionManager>;
|
|
101
|
+
export declare function createStageSessionManager(roots: StageRoots, stageId: string, sessionFile?: string): Promise<SessionManager>;
|
|
85
102
|
/**
|
|
86
103
|
* Open an existing stage session for post-restart reconstruct.
|
|
87
104
|
* Missing or corrupt files fail closed (KTD7) — never create a fresh session.
|
package/dist/agent/piAdapter.js
CHANGED
|
@@ -41,9 +41,9 @@ import { createAskOperatorTool, } from "../tools/askOperator.js";
|
|
|
41
41
|
import { createWriteStageArtifactTool } from "../tools/writeStageArtifact.js";
|
|
42
42
|
import "./cursorProvider.js";
|
|
43
43
|
import { findProviderSupport } from "./providerSupport.js";
|
|
44
|
-
import { mapSessionEventToActivity } from "./activity.js";
|
|
45
|
-
import { createStageActivityObserver } from "./activityObserver.js";
|
|
46
|
-
import { DEFAULT_STAGE_TIMEOUT_MS, runStageViaOpen } from "./port.js";
|
|
44
|
+
import { mapSessionEventToActivity, readActivityVerbose } from "./activity.js";
|
|
45
|
+
import { createStageActivityObserver, } from "./activityObserver.js";
|
|
46
|
+
import { DEFAULT_STAGE_TIMEOUT_MS, runtimeStageId, runStageViaOpen } from "./port.js";
|
|
47
47
|
/**
|
|
48
48
|
* Stage tool allowlist for sealed Pi sessions.
|
|
49
49
|
* Always includes `ask_operator` (R7); `write_stage_artifact` when registered
|
|
@@ -260,31 +260,98 @@ export function createConnectedAskWaitStageHandle(options) {
|
|
|
260
260
|
},
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Extract display text from a Pi tool_execution_update partialResult.
|
|
265
|
+
* Prefers content[].text blocks; otherwise JSON-stringifies.
|
|
266
|
+
*/
|
|
267
|
+
export function extractPartialResultText(partialResult) {
|
|
268
|
+
if (partialResult === undefined || partialResult === null) {
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
if (typeof partialResult === "string") {
|
|
272
|
+
return partialResult;
|
|
273
|
+
}
|
|
274
|
+
if (typeof partialResult === "object") {
|
|
275
|
+
const content = partialResult.content;
|
|
276
|
+
if (Array.isArray(content)) {
|
|
277
|
+
const parts = [];
|
|
278
|
+
for (const block of content) {
|
|
279
|
+
if (!block || typeof block !== "object")
|
|
280
|
+
continue;
|
|
281
|
+
const b = block;
|
|
282
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
283
|
+
parts.push(b.text);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (parts.length > 0) {
|
|
287
|
+
return parts.join("");
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
return JSON.stringify(partialResult);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return String(partialResult);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return String(partialResult);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Adapter-edge routing: stream deltas to the observer, map milestones to
|
|
301
|
+
* StageActivityEvent. Verbose thinking / live tool partials go to observer
|
|
302
|
+
* hooks (stderr streams + coalesced/throttled persist via onActivity).
|
|
303
|
+
*/
|
|
304
|
+
export function routeSessionEventToProgress(event, options) {
|
|
305
|
+
const { observer, verbose } = options;
|
|
306
|
+
if (event.type === "message_update") {
|
|
307
|
+
const ame = event.assistantMessageEvent;
|
|
308
|
+
if (ame && typeof ame === "object") {
|
|
309
|
+
const update = ame;
|
|
310
|
+
if (update.type === "text_delta") {
|
|
311
|
+
observer.onAssistantTextDelta(update.delta ?? "");
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (verbose && update.type === "thinking_delta") {
|
|
315
|
+
observer.onThinkingDelta(update.delta ?? "");
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (verbose &&
|
|
322
|
+
event.type === "tool_execution_update") {
|
|
323
|
+
const text = extractPartialResultText(event.partialResult);
|
|
324
|
+
if (text) {
|
|
325
|
+
observer.onToolPartialResult(text);
|
|
326
|
+
}
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (event.type === "message_end" || event.type === "agent_end") {
|
|
330
|
+
observer.onStreamBoundary();
|
|
331
|
+
}
|
|
332
|
+
if (event.type === "agent_start" ||
|
|
333
|
+
event.type === "turn_start" ||
|
|
334
|
+
event.type === "tool_execution_start") {
|
|
335
|
+
observer.onStreamBoundary();
|
|
336
|
+
}
|
|
337
|
+
const activity = mapSessionEventToActivity(event);
|
|
338
|
+
if (!activity) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
observer.onActivity(activity);
|
|
342
|
+
}
|
|
263
343
|
/**
|
|
264
344
|
* Map Pi session events to StageActivityEvent at the adapter edge, then
|
|
265
345
|
* forward to the activity observer (stderr + onActivity).
|
|
266
346
|
*/
|
|
267
347
|
function attachStageProgress(session, onActivity) {
|
|
268
348
|
const observer = createStageActivityObserver({ onActivity, writeStderr: true });
|
|
349
|
+
const verbose = readActivityVerbose();
|
|
269
350
|
const unsubscribe = session.subscribe((event) => {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
if (event.type === "message_end" || event.type === "agent_end") {
|
|
276
|
-
observer.onStreamBoundary();
|
|
277
|
-
}
|
|
278
|
-
if (event.type === "agent_start" ||
|
|
279
|
-
event.type === "turn_start" ||
|
|
280
|
-
event.type === "tool_execution_start") {
|
|
281
|
-
observer.onStreamBoundary();
|
|
282
|
-
}
|
|
283
|
-
const activity = mapSessionEventToActivity(event);
|
|
284
|
-
if (!activity) {
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
observer.onActivity(activity);
|
|
351
|
+
routeSessionEventToProgress(event, {
|
|
352
|
+
observer,
|
|
353
|
+
verbose,
|
|
354
|
+
});
|
|
288
355
|
});
|
|
289
356
|
return () => {
|
|
290
357
|
unsubscribe();
|
|
@@ -298,7 +365,7 @@ function buildUserPrompt(input, emitToolName, emitHintOverride, artifactToolName
|
|
|
298
365
|
emitHint += `\nOn status=success, payload is required and must match this JSON Schema:\n${JSON.stringify(input.stage.payload_schema, null, 2)}`;
|
|
299
366
|
}
|
|
300
367
|
const attempt = input.roots.attempt ?? 1;
|
|
301
|
-
const attemptArtifactsPath = `stages/${input
|
|
368
|
+
const attemptArtifactsPath = `stages/${runtimeStageId(input)}/attempts/${attempt}/artifacts/`;
|
|
302
369
|
const skillBaseDir = input.stage.skill !== undefined && input.skillFilePath !== undefined
|
|
303
370
|
? path.dirname(input.skillFilePath)
|
|
304
371
|
: undefined;
|
|
@@ -323,11 +390,11 @@ function buildUserPrompt(input, emitToolName, emitHintOverride, artifactToolName
|
|
|
323
390
|
: `Create factory stage artifacts under ${attemptArtifactsPath} relative to the run folder.`;
|
|
324
391
|
return [
|
|
325
392
|
`Task id: ${input.task.id}`,
|
|
326
|
-
`Stage id: ${input
|
|
393
|
+
`Stage id: ${runtimeStageId(input)}`,
|
|
327
394
|
`Goal: ${input.task.goal}`,
|
|
328
395
|
input.task.context ? `Context: ${input.task.context}` : "",
|
|
329
396
|
input.task.constraints ? `Constraints: ${input.task.constraints}` : "",
|
|
330
|
-
formatPriorEnvelope(input.priorEnvelope),
|
|
397
|
+
formatPriorEnvelope(input.priorEnvelope, input.priorEnvelopes),
|
|
331
398
|
"",
|
|
332
399
|
artifactGuidance,
|
|
333
400
|
emitHint,
|
|
@@ -423,6 +490,10 @@ export function stageSessionFilePath(roots, stageId) {
|
|
|
423
490
|
: noAttemptContext();
|
|
424
491
|
return ctx.sessionPath(roots.runWorkspaceDir, stageId);
|
|
425
492
|
}
|
|
493
|
+
export function resolveStageSessionFile(input) {
|
|
494
|
+
return (input.resumeToken ??
|
|
495
|
+
stageSessionFilePath(input.roots, runtimeStageId(input)));
|
|
496
|
+
}
|
|
426
497
|
export class StageSessionReconstructError extends Error {
|
|
427
498
|
stageId;
|
|
428
499
|
sessionFile;
|
|
@@ -437,8 +508,7 @@ export class StageSessionReconstructError extends Error {
|
|
|
437
508
|
* Create or reopen the durable stage session file under the run workspace.
|
|
438
509
|
* Touches an empty file first so Pi flushes the session header immediately.
|
|
439
510
|
*/
|
|
440
|
-
export async function createStageSessionManager(roots, stageId) {
|
|
441
|
-
const sessionFile = stageSessionFilePath(roots, stageId);
|
|
511
|
+
export async function createStageSessionManager(roots, stageId, sessionFile = stageSessionFilePath(roots, stageId)) {
|
|
442
512
|
await mkdir(path.dirname(sessionFile), { recursive: true });
|
|
443
513
|
if (!(await fileExists(sessionFile))) {
|
|
444
514
|
await writeFile(sessionFile, "");
|
|
@@ -616,7 +686,7 @@ async function prepareStageSessionWiring(input, sessionManager, existingAskWaitC
|
|
|
616
686
|
const provider = findProviderSupport(input.stage.model);
|
|
617
687
|
const capture = {};
|
|
618
688
|
const askWaitChannel = existingAskWaitChannel ?? new AskOperatorWaitChannel();
|
|
619
|
-
const emitDef = createEmitStageEnvelopeTool(capture, input.stage.payload_schema);
|
|
689
|
+
const emitDef = createEmitStageEnvelopeTool(capture, input.stage.payload_schema, input.forkEmitContext, input.cloneEmitContext);
|
|
620
690
|
const emitTool = defineTool(emitDef);
|
|
621
691
|
const askDef = createAskOperatorTool({
|
|
622
692
|
requestWait: (prompt) => askWaitChannel.requestWait(prompt),
|
|
@@ -624,7 +694,7 @@ async function prepareStageSessionWiring(input, sessionManager, existingAskWaitC
|
|
|
624
694
|
const askTool = defineTool(askDef);
|
|
625
695
|
const artifactDef = createWriteStageArtifactTool({
|
|
626
696
|
runWorkspaceDir: roots.runWorkspaceDir,
|
|
627
|
-
stageId: input
|
|
697
|
+
stageId: runtimeStageId(input),
|
|
628
698
|
attempt: roots.attempt ?? 1,
|
|
629
699
|
});
|
|
630
700
|
const artifactTool = defineTool(artifactDef);
|
|
@@ -721,18 +791,18 @@ function isStageRunResult(value) {
|
|
|
721
791
|
* Does not auto-continue the model turn — U4 owns the yield loop.
|
|
722
792
|
*/
|
|
723
793
|
export async function reconstructStageSessionForAnswer(input, answer) {
|
|
724
|
-
const sessionManager = await openStageSessionManager(input.roots, input
|
|
725
|
-
const sessionFile = ensureStageSessionFlushed(sessionManager, input
|
|
794
|
+
const sessionManager = await openStageSessionManager(input.roots, runtimeStageId(input));
|
|
795
|
+
const sessionFile = ensureStageSessionFlushed(sessionManager, runtimeStageId(input));
|
|
726
796
|
let injection;
|
|
727
797
|
try {
|
|
728
798
|
injection = injectOpaqueAnswerIntoSession(sessionManager, answer);
|
|
729
799
|
}
|
|
730
800
|
catch (err) {
|
|
731
|
-
throw new StageSessionReconstructError(`failed to inject answer into stage session: ${sessionFile}`, { stageId: input
|
|
801
|
+
throw new StageSessionReconstructError(`failed to inject answer into stage session: ${sessionFile}`, { stageId: runtimeStageId(input), sessionFile, cause: err });
|
|
732
802
|
}
|
|
733
803
|
const wiring = await prepareStageSessionWiring(input, sessionManager);
|
|
734
804
|
if (isStageRunResult(wiring)) {
|
|
735
|
-
throw new StageSessionReconstructError(wiring.ok === false ? wiring.reason : "stage session reconstruct failed", { stageId: input
|
|
805
|
+
throw new StageSessionReconstructError(wiring.ok === false ? wiring.reason : "stage session reconstruct failed", { stageId: runtimeStageId(input), sessionFile });
|
|
736
806
|
}
|
|
737
807
|
let session;
|
|
738
808
|
try {
|
|
@@ -753,7 +823,7 @@ export async function reconstructStageSessionForAnswer(input, answer) {
|
|
|
753
823
|
modelRuntime: wiring.modelRuntime,
|
|
754
824
|
});
|
|
755
825
|
if (resolved.error || !resolved.model) {
|
|
756
|
-
throw new StageSessionReconstructError(resolved.error ?? `Model not found: ${input.stage.model}`, { stageId: input
|
|
826
|
+
throw new StageSessionReconstructError(resolved.error ?? `Model not found: ${input.stage.model}`, { stageId: runtimeStageId(input), sessionFile });
|
|
757
827
|
}
|
|
758
828
|
await session.setModel(resolved.model);
|
|
759
829
|
if (resolved.thinkingLevel) {
|
|
@@ -779,7 +849,7 @@ export async function reconstructStageSessionForAnswer(input, answer) {
|
|
|
779
849
|
wiring.restoreProvider?.();
|
|
780
850
|
if (err instanceof StageSessionReconstructError)
|
|
781
851
|
throw err;
|
|
782
|
-
throw new StageSessionReconstructError(`failed to reconstruct stage session: ${err instanceof Error ? err.message : String(err)}`, { stageId: input
|
|
852
|
+
throw new StageSessionReconstructError(`failed to reconstruct stage session: ${err instanceof Error ? err.message : String(err)}`, { stageId: runtimeStageId(input), sessionFile, cause: err });
|
|
783
853
|
}
|
|
784
854
|
}
|
|
785
855
|
async function bindStageSession(input, sessionManager, wiring) {
|
|
@@ -795,7 +865,7 @@ async function bindStageSession(input, sessionManager, wiring) {
|
|
|
795
865
|
settingsManager: wiring.settingsManager,
|
|
796
866
|
});
|
|
797
867
|
const session = created.session;
|
|
798
|
-
ensureStageSessionFlushed(sessionManager, input
|
|
868
|
+
ensureStageSessionFlushed(sessionManager, runtimeStageId(input));
|
|
799
869
|
await session.bindExtensions({});
|
|
800
870
|
const resolved = resolveCliModel({
|
|
801
871
|
cliModel: input.stage.model,
|
|
@@ -830,7 +900,7 @@ export class PiAgentAdapter {
|
|
|
830
900
|
openStage(input) {
|
|
831
901
|
const timeoutMs = input.timeoutMs ?? DEFAULT_STAGE_TIMEOUT_MS;
|
|
832
902
|
const askWaitChannel = new AskOperatorWaitChannel();
|
|
833
|
-
const sessionFile =
|
|
903
|
+
const sessionFile = resolveStageSessionFile(input);
|
|
834
904
|
let sessionManager;
|
|
835
905
|
let resumeWaiting = false;
|
|
836
906
|
if (existsSync(sessionFile)) {
|
|
@@ -839,14 +909,14 @@ export class PiAgentAdapter {
|
|
|
839
909
|
}
|
|
840
910
|
catch (err) {
|
|
841
911
|
throw new StageSessionReconstructError(`stage session file corrupt or unreadable for resume: ${sessionFile}`, {
|
|
842
|
-
stageId: input
|
|
912
|
+
stageId: runtimeStageId(input),
|
|
843
913
|
sessionFile,
|
|
844
914
|
cause: err,
|
|
845
915
|
});
|
|
846
916
|
}
|
|
847
|
-
ensureStageSessionFlushed(sessionManager, input
|
|
917
|
+
ensureStageSessionFlushed(sessionManager, runtimeStageId(input));
|
|
848
918
|
if (!findOpenToolCall(sessionManager)) {
|
|
849
|
-
throw new StageSessionReconstructError(`stage session has no open tool call for resume: ${sessionFile}`, { stageId: input
|
|
919
|
+
throw new StageSessionReconstructError(`stage session has no open tool call for resume: ${sessionFile}`, { stageId: runtimeStageId(input), sessionFile });
|
|
850
920
|
}
|
|
851
921
|
resumeWaiting = true;
|
|
852
922
|
}
|
|
@@ -856,7 +926,7 @@ export class PiAgentAdapter {
|
|
|
856
926
|
let prepareError;
|
|
857
927
|
const preparePromise = (async () => {
|
|
858
928
|
if (!sessionManager) {
|
|
859
|
-
sessionManager = await createStageSessionManager(input.roots, input
|
|
929
|
+
sessionManager = await createStageSessionManager(input.roots, runtimeStageId(input), sessionFile);
|
|
860
930
|
}
|
|
861
931
|
const prepared = await prepareStageSessionWiring(input, sessionManager, askWaitChannel);
|
|
862
932
|
if (isStageRunResult(prepared)) {
|
|
@@ -908,11 +978,11 @@ export class PiAgentAdapter {
|
|
|
908
978
|
}
|
|
909
979
|
};
|
|
910
980
|
return createConnectedAskWaitStageHandle({
|
|
911
|
-
stageId: input
|
|
981
|
+
stageId: runtimeStageId(input),
|
|
912
982
|
askWaitChannel,
|
|
913
983
|
onBeforeWaitYield: () => {
|
|
914
984
|
if (sessionManager) {
|
|
915
|
-
ensureStageSessionFlushed(sessionManager, input
|
|
985
|
+
ensureStageSessionFlushed(sessionManager, runtimeStageId(input));
|
|
916
986
|
}
|
|
917
987
|
},
|
|
918
988
|
run: async () => {
|
|
@@ -925,7 +995,7 @@ export class PiAgentAdapter {
|
|
|
925
995
|
? {
|
|
926
996
|
onDeliver: (answer) => {
|
|
927
997
|
if (!sessionManager) {
|
|
928
|
-
throw new StageSessionReconstructError("stage session missing during resume deliver", { stageId: input
|
|
998
|
+
throw new StageSessionReconstructError("stage session missing during resume deliver", { stageId: runtimeStageId(input), sessionFile });
|
|
929
999
|
}
|
|
930
1000
|
injectOpaqueAnswerIntoSession(sessionManager, answer);
|
|
931
1001
|
if (session) {
|
|
@@ -935,7 +1005,7 @@ export class PiAgentAdapter {
|
|
|
935
1005
|
continueRun: async () => {
|
|
936
1006
|
return runWithTimeout(async () => {
|
|
937
1007
|
if (!session || !sessionManager) {
|
|
938
|
-
throw new StageSessionReconstructError("stage session missing during resume continue", { stageId: input
|
|
1008
|
+
throw new StageSessionReconstructError("stage session missing during resume continue", { stageId: runtimeStageId(input), sessionFile });
|
|
939
1009
|
}
|
|
940
1010
|
syncAgentMessagesFromSession(session, sessionManager);
|
|
941
1011
|
await session.agent.continue();
|
|
@@ -947,7 +1017,7 @@ export class PiAgentAdapter {
|
|
|
947
1017
|
await preparePromise.catch(() => undefined);
|
|
948
1018
|
if (closeOptions?.park) {
|
|
949
1019
|
if (sessionManager) {
|
|
950
|
-
ensureStageSessionFlushed(sessionManager, input
|
|
1020
|
+
ensureStageSessionFlushed(sessionManager, runtimeStageId(input));
|
|
951
1021
|
if (askWaitChannel.hasPending) {
|
|
952
1022
|
await repairPrematureAskOperatorClosure(sessionFile);
|
|
953
1023
|
}
|
package/dist/agent/port.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
2
|
+
import type { CloneEmitContext, ForkEmitContext } from "../types/forkChoice.js";
|
|
2
3
|
import type { StageConfig } from "../types/stage.js";
|
|
3
4
|
import type { TaskFile } from "../types/task.js";
|
|
4
5
|
import type { StageActivityEvent } from "./activity.js";
|
|
@@ -8,14 +9,20 @@ export type StageResumeToken = string;
|
|
|
8
9
|
export type StageRunInput = {
|
|
9
10
|
roots: StageRoots;
|
|
10
11
|
stage: StageConfig;
|
|
12
|
+
/** Runtime instance id (`work~2`). Defaults to `stage.id` when omitted. */
|
|
13
|
+
stageId?: string;
|
|
11
14
|
task: TaskFile;
|
|
12
15
|
priorEnvelope: StageEnvelope | null;
|
|
16
|
+
priorEnvelopes?: StageEnvelope[];
|
|
13
17
|
timeoutMs?: number;
|
|
14
18
|
resumeToken?: StageResumeToken;
|
|
15
19
|
/** Optional observe hook; HITL wait/answer uses openStage beside this. */
|
|
16
20
|
onActivity?: (event: StageActivityEvent) => void;
|
|
17
21
|
skillFilePath?: string;
|
|
22
|
+
forkEmitContext?: ForkEmitContext;
|
|
23
|
+
cloneEmitContext?: CloneEmitContext;
|
|
18
24
|
};
|
|
25
|
+
export declare function runtimeStageId(input: Pick<StageRunInput, "stage" | "stageId">): string;
|
|
19
26
|
export type StageRunResult = {
|
|
20
27
|
ok: true;
|
|
21
28
|
envelope: StageEnvelope;
|
package/dist/agent/port.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { CredentialSynchronizationError, ModelRuntime, } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { isUsableAuthFile, parseCredentialSource, piHomeAuthPath,
|
|
2
|
+
import { isUsableAuthFile, parseCredentialSource, piHomeAuthPath, resolveCredentialBinding, writeCredentialSourceToContext, } from "../runtime/credentialBinding.js";
|
|
3
|
+
import { readPersistedCredentialSourceFromContext, } from "../runtime/settingsFile.js";
|
|
4
|
+
import { resolveProjectContext } from "../project/resolveProjectContext.js";
|
|
3
5
|
export function makeMutationLock() {
|
|
4
6
|
let tail = Promise.resolve();
|
|
5
7
|
return {
|
|
@@ -245,8 +247,9 @@ export async function logoutProvider(cwd, providerId, ctx = defaultContext) {
|
|
|
245
247
|
});
|
|
246
248
|
}
|
|
247
249
|
export function detectPiHome(cwd) {
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
+
const projectCtx = resolveProjectContext(cwd);
|
|
251
|
+
const binding = resolveCredentialBinding(projectCtx);
|
|
252
|
+
const persisted = readPersistedCredentialSourceFromContext(projectCtx);
|
|
250
253
|
return {
|
|
251
254
|
piHomeUsable: isUsableAuthFile(piHomeAuthPath()),
|
|
252
255
|
...(persisted !== undefined ? { credentialSource: persisted } : {}),
|
|
@@ -255,8 +258,9 @@ export function detectPiHome(cwd) {
|
|
|
255
258
|
};
|
|
256
259
|
}
|
|
257
260
|
export function getCredentialSourceSettings(cwd) {
|
|
258
|
-
const
|
|
259
|
-
const
|
|
261
|
+
const projectCtx = resolveProjectContext(cwd);
|
|
262
|
+
const persisted = readPersistedCredentialSourceFromContext(projectCtx);
|
|
263
|
+
const binding = resolveCredentialBinding(projectCtx);
|
|
260
264
|
return {
|
|
261
265
|
...(persisted !== undefined ? { credentialSource: persisted } : {}),
|
|
262
266
|
binding: {
|
|
@@ -270,8 +274,9 @@ export function setCredentialSource(cwd, credentialSource) {
|
|
|
270
274
|
if (parsed === undefined) {
|
|
271
275
|
throw new ProviderAuthError('credentialSource must be "pi_home" or "sf_owned"', 400);
|
|
272
276
|
}
|
|
273
|
-
|
|
274
|
-
|
|
277
|
+
const projectCtx = resolveProjectContext(cwd);
|
|
278
|
+
writeCredentialSourceToContext(projectCtx, parsed);
|
|
279
|
+
const binding = resolveCredentialBinding(projectCtx);
|
|
275
280
|
return {
|
|
276
281
|
credentialSource: parsed,
|
|
277
282
|
binding: {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function displayCatalogPath(absPath: string, projectRoot?: string): string;
|
|
2
|
+
export declare function normalizeCatalogSlashes(pathValue: string): string;
|
|
3
|
+
export type PipelinePathMatchInput = {
|
|
4
|
+
pipeline_id: string;
|
|
5
|
+
pipeline_path?: string;
|
|
6
|
+
project_root?: string;
|
|
7
|
+
};
|
|
8
|
+
export type PipelineListingPath = {
|
|
9
|
+
id: string;
|
|
10
|
+
path: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function matchPipelineRun(run: PipelinePathMatchInput, pipeline: PipelineListingPath): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function displayCatalogPath(absPath, projectRoot) {
|
|
2
|
+
if (projectRoot) {
|
|
3
|
+
const root = projectRoot.replace(/\\/g, "/").replace(/\/$/, "");
|
|
4
|
+
const normalized = absPath.replace(/\\/g, "/");
|
|
5
|
+
if (normalized === root)
|
|
6
|
+
return ".";
|
|
7
|
+
const prefix = `${root}/`;
|
|
8
|
+
if (normalized.startsWith(prefix)) {
|
|
9
|
+
return normalized.slice(prefix.length);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const parts = absPath.replace(/\\/g, "/").split("/");
|
|
13
|
+
return parts[parts.length - 1] ?? absPath;
|
|
14
|
+
}
|
|
15
|
+
export function normalizeCatalogSlashes(pathValue) {
|
|
16
|
+
return pathValue.replace(/\\/g, "/");
|
|
17
|
+
}
|
|
18
|
+
export function matchPipelineRun(run, pipeline) {
|
|
19
|
+
if (run.pipeline_id === pipeline.id)
|
|
20
|
+
return true;
|
|
21
|
+
if (run.pipeline_path && run.project_root) {
|
|
22
|
+
const rel = displayCatalogPath(run.pipeline_path, run.project_root);
|
|
23
|
+
if (normalizeCatalogSlashes(rel) === normalizeCatalogSlashes(pipeline.path)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const ARTIFACT_USAGE = "Usage:\n sf artifact read --run <runId> --path <relPath> [--out <file>]";
|
|
2
|
+
export type ArtifactCommandIo = {
|
|
3
|
+
log: (line: string) => void;
|
|
4
|
+
error: (line: string) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function runArtifactCommand(args: string[], options?: {
|
|
7
|
+
cwd?: string;
|
|
8
|
+
projectRoot?: string;
|
|
9
|
+
io?: Partial<ArtifactCommandIo>;
|
|
10
|
+
}): Promise<number>;
|