@agentic-workflow-kit/orchestrator 0.1.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/LICENSE +21 -0
- package/dist/analysis/runAnalyzer.d.ts +22 -0
- package/dist/analysis/runAnalyzer.d.ts.map +1 -0
- package/dist/analysis/runAnalyzer.js +177 -0
- package/dist/artifacts/FileArtifactStore.d.ts +9 -0
- package/dist/artifacts/FileArtifactStore.d.ts.map +1 -0
- package/dist/artifacts/FileArtifactStore.js +21 -0
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +213 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +284 -0
- package/dist/clock/SystemClock.d.ts +6 -0
- package/dist/clock/SystemClock.d.ts.map +1 -0
- package/dist/clock/SystemClock.js +8 -0
- package/dist/config/configLoader.d.ts +5 -0
- package/dist/config/configLoader.d.ts.map +1 -0
- package/dist/config/configLoader.js +105 -0
- package/dist/config/generate-schema.d.ts +2 -0
- package/dist/config/generate-schema.d.ts.map +1 -0
- package/dist/config/generate-schema.js +8 -0
- package/dist/config/jsonSchema.d.ts +3 -0
- package/dist/config/jsonSchema.d.ts.map +1 -0
- package/dist/config/jsonSchema.js +44 -0
- package/dist/config/preset.d.ts +16 -0
- package/dist/config/preset.d.ts.map +1 -0
- package/dist/config/preset.js +14 -0
- package/dist/config/resolve.d.ts +12 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +30 -0
- package/dist/config/schema.d.ts +68 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +80 -0
- package/dist/drivers/StoryRunner.d.ts +24 -0
- package/dist/drivers/StoryRunner.d.ts.map +1 -0
- package/dist/drivers/StoryRunner.js +1 -0
- package/dist/drivers/codex-mcp/CodexMcpStoryRunner.d.ts +25 -0
- package/dist/drivers/codex-mcp/CodexMcpStoryRunner.d.ts.map +1 -0
- package/dist/drivers/codex-mcp/CodexMcpStoryRunner.js +145 -0
- package/dist/drivers/codex-mcp/schemaValidation.d.ts +7 -0
- package/dist/drivers/codex-mcp/schemaValidation.d.ts.map +1 -0
- package/dist/drivers/codex-mcp/schemaValidation.js +43 -0
- package/dist/drivers/codex-mcp/toolInput.d.ts +12 -0
- package/dist/drivers/codex-mcp/toolInput.d.ts.map +1 -0
- package/dist/drivers/codex-mcp/toolInput.js +82 -0
- package/dist/git/GitInspector.d.ts +34 -0
- package/dist/git/GitInspector.d.ts.map +1 -0
- package/dist/git/GitInspector.js +73 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/internal/guards.d.ts +4 -0
- package/dist/internal/guards.d.ts.map +1 -0
- package/dist/internal/guards.js +9 -0
- package/dist/logging/ConsoleLogger.d.ts +7 -0
- package/dist/logging/ConsoleLogger.d.ts.map +1 -0
- package/dist/logging/ConsoleLogger.js +16 -0
- package/dist/metrics/aggregate.d.ts +6 -0
- package/dist/metrics/aggregate.d.ts.map +1 -0
- package/dist/metrics/aggregate.js +32 -0
- package/dist/metrics/liveMetrics.d.ts +16 -0
- package/dist/metrics/liveMetrics.d.ts.map +1 -0
- package/dist/metrics/liveMetrics.js +16 -0
- package/dist/runner/CompletionGate.d.ts +25 -0
- package/dist/runner/CompletionGate.d.ts.map +1 -0
- package/dist/runner/CompletionGate.js +49 -0
- package/dist/runner/MetricsCollector.d.ts +27 -0
- package/dist/runner/MetricsCollector.d.ts.map +1 -0
- package/dist/runner/MetricsCollector.js +49 -0
- package/dist/runner/RunJournal.d.ts +32 -0
- package/dist/runner/RunJournal.d.ts.map +1 -0
- package/dist/runner/RunJournal.js +78 -0
- package/dist/runner/WorkflowRunner.d.ts +45 -0
- package/dist/runner/WorkflowRunner.d.ts.map +1 -0
- package/dist/runner/WorkflowRunner.js +289 -0
- package/dist/scheduler/scheduler.d.ts +8 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/scheduler/scheduler.js +8 -0
- package/dist/tracks/markdownTracker.d.ts +29 -0
- package/dist/tracks/markdownTracker.d.ts.map +1 -0
- package/dist/tracks/markdownTracker.js +349 -0
- package/dist/types.d.ts +222 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const nonEmpty = z.string().min(1);
|
|
3
|
+
export const ConfigSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
version: z.literal(1),
|
|
6
|
+
paths: z
|
|
7
|
+
.object({
|
|
8
|
+
tracksDir: nonEmpty.default('docs/tracks'),
|
|
9
|
+
specsDir: nonEmpty.default('docs/specs'),
|
|
10
|
+
plansDir: nonEmpty.default('docs/plans'),
|
|
11
|
+
archiveDir: nonEmpty.default('docs/tracks/archive'),
|
|
12
|
+
prdsDir: nonEmpty.default('docs/prds'),
|
|
13
|
+
})
|
|
14
|
+
.strict()
|
|
15
|
+
.prefault({}),
|
|
16
|
+
statuses: z
|
|
17
|
+
.object({
|
|
18
|
+
eligible: z.array(nonEmpty).min(1).default(['specced', 'plan-approved']),
|
|
19
|
+
inProgress: nonEmpty.default('implementing'),
|
|
20
|
+
complete: z.array(nonEmpty).min(1).default(['done', 'verified']),
|
|
21
|
+
})
|
|
22
|
+
.strict()
|
|
23
|
+
.prefault({}),
|
|
24
|
+
tracker: z
|
|
25
|
+
.object({ idPattern: nonEmpty.default('^[A-Z]{2,}[0-9]+$') })
|
|
26
|
+
.strict()
|
|
27
|
+
.prefault({}),
|
|
28
|
+
verify: z
|
|
29
|
+
.object({
|
|
30
|
+
changed: nonEmpty.nullable().default(null),
|
|
31
|
+
full: nonEmpty.nullable().default(null),
|
|
32
|
+
})
|
|
33
|
+
.strict()
|
|
34
|
+
.prefault({}),
|
|
35
|
+
git: z
|
|
36
|
+
.object({
|
|
37
|
+
strategy: z.enum(['worktree', 'branch']).default('worktree'),
|
|
38
|
+
branchPattern: nonEmpty.default('{track}/{id-lc}-{slug}'),
|
|
39
|
+
baseBranch: nonEmpty.default('main'),
|
|
40
|
+
commitOnBase: z.enum(['forbid', 'allow']).default('forbid'),
|
|
41
|
+
})
|
|
42
|
+
.strict()
|
|
43
|
+
.prefault({}),
|
|
44
|
+
pr: z
|
|
45
|
+
.object({
|
|
46
|
+
create: z.boolean().default(true),
|
|
47
|
+
ci: z
|
|
48
|
+
.object({ wait: z.boolean().default(false), command: nonEmpty.nullable().default(null) })
|
|
49
|
+
.strict()
|
|
50
|
+
.prefault({}),
|
|
51
|
+
review: z
|
|
52
|
+
.object({
|
|
53
|
+
wait: z.enum(['none', 'bot', 'human']).default('none'),
|
|
54
|
+
bot: nonEmpty.default('none'),
|
|
55
|
+
triageComments: z.boolean().default(false),
|
|
56
|
+
})
|
|
57
|
+
.strict()
|
|
58
|
+
.prefault({}),
|
|
59
|
+
merge: z
|
|
60
|
+
.object({
|
|
61
|
+
auto: z.boolean().default(false),
|
|
62
|
+
method: z.enum(['squash', 'merge', 'rebase']).default('squash'),
|
|
63
|
+
deleteBranch: z.boolean().default(true),
|
|
64
|
+
})
|
|
65
|
+
.strict()
|
|
66
|
+
.prefault({}),
|
|
67
|
+
})
|
|
68
|
+
.strict()
|
|
69
|
+
.prefault({}),
|
|
70
|
+
orchestrator: z
|
|
71
|
+
.object({
|
|
72
|
+
driver: nonEmpty.default('codex-mcp'),
|
|
73
|
+
maxParallel: z.number().int().min(1).default(2),
|
|
74
|
+
stopLaunchingOnBlocked: z.boolean().default(true),
|
|
75
|
+
childTimeoutMs: z.number().int().min(1).default(1_800_000),
|
|
76
|
+
})
|
|
77
|
+
.strict()
|
|
78
|
+
.prefault({}),
|
|
79
|
+
})
|
|
80
|
+
.strict();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ChildMetricsSnapshot, WorkflowStory } from '../types.js';
|
|
2
|
+
export interface StoryRunRequest {
|
|
3
|
+
story: WorkflowStory;
|
|
4
|
+
prompt: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
metadata: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface StoryRunResult {
|
|
9
|
+
storyId: string;
|
|
10
|
+
sessionId: string | null;
|
|
11
|
+
content: string;
|
|
12
|
+
rawResult: unknown;
|
|
13
|
+
invocation: Record<string, unknown>;
|
|
14
|
+
metrics?: ChildMetricsSnapshot;
|
|
15
|
+
}
|
|
16
|
+
export interface DriverToolStatus {
|
|
17
|
+
ok: boolean;
|
|
18
|
+
tools: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface StoryRunner {
|
|
21
|
+
runStory(request: StoryRunRequest): Promise<StoryRunResult>;
|
|
22
|
+
checkTools(): Promise<DriverToolStatus>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=StoryRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StoryRunner.d.ts","sourceRoot":"","sources":["../../src/drivers/StoryRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5D,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
+
import type { ResolvedWorkflowConfig } from '../../types.js';
|
|
4
|
+
import type { DriverToolStatus, StoryRunner, StoryRunRequest, StoryRunResult } from '../StoryRunner.js';
|
|
5
|
+
type CodexMcpClient = Pick<Client, 'connect' | 'callTool' | 'listTools' | 'close'>;
|
|
6
|
+
export interface CodexMcpStoryRunnerOptions {
|
|
7
|
+
startupTimeoutMs?: number;
|
|
8
|
+
requestTimeoutMs?: number;
|
|
9
|
+
retries?: number;
|
|
10
|
+
createClient?: () => {
|
|
11
|
+
client: CodexMcpClient;
|
|
12
|
+
transport: StdioClientTransport;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare class CodexMcpStoryRunner implements StoryRunner {
|
|
16
|
+
private readonly config;
|
|
17
|
+
private readonly options;
|
|
18
|
+
constructor(config: ResolvedWorkflowConfig, options?: CodexMcpStoryRunnerOptions);
|
|
19
|
+
runStory(request: StoryRunRequest): Promise<StoryRunResult>;
|
|
20
|
+
checkTools(): Promise<DriverToolStatus>;
|
|
21
|
+
private withClient;
|
|
22
|
+
private createClient;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=CodexMcpStoryRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodexMcpStoryRunner.d.ts","sourceRoot":"","sources":["../../../src/drivers/codex-mcp/CodexMcpStoryRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAKjF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASxG,KAAK,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC;AAEnF,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,SAAS,EAAE,oBAAoB,CAAA;KAAE,CAAC;CAClF;AAED,qBAAa,mBAAoB,YAAW,WAAW;IAEnD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE,0BAA+B;IAGrD,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAuC3D,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;YAsB/B,UAAU;IAwBxB,OAAO,CAAC,YAAY;CAcrB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
+
import pRetry, { AbortError } from 'p-retry';
|
|
4
|
+
import pTimeout from 'p-timeout';
|
|
5
|
+
import { isRecord } from '../../internal/guards.js';
|
|
6
|
+
import { validateCodexToolSchemas } from './schemaValidation.js';
|
|
7
|
+
import { buildCodexToolInput } from './toolInput.js';
|
|
8
|
+
const VERSION = '0.1.0';
|
|
9
|
+
const STARTUP_TIMEOUT_MS = 30_000;
|
|
10
|
+
const REQUEST_TIMEOUT_MS = 60 * 60 * 1000;
|
|
11
|
+
const RETRIES = 2;
|
|
12
|
+
export class CodexMcpStoryRunner {
|
|
13
|
+
config;
|
|
14
|
+
options;
|
|
15
|
+
constructor(config, options = {}) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.options = options;
|
|
18
|
+
}
|
|
19
|
+
async runStory(request) {
|
|
20
|
+
return await this.withClient(async (client) => {
|
|
21
|
+
const invocation = buildCodexToolInput(this.config, request.story, request.prompt);
|
|
22
|
+
const requestTimeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
23
|
+
const totalTimeoutMs = Math.min(requestTimeoutMs, this.config.orchestrator.childTimeoutMs);
|
|
24
|
+
const rawResult = await pTimeout(client.callTool({
|
|
25
|
+
name: 'codex',
|
|
26
|
+
arguments: invocation,
|
|
27
|
+
}, undefined, {
|
|
28
|
+
timeout: requestTimeoutMs,
|
|
29
|
+
resetTimeoutOnProgress: true,
|
|
30
|
+
maxTotalTimeout: totalTimeoutMs,
|
|
31
|
+
}), {
|
|
32
|
+
milliseconds: totalTimeoutMs,
|
|
33
|
+
message: 'Codex MCP request timed out',
|
|
34
|
+
});
|
|
35
|
+
if (isToolError(rawResult)) {
|
|
36
|
+
throw new AbortError(extractContent(rawResult) || 'Codex MCP returned a tool error');
|
|
37
|
+
}
|
|
38
|
+
const output = validateCodexToolOutput(rawResult);
|
|
39
|
+
return {
|
|
40
|
+
storyId: request.story.id,
|
|
41
|
+
sessionId: output.threadId,
|
|
42
|
+
content: output.content,
|
|
43
|
+
rawResult,
|
|
44
|
+
invocation: invocation,
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async checkTools() {
|
|
49
|
+
return await this.withClient(async (client) => {
|
|
50
|
+
const startupTimeoutMs = this.options.startupTimeoutMs ?? STARTUP_TIMEOUT_MS;
|
|
51
|
+
const result = await pTimeout(client.listTools({}, {
|
|
52
|
+
timeout: startupTimeoutMs,
|
|
53
|
+
maxTotalTimeout: startupTimeoutMs,
|
|
54
|
+
}), {
|
|
55
|
+
milliseconds: startupTimeoutMs,
|
|
56
|
+
message: 'Codex MCP tools/list timed out',
|
|
57
|
+
});
|
|
58
|
+
const tools = validateListToolsResult(result);
|
|
59
|
+
validateCodexToolSchemas(tools);
|
|
60
|
+
return { ok: true, tools: tools.map((tool) => tool.name) };
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async withClient(operation) {
|
|
64
|
+
return await pRetry(async () => {
|
|
65
|
+
const { client, transport } = this.createClient();
|
|
66
|
+
try {
|
|
67
|
+
await pTimeout(client.connect(transport), {
|
|
68
|
+
milliseconds: this.options.startupTimeoutMs ?? STARTUP_TIMEOUT_MS,
|
|
69
|
+
message: 'Codex MCP startup timed out',
|
|
70
|
+
});
|
|
71
|
+
return await operation(client);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error instanceof AbortError)
|
|
75
|
+
throw error;
|
|
76
|
+
if (isTransientError(error))
|
|
77
|
+
throw error;
|
|
78
|
+
throw new AbortError(error instanceof Error ? error : new Error(String(error)));
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await client.close();
|
|
82
|
+
}
|
|
83
|
+
}, {
|
|
84
|
+
retries: this.options.retries ?? RETRIES,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
createClient() {
|
|
88
|
+
if (this.options.createClient)
|
|
89
|
+
return this.options.createClient();
|
|
90
|
+
const client = new Client({
|
|
91
|
+
name: 'agentic-workflow-kit-orchestrator',
|
|
92
|
+
version: VERSION,
|
|
93
|
+
});
|
|
94
|
+
const transport = new StdioClientTransport({
|
|
95
|
+
command: 'codex',
|
|
96
|
+
args: ['mcp-server'],
|
|
97
|
+
cwd: this.config.workspace.rootAbs,
|
|
98
|
+
stderr: 'inherit',
|
|
99
|
+
});
|
|
100
|
+
return { client, transport };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function validateCodexToolOutput(value) {
|
|
104
|
+
if (!isRecord(value))
|
|
105
|
+
throw new AbortError('Codex MCP result must be an object');
|
|
106
|
+
if (!isRecord(value.structuredContent))
|
|
107
|
+
throw new AbortError('Codex MCP result missing structuredContent');
|
|
108
|
+
const { threadId, content } = value.structuredContent;
|
|
109
|
+
if (typeof threadId !== 'string' || threadId.length === 0) {
|
|
110
|
+
throw new AbortError('Codex MCP result missing structuredContent.threadId');
|
|
111
|
+
}
|
|
112
|
+
if (typeof content !== 'string') {
|
|
113
|
+
throw new AbortError('Codex MCP result missing structuredContent.content');
|
|
114
|
+
}
|
|
115
|
+
return { threadId, content };
|
|
116
|
+
}
|
|
117
|
+
function validateListToolsResult(value) {
|
|
118
|
+
if (!isRecord(value) || !Array.isArray(value.tools)) {
|
|
119
|
+
throw new AbortError('MCP tools/list result must contain a tools array');
|
|
120
|
+
}
|
|
121
|
+
return value.tools.map((tool, index) => {
|
|
122
|
+
if (!isRecord(tool) || typeof tool.name !== 'string' || !isRecord(tool.inputSchema)) {
|
|
123
|
+
throw new AbortError(`MCP tool ${index} is malformed`);
|
|
124
|
+
}
|
|
125
|
+
return tool;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function isToolError(value) {
|
|
129
|
+
return isRecord(value) && value.isError === true;
|
|
130
|
+
}
|
|
131
|
+
function extractContent(value) {
|
|
132
|
+
if (!isRecord(value) || !Array.isArray(value.content))
|
|
133
|
+
return '';
|
|
134
|
+
return value.content
|
|
135
|
+
.filter((block) => isRecord(block) && block.type === 'text' && typeof block.text === 'string')
|
|
136
|
+
.map((block) => block.text)
|
|
137
|
+
.join('\n');
|
|
138
|
+
}
|
|
139
|
+
function isTransientError(error) {
|
|
140
|
+
if (!(error instanceof Error))
|
|
141
|
+
return false;
|
|
142
|
+
// Retry only connect/startup transients. Request timeouts can represent a full story run,
|
|
143
|
+
// and ENOENT means the codex binary is missing, so both must fail without retry.
|
|
144
|
+
return /(startup|connect|connection|ECONN)/i.test(error.message);
|
|
145
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemaValidation.d.ts","sourceRoot":"","sources":["../../../src/drivers/codex-mcp/schemaValidation.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAKD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAoB/D"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isRecord } from '../../internal/guards.js';
|
|
2
|
+
const REQUIRED_APPROVAL_POLICIES = ['never', 'on-failure', 'on-request', 'untrusted'];
|
|
3
|
+
const REQUIRED_SANDBOX_MODES = ['danger-full-access', 'read-only', 'workspace-write'];
|
|
4
|
+
export function validateCodexToolSchemas(tools) {
|
|
5
|
+
const codex = tools.find((tool) => tool.name === 'codex');
|
|
6
|
+
if (!codex) {
|
|
7
|
+
throw new Error('Codex MCP server must expose a codex tool');
|
|
8
|
+
}
|
|
9
|
+
if (codex.inputSchema?.type !== 'object') {
|
|
10
|
+
throw new Error('Codex MCP codex tool must declare an object input schema');
|
|
11
|
+
}
|
|
12
|
+
const properties = codex.inputSchema.properties;
|
|
13
|
+
if (!isRecord(properties) || !isRecord(properties.prompt)) {
|
|
14
|
+
throw new Error('Codex MCP codex tool must declare a prompt input property');
|
|
15
|
+
}
|
|
16
|
+
requireProperty(properties, 'model');
|
|
17
|
+
requireProperty(properties, 'config');
|
|
18
|
+
const approvalPolicy = requireProperty(properties, 'approval-policy');
|
|
19
|
+
const sandbox = requireProperty(properties, 'sandbox');
|
|
20
|
+
validateEnumIfPresent(approvalPolicy, REQUIRED_APPROVAL_POLICIES, 'approval-policy');
|
|
21
|
+
validateEnumIfPresent(sandbox, REQUIRED_SANDBOX_MODES, 'sandbox');
|
|
22
|
+
}
|
|
23
|
+
function requireProperty(properties, propertyName) {
|
|
24
|
+
if (!(propertyName in properties)) {
|
|
25
|
+
const article = propertyName === 'approval-policy' ? 'an' : 'a';
|
|
26
|
+
throw new Error(`Codex MCP codex tool must declare ${article} ${propertyName} input property`);
|
|
27
|
+
}
|
|
28
|
+
return properties[propertyName];
|
|
29
|
+
}
|
|
30
|
+
function validateEnumIfPresent(schema, requiredValues, propertyName) {
|
|
31
|
+
if (!isRecord(schema) || schema.enum === undefined) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!Array.isArray(schema.enum)) {
|
|
35
|
+
throw new Error(`Codex MCP ${propertyName} input enum must be an array`);
|
|
36
|
+
}
|
|
37
|
+
const values = new Set(schema.enum);
|
|
38
|
+
for (const required of requiredValues) {
|
|
39
|
+
if (!values.has(required)) {
|
|
40
|
+
throw new Error(`Codex MCP ${propertyName} input enum must include "${required}"`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ResolvedGitConfig, ResolvedWorkflowConfig, WorkflowStory } from '../../types.js';
|
|
2
|
+
export interface CodexToolInput {
|
|
3
|
+
cwd: string;
|
|
4
|
+
prompt: string;
|
|
5
|
+
config?: Record<string, unknown>;
|
|
6
|
+
model?: string;
|
|
7
|
+
'approval-policy'?: string;
|
|
8
|
+
sandbox?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function buildCodexToolInput(config: ResolvedWorkflowConfig, story: WorkflowStory, prompt?: string): CodexToolInput;
|
|
11
|
+
export declare function buildGenericPrompt(story: WorkflowStory, git: ResolvedGitConfig): string;
|
|
12
|
+
//# sourceMappingURL=toolInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolInput.d.ts","sourceRoot":"","sources":["../../../src/drivers/codex-mcp/toolInput.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/F,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,aAAa,EACpB,MAAM,SAAwC,GAC7C,cAAc,CAkChB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAyCvF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export function buildCodexToolInput(config, story, prompt = buildGenericPrompt(story, config.git)) {
|
|
3
|
+
const childSession = config.codex.childSession;
|
|
4
|
+
const input = {
|
|
5
|
+
cwd: childSession.cwdAbs,
|
|
6
|
+
prompt,
|
|
7
|
+
};
|
|
8
|
+
if (childSession.model)
|
|
9
|
+
input.model = childSession.model;
|
|
10
|
+
if (childSession.approvalPolicy)
|
|
11
|
+
input['approval-policy'] = childSession.approvalPolicy;
|
|
12
|
+
if (childSession.sandbox)
|
|
13
|
+
input.sandbox = childSession.sandbox;
|
|
14
|
+
// D8 fix: inject the workspace .git and .worktrees directories as codex writable roots so the
|
|
15
|
+
// child session can run `git commit` and `git worktree add` under --sandbox workspace-write.
|
|
16
|
+
// Under workspace-write codex makes .git read-only by default, which prevents any git commit
|
|
17
|
+
// (every commit updates a ref under .git/refs/heads). Granting these two paths as writable roots
|
|
18
|
+
// keeps workspace-write restrictions intact for everything else (network, system dirs) while
|
|
19
|
+
// allowing git isolation to work. This is harmless under danger-full-access (already writable)
|
|
20
|
+
// and read-only (the child would not be committing anyway).
|
|
21
|
+
//
|
|
22
|
+
// Config shape: sandbox_workspace_write is a top-level TOML table in codex config, so we
|
|
23
|
+
// represent it as a nested object { sandbox_workspace_write: { writable_roots: [...] } } — the
|
|
24
|
+
// same mechanism used for scalar keys like model_reasoning_effort, but one level deeper because
|
|
25
|
+
// sandbox_workspace_write is a table, not a bare key. Verified empirically on 2026-06-03 via
|
|
26
|
+
// `codex exec -c 'sandbox_workspace_write.writable_roots=[...]'` (see d8-dispatch-sandbox-plan.md).
|
|
27
|
+
const workspaceRoot = childSession.cwdAbs;
|
|
28
|
+
const gitAbs = path.join(workspaceRoot, '.git');
|
|
29
|
+
const worktreesAbs = path.join(workspaceRoot, '.worktrees');
|
|
30
|
+
const writableRootsEntry = {
|
|
31
|
+
sandbox_workspace_write: { writable_roots: [gitAbs, worktreesAbs] },
|
|
32
|
+
};
|
|
33
|
+
input.config = { ...childSession.config, ...writableRootsEntry };
|
|
34
|
+
return input;
|
|
35
|
+
}
|
|
36
|
+
export function buildGenericPrompt(story, git) {
|
|
37
|
+
const metadata = story.metadata;
|
|
38
|
+
const branchPattern = renderBranchPattern(story, git.branchPattern);
|
|
39
|
+
const commitOnBase = git.commitOnBase === 'forbid'
|
|
40
|
+
? `Committing directly on \`${git.baseBranch}\` is forbidden.`
|
|
41
|
+
: `Committing directly on \`${git.baseBranch}\` is allowed by this repo policy.`;
|
|
42
|
+
return [
|
|
43
|
+
'Implement exactly one workflow tracker story from the current repository.',
|
|
44
|
+
'',
|
|
45
|
+
'Story:',
|
|
46
|
+
`- ID: ${story.id}`,
|
|
47
|
+
`- Title: ${story.title}`,
|
|
48
|
+
`- Status: ${story.status}`,
|
|
49
|
+
story.owner ? `- Owner: ${story.owner}` : '- Owner: unowned',
|
|
50
|
+
story.dependencies.length > 0 ? `- Dependencies: ${story.dependencies.join(', ')}` : '- Dependencies: none',
|
|
51
|
+
`- Track ID: ${metadata.trackId}`,
|
|
52
|
+
`- Track: ${metadata.trackTitle}`,
|
|
53
|
+
`- Tracker file: ${metadata.trackerPath}`,
|
|
54
|
+
metadata.wave ? `- Wave/phase: ${metadata.wave}` : null,
|
|
55
|
+
metadata.spec ? `- Spec: ${metadata.spec}` : null,
|
|
56
|
+
metadata.plan ? `- Plan: ${metadata.plan}` : null,
|
|
57
|
+
metadata.pr ? `- PR: ${metadata.pr}` : null,
|
|
58
|
+
'',
|
|
59
|
+
'Git policy (from .workflow/config.yaml - follow exactly):',
|
|
60
|
+
`- Isolation strategy: ${git.strategy}`,
|
|
61
|
+
`- Create/use branch: ${branchPattern} (base: ${git.baseBranch})`,
|
|
62
|
+
`- ${commitOnBase}`,
|
|
63
|
+
'- You MUST create the isolated branch/worktree, commit your work there, and confirm the commit exists BEFORE reporting the story done. An uncommitted tracker edit is not acceptance.',
|
|
64
|
+
'',
|
|
65
|
+
'Instructions:',
|
|
66
|
+
'1. Read repository instructions first, including AGENTS.md when present.',
|
|
67
|
+
'2. Read the selected tracker row and any linked spec, plan, related docs, or acceptance notes.',
|
|
68
|
+
'3. Implement only this story. Do not bundle adjacent tracker rows or unrelated cleanup.',
|
|
69
|
+
'4. Follow the Git policy above and the repository documentation, review, and verification rules.',
|
|
70
|
+
'5. Update the tracker row through the repository workflow when the story is complete.',
|
|
71
|
+
'6. The tracker row status is the only completion authority; child prose is not enough.',
|
|
72
|
+
'7. Report changed files, verification evidence, and blockers.',
|
|
73
|
+
]
|
|
74
|
+
.filter((line) => line !== null)
|
|
75
|
+
.join('\n');
|
|
76
|
+
}
|
|
77
|
+
function renderBranchPattern(story, branchPattern) {
|
|
78
|
+
return branchPattern
|
|
79
|
+
.replaceAll('{track}', story.metadata.trackId)
|
|
80
|
+
.replaceAll('{id}', story.id)
|
|
81
|
+
.replaceAll('{id-lc}', story.id.toLowerCase());
|
|
82
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ResolvedGitConfig, WorkflowStory } from '../types.js';
|
|
2
|
+
export interface StoryCommitEvidence {
|
|
3
|
+
committed: boolean;
|
|
4
|
+
branch: string | null;
|
|
5
|
+
isBaseBranch: boolean;
|
|
6
|
+
headSha: string | null;
|
|
7
|
+
baseSha: string | null;
|
|
8
|
+
uncommittedChanges: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface GitInspector {
|
|
11
|
+
snapshotBaseSha?(args: {
|
|
12
|
+
git: ResolvedGitConfig;
|
|
13
|
+
cwdAbs: string;
|
|
14
|
+
}): Promise<string | null>;
|
|
15
|
+
inspectStory(args: {
|
|
16
|
+
story: WorkflowStory;
|
|
17
|
+
git: ResolvedGitConfig;
|
|
18
|
+
cwdAbs: string;
|
|
19
|
+
baseShaAtLaunch?: string | null;
|
|
20
|
+
}): Promise<StoryCommitEvidence>;
|
|
21
|
+
}
|
|
22
|
+
export declare class RealGitInspector implements GitInspector {
|
|
23
|
+
snapshotBaseSha(args: {
|
|
24
|
+
git: ResolvedGitConfig;
|
|
25
|
+
cwdAbs: string;
|
|
26
|
+
}): Promise<string | null>;
|
|
27
|
+
inspectStory(args: {
|
|
28
|
+
story: WorkflowStory;
|
|
29
|
+
git: ResolvedGitConfig;
|
|
30
|
+
cwdAbs: string;
|
|
31
|
+
baseShaAtLaunch?: string | null;
|
|
32
|
+
}): Promise<StoryCommitEvidence>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=GitInspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitInspector.d.ts","sourceRoot":"","sources":["../../src/git/GitInspector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIpE,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,CAAC,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3F,YAAY,CAAC,IAAI,EAAE;QACjB,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,iBAAiB,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAClC;AAED,qBAAa,gBAAiB,YAAW,YAAY;IAC7C,eAAe,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzF,YAAY,CAAC,IAAI,EAAE;QACvB,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,iBAAiB,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA8BjC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
export class RealGitInspector {
|
|
5
|
+
async snapshotBaseSha(args) {
|
|
6
|
+
return await maybeGitOutput(args.cwdAbs, ['rev-parse', '--verify', args.git.baseBranch]);
|
|
7
|
+
}
|
|
8
|
+
async inspectStory(args) {
|
|
9
|
+
const currentBranch = await gitOutput(args.cwdAbs, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
10
|
+
const baseSha = await maybeGitOutput(args.cwdAbs, ['rev-parse', '--verify', args.git.baseBranch]);
|
|
11
|
+
const storyBranch = await resolveStoryBranch(args.cwdAbs, args.story, args.git);
|
|
12
|
+
const inspectedBranch = storyBranch ?? currentBranch;
|
|
13
|
+
const headSha = inspectedBranch
|
|
14
|
+
? await maybeGitOutput(args.cwdAbs, ['rev-parse', '--verify', inspectedBranch])
|
|
15
|
+
: null;
|
|
16
|
+
// Only the resolved story branch determines base-branch placement. In worktree strategy the
|
|
17
|
+
// inspected root checkout stays on the base branch while the child commits on a sibling worktree's
|
|
18
|
+
// story branch, so the inspected checkout's own HEAD must not contaminate this judgement.
|
|
19
|
+
const isBaseBranch = inspectedBranch === args.git.baseBranch;
|
|
20
|
+
const uncommittedChanges = (await gitOutput(args.cwdAbs, ['status', '--porcelain'])).length > 0;
|
|
21
|
+
const comparisonBase = args.baseShaAtLaunch ?? baseSha;
|
|
22
|
+
const commitCount = inspectedBranch && comparisonBase
|
|
23
|
+
? parseCommitCount(await maybeGitOutput(args.cwdAbs, ['rev-list', '--count', `${comparisonBase}..${inspectedBranch}`]))
|
|
24
|
+
: 0;
|
|
25
|
+
return {
|
|
26
|
+
committed: commitCount > 0,
|
|
27
|
+
branch: inspectedBranch,
|
|
28
|
+
isBaseBranch,
|
|
29
|
+
headSha,
|
|
30
|
+
baseSha,
|
|
31
|
+
uncommittedChanges,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function resolveStoryBranch(cwdAbs, story, git) {
|
|
36
|
+
const pattern = branchSearchPattern(story, git);
|
|
37
|
+
const output = await gitOutput(cwdAbs, ['branch', '--list', pattern]);
|
|
38
|
+
const branches = output
|
|
39
|
+
.split('\n')
|
|
40
|
+
// Strip the current-branch marker (`* `) and the other-worktree marker (`+ `) that
|
|
41
|
+
// `git branch --list` prepends; an unstripped `+ ` corrupts the branch name passed to rev-list.
|
|
42
|
+
.map((line) => line.replace(/^[*+]\s*/, '').trim())
|
|
43
|
+
.filter(Boolean)
|
|
44
|
+
.sort();
|
|
45
|
+
// A retried story can leave >1 branch matching the {slug} glob. Pick deterministically
|
|
46
|
+
// (lexically-first) so completion evidence is stable across runs rather than order-dependent.
|
|
47
|
+
return branches[0] ?? null;
|
|
48
|
+
}
|
|
49
|
+
function branchSearchPattern(story, git) {
|
|
50
|
+
return git.branchPattern
|
|
51
|
+
.replaceAll('{track}', story.metadata.trackId)
|
|
52
|
+
.replaceAll('{id}', story.id)
|
|
53
|
+
.replaceAll('{id-lc}', story.id.toLowerCase())
|
|
54
|
+
.replaceAll('{slug}', '*');
|
|
55
|
+
}
|
|
56
|
+
function parseCommitCount(value) {
|
|
57
|
+
if (value === null)
|
|
58
|
+
return 0;
|
|
59
|
+
const parsed = Number(value);
|
|
60
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
61
|
+
}
|
|
62
|
+
async function gitOutput(cwd, args) {
|
|
63
|
+
const { stdout } = await execFileAsync('git', args, { cwd });
|
|
64
|
+
return stdout.trim();
|
|
65
|
+
}
|
|
66
|
+
async function maybeGitOutput(cwd, args) {
|
|
67
|
+
try {
|
|
68
|
+
return await gitOutput(cwd, args);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { analyzeWorkflowRun } from './analysis/runAnalyzer.js';
|
|
2
|
+
export { createRunId, loadResolvedConfig } from './config/configLoader.js';
|
|
3
|
+
export { buildConfigJsonSchema, serializeConfigJsonSchema } from './config/jsonSchema.js';
|
|
4
|
+
export { type PresetName, type RepoSignals, selectPreset } from './config/preset.js';
|
|
5
|
+
export { type LoadConfigOptions, type LoadedConfig, loadConfig } from './config/resolve.js';
|
|
6
|
+
export { ConfigSchema, type WorkflowConfig } from './config/schema.js';
|
|
7
|
+
export { WorkflowRunner } from './runner/WorkflowRunner.js';
|
|
8
|
+
export { isCompleteStatus, selectDispatchableStories } from './scheduler/scheduler.js';
|
|
9
|
+
export { discoverMarkdownTracks, parseTrackerStories } from './tracks/markdownTracker.js';
|
|
10
|
+
export type { ResolvedWorkflowConfig, RunState, WorkflowCommand, WorkflowStory, WorkflowTrack, } from './types.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,YAAY,EACV,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { analyzeWorkflowRun } from './analysis/runAnalyzer.js';
|
|
2
|
+
export { createRunId, loadResolvedConfig } from './config/configLoader.js';
|
|
3
|
+
export { buildConfigJsonSchema, serializeConfigJsonSchema } from './config/jsonSchema.js';
|
|
4
|
+
export { selectPreset } from './config/preset.js';
|
|
5
|
+
export { loadConfig } from './config/resolve.js';
|
|
6
|
+
export { ConfigSchema } from './config/schema.js';
|
|
7
|
+
export { WorkflowRunner } from './runner/WorkflowRunner.js';
|
|
8
|
+
export { isCompleteStatus, selectDispatchableStories } from './scheduler/scheduler.js';
|
|
9
|
+
export { discoverMarkdownTracks, parseTrackerStories } from './tracks/markdownTracker.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/internal/guards.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE1E;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isRecord(value) {
|
|
2
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
export function isNodeError(value) {
|
|
5
|
+
return value instanceof Error && 'code' in value;
|
|
6
|
+
}
|
|
7
|
+
export function safeName(value) {
|
|
8
|
+
return value.replace(/[^a-zA-Z0-9._-]+/g, '-');
|
|
9
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Logger } from '../types.js';
|
|
2
|
+
export declare class ConsoleLogger implements Logger {
|
|
3
|
+
info(message: string, fields?: Record<string, unknown>): void;
|
|
4
|
+
warn(message: string, fields?: Record<string, unknown>): void;
|
|
5
|
+
error(message: string, fields?: Record<string, unknown>): void;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ConsoleLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleLogger.d.ts","sourceRoot":"","sources":["../../src/logging/ConsoleLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,aAAc,YAAW,MAAM;IAC1C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAGjE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAGjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;CAGnE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class ConsoleLogger {
|
|
2
|
+
info(message, fields = {}) {
|
|
3
|
+
console.log(format('info', message, fields));
|
|
4
|
+
}
|
|
5
|
+
warn(message, fields = {}) {
|
|
6
|
+
console.warn(format('warn', message, fields));
|
|
7
|
+
}
|
|
8
|
+
error(message, fields = {}) {
|
|
9
|
+
console.error(format('error', message, fields));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function format(level, message, fields) {
|
|
13
|
+
return Object.keys(fields).length > 0
|
|
14
|
+
? JSON.stringify({ level, message, ...fields })
|
|
15
|
+
: JSON.stringify({ level, message });
|
|
16
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ChildMetricsSnapshot, LiveMetricsSnapshot, TokenTotals } from '../types.js';
|
|
2
|
+
export declare function mergeChildMetrics(children: ChildMetricsSnapshot[]): LiveMetricsSnapshot['aggregate'];
|
|
3
|
+
export declare function addTokenTotals(a: TokenTotals, b: TokenTotals): TokenTotals;
|
|
4
|
+
export declare function mergeCounts(target: Record<string, number>, source: Record<string, number>): void;
|
|
5
|
+
export declare function emptyTokenTotals(): TokenTotals;
|
|
6
|
+
//# sourceMappingURL=aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/metrics/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAgBpG;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,WAAW,CAQ1E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAIhG;AAED,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C"}
|