mirror of https://github.com/buster-so/buster.git
Merge branch 'staging' into big-nate/bus-1374-remove-dashboard-cache-if-a-metric-version-is-updated
This commit is contained in:
commit
d96bb62a2e
|
@ -11,7 +11,7 @@
|
|||
"build": "tsup",
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"dev:build": "tsup --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"start": "bun dist/index.js",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest --coverage",
|
||||
|
|
|
@ -44,9 +44,22 @@ export class SlackOAuthService {
|
|||
'channels:history',
|
||||
'channels:read',
|
||||
'chat:write',
|
||||
'im:write',
|
||||
'im:read',
|
||||
'im:history',
|
||||
'mpim:read',
|
||||
'mpim:history',
|
||||
'mpim:write',
|
||||
'chat:write.public',
|
||||
'users:read',
|
||||
'users:read.email',
|
||||
'app_mentions:read',
|
||||
'commands',
|
||||
'groups:history',
|
||||
'groups:write',
|
||||
'files:write',
|
||||
'files:read',
|
||||
'reactions:write',
|
||||
],
|
||||
},
|
||||
tokenStorage,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"deploy": "npx trigger.dev@v4-beta deploy",
|
||||
"prebuild": "node scripts/validate-env.js",
|
||||
"build": "echo 'No build step required but we run it to make sure env is loaded' && tsc --noEmit",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
"noNonNullAssertion": "error",
|
||||
"useImportType": "warn",
|
||||
"useNodejsImportProtocol": "error",
|
||||
"useConsistentArrayType": "error"
|
||||
"useConsistentArrayType": "error",
|
||||
"noUnusedTemplateLiteral": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noExplicitAny": "error",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||
"dev": "tsc --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:watch": "vitest",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"typecheck": "tsc --noEmit",
|
||||
"dev": "tsc --watch",
|
||||
"dev:mastra": "mastra dev --dir src",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
|
|
|
@ -258,6 +258,7 @@ ${params.sqlDialectGuidance}
|
|||
- Only the following chart types are supported: table, line, bar, combo, pie/donut, number cards, and scatter plot. Other chart types are not supported.
|
||||
- You cannot write Python code or perform advanced analyses such as forecasting or modeling.
|
||||
- You cannot highlight or flag specific elements (e.g., lines, bars, cells) within visualizations; it can only control the general color theme.
|
||||
- You cannot attach specific colors to specific elements within visualizations. Only general color themes are supported.
|
||||
- Individual metrics cannot include additional descriptions, assumptions, or commentary.
|
||||
- Dashboard layout constraints:
|
||||
- Dashboards display collections of existing metrics referenced by their IDs.
|
||||
|
|
|
@ -509,6 +509,8 @@ ${params.sqlDialectGuidance}
|
|||
- The system is read-only and cannot write to databases.
|
||||
- Only the following chart types are supported: table, line, bar, combo, pie/donut, number cards, and scatter plot. Other chart types are not supported.
|
||||
- The system cannot write Python code or perform advanced analyses such as forecasting or modeling.
|
||||
- You cannot highlight or flag specific elements (e.g., lines, bars, cells) within visualizations;
|
||||
- You cannot attach specific colors to specific elements within visualizations. Only general color themes are supported.
|
||||
- Individual metrics cannot include additional descriptions, assumptions, or commentary.
|
||||
- Dashboard layout constraints:
|
||||
- Dashboards display collections of existing metrics referenced by their IDs.
|
||||
|
|
|
@ -95,8 +95,15 @@ function createDataMetadata(results: Record<string, unknown>[]): DataMetadata {
|
|||
columnType = ColumnType.Timestamp;
|
||||
simpleType = SimpleType.Date;
|
||||
} else if (typeof firstValue === 'string') {
|
||||
// Check if it looks like a date
|
||||
if (!Number.isNaN(Date.parse(firstValue))) {
|
||||
// Check if it's a numeric string first
|
||||
if (!Number.isNaN(Number(firstValue))) {
|
||||
columnType = Number.isInteger(Number(firstValue)) ? ColumnType.Int4 : ColumnType.Float8;
|
||||
simpleType = SimpleType.Number;
|
||||
} else if (
|
||||
!Number.isNaN(Date.parse(firstValue)) &&
|
||||
// Additional check to avoid parsing simple numbers as dates
|
||||
(firstValue.includes('-') || firstValue.includes('/') || firstValue.includes(':'))
|
||||
) {
|
||||
columnType = ColumnType.Timestamp;
|
||||
simpleType = SimpleType.Date;
|
||||
} else {
|
||||
|
@ -112,7 +119,13 @@ function createDataMetadata(results: Record<string, unknown>[]): DataMetadata {
|
|||
|
||||
if (values.length > 0) {
|
||||
if (simpleType === SimpleType.Number) {
|
||||
const numValues = values.filter((v) => typeof v === 'number') as number[];
|
||||
const numValues = values
|
||||
.map((v) => {
|
||||
if (typeof v === 'number') return v;
|
||||
if (typeof v === 'string' && !Number.isNaN(Number(v))) return Number(v);
|
||||
return null;
|
||||
})
|
||||
.filter((v) => v !== null) as number[];
|
||||
if (numValues.length > 0) {
|
||||
minValue = Math.min(...numValues);
|
||||
maxValue = Math.max(...numValues);
|
||||
|
|
|
@ -326,24 +326,25 @@ export function cleanupIncompleteToolCalls(messages: CoreMessage[]): CoreMessage
|
|||
|
||||
if (msg.role === 'assistant' && Array.isArray(msg.content)) {
|
||||
const toolCalls = msg.content.filter(
|
||||
c => typeof c === 'object' && 'type' in c && c.type === 'tool-call'
|
||||
(c) => typeof c === 'object' && 'type' in c && c.type === 'tool-call'
|
||||
);
|
||||
|
||||
// Check if any tool calls lack results
|
||||
const orphanedToolCalls = toolCalls.filter(toolCall => {
|
||||
const orphanedToolCalls = toolCalls.filter((toolCall) => {
|
||||
// Look ahead for matching tool result
|
||||
for (let j = i + 1; j < cleaned.length; j++) {
|
||||
const nextMsg = cleaned[j];
|
||||
if (!nextMsg) continue; // Add guard for undefined
|
||||
|
||||
|
||||
if (nextMsg.role === 'tool' && Array.isArray(nextMsg.content)) {
|
||||
const hasResult = nextMsg.content.some(
|
||||
c => typeof c === 'object' &&
|
||||
'type' in c &&
|
||||
c.type === 'tool-result' &&
|
||||
'toolCallId' in c &&
|
||||
'toolCallId' in toolCall &&
|
||||
c.toolCallId === toolCall.toolCallId
|
||||
(c) =>
|
||||
typeof c === 'object' &&
|
||||
'type' in c &&
|
||||
c.type === 'tool-result' &&
|
||||
'toolCallId' in c &&
|
||||
'toolCallId' in toolCall &&
|
||||
c.toolCallId === toolCall.toolCallId
|
||||
);
|
||||
if (hasResult) return false;
|
||||
}
|
||||
|
@ -353,11 +354,18 @@ export function cleanupIncompleteToolCalls(messages: CoreMessage[]): CoreMessage
|
|||
|
||||
if (orphanedToolCalls.length > 0) {
|
||||
// Remove the entire assistant message with orphaned tool calls
|
||||
console.info(`cleanupIncompleteToolCalls: Removing assistant message with ${orphanedToolCalls.length} orphaned tool calls`, {
|
||||
messageIndex: i,
|
||||
orphanedToolCallIds: orphanedToolCalls.map(tc => 'toolCallId' in tc ? tc.toolCallId : 'unknown'),
|
||||
textContent: msg.content.filter(c => typeof c === 'object' && 'type' in c && c.type === 'text').map(c => 'text' in c ? c.text : ''),
|
||||
});
|
||||
console.info(
|
||||
`cleanupIncompleteToolCalls: Removing assistant message with ${orphanedToolCalls.length} orphaned tool calls`,
|
||||
{
|
||||
messageIndex: i,
|
||||
orphanedToolCallIds: orphanedToolCalls.map((tc) =>
|
||||
'toolCallId' in tc ? tc.toolCallId : 'unknown'
|
||||
),
|
||||
textContent: msg.content
|
||||
.filter((c) => typeof c === 'object' && 'type' in c && c.type === 'text')
|
||||
.map((c) => ('text' in c ? c.text : '')),
|
||||
}
|
||||
);
|
||||
cleaned.splice(i, 1);
|
||||
break; // Only clean up the last problematic message
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import type { CoreMessage } from 'ai';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { cleanupIncompleteToolCalls } from '../../../src/utils/retry';
|
||||
|
||||
describe('cleanupIncompleteToolCalls', () => {
|
||||
|
@ -7,15 +7,15 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Hello'
|
||||
content: 'Hello',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'text', text: 'Let me help' },
|
||||
{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} }
|
||||
]
|
||||
}
|
||||
{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} },
|
||||
],
|
||||
},
|
||||
// No tool result - orphaned
|
||||
];
|
||||
|
||||
|
@ -28,16 +28,14 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} }
|
||||
]
|
||||
content: [{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} }],
|
||||
},
|
||||
{
|
||||
role: 'tool',
|
||||
content: [
|
||||
{ type: 'tool-result', toolCallId: '123', toolName: 'getTodo', result: { todo: 'test' } }
|
||||
]
|
||||
}
|
||||
{ type: 'tool-result', toolCallId: '123', toolName: 'getTodo', result: { todo: 'test' } },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const cleaned = cleanupIncompleteToolCalls(messages);
|
||||
|
@ -50,10 +48,8 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} },
|
||||
]
|
||||
}
|
||||
content: [{ type: 'tool-call', toolCallId: '123', toolName: 'getTodo', args: {} }],
|
||||
},
|
||||
// Missing result for toolCallId '123' - partially orphaned
|
||||
];
|
||||
|
||||
|
@ -65,27 +61,30 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: '111', toolName: 'getTodo', args: {} }
|
||||
]
|
||||
content: [{ type: 'tool-call', toolCallId: '111', toolName: 'getTodo', args: {} }],
|
||||
},
|
||||
{
|
||||
role: 'tool',
|
||||
content: [
|
||||
{ type: 'tool-result', toolCallId: '111', toolName: 'getTodo', result: { todo: 'first' } }
|
||||
]
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolCallId: '111',
|
||||
toolName: 'getTodo',
|
||||
result: { todo: 'first' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Another request'
|
||||
content: 'Another request',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'text', text: 'Processing...' },
|
||||
{ type: 'tool-call', toolCallId: '222', toolName: 'createTodo', args: { title: 'new' } }
|
||||
]
|
||||
}
|
||||
{ type: 'tool-call', toolCallId: '222', toolName: 'createTodo', args: { title: 'new' } },
|
||||
],
|
||||
},
|
||||
// No result for '222' - orphaned
|
||||
];
|
||||
|
||||
|
@ -100,12 +99,12 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Hello'
|
||||
content: 'Hello',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: 'Hi there, how can I help?'
|
||||
}
|
||||
content: 'Hi there, how can I help?',
|
||||
},
|
||||
];
|
||||
|
||||
const cleaned = cleanupIncompleteToolCalls(messages);
|
||||
|
@ -126,9 +125,9 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
content: [
|
||||
{ type: 'text', text: 'Let me search for that' },
|
||||
{ type: 'tool-call', toolCallId: '789', toolName: 'search', args: { query: 'test' } },
|
||||
{ type: 'text', text: 'Searching now...' }
|
||||
]
|
||||
}
|
||||
{ type: 'text', text: 'Searching now...' },
|
||||
],
|
||||
},
|
||||
// No tool result - orphaned
|
||||
];
|
||||
|
||||
|
@ -141,15 +140,18 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
{
|
||||
role: 'tool',
|
||||
content: [
|
||||
{ type: 'tool-result', toolCallId: '999', toolName: 'getTodo', result: { error: 'Not found' } }
|
||||
]
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolCallId: '999',
|
||||
toolName: 'getTodo',
|
||||
result: { error: 'Not found' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: '999', toolName: 'getTodo', args: {} }
|
||||
]
|
||||
}
|
||||
content: [{ type: 'tool-call', toolCallId: '999', toolName: 'getTodo', args: {} }],
|
||||
},
|
||||
];
|
||||
|
||||
const cleaned = cleanupIncompleteToolCalls(messages);
|
||||
|
@ -163,16 +165,26 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: 'abc', toolName: 'getTodo', args: {} },
|
||||
{ type: 'tool-call', toolCallId: 'def', toolName: 'createTodo', args: { title: 'new' } }
|
||||
]
|
||||
{ type: 'tool-call', toolCallId: 'def', toolName: 'createTodo', args: { title: 'new' } },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'tool',
|
||||
content: [
|
||||
{ type: 'tool-result', toolCallId: 'abc', toolName: 'getTodo', result: { todo: 'existing' } },
|
||||
{ type: 'tool-result', toolCallId: 'def', toolName: 'createTodo', result: { id: 1, title: 'new' } }
|
||||
]
|
||||
}
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolCallId: 'abc',
|
||||
toolName: 'getTodo',
|
||||
result: { todo: 'existing' },
|
||||
},
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolCallId: 'def',
|
||||
toolName: 'createTodo',
|
||||
result: { id: 1, title: 'new' },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const cleaned = cleanupIncompleteToolCalls(messages);
|
||||
|
@ -184,14 +196,12 @@ describe('cleanupIncompleteToolCalls', () => {
|
|||
const messages: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'text', text: 'Here is your answer' }
|
||||
]
|
||||
}
|
||||
content: [{ type: 'text', text: 'Here is your answer' }],
|
||||
},
|
||||
];
|
||||
|
||||
const cleaned = cleanupIncompleteToolCalls(messages);
|
||||
expect(cleaned).toHaveLength(1); // No changes
|
||||
expect(cleaned).toEqual(messages);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, it, expect, vi } from 'vitest';
|
||||
import type { CoreMessage } from 'ai';
|
||||
import { APICallError } from 'ai';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { detectRetryableError, handleRetryWithHealing } from '../../../src/utils/retry';
|
||||
import type { RetryableError, WorkflowContext } from '../../../src/utils/retry';
|
||||
|
||||
|
@ -12,7 +12,7 @@ describe('529 error handling', () => {
|
|||
responseHeaders: {},
|
||||
responseBody: 'Server is overloaded, please try again',
|
||||
url: 'https://api.example.com',
|
||||
requestBodyValues: {}
|
||||
requestBodyValues: {},
|
||||
});
|
||||
|
||||
const result = detectRetryableError(error);
|
||||
|
@ -27,36 +27,39 @@ describe('529 error handling', () => {
|
|||
const messagesWithOrphan: CoreMessage[] = [
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Please analyze this data'
|
||||
content: 'Please analyze this data',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'text', text: 'Let me analyze that for you' },
|
||||
{ type: 'tool-call', toolCallId: 'tc-123', toolName: 'analyzeData', args: { data: 'test' } }
|
||||
]
|
||||
}
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolCallId: 'tc-123',
|
||||
toolName: 'analyzeData',
|
||||
args: { data: 'test' },
|
||||
},
|
||||
],
|
||||
},
|
||||
// No tool result - connection interrupted
|
||||
];
|
||||
|
||||
const retryableError: RetryableError = {
|
||||
type: 'overloaded-error',
|
||||
originalError: new Error('529'),
|
||||
healingMessage: { role: 'user', content: 'Server overloaded (529). Retrying after cleanup...' },
|
||||
requiresMessageCleanup: true
|
||||
healingMessage: {
|
||||
role: 'user',
|
||||
content: 'Server overloaded (529). Retrying after cleanup...',
|
||||
},
|
||||
requiresMessageCleanup: true,
|
||||
};
|
||||
|
||||
const context: WorkflowContext = {
|
||||
const context: WorkflowContext = {
|
||||
currentStep: 'analyst',
|
||||
availableTools: new Set(['analyzeData', 'createMetrics'])
|
||||
availableTools: new Set(['analyzeData', 'createMetrics']),
|
||||
};
|
||||
|
||||
const result = await handleRetryWithHealing(
|
||||
retryableError,
|
||||
messagesWithOrphan,
|
||||
0,
|
||||
context
|
||||
);
|
||||
const result = await handleRetryWithHealing(retryableError, messagesWithOrphan, 0, context);
|
||||
|
||||
expect(result.healedMessages).toHaveLength(1); // Only user message remains
|
||||
expect(result.healedMessages[0]?.role).toBe('user');
|
||||
|
@ -71,7 +74,7 @@ describe('529 error handling', () => {
|
|||
responseHeaders: {},
|
||||
responseBody: 'Overloaded',
|
||||
url: 'https://api.example.com',
|
||||
requestBodyValues: {}
|
||||
requestBodyValues: {},
|
||||
});
|
||||
|
||||
const error500 = new APICallError({
|
||||
|
@ -80,7 +83,7 @@ describe('529 error handling', () => {
|
|||
responseHeaders: {},
|
||||
responseBody: 'Internal error',
|
||||
url: 'https://api.example.com',
|
||||
requestBodyValues: {}
|
||||
requestBodyValues: {},
|
||||
});
|
||||
|
||||
const result529 = detectRetryableError(error529);
|
||||
|
@ -94,19 +97,17 @@ describe('529 error handling', () => {
|
|||
});
|
||||
|
||||
it('should use longer backoff for 529 errors', async () => {
|
||||
const messages: CoreMessage[] = [
|
||||
{ role: 'user', content: 'Test' }
|
||||
];
|
||||
const messages: CoreMessage[] = [{ role: 'user', content: 'Test' }];
|
||||
|
||||
const retryableError: RetryableError = {
|
||||
type: 'overloaded-error',
|
||||
originalError: new Error('529'),
|
||||
healingMessage: { role: 'user', content: 'Retrying...' }
|
||||
healingMessage: { role: 'user', content: 'Retrying...' },
|
||||
};
|
||||
|
||||
const context: WorkflowContext = {
|
||||
const context: WorkflowContext = {
|
||||
currentStep: 'analyst', // Changed from 'test' to valid value
|
||||
availableTools: new Set()
|
||||
availableTools: new Set(),
|
||||
};
|
||||
|
||||
const result = await handleRetryWithHealing(
|
||||
|
@ -122,41 +123,36 @@ describe('529 error handling', () => {
|
|||
|
||||
it('should log cleanup details', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'info');
|
||||
|
||||
|
||||
const messagesWithMultipleOrphans: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: 'tc-1', toolName: 'tool1', args: {} },
|
||||
{ type: 'tool-call', toolCallId: 'tc-2', toolName: 'tool2', args: {} }
|
||||
]
|
||||
}
|
||||
{ type: 'tool-call', toolCallId: 'tc-2', toolName: 'tool2', args: {} },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const retryableError: RetryableError = {
|
||||
type: 'overloaded-error',
|
||||
originalError: new Error('529'),
|
||||
healingMessage: { role: 'user', content: 'Retrying...' }
|
||||
healingMessage: { role: 'user', content: 'Retrying...' },
|
||||
};
|
||||
|
||||
const context: WorkflowContext = {
|
||||
const context: WorkflowContext = {
|
||||
currentStep: 'analyst',
|
||||
availableTools: new Set()
|
||||
availableTools: new Set(),
|
||||
};
|
||||
|
||||
await handleRetryWithHealing(
|
||||
retryableError,
|
||||
messagesWithMultipleOrphans,
|
||||
0,
|
||||
context
|
||||
);
|
||||
await handleRetryWithHealing(retryableError, messagesWithMultipleOrphans, 0, context);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'analyst: Cleaned incomplete tool calls after 529 error',
|
||||
expect.objectContaining({
|
||||
originalCount: 1,
|
||||
cleanedCount: 0,
|
||||
removed: 1
|
||||
removed: 1,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -167,37 +163,35 @@ describe('529 error handling', () => {
|
|||
const completeMessages: CoreMessage[] = [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'tool-call', toolCallId: 'tc-123', toolName: 'getTodo', args: {} }
|
||||
]
|
||||
content: [{ type: 'tool-call', toolCallId: 'tc-123', toolName: 'getTodo', args: {} }],
|
||||
},
|
||||
{
|
||||
role: 'tool',
|
||||
content: [
|
||||
{ type: 'tool-result', toolCallId: 'tc-123', toolName: 'getTodo', result: { todo: 'test' } }
|
||||
]
|
||||
}
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolCallId: 'tc-123',
|
||||
toolName: 'getTodo',
|
||||
result: { todo: 'test' },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const retryableError: RetryableError = {
|
||||
type: 'overloaded-error',
|
||||
originalError: new Error('529'),
|
||||
healingMessage: { role: 'user', content: 'Retrying...' }
|
||||
healingMessage: { role: 'user', content: 'Retrying...' },
|
||||
};
|
||||
|
||||
const context: WorkflowContext = {
|
||||
const context: WorkflowContext = {
|
||||
currentStep: 'analyst',
|
||||
availableTools: new Set()
|
||||
availableTools: new Set(),
|
||||
};
|
||||
|
||||
const result = await handleRetryWithHealing(
|
||||
retryableError,
|
||||
completeMessages,
|
||||
0,
|
||||
context
|
||||
);
|
||||
const result = await handleRetryWithHealing(retryableError, completeMessages, 0, context);
|
||||
|
||||
expect(result.healedMessages).toHaveLength(2); // No cleanup needed
|
||||
expect(result.healedMessages).toEqual(completeMessages);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"build": "tsc",
|
||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"lint:fix": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
"db:studio": "drizzle-kit studio",
|
||||
"db:init": "echo 'dev:init should be run from turbo.json' && true",
|
||||
"dev": "echo 'Running db:init from turbo.json' && npm run db:init",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"stop": "pnpm run db:stop",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"lint:fix": "biome check --apply .",
|
||||
"format": "biome format .",
|
||||
"format:fix": "biome format --write ."
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"prebuild": "tsx scripts/type-import-check.ts",
|
||||
"build": "tsc --build",
|
||||
"dev": "tsc --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"dev": "tsc --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"build": "tsc",
|
||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:watch": "vitest watch",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"prebuild": "node scripts/validate-env.js",
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"module": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc --build",
|
||||
"lint": "biome check",
|
||||
"lint": "biome check --write",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest --coverage",
|
||||
"test:ui": "vitest --ui",
|
||||
|
|
Loading…
Reference in New Issue