astrocode-workflow 0.4.4 → 0.4.6

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 (46) hide show
  1. package/dist/src/hooks/continuation-enforcer.d.ts +1 -9
  2. package/dist/src/hooks/continuation-enforcer.js +12 -2
  3. package/dist/src/hooks/inject-provider.d.ts +1 -9
  4. package/dist/src/hooks/inject-provider.js +14 -5
  5. package/dist/src/state/types.d.ts +9 -0
  6. package/dist/src/tools/artifacts.d.ts +4 -4
  7. package/dist/src/tools/artifacts.js +12 -3
  8. package/dist/src/tools/health.d.ts +2 -2
  9. package/dist/src/tools/health.js +18 -11
  10. package/dist/src/tools/index.js +27 -34
  11. package/dist/src/tools/injects.d.ts +8 -8
  12. package/dist/src/tools/injects.js +24 -6
  13. package/dist/src/tools/metrics.d.ts +6 -5
  14. package/dist/src/tools/repair.d.ts +2 -2
  15. package/dist/src/tools/repair.js +5 -1
  16. package/dist/src/tools/reset.d.ts +2 -2
  17. package/dist/src/tools/reset.js +9 -1
  18. package/dist/src/tools/run.d.ts +3 -3
  19. package/dist/src/tools/run.js +8 -2
  20. package/dist/src/tools/spec.d.ts +2 -2
  21. package/dist/src/tools/spec.js +3 -2
  22. package/dist/src/tools/stage.d.ts +5 -5
  23. package/dist/src/tools/stage.js +16 -4
  24. package/dist/src/tools/status.d.ts +2 -2
  25. package/dist/src/tools/status.js +25 -2
  26. package/dist/src/tools/story.d.ts +5 -5
  27. package/dist/src/tools/story.js +16 -4
  28. package/dist/src/tools/workflow.d.ts +2 -2
  29. package/dist/src/tools/workflow.js +5 -1
  30. package/package.json +1 -1
  31. package/src/hooks/continuation-enforcer.ts +11 -9
  32. package/src/hooks/inject-provider.ts +16 -12
  33. package/src/state/types.ts +11 -0
  34. package/src/tools/artifacts.ts +16 -7
  35. package/src/tools/health.ts +22 -13
  36. package/src/tools/index.ts +32 -40
  37. package/src/tools/injects.ts +32 -14
  38. package/src/tools/metrics.ts +3 -6
  39. package/src/tools/repair.ts +8 -4
  40. package/src/tools/reset.ts +11 -3
  41. package/src/tools/run.ts +11 -5
  42. package/src/tools/spec.ts +5 -4
  43. package/src/tools/stage.ts +22 -10
  44. package/src/tools/status.ts +28 -5
  45. package/src/tools/story.ts +21 -9
  46. package/src/tools/workflow.ts +8 -3
@@ -1,8 +1,10 @@
1
1
  import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool";
2
2
  import type { AstrocodeConfig } from "../config/schema";
3
- import type { SqliteDb } from "../state/db";
3
+ import type { RuntimeState } from "../state/types";
4
4
  import { decideNextAction, getActiveRun, getStageRuns, getStory } from "../workflow/state-machine";
5
-
5
+ import { openSqlite, configurePragmas, ensureSchema } from "../state/db";
6
+ import { getAstroPaths } from "../shared/paths";
7
+ import fs from "node:fs";
6
8
 
