pi-workflow-engine 0.10.3 → 0.12.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.
Files changed (88) hide show
  1. package/.pi/extensions/pi-workflow-engine/index.ts +418 -213
  2. package/.pi/extensions/pi-workflow-engine/src/advisory-schema.ts +11 -4
  3. package/.pi/extensions/pi-workflow-engine/src/agent-attempt.ts +147 -0
  4. package/.pi/extensions/pi-workflow-engine/src/agent-limits.ts +35 -0
  5. package/.pi/extensions/pi-workflow-engine/src/agent-replay.ts +399 -0
  6. package/.pi/extensions/pi-workflow-engine/src/agent-retry.ts +116 -0
  7. package/.pi/extensions/pi-workflow-engine/src/agent-runner-types.ts +91 -0
  8. package/.pi/extensions/pi-workflow-engine/src/agent-runner.ts +154 -530
  9. package/.pi/extensions/pi-workflow-engine/src/agent-session-identity.ts +256 -0
  10. package/.pi/extensions/pi-workflow-engine/src/agent-session-providers.ts +50 -0
  11. package/.pi/extensions/pi-workflow-engine/src/agent-session.ts +368 -0
  12. package/.pi/extensions/pi-workflow-engine/src/agent-skills.ts +87 -39
  13. package/.pi/extensions/pi-workflow-engine/src/agent-workspace.ts +89 -0
  14. package/.pi/extensions/pi-workflow-engine/src/background-workflow-tool.ts +75 -0
  15. package/.pi/extensions/pi-workflow-engine/src/background-workflows.ts +492 -0
  16. package/.pi/extensions/pi-workflow-engine/src/budget.ts +10 -3
  17. package/.pi/extensions/pi-workflow-engine/src/cancellation.ts +55 -3
  18. package/.pi/extensions/pi-workflow-engine/src/command-completions.ts +36 -0
  19. package/.pi/extensions/pi-workflow-engine/src/concurrency.ts +230 -61
  20. package/.pi/extensions/pi-workflow-engine/src/diff-capture.ts +38 -55
  21. package/.pi/extensions/pi-workflow-engine/src/discovery.ts +70 -17
  22. package/.pi/extensions/pi-workflow-engine/src/dynamax-shortcuts.ts +59 -13
  23. package/.pi/extensions/pi-workflow-engine/src/dynamax.ts +123 -63
  24. package/.pi/extensions/pi-workflow-engine/src/engine.ts +357 -75
  25. package/.pi/extensions/pi-workflow-engine/src/filesystem-error.ts +4 -0
  26. package/.pi/extensions/pi-workflow-engine/src/finalizers.ts +66 -0
  27. package/.pi/extensions/pi-workflow-engine/src/identity-canonicalization.ts +138 -0
  28. package/.pi/extensions/pi-workflow-engine/src/identity-fingerprint.ts +15 -0
  29. package/.pi/extensions/pi-workflow-engine/src/inline-workflow.ts +10 -5
  30. package/.pi/extensions/pi-workflow-engine/src/journal.ts +156 -66
  31. package/.pi/extensions/pi-workflow-engine/src/model-profile-command.ts +167 -0
  32. package/.pi/extensions/pi-workflow-engine/src/model-profiles.ts +310 -0
  33. package/.pi/extensions/pi-workflow-engine/src/options.ts +96 -6
  34. package/.pi/extensions/pi-workflow-engine/src/pi-compat.ts +32 -0
  35. package/.pi/extensions/pi-workflow-engine/src/process-runner.ts +203 -39
  36. package/.pi/extensions/pi-workflow-engine/src/progress-types.ts +50 -0
  37. package/.pi/extensions/pi-workflow-engine/src/progress.ts +74 -122
  38. package/.pi/extensions/pi-workflow-engine/src/provider-usage-limit.ts +189 -0
  39. package/.pi/extensions/pi-workflow-engine/src/replay-path-identity.ts +48 -0
  40. package/.pi/extensions/pi-workflow-engine/src/research-contract.ts +89 -0
  41. package/.pi/extensions/pi-workflow-engine/src/research-evidence.ts +289 -0
  42. package/.pi/extensions/pi-workflow-engine/src/resume-context.ts +701 -0
  43. package/.pi/extensions/pi-workflow-engine/src/review/code-review-orchestration.ts +49 -0
  44. package/.pi/extensions/pi-workflow-engine/src/review/github-pr-comments.ts +75 -16
  45. package/.pi/extensions/pi-workflow-engine/src/review/review-actions.ts +83 -17
  46. package/.pi/extensions/pi-workflow-engine/src/review/review-budget.ts +45 -0
  47. package/.pi/extensions/pi-workflow-engine/src/review/review-fix-workflow.ts +117 -0
  48. package/.pi/extensions/pi-workflow-engine/src/review/review-handoff.ts +14 -66
  49. package/.pi/extensions/pi-workflow-engine/src/review/review-issues.ts +38 -12
  50. package/.pi/extensions/pi-workflow-engine/src/review/review-report.ts +42 -0
  51. package/.pi/extensions/pi-workflow-engine/src/review/review-results-flow.ts +18 -22
  52. package/.pi/extensions/pi-workflow-engine/src/review/review-results-viewer.ts +128 -56
  53. package/.pi/extensions/pi-workflow-engine/src/review/review-session-coordinator.ts +153 -0
  54. package/.pi/extensions/pi-workflow-engine/src/review/review-snapshot.ts +294 -0
  55. package/.pi/extensions/pi-workflow-engine/src/review-diff-target.ts +130 -0
  56. package/.pi/extensions/pi-workflow-engine/src/session-identity.ts +6 -0
  57. package/.pi/extensions/pi-workflow-engine/src/structured-output.ts +32 -0
  58. package/.pi/extensions/pi-workflow-engine/src/tool-capabilities.ts +44 -0
  59. package/.pi/extensions/pi-workflow-engine/src/tool-source-identity.ts +150 -0
  60. package/.pi/extensions/pi-workflow-engine/src/tree-fingerprint.ts +401 -0
  61. package/.pi/extensions/pi-workflow-engine/src/types.ts +87 -25
  62. package/.pi/extensions/pi-workflow-engine/src/ui/dynamax-editor-decoration.ts +220 -0
  63. package/.pi/extensions/pi-workflow-engine/src/ui/workflow-format.ts +26 -6
  64. package/.pi/extensions/pi-workflow-engine/src/ui/workflow-inspector.ts +88 -46
  65. package/.pi/extensions/pi-workflow-engine/src/ui/workflow-result-renderer.ts +7 -70
  66. package/.pi/extensions/pi-workflow-engine/src/ui/workflow-viewer-layout.ts +51 -0
  67. package/.pi/extensions/pi-workflow-engine/src/ui/workflow-widget.ts +12 -67
  68. package/.pi/extensions/pi-workflow-engine/src/unknown-error.ts +8 -0
  69. package/.pi/extensions/pi-workflow-engine/src/usage.ts +124 -16
  70. package/.pi/extensions/pi-workflow-engine/src/workflow-advisory-utils.ts +23 -3
  71. package/.pi/extensions/pi-workflow-engine/src/workflow-execution.ts +121 -0
  72. package/.pi/extensions/pi-workflow-engine/src/workflow-module.ts +19 -1
  73. package/.pi/extensions/pi-workflow-engine/src/workflow-run-background.ts +72 -0
  74. package/.pi/extensions/pi-workflow-engine/src/workflow-run-controller.ts +354 -0
  75. package/.pi/extensions/pi-workflow-engine/src/workflow-run-history.ts +162 -0
  76. package/.pi/extensions/pi-workflow-engine/src/workflow-run-record.ts +632 -0
  77. package/.pi/extensions/pi-workflow-engine/src/workflow-run-store.ts +172 -0
  78. package/.pi/extensions/pi-workflow-engine/src/workflow-usage-limit-scheduler.ts +80 -0
  79. package/.pi/extensions/pi-workflow-engine/src/workflows.ts +30 -3
  80. package/.pi/extensions/pi-workflow-engine/src/worktree.ts +321 -43
  81. package/.pi/extensions/pi-workflow-engine/workflows/code-review.ts +62 -64
  82. package/.pi/extensions/pi-workflow-engine/workflows/diagnose.ts +17 -17
  83. package/.pi/extensions/pi-workflow-engine/workflows/perf-review.ts +15 -16
  84. package/.pi/extensions/pi-workflow-engine/workflows/refactor-scout.ts +15 -15
  85. package/.pi/extensions/pi-workflow-engine/workflows/research.ts +170 -0
  86. package/README.md +82 -207
  87. package/USAGE.md +295 -21
  88. package/package.json +9 -9
