astrocode-workflow 0.1.20 → 0.1.23
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/dist/shared/paths.js +14 -2
- package/dist/ui/inject.js +5 -3
- package/dist/workflow/directives.js +8 -1
- package/package.json +1 -1
- package/src/shared/paths.ts +17 -2
- package/src/ui/inject.ts +6 -3
- package/src/workflow/directives.ts +8 -1
package/dist/shared/paths.js
CHANGED
|
@@ -42,9 +42,21 @@ export function assertInsideAstro(repoRoot, filePath) {
|
|
|
42
42
|
const absRepo = path.resolve(repoRoot);
|
|
43
43
|
const abs = path.resolve(filePath);
|
|
44
44
|
const astroRoot = path.resolve(path.join(repoRoot, ".astro"));
|
|
45
|
+
// Allow writing certain files in the repo root
|
|
46
|
+
const relPath = path.relative(repoRoot, filePath);
|
|
47
|
+
const allowedOutside = [
|
|
48
|
+
"stories.md",
|
|
49
|
+
"README.md",
|
|
50
|
+
"CHANGELOG.md",
|
|
51
|
+
"CONTRIBUTING.md",
|
|
52
|
+
"LICENSE",
|
|
53
|
+
".gitignore"
|
|
54
|
+
];
|
|
45
55
|
if (!abs.startsWith(astroRoot + path.sep) && abs !== astroRoot) {
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
// Check if it's an allowed file in repo root
|
|
57
|
+
if (!allowedOutside.includes(relPath)) {
|
|
58
|
+
throw new Error(`Refusing to write outside .astro: ${filePath} (relative: ${relPath}, astroRoot: ${astroRoot})`);
|
|
59
|
+
}
|
|
48
60
|
}
|
|
49
61
|
if (!abs.startsWith(absRepo + path.sep) && abs !== absRepo) {
|
|
50
62
|
throw new Error(`Refusing to write outside repo root: ${filePath}`);
|
package/dist/ui/inject.js
CHANGED
|
@@ -2,9 +2,11 @@ let isInjecting = false;
|
|
|
2
2
|
let queuedInjection = null;
|
|
3
3
|
export async function injectChatPrompt(opts) {
|
|
4
4
|
const { ctx, sessionId, text } = opts;
|
|
5
|
+
// Prefix to clearly indicate source as Astro agent
|
|
6
|
+
const prefixedText = `[Astro Agent]\n\n${text}`;
|
|
5
7
|
if (isInjecting) {
|
|
6
8
|
// Replace any existing queued injection (keep only latest)
|
|
7
|
-
queuedInjection = opts;
|
|
9
|
+
queuedInjection = { ...opts, text: prefixedText };
|
|
8
10
|
return;
|
|
9
11
|
}
|
|
10
12
|
isInjecting = true;
|
|
@@ -12,7 +14,7 @@ export async function injectChatPrompt(opts) {
|
|
|
12
14
|
await ctx.client.session.prompt({
|
|
13
15
|
path: { id: sessionId },
|
|
14
16
|
body: {
|
|
15
|
-
parts: [{ type: "text", text }],
|
|
17
|
+
parts: [{ type: "text", text: prefixedText }],
|
|
16
18
|
},
|
|
17
19
|
});
|
|
18
20
|
}
|
|
@@ -23,7 +25,7 @@ export async function injectChatPrompt(opts) {
|
|
|
23
25
|
const next = queuedInjection;
|
|
24
26
|
queuedInjection = null;
|
|
25
27
|
// Schedule next injection asynchronously to prevent recursion
|
|
26
|
-
setImmediate(() => injectChatPrompt(
|
|
28
|
+
setImmediate(() => injectChatPrompt({ ...queuedInjection, text: prefixedText }));
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
}
|
|
@@ -10,6 +10,8 @@ export function buildContinueDirective(opts) {
|
|
|
10
10
|
const body = clampChars(normalizeNewlines([
|
|
11
11
|
`[SYSTEM DIRECTIVE: ASTROCODE — CONTINUE]`,
|
|
12
12
|
``,
|
|
13
|
+
`This directive is injected by the Astro agent to continue the workflow.`,
|
|
14
|
+
``,
|
|
13
15
|
`Run: \`${run_id}\`${stage_key ? ` Stage: \`${stage_key}\`` : ""}`,
|
|
14
16
|
``,
|
|
15
17
|
`Next action: ${next_action}`,
|
|
@@ -34,6 +36,8 @@ export function buildBlockedDirective(opts) {
|
|
|
34
36
|
const body = normalizeNewlines([
|
|
35
37
|
`[SYSTEM DIRECTIVE: ASTROCODE — BLOCKED]`,
|
|
36
38
|
``,
|
|
39
|
+
`This directive is injected by the Astro agent indicating the workflow is blocked.`,
|
|
40
|
+
``,
|
|
37
41
|
`Run: \`${run_id}\` Stage: \`${stage_key}\``,
|
|
38
42
|
``,
|
|
39
43
|
`You are blocked. Ask the user exactly ONE question (below), then stop.`,
|
|
@@ -54,6 +58,8 @@ export function buildRepairDirective(opts) {
|
|
|
54
58
|
const body = normalizeNewlines([
|
|
55
59
|
`[SYSTEM DIRECTIVE: ASTROCODE — REPAIR]`,
|
|
56
60
|
``,
|
|
61
|
+
`This directive is injected by the Astro agent after performing a repair pass.`,
|
|
62
|
+
``,
|
|
57
63
|
`Astrocode performed a repair pass. Summarize in <= 10 lines and continue.`,
|
|
58
64
|
``,
|
|
59
65
|
`Repair report:`,
|
|
@@ -75,6 +81,8 @@ export function buildStageDirective(opts) {
|
|
|
75
81
|
const body = clampChars(normalizeNewlines([
|
|
76
82
|
`[SYSTEM DIRECTIVE: ASTROCODE — STAGE_${stageKeyUpper}]`,
|
|
77
83
|
``,
|
|
84
|
+
`This directive is injected by the Astro agent to delegate the stage task.`,
|
|
85
|
+
``,
|
|
78
86
|
`You are: \`${stage_agent_name}\``,
|
|
79
87
|
`Run: \`${run_id}\``,
|
|
80
88
|
`Story: \`${story_key}\` — ${story_title}`,
|
|
@@ -90,7 +98,6 @@ export function buildStageDirective(opts) {
|
|
|
90
98
|
` "schema_version": 1,`,
|
|
91
99
|
` "stage_key": "${stage_key}",`,
|
|
92
100
|
` "status": "ok",`,
|
|
93
|
-
` "summary": "Brief summary of work done",`,
|
|
94
101
|
` ...`,
|
|
95
102
|
` }`,
|
|
96
103
|
` ${"<!-- ASTRO_JSON_END -->"}`,
|
package/package.json
CHANGED
package/src/shared/paths.ts
CHANGED
|
@@ -61,10 +61,25 @@ export function assertInsideAstro(repoRoot: string, filePath: string) {
|
|
|
61
61
|
const absRepo = path.resolve(repoRoot);
|
|
62
62
|
const abs = path.resolve(filePath);
|
|
63
63
|
const astroRoot = path.resolve(path.join(repoRoot, ".astro"));
|
|
64
|
+
|
|
65
|
+
// Allow writing certain files in the repo root
|
|
66
|
+
const relPath = path.relative(repoRoot, filePath);
|
|
67
|
+
const allowedOutside = [
|
|
68
|
+
"stories.md",
|
|
69
|
+
"README.md",
|
|
70
|
+
"CHANGELOG.md",
|
|
71
|
+
"CONTRIBUTING.md",
|
|
72
|
+
"LICENSE",
|
|
73
|
+
".gitignore"
|
|
74
|
+
];
|
|
75
|
+
|
|
64
76
|
if (!abs.startsWith(astroRoot + path.sep) && abs !== astroRoot) {
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
// Check if it's an allowed file in repo root
|
|
78
|
+
if (!allowedOutside.includes(relPath)) {
|
|
79
|
+
throw new Error(`Refusing to write outside .astro: ${filePath} (relative: ${relPath}, astroRoot: ${astroRoot})`);
|
|
80
|
+
}
|
|
67
81
|
}
|
|
82
|
+
|
|
68
83
|
if (!abs.startsWith(absRepo + path.sep) && abs !== absRepo) {
|
|
69
84
|
throw new Error(`Refusing to write outside repo root: ${filePath}`);
|
|
70
85
|
}
|
package/src/ui/inject.ts
CHANGED
|
@@ -8,9 +8,12 @@ export async function injectChatPrompt(opts: {
|
|
|
8
8
|
}) {
|
|
9
9
|
const { ctx, sessionId, text } = opts;
|
|
10
10
|
|
|
11
|
+
// Prefix to clearly indicate source as Astro agent
|
|
12
|
+
const prefixedText = `[Astro Agent]\n\n${text}`;
|
|
13
|
+
|
|
11
14
|
if (isInjecting) {
|
|
12
15
|
// Replace any existing queued injection (keep only latest)
|
|
13
|
-
queuedInjection = opts;
|
|
16
|
+
queuedInjection = { ...opts, text: prefixedText };
|
|
14
17
|
return;
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -20,7 +23,7 @@ export async function injectChatPrompt(opts: {
|
|
|
20
23
|
await ctx.client.session.prompt({
|
|
21
24
|
path: { id: sessionId },
|
|
22
25
|
body: {
|
|
23
|
-
parts: [{ type: "text", text }],
|
|
26
|
+
parts: [{ type: "text", text: prefixedText }],
|
|
24
27
|
},
|
|
25
28
|
});
|
|
26
29
|
} finally {
|
|
@@ -30,7 +33,7 @@ export async function injectChatPrompt(opts: {
|
|
|
30
33
|
const next = queuedInjection;
|
|
31
34
|
queuedInjection = null;
|
|
32
35
|
// Schedule next injection asynchronously to prevent recursion
|
|
33
|
-
setImmediate(() => injectChatPrompt(
|
|
36
|
+
setImmediate(() => injectChatPrompt({ ...queuedInjection, text: prefixedText }));
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
}
|
|
@@ -32,6 +32,8 @@ export function buildContinueDirective(opts: {
|
|
|
32
32
|
[
|
|
33
33
|
`[SYSTEM DIRECTIVE: ASTROCODE — CONTINUE]`,
|
|
34
34
|
``,
|
|
35
|
+
`This directive is injected by the Astro agent to continue the workflow.`,
|
|
36
|
+
``,
|
|
35
37
|
`Run: \`${run_id}\`${stage_key ? ` Stage: \`${stage_key}\`` : ""}`,
|
|
36
38
|
``,
|
|
37
39
|
`Next action: ${next_action}`,
|
|
@@ -67,6 +69,8 @@ export function buildBlockedDirective(opts: {
|
|
|
67
69
|
[
|
|
68
70
|
`[SYSTEM DIRECTIVE: ASTROCODE — BLOCKED]`,
|
|
69
71
|
``,
|
|
72
|
+
`This directive is injected by the Astro agent indicating the workflow is blocked.`,
|
|
73
|
+
``,
|
|
70
74
|
`Run: \`${run_id}\` Stage: \`${stage_key}\``,
|
|
71
75
|
``,
|
|
72
76
|
`You are blocked. Ask the user exactly ONE question (below), then stop.`,
|
|
@@ -91,6 +95,8 @@ export function buildRepairDirective(opts: { report_md: string }): BuiltDirectiv
|
|
|
91
95
|
[
|
|
92
96
|
`[SYSTEM DIRECTIVE: ASTROCODE — REPAIR]`,
|
|
93
97
|
``,
|
|
98
|
+
`This directive is injected by the Astro agent after performing a repair pass.`,
|
|
99
|
+
``,
|
|
94
100
|
`Astrocode performed a repair pass. Summarize in <= 10 lines and continue.`,
|
|
95
101
|
``,
|
|
96
102
|
`Repair report:`,
|
|
@@ -130,6 +136,8 @@ export function buildStageDirective(opts: {
|
|
|
130
136
|
[
|
|
131
137
|
`[SYSTEM DIRECTIVE: ASTROCODE — STAGE_${stageKeyUpper}]`,
|
|
132
138
|
``,
|
|
139
|
+
`This directive is injected by the Astro agent to delegate the stage task.`,
|
|
140
|
+
``,
|
|
133
141
|
`You are: \`${stage_agent_name}\``,
|
|
134
142
|
`Run: \`${run_id}\``,
|
|
135
143
|
`Story: \`${story_key}\` — ${story_title}`,
|
|
@@ -145,7 +153,6 @@ export function buildStageDirective(opts: {
|
|
|
145
153
|
` "schema_version": 1,`,
|
|
146
154
|
` "stage_key": "${stage_key}",`,
|
|
147
155
|
` "status": "ok",`,
|
|
148
|
-
` "summary": "Brief summary of work done",`,
|
|
149
156
|
` ...`,
|
|
150
157
|
` }`,
|
|
151
158
|
` ${"<!-- ASTRO_JSON_END -->"}`,
|