mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix(daemon): preserve Windows chat attachments (#2158)
This commit is contained in:
parent
f650a043d9
commit
a83cfe9a0c
2 changed files with 58 additions and 13 deletions
|
|
@ -853,6 +853,32 @@ function isPathWithin(base, target) {
|
|||
);
|
||||
}
|
||||
|
||||
export function resolveSafeProjectAttachments(cwd, attachments, opts = {}) {
|
||||
if (!cwd || !Array.isArray(attachments)) return [];
|
||||
const pathImpl = opts.pathImpl ?? path;
|
||||
const existsSync = opts.existsSync ?? fs.existsSync;
|
||||
const root = pathImpl.resolve(cwd);
|
||||
const out = [];
|
||||
|
||||
for (const attachment of attachments) {
|
||||
if (typeof attachment !== 'string' || attachment.length === 0) continue;
|
||||
try {
|
||||
const abs = pathImpl.resolve(root, attachment);
|
||||
const relativePath = pathImpl.relative(root, abs);
|
||||
const withinRoot =
|
||||
relativePath === '' ||
|
||||
(relativePath.length > 0 &&
|
||||
!relativePath.startsWith('..') &&
|
||||
!pathImpl.isAbsolute(relativePath));
|
||||
if (withinRoot && existsSync(abs)) out.push(attachment);
|
||||
} catch {
|
||||
// Drop malformed paths; attachments are advisory prompt context.
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function resolveProcessResourcesPath() {
|
||||
if (
|
||||
typeof process.resourcesPath === 'string' &&
|
||||
|
|
@ -8108,19 +8134,7 @@ export async function startServer({
|
|||
// explicit list at the bottom of the user message so the agent knows
|
||||
// to Read it.
|
||||
const safeAttachments = cwd
|
||||
? (Array.isArray(attachments) ? attachments : [])
|
||||
.filter((p) => typeof p === 'string' && p.length > 0)
|
||||
.filter((p) => {
|
||||
try {
|
||||
const abs = path.resolve(cwd, p);
|
||||
return (
|
||||
(abs === cwd || abs.startsWith(cwd + path.sep)) &&
|
||||
fs.existsSync(abs)
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
? resolveSafeProjectAttachments(cwd, attachments)
|
||||
: [];
|
||||
|
||||
// Local code agents don't accept a separate "system" channel the way the
|
||||
|
|
|
|||
31
apps/daemon/tests/chat-attachments.test.ts
Normal file
31
apps/daemon/tests/chat-attachments.test.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import path from 'node:path';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { resolveSafeProjectAttachments } from '../src/server.js';
|
||||
|
||||
describe('resolveSafeProjectAttachments', () => {
|
||||
it('keeps Windows attachments when root and attachment path use different separators and drive casing', () => {
|
||||
const existing = new Set([
|
||||
'C:\\Users\\Designer\\Open Design\\m5-logo.png',
|
||||
'c:\\users\\designer\\open design\\assets\\mark.png',
|
||||
]);
|
||||
|
||||
const safe = resolveSafeProjectAttachments(
|
||||
'C:/Users/Designer/Open Design/',
|
||||
[
|
||||
'm5-logo.png',
|
||||
'c:/users/designer/open design/assets/mark.png',
|
||||
'C:/Users/Designer/Open Design Adjacent/secret.png',
|
||||
'..\\secret.png',
|
||||
],
|
||||
{
|
||||
existsSync: (target: string) => existing.has(target),
|
||||
pathImpl: path.win32,
|
||||
},
|
||||
);
|
||||
|
||||
expect(safe).toEqual([
|
||||
'm5-logo.png',
|
||||
'c:/users/designer/open design/assets/mark.png',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue