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
6 changes: 3 additions & 3 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ export const ACTOR_MAX_MEMORY_MBYTES = 4_096; // If the Actor requires 8GB of me

// Tool output
/**
* Usual tool output limit is 25k tokens, let's use 20k
* just in case where 1 token =~ 4 characters thus 80k chars.
* Usual tool output limit is 25k tokens where 1 token =~ 4 characters
* thus 50k chars so we have some buffer becase there was some issue with Claude code Actor call output token count.
* This is primarily used for Actor tool call output, but we can then
* reuse this in other tools as well.
*/
export const TOOL_MAX_OUTPUT_CHARS = 80000;
export const TOOL_MAX_OUTPUT_CHARS = 50000;

// MCP Server
export const SERVER_NAME = 'apify-mcp-server';
Expand Down
2 changes: 1 addition & 1 deletion src/utils/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function ensureOutputWithinCharLimit(items: DatasetItem[], importantField
* If important fields are defined, use only those fields for that fallback step.
*/
let sourceItems = items;
// Try only the important fields
// Try keeping only the important fields
if (importantFields.length > 0) {
const importantItems = items.map((item) => getValuesByDotKeys(item, importantFields));
const importantItemsString = JSON.stringify(importantItems);
Expand Down
39 changes: 38 additions & 1 deletion tests/unit/utils.actor.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';

import { getActorDefinitionStorageFieldNames } from '../../src/utils/actor.js';
import { ensureOutputWithinCharLimit, getActorDefinitionStorageFieldNames } from '../../src/utils/actor.js';

describe('getActorDefinitionStorageFieldNames', () => {
it('should return an array of field names from a single view (display.properties and transformation.fields)', () => {
Expand Down Expand Up @@ -98,3 +98,40 @@ describe('getActorDefinitionStorageFieldNames', () => {
expect(result.sort()).toEqual(['bar', 'baz', 'foo']);
});
});

describe('ensureOutputWithinCharLimit', () => {
it('should return all items when limit is high', () => {
const items = [
{ id: 1, name: 'Item 1', value: 'test' },
{ id: 2, name: 'Item 2', value: 'test' },
];
const charLimit = JSON.stringify(items).length;
const result = ensureOutputWithinCharLimit(items, [], charLimit);
expect(result).toEqual(items);
});

it('should use important fields when all items exceed limit', () => {
const items = [
{ id: 1, name: 'Item 1', description: 'Very long description that makes this item exceed the limit', extra: 'unnecessary data' },
{ id: 2, name: 'Item 2', description: 'Another long description', extra: 'more unnecessary data' },
];
const importantFields = ['id', 'name'];
const charLimit = 100; // Very small limit
const result = ensureOutputWithinCharLimit(items, importantFields, charLimit);
expect(result).toEqual([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
]);
});

it('should remove all items when limit is extremely small', () => {
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
];
const charLimit = 10; // Extremely small limit - even empty array JSON "[]" is 2 chars
const result = ensureOutputWithinCharLimit(items, [], charLimit);
expect(result).toEqual([]);
expect(JSON.stringify(result).length).toBeLessThanOrEqual(charLimit);
});
});