@promptbook/remote-server 0.112.0-12 → 0.112.0-15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/index.es.js +553 -2381
- package/esm/index.es.js.map +1 -1
- package/esm/src/cli/cli-commands/coder/{find-fresh-emoji-tag.d.ts → find-fresh-emoji-tags.d.ts} +1 -1
- package/esm/src/cli/cli-commands/coder.d.ts +1 -1
- package/esm/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
- package/esm/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
- package/esm/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
- package/esm/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
- package/esm/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
- package/esm/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
- package/esm/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +1 -1
- package/esm/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
- package/esm/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
- package/esm/src/llm-providers/google/google-models.d.ts +1 -1
- package/esm/src/llm-providers/openai/openai-models.d.ts +1 -1
- package/esm/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +1 -2
- package/esm/src/scrapers/document/DocumentScraper.d.ts +1 -2
- package/esm/src/scrapers/document-legacy/LegacyDocumentScraper.d.ts +1 -2
- package/esm/src/scripting/javascript/postprocessing-functions.d.ts +1 -1
- package/esm/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +1 -2
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -3
- package/umd/index.umd.js +627 -2452
- package/umd/index.umd.js.map +1 -1
- package/umd/src/cli/cli-commands/coder/{find-fresh-emoji-tag.d.ts → find-fresh-emoji-tags.d.ts} +1 -1
- package/umd/src/cli/cli-commands/coder.d.ts +1 -1
- package/umd/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
- package/umd/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
- package/umd/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
- package/umd/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
- package/umd/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
- package/umd/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
- package/umd/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +1 -1
- package/umd/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
- package/umd/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
- package/umd/src/llm-providers/google/google-models.d.ts +1 -1
- package/umd/src/llm-providers/openai/openai-models.d.ts +1 -1
- package/umd/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +1 -2
- package/umd/src/scrapers/document/DocumentScraper.d.ts +1 -2
- package/umd/src/scrapers/document-legacy/LegacyDocumentScraper.d.ts +1 -2
- package/umd/src/scripting/javascript/postprocessing-functions.d.ts +1 -1
- package/umd/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +1 -2
- package/umd/src/version.d.ts +1 -1
- package/esm/apps/agents-server/config.d.ts +0 -86
- package/esm/apps/agents-server/src/tools/$provideBrowserForServer.d.ts +0 -28
- package/esm/apps/agents-server/src/tools/BrowserConnectionProvider.d.ts +0 -142
- package/esm/apps/agents-server/src/tools/runBrowserArtifacts.d.ts +0 -25
- package/esm/apps/agents-server/src/tools/runBrowserConstants.d.ts +0 -21
- package/esm/apps/agents-server/src/tools/runBrowserErrorHandling.d.ts +0 -60
- package/esm/apps/agents-server/src/tools/runBrowserErrors.d.ts +0 -73
- package/esm/apps/agents-server/src/tools/runBrowserObservability.d.ts +0 -36
- package/esm/apps/agents-server/src/tools/runBrowserResultFormatting.d.ts +0 -47
- package/esm/apps/agents-server/src/tools/runBrowserRuntime.d.ts +0 -24
- package/esm/apps/agents-server/src/tools/runBrowserWorkflow.d.ts +0 -36
- package/esm/apps/agents-server/src/tools/run_browser.d.ts +0 -11
- package/esm/apps/agents-server/src/utils/retryWithBackoff.d.ts +0 -95
- package/esm/apps/agents-server/src/utils/runBrowserArtifactStorage.d.ts +0 -26
- package/umd/apps/agents-server/config.d.ts +0 -86
- package/umd/apps/agents-server/src/tools/$provideBrowserForServer.d.ts +0 -28
- package/umd/apps/agents-server/src/tools/BrowserConnectionProvider.d.ts +0 -142
- package/umd/apps/agents-server/src/tools/runBrowserArtifacts.d.ts +0 -25
- package/umd/apps/agents-server/src/tools/runBrowserConstants.d.ts +0 -21
- package/umd/apps/agents-server/src/tools/runBrowserErrorHandling.d.ts +0 -60
- package/umd/apps/agents-server/src/tools/runBrowserErrors.d.ts +0 -73
- package/umd/apps/agents-server/src/tools/runBrowserObservability.d.ts +0 -36
- package/umd/apps/agents-server/src/tools/runBrowserResultFormatting.d.ts +0 -47
- package/umd/apps/agents-server/src/tools/runBrowserRuntime.d.ts +0 -24
- package/umd/apps/agents-server/src/tools/runBrowserWorkflow.d.ts +0 -36
- package/umd/apps/agents-server/src/tools/run_browser.d.ts +0 -11
- package/umd/apps/agents-server/src/utils/retryWithBackoff.d.ts +0 -95
- package/umd/apps/agents-server/src/utils/runBrowserArtifactStorage.d.ts +0 -26
package/esm/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join, basename, dirname, isAbsolute } from 'path';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import colors from 'colors';
|
|
4
|
-
import
|
|
4
|
+
import _spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
5
5
|
import { forTime } from 'waitasecond';
|
|
6
6
|
import express from 'express';
|
|
7
7
|
import * as OpenApiValidator from 'express-openapi-validator';
|
|
@@ -9,15 +9,12 @@ import http from 'http';
|
|
|
9
9
|
import { Server } from 'socket.io';
|
|
10
10
|
import swaggerUi from 'swagger-ui-express';
|
|
11
11
|
import { stat, access, constants, readFile, writeFile, readdir, mkdir, watch, rm } from 'fs/promises';
|
|
12
|
-
import { randomBytes
|
|
12
|
+
import { randomBytes } from 'crypto';
|
|
13
13
|
import { SHA256 } from 'crypto-js';
|
|
14
14
|
import hexEncoder from 'crypto-js/enc-hex';
|
|
15
15
|
import { Readability } from '@mozilla/readability';
|
|
16
16
|
import { JSDOM } from 'jsdom';
|
|
17
17
|
import { Converter } from 'showdown';
|
|
18
|
-
import { tmpdir } from 'os';
|
|
19
|
-
import { ConfigChecker } from 'configchecker';
|
|
20
|
-
import { chromium } from 'playwright';
|
|
21
18
|
import { createElement } from 'react';
|
|
22
19
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
23
20
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
@@ -43,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
43
40
|
* @generated
|
|
44
41
|
* @see https://github.com/webgptorg/promptbook
|
|
45
42
|
*/
|
|
46
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
43
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-15';
|
|
47
44
|
/**
|
|
48
45
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
49
46
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -1432,7 +1429,7 @@ async function startAgentServer(options) {
|
|
|
1432
1429
|
function getErrorReportUrl(error) {
|
|
1433
1430
|
const report = {
|
|
1434
1431
|
title: `🐜 Error report from ${NAME}`,
|
|
1435
|
-
body: spaceTrim$
|
|
1432
|
+
body: spaceTrim$1((block) => `
|
|
1436
1433
|
|
|
1437
1434
|
|
|
1438
1435
|
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
@@ -1899,7 +1896,7 @@ function serializeError(error) {
|
|
|
1899
1896
|
const { name, message, stack } = error;
|
|
1900
1897
|
const { id } = error;
|
|
1901
1898
|
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
1902
|
-
console.error(spaceTrim$
|
|
1899
|
+
console.error(spaceTrim$1((block) => `
|
|
1903
1900
|
|
|
1904
1901
|
Cannot serialize error with name "${name}"
|
|
1905
1902
|
|
|
@@ -2245,7 +2242,7 @@ function checkSerializableAsJson(options) {
|
|
|
2245
2242
|
}
|
|
2246
2243
|
else if (typeof value === 'object') {
|
|
2247
2244
|
if (value instanceof Date) {
|
|
2248
|
-
throw new UnexpectedError(spaceTrim$
|
|
2245
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2249
2246
|
\`${name}\` is Date
|
|
2250
2247
|
|
|
2251
2248
|
Use \`string_date_iso8601\` instead
|
|
@@ -2264,7 +2261,7 @@ function checkSerializableAsJson(options) {
|
|
|
2264
2261
|
throw new UnexpectedError(`${name} is RegExp`);
|
|
2265
2262
|
}
|
|
2266
2263
|
else if (value instanceof Error) {
|
|
2267
|
-
throw new UnexpectedError(spaceTrim$
|
|
2264
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2268
2265
|
\`${name}\` is unserialized Error
|
|
2269
2266
|
|
|
2270
2267
|
Use function \`serializeError\`
|
|
@@ -2287,7 +2284,7 @@ function checkSerializableAsJson(options) {
|
|
|
2287
2284
|
}
|
|
2288
2285
|
catch (error) {
|
|
2289
2286
|
assertsError(error);
|
|
2290
|
-
throw new UnexpectedError(spaceTrim$
|
|
2287
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2291
2288
|
\`${name}\` is not serializable
|
|
2292
2289
|
|
|
2293
2290
|
${block(error.stack || error.message)}
|
|
@@ -2319,7 +2316,7 @@ function checkSerializableAsJson(options) {
|
|
|
2319
2316
|
}
|
|
2320
2317
|
}
|
|
2321
2318
|
else {
|
|
2322
|
-
throw new UnexpectedError(spaceTrim$
|
|
2319
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2323
2320
|
\`${name}\` is unknown type
|
|
2324
2321
|
|
|
2325
2322
|
Additional message for \`${name}\`:
|
|
@@ -2982,7 +2979,7 @@ function jsonParse(value) {
|
|
|
2982
2979
|
}
|
|
2983
2980
|
else if (typeof value !== 'string') {
|
|
2984
2981
|
console.error('Can not parse JSON from non-string value.', { text: value });
|
|
2985
|
-
throw new Error(spaceTrim$
|
|
2982
|
+
throw new Error(spaceTrim$1(`
|
|
2986
2983
|
Can not parse JSON from non-string value.
|
|
2987
2984
|
|
|
2988
2985
|
The value type: ${typeof value}
|
|
@@ -2996,7 +2993,7 @@ function jsonParse(value) {
|
|
|
2996
2993
|
if (!(error instanceof Error)) {
|
|
2997
2994
|
throw error;
|
|
2998
2995
|
}
|
|
2999
|
-
throw new Error(spaceTrim$
|
|
2996
|
+
throw new Error(spaceTrim$1((block) => `
|
|
3000
2997
|
${block(error.message)}
|
|
3001
2998
|
|
|
3002
2999
|
The expected JSON text:
|
|
@@ -3049,7 +3046,7 @@ function deserializeError(error, isStackAddedToMessage = true) {
|
|
|
3049
3046
|
message = `${name}: ${message}`;
|
|
3050
3047
|
}
|
|
3051
3048
|
if (isStackAddedToMessage && stack !== undefined && stack !== '') {
|
|
3052
|
-
message = spaceTrim$
|
|
3049
|
+
message = spaceTrim$1((block) => `
|
|
3053
3050
|
${block(message)}
|
|
3054
3051
|
|
|
3055
3052
|
Original stack trace:
|
|
@@ -3604,7 +3601,7 @@ function pipelineJsonToString(pipelineJson) {
|
|
|
3604
3601
|
pipelineString += '\n\n';
|
|
3605
3602
|
pipelineString += '```' + contentLanguage;
|
|
3606
3603
|
pipelineString += '\n';
|
|
3607
|
-
pipelineString += spaceTrim$
|
|
3604
|
+
pipelineString += spaceTrim$1(content);
|
|
3608
3605
|
// <- TODO: [main] !!3 Escape
|
|
3609
3606
|
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
3610
3607
|
pipelineString += '\n';
|
|
@@ -4036,14 +4033,14 @@ class MultipleLlmExecutionTools {
|
|
|
4036
4033
|
if (description === undefined) {
|
|
4037
4034
|
return headLine;
|
|
4038
4035
|
}
|
|
4039
|
-
return spaceTrim$
|
|
4036
|
+
return spaceTrim$1((block) => `
|
|
4040
4037
|
${headLine}
|
|
4041
4038
|
|
|
4042
4039
|
${ /* <- Note: Indenting the description: */block(description)}
|
|
4043
4040
|
`);
|
|
4044
4041
|
})
|
|
4045
4042
|
.join('\n\n');
|
|
4046
|
-
return spaceTrim$
|
|
4043
|
+
return spaceTrim$1((block) => `
|
|
4047
4044
|
Multiple LLM Providers:
|
|
4048
4045
|
|
|
4049
4046
|
${block(innerModelsTitlesAndDescriptions)}
|
|
@@ -4145,7 +4142,7 @@ class MultipleLlmExecutionTools {
|
|
|
4145
4142
|
// 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
4146
4143
|
// 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
4147
4144
|
// 3) ...
|
|
4148
|
-
spaceTrim$
|
|
4145
|
+
spaceTrim$1((block) => `
|
|
4149
4146
|
All execution tools of ${this.title} failed:
|
|
4150
4147
|
|
|
4151
4148
|
${block(errors
|
|
@@ -4158,7 +4155,7 @@ class MultipleLlmExecutionTools {
|
|
|
4158
4155
|
throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\` into ${this.title}`);
|
|
4159
4156
|
}
|
|
4160
4157
|
else {
|
|
4161
|
-
throw new PipelineExecutionError(spaceTrim$
|
|
4158
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
4162
4159
|
You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}" into ${this.title}
|
|
4163
4160
|
|
|
4164
4161
|
Available \`LlmExecutionTools\`:
|
|
@@ -4195,7 +4192,7 @@ class MultipleLlmExecutionTools {
|
|
|
4195
4192
|
*/
|
|
4196
4193
|
function joinLlmExecutionTools(title, ...llmExecutionTools) {
|
|
4197
4194
|
if (llmExecutionTools.length === 0) {
|
|
4198
|
-
const warningMessage = spaceTrim$
|
|
4195
|
+
const warningMessage = spaceTrim$1(`
|
|
4199
4196
|
You have not provided any \`LlmExecutionTools\`
|
|
4200
4197
|
This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
|
|
4201
4198
|
|
|
@@ -4512,14 +4509,14 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
4512
4509
|
return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
|
|
4513
4510
|
});
|
|
4514
4511
|
if (metadata.length === 0) {
|
|
4515
|
-
return spaceTrim$
|
|
4512
|
+
return spaceTrim$1(`
|
|
4516
4513
|
**No scrapers are available**
|
|
4517
4514
|
|
|
4518
4515
|
This is a unexpected behavior, you are probably using some broken version of Promptbook
|
|
4519
4516
|
At least there should be available the metadata of the scrapers
|
|
4520
4517
|
`);
|
|
4521
4518
|
}
|
|
4522
|
-
return spaceTrim$
|
|
4519
|
+
return spaceTrim$1((block) => `
|
|
4523
4520
|
Available scrapers are:
|
|
4524
4521
|
${block(metadata
|
|
4525
4522
|
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
|
|
@@ -5025,7 +5022,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
|
|
|
5025
5022
|
else if (urlOrRequest instanceof Request) {
|
|
5026
5023
|
url = urlOrRequest.url;
|
|
5027
5024
|
}
|
|
5028
|
-
throw new PromptbookFetchError(spaceTrim$
|
|
5025
|
+
throw new PromptbookFetchError(spaceTrim$1((block) => `
|
|
5029
5026
|
Can not fetch "${url}"
|
|
5030
5027
|
|
|
5031
5028
|
Fetch error:
|
|
@@ -5185,7 +5182,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
5185
5182
|
const fileExtension = getFileExtension(filename);
|
|
5186
5183
|
const mimeType = extensionToMimeType(fileExtension || '');
|
|
5187
5184
|
if (!(await isFileExisting(filename, tools.fs))) {
|
|
5188
|
-
throw new NotFoundError(spaceTrim$
|
|
5185
|
+
throw new NotFoundError(spaceTrim$1((block) => `
|
|
5189
5186
|
Can not make source handler for file which does not exist:
|
|
5190
5187
|
|
|
5191
5188
|
File:
|
|
@@ -5278,7 +5275,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
5278
5275
|
// <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
|
|
5279
5276
|
break;
|
|
5280
5277
|
}
|
|
5281
|
-
console.warn(spaceTrim$
|
|
5278
|
+
console.warn(spaceTrim$1((block) => `
|
|
5282
5279
|
Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
|
|
5283
5280
|
|
|
5284
5281
|
The source:
|
|
@@ -5294,7 +5291,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
5294
5291
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
5295
5292
|
}
|
|
5296
5293
|
if (partialPieces === null) {
|
|
5297
|
-
throw new KnowledgeScrapeError(spaceTrim$
|
|
5294
|
+
throw new KnowledgeScrapeError(spaceTrim$1((block) => `
|
|
5298
5295
|
Cannot scrape knowledge
|
|
5299
5296
|
|
|
5300
5297
|
The source:
|
|
@@ -5869,7 +5866,7 @@ const CsvFormatParser = {
|
|
|
5869
5866
|
const { value, outputParameterName, settings, mapCallback, onProgress } = options;
|
|
5870
5867
|
const csv = csvParse(value, settings);
|
|
5871
5868
|
if (csv.errors.length !== 0) {
|
|
5872
|
-
throw new CsvFormatError(spaceTrim$
|
|
5869
|
+
throw new CsvFormatError(spaceTrim$1((block) => `
|
|
5873
5870
|
CSV parsing error
|
|
5874
5871
|
|
|
5875
5872
|
Error(s) from CSV parsing:
|
|
@@ -5914,7 +5911,7 @@ const CsvFormatParser = {
|
|
|
5914
5911
|
const { value, settings, mapCallback, onProgress } = options;
|
|
5915
5912
|
const csv = csvParse(value, settings);
|
|
5916
5913
|
if (csv.errors.length !== 0) {
|
|
5917
|
-
throw new CsvFormatError(spaceTrim$
|
|
5914
|
+
throw new CsvFormatError(spaceTrim$1((block) => `
|
|
5918
5915
|
CSV parsing error
|
|
5919
5916
|
|
|
5920
5917
|
Error(s) from CSV parsing:
|
|
@@ -6124,7 +6121,7 @@ function mapAvailableToExpectedParameters(options) {
|
|
|
6124
6121
|
}
|
|
6125
6122
|
// Phase 2️⃣: Non-matching mapping
|
|
6126
6123
|
if (expectedParameterNames.size !== availableParametersNames.size) {
|
|
6127
|
-
throw new PipelineExecutionError(spaceTrim$
|
|
6124
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
6128
6125
|
Can not map available parameters to expected parameters
|
|
6129
6126
|
|
|
6130
6127
|
Mapped parameters:
|
|
@@ -6927,7 +6924,7 @@ async function executeFormatSubvalues(options) {
|
|
|
6927
6924
|
return /* not await */ executeAttempts({ ...options, logLlmCall });
|
|
6928
6925
|
}
|
|
6929
6926
|
if (jokerParameterNames.length !== 0) {
|
|
6930
|
-
throw new UnexpectedError(spaceTrim$
|
|
6927
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
6931
6928
|
JOKER parameters are not supported together with FOREACH command
|
|
6932
6929
|
|
|
6933
6930
|
[🧞♀️] This should be prevented in \`validatePipeline\`
|
|
@@ -6940,7 +6937,7 @@ async function executeFormatSubvalues(options) {
|
|
|
6940
6937
|
if (formatDefinition === undefined) {
|
|
6941
6938
|
throw new UnexpectedError(
|
|
6942
6939
|
// <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
6943
|
-
spaceTrim$
|
|
6940
|
+
spaceTrim$1((block) => `
|
|
6944
6941
|
Unsupported format "${task.foreach.formatName}"
|
|
6945
6942
|
|
|
6946
6943
|
Available formats:
|
|
@@ -6957,7 +6954,7 @@ async function executeFormatSubvalues(options) {
|
|
|
6957
6954
|
if (subvalueParser === undefined) {
|
|
6958
6955
|
throw new UnexpectedError(
|
|
6959
6956
|
// <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
6960
|
-
spaceTrim$
|
|
6957
|
+
spaceTrim$1((block) => `
|
|
6961
6958
|
Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
|
|
6962
6959
|
|
|
6963
6960
|
Available subformat names for format "${formatDefinition.formatName}":
|
|
@@ -6997,7 +6994,7 @@ async function executeFormatSubvalues(options) {
|
|
|
6997
6994
|
if (!(error instanceof PipelineExecutionError)) {
|
|
6998
6995
|
throw error;
|
|
6999
6996
|
}
|
|
7000
|
-
const highLevelError = new PipelineExecutionError(spaceTrim$
|
|
6997
|
+
const highLevelError = new PipelineExecutionError(spaceTrim$1((block) => `
|
|
7001
6998
|
${error.message}
|
|
7002
6999
|
|
|
7003
7000
|
This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
|
|
@@ -7021,7 +7018,7 @@ async function executeFormatSubvalues(options) {
|
|
|
7021
7018
|
...options,
|
|
7022
7019
|
priority: priority + index,
|
|
7023
7020
|
parameters: allSubparameters,
|
|
7024
|
-
pipelineIdentification: spaceTrim$
|
|
7021
|
+
pipelineIdentification: spaceTrim$1((block) => `
|
|
7025
7022
|
${block(pipelineIdentification)}
|
|
7026
7023
|
Subparameter index: ${index}
|
|
7027
7024
|
`),
|
|
@@ -7030,7 +7027,7 @@ async function executeFormatSubvalues(options) {
|
|
|
7030
7027
|
}
|
|
7031
7028
|
catch (error) {
|
|
7032
7029
|
if (length > BIG_DATASET_TRESHOLD) {
|
|
7033
|
-
console.error(spaceTrim$
|
|
7030
|
+
console.error(spaceTrim$1((block) => `
|
|
7034
7031
|
${error.message}
|
|
7035
7032
|
|
|
7036
7033
|
This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
|
|
@@ -7920,13 +7917,13 @@ function $registeredLlmToolsMessage() {
|
|
|
7920
7917
|
});
|
|
7921
7918
|
const usedEnvMessage = `Unknown \`.env\` file` ;
|
|
7922
7919
|
if (metadata.length === 0) {
|
|
7923
|
-
return spaceTrim$
|
|
7920
|
+
return spaceTrim$1((block) => `
|
|
7924
7921
|
No LLM providers are available.
|
|
7925
7922
|
|
|
7926
7923
|
${block(usedEnvMessage)}
|
|
7927
7924
|
`);
|
|
7928
7925
|
}
|
|
7929
|
-
return spaceTrim$
|
|
7926
|
+
return spaceTrim$1((block) => `
|
|
7930
7927
|
|
|
7931
7928
|
${block(usedEnvMessage)}
|
|
7932
7929
|
|
|
@@ -7972,7 +7969,7 @@ function $registeredLlmToolsMessage() {
|
|
|
7972
7969
|
morePieces.push(`Not configured`); // <- Note: Can not be configured via environment variables
|
|
7973
7970
|
}
|
|
7974
7971
|
}
|
|
7975
|
-
let providerMessage = spaceTrim$
|
|
7972
|
+
let providerMessage = spaceTrim$1(`
|
|
7976
7973
|
${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
7977
7974
|
${morePieces.join('; ')}
|
|
7978
7975
|
`);
|
|
@@ -8018,7 +8015,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
8018
8015
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
8019
8016
|
if (registeredItem === undefined) {
|
|
8020
8017
|
// console.log('$llmToolsRegister.list()', $llmToolsRegister.list());
|
|
8021
|
-
throw new Error(spaceTrim$
|
|
8018
|
+
throw new Error(spaceTrim$1((block) => `
|
|
8022
8019
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
8023
8020
|
Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
|
|
8024
8021
|
|
|
@@ -8397,7 +8394,7 @@ function buildParametersSection(items) {
|
|
|
8397
8394
|
const entries = items
|
|
8398
8395
|
.flatMap((item) => formatParameterListItem(item).split(/\r?\n/))
|
|
8399
8396
|
.filter((line) => line !== '');
|
|
8400
|
-
return spaceTrim$
|
|
8397
|
+
return spaceTrim$1((block) => `
|
|
8401
8398
|
**Parameters:**
|
|
8402
8399
|
${block(entries.join('\n'))}
|
|
8403
8400
|
|
|
@@ -8470,7 +8467,7 @@ function isPromptString(value) {
|
|
|
8470
8467
|
*/
|
|
8471
8468
|
function prompt(strings, ...values) {
|
|
8472
8469
|
if (values.length === 0) {
|
|
8473
|
-
return new PromptString(spaceTrim$
|
|
8470
|
+
return new PromptString(spaceTrim$1(strings.join('')));
|
|
8474
8471
|
}
|
|
8475
8472
|
const stringsWithHiddenParameters = strings.map((stringsItem) => ParameterEscaping.hideBrackets(stringsItem));
|
|
8476
8473
|
const parameterMetadata = values.map((value) => {
|
|
@@ -8511,7 +8508,7 @@ function prompt(strings, ...values) {
|
|
|
8511
8508
|
? `${result}${stringsItem}`
|
|
8512
8509
|
: `${result}${stringsItem}${ParameterSection.formatParameterPlaceholder(parameterName)}`;
|
|
8513
8510
|
}, '');
|
|
8514
|
-
pipelineString = spaceTrim$
|
|
8511
|
+
pipelineString = spaceTrim$1(pipelineString);
|
|
8515
8512
|
try {
|
|
8516
8513
|
pipelineString = templateParameters(pipelineString, parameters);
|
|
8517
8514
|
}
|
|
@@ -8520,7 +8517,7 @@ function prompt(strings, ...values) {
|
|
|
8520
8517
|
throw error;
|
|
8521
8518
|
}
|
|
8522
8519
|
console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
|
|
8523
|
-
throw new UnexpectedError(spaceTrim$
|
|
8520
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
8524
8521
|
Internal error in prompt template literal
|
|
8525
8522
|
|
|
8526
8523
|
${block(JSON.stringify({ strings, values }, null, 4))}}
|
|
@@ -8601,7 +8598,7 @@ function attachClientVersionHeader(headers) {
|
|
|
8601
8598
|
* @public exported from `@promptbook/utils`
|
|
8602
8599
|
*/
|
|
8603
8600
|
function computeHash(value) {
|
|
8604
|
-
return SHA256(hexEncoder.parse(spaceTrim$
|
|
8601
|
+
return SHA256(hexEncoder.parse(spaceTrim$1(valueToString(value)))).toString( /* hex */);
|
|
8605
8602
|
}
|
|
8606
8603
|
/**
|
|
8607
8604
|
* TODO: [🥬][🥬] Use this ACRY
|
|
@@ -10510,8 +10507,8 @@ class MarkdownScraper {
|
|
|
10510
10507
|
knowledgeTextPieces.map(async (knowledgeTextPiece, i) => {
|
|
10511
10508
|
// Note: These are just default values, they will be overwritten by the actual values:
|
|
10512
10509
|
let name = `piece-${i}`;
|
|
10513
|
-
let title = spaceTrim$
|
|
10514
|
-
const knowledgePieceContent = spaceTrim$
|
|
10510
|
+
let title = spaceTrim$1(knowledgeTextPiece.substring(0, 100));
|
|
10511
|
+
const knowledgePieceContent = spaceTrim$1(knowledgeTextPiece);
|
|
10515
10512
|
let keywords = [];
|
|
10516
10513
|
const index = [];
|
|
10517
10514
|
/*
|
|
@@ -10524,7 +10521,7 @@ class MarkdownScraper {
|
|
|
10524
10521
|
isCrashedOnError: true,
|
|
10525
10522
|
});
|
|
10526
10523
|
const { title: titleRaw = 'Untitled' } = titleResult.outputParameters;
|
|
10527
|
-
title = spaceTrim$
|
|
10524
|
+
title = spaceTrim$1(titleRaw) /* <- TODO: Maybe do in pipeline */;
|
|
10528
10525
|
name = titleToName(title);
|
|
10529
10526
|
// --- Keywords
|
|
10530
10527
|
const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise({
|
|
@@ -10877,2200 +10874,190 @@ async function fetchUrlContent(url) {
|
|
|
10877
10874
|
*/
|
|
10878
10875
|
|
|
10879
10876
|
/**
|
|
10880
|
-
*
|
|
10881
|
-
*
|
|
10882
|
-
* @private internal runtime wiring for commitment tools
|
|
10883
|
-
*/
|
|
10884
|
-
const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
|
|
10885
|
-
/**
|
|
10886
|
-
* Hidden argument key used to pass runtime context into individual tool calls.
|
|
10887
|
-
*
|
|
10888
|
-
* @private internal runtime wiring for commitment tools
|
|
10889
|
-
*/
|
|
10890
|
-
const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
|
|
10891
|
-
/**
|
|
10892
|
-
* Prompt parameter key used to pass a hidden tool-progress listener token into script execution.
|
|
10893
|
-
*
|
|
10894
|
-
* @private internal runtime wiring for commitment tools
|
|
10895
|
-
*/
|
|
10896
|
-
const TOOL_PROGRESS_TOKEN_PARAMETER = 'promptbookToolProgressToken';
|
|
10897
|
-
/**
|
|
10898
|
-
* Hidden argument key used to pass a tool-progress listener token into individual tool calls.
|
|
10899
|
-
*
|
|
10900
|
-
* @private internal runtime wiring for commitment tools
|
|
10901
|
-
*/
|
|
10902
|
-
const TOOL_PROGRESS_TOKEN_ARGUMENT = '__promptbookToolProgressToken';
|
|
10903
|
-
/**
|
|
10904
|
-
* Monotonic counter used for hidden progress-listener tokens.
|
|
10877
|
+
* Cached implementation of `run_browser` when it can be resolved.
|
|
10905
10878
|
*
|
|
10906
|
-
* @private internal
|
|
10879
|
+
* @private internal utility for USE BROWSER commitment
|
|
10907
10880
|
*/
|
|
10908
|
-
let
|
|
10881
|
+
let cachedRunBrowserTool = null;
|
|
10909
10882
|
/**
|
|
10910
|
-
*
|
|
10883
|
+
* Cached loading error to avoid repeating expensive resolution attempts.
|
|
10911
10884
|
*
|
|
10912
|
-
* @private internal
|
|
10885
|
+
* @private internal utility for USE BROWSER commitment
|
|
10913
10886
|
*/
|
|
10914
|
-
|
|
10887
|
+
let cachedRunBrowserToolError = null;
|
|
10915
10888
|
/**
|
|
10916
|
-
*
|
|
10889
|
+
* Attempts to load the server-side `run_browser` tool lazily.
|
|
10917
10890
|
*
|
|
10918
|
-
* @
|
|
10891
|
+
* @returns Loaded `run_browser` implementation
|
|
10892
|
+
* @private internal utility for USE BROWSER commitment
|
|
10919
10893
|
*/
|
|
10920
|
-
function
|
|
10921
|
-
if (
|
|
10922
|
-
return
|
|
10894
|
+
function loadRunBrowserToolForNode() {
|
|
10895
|
+
if (cachedRunBrowserTool !== null) {
|
|
10896
|
+
return cachedRunBrowserTool;
|
|
10923
10897
|
}
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10898
|
+
if (cachedRunBrowserToolError !== null) {
|
|
10899
|
+
throw cachedRunBrowserToolError;
|
|
10900
|
+
}
|
|
10901
|
+
try {
|
|
10902
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
10903
|
+
const runBrowserModule = require('../../../apps/agents-server/src/tools/run_browser');
|
|
10904
|
+
if (typeof runBrowserModule.run_browser !== 'function') {
|
|
10905
|
+
throw new Error('run_browser value is not a function but ' + typeof runBrowserModule.run_browser);
|
|
10931
10906
|
}
|
|
10907
|
+
cachedRunBrowserTool = runBrowserModule.run_browser;
|
|
10908
|
+
return cachedRunBrowserTool;
|
|
10932
10909
|
}
|
|
10933
|
-
|
|
10934
|
-
|
|
10910
|
+
catch (error) {
|
|
10911
|
+
assertsError(error);
|
|
10912
|
+
cachedRunBrowserToolError = error;
|
|
10913
|
+
throw error;
|
|
10935
10914
|
}
|
|
10936
|
-
return parsed;
|
|
10937
|
-
}
|
|
10938
|
-
/**
|
|
10939
|
-
* Reads runtime context attached to tool call arguments.
|
|
10940
|
-
*
|
|
10941
|
-
* @private internal runtime wiring for commitment tools
|
|
10942
|
-
*/
|
|
10943
|
-
function readToolRuntimeContextFromToolArgs(args) {
|
|
10944
|
-
return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
|
|
10945
10915
|
}
|
|
10946
10916
|
/**
|
|
10947
|
-
*
|
|
10917
|
+
* Resolves the server-side implementation of the `run_browser` tool for Node.js environments.
|
|
10948
10918
|
*
|
|
10949
|
-
*
|
|
10950
|
-
|
|
10951
|
-
function readToolProgressTokenFromToolArgs(args) {
|
|
10952
|
-
const token = args[TOOL_PROGRESS_TOKEN_ARGUMENT];
|
|
10953
|
-
return typeof token === 'string' && token.trim().length > 0 ? token : null;
|
|
10954
|
-
}
|
|
10955
|
-
/**
|
|
10956
|
-
* Serializes runtime context for prompt parameters.
|
|
10919
|
+
* This uses fully lazy resolution to keep CLI startup independent from optional browser tooling.
|
|
10920
|
+
* When the server tool cannot be resolved, the fallback implementation throws a helpful error.
|
|
10957
10921
|
*
|
|
10958
|
-
* @private internal
|
|
10922
|
+
* @private internal utility for USE BROWSER commitment
|
|
10959
10923
|
*/
|
|
10960
|
-
function
|
|
10961
|
-
return
|
|
10924
|
+
function resolveRunBrowserToolForNode() {
|
|
10925
|
+
return async (args) => {
|
|
10926
|
+
try {
|
|
10927
|
+
const runBrowserTool = loadRunBrowserToolForNode();
|
|
10928
|
+
return await runBrowserTool(args);
|
|
10929
|
+
}
|
|
10930
|
+
catch (error) {
|
|
10931
|
+
assertsError(error);
|
|
10932
|
+
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
10933
|
+
\`run_browser\` tool is not available in this environment.
|
|
10934
|
+
This commitment requires the Agents Server browser runtime with Playwright CLI.
|
|
10935
|
+
|
|
10936
|
+
${error.name}:
|
|
10937
|
+
${block(error.message)}
|
|
10938
|
+
`));
|
|
10939
|
+
}
|
|
10940
|
+
};
|
|
10962
10941
|
}
|
|
10942
|
+
|
|
10963
10943
|
/**
|
|
10964
|
-
*
|
|
10944
|
+
* Resolves the server-side implementation of the send_email tool for Node.js environments.
|
|
10965
10945
|
*
|
|
10966
|
-
*
|
|
10967
|
-
*
|
|
10946
|
+
* This uses a lazy require so the core package can still load even if the Agents Server
|
|
10947
|
+
* module is unavailable. When the server tool cannot be resolved, a fallback implementation
|
|
10948
|
+
* throws a helpful error message.
|
|
10968
10949
|
*
|
|
10969
|
-
* @
|
|
10970
|
-
* @returns Hidden token used to route progress updates.
|
|
10971
|
-
* @private internal runtime wiring for commitment tools
|
|
10950
|
+
* @private internal utility for USE EMAIL commitment
|
|
10972
10951
|
*/
|
|
10973
|
-
function
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10952
|
+
function resolveSendEmailToolForNode() {
|
|
10953
|
+
try {
|
|
10954
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
10955
|
+
const { send_email } = require('../../../apps/agents-server/src/tools/send_email');
|
|
10956
|
+
if (typeof send_email !== 'function') {
|
|
10957
|
+
throw new Error('send_email value is not a function but ' + typeof send_email);
|
|
10958
|
+
}
|
|
10959
|
+
return send_email;
|
|
10960
|
+
}
|
|
10961
|
+
catch (error) {
|
|
10962
|
+
const normalizedError = error instanceof Error
|
|
10963
|
+
? error
|
|
10964
|
+
: new Error(typeof error === 'string' ? error : JSON.stringify(error !== null && error !== void 0 ? error : 'Unknown error'));
|
|
10965
|
+
return async () => {
|
|
10966
|
+
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
10967
|
+
\`send_email\` tool is not available in this environment.
|
|
10968
|
+
This commitment requires Agents Server runtime with wallet-backed SMTP sending.
|
|
10969
|
+
|
|
10970
|
+
${normalizedError.name}:
|
|
10971
|
+
${block(normalizedError.message)}
|
|
10972
|
+
`));
|
|
10973
|
+
};
|
|
10974
|
+
}
|
|
10978
10975
|
}
|
|
10976
|
+
|
|
10979
10977
|
/**
|
|
10980
|
-
*
|
|
10978
|
+
* Resolves the server-side `spawn_agent` tool for Node.js runtimes.
|
|
10981
10979
|
*
|
|
10982
|
-
*
|
|
10983
|
-
* @private internal runtime wiring for commitment tools
|
|
10984
|
-
*/
|
|
10985
|
-
function unregisterToolCallProgressListener(token) {
|
|
10986
|
-
toolCallProgressListeners.delete(token);
|
|
10987
|
-
}
|
|
10988
|
-
/**
|
|
10989
|
-
* Emits one tool progress update using a hidden token carried in tool arguments.
|
|
10980
|
+
* Uses lazy require so core package can load outside Agents Server.
|
|
10990
10981
|
*
|
|
10991
|
-
* @
|
|
10992
|
-
* @param update - Incremental progress update.
|
|
10993
|
-
* @returns `true` when a listener was found and notified.
|
|
10994
|
-
* @private internal runtime wiring for commitment tools
|
|
10982
|
+
* @private internal utility for USE SPAWN commitment
|
|
10995
10983
|
*/
|
|
10996
|
-
function
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
10984
|
+
function resolveSpawnAgentToolForNode() {
|
|
10985
|
+
try {
|
|
10986
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
10987
|
+
const { spawn_agent } = require('../../../apps/agents-server/src/tools/spawn_agent');
|
|
10988
|
+
if (typeof spawn_agent !== 'function') {
|
|
10989
|
+
throw new Error('spawn_agent value is not a function but ' + typeof spawn_agent);
|
|
10990
|
+
}
|
|
10991
|
+
return spawn_agent;
|
|
11000
10992
|
}
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
10993
|
+
catch (error) {
|
|
10994
|
+
const normalizedError = error instanceof Error
|
|
10995
|
+
? error
|
|
10996
|
+
: new Error(typeof error === 'string' ? error : JSON.stringify(error !== null && error !== void 0 ? error : 'Unknown error'));
|
|
10997
|
+
return async () => {
|
|
10998
|
+
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
10999
|
+
\`spawn_agent\` tool is not available in this environment.
|
|
11000
|
+
This commitment requires Agents Server runtime with agent persistence enabled.
|
|
11001
|
+
|
|
11002
|
+
${normalizedError.name}:
|
|
11003
|
+
${block(normalizedError.message)}
|
|
11004
|
+
`));
|
|
11005
|
+
};
|
|
11004
11006
|
}
|
|
11005
|
-
listener(update);
|
|
11006
|
-
return true;
|
|
11007
11007
|
}
|
|
11008
|
-
/**
|
|
11009
|
-
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
11010
|
-
*/
|
|
11011
11008
|
|
|
11012
11009
|
/**
|
|
11013
|
-
*
|
|
11010
|
+
* Generates a regex pattern to match a specific commitment
|
|
11014
11011
|
*
|
|
11015
|
-
*
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
* Runtime environment variable that overrides local artifact storage directory.
|
|
11020
|
-
*/
|
|
11021
|
-
const RUN_BROWSER_ARTIFACT_STORAGE_DIRECTORY_ENV = 'RUN_BROWSER_ARTIFACT_STORAGE_DIRECTORY';
|
|
11022
|
-
/**
|
|
11023
|
-
* Default writable directory for `run_browser` screenshot/video artifacts.
|
|
11024
|
-
*/
|
|
11025
|
-
const DEFAULT_RUN_BROWSER_ARTIFACT_STORAGE_DIRECTORY = join(tmpdir(), 'promptbook', 'run-browser-artifacts');
|
|
11026
|
-
/**
|
|
11027
|
-
* Converts Windows separators to POSIX separators for payload paths.
|
|
11028
|
-
*/
|
|
11029
|
-
function toPosixPath(pathname) {
|
|
11030
|
-
return pathname.split('\\').join('/');
|
|
11031
|
-
}
|
|
11032
|
-
/**
|
|
11033
|
-
* Resolves writable filesystem directory used for artifact persistence.
|
|
11012
|
+
* Note: It always creates new Regex object
|
|
11013
|
+
* Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
|
|
11014
|
+
*
|
|
11015
|
+
* @private - TODO: [🧠] Maybe should be public?
|
|
11034
11016
|
*/
|
|
11035
|
-
function
|
|
11036
|
-
const
|
|
11037
|
-
|
|
11038
|
-
|
|
11017
|
+
function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
|
|
11018
|
+
const allCommitments = [commitment, ...aliases];
|
|
11019
|
+
const patterns = allCommitments.map((commitment) => {
|
|
11020
|
+
const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
11021
|
+
return escapedCommitment.split(/\s+/).join('\\s+');
|
|
11022
|
+
});
|
|
11023
|
+
const keywordPattern = patterns.join('|');
|
|
11024
|
+
if (requiresContent) {
|
|
11025
|
+
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
|
|
11026
|
+
}
|
|
11027
|
+
else {
|
|
11028
|
+
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
|
|
11039
11029
|
}
|
|
11040
|
-
return DEFAULT_RUN_BROWSER_ARTIFACT_STORAGE_DIRECTORY;
|
|
11041
|
-
}
|
|
11042
|
-
/**
|
|
11043
|
-
* Resolves absolute filesystem path of one artifact filename.
|
|
11044
|
-
*/
|
|
11045
|
-
function resolveRunBrowserArtifactFilesystemPath(artifactFilename) {
|
|
11046
|
-
return join(resolveRunBrowserArtifactStorageDirectory(), artifactFilename);
|
|
11047
11030
|
}
|
|
11048
11031
|
/**
|
|
11049
|
-
*
|
|
11032
|
+
* Generates a regex pattern to match a specific commitment type
|
|
11033
|
+
*
|
|
11034
|
+
* Note: It just matches the type part of the commitment
|
|
11035
|
+
* Note: It always creates new Regex object
|
|
11036
|
+
* Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
|
|
11037
|
+
*
|
|
11038
|
+
* @private
|
|
11050
11039
|
*/
|
|
11051
|
-
function
|
|
11052
|
-
|
|
11040
|
+
function createCommitmentTypeRegex(commitment, aliases = []) {
|
|
11041
|
+
const allCommitments = [commitment, ...aliases];
|
|
11042
|
+
const patterns = allCommitments.map((commitment) => {
|
|
11043
|
+
const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
11044
|
+
return escapedCommitment.split(/\s+/).join('\\s+');
|
|
11045
|
+
});
|
|
11046
|
+
const keywordPattern = patterns.join('|');
|
|
11047
|
+
const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
|
|
11048
|
+
return regex;
|
|
11053
11049
|
}
|
|
11054
11050
|
|
|
11055
11051
|
/**
|
|
11056
|
-
*
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
* Error thrown when a remote Playwright browser cannot be reached.
|
|
11052
|
+
* Base implementation of CommitmentDefinition that provides common functionality
|
|
11053
|
+
* Most commitments can extend this class and only override the applyToAgentModelRequirements method
|
|
11054
|
+
*
|
|
11055
|
+
* @private
|
|
11061
11056
|
*/
|
|
11062
|
-
class
|
|
11063
|
-
constructor(
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
this.code = REMOTE_BROWSER_UNAVAILABLE_ERROR_CODE;
|
|
11067
|
-
this.isRetryable = true;
|
|
11068
|
-
this.debug = options.debug;
|
|
11069
|
-
this.suggestedNextSteps =
|
|
11070
|
-
(_a = options.suggestedNextSteps) !== null && _a !== void 0 ? _a : [
|
|
11071
|
-
'Verify remote browser infrastructure is running and reachable from Agents Server.',
|
|
11072
|
-
'Check firewall and DNS routing for the remote browser host and port.',
|
|
11073
|
-
'Retry later or continue with non-graphical fallback scraping.',
|
|
11074
|
-
];
|
|
11075
|
-
this.cause = options.cause;
|
|
11076
|
-
Object.setPrototypeOf(this, RemoteBrowserUnavailableError.prototype);
|
|
11077
|
-
}
|
|
11078
|
-
}
|
|
11079
|
-
/**
|
|
11080
|
-
* Returns true when an unknown value is one of the remote-browser outage errors.
|
|
11081
|
-
*/
|
|
11082
|
-
function isRemoteBrowserUnavailableError(error) {
|
|
11083
|
-
return error instanceof RemoteBrowserUnavailableError;
|
|
11084
|
-
}
|
|
11085
|
-
/**
|
|
11086
|
-
* Sanitizes a remote websocket endpoint so debug payloads never expose path secrets.
|
|
11087
|
-
*/
|
|
11088
|
-
function sanitizeRemoteBrowserEndpoint(wsEndpoint) {
|
|
11089
|
-
var _a, _b;
|
|
11090
|
-
try {
|
|
11091
|
-
const parsedEndpoint = new URL(wsEndpoint);
|
|
11092
|
-
return {
|
|
11093
|
-
protocol: parsedEndpoint.protocol || null,
|
|
11094
|
-
host: parsedEndpoint.hostname || null,
|
|
11095
|
-
port: parsedEndpoint.port ? Number.parseInt(parsedEndpoint.port, 10) : null,
|
|
11096
|
-
};
|
|
11097
|
-
}
|
|
11098
|
-
catch (_c) {
|
|
11099
|
-
const hostPortMatch = wsEndpoint.trim().match(/^(?:wss?:\/\/)?(?<host>[^:/?#]+)(?::(?<port>\d{1,5}))?/i);
|
|
11100
|
-
const host = ((_a = hostPortMatch === null || hostPortMatch === void 0 ? void 0 : hostPortMatch.groups) === null || _a === void 0 ? void 0 : _a.host) || null;
|
|
11101
|
-
const parsedPort = (_b = hostPortMatch === null || hostPortMatch === void 0 ? void 0 : hostPortMatch.groups) === null || _b === void 0 ? void 0 : _b.port;
|
|
11102
|
-
return {
|
|
11103
|
-
protocol: wsEndpoint.startsWith('wss://') ? 'wss:' : wsEndpoint.startsWith('ws://') ? 'ws:' : null,
|
|
11104
|
-
host,
|
|
11105
|
-
port: parsedPort ? Number.parseInt(parsedPort, 10) : null,
|
|
11106
|
-
};
|
|
11107
|
-
}
|
|
11108
|
-
}
|
|
11109
|
-
/**
|
|
11110
|
-
* Extracts network-like error code from unknown error payload.
|
|
11111
|
-
*/
|
|
11112
|
-
function extractNetworkErrorCode(error) {
|
|
11113
|
-
var _a;
|
|
11114
|
-
if (error && typeof error === 'object') {
|
|
11115
|
-
const maybeCode = error.code;
|
|
11116
|
-
if (typeof maybeCode === 'string' && maybeCode.trim()) {
|
|
11117
|
-
return maybeCode.trim().toUpperCase();
|
|
11118
|
-
}
|
|
11119
|
-
}
|
|
11120
|
-
const message = getErrorMessage(error);
|
|
11121
|
-
const match = message.match(/\b(ECONNREFUSED|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ECONNRESET|EHOSTUNREACH|ENETUNREACH)\b/i);
|
|
11122
|
-
return ((_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || null;
|
|
11123
|
-
}
|
|
11124
|
-
/**
|
|
11125
|
-
* Classifies whether an unknown error most likely represents remote browser infra outage.
|
|
11126
|
-
*/
|
|
11127
|
-
function isRemoteBrowserInfrastructureError(error) {
|
|
11128
|
-
const networkErrorCode = extractNetworkErrorCode(error);
|
|
11129
|
-
if (networkErrorCode) {
|
|
11130
|
-
return true;
|
|
11131
|
-
}
|
|
11132
|
-
const message = getErrorMessage(error).toLowerCase();
|
|
11133
|
-
const isWebSocketFailure = message.includes('websocket') ||
|
|
11134
|
-
message.includes('<ws error>') ||
|
|
11135
|
-
message.includes('ws connect error') ||
|
|
11136
|
-
message.includes('socket hang up');
|
|
11137
|
-
const hasHandshakeFailure = message.includes('unexpected server response') ||
|
|
11138
|
-
message.includes('handshake') ||
|
|
11139
|
-
message.includes('code=1006') ||
|
|
11140
|
-
message.includes('disconnected');
|
|
11141
|
-
return isWebSocketFailure && hasHandshakeFailure;
|
|
11142
|
-
}
|
|
11143
|
-
/**
|
|
11144
|
-
* Converts unknown thrown values into safe string messages.
|
|
11145
|
-
*/
|
|
11146
|
-
function getErrorMessage(error) {
|
|
11147
|
-
return error instanceof Error ? error.message : String(error);
|
|
11148
|
-
}
|
|
11149
|
-
/**
|
|
11150
|
-
* Converts unknown errors into stack payloads that are safe to render in debug mode.
|
|
11151
|
-
*/
|
|
11152
|
-
function getErrorStack(error) {
|
|
11153
|
-
return error instanceof Error && error.stack ? error.stack : null;
|
|
11154
|
-
}
|
|
11155
|
-
|
|
11156
|
-
/**
|
|
11157
|
-
* Matches unsupported characters in snapshot file suffixes.
|
|
11158
|
-
*/
|
|
11159
|
-
const SNAPSHOT_FILE_SUFFIX_UNSAFE_CHARACTER_PATTERN = /[^a-z0-9-]/g;
|
|
11160
|
-
/**
|
|
11161
|
-
* Creates one filesystem-safe optional filename suffix for a snapshot.
|
|
11162
|
-
*/
|
|
11163
|
-
function createSnapshotFileSuffix(rawSuffix) {
|
|
11164
|
-
if (!rawSuffix) {
|
|
11165
|
-
return '';
|
|
11166
|
-
}
|
|
11167
|
-
const normalized = rawSuffix
|
|
11168
|
-
.trim()
|
|
11169
|
-
.toLowerCase()
|
|
11170
|
-
.replace(/\s+/g, '-')
|
|
11171
|
-
.replace(SNAPSHOT_FILE_SUFFIX_UNSAFE_CHARACTER_PATTERN, '-')
|
|
11172
|
-
.replace(/-+/g, '-')
|
|
11173
|
-
.replace(/^-|-$/g, '');
|
|
11174
|
-
return normalized;
|
|
11175
|
-
}
|
|
11176
|
-
/**
|
|
11177
|
-
* Resolves snapshot filename for one session and optional stage suffix.
|
|
11178
|
-
*/
|
|
11179
|
-
function resolveSnapshotFilename(sessionId, fileSuffix) {
|
|
11180
|
-
const safeSuffix = createSnapshotFileSuffix(fileSuffix);
|
|
11181
|
-
return safeSuffix ? `${sessionId}-${safeSuffix}.png` : `${sessionId}.png`;
|
|
11182
|
-
}
|
|
11183
|
-
/**
|
|
11184
|
-
* Creates one user-facing description for an executed browser action.
|
|
11185
|
-
*/
|
|
11186
|
-
function formatActionSummary(action) {
|
|
11187
|
-
switch (action.type) {
|
|
11188
|
-
case 'navigate':
|
|
11189
|
-
return `Navigate to ${action.url}`;
|
|
11190
|
-
case 'click':
|
|
11191
|
-
return `Click ${action.selector}`;
|
|
11192
|
-
case 'type':
|
|
11193
|
-
return `Type into ${action.selector}`;
|
|
11194
|
-
case 'wait':
|
|
11195
|
-
return `Wait ${action.milliseconds}ms`;
|
|
11196
|
-
case 'scroll':
|
|
11197
|
-
return action.selector ? `Scroll ${action.pixels}px in ${action.selector}` : `Scroll ${action.pixels}px on page`;
|
|
11198
|
-
}
|
|
11199
|
-
}
|
|
11200
|
-
/**
|
|
11201
|
-
* Screenshot/artifact and page-cleanup helpers for `run_browser`.
|
|
11202
|
-
*
|
|
11203
|
-
* @private function of `run_browser`
|
|
11204
|
-
*/
|
|
11205
|
-
const runBrowserArtifacts = {
|
|
11206
|
-
/**
|
|
11207
|
-
* Captures a screenshot artifact for the current page and returns relative path.
|
|
11208
|
-
*/
|
|
11209
|
-
async captureSnapshot(page, sessionId, fileSuffix) {
|
|
11210
|
-
const snapshotFilename = resolveSnapshotFilename(sessionId, fileSuffix);
|
|
11211
|
-
const snapshotDirectoryPath = resolveRunBrowserArtifactStorageDirectory();
|
|
11212
|
-
const snapshotPath = resolveRunBrowserArtifactFilesystemPath(snapshotFilename);
|
|
11213
|
-
try {
|
|
11214
|
-
await mkdir(snapshotDirectoryPath, { recursive: true });
|
|
11215
|
-
try {
|
|
11216
|
-
await page.screenshot({ path: snapshotPath, fullPage: true });
|
|
11217
|
-
}
|
|
11218
|
-
catch (error) {
|
|
11219
|
-
console.warn('[run_browser] Full-page snapshot failed, retrying viewport-only screenshot', {
|
|
11220
|
-
sessionId,
|
|
11221
|
-
snapshotFilename,
|
|
11222
|
-
error: getErrorMessage(error),
|
|
11223
|
-
});
|
|
11224
|
-
await page.screenshot({ path: snapshotPath, fullPage: false });
|
|
11225
|
-
}
|
|
11226
|
-
return resolveRunBrowserArtifactPublicPath(snapshotFilename);
|
|
11227
|
-
}
|
|
11228
|
-
catch (error) {
|
|
11229
|
-
console.error('[run_browser] Failed to capture snapshot', {
|
|
11230
|
-
sessionId,
|
|
11231
|
-
snapshotFilename,
|
|
11232
|
-
error: getErrorMessage(error),
|
|
11233
|
-
});
|
|
11234
|
-
return null;
|
|
11235
|
-
}
|
|
11236
|
-
},
|
|
11237
|
-
/**
|
|
11238
|
-
* Safely retrieves page title from current browser page.
|
|
11239
|
-
*/
|
|
11240
|
-
async getPageTitle(page) {
|
|
11241
|
-
try {
|
|
11242
|
-
return await page.title();
|
|
11243
|
-
}
|
|
11244
|
-
catch (_a) {
|
|
11245
|
-
return null;
|
|
11246
|
-
}
|
|
11247
|
-
},
|
|
11248
|
-
/**
|
|
11249
|
-
* Closes browser page and logs non-fatal cleanup errors.
|
|
11250
|
-
*/
|
|
11251
|
-
async cleanupPage(page, sessionId) {
|
|
11252
|
-
if (!page) {
|
|
11253
|
-
return;
|
|
11254
|
-
}
|
|
11255
|
-
try {
|
|
11256
|
-
await page.close();
|
|
11257
|
-
}
|
|
11258
|
-
catch (error) {
|
|
11259
|
-
console.error('[run_browser] Failed to cleanup browser page', {
|
|
11260
|
-
sessionId,
|
|
11261
|
-
error: getErrorMessage(error),
|
|
11262
|
-
});
|
|
11263
|
-
}
|
|
11264
|
-
},
|
|
11265
|
-
/**
|
|
11266
|
-
* Captures one screenshot artifact and enriches it with page metadata.
|
|
11267
|
-
*/
|
|
11268
|
-
async captureSnapshotArtifact(options) {
|
|
11269
|
-
const { page, sessionId, label, fileSuffix, actionIndex, action } = options;
|
|
11270
|
-
const path = await this.captureSnapshot(page, sessionId, fileSuffix);
|
|
11271
|
-
if (!path) {
|
|
11272
|
-
return null;
|
|
11273
|
-
}
|
|
11274
|
-
const actionSummary = action ? formatActionSummary(action) : undefined;
|
|
11275
|
-
return {
|
|
11276
|
-
kind: 'screenshot',
|
|
11277
|
-
label,
|
|
11278
|
-
path,
|
|
11279
|
-
capturedAt: new Date().toISOString(),
|
|
11280
|
-
url: page.url(),
|
|
11281
|
-
title: await this.getPageTitle(page),
|
|
11282
|
-
actionIndex,
|
|
11283
|
-
actionSummary,
|
|
11284
|
-
};
|
|
11285
|
-
},
|
|
11286
|
-
};
|
|
11287
|
-
|
|
11288
|
-
/**
|
|
11289
|
-
* Shared constants used by the `run_browser` tool.
|
|
11290
|
-
*
|
|
11291
|
-
* @private internal constants of `run_browser`
|
|
11292
|
-
*/
|
|
11293
|
-
const runBrowserConstants = {
|
|
11294
|
-
sessionPrefix: 'agents-server-run-browser',
|
|
11295
|
-
snapshotDirectory: '.playwright-cli',
|
|
11296
|
-
resultSchema: 'promptbook/run-browser@1',
|
|
11297
|
-
defaultWaitMs: 1000,
|
|
11298
|
-
maxWaitMs: 60000,
|
|
11299
|
-
defaultScrollPixels: 800,
|
|
11300
|
-
defaultNavigationTimeoutMs: 20000,
|
|
11301
|
-
defaultActionTimeoutMs: 15000,
|
|
11302
|
-
fallbackDynamicContentWarning: 'Remote browser is unavailable. Fallback scraping was used and dynamic content may be missing.',
|
|
11303
|
-
validationErrorCode: 'RUN_BROWSER_VALIDATION_ERROR',
|
|
11304
|
-
navigationFailedErrorCode: 'RUN_BROWSER_NAVIGATION_FAILED',
|
|
11305
|
-
actionFailedErrorCode: 'RUN_BROWSER_ACTION_FAILED',
|
|
11306
|
-
cancelledErrorCode: 'RUN_BROWSER_CANCELLED',
|
|
11307
|
-
unknownErrorCode: 'RUN_BROWSER_UNKNOWN_ERROR',
|
|
11308
|
-
};
|
|
11309
|
-
|
|
11310
|
-
const config = ConfigChecker.from({
|
|
11311
|
-
...process.env,
|
|
11312
|
-
// Note: To expose env variables to the browser, using this seemingly strange syntax:
|
|
11313
|
-
// @see https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#exposing-environment-variables-to-the-browser
|
|
11314
|
-
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
|
|
11315
|
-
NEXT_PUBLIC_VERCEL_ENV: process.env.NEXT_PUBLIC_VERCEL_ENV,
|
|
11316
|
-
NEXT_PUBLIC_VERCEL_TARGET_ENV: process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV,
|
|
11317
|
-
NEXT_PUBLIC_VERCEL_URL: process.env.NEXT_PUBLIC_VERCEL_URL,
|
|
11318
|
-
NEXT_PUBLIC_VERCEL_BRANCH_URL: process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL,
|
|
11319
|
-
NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL: process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL,
|
|
11320
|
-
NEXT_PUBLIC_VERCEL_GIT_PROVIDER: process.env.NEXT_PUBLIC_VERCEL_GIT_PROVIDER,
|
|
11321
|
-
NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER: process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER,
|
|
11322
|
-
NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG: process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG,
|
|
11323
|
-
NEXT_PUBLIC_VERCEL_GIT_REPO_ID: process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_ID,
|
|
11324
|
-
NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
|
|
11325
|
-
NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE,
|
|
11326
|
-
NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF,
|
|
11327
|
-
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME,
|
|
11328
|
-
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
|
|
11329
|
-
NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA: process.env.NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA,
|
|
11330
|
-
NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID: process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID,
|
|
11331
|
-
});
|
|
11332
|
-
/**
|
|
11333
|
-
* Public URL of the deployment, e.g. "https://my-app.vercel.app"
|
|
11334
|
-
*
|
|
11335
|
-
* Note: When a request resolves through the global `_Server` registry,
|
|
11336
|
-
* this URL will be overridden by the matched server domain.
|
|
11337
|
-
*/
|
|
11338
|
-
config.get('NEXT_PUBLIC_SITE_URL').url().value;
|
|
11339
|
-
/**
|
|
11340
|
-
* [♐️] Vercel environment: "development" | "preview" | "production"
|
|
11341
|
-
*/
|
|
11342
|
-
config.get('NEXT_PUBLIC_VERCEL_ENV').value;
|
|
11343
|
-
/**
|
|
11344
|
-
* [♐️] Target environment – can be system or custom
|
|
11345
|
-
*/
|
|
11346
|
-
config.get('NEXT_PUBLIC_VERCEL_TARGET_ENV').value;
|
|
11347
|
-
/**
|
|
11348
|
-
* [♐️] Deployment URL (without https://), e.g. "my-app-abc123.vercel.app"
|
|
11349
|
-
*/
|
|
11350
|
-
config.get('NEXT_PUBLIC_VERCEL_URL').value;
|
|
11351
|
-
/**
|
|
11352
|
-
* [♐️] Branch URL (without https://), only for branch deployments
|
|
11353
|
-
*/
|
|
11354
|
-
config.get('NEXT_PUBLIC_VERCEL_BRANCH_URL').value;
|
|
11355
|
-
/**
|
|
11356
|
-
* [♐️] Production domain of the project
|
|
11357
|
-
*/
|
|
11358
|
-
config.get('NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL').value;
|
|
11359
|
-
/**
|
|
11360
|
-
* [♐️] Git provider (github | gitlab | bitbucket)
|
|
11361
|
-
*/
|
|
11362
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_PROVIDER').value;
|
|
11363
|
-
/**
|
|
11364
|
-
* [♐️] Repository owner (e.g. "hejny")
|
|
11365
|
-
*/
|
|
11366
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER').value;
|
|
11367
|
-
/**
|
|
11368
|
-
* [♐️] Repository slug (e.g. "my-project")
|
|
11369
|
-
*/
|
|
11370
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG').value;
|
|
11371
|
-
/**
|
|
11372
|
-
* [♐️] Repository internal ID
|
|
11373
|
-
*/
|
|
11374
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_REPO_ID').value;
|
|
11375
|
-
/**
|
|
11376
|
-
* [♐️] Git commit SHA (short or long)
|
|
11377
|
-
*/
|
|
11378
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA').value;
|
|
11379
|
-
/**
|
|
11380
|
-
* [♐️] Commit message used for this deployment
|
|
11381
|
-
*/
|
|
11382
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE').value;
|
|
11383
|
-
/**
|
|
11384
|
-
* [♐️] Branch name (ref), e.g. "main"
|
|
11385
|
-
*/
|
|
11386
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF').value;
|
|
11387
|
-
/**
|
|
11388
|
-
* Author name of the commit
|
|
11389
|
-
*/
|
|
11390
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME').value;
|
|
11391
|
-
/**
|
|
11392
|
-
* [♐️] Author login/username
|
|
11393
|
-
*/
|
|
11394
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN').value;
|
|
11395
|
-
/**
|
|
11396
|
-
* [♐️] Previous deployment commit SHA (if exists)
|
|
11397
|
-
*/
|
|
11398
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA').value;
|
|
11399
|
-
/**
|
|
11400
|
-
* [♐️] Pull Request ID for PR-based deployments
|
|
11401
|
-
*/
|
|
11402
|
-
config.get('NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID').value;
|
|
11403
|
-
/**
|
|
11404
|
-
* Supabase table prefix
|
|
11405
|
-
*
|
|
11406
|
-
* This remains the fallback/default prefix used before `_Server` contains records
|
|
11407
|
-
* or for local development requests.
|
|
11408
|
-
*/
|
|
11409
|
-
config.get('SUPABASE_TABLE_PREFIX').value;
|
|
11410
|
-
/**
|
|
11411
|
-
* WebSocket endpoint URL for remote Playwright browser server (e.g., ws://browser-server:3000).
|
|
11412
|
-
*
|
|
11413
|
-
* When set, browser automation will connect to this remote server instead of launching a local browser.
|
|
11414
|
-
* This is useful for environments like Vercel where running a full browser locally is not possible.
|
|
11415
|
-
* Leave empty to use local browser mode.
|
|
11416
|
-
*/
|
|
11417
|
-
const rawRemoteBrowserUrl = config.get('REMOTE_BROWSER_URL').value;
|
|
11418
|
-
/**
|
|
11419
|
-
* WebSocket endpoint URL for remote Playwright browser server (e.g., ws://browser-server:3000).
|
|
11420
|
-
*
|
|
11421
|
-
* When set, browser automation will connect to this remote server instead of launching a local browser.
|
|
11422
|
-
* This is useful for environments like Vercel where running a full browser locally is not possible.
|
|
11423
|
-
* Leave empty to use local browser mode.
|
|
11424
|
-
*/
|
|
11425
|
-
const REMOTE_BROWSER_URL = typeof rawRemoteBrowserUrl === 'string' ? rawRemoteBrowserUrl : '';
|
|
11426
|
-
|
|
11427
|
-
/**
|
|
11428
|
-
* Reads a positive integer value from environment variables.
|
|
11429
|
-
*/
|
|
11430
|
-
function resolvePositiveIntFromEnv$1(variableName, defaultValue) {
|
|
11431
|
-
const rawValue = process.env[variableName];
|
|
11432
|
-
if (!rawValue || !rawValue.trim()) {
|
|
11433
|
-
return defaultValue;
|
|
11434
|
-
}
|
|
11435
|
-
const parsed = Number.parseInt(rawValue.trim(), 10);
|
|
11436
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
11437
|
-
return defaultValue;
|
|
11438
|
-
}
|
|
11439
|
-
return parsed;
|
|
11440
|
-
}
|
|
11441
|
-
/**
|
|
11442
|
-
* Runtime helpers for mode/session/timeout handling in `run_browser`.
|
|
11443
|
-
*
|
|
11444
|
-
* @private function of `run_browser`
|
|
11445
|
-
*/
|
|
11446
|
-
const runBrowserRuntime = {
|
|
11447
|
-
/**
|
|
11448
|
-
* Creates a dedicated session id for one tool invocation.
|
|
11449
|
-
*/
|
|
11450
|
-
createRunBrowserSessionId() {
|
|
11451
|
-
return `${runBrowserConstants.sessionPrefix}-${randomUUID()}`;
|
|
11452
|
-
},
|
|
11453
|
-
/**
|
|
11454
|
-
* Determines whether the browser tool is running in local or remote mode.
|
|
11455
|
-
*/
|
|
11456
|
-
resolveExecutionMode() {
|
|
11457
|
-
return REMOTE_BROWSER_URL && REMOTE_BROWSER_URL.trim().length > 0 ? 'remote' : 'local';
|
|
11458
|
-
},
|
|
11459
|
-
/**
|
|
11460
|
-
* Converts the execution mode into a human-readable label.
|
|
11461
|
-
*/
|
|
11462
|
-
formatExecutionMode(mode) {
|
|
11463
|
-
return mode === 'remote' ? 'remote-browser' : 'local-browser';
|
|
11464
|
-
},
|
|
11465
|
-
/**
|
|
11466
|
-
* Resolves timeout configuration from env defaults and optional call overrides.
|
|
11467
|
-
*/
|
|
11468
|
-
resolveTimeoutConfiguration(overrides) {
|
|
11469
|
-
const envNavigationTimeoutMs = resolvePositiveIntFromEnv$1('RUN_BROWSER_NAVIGATION_TIMEOUT_MS', runBrowserConstants.defaultNavigationTimeoutMs);
|
|
11470
|
-
const envActionTimeoutMs = resolvePositiveIntFromEnv$1('RUN_BROWSER_ACTION_TIMEOUT_MS', runBrowserConstants.defaultActionTimeoutMs);
|
|
11471
|
-
const navigationTimeoutMs = (overrides === null || overrides === void 0 ? void 0 : overrides.navigationMs) && Number.isFinite(overrides.navigationMs) && overrides.navigationMs > 0
|
|
11472
|
-
? Math.floor(overrides.navigationMs)
|
|
11473
|
-
: envNavigationTimeoutMs;
|
|
11474
|
-
const actionTimeoutMs = (overrides === null || overrides === void 0 ? void 0 : overrides.actionMs) && Number.isFinite(overrides.actionMs) && overrides.actionMs > 0
|
|
11475
|
-
? Math.floor(overrides.actionMs)
|
|
11476
|
-
: envActionTimeoutMs;
|
|
11477
|
-
return {
|
|
11478
|
-
navigationTimeoutMs,
|
|
11479
|
-
actionTimeoutMs,
|
|
11480
|
-
};
|
|
11481
|
-
},
|
|
11482
|
-
};
|
|
11483
|
-
|
|
11484
|
-
/**
|
|
11485
|
-
* Error classification and cancellation helpers used by `run_browser`.
|
|
11486
|
-
*
|
|
11487
|
-
* @private function of `run_browser`
|
|
11488
|
-
*/
|
|
11489
|
-
const runBrowserErrorHandling = {
|
|
11490
|
-
/**
|
|
11491
|
-
* Creates one tagged ParseError used for deterministic input validation failures.
|
|
11492
|
-
*/
|
|
11493
|
-
createRunBrowserValidationError(options) {
|
|
11494
|
-
const error = new ParseError(options.message);
|
|
11495
|
-
error.name = 'RunBrowserValidationError';
|
|
11496
|
-
error.runBrowserCode = runBrowserConstants.validationErrorCode;
|
|
11497
|
-
error.isRetryable = false;
|
|
11498
|
-
error.suggestedNextSteps = [
|
|
11499
|
-
'Fix the action payload to match the run_browser schema.',
|
|
11500
|
-
'Check selectors and required action fields before retrying.',
|
|
11501
|
-
];
|
|
11502
|
-
error.debug = options.debug;
|
|
11503
|
-
return error;
|
|
11504
|
-
},
|
|
11505
|
-
/**
|
|
11506
|
-
* Creates one tagged KnowledgeScrapeError used for navigation failures.
|
|
11507
|
-
*/
|
|
11508
|
-
createRunBrowserNavigationError(options) {
|
|
11509
|
-
const error = new KnowledgeScrapeError(options.message);
|
|
11510
|
-
error.name = 'RunBrowserNavigationError';
|
|
11511
|
-
error.runBrowserCode = runBrowserConstants.navigationFailedErrorCode;
|
|
11512
|
-
error.isRetryable = false;
|
|
11513
|
-
error.suggestedNextSteps = [
|
|
11514
|
-
'Verify the URL is reachable and not blocked.',
|
|
11515
|
-
'Retry with a simpler action sequence.',
|
|
11516
|
-
];
|
|
11517
|
-
error.debug = options.debug;
|
|
11518
|
-
error.cause = options.cause;
|
|
11519
|
-
return error;
|
|
11520
|
-
},
|
|
11521
|
-
/**
|
|
11522
|
-
* Creates one tagged KnowledgeScrapeError used for action failures.
|
|
11523
|
-
*/
|
|
11524
|
-
createRunBrowserActionError(options) {
|
|
11525
|
-
const error = new KnowledgeScrapeError(options.message);
|
|
11526
|
-
error.name = 'RunBrowserActionError';
|
|
11527
|
-
error.runBrowserCode = runBrowserConstants.actionFailedErrorCode;
|
|
11528
|
-
error.isRetryable = false;
|
|
11529
|
-
error.suggestedNextSteps = [
|
|
11530
|
-
'Verify selectors and action values.',
|
|
11531
|
-
'Reduce the action sequence to isolate the failing step.',
|
|
11532
|
-
];
|
|
11533
|
-
error.debug = options.debug;
|
|
11534
|
-
error.cause = options.cause;
|
|
11535
|
-
return error;
|
|
11536
|
-
},
|
|
11537
|
-
/**
|
|
11538
|
-
* Creates one tagged KnowledgeScrapeError used for cancellation.
|
|
11539
|
-
*/
|
|
11540
|
-
createRunBrowserCancelledError(options) {
|
|
11541
|
-
const error = new KnowledgeScrapeError(options.message);
|
|
11542
|
-
error.name = 'RunBrowserCancelledError';
|
|
11543
|
-
error.runBrowserCode = runBrowserConstants.cancelledErrorCode;
|
|
11544
|
-
error.isRetryable = true;
|
|
11545
|
-
error.suggestedNextSteps = [
|
|
11546
|
-
'Retry while request context is still active.',
|
|
11547
|
-
'Increase timeout if operation is expected to run longer.',
|
|
11548
|
-
];
|
|
11549
|
-
error.debug = options.debug;
|
|
11550
|
-
error.cause = options.cause;
|
|
11551
|
-
return error;
|
|
11552
|
-
},
|
|
11553
|
-
/**
|
|
11554
|
-
* Checks whether an unknown error carries run_browser classification tags.
|
|
11555
|
-
*/
|
|
11556
|
-
isTaggedRunBrowserError(error) {
|
|
11557
|
-
if (!error || typeof error !== 'object') {
|
|
11558
|
-
return false;
|
|
11559
|
-
}
|
|
11560
|
-
const candidate = error;
|
|
11561
|
-
return (typeof candidate.runBrowserCode === 'string' &&
|
|
11562
|
-
typeof candidate.isRetryable === 'boolean' &&
|
|
11563
|
-
Array.isArray(candidate.suggestedNextSteps) &&
|
|
11564
|
-
typeof candidate.debug === 'object' &&
|
|
11565
|
-
candidate.debug !== null);
|
|
11566
|
-
},
|
|
11567
|
-
/**
|
|
11568
|
-
* Converts unknown errors into structured tool error payloads.
|
|
11569
|
-
*/
|
|
11570
|
-
classifyRunBrowserToolError(options) {
|
|
11571
|
-
if (isRemoteBrowserUnavailableError(options.error)) {
|
|
11572
|
-
return {
|
|
11573
|
-
code: options.error.code,
|
|
11574
|
-
message: options.error.message,
|
|
11575
|
-
isRetryable: options.error.isRetryable,
|
|
11576
|
-
suggestedNextSteps: options.error.suggestedNextSteps,
|
|
11577
|
-
debug: {
|
|
11578
|
-
...options.error.debug,
|
|
11579
|
-
sessionId: options.sessionId,
|
|
11580
|
-
mode: runBrowserRuntime.formatExecutionMode(options.mode),
|
|
11581
|
-
},
|
|
11582
|
-
};
|
|
11583
|
-
}
|
|
11584
|
-
if (this.isTaggedRunBrowserError(options.error)) {
|
|
11585
|
-
return {
|
|
11586
|
-
code: options.error.runBrowserCode,
|
|
11587
|
-
message: options.error.message,
|
|
11588
|
-
isRetryable: options.error.isRetryable,
|
|
11589
|
-
suggestedNextSteps: options.error.suggestedNextSteps,
|
|
11590
|
-
debug: {
|
|
11591
|
-
...options.error.debug,
|
|
11592
|
-
sessionId: options.sessionId,
|
|
11593
|
-
mode: runBrowserRuntime.formatExecutionMode(options.mode),
|
|
11594
|
-
},
|
|
11595
|
-
};
|
|
11596
|
-
}
|
|
11597
|
-
const remoteBrowserEndpoint = REMOTE_BROWSER_URL && REMOTE_BROWSER_URL.trim().length > 0
|
|
11598
|
-
? sanitizeRemoteBrowserEndpoint(REMOTE_BROWSER_URL.trim())
|
|
11599
|
-
: null;
|
|
11600
|
-
const message = getErrorMessage(options.error);
|
|
11601
|
-
return {
|
|
11602
|
-
code: runBrowserConstants.unknownErrorCode,
|
|
11603
|
-
message,
|
|
11604
|
-
isRetryable: false,
|
|
11605
|
-
suggestedNextSteps: ['Inspect debug details to identify the failing phase.', 'Retry with fewer actions.'],
|
|
11606
|
-
debug: {
|
|
11607
|
-
sessionId: options.sessionId,
|
|
11608
|
-
mode: runBrowserRuntime.formatExecutionMode(options.mode),
|
|
11609
|
-
remoteBrowserEndpoint,
|
|
11610
|
-
message,
|
|
11611
|
-
stack: getErrorStack(options.error),
|
|
11612
|
-
},
|
|
11613
|
-
};
|
|
11614
|
-
},
|
|
11615
|
-
/**
|
|
11616
|
-
* Asserts that the run was not aborted.
|
|
11617
|
-
*/
|
|
11618
|
-
assertNotAborted(signal, sessionId) {
|
|
11619
|
-
if (!(signal === null || signal === void 0 ? void 0 : signal.aborted)) {
|
|
11620
|
-
return;
|
|
11621
|
-
}
|
|
11622
|
-
throw this.createRunBrowserCancelledError({
|
|
11623
|
-
message: 'run_browser execution was cancelled.',
|
|
11624
|
-
debug: { sessionId },
|
|
11625
|
-
});
|
|
11626
|
-
},
|
|
11627
|
-
/**
|
|
11628
|
-
* Returns true when the tool error represents remote browser unavailability.
|
|
11629
|
-
*/
|
|
11630
|
-
isRemoteBrowserUnavailableCode(code) {
|
|
11631
|
-
return code === REMOTE_BROWSER_UNAVAILABLE_ERROR_CODE;
|
|
11632
|
-
},
|
|
11633
|
-
};
|
|
11634
|
-
|
|
11635
|
-
/**
|
|
11636
|
-
* In-memory observability counters for browser tool execution.
|
|
11637
|
-
*/
|
|
11638
|
-
const RUN_BROWSER_OBSERVABILITY = {
|
|
11639
|
-
totalRuns: 0,
|
|
11640
|
-
fallbackRuns: 0,
|
|
11641
|
-
errorCodeCounts: {},
|
|
11642
|
-
};
|
|
11643
|
-
/**
|
|
11644
|
-
* Observability counters and metric logging for `run_browser`.
|
|
11645
|
-
*
|
|
11646
|
-
* @private function of `run_browser`
|
|
11647
|
-
*/
|
|
11648
|
-
const runBrowserObservability = {
|
|
11649
|
-
/**
|
|
11650
|
-
* Increments total-run counter and returns the updated value.
|
|
11651
|
-
*/
|
|
11652
|
-
incrementTotalRuns() {
|
|
11653
|
-
RUN_BROWSER_OBSERVABILITY.totalRuns++;
|
|
11654
|
-
return RUN_BROWSER_OBSERVABILITY.totalRuns;
|
|
11655
|
-
},
|
|
11656
|
-
/**
|
|
11657
|
-
* Returns current total run count.
|
|
11658
|
-
*/
|
|
11659
|
-
getTotalRuns() {
|
|
11660
|
-
return RUN_BROWSER_OBSERVABILITY.totalRuns;
|
|
11661
|
-
},
|
|
11662
|
-
/**
|
|
11663
|
-
* Increments fallback counter and returns updated metrics.
|
|
11664
|
-
*/
|
|
11665
|
-
incrementFallbackRunsAndGetMetrics() {
|
|
11666
|
-
RUN_BROWSER_OBSERVABILITY.fallbackRuns++;
|
|
11667
|
-
return {
|
|
11668
|
-
fallbackRuns: RUN_BROWSER_OBSERVABILITY.fallbackRuns,
|
|
11669
|
-
fallbackRate: RUN_BROWSER_OBSERVABILITY.totalRuns === 0
|
|
11670
|
-
? 0
|
|
11671
|
-
: RUN_BROWSER_OBSERVABILITY.fallbackRuns / RUN_BROWSER_OBSERVABILITY.totalRuns,
|
|
11672
|
-
};
|
|
11673
|
-
},
|
|
11674
|
-
/**
|
|
11675
|
-
* Increments one error-code counter and returns the updated value.
|
|
11676
|
-
*/
|
|
11677
|
-
incrementRunBrowserErrorCodeCounter(code) {
|
|
11678
|
-
const currentValue = RUN_BROWSER_OBSERVABILITY.errorCodeCounts[code] || 0;
|
|
11679
|
-
const nextValue = currentValue + 1;
|
|
11680
|
-
RUN_BROWSER_OBSERVABILITY.errorCodeCounts[code] = nextValue;
|
|
11681
|
-
return nextValue;
|
|
11682
|
-
},
|
|
11683
|
-
/**
|
|
11684
|
-
* Writes one structured metric line for browser-tool observability.
|
|
11685
|
-
*/
|
|
11686
|
-
logRunBrowserMetric(options) {
|
|
11687
|
-
console.info('[run_browser][metric]', {
|
|
11688
|
-
tool: 'run_browser',
|
|
11689
|
-
mode: options.mode,
|
|
11690
|
-
sessionId: options.sessionId,
|
|
11691
|
-
event: options.event,
|
|
11692
|
-
...(options.payload || {}),
|
|
11693
|
-
});
|
|
11694
|
-
},
|
|
11695
|
-
};
|
|
11696
|
-
|
|
11697
|
-
/**
|
|
11698
|
-
* Computes one compact preview of a fallback scrape payload.
|
|
11699
|
-
*/
|
|
11700
|
-
function createContentPreview(content) {
|
|
11701
|
-
const normalized = content.replace(/\s+/g, ' ').trim();
|
|
11702
|
-
if (normalized.length <= 280) {
|
|
11703
|
-
return normalized;
|
|
11704
|
-
}
|
|
11705
|
-
return `${normalized.slice(0, 277)}...`;
|
|
11706
|
-
}
|
|
11707
|
-
/**
|
|
11708
|
-
* Payload and markdown formatters for `run_browser` outcomes.
|
|
11709
|
-
*
|
|
11710
|
-
* @private function of `run_browser`
|
|
11711
|
-
*/
|
|
11712
|
-
const runBrowserResultFormatting = {
|
|
11713
|
-
/**
|
|
11714
|
-
* Produces one structured payload consumed by chat UI browser replay renderers.
|
|
11715
|
-
*/
|
|
11716
|
-
createResultPayload(options) {
|
|
11717
|
-
return {
|
|
11718
|
-
schema: runBrowserConstants.resultSchema,
|
|
11719
|
-
sessionId: options.sessionId,
|
|
11720
|
-
mode: options.mode,
|
|
11721
|
-
modeUsed: options.modeUsed,
|
|
11722
|
-
initialUrl: options.initialUrl,
|
|
11723
|
-
finalUrl: options.finalUrl,
|
|
11724
|
-
finalTitle: options.finalTitle,
|
|
11725
|
-
executedActions: options.executedActions,
|
|
11726
|
-
artifacts: options.artifacts,
|
|
11727
|
-
warning: options.warning,
|
|
11728
|
-
error: options.error,
|
|
11729
|
-
fallback: options.modeUsed === 'fallback' && options.fallbackContent !== null
|
|
11730
|
-
? {
|
|
11731
|
-
scraper: 'fetch_url_content',
|
|
11732
|
-
contentPreview: createContentPreview(options.fallbackContent),
|
|
11733
|
-
}
|
|
11734
|
-
: null,
|
|
11735
|
-
timing: options.timing,
|
|
11736
|
-
};
|
|
11737
|
-
},
|
|
11738
|
-
/**
|
|
11739
|
-
* Produces a model-friendly markdown summary from browser execution artifacts.
|
|
11740
|
-
*/
|
|
11741
|
-
formatSuccessResult(options) {
|
|
11742
|
-
const { payload, snapshotPath } = options;
|
|
11743
|
-
return spaceTrim$1((block) => {
|
|
11744
|
-
var _a, _b, _c;
|
|
11745
|
-
return `
|
|
11746
|
-
# Browser run completed
|
|
11747
|
-
|
|
11748
|
-
**Session:** ${payload.sessionId}
|
|
11749
|
-
**Mode requested:** ${runBrowserRuntime.formatExecutionMode(payload.mode)}
|
|
11750
|
-
**Mode used:** ${payload.modeUsed}
|
|
11751
|
-
**Initial URL:** ${payload.initialUrl}
|
|
11752
|
-
**Executed actions:** ${payload.executedActions.length}
|
|
11753
|
-
|
|
11754
|
-
## Final page
|
|
11755
|
-
|
|
11756
|
-
- URL: ${payload.finalUrl || 'Unknown'}
|
|
11757
|
-
- Title: ${payload.finalTitle || 'Unknown'}
|
|
11758
|
-
|
|
11759
|
-
## Timings
|
|
11760
|
-
|
|
11761
|
-
- Connect: ${(_a = payload.timing.connectDurationMs) !== null && _a !== void 0 ? _a : 'Unknown'} ms
|
|
11762
|
-
- Initial navigation: ${(_b = payload.timing.initialNavigationDurationMs) !== null && _b !== void 0 ? _b : 'Unknown'} ms
|
|
11763
|
-
- Time to first byte: ${(_c = payload.timing.timeToFirstByteMs) !== null && _c !== void 0 ? _c : 'Unknown'} ms
|
|
11764
|
-
- Total: ${payload.timing.totalDurationMs} ms
|
|
11765
|
-
|
|
11766
|
-
${payload.artifacts.length === 0
|
|
11767
|
-
? ''
|
|
11768
|
-
: `
|
|
11769
|
-
## Visual replay
|
|
11770
|
-
|
|
11771
|
-
${payload.artifacts
|
|
11772
|
-
.map((artifact, index) => {
|
|
11773
|
-
const actionPart = artifact.actionSummary ? ` (${artifact.actionSummary})` : '';
|
|
11774
|
-
return `- ${index + 1}. ${artifact.label}${actionPart}: ${artifact.path}`;
|
|
11775
|
-
})
|
|
11776
|
-
.join('\n')}
|
|
11777
|
-
`}
|
|
11778
|
-
|
|
11779
|
-
${!snapshotPath
|
|
11780
|
-
? ''
|
|
11781
|
-
: `
|
|
11782
|
-
## Final snapshot
|
|
11783
|
-
|
|
11784
|
-
${snapshotPath}
|
|
11785
|
-
`}
|
|
11786
|
-
|
|
11787
|
-
## Playback payload
|
|
11788
|
-
|
|
11789
|
-
\`\`\`json
|
|
11790
|
-
${JSON.stringify(payload, null, 2)}
|
|
11791
|
-
\`\`\`
|
|
11792
|
-
|
|
11793
|
-
${block(payload.executedActions.length === 0
|
|
11794
|
-
? ''
|
|
11795
|
-
: `
|
|
11796
|
-
## Action log
|
|
11797
|
-
|
|
11798
|
-
${payload.executedActions
|
|
11799
|
-
.map((action, index) => `- ${index + 1}. ${JSON.stringify(action)}`)
|
|
11800
|
-
.join('\n')}
|
|
11801
|
-
`)}
|
|
11802
|
-
|
|
11803
|
-
Note: Browser page has been automatically closed to free up resources.
|
|
11804
|
-
`;
|
|
11805
|
-
});
|
|
11806
|
-
},
|
|
11807
|
-
/**
|
|
11808
|
-
* Produces a model-friendly markdown payload when fallback scraping is used.
|
|
11809
|
-
*/
|
|
11810
|
-
formatFallbackResult(options) {
|
|
11811
|
-
const { payload, fallbackContent, requestedActions } = options;
|
|
11812
|
-
return spaceTrim$1(`
|
|
11813
|
-
# Browser run completed with fallback
|
|
11814
|
-
|
|
11815
|
-
**Session:** ${payload.sessionId}
|
|
11816
|
-
**Mode requested:** ${runBrowserRuntime.formatExecutionMode(payload.mode)}
|
|
11817
|
-
**Mode used:** ${payload.modeUsed}
|
|
11818
|
-
**Initial URL:** ${payload.initialUrl}
|
|
11819
|
-
**Requested actions:** ${requestedActions}
|
|
11820
|
-
**Executed actions:** ${payload.executedActions.length}
|
|
11821
|
-
**Warning:** ${payload.warning || runBrowserConstants.fallbackDynamicContentWarning}
|
|
11822
|
-
|
|
11823
|
-
## Extracted content
|
|
11824
|
-
|
|
11825
|
-
${fallbackContent}
|
|
11826
|
-
|
|
11827
|
-
## Playback payload
|
|
11828
|
-
|
|
11829
|
-
\`\`\`json
|
|
11830
|
-
${JSON.stringify(payload, null, 2)}
|
|
11831
|
-
\`\`\`
|
|
11832
|
-
`);
|
|
11833
|
-
},
|
|
11834
|
-
/**
|
|
11835
|
-
* Produces a model-friendly markdown error payload from browser execution failures.
|
|
11836
|
-
*/
|
|
11837
|
-
formatErrorResult(options) {
|
|
11838
|
-
const { payload } = options;
|
|
11839
|
-
const toolError = payload.error;
|
|
11840
|
-
const suggestedNextSteps = (toolError === null || toolError === void 0 ? void 0 : toolError.suggestedNextSteps) || [];
|
|
11841
|
-
return spaceTrim$1(`
|
|
11842
|
-
# Browser run failed
|
|
11843
|
-
|
|
11844
|
-
**Session:** ${payload.sessionId}
|
|
11845
|
-
**Mode requested:** ${runBrowserRuntime.formatExecutionMode(payload.mode)}
|
|
11846
|
-
**Mode used:** ${payload.modeUsed}
|
|
11847
|
-
**Initial URL:** ${payload.initialUrl}
|
|
11848
|
-
**Error code:** ${(toolError === null || toolError === void 0 ? void 0 : toolError.code) || runBrowserConstants.unknownErrorCode}
|
|
11849
|
-
**Error:** ${(toolError === null || toolError === void 0 ? void 0 : toolError.message) || 'Unknown browser tool error'}
|
|
11850
|
-
|
|
11851
|
-
${suggestedNextSteps.length === 0
|
|
11852
|
-
? ''
|
|
11853
|
-
: `
|
|
11854
|
-
## Suggested next steps
|
|
11855
|
-
|
|
11856
|
-
${suggestedNextSteps.map((step) => `- ${step}`).join('\n')}
|
|
11857
|
-
`}
|
|
11858
|
-
|
|
11859
|
-
## Playback payload
|
|
11860
|
-
|
|
11861
|
-
\`\`\`json
|
|
11862
|
-
${JSON.stringify(payload, null, 2)}
|
|
11863
|
-
\`\`\`
|
|
11864
|
-
|
|
11865
|
-
The browser tool could not complete the requested actions.
|
|
11866
|
-
`);
|
|
11867
|
-
},
|
|
11868
|
-
};
|
|
11869
|
-
|
|
11870
|
-
/**
|
|
11871
|
-
* @@@
|
|
11872
|
-
*
|
|
11873
|
-
* @private within the repository
|
|
11874
|
-
*/
|
|
11875
|
-
function locateChrome() {
|
|
11876
|
-
return locateApp({
|
|
11877
|
-
appName: 'Chrome',
|
|
11878
|
-
linuxWhich: 'google-chrome',
|
|
11879
|
-
windowsSuffix: '\\Google\\Chrome\\Application\\chrome.exe',
|
|
11880
|
-
macOsName: 'Google Chrome',
|
|
11881
|
-
});
|
|
11882
|
-
}
|
|
11883
|
-
|
|
11884
|
-
/**
|
|
11885
|
-
* Creates one standard abort error for cancelled retry loops.
|
|
11886
|
-
*
|
|
11887
|
-
* @private utility for Agents Server runtime retries
|
|
11888
|
-
*/
|
|
11889
|
-
function createAbortError$1() {
|
|
11890
|
-
const error = new Error('Operation was aborted.');
|
|
11891
|
-
error.name = 'AbortError';
|
|
11892
|
-
return error;
|
|
11893
|
-
}
|
|
11894
|
-
/**
|
|
11895
|
-
* Throws when the supplied signal is already aborted.
|
|
11896
|
-
*
|
|
11897
|
-
* @private utility for Agents Server runtime retries
|
|
11898
|
-
*/
|
|
11899
|
-
function assertNotAborted(signal) {
|
|
11900
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
11901
|
-
throw createAbortError$1();
|
|
11902
|
-
}
|
|
11903
|
-
}
|
|
11904
|
-
/**
|
|
11905
|
-
* Waits for a duration while respecting cancellation.
|
|
11906
|
-
*
|
|
11907
|
-
* @private utility for Agents Server runtime retries
|
|
11908
|
-
*/
|
|
11909
|
-
async function sleepWithAbort(delayMs, signal) {
|
|
11910
|
-
if (delayMs <= 0) {
|
|
11911
|
-
assertNotAborted(signal);
|
|
11912
|
-
return;
|
|
11913
|
-
}
|
|
11914
|
-
await new Promise((resolve, reject) => {
|
|
11915
|
-
const timeout = setTimeout(() => {
|
|
11916
|
-
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
11917
|
-
resolve();
|
|
11918
|
-
}, delayMs);
|
|
11919
|
-
const onAbort = () => {
|
|
11920
|
-
clearTimeout(timeout);
|
|
11921
|
-
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
11922
|
-
reject(createAbortError$1());
|
|
11923
|
-
};
|
|
11924
|
-
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
|
|
11925
|
-
});
|
|
11926
|
-
}
|
|
11927
|
-
/**
|
|
11928
|
-
* Resolves the retry wait duration for one failed attempt.
|
|
11929
|
-
*
|
|
11930
|
-
* @private utility for Agents Server runtime retries
|
|
11931
|
-
*/
|
|
11932
|
-
function resolveBackoffDelayMs(options) {
|
|
11933
|
-
const exponentialDelay = options.initialDelayMs * Math.pow(options.backoffFactor, Math.max(0, options.attempt - 1));
|
|
11934
|
-
const boundedDelay = Math.min(exponentialDelay, options.maxDelayMs);
|
|
11935
|
-
const jitterDelay = boundedDelay * options.jitterRatio * Math.max(0, options.random());
|
|
11936
|
-
return Math.max(0, Math.round(boundedDelay + jitterDelay));
|
|
11937
|
-
}
|
|
11938
|
-
/**
|
|
11939
|
-
* Retries one async operation with exponential backoff and jitter.
|
|
11940
|
-
*
|
|
11941
|
-
* @private utility for Agents Server runtime retries
|
|
11942
|
-
*/
|
|
11943
|
-
async function retryWithBackoff(operation, options) {
|
|
11944
|
-
var _a, _b, _c;
|
|
11945
|
-
const startedAt = Date.now();
|
|
11946
|
-
const totalAttempts = Math.max(1, options.retries + 1);
|
|
11947
|
-
const random = (_a = options.random) !== null && _a !== void 0 ? _a : Math.random;
|
|
11948
|
-
const sleep = (_b = options.sleep) !== null && _b !== void 0 ? _b : sleepWithAbort;
|
|
11949
|
-
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
11950
|
-
assertNotAborted(options.signal);
|
|
11951
|
-
try {
|
|
11952
|
-
const value = await operation(attempt);
|
|
11953
|
-
return {
|
|
11954
|
-
value,
|
|
11955
|
-
attempts: attempt,
|
|
11956
|
-
durationMs: Date.now() - startedAt,
|
|
11957
|
-
};
|
|
11958
|
-
}
|
|
11959
|
-
catch (error) {
|
|
11960
|
-
const isLastAttempt = attempt >= totalAttempts;
|
|
11961
|
-
const isRetryable = options.shouldRetry ? options.shouldRetry(error, attempt) : true;
|
|
11962
|
-
if (isLastAttempt || !isRetryable) {
|
|
11963
|
-
throw error;
|
|
11964
|
-
}
|
|
11965
|
-
const delayMs = resolveBackoffDelayMs({
|
|
11966
|
-
attempt,
|
|
11967
|
-
initialDelayMs: options.initialDelayMs,
|
|
11968
|
-
maxDelayMs: options.maxDelayMs,
|
|
11969
|
-
backoffFactor: options.backoffFactor,
|
|
11970
|
-
jitterRatio: options.jitterRatio,
|
|
11971
|
-
random,
|
|
11972
|
-
});
|
|
11973
|
-
(_c = options.onRetry) === null || _c === void 0 ? void 0 : _c.call(options, {
|
|
11974
|
-
attempt,
|
|
11975
|
-
retries: options.retries,
|
|
11976
|
-
delayMs,
|
|
11977
|
-
error,
|
|
11978
|
-
});
|
|
11979
|
-
await sleep(delayMs, options.signal);
|
|
11980
|
-
}
|
|
11981
|
-
}
|
|
11982
|
-
throw new Error('Retry loop exited unexpectedly.');
|
|
11983
|
-
}
|
|
11984
|
-
|
|
11985
|
-
const DEFAULT_BROWSER_USER_DATA_DIR = join(tmpdir(), 'promptbook', 'browser', 'user-data');
|
|
11986
|
-
/**
|
|
11987
|
-
* Default remote browser connect timeout in milliseconds.
|
|
11988
|
-
*/
|
|
11989
|
-
const DEFAULT_REMOTE_CONNECT_TIMEOUT_MS = 10000;
|
|
11990
|
-
/**
|
|
11991
|
-
* Default retry count for remote browser connection establishment.
|
|
11992
|
-
*/
|
|
11993
|
-
const DEFAULT_REMOTE_CONNECT_RETRIES = 2;
|
|
11994
|
-
/**
|
|
11995
|
-
* Default initial retry delay for remote browser connection.
|
|
11996
|
-
*/
|
|
11997
|
-
const DEFAULT_REMOTE_CONNECT_BACKOFF_INITIAL_MS = 250;
|
|
11998
|
-
/**
|
|
11999
|
-
* Default maximum retry delay for remote browser connection.
|
|
12000
|
-
*/
|
|
12001
|
-
const DEFAULT_REMOTE_CONNECT_BACKOFF_MAX_MS = 1000;
|
|
12002
|
-
/**
|
|
12003
|
-
* Default exponential multiplier for remote browser retry delay.
|
|
12004
|
-
*/
|
|
12005
|
-
const DEFAULT_REMOTE_CONNECT_BACKOFF_FACTOR = 4;
|
|
12006
|
-
/**
|
|
12007
|
-
* Default retry jitter ratio for remote browser connection.
|
|
12008
|
-
*/
|
|
12009
|
-
const DEFAULT_REMOTE_CONNECT_JITTER_RATIO = 0.2;
|
|
12010
|
-
/**
|
|
12011
|
-
* In-memory metrics counters for remote browser connect attempts.
|
|
12012
|
-
*/
|
|
12013
|
-
const REMOTE_BROWSER_CONNECT_METRICS = {
|
|
12014
|
-
success: 0,
|
|
12015
|
-
failure: 0,
|
|
12016
|
-
};
|
|
12017
|
-
/**
|
|
12018
|
-
* Reads a positive integer from environment variables with a fallback default.
|
|
12019
|
-
*/
|
|
12020
|
-
function resolvePositiveIntFromEnv(variableName, defaultValue) {
|
|
12021
|
-
const rawValue = process.env[variableName];
|
|
12022
|
-
if (!rawValue || !rawValue.trim()) {
|
|
12023
|
-
return defaultValue;
|
|
12024
|
-
}
|
|
12025
|
-
const parsed = Number.parseInt(rawValue.trim(), 10);
|
|
12026
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12027
|
-
return defaultValue;
|
|
12028
|
-
}
|
|
12029
|
-
return parsed;
|
|
12030
|
-
}
|
|
12031
|
-
/**
|
|
12032
|
-
* Reads a positive number from environment variables with a fallback default.
|
|
12033
|
-
*/
|
|
12034
|
-
function resolvePositiveNumberFromEnv(variableName, defaultValue) {
|
|
12035
|
-
const rawValue = process.env[variableName];
|
|
12036
|
-
if (!rawValue || !rawValue.trim()) {
|
|
12037
|
-
return defaultValue;
|
|
12038
|
-
}
|
|
12039
|
-
const parsed = Number.parseFloat(rawValue.trim());
|
|
12040
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12041
|
-
return defaultValue;
|
|
12042
|
-
}
|
|
12043
|
-
return parsed;
|
|
12044
|
-
}
|
|
12045
|
-
/**
|
|
12046
|
-
* Reads a non-negative integer from environment variables with a fallback default.
|
|
12047
|
-
*/
|
|
12048
|
-
function resolveNonNegativeIntFromEnv(variableName, defaultValue) {
|
|
12049
|
-
const rawValue = process.env[variableName];
|
|
12050
|
-
if (!rawValue || !rawValue.trim()) {
|
|
12051
|
-
return defaultValue;
|
|
12052
|
-
}
|
|
12053
|
-
const parsed = Number.parseInt(rawValue.trim(), 10);
|
|
12054
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
12055
|
-
return defaultValue;
|
|
12056
|
-
}
|
|
12057
|
-
return parsed;
|
|
12058
|
-
}
|
|
12059
|
-
/**
|
|
12060
|
-
* Reads a non-negative number from environment variables with a fallback default.
|
|
12061
|
-
*/
|
|
12062
|
-
function resolveNonNegativeNumberFromEnv(variableName, defaultValue) {
|
|
12063
|
-
const rawValue = process.env[variableName];
|
|
12064
|
-
if (!rawValue || !rawValue.trim()) {
|
|
12065
|
-
return defaultValue;
|
|
12066
|
-
}
|
|
12067
|
-
const parsed = Number.parseFloat(rawValue.trim());
|
|
12068
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
12069
|
-
return defaultValue;
|
|
12070
|
-
}
|
|
12071
|
-
return parsed;
|
|
12072
|
-
}
|
|
12073
|
-
/**
|
|
12074
|
-
* Creates one standard abort error.
|
|
12075
|
-
*/
|
|
12076
|
-
function createAbortError() {
|
|
12077
|
-
const error = new Error('Browser connection request was aborted.');
|
|
12078
|
-
error.name = 'AbortError';
|
|
12079
|
-
return error;
|
|
12080
|
-
}
|
|
12081
|
-
/**
|
|
12082
|
-
* Provides browser context instances with support for both local and remote browser connections.
|
|
12083
|
-
*
|
|
12084
|
-
* This provider manages browser lifecycle and supports:
|
|
12085
|
-
* - Local mode: Launches a persistent Chromium context on the same machine
|
|
12086
|
-
* - Remote mode: Connects to a remote Playwright browser via WebSocket
|
|
12087
|
-
*
|
|
12088
|
-
* The remote mode is useful for environments like Vercel where running a full browser
|
|
12089
|
-
* is not possible due to resource constraints.
|
|
12090
|
-
*
|
|
12091
|
-
* @private internal utility for Agents Server browser tools
|
|
12092
|
-
*/
|
|
12093
|
-
class BrowserConnectionProvider {
|
|
12094
|
-
/**
|
|
12095
|
-
* Creates a new BrowserConnectionProvider.
|
|
12096
|
-
*
|
|
12097
|
-
* @param options - Provider options
|
|
12098
|
-
* @param options.isVerbose - Enable verbose logging
|
|
12099
|
-
*/
|
|
12100
|
-
constructor(options = {}) {
|
|
12101
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
12102
|
-
this.browserContext = null;
|
|
12103
|
-
this.connectionMode = null;
|
|
12104
|
-
this.isVerbose = (_a = options.isVerbose) !== null && _a !== void 0 ? _a : false;
|
|
12105
|
-
this.remoteConnectTimeoutMs =
|
|
12106
|
-
(_b = options.remoteConnectTimeoutMs) !== null && _b !== void 0 ? _b : resolvePositiveIntFromEnv('RUN_BROWSER_CONNECT_TIMEOUT_MS', DEFAULT_REMOTE_CONNECT_TIMEOUT_MS);
|
|
12107
|
-
this.remoteConnectRetries =
|
|
12108
|
-
(_c = options.remoteConnectRetries) !== null && _c !== void 0 ? _c : resolveNonNegativeIntFromEnv('RUN_BROWSER_CONNECT_RETRIES', DEFAULT_REMOTE_CONNECT_RETRIES);
|
|
12109
|
-
this.remoteConnectBackoffInitialMs =
|
|
12110
|
-
(_d = options.remoteConnectBackoffInitialMs) !== null && _d !== void 0 ? _d : resolvePositiveIntFromEnv('RUN_BROWSER_CONNECT_BACKOFF_INITIAL_MS', DEFAULT_REMOTE_CONNECT_BACKOFF_INITIAL_MS);
|
|
12111
|
-
this.remoteConnectBackoffMaxMs =
|
|
12112
|
-
(_e = options.remoteConnectBackoffMaxMs) !== null && _e !== void 0 ? _e : resolvePositiveIntFromEnv('RUN_BROWSER_CONNECT_BACKOFF_MAX_MS', DEFAULT_REMOTE_CONNECT_BACKOFF_MAX_MS);
|
|
12113
|
-
this.remoteConnectBackoffFactor =
|
|
12114
|
-
(_f = options.remoteConnectBackoffFactor) !== null && _f !== void 0 ? _f : resolvePositiveNumberFromEnv('RUN_BROWSER_CONNECT_BACKOFF_FACTOR', DEFAULT_REMOTE_CONNECT_BACKOFF_FACTOR);
|
|
12115
|
-
this.remoteConnectJitterRatio =
|
|
12116
|
-
(_g = options.remoteConnectJitterRatio) !== null && _g !== void 0 ? _g : resolveNonNegativeNumberFromEnv('RUN_BROWSER_CONNECT_JITTER_RATIO', DEFAULT_REMOTE_CONNECT_JITTER_RATIO);
|
|
12117
|
-
this.random = (_h = options.random) !== null && _h !== void 0 ? _h : Math.random;
|
|
12118
|
-
this.sleep = options.sleep;
|
|
12119
|
-
}
|
|
12120
|
-
/**
|
|
12121
|
-
* Gets a browser context, creating a new one if needed.
|
|
12122
|
-
*
|
|
12123
|
-
* This method automatically determines whether to use local or remote browser
|
|
12124
|
-
* based on the REMOTE_BROWSER_URL environment variable.
|
|
12125
|
-
*
|
|
12126
|
-
* @returns Browser context instance
|
|
12127
|
-
*/
|
|
12128
|
-
async getBrowserContext(options = {}) {
|
|
12129
|
-
var _a;
|
|
12130
|
-
if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
12131
|
-
throw createAbortError();
|
|
12132
|
-
}
|
|
12133
|
-
// Check if we have a cached connection that's still valid
|
|
12134
|
-
if (this.browserContext !== null && this.isBrowserContextAlive(this.browserContext)) {
|
|
12135
|
-
return this.browserContext;
|
|
12136
|
-
}
|
|
12137
|
-
// Determine connection mode from configuration
|
|
12138
|
-
const mode = this.resolveConnectionMode();
|
|
12139
|
-
this.connectionMode = mode;
|
|
12140
|
-
if (this.isVerbose) {
|
|
12141
|
-
console.info('[BrowserConnectionProvider] Creating new browser context', {
|
|
12142
|
-
mode: mode.type,
|
|
12143
|
-
wsEndpoint: mode.type === 'remote' ? mode.wsEndpoint : undefined,
|
|
12144
|
-
});
|
|
12145
|
-
}
|
|
12146
|
-
// Create new browser context based on mode
|
|
12147
|
-
if (mode.type === 'local') {
|
|
12148
|
-
this.browserContext = await this.createLocalBrowserContext();
|
|
12149
|
-
}
|
|
12150
|
-
else {
|
|
12151
|
-
this.browserContext = await this.createRemoteBrowserContext(mode.wsEndpoint, options);
|
|
12152
|
-
}
|
|
12153
|
-
return this.browserContext;
|
|
12154
|
-
}
|
|
12155
|
-
/**
|
|
12156
|
-
* Closes all pages in the current browser context.
|
|
12157
|
-
*
|
|
12158
|
-
* This method is useful for cleanup between agent tasks without closing
|
|
12159
|
-
* the entire browser instance.
|
|
12160
|
-
*/
|
|
12161
|
-
async closeAllPages() {
|
|
12162
|
-
if (!this.browserContext) {
|
|
12163
|
-
return;
|
|
12164
|
-
}
|
|
12165
|
-
try {
|
|
12166
|
-
const pages = this.browserContext.pages();
|
|
12167
|
-
if (this.isVerbose) {
|
|
12168
|
-
console.info('[BrowserConnectionProvider] Closing all pages', {
|
|
12169
|
-
pageCount: pages.length,
|
|
12170
|
-
});
|
|
12171
|
-
}
|
|
12172
|
-
await Promise.all(pages.map((page) => page.close().catch((error) => {
|
|
12173
|
-
console.error('[BrowserConnectionProvider] Failed to close page', { error });
|
|
12174
|
-
})));
|
|
12175
|
-
}
|
|
12176
|
-
catch (error) {
|
|
12177
|
-
console.error('[BrowserConnectionProvider] Error closing pages', { error });
|
|
12178
|
-
}
|
|
12179
|
-
}
|
|
12180
|
-
/**
|
|
12181
|
-
* Closes the browser context and disconnects from the browser.
|
|
12182
|
-
*
|
|
12183
|
-
* This should be called when the browser is no longer needed to free up resources.
|
|
12184
|
-
* For local mode, this closes the browser process. For remote mode, it disconnects
|
|
12185
|
-
* from the remote browser but doesn't shut down the remote server.
|
|
12186
|
-
*/
|
|
12187
|
-
async close() {
|
|
12188
|
-
var _a;
|
|
12189
|
-
if (!this.browserContext) {
|
|
12190
|
-
return;
|
|
12191
|
-
}
|
|
12192
|
-
try {
|
|
12193
|
-
if (this.isVerbose) {
|
|
12194
|
-
console.info('[BrowserConnectionProvider] Closing browser context', {
|
|
12195
|
-
mode: (_a = this.connectionMode) === null || _a === void 0 ? void 0 : _a.type,
|
|
12196
|
-
});
|
|
12197
|
-
}
|
|
12198
|
-
await this.browserContext.close();
|
|
12199
|
-
this.browserContext = null;
|
|
12200
|
-
this.connectionMode = null;
|
|
12201
|
-
}
|
|
12202
|
-
catch (error) {
|
|
12203
|
-
console.error('[BrowserConnectionProvider] Error closing browser context', { error });
|
|
12204
|
-
// Reset state even if close fails
|
|
12205
|
-
this.browserContext = null;
|
|
12206
|
-
this.connectionMode = null;
|
|
12207
|
-
}
|
|
12208
|
-
}
|
|
12209
|
-
/**
|
|
12210
|
-
* Checks if a browser context is still alive and connected.
|
|
12211
|
-
*
|
|
12212
|
-
* @param context - Browser context to check
|
|
12213
|
-
* @returns True if the context is connected and usable
|
|
12214
|
-
*/
|
|
12215
|
-
isBrowserContextAlive(context) {
|
|
12216
|
-
try {
|
|
12217
|
-
const browser = context.browser();
|
|
12218
|
-
return browser !== null && browser.isConnected();
|
|
12219
|
-
}
|
|
12220
|
-
catch (_a) {
|
|
12221
|
-
return false;
|
|
12222
|
-
}
|
|
12223
|
-
}
|
|
12224
|
-
/**
|
|
12225
|
-
* Determines whether to use local or remote browser based on configuration.
|
|
12226
|
-
*
|
|
12227
|
-
* @returns Connection mode configuration
|
|
12228
|
-
*/
|
|
12229
|
-
resolveConnectionMode() {
|
|
12230
|
-
const remoteBrowserUrl = REMOTE_BROWSER_URL;
|
|
12231
|
-
if (remoteBrowserUrl && remoteBrowserUrl.trim().length > 0) {
|
|
12232
|
-
return {
|
|
12233
|
-
type: 'remote',
|
|
12234
|
-
wsEndpoint: remoteBrowserUrl.trim(),
|
|
12235
|
-
};
|
|
12236
|
-
}
|
|
12237
|
-
return { type: 'local' };
|
|
12238
|
-
}
|
|
12239
|
-
/**
|
|
12240
|
-
* Creates a local browser context using persistent Chromium.
|
|
12241
|
-
*
|
|
12242
|
-
* @returns Local browser context
|
|
12243
|
-
*/
|
|
12244
|
-
async createLocalBrowserContext() {
|
|
12245
|
-
if (this.isVerbose) {
|
|
12246
|
-
console.info('[BrowserConnectionProvider] Launching local browser context');
|
|
12247
|
-
}
|
|
12248
|
-
const userDataDir = join(DEFAULT_BROWSER_USER_DATA_DIR, 'run-browser');
|
|
12249
|
-
await mkdir(userDataDir, { recursive: true });
|
|
12250
|
-
const launchOptions = {
|
|
12251
|
-
headless: false,
|
|
12252
|
-
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
|
|
12253
|
-
};
|
|
12254
|
-
try {
|
|
12255
|
-
const chromePath = await locateChrome();
|
|
12256
|
-
launchOptions.executablePath = chromePath;
|
|
12257
|
-
}
|
|
12258
|
-
catch (error) {
|
|
12259
|
-
if (this.isVerbose) {
|
|
12260
|
-
console.warn('[BrowserConnectionProvider] Could not locate system Chrome; using Playwright bundled Chromium', {
|
|
12261
|
-
error: error instanceof Error ? error.message : String(error),
|
|
12262
|
-
});
|
|
12263
|
-
}
|
|
12264
|
-
}
|
|
12265
|
-
return await chromium.launchPersistentContext(userDataDir, launchOptions);
|
|
12266
|
-
}
|
|
12267
|
-
/**
|
|
12268
|
-
* Creates a remote browser context by connecting to a Playwright server.
|
|
12269
|
-
*
|
|
12270
|
-
* @param wsEndpoint - WebSocket endpoint of the remote Playwright server
|
|
12271
|
-
* @returns Remote browser context
|
|
12272
|
-
*/
|
|
12273
|
-
async createRemoteBrowserContext(wsEndpoint, options) {
|
|
12274
|
-
const endpointDebug = sanitizeRemoteBrowserEndpoint(wsEndpoint);
|
|
12275
|
-
const startedAt = Date.now();
|
|
12276
|
-
if (this.isVerbose) {
|
|
12277
|
-
console.info('[BrowserConnectionProvider] Connecting to remote browser', {
|
|
12278
|
-
endpoint: endpointDebug,
|
|
12279
|
-
connectTimeoutMs: this.remoteConnectTimeoutMs,
|
|
12280
|
-
retries: this.remoteConnectRetries,
|
|
12281
|
-
});
|
|
12282
|
-
}
|
|
12283
|
-
let attempts = 0;
|
|
12284
|
-
try {
|
|
12285
|
-
const connectResult = await retryWithBackoff(async (attempt) => {
|
|
12286
|
-
attempts = attempt;
|
|
12287
|
-
return await chromium.connect(wsEndpoint, {
|
|
12288
|
-
timeout: this.remoteConnectTimeoutMs,
|
|
12289
|
-
});
|
|
12290
|
-
}, {
|
|
12291
|
-
retries: this.remoteConnectRetries,
|
|
12292
|
-
initialDelayMs: this.remoteConnectBackoffInitialMs,
|
|
12293
|
-
maxDelayMs: this.remoteConnectBackoffMaxMs,
|
|
12294
|
-
backoffFactor: this.remoteConnectBackoffFactor,
|
|
12295
|
-
jitterRatio: this.remoteConnectJitterRatio,
|
|
12296
|
-
signal: options.signal,
|
|
12297
|
-
shouldRetry: (error) => isRemoteBrowserInfrastructureError(error),
|
|
12298
|
-
onRetry: ({ attempt, delayMs, error }) => {
|
|
12299
|
-
console.warn('[run_browser][retry]', {
|
|
12300
|
-
tool: 'run_browser',
|
|
12301
|
-
mode: 'remote-browser',
|
|
12302
|
-
sessionId: options.sessionId || null,
|
|
12303
|
-
event: 'remote_browser_connect_retry',
|
|
12304
|
-
attempt,
|
|
12305
|
-
delayMs,
|
|
12306
|
-
endpoint: endpointDebug,
|
|
12307
|
-
errorCode: extractNetworkErrorCode(error),
|
|
12308
|
-
error: getErrorMessage(error),
|
|
12309
|
-
});
|
|
12310
|
-
},
|
|
12311
|
-
random: this.random,
|
|
12312
|
-
sleep: this.sleep,
|
|
12313
|
-
});
|
|
12314
|
-
const browser = connectResult.value;
|
|
12315
|
-
// For remote connections, we need to create a new context
|
|
12316
|
-
// Note: Remote browsers don't support persistent contexts
|
|
12317
|
-
const context = await browser.newContext();
|
|
12318
|
-
REMOTE_BROWSER_CONNECT_METRICS.success++;
|
|
12319
|
-
console.info('[run_browser][metric]', {
|
|
12320
|
-
tool: 'run_browser',
|
|
12321
|
-
mode: 'remote-browser',
|
|
12322
|
-
sessionId: options.sessionId || null,
|
|
12323
|
-
event: 'remote_browser_connect_success',
|
|
12324
|
-
attempts: connectResult.attempts,
|
|
12325
|
-
connectDurationMs: connectResult.durationMs,
|
|
12326
|
-
endpoint: endpointDebug,
|
|
12327
|
-
counter: REMOTE_BROWSER_CONNECT_METRICS.success,
|
|
12328
|
-
});
|
|
12329
|
-
if (this.isVerbose) {
|
|
12330
|
-
console.info('[BrowserConnectionProvider] Successfully connected to remote browser');
|
|
12331
|
-
}
|
|
12332
|
-
return context;
|
|
12333
|
-
}
|
|
12334
|
-
catch (error) {
|
|
12335
|
-
REMOTE_BROWSER_CONNECT_METRICS.failure++;
|
|
12336
|
-
const durationMs = Date.now() - startedAt;
|
|
12337
|
-
const remoteInfraUnavailable = isRemoteBrowserInfrastructureError(error);
|
|
12338
|
-
if (remoteInfraUnavailable) {
|
|
12339
|
-
const remoteBrowserUnavailableError = new RemoteBrowserUnavailableError({
|
|
12340
|
-
message: `Remote browser is unavailable. Could not establish a websocket connection.`,
|
|
12341
|
-
debug: {
|
|
12342
|
-
endpoint: endpointDebug,
|
|
12343
|
-
attempts: Math.max(1, attempts),
|
|
12344
|
-
connectTimeoutMs: this.remoteConnectTimeoutMs,
|
|
12345
|
-
durationMs,
|
|
12346
|
-
networkErrorCode: extractNetworkErrorCode(error),
|
|
12347
|
-
originalMessage: getErrorMessage(error),
|
|
12348
|
-
},
|
|
12349
|
-
cause: error,
|
|
12350
|
-
});
|
|
12351
|
-
console.warn('[run_browser][metric]', {
|
|
12352
|
-
tool: 'run_browser',
|
|
12353
|
-
mode: 'remote-browser',
|
|
12354
|
-
sessionId: options.sessionId || null,
|
|
12355
|
-
event: 'remote_browser_connect_failure',
|
|
12356
|
-
errorCode: remoteBrowserUnavailableError.code,
|
|
12357
|
-
attempts: Math.max(1, attempts),
|
|
12358
|
-
connectDurationMs: durationMs,
|
|
12359
|
-
endpoint: endpointDebug,
|
|
12360
|
-
counter: REMOTE_BROWSER_CONNECT_METRICS.failure,
|
|
12361
|
-
});
|
|
12362
|
-
throw remoteBrowserUnavailableError;
|
|
12363
|
-
}
|
|
12364
|
-
console.error('[run_browser][metric]', {
|
|
12365
|
-
tool: 'run_browser',
|
|
12366
|
-
mode: 'remote-browser',
|
|
12367
|
-
sessionId: options.sessionId || null,
|
|
12368
|
-
event: 'remote_browser_connect_failure',
|
|
12369
|
-
errorCode: 'REMOTE_BROWSER_CONNECT_ERROR',
|
|
12370
|
-
attempts: Math.max(1, attempts),
|
|
12371
|
-
connectDurationMs: durationMs,
|
|
12372
|
-
endpoint: endpointDebug,
|
|
12373
|
-
error: getErrorMessage(error),
|
|
12374
|
-
counter: REMOTE_BROWSER_CONNECT_METRICS.failure,
|
|
12375
|
-
});
|
|
12376
|
-
throw error;
|
|
12377
|
-
}
|
|
12378
|
-
}
|
|
12379
|
-
}
|
|
12380
|
-
|
|
12381
|
-
/**
|
|
12382
|
-
* Singleton instance of the browser connection provider.
|
|
12383
|
-
*
|
|
12384
|
-
* @private internal cache for `$provideBrowserForServer`
|
|
12385
|
-
*/
|
|
12386
|
-
let browserProvider = null;
|
|
12387
|
-
/**
|
|
12388
|
-
* Provides a browser context for server-side operations, with caching to reuse instances.
|
|
12389
|
-
*
|
|
12390
|
-
* This function supports both local and remote browser connections based on environment configuration.
|
|
12391
|
-
* Use REMOTE_BROWSER_URL environment variable to configure a remote Playwright server.
|
|
12392
|
-
*
|
|
12393
|
-
* @param options - Optional runtime request options used for cancellation and logging context.
|
|
12394
|
-
* @returns Browser context instance
|
|
12395
|
-
*/
|
|
12396
|
-
async function $provideBrowserForServer(options = {}) {
|
|
12397
|
-
if (browserProvider === null) {
|
|
12398
|
-
browserProvider = new BrowserConnectionProvider({ isVerbose: false });
|
|
12399
|
-
}
|
|
12400
|
-
return await browserProvider.getBrowserContext(options);
|
|
12401
|
-
}
|
|
12402
|
-
/**
|
|
12403
|
-
* TODO: [🏓] Unite `xxxForServer` and `xxxForNode` naming
|
|
12404
|
-
*/
|
|
12405
|
-
|
|
12406
|
-
/**
|
|
12407
|
-
* Attempts to compute time-to-first-byte from Playwright response timing.
|
|
12408
|
-
*/
|
|
12409
|
-
function resolveTimeToFirstByteMs(response) {
|
|
12410
|
-
if (!response) {
|
|
12411
|
-
return null;
|
|
12412
|
-
}
|
|
12413
|
-
try {
|
|
12414
|
-
const timing = response.request().timing();
|
|
12415
|
-
if (typeof (timing === null || timing === void 0 ? void 0 : timing.responseStart) === 'number' &&
|
|
12416
|
-
typeof (timing === null || timing === void 0 ? void 0 : timing.startTime) === 'number' &&
|
|
12417
|
-
timing.responseStart >= timing.startTime) {
|
|
12418
|
-
return Math.round(timing.responseStart - timing.startTime);
|
|
12419
|
-
}
|
|
12420
|
-
}
|
|
12421
|
-
catch (_a) {
|
|
12422
|
-
return null;
|
|
12423
|
-
}
|
|
12424
|
-
return null;
|
|
12425
|
-
}
|
|
12426
|
-
/**
|
|
12427
|
-
* Page open, action normalization and action execution helpers for `run_browser`.
|
|
12428
|
-
*
|
|
12429
|
-
* @private function of `run_browser`
|
|
12430
|
-
*/
|
|
12431
|
-
const runBrowserWorkflow = {
|
|
12432
|
-
/**
|
|
12433
|
-
* Opens a new browser page and navigates to the requested URL.
|
|
12434
|
-
*/
|
|
12435
|
-
async openPageWithUrl(options) {
|
|
12436
|
-
runBrowserErrorHandling.assertNotAborted(options.signal, options.sessionId);
|
|
12437
|
-
const connectStartedAt = Date.now();
|
|
12438
|
-
const browserContext = await $provideBrowserForServer({
|
|
12439
|
-
signal: options.signal,
|
|
12440
|
-
sessionId: options.sessionId,
|
|
12441
|
-
});
|
|
12442
|
-
const connectDurationMs = Date.now() - connectStartedAt;
|
|
12443
|
-
const page = await browserContext.newPage();
|
|
12444
|
-
page.setDefaultNavigationTimeout(options.timeouts.navigationTimeoutMs);
|
|
12445
|
-
page.setDefaultTimeout(options.timeouts.actionTimeoutMs);
|
|
12446
|
-
const navigationStartedAt = Date.now();
|
|
12447
|
-
try {
|
|
12448
|
-
const navigationResponse = await page.goto(options.url, {
|
|
12449
|
-
waitUntil: 'domcontentloaded',
|
|
12450
|
-
timeout: options.timeouts.navigationTimeoutMs,
|
|
12451
|
-
});
|
|
12452
|
-
return {
|
|
12453
|
-
page,
|
|
12454
|
-
connectDurationMs,
|
|
12455
|
-
initialNavigationDurationMs: Date.now() - navigationStartedAt,
|
|
12456
|
-
timeToFirstByteMs: resolveTimeToFirstByteMs(navigationResponse),
|
|
12457
|
-
};
|
|
12458
|
-
}
|
|
12459
|
-
catch (error) {
|
|
12460
|
-
throw runBrowserErrorHandling.createRunBrowserNavigationError({
|
|
12461
|
-
message: `Failed to navigate to \`${options.url}\`.`,
|
|
12462
|
-
debug: {
|
|
12463
|
-
phase: 'initial-navigation',
|
|
12464
|
-
url: options.url,
|
|
12465
|
-
navigationTimeoutMs: options.timeouts.navigationTimeoutMs,
|
|
12466
|
-
},
|
|
12467
|
-
cause: error,
|
|
12468
|
-
});
|
|
12469
|
-
}
|
|
12470
|
-
},
|
|
12471
|
-
/**
|
|
12472
|
-
* Validates and normalizes browser actions received from the model.
|
|
12473
|
-
*/
|
|
12474
|
-
normalizeActions(actions) {
|
|
12475
|
-
if (!actions || actions.length === 0) {
|
|
12476
|
-
return [];
|
|
12477
|
-
}
|
|
12478
|
-
return actions.map((action, index) => this.normalizeAction(action, index));
|
|
12479
|
-
},
|
|
12480
|
-
/**
|
|
12481
|
-
* Validates and normalizes a single action.
|
|
12482
|
-
*/
|
|
12483
|
-
normalizeAction(action, index) {
|
|
12484
|
-
var _a, _b, _c;
|
|
12485
|
-
switch (action.type) {
|
|
12486
|
-
case 'navigate': {
|
|
12487
|
-
const url = String(action.value || '').trim();
|
|
12488
|
-
if (!url) {
|
|
12489
|
-
throw runBrowserErrorHandling.createRunBrowserValidationError({
|
|
12490
|
-
message: spaceTrim$1(`Action ${index + 1}: \`navigate\` requires non-empty \`value\` URL.`),
|
|
12491
|
-
debug: {
|
|
12492
|
-
actionIndex: index + 1,
|
|
12493
|
-
actionType: action.type,
|
|
12494
|
-
},
|
|
12495
|
-
});
|
|
12496
|
-
}
|
|
12497
|
-
return { type: 'navigate', url };
|
|
12498
|
-
}
|
|
12499
|
-
case 'click': {
|
|
12500
|
-
const selector = String(action.selector || '').trim();
|
|
12501
|
-
if (!selector) {
|
|
12502
|
-
throw runBrowserErrorHandling.createRunBrowserValidationError({
|
|
12503
|
-
message: spaceTrim$1(`Action ${index + 1}: \`click\` requires non-empty \`selector\`.`),
|
|
12504
|
-
debug: {
|
|
12505
|
-
actionIndex: index + 1,
|
|
12506
|
-
actionType: action.type,
|
|
12507
|
-
},
|
|
12508
|
-
});
|
|
12509
|
-
}
|
|
12510
|
-
return { type: 'click', selector };
|
|
12511
|
-
}
|
|
12512
|
-
case 'type': {
|
|
12513
|
-
const selector = String(action.selector || '').trim();
|
|
12514
|
-
if (!selector) {
|
|
12515
|
-
throw runBrowserErrorHandling.createRunBrowserValidationError({
|
|
12516
|
-
message: spaceTrim$1(`Action ${index + 1}: \`type\` requires non-empty \`selector\`.`),
|
|
12517
|
-
debug: {
|
|
12518
|
-
actionIndex: index + 1,
|
|
12519
|
-
actionType: action.type,
|
|
12520
|
-
},
|
|
12521
|
-
});
|
|
12522
|
-
}
|
|
12523
|
-
const text = String((_a = action.value) !== null && _a !== void 0 ? _a : '');
|
|
12524
|
-
return { type: 'type', selector, text };
|
|
12525
|
-
}
|
|
12526
|
-
case 'wait': {
|
|
12527
|
-
const requestedValue = Number.parseInt(String((_b = action.value) !== null && _b !== void 0 ? _b : runBrowserConstants.defaultWaitMs), 10);
|
|
12528
|
-
const milliseconds = Number.isFinite(requestedValue)
|
|
12529
|
-
? Math.min(Math.max(requestedValue, 1), runBrowserConstants.maxWaitMs)
|
|
12530
|
-
: runBrowserConstants.defaultWaitMs;
|
|
12531
|
-
return { type: 'wait', milliseconds };
|
|
12532
|
-
}
|
|
12533
|
-
case 'scroll': {
|
|
12534
|
-
const requestedValue = Number.parseInt(String((_c = action.value) !== null && _c !== void 0 ? _c : runBrowserConstants.defaultScrollPixels), 10);
|
|
12535
|
-
const pixels = Number.isFinite(requestedValue) ? requestedValue : runBrowserConstants.defaultScrollPixels;
|
|
12536
|
-
const rawSelector = String(action.selector || '').trim();
|
|
12537
|
-
return { type: 'scroll', selector: rawSelector || null, pixels };
|
|
12538
|
-
}
|
|
12539
|
-
}
|
|
12540
|
-
},
|
|
12541
|
-
/**
|
|
12542
|
-
* Executes one normalized browser action on a Playwright page.
|
|
12543
|
-
*/
|
|
12544
|
-
async executeAction(options) {
|
|
12545
|
-
const { page, action, actionIndex, timeouts, signal } = options;
|
|
12546
|
-
runBrowserErrorHandling.assertNotAborted(signal, `action-${actionIndex}`);
|
|
12547
|
-
try {
|
|
12548
|
-
switch (action.type) {
|
|
12549
|
-
case 'navigate':
|
|
12550
|
-
await page.goto(action.url, {
|
|
12551
|
-
waitUntil: 'domcontentloaded',
|
|
12552
|
-
timeout: timeouts.navigationTimeoutMs,
|
|
12553
|
-
});
|
|
12554
|
-
return;
|
|
12555
|
-
case 'click':
|
|
12556
|
-
await page.locator(action.selector).first().click({ timeout: timeouts.actionTimeoutMs });
|
|
12557
|
-
return;
|
|
12558
|
-
case 'type':
|
|
12559
|
-
await page.locator(action.selector).first().fill(action.text, { timeout: timeouts.actionTimeoutMs });
|
|
12560
|
-
return;
|
|
12561
|
-
case 'wait':
|
|
12562
|
-
if (action.milliseconds > timeouts.actionTimeoutMs) {
|
|
12563
|
-
throw runBrowserErrorHandling.createRunBrowserActionError({
|
|
12564
|
-
message: `Action ${actionIndex}: \`wait\` exceeds action timeout (${timeouts.actionTimeoutMs}ms).`,
|
|
12565
|
-
debug: {
|
|
12566
|
-
actionIndex,
|
|
12567
|
-
action,
|
|
12568
|
-
actionTimeoutMs: timeouts.actionTimeoutMs,
|
|
12569
|
-
},
|
|
12570
|
-
});
|
|
12571
|
-
}
|
|
12572
|
-
await page.waitForTimeout(action.milliseconds);
|
|
12573
|
-
return;
|
|
12574
|
-
case 'scroll':
|
|
12575
|
-
if (action.selector) {
|
|
12576
|
-
await page
|
|
12577
|
-
.locator(action.selector)
|
|
12578
|
-
.first()
|
|
12579
|
-
.scrollIntoViewIfNeeded({ timeout: timeouts.actionTimeoutMs });
|
|
12580
|
-
}
|
|
12581
|
-
await page.mouse.wheel(0, action.pixels);
|
|
12582
|
-
return;
|
|
12583
|
-
}
|
|
12584
|
-
}
|
|
12585
|
-
catch (error) {
|
|
12586
|
-
if (runBrowserErrorHandling.isTaggedRunBrowserError(error)) {
|
|
12587
|
-
throw error;
|
|
12588
|
-
}
|
|
12589
|
-
if (action.type === 'navigate') {
|
|
12590
|
-
throw runBrowserErrorHandling.createRunBrowserNavigationError({
|
|
12591
|
-
message: `Action ${actionIndex}: failed to navigate to \`${action.url}\`.`,
|
|
12592
|
-
debug: {
|
|
12593
|
-
actionIndex,
|
|
12594
|
-
action,
|
|
12595
|
-
navigationTimeoutMs: timeouts.navigationTimeoutMs,
|
|
12596
|
-
},
|
|
12597
|
-
cause: error,
|
|
12598
|
-
});
|
|
12599
|
-
}
|
|
12600
|
-
throw runBrowserErrorHandling.createRunBrowserActionError({
|
|
12601
|
-
message: `Action ${actionIndex}: failed to execute \`${action.type}\`.`,
|
|
12602
|
-
debug: {
|
|
12603
|
-
actionIndex,
|
|
12604
|
-
action,
|
|
12605
|
-
actionTimeoutMs: timeouts.actionTimeoutMs,
|
|
12606
|
-
},
|
|
12607
|
-
cause: error,
|
|
12608
|
-
});
|
|
12609
|
-
}
|
|
12610
|
-
},
|
|
12611
|
-
};
|
|
12612
|
-
|
|
12613
|
-
/**
|
|
12614
|
-
* Summarizes one normalized browser action in user-facing language.
|
|
12615
|
-
*/
|
|
12616
|
-
function formatRunBrowserActionSummary(action) {
|
|
12617
|
-
switch (action.type) {
|
|
12618
|
-
case 'navigate':
|
|
12619
|
-
return `Navigate to ${action.url}`;
|
|
12620
|
-
case 'click':
|
|
12621
|
-
return `Click ${action.selector}`;
|
|
12622
|
-
case 'type':
|
|
12623
|
-
return `Type into ${action.selector}`;
|
|
12624
|
-
case 'wait':
|
|
12625
|
-
return `Wait ${action.milliseconds}ms`;
|
|
12626
|
-
case 'scroll':
|
|
12627
|
-
return action.selector ? `Scroll ${action.pixels}px in ${action.selector}` : `Scroll ${action.pixels}px on page`;
|
|
12628
|
-
}
|
|
12629
|
-
}
|
|
12630
|
-
/**
|
|
12631
|
-
* Emits one incremental browser-tool update when a hidden chat-progress listener is attached.
|
|
12632
|
-
*/
|
|
12633
|
-
function emitRunBrowserProgress(args, update) {
|
|
12634
|
-
emitToolCallProgressFromToolArgs(args, update);
|
|
12635
|
-
}
|
|
12636
|
-
/**
|
|
12637
|
-
* Returns the current timestamp in the branded ISO-8601 format used by tool-call logs.
|
|
12638
|
-
*/
|
|
12639
|
-
function createRunBrowserLogTimestamp() {
|
|
12640
|
-
return new Date().toISOString();
|
|
12641
|
-
}
|
|
12642
|
-
/**
|
|
12643
|
-
* Executes non-graphical fallback scraping.
|
|
12644
|
-
*/
|
|
12645
|
-
async function runFallbackScrape(url) {
|
|
12646
|
-
return await fetchUrlContent(url);
|
|
12647
|
-
}
|
|
12648
|
-
/**
|
|
12649
|
-
* Runs interactive browser automation through Playwright.
|
|
12650
|
-
*
|
|
12651
|
-
* @param args Tool arguments provided by the model.
|
|
12652
|
-
* @param internalOptions Optional runtime options for cancellation.
|
|
12653
|
-
* @returns Markdown summary with structured playback payload.
|
|
12654
|
-
*/
|
|
12655
|
-
async function run_browser(args, internalOptions = {}) {
|
|
12656
|
-
runBrowserObservability.incrementTotalRuns();
|
|
12657
|
-
const startedAt = Date.now();
|
|
12658
|
-
const sessionId = runBrowserRuntime.createRunBrowserSessionId();
|
|
12659
|
-
const initialUrl = String(args.url || '').trim();
|
|
12660
|
-
const mode = runBrowserRuntime.resolveExecutionMode();
|
|
12661
|
-
const timeoutConfiguration = runBrowserRuntime.resolveTimeoutConfiguration(args.timeouts);
|
|
12662
|
-
let page = null;
|
|
12663
|
-
let connectDurationMs = null;
|
|
12664
|
-
let initialNavigationDurationMs = null;
|
|
12665
|
-
let timeToFirstByteMs = null;
|
|
12666
|
-
try {
|
|
12667
|
-
if (!initialUrl) {
|
|
12668
|
-
throw runBrowserErrorHandling.createRunBrowserValidationError({
|
|
12669
|
-
message: 'Missing required `url` argument.',
|
|
12670
|
-
debug: {
|
|
12671
|
-
field: 'url',
|
|
12672
|
-
},
|
|
12673
|
-
});
|
|
12674
|
-
}
|
|
12675
|
-
const normalizedActions = runBrowserWorkflow.normalizeActions(args.actions);
|
|
12676
|
-
runBrowserErrorHandling.assertNotAborted(internalOptions.signal, sessionId);
|
|
12677
|
-
const openedPage = await runBrowserWorkflow.openPageWithUrl({
|
|
12678
|
-
url: initialUrl,
|
|
12679
|
-
sessionId,
|
|
12680
|
-
timeouts: timeoutConfiguration,
|
|
12681
|
-
signal: internalOptions.signal,
|
|
12682
|
-
});
|
|
12683
|
-
page = openedPage.page;
|
|
12684
|
-
connectDurationMs = openedPage.connectDurationMs;
|
|
12685
|
-
initialNavigationDurationMs = openedPage.initialNavigationDurationMs;
|
|
12686
|
-
timeToFirstByteMs = openedPage.timeToFirstByteMs;
|
|
12687
|
-
emitRunBrowserProgress(args, {
|
|
12688
|
-
state: 'PARTIAL',
|
|
12689
|
-
log: {
|
|
12690
|
-
createdAt: createRunBrowserLogTimestamp(),
|
|
12691
|
-
kind: 'browser-session',
|
|
12692
|
-
title: 'Browser ready',
|
|
12693
|
-
message: 'Opened the initial page and started the browser session.',
|
|
12694
|
-
payload: {
|
|
12695
|
-
sessionId,
|
|
12696
|
-
initialUrl,
|
|
12697
|
-
connectDurationMs,
|
|
12698
|
-
initialNavigationDurationMs,
|
|
12699
|
-
timeToFirstByteMs,
|
|
12700
|
-
},
|
|
12701
|
-
},
|
|
12702
|
-
});
|
|
12703
|
-
const artifacts = [];
|
|
12704
|
-
const initialArtifact = await runBrowserArtifacts.captureSnapshotArtifact({
|
|
12705
|
-
page,
|
|
12706
|
-
sessionId,
|
|
12707
|
-
label: 'Initial page',
|
|
12708
|
-
fileSuffix: 'initial',
|
|
12709
|
-
});
|
|
12710
|
-
if (initialArtifact) {
|
|
12711
|
-
artifacts.push(initialArtifact);
|
|
12712
|
-
}
|
|
12713
|
-
for (const [index, action] of normalizedActions.entries()) {
|
|
12714
|
-
runBrowserErrorHandling.assertNotAborted(internalOptions.signal, sessionId);
|
|
12715
|
-
emitRunBrowserProgress(args, {
|
|
12716
|
-
state: 'PARTIAL',
|
|
12717
|
-
log: {
|
|
12718
|
-
createdAt: createRunBrowserLogTimestamp(),
|
|
12719
|
-
kind: 'browser-action',
|
|
12720
|
-
title: `Action ${index + 1} running`,
|
|
12721
|
-
message: formatRunBrowserActionSummary(action),
|
|
12722
|
-
payload: {
|
|
12723
|
-
actionIndex: index + 1,
|
|
12724
|
-
action,
|
|
12725
|
-
phase: 'running',
|
|
12726
|
-
},
|
|
12727
|
-
},
|
|
12728
|
-
});
|
|
12729
|
-
await runBrowserWorkflow.executeAction({
|
|
12730
|
-
page,
|
|
12731
|
-
action,
|
|
12732
|
-
actionIndex: index + 1,
|
|
12733
|
-
timeouts: timeoutConfiguration,
|
|
12734
|
-
signal: internalOptions.signal,
|
|
12735
|
-
});
|
|
12736
|
-
emitRunBrowserProgress(args, {
|
|
12737
|
-
state: 'PARTIAL',
|
|
12738
|
-
log: {
|
|
12739
|
-
createdAt: createRunBrowserLogTimestamp(),
|
|
12740
|
-
kind: 'browser-action',
|
|
12741
|
-
title: `Action ${index + 1} finished`,
|
|
12742
|
-
message: formatRunBrowserActionSummary(action),
|
|
12743
|
-
payload: {
|
|
12744
|
-
actionIndex: index + 1,
|
|
12745
|
-
action,
|
|
12746
|
-
phase: 'complete',
|
|
12747
|
-
},
|
|
12748
|
-
},
|
|
12749
|
-
});
|
|
12750
|
-
const actionArtifact = await runBrowserArtifacts.captureSnapshotArtifact({
|
|
12751
|
-
page,
|
|
12752
|
-
sessionId,
|
|
12753
|
-
label: `After action ${index + 1}`,
|
|
12754
|
-
fileSuffix: `action-${String(index + 1).padStart(3, '0')}-${action.type}`,
|
|
12755
|
-
actionIndex: index + 1,
|
|
12756
|
-
action,
|
|
12757
|
-
});
|
|
12758
|
-
if (actionArtifact) {
|
|
12759
|
-
artifacts.push(actionArtifact);
|
|
12760
|
-
}
|
|
12761
|
-
}
|
|
12762
|
-
const snapshotPath = await runBrowserArtifacts.captureSnapshot(page, sessionId);
|
|
12763
|
-
const finalUrl = page.url();
|
|
12764
|
-
const finalTitle = await runBrowserArtifacts.getPageTitle(page);
|
|
12765
|
-
if (snapshotPath) {
|
|
12766
|
-
artifacts.push({
|
|
12767
|
-
kind: 'screenshot',
|
|
12768
|
-
label: 'Final page',
|
|
12769
|
-
path: snapshotPath,
|
|
12770
|
-
capturedAt: new Date().toISOString(),
|
|
12771
|
-
url: finalUrl,
|
|
12772
|
-
title: finalTitle,
|
|
12773
|
-
});
|
|
12774
|
-
}
|
|
12775
|
-
const payload = runBrowserResultFormatting.createResultPayload({
|
|
12776
|
-
sessionId,
|
|
12777
|
-
mode,
|
|
12778
|
-
modeUsed: 'remote-browser',
|
|
12779
|
-
initialUrl,
|
|
12780
|
-
finalUrl,
|
|
12781
|
-
finalTitle,
|
|
12782
|
-
executedActions: normalizedActions,
|
|
12783
|
-
artifacts,
|
|
12784
|
-
warning: null,
|
|
12785
|
-
error: null,
|
|
12786
|
-
fallbackContent: null,
|
|
12787
|
-
timing: {
|
|
12788
|
-
connectDurationMs,
|
|
12789
|
-
initialNavigationDurationMs,
|
|
12790
|
-
timeToFirstByteMs,
|
|
12791
|
-
totalDurationMs: Date.now() - startedAt,
|
|
12792
|
-
},
|
|
12793
|
-
});
|
|
12794
|
-
runBrowserObservability.logRunBrowserMetric({
|
|
12795
|
-
event: 'run_browser_success',
|
|
12796
|
-
sessionId,
|
|
12797
|
-
mode: 'remote-browser',
|
|
12798
|
-
payload: {
|
|
12799
|
-
actions: normalizedActions.length,
|
|
12800
|
-
connectDurationMs,
|
|
12801
|
-
initialNavigationDurationMs,
|
|
12802
|
-
timeToFirstByteMs,
|
|
12803
|
-
},
|
|
12804
|
-
});
|
|
12805
|
-
return runBrowserResultFormatting.formatSuccessResult({
|
|
12806
|
-
payload,
|
|
12807
|
-
snapshotPath,
|
|
12808
|
-
});
|
|
12809
|
-
}
|
|
12810
|
-
catch (error) {
|
|
12811
|
-
const toolError = runBrowserErrorHandling.classifyRunBrowserToolError({
|
|
12812
|
-
error,
|
|
12813
|
-
sessionId,
|
|
12814
|
-
mode,
|
|
12815
|
-
});
|
|
12816
|
-
const errorCodeCount = runBrowserObservability.incrementRunBrowserErrorCodeCounter(toolError.code);
|
|
12817
|
-
if (runBrowserErrorHandling.isRemoteBrowserUnavailableCode(toolError.code) && initialUrl) {
|
|
12818
|
-
const fallbackContent = await runFallbackScrape(initialUrl);
|
|
12819
|
-
const { fallbackRuns, fallbackRate } = runBrowserObservability.incrementFallbackRunsAndGetMetrics();
|
|
12820
|
-
emitRunBrowserProgress(args, {
|
|
12821
|
-
state: 'PARTIAL',
|
|
12822
|
-
log: {
|
|
12823
|
-
createdAt: createRunBrowserLogTimestamp(),
|
|
12824
|
-
kind: 'warning',
|
|
12825
|
-
level: 'warning',
|
|
12826
|
-
title: 'Fallback enabled',
|
|
12827
|
-
message: 'Remote browser was unavailable, so fallback scraping was used instead.',
|
|
12828
|
-
payload: {
|
|
12829
|
-
errorCode: toolError.code,
|
|
12830
|
-
initialUrl,
|
|
12831
|
-
},
|
|
12832
|
-
},
|
|
12833
|
-
});
|
|
12834
|
-
const payload = runBrowserResultFormatting.createResultPayload({
|
|
12835
|
-
sessionId,
|
|
12836
|
-
mode,
|
|
12837
|
-
modeUsed: 'fallback',
|
|
12838
|
-
initialUrl,
|
|
12839
|
-
finalUrl: null,
|
|
12840
|
-
finalTitle: null,
|
|
12841
|
-
executedActions: [],
|
|
12842
|
-
artifacts: [],
|
|
12843
|
-
warning: runBrowserConstants.fallbackDynamicContentWarning,
|
|
12844
|
-
error: toolError,
|
|
12845
|
-
fallbackContent,
|
|
12846
|
-
timing: {
|
|
12847
|
-
connectDurationMs,
|
|
12848
|
-
initialNavigationDurationMs,
|
|
12849
|
-
timeToFirstByteMs,
|
|
12850
|
-
totalDurationMs: Date.now() - startedAt,
|
|
12851
|
-
},
|
|
12852
|
-
});
|
|
12853
|
-
runBrowserObservability.logRunBrowserMetric({
|
|
12854
|
-
event: 'run_browser_fallback_used',
|
|
12855
|
-
sessionId,
|
|
12856
|
-
mode: 'fallback',
|
|
12857
|
-
payload: {
|
|
12858
|
-
errorCode: toolError.code,
|
|
12859
|
-
errorCodeCount,
|
|
12860
|
-
fallbackRuns,
|
|
12861
|
-
totalRuns: runBrowserObservability.getTotalRuns(),
|
|
12862
|
-
fallbackRate,
|
|
12863
|
-
},
|
|
12864
|
-
});
|
|
12865
|
-
return runBrowserResultFormatting.formatFallbackResult({
|
|
12866
|
-
payload,
|
|
12867
|
-
fallbackContent,
|
|
12868
|
-
requestedActions: Array.isArray(args.actions) ? args.actions.length : 0,
|
|
12869
|
-
});
|
|
12870
|
-
}
|
|
12871
|
-
emitRunBrowserProgress(args, {
|
|
12872
|
-
state: 'ERROR',
|
|
12873
|
-
log: {
|
|
12874
|
-
createdAt: createRunBrowserLogTimestamp(),
|
|
12875
|
-
kind: 'error',
|
|
12876
|
-
level: 'error',
|
|
12877
|
-
title: 'Browser run failed',
|
|
12878
|
-
message: toolError.message,
|
|
12879
|
-
payload: {
|
|
12880
|
-
code: toolError.code,
|
|
12881
|
-
debug: toolError.debug,
|
|
12882
|
-
},
|
|
12883
|
-
},
|
|
12884
|
-
});
|
|
12885
|
-
const payload = runBrowserResultFormatting.createResultPayload({
|
|
12886
|
-
sessionId,
|
|
12887
|
-
mode,
|
|
12888
|
-
modeUsed: 'remote-browser',
|
|
12889
|
-
initialUrl,
|
|
12890
|
-
finalUrl: page ? page.url() : null,
|
|
12891
|
-
finalTitle: page ? await runBrowserArtifacts.getPageTitle(page) : null,
|
|
12892
|
-
executedActions: [],
|
|
12893
|
-
artifacts: [],
|
|
12894
|
-
warning: null,
|
|
12895
|
-
error: toolError,
|
|
12896
|
-
fallbackContent: null,
|
|
12897
|
-
timing: {
|
|
12898
|
-
connectDurationMs,
|
|
12899
|
-
initialNavigationDurationMs,
|
|
12900
|
-
timeToFirstByteMs,
|
|
12901
|
-
totalDurationMs: Date.now() - startedAt,
|
|
12902
|
-
},
|
|
12903
|
-
});
|
|
12904
|
-
runBrowserObservability.logRunBrowserMetric({
|
|
12905
|
-
event: 'run_browser_failed',
|
|
12906
|
-
sessionId,
|
|
12907
|
-
mode: 'remote-browser',
|
|
12908
|
-
payload: {
|
|
12909
|
-
errorCode: toolError.code,
|
|
12910
|
-
errorCodeCount,
|
|
12911
|
-
connectDurationMs,
|
|
12912
|
-
initialNavigationDurationMs,
|
|
12913
|
-
timeToFirstByteMs,
|
|
12914
|
-
},
|
|
12915
|
-
});
|
|
12916
|
-
return runBrowserResultFormatting.formatErrorResult({
|
|
12917
|
-
payload,
|
|
12918
|
-
});
|
|
12919
|
-
}
|
|
12920
|
-
finally {
|
|
12921
|
-
await runBrowserArtifacts.cleanupPage(page, sessionId);
|
|
12922
|
-
}
|
|
12923
|
-
}
|
|
12924
|
-
|
|
12925
|
-
/**
|
|
12926
|
-
* Resolves the server-side implementation of the `run_browser` tool for Node.js environments.
|
|
12927
|
-
*
|
|
12928
|
-
* This uses lazy `require` to keep the core package decoupled from Agents Server internals.
|
|
12929
|
-
* When the server tool cannot be resolved, the fallback implementation throws a helpful error.
|
|
12930
|
-
*
|
|
12931
|
-
* @private internal utility for USE BROWSER commitment
|
|
12932
|
-
*/
|
|
12933
|
-
function resolveRunBrowserToolForNode() {
|
|
12934
|
-
try {
|
|
12935
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12936
|
-
// const { run_browser } = require('../../../apps/agents-server/src/tools/run_browser');
|
|
12937
|
-
if (typeof run_browser !== 'function') {
|
|
12938
|
-
throw new Error('run_browser value is not a function but ' + typeof run_browser);
|
|
12939
|
-
}
|
|
12940
|
-
return run_browser;
|
|
12941
|
-
}
|
|
12942
|
-
catch (error) {
|
|
12943
|
-
assertsError(error);
|
|
12944
|
-
return async () => {
|
|
12945
|
-
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
12946
|
-
\`run_browser\` tool is not available in this environment.
|
|
12947
|
-
This commitment requires the Agents Server browser runtime with Playwright CLI.
|
|
12948
|
-
|
|
12949
|
-
${error.name}:
|
|
12950
|
-
${block(error.message)}
|
|
12951
|
-
`));
|
|
12952
|
-
};
|
|
12953
|
-
}
|
|
12954
|
-
}
|
|
12955
|
-
|
|
12956
|
-
/**
|
|
12957
|
-
* Resolves the server-side implementation of the send_email tool for Node.js environments.
|
|
12958
|
-
*
|
|
12959
|
-
* This uses a lazy require so the core package can still load even if the Agents Server
|
|
12960
|
-
* module is unavailable. When the server tool cannot be resolved, a fallback implementation
|
|
12961
|
-
* throws a helpful error message.
|
|
12962
|
-
*
|
|
12963
|
-
* @private internal utility for USE EMAIL commitment
|
|
12964
|
-
*/
|
|
12965
|
-
function resolveSendEmailToolForNode() {
|
|
12966
|
-
try {
|
|
12967
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12968
|
-
const { send_email } = require('../../../apps/agents-server/src/tools/send_email');
|
|
12969
|
-
if (typeof send_email !== 'function') {
|
|
12970
|
-
throw new Error('send_email value is not a function but ' + typeof send_email);
|
|
12971
|
-
}
|
|
12972
|
-
return send_email;
|
|
12973
|
-
}
|
|
12974
|
-
catch (error) {
|
|
12975
|
-
const normalizedError = error instanceof Error
|
|
12976
|
-
? error
|
|
12977
|
-
: new Error(typeof error === 'string' ? error : JSON.stringify(error !== null && error !== void 0 ? error : 'Unknown error'));
|
|
12978
|
-
return async () => {
|
|
12979
|
-
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
12980
|
-
\`send_email\` tool is not available in this environment.
|
|
12981
|
-
This commitment requires Agents Server runtime with wallet-backed SMTP sending.
|
|
12982
|
-
|
|
12983
|
-
${normalizedError.name}:
|
|
12984
|
-
${block(normalizedError.message)}
|
|
12985
|
-
`));
|
|
12986
|
-
};
|
|
12987
|
-
}
|
|
12988
|
-
}
|
|
12989
|
-
|
|
12990
|
-
/**
|
|
12991
|
-
* Resolves the server-side `spawn_agent` tool for Node.js runtimes.
|
|
12992
|
-
*
|
|
12993
|
-
* Uses lazy require so core package can load outside Agents Server.
|
|
12994
|
-
*
|
|
12995
|
-
* @private internal utility for USE SPAWN commitment
|
|
12996
|
-
*/
|
|
12997
|
-
function resolveSpawnAgentToolForNode() {
|
|
12998
|
-
try {
|
|
12999
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
13000
|
-
const { spawn_agent } = require('../../../apps/agents-server/src/tools/spawn_agent');
|
|
13001
|
-
if (typeof spawn_agent !== 'function') {
|
|
13002
|
-
throw new Error('spawn_agent value is not a function but ' + typeof spawn_agent);
|
|
13003
|
-
}
|
|
13004
|
-
return spawn_agent;
|
|
13005
|
-
}
|
|
13006
|
-
catch (error) {
|
|
13007
|
-
const normalizedError = error instanceof Error
|
|
13008
|
-
? error
|
|
13009
|
-
: new Error(typeof error === 'string' ? error : JSON.stringify(error !== null && error !== void 0 ? error : 'Unknown error'));
|
|
13010
|
-
return async () => {
|
|
13011
|
-
throw new EnvironmentMismatchError(spaceTrim$1((block) => `
|
|
13012
|
-
\`spawn_agent\` tool is not available in this environment.
|
|
13013
|
-
This commitment requires Agents Server runtime with agent persistence enabled.
|
|
13014
|
-
|
|
13015
|
-
${normalizedError.name}:
|
|
13016
|
-
${block(normalizedError.message)}
|
|
13017
|
-
`));
|
|
13018
|
-
};
|
|
13019
|
-
}
|
|
13020
|
-
}
|
|
13021
|
-
|
|
13022
|
-
/**
|
|
13023
|
-
* Generates a regex pattern to match a specific commitment
|
|
13024
|
-
*
|
|
13025
|
-
* Note: It always creates new Regex object
|
|
13026
|
-
* Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
|
|
13027
|
-
*
|
|
13028
|
-
* @private - TODO: [🧠] Maybe should be public?
|
|
13029
|
-
*/
|
|
13030
|
-
function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
|
|
13031
|
-
const allCommitments = [commitment, ...aliases];
|
|
13032
|
-
const patterns = allCommitments.map((commitment) => {
|
|
13033
|
-
const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13034
|
-
return escapedCommitment.split(/\s+/).join('\\s+');
|
|
13035
|
-
});
|
|
13036
|
-
const keywordPattern = patterns.join('|');
|
|
13037
|
-
if (requiresContent) {
|
|
13038
|
-
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
|
|
13039
|
-
}
|
|
13040
|
-
else {
|
|
13041
|
-
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
|
|
13042
|
-
}
|
|
13043
|
-
}
|
|
13044
|
-
/**
|
|
13045
|
-
* Generates a regex pattern to match a specific commitment type
|
|
13046
|
-
*
|
|
13047
|
-
* Note: It just matches the type part of the commitment
|
|
13048
|
-
* Note: It always creates new Regex object
|
|
13049
|
-
* Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
|
|
13050
|
-
*
|
|
13051
|
-
* @private
|
|
13052
|
-
*/
|
|
13053
|
-
function createCommitmentTypeRegex(commitment, aliases = []) {
|
|
13054
|
-
const allCommitments = [commitment, ...aliases];
|
|
13055
|
-
const patterns = allCommitments.map((commitment) => {
|
|
13056
|
-
const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13057
|
-
return escapedCommitment.split(/\s+/).join('\\s+');
|
|
13058
|
-
});
|
|
13059
|
-
const keywordPattern = patterns.join('|');
|
|
13060
|
-
const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
|
|
13061
|
-
return regex;
|
|
13062
|
-
}
|
|
13063
|
-
|
|
13064
|
-
/**
|
|
13065
|
-
* Base implementation of CommitmentDefinition that provides common functionality
|
|
13066
|
-
* Most commitments can extend this class and only override the applyToAgentModelRequirements method
|
|
13067
|
-
*
|
|
13068
|
-
* @private
|
|
13069
|
-
*/
|
|
13070
|
-
class BaseCommitmentDefinition {
|
|
13071
|
-
constructor(type, aliases = []) {
|
|
13072
|
-
this.type = type;
|
|
13073
|
-
this.aliases = aliases;
|
|
11057
|
+
class BaseCommitmentDefinition {
|
|
11058
|
+
constructor(type, aliases = []) {
|
|
11059
|
+
this.type = type;
|
|
11060
|
+
this.aliases = aliases;
|
|
13074
11061
|
}
|
|
13075
11062
|
/**
|
|
13076
11063
|
* Whether this commitment requires content.
|
|
@@ -14716,74 +12703,178 @@ function getMemoryToolRuntimeAdapterOrDisabledResult(action, runtimeContext) {
|
|
|
14716
12703
|
};
|
|
14717
12704
|
}
|
|
14718
12705
|
}
|
|
14719
|
-
|
|
12706
|
+
|
|
12707
|
+
/**
|
|
12708
|
+
* Parses a memory identifier argument shared across MEMORY tools.
|
|
12709
|
+
*
|
|
12710
|
+
* @private function of MemoryCommitmentDefinition
|
|
12711
|
+
*/
|
|
12712
|
+
function parseMemoryIdArg(value) {
|
|
12713
|
+
const memoryId = typeof value === 'string' ? value.trim() : '';
|
|
12714
|
+
if (!memoryId) {
|
|
12715
|
+
throw new Error('Memory id is required.');
|
|
12716
|
+
}
|
|
12717
|
+
return memoryId;
|
|
12718
|
+
}
|
|
12719
|
+
/**
|
|
12720
|
+
* Collection of MEMORY tool argument parsers.
|
|
12721
|
+
*
|
|
12722
|
+
* @private function of MemoryCommitmentDefinition
|
|
12723
|
+
*/
|
|
12724
|
+
const parseMemoryToolArgs = {
|
|
12725
|
+
/**
|
|
12726
|
+
* Parses retrieve memory arguments.
|
|
12727
|
+
*/
|
|
12728
|
+
retrieve(args) {
|
|
12729
|
+
const query = typeof args.query === 'string' ? args.query.trim() : undefined;
|
|
12730
|
+
const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
|
|
12731
|
+
return {
|
|
12732
|
+
query: query && query.length > 0 ? query : undefined,
|
|
12733
|
+
limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
|
|
12734
|
+
};
|
|
12735
|
+
},
|
|
12736
|
+
/**
|
|
12737
|
+
* Parses store memory arguments.
|
|
12738
|
+
*/
|
|
12739
|
+
store(args) {
|
|
12740
|
+
const content = typeof args.content === 'string' ? args.content.trim() : '';
|
|
12741
|
+
if (!content) {
|
|
12742
|
+
throw new Error('Memory content is required.');
|
|
12743
|
+
}
|
|
12744
|
+
return {
|
|
12745
|
+
content,
|
|
12746
|
+
isGlobal: args.isGlobal === true,
|
|
12747
|
+
};
|
|
12748
|
+
},
|
|
12749
|
+
/**
|
|
12750
|
+
* Parses update memory arguments.
|
|
12751
|
+
*/
|
|
12752
|
+
update(args) {
|
|
12753
|
+
const memoryId = parseMemoryIdArg(args.memoryId);
|
|
12754
|
+
const content = typeof args.content === 'string' ? args.content.trim() : '';
|
|
12755
|
+
if (!content) {
|
|
12756
|
+
throw new Error('Memory content is required.');
|
|
12757
|
+
}
|
|
12758
|
+
const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
|
|
12759
|
+
return {
|
|
12760
|
+
memoryId,
|
|
12761
|
+
content,
|
|
12762
|
+
isGlobal,
|
|
12763
|
+
};
|
|
12764
|
+
},
|
|
12765
|
+
/**
|
|
12766
|
+
* Parses delete memory arguments.
|
|
12767
|
+
*/
|
|
12768
|
+
delete(args) {
|
|
12769
|
+
return {
|
|
12770
|
+
memoryId: parseMemoryIdArg(args.memoryId),
|
|
12771
|
+
};
|
|
12772
|
+
},
|
|
12773
|
+
};
|
|
12774
|
+
|
|
12775
|
+
/**
|
|
12776
|
+
* Prompt parameter key used to pass hidden runtime context to tool execution.
|
|
12777
|
+
*
|
|
12778
|
+
* @private internal runtime wiring for commitment tools
|
|
12779
|
+
*/
|
|
12780
|
+
const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
|
|
12781
|
+
/**
|
|
12782
|
+
* Hidden argument key used to pass runtime context into individual tool calls.
|
|
12783
|
+
*
|
|
12784
|
+
* @private internal runtime wiring for commitment tools
|
|
12785
|
+
*/
|
|
12786
|
+
const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
|
|
12787
|
+
/**
|
|
12788
|
+
* Prompt parameter key used to pass a hidden tool-progress listener token into script execution.
|
|
12789
|
+
*
|
|
12790
|
+
* @private internal runtime wiring for commitment tools
|
|
12791
|
+
*/
|
|
12792
|
+
const TOOL_PROGRESS_TOKEN_PARAMETER = 'promptbookToolProgressToken';
|
|
12793
|
+
/**
|
|
12794
|
+
* Hidden argument key used to pass a tool-progress listener token into individual tool calls.
|
|
12795
|
+
*
|
|
12796
|
+
* @private internal runtime wiring for commitment tools
|
|
12797
|
+
*/
|
|
12798
|
+
const TOOL_PROGRESS_TOKEN_ARGUMENT = '__promptbookToolProgressToken';
|
|
12799
|
+
/**
|
|
12800
|
+
* Monotonic counter used for hidden progress-listener tokens.
|
|
12801
|
+
*
|
|
12802
|
+
* @private internal runtime wiring for commitment tools
|
|
12803
|
+
*/
|
|
12804
|
+
let toolCallProgressListenerCounter = 0;
|
|
12805
|
+
/**
|
|
12806
|
+
* Active tool-progress listeners keyed by hidden execution token.
|
|
12807
|
+
*
|
|
12808
|
+
* @private internal runtime wiring for commitment tools
|
|
12809
|
+
*/
|
|
12810
|
+
const toolCallProgressListeners = new Map();
|
|
12811
|
+
/**
|
|
12812
|
+
* Parses unknown runtime context payload into a normalized object.
|
|
12813
|
+
*
|
|
12814
|
+
* @private internal runtime wiring for commitment tools
|
|
12815
|
+
*/
|
|
12816
|
+
function parseToolRuntimeContext(rawValue) {
|
|
12817
|
+
if (!rawValue) {
|
|
12818
|
+
return null;
|
|
12819
|
+
}
|
|
12820
|
+
let parsed = rawValue;
|
|
12821
|
+
if (typeof rawValue === 'string') {
|
|
12822
|
+
try {
|
|
12823
|
+
parsed = JSON.parse(rawValue);
|
|
12824
|
+
}
|
|
12825
|
+
catch (_a) {
|
|
12826
|
+
return null;
|
|
12827
|
+
}
|
|
12828
|
+
}
|
|
12829
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
12830
|
+
return null;
|
|
12831
|
+
}
|
|
12832
|
+
return parsed;
|
|
12833
|
+
}
|
|
12834
|
+
/**
|
|
12835
|
+
* Reads runtime context attached to tool call arguments.
|
|
12836
|
+
*
|
|
12837
|
+
* @private internal runtime wiring for commitment tools
|
|
12838
|
+
*/
|
|
12839
|
+
function readToolRuntimeContextFromToolArgs(args) {
|
|
12840
|
+
return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
|
|
12841
|
+
}
|
|
12842
|
+
/**
|
|
12843
|
+
* Serializes runtime context for prompt parameters.
|
|
12844
|
+
*
|
|
12845
|
+
* @private internal runtime wiring for commitment tools
|
|
12846
|
+
*/
|
|
12847
|
+
function serializeToolRuntimeContext(context) {
|
|
12848
|
+
return JSON.stringify(context);
|
|
12849
|
+
}
|
|
12850
|
+
/**
|
|
12851
|
+
* Registers one in-memory listener that receives progress updates emitted by a running tool.
|
|
12852
|
+
*
|
|
12853
|
+
* The returned token is passed into script execution as a hidden argument so tool implementations
|
|
12854
|
+
* can stream progress without exposing extra parameters to the model.
|
|
12855
|
+
*
|
|
12856
|
+
* @param listener - Listener notified about tool progress.
|
|
12857
|
+
* @returns Hidden token used to route progress updates.
|
|
12858
|
+
* @private internal runtime wiring for commitment tools
|
|
12859
|
+
*/
|
|
12860
|
+
function registerToolCallProgressListener(listener) {
|
|
12861
|
+
toolCallProgressListenerCounter += 1;
|
|
12862
|
+
const token = `tool-progress:${Date.now()}:${toolCallProgressListenerCounter}`;
|
|
12863
|
+
toolCallProgressListeners.set(token, listener);
|
|
12864
|
+
return token;
|
|
12865
|
+
}
|
|
14720
12866
|
/**
|
|
14721
|
-
*
|
|
12867
|
+
* Unregisters one in-memory progress listener.
|
|
14722
12868
|
*
|
|
14723
|
-
* @
|
|
12869
|
+
* @param token - Token previously created by `registerToolCallProgressListener`.
|
|
12870
|
+
* @private internal runtime wiring for commitment tools
|
|
14724
12871
|
*/
|
|
14725
|
-
function
|
|
14726
|
-
|
|
14727
|
-
if (!memoryId) {
|
|
14728
|
-
throw new Error('Memory id is required.');
|
|
14729
|
-
}
|
|
14730
|
-
return memoryId;
|
|
12872
|
+
function unregisterToolCallProgressListener(token) {
|
|
12873
|
+
toolCallProgressListeners.delete(token);
|
|
14731
12874
|
}
|
|
14732
12875
|
/**
|
|
14733
|
-
*
|
|
14734
|
-
*
|
|
14735
|
-
* @private function of MemoryCommitmentDefinition
|
|
12876
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
14736
12877
|
*/
|
|
14737
|
-
const parseMemoryToolArgs = {
|
|
14738
|
-
/**
|
|
14739
|
-
* Parses retrieve memory arguments.
|
|
14740
|
-
*/
|
|
14741
|
-
retrieve(args) {
|
|
14742
|
-
const query = typeof args.query === 'string' ? args.query.trim() : undefined;
|
|
14743
|
-
const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
|
|
14744
|
-
return {
|
|
14745
|
-
query: query && query.length > 0 ? query : undefined,
|
|
14746
|
-
limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
|
|
14747
|
-
};
|
|
14748
|
-
},
|
|
14749
|
-
/**
|
|
14750
|
-
* Parses store memory arguments.
|
|
14751
|
-
*/
|
|
14752
|
-
store(args) {
|
|
14753
|
-
const content = typeof args.content === 'string' ? args.content.trim() : '';
|
|
14754
|
-
if (!content) {
|
|
14755
|
-
throw new Error('Memory content is required.');
|
|
14756
|
-
}
|
|
14757
|
-
return {
|
|
14758
|
-
content,
|
|
14759
|
-
isGlobal: args.isGlobal === true,
|
|
14760
|
-
};
|
|
14761
|
-
},
|
|
14762
|
-
/**
|
|
14763
|
-
* Parses update memory arguments.
|
|
14764
|
-
*/
|
|
14765
|
-
update(args) {
|
|
14766
|
-
const memoryId = parseMemoryIdArg(args.memoryId);
|
|
14767
|
-
const content = typeof args.content === 'string' ? args.content.trim() : '';
|
|
14768
|
-
if (!content) {
|
|
14769
|
-
throw new Error('Memory content is required.');
|
|
14770
|
-
}
|
|
14771
|
-
const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
|
|
14772
|
-
return {
|
|
14773
|
-
memoryId,
|
|
14774
|
-
content,
|
|
14775
|
-
isGlobal,
|
|
14776
|
-
};
|
|
14777
|
-
},
|
|
14778
|
-
/**
|
|
14779
|
-
* Parses delete memory arguments.
|
|
14780
|
-
*/
|
|
14781
|
-
delete(args) {
|
|
14782
|
-
return {
|
|
14783
|
-
memoryId: parseMemoryIdArg(args.memoryId),
|
|
14784
|
-
};
|
|
14785
|
-
},
|
|
14786
|
-
};
|
|
14787
12878
|
|
|
14788
12879
|
/**
|
|
14789
12880
|
* Resolves runtime context from hidden tool arguments.
|
|
@@ -22493,9 +20584,9 @@ function createTimeoutSystemMessage(extraInstructions) {
|
|
|
22493
20584
|
return spaceTrim$1((block) => `
|
|
22494
20585
|
Timeout scheduling:
|
|
22495
20586
|
- Use "set_timeout" to wake this same chat thread in the future.
|
|
22496
|
-
-
|
|
20587
|
+
- Use "list_timeouts" to review timeouts across all chats for the same user+agent scope.
|
|
20588
|
+
- "cancel_timeout" accepts a timeout id from any chat in this same user+agent scope.
|
|
22497
20589
|
- When one timeout elapses, you will receive a new user-like message that explicitly says it is a timeout wake-up and includes the \`timeoutId\`.
|
|
22498
|
-
- Use "cancel_timeout" when a previously scheduled timeout is no longer relevant.
|
|
22499
20590
|
- Do not claim a timer was set or cancelled unless the tool confirms it.
|
|
22500
20591
|
${block(extraInstructions)}
|
|
22501
20592
|
`);
|
|
@@ -22556,13 +20647,6 @@ function parseToolExecutionEnvelope(rawValue) {
|
|
|
22556
20647
|
* @private internal utility of USE TIMEOUT
|
|
22557
20648
|
*/
|
|
22558
20649
|
function createDisabledTimeoutResult(action, message) {
|
|
22559
|
-
if (action === 'set') {
|
|
22560
|
-
return {
|
|
22561
|
-
action,
|
|
22562
|
-
status: 'disabled',
|
|
22563
|
-
message,
|
|
22564
|
-
};
|
|
22565
|
-
}
|
|
22566
20650
|
return {
|
|
22567
20651
|
action,
|
|
22568
20652
|
status: 'disabled',
|
|
@@ -22589,6 +20673,18 @@ function getTimeoutToolRuntimeAdapterOrDisabledResult(action, runtimeContext) {
|
|
|
22589
20673
|
}
|
|
22590
20674
|
}
|
|
22591
20675
|
|
|
20676
|
+
/**
|
|
20677
|
+
* Default number of rows returned by `list_timeouts`.
|
|
20678
|
+
*
|
|
20679
|
+
* @private internal USE TIMEOUT constant
|
|
20680
|
+
*/
|
|
20681
|
+
const DEFAULT_LIST_TIMEOUTS_LIMIT = 20;
|
|
20682
|
+
/**
|
|
20683
|
+
* Hard cap for `list_timeouts` page size.
|
|
20684
|
+
*
|
|
20685
|
+
* @private internal USE TIMEOUT constant
|
|
20686
|
+
*/
|
|
20687
|
+
const MAX_LIST_TIMEOUTS_LIMIT = 100;
|
|
22592
20688
|
/**
|
|
22593
20689
|
* Parses and validates `USE TIMEOUT` tool arguments.
|
|
22594
20690
|
*
|
|
@@ -22623,6 +20719,31 @@ const parseTimeoutToolArgs = {
|
|
|
22623
20719
|
}
|
|
22624
20720
|
return { timeoutId };
|
|
22625
20721
|
},
|
|
20722
|
+
/**
|
|
20723
|
+
* Parses `list_timeouts` input.
|
|
20724
|
+
*/
|
|
20725
|
+
list(args) {
|
|
20726
|
+
if (args.includeFinished !== undefined && typeof args.includeFinished !== 'boolean') {
|
|
20727
|
+
throw new PipelineExecutionError(spaceTrim$1(`
|
|
20728
|
+
Timeout \`includeFinished\` must be a boolean when provided.
|
|
20729
|
+
`));
|
|
20730
|
+
}
|
|
20731
|
+
const parsedLimit = args.limit === undefined ? DEFAULT_LIST_TIMEOUTS_LIMIT : Math.floor(Number(args.limit));
|
|
20732
|
+
if (!Number.isFinite(parsedLimit) || parsedLimit <= 0) {
|
|
20733
|
+
throw new PipelineExecutionError(spaceTrim$1(`
|
|
20734
|
+
Timeout \`limit\` must be a positive number.
|
|
20735
|
+
`));
|
|
20736
|
+
}
|
|
20737
|
+
if (parsedLimit > MAX_LIST_TIMEOUTS_LIMIT) {
|
|
20738
|
+
throw new PipelineExecutionError(spaceTrim$1(`
|
|
20739
|
+
Timeout \`limit\` must be at most \`${MAX_LIST_TIMEOUTS_LIMIT}\`.
|
|
20740
|
+
`));
|
|
20741
|
+
}
|
|
20742
|
+
return {
|
|
20743
|
+
includeFinished: args.includeFinished === true,
|
|
20744
|
+
limit: parsedLimit,
|
|
20745
|
+
};
|
|
20746
|
+
},
|
|
22626
20747
|
};
|
|
22627
20748
|
|
|
22628
20749
|
/**
|
|
@@ -22633,6 +20754,7 @@ const parseTimeoutToolArgs = {
|
|
|
22633
20754
|
const TimeoutToolNames = {
|
|
22634
20755
|
set: 'set_timeout',
|
|
22635
20756
|
cancel: 'cancel_timeout',
|
|
20757
|
+
list: 'list_timeouts',
|
|
22636
20758
|
};
|
|
22637
20759
|
|
|
22638
20760
|
/**
|
|
@@ -22732,6 +20854,35 @@ function createTimeoutToolFunctions() {
|
|
|
22732
20854
|
return JSON.stringify(result);
|
|
22733
20855
|
}
|
|
22734
20856
|
},
|
|
20857
|
+
async [TimeoutToolNames.list](args) {
|
|
20858
|
+
const runtimeContext = resolveTimeoutRuntimeContext(args);
|
|
20859
|
+
const { adapter, disabledResult } = getTimeoutToolRuntimeAdapterOrDisabledResult('list', runtimeContext);
|
|
20860
|
+
if (!adapter || disabledResult) {
|
|
20861
|
+
return JSON.stringify(disabledResult);
|
|
20862
|
+
}
|
|
20863
|
+
try {
|
|
20864
|
+
const parsedArgs = parseTimeoutToolArgs.list(args);
|
|
20865
|
+
const listedTimeouts = await adapter.listTimeouts(parsedArgs, runtimeContext);
|
|
20866
|
+
const result = {
|
|
20867
|
+
action: 'list',
|
|
20868
|
+
status: 'listed',
|
|
20869
|
+
items: listedTimeouts.items,
|
|
20870
|
+
total: listedTimeouts.total,
|
|
20871
|
+
};
|
|
20872
|
+
return createToolExecutionEnvelope({
|
|
20873
|
+
assistantMessage: listedTimeouts.total === 1 ? 'Found 1 timeout.' : `Found ${listedTimeouts.total} timeouts.`,
|
|
20874
|
+
toolResult: result,
|
|
20875
|
+
});
|
|
20876
|
+
}
|
|
20877
|
+
catch (error) {
|
|
20878
|
+
const result = {
|
|
20879
|
+
action: 'list',
|
|
20880
|
+
status: 'error',
|
|
20881
|
+
message: error instanceof Error ? error.message : String(error),
|
|
20882
|
+
};
|
|
20883
|
+
return JSON.stringify(result);
|
|
20884
|
+
}
|
|
20885
|
+
},
|
|
22735
20886
|
};
|
|
22736
20887
|
}
|
|
22737
20888
|
|
|
@@ -22765,26 +20916,45 @@ function createTimeoutTools(existingTools = []) {
|
|
|
22765
20916
|
if (!tools.some((tool) => tool.name === TimeoutToolNames.cancel)) {
|
|
22766
20917
|
tools.push({
|
|
22767
20918
|
name: TimeoutToolNames.cancel,
|
|
22768
|
-
description: 'Cancel one previously scheduled timeout
|
|
20919
|
+
description: 'Cancel one previously scheduled timeout within the same user+agent scope, even if it was set in another chat.',
|
|
22769
20920
|
parameters: {
|
|
22770
20921
|
type: 'object',
|
|
22771
20922
|
properties: {
|
|
22772
20923
|
timeoutId: {
|
|
22773
20924
|
type: 'string',
|
|
22774
|
-
description: 'Identifier returned earlier by `set_timeout`.',
|
|
20925
|
+
description: 'Identifier returned earlier by `set_timeout` or `list_timeouts`.',
|
|
22775
20926
|
},
|
|
22776
20927
|
},
|
|
22777
20928
|
required: ['timeoutId'],
|
|
22778
20929
|
},
|
|
22779
20930
|
});
|
|
22780
20931
|
}
|
|
20932
|
+
if (!tools.some((tool) => tool.name === TimeoutToolNames.list)) {
|
|
20933
|
+
tools.push({
|
|
20934
|
+
name: TimeoutToolNames.list,
|
|
20935
|
+
description: 'List scheduled timeouts across all chats for this same user+agent scope so they can be reviewed or cancelled.',
|
|
20936
|
+
parameters: {
|
|
20937
|
+
type: 'object',
|
|
20938
|
+
properties: {
|
|
20939
|
+
includeFinished: {
|
|
20940
|
+
type: 'boolean',
|
|
20941
|
+
description: 'When true, include completed, failed, and cancelled rows in addition to active timeouts.',
|
|
20942
|
+
},
|
|
20943
|
+
limit: {
|
|
20944
|
+
type: 'number',
|
|
20945
|
+
description: 'Maximum number of rows to return (default 20, max 100).',
|
|
20946
|
+
},
|
|
20947
|
+
},
|
|
20948
|
+
},
|
|
20949
|
+
});
|
|
20950
|
+
}
|
|
22781
20951
|
return tools;
|
|
22782
20952
|
}
|
|
22783
20953
|
|
|
22784
20954
|
/**
|
|
22785
20955
|
* `USE TIMEOUT` commitment definition.
|
|
22786
20956
|
*
|
|
22787
|
-
* The `USE TIMEOUT` commitment enables
|
|
20957
|
+
* The `USE TIMEOUT` commitment enables timeout wake-ups and scoped timeout management.
|
|
22788
20958
|
*
|
|
22789
20959
|
* @private [🪔] Maybe export the commitments through some package
|
|
22790
20960
|
*/
|
|
@@ -22799,7 +20969,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
22799
20969
|
* Short one-line description of `USE TIMEOUT`.
|
|
22800
20970
|
*/
|
|
22801
20971
|
get description() {
|
|
22802
|
-
return 'Enable
|
|
20972
|
+
return 'Enable timeout wake-ups plus scoped timeout listing/cancellation across chats.';
|
|
22803
20973
|
}
|
|
22804
20974
|
/**
|
|
22805
20975
|
* Icon for this commitment.
|
|
@@ -22814,14 +20984,15 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
22814
20984
|
return spaceTrim$1(`
|
|
22815
20985
|
# USE TIMEOUT
|
|
22816
20986
|
|
|
22817
|
-
Enables
|
|
20987
|
+
Enables timeout wake-ups and timeout management for the same user+agent scope.
|
|
22818
20988
|
|
|
22819
20989
|
## Key aspects
|
|
22820
20990
|
|
|
22821
20991
|
- The agent uses \`set_timeout\` to schedule a future wake-up in the same chat thread.
|
|
22822
20992
|
- The tool returns immediately while the timeout is stored and executed by the runtime later.
|
|
22823
20993
|
- The wake-up arrives as a new user-like timeout message in the same conversation.
|
|
22824
|
-
- The agent can
|
|
20994
|
+
- The agent can inspect known timeouts via \`list_timeouts\`.
|
|
20995
|
+
- The agent can cancel an existing timeout by \`timeoutId\` via \`cancel_timeout\`, including timeouts created in another chat.
|
|
22825
20996
|
- Commitment content is treated as optional timeout policy instructions.
|
|
22826
20997
|
|
|
22827
20998
|
## Examples
|
|
@@ -22850,6 +21021,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
22850
21021
|
return {
|
|
22851
21022
|
[TimeoutToolNames.set]: 'Set timer',
|
|
22852
21023
|
[TimeoutToolNames.cancel]: 'Cancel timer',
|
|
21024
|
+
[TimeoutToolNames.list]: 'List timers',
|
|
22853
21025
|
};
|
|
22854
21026
|
}
|
|
22855
21027
|
/**
|
|
@@ -23703,7 +21875,7 @@ function getAllCommitmentsToolFunctionsForNode() {
|
|
|
23703
21875
|
function extractOneBlockFromMarkdown(markdown) {
|
|
23704
21876
|
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
23705
21877
|
if (codeBlocks.length !== 1) {
|
|
23706
|
-
throw new ParseError(spaceTrim$
|
|
21878
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
23707
21879
|
There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
|
|
23708
21880
|
|
|
23709
21881
|
${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
|
|
@@ -23812,7 +21984,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23812
21984
|
}
|
|
23813
21985
|
// Note: [💎]
|
|
23814
21986
|
// Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
|
|
23815
|
-
const spaceTrim = (_) =>
|
|
21987
|
+
const spaceTrim = (_) => _spaceTrim(_);
|
|
23816
21988
|
$preserve(spaceTrim);
|
|
23817
21989
|
const removeQuotes$1 = removeQuotes;
|
|
23818
21990
|
$preserve(removeQuotes$1);
|
|
@@ -23903,7 +22075,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23903
22075
|
.join('\n');
|
|
23904
22076
|
// script = templateParameters(script, parameters);
|
|
23905
22077
|
// <- TODO: [🧠][🥳] Should be this is one of two variants how to use parameters in script
|
|
23906
|
-
const statementToEvaluate =
|
|
22078
|
+
const statementToEvaluate = _spaceTrim((block) => `
|
|
23907
22079
|
|
|
23908
22080
|
// Build-in functions:
|
|
23909
22081
|
${block(buildinFunctionsStatement)}
|
|
@@ -23918,7 +22090,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23918
22090
|
(async ()=>{ ${script} })()
|
|
23919
22091
|
`);
|
|
23920
22092
|
if (this.options.isVerbose) {
|
|
23921
|
-
console.info(
|
|
22093
|
+
console.info(_spaceTrim((block) => `
|
|
23922
22094
|
🚀 Evaluating ${scriptLanguage} script:
|
|
23923
22095
|
|
|
23924
22096
|
${block(statementToEvaluate)}`));
|
|
@@ -23927,7 +22099,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23927
22099
|
try {
|
|
23928
22100
|
result = await eval(statementToEvaluate);
|
|
23929
22101
|
if (this.options.isVerbose) {
|
|
23930
|
-
console.info(
|
|
22102
|
+
console.info(_spaceTrim((block) => `
|
|
23931
22103
|
🚀 Script evaluated successfully, result:
|
|
23932
22104
|
${block(valueToString(result))}
|
|
23933
22105
|
`));
|
|
@@ -23946,7 +22118,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23946
22118
|
To: [PipelineExecutionError: Parameter `{thing}` is not defined],
|
|
23947
22119
|
*/
|
|
23948
22120
|
if (!statementToEvaluate.includes(undefinedName + '(')) {
|
|
23949
|
-
throw new PipelineExecutionError(
|
|
22121
|
+
throw new PipelineExecutionError(_spaceTrim((block) => `
|
|
23950
22122
|
|
|
23951
22123
|
Parameter \`{${undefinedName}}\` is not defined
|
|
23952
22124
|
|
|
@@ -23968,7 +22140,7 @@ class JavascriptEvalExecutionTools {
|
|
|
23968
22140
|
`));
|
|
23969
22141
|
}
|
|
23970
22142
|
else {
|
|
23971
|
-
throw new PipelineExecutionError(
|
|
22143
|
+
throw new PipelineExecutionError(_spaceTrim((block) => `
|
|
23972
22144
|
Function ${undefinedName}() is not defined
|
|
23973
22145
|
|
|
23974
22146
|
- Make sure that the function is one of built-in functions
|
|
@@ -25325,7 +23497,7 @@ function validateBook(source) {
|
|
|
25325
23497
|
* @deprecated Use `$generateBookBoilerplate` instead
|
|
25326
23498
|
* @public exported from `@promptbook/core`
|
|
25327
23499
|
*/
|
|
25328
|
-
padBook(validateBook(spaceTrim$
|
|
23500
|
+
padBook(validateBook(spaceTrim$1(`
|
|
25329
23501
|
AI Avatar
|
|
25330
23502
|
|
|
25331
23503
|
PERSONA A friendly AI assistant that helps you with your tasks
|
|
@@ -25374,7 +23546,7 @@ function book(strings, ...values) {
|
|
|
25374
23546
|
const bookString = prompt(strings, ...values).toString();
|
|
25375
23547
|
if (!isValidPipelineString(bookString)) {
|
|
25376
23548
|
// TODO: Make the CustomError for this
|
|
25377
|
-
throw new Error(spaceTrim$
|
|
23549
|
+
throw new Error(spaceTrim$1(`
|
|
25378
23550
|
The string is not a valid pipeline string
|
|
25379
23551
|
|
|
25380
23552
|
book\`
|
|
@@ -25384,7 +23556,7 @@ function book(strings, ...values) {
|
|
|
25384
23556
|
}
|
|
25385
23557
|
if (!isValidBook(bookString)) {
|
|
25386
23558
|
// TODO: Make the CustomError for this
|
|
25387
|
-
throw new Error(spaceTrim$
|
|
23559
|
+
throw new Error(spaceTrim$1(`
|
|
25388
23560
|
The string is not a valid book
|
|
25389
23561
|
|
|
25390
23562
|
book\`
|
|
@@ -25668,7 +23840,7 @@ function computeAgentHash(agentSource) {
|
|
|
25668
23840
|
* @public exported from `@promptbook/core`
|
|
25669
23841
|
*/
|
|
25670
23842
|
function normalizeAgentName(rawAgentName) {
|
|
25671
|
-
return titleToName(spaceTrim$
|
|
23843
|
+
return titleToName(spaceTrim$1(rawAgentName));
|
|
25672
23844
|
}
|
|
25673
23845
|
|
|
25674
23846
|
/**
|
|
@@ -26112,7 +24284,7 @@ function parseAgentSource(agentSource) {
|
|
|
26112
24284
|
continue;
|
|
26113
24285
|
}
|
|
26114
24286
|
if (commitment.type === 'FROM') {
|
|
26115
|
-
const content = spaceTrim$
|
|
24287
|
+
const content = spaceTrim$1(commitment.content).split(/\r?\n/)[0] || '';
|
|
26116
24288
|
if (content === 'Adam' || content === '' /* <- Note: Adam is implicit */) {
|
|
26117
24289
|
continue;
|
|
26118
24290
|
}
|
|
@@ -26135,7 +24307,7 @@ function parseAgentSource(agentSource) {
|
|
|
26135
24307
|
continue;
|
|
26136
24308
|
}
|
|
26137
24309
|
if (commitment.type === 'IMPORT') {
|
|
26138
|
-
const content = spaceTrim$
|
|
24310
|
+
const content = spaceTrim$1(commitment.content).split(/\r?\n/)[0] || '';
|
|
26139
24311
|
let label = content;
|
|
26140
24312
|
let iconName = 'ExternalLink'; // Import remote
|
|
26141
24313
|
try {
|
|
@@ -26173,7 +24345,7 @@ function parseAgentSource(agentSource) {
|
|
|
26173
24345
|
continue;
|
|
26174
24346
|
}
|
|
26175
24347
|
if (commitment.type === 'KNOWLEDGE') {
|
|
26176
|
-
const content = spaceTrim$
|
|
24348
|
+
const content = spaceTrim$1(commitment.content);
|
|
26177
24349
|
const extractedUrls = extractUrlsFromText(content);
|
|
26178
24350
|
let label = content;
|
|
26179
24351
|
let iconName = 'Book';
|
|
@@ -26232,7 +24404,7 @@ function parseAgentSource(agentSource) {
|
|
|
26232
24404
|
continue;
|
|
26233
24405
|
}
|
|
26234
24406
|
if (commitment.type === 'META LINK') {
|
|
26235
|
-
const linkValue = spaceTrim$
|
|
24407
|
+
const linkValue = spaceTrim$1(commitment.content);
|
|
26236
24408
|
links.push(linkValue);
|
|
26237
24409
|
meta.link = linkValue;
|
|
26238
24410
|
continue;
|
|
@@ -26242,11 +24414,11 @@ function parseAgentSource(agentSource) {
|
|
|
26242
24414
|
continue;
|
|
26243
24415
|
}
|
|
26244
24416
|
if (commitment.type === 'META IMAGE') {
|
|
26245
|
-
meta.image = spaceTrim$
|
|
24417
|
+
meta.image = spaceTrim$1(commitment.content);
|
|
26246
24418
|
continue;
|
|
26247
24419
|
}
|
|
26248
24420
|
if (commitment.type === 'META DESCRIPTION') {
|
|
26249
|
-
meta.description = spaceTrim$
|
|
24421
|
+
meta.description = spaceTrim$1(commitment.content);
|
|
26250
24422
|
continue;
|
|
26251
24423
|
}
|
|
26252
24424
|
if (commitment.type === 'META DISCLAIMER') {
|
|
@@ -26254,7 +24426,7 @@ function parseAgentSource(agentSource) {
|
|
|
26254
24426
|
continue;
|
|
26255
24427
|
}
|
|
26256
24428
|
if (commitment.type === 'META INPUT PLACEHOLDER') {
|
|
26257
|
-
meta.inputPlaceholder = spaceTrim$
|
|
24429
|
+
meta.inputPlaceholder = spaceTrim$1(commitment.content);
|
|
26258
24430
|
continue;
|
|
26259
24431
|
}
|
|
26260
24432
|
if (commitment.type === 'MESSAGE SUFFIX') {
|
|
@@ -26270,7 +24442,7 @@ function parseAgentSource(agentSource) {
|
|
|
26270
24442
|
continue;
|
|
26271
24443
|
}
|
|
26272
24444
|
if (commitment.type === 'META VOICE') {
|
|
26273
|
-
meta.voice = spaceTrim$
|
|
24445
|
+
meta.voice = spaceTrim$1(commitment.content);
|
|
26274
24446
|
continue;
|
|
26275
24447
|
}
|
|
26276
24448
|
if (commitment.type !== 'META') {
|
|
@@ -26279,10 +24451,10 @@ function parseAgentSource(agentSource) {
|
|
|
26279
24451
|
// Parse META commitments - format is "META TYPE content"
|
|
26280
24452
|
const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
|
|
26281
24453
|
if (metaTypeRaw === 'LINK') {
|
|
26282
|
-
links.push(spaceTrim$
|
|
24454
|
+
links.push(spaceTrim$1(commitment.content.substring(metaTypeRaw.length)));
|
|
26283
24455
|
}
|
|
26284
24456
|
const metaType = normalizeTo_camelCase(metaTypeRaw);
|
|
26285
|
-
meta[metaType] = spaceTrim$
|
|
24457
|
+
meta[metaType] = spaceTrim$1(commitment.content.substring(metaTypeRaw.length));
|
|
26286
24458
|
}
|
|
26287
24459
|
// Generate fullname fallback if no meta fullname specified
|
|
26288
24460
|
if (!meta.fullname) {
|
|
@@ -26313,7 +24485,7 @@ function parseAgentSource(agentSource) {
|
|
|
26313
24485
|
* @returns The content with normalized separators
|
|
26314
24486
|
*/
|
|
26315
24487
|
function normalizeSeparator(content) {
|
|
26316
|
-
const trimmed = spaceTrim$
|
|
24488
|
+
const trimmed = spaceTrim$1(content);
|
|
26317
24489
|
if (trimmed.includes(',')) {
|
|
26318
24490
|
return trimmed;
|
|
26319
24491
|
}
|
|
@@ -26326,7 +24498,7 @@ function normalizeSeparator(content) {
|
|
|
26326
24498
|
* @returns Normalized domain or a trimmed fallback.
|
|
26327
24499
|
*/
|
|
26328
24500
|
function normalizeMetaDomain(content) {
|
|
26329
|
-
const trimmed = spaceTrim$
|
|
24501
|
+
const trimmed = spaceTrim$1(content);
|
|
26330
24502
|
return normalizeDomainForMatching(trimmed) || trimmed.toLowerCase();
|
|
26331
24503
|
}
|
|
26332
24504
|
/**
|
|
@@ -27586,7 +25758,7 @@ function pricing(value) {
|
|
|
27586
25758
|
/**
|
|
27587
25759
|
* List of available OpenAI models with pricing
|
|
27588
25760
|
*
|
|
27589
|
-
* Note: Synced with official API docs at
|
|
25761
|
+
* Note: Synced with official API docs at 2026-03-22
|
|
27590
25762
|
*
|
|
27591
25763
|
* @see https://platform.openai.com/docs/models/
|
|
27592
25764
|
* @see https://openai.com/api/pricing/
|
|
@@ -27708,8 +25880,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27708
25880
|
modelName: 'gpt-4.1',
|
|
27709
25881
|
modelDescription: 'Smartest non-reasoning model with 128K context window. Enhanced version of GPT-4 with improved instruction following, better factual accuracy, and reduced hallucinations. Features advanced function calling capabilities and superior performance on coding tasks. Ideal for applications requiring high intelligence without reasoning overhead.',
|
|
27710
25882
|
pricing: {
|
|
27711
|
-
prompt: pricing(`$
|
|
27712
|
-
output: pricing(`$
|
|
25883
|
+
prompt: pricing(`$2.00 / 1M tokens`),
|
|
25884
|
+
output: pricing(`$8.00 / 1M tokens`),
|
|
27713
25885
|
},
|
|
27714
25886
|
},
|
|
27715
25887
|
/**/
|
|
@@ -27720,8 +25892,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27720
25892
|
modelName: 'gpt-4.1-mini',
|
|
27721
25893
|
modelDescription: 'Smaller, faster version of GPT-4.1 with 128K context window. Balances intelligence and efficiency with 3x faster inference than base GPT-4.1. Maintains strong capabilities across text generation, reasoning, and coding while offering better cost-performance ratio for most applications.',
|
|
27722
25894
|
pricing: {
|
|
27723
|
-
prompt: pricing(`$0.
|
|
27724
|
-
output: pricing(`$
|
|
25895
|
+
prompt: pricing(`$0.40 / 1M tokens`),
|
|
25896
|
+
output: pricing(`$1.60 / 1M tokens`),
|
|
27725
25897
|
},
|
|
27726
25898
|
},
|
|
27727
25899
|
/**/
|
|
@@ -27732,8 +25904,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27732
25904
|
modelName: 'gpt-4.1-nano',
|
|
27733
25905
|
modelDescription: 'Fastest, most cost-efficient version of GPT-4.1 with 128K context window. Optimized for high-throughput applications requiring good quality at minimal cost. Features 5x faster inference than GPT-4.1 while maintaining adequate performance for most general-purpose tasks.',
|
|
27734
25906
|
pricing: {
|
|
27735
|
-
prompt: pricing(`$0.
|
|
27736
|
-
output: pricing(`$0.
|
|
25907
|
+
prompt: pricing(`$0.10 / 1M tokens`),
|
|
25908
|
+
output: pricing(`$0.40 / 1M tokens`),
|
|
27737
25909
|
},
|
|
27738
25910
|
},
|
|
27739
25911
|
/**/
|
|
@@ -27744,8 +25916,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27744
25916
|
modelName: 'o3',
|
|
27745
25917
|
modelDescription: 'Advanced reasoning model with 128K context window specializing in complex logical, mathematical, and analytical tasks. Successor to o1 with enhanced step-by-step problem-solving capabilities and superior performance on STEM-focused problems. Ideal for professional applications requiring deep analytical thinking and precise reasoning.',
|
|
27746
25918
|
pricing: {
|
|
27747
|
-
prompt: pricing(`$
|
|
27748
|
-
output: pricing(`$
|
|
25919
|
+
prompt: pricing(`$2.00 / 1M tokens`),
|
|
25920
|
+
output: pricing(`$8.00 / 1M tokens`),
|
|
27749
25921
|
},
|
|
27750
25922
|
},
|
|
27751
25923
|
/**/
|
|
@@ -27756,8 +25928,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27756
25928
|
modelName: 'o3-pro',
|
|
27757
25929
|
modelDescription: 'Enhanced version of o3 with more compute allocated for better responses on the most challenging problems. Features extended reasoning time and improved accuracy on complex analytical tasks. Designed for applications where maximum reasoning quality is more important than response speed.',
|
|
27758
25930
|
pricing: {
|
|
27759
|
-
prompt: pricing(`$
|
|
27760
|
-
output: pricing(`$
|
|
25931
|
+
prompt: pricing(`$20.00 / 1M tokens`),
|
|
25932
|
+
output: pricing(`$80.00 / 1M tokens`),
|
|
27761
25933
|
},
|
|
27762
25934
|
},
|
|
27763
25935
|
/**/
|
|
@@ -27768,8 +25940,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
27768
25940
|
modelName: 'o4-mini',
|
|
27769
25941
|
modelDescription: 'Fast, cost-efficient reasoning model with 128K context window. Successor to o1-mini with improved analytical capabilities while maintaining speed advantages. Features enhanced mathematical reasoning and logical problem-solving at significantly lower cost than full reasoning models.',
|
|
27770
25942
|
pricing: {
|
|
27771
|
-
prompt: pricing(`$
|
|
27772
|
-
output: pricing(`$
|
|
25943
|
+
prompt: pricing(`$1.10 / 1M tokens`),
|
|
25944
|
+
output: pricing(`$4.40 / 1M tokens`),
|
|
27773
25945
|
},
|
|
27774
25946
|
},
|
|
27775
25947
|
/**/
|
|
@@ -28127,8 +26299,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
28127
26299
|
modelName: 'gpt-4o-2024-05-13',
|
|
28128
26300
|
modelDescription: 'May 2024 version of GPT-4o with 128K context window. Features enhanced multimodal capabilities including superior image understanding (up to 20MP), audio processing, and improved reasoning. Optimized for 2x lower latency than GPT-4 Turbo while maintaining high performance. Includes knowledge up to October 2023. Ideal for production applications requiring reliable multimodal capabilities.',
|
|
28129
26301
|
pricing: {
|
|
28130
|
-
prompt: pricing(`$
|
|
28131
|
-
output: pricing(`$
|
|
26302
|
+
prompt: pricing(`$2.50 / 1M tokens`),
|
|
26303
|
+
output: pricing(`$10.00 / 1M tokens`),
|
|
28132
26304
|
},
|
|
28133
26305
|
},
|
|
28134
26306
|
/**/
|
|
@@ -28139,8 +26311,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
28139
26311
|
modelName: 'gpt-4o',
|
|
28140
26312
|
modelDescription: "OpenAI's most advanced general-purpose multimodal model with 128K context window. Optimized for balanced performance, speed, and cost with 2x faster responses than GPT-4 Turbo. Features excellent vision processing, audio understanding, reasoning, and text generation quality. Represents optimal balance of capability and efficiency for most advanced applications.",
|
|
28141
26313
|
pricing: {
|
|
28142
|
-
prompt: pricing(`$
|
|
28143
|
-
output: pricing(`$
|
|
26314
|
+
prompt: pricing(`$2.50 / 1M tokens`),
|
|
26315
|
+
output: pricing(`$10.00 / 1M tokens`),
|
|
28144
26316
|
},
|
|
28145
26317
|
},
|
|
28146
26318
|
/**/
|
|
@@ -28211,8 +26383,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
28211
26383
|
modelName: 'o3-mini',
|
|
28212
26384
|
modelDescription: 'Cost-effective reasoning model with 128K context window optimized for academic and scientific problem-solving. Features efficient performance on STEM tasks with specialized capabilities in mathematics, physics, chemistry, and computer science. Offers 80% of O1 performance on technical domains at significantly lower cost. Ideal for educational applications and research support.',
|
|
28213
26385
|
pricing: {
|
|
28214
|
-
prompt: pricing(`$
|
|
28215
|
-
output: pricing(`$
|
|
26386
|
+
prompt: pricing(`$1.10 / 1M tokens`),
|
|
26387
|
+
output: pricing(`$4.40 / 1M tokens`),
|
|
28216
26388
|
},
|
|
28217
26389
|
},
|
|
28218
26390
|
/**/
|
|
@@ -28312,53 +26484,6 @@ resultContent, rawResponse, duration = ZERO_VALUE) {
|
|
|
28312
26484
|
* TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
|
|
28313
26485
|
*/
|
|
28314
26486
|
|
|
28315
|
-
/**
|
|
28316
|
-
* Maps Promptbook tools to OpenAI tools.
|
|
28317
|
-
*
|
|
28318
|
-
* @private
|
|
28319
|
-
*/
|
|
28320
|
-
function mapToolsToOpenAi(tools) {
|
|
28321
|
-
return tools.map((tool) => ({
|
|
28322
|
-
type: 'function',
|
|
28323
|
-
function: {
|
|
28324
|
-
name: tool.name,
|
|
28325
|
-
description: tool.description,
|
|
28326
|
-
parameters: tool.parameters,
|
|
28327
|
-
},
|
|
28328
|
-
}));
|
|
28329
|
-
}
|
|
28330
|
-
|
|
28331
|
-
/**
|
|
28332
|
-
* Builds a tool invocation script that injects hidden runtime context into tool args.
|
|
28333
|
-
*
|
|
28334
|
-
* @private utility of OpenAI tool execution wrappers
|
|
28335
|
-
*/
|
|
28336
|
-
function buildToolInvocationScript(options) {
|
|
28337
|
-
const { functionName, functionArgsExpression } = options;
|
|
28338
|
-
return `
|
|
28339
|
-
const args = ${functionArgsExpression};
|
|
28340
|
-
const runtimeContextRaw =
|
|
28341
|
-
typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
|
|
28342
|
-
? undefined
|
|
28343
|
-
: ${TOOL_RUNTIME_CONTEXT_PARAMETER};
|
|
28344
|
-
|
|
28345
|
-
if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
28346
|
-
args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
|
|
28347
|
-
}
|
|
28348
|
-
|
|
28349
|
-
const toolProgressTokenRaw =
|
|
28350
|
-
typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
|
|
28351
|
-
? undefined
|
|
28352
|
-
: ${TOOL_PROGRESS_TOKEN_PARAMETER};
|
|
28353
|
-
|
|
28354
|
-
if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
28355
|
-
args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
|
|
28356
|
-
}
|
|
28357
|
-
|
|
28358
|
-
return await ${functionName}(args);
|
|
28359
|
-
`;
|
|
28360
|
-
}
|
|
28361
|
-
|
|
28362
26487
|
/**
|
|
28363
26488
|
* Parses an OpenAI error message to identify which parameter is unsupported
|
|
28364
26489
|
*
|
|
@@ -28415,6 +26540,53 @@ function isUnsupportedParameterError(error) {
|
|
|
28415
26540
|
errorMessage.includes('does not support'));
|
|
28416
26541
|
}
|
|
28417
26542
|
|
|
26543
|
+
/**
|
|
26544
|
+
* Builds a tool invocation script that injects hidden runtime context into tool args.
|
|
26545
|
+
*
|
|
26546
|
+
* @private utility of OpenAI tool execution wrappers
|
|
26547
|
+
*/
|
|
26548
|
+
function buildToolInvocationScript(options) {
|
|
26549
|
+
const { functionName, functionArgsExpression } = options;
|
|
26550
|
+
return `
|
|
26551
|
+
const args = ${functionArgsExpression};
|
|
26552
|
+
const runtimeContextRaw =
|
|
26553
|
+
typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
|
|
26554
|
+
? undefined
|
|
26555
|
+
: ${TOOL_RUNTIME_CONTEXT_PARAMETER};
|
|
26556
|
+
|
|
26557
|
+
if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
26558
|
+
args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
|
|
26559
|
+
}
|
|
26560
|
+
|
|
26561
|
+
const toolProgressTokenRaw =
|
|
26562
|
+
typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
|
|
26563
|
+
? undefined
|
|
26564
|
+
: ${TOOL_PROGRESS_TOKEN_PARAMETER};
|
|
26565
|
+
|
|
26566
|
+
if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
26567
|
+
args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
|
|
26568
|
+
}
|
|
26569
|
+
|
|
26570
|
+
return await ${functionName}(args);
|
|
26571
|
+
`;
|
|
26572
|
+
}
|
|
26573
|
+
|
|
26574
|
+
/**
|
|
26575
|
+
* Maps Promptbook tools to OpenAI tools.
|
|
26576
|
+
*
|
|
26577
|
+
* @private
|
|
26578
|
+
*/
|
|
26579
|
+
function mapToolsToOpenAi(tools) {
|
|
26580
|
+
return tools.map((tool) => ({
|
|
26581
|
+
type: 'function',
|
|
26582
|
+
function: {
|
|
26583
|
+
name: tool.name,
|
|
26584
|
+
description: tool.description,
|
|
26585
|
+
parameters: tool.parameters,
|
|
26586
|
+
},
|
|
26587
|
+
}));
|
|
26588
|
+
}
|
|
26589
|
+
|
|
28418
26590
|
/**
|
|
28419
26591
|
* Provides access to the structured clone implementation when available.
|
|
28420
26592
|
*/
|
|
@@ -29381,7 +27553,7 @@ class OpenAiCompatibleExecutionTools {
|
|
|
29381
27553
|
// Note: Match exact or prefix for model families
|
|
29382
27554
|
const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
|
|
29383
27555
|
if (model === undefined) {
|
|
29384
|
-
throw new PipelineExecutionError(spaceTrim$
|
|
27556
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
29385
27557
|
Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
|
|
29386
27558
|
|
|
29387
27559
|
Available models:
|
|
@@ -30307,7 +28479,7 @@ class OpenAiVectorStoreHandler extends OpenAiExecutionTools {
|
|
|
30307
28479
|
}
|
|
30308
28480
|
}
|
|
30309
28481
|
|
|
30310
|
-
const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5-
|
|
28482
|
+
const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5.4-nano';
|
|
30311
28483
|
/**
|
|
30312
28484
|
* Creates one structured log entry for streamed tool-call updates.
|
|
30313
28485
|
*
|
|
@@ -30802,7 +28974,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
30802
28974
|
}),
|
|
30803
28975
|
],
|
|
30804
28976
|
};
|
|
30805
|
-
const errorMessage = spaceTrim$
|
|
28977
|
+
const errorMessage = spaceTrim$1((block) => `
|
|
30806
28978
|
|
|
30807
28979
|
The invoked tool \`${functionName}\` failed with error:
|
|
30808
28980
|
|
|
@@ -31520,7 +29692,7 @@ class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
31520
29692
|
assertsError(error);
|
|
31521
29693
|
const serializedError = serializeError(error);
|
|
31522
29694
|
errors = [serializedError];
|
|
31523
|
-
functionResponse = spaceTrim$
|
|
29695
|
+
functionResponse = spaceTrim$1((block) => `
|
|
31524
29696
|
|
|
31525
29697
|
The invoked tool \`${functionName}\` failed with error:
|
|
31526
29698
|
|
|
@@ -32528,7 +30700,7 @@ class SelfLearningManager {
|
|
|
32528
30700
|
if (isJsonSchemaResponseFormat(responseFormat)) {
|
|
32529
30701
|
const jsonSchema = responseFormat.json_schema;
|
|
32530
30702
|
const schemaJson = JSON.stringify(jsonSchema, null, 4);
|
|
32531
|
-
userMessageContent = spaceTrim$
|
|
30703
|
+
userMessageContent = spaceTrim$1((block) => `
|
|
32532
30704
|
${block(prompt.content)}
|
|
32533
30705
|
|
|
32534
30706
|
NOTE Request was made through OpenAI Compatible API with \`response_format\` of type \`json_schema\` with the following schema:
|
|
@@ -32559,12 +30731,12 @@ class SelfLearningManager {
|
|
|
32559
30731
|
const formattedAgentMessage = formatAgentMessageForJsonMode(result.content, usesJsonSchemaMode);
|
|
32560
30732
|
const teacherInstructions = extractOpenTeacherInstructions(agentSource);
|
|
32561
30733
|
const teacherInstructionsSection = teacherInstructions
|
|
32562
|
-
? spaceTrim$
|
|
30734
|
+
? spaceTrim$1((block) => `
|
|
32563
30735
|
**Teacher instructions:**
|
|
32564
30736
|
${block(teacherInstructions)}
|
|
32565
30737
|
`)
|
|
32566
30738
|
: '';
|
|
32567
|
-
const teacherPromptContent = spaceTrim$
|
|
30739
|
+
const teacherPromptContent = spaceTrim$1((block) => `
|
|
32568
30740
|
|
|
32569
30741
|
You are a teacher agent helping another agent to learn from its interactions.
|
|
32570
30742
|
|
|
@@ -32597,7 +30769,7 @@ class SelfLearningManager {
|
|
|
32597
30769
|
? '- This interaction used JSON mode, so the agent answer should stay as a formatted JSON code block.'
|
|
32598
30770
|
: ''}
|
|
32599
30771
|
${block(isInitialMessageMissing
|
|
32600
|
-
? spaceTrim$
|
|
30772
|
+
? spaceTrim$1(`
|
|
32601
30773
|
- The agent source does not have an INITIAL MESSAGE defined, generate one.
|
|
32602
30774
|
- The INITIAL MESSAGE should be welcoming, informative about the agent capabilities and also should give some quick options to start the conversation with the agent.
|
|
32603
30775
|
- The quick option looks like \`[👋 Hello](?message=Hello, how are you?)\`
|
|
@@ -32640,7 +30812,7 @@ class SelfLearningManager {
|
|
|
32640
30812
|
*/
|
|
32641
30813
|
appendToAgentSource(section) {
|
|
32642
30814
|
const currentSource = this.options.getAgentSource();
|
|
32643
|
-
const newSource = padBook(validateBook(spaceTrim$
|
|
30815
|
+
const newSource = padBook(validateBook(spaceTrim$1(currentSource) + section));
|
|
32644
30816
|
this.options.updateAgentSource(newSource);
|
|
32645
30817
|
}
|
|
32646
30818
|
}
|
|
@@ -32668,13 +30840,13 @@ function formatAgentMessageForJsonMode(content, isJsonMode) {
|
|
|
32668
30840
|
}
|
|
32669
30841
|
const parsedJson = tryParseJson(content);
|
|
32670
30842
|
if (parsedJson === null) {
|
|
32671
|
-
return spaceTrim$
|
|
30843
|
+
return spaceTrim$1((block) => `
|
|
32672
30844
|
\`\`\`json
|
|
32673
30845
|
${block(content)}
|
|
32674
30846
|
\`\`\`
|
|
32675
30847
|
`);
|
|
32676
30848
|
}
|
|
32677
|
-
return spaceTrim$
|
|
30849
|
+
return spaceTrim$1((block) => `
|
|
32678
30850
|
\`\`\`json
|
|
32679
30851
|
${block(JSON.stringify(parsedJson, null, 4))}
|
|
32680
30852
|
\`\`\`
|
|
@@ -32706,7 +30878,7 @@ function formatSelfLearningSample(options) {
|
|
|
32706
30878
|
const internalMessagesSection = options.internalMessages
|
|
32707
30879
|
.map((internalMessage) => formatInternalLearningMessage(internalMessage))
|
|
32708
30880
|
.join('\n\n');
|
|
32709
|
-
return spaceTrim$
|
|
30881
|
+
return spaceTrim$1((block) => `
|
|
32710
30882
|
|
|
32711
30883
|
USER MESSAGE
|
|
32712
30884
|
${block(options.userMessageContent)}
|
|
@@ -32724,7 +30896,7 @@ function formatSelfLearningSample(options) {
|
|
|
32724
30896
|
* @private function of Agent
|
|
32725
30897
|
*/
|
|
32726
30898
|
function formatInternalLearningMessage(internalMessage) {
|
|
32727
|
-
return spaceTrim$
|
|
30899
|
+
return spaceTrim$1((block) => `
|
|
32728
30900
|
INTERNAL MESSAGE
|
|
32729
30901
|
${block(stringifyInternalLearningPayload(internalMessage))}
|
|
32730
30902
|
`);
|
|
@@ -33190,7 +31362,7 @@ function buildRemoteAgentSource(profile, meta) {
|
|
|
33190
31362
|
.filter((line) => Boolean(line))
|
|
33191
31363
|
.join('\n');
|
|
33192
31364
|
const personaBlock = profile.personaDescription
|
|
33193
|
-
? spaceTrim$
|
|
31365
|
+
? spaceTrim$1((block) => `
|
|
33194
31366
|
PERSONA
|
|
33195
31367
|
${block(profile.personaDescription || '')}
|
|
33196
31368
|
`)
|
|
@@ -33226,7 +31398,7 @@ class RemoteAgent extends Agent {
|
|
|
33226
31398
|
// <- TODO: [🐱🚀] What about closed-source agents?
|
|
33227
31399
|
// <- TODO: [🐱🚀] Maybe use promptbookFetch
|
|
33228
31400
|
if (!profileResponse.ok) {
|
|
33229
|
-
throw new Error(spaceTrim$
|
|
31401
|
+
throw new Error(spaceTrim$1((block) => `
|
|
33230
31402
|
Failed to fetch remote agent profile:
|
|
33231
31403
|
|
|
33232
31404
|
Agent URL:
|