feat: enable remote SDK and resilient device orchestration
This commit is contained in:
1 parent
3cc711df51
commit
ddfa420945
110 files changed
+14450
-12954
No files matched your search
@@ -283,6 +283,39 @@ export function consolidateLogsToBlocks(rawLogs: any[]): StepBlock[] {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache for the token-estimate fallback. Tool payloads can carry multi-megabyte
|
||||
* base64 screenshots; serializing them on every recompute would block the main
|
||||
* thread, so each payload object is measured exactly once.
|
||||
*/
|
||||
const payloadSizeCache = new WeakMap<object, { isImage: boolean; length: number }>();
|
||||
|
||||
function estimatePayloadSize(payload: any): { isImage: boolean; length: number } {
|
||||
if (typeof payload === 'string') {
|
||||
return {
|
||||
isImage: payload.includes('data:image/') || payload.includes('base64,'),
|
||||
length: payload.length
|
||||
};
|
||||
}
|
||||
if (payload === null || typeof payload !== 'object') {
|
||||
return { isImage: false, length: String(payload).length };
|
||||
}
|
||||
const cached = payloadSizeCache.get(payload);
|
||||
if (cached) return cached;
|
||||
let payloadStr = '';
|
||||
try {
|
||||
payloadStr = JSON.stringify(payload) || '';
|
||||
} catch {
|
||||
payloadStr = String(payload);
|
||||
}
|
||||
const result = {
|
||||
isImage: payloadStr.includes('data:image/') || payloadStr.includes('base64,'),
|
||||
length: payloadStr.length
|
||||
};
|
||||
payloadSizeCache.set(payload, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely extract and aggregate token usage for a step block
|
||||
*/
|
||||
@@ -345,11 +378,11 @@ export function extractBlockTokens(block: StepBlock): { total: number; prompt: n
|
||||
if (data.generic_tools && Array.isArray(data.generic_tools)) {
|
||||
data.generic_tools.forEach((t: any) => {
|
||||
if (t.payload) {
|
||||
const payloadStr = typeof t.payload === 'string' ? t.payload : JSON.stringify(t.payload);
|
||||
if (payloadStr.includes('data:image/') || payloadStr.includes('base64,')) {
|
||||
const estimate = estimatePayloadSize(t.payload);
|
||||
if (estimate.isImage) {
|
||||
numImages += 1;
|
||||
} else {
|
||||
textLen += payloadStr.length;
|
||||
textLen += estimate.length;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -18,11 +18,27 @@ import { ActionParam } from '../core/models/stream.model';
|
||||
import { isAndroidAction, isReportStatusAction } from './action-formatter.util';
|
||||
import { extractNumbersFromCoordinateValue, isPureDirectionString, parseSequenceCoordinates } from './image-overlay.util';
|
||||
|
||||
// Tool objects are replaced (not mutated) when a trace is updated, so a
|
||||
// WeakMap keyed on the tool is a safe memo for the parsed-args lookup that
|
||||
// templates would otherwise re-run (including JSON.parse) on every render.
|
||||
const toolArgsCache = new WeakMap<object, any>();
|
||||
|
||||
/**
|
||||
* Extract arguments from tool payload or direct args field
|
||||
*/
|
||||
export function getToolArgs(tool: any): any {
|
||||
if (!tool) return {};
|
||||
if (typeof tool === 'object') {
|
||||
const cached = toolArgsCache.get(tool);
|
||||
if (cached !== undefined) return cached;
|
||||
const args = computeToolArgs(tool);
|
||||
toolArgsCache.set(tool, args);
|
||||
return args;
|
||||
}
|
||||
return computeToolArgs(tool);
|
||||
}
|
||||
|
||||
function computeToolArgs(tool: any): any {
|
||||
if (tool.payload) {
|
||||
let payloadObj = tool.payload;
|
||||
if (typeof payloadObj === 'string') {
|
||||
|
||||
Reference in new issue
Block a user