codecartographer-pi 0.19.4 → 0.19.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.
@@ -12,6 +12,7 @@
12
12
  // write, closeout-stub creation, dashboard regen. UI notifications stay in
13
13
  // the calling handler.
14
14
  import { runPhase } from "./agent-runner.js";
15
+ import { notifyCtx } from "./notify.js";
15
16
  import { clearPhase, finishPhase, getPhaseActivity, startPhase } from "./agent-state.js";
16
17
  import { buildSteeringMessage, rewritePhasePrompt } from "./agent-rewriter.js";
17
18
  import { buildPhaseSummary } from "./agent-summary.js";
@@ -34,13 +35,11 @@ export async function runSinglePhase(ctx, pi, state, phase, options) {
34
35
  preflight: options.preflight,
35
36
  });
36
37
  if (options.llmSteerEnabled) {
37
- if (ctx.hasUI)
38
- ctx.ui.notify(`Customizing ${phase.id} prompt via LLM rewriter…`, "info");
38
+ notifyCtx(ctx, `Customizing ${phase.id} prompt via LLM rewriter…`, "info");
39
39
  const rewrite = await rewritePhasePrompt({ ctx, state, originalPrompt: prompt, nextPhaseId: phase.id });
40
40
  if (rewrite.used) {
41
41
  prompt = rewrite.prompt;
42
- if (ctx.hasUI)
43
- ctx.ui.notify(`LLM rewriter customized ${phase.id} seed prompt.`, "info");
42
+ notifyCtx(ctx, `LLM rewriter customized ${phase.id} seed prompt.`, "info");
44
43
  pi.sendMessage({
45
44
  customType: "codecarto-steering",
46
45
  content: buildSteeringMessage({
@@ -51,15 +50,14 @@ export async function runSinglePhase(ctx, pi, state, phase, options) {
51
50
  display: true,
52
51
  });
53
52
  }
54
- else if (ctx.hasUI) {
55
- ctx.ui.notify(`LLM rewriter skipped (${rewrite.skipReason}); using stock prompt.`, "warning");
53
+ else {
54
+ notifyCtx(ctx, `LLM rewriter skipped (${rewrite.skipReason}); using stock prompt.`, "warning");
56
55
  }
57
56
  }
58
57
  const activity = startPhase(phase.id);
59
- if (ctx.hasUI) {
60
- ctx.ui.notify(`CodeCartographer phase: ${phase.id} (sub-agent running)`, "info");
58
+ notifyCtx(ctx, `CodeCartographer phase: ${phase.id} (sub-agent running)`, "info");
59
+ if (ctx.hasUI)
61
60
  getAgentsWidget().attach(ctx.ui);
62
- }
63
61
  try {
64
62
  const result = await runPhase(ctx, prompt, {
65
63
  onSessionCreated: (session) => { activity.session = session; },
@@ -84,11 +82,9 @@ export async function runSinglePhase(ctx, pi, state, phase, options) {
84
82
  }, { sessionName: `CodeCartographer phase: ${phase.id}`, primaryOutput: phase.primary_output }, options.signal);
85
83
  const status = result.aborted ? "aborted" : "completed";
86
84
  finishPhase(phase.id, { status });
87
- if (ctx.hasUI) {
88
- ctx.ui.notify(result.aborted
89
- ? `Phase ${phase.id} aborted.`
90
- : `Phase ${phase.id} sub-agent finished (${result.toolUses} tool uses, ${result.turnCount} turns).`, result.aborted ? "warning" : "info");
91
- }
85
+ notifyCtx(ctx, result.aborted
86
+ ? `Phase ${phase.id} aborted.`
87
+ : `Phase ${phase.id} sub-agent finished (${result.toolUses} tool uses, ${result.turnCount} turns).`, result.aborted ? "warning" : "info");
92
88
  pi.sendMessage({
93
89
  customType: "codecarto-phase-summary",
94
90
  content: buildPhaseSummary({
@@ -115,9 +111,7 @@ export async function runSinglePhase(ctx, pi, state, phase, options) {
115
111
  catch (err) {
116
112
  const message = err instanceof Error ? err.message : String(err);
117
113
  finishPhase(phase.id, { status: "error", error: message });
118
- if (ctx.hasUI) {
119
- ctx.ui.notify(`Phase ${phase.id} sub-agent failed: ${message}`, "error");
120
- }
114
+ notifyCtx(ctx, `Phase ${phase.id} sub-agent failed: ${message}`, "error");
121
115
  pi.sendMessage({
122
116
  customType: "codecarto-phase-summary",
123
117
  content: buildPhaseSummary({
@@ -10,10 +10,10 @@
10
10
  //
11
11
  // Same one-shot pattern as agent-rewriter.ts:runRewriterOnce — different
12
12
  // system prompt, different output target. Never throws.
13
- import { readFile, readdir, rename, writeFile } from "node:fs/promises";
13
+ import { readFile, readdir } from "node:fs/promises";
14
14
  import { join } from "node:path";
15
15
  import { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager, SettingsManager, } from "@earendil-works/pi-coding-agent";
16
- import { computeTotals, NARRATION_CACHE_RELATIVE_PATH, loadUsage, pathExists, stringifySimpleYaml, } from "../../core/index.js";
16
+ import { atomicWriteFile, computeTotals, NARRATION_CACHE_RELATIVE_PATH, loadUsage, pathExists, stringifySimpleYaml, } from "../../core/index.js";
17
17
  import { createChildModelRuntime } from "./child-model-runtime.js";
18
18
  // Per-closeout byte budget when stuffing the narrator's input. Three
19
19
  // closeouts × 4 KB each ≈ 12 KB of prompt context, which is well under any
@@ -133,10 +133,7 @@ async function writeNarrationCache(workspaceDir, content, phaseCount) {
133
133
  const generatedAt = new Date().toISOString();
134
134
  const frontmatter = stringifySimpleYaml({ generatedAt, phaseCountAtGeneration: phaseCount });
135
135
  const body = `---\n${frontmatter}\n---\n${content}\n`;
136
- const path = join(workspaceDir, NARRATION_CACHE_RELATIVE_PATH);
137
- const tempPath = `${path}.${process.pid}.${Date.now()}.tmp`;
138
- await writeFile(tempPath, body, "utf8");
139
- await rename(tempPath, path);
136
+ await atomicWriteFile(join(workspaceDir, NARRATION_CACHE_RELATIVE_PATH), body);
140
137
  }
141
138
  async function runNarratorOnce(ctx, prompt) {
142
139
  const cwd = ctx.cwd;
@@ -2,9 +2,9 @@
2
2
  // HTML to `.codecarto/dashboard.html`. Best-effort — failures are swallowed
3
3
  // and never escalate to a phase error the user sees, mirroring the
4
4
  // recordUsage discipline at extensions/codecarto/index.ts.
5
- import { readdir, readFile, rename, writeFile } from "node:fs/promises";
5
+ import { readdir, readFile } from "node:fs/promises";
6
6
  import { join } from "node:path";
7
- import { DASHBOARD_RELATIVE_PATH, getWorkspaceState, loadUsage, NARRATION_CACHE_RELATIVE_PATH, parseSimpleYaml, pathExists, renderDashboard, } from "../../core/index.js";
7
+ import { atomicWriteFile, DASHBOARD_RELATIVE_PATH, getWorkspaceState, loadUsage, NARRATION_CACHE_RELATIVE_PATH, parseSimpleYaml, pathExists, renderDashboard, } from "../../core/index.js";
8
8
  const CLOSEOUT_FILENAME_RE = /^(\d{4}-\d{2}-\d{2})-(.+)\.md$/;
9
9
  /**
10
10
  * Render and atomically replace `.codecarto/dashboard.html`.
@@ -36,10 +36,7 @@ export async function writeDashboard(cwd, packageVersion) {
36
36
  narration,
37
37
  };
38
38
  const html = renderDashboard(inputs);
39
- const path = join(workspaceDir, DASHBOARD_RELATIVE_PATH);
40
- const tempPath = `${path}.${process.pid}.${Date.now()}.tmp`;
41
- await writeFile(tempPath, html, "utf8");
42
- await rename(tempPath, path);
39
+ await atomicWriteFile(join(workspaceDir, DASHBOARD_RELATIVE_PATH), html);
43
40
  return true;
44
41
  }
45
42
  catch {