@llm-dev-ops/agentics-cli 2.7.42 → 2.8.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/analytics-hub/consensus/consensus.md +47 -0
- package/agents/analytics-hub/recommendation/recommendation.md +47 -0
- package/agents/auto-optimizer/model-select/model-select.md +49 -0
- package/agents/auto-optimizer/self-optimize/self-optimize.md +44 -0
- package/agents/auto-optimizer/token/token.md +50 -0
- package/agents/benchmark-exchange/publish/publish.md +29 -0
- package/agents/config-manager/validate/validate.md +40 -0
- package/agents/connector-hub/auth-identity/auth-identity.md +29 -0
- package/agents/connector-hub/database-query/database-query.md +29 -0
- package/agents/connector-hub/erp-surface/erp-surface.md +29 -0
- package/agents/connector-hub/event-normalize/event-normalize.md +29 -0
- package/agents/connector-hub/webhook-ingest/webhook-ingest.md +29 -0
- package/agents/copilot/clarifier/clarifier.md +47 -0
- package/agents/copilot/config/config.md +37 -0
- package/agents/copilot/decomposer/decomposer.md +46 -0
- package/agents/copilot/intent/intent.md +43 -0
- package/agents/copilot/meta-reasoner/meta-reasoner.md +43 -0
- package/agents/copilot/planner/planner.md +47 -0
- package/agents/copilot/reflection/reflection.md +40 -0
- package/agents/costops/attribution/attribution.md +39 -0
- package/agents/costops/budget/budget.md +40 -0
- package/agents/costops/forecast/forecast.md +40 -0
- package/agents/costops/roi/roi.md +37 -0
- package/agents/costops/tradeoff/tradeoff.md +39 -0
- package/agents/data-vault/access-control/access-control.md +46 -0
- package/agents/data-vault/anonymize/anonymize.md +54 -0
- package/agents/edge/caching/caching.md +46 -0
- package/agents/edge/circuit-breaker/circuit-breaker.md +44 -0
- package/agents/edge/execution-guard/execution-guard.md +41 -0
- package/agents/edge/failover/failover.md +45 -0
- package/agents/edge/tool-invoke/tool-invoke.md +44 -0
- package/agents/forge/api-translation/api-translation.md +29 -0
- package/agents/forge/cli/cli.md +29 -0
- package/agents/forge/sdk/sdk.md +29 -0
- package/agents/forge/version-compat/version-compat.md +29 -0
- package/agents/governance-dashboard/audit/audit.md +39 -0
- package/agents/governance-dashboard/impact/impact.md +37 -0
- package/agents/governance-dashboard/oversight/oversight.md +41 -0
- package/agents/incident-manager/escalation/escalation.md +45 -0
- package/agents/incident-manager/hitl/hitl.md +46 -0
- package/agents/incident-manager/post-mortem/post-mortem.md +52 -0
- package/agents/inference-gateway/route/route.md +29 -0
- package/agents/latency-lens/cold-start/cold-start.md +29 -0
- package/agents/latency-lens/latency/latency.md +29 -0
- package/agents/marketplace/deprecation/deprecation.md +29 -0
- package/agents/marketplace/package/package.md +29 -0
- package/agents/memory-graph/conversation/conversation.md +37 -0
- package/agents/memory-graph/decisions/decisions.md +45 -0
- package/agents/memory-graph/knowledge-graph/knowledge-graph.md +46 -0
- package/agents/memory-graph/lineage/lineage.md +37 -0
- package/agents/memory-graph/patterns/patterns.md +45 -0
- package/agents/memory-graph/retrieval/retrieval.md +43 -0
- package/agents/observatory/failures/failures.md +29 -0
- package/agents/observatory/health-check/health-check.md +29 -0
- package/agents/observatory/post-mortem/post-mortem.md +29 -0
- package/agents/observatory/slo/slo.md +29 -0
- package/agents/observatory/telemetry/telemetry.md +29 -0
- package/agents/observatory/usage-patterns/usage-patterns.md +29 -0
- package/agents/observatory/visualization/visualization.md +29 -0
- package/agents/orchestrator/dependencies/dependencies.md +40 -0
- package/agents/orchestrator/parallel/parallel.md +43 -0
- package/agents/orchestrator/retry/retry.md +45 -0
- package/agents/orchestrator/scheduler/scheduler.md +44 -0
- package/agents/orchestrator/state-machine/state-machine.md +53 -0
- package/agents/orchestrator/swarm/swarm.md +44 -0
- package/agents/orchestrator/workflow/workflow.md +48 -0
- package/agents/platform/decision/decision.md +40 -0
- package/agents/platform/decision-memo/decision-memo.md +69 -0
- package/agents/platform/executive-summary/executive-summary.md +44 -0
- package/agents/platform/risk-score/risk-score.md +50 -0
- package/agents/policy-engine/approval/approval.md +40 -0
- package/agents/policy-engine/constraints/constraints.md +38 -0
- package/agents/policy-engine/enforce/enforce.md +39 -0
- package/agents/registry/bootstrap/bootstrap.md +29 -0
- package/agents/registry/index/index.md +29 -0
- package/agents/registry/reputation/reputation.md +29 -0
- package/agents/research-lab/hypothesis/hypothesis.md +50 -0
- package/agents/research-lab/metrics/metrics.md +50 -0
- package/agents/schema-registry/validate/validate.md +37 -0
- package/agents/sentinel/alert/alert.md +29 -0
- package/agents/sentinel/anomaly/anomaly.md +29 -0
- package/agents/sentinel/correlation/correlation.md +29 -0
- package/agents/sentinel/drift/drift.md +29 -0
- package/agents/sentinel/rca/rca.md +29 -0
- package/agents/shield/abuse/abuse.md +29 -0
- package/agents/shield/credential-exposure/credential-exposure.md +29 -0
- package/agents/shield/moderation/moderation.md +29 -0
- package/agents/shield/pii/pii.md +29 -0
- package/agents/shield/prompt-injection/prompt-injection.md +29 -0
- package/agents/shield/redaction/redaction.md +29 -0
- package/agents/shield/safety-boundary/safety-boundary.md +29 -0
- package/agents/shield/secrets/secrets.md +29 -0
- package/agents/shield/toxicity/toxicity.md +29 -0
- package/agents/simulator/scenario/scenario.md +53 -0
- package/agents/simulator/what-if/what-if.md +52 -0
- package/agents/test-bench/adversarial/adversarial.md +33 -0
- package/agents/test-bench/benchmark/benchmark.md +34 -0
- package/agents/test-bench/bias/bias.md +33 -0
- package/agents/test-bench/compare/compare.md +33 -0
- package/agents/test-bench/consistency/consistency.md +33 -0
- package/agents/test-bench/faithfulness/faithfulness.md +34 -0
- package/agents/test-bench/golden-dataset/golden-dataset.md +33 -0
- package/agents/test-bench/hallucination/hallucination.md +34 -0
- package/agents/test-bench/prompt-sensitivity/prompt-sensitivity.md +33 -0
- package/agents/test-bench/quality/quality.md +33 -0
- package/agents/test-bench/red-team/red-team.md +33 -0
- package/agents/test-bench/regression/regression.md +33 -0
- package/agents/test-bench/stress/stress.md +34 -0
- package/agents/test-bench/synthetic-data/synthetic-data.md +35 -0
- package/dist/agents/agent-prompts.d.ts +77 -0
- package/dist/agents/agent-prompts.d.ts.map +1 -0
- package/dist/agents/agent-prompts.js +230 -0
- package/dist/agents/agent-prompts.js.map +1 -0
- package/dist/agents/repo-agent-runner.d.ts +1 -0
- package/dist/agents/repo-agent-runner.d.ts.map +1 -1
- package/dist/agents/repo-agent-runner.js +67 -35
- package/dist/agents/repo-agent-runner.js.map +1 -1
- package/dist/cli/index.js +22 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/agents.d.ts +19 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +344 -144
- package/dist/commands/agents.js.map +1 -1
- package/dist/pipeline/fleet-dispatch-bounds.d.ts +115 -0
- package/dist/pipeline/fleet-dispatch-bounds.d.ts.map +1 -0
- package/dist/pipeline/fleet-dispatch-bounds.js +190 -0
- package/dist/pipeline/fleet-dispatch-bounds.js.map +1 -0
- package/dist/pipeline/phase3/phases/domain-codegen.d.ts.map +1 -1
- package/dist/pipeline/phase3/phases/domain-codegen.js +8 -2
- package/dist/pipeline/phase3/phases/domain-codegen.js.map +1 -1
- package/dist/pipeline/phase4/phases/schema-generator.js +3 -3
- package/dist/pipeline/phase4/phases/schema-generator.js.map +1 -1
- package/dist/pipeline/phase7/coherence-gate.d.ts.map +1 -1
- package/dist/pipeline/phase7/coherence-gate.js +8 -24
- package/dist/pipeline/phase7/coherence-gate.js.map +1 -1
- package/dist/pipeline/phase7/coordinator.d.ts +34 -0
- package/dist/pipeline/phase7/coordinator.d.ts.map +1 -1
- package/dist/pipeline/phase7/coordinator.js +131 -71
- package/dist/pipeline/phase7/coordinator.js.map +1 -1
- package/dist/pipeline/phase7/field-mappers.d.ts +43 -0
- package/dist/pipeline/phase7/field-mappers.d.ts.map +1 -0
- package/dist/pipeline/phase7/field-mappers.js +278 -0
- package/dist/pipeline/phase7/field-mappers.js.map +1 -0
- package/dist/pipeline/phase7/field-writer.d.ts +53 -0
- package/dist/pipeline/phase7/field-writer.d.ts.map +1 -0
- package/dist/pipeline/phase7/field-writer.js +178 -0
- package/dist/pipeline/phase7/field-writer.js.map +1 -0
- package/dist/pipeline/phase7/writer-agent.d.ts +83 -0
- package/dist/pipeline/phase7/writer-agent.d.ts.map +1 -0
- package/dist/pipeline/phase7/writer-agent.js +174 -0
- package/dist/pipeline/phase7/writer-agent.js.map +1 -0
- package/dist/pipeline/ruflo-phase-executor.d.ts.map +1 -1
- package/dist/pipeline/ruflo-phase-executor.js +21 -6
- package/dist/pipeline/ruflo-phase-executor.js.map +1 -1
- package/dist/pipeline/swarm-orchestrator.d.ts +3 -41
- package/dist/pipeline/swarm-orchestrator.d.ts.map +1 -1
- package/dist/pipeline/swarm-orchestrator.js +9 -75
- package/dist/pipeline/swarm-orchestrator.js.map +1 -1
- package/dist/synthesis/fcv-coherence.d.ts +24 -0
- package/dist/synthesis/fcv-coherence.d.ts.map +1 -0
- package/dist/synthesis/fcv-coherence.js +36 -0
- package/dist/synthesis/fcv-coherence.js.map +1 -0
- package/dist/synthesis/financial-claim-extractor.d.ts +8 -0
- package/dist/synthesis/financial-claim-extractor.d.ts.map +1 -1
- package/dist/synthesis/financial-claim-extractor.js +74 -1
- package/dist/synthesis/financial-claim-extractor.js.map +1 -1
- package/dist/synthesis/financial-consistency-rules.d.ts.map +1 -1
- package/dist/synthesis/financial-consistency-rules.js +21 -12
- package/dist/synthesis/financial-consistency-rules.js.map +1 -1
- package/dist/synthesis/financial-consistency-runner.d.ts +12 -0
- package/dist/synthesis/financial-consistency-runner.d.ts.map +1 -1
- package/dist/synthesis/financial-consistency-runner.js +25 -3
- package/dist/synthesis/financial-consistency-runner.js.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.js +5 -0
- package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts +2 -0
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +8 -8
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/dist/synthesis/unit-economics-loader.d.ts +7 -0
- package/dist/synthesis/unit-economics-loader.d.ts.map +1 -1
- package/dist/synthesis/unit-economics-loader.js +11 -2
- package/dist/synthesis/unit-economics-loader.js.map +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet dispatch bounds — shared timeout / circuit-breaker primitives.
|
|
3
|
+
*
|
|
4
|
+
* ADR-PIPELINE-108: the Phase 1 full-fleet dispatch (109 agents) and the
|
|
5
|
+
* Phase 2–6 phase fanouts must share ONE bounding discipline:
|
|
6
|
+
* - a per-agent timeout so no single agent can stall the batch, and
|
|
7
|
+
* - a per-fanout cloud circuit breaker so a dead backend short-circuits
|
|
8
|
+
* the remaining cloud calls instead of each eating its full timeout.
|
|
9
|
+
*
|
|
10
|
+
* These primitives previously lived inside `swarm-orchestrator.ts`, but
|
|
11
|
+
* `swarm-orchestrator.ts` imports `executeAgentsInvokeCommand` from
|
|
12
|
+
* `commands/agents.ts`. Having `agents.ts` import the breaker back from the
|
|
13
|
+
* orchestrator would create an import cycle, so the shared pieces live here
|
|
14
|
+
* in a leaf module that neither imports from. `swarm-orchestrator.ts`
|
|
15
|
+
* re-exports `CloudCircuitBreaker` / `CloudBreakerState` for back-compat
|
|
16
|
+
* (existing tests import them from there).
|
|
17
|
+
*/
|
|
18
|
+
/** Default consecutive cloud-failure threshold before the breaker trips. */
|
|
19
|
+
export declare const DEFAULT_CLOUD_BREAKER_THRESHOLD = 3;
|
|
20
|
+
/** State exposed by `CloudCircuitBreaker.state()`. */
|
|
21
|
+
export interface CloudBreakerState {
|
|
22
|
+
readonly tripped: boolean;
|
|
23
|
+
readonly after_n_timeouts: number;
|
|
24
|
+
readonly agents: ReadonlyArray<string>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Per-fanout circuit breaker that trips after N consecutive cloud-tier
|
|
28
|
+
* failures and short-circuits remaining cloud invocations. Local-tier
|
|
29
|
+
* successes do not reset the streak; they bypass the breaker.
|
|
30
|
+
*
|
|
31
|
+
* Cloud-tier successes DO reset the streak — if even one cloud call works,
|
|
32
|
+
* we trust the cloud is alive again. This matches the originating-run
|
|
33
|
+
* failure mode where an entire backend fleet was down at once.
|
|
34
|
+
*
|
|
35
|
+
* Resets per fanout. Exported for unit tests.
|
|
36
|
+
*/
|
|
37
|
+
export declare class CloudCircuitBreaker {
|
|
38
|
+
private consecutiveCloudFailures;
|
|
39
|
+
private trippedFlag;
|
|
40
|
+
private trippedAfterN;
|
|
41
|
+
private readonly trippedAgents;
|
|
42
|
+
private readonly threshold;
|
|
43
|
+
constructor(threshold?: number);
|
|
44
|
+
/**
|
|
45
|
+
* Record an invocation outcome. `tier` is the tier the call was dispatched
|
|
46
|
+
* on. `failed=true` AND `tier='cloud'` increments the consecutive-failure
|
|
47
|
+
* counter; a cloud success resets it.
|
|
48
|
+
*/
|
|
49
|
+
record(failed: boolean, tier: 'cloud' | 'local' | 'unknown', agentLabel: string): void;
|
|
50
|
+
/** Returns true once the breaker has tripped. */
|
|
51
|
+
shouldSkip(): boolean;
|
|
52
|
+
/** Snapshot of the breaker state for status.json / gate-decision-log. */
|
|
53
|
+
state(): CloudBreakerState;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the cloud-breaker threshold from env (`AGENTICS_CLOUD_BREAKER_THRESHOLD`).
|
|
57
|
+
* Falls back to the default constant.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveCloudBreakerThreshold(): number;
|
|
60
|
+
/** Default per-agent invocation timeout for the Phase 1 fleet (matches the
|
|
61
|
+
* Phase 2–6 path's 30s). Env override: `AGENTICS_FLEET_AGENT_TIMEOUT_MS`. */
|
|
62
|
+
export declare const DEFAULT_FLEET_AGENT_TIMEOUT_MS = 30000;
|
|
63
|
+
/** Default fleet-wide deadline. Larger than a phase fanout (the fleet is
|
|
64
|
+
* ~109 agents). Env override: `AGENTICS_FLEET_TIMEOUT_MS`. */
|
|
65
|
+
export declare const DEFAULT_FLEET_TIMEOUT_MS = 60000;
|
|
66
|
+
/** Per-agent timeout for the fleet (D1). */
|
|
67
|
+
export declare function resolveFleetAgentTimeoutMs(): number;
|
|
68
|
+
/** Fleet-wide deadline (D2). */
|
|
69
|
+
export declare function resolveFleetTimeoutMs(): number;
|
|
70
|
+
/** The effective bounds, for recording into manifest.json (D5). */
|
|
71
|
+
export interface FleetDispatchConfig {
|
|
72
|
+
readonly agent_timeout_ms: number;
|
|
73
|
+
readonly fleet_timeout_ms: number;
|
|
74
|
+
readonly cloud_breaker_threshold: number;
|
|
75
|
+
}
|
|
76
|
+
export declare function resolveFleetDispatchConfig(): FleetDispatchConfig;
|
|
77
|
+
export type AgentTier = 'repo' | 'cloud';
|
|
78
|
+
/**
|
|
79
|
+
* Pure tier-selection logic (kept in this leaf module so it is unit-testable
|
|
80
|
+
* without importing the repo-agent-runner, which uses import.meta and breaks
|
|
81
|
+
* jest). `forced` is the raw `AGENTICS_AGENT_TIER` value.
|
|
82
|
+
*
|
|
83
|
+
* - `forced==='cloud'` → cloud
|
|
84
|
+
* - `forced==='repo'` → repo if a repo mapping exists, else cloud
|
|
85
|
+
* - default (`auto`) → repo only when repo mode is on AND a repo mapping
|
|
86
|
+
* exists AND source is actually cached (the D2 gate); else cloud.
|
|
87
|
+
*/
|
|
88
|
+
export declare function decideAgentTier(opts: {
|
|
89
|
+
forced?: string | undefined;
|
|
90
|
+
hasRepo: boolean;
|
|
91
|
+
repoMode: boolean;
|
|
92
|
+
sourceCached: boolean;
|
|
93
|
+
}): AgentTier;
|
|
94
|
+
/** Sentinel returned by {@link withAgentTimeout} when the deadline wins. */
|
|
95
|
+
export declare const AGENT_TIMED_OUT: unique symbol;
|
|
96
|
+
/**
|
|
97
|
+
* Race a promise against a timeout. Resolves to {@link AGENT_TIMED_OUT} when
|
|
98
|
+
* the deadline fires first. The underlying promise is NOT cancelled (Node has
|
|
99
|
+
* no cancellation), but the caller stops waiting on it — the key property the
|
|
100
|
+
* Phase 1 fleet needs so one slow agent cannot stall the batch.
|
|
101
|
+
*
|
|
102
|
+
* The timer is cleared on settle so it never keeps the event loop alive.
|
|
103
|
+
*/
|
|
104
|
+
export declare function withAgentTimeout<T>(promise: Promise<T>, ms: number): Promise<T | typeof AGENT_TIMED_OUT>;
|
|
105
|
+
/** Sentinel returned by {@link raceFleetDeadline} when the fleet deadline wins. */
|
|
106
|
+
export declare const FLEET_TIMED_OUT: "TIMEOUT";
|
|
107
|
+
/**
|
|
108
|
+
* ADR-PIPELINE-108 D2: race the whole agent batch against a wall-clock fleet
|
|
109
|
+
* deadline. Returns the settled batch if it finishes first, else
|
|
110
|
+
* {@link FLEET_TIMED_OUT}. The deadline timer is cleared on settle so a normal
|
|
111
|
+
* (non-timeout) completion never leaves a dangling timer holding the event loop
|
|
112
|
+
* open — important for long-lived (daemon/server) callers.
|
|
113
|
+
*/
|
|
114
|
+
export declare function raceFleetDeadline<T>(batch: Promise<T>, ms: number): Promise<T | typeof FLEET_TIMED_OUT>;
|
|
115
|
+
//# sourceMappingURL=fleet-dispatch-bounds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-dispatch-bounds.d.ts","sourceRoot":"","sources":["../../src/pipeline/fleet-dispatch-bounds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,4EAA4E;AAC5E,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,SAAS,SAAkC;IAIvD;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAqBtF,iDAAiD;IACjD,UAAU,IAAI,OAAO;IAErB,yEAAyE;IACzE,KAAK,IAAI,iBAAiB;CAO3B;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAOrD;AAMD;8EAC8E;AAC9E,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAErD;+DAC+D;AAC/D,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAW/C,4CAA4C;AAC5C,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,gCAAgC;AAChC,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;CAC1C;AAED,wBAAgB,0BAA0B,IAAI,mBAAmB,CAMhE;AAMD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzC;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,SAAS,CAMZ;AAED,4EAA4E;AAC5E,eAAO,MAAM,eAAe,eAA4B,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,CAAC,GAAG,OAAO,eAAe,CAAC,CAUrC;AAED,mFAAmF;AACnF,eAAO,MAAM,eAAe,EAAG,SAAkB,CAAC;AAElD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,CAAC,GAAG,OAAO,eAAe,CAAC,CAUrC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet dispatch bounds — shared timeout / circuit-breaker primitives.
|
|
3
|
+
*
|
|
4
|
+
* ADR-PIPELINE-108: the Phase 1 full-fleet dispatch (109 agents) and the
|
|
5
|
+
* Phase 2–6 phase fanouts must share ONE bounding discipline:
|
|
6
|
+
* - a per-agent timeout so no single agent can stall the batch, and
|
|
7
|
+
* - a per-fanout cloud circuit breaker so a dead backend short-circuits
|
|
8
|
+
* the remaining cloud calls instead of each eating its full timeout.
|
|
9
|
+
*
|
|
10
|
+
* These primitives previously lived inside `swarm-orchestrator.ts`, but
|
|
11
|
+
* `swarm-orchestrator.ts` imports `executeAgentsInvokeCommand` from
|
|
12
|
+
* `commands/agents.ts`. Having `agents.ts` import the breaker back from the
|
|
13
|
+
* orchestrator would create an import cycle, so the shared pieces live here
|
|
14
|
+
* in a leaf module that neither imports from. `swarm-orchestrator.ts`
|
|
15
|
+
* re-exports `CloudCircuitBreaker` / `CloudBreakerState` for back-compat
|
|
16
|
+
* (existing tests import them from there).
|
|
17
|
+
*/
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Cloud circuit breaker (ADR-094 D7, generalised by ADR-108)
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/** Default consecutive cloud-failure threshold before the breaker trips. */
|
|
22
|
+
export const DEFAULT_CLOUD_BREAKER_THRESHOLD = 3;
|
|
23
|
+
/**
|
|
24
|
+
* Per-fanout circuit breaker that trips after N consecutive cloud-tier
|
|
25
|
+
* failures and short-circuits remaining cloud invocations. Local-tier
|
|
26
|
+
* successes do not reset the streak; they bypass the breaker.
|
|
27
|
+
*
|
|
28
|
+
* Cloud-tier successes DO reset the streak — if even one cloud call works,
|
|
29
|
+
* we trust the cloud is alive again. This matches the originating-run
|
|
30
|
+
* failure mode where an entire backend fleet was down at once.
|
|
31
|
+
*
|
|
32
|
+
* Resets per fanout. Exported for unit tests.
|
|
33
|
+
*/
|
|
34
|
+
export class CloudCircuitBreaker {
|
|
35
|
+
consecutiveCloudFailures = 0;
|
|
36
|
+
trippedFlag = false;
|
|
37
|
+
trippedAfterN = 0;
|
|
38
|
+
trippedAgents = [];
|
|
39
|
+
threshold;
|
|
40
|
+
constructor(threshold = DEFAULT_CLOUD_BREAKER_THRESHOLD) {
|
|
41
|
+
this.threshold = Math.max(1, threshold);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Record an invocation outcome. `tier` is the tier the call was dispatched
|
|
45
|
+
* on. `failed=true` AND `tier='cloud'` increments the consecutive-failure
|
|
46
|
+
* counter; a cloud success resets it.
|
|
47
|
+
*/
|
|
48
|
+
record(failed, tier, agentLabel) {
|
|
49
|
+
if (this.trippedFlag)
|
|
50
|
+
return; // already tripped — record-only mode
|
|
51
|
+
if (tier === 'cloud') {
|
|
52
|
+
if (failed) {
|
|
53
|
+
this.consecutiveCloudFailures++;
|
|
54
|
+
this.trippedAgents.push(agentLabel);
|
|
55
|
+
if (this.consecutiveCloudFailures >= this.threshold) {
|
|
56
|
+
this.trippedFlag = true;
|
|
57
|
+
this.trippedAfterN = this.consecutiveCloudFailures;
|
|
58
|
+
process.stderr.write(`[BREAKER] cloud breaker tripped after ${this.trippedAfterN} timeouts (${this.trippedAgents.slice(0, 5).join(', ')}${this.trippedAgents.length > 5 ? ', …' : ''})\n`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Cloud success — clear the streak. Cloud is alive.
|
|
63
|
+
this.consecutiveCloudFailures = 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// local-tier outcomes don't move the breaker state.
|
|
67
|
+
}
|
|
68
|
+
/** Returns true once the breaker has tripped. */
|
|
69
|
+
shouldSkip() { return this.trippedFlag; }
|
|
70
|
+
/** Snapshot of the breaker state for status.json / gate-decision-log. */
|
|
71
|
+
state() {
|
|
72
|
+
return {
|
|
73
|
+
tripped: this.trippedFlag,
|
|
74
|
+
after_n_timeouts: this.trippedAfterN,
|
|
75
|
+
agents: [...this.trippedAgents],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve the cloud-breaker threshold from env (`AGENTICS_CLOUD_BREAKER_THRESHOLD`).
|
|
81
|
+
* Falls back to the default constant.
|
|
82
|
+
*/
|
|
83
|
+
export function resolveCloudBreakerThreshold() {
|
|
84
|
+
const env = process.env['AGENTICS_CLOUD_BREAKER_THRESHOLD'];
|
|
85
|
+
if (env) {
|
|
86
|
+
const parsed = parseInt(env, 10);
|
|
87
|
+
if (!Number.isNaN(parsed) && parsed >= 1)
|
|
88
|
+
return parsed;
|
|
89
|
+
}
|
|
90
|
+
return DEFAULT_CLOUD_BREAKER_THRESHOLD;
|
|
91
|
+
}
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Per-agent + fleet timeouts (ADR-108 D1, D2, D5)
|
|
94
|
+
// ============================================================================
|
|
95
|
+
/** Default per-agent invocation timeout for the Phase 1 fleet (matches the
|
|
96
|
+
* Phase 2–6 path's 30s). Env override: `AGENTICS_FLEET_AGENT_TIMEOUT_MS`. */
|
|
97
|
+
export const DEFAULT_FLEET_AGENT_TIMEOUT_MS = 30_000;
|
|
98
|
+
/** Default fleet-wide deadline. Larger than a phase fanout (the fleet is
|
|
99
|
+
* ~109 agents). Env override: `AGENTICS_FLEET_TIMEOUT_MS`. */
|
|
100
|
+
export const DEFAULT_FLEET_TIMEOUT_MS = 60_000;
|
|
101
|
+
function resolvePositiveIntEnv(name, fallback) {
|
|
102
|
+
const env = process.env[name];
|
|
103
|
+
if (env) {
|
|
104
|
+
const parsed = parseInt(env, 10);
|
|
105
|
+
if (!Number.isNaN(parsed) && parsed >= 1)
|
|
106
|
+
return parsed;
|
|
107
|
+
}
|
|
108
|
+
return fallback;
|
|
109
|
+
}
|
|
110
|
+
/** Per-agent timeout for the fleet (D1). */
|
|
111
|
+
export function resolveFleetAgentTimeoutMs() {
|
|
112
|
+
return resolvePositiveIntEnv('AGENTICS_FLEET_AGENT_TIMEOUT_MS', DEFAULT_FLEET_AGENT_TIMEOUT_MS);
|
|
113
|
+
}
|
|
114
|
+
/** Fleet-wide deadline (D2). */
|
|
115
|
+
export function resolveFleetTimeoutMs() {
|
|
116
|
+
return resolvePositiveIntEnv('AGENTICS_FLEET_TIMEOUT_MS', DEFAULT_FLEET_TIMEOUT_MS);
|
|
117
|
+
}
|
|
118
|
+
export function resolveFleetDispatchConfig() {
|
|
119
|
+
return {
|
|
120
|
+
agent_timeout_ms: resolveFleetAgentTimeoutMs(),
|
|
121
|
+
fleet_timeout_ms: resolveFleetTimeoutMs(),
|
|
122
|
+
cloud_breaker_threshold: resolveCloudBreakerThreshold(),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Pure tier-selection logic (kept in this leaf module so it is unit-testable
|
|
127
|
+
* without importing the repo-agent-runner, which uses import.meta and breaks
|
|
128
|
+
* jest). `forced` is the raw `AGENTICS_AGENT_TIER` value.
|
|
129
|
+
*
|
|
130
|
+
* - `forced==='cloud'` → cloud
|
|
131
|
+
* - `forced==='repo'` → repo if a repo mapping exists, else cloud
|
|
132
|
+
* - default (`auto`) → repo only when repo mode is on AND a repo mapping
|
|
133
|
+
* exists AND source is actually cached (the D2 gate); else cloud.
|
|
134
|
+
*/
|
|
135
|
+
export function decideAgentTier(opts) {
|
|
136
|
+
const forced = (opts.forced ?? '').toLowerCase();
|
|
137
|
+
if (forced === 'cloud')
|
|
138
|
+
return 'cloud';
|
|
139
|
+
if (forced === 'repo')
|
|
140
|
+
return opts.hasRepo ? 'repo' : 'cloud';
|
|
141
|
+
if (opts.repoMode && opts.hasRepo && opts.sourceCached)
|
|
142
|
+
return 'repo';
|
|
143
|
+
return 'cloud';
|
|
144
|
+
}
|
|
145
|
+
/** Sentinel returned by {@link withAgentTimeout} when the deadline wins. */
|
|
146
|
+
export const AGENT_TIMED_OUT = Symbol('agent-timed-out');
|
|
147
|
+
/**
|
|
148
|
+
* Race a promise against a timeout. Resolves to {@link AGENT_TIMED_OUT} when
|
|
149
|
+
* the deadline fires first. The underlying promise is NOT cancelled (Node has
|
|
150
|
+
* no cancellation), but the caller stops waiting on it — the key property the
|
|
151
|
+
* Phase 1 fleet needs so one slow agent cannot stall the batch.
|
|
152
|
+
*
|
|
153
|
+
* The timer is cleared on settle so it never keeps the event loop alive.
|
|
154
|
+
*/
|
|
155
|
+
export async function withAgentTimeout(promise, ms) {
|
|
156
|
+
let timer;
|
|
157
|
+
const timeout = new Promise((resolve) => {
|
|
158
|
+
timer = setTimeout(() => resolve(AGENT_TIMED_OUT), ms);
|
|
159
|
+
});
|
|
160
|
+
try {
|
|
161
|
+
return await Promise.race([promise, timeout]);
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
if (timer)
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** Sentinel returned by {@link raceFleetDeadline} when the fleet deadline wins. */
|
|
169
|
+
export const FLEET_TIMED_OUT = 'TIMEOUT';
|
|
170
|
+
/**
|
|
171
|
+
* ADR-PIPELINE-108 D2: race the whole agent batch against a wall-clock fleet
|
|
172
|
+
* deadline. Returns the settled batch if it finishes first, else
|
|
173
|
+
* {@link FLEET_TIMED_OUT}. The deadline timer is cleared on settle so a normal
|
|
174
|
+
* (non-timeout) completion never leaves a dangling timer holding the event loop
|
|
175
|
+
* open — important for long-lived (daemon/server) callers.
|
|
176
|
+
*/
|
|
177
|
+
export async function raceFleetDeadline(batch, ms) {
|
|
178
|
+
let timer;
|
|
179
|
+
const deadline = new Promise((resolve) => {
|
|
180
|
+
timer = setTimeout(() => resolve(FLEET_TIMED_OUT), ms);
|
|
181
|
+
});
|
|
182
|
+
try {
|
|
183
|
+
return await Promise.race([batch, deadline]);
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
if (timer)
|
|
187
|
+
clearTimeout(timer);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=fleet-dispatch-bounds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-dispatch-bounds.js","sourceRoot":"","sources":["../../src/pipeline/fleet-dispatch-bounds.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-codegen.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/phase3/phases/domain-codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EAGtB,aAAa,EAEd,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,iBAAiB,EAQjB,OAAO,EAGP,iBAAiB,EAGlB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"domain-codegen.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/phase3/phases/domain-codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EAGtB,aAAa,EAEd,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,iBAAiB,EAQjB,OAAO,EAGP,iBAAiB,EAGlB,MAAM,uBAAuB,CAAC;AA4hH/B;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,sBAAsB,EAChC,KAAK,EAAE,iBAAiB,GACvB,aAAa,CA+Uf;AAuiBD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAwK5B"}
|
|
@@ -558,8 +558,14 @@ function extractFieldsFromDescription(description, entityName) {
|
|
|
558
558
|
// ADR-PIPELINE-021: If description patterns found nothing, try matching against
|
|
559
559
|
// the entity NAME itself (e.g. "UpgradeOptions" → matches "upgrade" pattern).
|
|
560
560
|
// This catches entities with generic descriptions but domain-specific names.
|
|
561
|
-
|
|
562
|
-
|
|
561
|
+
//
|
|
562
|
+
// Recurse AT MOST ONCE: only when the description is not already the spaced
|
|
563
|
+
// entity name. The recursive call passes the spaced name AS the description,
|
|
564
|
+
// so without this guard it would recurse on identical arguments forever
|
|
565
|
+
// (Maximum-call-stack-size-exceeded — the domain-codegen crash this fixes).
|
|
566
|
+
const spacedEntityName = entityName.replace(/([A-Z])/g, ' $1');
|
|
567
|
+
if (fields.length === 0 && description !== spacedEntityName) {
|
|
568
|
+
const nameFields = extractFieldsFromDescription(spacedEntityName, entityName);
|
|
563
569
|
if (nameFields.length > 0 && !(nameFields.length === 1 && nameFields[0].type === 'Record<string, unknown>')) {
|
|
564
570
|
fields.push(...nameFields);
|
|
565
571
|
}
|