@bradygaster/squad-sdk 0.8.25 → 0.9.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/dist/adapter/client.d.ts +17 -0
- package/dist/adapter/client.d.ts.map +1 -1
- package/dist/adapter/client.js +101 -1
- package/dist/adapter/client.js.map +1 -1
- package/dist/agents/history-shadow.d.ts.map +1 -1
- package/dist/agents/history-shadow.js +99 -32
- package/dist/agents/history-shadow.js.map +1 -1
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/model-selector.d.ts +2 -0
- package/dist/agents/model-selector.d.ts.map +1 -1
- package/dist/agents/model-selector.js +41 -35
- package/dist/agents/model-selector.js.map +1 -1
- package/dist/agents/personal.d.ts +35 -0
- package/dist/agents/personal.d.ts.map +1 -0
- package/dist/agents/personal.js +67 -0
- package/dist/agents/personal.js.map +1 -0
- package/dist/builders/index.d.ts +3 -2
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +28 -0
- package/dist/builders/index.js.map +1 -1
- package/dist/builders/types.d.ts +13 -0
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/config/init.d.ts +8 -0
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +131 -20
- package/dist/config/init.js.map +1 -1
- package/dist/config/models.d.ts +112 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +329 -18
- package/dist/config/models.js.map +1 -1
- package/dist/coordinator/index.js +2 -2
- package/dist/coordinator/index.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/platform/azure-devops.d.ts +42 -0
- package/dist/platform/azure-devops.d.ts.map +1 -1
- package/dist/platform/azure-devops.js +75 -0
- package/dist/platform/azure-devops.js.map +1 -1
- package/dist/platform/comms-file-log.d.ts.map +1 -1
- package/dist/platform/comms-file-log.js +2 -1
- package/dist/platform/comms-file-log.js.map +1 -1
- package/dist/platform/index.d.ts +2 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +1 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/ralph/capabilities.d.ts +67 -0
- package/dist/ralph/capabilities.d.ts.map +1 -0
- package/dist/ralph/capabilities.js +111 -0
- package/dist/ralph/capabilities.js.map +1 -0
- package/dist/ralph/index.d.ts +2 -0
- package/dist/ralph/index.d.ts.map +1 -1
- package/dist/ralph/index.js +6 -5
- package/dist/ralph/index.js.map +1 -1
- package/dist/ralph/rate-limiting.d.ts +99 -0
- package/dist/ralph/rate-limiting.d.ts.map +1 -0
- package/dist/ralph/rate-limiting.js +170 -0
- package/dist/ralph/rate-limiting.js.map +1 -0
- package/dist/resolution.d.ts +24 -2
- package/dist/resolution.d.ts.map +1 -1
- package/dist/resolution.js +106 -6
- package/dist/resolution.js.map +1 -1
- package/dist/roles/catalog-categories.d.ts +146 -0
- package/dist/roles/catalog-categories.d.ts.map +1 -0
- package/dist/roles/catalog-categories.js +374 -0
- package/dist/roles/catalog-categories.js.map +1 -0
- package/dist/roles/catalog-engineering.d.ts +212 -0
- package/dist/roles/catalog-engineering.d.ts.map +1 -0
- package/dist/roles/catalog-engineering.js +549 -0
- package/dist/roles/catalog-engineering.js.map +1 -0
- package/dist/roles/catalog.d.ts +24 -0
- package/dist/roles/catalog.d.ts.map +1 -0
- package/dist/roles/catalog.js +28 -0
- package/dist/roles/catalog.js.map +1 -0
- package/dist/roles/index.d.ts +69 -0
- package/dist/roles/index.d.ts.map +1 -0
- package/dist/roles/index.js +197 -0
- package/dist/roles/index.js.map +1 -0
- package/dist/roles/types.d.ts +87 -0
- package/dist/roles/types.d.ts.map +1 -0
- package/dist/roles/types.js +14 -0
- package/dist/roles/types.js.map +1 -0
- package/dist/runtime/benchmarks.js +5 -5
- package/dist/runtime/benchmarks.js.map +1 -1
- package/dist/runtime/constants.d.ts +2 -2
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +5 -3
- package/dist/runtime/constants.js.map +1 -1
- package/dist/runtime/cross-squad.d.ts +118 -0
- package/dist/runtime/cross-squad.d.ts.map +1 -0
- package/dist/runtime/cross-squad.js +234 -0
- package/dist/runtime/cross-squad.js.map +1 -0
- package/dist/runtime/otel-init.d.ts +24 -17
- package/dist/runtime/otel-init.d.ts.map +1 -1
- package/dist/runtime/otel-init.js +29 -20
- package/dist/runtime/otel-init.js.map +1 -1
- package/dist/runtime/otel-metrics.d.ts +5 -0
- package/dist/runtime/otel-metrics.d.ts.map +1 -1
- package/dist/runtime/otel-metrics.js +54 -0
- package/dist/runtime/otel-metrics.js.map +1 -1
- package/dist/runtime/rework.d.ts +71 -0
- package/dist/runtime/rework.d.ts.map +1 -0
- package/dist/runtime/rework.js +107 -0
- package/dist/runtime/rework.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +128 -0
- package/dist/runtime/scheduler.d.ts.map +1 -0
- package/dist/runtime/scheduler.js +427 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/squad-observer.d.ts.map +1 -1
- package/dist/runtime/squad-observer.js +4 -0
- package/dist/runtime/squad-observer.js.map +1 -1
- package/dist/runtime/streaming.d.ts +2 -0
- package/dist/runtime/streaming.d.ts.map +1 -1
- package/dist/runtime/streaming.js +6 -0
- package/dist/runtime/streaming.js.map +1 -1
- package/dist/runtime/telemetry.d.ts +2 -0
- package/dist/runtime/telemetry.d.ts.map +1 -1
- package/dist/runtime/telemetry.js +6 -0
- package/dist/runtime/telemetry.js.map +1 -1
- package/dist/sharing/consult.d.ts +2 -2
- package/dist/sharing/consult.js +6 -6
- package/dist/sharing/consult.js.map +1 -1
- package/dist/sharing/export.d.ts.map +1 -1
- package/dist/sharing/export.js +17 -4
- package/dist/sharing/export.js.map +1 -1
- package/dist/skills/handler-types.d.ts +271 -0
- package/dist/skills/handler-types.d.ts.map +1 -0
- package/dist/skills/handler-types.js +31 -0
- package/dist/skills/handler-types.js.map +1 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +3 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/skill-script-loader.d.ts +65 -0
- package/dist/skills/skill-script-loader.d.ts.map +1 -0
- package/dist/skills/skill-script-loader.js +227 -0
- package/dist/skills/skill-script-loader.js.map +1 -0
- package/dist/skills/skill-source.d.ts.map +1 -1
- package/dist/skills/skill-source.js +5 -1
- package/dist/skills/skill-source.js.map +1 -1
- package/dist/tools/index.d.ts +10 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +49 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/upstream/resolver.d.ts.map +1 -1
- package/dist/upstream/resolver.js +14 -5
- package/dist/upstream/resolver.js.map +1 -1
- package/package.json +34 -3
- package/templates/casting/Futurama.json +10 -0
- package/templates/casting-policy.json +4 -2
- package/templates/casting-reference.md +104 -0
- package/templates/cooperative-rate-limiting.md +229 -0
- package/templates/issue-lifecycle.md +412 -0
- package/templates/keda-scaler.md +164 -0
- package/templates/machine-capabilities.md +75 -0
- package/templates/mcp-config.md +0 -8
- package/templates/orchestration-log.md +27 -27
- package/templates/package.json +3 -0
- package/templates/ralph-circuit-breaker.md +313 -0
- package/templates/ralph-triage.js +543 -0
- package/templates/routing.md +5 -20
- package/templates/schedule.json +19 -0
- package/templates/scribe-charter.md +1 -1
- package/templates/skills/agent-collaboration/SKILL.md +42 -0
- package/templates/skills/agent-conduct/SKILL.md +24 -0
- package/templates/skills/architectural-proposals/SKILL.md +151 -0
- package/templates/skills/ci-validation-gates/SKILL.md +84 -0
- package/templates/skills/cli-wiring/SKILL.md +47 -0
- package/templates/skills/client-compatibility/SKILL.md +89 -0
- package/templates/skills/cross-squad/SKILL.md +114 -0
- package/templates/skills/distributed-mesh/SKILL.md +287 -0
- package/templates/skills/distributed-mesh/mesh.json.example +30 -0
- package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -0
- package/templates/skills/distributed-mesh/sync-mesh.sh +104 -0
- package/templates/skills/docs-standards/SKILL.md +71 -0
- package/templates/skills/economy-mode/SKILL.md +114 -0
- package/templates/skills/external-comms/SKILL.md +329 -0
- package/templates/skills/gh-auth-isolation/SKILL.md +183 -0
- package/templates/skills/git-workflow/SKILL.md +204 -0
- package/templates/skills/github-multi-account/SKILL.md +95 -0
- package/templates/skills/history-hygiene/SKILL.md +36 -0
- package/templates/skills/humanizer/SKILL.md +105 -0
- package/templates/skills/init-mode/SKILL.md +102 -0
- package/templates/skills/model-selection/SKILL.md +117 -0
- package/templates/skills/nap/SKILL.md +24 -0
- package/templates/skills/personal-squad/SKILL.md +57 -0
- package/templates/skills/release-process/SKILL.md +423 -0
- package/templates/skills/reskill/SKILL.md +92 -0
- package/templates/skills/reviewer-protocol/SKILL.md +79 -0
- package/templates/skills/secret-handling/SKILL.md +200 -0
- package/templates/skills/session-recovery/SKILL.md +155 -0
- package/templates/skills/squad-conventions/SKILL.md +69 -0
- package/templates/skills/test-discipline/SKILL.md +37 -0
- package/templates/skills/windows-compatibility/SKILL.md +74 -0
- package/templates/squad.agent.md +1287 -1146
- package/templates/workflows/squad-docs.yml +8 -4
- package/templates/workflows/squad-heartbeat.yml +55 -200
- package/templates/workflows/squad-insider-release.yml +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predictive Circuit Breaker — Rate Limit Protection
|
|
3
|
+
*
|
|
4
|
+
* Opens the circuit BEFORE getting a 429 by predicting when
|
|
5
|
+
* API quota will be exhausted. Prediction uses the observed
|
|
6
|
+
* consumption rate between the oldest and newest samples
|
|
7
|
+
* (first-to-last delta), not a full least-squares regression.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/bradygaster/squad/issues/515
|
|
10
|
+
*/
|
|
11
|
+
/** A rate limit sample from API response headers */
|
|
12
|
+
export interface RateSample {
|
|
13
|
+
timestamp: number;
|
|
14
|
+
remaining: number;
|
|
15
|
+
limit: number;
|
|
16
|
+
}
|
|
17
|
+
/** Traffic light state for rate-aware scheduling */
|
|
18
|
+
export type TrafficLight = 'green' | 'amber' | 'red';
|
|
19
|
+
/** Agent priority for quota allocation */
|
|
20
|
+
export type AgentPriority = 0 | 1 | 2;
|
|
21
|
+
/**
|
|
22
|
+
* Determine traffic light from rate limit headers.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getTrafficLight(remaining: number, limit: number): TrafficLight;
|
|
25
|
+
/**
|
|
26
|
+
* Check if an agent should proceed based on traffic light and priority.
|
|
27
|
+
* - GREEN: all agents proceed
|
|
28
|
+
* - AMBER: only P0 agents proceed
|
|
29
|
+
* - RED: no agents proceed
|
|
30
|
+
*/
|
|
31
|
+
export declare function shouldProceed(light: TrafficLight, priority: AgentPriority): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Get retry delay with priority-based jitter windows.
|
|
34
|
+
* Higher priority agents retry sooner with smaller windows.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getRetryDelay(priority: AgentPriority, attempt: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Predictive circuit breaker that opens BEFORE rate limit errors.
|
|
39
|
+
*
|
|
40
|
+
* Tracks the last N rate limit samples and uses linear regression
|
|
41
|
+
* to predict when quota will be exhausted. If predicted ETA is
|
|
42
|
+
* below the warning threshold, the circuit opens preemptively.
|
|
43
|
+
*/
|
|
44
|
+
export declare class PredictiveCircuitBreaker {
|
|
45
|
+
private samples;
|
|
46
|
+
private readonly maxSamples;
|
|
47
|
+
private readonly warningThresholdSeconds;
|
|
48
|
+
constructor(options?: {
|
|
49
|
+
maxSamples?: number;
|
|
50
|
+
warningThresholdSeconds?: number;
|
|
51
|
+
});
|
|
52
|
+
/** Record a rate limit sample from API response headers */
|
|
53
|
+
addSample(remaining: number, limit: number): void;
|
|
54
|
+
/** Get all recorded samples (for testing/debugging) */
|
|
55
|
+
getSamples(): readonly RateSample[];
|
|
56
|
+
/**
|
|
57
|
+
* Predict seconds until quota exhaustion using the observed
|
|
58
|
+
* consumption rate between the first and last recorded samples.
|
|
59
|
+
* Returns null if insufficient data or quota is not being consumed.
|
|
60
|
+
*/
|
|
61
|
+
predictExhaustion(): number | null;
|
|
62
|
+
/**
|
|
63
|
+
* Should the circuit open preemptively?
|
|
64
|
+
* Returns true when predicted ETA to exhaustion is below threshold.
|
|
65
|
+
*/
|
|
66
|
+
shouldOpen(): boolean;
|
|
67
|
+
/** Reset all samples (e.g., after rate limit window resets) */
|
|
68
|
+
reset(): void;
|
|
69
|
+
}
|
|
70
|
+
/** Rate pool allocation for cooperative multi-agent quota management */
|
|
71
|
+
export interface RatePoolAllocation {
|
|
72
|
+
priority: AgentPriority;
|
|
73
|
+
allocated: number;
|
|
74
|
+
used: number;
|
|
75
|
+
leaseExpiry: string;
|
|
76
|
+
}
|
|
77
|
+
/** Shared rate pool state */
|
|
78
|
+
export interface RatePool {
|
|
79
|
+
totalLimit: number;
|
|
80
|
+
resetAt: string;
|
|
81
|
+
allocations: Record<string, RatePoolAllocation>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if an agent has remaining quota in the cooperative pool.
|
|
85
|
+
* Pure read — no side effects.
|
|
86
|
+
*/
|
|
87
|
+
export declare function canUseQuota(pool: RatePool, agentName: string): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Consume one unit of quota for an agent.
|
|
90
|
+
* Also reclaims stale leases from other crashed agents so their
|
|
91
|
+
* unused allocation is freed for the pool.
|
|
92
|
+
* Call this after canUseQuota() confirms there is quota available.
|
|
93
|
+
*/
|
|
94
|
+
export declare function consumeQuota(pool: RatePool, agentName: string): void;
|
|
95
|
+
/**
|
|
96
|
+
* Load rate pool state from the shared file.
|
|
97
|
+
*/
|
|
98
|
+
export declare function loadRatePool(teamRoot?: string): Promise<RatePool | null>;
|
|
99
|
+
//# sourceMappingURL=rate-limiting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiting.d.ts","sourceRoot":"","sources":["../../src/ralph/rate-limiting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oDAAoD;AACpD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;AAErD,0CAA0C;AAC1C,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAStC;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAM9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAInF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAK9E;AAED;;;;;;GAMG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAS;gBAErC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;KAAE;IAK/E,2DAA2D;IAC3D,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjD,uDAAuD;IACvD,UAAU,IAAI,SAAS,UAAU,EAAE;IAInC;;;;OAIG;IACH,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAkBlC;;;OAGG;IACH,UAAU,IAAI,OAAO;IAMrB,+DAA+D;IAC/D,KAAK,IAAI,IAAI;CAGd;AAED,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,6BAA6B;AAC7B,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAKtE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAapE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAmB9E"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predictive Circuit Breaker — Rate Limit Protection
|
|
3
|
+
*
|
|
4
|
+
* Opens the circuit BEFORE getting a 429 by predicting when
|
|
5
|
+
* API quota will be exhausted. Prediction uses the observed
|
|
6
|
+
* consumption rate between the oldest and newest samples
|
|
7
|
+
* (first-to-last delta), not a full least-squares regression.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/bradygaster/squad/issues/515
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
|
+
import { existsSync } from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
/** Priority-based retry windows (ms) */
|
|
16
|
+
const RETRY_WINDOWS = {
|
|
17
|
+
0: [500, 5_000], // P0 (Lead): 500ms–5s
|
|
18
|
+
1: [2_000, 30_000], // P1 (Specialists): 2s–30s
|
|
19
|
+
2: [5_000, 60_000], // P2 (Ralph/Scribe): 5s–60s
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Determine traffic light from rate limit headers.
|
|
23
|
+
*/
|
|
24
|
+
export function getTrafficLight(remaining, limit) {
|
|
25
|
+
if (limit === 0)
|
|
26
|
+
return 'red';
|
|
27
|
+
const pct = remaining / limit;
|
|
28
|
+
if (pct > 0.20)
|
|
29
|
+
return 'green';
|
|
30
|
+
if (pct > 0.05)
|
|
31
|
+
return 'amber';
|
|
32
|
+
return 'red';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if an agent should proceed based on traffic light and priority.
|
|
36
|
+
* - GREEN: all agents proceed
|
|
37
|
+
* - AMBER: only P0 agents proceed
|
|
38
|
+
* - RED: no agents proceed
|
|
39
|
+
*/
|
|
40
|
+
export function shouldProceed(light, priority) {
|
|
41
|
+
if (light === 'green')
|
|
42
|
+
return true;
|
|
43
|
+
if (light === 'amber')
|
|
44
|
+
return priority === 0;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get retry delay with priority-based jitter windows.
|
|
49
|
+
* Higher priority agents retry sooner with smaller windows.
|
|
50
|
+
*/
|
|
51
|
+
export function getRetryDelay(priority, attempt) {
|
|
52
|
+
const [min, max] = RETRY_WINDOWS[priority] ?? RETRY_WINDOWS[2];
|
|
53
|
+
const base = Math.min(min * Math.pow(2, attempt), max);
|
|
54
|
+
const jitter = Math.random() * base * 0.5;
|
|
55
|
+
return Math.round(base + jitter);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Predictive circuit breaker that opens BEFORE rate limit errors.
|
|
59
|
+
*
|
|
60
|
+
* Tracks the last N rate limit samples and uses linear regression
|
|
61
|
+
* to predict when quota will be exhausted. If predicted ETA is
|
|
62
|
+
* below the warning threshold, the circuit opens preemptively.
|
|
63
|
+
*/
|
|
64
|
+
export class PredictiveCircuitBreaker {
|
|
65
|
+
samples = [];
|
|
66
|
+
maxSamples;
|
|
67
|
+
warningThresholdSeconds;
|
|
68
|
+
constructor(options) {
|
|
69
|
+
this.maxSamples = options?.maxSamples ?? 10;
|
|
70
|
+
this.warningThresholdSeconds = options?.warningThresholdSeconds ?? 120;
|
|
71
|
+
}
|
|
72
|
+
/** Record a rate limit sample from API response headers */
|
|
73
|
+
addSample(remaining, limit) {
|
|
74
|
+
this.samples.push({ timestamp: Date.now(), remaining, limit });
|
|
75
|
+
if (this.samples.length > this.maxSamples) {
|
|
76
|
+
this.samples.shift();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Get all recorded samples (for testing/debugging) */
|
|
80
|
+
getSamples() {
|
|
81
|
+
return this.samples;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Predict seconds until quota exhaustion using the observed
|
|
85
|
+
* consumption rate between the first and last recorded samples.
|
|
86
|
+
* Returns null if insufficient data or quota is not being consumed.
|
|
87
|
+
*/
|
|
88
|
+
predictExhaustion() {
|
|
89
|
+
if (this.samples.length < 3)
|
|
90
|
+
return null;
|
|
91
|
+
const n = this.samples.length;
|
|
92
|
+
const first = this.samples[0];
|
|
93
|
+
const last = this.samples[n - 1];
|
|
94
|
+
const elapsedMs = last.timestamp - first.timestamp;
|
|
95
|
+
if (elapsedMs === 0)
|
|
96
|
+
return null;
|
|
97
|
+
const consumed = first.remaining - last.remaining;
|
|
98
|
+
if (consumed <= 0)
|
|
99
|
+
return null; // Not consuming or recovering
|
|
100
|
+
const consumedPerMs = consumed / elapsedMs;
|
|
101
|
+
const msUntilExhausted = last.remaining / consumedPerMs;
|
|
102
|
+
return msUntilExhausted / 1000;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Should the circuit open preemptively?
|
|
106
|
+
* Returns true when predicted ETA to exhaustion is below threshold.
|
|
107
|
+
*/
|
|
108
|
+
shouldOpen() {
|
|
109
|
+
const eta = this.predictExhaustion();
|
|
110
|
+
if (eta === null)
|
|
111
|
+
return false;
|
|
112
|
+
return eta < this.warningThresholdSeconds;
|
|
113
|
+
}
|
|
114
|
+
/** Reset all samples (e.g., after rate limit window resets) */
|
|
115
|
+
reset() {
|
|
116
|
+
this.samples = [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if an agent has remaining quota in the cooperative pool.
|
|
121
|
+
* Pure read — no side effects.
|
|
122
|
+
*/
|
|
123
|
+
export function canUseQuota(pool, agentName) {
|
|
124
|
+
const alloc = pool.allocations[agentName];
|
|
125
|
+
if (!alloc)
|
|
126
|
+
return true; // Unknown agent — allow gracefully
|
|
127
|
+
return alloc.used < alloc.allocated;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Consume one unit of quota for an agent.
|
|
131
|
+
* Also reclaims stale leases from other crashed agents so their
|
|
132
|
+
* unused allocation is freed for the pool.
|
|
133
|
+
* Call this after canUseQuota() confirms there is quota available.
|
|
134
|
+
*/
|
|
135
|
+
export function consumeQuota(pool, agentName) {
|
|
136
|
+
const alloc = pool.allocations[agentName];
|
|
137
|
+
if (!alloc)
|
|
138
|
+
return; // Unknown agent — nothing to consume
|
|
139
|
+
// Reclaim stale leases from other agents
|
|
140
|
+
const now = new Date();
|
|
141
|
+
for (const [name, a] of Object.entries(pool.allocations)) {
|
|
142
|
+
if (new Date(a.leaseExpiry) < now && name !== agentName) {
|
|
143
|
+
a.allocated = 0;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
alloc.used++;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Load rate pool state from the shared file.
|
|
150
|
+
*/
|
|
151
|
+
export async function loadRatePool(teamRoot) {
|
|
152
|
+
const candidates = [];
|
|
153
|
+
if (teamRoot) {
|
|
154
|
+
candidates.push(path.join(teamRoot, '.squad', 'rate-pool.json'));
|
|
155
|
+
}
|
|
156
|
+
candidates.push(path.join(os.homedir(), '.squad', 'rate-pool.json'));
|
|
157
|
+
for (const candidate of candidates) {
|
|
158
|
+
if (existsSync(candidate)) {
|
|
159
|
+
try {
|
|
160
|
+
const raw = await readFile(candidate, 'utf8');
|
|
161
|
+
return JSON.parse(raw);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// Malformed — skip
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=rate-limiting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiting.js","sourceRoot":"","sources":["../../src/ralph/rate-limiting.ts"],"names":[],"mappings":"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"}
|
package/dist/resolution.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface ResolvedSquadPaths {
|
|
|
37
37
|
projectDir: string;
|
|
38
38
|
/** Team identity root (agents, casting, skills) */
|
|
39
39
|
teamDir: string;
|
|
40
|
+
/** User's personal squad dir, null if not found or disabled */
|
|
41
|
+
personalDir: string | null;
|
|
40
42
|
config: SquadDirConfig | null;
|
|
41
43
|
name: '.squad' | '.ai-team';
|
|
42
44
|
isLegacy: boolean;
|
|
@@ -44,10 +46,14 @@ export interface ResolvedSquadPaths {
|
|
|
44
46
|
/**
|
|
45
47
|
* Walk up the directory tree from `startDir` looking for a `.squad/` directory.
|
|
46
48
|
*
|
|
47
|
-
* Stops at the repository root (the directory containing `.git`).
|
|
49
|
+
* Stops at the repository root (the directory containing `.git` as a directory).
|
|
50
|
+
* When `.git` is a **file** (git worktree), falls back to the main checkout strategy:
|
|
51
|
+
* reads the `gitdir:` pointer, resolves the main checkout path, and checks there.
|
|
48
52
|
* Returns the **absolute path** to the `.squad/` directory, or `null` if none is found.
|
|
49
53
|
*
|
|
50
|
-
*
|
|
54
|
+
* Resolution order (worktree-local strategy first, main-checkout strategy second):
|
|
55
|
+
* 1. Walk up from `startDir` checking for `.squad/` — stops at `.git` directory boundary
|
|
56
|
+
* 2. If `.git` is a file (worktree), check the main checkout for `.squad/`
|
|
51
57
|
*
|
|
52
58
|
* @param startDir - Directory to start searching from. Defaults to `process.cwd()`.
|
|
53
59
|
* @returns Absolute path to `.squad/` or `null`.
|
|
@@ -88,6 +94,16 @@ export declare function resolveSquadPaths(startDir?: string): ResolvedSquadPaths
|
|
|
88
94
|
* @returns Absolute path to the global squad config directory.
|
|
89
95
|
*/
|
|
90
96
|
export declare function resolveGlobalSquadPath(): string;
|
|
97
|
+
/**
|
|
98
|
+
* Resolves the user's personal squad directory.
|
|
99
|
+
* Returns null if SQUAD_NO_PERSONAL is set or directory doesn't exist.
|
|
100
|
+
*
|
|
101
|
+
* Platform paths:
|
|
102
|
+
* - Windows: %APPDATA%/squad/personal-squad
|
|
103
|
+
* - macOS: ~/Library/Application Support/squad/personal-squad
|
|
104
|
+
* - Linux: $XDG_CONFIG_HOME/squad/personal-squad or ~/.config/squad/personal-squad
|
|
105
|
+
*/
|
|
106
|
+
export declare function resolvePersonalSquadDir(): string | null;
|
|
91
107
|
/**
|
|
92
108
|
* Validate that a file path is within `.squad/` or the system temp directory.
|
|
93
109
|
*
|
|
@@ -111,6 +127,12 @@ export declare function ensureSquadPath(filePath: string, squadRoot: string): st
|
|
|
111
127
|
* @throws If filePath is outside both roots and not in the system temp directory.
|
|
112
128
|
*/
|
|
113
129
|
export declare function ensureSquadPathDual(filePath: string, projectDir: string, teamDir: string): string;
|
|
130
|
+
/**
|
|
131
|
+
* Validates a file path is inside one of three allowed directories:
|
|
132
|
+
* projectDir, teamDir, personalDir, or system temp.
|
|
133
|
+
* Extends ensureSquadPathDual() for triple-root (project + team + personal).
|
|
134
|
+
*/
|
|
135
|
+
export declare function ensureSquadPathTriple(filePath: string, projectDir: string, teamDir: string, personalDir: string | null): string;
|
|
114
136
|
/**
|
|
115
137
|
* ensureSquadPath that works with resolved dual-root paths.
|
|
116
138
|
* Convenience wrapper around ensureSquadPathDual.
|
package/dist/resolution.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../src/resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../src/resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAkCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsC7D;AAyDD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CA0BrE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAEpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAmC9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAuB/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAQvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAmB3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAyBjG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,MAAM,CAeR;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAE3F"}
|
package/dist/resolution.js
CHANGED
|
@@ -14,13 +14,50 @@
|
|
|
14
14
|
import fs from 'node:fs';
|
|
15
15
|
import path from 'node:path';
|
|
16
16
|
import os from 'node:os';
|
|
17
|
+
/**
|
|
18
|
+
* Given a directory containing a `.git` worktree pointer file, parse the file
|
|
19
|
+
* to derive the absolute path of the main checkout.
|
|
20
|
+
*
|
|
21
|
+
* The `.git` file format is: `gitdir: <relative-or-absolute-path-to-.git/worktrees/name>`
|
|
22
|
+
* The main checkout is: dirname(dirname(dirname(resolvedGitdir))) — i.e. two levels up
|
|
23
|
+
* from the gitdir path puts us at the shared `.git/` dir, and one more dirname gives
|
|
24
|
+
* us the main working tree root.
|
|
25
|
+
*
|
|
26
|
+
* @returns Absolute path to the main working tree, or `null` if resolution fails.
|
|
27
|
+
*/
|
|
28
|
+
function getMainWorktreePath(worktreeDir, gitFilePath) {
|
|
29
|
+
try {
|
|
30
|
+
const content = fs.readFileSync(gitFilePath, 'utf-8').trim();
|
|
31
|
+
const match = content.match(/^gitdir:\s*(.+)$/m);
|
|
32
|
+
if (!match || !match[1])
|
|
33
|
+
return null;
|
|
34
|
+
// worktreeGitDir = /main/.git/worktrees/name
|
|
35
|
+
const worktreeGitDir = path.resolve(worktreeDir, match[1].trim());
|
|
36
|
+
// mainGitDir = /main/.git (up 2 from worktreeGitDir)
|
|
37
|
+
const mainGitDir = path.resolve(worktreeGitDir, '..', '..');
|
|
38
|
+
// mainCheckout = /main (dirname of mainGitDir)
|
|
39
|
+
const mainCheckout = path.dirname(mainGitDir);
|
|
40
|
+
// Verify the derived main checkout is a real git repo
|
|
41
|
+
if (!fs.existsSync(mainGitDir) || !fs.statSync(mainGitDir).isDirectory()) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return mainCheckout;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
17
50
|
/**
|
|
18
51
|
* Walk up the directory tree from `startDir` looking for a `.squad/` directory.
|
|
19
52
|
*
|
|
20
|
-
* Stops at the repository root (the directory containing `.git`).
|
|
53
|
+
* Stops at the repository root (the directory containing `.git` as a directory).
|
|
54
|
+
* When `.git` is a **file** (git worktree), falls back to the main checkout strategy:
|
|
55
|
+
* reads the `gitdir:` pointer, resolves the main checkout path, and checks there.
|
|
21
56
|
* Returns the **absolute path** to the `.squad/` directory, or `null` if none is found.
|
|
22
57
|
*
|
|
23
|
-
*
|
|
58
|
+
* Resolution order (worktree-local strategy first, main-checkout strategy second):
|
|
59
|
+
* 1. Walk up from `startDir` checking for `.squad/` — stops at `.git` directory boundary
|
|
60
|
+
* 2. If `.git` is a file (worktree), check the main checkout for `.squad/`
|
|
24
61
|
*
|
|
25
62
|
* @param startDir - Directory to start searching from. Defaults to `process.cwd()`.
|
|
26
63
|
* @returns Absolute path to `.squad/` or `null`.
|
|
@@ -33,10 +70,21 @@ export function resolveSquad(startDir) {
|
|
|
33
70
|
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
34
71
|
return candidate;
|
|
35
72
|
}
|
|
36
|
-
// Stop if we hit a .git boundary (directory or worktree file)
|
|
37
73
|
const gitMarker = path.join(current, '.git');
|
|
38
74
|
if (fs.existsSync(gitMarker)) {
|
|
39
|
-
|
|
75
|
+
if (fs.statSync(gitMarker).isDirectory()) {
|
|
76
|
+
// Real repo root — stop walking, no .squad/ found in this checkout
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
// .git is a file — this is a git worktree
|
|
80
|
+
// Worktree-local .squad/ was already checked above; fall back to main checkout
|
|
81
|
+
const mainCheckout = getMainWorktreePath(current, gitMarker);
|
|
82
|
+
if (mainCheckout) {
|
|
83
|
+
const mainCandidate = path.join(mainCheckout, '.squad');
|
|
84
|
+
if (fs.existsSync(mainCandidate) && fs.statSync(mainCandidate).isDirectory()) {
|
|
85
|
+
return mainCandidate;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
40
88
|
return null;
|
|
41
89
|
}
|
|
42
90
|
const parent = path.dirname(current);
|
|
@@ -56,7 +104,10 @@ const SQUAD_DIR_NAMES = ['.squad', '.ai-team'];
|
|
|
56
104
|
* Find the squad directory by walking up from `startDir`, checking both
|
|
57
105
|
* `.squad/` and `.ai-team/` (legacy fallback).
|
|
58
106
|
*
|
|
59
|
-
*
|
|
107
|
+
* Worktree-aware: when `.git` is a file (worktree pointer), falls back to
|
|
108
|
+
* checking the main checkout for either squad directory name.
|
|
109
|
+
*
|
|
110
|
+
* Returns the absolute path and the directory name used.
|
|
60
111
|
*/
|
|
61
112
|
function findSquadDir(startDir) {
|
|
62
113
|
let current = path.resolve(startDir);
|
|
@@ -68,9 +119,22 @@ function findSquadDir(startDir) {
|
|
|
68
119
|
return { dir: candidate, name };
|
|
69
120
|
}
|
|
70
121
|
}
|
|
71
|
-
// Stop if we hit a .git boundary
|
|
72
122
|
const gitMarker = path.join(current, '.git');
|
|
73
123
|
if (fs.existsSync(gitMarker)) {
|
|
124
|
+
if (fs.statSync(gitMarker).isDirectory()) {
|
|
125
|
+
// Real repo root — stop, no squad dir found in this checkout
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
// .git is a file — this is a git worktree; fall back to main checkout
|
|
129
|
+
const mainCheckout = getMainWorktreePath(current, gitMarker);
|
|
130
|
+
if (mainCheckout) {
|
|
131
|
+
for (const name of SQUAD_DIR_NAMES) {
|
|
132
|
+
const candidate = path.join(mainCheckout, name);
|
|
133
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
134
|
+
return { dir: candidate, name };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
74
138
|
return null;
|
|
75
139
|
}
|
|
76
140
|
const parent = path.dirname(current);
|
|
@@ -143,6 +207,7 @@ export function resolveSquadPaths(startDir) {
|
|
|
143
207
|
mode: 'remote',
|
|
144
208
|
projectDir,
|
|
145
209
|
teamDir,
|
|
210
|
+
personalDir: resolvePersonalSquadDir(),
|
|
146
211
|
config,
|
|
147
212
|
name,
|
|
148
213
|
isLegacy,
|
|
@@ -153,6 +218,7 @@ export function resolveSquadPaths(startDir) {
|
|
|
153
218
|
mode: 'local',
|
|
154
219
|
projectDir,
|
|
155
220
|
teamDir: projectDir,
|
|
221
|
+
personalDir: resolvePersonalSquadDir(),
|
|
156
222
|
config,
|
|
157
223
|
name,
|
|
158
224
|
isLegacy,
|
|
@@ -193,6 +259,24 @@ export function resolveGlobalSquadPath() {
|
|
|
193
259
|
}
|
|
194
260
|
return globalDir;
|
|
195
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Resolves the user's personal squad directory.
|
|
264
|
+
* Returns null if SQUAD_NO_PERSONAL is set or directory doesn't exist.
|
|
265
|
+
*
|
|
266
|
+
* Platform paths:
|
|
267
|
+
* - Windows: %APPDATA%/squad/personal-squad
|
|
268
|
+
* - macOS: ~/Library/Application Support/squad/personal-squad
|
|
269
|
+
* - Linux: $XDG_CONFIG_HOME/squad/personal-squad or ~/.config/squad/personal-squad
|
|
270
|
+
*/
|
|
271
|
+
export function resolvePersonalSquadDir() {
|
|
272
|
+
if (process.env['SQUAD_NO_PERSONAL'])
|
|
273
|
+
return null;
|
|
274
|
+
const globalDir = resolveGlobalSquadPath();
|
|
275
|
+
const personalDir = path.join(globalDir, 'personal-squad');
|
|
276
|
+
if (!fs.existsSync(personalDir))
|
|
277
|
+
return null;
|
|
278
|
+
return personalDir;
|
|
279
|
+
}
|
|
196
280
|
/**
|
|
197
281
|
* Validate that a file path is within `.squad/` or the system temp directory.
|
|
198
282
|
*
|
|
@@ -249,6 +333,22 @@ export function ensureSquadPathDual(filePath, projectDir, teamDir) {
|
|
|
249
333
|
throw new Error(`Path "${resolved}" is outside both squad roots ("${resolvedProject}", "${resolvedTeam}"). ` +
|
|
250
334
|
'All squad scratch/temp/state files must be written inside a squad directory or the system temp directory.');
|
|
251
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Validates a file path is inside one of three allowed directories:
|
|
338
|
+
* projectDir, teamDir, personalDir, or system temp.
|
|
339
|
+
* Extends ensureSquadPathDual() for triple-root (project + team + personal).
|
|
340
|
+
*/
|
|
341
|
+
export function ensureSquadPathTriple(filePath, projectDir, teamDir, personalDir) {
|
|
342
|
+
const resolved = path.resolve(filePath);
|
|
343
|
+
const tmpDir = os.tmpdir();
|
|
344
|
+
const allowed = [projectDir, teamDir, personalDir, tmpDir].filter(Boolean);
|
|
345
|
+
for (const dir of allowed) {
|
|
346
|
+
if (resolved.startsWith(path.resolve(dir) + path.sep) || resolved === path.resolve(dir)) {
|
|
347
|
+
return resolved;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
throw new Error(`Path "${resolved}" is outside all allowed directories: ${allowed.join(', ')}`);
|
|
351
|
+
}
|
|
252
352
|
/**
|
|
253
353
|
* ensureSquadPath that works with resolved dual-root paths.
|
|
254
354
|
* Convenience wrapper around ensureSquadPathDual.
|
package/dist/resolution.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../src/resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../src/resolution.ts"],"names":[],"mappings":"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"}
|