@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.
- package/dist/agent-policy.d.ts +225 -0
- package/dist/agent-policy.d.ts.map +1 -0
- package/dist/agent-policy.js +665 -0
- package/dist/agent-policy.js.map +1 -0
- package/dist/cloud-policy-fetcher.d.ts +12 -0
- package/dist/cloud-policy-fetcher.d.ts.map +1 -0
- package/dist/cloud-policy-fetcher.js +64 -0
- package/dist/cloud-policy-fetcher.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -0
|
@@ -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":"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"}
|
|
@@ -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"}
|
package/dist/index.d.ts
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, 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
|
+
}
|