@bastani/atomic 0.6.3-0 → 0.6.4-0
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/.agents/skills/ast-grep/SKILL.md +323 -0
- package/.agents/skills/ast-grep/references/rule_reference.md +297 -0
- package/.agents/skills/ripgrep/SKILL.md +382 -0
- package/.mcp.json +5 -6
- package/dist/commands/cli/claude-inflight-hook.d.ts +100 -0
- package/dist/commands/cli/claude-inflight-hook.d.ts.map +1 -0
- package/dist/commands/cli/claude-stop-hook.d.ts +2 -0
- package/dist/commands/cli/claude-stop-hook.d.ts.map +1 -1
- package/dist/lib/spawn.d.ts +1 -1
- package/dist/lib/spawn.d.ts.map +1 -1
- package/dist/sdk/providers/claude.d.ts +36 -0
- package/dist/sdk/providers/claude.d.ts.map +1 -1
- package/dist/sdk/providers/copilot.d.ts +17 -1
- package/dist/sdk/providers/copilot.d.ts.map +1 -1
- package/dist/sdk/runtime/executor.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +49 -34
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +18 -16
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/batching.d.ts +43 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/batching.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +30 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts +2 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +18 -16
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
- package/dist/services/config/additional-instructions.d.ts +67 -0
- package/dist/services/config/additional-instructions.d.ts.map +1 -0
- package/package.json +3 -1
- package/src/cli.ts +18 -1
- package/src/commands/cli/chat/index.ts +52 -2
- package/src/commands/cli/claude-inflight-hook.test.ts +598 -0
- package/src/commands/cli/claude-inflight-hook.ts +359 -0
- package/src/commands/cli/claude-stop-hook.ts +40 -4
- package/src/commands/cli/init/index.ts +9 -0
- package/src/lib/spawn.ts +6 -2
- package/src/sdk/providers/claude.ts +131 -0
- package/src/sdk/providers/copilot.ts +30 -1
- package/src/sdk/runtime/executor.ts +43 -2
- package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +318 -158
- package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +253 -129
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/batching.ts +65 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/ignore-by-default.d.ts +8 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.ts +203 -12
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/scout.ts +248 -78
- package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +258 -146
- package/src/services/config/additional-instructions.ts +273 -0
- package/src/services/system/auto-sync.ts +10 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copilot workflow source validation.
|
|
2
|
+
* Copilot workflow source validation + helpers.
|
|
3
3
|
*
|
|
4
4
|
* Checks that Copilot workflow source files use the runtime-managed
|
|
5
5
|
* `s.client` and `s.session` instead of manual SDK client creation.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { SessionConfig as CopilotSessionConfig } from "@github/copilot-sdk";
|
|
8
9
|
import { createProviderValidator } from "../types.ts";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -27,6 +28,34 @@ export function copilotSubprocessEnv(): Record<string, string | undefined> {
|
|
|
27
28
|
return { ...process.env, NODE_NO_WARNINGS: "1" };
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Fold the atomic-managed additional instructions into a caller's
|
|
33
|
+
* `systemMessage` value on `client.createSession`. Behavior:
|
|
34
|
+
*
|
|
35
|
+
* - **No caller value** → `{ mode: "append", content: extra }`. The
|
|
36
|
+
* SDK's default mode is append and preserves the SDK persona.
|
|
37
|
+
* - **Append/customize mode** → concatenate our content to the existing
|
|
38
|
+
* `content` field (newline-separated when both are present).
|
|
39
|
+
* - **Replace mode** → leave alone. The caller has explicitly opted out
|
|
40
|
+
* of SDK-managed sections; silently re-adding the persona-style append
|
|
41
|
+
* would violate that contract.
|
|
42
|
+
*
|
|
43
|
+
* Exported for unit testing.
|
|
44
|
+
*/
|
|
45
|
+
export function mergeCopilotSystemMessage(
|
|
46
|
+
existing: CopilotSessionConfig["systemMessage"],
|
|
47
|
+
extra: string,
|
|
48
|
+
): CopilotSessionConfig["systemMessage"] {
|
|
49
|
+
if (!extra) return existing;
|
|
50
|
+
if (existing === undefined) {
|
|
51
|
+
return { mode: "append", content: extra };
|
|
52
|
+
}
|
|
53
|
+
if (existing.mode === "replace") return existing;
|
|
54
|
+
const prev = existing.content ?? "";
|
|
55
|
+
const merged = prev ? `${prev}\n\n${extra}` : extra;
|
|
56
|
+
return { ...existing, content: merged };
|
|
57
|
+
}
|
|
58
|
+
|
|
30
59
|
/**
|
|
31
60
|
* Validate a Copilot workflow source file for common mistakes.
|
|
32
61
|
*/
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
} from "../../services/config/definitions.ts";
|
|
41
41
|
import { getProviderOverrides } from "../../services/config/atomic-config.ts";
|
|
42
42
|
import { getCopilotScmDisableFlags } from "../../services/config/scm-sync.ts";
|
|
43
|
+
import { reconcileOpencodeInstructions } from "../../services/config/additional-instructions.ts";
|
|
43
44
|
import { ensureDir } from "../../services/system/copy.ts";
|
|
44
45
|
import type { SessionEvent } from "@github/copilot-sdk";
|
|
45
46
|
import type { SessionPromptResponse } from "@opencode-ai/sdk/v2";
|
|
@@ -481,6 +482,19 @@ export async function executeWorkflow(
|
|
|
481
482
|
detach = false,
|
|
482
483
|
} = options;
|
|
483
484
|
|
|
485
|
+
// OpenCode reads its `instructions` array from `.opencode/opencode.json`
|
|
486
|
+
// at server-start time — both for the interactive tmux-pane path and the
|
|
487
|
+
// headless `createOpencode({ port: 0 })` path. Reconcile here, before
|
|
488
|
+
// either spawn, so the resolved AGENTS.md is the source of truth on
|
|
489
|
+
// every workflow run. Best-effort: a malformed config shouldn't block.
|
|
490
|
+
if (agent === "opencode") {
|
|
491
|
+
try {
|
|
492
|
+
await reconcileOpencodeInstructions(projectRoot);
|
|
493
|
+
} catch {
|
|
494
|
+
/* swallow */
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
484
498
|
const workflowRunId = generateId();
|
|
485
499
|
const tmuxSessionName = `atomic-wf-${agent}-${definition.name}-${workflowRunId}`;
|
|
486
500
|
const sessionsBaseDir = join(getSessionsBaseDir(), workflowRunId);
|
|
@@ -1174,6 +1188,14 @@ function createMessagesReader(
|
|
|
1174
1188
|
interface SharedRunnerState {
|
|
1175
1189
|
tmuxSessionName: string;
|
|
1176
1190
|
sessionsBaseDir: string;
|
|
1191
|
+
/**
|
|
1192
|
+
* The project root the workflow is operating against. Threaded through to
|
|
1193
|
+
* provider initialization so headless paths resolve project-scoped config
|
|
1194
|
+
* (e.g. `additional-instructions`) from the workflow's actual root rather
|
|
1195
|
+
* than `process.cwd()`, which can drift when workflows are invoked
|
|
1196
|
+
* programmatically or from a subdirectory.
|
|
1197
|
+
*/
|
|
1198
|
+
projectRoot: string;
|
|
1177
1199
|
agent: AgentType;
|
|
1178
1200
|
/**
|
|
1179
1201
|
* Structured inputs for this workflow run. Free-form workflows use
|
|
@@ -1270,6 +1292,7 @@ async function initProviderClientAndSession<A extends AgentType>(
|
|
|
1270
1292
|
agent: A,
|
|
1271
1293
|
serverUrl: string,
|
|
1272
1294
|
paneId: string,
|
|
1295
|
+
projectRoot: string,
|
|
1273
1296
|
clientOpts: StageClientOptions<A>,
|
|
1274
1297
|
sessionOpts: StageSessionOptions<A>,
|
|
1275
1298
|
headless = false,
|
|
@@ -1289,7 +1312,12 @@ async function initProviderClientAndSession<A extends AgentType>(
|
|
|
1289
1312
|
switch (agent) {
|
|
1290
1313
|
case "copilot": {
|
|
1291
1314
|
const { CopilotClient, approveAll } = await import("@github/copilot-sdk");
|
|
1292
|
-
const { copilotSubprocessEnv } = await import(
|
|
1315
|
+
const { copilotSubprocessEnv, mergeCopilotSystemMessage } = await import(
|
|
1316
|
+
"../providers/copilot.ts"
|
|
1317
|
+
);
|
|
1318
|
+
const { resolveAdditionalInstructionsContent } = await import(
|
|
1319
|
+
"../../services/config/additional-instructions.ts"
|
|
1320
|
+
);
|
|
1293
1321
|
const copilotClientOpts = clientOpts as StageClientOptions<"copilot">;
|
|
1294
1322
|
const copilotSessionOpts = sessionOpts as StageSessionOptions<"copilot">;
|
|
1295
1323
|
// Headless: let the SDK spawn its own CLI process (no cliUrl).
|
|
@@ -1320,6 +1348,9 @@ async function initProviderClientAndSession<A extends AgentType>(
|
|
|
1320
1348
|
// In headless stages, add `ask_user` to the session's excludedTools so
|
|
1321
1349
|
// the agent cannot call the interactive question tool — there is no
|
|
1322
1350
|
// human attached to answer and the SDK would otherwise sit blocked.
|
|
1351
|
+
const additionalInstructions = await resolveAdditionalInstructionsContent(
|
|
1352
|
+
projectRoot,
|
|
1353
|
+
);
|
|
1323
1354
|
const sessionConfig = {
|
|
1324
1355
|
onPermissionRequest: approveAll,
|
|
1325
1356
|
...copilotSessionOpts,
|
|
@@ -1334,6 +1365,14 @@ async function initProviderClientAndSession<A extends AgentType>(
|
|
|
1334
1365
|
),
|
|
1335
1366
|
}
|
|
1336
1367
|
: {}),
|
|
1368
|
+
...(additionalInstructions
|
|
1369
|
+
? {
|
|
1370
|
+
systemMessage: mergeCopilotSystemMessage(
|
|
1371
|
+
copilotSessionOpts.systemMessage,
|
|
1372
|
+
additionalInstructions,
|
|
1373
|
+
),
|
|
1374
|
+
}
|
|
1375
|
+
: {}),
|
|
1337
1376
|
};
|
|
1338
1377
|
const session = await client.createSession(sessionConfig);
|
|
1339
1378
|
if (!headless) {
|
|
@@ -1379,7 +1418,7 @@ async function initProviderClientAndSession<A extends AgentType>(
|
|
|
1379
1418
|
// tracks the latest one and exposes it as `sessionId`.
|
|
1380
1419
|
const client = new HeadlessClaudeClientWrapper();
|
|
1381
1420
|
await client.start();
|
|
1382
|
-
const session = new HeadlessClaudeSessionWrapper();
|
|
1421
|
+
const session = new HeadlessClaudeSessionWrapper(projectRoot);
|
|
1383
1422
|
// Cast through `unknown` — `HeadlessClaudeClientWrapper` intentionally
|
|
1384
1423
|
// omits the interactive-only fields (`paneId`, `sessionDir`, etc.)
|
|
1385
1424
|
// that `ClaudeClientWrapper` has; both satisfy the same runtime
|
|
@@ -1661,6 +1700,7 @@ function createSessionRunner(
|
|
|
1661
1700
|
shared.agent,
|
|
1662
1701
|
serverUrl,
|
|
1663
1702
|
paneId,
|
|
1703
|
+
shared.projectRoot,
|
|
1664
1704
|
clientOpts,
|
|
1665
1705
|
sessionOpts,
|
|
1666
1706
|
isHeadless,
|
|
@@ -2002,6 +2042,7 @@ export async function runOrchestrator(
|
|
|
2002
2042
|
const shared: SharedRunnerState = {
|
|
2003
2043
|
tmuxSessionName,
|
|
2004
2044
|
sessionsBaseDir,
|
|
2045
|
+
projectRoot: cwd,
|
|
2005
2046
|
agent,
|
|
2006
2047
|
inputs,
|
|
2007
2048
|
providerOverrides,
|