agentweaver 0.1.17 → 0.1.18
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 +104 -23
- package/dist/artifacts.js +41 -0
- package/dist/index.js +252 -27
- package/dist/interactive/controller.js +249 -13
- package/dist/interactive/ink/index.js +2 -2
- package/dist/interactive/state.js +1 -0
- package/dist/interactive/web/index.js +179 -0
- package/dist/interactive/web/protocol.js +154 -0
- package/dist/interactive/web/server.js +575 -0
- package/dist/interactive/web/static/app.js +709 -0
- package/dist/interactive/web/static/index.html +77 -0
- package/dist/interactive/web/static/styles.css +2 -0
- package/dist/interactive/web/static/styles.input.css +469 -0
- package/dist/pipeline/flow-catalog.js +4 -0
- package/dist/pipeline/flow-specs/auto-common-guided.json +313 -0
- package/dist/pipeline/flow-specs/auto-common.json +3 -1
- package/dist/pipeline/flow-specs/design-review/design-review-loop.json +2 -0
- package/dist/pipeline/flow-specs/design-review.json +2 -0
- package/dist/pipeline/flow-specs/implement.json +3 -1
- package/dist/pipeline/flow-specs/plan.json +4 -0
- package/dist/pipeline/flow-specs/playbook-init.json +199 -0
- package/dist/pipeline/flow-specs/review/review-fix.json +3 -1
- package/dist/pipeline/flow-specs/review/review-loop.json +4 -0
- package/dist/pipeline/flow-specs/review/review.json +2 -0
- package/dist/pipeline/node-registry.js +45 -0
- package/dist/pipeline/nodes/flow-run-node.js +13 -1
- package/dist/pipeline/nodes/playbook-ensure-node.js +115 -0
- package/dist/pipeline/nodes/playbook-inventory-node.js +51 -0
- package/dist/pipeline/nodes/playbook-questions-form-node.js +166 -0
- package/dist/pipeline/nodes/playbook-write-node.js +243 -0
- package/dist/pipeline/nodes/project-guidance-node.js +69 -0
- package/dist/pipeline/prompt-registry.js +4 -1
- package/dist/pipeline/prompt-runtime.js +6 -2
- package/dist/pipeline/spec-types.js +19 -0
- package/dist/pipeline/value-resolver.js +39 -1
- package/dist/playbook/practice-candidates.js +12 -0
- package/dist/playbook/repo-inventory.js +208 -0
- package/dist/prompts.js +31 -0
- package/dist/runtime/playbook.js +485 -0
- package/dist/runtime/project-guidance.js +339 -0
- package/dist/structured-artifact-schema-registry.js +8 -0
- package/dist/structured-artifact-schemas.json +235 -0
- package/dist/structured-artifacts.js +7 -1
- package/docs/declarative-workflows.md +565 -0
- package/docs/features.md +77 -0
- package/docs/playbook.md +327 -0
- package/package.json +8 -3
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const ACTION_TYPES = new Set([
|
|
2
|
+
"flow.select",
|
|
3
|
+
"folder.toggle",
|
|
4
|
+
"run.openConfirm",
|
|
5
|
+
"confirm.select",
|
|
6
|
+
"confirm.accept",
|
|
7
|
+
"confirm.cancel",
|
|
8
|
+
"form.update",
|
|
9
|
+
"form.fieldUpdate",
|
|
10
|
+
"form.submit",
|
|
11
|
+
"form.cancel",
|
|
12
|
+
"interrupt.openConfirm",
|
|
13
|
+
"flow.interrupt",
|
|
14
|
+
"log.clear",
|
|
15
|
+
"help.toggle",
|
|
16
|
+
"scroll",
|
|
17
|
+
]);
|
|
18
|
+
const SCROLL_PANES = new Set(["flows", "progress", "summary", "log", "help"]);
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function optionalActionId(value) {
|
|
23
|
+
if (value.actionId === undefined) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value.actionId !== "string" || value.actionId.trim().length === 0) {
|
|
27
|
+
throw new Error("actionId must be a non-empty string when provided.");
|
|
28
|
+
}
|
|
29
|
+
return value.actionId;
|
|
30
|
+
}
|
|
31
|
+
function requireNonEmptyString(value, fieldName) {
|
|
32
|
+
const field = value[fieldName];
|
|
33
|
+
if (typeof field !== "string" || field.trim().length === 0) {
|
|
34
|
+
throw new Error(`${fieldName} must be a non-empty string.`);
|
|
35
|
+
}
|
|
36
|
+
return field;
|
|
37
|
+
}
|
|
38
|
+
function optionalNonEmptyString(value, fieldName) {
|
|
39
|
+
if (value[fieldName] === undefined) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return requireNonEmptyString(value, fieldName);
|
|
43
|
+
}
|
|
44
|
+
function optionalInteger(value, fieldName) {
|
|
45
|
+
if (value[fieldName] === undefined) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
const field = value[fieldName];
|
|
49
|
+
if (typeof field !== "number" || !Number.isInteger(field)) {
|
|
50
|
+
throw new Error(`${fieldName} must be an integer.`);
|
|
51
|
+
}
|
|
52
|
+
return field;
|
|
53
|
+
}
|
|
54
|
+
function requireValues(value, fieldName = "values") {
|
|
55
|
+
const values = value[fieldName];
|
|
56
|
+
if (!isRecord(values)) {
|
|
57
|
+
throw new Error(`${fieldName} must be an object.`);
|
|
58
|
+
}
|
|
59
|
+
return values;
|
|
60
|
+
}
|
|
61
|
+
export function parseClientAction(raw) {
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(raw);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new Error("Protocol message must be valid JSON.");
|
|
68
|
+
}
|
|
69
|
+
if (!isRecord(parsed) || typeof parsed.type !== "string") {
|
|
70
|
+
throw new Error("Protocol message requires a string type.");
|
|
71
|
+
}
|
|
72
|
+
if (!ACTION_TYPES.has(parsed.type)) {
|
|
73
|
+
throw new Error(`Unknown protocol action: ${parsed.type}`);
|
|
74
|
+
}
|
|
75
|
+
const actionId = optionalActionId(parsed);
|
|
76
|
+
if (parsed.type === "flow.select") {
|
|
77
|
+
const index = optionalInteger(parsed, "index");
|
|
78
|
+
const key = optionalNonEmptyString(parsed, "key");
|
|
79
|
+
if (index === undefined && key === undefined) {
|
|
80
|
+
throw new Error("flow.select requires index or key.");
|
|
81
|
+
}
|
|
82
|
+
return { type: "flow.select", ...(index !== undefined ? { index } : {}), ...(key ? { key } : {}), ...(actionId ? { actionId } : {}) };
|
|
83
|
+
}
|
|
84
|
+
if (parsed.type === "folder.toggle") {
|
|
85
|
+
return { type: "folder.toggle", key: requireNonEmptyString(parsed, "key"), ...(actionId ? { actionId } : {}) };
|
|
86
|
+
}
|
|
87
|
+
if (parsed.type === "run.openConfirm") {
|
|
88
|
+
const flowId = optionalNonEmptyString(parsed, "flowId");
|
|
89
|
+
const key = optionalNonEmptyString(parsed, "key");
|
|
90
|
+
return { type: "run.openConfirm", ...(flowId ? { flowId } : {}), ...(key ? { key } : {}), ...(actionId ? { actionId } : {}) };
|
|
91
|
+
}
|
|
92
|
+
if (parsed.type === "confirm.select") {
|
|
93
|
+
return { type: "confirm.select", action: requireNonEmptyString(parsed, "action"), ...(actionId ? { actionId } : {}) };
|
|
94
|
+
}
|
|
95
|
+
if (parsed.type === "confirm.accept") {
|
|
96
|
+
const action = optionalNonEmptyString(parsed, "action");
|
|
97
|
+
return { type: "confirm.accept", ...(action ? { action } : {}), ...(actionId ? { actionId } : {}) };
|
|
98
|
+
}
|
|
99
|
+
if (parsed.type === "confirm.cancel" || parsed.type === "form.cancel" || parsed.type === "log.clear") {
|
|
100
|
+
return { type: parsed.type, ...(actionId ? { actionId } : {}) };
|
|
101
|
+
}
|
|
102
|
+
if (parsed.type === "form.update") {
|
|
103
|
+
return { type: "form.update", values: requireValues(parsed), ...(actionId ? { actionId } : {}) };
|
|
104
|
+
}
|
|
105
|
+
if (parsed.type === "form.fieldUpdate") {
|
|
106
|
+
const fieldId = requireNonEmptyString(parsed, "fieldId");
|
|
107
|
+
if (!("value" in parsed)) {
|
|
108
|
+
throw new Error("value is required.");
|
|
109
|
+
}
|
|
110
|
+
const value = parsed.value;
|
|
111
|
+
if (typeof value !== "string"
|
|
112
|
+
&& typeof value !== "boolean"
|
|
113
|
+
&& (!Array.isArray(value) || value.some((item) => typeof item !== "string"))) {
|
|
114
|
+
throw new Error("value must be a string, boolean, or string array.");
|
|
115
|
+
}
|
|
116
|
+
return { type: "form.fieldUpdate", fieldId, value, ...(actionId ? { actionId } : {}) };
|
|
117
|
+
}
|
|
118
|
+
if (parsed.type === "form.submit") {
|
|
119
|
+
return {
|
|
120
|
+
type: "form.submit",
|
|
121
|
+
...(parsed.values !== undefined ? { values: requireValues(parsed) } : {}),
|
|
122
|
+
...(actionId ? { actionId } : {}),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (parsed.type === "interrupt.openConfirm") {
|
|
126
|
+
return { type: "interrupt.openConfirm", ...(actionId ? { actionId } : {}) };
|
|
127
|
+
}
|
|
128
|
+
if (parsed.type === "flow.interrupt") {
|
|
129
|
+
const flowId = optionalNonEmptyString(parsed, "flowId");
|
|
130
|
+
return { type: "flow.interrupt", ...(flowId ? { flowId } : {}), ...(actionId ? { actionId } : {}) };
|
|
131
|
+
}
|
|
132
|
+
if (parsed.type === "help.toggle") {
|
|
133
|
+
if (parsed.visible !== undefined && typeof parsed.visible !== "boolean") {
|
|
134
|
+
throw new Error("visible must be a boolean when provided.");
|
|
135
|
+
}
|
|
136
|
+
return { type: "help.toggle", ...(parsed.visible !== undefined ? { visible: parsed.visible } : {}), ...(actionId ? { actionId } : {}) };
|
|
137
|
+
}
|
|
138
|
+
const pane = requireNonEmptyString(parsed, "pane");
|
|
139
|
+
if (!SCROLL_PANES.has(pane)) {
|
|
140
|
+
throw new Error("scroll pane must be one of flows, progress, summary, log, or help.");
|
|
141
|
+
}
|
|
142
|
+
const delta = optionalInteger(parsed, "delta");
|
|
143
|
+
const offset = optionalInteger(parsed, "offset");
|
|
144
|
+
if (delta === undefined && offset === undefined) {
|
|
145
|
+
throw new Error("scroll requires delta or offset.");
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
type: "scroll",
|
|
149
|
+
pane: pane,
|
|
150
|
+
...(delta !== undefined ? { delta } : {}),
|
|
151
|
+
...(offset !== undefined ? { offset } : {}),
|
|
152
|
+
...(actionId ? { actionId } : {}),
|
|
153
|
+
};
|
|
154
|
+
}
|