@@ -0,0 +1,116 @@
1
+ import { isRetryableAssistantError, type AssistantMessage } from "@earendil-works/pi-ai";
2
+ import { abortReason, throwIfAborted } from "./cancellation.ts";
3
+ import {
4
+ providerUsageLimitFromMessages,
5
+ type WorkflowProviderUsageLimitError,
6
+ } from "./provider-usage-limit.ts";
7
+
8
+ export const AGENT_RETRY_BASE_DELAY_MS = 1_000;
9
+ export const AGENT_RETRY_MAX_DELAY_MS = 30_000;
10
+ export const WORKFLOW_PROVIDER_ERROR_CODE = "WORKFLOW_PROVIDER_ERROR";
11
+
12
+ export interface AgentRetryScheduler {
13
+ sleep(delayMs: number, signal: AbortSignal | undefined): Promise<void>;
14
+ }
15
+
16
+ export interface ProviderErrorDetails {
17
+ readonly stopReason: "error";
18
+ readonly retryable: boolean;
19
+ readonly provider?: string;
20
+ readonly model?: string;
21
+ readonly api?: string;
22
+ }
23
+
24
+ /** Provider failure reconstructed from pi's terminal assistant-message metadata. */
25
+ export class WorkflowProviderError extends Error {
26
+ override readonly name = "WorkflowProviderError";
27
+ readonly code = WORKFLOW_PROVIDER_ERROR_CODE;
28
+
29
+ constructor(
30
+ message: string,
31
+ readonly details: ProviderErrorDetails,
32
+ ) {
33
+ super(message);
34
+ }
35
+
36
+ get retryable(): boolean {
37
+ return this.details.retryable;
38
+ }
39
+
40
+ toJSON(): {
41
+ readonly name: string;
42
+ readonly message: string;
43
+ readonly code: string;
44
+ readonly details: ProviderErrorDetails;
45
+ } {
46
+ return { name: this.name, message: this.message, code: this.code, details: this.details };
47
+ }
48
+ }
49
+
50
+ export const defaultAgentRetryScheduler: AgentRetryScheduler = {
51
+ async sleep(delayMs, signal) {
52
+ throwIfAborted(signal);
53
+ await new Promise<void>((resolve, reject) => {
54
+ const cleanup = () => signal?.removeEventListener("abort", onAbort);
55
+ const timer = setTimeout(() => {
56
+ cleanup();
57
+ resolve();
58
+ }, delayMs);
59
+ const onAbort = () => {
60
+ clearTimeout(timer);
61
+ cleanup();
62
+ reject(abortReason(signal));
63
+ };
64
+ signal?.addEventListener("abort", onAbort, { once: true });
65
+ if (signal?.aborted) onAbort();
66
+ });
67
+ },
68
+ };
69
+
70
+ export function agentRetryDelayMs(retryAttempt: number): number {
71
+ return Math.min(AGENT_RETRY_MAX_DELAY_MS, AGENT_RETRY_BASE_DELAY_MS * 2 ** Math.max(0, retryAttempt - 1));
72
+ }
73
+
74
+ export function providerErrorFromMessages(
75
+ messages: readonly unknown[],
76
+ options: { readonly pauseOnUsageLimit?: boolean } = {},
77
+ ): WorkflowProviderError | WorkflowProviderUsageLimitError | undefined {
78
+ const usageLimit = providerUsageLimitFromMessages(messages);
79
+ if (usageLimit && options.pauseOnUsageLimit) return usageLimit;
80
+ const message = messages.findLast(isAssistantMessage);
81
+ if (!message || message.stopReason !== "error") return undefined;
82
+ const errorMessage = typeof message.errorMessage === "string" && message.errorMessage.length > 0
83
+ ? message.errorMessage
84
+ : "Provider session ended with an unspecified error.";
85
+ const retryable = isRetryableAssistantError(message as AssistantMessage);
86
+ const provider = stringDetail(message.provider);
87
+ const model = stringDetail(message.model);
88
+ const api = stringDetail(message.api);
89
+ return new WorkflowProviderError(errorMessage, {
90
+ stopReason: "error",
91
+ retryable,
92
+ ...(provider ? { provider } : {}),
93
+ ...(model ? { model } : {}),
94
+ ...(api ? { api } : {}),
95
+ });
96
+ }
97
+
98
+ function isAssistantMessage(value: unknown): value is {
99
+ readonly role: "assistant";
100
+ readonly stopReason?: unknown;
101
+ readonly errorMessage?: unknown;
102
+ readonly provider?: unknown;
103
+ readonly model?: unknown;
104
+ readonly api?: unknown;
105
+ } {
106
+ return (
107
+ typeof value === "object" &&
108
+ value !== null &&
109
+ "role" in value &&
110
+ value.role === "assistant"
111
+ );
112
+ }
113
+
114
+ function stringDetail(value: unknown): string | undefined {
115
+ return typeof value === "string" && value.length > 0 ? value : undefined;
116
+ }
@@ -0,0 +1,91 @@
1
+ import type { Api, Model } from "@earendil-works/pi-ai";
2
+ import type {
3
+ AgentSession,
4
+ CreateAgentSessionOptions,
5
+ ModelRegistry,
6
+ } from "@earendil-works/pi-coding-agent";
7
+ import type { WorkflowBudget } from "./budget.ts";
8
+ import type { Semaphore } from "./concurrency.ts";
9
+ import type { WorkflowAgentLimiter } from "./agent-limits.ts";
10
+ import type { AgentRetryScheduler } from "./agent-retry.ts";
11
+ import type { ResolvedWorkflowModelProfiles } from "./model-profiles.ts";
12
+ import type { WorkflowJournal } from "./journal.ts";
13
+ import type { PerfSink } from "./perf.ts";
14
+ import type { AgentOptions, WorkflowProgressEvent } from "./types.ts";
15
+ import type { WorkflowUsageSink } from "./usage.ts";
16
+ import type { WorktreeBaseline, WorktreeRegistry } from "./worktree.ts";
17
+
18
+ export type AgentRunnerSession = Pick<
19
+ AgentSession,
20
+ | "messages"
21
+ | "systemPrompt"
22
+ | "model"
23
+ | "thinkingLevel"
24
+ | "prompt"
25
+ | "subscribe"
26
+ | "dispose"
27
+ | "abort"
28
+ | "getAllTools"
29
+ | "getActiveToolNames"
30
+ | "getToolDefinition"
31
+ | "setActiveToolsByName"
32
+ | "setAutoRetryEnabled"
33
+ | "getLastAssistantText"
34
+ >;
35
+
36
+ export type CreateAgentSession = (options: CreateAgentSessionOptions) => Promise<{ session: AgentRunnerSession }>;
37
+
38
+ export interface AgentProgress {
39
+ agentQueued(phase: string | undefined, label: string): number;
40
+ agentStart(phase: string | undefined, label: string, id?: number): void;
41
+ agentTool(label: string, tool: string, id?: number): void;
42
+ agentDone(label: string, id?: number): void;
43
+ agentFailed(label: string, error: unknown, id?: number): void;
44
+ event(event: WorkflowProgressEvent): void;
45
+ log(message: string): void;
46
+ }
47
+
48
+ interface RunContextBase {
49
+ cwd: string;
50
+ hostModel: Model<Api> | undefined;
51
+ semaphore: Semaphore;
52
+ agentLimiter: WorkflowAgentLimiter;
53
+ agentTimeoutMs: number;
54
+ agentRetries: number;
55
+ pauseOnProviderUsageLimit?: boolean;
56
+ resumeEditedWorkflow?: boolean;
57
+ retryScheduler: AgentRetryScheduler;
58
+ modelProfiles: ResolvedWorkflowModelProfiles;
59
+ progress: AgentProgress;
60
+ signal: AbortSignal | undefined;
61
+ perf: PerfSink;
62
+ usage: WorkflowUsageSink;
63
+ budget: WorkflowBudget;
64
+ journal: WorkflowJournal;
65
+ worktrees: WorktreeRegistry;
66
+ }
67
+
68
+ /** Shared per-run context threaded into every agent() call. */
69
+ export type RunContext = RunContextBase & (
70
+ | {
71
+ /** Production sessions inherit the host's live provider and auth state. */
72
+ modelRegistry: ModelRegistry;
73
+ createSession?: undefined;
74
+ }
75
+ | {
76
+ /** Injected test sessions bypass Pi's resource loader and therefore do not resolve skills. */
77
+ modelRegistry: Pick<ModelRegistry, "find">;
78
+ createSession: CreateAgentSession;
79
+ }
80
+ );
81
+
82
+ /** Runtime-only options. The authored WorkflowApi exposes only AgentOptions. */
83
+ export type AgentExecutionOptions = AgentOptions & {
84
+ readonly worktreeBaseline?: WorktreeBaseline;
85
+ };
86
+
87
+ export interface AgentRunTags {
88
+ readonly [key: string]: string | number;
89
+ readonly label: string;
90
+ readonly phase: string;
91
+ }