@signalridge/pi-workflows 1.7.1 → 1.7.3
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/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/skills/workflow-authoring/SKILL.md +1 -1
- package/skills/workflow-authoring/references/capabilities.md +1 -1
- package/skills/workflow-authoring/references/capability-details.md +1 -1
- package/skills/workflow-patterns/SKILL.md +1 -1
- package/skills/workflow-review/SKILL.md +1 -1
- package/src/arming.ts +10 -0
- package/src/index.ts +37 -1
- package/src/runtime.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.7.3
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- e04f729: Remove repeated copies of the workflow arming reminder while preserving other input hooks.
|
|
7
|
+
|
|
8
|
+
## 1.7.2
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 919655f: Yield before live agent dispatch so synchronous managed-spawn setup cannot be interrupted by the script bootstrap watchdog before promise tracking is attached. Preserve lexical call identity and reservations, check cancellation after yielding, and retain the 1000ms script watchdog. Add real Node process regressions for slow setup, runaway scripts, and pending-spawn cleanup.
|
|
12
|
+
|
|
3
13
|
## 1.7.1
|
|
4
14
|
### Patch Changes
|
|
5
15
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: workflow-authoring
|
|
3
3
|
description: Design, write, review, and debug Pi JavaScript workflows that coordinate multiple subagents. Use when a request needs named dependencies, bounded fan-out, per-item pipelines, quality gates, saved or nested workflows, pause/resume, or workflow progress; do not use it merely to run an existing named workflow.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "1.7.
|
|
5
|
+
version: "1.7.3"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Workflow authoring
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Workflow capability index
|
|
3
3
|
|
|
4
4
|
Contract format: `2.0.0`<br>
|
|
5
|
-
Contract content / skill / extension: `1.7.
|
|
5
|
+
Contract content / skill / extension: `1.7.3`
|
|
6
6
|
|
|
7
7
|
This compact generated index covers supported runtime globals and workflow-tool inputs. For constraints, compatibility behavior, internal boundaries, and dynamic-reference ownership, follow the [exhaustive generated facts](capability-details.md).
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Exhaustive workflow capability facts
|
|
3
3
|
|
|
4
4
|
Contract format: `2.0.0`<br>
|
|
5
|
-
Contract content / skill / extension: `1.7.
|
|
5
|
+
Contract content / skill / extension: `1.7.3`
|
|
6
6
|
|
|
7
7
|
Every exact fact below is projected from the installed extension's capability contract. Explanatory judgment belongs in the hand-written references next to this file.
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: workflow-patterns
|
|
3
3
|
description: Choose and run one of Pi's built-in multi-agent workflows for research, adversarial review, code review, multi-perspective analysis, or codebase auditing. Use when the request matches a named pattern; use workflow-authoring instead for a new script or custom topology.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "1.7.
|
|
5
|
+
version: "1.7.3"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Built-in workflow patterns
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: workflow-review
|
|
3
3
|
description: Audit an existing Pi JavaScript workflow for topology, prompt/data flow, limits, failure handling, cancellation, resume safety, and publication compatibility. Use when reviewing or debugging a workflow script or saved run; do not use to run a standard named workflow.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "1.7.
|
|
5
|
+
version: "1.7.3"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Workflow review
|
package/src/arming.ts
CHANGED
|
@@ -29,6 +29,16 @@ export const DEFAULT_TRIGGER_WORD = "workflow";
|
|
|
29
29
|
export const WORKFLOW_ARMED_DIRECTIVE =
|
|
30
30
|
"<system-reminder>You typed the workflow trigger word, which counts as an explicit opt-in to multi-agent orchestration: the `workflow` tool is authorized for this turn. It runs in the background by default — the turn ends and the result is delivered back into the conversation when it finishes, which is expected rather than a stall, so you need not stay and block. Pass background:false only when the user is waiting for the result inline. This is permission, not an instruction: if the request is conversational, trivial, or better answered directly, answer it directly and do not run a workflow.</system-reminder>";
|
|
31
31
|
|
|
32
|
+
/** Keep one copy when an earlier input transform already added this directive. */
|
|
33
|
+
export function deduplicateWorkflowDirective(text: string): string {
|
|
34
|
+
let seen = false;
|
|
35
|
+
return text.replaceAll(WORKFLOW_ARMED_DIRECTIVE, (directive) => {
|
|
36
|
+
if (seen) return "";
|
|
37
|
+
seen = true;
|
|
38
|
+
return directive;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
function escapeRegExp(text: string): string {
|
|
33
43
|
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34
44
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,12 @@ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@e
|
|
|
3
3
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { Text } from "@earendil-works/pi-tui";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_TRIGGER_WORD,
|
|
8
|
+
deduplicateWorkflowDirective,
|
|
9
|
+
hasTriggerWord,
|
|
10
|
+
WORKFLOW_ARMED_DIRECTIVE,
|
|
11
|
+
} from "./arming.js";
|
|
7
12
|
import { BUILTIN_WORKFLOWS, validateBuiltinArgs } from "./builtins.js";
|
|
8
13
|
import { type CommandResult, resolveCodeReviewScope } from "./code-review-scope.js";
|
|
9
14
|
import { type ScriptStartOptions, type ScriptStartResult, WorkflowEngine, WorkflowWaitAbortedError } from "./engine.js";
|
|
@@ -952,6 +957,14 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
952
957
|
// question. Nothing is swallowed and no UI opens.
|
|
953
958
|
pi.on("input", (event) => {
|
|
954
959
|
if (event.source === "extension") return { action: "continue" as const };
|
|
960
|
+
const deduplicatedText = deduplicateWorkflowDirective(event.text);
|
|
961
|
+
if (deduplicatedText !== event.text) {
|
|
962
|
+
return {
|
|
963
|
+
action: "transform" as const,
|
|
964
|
+
text: deduplicatedText,
|
|
965
|
+
...(event.images ? { images: event.images } : {}),
|
|
966
|
+
};
|
|
967
|
+
}
|
|
955
968
|
const explicitTrigger = keywordTriggerEnabled && hasTriggerWord(event.text, triggerKeyword);
|
|
956
969
|
const substantive = effortLevel !== "off" && event.text.trim().length >= 16 && !event.text.trim().startsWith("/");
|
|
957
970
|
if (!explicitTrigger && !substantive) return { action: "continue" as const };
|
|
@@ -969,6 +982,29 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
969
982
|
};
|
|
970
983
|
});
|
|
971
984
|
|
|
985
|
+
// Input transforms can be chained with handlers loaded after this package.
|
|
986
|
+
// Normalize only our own repeated marker again at the final context boundary;
|
|
987
|
+
// unrelated plugin content and hooks remain untouched.
|
|
988
|
+
pi.on("context", (event) => {
|
|
989
|
+
type UserMessage = Extract<(typeof event.messages)[number], { role: "user" }>;
|
|
990
|
+
let lastUserIndex = -1;
|
|
991
|
+
let lastUserMessage: UserMessage | undefined;
|
|
992
|
+
for (let index = 0; index < event.messages.length; index += 1) {
|
|
993
|
+
const message = event.messages[index];
|
|
994
|
+
if (message && "role" in message && message.role === "user") {
|
|
995
|
+
lastUserIndex = index;
|
|
996
|
+
lastUserMessage = message;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
const message = lastUserMessage;
|
|
1000
|
+
if (lastUserIndex < 0 || !message || !("content" in message) || typeof message.content !== "string") return;
|
|
1001
|
+
const deduplicatedText = deduplicateWorkflowDirective(message.content);
|
|
1002
|
+
if (deduplicatedText === message.content) return;
|
|
1003
|
+
const messages = event.messages.slice();
|
|
1004
|
+
messages[lastUserIndex] = { ...message, content: deduplicatedText };
|
|
1005
|
+
return { messages };
|
|
1006
|
+
});
|
|
1007
|
+
|
|
972
1008
|
// Standing effort mode mirrors the reference: it auto-arms substantive
|
|
973
1009
|
// interactive messages but remains guidance, not an inferred spend ceiling.
|
|
974
1010
|
pi.registerCommand("effort", {
|
package/src/runtime.ts
CHANGED
|
@@ -1606,6 +1606,16 @@ export async function runWorkflow<T = unknown>(
|
|
|
1606
1606
|
shared.physicalAgentCount++;
|
|
1607
1607
|
|
|
1608
1608
|
return limiter(async () => {
|
|
1609
|
+
// Keep lexical identity, scope, thread ownership and cap reservations above
|
|
1610
|
+
// synchronous, but leave the timed VM bootstrap before invoking host code.
|
|
1611
|
+
// Even an immediately available limiter slot must yield: synchronous spawn
|
|
1612
|
+
// setup can outlast the script watchdog and interrupt RPC promise creation
|
|
1613
|
+
// before its callers attach rejection/cleanup handlers. The returned call
|
|
1614
|
+
// is now tracked before dispatch, and a bootstrap timeout cancels it here.
|
|
1615
|
+
await Promise.resolve();
|
|
1616
|
+
throwIfAborted();
|
|
1617
|
+
if (batch?.cancelled) throw agentLimitError();
|
|
1618
|
+
|
|
1609
1619
|
const timeout = agentOptions.timeoutMs !== undefined ? agentOptions.timeoutMs : agentTimeoutMs;
|
|
1610
1620
|
const retryAttempts = normalizeAgentRetries(agentOptions.retries ?? options.agentRetries ?? 0);
|
|
1611
1621
|
const maxAttempts = retryAttempts + 1;
|