@agent-relay/sdk 4.0.2 → 4.0.4
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/bin/agent-relay-broker-darwin-arm64 +0 -0
- package/bin/agent-relay-broker-darwin-x64 +0 -0
- package/bin/agent-relay-broker-linux-arm64 +0 -0
- package/bin/agent-relay-broker-linux-x64 +0 -0
- package/dist/client.d.ts +3 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/provisioner/__tests__/audit.test.d.ts +2 -0
- package/dist/provisioner/__tests__/audit.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/audit.test.js +45 -0
- package/dist/provisioner/__tests__/audit.test.js.map +1 -0
- package/dist/provisioner/__tests__/compiler.test.d.ts +2 -0
- package/dist/provisioner/__tests__/compiler.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/compiler.test.js +345 -0
- package/dist/provisioner/__tests__/compiler.test.js.map +1 -0
- package/dist/provisioner/__tests__/presets.test.d.ts +2 -0
- package/dist/provisioner/__tests__/presets.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/presets.test.js +23 -0
- package/dist/provisioner/__tests__/presets.test.js.map +1 -0
- package/dist/provisioner/__tests__/seeder.test.d.ts +2 -0
- package/dist/provisioner/__tests__/seeder.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/seeder.test.js +224 -0
- package/dist/provisioner/__tests__/seeder.test.js.map +1 -0
- package/dist/provisioner/__tests__/tar-seeder.test.d.ts +2 -0
- package/dist/provisioner/__tests__/tar-seeder.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/tar-seeder.test.js +191 -0
- package/dist/provisioner/__tests__/tar-seeder.test.js.map +1 -0
- package/dist/provisioner/__tests__/token-factory.test.d.ts +2 -0
- package/dist/provisioner/__tests__/token-factory.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/token-factory.test.js +127 -0
- package/dist/provisioner/__tests__/token-factory.test.js.map +1 -0
- package/dist/provisioner/__tests__/token.test.d.ts +2 -0
- package/dist/provisioner/__tests__/token.test.d.ts.map +1 -0
- package/dist/provisioner/__tests__/token.test.js +44 -0
- package/dist/provisioner/__tests__/token.test.js.map +1 -0
- package/dist/provisioner/audit.d.ts +19 -0
- package/dist/provisioner/audit.d.ts.map +1 -0
- package/dist/provisioner/audit.js +74 -0
- package/dist/provisioner/audit.js.map +1 -0
- package/dist/provisioner/compiler.d.ts +23 -0
- package/dist/provisioner/compiler.d.ts.map +1 -0
- package/dist/provisioner/compiler.js +355 -0
- package/dist/provisioner/compiler.js.map +1 -0
- package/dist/provisioner/index.d.ts +9 -0
- package/dist/provisioner/index.d.ts.map +1 -0
- package/dist/provisioner/index.js +266 -0
- package/dist/provisioner/index.js.map +1 -0
- package/dist/provisioner/mount.d.ts +14 -0
- package/dist/provisioner/mount.d.ts.map +1 -0
- package/dist/provisioner/mount.js +329 -0
- package/dist/provisioner/mount.js.map +1 -0
- package/dist/provisioner/seeder.d.ts +17 -0
- package/dist/provisioner/seeder.d.ts.map +1 -0
- package/dist/provisioner/seeder.js +419 -0
- package/dist/provisioner/seeder.js.map +1 -0
- package/dist/provisioner/token.d.ts +38 -0
- package/dist/provisioner/token.d.ts.map +1 -0
- package/dist/provisioner/token.js +74 -0
- package/dist/provisioner/token.js.map +1 -0
- package/dist/provisioner/types.d.ts +133 -0
- package/dist/provisioner/types.d.ts.map +1 -0
- package/dist/provisioner/types.js +2 -0
- package/dist/provisioner/types.js.map +1 -0
- package/dist/relay.d.ts +6 -0
- package/dist/relay.d.ts.map +1 -1
- package/dist/relay.js +17 -5
- package/dist/relay.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workflows/__tests__/e2e-permissions.test.d.ts +2 -0
- package/dist/workflows/__tests__/e2e-permissions.test.d.ts.map +1 -0
- package/dist/workflows/__tests__/e2e-permissions.test.js +331 -0
- package/dist/workflows/__tests__/e2e-permissions.test.js.map +1 -0
- package/dist/workflows/__tests__/permission-types.test.d.ts +2 -0
- package/dist/workflows/__tests__/permission-types.test.d.ts.map +1 -0
- package/dist/workflows/__tests__/permission-types.test.js +124 -0
- package/dist/workflows/__tests__/permission-types.test.js.map +1 -0
- package/dist/workflows/__tests__/permissions-integration.test.d.ts +2 -0
- package/dist/workflows/__tests__/permissions-integration.test.d.ts.map +1 -0
- package/dist/workflows/__tests__/permissions-integration.test.js +526 -0
- package/dist/workflows/__tests__/permissions-integration.test.js.map +1 -0
- package/dist/workflows/dry-run-format.d.ts.map +1 -1
- package/dist/workflows/dry-run-format.js +8 -0
- package/dist/workflows/dry-run-format.js.map +1 -1
- package/dist/workflows/runner.d.ts +14 -0
- package/dist/workflows/runner.d.ts.map +1 -1
- package/dist/workflows/runner.js +455 -6
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/types.d.ts +190 -0
- package/dist/workflows/types.d.ts.map +1 -1
- package/dist/workflows/types.js +29 -0
- package/dist/workflows/types.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
const tempDirs = [];
|
|
7
|
+
const mockFetch = vi.fn().mockResolvedValue({
|
|
8
|
+
ok: true,
|
|
9
|
+
json: () => Promise.resolve({ data: { api_key: 'rk_test', workspace_id: 'ws-test' } }),
|
|
10
|
+
text: () => Promise.resolve(''),
|
|
11
|
+
});
|
|
12
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
13
|
+
let lastProvisionResult;
|
|
14
|
+
const mockProvisionWorkflowAgents = vi.fn();
|
|
15
|
+
vi.mock('../../provisioner/index.js', async () => {
|
|
16
|
+
const actual = await vi.importActual('../../provisioner/index.js');
|
|
17
|
+
mockProvisionWorkflowAgents.mockImplementation(async (config) => {
|
|
18
|
+
const scopes = new Map();
|
|
19
|
+
const tokens = new Map();
|
|
20
|
+
const agents = {};
|
|
21
|
+
let readonly = 0;
|
|
22
|
+
let readwrite = 0;
|
|
23
|
+
let denied = 0;
|
|
24
|
+
let customScopes = 0;
|
|
25
|
+
for (const [agentName, permissions] of Object.entries(config.agents ?? {})) {
|
|
26
|
+
const compiled = actual.resolveAgentPermissions(agentName, permissions, config.projectDir, config.workspace);
|
|
27
|
+
const token = `token:${agentName}`;
|
|
28
|
+
scopes.set(agentName, [...compiled.scopes]);
|
|
29
|
+
tokens.set(agentName, token);
|
|
30
|
+
readonly += compiled.summary.readonly;
|
|
31
|
+
readwrite += compiled.summary.readwrite;
|
|
32
|
+
denied += compiled.summary.denied;
|
|
33
|
+
customScopes += compiled.summary.customScopes;
|
|
34
|
+
agents[agentName] = {
|
|
35
|
+
name: agentName,
|
|
36
|
+
tokenPath: path.resolve(config.projectDir, '.relay', 'tokens', `${agentName}.jwt`),
|
|
37
|
+
token,
|
|
38
|
+
scopes: [...compiled.scopes],
|
|
39
|
+
compiled,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const result = {
|
|
43
|
+
agents,
|
|
44
|
+
agentNames: Object.keys(config.agents ?? {}),
|
|
45
|
+
adminToken: 'admin-token',
|
|
46
|
+
seededFileCount: 0,
|
|
47
|
+
seededAclCount: 0,
|
|
48
|
+
summary: { readonly, readwrite, denied, customScopes },
|
|
49
|
+
mounts: new Map(),
|
|
50
|
+
tokens,
|
|
51
|
+
scopes,
|
|
52
|
+
};
|
|
53
|
+
lastProvisionResult = { scopes, tokens };
|
|
54
|
+
return result;
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
...actual,
|
|
58
|
+
provisionWorkflowAgents: mockProvisionWorkflowAgents,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
vi.mock('@relaycast/sdk', () => ({
|
|
62
|
+
RelayCast: vi.fn(),
|
|
63
|
+
RelayError: class RelayError extends Error {
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
function never() {
|
|
67
|
+
return new Promise(() => { });
|
|
68
|
+
}
|
|
69
|
+
let queuedPtyOutputs = [];
|
|
70
|
+
let waitForExitFn;
|
|
71
|
+
let waitForIdleFn;
|
|
72
|
+
const mockAgent = {
|
|
73
|
+
name: 'workflow-agent',
|
|
74
|
+
exitCode: 0,
|
|
75
|
+
exitSignal: undefined,
|
|
76
|
+
get waitForExit() {
|
|
77
|
+
return waitForExitFn;
|
|
78
|
+
},
|
|
79
|
+
get waitForIdle() {
|
|
80
|
+
return waitForIdleFn;
|
|
81
|
+
},
|
|
82
|
+
release: vi.fn().mockResolvedValue(undefined),
|
|
83
|
+
};
|
|
84
|
+
const mockHuman = {
|
|
85
|
+
name: 'WorkflowRunner',
|
|
86
|
+
sendMessage: vi.fn().mockResolvedValue(undefined),
|
|
87
|
+
};
|
|
88
|
+
const mockRelayInstance = {
|
|
89
|
+
spawnPty: vi.fn(),
|
|
90
|
+
human: vi.fn().mockReturnValue(mockHuman),
|
|
91
|
+
shutdown: vi.fn().mockResolvedValue(undefined),
|
|
92
|
+
onBrokerStderr: vi.fn().mockReturnValue(() => { }),
|
|
93
|
+
listAgentsRaw: vi.fn().mockResolvedValue([]),
|
|
94
|
+
onWorkerOutput: null,
|
|
95
|
+
onMessageReceived: null,
|
|
96
|
+
onAgentSpawned: null,
|
|
97
|
+
onAgentReleased: null,
|
|
98
|
+
onAgentExited: null,
|
|
99
|
+
onAgentIdle: null,
|
|
100
|
+
onDeliveryUpdate: null,
|
|
101
|
+
};
|
|
102
|
+
const defaultSpawnPtyImplementation = async ({ name, task }) => {
|
|
103
|
+
const queued = queuedPtyOutputs.shift();
|
|
104
|
+
const stepComplete = task?.match(/STEP_COMPLETE:([^\n]+)/u)?.[1]?.trim();
|
|
105
|
+
const output = queued ?? (stepComplete ? `STEP_COMPLETE:${stepComplete}\n` : 'STEP_COMPLETE:done\n');
|
|
106
|
+
queueMicrotask(() => {
|
|
107
|
+
mockRelayInstance.onWorkerOutput?.({ name, chunk: output });
|
|
108
|
+
});
|
|
109
|
+
return { ...mockAgent, name };
|
|
110
|
+
};
|
|
111
|
+
vi.mock('../../relay.js', () => ({
|
|
112
|
+
AgentRelay: vi.fn().mockImplementation(() => mockRelayInstance),
|
|
113
|
+
}));
|
|
114
|
+
let queuedSubprocessResults = [];
|
|
115
|
+
const mockSubprocessSpawn = vi.fn().mockImplementation((_cmd, _args, _options) => {
|
|
116
|
+
const result = queuedSubprocessResults.shift() ?? { stdout: 'non-interactive complete\n', code: 0 };
|
|
117
|
+
const child = new EventEmitter();
|
|
118
|
+
child.stdout = new EventEmitter();
|
|
119
|
+
child.stderr = new EventEmitter();
|
|
120
|
+
child.pid = 4321;
|
|
121
|
+
child.kill = vi.fn();
|
|
122
|
+
queueMicrotask(() => {
|
|
123
|
+
if (result.error) {
|
|
124
|
+
child.emit('error', result.error);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (result.stdout) {
|
|
128
|
+
child.stdout.emit('data', Buffer.from(result.stdout));
|
|
129
|
+
}
|
|
130
|
+
if (result.stderr) {
|
|
131
|
+
child.stderr.emit('data', Buffer.from(result.stderr));
|
|
132
|
+
}
|
|
133
|
+
child.emit('close', result.code ?? 0, result.signal ?? null);
|
|
134
|
+
});
|
|
135
|
+
return child;
|
|
136
|
+
});
|
|
137
|
+
vi.mock('node:child_process', async () => {
|
|
138
|
+
const actual = await vi.importActual('node:child_process');
|
|
139
|
+
return {
|
|
140
|
+
...actual,
|
|
141
|
+
spawn: mockSubprocessSpawn,
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
const { WorkflowRunner } = await import('../runner.js');
|
|
145
|
+
function makeDb() {
|
|
146
|
+
const runs = new Map();
|
|
147
|
+
const steps = new Map();
|
|
148
|
+
return {
|
|
149
|
+
insertRun: vi.fn(async (run) => {
|
|
150
|
+
runs.set(run.id, { ...run });
|
|
151
|
+
}),
|
|
152
|
+
updateRun: vi.fn(async (id, patch) => {
|
|
153
|
+
const existing = runs.get(id);
|
|
154
|
+
if (existing)
|
|
155
|
+
runs.set(id, { ...existing, ...patch });
|
|
156
|
+
}),
|
|
157
|
+
getRun: vi.fn(async (id) => {
|
|
158
|
+
const run = runs.get(id);
|
|
159
|
+
return run ? { ...run } : null;
|
|
160
|
+
}),
|
|
161
|
+
insertStep: vi.fn(async (step) => {
|
|
162
|
+
steps.set(step.id, { ...step });
|
|
163
|
+
}),
|
|
164
|
+
updateStep: vi.fn(async (id, patch) => {
|
|
165
|
+
const existing = steps.get(id);
|
|
166
|
+
if (existing)
|
|
167
|
+
steps.set(id, { ...existing, ...patch });
|
|
168
|
+
}),
|
|
169
|
+
getStepsByRunId: vi.fn(async (runId) => {
|
|
170
|
+
return [...steps.values()].filter((step) => step.runId === runId);
|
|
171
|
+
}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function createProject(files) {
|
|
175
|
+
const dir = mkdtempSync(path.join(os.tmpdir(), 'relay-permissions-integration-'));
|
|
176
|
+
tempDirs.push(dir);
|
|
177
|
+
for (const [relativePath, contents] of Object.entries(files)) {
|
|
178
|
+
const absolutePath = path.join(dir, relativePath);
|
|
179
|
+
mkdirSync(path.dirname(absolutePath), { recursive: true });
|
|
180
|
+
writeFileSync(absolutePath, contents);
|
|
181
|
+
}
|
|
182
|
+
return dir;
|
|
183
|
+
}
|
|
184
|
+
function createBaseProject() {
|
|
185
|
+
return createProject({
|
|
186
|
+
'src/app.ts': 'export const app = true;\n',
|
|
187
|
+
'docs/review.md': '# review\n',
|
|
188
|
+
'.env': 'SECRET=1\n',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
function makeRunner(cwd) {
|
|
192
|
+
return new WorkflowRunner({
|
|
193
|
+
cwd,
|
|
194
|
+
db: makeDb(),
|
|
195
|
+
workspaceId: 'ws-test',
|
|
196
|
+
relay: {
|
|
197
|
+
env: {
|
|
198
|
+
AGENT_RELAY_WORKFLOW_DISABLE_RELAYCAST: '1',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function makeConfig(agents, steps, permissionProfiles) {
|
|
204
|
+
return {
|
|
205
|
+
version: '1',
|
|
206
|
+
name: 'permissions-integration',
|
|
207
|
+
permission_profiles: permissionProfiles,
|
|
208
|
+
swarm: { pattern: 'dag' },
|
|
209
|
+
agents,
|
|
210
|
+
workflows: [
|
|
211
|
+
{
|
|
212
|
+
name: 'default',
|
|
213
|
+
steps: steps ??
|
|
214
|
+
agents.map((agent, index) => ({
|
|
215
|
+
name: `step-${index + 1}`,
|
|
216
|
+
agent: agent.name,
|
|
217
|
+
task: `Complete work for ${agent.name}`,
|
|
218
|
+
})),
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
trajectories: false,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function getProvisionedScopes(agentName) {
|
|
225
|
+
expect(lastProvisionResult).toBeDefined();
|
|
226
|
+
const scopes = lastProvisionResult?.scopes.get(agentName);
|
|
227
|
+
expect(scopes).toBeDefined();
|
|
228
|
+
return scopes ?? [];
|
|
229
|
+
}
|
|
230
|
+
beforeEach(() => {
|
|
231
|
+
vi.clearAllMocks();
|
|
232
|
+
lastProvisionResult = undefined;
|
|
233
|
+
queuedPtyOutputs = [];
|
|
234
|
+
queuedSubprocessResults = [];
|
|
235
|
+
waitForExitFn = vi.fn().mockResolvedValue('exited');
|
|
236
|
+
waitForIdleFn = vi.fn().mockImplementation(() => never());
|
|
237
|
+
mockAgent.release.mockResolvedValue(undefined);
|
|
238
|
+
mockRelayInstance.spawnPty.mockImplementation(defaultSpawnPtyImplementation);
|
|
239
|
+
mockRelayInstance.onWorkerOutput = null;
|
|
240
|
+
});
|
|
241
|
+
afterEach(() => {
|
|
242
|
+
while (tempDirs.length > 0) {
|
|
243
|
+
rmSync(tempDirs.pop(), { recursive: true, force: true });
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
describe('WorkflowRunner permission lifecycle integration', () => {
|
|
247
|
+
it('mints workflow tokens before spawning interactive agents', async () => {
|
|
248
|
+
const projectDir = createBaseProject();
|
|
249
|
+
const runner = makeRunner(projectDir);
|
|
250
|
+
const config = makeConfig([
|
|
251
|
+
{
|
|
252
|
+
name: 'writer',
|
|
253
|
+
cli: 'claude',
|
|
254
|
+
permissions: { access: 'readwrite' },
|
|
255
|
+
},
|
|
256
|
+
]);
|
|
257
|
+
const run = await runner.execute(config, 'default');
|
|
258
|
+
expect(run.status).toBe('completed');
|
|
259
|
+
expect(mockProvisionWorkflowAgents).toHaveBeenCalledTimes(1);
|
|
260
|
+
expect(mockRelayInstance.spawnPty).toHaveBeenCalledTimes(1);
|
|
261
|
+
expect(mockProvisionWorkflowAgents.mock.invocationCallOrder[0]).toBeLessThan(mockRelayInstance.spawnPty.mock.invocationCallOrder[0]);
|
|
262
|
+
});
|
|
263
|
+
it('skips provisioning entirely when no agent permissions are configured', async () => {
|
|
264
|
+
const projectDir = createBaseProject();
|
|
265
|
+
const runner = makeRunner(projectDir);
|
|
266
|
+
const config = makeConfig([{ name: 'legacy-agent', cli: 'claude' }]);
|
|
267
|
+
const run = await runner.execute(config, 'default');
|
|
268
|
+
expect(run.status).toBe('completed');
|
|
269
|
+
expect(mockProvisionWorkflowAgents).not.toHaveBeenCalled();
|
|
270
|
+
expect(mockRelayInstance.spawnPty).toHaveBeenCalledTimes(1);
|
|
271
|
+
});
|
|
272
|
+
it('provisions reviewer agents with readonly scopes only', async () => {
|
|
273
|
+
const projectDir = createBaseProject();
|
|
274
|
+
const runner = makeRunner(projectDir);
|
|
275
|
+
const config = makeConfig([
|
|
276
|
+
{
|
|
277
|
+
name: 'reviewer-agent',
|
|
278
|
+
cli: 'claude',
|
|
279
|
+
permissions: { access: 'readonly' },
|
|
280
|
+
},
|
|
281
|
+
]);
|
|
282
|
+
const run = await runner.execute(config, 'default');
|
|
283
|
+
const scopes = getProvisionedScopes('reviewer-agent');
|
|
284
|
+
expect(run.status).toBe('completed');
|
|
285
|
+
expect(lastProvisionResult?.tokens.get('reviewer-agent')).toBe('token:reviewer-agent');
|
|
286
|
+
expect(scopes.length).toBeGreaterThan(0);
|
|
287
|
+
expect(scopes.every((scope) => !scope.includes(':write:'))).toBe(true);
|
|
288
|
+
expect(scopes.every((scope) => scope.includes(':read:'))).toBe(true);
|
|
289
|
+
});
|
|
290
|
+
it('provisions worker agents with readwrite scopes', async () => {
|
|
291
|
+
const projectDir = createBaseProject();
|
|
292
|
+
const runner = makeRunner(projectDir);
|
|
293
|
+
const config = makeConfig([
|
|
294
|
+
{
|
|
295
|
+
name: 'worker-agent',
|
|
296
|
+
cli: 'claude',
|
|
297
|
+
permissions: { access: 'readwrite' },
|
|
298
|
+
},
|
|
299
|
+
]);
|
|
300
|
+
const run = await runner.execute(config, 'default');
|
|
301
|
+
const scopes = getProvisionedScopes('worker-agent');
|
|
302
|
+
expect(run.status).toBe('completed');
|
|
303
|
+
expect(scopes).toContain('relayfile:fs:write:/src/app.ts');
|
|
304
|
+
expect(scopes).toContain('relayfile:fs:write:/docs/review.md');
|
|
305
|
+
});
|
|
306
|
+
it('provisions lead agents with full-access scopes', async () => {
|
|
307
|
+
const projectDir = createBaseProject();
|
|
308
|
+
const runner = makeRunner(projectDir);
|
|
309
|
+
const config = makeConfig([
|
|
310
|
+
{
|
|
311
|
+
name: 'lead-agent',
|
|
312
|
+
cli: 'claude',
|
|
313
|
+
permissions: { access: 'full' },
|
|
314
|
+
},
|
|
315
|
+
]);
|
|
316
|
+
const run = await runner.execute(config, 'default');
|
|
317
|
+
const scopes = getProvisionedScopes('lead-agent');
|
|
318
|
+
expect(run.status).toBe('completed');
|
|
319
|
+
expect(scopes).toContain('relayfile:fs:write:/.env');
|
|
320
|
+
expect(scopes).toContain('relayfile:fs:write:/src/app.ts');
|
|
321
|
+
expect(scopes).toContain('relayfile:fs:write:/docs/review.md');
|
|
322
|
+
});
|
|
323
|
+
it('passes the workflow agent token through to spawnPty', async () => {
|
|
324
|
+
const projectDir = createBaseProject();
|
|
325
|
+
const runner = makeRunner(projectDir);
|
|
326
|
+
const config = makeConfig([
|
|
327
|
+
{
|
|
328
|
+
name: 'interactive-agent',
|
|
329
|
+
cli: 'claude',
|
|
330
|
+
permissions: { access: 'readwrite' },
|
|
331
|
+
},
|
|
332
|
+
]);
|
|
333
|
+
const run = await runner.execute(config, 'default');
|
|
334
|
+
expect(run.status).toBe('completed');
|
|
335
|
+
expect(mockRelayInstance.spawnPty).toHaveBeenCalledWith(expect.objectContaining({
|
|
336
|
+
agentToken: 'token:interactive-agent',
|
|
337
|
+
}));
|
|
338
|
+
});
|
|
339
|
+
it('merges permission profiles into agent permissions before provisioning', async () => {
|
|
340
|
+
const projectDir = createBaseProject();
|
|
341
|
+
const runner = makeRunner(projectDir);
|
|
342
|
+
const config = makeConfig([
|
|
343
|
+
{
|
|
344
|
+
name: 'profiled-agent',
|
|
345
|
+
cli: 'claude',
|
|
346
|
+
permissions: {
|
|
347
|
+
profile: 'reviewer',
|
|
348
|
+
why: 'Needs shared reviewer constraints with one extra scope',
|
|
349
|
+
files: {
|
|
350
|
+
read: ['docs/**'],
|
|
351
|
+
},
|
|
352
|
+
scopes: ['relay:custom:use:/review'],
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
], undefined, {
|
|
356
|
+
reviewer: {
|
|
357
|
+
description: 'Reusable reviewer profile',
|
|
358
|
+
access: 'readonly',
|
|
359
|
+
files: {
|
|
360
|
+
read: ['src/**'],
|
|
361
|
+
deny: ['.env'],
|
|
362
|
+
},
|
|
363
|
+
exec: ['git diff'],
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
const run = await runner.execute(config, 'default');
|
|
367
|
+
const provisionedPermissions = mockProvisionWorkflowAgents.mock.calls[0]?.[0]?.agents?.['profiled-agent'];
|
|
368
|
+
expect(run.status).toBe('completed');
|
|
369
|
+
expect(provisionedPermissions).toEqual({
|
|
370
|
+
description: 'Reusable reviewer profile',
|
|
371
|
+
profile: 'reviewer',
|
|
372
|
+
why: 'Needs shared reviewer constraints with one extra scope',
|
|
373
|
+
access: 'readonly',
|
|
374
|
+
files: {
|
|
375
|
+
read: ['src/**', 'docs/**'],
|
|
376
|
+
deny: ['.env'],
|
|
377
|
+
},
|
|
378
|
+
scopes: ['relay:custom:use:/review'],
|
|
379
|
+
exec: ['git diff'],
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
it('injects RELAY_AGENT_TOKEN into non-interactive agent environments', async () => {
|
|
383
|
+
const projectDir = createBaseProject();
|
|
384
|
+
const runner = makeRunner(projectDir);
|
|
385
|
+
const config = makeConfig([
|
|
386
|
+
{
|
|
387
|
+
name: 'headless-agent',
|
|
388
|
+
cli: 'claude',
|
|
389
|
+
interactive: false,
|
|
390
|
+
permissions: { access: 'readwrite' },
|
|
391
|
+
},
|
|
392
|
+
]);
|
|
393
|
+
const run = await runner.execute(config, 'default');
|
|
394
|
+
const spawnOptions = mockSubprocessSpawn.mock.calls[0]?.[2];
|
|
395
|
+
expect(run.status).toBe('completed');
|
|
396
|
+
expect(mockRelayInstance.spawnPty).not.toHaveBeenCalled();
|
|
397
|
+
expect(mockSubprocessSpawn).toHaveBeenCalledTimes(1);
|
|
398
|
+
expect(spawnOptions?.env?.RELAY_AGENT_TOKEN).toBe('token:headless-agent');
|
|
399
|
+
expect(spawnOptions?.env?.RELAYFILE_TOKEN).toBe('token:headless-agent');
|
|
400
|
+
});
|
|
401
|
+
it('clears workflow-scoped tokens after successful completion', async () => {
|
|
402
|
+
const projectDir = createBaseProject();
|
|
403
|
+
const runner = makeRunner(projectDir);
|
|
404
|
+
const config = makeConfig([
|
|
405
|
+
{
|
|
406
|
+
name: 'cleanup-agent',
|
|
407
|
+
cli: 'claude',
|
|
408
|
+
permissions: { access: 'readwrite' },
|
|
409
|
+
},
|
|
410
|
+
]);
|
|
411
|
+
const run = await runner.execute(config, 'default');
|
|
412
|
+
expect(run.status).toBe('completed');
|
|
413
|
+
expect(runner.agentTokens.size).toBe(0);
|
|
414
|
+
});
|
|
415
|
+
it('clears workflow-scoped tokens after failed workflows', async () => {
|
|
416
|
+
const projectDir = createBaseProject();
|
|
417
|
+
const runner = makeRunner(projectDir);
|
|
418
|
+
const config = makeConfig([
|
|
419
|
+
{
|
|
420
|
+
name: 'failing-agent',
|
|
421
|
+
cli: 'claude',
|
|
422
|
+
permissions: { access: 'readwrite' },
|
|
423
|
+
},
|
|
424
|
+
]);
|
|
425
|
+
mockRelayInstance.spawnPty.mockRejectedValueOnce(new Error('spawn failed'));
|
|
426
|
+
const run = await runner.execute(config, 'default');
|
|
427
|
+
expect(run.status).toBe('failed');
|
|
428
|
+
expect(runner.agentTokens.size).toBe(0);
|
|
429
|
+
});
|
|
430
|
+
it('reports resolved permissions during dry-run without minting tokens', () => {
|
|
431
|
+
const projectDir = createProject({
|
|
432
|
+
'src/app.ts': 'export const app = true;\n',
|
|
433
|
+
'.agentreadonly': 'src/app.ts\n',
|
|
434
|
+
});
|
|
435
|
+
const runner = makeRunner(projectDir);
|
|
436
|
+
const config = makeConfig([
|
|
437
|
+
{
|
|
438
|
+
name: 'dry-run-agent',
|
|
439
|
+
cli: 'claude',
|
|
440
|
+
permissions: {
|
|
441
|
+
access: 'readonly',
|
|
442
|
+
files: {
|
|
443
|
+
read: ['src/**'],
|
|
444
|
+
},
|
|
445
|
+
scopes: ['relay:custom:use:/feature'],
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
]);
|
|
449
|
+
const report = runner.dryRun(config, 'default');
|
|
450
|
+
const permissionEntry = report.permissions?.find((entry) => entry.agent === 'dry-run-agent');
|
|
451
|
+
expect(report.valid).toBe(true);
|
|
452
|
+
expect(permissionEntry).toMatchObject({
|
|
453
|
+
agent: 'dry-run-agent',
|
|
454
|
+
access: 'readonly',
|
|
455
|
+
source: 'yaml',
|
|
456
|
+
});
|
|
457
|
+
expect(permissionEntry?.scopes ?? 0).toBeGreaterThan(0);
|
|
458
|
+
expect(mockProvisionWorkflowAgents).not.toHaveBeenCalled();
|
|
459
|
+
expect(mockRelayInstance.spawnPty).not.toHaveBeenCalled();
|
|
460
|
+
expect(runner.agentTokens.size).toBe(0);
|
|
461
|
+
});
|
|
462
|
+
it('rejects invalid permission config during validation before provisioning', async () => {
|
|
463
|
+
const projectDir = createBaseProject();
|
|
464
|
+
const runner = makeRunner(projectDir);
|
|
465
|
+
const config = makeConfig([
|
|
466
|
+
{
|
|
467
|
+
name: 'invalid-agent',
|
|
468
|
+
cli: 'claude',
|
|
469
|
+
permissions: {
|
|
470
|
+
access: 'bogus',
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
]);
|
|
474
|
+
await expect(runner.execute(config, 'default')).rejects.toThrow('Permission validation failed');
|
|
475
|
+
expect(mockProvisionWorkflowAgents).not.toHaveBeenCalled();
|
|
476
|
+
expect(mockRelayInstance.spawnPty).not.toHaveBeenCalled();
|
|
477
|
+
});
|
|
478
|
+
it('rejects unknown permission profiles during validation before provisioning', async () => {
|
|
479
|
+
const projectDir = createBaseProject();
|
|
480
|
+
const runner = makeRunner(projectDir);
|
|
481
|
+
const config = makeConfig([
|
|
482
|
+
{
|
|
483
|
+
name: 'invalid-profile-agent',
|
|
484
|
+
cli: 'claude',
|
|
485
|
+
permissions: {
|
|
486
|
+
profile: 'missing-reviewer',
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
]);
|
|
490
|
+
await expect(runner.execute(config, 'default')).rejects.toThrow('Permission validation failed');
|
|
491
|
+
expect(mockProvisionWorkflowAgents).not.toHaveBeenCalled();
|
|
492
|
+
expect(mockRelayInstance.spawnPty).not.toHaveBeenCalled();
|
|
493
|
+
});
|
|
494
|
+
it('merges dotfile rules with YAML overrides into the expected scopes', async () => {
|
|
495
|
+
const projectDir = createProject({
|
|
496
|
+
'.agentignore': 'blocked.txt\n',
|
|
497
|
+
'.agentreadonly': 'locked.txt\n',
|
|
498
|
+
'blocked.txt': 'blocked\n',
|
|
499
|
+
'locked.txt': 'locked\n',
|
|
500
|
+
'plain.txt': 'plain\n',
|
|
501
|
+
});
|
|
502
|
+
const runner = makeRunner(projectDir);
|
|
503
|
+
const config = makeConfig([
|
|
504
|
+
{
|
|
505
|
+
name: 'override-agent',
|
|
506
|
+
cli: 'claude',
|
|
507
|
+
permissions: {
|
|
508
|
+
access: 'restricted',
|
|
509
|
+
files: {
|
|
510
|
+
read: ['blocked.txt'],
|
|
511
|
+
write: ['locked.txt'],
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
]);
|
|
516
|
+
const run = await runner.execute(config, 'default');
|
|
517
|
+
const scopes = getProvisionedScopes('override-agent');
|
|
518
|
+
expect(run.status).toBe('completed');
|
|
519
|
+
expect(scopes).toEqual([
|
|
520
|
+
'relayfile:fs:read:/blocked.txt',
|
|
521
|
+
'relayfile:fs:read:/locked.txt',
|
|
522
|
+
'relayfile:fs:write:/locked.txt',
|
|
523
|
+
]);
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
//# sourceMappingURL=permissions-integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions-integration.test.js","sourceRoot":"","sources":["../../../src/workflows/__tests__/permissions-integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dry-run-format.d.ts","sourceRoot":"","sources":["../../src/workflows/dry-run-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"dry-run-format.d.ts","sourceRoot":"","sources":["../../src/workflows/dry-run-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkF/D"}
|
|
@@ -26,6 +26,14 @@ export function formatDryRunReport(report) {
|
|
|
26
26
|
}
|
|
27
27
|
lines.push('');
|
|
28
28
|
}
|
|
29
|
+
// Permissions
|
|
30
|
+
if (report.permissions && report.permissions.length > 0) {
|
|
31
|
+
lines.push(`Permissions (${report.permissions.length} agents):`);
|
|
32
|
+
for (const perm of report.permissions) {
|
|
33
|
+
lines.push(` ${perm.agent}: ${perm.access} (read: ${perm.readPaths}, write: ${perm.writePaths}, deny: ${perm.denyPaths}, scopes: ${perm.scopes}) [${perm.source}]`);
|
|
34
|
+
}
|
|
35
|
+
lines.push('');
|
|
36
|
+
}
|
|
29
37
|
// Execution Plan
|
|
30
38
|
if (report.waves.length > 0) {
|
|
31
39
|
lines.push(`Execution Plan (${report.totalSteps} steps, ${report.estimatedWaves} waves):`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dry-run-format.js","sourceRoot":"","sources":["../../src/workflows/dry-run-format.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS;IACT,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,IAAI,GAAa,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,SAAS;IACT,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACtE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,QAAQ,CAAC;YAChF,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,KAAK,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"dry-run-format.js","sourceRoot":"","sources":["../../src/workflows/dry-run-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -150,6 +150,10 @@ export declare class WorkflowRunner {
|
|
|
150
150
|
private currentRunId?;
|
|
151
151
|
/** Live Agent handles keyed by name, for hub-mediated nudging. */
|
|
152
152
|
private readonly activeAgentHandles;
|
|
153
|
+
/** Per-agent workflow tokens for relay/relayfile auth across spawn modes. */
|
|
154
|
+
private readonly agentTokens;
|
|
155
|
+
/** Per-agent relayfile mounts keyed by logical agent definition name. */
|
|
156
|
+
private readonly agentMounts;
|
|
153
157
|
private readonly ptyOutputBuffers;
|
|
154
158
|
/** Snapshot of PTY output from the most recent failed attempt, keyed by step name. */
|
|
155
159
|
private readonly lastFailedStepOutput;
|
|
@@ -193,6 +197,11 @@ export declare class WorkflowRunner {
|
|
|
193
197
|
* Throws if a required path does not exist.
|
|
194
198
|
*/
|
|
195
199
|
private resolvePathDefinitions;
|
|
200
|
+
private validatePermissions;
|
|
201
|
+
private mergePermissionLists;
|
|
202
|
+
private mergePermissionFiles;
|
|
203
|
+
private mergePermissionProfile;
|
|
204
|
+
private applyPermissionProfiles;
|
|
196
205
|
/**
|
|
197
206
|
* Resolve an agent's effective working directory, considering `workdir` (named path reference)
|
|
198
207
|
* and `cwd` (explicit path). `workdir` takes precedence when both are set.
|
|
@@ -204,6 +213,9 @@ export declare class WorkflowRunner {
|
|
|
204
213
|
*/
|
|
205
214
|
private resolveStepWorkdir;
|
|
206
215
|
private resolveEffectiveCwd;
|
|
216
|
+
private resolveMountedCwd;
|
|
217
|
+
private resolveExecutionCwd;
|
|
218
|
+
private stopProvisionedMounts;
|
|
207
219
|
private static readonly EVIDENCE_IGNORED_DIRS;
|
|
208
220
|
getStepCompletionEvidence(stepName: string): StepCompletionEvidence | undefined;
|
|
209
221
|
private getOrCreateStepEvidenceRecord;
|
|
@@ -237,6 +249,7 @@ export declare class WorkflowRunner {
|
|
|
237
249
|
*/
|
|
238
250
|
private ensureRelaycastApiKey;
|
|
239
251
|
private getRelayEnv;
|
|
252
|
+
private provisionAgents;
|
|
240
253
|
private getRelaycastBaseUrl;
|
|
241
254
|
private getRelaycastClient;
|
|
242
255
|
private ensureRelaycastRunnerAgent;
|
|
@@ -249,6 +262,7 @@ export declare class WorkflowRunner {
|
|
|
249
262
|
parseYamlFile(filePath: string): Promise<RelayYamlConfig>;
|
|
250
263
|
/** Parse a relay.yaml string. */
|
|
251
264
|
parseYamlString(raw: string, source?: string): RelayYamlConfig;
|
|
265
|
+
private normalizeLegacyPermissionConfig;
|
|
252
266
|
/** Validate a config object against the RelayYamlConfig shape. */
|
|
253
267
|
validateConfig(config: unknown, source?: string): asserts config is RelayYamlConfig;
|
|
254
268
|
/**
|