agentic-orchestrator 0.1.26 → 0.1.28
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.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.md +47 -14
- package/agentic/orchestrator/agents.yaml +13 -0
- package/agentic/orchestrator/policy.yaml +3 -0
- package/agentic/orchestrator/schemas/agents.schema.json +76 -0
- package/agentic/orchestrator/schemas/policy.schema.json +16 -0
- package/agentic/orchestrator/schemas/policy.user.schema.json +16 -0
- package/agentic/orchestrator/schemas/state.schema.json +53 -0
- package/apps/control-plane/src/application/configuration-service.ts +181 -0
- package/apps/control-plane/src/application/kernel-tool-wiring.ts +292 -0
- package/apps/control-plane/src/application/services/checkpoint-service.ts +523 -0
- package/apps/control-plane/src/application/services/feature-send-message-service.ts +132 -0
- package/apps/control-plane/src/application/services/patch-service.ts +29 -5
- package/apps/control-plane/src/application/services/repo-operations-service.ts +276 -0
- package/apps/control-plane/src/application/services/worktree-watchdog-service.ts +156 -0
- package/apps/control-plane/src/cli/cli-argument-parser.ts +12 -0
- package/apps/control-plane/src/cli/help-command-handler.ts +17 -0
- package/apps/control-plane/src/cli/init-command-handler.ts +31 -0
- package/apps/control-plane/src/cli/resume-command-handler.ts +31 -4
- package/apps/control-plane/src/cli/rollback-command-handler.ts +217 -0
- package/apps/control-plane/src/cli/run-command-handler.ts +8 -0
- package/apps/control-plane/src/cli/types.ts +3 -0
- package/apps/control-plane/src/core/kernel-types.ts +55 -0
- package/apps/control-plane/src/core/kernel.ts +61 -878
- package/apps/control-plane/src/core/tool-caller.ts +10 -0
- package/apps/control-plane/src/core/utils/field-readers.ts +38 -0
- package/apps/control-plane/src/core/utils/index-normalizer.ts +119 -0
- package/apps/control-plane/src/core/utils/path-normalizers.ts +22 -0
- package/apps/control-plane/src/interfaces/cli/bootstrap.ts +15 -0
- package/apps/control-plane/src/providers/api-worker-provider.ts +14 -12
- package/apps/control-plane/src/providers/cli-worker-provider.ts +82 -12
- package/apps/control-plane/src/providers/providers.ts +45 -24
- package/apps/control-plane/src/providers/worker-provider-factory.ts +36 -1
- package/apps/control-plane/src/supervisor/run-coordinator.ts +91 -36
- package/apps/control-plane/src/supervisor/runtime.ts +107 -1
- package/apps/control-plane/src/supervisor/types.ts +9 -0
- package/apps/control-plane/src/supervisor/worker-decision-loop.ts +253 -14
- package/apps/control-plane/test/checkpoint-service.spec.ts +537 -0
- package/apps/control-plane/test/cli-helpers.spec.ts +28 -0
- package/apps/control-plane/test/cli.unit.spec.ts +52 -0
- package/apps/control-plane/test/configuration-service.spec.ts +466 -0
- package/apps/control-plane/test/dashboard-api.integration.spec.ts +537 -0
- package/apps/control-plane/test/dashboard-client.spec.ts +233 -0
- package/apps/control-plane/test/feature-send-message-service.spec.ts +314 -0
- package/apps/control-plane/test/init-wizard.spec.ts +35 -0
- package/apps/control-plane/test/path-normalizers.spec.ts +41 -0
- package/apps/control-plane/test/repo-operations-service.spec.ts +339 -0
- package/apps/control-plane/test/resume-command.spec.ts +33 -0
- package/apps/control-plane/test/review-workspace-logic.spec.ts +130 -0
- package/apps/control-plane/test/rollback-command.spec.ts +208 -0
- package/apps/control-plane/test/run-coordinator.spec.ts +119 -0
- package/apps/control-plane/test/worker-decision-loop.spec.ts +209 -0
- package/apps/control-plane/test/worker-provider-adapters.spec.ts +102 -0
- package/apps/control-plane/test/worker-provider-factory.spec.ts +14 -0
- package/apps/control-plane/test/worktree-watchdog-service.spec.ts +147 -0
- package/config/agentic/orchestrator/agents.yaml +13 -0
- package/dist/apps/control-plane/application/configuration-service.d.ts +19 -0
- package/dist/apps/control-plane/application/configuration-service.js +123 -0
- package/dist/apps/control-plane/application/configuration-service.js.map +1 -0
- package/dist/apps/control-plane/application/kernel-tool-wiring.d.ts +39 -0
- package/dist/apps/control-plane/application/kernel-tool-wiring.js +38 -0
- package/dist/apps/control-plane/application/kernel-tool-wiring.js.map +1 -0
- package/dist/apps/control-plane/application/services/checkpoint-service.d.ts +84 -0
- package/dist/apps/control-plane/application/services/checkpoint-service.js +367 -0
- package/dist/apps/control-plane/application/services/checkpoint-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/feature-send-message-service.d.ts +25 -0
- package/dist/apps/control-plane/application/services/feature-send-message-service.js +105 -0
- package/dist/apps/control-plane/application/services/feature-send-message-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/patch-service.d.ts +6 -0
- package/dist/apps/control-plane/application/services/patch-service.js +11 -2
- package/dist/apps/control-plane/application/services/patch-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/repo-operations-service.d.ts +70 -0
- package/dist/apps/control-plane/application/services/repo-operations-service.js +213 -0
- package/dist/apps/control-plane/application/services/repo-operations-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.d.ts +23 -0
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.js +119 -0
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.js.map +1 -0
- package/dist/apps/control-plane/cli/cli-argument-parser.js +12 -0
- package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
- package/dist/apps/control-plane/cli/help-command-handler.js +17 -0
- package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/init-command-handler.js +23 -0
- package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/resume-command-handler.js +25 -5
- package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/rollback-command-handler.d.ts +6 -0
- package/dist/apps/control-plane/cli/rollback-command-handler.js +177 -0
- package/dist/apps/control-plane/cli/rollback-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/run-command-handler.js +7 -1
- package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/types.d.ts +3 -0
- package/dist/apps/control-plane/cli/types.js +1 -0
- package/dist/apps/control-plane/cli/types.js.map +1 -1
- package/dist/apps/control-plane/core/configuration-service.d.ts +25 -0
- package/dist/apps/control-plane/core/configuration-service.js +130 -0
- package/dist/apps/control-plane/core/configuration-service.js.map +1 -0
- package/dist/apps/control-plane/core/kernel-tool-wiring.d.ts +50 -0
- package/dist/apps/control-plane/core/kernel-tool-wiring.js +44 -0
- package/dist/apps/control-plane/core/kernel-tool-wiring.js.map +1 -0
- package/dist/apps/control-plane/core/kernel-types.d.ts +48 -0
- package/dist/apps/control-plane/core/kernel-types.js +2 -0
- package/dist/apps/control-plane/core/kernel-types.js.map +1 -0
- package/dist/apps/control-plane/core/kernel.d.ts +17 -48
- package/dist/apps/control-plane/core/kernel.js +44 -539
- package/dist/apps/control-plane/core/kernel.js.map +1 -1
- package/dist/apps/control-plane/core/tool-caller.d.ts +10 -0
- package/dist/apps/control-plane/core/utils/error-normalizer.d.ts +2 -0
- package/dist/apps/control-plane/core/utils/error-normalizer.js +51 -0
- package/dist/apps/control-plane/core/utils/error-normalizer.js.map +1 -0
- package/dist/apps/control-plane/core/utils/field-readers.d.ts +9 -0
- package/dist/apps/control-plane/core/utils/field-readers.js +30 -0
- package/dist/apps/control-plane/core/utils/field-readers.js.map +1 -0
- package/dist/apps/control-plane/core/utils/index-normalizer.d.ts +7 -0
- package/dist/apps/control-plane/core/utils/index-normalizer.js +92 -0
- package/dist/apps/control-plane/core/utils/index-normalizer.js.map +1 -0
- package/dist/apps/control-plane/core/utils/path-normalizers.d.ts +2 -0
- package/dist/apps/control-plane/core/utils/path-normalizers.js +17 -0
- package/dist/apps/control-plane/core/utils/path-normalizers.js.map +1 -0
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js +13 -1
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
- package/dist/apps/control-plane/providers/api-worker-provider.d.ts +4 -13
- package/dist/apps/control-plane/providers/api-worker-provider.js +10 -0
- package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -1
- package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +11 -13
- package/dist/apps/control-plane/providers/cli-worker-provider.js +64 -0
- package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -1
- package/dist/apps/control-plane/providers/providers.d.ts +31 -24
- package/dist/apps/control-plane/providers/providers.js +10 -0
- package/dist/apps/control-plane/providers/providers.js.map +1 -1
- package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +11 -0
- package/dist/apps/control-plane/providers/worker-provider-factory.js +20 -1
- package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
- package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +3 -0
- package/dist/apps/control-plane/supervisor/run-coordinator.js +81 -33
- package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
- package/dist/apps/control-plane/supervisor/runtime.d.ts +8 -1
- package/dist/apps/control-plane/supervisor/runtime.js +90 -0
- package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
- package/dist/apps/control-plane/supervisor/types.d.ts +11 -0
- package/dist/apps/control-plane/supervisor/types.js.map +1 -1
- package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +21 -1
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js +207 -13
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
- package/package.json +1 -1
- package/packages/web-dashboard/package.json +2 -0
- package/packages/web-dashboard/src/app/analytics/page.tsx +83 -2
- package/packages/web-dashboard/src/app/api/actions/route.ts +92 -1
- package/packages/web-dashboard/src/app/api/analytics/route.ts +5 -2
- package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/[checkpointId]/diff/route.ts +43 -0
- package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/compare/route.ts +45 -0
- package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/stream/route.ts +170 -0
- package/packages/web-dashboard/src/app/api/features/[id]/file-diff/route.ts +144 -0
- package/packages/web-dashboard/src/app/api/features/[id]/log-stream/route.ts +167 -0
- package/packages/web-dashboard/src/app/api/features/[id]/raw-logs/[filename]/route.ts +65 -0
- package/packages/web-dashboard/src/app/api/features/[id]/raw-logs/route.ts +63 -0
- package/packages/web-dashboard/src/app/api/features/[id]/timeline/route.ts +60 -0
- package/packages/web-dashboard/src/app/feature/[id]/page.tsx +32 -11
- package/packages/web-dashboard/src/app/globals.css +2 -0
- package/packages/web-dashboard/src/components/detail-panel.tsx +483 -0
- package/packages/web-dashboard/src/components/review-workspace.tsx +1162 -0
- package/packages/web-dashboard/src/lib/aop-client.ts +725 -0
- package/packages/web-dashboard/src/lib/review-contracts.ts +182 -0
- package/packages/web-dashboard/src/lib/review-workspace-logic.ts +64 -0
- package/packages/web-dashboard/src/lib/types.ts +131 -0
- package/packages/web-dashboard/src/styles/dashboard.module.css +333 -0
- package/spec-files/completed/agentic_orchestrator_execution_mode_spec.md +1905 -0
- package/spec-files/outstanding/agentic_orchestrator_runtime_inspection_spec.md +940 -0
- package/spec-files/outstanding/execution_mode_critical_review.md +355 -0
- package/spec-files/outstanding/shadow_workspace_implementation_spec.md +1271 -0
- package/spec-files/outstanding/shadow_workspace_spec_summary.md +222 -0
- package/spec-files/progress.md +269 -1
|
@@ -26,6 +26,16 @@ export interface ToolCaller {
|
|
|
26
26
|
export interface FeatureStateFrontMatter {
|
|
27
27
|
version: number;
|
|
28
28
|
status: string;
|
|
29
|
+
execution_mode?: 'deterministic' | 'interactive';
|
|
30
|
+
checkpoints?: Array<{
|
|
31
|
+
checkpoint_id: string;
|
|
32
|
+
timestamp: string;
|
|
33
|
+
files_changed: string[];
|
|
34
|
+
validation_status: 'valid' | 'invalid' | 'skipped';
|
|
35
|
+
violations?: string[];
|
|
36
|
+
severity?: 'info' | 'warning' | 'error' | 'critical';
|
|
37
|
+
diff_snapshot?: string;
|
|
38
|
+
}>;
|
|
29
39
|
cluster?: Record<string, string>;
|
|
30
40
|
gate_retry_count?: number;
|
|
31
41
|
last_retry_at?: string | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
type AnyRecord = Record<string, any>;
|
|
3
|
+
|
|
4
|
+
export function asArray<T = unknown>(value: unknown): T[] {
|
|
5
|
+
return Array.isArray(value) ? (value as T[]) : [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function readStringField(record: AnyRecord, key: string): string | null {
|
|
9
|
+
const value = record[key];
|
|
10
|
+
return typeof value === 'string' ? value : null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function readNumberField(record: AnyRecord, key: string): number | null {
|
|
14
|
+
const value = record[key];
|
|
15
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function readPositiveIntegerField(record: AnyRecord, key: string): number | null {
|
|
19
|
+
const value = record[key];
|
|
20
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return Math.floor(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readBooleanField(record: AnyRecord, key: string): boolean | null {
|
|
27
|
+
const value = record[key];
|
|
28
|
+
return typeof value === 'boolean' ? value : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function readObjectField(record: AnyRecord, key: string): AnyRecord {
|
|
32
|
+
const value = record[key];
|
|
33
|
+
return value && typeof value === 'object' ? (value as AnyRecord) : {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function normalizeSet(array: string[]): string[] {
|
|
37
|
+
return [...new Set(array)].sort((a, b) => a.localeCompare(b));
|
|
38
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { stableHash, nowIso } from '../fs.js';
|
|
2
|
+
import type { RuntimeSessionsSnapshot } from '../runtime-sessions.js';
|
|
3
|
+
import { asArray, normalizeSet } from './field-readers.js';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
type AnyRecord = Record<string, any>;
|
|
7
|
+
|
|
8
|
+
export function emptyRuntimeSessions(at = nowIso()): RuntimeSessionsSnapshot {
|
|
9
|
+
return {
|
|
10
|
+
run_id: 'none',
|
|
11
|
+
orchestrator_session_id: 'unknown',
|
|
12
|
+
provider: 'unknown',
|
|
13
|
+
model: 'unknown',
|
|
14
|
+
provider_config_ref_hash: stableHash('none'),
|
|
15
|
+
owner_instance_id: 'none',
|
|
16
|
+
lease_id: 'none',
|
|
17
|
+
started_at: at,
|
|
18
|
+
last_heartbeat_at: at,
|
|
19
|
+
lease_expires_at: at,
|
|
20
|
+
orchestrator_epoch: 0,
|
|
21
|
+
feature_sessions: {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function normalizeRuntimeSessions(value: unknown, at = nowIso()): RuntimeSessionsSnapshot {
|
|
26
|
+
const fallback = emptyRuntimeSessions(at);
|
|
27
|
+
const source = value && typeof value === 'object' ? (value as Record<string, unknown>) : {};
|
|
28
|
+
const featureSessionsInput =
|
|
29
|
+
source.feature_sessions && typeof source.feature_sessions === 'object'
|
|
30
|
+
? (source.feature_sessions as Record<string, unknown>)
|
|
31
|
+
: {};
|
|
32
|
+
const featureSessions: RuntimeSessionsSnapshot['feature_sessions'] = {};
|
|
33
|
+
|
|
34
|
+
for (const [featureId, raw] of Object.entries(featureSessionsInput)) {
|
|
35
|
+
if (!featureId || typeof raw !== 'object' || !raw) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const typed = raw as Record<string, unknown>;
|
|
39
|
+
featureSessions[featureId] = {
|
|
40
|
+
planner_session_id:
|
|
41
|
+
typeof typed.planner_session_id === 'string' ? typed.planner_session_id : 'unassigned',
|
|
42
|
+
builder_session_id:
|
|
43
|
+
typeof typed.builder_session_id === 'string' ? typed.builder_session_id : 'unassigned',
|
|
44
|
+
qa_session_id: typeof typed.qa_session_id === 'string' ? typed.qa_session_id : 'unassigned',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const epoch =
|
|
49
|
+
typeof source.orchestrator_epoch === 'number' && Number.isFinite(source.orchestrator_epoch)
|
|
50
|
+
? Math.max(0, Math.floor(source.orchestrator_epoch))
|
|
51
|
+
: 0;
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
run_id: typeof source.run_id === 'string' && source.run_id ? source.run_id : fallback.run_id,
|
|
55
|
+
orchestrator_session_id:
|
|
56
|
+
typeof source.orchestrator_session_id === 'string' && source.orchestrator_session_id
|
|
57
|
+
? source.orchestrator_session_id
|
|
58
|
+
: fallback.orchestrator_session_id,
|
|
59
|
+
provider:
|
|
60
|
+
typeof source.provider === 'string' && source.provider ? source.provider : fallback.provider,
|
|
61
|
+
model: typeof source.model === 'string' && source.model ? source.model : fallback.model,
|
|
62
|
+
provider_config_ref_hash:
|
|
63
|
+
typeof source.provider_config_ref_hash === 'string' && source.provider_config_ref_hash
|
|
64
|
+
? source.provider_config_ref_hash
|
|
65
|
+
: fallback.provider_config_ref_hash,
|
|
66
|
+
owner_instance_id:
|
|
67
|
+
typeof source.owner_instance_id === 'string' && source.owner_instance_id
|
|
68
|
+
? source.owner_instance_id
|
|
69
|
+
: fallback.owner_instance_id,
|
|
70
|
+
lease_id:
|
|
71
|
+
typeof source.lease_id === 'string' && source.lease_id ? source.lease_id : fallback.lease_id,
|
|
72
|
+
started_at:
|
|
73
|
+
typeof source.started_at === 'string' && source.started_at
|
|
74
|
+
? source.started_at
|
|
75
|
+
: fallback.started_at,
|
|
76
|
+
last_heartbeat_at:
|
|
77
|
+
typeof source.last_heartbeat_at === 'string' && source.last_heartbeat_at
|
|
78
|
+
? source.last_heartbeat_at
|
|
79
|
+
: fallback.last_heartbeat_at,
|
|
80
|
+
lease_expires_at:
|
|
81
|
+
typeof source.lease_expires_at === 'string' && source.lease_expires_at
|
|
82
|
+
? source.lease_expires_at
|
|
83
|
+
: fallback.lease_expires_at,
|
|
84
|
+
orchestrator_epoch: epoch,
|
|
85
|
+
feature_sessions: featureSessions,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function normalizeIndexShape(value: unknown): AnyRecord {
|
|
90
|
+
const now = nowIso();
|
|
91
|
+
const source = value && typeof value === 'object' ? (value as Record<string, unknown>) : {};
|
|
92
|
+
return {
|
|
93
|
+
version:
|
|
94
|
+
typeof source.version === 'number' && Number.isFinite(source.version)
|
|
95
|
+
? Math.max(1, Math.floor(source.version))
|
|
96
|
+
: 1,
|
|
97
|
+
active: normalizeSet(asArray<string>(source.active).filter((item) => typeof item === 'string')),
|
|
98
|
+
blocked: normalizeSet(
|
|
99
|
+
asArray<string>(source.blocked).filter((item) => typeof item === 'string'),
|
|
100
|
+
),
|
|
101
|
+
merged: normalizeSet(asArray<string>(source.merged).filter((item) => typeof item === 'string')),
|
|
102
|
+
locks: source.locks && typeof source.locks === 'object' ? source.locks : {},
|
|
103
|
+
lock_leases:
|
|
104
|
+
source.lock_leases && typeof source.lock_leases === 'object' ? source.lock_leases : {},
|
|
105
|
+
blocked_queue: asArray(source.blocked_queue).filter((item) => item && typeof item === 'object'),
|
|
106
|
+
dep_blocked: asArray(source.dep_blocked).filter((item) => item && typeof item === 'object'),
|
|
107
|
+
updated_at:
|
|
108
|
+
typeof source.updated_at === 'string' && source.updated_at ? source.updated_at : now,
|
|
109
|
+
runtime_sessions: normalizeRuntimeSessions(source.runtime_sessions, now),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function isRunLeaseFresh(runtimeSessions: RuntimeSessionsSnapshot): boolean {
|
|
114
|
+
const expiry = new Date(runtimeSessions.lease_expires_at).getTime();
|
|
115
|
+
if (!Number.isFinite(expiry)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return expiry > Date.now();
|
|
119
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
export function normalizeRepoPathForState(repoRoot: string, absolutePath: string): string {
|
|
4
|
+
const relative = path.relative(repoRoot, absolutePath).replaceAll('\\\\', '/');
|
|
5
|
+
if (!relative || relative === '.') {
|
|
6
|
+
return '.';
|
|
7
|
+
}
|
|
8
|
+
return relative;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function normalizeFromWorktree(
|
|
12
|
+
worktreePath: string,
|
|
13
|
+
repoRoot: string,
|
|
14
|
+
repoRelativeFromWorktree: string,
|
|
15
|
+
): string {
|
|
16
|
+
const absolute = path.resolve(repoRoot, repoRelativeFromWorktree);
|
|
17
|
+
const maybeRelativeToWorktree = path.relative(worktreePath, absolute).replaceAll('\\\\', '/');
|
|
18
|
+
if (!maybeRelativeToWorktree.startsWith('../')) {
|
|
19
|
+
return maybeRelativeToWorktree;
|
|
20
|
+
}
|
|
21
|
+
return path.relative(repoRoot, absolute).replaceAll('\\\\', '/');
|
|
22
|
+
}
|
|
@@ -17,6 +17,7 @@ import { ResumeCommandHandler } from '../../cli/resume-command-handler.js';
|
|
|
17
17
|
import { StopCommandHandler } from '../../cli/stop-command-handler.js';
|
|
18
18
|
import { DeleteCommandHandler } from '../../cli/delete-command-handler.js';
|
|
19
19
|
import { CleanupCommandHandler } from '../../cli/cleanup-command-handler.js';
|
|
20
|
+
import { RollbackCommandHandler } from '../../cli/rollback-command-handler.js';
|
|
20
21
|
import { RunCommandHandler } from '../../cli/run-command-handler.js';
|
|
21
22
|
import { InitCommandHandler } from '../../cli/init-command-handler.js';
|
|
22
23
|
import { DashboardCommandHandler } from '../../cli/dashboard-command-handler.js';
|
|
@@ -30,6 +31,7 @@ import { resolveProviderSelection } from '../../providers/providers.js';
|
|
|
30
31
|
import {
|
|
31
32
|
DefaultWorkerProviderFactory,
|
|
32
33
|
resolveWorkerProviderMode,
|
|
34
|
+
resolveWorkerProviderObservability,
|
|
33
35
|
resolveWorkerProviderPolicy,
|
|
34
36
|
resolveWorkerProviderRuntime,
|
|
35
37
|
} from '../../providers/worker-provider-factory.js';
|
|
@@ -355,6 +357,10 @@ export async function runCli(
|
|
|
355
357
|
policySnapshot.execution && typeof policySnapshot.execution === 'object'
|
|
356
358
|
? (policySnapshot.execution as Record<string, unknown>)
|
|
357
359
|
: null;
|
|
360
|
+
const observabilityPolicy =
|
|
361
|
+
policySnapshot.observability && typeof policySnapshot.observability === 'object'
|
|
362
|
+
? (policySnapshot.observability as Record<string, unknown>)
|
|
363
|
+
: null;
|
|
358
364
|
commandProvider = workerProviderFactory.create({
|
|
359
365
|
selection,
|
|
360
366
|
mode: resolveWorkerProviderMode(
|
|
@@ -364,7 +370,9 @@ export async function runCli(
|
|
|
364
370
|
),
|
|
365
371
|
context: options.command === CliCommand.Send ? 'send' : 'attach',
|
|
366
372
|
policy: resolveWorkerProviderPolicy(executionPolicy),
|
|
373
|
+
observability: resolveWorkerProviderObservability(observabilityPolicy),
|
|
367
374
|
runtime: resolveWorkerProviderRuntime(kernel.getAgentsConfig().runtime),
|
|
375
|
+
repoRoot,
|
|
368
376
|
});
|
|
369
377
|
kernel.setProvider(commandProvider);
|
|
370
378
|
}
|
|
@@ -416,6 +424,13 @@ export async function runCli(
|
|
|
416
424
|
return 0;
|
|
417
425
|
}
|
|
418
426
|
|
|
427
|
+
if (options.command === CliCommand.Rollback) {
|
|
428
|
+
const handler = new RollbackCommandHandler(repoRoot);
|
|
429
|
+
const payload = await handler.execute(options);
|
|
430
|
+
printPayload(payload);
|
|
431
|
+
return 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
419
434
|
if (options.command === CliCommand.Retry) {
|
|
420
435
|
const handler = new RetryCommandHandler(toolClient, runId);
|
|
421
436
|
const payload = await handler.execute(options);
|
|
@@ -5,7 +5,9 @@ import type {
|
|
|
5
5
|
ProviderSelection,
|
|
6
6
|
WorkerCapabilities,
|
|
7
7
|
WorkerHandle,
|
|
8
|
+
WorkerProviderCapabilities,
|
|
8
9
|
WorkerProvider,
|
|
10
|
+
WorkerRunInput,
|
|
9
11
|
WorkerSession,
|
|
10
12
|
} from './providers.js';
|
|
11
13
|
import type { ProviderOutputParser } from './output-parsers/types.js';
|
|
@@ -52,6 +54,13 @@ export class ApiWorkerProvider implements WorkerProvider {
|
|
|
52
54
|
supportsIdleDetection: false,
|
|
53
55
|
supportsSpawnDetection: false,
|
|
54
56
|
};
|
|
57
|
+
private readonly providerCapabilities: WorkerProviderCapabilities = {
|
|
58
|
+
supportsInteractiveMode: false,
|
|
59
|
+
supportsWorkingDirectory: false,
|
|
60
|
+
supportsPauseResume: false,
|
|
61
|
+
supportsMessagePassing: false,
|
|
62
|
+
supportsAcknowledgment: false,
|
|
63
|
+
};
|
|
55
64
|
|
|
56
65
|
constructor(selection: ProviderSelection, options: ApiWorkerProviderOptions) {
|
|
57
66
|
this.selection = selection;
|
|
@@ -95,18 +104,7 @@ export class ApiWorkerProvider implements WorkerProvider {
|
|
|
95
104
|
return Promise.resolve({ closed: true });
|
|
96
105
|
}
|
|
97
106
|
|
|
98
|
-
runWorker(input: {
|
|
99
|
-
role: string;
|
|
100
|
-
feature_id: string;
|
|
101
|
-
context_bundle?: Record<string, unknown>;
|
|
102
|
-
instructions?: string;
|
|
103
|
-
last_tool_results?: Array<Record<string, unknown>>;
|
|
104
|
-
runtime_selection?: {
|
|
105
|
-
provider: string;
|
|
106
|
-
model: string;
|
|
107
|
-
provider_config_ref: string | null;
|
|
108
|
-
};
|
|
109
|
-
}): Promise<Record<string, unknown>> {
|
|
107
|
+
runWorker(input: WorkerRunInput): Promise<Record<string, unknown>> {
|
|
110
108
|
const workerHandle: WorkerHandle = {
|
|
111
109
|
capabilities: this.workerCapabilities,
|
|
112
110
|
kill: () => {
|
|
@@ -169,4 +167,8 @@ export class ApiWorkerProvider implements WorkerProvider {
|
|
|
169
167
|
});
|
|
170
168
|
}
|
|
171
169
|
}
|
|
170
|
+
|
|
171
|
+
getCapabilities(): WorkerProviderCapabilities {
|
|
172
|
+
return this.providerCapabilities;
|
|
173
|
+
}
|
|
172
174
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
2
4
|
import { ERROR_CODES } from '../core/error-codes.js';
|
|
3
5
|
import {
|
|
4
6
|
NodeProviderCommandRunner,
|
|
@@ -6,6 +8,8 @@ import {
|
|
|
6
8
|
type ProviderCommandResult,
|
|
7
9
|
type ProviderCommandRunner,
|
|
8
10
|
type ProviderSelection,
|
|
11
|
+
type WorkerProviderCapabilities,
|
|
12
|
+
type WorkerRunInput,
|
|
9
13
|
type WorkerCapabilities,
|
|
10
14
|
type WorkerHandle,
|
|
11
15
|
type WorkerProvider,
|
|
@@ -18,6 +22,9 @@ import { WorkerWatchdog, type WatchdogOutcome } from './worker-watchdog.js';
|
|
|
18
22
|
interface CliWorkerProviderOptions {
|
|
19
23
|
outputParser: ProviderOutputParser;
|
|
20
24
|
commandRunner?: ProviderCommandRunner;
|
|
25
|
+
repoRoot?: string;
|
|
26
|
+
rawAgentLogsEnabled?: boolean;
|
|
27
|
+
rawAgentLogsRetentionDays?: number;
|
|
21
28
|
workerResponseTimeoutMs: number;
|
|
22
29
|
workerSpawnTimeoutMs?: number;
|
|
23
30
|
workerIdleTimeoutMs?: number;
|
|
@@ -39,6 +46,14 @@ const DEFAULT_SPAWN_TIMEOUT_MS = 15_000;
|
|
|
39
46
|
const DEFAULT_IDLE_TIMEOUT_MS = 120_000;
|
|
40
47
|
const DEFAULT_WATCHDOG_POLL_INTERVAL_MS = 1_000;
|
|
41
48
|
const DEFAULT_KILL_GRACE_PERIOD_MS = 1_500;
|
|
49
|
+
const DEFAULT_RAW_LOG_RETENTION_DAYS = 60;
|
|
50
|
+
const CLI_PROVIDER_CAPABILITIES: WorkerProviderCapabilities = {
|
|
51
|
+
supportsInteractiveMode: true,
|
|
52
|
+
supportsWorkingDirectory: true,
|
|
53
|
+
supportsPauseResume: false,
|
|
54
|
+
supportsMessagePassing: true,
|
|
55
|
+
supportsAcknowledgment: false,
|
|
56
|
+
};
|
|
42
57
|
|
|
43
58
|
function buildStructuredWorkerPrompt(
|
|
44
59
|
payload: Record<string, unknown>,
|
|
@@ -201,6 +216,9 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
201
216
|
private readonly workerIdleTimeoutMs: number;
|
|
202
217
|
private readonly workerWatchdogPollIntervalMs: number;
|
|
203
218
|
private readonly workerKillGracePeriodMs: number;
|
|
219
|
+
private readonly repoRoot: string | null;
|
|
220
|
+
private readonly rawAgentLogsEnabled: boolean;
|
|
221
|
+
private readonly rawAgentLogsRetentionDays: number;
|
|
204
222
|
private readonly workerCapabilities: WorkerCapabilities;
|
|
205
223
|
private readonly runTemplate: ProviderCommandTemplate | undefined;
|
|
206
224
|
private readonly attachTemplate: ProviderCommandTemplate | undefined;
|
|
@@ -229,6 +247,13 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
229
247
|
options.workerKillGracePeriodMs,
|
|
230
248
|
DEFAULT_KILL_GRACE_PERIOD_MS,
|
|
231
249
|
);
|
|
250
|
+
this.repoRoot =
|
|
251
|
+
typeof options.repoRoot === 'string' && options.repoRoot.length > 0 ? options.repoRoot : null;
|
|
252
|
+
this.rawAgentLogsEnabled = options.rawAgentLogsEnabled === true;
|
|
253
|
+
this.rawAgentLogsRetentionDays = asPositiveInteger(
|
|
254
|
+
options.rawAgentLogsRetentionDays,
|
|
255
|
+
DEFAULT_RAW_LOG_RETENTION_DAYS,
|
|
256
|
+
);
|
|
232
257
|
this.workerCapabilities = resolveCliWorkerCapabilities(selection);
|
|
233
258
|
this.runTemplate = resolveRunTemplate(selection);
|
|
234
259
|
this.attachTemplate = resolveAttachTemplate(selection);
|
|
@@ -290,18 +315,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
290
315
|
return Promise.resolve({ closed: true });
|
|
291
316
|
}
|
|
292
317
|
|
|
293
|
-
async runWorker(input: {
|
|
294
|
-
role: string;
|
|
295
|
-
feature_id: string;
|
|
296
|
-
context_bundle?: Record<string, unknown>;
|
|
297
|
-
instructions?: string;
|
|
298
|
-
last_tool_results?: Array<Record<string, unknown>>;
|
|
299
|
-
runtime_selection?: {
|
|
300
|
-
provider: string;
|
|
301
|
-
model: string;
|
|
302
|
-
provider_config_ref: string | null;
|
|
303
|
-
};
|
|
304
|
-
}): Promise<Record<string, unknown>> {
|
|
318
|
+
async runWorker(input: WorkerRunInput): Promise<Record<string, unknown>> {
|
|
305
319
|
if (!this.runTemplate) {
|
|
306
320
|
throw providerError(
|
|
307
321
|
ERROR_CODES.PROVIDER_RUNTIME_UNAVAILABLE,
|
|
@@ -364,6 +378,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
364
378
|
try {
|
|
365
379
|
runResult = await this.commandRunner.run(this.runTemplate.command, args, {
|
|
366
380
|
stdin: prompt,
|
|
381
|
+
cwd: input.working_directory,
|
|
367
382
|
timeoutMs: runnerBackstopTimeoutMs,
|
|
368
383
|
env: buildRunCommandEnv(this.selection),
|
|
369
384
|
onLifecycleEvent: (event) => {
|
|
@@ -391,6 +406,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
391
406
|
effectiveTimeoutMs,
|
|
392
407
|
watchdogOutcome,
|
|
393
408
|
);
|
|
409
|
+
await this.persistRawAgentOutput(input.feature_id, input.role, runResult.stdout ?? '');
|
|
394
410
|
|
|
395
411
|
return this.outputParser.parse(runResult.stdout ?? '', {
|
|
396
412
|
sessionId,
|
|
@@ -401,6 +417,10 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
401
417
|
});
|
|
402
418
|
}
|
|
403
419
|
|
|
420
|
+
getCapabilities(): WorkerProviderCapabilities {
|
|
421
|
+
return CLI_PROVIDER_CAPABILITIES;
|
|
422
|
+
}
|
|
423
|
+
|
|
404
424
|
private sessionKey(role: string, featureId: string): string {
|
|
405
425
|
return `${role}::${featureId}`;
|
|
406
426
|
}
|
|
@@ -520,4 +540,54 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
520
540
|
},
|
|
521
541
|
);
|
|
522
542
|
}
|
|
543
|
+
|
|
544
|
+
private async persistRawAgentOutput(
|
|
545
|
+
featureId: string,
|
|
546
|
+
role: string,
|
|
547
|
+
stdout: string,
|
|
548
|
+
): Promise<void> {
|
|
549
|
+
if (!this.rawAgentLogsEnabled || !this.repoRoot) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if (stdout.trim().length === 0) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (role !== 'planner' && role !== 'builder' && role !== 'qa') {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const logsDir = path.join(this.repoRoot, '.aop', 'features', featureId, 'logs');
|
|
560
|
+
const filename = `${role}-${Date.now()}.txt`;
|
|
561
|
+
const filePath = path.join(logsDir, filename);
|
|
562
|
+
|
|
563
|
+
try {
|
|
564
|
+
await fs.mkdir(logsDir, { recursive: true });
|
|
565
|
+
await fs.writeFile(filePath, stdout, 'utf8');
|
|
566
|
+
await this.cleanupExpiredRawAgentLogs(logsDir);
|
|
567
|
+
} catch {
|
|
568
|
+
// Raw log persistence must not fail orchestration flow.
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
private async cleanupExpiredRawAgentLogs(logsDir: string): Promise<void> {
|
|
573
|
+
const cutoffMs = Date.now() - this.rawAgentLogsRetentionDays * 24 * 60 * 60 * 1000;
|
|
574
|
+
try {
|
|
575
|
+
const files = await fs.readdir(logsDir);
|
|
576
|
+
await Promise.all(
|
|
577
|
+
files.map(async (filename) => {
|
|
578
|
+
const match = filename.match(/^(planner|builder|qa)-([0-9]{13})\.txt$/);
|
|
579
|
+
if (!match) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const unixMs = Number.parseInt(match[2], 10);
|
|
583
|
+
if (Number.isNaN(unixMs) || unixMs >= cutoffMs) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
await fs.unlink(path.join(logsDir, filename)).catch(() => undefined);
|
|
587
|
+
}),
|
|
588
|
+
);
|
|
589
|
+
} catch {
|
|
590
|
+
// Best effort cleanup.
|
|
591
|
+
}
|
|
592
|
+
}
|
|
523
593
|
}
|
|
@@ -225,6 +225,32 @@ export interface WorkerSession {
|
|
|
225
225
|
system_prompt_loaded: boolean;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
export type ExecutionMode = 'deterministic' | 'interactive';
|
|
229
|
+
|
|
230
|
+
export interface WorkerProviderCapabilities {
|
|
231
|
+
supportsInteractiveMode: boolean;
|
|
232
|
+
supportsWorkingDirectory: boolean;
|
|
233
|
+
supportsPauseResume: boolean;
|
|
234
|
+
supportsMessagePassing: boolean;
|
|
235
|
+
supportsAcknowledgment: boolean;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface WorkerRunInput {
|
|
239
|
+
role: string;
|
|
240
|
+
feature_id: string;
|
|
241
|
+
context_bundle?: Record<string, unknown>;
|
|
242
|
+
instructions?: string;
|
|
243
|
+
last_tool_results?: Array<Record<string, unknown>>;
|
|
244
|
+
runtime_selection?: {
|
|
245
|
+
provider: string;
|
|
246
|
+
model: string;
|
|
247
|
+
provider_config_ref: string | null;
|
|
248
|
+
};
|
|
249
|
+
execution_mode?: ExecutionMode;
|
|
250
|
+
working_directory?: string;
|
|
251
|
+
pause_resume_protocol?: 'signal' | 'message' | 'none';
|
|
252
|
+
}
|
|
253
|
+
|
|
228
254
|
/**
|
|
229
255
|
* Worker provider interface for agent session management.
|
|
230
256
|
*
|
|
@@ -293,18 +319,7 @@ export interface WorkerProvider {
|
|
|
293
319
|
* @param input - execution input with role, feature, context, instructions
|
|
294
320
|
* @returns Worker output with tool calls and text
|
|
295
321
|
*/
|
|
296
|
-
runWorker(input:
|
|
297
|
-
role: string;
|
|
298
|
-
feature_id: string;
|
|
299
|
-
context_bundle?: Record<string, unknown>;
|
|
300
|
-
instructions?: string;
|
|
301
|
-
last_tool_results?: Array<Record<string, unknown>>;
|
|
302
|
-
runtime_selection?: {
|
|
303
|
-
provider: string;
|
|
304
|
-
model: string;
|
|
305
|
-
provider_config_ref: string | null;
|
|
306
|
-
};
|
|
307
|
-
}): Promise<Record<string, unknown>>;
|
|
322
|
+
runWorker(input: WorkerRunInput): Promise<Record<string, unknown>>;
|
|
308
323
|
|
|
309
324
|
/**
|
|
310
325
|
* Sends a message to an active session (optional).
|
|
@@ -328,6 +343,11 @@ export interface WorkerProvider {
|
|
|
328
343
|
* @returns Session status
|
|
329
344
|
*/
|
|
330
345
|
getSessionInfo?(sessionId: string): Promise<{ active: boolean; provider: string }>;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Reports provider runtime capabilities (optional).
|
|
349
|
+
*/
|
|
350
|
+
getCapabilities?(): WorkerProviderCapabilities;
|
|
331
351
|
}
|
|
332
352
|
|
|
333
353
|
/**
|
|
@@ -367,6 +387,7 @@ export interface ProviderCommandRunnerOptions {
|
|
|
367
387
|
interactive?: boolean;
|
|
368
388
|
stdin?: string;
|
|
369
389
|
env?: NodeJS.ProcessEnv;
|
|
390
|
+
cwd?: string;
|
|
370
391
|
timeoutMs?: number;
|
|
371
392
|
onLifecycleEvent?: (event: WorkerLifecycleEvent) => void;
|
|
372
393
|
registerKill?: (kill: (signal: 'SIGTERM' | 'SIGKILL') => void) => void;
|
|
@@ -391,6 +412,7 @@ export class NodeProviderCommandRunner implements ProviderCommandRunner {
|
|
|
391
412
|
try {
|
|
392
413
|
child = spawn(command, args, {
|
|
393
414
|
env: options.env,
|
|
415
|
+
cwd: options.cwd,
|
|
394
416
|
stdio: options.interactive ? 'inherit' : ['pipe', 'pipe', 'pipe'],
|
|
395
417
|
});
|
|
396
418
|
} catch {
|
|
@@ -638,18 +660,7 @@ export class NullWorkerProvider implements WorkerProvider {
|
|
|
638
660
|
role,
|
|
639
661
|
feature_id,
|
|
640
662
|
context_bundle,
|
|
641
|
-
}: {
|
|
642
|
-
role: string;
|
|
643
|
-
feature_id: string;
|
|
644
|
-
context_bundle?: Record<string, unknown>;
|
|
645
|
-
instructions?: string;
|
|
646
|
-
last_tool_results?: Array<Record<string, unknown>>;
|
|
647
|
-
runtime_selection?: {
|
|
648
|
-
provider: string;
|
|
649
|
-
model: string;
|
|
650
|
-
provider_config_ref: string | null;
|
|
651
|
-
};
|
|
652
|
-
}): Promise<Record<string, unknown>> {
|
|
663
|
+
}: WorkerRunInput): Promise<Record<string, unknown>> {
|
|
653
664
|
if (role === 'planner') {
|
|
654
665
|
const state = context_bundle?.state;
|
|
655
666
|
const frontMatter =
|
|
@@ -715,4 +726,14 @@ export class NullWorkerProvider implements WorkerProvider {
|
|
|
715
726
|
}
|
|
716
727
|
throw commandFailureError(this.selection.provider, kind, details, ERROR_CODES.INTERNAL_ERROR);
|
|
717
728
|
}
|
|
729
|
+
|
|
730
|
+
getCapabilities(): WorkerProviderCapabilities {
|
|
731
|
+
return {
|
|
732
|
+
supportsInteractiveMode: false,
|
|
733
|
+
supportsWorkingDirectory: false,
|
|
734
|
+
supportsPauseResume: false,
|
|
735
|
+
supportsMessagePassing: Boolean(this.sendMessage),
|
|
736
|
+
supportsAcknowledgment: false,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
718
739
|
}
|
|
@@ -31,6 +31,11 @@ export interface WorkerProviderFactoryPolicy {
|
|
|
31
31
|
require_live_provider_for_run: boolean;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
export interface WorkerProviderFactoryObservability {
|
|
35
|
+
raw_agent_logs_enabled: boolean;
|
|
36
|
+
raw_agent_logs_retention_days: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
34
39
|
export interface WorkerProviderFactoryRuntime {
|
|
35
40
|
worker_response_timeout_ms: number;
|
|
36
41
|
worker_spawn_timeout_ms: number;
|
|
@@ -49,7 +54,9 @@ export interface CreateWorkerProviderInput {
|
|
|
49
54
|
mode: WorkerProviderMode;
|
|
50
55
|
context: ProviderCommandContext;
|
|
51
56
|
policy: WorkerProviderFactoryPolicy;
|
|
57
|
+
observability?: WorkerProviderFactoryObservability;
|
|
52
58
|
runtime: WorkerProviderFactoryRuntime;
|
|
59
|
+
repoRoot?: string;
|
|
53
60
|
commandRunner?: ProviderCommandRunner;
|
|
54
61
|
}
|
|
55
62
|
|
|
@@ -81,6 +88,11 @@ interface PolicyConfigInput {
|
|
|
81
88
|
no_progress_action?: unknown;
|
|
82
89
|
}
|
|
83
90
|
|
|
91
|
+
interface ObservabilityConfigInput {
|
|
92
|
+
raw_agent_logs_enabled?: unknown;
|
|
93
|
+
raw_agent_logs_retention_days?: unknown;
|
|
94
|
+
}
|
|
95
|
+
|
|
84
96
|
function asPositiveInteger(value: unknown, fallback: number): number {
|
|
85
97
|
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1) {
|
|
86
98
|
return fallback;
|
|
@@ -175,6 +187,15 @@ export function resolveWorkerProviderPolicy(
|
|
|
175
187
|
};
|
|
176
188
|
}
|
|
177
189
|
|
|
190
|
+
export function resolveWorkerProviderObservability(
|
|
191
|
+
input: ObservabilityConfigInput | null | undefined,
|
|
192
|
+
): WorkerProviderFactoryObservability {
|
|
193
|
+
return {
|
|
194
|
+
raw_agent_logs_enabled: input?.raw_agent_logs_enabled === true,
|
|
195
|
+
raw_agent_logs_retention_days: asPositiveInteger(input?.raw_agent_logs_retention_days, 60),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
178
199
|
export function resolveMalformedWorkerOutputAction(
|
|
179
200
|
input: PolicyConfigInput | null | undefined,
|
|
180
201
|
): WorkerMalformedOutputAction {
|
|
@@ -219,7 +240,12 @@ export function resolvePlanConformanceStallAction(
|
|
|
219
240
|
|
|
220
241
|
export class DefaultWorkerProviderFactory implements WorkerProviderFactory {
|
|
221
242
|
create(input: CreateWorkerProviderInput): WorkerProvider {
|
|
222
|
-
const { selection, mode, context, policy, runtime, commandRunner } =
|
|
243
|
+
const { selection, mode, context, policy, runtime, observability, repoRoot, commandRunner } =
|
|
244
|
+
input;
|
|
245
|
+
const resolvedObservability = observability ?? {
|
|
246
|
+
raw_agent_logs_enabled: false,
|
|
247
|
+
raw_agent_logs_retention_days: 60,
|
|
248
|
+
};
|
|
223
249
|
|
|
224
250
|
if (!SUPPORTED_PROVIDERS.has(selection.provider)) {
|
|
225
251
|
throw toAppError(ERROR_CODES.UNSUPPORTED_AGENT_PROVIDER, 'Unsupported worker provider', {
|
|
@@ -259,6 +285,9 @@ export class DefaultWorkerProviderFactory implements WorkerProviderFactory {
|
|
|
259
285
|
return new CliWorkerProvider(selection, {
|
|
260
286
|
outputParser: new CodexOutputParser(),
|
|
261
287
|
commandRunner,
|
|
288
|
+
repoRoot,
|
|
289
|
+
rawAgentLogsEnabled: resolvedObservability.raw_agent_logs_enabled,
|
|
290
|
+
rawAgentLogsRetentionDays: resolvedObservability.raw_agent_logs_retention_days,
|
|
262
291
|
workerResponseTimeoutMs: runtime.worker_response_timeout_ms,
|
|
263
292
|
workerSpawnTimeoutMs: runtime.worker_spawn_timeout_ms,
|
|
264
293
|
workerIdleTimeoutMs: runtime.worker_idle_timeout_ms,
|
|
@@ -271,6 +300,9 @@ export class DefaultWorkerProviderFactory implements WorkerProviderFactory {
|
|
|
271
300
|
return new CliWorkerProvider(selection, {
|
|
272
301
|
outputParser: new ClaudeOutputParser(),
|
|
273
302
|
commandRunner,
|
|
303
|
+
repoRoot,
|
|
304
|
+
rawAgentLogsEnabled: resolvedObservability.raw_agent_logs_enabled,
|
|
305
|
+
rawAgentLogsRetentionDays: resolvedObservability.raw_agent_logs_retention_days,
|
|
274
306
|
workerResponseTimeoutMs: runtime.worker_response_timeout_ms,
|
|
275
307
|
workerSpawnTimeoutMs: runtime.worker_spawn_timeout_ms,
|
|
276
308
|
workerIdleTimeoutMs: runtime.worker_idle_timeout_ms,
|
|
@@ -287,6 +319,9 @@ export class DefaultWorkerProviderFactory implements WorkerProviderFactory {
|
|
|
287
319
|
return new CliWorkerProvider(selection, {
|
|
288
320
|
outputParser: new GenericCliOutputParser(),
|
|
289
321
|
commandRunner,
|
|
322
|
+
repoRoot,
|
|
323
|
+
rawAgentLogsEnabled: resolvedObservability.raw_agent_logs_enabled,
|
|
324
|
+
rawAgentLogsRetentionDays: resolvedObservability.raw_agent_logs_retention_days,
|
|
290
325
|
workerResponseTimeoutMs: runtime.worker_response_timeout_ms,
|
|
291
326
|
workerSpawnTimeoutMs: runtime.worker_spawn_timeout_ms,
|
|
292
327
|
workerIdleTimeoutMs: runtime.worker_idle_timeout_ms,
|