Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/__tests__/cli-diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ test('cli forwards --debug as verbose/debug metadata', async () => {
assert.equal(result.calls.length, 1);
assert.equal(result.calls[0]?.flags?.verbose, true);
assert.equal(result.calls[0]?.meta?.debug, true);
assert.equal(result.calls[0]?.meta?.cwd, process.cwd());
assert.equal(typeof result.calls[0]?.meta?.requestId, 'string');
});

Expand Down
1 change: 1 addition & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export async function runCli(argv: string[], deps: CliDeps = DEFAULT_CLI_DEPS):
meta: {
requestId,
debug: Boolean(flags.verbose),
cwd: process.cwd(),
},
});
try {
Expand Down
1 change: 1 addition & 0 deletions src/daemon-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export async function sendToDaemon(req: Omit<DaemonRequest, 'token'>): Promise<D
meta: {
requestId,
debug,
cwd: req.meta?.cwd,
},
};
emitDiagnostic({
Expand Down
13 changes: 13 additions & 0 deletions src/daemon/__tests__/session-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ function makeSession(name: string): SessionState {
};
}

test('expandHome resolves tilde, relative-with-cwd, and absolute paths', () => {
const homePath = SessionStore.expandHome('~/flows/replay.ad');
assert.equal(homePath.startsWith(os.homedir()), true);
assert.equal(homePath.endsWith(path.join('flows', 'replay.ad')), true);

const relativePath = SessionStore.expandHome('workflows/replay.ad', '/tmp/agent-device-cwd');
assert.equal(relativePath, path.resolve('/tmp/agent-device-cwd', 'workflows/replay.ad'));

const absoluteInput = path.resolve('/tmp', 'agent-device-absolute.ad');
const absolutePath = SessionStore.expandHome(absoluteInput, '/tmp/ignored-cwd');
assert.equal(absolutePath, absoluteInput);
});

test('recordAction stores normalized action entries', () => {
const store = new SessionStore(path.join(os.tmpdir(), 'agent-device-tests'));
const session = makeSession('default');
Expand Down
33 changes: 33 additions & 0 deletions src/daemon/handlers/__tests__/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,39 @@ test('replay parses open --relaunch flag and replays open with relaunch semantic
assert.equal(invoked[0]?.flags?.relaunch, true);
});

test('replay resolves relative script path against request cwd', async () => {
const sessionStore = makeSessionStore();
const replayRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-device-replay-cwd-'));
const replayDir = path.join(replayRoot, 'workflows');
fs.mkdirSync(replayDir, { recursive: true });
fs.writeFileSync(path.join(replayDir, 'flow.ad'), 'open "Settings"\n');

const invoked: DaemonRequest[] = [];
const response = await handleSessionCommands({
req: {
token: 't',
session: 'default',
command: 'replay',
positionals: ['workflows/flow.ad'],
flags: {},
meta: { cwd: replayRoot },
},
sessionName: 'default',
logPath: path.join(os.tmpdir(), 'daemon.log'),
sessionStore,
invoke: async (req) => {
invoked.push(req);
return { ok: true, data: {} };
},
});

assert.ok(response);
assert.equal(response?.ok, true);
assert.equal(invoked.length, 1);
assert.equal(invoked[0]?.command, 'open');
assert.deepEqual(invoked[0]?.positionals, ['Settings']);
});

test('replay parses press series flags and passes them to invoke', async () => {
const sessionStore = makeSessionStore();
const replayRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-device-replay-press-series-'));
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/handlers/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ export async function handleSessionCommands(params: {
return { ok: false, error: { code: 'INVALID_ARGS', message: 'replay requires a path' } };
}
try {
const resolved = SessionStore.expandHome(filePath);
const resolved = SessionStore.expandHome(filePath, req.meta?.cwd);
const script = fs.readFileSync(resolved, 'utf8');
const firstNonWhitespace = script.trimStart()[0];
if (firstNonWhitespace === '{' || firstNonWhitespace === '[') {
Expand Down
5 changes: 4 additions & 1 deletion src/daemon/session-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,13 @@ export class SessionStore {
return path.join(this.sessionsDir, `${safeName}-${timestamp}.trace.log`);
}

static expandHome(filePath: string): string {
static expandHome(filePath: string, cwd?: string): string {
if (filePath.startsWith('~/')) {
return path.join(os.homedir(), filePath.slice(2));
}
if (cwd && !path.isAbsolute(filePath)) {
return path.resolve(cwd, filePath);
}
return path.resolve(filePath);
}

Expand Down
1 change: 1 addition & 0 deletions src/daemon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type DaemonRequest = {
meta?: {
requestId?: string;
debug?: boolean;
cwd?: string;
};
};

Expand Down
Loading