7
9
  function statusIcon(status: string): string {
8
10
  switch (status) {
@@ -36,8 +38,8 @@ function stageIcon(status: string): string {
36
38
  }
37
39
  }
38
40
 
39
- export function createAstroStatusTool(opts: { ctx: any; config: AstrocodeConfig; db?: SqliteDb | null }): ToolDefinition {
40
- const { ctx, config, db } = opts;
41
+ export function createAstroStatusTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState }): ToolDefinition {
42
+ const { ctx, config, runtime } = opts;
41
43
 
42
44
  return tool({
43
45
  description: "Show a compact Astrocode status dashboard: active run/stage, pipeline, story board counts, and next action.",
@@ -46,18 +48,39 @@ export function createAstroStatusTool(opts: { ctx: any; config: AstrocodeConfig;
46
48
  include_recent_events: tool.schema.boolean().default(false),
47
49
  },
48
50
  execute: async ({ include_board, include_recent_events }) => {
51
+ // Lazy initialization: if DB is missing but file exists, try to connect
52
+ if (!runtime.db) {
53
+ const repoRoot = (ctx as any).directory || process.cwd();
54
+ const paths = getAstroPaths(repoRoot, config.db.path);
55
+ if (fs.existsSync(paths.dbPath)) {
56
+ try {
57
+ const db = openSqlite(paths.dbPath, { busyTimeoutMs: config.db.busy_timeout_ms });
58
+ configurePragmas(db, config.db.pragmas);
59
+ ensureSchema(db, { allowAutoMigrate: config.db.allow_auto_migrate, silent: true });
60
+ runtime.db = db;
61
+ runtime.limitedMode = false;
62
+ runtime.limitedModeReason = null;
63
+ } catch {
64
+ // Ignore lazy init failures, will fall through to "not initialized" message
65
+ }
66
+ }
67
+ }
68
+
69
+ const { db } = runtime;
70
+
49
71
  if (!db) {
50
72
  return [
51
73
  `⚠️ Astrocode not initialized.`,
52
74
  ``,
53
75
  `- Reason: Database not available`,
54
76
  ``,
55
- `Next: run **astro_init**, then restart the agent/runtime, then run /astro-status.`,
77
+ `Next: run **astro_init**, then run /astro-status again.`,
56
78
  ].join("\n");
57
79
  }
58
80
 
59
81
  try {
60
82
  const active = getActiveRun(db);
83
+ // ... rest of existing logic ...
61
84
 
62
85
  const lines: string[] = [];
63
86
  lines.push(`# Astrocode Status`);
@@ -1,6 +1,6 @@
1
1
  import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool";
2
2
  import type { AstrocodeConfig } from "../config/schema";
3
- import type { SqliteDb } from "../state/db";
3
+ import type { RuntimeState } from "../state/types";
4
4
  import { withTx } from "../state/db";
5
5
  import { nowISO } from "../shared/time";
6
6
  import type { StoryState } from "../state/types";
@@ -9,8 +9,8 @@ import { insertStory } from "../workflow/story-helpers";
9
9
 
10
10
 
11
11
 
12
- export function createAstroStoryQueueTool(opts: { ctx: any; config: AstrocodeConfig; db: SqliteDb }): ToolDefinition {
13
- const { db } = opts;
12
+ export function createAstroStoryQueueTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState }): ToolDefinition {
13
+ const { runtime } = opts;
14
14
 
15
15
  return tool({
16
16
  description: "Create a queued story (ticket) in Astrocode. Returns story_key.",
@@ -21,6 +21,9 @@ export function createAstroStoryQueueTool(opts: { ctx: any; config: AstrocodeCon
21
21
  priority: tool.schema.number().int().default(0),
22
22
  },
23
23
  execute: async ({ title, body_md, epic_key, priority }) => {
24
+ const { db } = runtime;
25
+ if (!db) return "⚠️ Astrocode not initialized. Run **astro_init** first.";
26
+
24
27
  const story_key = withTx(db, () => {
25
28
  const key = insertStory(db, { title, body_md, epic_key: epic_key ?? null, priority: priority ?? 0, state: 'queued' });
26
29
  return key;
@@ -31,8 +34,8 @@ export function createAstroStoryQueueTool(opts: { ctx: any; config: AstrocodeCon
31
34
  });
32
35
  }
33
36
 
34
- export function createAstroStoryApproveTool(opts: { ctx: any; config: AstrocodeConfig; db: SqliteDb }): ToolDefinition {
35
- const { db } = opts;
37
+ export function createAstroStoryApproveTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState }): ToolDefinition {
38
+ const { runtime } = opts;
36
39
 
37
40
  return tool({
38
41
  description: "Approve a story so it becomes eligible to run.",
@@ -40,6 +43,9 @@ export function createAstroStoryApproveTool(opts: { ctx: any; config: AstrocodeC
40
43
  story_key: tool.schema.string().min(1),
41
44
  },
42
45
  execute: async ({ story_key }) => {
46
+ const { db } = runtime;
47
+ if (!db) return "⚠️ Astrocode not initialized. Run **astro_init** first.";
48
+
43
49
  const now = nowISO();
44
50
  const row = db.prepare("SELECT story_key, state, title FROM stories WHERE story_key=?").get(story_key) as any;
45
51
  if (!row) throw new Error(`Story not found: ${story_key}`);
@@ -52,8 +58,8 @@ export function createAstroStoryApproveTool(opts: { ctx: any; config: AstrocodeC
52
58
  });
53
59
  }
54
60
 
55
- export function createAstroStoryBoardTool(opts: { ctx: any; config: AstrocodeConfig; db: SqliteDb }): ToolDefinition {
56
- const { db } = opts;
61
+ export function createAstroStoryBoardTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState }): ToolDefinition {
62
+ const { runtime } = opts;
57
63
 
58
64
  return tool({
59
65
  description: "Show stories grouped by state (a compact board).",
@@ -61,6 +67,9 @@ export function createAstroStoryBoardTool(opts: { ctx: any; config: AstrocodeCon
61
67
  limit_per_state: tool.schema.number().int().positive().default(20),
62
68
  },
63
69
  execute: async ({ limit_per_state }) => {
70
+ const { db } = runtime;
71
+ if (!db) return "⚠️ Astrocode not initialized. Run **astro_init** first.";
72
+
64
73
  const states: StoryState[] = ["queued", "approved", "in_progress", "blocked", "done", "archived"];
65
74
  const lines: string[] = [];
66
75
  lines.push("# Story board");
@@ -80,8 +89,8 @@ export function createAstroStoryBoardTool(opts: { ctx: any; config: AstrocodeCon
80
89
  });
81
90
  }
82
91
 
83
- export function createAstroStorySetStateTool(opts: { ctx: any; config: AstrocodeConfig; db: SqliteDb }): ToolDefinition {
84
- const { db } = opts;
92
+ export function createAstroStorySetStateTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState }): ToolDefinition {
93
+ const { runtime } = opts;
85
94
 
86
95
  return tool({
87
96
  description:
@@ -92,6 +101,9 @@ export function createAstroStorySetStateTool(opts: { ctx: any; config: Astrocode
92
101
  note: tool.schema.string().default(""),
93
102
  },
94
103
  execute: async ({ story_key, state, note }) => {
104
+ const { db } = runtime;
105
+ if (!db) return "⚠️ Astrocode not initialized. Run **astro_init** first.";
106
+
95
107
  const now = nowISO();
96
108
  const row = db.prepare("SELECT story_key, title, state FROM stories WHERE story_key=?").get(story_key) as any;
97
109
  if (!row) throw new Error(`Story not found: ${story_key}`);
@@ -2,7 +2,7 @@
2
2
  import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool";
3
3
  import path from "node:path";
4
4
  import type { AstrocodeConfig } from "../config/schema";
5
- import type { SqliteDb } from "../state/db";
5
+ import type { RuntimeState } from "../state/types";
6
6
  import { withTx } from "../state/db";
7
7
  import type { StageKey } from "../state/types";
8
8
  import type { UiEmitEvent } from "../workflow/state-machine";
@@ -171,8 +171,8 @@ function buildUiMessage(e: UiEmitEvent): { title: string; message: string; varia
171
171
  }
172
172
  }
173
173
 
174
- export function createAstroWorkflowProceedTool(opts: { ctx: any; config: AstrocodeConfig; db: SqliteDb; agents?: Record<string, AgentConfig> }): ToolDefinition {
175
- const { ctx, config, db, agents } = opts;
174
+ export function createAstroWorkflowProceedTool(opts: { ctx: any; config: AstrocodeConfig; runtime: RuntimeState; agents?: Record<string, AgentConfig> }): ToolDefinition {
175
+ const { ctx, config, runtime, agents } = opts;
176
176
  const toasts = createToastManager({ ctx, throttleMs: config.ui.toasts.throttle_ms });
177
177
 
178
178
  return tool({
@@ -183,6 +183,11 @@ export function createAstroWorkflowProceedTool(opts: { ctx: any; config: Astroco
183
183
  max_steps: tool.schema.number().int().positive().default(config.workflow.default_max_steps),
184
184
  },
185
185
  execute: async ({ mode, max_steps }) => {
186
+ const { db } = runtime;
187
+ if (!db) {
188
+ return "⚠️ Cannot proceed: Astrocode is not initialized. Run **astro_init** first.";
189
+ }
190
+
186
191
  const sessionId = (ctx as any).sessionID as string | undefined;
187
192
  const steps = Math.min(max_steps, config.workflow.loop_max_steps_hard_cap);
188
193