stageflow 0.32.0 → 0.33.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 +1 -0
- package/dist/agent/fakeAgent.js +0 -6
- package/dist/agent/providerAuth.d.ts +6 -0
- package/dist/agent/providerAuth.js +50 -14
- package/dist/agent/resolveAgentPort.d.ts +2 -0
- package/dist/agent/resolveAgentPort.js +5 -1
- package/dist/config/listConfig.d.ts +0 -16
- package/dist/config/listConfig.js +0 -3
- package/dist/hosted/containment.d.ts +3 -0
- package/dist/hosted/containment.js +36 -0
- package/dist/hosted/errors.d.ts +21 -0
- package/dist/hosted/errors.js +30 -0
- package/dist/hosted/packageSkills.d.ts +3 -0
- package/dist/hosted/packageSkills.js +80 -0
- package/dist/hosted/runtime.d.ts +12 -0
- package/dist/hosted/runtime.js +596 -0
- package/dist/hosted/sequencer.d.ts +28 -0
- package/dist/hosted/sequencer.js +129 -0
- package/dist/hosted/translate.d.ts +3 -0
- package/dist/hosted/translate.js +43 -0
- package/dist/hosted/types.d.ts +108 -0
- package/dist/hosted/types.js +10 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +5 -0
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/projection/projectRun.d.ts +0 -1
- package/dist/projection/projectRun.js +0 -1
- package/dist/runtime/containerLimits.d.ts +0 -3
- package/dist/runtime/containerLimits.js +0 -5
- package/dist/runtime/credentialBinding.d.ts +3 -0
- package/dist/runtime/credentialBinding.js +9 -0
- package/dist/runtime/runRetentionSweep.d.ts +0 -2
- package/dist/runtime/runRetentionSweep.js +0 -8
- package/dist/runtime/stageRoots.js +5 -1
- package/package.json +9 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { redactString } from "../logging/redact.js";
|
|
2
|
+
import { HostedRuntimeError } from "./errors.js";
|
|
3
|
+
import { HOSTED_EVENT_SCHEMA_VERSION, } from "./types.js";
|
|
4
|
+
export class HostedEventSequencer {
|
|
5
|
+
sink;
|
|
6
|
+
context;
|
|
7
|
+
timeoutMs;
|
|
8
|
+
attempts;
|
|
9
|
+
chain = Promise.resolve();
|
|
10
|
+
held = [];
|
|
11
|
+
holding = true;
|
|
12
|
+
sequence = 0;
|
|
13
|
+
runId = "";
|
|
14
|
+
failed = false;
|
|
15
|
+
failure;
|
|
16
|
+
constructor(sink, context, timeoutMs, attempts) {
|
|
17
|
+
this.sink = sink;
|
|
18
|
+
this.context = context;
|
|
19
|
+
this.timeoutMs = timeoutMs;
|
|
20
|
+
this.attempts = attempts;
|
|
21
|
+
}
|
|
22
|
+
setRunId(runId) {
|
|
23
|
+
this.runId = runId;
|
|
24
|
+
}
|
|
25
|
+
emit(body) {
|
|
26
|
+
if (this.failed)
|
|
27
|
+
return Promise.reject(this.failureError());
|
|
28
|
+
if (this.holding) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
this.held.push({ body, resolve, reject });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return this.enqueue(body);
|
|
34
|
+
}
|
|
35
|
+
emitNow(body) {
|
|
36
|
+
if (this.failed)
|
|
37
|
+
return Promise.reject(this.failureError());
|
|
38
|
+
return this.enqueue(body);
|
|
39
|
+
}
|
|
40
|
+
release() {
|
|
41
|
+
if (!this.holding)
|
|
42
|
+
return;
|
|
43
|
+
this.holding = false;
|
|
44
|
+
const queued = this.held;
|
|
45
|
+
this.held = [];
|
|
46
|
+
for (const item of queued) {
|
|
47
|
+
const run = this.chain.then(() => this.deliver(item.body));
|
|
48
|
+
this.chain = run.then(() => undefined, () => undefined);
|
|
49
|
+
void run.then(item.resolve, item.reject);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
rejectHeld(error) {
|
|
53
|
+
this.holding = false;
|
|
54
|
+
const queued = this.held;
|
|
55
|
+
this.held = [];
|
|
56
|
+
for (const item of queued)
|
|
57
|
+
item.reject(error);
|
|
58
|
+
}
|
|
59
|
+
enqueue(body) {
|
|
60
|
+
const run = this.chain.then(() => this.deliver(body));
|
|
61
|
+
this.chain = run.then(() => undefined, () => undefined);
|
|
62
|
+
return run;
|
|
63
|
+
}
|
|
64
|
+
async deliver(body) {
|
|
65
|
+
if (this.failed)
|
|
66
|
+
throw this.failureError();
|
|
67
|
+
const sequence = ++this.sequence;
|
|
68
|
+
const event = this.envelope(body, sequence);
|
|
69
|
+
let last;
|
|
70
|
+
for (let attempt = 1; attempt <= this.attempts; attempt += 1) {
|
|
71
|
+
try {
|
|
72
|
+
await withTimeout(this.sink.onEvent(event), this.timeoutMs);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
last = error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const message = redactString(errorMessage(last));
|
|
80
|
+
this.failed = true;
|
|
81
|
+
this.failure = { eventType: event.type, sequence, message };
|
|
82
|
+
throw this.failureError();
|
|
83
|
+
}
|
|
84
|
+
envelope(body, sequence) {
|
|
85
|
+
return {
|
|
86
|
+
schemaVersion: HOSTED_EVENT_SCHEMA_VERSION,
|
|
87
|
+
eventId: `${this.context.externalAttemptId}:${sequence}`,
|
|
88
|
+
sequence,
|
|
89
|
+
occurredAt: new Date().toISOString(),
|
|
90
|
+
runId: this.runId,
|
|
91
|
+
externalRunId: this.context.externalRunId,
|
|
92
|
+
externalAttemptId: this.context.externalAttemptId,
|
|
93
|
+
packageRevision: this.context.packageRevision,
|
|
94
|
+
...(this.context.attributes !== undefined
|
|
95
|
+
? { attributes: this.context.attributes }
|
|
96
|
+
: {}),
|
|
97
|
+
...body,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
failureError() {
|
|
101
|
+
const failure = this.failure;
|
|
102
|
+
return new HostedRuntimeError(failure?.message ?? "hosted event sink failed", {
|
|
103
|
+
code: "event_sink_failed",
|
|
104
|
+
externalRunId: this.context.externalRunId,
|
|
105
|
+
externalAttemptId: this.context.externalAttemptId,
|
|
106
|
+
...(this.runId !== "" ? { runId: this.runId } : {}),
|
|
107
|
+
...(failure !== undefined
|
|
108
|
+
? { eventType: failure.eventType, sequence: failure.sequence }
|
|
109
|
+
: {}),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function errorMessage(error) {
|
|
114
|
+
return error instanceof Error ? error.message : String(error);
|
|
115
|
+
}
|
|
116
|
+
function withTimeout(work, timeoutMs) {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
const timer = setTimeout(() => {
|
|
119
|
+
reject(new Error("hosted event sink timed out"));
|
|
120
|
+
}, timeoutMs);
|
|
121
|
+
work.then(() => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
resolve();
|
|
124
|
+
}, (error) => {
|
|
125
|
+
clearTimeout(timer);
|
|
126
|
+
reject(error);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { redactString } from "../logging/redact.js";
|
|
2
|
+
const ACTIVITY_EVENTS = new Set([
|
|
3
|
+
"agent_start",
|
|
4
|
+
"agent_end",
|
|
5
|
+
"turn_start",
|
|
6
|
+
"tool_start",
|
|
7
|
+
"tool_end",
|
|
8
|
+
"tool_progress",
|
|
9
|
+
"message",
|
|
10
|
+
"operator_prompt",
|
|
11
|
+
"operator_answer",
|
|
12
|
+
]);
|
|
13
|
+
function redactActivity(event) {
|
|
14
|
+
return JSON.parse(redactString(JSON.stringify(event)));
|
|
15
|
+
}
|
|
16
|
+
export function translateStageEvent(stageId, event, attempt) {
|
|
17
|
+
if (ACTIVITY_EVENTS.has(event.event)) {
|
|
18
|
+
return {
|
|
19
|
+
type: "stage.activity",
|
|
20
|
+
stageId,
|
|
21
|
+
attempt,
|
|
22
|
+
activity: redactActivity(event),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
switch (event.event) {
|
|
26
|
+
case "started":
|
|
27
|
+
return { type: "stage.started", stageId, attempt };
|
|
28
|
+
case "waiting_for_input":
|
|
29
|
+
return { type: "stage.waiting", stageId, attempt };
|
|
30
|
+
case "succeeded":
|
|
31
|
+
return { type: "stage.succeeded", stageId, attempt };
|
|
32
|
+
case "failed":
|
|
33
|
+
case "interrupted":
|
|
34
|
+
return {
|
|
35
|
+
type: "stage.failed",
|
|
36
|
+
stageId,
|
|
37
|
+
attempt,
|
|
38
|
+
reason: redactString(event.reason),
|
|
39
|
+
};
|
|
40
|
+
default:
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { StageActivityEvent } from "../agent/activity.js";
|
|
2
|
+
import type { HostedErrorCode } from "./errors.js";
|
|
3
|
+
export declare const HOSTED_EVENT_SCHEMA_VERSION: 1;
|
|
4
|
+
/** One sink call is attempted this many times. Delivery is at least once, not exactly once. */
|
|
5
|
+
export declare const HOSTED_DELIVERY_ATTEMPTS = 2;
|
|
6
|
+
/** Bound for a single sink call. The private sink and Cloud worker own further retries. */
|
|
7
|
+
export declare const DEFAULT_EVENT_DELIVERY_TIMEOUT_MS = 10000;
|
|
8
|
+
/**
|
|
9
|
+
* After cancellation or timeout, Core waits at most this long for in-flight
|
|
10
|
+
* stage work to stop. `AgentPort` handles must stop inside `close()`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const HOSTED_CANCEL_GRACE_MS = 5000;
|
|
13
|
+
export type HostedRunContext = {
|
|
14
|
+
/** Opaque Cloud run id. Core copies it and does not interpret it. */
|
|
15
|
+
externalRunId: string;
|
|
16
|
+
/** Opaque Cloud attempt id. Core copies it and does not interpret it. */
|
|
17
|
+
externalAttemptId: string;
|
|
18
|
+
/** Revision of the package Cloud already materialized. */
|
|
19
|
+
packageRevision: string;
|
|
20
|
+
/** Extra non-secret correlation strings. */
|
|
21
|
+
attributes?: Readonly<Record<string, string>>;
|
|
22
|
+
};
|
|
23
|
+
export type HostedPipelineInput = {
|
|
24
|
+
packageRoot: string;
|
|
25
|
+
pipeline: string;
|
|
26
|
+
taskYaml: string;
|
|
27
|
+
context: HostedRunContext;
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
maxActiveStagesPerRun?: number;
|
|
30
|
+
/** Wall-clock limit for the hosted run. Omit for no hosted-level limit. */
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
};
|
|
33
|
+
export type HostedExecutionReceipt = {
|
|
34
|
+
coreVersion: string;
|
|
35
|
+
eventSchemaVersion: typeof HOSTED_EVENT_SCHEMA_VERSION;
|
|
36
|
+
packageRevision: string;
|
|
37
|
+
executionMode: "inline";
|
|
38
|
+
startedAt: string;
|
|
39
|
+
finishedAt: string;
|
|
40
|
+
};
|
|
41
|
+
export type HostedPipelineResult = {
|
|
42
|
+
/** Null when the run failed before Core created a local run. */
|
|
43
|
+
runId: string | null;
|
|
44
|
+
externalRunId: string;
|
|
45
|
+
externalAttemptId: string;
|
|
46
|
+
status: "succeeded" | "failed" | "cancelled" | "waiting";
|
|
47
|
+
code?: HostedErrorCode;
|
|
48
|
+
reason?: string;
|
|
49
|
+
/** Present once a local run exists. Caller exports artifacts from here. */
|
|
50
|
+
workspaceDir?: string;
|
|
51
|
+
receipt: HostedExecutionReceipt;
|
|
52
|
+
};
|
|
53
|
+
export type HostedEventEnvelope = {
|
|
54
|
+
schemaVersion: typeof HOSTED_EVENT_SCHEMA_VERSION;
|
|
55
|
+
eventId: string;
|
|
56
|
+
sequence: number;
|
|
57
|
+
occurredAt: string;
|
|
58
|
+
runId: string;
|
|
59
|
+
externalRunId: string;
|
|
60
|
+
externalAttemptId: string;
|
|
61
|
+
packageRevision: string;
|
|
62
|
+
attributes?: Readonly<Record<string, string>>;
|
|
63
|
+
};
|
|
64
|
+
export type HostedRunEvent = HostedEventEnvelope & ({
|
|
65
|
+
type: "run.created";
|
|
66
|
+
} | {
|
|
67
|
+
type: "run.started";
|
|
68
|
+
} | {
|
|
69
|
+
type: "stage.started";
|
|
70
|
+
stageId: string;
|
|
71
|
+
attempt: number;
|
|
72
|
+
} | {
|
|
73
|
+
type: "stage.activity";
|
|
74
|
+
stageId: string;
|
|
75
|
+
attempt: number;
|
|
76
|
+
activity: StageActivityEvent;
|
|
77
|
+
} | {
|
|
78
|
+
type: "stage.waiting";
|
|
79
|
+
stageId: string;
|
|
80
|
+
attempt: number;
|
|
81
|
+
} | {
|
|
82
|
+
type: "stage.succeeded";
|
|
83
|
+
stageId: string;
|
|
84
|
+
attempt: number;
|
|
85
|
+
} | {
|
|
86
|
+
type: "stage.failed";
|
|
87
|
+
stageId: string;
|
|
88
|
+
attempt: number;
|
|
89
|
+
reason?: string;
|
|
90
|
+
} | {
|
|
91
|
+
type: "run.succeeded";
|
|
92
|
+
receipt: HostedExecutionReceipt;
|
|
93
|
+
} | {
|
|
94
|
+
type: "run.failed";
|
|
95
|
+
code?: HostedErrorCode;
|
|
96
|
+
reason?: string;
|
|
97
|
+
receipt: HostedExecutionReceipt;
|
|
98
|
+
} | {
|
|
99
|
+
type: "run.cancelled";
|
|
100
|
+
reason?: string;
|
|
101
|
+
receipt: HostedExecutionReceipt;
|
|
102
|
+
});
|
|
103
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
104
|
+
export type HostedEventBody = DistributiveOmit<HostedRunEvent, keyof HostedEventEnvelope>;
|
|
105
|
+
export interface HostedEventSink {
|
|
106
|
+
onEvent(event: HostedRunEvent): Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const HOSTED_EVENT_SCHEMA_VERSION = 1;
|
|
2
|
+
/** One sink call is attempted this many times. Delivery is at least once, not exactly once. */
|
|
3
|
+
export const HOSTED_DELIVERY_ATTEMPTS = 2;
|
|
4
|
+
/** Bound for a single sink call. The private sink and Cloud worker own further retries. */
|
|
5
|
+
export const DEFAULT_EVENT_DELIVERY_TIMEOUT_MS = 10_000;
|
|
6
|
+
/**
|
|
7
|
+
* After cancellation or timeout, Core waits at most this long for in-flight
|
|
8
|
+
* stage work to stop. `AgentPort` handles must stop inside `close()`.
|
|
9
|
+
*/
|
|
10
|
+
export const HOSTED_CANCEL_GRACE_MS = 5_000;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,17 @@ export { resolveStageflowContext, projectContextFromStageflow, type StageflowCon
|
|
|
5
5
|
export { PACKAGE_NAME, PACKAGE_VERSION } from "./package-meta.js";
|
|
6
6
|
export type { StageEnvelope } from "./types/envelope.js";
|
|
7
7
|
export { assertRequiredEnvelope, isAdvancingEnvelope, } from "./envelope/check.js";
|
|
8
|
-
export type { AgentPort } from "./agent/port.js";
|
|
8
|
+
export type { AgentPort, StageHandle, StageHandleEvent, StageRunInput, StageRunResult, } from "./agent/port.js";
|
|
9
|
+
export { createPiAgentPort } from "./agent/resolveAgentPort.js";
|
|
10
|
+
export { configurePiProviderApiKey } from "./agent/providerAuth.js";
|
|
9
11
|
export type { StageActivityEvent, StageLogLine } from "./agent/activity.js";
|
|
10
12
|
export type { StageRoots } from "./runtime/stageRoots.js";
|
|
11
13
|
export { runPipeline, startPipeline } from "./runtime/pipelineRunner.js";
|
|
14
|
+
export { createHostedRuntime, type HostedRuntime, } from "./hosted/runtime.js";
|
|
15
|
+
export { HostedRuntimeError, HOSTED_ERROR_CODES } from "./hosted/errors.js";
|
|
16
|
+
export type { HostedErrorCode } from "./hosted/errors.js";
|
|
17
|
+
export { HOSTED_EVENT_SCHEMA_VERSION, HOSTED_DELIVERY_ATTEMPTS, DEFAULT_EVENT_DELIVERY_TIMEOUT_MS, HOSTED_CANCEL_GRACE_MS, } from "./hosted/types.js";
|
|
18
|
+
export type { HostedRunContext, HostedPipelineInput, HostedPipelineResult, HostedExecutionReceipt, HostedEventEnvelope, HostedRunEvent, HostedEventSink, } from "./hosted/types.js";
|
|
12
19
|
export { createRunStore } from "./runstore/createStore.js";
|
|
13
20
|
export type { RunStoreConfig, RunStoreKind } from "./runstore/createStore.js";
|
|
14
21
|
export type { RunStore, RunSummary, RunDetail, RunMeta, RunStatus, StageSnapshot, StageLogEvent, CreatedRun, } from "./runstore/port.js";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,12 @@ export { resolveProjectContext, legacyProjectContext, } from "./project/resolveP
|
|
|
4
4
|
export { resolveStageflowContext, projectContextFromStageflow, } from "./project/resolveStageflowContext.js";
|
|
5
5
|
export { PACKAGE_NAME, PACKAGE_VERSION } from "./package-meta.js";
|
|
6
6
|
export { assertRequiredEnvelope, isAdvancingEnvelope, } from "./envelope/check.js";
|
|
7
|
+
export { createPiAgentPort } from "./agent/resolveAgentPort.js";
|
|
8
|
+
export { configurePiProviderApiKey } from "./agent/providerAuth.js";
|
|
7
9
|
export { runPipeline, startPipeline } from "./runtime/pipelineRunner.js";
|
|
10
|
+
export { createHostedRuntime, } from "./hosted/runtime.js";
|
|
11
|
+
export { HostedRuntimeError, HOSTED_ERROR_CODES } from "./hosted/errors.js";
|
|
12
|
+
export { HOSTED_EVENT_SCHEMA_VERSION, HOSTED_DELIVERY_ATTEMPTS, DEFAULT_EVENT_DELIVERY_TIMEOUT_MS, HOSTED_CANCEL_GRACE_MS, } from "./hosted/types.js";
|
|
8
13
|
export { createRunStore } from "./runstore/createStore.js";
|
|
9
14
|
export { deriveStatusFromStages } from "./runstore/port.js";
|
|
10
15
|
export { RunManager } from "./runtime/runManager.js";
|
package/dist/package-meta.d.ts
CHANGED
package/dist/package-meta.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os from "node:os";
|
|
2
1
|
export type ContainerLimits = {
|
|
3
2
|
memoryLimitBytes: number | undefined;
|
|
4
3
|
maxActiveStageProcesses: number;
|
|
@@ -12,5 +11,3 @@ export declare function readContainerMemoryLimit(roots?: readonly string[]): {
|
|
|
12
11
|
export declare function deriveContainerLimits(memoryLimitBytes: number | undefined, source?: ContainerLimits["source"]): ContainerLimits;
|
|
13
12
|
export declare function getContainerLimits(): ContainerLimits;
|
|
14
13
|
export declare function resetContainerLimitsForTests(): void;
|
|
15
|
-
/** Test hook: prove sizing never consults os.totalmem. */
|
|
16
|
-
export declare function assertNoOsTotalmemInSizing(): typeof os.totalmem;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
const HOST_RESERVE_MIB = 512;
|
|
4
3
|
const WORKER_BUDGET_MIB = 512;
|
|
5
4
|
const MAX_CAP = 8;
|
|
@@ -78,7 +77,3 @@ export function getContainerLimits() {
|
|
|
78
77
|
export function resetContainerLimitsForTests() {
|
|
79
78
|
cached = undefined;
|
|
80
79
|
}
|
|
81
|
-
/** Test hook: prove sizing never consults os.totalmem. */
|
|
82
|
-
export function assertNoOsTotalmemInSizing() {
|
|
83
|
-
return os.totalmem;
|
|
84
|
-
}
|
|
@@ -19,5 +19,8 @@ export declare function stageflowAgentAuthPath(override?: string): string;
|
|
|
19
19
|
export declare function piHomeAuthPath(override?: string): string;
|
|
20
20
|
export declare function isUsableAuthFile(authPath: string): boolean;
|
|
21
21
|
export declare function ensureSfOwnedAuthStore(): string;
|
|
22
|
+
/** Use this auth file for credential binding and do not create the operator home. */
|
|
23
|
+
export declare function runWithExplicitAuthPath<T>(authPath: string, fn: () => Promise<T>): Promise<T>;
|
|
24
|
+
export declare function currentExplicitAuthPath(): string | undefined;
|
|
22
25
|
export declare function resolveCredentialBinding(ctx: ProjectContext | string, _options?: ResolveCredentialBindingOptions): CredentialBinding;
|
|
23
26
|
export { readCredentialSourceFromFile, writeCredentialSourceToFile, } from "./settingsFile.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { ensureGlobalHome } from "../project/globalHome.js";
|
|
4
5
|
import { resolveProjectContext, } from "../project/resolveProjectContext.js";
|
|
@@ -53,6 +54,14 @@ export function ensureSfOwnedAuthStore() {
|
|
|
53
54
|
}
|
|
54
55
|
return authPath;
|
|
55
56
|
}
|
|
57
|
+
const explicitAuthPath = new AsyncLocalStorage();
|
|
58
|
+
/** Use this auth file for credential binding and do not create the operator home. */
|
|
59
|
+
export function runWithExplicitAuthPath(authPath, fn) {
|
|
60
|
+
return explicitAuthPath.run(path.resolve(authPath), fn);
|
|
61
|
+
}
|
|
62
|
+
export function currentExplicitAuthPath() {
|
|
63
|
+
return explicitAuthPath.getStore();
|
|
64
|
+
}
|
|
56
65
|
export function resolveCredentialBinding(ctx, _options = {}) {
|
|
57
66
|
const projectCtx = typeof ctx === "string" ? resolveProjectContext(ctx) : ctx;
|
|
58
67
|
const persisted = readCredentialSourceFromContext(projectCtx);
|
|
@@ -15,8 +15,6 @@ export type RunRetentionSweepOptions = {
|
|
|
15
15
|
artifactMaxBytes?: number;
|
|
16
16
|
bareCacheTtlMs?: number;
|
|
17
17
|
};
|
|
18
|
-
export declare function getSlimWalkCallCount(): number;
|
|
19
|
-
export declare function resetSlimWalkCallCount(): void;
|
|
20
18
|
/**
|
|
21
19
|
* Walk attempt + legacy artifact trees and remove SLIM-eligible paths.
|
|
22
20
|
* Never removes envelope.json, log.jsonl, or under-threshold artifacts.
|
|
@@ -7,13 +7,6 @@ import { reclaimWorkspaceBinding, worktreePathForRun, } from "./repositoryMateri
|
|
|
7
7
|
import { deleteRunEverywhere } from "./runDeletion.js";
|
|
8
8
|
const SLIM_ATTEMPT_FILES = ["pi-session.jsonl", "stream.log"];
|
|
9
9
|
const SLIM_ATTEMPT_DIRS = [".pi-agent"];
|
|
10
|
-
let slimWalkCallCount = 0;
|
|
11
|
-
export function getSlimWalkCallCount() {
|
|
12
|
-
return slimWalkCallCount;
|
|
13
|
-
}
|
|
14
|
-
export function resetSlimWalkCallCount() {
|
|
15
|
-
slimWalkCallCount = 0;
|
|
16
|
-
}
|
|
17
10
|
async function pathExists(target) {
|
|
18
11
|
try {
|
|
19
12
|
await stat(target);
|
|
@@ -84,7 +77,6 @@ async function slimAttemptDir(attemptDir, maxBytes) {
|
|
|
84
77
|
* Never removes envelope.json, log.jsonl, or under-threshold artifacts.
|
|
85
78
|
*/
|
|
86
79
|
export async function slimRunWorkspaceArtifacts(workspaceDir, maxBytes) {
|
|
87
|
-
slimWalkCallCount += 1;
|
|
88
80
|
const stagesRoot = path.join(workspaceDir, "stages");
|
|
89
81
|
if (!(await pathExists(stagesRoot)))
|
|
90
82
|
return;
|
|
@@ -3,7 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { isCursorModelRef } from "../agent/cursorProvider.js";
|
|
4
4
|
import { stageDir } from "../runstore/paths.js";
|
|
5
5
|
import { noAttemptContext } from "./stageAttemptContext.js";
|
|
6
|
-
import { resolveCredentialBinding } from "./credentialBinding.js";
|
|
6
|
+
import { resolveCredentialBinding, currentExplicitAuthPath } from "./credentialBinding.js";
|
|
7
7
|
export const STAGEFLOW_CHECKOUT = "STAGEFLOW_CHECKOUT";
|
|
8
8
|
export const STAGEFLOW_RUN_WORKSPACE = "STAGEFLOW_RUN_WORKSPACE";
|
|
9
9
|
export const STAGEFLOW_REPOSITORY = "STAGEFLOW_REPOSITORY";
|
|
@@ -127,6 +127,10 @@ export function stageBindingEnvFromRun(options) {
|
|
|
127
127
|
export function withResolvedAuthPath(roots, factoryCwd) {
|
|
128
128
|
if (roots.authPath)
|
|
129
129
|
return roots;
|
|
130
|
+
const explicit = currentExplicitAuthPath();
|
|
131
|
+
if (explicit !== undefined) {
|
|
132
|
+
return { ...roots, authPath: explicit };
|
|
133
|
+
}
|
|
130
134
|
const binding = resolveCredentialBinding(factoryCwd);
|
|
131
135
|
return { ...roots, authPath: binding.authPath };
|
|
132
136
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stageflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Stageflow — CLI pipeline runtime for configurable stages on Pi",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
6
14
|
"bin": {
|
|
7
15
|
"sf": "./dist/cli.js",
|
|
8
16
|
"stageflow": "./dist/cli.js"
|