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
11 changes: 8 additions & 3 deletions middleware/src/routes/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,15 @@ export function createStoreRouter(deps: StoreDeps): Router {
}
});

router.get('/:id', async (req: Request, res: Response) => {
// Regex route so scoped plugin IDs like `@omadia/agent-foo` (which
// contain a literal `/`) are captured as one parameter rather than
// being split into two path segments by Express. Uses `+` so the
// empty-path case (`GET /`) is not captured here and is handled by
// the `GET /` list route above.
router.get(/^\/(.+)$/, async (req: Request, res: Response) => {
try {
const rawId = req.params['id'];
const id = typeof rawId === 'string' ? rawId : undefined;
const rawId = req.params[0] as string | undefined;
const id = typeof rawId === 'string' && rawId.length > 0 ? rawId : undefined;
if (!id) {
res.status(400).json({ code: 'store.invalid_id', message: 'missing id' });
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ describe('agent-reference / Toolkit query_notes_by_person (OB-29-4)', () => {
body: 'Anna war heute auch dabei.',
createdAt: '2026-05-03T11:00:00.000Z',
},
{
id: 'n4',
title: 'Sprint-Review mit John Mueller',
body: 'John Mueller hatte Bedenken zum Zeitplan.',
createdAt: '2026-05-04T14:00:00.000Z',
},
];
store = makePopulatedStore(records);
toolkit = createToolkit({ notes: store, log: () => {} });
Expand Down Expand Up @@ -102,9 +108,9 @@ describe('agent-reference / Toolkit query_notes_by_person (OB-29-4)', () => {
assert.ok(parsed._pendingUserChoice);
assert.match(
parsed._pendingUserChoice!.question,
/2 Notizen erw.hnen "John"/,
/3 Notizen erw.hnen "John"/,
);
assert.equal(parsed._pendingUserChoice!.options.length, 2);
assert.equal(parsed._pendingUserChoice!.options.length, 3);
for (const o of parsed._pendingUserChoice!.options) {
assert.match(o.value, /^note:n\d+$/);
assert.ok(o.label.length > 0);
Expand Down
9 changes: 4 additions & 5 deletions middleware/test/agent-reference-maximum/storeFilter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,10 @@ describe('agent-reference / Store filter for is_reference_only', () => {
const registry = new InMemoryInstalledRegistry();
const router = createStoreRouter({ catalog, registry });

// npm-scoped plugin IDs contain `/`, which Express won't match in a
// `/:id` segment unless URL-encoded. The production UI URL-encodes
// before fetching; mirror that here.
const encodedId = encodeURIComponent('@omadia/agent-reference-maximum');
const { status, body } = await callRouter(router, `/${encodedId}`);
const { status, body } = await callRouter(
router,
'/@omadia/agent-reference-maximum',
);
assert.equal(status, 404);
const payload = body as { code: string };
assert.equal(payload.code, 'store.plugin_not_found');
Expand Down
Loading