feat(core-api): add rapid order transcribe and parse endpoints
This commit is contained in:
@@ -150,6 +150,130 @@ test('POST /core/invoke-llm enforces per-user rate limit', async () => {
|
||||
assert.equal(typeof second.headers['retry-after'], 'string');
|
||||
});
|
||||
|
||||
test('POST /core/upload-file accepts audio/webm for rapid transcription', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/upload-file')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.field('visibility', 'private')
|
||||
.attach('file', Buffer.from('fake-audio-data'), {
|
||||
filename: 'rapid-request.webm',
|
||||
contentType: 'audio/webm',
|
||||
});
|
||||
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(res.body.contentType, 'audio/webm');
|
||||
assert.equal(typeof res.body.fileUri, 'string');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/transcribe returns transcript in mock mode', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/rapid-orders/transcribe')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
audioFileUri: 'gs://krow-workforce-dev-private/uploads/test-user/request.webm',
|
||||
locale: 'en-US',
|
||||
promptHints: ['server', 'urgent'],
|
||||
});
|
||||
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(typeof res.body.transcript, 'string');
|
||||
assert.ok(res.body.transcript.length > 0);
|
||||
assert.equal(typeof res.body.confidence, 'number');
|
||||
assert.equal(typeof res.body.model, 'string');
|
||||
assert.equal(typeof res.body.requestId, 'string');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/transcribe rejects non-owned file URI', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/rapid-orders/transcribe')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
audioFileUri: 'gs://krow-workforce-dev-private/uploads/other-user/request.webm',
|
||||
locale: 'en-US',
|
||||
});
|
||||
|
||||
assert.equal(res.status, 403);
|
||||
assert.equal(res.body.code, 'FORBIDDEN');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/parse returns structured rapid order draft', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/rapid-orders/parse')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
text: 'Need 2 servers ASAP for 4 hours',
|
||||
locale: 'en-US',
|
||||
timezone: 'America/New_York',
|
||||
now: '2026-02-27T12:00:00.000Z',
|
||||
});
|
||||
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(res.body.parsed.orderType, 'ONE_TIME');
|
||||
assert.equal(res.body.parsed.isRapid, true);
|
||||
assert.equal(Array.isArray(res.body.parsed.positions), true);
|
||||
assert.equal(res.body.parsed.positions[0].role, 'server');
|
||||
assert.equal(res.body.parsed.positions[0].count, 2);
|
||||
assert.equal(res.body.parsed.durationMinutes, 240);
|
||||
assert.equal(typeof res.body.confidence.overall, 'number');
|
||||
assert.equal(typeof res.body.requestId, 'string');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/parse validates timezone', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/rapid-orders/parse')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
text: 'Need 2 servers ASAP',
|
||||
timezone: 'Mars/OlympusMons',
|
||||
});
|
||||
|
||||
assert.equal(res.status, 400);
|
||||
assert.equal(res.body.code, 'VALIDATION_ERROR');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/parse rejects unknown fields', async () => {
|
||||
const app = createApp();
|
||||
const res = await request(app)
|
||||
.post('/core/rapid-orders/parse')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
text: 'Need 2 servers ASAP',
|
||||
unexpected: 'not-allowed',
|
||||
});
|
||||
|
||||
assert.equal(res.status, 400);
|
||||
assert.equal(res.body.code, 'VALIDATION_ERROR');
|
||||
});
|
||||
|
||||
test('POST /core/rapid-orders/parse enforces per-user model rate limit', async () => {
|
||||
process.env.LLM_RATE_LIMIT_PER_MINUTE = '1';
|
||||
const app = createApp();
|
||||
|
||||
const first = await request(app)
|
||||
.post('/core/rapid-orders/parse')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
text: 'Need 2 servers ASAP for 4 hours',
|
||||
});
|
||||
|
||||
const second = await request(app)
|
||||
.post('/core/rapid-orders/parse')
|
||||
.set('Authorization', 'Bearer test-token')
|
||||
.send({
|
||||
text: 'Need 3 bartenders tonight',
|
||||
});
|
||||
|
||||
assert.equal(first.status, 200);
|
||||
assert.equal(second.status, 429);
|
||||
assert.equal(second.body.code, 'RATE_LIMITED');
|
||||
assert.equal(typeof second.headers['retry-after'], 'string');
|
||||
});
|
||||
|
||||
test('POST /core/verifications creates async job and GET returns status', async () => {
|
||||
const app = createApp();
|
||||
const created = await request(app)
|
||||
|
||||
Reference in New Issue
Block a user