astrocode-workflow 0.4.0 → 0.4.2
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/index.js +6 -0
- package/dist/shared/metrics.d.ts +66 -0
- package/dist/shared/metrics.js +112 -0
- package/dist/src/agents/commands.d.ts +9 -0
- package/dist/src/agents/commands.js +121 -0
- package/dist/src/agents/prompts.d.ts +3 -0
- package/dist/src/agents/prompts.js +232 -0
- package/dist/src/agents/registry.d.ts +6 -0
- package/dist/src/agents/registry.js +242 -0
- package/dist/src/agents/types.d.ts +14 -0
- package/dist/src/agents/types.js +8 -0
- package/dist/src/astro/workflow-runner.d.ts +11 -0
- package/dist/src/astro/workflow-runner.js +14 -0
- package/dist/src/config/config-handler.d.ts +4 -0
- package/dist/src/config/config-handler.js +46 -0
- package/dist/src/config/defaults.d.ts +3 -0
- package/dist/src/config/defaults.js +3 -0
- package/dist/src/config/loader.d.ts +11 -0
- package/dist/src/config/loader.js +82 -0
- package/dist/src/config/schema.d.ts +195 -0
- package/dist/src/config/schema.js +224 -0
- package/dist/src/hooks/continuation-enforcer.d.ts +34 -0
- package/dist/src/hooks/continuation-enforcer.js +190 -0
- package/dist/src/hooks/inject-provider.d.ts +27 -0
- package/dist/src/hooks/inject-provider.js +189 -0
- package/dist/src/hooks/tool-output-truncator.d.ts +25 -0
- package/dist/src/hooks/tool-output-truncator.js +57 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +307 -0
- package/dist/src/shared/deep-merge.d.ts +8 -0
- package/dist/src/shared/deep-merge.js +25 -0
- package/dist/src/shared/hash.d.ts +1 -0
- package/dist/src/shared/hash.js +4 -0
- package/dist/src/shared/log.d.ts +7 -0
- package/dist/src/shared/log.js +24 -0
- package/dist/src/shared/metrics.d.ts +66 -0
- package/dist/src/shared/metrics.js +112 -0
- package/dist/src/shared/model-tuning.d.ts +9 -0
- package/dist/src/shared/model-tuning.js +28 -0
- package/dist/src/shared/paths.d.ts +19 -0
- package/dist/src/shared/paths.js +64 -0
- package/dist/src/shared/text.d.ts +4 -0
- package/dist/src/shared/text.js +19 -0
- package/dist/src/shared/time.d.ts +1 -0
- package/dist/src/shared/time.js +3 -0
- package/dist/src/state/adapters/index.d.ts +41 -0
- package/dist/src/state/adapters/index.js +115 -0
- package/dist/src/state/db.d.ts +16 -0
- package/dist/src/state/db.js +225 -0
- package/dist/src/state/ids.d.ts +8 -0
- package/dist/src/state/ids.js +25 -0
- package/dist/src/state/repo-lock.d.ts +67 -0
- package/dist/src/state/repo-lock.js +580 -0
- package/dist/src/state/schema.d.ts +2 -0
- package/dist/src/state/schema.js +258 -0
- package/dist/src/state/types.d.ts +71 -0
- package/dist/src/state/types.js +1 -0
- package/dist/src/state/workflow-repo-lock.d.ts +23 -0
- package/dist/src/state/workflow-repo-lock.js +83 -0
- package/dist/src/tools/artifacts.d.ts +18 -0
- package/dist/src/tools/artifacts.js +71 -0
- package/dist/src/tools/health.d.ts +8 -0
- package/dist/src/tools/health.js +88 -0
- package/dist/src/tools/index.d.ts +20 -0
- package/dist/src/tools/index.js +94 -0
- package/dist/src/tools/init.d.ts +17 -0
- package/dist/src/tools/init.js +96 -0
- package/dist/src/tools/injects.d.ts +53 -0
- package/dist/src/tools/injects.js +325 -0
- package/dist/src/tools/lock.d.ts +4 -0
- package/dist/src/tools/lock.js +78 -0
- package/dist/src/tools/metrics.d.ts +7 -0
- package/dist/src/tools/metrics.js +61 -0
- package/dist/src/tools/repair.d.ts +8 -0
- package/dist/src/tools/repair.js +26 -0
- package/dist/src/tools/reset.d.ts +8 -0
- package/dist/src/tools/reset.js +92 -0
- package/dist/src/tools/run.d.ts +13 -0
- package/dist/src/tools/run.js +54 -0
- package/dist/src/tools/spec.d.ts +12 -0
- package/dist/src/tools/spec.js +44 -0
- package/dist/src/tools/stage.d.ts +23 -0
- package/dist/src/tools/stage.js +371 -0
- package/dist/src/tools/status.d.ts +8 -0
- package/dist/src/tools/status.js +125 -0
- package/dist/src/tools/story.d.ts +23 -0
- package/dist/src/tools/story.js +85 -0
- package/dist/src/tools/workflow.d.ts +13 -0
- package/dist/src/tools/workflow.js +345 -0
- package/dist/src/ui/inject.d.ts +12 -0
- package/dist/src/ui/inject.js +107 -0
- package/dist/src/ui/toasts.d.ts +13 -0
- package/dist/src/ui/toasts.js +39 -0
- package/dist/src/workflow/artifacts.d.ts +24 -0
- package/dist/src/workflow/artifacts.js +45 -0
- package/dist/src/workflow/baton.d.ts +72 -0
- package/dist/src/workflow/baton.js +166 -0
- package/dist/src/workflow/context.d.ts +20 -0
- package/dist/src/workflow/context.js +113 -0
- package/dist/src/workflow/directives.d.ts +39 -0
- package/dist/src/workflow/directives.js +137 -0
- package/dist/src/workflow/repair.d.ts +8 -0
- package/dist/src/workflow/repair.js +99 -0
- package/dist/src/workflow/state-machine.d.ts +86 -0
- package/dist/src/workflow/state-machine.js +216 -0
- package/dist/src/workflow/story-helpers.d.ts +9 -0
- package/dist/src/workflow/story-helpers.js +13 -0
- package/dist/state/db.d.ts +1 -0
- package/dist/state/db.js +9 -0
- package/dist/state/repo-lock.d.ts +3 -0
- package/dist/state/repo-lock.js +29 -0
- package/dist/test/integration/db-transactions.test.d.ts +1 -0
- package/dist/test/integration/db-transactions.test.js +126 -0
- package/dist/test/integration/injection-metrics.test.d.ts +1 -0
- package/dist/test/integration/injection-metrics.test.js +129 -0
- package/dist/tools/health.d.ts +8 -0
- package/dist/tools/health.js +119 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/metrics.d.ts +7 -0
- package/dist/tools/metrics.js +61 -0
- package/dist/tools/reset.d.ts +8 -0
- package/dist/tools/reset.js +92 -0
- package/dist/tools/workflow.js +178 -168
- package/dist/ui/inject.js +21 -9
- package/package.json +6 -4
- package/src/astro/workflow-runner.ts +16 -0
- package/src/config/schema.ts +1 -0
- package/src/hooks/inject-provider.ts +94 -14
- package/src/index.ts +7 -0
- package/src/shared/metrics.ts +148 -0
- package/src/state/db.ts +10 -1
- package/src/state/schema.ts +8 -1
- package/src/tools/health.ts +99 -0
- package/src/tools/index.ts +12 -3
- package/src/tools/init.ts +7 -6
- package/src/tools/metrics.ts +71 -0
- package/src/tools/repair.ts +8 -4
- package/src/tools/reset.ts +100 -0
- package/src/tools/stage.ts +1 -0
- package/src/tools/status.ts +2 -1
- package/src/tools/story.ts +1 -0
- package/src/tools/workflow.ts +2 -0
- package/src/ui/inject.ts +21 -9
- package/src/workflow/repair.ts +2 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/tools/metrics.ts
|
|
2
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
3
|
+
import { metrics } from "../shared/metrics";
|
|
4
|
+
export function createAstroMetricsTool(opts) {
|
|
5
|
+
return tool({
|
|
6
|
+
description: "Get performance metrics for Astrocode operations including transaction times, injection success rates, and error statistics.",
|
|
7
|
+
args: {},
|
|
8
|
+
execute: async () => {
|
|
9
|
+
return runMetricsTool();
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function runMetricsTool() {
|
|
14
|
+
const stats = metrics.getMetrics();
|
|
15
|
+
const txStats = metrics.getTransactionStats();
|
|
16
|
+
const injectionStats = metrics.getInjectionStats();
|
|
17
|
+
let output = "# Astrocode Performance Metrics\n\n";
|
|
18
|
+
// Transaction Stats
|
|
19
|
+
if (txStats) {
|
|
20
|
+
output += "## Database Transactions\n\n";
|
|
21
|
+
output += `**Total:** ${txStats.total}\n`;
|
|
22
|
+
output += `**Success Rate:** ${(txStats.successRate * 100).toFixed(1)}% (${txStats.successful}/${txStats.total})\n`;
|
|
23
|
+
output += `**Average Duration:** ${txStats.avgDuration.toFixed(2)}ms\n`;
|
|
24
|
+
output += `**Duration Range:** ${txStats.minDuration}ms - ${txStats.maxDuration}ms\n`;
|
|
25
|
+
output += `**Average Nesting Depth:** ${txStats.avgNestedDepth.toFixed(1)}\n\n`;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
output += "## Database Transactions\n\nNo transaction data available.\n\n";
|
|
29
|
+
}
|
|
30
|
+
// Injection Stats
|
|
31
|
+
if (injectionStats) {
|
|
32
|
+
output += "## UI Injections\n\n";
|
|
33
|
+
output += `**Total:** ${injectionStats.total}\n`;
|
|
34
|
+
output += `**Success Rate:** ${(injectionStats.successRate * 100).toFixed(1)}% (${injectionStats.successful}/${injectionStats.total})\n`;
|
|
35
|
+
output += `**Average Attempts:** ${injectionStats.avgAttempts.toFixed(1)}\n`;
|
|
36
|
+
output += `**Total Retries:** ${injectionStats.totalRetries}\n`;
|
|
37
|
+
output += `**Average Duration:** ${injectionStats.avgDuration.toFixed(2)}ms\n\n`;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
output += "## UI Injections\n\nNo injection data available.\n\n";
|
|
41
|
+
}
|
|
42
|
+
// Recent Errors
|
|
43
|
+
if (stats.errors.length > 0) {
|
|
44
|
+
output += "## Recent Errors\n\n";
|
|
45
|
+
const recentErrors = stats.errors.slice(-10); // Last 10 errors
|
|
46
|
+
for (const error of recentErrors) {
|
|
47
|
+
const timestamp = new Date(error.timestamp).toISOString();
|
|
48
|
+
output += `- **[${error.type}]** ${timestamp}: ${error.message}\n`;
|
|
49
|
+
}
|
|
50
|
+
output += "\n";
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
output += "## Recent Errors\n\nNo errors recorded.\n\n";
|
|
54
|
+
}
|
|
55
|
+
// Raw Data Summary
|
|
56
|
+
output += "## Data Summary\n\n";
|
|
57
|
+
output += `**Transactions Tracked:** ${stats.transactions.length}\n`;
|
|
58
|
+
output += `**Injections Tracked:** ${stats.injections.length}\n`;
|
|
59
|
+
output += `**Errors Recorded:** ${stats.errors.length}\n`;
|
|
60
|
+
return output;
|
|
61
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { AstrocodeConfig } from "../config/schema";
|
|
3
|
+
import type { SqliteDb } from "../state/db";
|
|
4
|
+
export declare function createAstroRepairTool(opts: {
|
|
5
|
+
ctx: any;
|
|
6
|
+
config: AstrocodeConfig;
|
|
7
|
+
db: SqliteDb;
|
|
8
|
+
}): ToolDefinition;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { withTx } from "../state/db";
|
|
3
|
+
import { repairState, formatRepairReport } from "../workflow/repair";
|
|
4
|
+
import { putArtifact } from "../workflow/artifacts";
|
|
5
|
+
import { nowISO } from "../shared/time";
|
|
6
|
+
export function createAstroRepairTool(opts) {
|
|
7
|
+
const { ctx, config, db } = opts;
|
|
8
|
+
return tool({
|
|
9
|
+
description: "Repair Astrocode invariants and recover from inconsistent DB state. Writes a repair report artifact.",
|
|
10
|
+
args: {
|
|
11
|
+
write_report_artifact: tool.schema.boolean().default(true),
|
|
12
|
+
},
|
|
13
|
+
execute: async ({ write_report_artifact }) => {
|
|
14
|
+
const repoRoot = ctx.directory;
|
|
15
|
+
// Repair database state
|
|
16
|
+
const report = withTx(db, () => repairState(db, config));
|
|
17
|
+
const fullMd = formatRepairReport(report);
|
|
18
|
+
if (write_report_artifact) {
|
|
19
|
+
const rel = `.astro/repair/repair_${nowISO().replace(/[:.]/g, "-")}.md`;
|
|
20
|
+
const a = putArtifact({ repoRoot, db, run_id: null, stage_key: null, type: "log", rel_path: rel, content: fullMd, meta: { kind: "repair" } });
|
|
21
|
+
return fullMd + `\n\nReport saved: ${rel} (artifact=${a.artifact_id})`;
|
|
22
|
+
}
|
|
23
|
+
return fullMd;
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { AstrocodeConfig } from "../config/schema";
|
|
3
|
+
import type { SqliteDb } from "../state/db";
|
|
4
|
+
export declare function createAstroResetTool(opts: {
|
|
5
|
+
ctx: any;
|
|
6
|
+
config: AstrocodeConfig;
|
|
7
|
+
db: SqliteDb;
|
|
8
|
+
}): ToolDefinition;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// src/tools/reset.ts
|
|
2
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
export function createAstroResetTool(opts) {
|
|
6
|
+
const { ctx, config, db } = opts;
|
|
7
|
+
return tool({
|
|
8
|
+
description: "Reset Astrocode database: safely delete all DB files and WAL/SHM after killing concurrent processes.",
|
|
9
|
+
args: {
|
|
10
|
+
confirm: tool.schema.string().default("").describe("Type 'RESET' to confirm destructive operation"),
|
|
11
|
+
},
|
|
12
|
+
execute: async ({ confirm }) => {
|
|
13
|
+
if (confirm !== "RESET") {
|
|
14
|
+
return [
|
|
15
|
+
"❌ Reset cancelled - confirmation required",
|
|
16
|
+
"",
|
|
17
|
+
"This operation will:",
|
|
18
|
+
"- Delete .astro/astro.db",
|
|
19
|
+
"- Delete .astro/astro.db-wal (if exists)",
|
|
20
|
+
"- Delete .astro/astro.db-shm (if exists)",
|
|
21
|
+
"- Lose all workflow data, stories, runs, artifacts",
|
|
22
|
+
"",
|
|
23
|
+
"To confirm: astro_reset(confirm=\"RESET\")",
|
|
24
|
+
].join("\n");
|
|
25
|
+
}
|
|
26
|
+
const repoRoot = ctx.directory || process.cwd();
|
|
27
|
+
const dbPath = config.db?.path || ".astro/astro.db";
|
|
28
|
+
const fullDbPath = path.resolve(repoRoot, dbPath);
|
|
29
|
+
const lines = [];
|
|
30
|
+
lines.push("🗑️ Astrocode Database Reset");
|
|
31
|
+
lines.push(`- Repo: ${repoRoot}`);
|
|
32
|
+
lines.push(`- Target: ${fullDbPath}`);
|
|
33
|
+
// Check for lock file
|
|
34
|
+
const lockPath = `${repoRoot}/.astro/astro.lock`;
|
|
35
|
+
if (fs.existsSync(lockPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const lockContent = fs.readFileSync(lockPath, "utf8").trim();
|
|
38
|
+
const pid = parseInt(lockContent.split(" ")[0]);
|
|
39
|
+
lines.push(`- Lock file found for PID ${pid}`);
|
|
40
|
+
// Try to kill the process
|
|
41
|
+
try {
|
|
42
|
+
process.kill(pid, 'SIGTERM');
|
|
43
|
+
lines.push(`- Sent SIGTERM to PID ${pid}, waiting 2s...`);
|
|
44
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
lines.push(`- Could not kill PID ${pid}: ${String(e)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
lines.push(`- Error reading lock file: ${String(e)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Delete DB files
|
|
55
|
+
const filesToDelete = [
|
|
56
|
+
fullDbPath,
|
|
57
|
+
`${fullDbPath}-wal`,
|
|
58
|
+
`${fullDbPath}-shm`,
|
|
59
|
+
lockPath,
|
|
60
|
+
];
|
|
61
|
+
let deletedCount = 0;
|
|
62
|
+
for (const filePath of filesToDelete) {
|
|
63
|
+
try {
|
|
64
|
+
if (fs.existsSync(filePath)) {
|
|
65
|
+
fs.unlinkSync(filePath);
|
|
66
|
+
lines.push(`- Deleted: ${path.relative(repoRoot, filePath)}`);
|
|
67
|
+
deletedCount++;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
lines.push(`- Skipped: ${path.relative(repoRoot, filePath)} (not found)`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
lines.push(`- Failed to delete ${path.relative(repoRoot, filePath)}: ${String(e)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
lines.push(``);
|
|
78
|
+
if (deletedCount > 0) {
|
|
79
|
+
lines.push(`✅ Reset complete - ${deletedCount} files deleted`);
|
|
80
|
+
lines.push(``);
|
|
81
|
+
lines.push(`Next steps:`);
|
|
82
|
+
lines.push(`1. Run: astro_init`);
|
|
83
|
+
lines.push(`2. Run: astro_status`);
|
|
84
|
+
lines.push(`3. Import your stories and restart workflow`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
lines.push(`ℹ️ No files found to delete`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join("\n");
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { AstrocodeConfig } from "../config/schema";
|
|
3
|
+
import type { SqliteDb } from "../state/db";
|
|
4
|
+
export declare function createAstroRunGetTool(opts: {
|
|
5
|
+
ctx: any;
|
|
6
|
+
config: AstrocodeConfig;
|
|
7
|
+
db: SqliteDb;
|
|
8
|
+
}): ToolDefinition;
|
|
9
|
+
export declare function createAstroRunAbortTool(opts: {
|
|
10
|
+
ctx: any;
|
|
11
|
+
config: AstrocodeConfig;
|
|
12
|
+
db: SqliteDb;
|
|
13
|
+
}): ToolDefinition;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { abortRun, getActiveRun, getStageRuns, getStory } from "../workflow/state-machine";
|
|
3
|
+
export function createAstroRunGetTool(opts) {
|
|
4
|
+
const { db } = opts;
|
|
5
|
+
return tool({
|
|
6
|
+
description: "Get run details (and stage run statuses). Defaults to active run if run_id omitted.",
|
|
7
|
+
args: {
|
|
8
|
+
run_id: tool.schema.string().optional(),
|
|
9
|
+
include_stage_summaries: tool.schema.boolean().default(false),
|
|
10
|
+
},
|
|
11
|
+
execute: async ({ run_id, include_stage_summaries }) => {
|
|
12
|
+
const active = getActiveRun(db);
|
|
13
|
+
const rid = run_id ?? active?.run_id;
|
|
14
|
+
if (!rid)
|
|
15
|
+
return "No active run.";
|
|
16
|
+
const run = db.prepare("SELECT * FROM runs WHERE run_id=?").get(rid);
|
|
17
|
+
if (!run)
|
|
18
|
+
throw new Error(`Run not found: ${rid}`);
|
|
19
|
+
const story = getStory(db, run.story_key);
|
|
20
|
+
const stages = getStageRuns(db, rid);
|
|
21
|
+
const lines = [];
|
|
22
|
+
lines.push(`# Run ${rid}`);
|
|
23
|
+
lines.push(`- Status: **${run.status}**`);
|
|
24
|
+
lines.push(`- Story: \`${run.story_key}\` — ${story?.title ?? "(missing)"}`);
|
|
25
|
+
lines.push(`- Current stage: \`${run.current_stage_key ?? "?"}\``);
|
|
26
|
+
lines.push("", "## Stages");
|
|
27
|
+
for (const s of stages) {
|
|
28
|
+
lines.push(`- \`${s.stage_key}\` (${s.status})`);
|
|
29
|
+
if (include_stage_summaries && s.summary_md) {
|
|
30
|
+
lines.push(` - summary: ${s.summary_md.split("\n")[0].slice(0, 120)}${s.summary_md.length > 120 ? "…" : ""}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return lines.join("\n").trim();
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function createAstroRunAbortTool(opts) {
|
|
38
|
+
const { db } = opts;
|
|
39
|
+
return tool({
|
|
40
|
+
description: "Abort a run and unlock its story (returns story to approved). Defaults to active run if run_id omitted.",
|
|
41
|
+
args: {
|
|
42
|
+
run_id: tool.schema.string().optional(),
|
|
43
|
+
reason: tool.schema.string().default("aborted by user"),
|
|
44
|
+
},
|
|
45
|
+
execute: async ({ run_id, reason }) => {
|
|
46
|
+
const active = getActiveRun(db);
|
|
47
|
+
const rid = run_id ?? active?.run_id;
|
|
48
|
+
if (!rid)
|
|
49
|
+
return "No active run to abort.";
|
|
50
|
+
abortRun(db, rid, reason);
|
|
51
|
+
return `🛑 Aborted run ${rid}. Reason: ${reason}`;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { AstrocodeConfig } from "../config/schema";
|
|
3
|
+
import type { SqliteDb } from "../state/db";
|
|
4
|
+
export declare function createAstroSpecGetTool(opts: {
|
|
5
|
+
ctx: any;
|
|
6
|
+
config: AstrocodeConfig;
|
|
7
|
+
}): ToolDefinition;
|
|
8
|
+
export declare function createAstroSpecSetTool(opts: {
|
|
9
|
+
ctx: any;
|
|
10
|
+
config: AstrocodeConfig;
|
|
11
|
+
db: SqliteDb;
|
|
12
|
+
}): ToolDefinition;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
4
|
+
import { getAstroPaths, ensureAstroDirs } from "../shared/paths";
|
|
5
|
+
import { nowISO } from "../shared/time";
|
|
6
|
+
import { sha256Hex } from "../shared/hash";
|
|
7
|
+
export function createAstroSpecGetTool(opts) {
|
|
8
|
+
const { ctx, config } = opts;
|
|
9
|
+
return tool({
|
|
10
|
+
description: "Get current project spec stored at .astro/spec.md",
|
|
11
|
+
args: {},
|
|
12
|
+
execute: async () => {
|
|
13
|
+
const repoRoot = ctx.directory;
|
|
14
|
+
const paths = getAstroPaths(repoRoot, config.db.path);
|
|
15
|
+
ensureAstroDirs(paths);
|
|
16
|
+
if (!fs.existsSync(paths.specPath))
|
|
17
|
+
return "No spec found at .astro/spec.md (run astro_init or astro_spec_set).";
|
|
18
|
+
const md = fs.readFileSync(paths.specPath, "utf-8");
|
|
19
|
+
return md;
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function createAstroSpecSetTool(opts) {
|
|
24
|
+
const { ctx, config, db } = opts;
|
|
25
|
+
return tool({
|
|
26
|
+
description: "Set/replace the project spec at .astro/spec.md and record its hash in the DB.",
|
|
27
|
+
args: {
|
|
28
|
+
spec_md: tool.schema.string().min(1),
|
|
29
|
+
},
|
|
30
|
+
execute: async ({ spec_md }) => {
|
|
31
|
+
if (!db) {
|
|
32
|
+
return "❌ Database not available. Cannot track spec hash. Astrocode is running in limited mode.";
|
|
33
|
+
}
|
|
34
|
+
const repoRoot = ctx.directory;
|
|
35
|
+
const paths = getAstroPaths(repoRoot, config.db.path);
|
|
36
|
+
ensureAstroDirs(paths);
|
|
37
|
+
fs.writeFileSync(paths.specPath, spec_md);
|
|
38
|
+
const h = sha256Hex(spec_md);
|
|
39
|
+
const now = nowISO();
|
|
40
|
+
db.prepare("UPDATE repo_state SET spec_hash_after=?, updated_at=? WHERE id=1").run(h, now);
|
|
41
|
+
return `✅ Spec updated (${path.relative(repoRoot, paths.specPath)}). sha256=${h}`;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { AstrocodeConfig } from "../config/schema";
|
|
3
|
+
import type { SqliteDb } from "../state/db";
|
|
4
|
+
export declare function createAstroStageStartTool(opts: {
|
|
5
|
+
ctx: any;
|
|
6
|
+
config: AstrocodeConfig;
|
|
7
|
+
db: SqliteDb;
|
|
8
|
+
}): ToolDefinition;
|
|
9
|
+
export declare function createAstroStageCompleteTool(opts: {
|
|
10
|
+
ctx: any;
|
|
11
|
+
config: AstrocodeConfig;
|
|
12
|
+
db: SqliteDb;
|
|
13
|
+
}): ToolDefinition;
|
|
14
|
+
export declare function createAstroStageFailTool(opts: {
|
|
15
|
+
ctx: any;
|
|
16
|
+
config: AstrocodeConfig;
|
|
17
|
+
db: SqliteDb;
|
|
18
|
+
}): ToolDefinition;
|
|
19
|
+
export declare function createAstroStageResetTool(opts: {
|
|
20
|
+
ctx: any;
|
|
21
|
+
config: AstrocodeConfig;
|
|
22
|
+
db: SqliteDb;
|
|
23
|
+
}): ToolDefinition;
|