@agent-relay/policy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Agent Policy Service
3
+ *
4
+ * Manages agent permissions and rules with multi-level fallback:
5
+ * 1. Repo-level policy (.claude/agents/*.md)
6
+ * 2. Workspace-level policy (from cloud API)
7
+ * 3. Built-in safe defaults
8
+ *
9
+ * Provides spawn authorization, tool permission checks, and audit logging.
10
+ */
11
+ /**
12
+ * PRPM-style policy file format (YAML or JSON)
13
+ *
14
+ * Policy files are loaded from (in order of precedence):
15
+ * 1. User-level: ~/.config/agent-relay/policies/*.yaml (NOT in source control)
16
+ * 2. Cloud: Workspace config from dashboard (stored in database)
17
+ *
18
+ * PRPM packages install to the user-level location to avoid polluting repos.
19
+ * Install via: prpm install @org/strict-agent-rules --global
20
+ *
21
+ * Example policy file (~/.config/agent-relay/policies/strict-rules.yaml):
22
+ * ```yaml
23
+ * name: strict-spawn-rules
24
+ * version: 1.0.0
25
+ * description: Restrict agent spawning to leads only
26
+ *
27
+ * agents:
28
+ * - name: Lead
29
+ * canSpawn: ["*"]
30
+ * canMessage: ["*"]
31
+ * - name: Worker*
32
+ * canSpawn: []
33
+ * canMessage: ["Lead", "Coordinator"]
34
+ *
35
+ * settings:
36
+ * requireExplicitAgents: false
37
+ * auditEnabled: true
38
+ * ```
39
+ */
40
+ /**
41
+ * Agent policy definition
42
+ */
43
+ export interface AgentPolicy {
44
+ /** Agent name pattern (supports wildcards: "Lead", "Worker*", "*") */
45
+ name: string;
46
+ /** Allowed tools (empty = all allowed, ["none"] = no tools) */
47
+ allowedTools?: string[];
48
+ /** Agents this agent can spawn (empty = can spawn any) */
49
+ canSpawn?: string[];
50
+ /** Agents this agent can message (empty = can message any) */
51
+ canMessage?: string[];
52
+ /** Maximum concurrent spawns allowed */
53
+ maxSpawns?: number;
54
+ /** Rate limit: messages per minute */
55
+ rateLimit?: number;
56
+ /** Whether this agent can be spawned by others */
57
+ canBeSpawned?: boolean;
58
+ /** Custom metadata */
59
+ metadata?: Record<string, unknown>;
60
+ }
61
+ /**
62
+ * Workspace-level policy configuration
63
+ */
64
+ export interface WorkspacePolicy {
65
+ /** Default policy for agents without explicit config */
66
+ defaultPolicy: AgentPolicy;
67
+ /** Named agent policies */
68
+ agents: AgentPolicy[];
69
+ /** Global settings */
70
+ settings: {
71
+ /** Require explicit agent definitions (reject unknown agents) */
72
+ requireExplicitAgents: boolean;
73
+ /** Enable audit logging */
74
+ auditEnabled: boolean;
75
+ /** Maximum total agents */
76
+ maxTotalAgents: number;
77
+ };
78
+ }
79
+ /**
80
+ * Policy decision with reasoning
81
+ */
82
+ export interface PolicyDecision {
83
+ allowed: boolean;
84
+ reason: string;
85
+ policySource: 'repo' | 'local' | 'workspace' | 'default';
86
+ matchedPolicy?: AgentPolicy;
87
+ }
88
+ /**
89
+ * Audit log entry
90
+ */
91
+ export interface AuditEntry {
92
+ timestamp: number;
93
+ action: 'spawn' | 'message' | 'tool' | 'release';
94
+ actor: string;
95
+ target?: string;
96
+ decision: PolicyDecision;
97
+ context?: Record<string, unknown>;
98
+ }
99
+ /**
100
+ * Cloud policy fetcher interface
101
+ * Implement this to fetch workspace policies from cloud API
102
+ */
103
+ export interface CloudPolicyFetcher {
104
+ getWorkspacePolicy(workspaceId: string): Promise<WorkspacePolicy | null>;
105
+ }
106
+ export declare class AgentPolicyService {
107
+ private projectRoot;
108
+ private workspaceId?;
109
+ private cloudFetcher?;
110
+ private cachedWorkspacePolicy?;
111
+ private cachedLocalPolicy?;
112
+ private policyCacheExpiry;
113
+ private localPolicyCacheExpiry;
114
+ private auditLog;
115
+ private strictMode;
116
+ /** Cache TTL in milliseconds (5 minutes) */
117
+ private static readonly CACHE_TTL_MS;
118
+ /** Local policy cache TTL (1 minute - files can change) */
119
+ private static readonly LOCAL_CACHE_TTL_MS;
120
+ /** Maximum audit log entries to keep in memory */
121
+ private static readonly MAX_AUDIT_ENTRIES;
122
+ constructor(options: {
123
+ projectRoot: string;
124
+ workspaceId?: string;
125
+ cloudFetcher?: CloudPolicyFetcher;
126
+ strictMode?: boolean;
127
+ });
128
+ /**
129
+ * Get the user-level policies directory
130
+ * Uses ~/.config/agent-relay/policies/ (not in source control)
131
+ */
132
+ private getUserPoliciesDir;
133
+ /**
134
+ * Load policies from user-level directory (PRPM-installable)
135
+ * Files are YAML/JSON with agent policy definitions
136
+ * Location: ~/.config/agent-relay/policies/*.yaml
137
+ */
138
+ private loadLocalPolicies;
139
+ /**
140
+ * Simple YAML parser for policy files
141
+ * Handles basic key: value and arrays
142
+ */
143
+ private parseSimpleYaml;
144
+ /**
145
+ * Parse a YAML value string
146
+ */
147
+ private parseValue;
148
+ /**
149
+ * Check if an agent can spawn another agent
150
+ */
151
+ canSpawn(spawnerName: string, targetName: string, targetCli: string): Promise<PolicyDecision>;
152
+ /**
153
+ * Check if an agent can send a message to another agent
154
+ */
155
+ canMessage(senderName: string, recipientName: string): Promise<PolicyDecision>;
156
+ /**
157
+ * Check if an agent can use a specific tool
158
+ */
159
+ canUseTool(agentName: string, toolName: string): Promise<PolicyDecision>;
160
+ /**
161
+ * Get the effective policy for an agent
162
+ * Fallback chain: repo config → user PRPM policies → cloud workspace → defaults
163
+ */
164
+ getAgentPolicy(agentName: string): Promise<{
165
+ matchedPolicy: AgentPolicy;
166
+ policySource: 'repo' | 'local' | 'workspace' | 'default';
167
+ }>;
168
+ /**
169
+ * Get workspace policy from cloud (with caching)
170
+ */
171
+ private getWorkspacePolicy;
172
+ /**
173
+ * Find matching policy from a list (supports wildcards)
174
+ */
175
+ private findMatchingPolicy;
176
+ /**
177
+ * Check if a name matches any pattern in the list
178
+ * Supports: exact match, prefix* match, *suffix match, * (all)
179
+ */
180
+ private matchesPattern;
181
+ /**
182
+ * Convert AgentConfig to AgentPolicy
183
+ */
184
+ private configToPolicy;
185
+ /**
186
+ * Record an audit entry
187
+ */
188
+ private audit;
189
+ /**
190
+ * Get audit log entries
191
+ */
192
+ getAuditLog(options?: {
193
+ limit?: number;
194
+ action?: AuditEntry['action'];
195
+ actor?: string;
196
+ deniedOnly?: boolean;
197
+ }): AuditEntry[];
198
+ /**
199
+ * Clear audit log
200
+ */
201
+ clearAuditLog(): void;
202
+ /**
203
+ * Invalidate cached workspace policy
204
+ */
205
+ invalidateCache(): void;
206
+ /**
207
+ * Get a human-readable policy summary for an agent
208
+ * This can be injected into agent prompts to inform them of their permissions
209
+ */
210
+ getPolicySummary(agentName: string): Promise<string>;
211
+ /**
212
+ * Get a concise policy instruction for injection into agent prompts
213
+ */
214
+ getPolicyInstruction(agentName: string): Promise<string | null>;
215
+ }
216
+ /**
217
+ * Create a policy service for a project
218
+ */
219
+ export declare function createPolicyService(options: {
220
+ projectRoot: string;
221
+ workspaceId?: string;
222
+ cloudFetcher?: CloudPolicyFetcher;
223
+ strictMode?: boolean;
224
+ }): AgentPolicyService;
225
+ //# sourceMappingURL=agent-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-policy.d.ts","sourceRoot":"","sources":["../src/agent-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,665 @@
1
+ /**
2
+ * Agent Policy Service
3
+ *
4
+ * Manages agent permissions and rules with multi-level fallback:
5
+ * 1. Repo-level policy (.claude/agents/*.md)
6
+ * 2. Workspace-level policy (from cloud API)
7
+ * 3. Built-in safe defaults
8
+ *
9
+ * Provides spawn authorization, tool permission checks, and audit logging.
10
+ */
11
+ import fs from 'node:fs';
12
+ import path from 'node:path';
13
+ import { findAgentConfig } from '@agent-relay/config/agent-config';
14
+ import os from 'node:os';
15
+ /** Built-in safe defaults when no policy exists */
16
+ const DEFAULT_POLICY = {
17
+ name: '*',
18
+ allowedTools: undefined, // All tools allowed by default
19
+ canSpawn: undefined, // Can spawn any agent
20
+ canMessage: undefined, // Can message any agent
21
+ maxSpawns: 10,
22
+ rateLimit: 60, // 60 messages per minute
23
+ canBeSpawned: true,
24
+ };
25
+ /** Restrictive defaults for unknown agents in strict mode */
26
+ const STRICT_DEFAULT_POLICY = {
27
+ name: '*',
28
+ allowedTools: ['Read', 'Grep', 'Glob'], // Read-only by default
29
+ canSpawn: [], // Cannot spawn
30
+ canMessage: ['Lead', 'Coordinator'], // Can only message leads
31
+ maxSpawns: 0,
32
+ rateLimit: 10,
33
+ canBeSpawned: false,
34
+ };
35
+ export class AgentPolicyService {
36
+ projectRoot;
37
+ workspaceId;
38
+ cloudFetcher;
39
+ cachedWorkspacePolicy;
40
+ cachedLocalPolicy;
41
+ policyCacheExpiry = 0;
42
+ localPolicyCacheExpiry = 0;
43
+ auditLog = [];
44
+ strictMode;
45
+ /** Cache TTL in milliseconds (5 minutes) */
46
+ static CACHE_TTL_MS = 5 * 60 * 1000;
47
+ /** Local policy cache TTL (1 minute - files can change) */
48
+ static LOCAL_CACHE_TTL_MS = 60 * 1000;
49
+ /** Maximum audit log entries to keep in memory */
50
+ static MAX_AUDIT_ENTRIES = 1000;
51
+ constructor(options) {
52
+ this.projectRoot = options.projectRoot;
53
+ this.workspaceId = options.workspaceId;
54
+ this.cloudFetcher = options.cloudFetcher;
55
+ this.strictMode = options.strictMode ?? false;
56
+ }
57
+ /**
58
+ * Get the user-level policies directory
59
+ * Uses ~/.config/agent-relay/policies/ (not in source control)
60
+ */
61
+ getUserPoliciesDir() {
62
+ const configDir = process.env.AGENT_RELAY_CONFIG_DIR ??
63
+ path.join(os.homedir(), '.config', 'agent-relay');
64
+ return path.join(configDir, 'policies');
65
+ }
66
+ /**
67
+ * Load policies from user-level directory (PRPM-installable)
68
+ * Files are YAML/JSON with agent policy definitions
69
+ * Location: ~/.config/agent-relay/policies/*.yaml
70
+ */
71
+ loadLocalPolicies() {
72
+ // Check cache
73
+ if (this.cachedLocalPolicy && Date.now() < this.localPolicyCacheExpiry) {
74
+ return this.cachedLocalPolicy;
75
+ }
76
+ const policiesDir = this.getUserPoliciesDir();
77
+ if (!fs.existsSync(policiesDir)) {
78
+ return null;
79
+ }
80
+ try {
81
+ const files = fs.readdirSync(policiesDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml') || f.endsWith('.json'));
82
+ if (files.length === 0) {
83
+ return null;
84
+ }
85
+ // Merge all policy files
86
+ const mergedAgents = [];
87
+ let mergedSettings = {
88
+ requireExplicitAgents: false,
89
+ auditEnabled: true,
90
+ maxTotalAgents: 50,
91
+ };
92
+ let mergedDefault = { ...DEFAULT_POLICY };
93
+ for (const file of files) {
94
+ const filePath = path.join(policiesDir, file);
95
+ const content = fs.readFileSync(filePath, 'utf-8');
96
+ let parsed;
97
+ if (file.endsWith('.json')) {
98
+ parsed = JSON.parse(content);
99
+ }
100
+ else {
101
+ // Simple YAML parsing for policy files
102
+ parsed = this.parseSimpleYaml(content);
103
+ }
104
+ // Merge agents
105
+ if (Array.isArray(parsed.agents)) {
106
+ for (const agent of parsed.agents) {
107
+ if (agent && typeof agent === 'object' && 'name' in agent) {
108
+ mergedAgents.push(agent);
109
+ }
110
+ }
111
+ }
112
+ // Merge settings (later files override)
113
+ if (parsed.settings && typeof parsed.settings === 'object') {
114
+ mergedSettings = { ...mergedSettings, ...parsed.settings };
115
+ }
116
+ // Merge default policy
117
+ if (parsed.defaultPolicy && typeof parsed.defaultPolicy === 'object') {
118
+ mergedDefault = { ...mergedDefault, ...parsed.defaultPolicy };
119
+ }
120
+ }
121
+ const policy = {
122
+ defaultPolicy: mergedDefault,
123
+ agents: mergedAgents,
124
+ settings: mergedSettings,
125
+ };
126
+ this.cachedLocalPolicy = policy;
127
+ this.localPolicyCacheExpiry = Date.now() + AgentPolicyService.LOCAL_CACHE_TTL_MS;
128
+ return policy;
129
+ }
130
+ catch (err) {
131
+ console.error('[policy] Failed to load local policies:', err);
132
+ return null;
133
+ }
134
+ }
135
+ /**
136
+ * Simple YAML parser for policy files
137
+ * Handles basic key: value and arrays
138
+ */
139
+ parseSimpleYaml(content) {
140
+ const result = {};
141
+ const lines = content.split('\n');
142
+ let _currentKey = '';
143
+ let currentArray = null;
144
+ let currentObject = null;
145
+ let indent = 0;
146
+ for (const line of lines) {
147
+ const trimmed = line.trim();
148
+ // Skip comments and empty lines
149
+ if (!trimmed || trimmed.startsWith('#'))
150
+ continue;
151
+ // Calculate indentation
152
+ const lineIndent = line.length - line.trimStart().length;
153
+ // Array item
154
+ if (trimmed.startsWith('- ')) {
155
+ const value = trimmed.slice(2).trim();
156
+ // Object in array (e.g., "- name: Worker")
157
+ if (value.includes(':')) {
158
+ const [key, val] = value.split(':').map(s => s.trim());
159
+ currentObject = { [key]: this.parseValue(val) };
160
+ if (currentArray) {
161
+ currentArray.push(currentObject);
162
+ }
163
+ }
164
+ else {
165
+ // Simple array value
166
+ if (currentArray) {
167
+ currentArray.push(this.parseValue(value));
168
+ }
169
+ }
170
+ continue;
171
+ }
172
+ // Key: value pair
173
+ const colonIdx = trimmed.indexOf(':');
174
+ if (colonIdx > 0) {
175
+ const key = trimmed.slice(0, colonIdx).trim();
176
+ const value = trimmed.slice(colonIdx + 1).trim();
177
+ // If we're inside an object in an array
178
+ if (currentObject && lineIndent > indent) {
179
+ currentObject[key] = this.parseValue(value);
180
+ continue;
181
+ }
182
+ // Top-level or section key
183
+ if (value === '' || value === '|' || value === '>') {
184
+ // Start of array or nested object
185
+ _currentKey = key;
186
+ currentArray = [];
187
+ currentObject = null;
188
+ indent = lineIndent;
189
+ result[key] = currentArray;
190
+ }
191
+ else {
192
+ // Simple key: value
193
+ if (lineIndent === 0) {
194
+ result[key] = this.parseValue(value);
195
+ _currentKey = '';
196
+ currentArray = null;
197
+ currentObject = null;
198
+ }
199
+ else if (currentObject) {
200
+ currentObject[key] = this.parseValue(value);
201
+ }
202
+ }
203
+ }
204
+ }
205
+ return result;
206
+ }
207
+ /**
208
+ * Parse a YAML value string
209
+ */
210
+ parseValue(value) {
211
+ if (!value || value === '~' || value === 'null')
212
+ return null;
213
+ if (value === 'true')
214
+ return true;
215
+ if (value === 'false')
216
+ return false;
217
+ // Array notation [a, b, c]
218
+ if (value.startsWith('[') && value.endsWith(']')) {
219
+ const inner = value.slice(1, -1);
220
+ if (!inner.trim())
221
+ return [];
222
+ return inner.split(',').map(s => {
223
+ const trimmed = s.trim().replace(/^["']|["']$/g, '');
224
+ return trimmed;
225
+ });
226
+ }
227
+ // Number
228
+ if (/^-?\d+(\.\d+)?$/.test(value)) {
229
+ return parseFloat(value);
230
+ }
231
+ // String (remove quotes if present)
232
+ return value.replace(/^["']|["']$/g, '');
233
+ }
234
+ /**
235
+ * Check if an agent can spawn another agent
236
+ */
237
+ async canSpawn(spawnerName, targetName, targetCli) {
238
+ const spawnerPolicy = await this.getAgentPolicy(spawnerName);
239
+ const targetPolicy = await this.getAgentPolicy(targetName);
240
+ // Check if target can be spawned
241
+ if (targetPolicy.matchedPolicy?.canBeSpawned === false) {
242
+ const decision = {
243
+ allowed: false,
244
+ reason: `Agent "${targetName}" is not allowed to be spawned`,
245
+ policySource: targetPolicy.policySource,
246
+ matchedPolicy: targetPolicy.matchedPolicy,
247
+ };
248
+ this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
249
+ return decision;
250
+ }
251
+ // Check if spawner can spawn
252
+ const canSpawnList = spawnerPolicy.matchedPolicy?.canSpawn;
253
+ if (canSpawnList !== undefined && canSpawnList.length > 0) {
254
+ const canSpawn = this.matchesPattern(targetName, canSpawnList);
255
+ if (!canSpawn) {
256
+ const decision = {
257
+ allowed: false,
258
+ reason: `Agent "${spawnerName}" is not allowed to spawn "${targetName}"`,
259
+ policySource: spawnerPolicy.policySource,
260
+ matchedPolicy: spawnerPolicy.matchedPolicy,
261
+ };
262
+ this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
263
+ return decision;
264
+ }
265
+ }
266
+ // Check max spawns (would need spawn count tracking - placeholder)
267
+ const decision = {
268
+ allowed: true,
269
+ reason: 'Spawn permitted by policy',
270
+ policySource: spawnerPolicy.policySource,
271
+ matchedPolicy: spawnerPolicy.matchedPolicy,
272
+ };
273
+ this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
274
+ return decision;
275
+ }
276
+ /**
277
+ * Check if an agent can send a message to another agent
278
+ */
279
+ async canMessage(senderName, recipientName) {
280
+ const senderPolicy = await this.getAgentPolicy(senderName);
281
+ const canMessageList = senderPolicy.matchedPolicy?.canMessage;
282
+ if (canMessageList !== undefined && canMessageList.length > 0) {
283
+ const canMessage = this.matchesPattern(recipientName, canMessageList);
284
+ if (!canMessage) {
285
+ const decision = {
286
+ allowed: false,
287
+ reason: `Agent "${senderName}" is not allowed to message "${recipientName}"`,
288
+ policySource: senderPolicy.policySource,
289
+ matchedPolicy: senderPolicy.matchedPolicy,
290
+ };
291
+ this.audit('message', senderName, recipientName, decision);
292
+ return decision;
293
+ }
294
+ }
295
+ const decision = {
296
+ allowed: true,
297
+ reason: 'Message permitted by policy',
298
+ policySource: senderPolicy.policySource,
299
+ matchedPolicy: senderPolicy.matchedPolicy,
300
+ };
301
+ this.audit('message', senderName, recipientName, decision);
302
+ return decision;
303
+ }
304
+ /**
305
+ * Check if an agent can use a specific tool
306
+ */
307
+ async canUseTool(agentName, toolName) {
308
+ const policy = await this.getAgentPolicy(agentName);
309
+ const allowedTools = policy.matchedPolicy?.allowedTools;
310
+ if (allowedTools !== undefined) {
311
+ // ["none"] means no tools allowed
312
+ if (allowedTools.length === 1 && allowedTools[0] === 'none') {
313
+ const decision = {
314
+ allowed: false,
315
+ reason: `Agent "${agentName}" is not allowed to use any tools`,
316
+ policySource: policy.policySource,
317
+ matchedPolicy: policy.matchedPolicy,
318
+ };
319
+ this.audit('tool', agentName, toolName, decision);
320
+ return decision;
321
+ }
322
+ // Check if tool is in allowed list
323
+ const allowed = this.matchesPattern(toolName, allowedTools);
324
+ if (!allowed) {
325
+ const decision = {
326
+ allowed: false,
327
+ reason: `Agent "${agentName}" is not allowed to use tool "${toolName}"`,
328
+ policySource: policy.policySource,
329
+ matchedPolicy: policy.matchedPolicy,
330
+ };
331
+ this.audit('tool', agentName, toolName, decision);
332
+ return decision;
333
+ }
334
+ }
335
+ const decision = {
336
+ allowed: true,
337
+ reason: 'Tool usage permitted by policy',
338
+ policySource: policy.policySource,
339
+ matchedPolicy: policy.matchedPolicy,
340
+ };
341
+ this.audit('tool', agentName, toolName, decision);
342
+ return decision;
343
+ }
344
+ /**
345
+ * Get the effective policy for an agent
346
+ * Fallback chain: repo config → user PRPM policies → cloud workspace → defaults
347
+ */
348
+ async getAgentPolicy(agentName) {
349
+ // 1. Try repo-level config (.claude/agents/*.md)
350
+ const repoConfig = findAgentConfig(agentName, this.projectRoot);
351
+ if (repoConfig) {
352
+ return {
353
+ matchedPolicy: this.configToPolicy(repoConfig),
354
+ policySource: 'repo',
355
+ };
356
+ }
357
+ // 2. Try user-level PRPM policies (~/.config/agent-relay/policies/*.yaml)
358
+ const localPolicy = this.loadLocalPolicies();
359
+ if (localPolicy) {
360
+ // Check for strict mode in local policy
361
+ if (localPolicy.settings?.requireExplicitAgents) {
362
+ const matchedPolicy = this.findMatchingPolicy(agentName, localPolicy.agents);
363
+ if (matchedPolicy) {
364
+ return { matchedPolicy, policySource: 'local' };
365
+ }
366
+ // Unknown agent in strict mode
367
+ return {
368
+ matchedPolicy: { ...STRICT_DEFAULT_POLICY, name: agentName },
369
+ policySource: 'local',
370
+ };
371
+ }
372
+ // Find matching policy
373
+ const matchedPolicy = this.findMatchingPolicy(agentName, localPolicy.agents);
374
+ if (matchedPolicy) {
375
+ return { matchedPolicy, policySource: 'local' };
376
+ }
377
+ // Use local default
378
+ if (localPolicy.defaultPolicy) {
379
+ return {
380
+ matchedPolicy: { ...localPolicy.defaultPolicy, name: agentName },
381
+ policySource: 'local',
382
+ };
383
+ }
384
+ }
385
+ // 3. Try workspace-level policy from cloud
386
+ const workspacePolicy = await this.getWorkspacePolicy();
387
+ if (workspacePolicy) {
388
+ // Check for strict mode
389
+ if (workspacePolicy.settings?.requireExplicitAgents) {
390
+ // In strict mode, unknown agents get restrictive defaults
391
+ const matchedPolicy = this.findMatchingPolicy(agentName, workspacePolicy.agents);
392
+ if (matchedPolicy) {
393
+ return { matchedPolicy, policySource: 'workspace' };
394
+ }
395
+ // Unknown agent in strict mode
396
+ return {
397
+ matchedPolicy: { ...STRICT_DEFAULT_POLICY, name: agentName },
398
+ policySource: 'workspace',
399
+ };
400
+ }
401
+ // Find matching policy
402
+ const matchedPolicy = this.findMatchingPolicy(agentName, workspacePolicy.agents);
403
+ if (matchedPolicy) {
404
+ return { matchedPolicy, policySource: 'workspace' };
405
+ }
406
+ // Use workspace default
407
+ if (workspacePolicy.defaultPolicy) {
408
+ return {
409
+ matchedPolicy: { ...workspacePolicy.defaultPolicy, name: agentName },
410
+ policySource: 'workspace',
411
+ };
412
+ }
413
+ }
414
+ // 4. Fall back to built-in defaults
415
+ const defaultPolicy = this.strictMode ? STRICT_DEFAULT_POLICY : DEFAULT_POLICY;
416
+ return {
417
+ matchedPolicy: { ...defaultPolicy, name: agentName },
418
+ policySource: 'default',
419
+ };
420
+ }
421
+ /**
422
+ * Get workspace policy from cloud (with caching)
423
+ */
424
+ async getWorkspacePolicy() {
425
+ if (!this.workspaceId || !this.cloudFetcher) {
426
+ return null;
427
+ }
428
+ // Check cache
429
+ if (this.cachedWorkspacePolicy && Date.now() < this.policyCacheExpiry) {
430
+ return this.cachedWorkspacePolicy;
431
+ }
432
+ try {
433
+ const policy = await this.cloudFetcher.getWorkspacePolicy(this.workspaceId);
434
+ if (policy) {
435
+ this.cachedWorkspacePolicy = policy;
436
+ this.policyCacheExpiry = Date.now() + AgentPolicyService.CACHE_TTL_MS;
437
+ }
438
+ return policy;
439
+ }
440
+ catch (err) {
441
+ console.error('[policy] Failed to fetch workspace policy:', err);
442
+ // Return cached policy if available, even if expired
443
+ return this.cachedWorkspacePolicy ?? null;
444
+ }
445
+ }
446
+ /**
447
+ * Find matching policy from a list (supports wildcards)
448
+ */
449
+ findMatchingPolicy(agentName, policies) {
450
+ // First try exact match
451
+ const exactMatch = policies.find(p => p.name.toLowerCase() === agentName.toLowerCase());
452
+ if (exactMatch)
453
+ return exactMatch;
454
+ // Then try pattern match
455
+ for (const policy of policies) {
456
+ if (this.matchesPattern(agentName, [policy.name])) {
457
+ return policy;
458
+ }
459
+ }
460
+ return null;
461
+ }
462
+ /**
463
+ * Check if a name matches any pattern in the list
464
+ * Supports: exact match, prefix* match, *suffix match, * (all)
465
+ */
466
+ matchesPattern(name, patterns) {
467
+ const lowerName = name.toLowerCase();
468
+ for (const pattern of patterns) {
469
+ const lowerPattern = pattern.toLowerCase();
470
+ // Wildcard all
471
+ if (lowerPattern === '*')
472
+ return true;
473
+ // Exact match
474
+ if (lowerPattern === lowerName)
475
+ return true;
476
+ // Prefix match (e.g., "Worker*" matches "WorkerA")
477
+ if (lowerPattern.endsWith('*')) {
478
+ const prefix = lowerPattern.slice(0, -1);
479
+ if (lowerName.startsWith(prefix))
480
+ return true;
481
+ }
482
+ // Suffix match (e.g., "*Lead" matches "TeamLead")
483
+ if (lowerPattern.startsWith('*')) {
484
+ const suffix = lowerPattern.slice(1);
485
+ if (lowerName.endsWith(suffix))
486
+ return true;
487
+ }
488
+ }
489
+ return false;
490
+ }
491
+ /**
492
+ * Convert AgentConfig to AgentPolicy
493
+ */
494
+ configToPolicy(config) {
495
+ return {
496
+ name: config.name,
497
+ allowedTools: config.allowedTools,
498
+ // Other fields come from defaults since repo config doesn't specify them
499
+ canSpawn: undefined,
500
+ canMessage: undefined,
501
+ maxSpawns: 10,
502
+ rateLimit: 60,
503
+ canBeSpawned: true,
504
+ };
505
+ }
506
+ /**
507
+ * Record an audit entry
508
+ */
509
+ audit(action, actor, target, decision, context) {
510
+ const entry = {
511
+ timestamp: Date.now(),
512
+ action,
513
+ actor,
514
+ target,
515
+ decision,
516
+ context,
517
+ };
518
+ this.auditLog.push(entry);
519
+ // Trim log if too large
520
+ if (this.auditLog.length > AgentPolicyService.MAX_AUDIT_ENTRIES) {
521
+ this.auditLog = this.auditLog.slice(-AgentPolicyService.MAX_AUDIT_ENTRIES / 2);
522
+ }
523
+ // Log denied actions
524
+ if (!decision.allowed) {
525
+ console.warn(`[policy] DENIED: ${action} by ${actor}${target ? ` -> ${target}` : ''}: ${decision.reason}`);
526
+ }
527
+ }
528
+ /**
529
+ * Get audit log entries
530
+ */
531
+ getAuditLog(options) {
532
+ let entries = [...this.auditLog];
533
+ if (options?.action) {
534
+ entries = entries.filter(e => e.action === options.action);
535
+ }
536
+ if (options?.actor) {
537
+ entries = entries.filter(e => e.actor === options.actor);
538
+ }
539
+ if (options?.deniedOnly) {
540
+ entries = entries.filter(e => !e.decision.allowed);
541
+ }
542
+ if (options?.limit) {
543
+ entries = entries.slice(-options.limit);
544
+ }
545
+ return entries;
546
+ }
547
+ /**
548
+ * Clear audit log
549
+ */
550
+ clearAuditLog() {
551
+ this.auditLog = [];
552
+ }
553
+ /**
554
+ * Invalidate cached workspace policy
555
+ */
556
+ invalidateCache() {
557
+ this.cachedWorkspacePolicy = undefined;
558
+ this.policyCacheExpiry = 0;
559
+ }
560
+ /**
561
+ * Get a human-readable policy summary for an agent
562
+ * This can be injected into agent prompts to inform them of their permissions
563
+ */
564
+ async getPolicySummary(agentName) {
565
+ const { matchedPolicy, policySource } = await this.getAgentPolicy(agentName);
566
+ const lines = [
567
+ `# Agent Policy for ${agentName}`,
568
+ `Source: ${policySource}`,
569
+ '',
570
+ ];
571
+ // Tools
572
+ if (matchedPolicy.allowedTools) {
573
+ if (matchedPolicy.allowedTools.length === 1 && matchedPolicy.allowedTools[0] === 'none') {
574
+ lines.push('**Tools**: No tools allowed');
575
+ }
576
+ else {
577
+ lines.push(`**Allowed Tools**: ${matchedPolicy.allowedTools.join(', ')}`);
578
+ }
579
+ }
580
+ else {
581
+ lines.push('**Tools**: All tools allowed');
582
+ }
583
+ // Spawning
584
+ if (matchedPolicy.canSpawn) {
585
+ if (matchedPolicy.canSpawn.length === 0) {
586
+ lines.push('**Spawning**: Cannot spawn other agents');
587
+ }
588
+ else {
589
+ lines.push(`**Can Spawn**: ${matchedPolicy.canSpawn.join(', ')}`);
590
+ }
591
+ }
592
+ else {
593
+ lines.push('**Spawning**: Can spawn any agent');
594
+ }
595
+ // Messaging
596
+ if (matchedPolicy.canMessage) {
597
+ if (matchedPolicy.canMessage.length === 0) {
598
+ lines.push('**Messaging**: Cannot message other agents');
599
+ }
600
+ else {
601
+ lines.push(`**Can Message**: ${matchedPolicy.canMessage.join(', ')}`);
602
+ }
603
+ }
604
+ else {
605
+ lines.push('**Messaging**: Can message any agent');
606
+ }
607
+ // Limits
608
+ if (matchedPolicy.maxSpawns !== undefined) {
609
+ lines.push(`**Max Spawns**: ${matchedPolicy.maxSpawns}`);
610
+ }
611
+ if (matchedPolicy.rateLimit !== undefined) {
612
+ lines.push(`**Rate Limit**: ${matchedPolicy.rateLimit} messages/min`);
613
+ }
614
+ return lines.join('\n');
615
+ }
616
+ /**
617
+ * Get a concise policy instruction for injection into agent prompts
618
+ */
619
+ async getPolicyInstruction(agentName) {
620
+ const { matchedPolicy, policySource: _policySource } = await this.getAgentPolicy(agentName);
621
+ // Only generate instructions if there are restrictions
622
+ const hasRestrictions = matchedPolicy.allowedTools !== undefined ||
623
+ matchedPolicy.canSpawn !== undefined ||
624
+ matchedPolicy.canMessage !== undefined;
625
+ if (!hasRestrictions) {
626
+ return null; // No restrictions, no need to inform agent
627
+ }
628
+ const restrictions = [];
629
+ if (matchedPolicy.allowedTools) {
630
+ if (matchedPolicy.allowedTools.length === 1 && matchedPolicy.allowedTools[0] === 'none') {
631
+ restrictions.push('You are not allowed to use any tools.');
632
+ }
633
+ else {
634
+ restrictions.push(`You may only use these tools: ${matchedPolicy.allowedTools.join(', ')}.`);
635
+ }
636
+ }
637
+ if (matchedPolicy.canSpawn) {
638
+ if (matchedPolicy.canSpawn.length === 0) {
639
+ restrictions.push('You are not allowed to spawn other agents.');
640
+ }
641
+ else {
642
+ restrictions.push(`You may only spawn these agents: ${matchedPolicy.canSpawn.join(', ')}.`);
643
+ }
644
+ }
645
+ if (matchedPolicy.canMessage) {
646
+ if (matchedPolicy.canMessage.length === 0) {
647
+ restrictions.push('You are not allowed to message other agents.');
648
+ }
649
+ else {
650
+ restrictions.push(`You may only message these agents: ${matchedPolicy.canMessage.join(', ')}.`);
651
+ }
652
+ }
653
+ if (restrictions.length === 0) {
654
+ return null;
655
+ }
656
+ return `[Policy Restrictions]\n${restrictions.join('\n')}`;
657
+ }
658
+ }
659
+ /**
660
+ * Create a policy service for a project
661
+ */
662
+ export function createPolicyService(options) {
663
+ return new AgentPolicyService(options);
664
+ }
665
+ //# sourceMappingURL=agent-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-policy.js","sourceRoot":"","sources":["../src/agent-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAoB,MAAM,kCAAkC,CAAC;AAErF,OAAO,EAAE,MAAM,SAAS,CAAC;AA+FzB,mDAAmD;AACnD,MAAM,cAAc,GAAgB;IAClC,IAAI,EAAE,GAAG;IACT,YAAY,EAAE,SAAS,EAAE,+BAA+B;IACxD,QAAQ,EAAE,SAAS,EAAE,sBAAsB;IAC3C,UAAU,EAAE,SAAS,EAAE,wBAAwB;IAC/C,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,EAAE,EAAE,yBAAyB;IACxC,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF,6DAA6D;AAC7D,MAAM,qBAAqB,GAAgB;IACzC,IAAI,EAAE,GAAG;IACT,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,uBAAuB;IAC/D,QAAQ,EAAE,EAAE,EAAE,eAAe;IAC7B,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,yBAAyB;IAC9D,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,EAAE;IACb,YAAY,EAAE,KAAK;CACpB,CAAC;AAUF,MAAM,OAAO,kBAAkB;IACrB,WAAW,CAAS;IACpB,WAAW,CAAU;IACrB,YAAY,CAAsB;IAClC,qBAAqB,CAAmB;IACxC,iBAAiB,CAAmB;IACpC,iBAAiB,GAAG,CAAC,CAAC;IACtB,sBAAsB,GAAG,CAAC,CAAC;IAC3B,QAAQ,GAAiB,EAAE,CAAC;IAC5B,UAAU,CAAU;IAE5B,4CAA4C;IACpC,MAAM,CAAU,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACrD,2DAA2D;IACnD,MAAM,CAAU,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,kDAAkD;IAC1C,MAAM,CAAU,iBAAiB,GAAG,IAAI,CAAC;IAEjD,YAAY,OAKX;QACC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC;IAChD,CAAC;IAED;;;OAGG;IACK,kBAAkB;QACxB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB;YAClD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACK,iBAAiB;QACvB,cAAc;QACd,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC,iBAAiB,CAAC;QAChC,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACnD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CACjE,CAAC;YAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,yBAAyB;YACzB,MAAM,YAAY,GAAkB,EAAE,CAAC;YACvC,IAAI,cAAc,GAAgC;gBAChD,qBAAqB,EAAE,KAAK;gBAC5B,YAAY,EAAE,IAAI;gBAClB,cAAc,EAAE,EAAE;aACnB,CAAC;YACF,IAAI,aAAa,GAAgB,EAAE,GAAG,cAAc,EAAE,CAAC;YAEvD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAEnD,IAAI,MAA+B,CAAC;gBACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,uCAAuC;oBACvC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBACzC,CAAC;gBAED,eAAe;gBACf,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACjC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;wBAClC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;4BAC1D,YAAY,CAAC,IAAI,CAAC,KAAoB,CAAC,CAAC;wBAC1C,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,wCAAwC;gBACxC,IAAI,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC3D,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,CAAC,QAAmC,EAAE,CAAC;gBACxF,CAAC;gBAED,uBAAuB;gBACvB,IAAI,MAAM,CAAC,aAAa,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;oBACrE,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC,aAA4B,EAAE,CAAC;gBAC/E,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAoB;gBAC9B,aAAa,EAAE,aAAa;gBAC5B,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,cAAc;aACzB,CAAC;YAEF,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC;YAChC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC,kBAAkB,CAAC;YAEjF,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,eAAe,CAAC,OAAe;QACrC,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,IAAI,YAAY,GAAqB,IAAI,CAAC;QAC1C,IAAI,aAAa,GAAmC,IAAI,CAAC;QACzD,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAE5B,gCAAgC;YAChC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAElD,wBAAwB;YACxB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;YAEzD,aAAa;YACb,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEtC,2CAA2C;gBAC3C,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;oBACvD,aAAa,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChD,IAAI,YAAY,EAAE,CAAC;wBACjB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,qBAAqB;oBACrB,IAAI,YAAY,EAAE,CAAC;wBACjB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC5C,CAAC;gBACH,CAAC;gBACD,SAAS;YACX,CAAC;YAED,kBAAkB;YAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEjD,wCAAwC;gBACxC,IAAI,aAAa,IAAI,UAAU,GAAG,MAAM,EAAE,CAAC;oBACzC,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;oBAC5C,SAAS;gBACX,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBACnD,kCAAkC;oBAClC,WAAW,GAAG,GAAG,CAAC;oBAClB,YAAY,GAAG,EAAE,CAAC;oBAClB,aAAa,GAAG,IAAI,CAAC;oBACrB,MAAM,GAAG,UAAU,CAAC;oBACpB,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACN,oBAAoB;oBACpB,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;wBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;wBACrC,WAAW,GAAG,EAAE,CAAC;wBACjB,YAAY,GAAG,IAAI,CAAC;wBACpB,aAAa,GAAG,IAAI,CAAC;oBACvB,CAAC;yBAAM,IAAI,aAAa,EAAE,CAAC;wBACzB,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,KAAa;QAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAC7D,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QAEpC,2BAA2B;QAC3B,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBAAE,OAAO,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC9B,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBACrD,OAAO,OAAO,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC;QAED,SAAS;QACT,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,oCAAoC;QACpC,OAAO,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CACZ,WAAmB,EACnB,UAAkB,EAClB,SAAiB;QAEjB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAE3D,iCAAiC;QACjC,IAAI,YAAY,CAAC,aAAa,EAAE,YAAY,KAAK,KAAK,EAAE,CAAC;YACvD,MAAM,QAAQ,GAAmB;gBAC/B,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,UAAU,UAAU,gCAAgC;gBAC5D,YAAY,EAAE,YAAY,CAAC,YAAY;gBACvC,aAAa,EAAE,YAAY,CAAC,aAAa;aAC1C,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;YAC3E,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,6BAA6B;QAC7B,MAAM,YAAY,GAAG,aAAa,CAAC,aAAa,EAAE,QAAQ,CAAC;QAC3D,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YAC/D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAmB;oBAC/B,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,UAAU,WAAW,8BAA8B,UAAU,GAAG;oBACxE,YAAY,EAAE,aAAa,CAAC,YAAY;oBACxC,aAAa,EAAE,aAAa,CAAC,aAAa;iBAC3C,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC3E,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,mEAAmE;QACnE,MAAM,QAAQ,GAAmB;YAC/B,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,2BAA2B;YACnC,YAAY,EAAE,aAAa,CAAC,YAAY;YACxC,aAAa,EAAE,aAAa,CAAC,aAAa;SAC3C,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3E,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CACd,UAAkB,EAClB,aAAqB;QAErB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAE3D,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,EAAE,UAAU,CAAC;QAC9D,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,QAAQ,GAAmB;oBAC/B,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,UAAU,UAAU,gCAAgC,aAAa,GAAG;oBAC5E,YAAY,EAAE,YAAY,CAAC,YAAY;oBACvC,aAAa,EAAE,YAAY,CAAC,aAAa;iBAC1C,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;gBAC3D,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAmB;YAC/B,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,6BAA6B;YACrC,YAAY,EAAE,YAAY,CAAC,YAAY;YACvC,aAAa,EAAE,YAAY,CAAC,aAAa;SAC1C,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC3D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,QAAgB;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAEpD,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC;QACxD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,kCAAkC;YAClC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC5D,MAAM,QAAQ,GAAmB;oBAC/B,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,UAAU,SAAS,mCAAmC;oBAC9D,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,aAAa,EAAE,MAAM,CAAC,aAAa;iBACpC,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAClD,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,mCAAmC;YACnC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,QAAQ,GAAmB;oBAC/B,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,UAAU,SAAS,iCAAiC,QAAQ,GAAG;oBACvE,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,aAAa,EAAE,MAAM,CAAC,aAAa;iBACpC,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAClD,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAmB;YAC/B,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,gCAAgC;YACxC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,aAAa,EAAE,MAAM,CAAC,aAAa;SACpC,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,SAAiB;QAIpC,iDAAiD;QACjD,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAChE,IAAI,UAAU,EAAE,CAAC;YACf,OAAO;gBACL,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;gBAC9C,YAAY,EAAE,MAAM;aACrB,CAAC;QACJ,CAAC;QAED,0EAA0E;QAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC7C,IAAI,WAAW,EAAE,CAAC;YAChB,wCAAwC;YACxC,IAAI,WAAW,CAAC,QAAQ,EAAE,qBAAqB,EAAE,CAAC;gBAChD,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;gBAC7E,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;gBAClD,CAAC;gBACD,+BAA+B;gBAC/B,OAAO;oBACL,aAAa,EAAE,EAAE,GAAG,qBAAqB,EAAE,IAAI,EAAE,SAAS,EAAE;oBAC5D,YAAY,EAAE,OAAO;iBACtB,CAAC;YACJ,CAAC;YAED,uBAAuB;YACvB,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;YAC7E,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;YAClD,CAAC;YAED,oBAAoB;YACpB,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;gBAC9B,OAAO;oBACL,aAAa,EAAE,EAAE,GAAG,WAAW,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;oBAChE,YAAY,EAAE,OAAO;iBACtB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxD,IAAI,eAAe,EAAE,CAAC;YACpB,wBAAwB;YACxB,IAAI,eAAe,CAAC,QAAQ,EAAE,qBAAqB,EAAE,CAAC;gBACpD,0DAA0D;gBAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;gBACjF,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;gBACtD,CAAC;gBACD,+BAA+B;gBAC/B,OAAO;oBACL,aAAa,EAAE,EAAE,GAAG,qBAAqB,EAAE,IAAI,EAAE,SAAS,EAAE;oBAC5D,YAAY,EAAE,WAAW;iBAC1B,CAAC;YACJ,CAAC;YAED,uBAAuB;YACvB,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YACjF,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;YACtD,CAAC;YAED,wBAAwB;YACxB,IAAI,eAAe,CAAC,aAAa,EAAE,CAAC;gBAClC,OAAO;oBACL,aAAa,EAAE,EAAE,GAAG,eAAe,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;oBACpE,YAAY,EAAE,WAAW;iBAC1B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,cAAc,CAAC;QAC/E,OAAO;YACL,aAAa,EAAE,EAAE,GAAG,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;YACpD,YAAY,EAAE,SAAS;SACxB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB;QAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,cAAc;QACd,IAAI,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACtE,OAAO,IAAI,CAAC,qBAAqB,CAAC;QACpC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC5E,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAC;gBACpC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC,YAAY,CAAC;YACxE,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;YACjE,qDAAqD;YACrD,OAAO,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC;QAC5C,CAAC;IACH,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,SAAiB,EAAE,QAAuB;QACnE,wBAAwB;QACxB,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QACxF,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAElC,yBAAyB;QACzB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAClD,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,IAAY,EAAE,QAAkB;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YAE3C,eAAe;YACf,IAAI,YAAY,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAEtC,cAAc;YACd,IAAI,YAAY,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC;YAE5C,mDAAmD;YACnD,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzC,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC;oBAAE,OAAO,IAAI,CAAC;YAChD,CAAC;YAED,kDAAkD;YAClD,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACrC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,OAAO,IAAI,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,MAAmB;QACxC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,yEAAyE;YACzE,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,SAAS;YACrB,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CACX,MAA4B,EAC5B,KAAa,EACb,MAA0B,EAC1B,QAAwB,EACxB,OAAiC;QAEjC,MAAM,KAAK,GAAe;YACxB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM;YACN,KAAK;YACL,MAAM;YACN,QAAQ;YACR,OAAO;SACR,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE1B,wBAAwB;QACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,CAAC;YAChE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,qBAAqB;QACrB,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,oBAAoB,MAAM,OAAO,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,OAKX;QACC,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,aAAa;QACX,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QACvC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACtC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAE7E,MAAM,KAAK,GAAa;YACtB,sBAAsB,SAAS,EAAE;YACjC,WAAW,YAAY,EAAE;YACzB,EAAE;SACH,CAAC;QAEF,QAAQ;QACR,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;YAC/B,IAAI,aAAa,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBACxF,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,sBAAsB,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC7C,CAAC;QAED,WAAW;QACX,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAClD,CAAC;QAED,YAAY;QACZ,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,aAAa,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAC3D,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,oBAAoB,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACrD,CAAC;QAED,SAAS;QACT,IAAI,aAAa,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,mBAAmB,aAAa,CAAC,SAAS,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,aAAa,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,mBAAmB,aAAa,CAAC,SAAS,eAAe,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB,CAAC,SAAiB;QAC1C,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAE5F,uDAAuD;QACvD,MAAM,eAAe,GACnB,aAAa,CAAC,YAAY,KAAK,SAAS;YACxC,aAAa,CAAC,QAAQ,KAAK,SAAS;YACpC,aAAa,CAAC,UAAU,KAAK,SAAS,CAAC;QAEzC,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,CAAC,2CAA2C;QAC1D,CAAC;QAED,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;YAC/B,IAAI,aAAa,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBACxF,YAAY,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,IAAI,CAAC,iCAAiC,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;QAED,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxC,YAAY,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,IAAI,CAAC,oCAAoC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9F,CAAC;QACH,CAAC;QAED,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,aAAa,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1C,YAAY,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,IAAI,CAAC,sCAAsC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClG,CAAC;QACH,CAAC;QAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,0BAA0B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7D,CAAC;;AAGH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAKnC;IACC,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Cloud Policy Fetcher
3
+ *
4
+ * Fetches workspace agent policies from the cloud API.
5
+ * Used by workspace containers to get their policy configuration.
6
+ */
7
+ import type { CloudPolicyFetcher } from './agent-policy.js';
8
+ /**
9
+ * Create a cloud policy fetcher for workspace containers
10
+ */
11
+ export declare function createCloudPolicyFetcher(): CloudPolicyFetcher | null;
12
+ //# sourceMappingURL=cloud-policy-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-policy-fetcher.d.ts","sourceRoot":"","sources":["../src/cloud-policy-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,mBAAmB,CAAC;AAE1F;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,GAAG,IAAI,CAiEpE"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Cloud Policy Fetcher
3
+ *
4
+ * Fetches workspace agent policies from the cloud API.
5
+ * Used by workspace containers to get their policy configuration.
6
+ */
7
+ /**
8
+ * Create a cloud policy fetcher for workspace containers
9
+ */
10
+ export function createCloudPolicyFetcher() {
11
+ const cloudApiUrl = process.env.CLOUD_API_URL;
12
+ const workspaceId = process.env.WORKSPACE_ID;
13
+ const workspaceToken = process.env.WORKSPACE_TOKEN;
14
+ if (!cloudApiUrl || !workspaceId) {
15
+ return null;
16
+ }
17
+ return {
18
+ async getWorkspacePolicy(requestedWorkspaceId) {
19
+ // Only allow fetching policy for this workspace
20
+ if (requestedWorkspaceId !== workspaceId) {
21
+ console.warn(`[policy-fetcher] Attempted to fetch policy for different workspace: ${requestedWorkspaceId}`);
22
+ return null;
23
+ }
24
+ try {
25
+ const url = `${cloudApiUrl}/api/policy/${workspaceId}/internal`;
26
+ const headers = {
27
+ 'Content-Type': 'application/json',
28
+ };
29
+ // Add auth header if we have a workspace token
30
+ if (workspaceToken) {
31
+ headers['Authorization'] = `Bearer ${workspaceToken}`;
32
+ }
33
+ const response = await fetch(url, { headers });
34
+ if (!response.ok) {
35
+ console.error(`[policy-fetcher] Failed to fetch policy: ${response.status} ${response.statusText}`);
36
+ return null;
37
+ }
38
+ const data = await response.json();
39
+ // Convert API response to WorkspacePolicy
40
+ const policy = {
41
+ defaultPolicy: data.defaultPolicy ?? {
42
+ name: '*',
43
+ maxSpawns: 10,
44
+ rateLimit: 60,
45
+ canBeSpawned: true,
46
+ },
47
+ agents: data.agents ?? [],
48
+ settings: data.settings ?? {
49
+ requireExplicitAgents: false,
50
+ auditEnabled: true,
51
+ maxTotalAgents: 50,
52
+ },
53
+ };
54
+ console.log(`[policy-fetcher] Fetched policy for workspace ${workspaceId}: ${policy.agents.length} agent rules`);
55
+ return policy;
56
+ }
57
+ catch (error) {
58
+ console.error('[policy-fetcher] Error fetching policy:', error);
59
+ return null;
60
+ }
61
+ },
62
+ };
63
+ }
64
+ //# sourceMappingURL=cloud-policy-fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-policy-fetcher.js","sourceRoot":"","sources":["../src/cloud-policy-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAEnD,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,KAAK,CAAC,kBAAkB,CAAC,oBAA4B;YACnD,gDAAgD;YAChD,IAAI,oBAAoB,KAAK,WAAW,EAAE,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,uEAAuE,oBAAoB,EAAE,CAAC,CAAC;gBAC5G,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,GAAG,WAAW,eAAe,WAAW,WAAW,CAAC;gBAChE,MAAM,OAAO,GAA2B;oBACtC,cAAc,EAAE,kBAAkB;iBACnC,CAAC;gBAEF,+CAA+C;gBAC/C,IAAI,cAAc,EAAE,CAAC;oBACnB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,cAAc,EAAE,CAAC;gBACxD,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAE/C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,OAAO,CAAC,KAAK,CAAC,4CAA4C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;oBACpG,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAI/B,CAAC;gBAEF,0CAA0C;gBAC1C,MAAM,MAAM,GAAoB;oBAC9B,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI;wBACnC,IAAI,EAAE,GAAG;wBACT,SAAS,EAAE,EAAE;wBACb,SAAS,EAAE,EAAE;wBACb,YAAY,EAAE,IAAI;qBACnB;oBACD,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;oBACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI;wBACzB,qBAAqB,EAAE,KAAK;wBAC5B,YAAY,EAAE,IAAI;wBAClB,cAAc,EAAE,EAAE;qBACnB;iBACF,CAAC;gBAEF,OAAO,CAAC,GAAG,CAAC,iDAAiD,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,cAAc,CAAC,CAAC;gBACjH,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;gBAChE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @relay/policy
3
+ *
4
+ * Agent policy management with multi-level fallback:
5
+ * - Repo-level policy (.claude/agents/*.md)
6
+ * - User-level PRPM policies (~/.config/agent-relay/policies/*.yaml)
7
+ * - Cloud workspace policies
8
+ * - Built-in safe defaults
9
+ */
10
+ export { AgentPolicyService, createPolicyService, type AgentPolicy, type WorkspacePolicy, type PolicyDecision, type AuditEntry, type CloudPolicyFetcher, } from './agent-policy.js';
11
+ export { createCloudPolicyFetcher } from './cloud-policy-fetcher.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @relay/policy
3
+ *
4
+ * Agent policy management with multi-level fallback:
5
+ * - Repo-level policy (.claude/agents/*.md)
6
+ * - User-level PRPM policies (~/.config/agent-relay/policies/*.yaml)
7
+ * - Cloud workspace policies
8
+ * - Built-in safe defaults
9
+ */
10
+ export { AgentPolicyService, createPolicyService, } from './agent-policy.js';
11
+ export { createCloudPolicyFetcher } from './cloud-policy-fetcher.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAMpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@agent-relay/policy",
3
+ "version": "0.1.0",
4
+ "description": "Agent policy management with multi-level fallback (repo, local PRPM, cloud workspace)",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "clean": "rm -rf dist",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest"
23
+ },
24
+ "dependencies": {
25
+ "@agent-relay/config": "^0.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.19.3",
29
+ "typescript": "^5.9.3",
30
+ "vitest": "^3.2.4"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }