tesseract-agent 0.11.14 → 0.11.16
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/dist-bundle/cli.js +1282 -881
- package/dist-bundle/mesh-core/package.json +1 -1
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -11692,8 +11692,8 @@ var capitalizeFirstCharacter, error28;
|
|
|
11692
11692
|
var init_lt = __esm({
|
|
11693
11693
|
"../../node_modules/zod/v4/locales/lt.js"() {
|
|
11694
11694
|
init_util();
|
|
11695
|
-
capitalizeFirstCharacter = (
|
|
11696
|
-
return
|
|
11695
|
+
capitalizeFirstCharacter = (text13) => {
|
|
11696
|
+
return text13.charAt(0).toUpperCase() + text13.slice(1);
|
|
11697
11697
|
};
|
|
11698
11698
|
error28 = () => {
|
|
11699
11699
|
const Sizable = {
|
|
@@ -22599,6 +22599,14 @@ var init_capabilities = __esm({
|
|
|
22599
22599
|
vars: [],
|
|
22600
22600
|
content: `Whether a personal HeyGen key is set. Never returns the key itself.`
|
|
22601
22601
|
},
|
|
22602
|
+
{
|
|
22603
|
+
id: "capability.image.has_avatar_free_tier",
|
|
22604
|
+
group: "tools",
|
|
22605
|
+
label: "Free avatar-video tier available?",
|
|
22606
|
+
help: "What the model is told the `image.has_avatar_free_tier` App-Control capability does (image domain, read).",
|
|
22607
|
+
vars: [],
|
|
22608
|
+
content: `Whether the free Tesseract avatar tier can actually serve a request on this deployment \u2014 a signed-in account AND a HeyGen account behind our proxy. Check it before drafting a script: when it is false and the user has no HeyGen key of their own, generate_avatar_video cannot succeed.`
|
|
22609
|
+
},
|
|
22602
22610
|
{
|
|
22603
22611
|
id: "capability.image.remove_provider_key",
|
|
22604
22612
|
group: "tools",
|
|
@@ -23039,6 +23047,86 @@ var init_capabilities = __esm({
|
|
|
23039
23047
|
vars: [],
|
|
23040
23048
|
content: `Open the presentation surface in the app so a deck can be picked and presented.`
|
|
23041
23049
|
},
|
|
23050
|
+
{
|
|
23051
|
+
id: "capability.present.list_decks",
|
|
23052
|
+
group: "tools",
|
|
23053
|
+
label: "List presentations",
|
|
23054
|
+
help: "What the model is told the `present.list_decks` App-Control capability does (present domain, read).",
|
|
23055
|
+
vars: [],
|
|
23056
|
+
content: `Every presentation in the user's library, with its slide count and its deck folder \u2014 the handle every other presentation capability takes. Use it before editing, so you work on the deck the user means rather than making a second one.`
|
|
23057
|
+
},
|
|
23058
|
+
{
|
|
23059
|
+
id: "capability.present.create_deck",
|
|
23060
|
+
group: "tools",
|
|
23061
|
+
label: "Create a presentation",
|
|
23062
|
+
help: "What the model is told the `present.create_deck` App-Control capability does (present domain, write).",
|
|
23063
|
+
vars: [],
|
|
23064
|
+
content: `Make a new, empty Tesseract Stage presentation in the user's library (~/Documents/Tesseract/Presentations) and return its deck folder. This is how you make a presentation \u2014 NOT a PowerPoint file, NOT markdown, NOT an HTML canvas. Pass the title in the user's own words and language. Optionally set a theme: CSS custom properties every slide inherits, e.g. { "--bg": "#FFFFFF", "--ink": "#16130F", "--accent": "#D97757" }. Then write slides with write_slide.`
|
|
23065
|
+
},
|
|
23066
|
+
{
|
|
23067
|
+
id: "capability.present.write_slide",
|
|
23068
|
+
group: "tools",
|
|
23069
|
+
label: "Write a slide",
|
|
23070
|
+
help: "What the model is told the `present.write_slide` App-Control capability does (present domain, write).",
|
|
23071
|
+
vars: [],
|
|
23072
|
+
content: `Write one slide file into a presentation. A slide is a React component in TSX: \`export const meta = { id, title, summary?, notes?, transition?, builds? }\` plus a default-exported component. Path is \`slides/NN-name.tsx\` and FILENAME ORDER IS SLIDE ORDER, so number the prefixes (01, 02, 03\u2026); reordering later is a rename. Shared helpers may live anywhere else in the package and be imported relatively. Always run validate_deck afterwards.`
|
|
23073
|
+
},
|
|
23074
|
+
{
|
|
23075
|
+
id: "capability.present.read_slide",
|
|
23076
|
+
group: "tools",
|
|
23077
|
+
label: "Read a slide",
|
|
23078
|
+
help: "What the model is told the `present.read_slide` App-Control capability does (present domain, read).",
|
|
23079
|
+
vars: [],
|
|
23080
|
+
content: `Read one file back out of a presentation. Use it before editing a slide you did not just write, so a revision preserves what is already there instead of replacing it from memory.`
|
|
23081
|
+
},
|
|
23082
|
+
{
|
|
23083
|
+
id: "capability.present.delete_slide",
|
|
23084
|
+
group: "tools",
|
|
23085
|
+
label: "Delete a slide",
|
|
23086
|
+
help: "What the model is told the `present.delete_slide` App-Control capability does (present domain, write).",
|
|
23087
|
+
vars: [],
|
|
23088
|
+
content: `Remove one file from a presentation. Deleting a slide renumbers nothing \u2014 the remaining filenames still sort, so a gap in the numbering is harmless.`
|
|
23089
|
+
},
|
|
23090
|
+
{
|
|
23091
|
+
id: "capability.present.validate_deck",
|
|
23092
|
+
group: "tools",
|
|
23093
|
+
label: "Check a presentation",
|
|
23094
|
+
help: "What the model is told the `present.validate_deck` App-Control capability does (present domain, read).",
|
|
23095
|
+
vars: [],
|
|
23096
|
+
content: `Compile every slide and report what is wrong \u2014 syntax errors with line numbers, imports that do not resolve, missing or duplicate \`meta\`. ALWAYS call this after writing slides, and fix what it reports before telling the user the presentation is ready: a deck that fails does so in front of an audience. It reports load-time problems only; it cannot catch a mistake that appears only while a slide renders.`
|
|
23097
|
+
},
|
|
23098
|
+
{
|
|
23099
|
+
id: "capability.present.set_deck_theme",
|
|
23100
|
+
group: "tools",
|
|
23101
|
+
label: "Set a presentation's theme",
|
|
23102
|
+
help: "What the model is told the `present.set_deck_theme` App-Control capability does (present domain, write).",
|
|
23103
|
+
vars: [],
|
|
23104
|
+
content: `Replace the CSS custom properties every slide in a presentation inherits \u2014 the deck's look in one place. Restyling a deck is this call, not an edit to every slide.`
|
|
23105
|
+
},
|
|
23106
|
+
{
|
|
23107
|
+
id: "capability.present.add_asset",
|
|
23108
|
+
group: "tools",
|
|
23109
|
+
label: "Add an image to a presentation",
|
|
23110
|
+
help: "What the model is told the `present.add_asset` App-Control capability does (present domain, write).",
|
|
23111
|
+
vars: [],
|
|
23112
|
+
content: `Copy an image, photo or audio file from anywhere on disk INTO the presentation, and get back the path to import from a slide (\`import hero from '../assets/hero.png?url'\`). Do this for anything a slide shows: a presentation must carry its own files, or it breaks the moment it is moved or sent to someone.`
|
|
23113
|
+
},
|
|
23114
|
+
{
|
|
23115
|
+
id: "capability.present.open_deck",
|
|
23116
|
+
group: "tools",
|
|
23117
|
+
label: "Open a presentation",
|
|
23118
|
+
help: "What the model is told the `present.open_deck` App-Control capability does (present domain, write).",
|
|
23119
|
+
vars: [],
|
|
23120
|
+
content: `Open a presentation in the Stage tab so the user can see it. Checks it first and reports the problems instead if it cannot be shown.`
|
|
23121
|
+
},
|
|
23122
|
+
{
|
|
23123
|
+
id: "capability.present.delete_deck",
|
|
23124
|
+
group: "tools",
|
|
23125
|
+
label: "Delete a presentation",
|
|
23126
|
+
help: "What the model is told the `present.delete_deck` App-Control capability does (present domain, write).",
|
|
23127
|
+
vars: [],
|
|
23128
|
+
content: `Delete a whole presentation from the library, permanently. Ask the user first \u2014 this is their document, and there is no undo.`
|
|
23129
|
+
},
|
|
23042
23130
|
{
|
|
23043
23131
|
id: "capability.present.end",
|
|
23044
23132
|
group: "tools",
|
|
@@ -23703,6 +23791,14 @@ Apply a plan the user has approved. Requires the plan_hash from tutorial_plan_in
|
|
|
23703
23791
|
help: "What the model is told `tutorial_await_decision` does \u2014 blocks until the user approves the tour, asks for changes, or asks to re-pick a target.",
|
|
23704
23792
|
vars: [],
|
|
23705
23793
|
content: `Wait for the user to decide on the tour card. Call this straight after tutorial_review_scenario and WAIT \u2014 do not carry on, do not start planning, do not fill the silence. It returns when they approve, ask for changes, or ask for a step to point at something else. Their in-place edits are saved automatically, so whatever wording they left is the wording that ships.`
|
|
23794
|
+
},
|
|
23795
|
+
{
|
|
23796
|
+
id: "tool.capabilities.tesseract_capabilities",
|
|
23797
|
+
group: "tools",
|
|
23798
|
+
label: "tesseract_capabilities",
|
|
23799
|
+
help: "What the model is told the `tesseract_capabilities` tool does \u2014 the one tool that hands it Tesseract's own capability map (docs/CAPABILITIES.md). This description is the only thing deciding whether the model consults the map before answering \u201Cwhat can you do?\u201D or declaring a feature impossible, so it is the highest-leverage entry here. The builder passes the live section index as the `sections` variable.",
|
|
23800
|
+
vars: ["sections"],
|
|
23801
|
+
content: `Return Tesseract's own capability map \u2014 what THE PRODUCT can do, which is far more than the tools you happen to hold this turn (most of Tesseract is UI, services and other clients you never call). Read it BEFORE answering any question about what Tesseract, or you inside it, can do: "what can you do?", "can Tesseract <x>?", "how do I <x> in this app?", "is there a way to", "does it support", "what features", "help me get started" \u2014 and before telling a user something is impossible. It also lists what is deliberately NOT built, which is the most common way to be wrong about this product, so never claim a feature is missing without checking here first. Sections: {{sections}}. Omit \`section\` for the whole map (~22 KB); pass a section number, title or keyword to get just that part when the question is narrow.`
|
|
23706
23802
|
}
|
|
23707
23803
|
];
|
|
23708
23804
|
}
|
|
@@ -23997,6 +24093,17 @@ var init_permissions = __esm({
|
|
|
23997
24093
|
}
|
|
23998
24094
|
});
|
|
23999
24095
|
|
|
24096
|
+
// ../../packages/shared/dist/platform-availability.js
|
|
24097
|
+
var HOSTING_AVAILABLE, SSO_AVAILABLE, CLOUD_SERVER_AVAILABLE;
|
|
24098
|
+
var init_platform_availability = __esm({
|
|
24099
|
+
"../../packages/shared/dist/platform-availability.js"() {
|
|
24100
|
+
"use strict";
|
|
24101
|
+
HOSTING_AVAILABLE = false;
|
|
24102
|
+
SSO_AVAILABLE = false;
|
|
24103
|
+
CLOUD_SERVER_AVAILABLE = false;
|
|
24104
|
+
}
|
|
24105
|
+
});
|
|
24106
|
+
|
|
24000
24107
|
// ../../packages/shared/dist/app-elements.js
|
|
24001
24108
|
var APP_ELEMENTS, byId, APP_ELEMENT_IDS;
|
|
24002
24109
|
var init_app_elements = __esm({
|
|
@@ -24315,6 +24422,13 @@ function schemaFieldRejected(status2, body) {
|
|
|
24315
24422
|
function anthropicBaseUrl(env) {
|
|
24316
24423
|
return env?.ANTHROPIC_BASE_URL?.trim() || process.env.ANTHROPIC_BASE_URL?.trim() || "https://api.anthropic.com";
|
|
24317
24424
|
}
|
|
24425
|
+
function isAnthropicEndpoint(env) {
|
|
24426
|
+
try {
|
|
24427
|
+
return /(^|\.)api\.anthropic\.com$/i.test(new URL(anthropicBaseUrl(env)).hostname);
|
|
24428
|
+
} catch {
|
|
24429
|
+
return false;
|
|
24430
|
+
}
|
|
24431
|
+
}
|
|
24318
24432
|
var OAUTH_BETA_HEADER;
|
|
24319
24433
|
var init_model_json = __esm({
|
|
24320
24434
|
"../../packages/shared/dist/model-json.js"() {
|
|
@@ -24347,9 +24461,9 @@ function withRunDirective(userText, directive) {
|
|
|
24347
24461
|
return `${head}${RUN_DIRECTIVE_MARK}
|
|
24348
24462
|
${directive}`;
|
|
24349
24463
|
}
|
|
24350
|
-
function stripRunDirective(
|
|
24351
|
-
const at =
|
|
24352
|
-
return at < 0 ?
|
|
24464
|
+
function stripRunDirective(text13) {
|
|
24465
|
+
const at = text13.indexOf(RUN_DIRECTIVE_MARK);
|
|
24466
|
+
return at < 0 ? text13 : text13.slice(0, at).trimEnd();
|
|
24353
24467
|
}
|
|
24354
24468
|
var RUN_DIRECTIVE_MARK;
|
|
24355
24469
|
var init_run_directive = __esm({
|
|
@@ -24397,6 +24511,13 @@ var init_digit_recall = __esm({
|
|
|
24397
24511
|
}
|
|
24398
24512
|
});
|
|
24399
24513
|
|
|
24514
|
+
// ../../packages/shared/dist/tab-nav.js
|
|
24515
|
+
var init_tab_nav = __esm({
|
|
24516
|
+
"../../packages/shared/dist/tab-nav.js"() {
|
|
24517
|
+
"use strict";
|
|
24518
|
+
}
|
|
24519
|
+
});
|
|
24520
|
+
|
|
24400
24521
|
// ../../packages/shared/dist/telemetry.js
|
|
24401
24522
|
var TELEMETRY_EVENTS, EVENT_CATEGORY;
|
|
24402
24523
|
var init_telemetry = __esm({
|
|
@@ -24697,6 +24818,7 @@ var NO_QUOTAS, NO_FEATURES, PLAN_CATALOG;
|
|
|
24697
24818
|
var init_plans = __esm({
|
|
24698
24819
|
"../../packages/shared/dist/plans.js"() {
|
|
24699
24820
|
"use strict";
|
|
24821
|
+
init_platform_availability();
|
|
24700
24822
|
NO_QUOTAS = { computeHours: 0, storageGb: 0, egressGb: 0, videoSeconds: 0 };
|
|
24701
24823
|
NO_FEATURES = {
|
|
24702
24824
|
sync: false,
|
|
@@ -24725,7 +24847,7 @@ var init_plans = __esm({
|
|
|
24725
24847
|
tagline: "Your machine, your phone, your voice.",
|
|
24726
24848
|
features: [
|
|
24727
24849
|
"Unlimited agent usage",
|
|
24728
|
-
"
|
|
24850
|
+
"It operates this computer \u2014 screen, files and browser",
|
|
24729
24851
|
"Voice mode",
|
|
24730
24852
|
"Mobile app \u2014 reach your computer from your phone",
|
|
24731
24853
|
"Cloud workspace \u2014 your machine and recent projects in one view",
|
|
@@ -24744,9 +24866,11 @@ var init_plans = __esm({
|
|
|
24744
24866
|
features: [
|
|
24745
24867
|
"Everything in Free",
|
|
24746
24868
|
"Unlimited machines \u2014 run agents on all of them",
|
|
24747
|
-
"Tesseract cloud server \u2014 a managed always-on agent in the cloud",
|
|
24748
|
-
|
|
24749
|
-
|
|
24869
|
+
...CLOUD_SERVER_AVAILABLE ? ["Tesseract cloud server \u2014 a managed always-on agent in the cloud"] : [],
|
|
24870
|
+
...HOSTING_AVAILABLE ? [
|
|
24871
|
+
"Deploy to the cloud \u2014 your app on a *.tesseract.dev URL",
|
|
24872
|
+
"Includes ~1 always-on service + 20 GB storage + 100 GB bandwidth (overage metered)"
|
|
24873
|
+
] : [],
|
|
24750
24874
|
"Premium missions \u2014 GDPR, security, UX, performance audits that fix & verify",
|
|
24751
24875
|
"Sync settings across your devices",
|
|
24752
24876
|
"Email support"
|
|
@@ -24756,10 +24880,10 @@ var init_plans = __esm({
|
|
|
24756
24880
|
sync: true,
|
|
24757
24881
|
mobile: true,
|
|
24758
24882
|
cloudWorkspace: true,
|
|
24759
|
-
cloudServer:
|
|
24883
|
+
cloudServer: CLOUD_SERVER_AVAILABLE,
|
|
24760
24884
|
remoteAgents: true,
|
|
24761
24885
|
voice: true,
|
|
24762
|
-
hosting:
|
|
24886
|
+
hosting: HOSTING_AVAILABLE,
|
|
24763
24887
|
plugins: true,
|
|
24764
24888
|
missions: true,
|
|
24765
24889
|
scheduling: true,
|
|
@@ -24780,26 +24904,27 @@ var init_plans = __esm({
|
|
|
24780
24904
|
"Parallel agents",
|
|
24781
24905
|
"Advanced browser automation",
|
|
24782
24906
|
"API access",
|
|
24783
|
-
"
|
|
24784
|
-
"
|
|
24907
|
+
...SSO_AVAILABLE ? ["Company sign-on and audit log"] : [],
|
|
24908
|
+
"Centralized billing across seats",
|
|
24909
|
+
...HOSTING_AVAILABLE ? ["Pooled cloud hosting \u2014 bigger shared quota"] : [],
|
|
24785
24910
|
"Priority support"
|
|
24786
24911
|
],
|
|
24787
24912
|
featurePolicy: {
|
|
24788
24913
|
sync: true,
|
|
24789
24914
|
mobile: true,
|
|
24790
24915
|
cloudWorkspace: true,
|
|
24791
|
-
cloudServer:
|
|
24916
|
+
cloudServer: CLOUD_SERVER_AVAILABLE,
|
|
24792
24917
|
remoteAgents: true,
|
|
24793
24918
|
voice: true,
|
|
24794
24919
|
team: true,
|
|
24795
24920
|
parallelAgents: true,
|
|
24796
24921
|
advancedBrowser: true,
|
|
24797
|
-
hosting:
|
|
24922
|
+
hosting: HOSTING_AVAILABLE,
|
|
24798
24923
|
plugins: true,
|
|
24799
24924
|
missions: true,
|
|
24800
24925
|
scheduling: true,
|
|
24801
24926
|
api: true,
|
|
24802
|
-
sso:
|
|
24927
|
+
sso: SSO_AVAILABLE,
|
|
24803
24928
|
seats: 2,
|
|
24804
24929
|
maxMachines: 0
|
|
24805
24930
|
},
|
|
@@ -25520,8 +25645,26 @@ var init_engines = __esm({
|
|
|
25520
25645
|
capabilities: CLAUDE_CAPABILITIES,
|
|
25521
25646
|
runModeTiming: CLAUDE_RUN_MODE_TIMING,
|
|
25522
25647
|
homepageUrl: "https://docs.claude.com/en/docs/claude-code",
|
|
25523
|
-
|
|
25524
|
-
|
|
25648
|
+
// The NATIVE installer, not npm. Two reasons, in order of how often they bite:
|
|
25649
|
+
// 1. npm needs a Node toolchain the machine may simply not have — and a GUI-launched app
|
|
25650
|
+
// sees PATH=/usr/bin:/bin:/usr/sbin:/sbin, so even an nvm-managed node is invisible.
|
|
25651
|
+
// The native installer needs only curl/wget and a shell.
|
|
25652
|
+
// 2. npm would land under our own `--prefix` (~/.tesseract/runtimes/bin), which the thing
|
|
25653
|
+
// that SPAWNS claude (agent-core's findUserInstalledClaude) does not search — so the
|
|
25654
|
+
// install would "succeed" and the engine would still read as missing. The native
|
|
25655
|
+
// installer writes ~/.local/bin/claude, which both the probe and the spawner know.
|
|
25656
|
+
// `install.sh` hard-refuses Windows, and `irm | iex` cannot take the version argument, so
|
|
25657
|
+
// Windows gets the documented scriptblock form rather than a quoting variant.
|
|
25658
|
+
installCommand: "curl -fsSL https://claude.ai/install.sh | bash -s {version}",
|
|
25659
|
+
installCommandWin: "& ([scriptblock]::Create((irm https://claude.ai/install.ps1))) {version}",
|
|
25660
|
+
// Its own updater. A copy managed by brew/winget reports "up to date" and does nothing —
|
|
25661
|
+
// which autoFixUnusable surfaces honestly via its post-update re-check rather than
|
|
25662
|
+
// claiming success.
|
|
25663
|
+
updateCommand: "claude update",
|
|
25664
|
+
// The documented uninstall. Both halves: the launcher and the versions directory.
|
|
25665
|
+
removeCommand: "rm -f ~/.local/bin/claude && rm -rf ~/.local/share/claude",
|
|
25666
|
+
removeCommandWin: 'Remove-Item -Path "$env:USERPROFILE\\.local\\bin\\claude.exe" -Force; Remove-Item -Path "$env:USERPROFILE\\.local\\share\\claude" -Recurse -Force',
|
|
25667
|
+
installHint: "Tesseract runs the Claude Code CLI you have installed rather than bundling one; install it to use this engine."
|
|
25525
25668
|
},
|
|
25526
25669
|
"openai-codex": {
|
|
25527
25670
|
id: "openai-codex",
|
|
@@ -26071,6 +26214,7 @@ var init_runner_compat = __esm({
|
|
|
26071
26214
|
"use strict";
|
|
26072
26215
|
init_engines();
|
|
26073
26216
|
init_providers();
|
|
26217
|
+
init_model_catalog();
|
|
26074
26218
|
GATEWAY_WIRES = {
|
|
26075
26219
|
"claude-code": { kind: "anthropic-env" },
|
|
26076
26220
|
"openai-codex": { kind: "codex-home" },
|
|
@@ -26337,6 +26481,10 @@ var init_runtimes = __esm({
|
|
|
26337
26481
|
label: ENGINE_CATALOG[id].label,
|
|
26338
26482
|
cliBinary: ENGINE_CATALOG[id].cliBinary,
|
|
26339
26483
|
installCommand: ENGINE_CATALOG[id].installCommand,
|
|
26484
|
+
installCommandWin: ENGINE_CATALOG[id].installCommandWin,
|
|
26485
|
+
updateCommand: ENGINE_CATALOG[id].updateCommand,
|
|
26486
|
+
removeCommand: ENGINE_CATALOG[id].removeCommand,
|
|
26487
|
+
removeCommandWin: ENGINE_CATALOG[id].removeCommandWin,
|
|
26340
26488
|
kind: "engine"
|
|
26341
26489
|
})),
|
|
26342
26490
|
{ id: "ollama", label: "Ollama", cliBinary: "ollama", installCommand: "curl -fsSL https://ollama.com/install.sh | sh", kind: "tool" },
|
|
@@ -26482,26 +26630,47 @@ function providerBase(key2, which2) {
|
|
|
26482
26630
|
return fromServer;
|
|
26483
26631
|
return which2 === "anthropic" ? gatewayAnthropicBaseUrl(key2.baseUrl) : which2 === "openai" ? gatewayOpenAiBaseUrl(key2.baseUrl) : gatewayGeminiBaseUrl(key2.baseUrl);
|
|
26484
26632
|
}
|
|
26633
|
+
function slotProviders(key2) {
|
|
26634
|
+
const out = /* @__PURE__ */ new Map();
|
|
26635
|
+
for (const slot of Object.keys(TIER_PROVIDER)) {
|
|
26636
|
+
const id = key2.models[slot]?.trim();
|
|
26637
|
+
if (id)
|
|
26638
|
+
out.set(id, TIER_PROVIDER[slot]);
|
|
26639
|
+
}
|
|
26640
|
+
return out;
|
|
26641
|
+
}
|
|
26485
26642
|
function tiers(engineId, key2, models) {
|
|
26486
|
-
const
|
|
26487
|
-
const
|
|
26643
|
+
const provider = gatewayProviderForEngine(engineId);
|
|
26644
|
+
const preference = provider ? TIER_PREFERENCE[provider] : void 0;
|
|
26645
|
+
const byModel = slotProviders(key2);
|
|
26488
26646
|
const asked = (v) => {
|
|
26489
26647
|
const t = v?.trim();
|
|
26490
26648
|
if (!t)
|
|
26491
26649
|
return void 0;
|
|
26492
26650
|
if (t.includes("/"))
|
|
26493
26651
|
return t;
|
|
26494
|
-
return
|
|
26652
|
+
return byModel.get(t) === provider ? t : void 0;
|
|
26495
26653
|
};
|
|
26496
|
-
const
|
|
26497
|
-
|
|
26498
|
-
|
|
26654
|
+
const pick3 = (slots) => {
|
|
26655
|
+
for (const slot of slots) {
|
|
26656
|
+
const id = key2.models[slot]?.trim();
|
|
26657
|
+
if (id)
|
|
26658
|
+
return id;
|
|
26659
|
+
}
|
|
26660
|
+
return void 0;
|
|
26661
|
+
};
|
|
26662
|
+
const serverDefault = asked(key2.defaults?.model);
|
|
26663
|
+
const main2 = asked(models.main) || serverDefault || preference && pick3(preference.main);
|
|
26664
|
+
const fast = asked(models.fast) || serverDefault || preference && pick3(preference.fast) || main2;
|
|
26665
|
+
return { main: main2 || void 0, fast: fast || void 0 };
|
|
26499
26666
|
}
|
|
26500
26667
|
function planGatewayRun(engineId, key2, models, homeBase) {
|
|
26501
26668
|
const wire = gatewayWireFor(engineId);
|
|
26502
26669
|
if (!wire)
|
|
26503
26670
|
return void 0;
|
|
26504
26671
|
const { main: main2, fast } = tiers(engineId, key2, models);
|
|
26672
|
+
if (!main2 || !fast)
|
|
26673
|
+
return void 0;
|
|
26505
26674
|
const effort = ENGINE_CATALOG[engineId]?.modelControls.reasoningEfforts?.includes(models.reasoningEffort ?? "") ? models.reasoningEffort : void 0;
|
|
26506
26675
|
return planEndpointRun(wire.kind, {
|
|
26507
26676
|
baseUrl: wire.kind === "anthropic-env" ? providerBase(key2, "anthropic") : wire.kind === "gemini-env" ? providerBase(key2, "gemini") : providerBase(key2, "openai"),
|
|
@@ -26515,13 +26684,30 @@ function planGatewayRun(engineId, key2, models, homeBase) {
|
|
|
26515
26684
|
homeKey: HOME_DIR_NAME[engineId]
|
|
26516
26685
|
}, homeBase);
|
|
26517
26686
|
}
|
|
26518
|
-
var HOME_DIR_NAME;
|
|
26687
|
+
var TIER_PROVIDER, TIER_PREFERENCE, HOME_DIR_NAME;
|
|
26519
26688
|
var init_gateway_plan = __esm({
|
|
26520
26689
|
"../../packages/shared/dist/gateway-plan.js"() {
|
|
26521
26690
|
"use strict";
|
|
26522
26691
|
init_runner_compat();
|
|
26523
26692
|
init_engine_endpoint();
|
|
26524
26693
|
init_engines();
|
|
26694
|
+
TIER_PROVIDER = {
|
|
26695
|
+
low: "openai",
|
|
26696
|
+
high: "openai",
|
|
26697
|
+
image: "openai",
|
|
26698
|
+
codex: "openai",
|
|
26699
|
+
gpt: "openai",
|
|
26700
|
+
vision: "google-ai",
|
|
26701
|
+
claude: "anthropic",
|
|
26702
|
+
claudeFast: "anthropic"
|
|
26703
|
+
};
|
|
26704
|
+
TIER_PREFERENCE = {
|
|
26705
|
+
// No fast rung of its own on the OpenAI side: Codex is one model plus a reasoning dial,
|
|
26706
|
+
// and the nano model remains the cheap fallback for anything that asks for one.
|
|
26707
|
+
openai: { main: ["codex", "gpt", "high"], fast: ["low", "high"] },
|
|
26708
|
+
anthropic: { main: ["claude"], fast: ["claudeFast", "claude"] },
|
|
26709
|
+
"google-ai": { main: ["vision"], fast: ["vision"] }
|
|
26710
|
+
};
|
|
26525
26711
|
HOME_DIR_NAME = {
|
|
26526
26712
|
opencode: "opencode-bundled",
|
|
26527
26713
|
"openai-codex": "gateway-openai-codex"
|
|
@@ -27637,6 +27823,14 @@ var init_stage_types = __esm({
|
|
|
27637
27823
|
}
|
|
27638
27824
|
});
|
|
27639
27825
|
|
|
27826
|
+
// ../../packages/shared/dist/deck-package.js
|
|
27827
|
+
var init_deck_package = __esm({
|
|
27828
|
+
"../../packages/shared/dist/deck-package.js"() {
|
|
27829
|
+
"use strict";
|
|
27830
|
+
init_stage_types();
|
|
27831
|
+
}
|
|
27832
|
+
});
|
|
27833
|
+
|
|
27640
27834
|
// ../../packages/shared/dist/rdesk-client-ipc.js
|
|
27641
27835
|
var init_rdesk_client_ipc = __esm({
|
|
27642
27836
|
"../../packages/shared/dist/rdesk-client-ipc.js"() {
|
|
@@ -27662,10 +27856,10 @@ var init_user_dialog = __esm({
|
|
|
27662
27856
|
});
|
|
27663
27857
|
|
|
27664
27858
|
// ../../packages/shared/dist/session-ops.js
|
|
27665
|
-
function cleanTaskNotifications(
|
|
27666
|
-
if (!
|
|
27667
|
-
return
|
|
27668
|
-
return
|
|
27859
|
+
function cleanTaskNotifications(text13) {
|
|
27860
|
+
if (!text13.includes("<task-notification>"))
|
|
27861
|
+
return text13;
|
|
27862
|
+
return text13.replace(/<task-notification>([\s\S]*?)<\/task-notification>/g, (_all, inner) => {
|
|
27669
27863
|
const g = (name) => {
|
|
27670
27864
|
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(inner);
|
|
27671
27865
|
return m ? m[1].trim() : "";
|
|
@@ -27676,8 +27870,8 @@ function cleanTaskNotifications(text12) {
|
|
|
27676
27870
|
}).trim();
|
|
27677
27871
|
}
|
|
27678
27872
|
function transcriptToText(msgs, cap = MERGE_PER_SOURCE_CAP) {
|
|
27679
|
-
const
|
|
27680
|
-
return
|
|
27873
|
+
const text13 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${cleanTaskNotifications(m.content)}`).join("\n").slice(0, cap);
|
|
27874
|
+
return text13.trim() ? text13 : "";
|
|
27681
27875
|
}
|
|
27682
27876
|
function buildMergeSeed(transcripts) {
|
|
27683
27877
|
return [
|
|
@@ -27689,10 +27883,10 @@ function buildMergeSeed(transcripts) {
|
|
|
27689
27883
|
${t}`)
|
|
27690
27884
|
].join("\n\n");
|
|
27691
27885
|
}
|
|
27692
|
-
function parseSummaryReply(
|
|
27693
|
-
const m = /^\s*TITLE:\s*(.+?)\s*\n-{3,}\s*\n([\s\S]+)$/.exec(
|
|
27886
|
+
function parseSummaryReply(text13) {
|
|
27887
|
+
const m = /^\s*TITLE:\s*(.+?)\s*\n-{3,}\s*\n([\s\S]+)$/.exec(text13);
|
|
27694
27888
|
const title = m?.[1]?.trim();
|
|
27695
|
-
const summary = (m?.[2] ??
|
|
27889
|
+
const summary = (m?.[2] ?? text13).trim();
|
|
27696
27890
|
return title ? { title, summary } : { summary };
|
|
27697
27891
|
}
|
|
27698
27892
|
var MERGE_PER_SOURCE_CAP;
|
|
@@ -27797,6 +27991,7 @@ var init_dist2 = __esm({
|
|
|
27797
27991
|
"use strict";
|
|
27798
27992
|
init_surface_merge();
|
|
27799
27993
|
init_permissions();
|
|
27994
|
+
init_platform_availability();
|
|
27800
27995
|
init_app_elements();
|
|
27801
27996
|
init_ws_protocol();
|
|
27802
27997
|
init_context_overflow();
|
|
@@ -27807,6 +28002,7 @@ var init_dist2 = __esm({
|
|
|
27807
28002
|
init_run_directive();
|
|
27808
28003
|
init_proactive_compaction();
|
|
27809
28004
|
init_digit_recall();
|
|
28005
|
+
init_tab_nav();
|
|
27810
28006
|
init_telemetry();
|
|
27811
28007
|
init_error_report();
|
|
27812
28008
|
init_eula();
|
|
@@ -27849,6 +28045,7 @@ var init_dist2 = __esm({
|
|
|
27849
28045
|
init_chat_slash();
|
|
27850
28046
|
init_present_protocol();
|
|
27851
28047
|
init_stage_types();
|
|
28048
|
+
init_deck_package();
|
|
27852
28049
|
init_rdesk_client_ipc();
|
|
27853
28050
|
init_user_dialog();
|
|
27854
28051
|
init_session_ops();
|
|
@@ -30539,8 +30736,8 @@ function makeApi(deps, toolId, tier) {
|
|
|
30539
30736
|
await h.close();
|
|
30540
30737
|
return r.cancelled ? null : r.value ?? [];
|
|
30541
30738
|
},
|
|
30542
|
-
notify: async (
|
|
30543
|
-
await api.open({ kind: "markdown", initial: { markdown:
|
|
30739
|
+
notify: async (text13, opts) => {
|
|
30740
|
+
await api.open({ kind: "markdown", initial: { markdown: text13, level: opts?.level } });
|
|
30544
30741
|
}
|
|
30545
30742
|
};
|
|
30546
30743
|
return api;
|
|
@@ -30551,11 +30748,11 @@ function buildToolCtx(deps, sessionId, toolId, log10 = NOOP_LOG, tier = "third-p
|
|
|
30551
30748
|
return getSid();
|
|
30552
30749
|
}, toolId, log: log10 };
|
|
30553
30750
|
}
|
|
30554
|
-
function wrapCtxTool(
|
|
30555
|
-
const raw =
|
|
30751
|
+
function wrapCtxTool(tool22, ctx2) {
|
|
30752
|
+
const raw = tool22.__ctxHandler;
|
|
30556
30753
|
if (typeof raw !== "function")
|
|
30557
|
-
return
|
|
30558
|
-
return { ...
|
|
30754
|
+
return tool22;
|
|
30755
|
+
return { ...tool22, handler: async (args) => raw(args, ctx2) };
|
|
30559
30756
|
}
|
|
30560
30757
|
var NOOP_LOG;
|
|
30561
30758
|
var init_surface_ctx = __esm({
|
|
@@ -30713,11 +30910,11 @@ var init_hook_bus = __esm({
|
|
|
30713
30910
|
// ../../packages/agent-core/dist/jobs/file-tailer.js
|
|
30714
30911
|
import { statSync } from "node:fs";
|
|
30715
30912
|
import { open } from "node:fs/promises";
|
|
30716
|
-
function parseBackgroundTaskResult(
|
|
30717
|
-
if (!
|
|
30913
|
+
function parseBackgroundTaskResult(text13) {
|
|
30914
|
+
if (!text13 || !text13.includes(".output"))
|
|
30718
30915
|
return null;
|
|
30719
|
-
const id = /\bID:\s*([A-Za-z0-9_-]+)/.exec(
|
|
30720
|
-
const path6 = /Output is being written to:\s*([^\s]+\.output)/.exec(
|
|
30916
|
+
const id = /\bID:\s*([A-Za-z0-9_-]+)/.exec(text13);
|
|
30917
|
+
const path6 = /Output is being written to:\s*([^\s]+\.output)/.exec(text13);
|
|
30721
30918
|
if (!id?.[1] || !path6?.[1])
|
|
30722
30919
|
return null;
|
|
30723
30920
|
return { taskId: id[1], outputPath: path6[1] };
|
|
@@ -31737,6 +31934,8 @@ var init_parallel_tools = __esm({
|
|
|
31737
31934
|
"browser_events",
|
|
31738
31935
|
"capture_element_styles",
|
|
31739
31936
|
// ── Listings, capability probes and status reads.
|
|
31937
|
+
// tesseract_capabilities returns an inlined constant — concurrent calls are indistinguishable.
|
|
31938
|
+
"tesseract_capabilities",
|
|
31740
31939
|
"list_effects",
|
|
31741
31940
|
"list_upscale_models",
|
|
31742
31941
|
"list_voices",
|
|
@@ -31789,8 +31988,8 @@ var init_tool_spec = __esm({
|
|
|
31789
31988
|
import { tool as tool14 } from "@anthropic-ai/claude-agent-sdk";
|
|
31790
31989
|
function buildScreenControlSdkTools(p) {
|
|
31791
31990
|
return screenControlSpecs().map((spec) => tool14(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
|
|
31792
|
-
const
|
|
31793
|
-
return { content: [{ type: "text", text:
|
|
31991
|
+
const text13 = await p.exec(spec.name, args ?? {});
|
|
31992
|
+
return { content: [{ type: "text", text: text13 || "Done." }] };
|
|
31794
31993
|
}));
|
|
31795
31994
|
}
|
|
31796
31995
|
var ANNOTATE_STYLES, SCREEN_CONTROL_SHAPES, screenControlSpecs;
|
|
@@ -32596,6 +32795,10 @@ ${JSON.stringify(r, null, 2)}`
|
|
|
32596
32795
|
{ id: "settings.has_search_key", domain: "settings", title: "Web search available?", input: external_exports.object({}), mutation: "read", availability: "host", binding: { kind: "ipc", channel: "serp", verb: "hasKey" } },
|
|
32597
32796
|
{ id: "image.set_avatar_key", domain: "image", title: "Set avatar-video (HeyGen) key", input: external_exports.object({ api_key: external_exports.string().describe("HeyGen API key (secret); blank clears.") }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "heygen", verb: "setKey" } },
|
|
32598
32797
|
{ id: "image.has_avatar_key", domain: "image", title: "Avatar-video key configured?", input: external_exports.object({}), mutation: "read", availability: "host", binding: { kind: "ipc", channel: "heygen", verb: "hasKey" } },
|
|
32798
|
+
// Whether the FREE brokered tier can serve an avatar video HERE — the user's own key is
|
|
32799
|
+
// the other half, above. Worth asking before drafting a script: the deployment may hold
|
|
32800
|
+
// no HeyGen account, and generate_avatar_video then fails at submit with the work done.
|
|
32801
|
+
{ id: "image.has_avatar_free_tier", domain: "image", title: "Free avatar-video tier available?", input: external_exports.object({}), mutation: "read", availability: "host", binding: { kind: "ipc", channel: "heygen", verb: "brokered" } },
|
|
32599
32802
|
{ id: "image.remove_provider_key", domain: "image", title: "Remove image provider key", input: external_exports.object({ provider_id: IMAGE_PROVIDER }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "removeKey" } },
|
|
32600
32803
|
{ id: "image.set_default_provider", domain: "image", title: "Set default image provider", input: external_exports.object({ provider_id: IMAGE_PROVIDER }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "setDefault" } },
|
|
32601
32804
|
{ id: "image.set_provider_model", domain: "image", title: "Set image provider model", input: external_exports.object({ provider_id: IMAGE_PROVIDER, model: external_exports.string() }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "setModel" } },
|
|
@@ -32760,6 +32963,134 @@ ${JSON.stringify(r, null, 2)}`
|
|
|
32760
32963
|
availability: "desktop",
|
|
32761
32964
|
binding: { kind: "command", command: "app.openStage" }
|
|
32762
32965
|
},
|
|
32966
|
+
// ── The presentation LIBRARY: authoring, not driving ──────────────────────────────────
|
|
32967
|
+
// Everything above drives a deck that is already running, and lives in the daemon because
|
|
32968
|
+
// a phone remote reaches it. These WRITE FILES, so they are 'desktop': the library is a
|
|
32969
|
+
// folder in the user's Documents, and only the desktop process can touch it.
|
|
32970
|
+
//
|
|
32971
|
+
// A deck is TSX — the same slide contract the app's own decks use — so the model authors
|
|
32972
|
+
// by writing files and then calling `validate_deck` until it comes back clean. That loop
|
|
32973
|
+
// is the whole design: without it the first sign of a stray bracket on slide 14 is a
|
|
32974
|
+
// blank rectangle at the front of a room.
|
|
32975
|
+
{
|
|
32976
|
+
id: "present.list_decks",
|
|
32977
|
+
domain: "present",
|
|
32978
|
+
title: "List presentations",
|
|
32979
|
+
input: external_exports.object({}),
|
|
32980
|
+
mutation: "read",
|
|
32981
|
+
availability: "desktop",
|
|
32982
|
+
binding: { kind: "ipc", channel: "decklib", verb: "list" }
|
|
32983
|
+
},
|
|
32984
|
+
{
|
|
32985
|
+
id: "present.create_deck",
|
|
32986
|
+
domain: "present",
|
|
32987
|
+
title: "Create a presentation",
|
|
32988
|
+
input: external_exports.object({
|
|
32989
|
+
title: external_exports.string().describe("What the presentation is called. Shown in the library and used for its folder name; keep the user's own wording and language."),
|
|
32990
|
+
description: external_exports.string().optional().describe("One line about what it is for."),
|
|
32991
|
+
theme: external_exports.record(external_exports.string(), external_exports.string()).optional().describe('CSS custom properties applied to every slide, e.g. { "--bg": "#FFFFFF", "--ink": "#16130F", "--accent": "#D97757" }.')
|
|
32992
|
+
}),
|
|
32993
|
+
mutation: "write",
|
|
32994
|
+
availability: "desktop",
|
|
32995
|
+
binding: { kind: "ipc", channel: "decklib", verb: "create" },
|
|
32996
|
+
summarize: (r) => `Created the presentation "${r?.title ?? ""}".`
|
|
32997
|
+
},
|
|
32998
|
+
{
|
|
32999
|
+
id: "present.write_slide",
|
|
33000
|
+
domain: "present",
|
|
33001
|
+
title: "Write a slide",
|
|
33002
|
+
input: external_exports.object({
|
|
33003
|
+
deck: external_exports.string().describe("The deck folder, exactly as `list_decks` or `create_deck` returned it (ends in .tessdeck)."),
|
|
33004
|
+
path: external_exports.string().describe('Path inside the presentation, e.g. "slides/03-pricing.tsx". Filename order IS slide order, so number the prefixes. Helper files may live anywhere in the package.'),
|
|
33005
|
+
source: external_exports.string().describe("The whole file. A slide exports `meta` ({ id, title, summary?, notes?, transition?, builds? }) and a default React component.")
|
|
33006
|
+
}),
|
|
33007
|
+
mutation: "write",
|
|
33008
|
+
availability: "desktop",
|
|
33009
|
+
binding: { kind: "ipc", channel: "decklib", verb: "writeFile" },
|
|
33010
|
+
summarize: (_r, i) => `Wrote ${i.path ?? "a slide"}.`
|
|
33011
|
+
},
|
|
33012
|
+
{
|
|
33013
|
+
id: "present.read_slide",
|
|
33014
|
+
domain: "present",
|
|
33015
|
+
title: "Read a slide",
|
|
33016
|
+
input: external_exports.object({
|
|
33017
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33018
|
+
path: external_exports.string().describe('Path inside the presentation, e.g. "slides/03-pricing.tsx".')
|
|
33019
|
+
}),
|
|
33020
|
+
mutation: "read",
|
|
33021
|
+
availability: "desktop",
|
|
33022
|
+
binding: { kind: "ipc", channel: "decklib", verb: "readFile" }
|
|
33023
|
+
},
|
|
33024
|
+
{
|
|
33025
|
+
id: "present.delete_slide",
|
|
33026
|
+
domain: "present",
|
|
33027
|
+
title: "Delete a slide",
|
|
33028
|
+
input: external_exports.object({
|
|
33029
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33030
|
+
path: external_exports.string().describe("Path inside the presentation.")
|
|
33031
|
+
}),
|
|
33032
|
+
mutation: "write",
|
|
33033
|
+
availability: "desktop",
|
|
33034
|
+
binding: { kind: "ipc", channel: "decklib", verb: "deleteFile" },
|
|
33035
|
+
summarize: (_r, i) => `Deleted ${i.path ?? "a slide"}.`
|
|
33036
|
+
},
|
|
33037
|
+
{
|
|
33038
|
+
id: "present.validate_deck",
|
|
33039
|
+
domain: "present",
|
|
33040
|
+
title: "Check a presentation",
|
|
33041
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33042
|
+
mutation: "read",
|
|
33043
|
+
availability: "desktop",
|
|
33044
|
+
binding: { kind: "ipc", channel: "decklib", verb: "validate" },
|
|
33045
|
+
summarize: (r) => typeof r === "string" ? r : "Checked the presentation."
|
|
33046
|
+
},
|
|
33047
|
+
{
|
|
33048
|
+
id: "present.set_deck_theme",
|
|
33049
|
+
domain: "present",
|
|
33050
|
+
title: "Set a presentation\u2019s theme",
|
|
33051
|
+
input: external_exports.object({
|
|
33052
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33053
|
+
theme: external_exports.record(external_exports.string(), external_exports.string()).describe(`CSS custom properties, e.g. { "--bg": "#0C0A14", "--ink": "#FFFFFF" }. Replaces the deck's current theme.`)
|
|
33054
|
+
}),
|
|
33055
|
+
mutation: "write",
|
|
33056
|
+
availability: "desktop",
|
|
33057
|
+
binding: { kind: "ipc", channel: "decklib", verb: "setTheme" },
|
|
33058
|
+
summarize: () => "Updated the presentation\u2019s theme."
|
|
33059
|
+
},
|
|
33060
|
+
{
|
|
33061
|
+
id: "present.add_asset",
|
|
33062
|
+
domain: "present",
|
|
33063
|
+
title: "Add an image to a presentation",
|
|
33064
|
+
input: external_exports.object({
|
|
33065
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33066
|
+
source_path: external_exports.string().describe("Absolute path of the file to copy in \u2014 a generated image, a photo, an audio clip."),
|
|
33067
|
+
name: external_exports.string().optional().describe("Filename to use inside the presentation.")
|
|
33068
|
+
}),
|
|
33069
|
+
mutation: "write",
|
|
33070
|
+
availability: "desktop",
|
|
33071
|
+
binding: { kind: "ipc", channel: "decklib", verb: "addAsset" },
|
|
33072
|
+
summarize: (r) => `Added ${typeof r === "string" ? r : "an asset"} to the presentation.`
|
|
33073
|
+
},
|
|
33074
|
+
{
|
|
33075
|
+
id: "present.open_deck",
|
|
33076
|
+
domain: "present",
|
|
33077
|
+
title: "Open a presentation",
|
|
33078
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33079
|
+
mutation: "write",
|
|
33080
|
+
availability: "desktop",
|
|
33081
|
+
binding: { kind: "ipc", channel: "decklib", verb: "open" },
|
|
33082
|
+
summarize: () => "Opened the presentation in Stage."
|
|
33083
|
+
},
|
|
33084
|
+
{
|
|
33085
|
+
id: "present.delete_deck",
|
|
33086
|
+
domain: "present",
|
|
33087
|
+
title: "Delete a presentation",
|
|
33088
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33089
|
+
mutation: "write",
|
|
33090
|
+
availability: "desktop",
|
|
33091
|
+
binding: { kind: "ipc", channel: "decklib", verb: "delete" },
|
|
33092
|
+
summarize: (_r, i) => `Deleted the presentation ${i.deck ?? ""}.`
|
|
33093
|
+
},
|
|
32763
33094
|
{
|
|
32764
33095
|
id: "present.end",
|
|
32765
33096
|
domain: "present",
|
|
@@ -32954,6 +33285,75 @@ var init_app_control_tools = __esm({
|
|
|
32954
33285
|
}
|
|
32955
33286
|
});
|
|
32956
33287
|
|
|
33288
|
+
// ../../packages/agent-core/dist/capabilities-doc.generated.js
|
|
33289
|
+
var CAPABILITIES_DOC;
|
|
33290
|
+
var init_capabilities_doc_generated = __esm({
|
|
33291
|
+
"../../packages/agent-core/dist/capabilities-doc.generated.js"() {
|
|
33292
|
+
"use strict";
|
|
33293
|
+
CAPABILITIES_DOC = '# Tesseract \u2014 what the product can do\n\nOne-page map of **every user-reachable capability**, derived from the 80 area briefs in\n[`functional-testing/`](functional-testing/). It is the source for the `tesseract_capabilities`\ntool, so the agent can answer "what can you do?" about *Tesseract*, not just about its own toolbelt.\n\n> Read this before telling a user something is or isn\'t possible. \xA718 lists what is deliberately\n> **not** built \u2014 promising any of it is the most common way to be wrong about this product.\n\n---\n\n## 1. What Tesseract is\n\nA desktop-first AI workspace: an always-on agent that can drive your machine, your browser and your\nfiles; plus a fleet layer that makes every machine you own reachable from any of them; plus a set of\ncreative, communication and security products built on the same transport. It ships as **eight\nseparate clients** and is not a single app.\n\n## 2. Clients (each a distinct product)\n\n| Client | What it is |\n|---|---|\n| **Desktop** (Electron, mac/Win/Linux) | The full product. Tab workspace \u2014 **no router**: a recursive split-pane tree of tab groups, **24 tab kinds**, **10 dockable panels** (dock left/right/bottom, float, detach), multi-window, native menu, command + search palettes (**31 stable command ids**), \u23181\u20130 tab assign/recall, per-machine keybinding overrides, memory governor + layout restore. |\n| **Web** (`dist-web`) | Same React renderer over a relay transport. **No local agent, no local engine** \u2014 it always runs on a remote host. Terminals are all remote and pinned to the opening host. Documented stubs: undo-delete, engines, runner configs, window resize; voice keys sit in `localStorage`. Always auth-gated. |\n| **Mobile** (Flutter, iOS/Android/macOS) | A **roaming client** \u2014 it never hosts an agent. Chat with streaming, team chat, present-follower, full password vault (incl. TOTP + native autofill), realtime voice, rdesk viewer, clipboard sync, push. Uniquely: **phone-as-host** (serve your photo library and files to your desktop) and a create-video screen. |\n| **CLI** `tesseract-agent` (npm) | Headless daemon, ~18 commands: `login/logout/whoami`, `run`, service `install/start/stop/restart/status/logs`, `link add`, `runner \u2026`, `net \u2026`, self-update. `--instance <id>` namespaces state dir, service name and device id. Docker-friendly (`login --token` then `run` as PID 1). |\n| **Browser extension** (Chrome MV3) | Claude sidebar (sessions, slash commands, todos, sources, DOM tree, run modes), element picker, vault/autofill popup with biometrics, QR pairing, fullpage + plan views. Talks to the daemon through a native-messaging companion host. |\n| **Remote Desktop** (`apps/rdesk`) | Slim standalone binary, ~\xBC the size \u2014 ships **no AI/browser payload**. Server/client/chooser roles, coexists with the full daemon (demotes itself to client rather than quitting). |\n| **Mesh** (`apps/mesh`) | Slim standalone binary for the private network only \u2014 "moves packets, not pixels". Create a mesh, enrol, list peers. No role chooser by design. |\n| **Thin installer** (Flutter, ~20\u201340 MB) | The default download. Resolves the release feed at run time, picks the arch-correct asset, streams + sha512-verifies, installs, launches. Version-agnostic. |\n\nPlus the **admin/operations console** (`admin.tesseract.dev`: gateway credentials, users and keys,\nerror inspector, remediation trigger, audit log) and the **landing site** with its waitlist.\n\n## 3. The agent\n\n- **Turn lifecycle**: stream, interrupt, rapid-follow-up auto-cancel (first seconds only), stall\n watchdog, orphan-turn recovery, token compaction, usage-limit handling, cost ledger per session.\n- **Run modes**: **5 permission modes \xD7 6 effort levels**, thinking budget, per-turn engine/model pick.\n Default permission mode is `bypassPermissions`.\n- **Interactive cards** (~9): permission request, plan review, elicitation, confirm, verification,\n user dialog, skill UI, archive password, unattended report. "Deny & stop" also aborts the turn.\n- **Block renderers** (~9): mission, subagent, report, sources, provenance, event, notice, surface,\n image grid \u2014 plus tool-run cards joined at render time with 6/8-line clamping.\n- **Composer** (~25 actions): attach, slash commands, @-mention, reverse search, screen-region\n capture, element picker, voice, undo-last-turn, queued-message reorder.\n- **Sessions**: list, search (one host-side search across every engine\'s stored conversations),\n resume, summarize, **fork**, merge, delete-message, keep-alive, focus; session mirror + transfer;\n share a conversation by unguessable capability token.\n- **Subsystems**: reinforced verification, plan splitter, narrator (live status strip, capped at 24\n model calls/turn), hook bus (9 events), option ratings, unattended mode.\n- **Also**: a playable **chess** surface (5 tools) and chat slash toys (`/shrug`, `/tableflip`, \u2026).\n\n## 4. Engines, runners, gateway\n\n- **4 engines \xD7 3 auth modes** (`oauth` / `apiKey` / `localCli`), a 24-capability engine matrix,\n engine + model swap mid-session (model/permission-mode reconcile live; effort/cwd/MCP/system-prompt\n force a respawn).\n- **Runner config pool** with rotation, cooldown and failover; auto-retry is bounded and only fires\n when the turn did no work.\n- **Provider gateway** \u2014 a credential-injecting reverse proxy, **19 routes** across AGENT (anthropic,\n openai, google-ai, groq, xai, deepseek, moonshot, openrouter, custom-openai, customer-litellm,\n azure-openai), EMBEDDING, SEARCH (serpapi), VIDEO (heygen, gemini), VOICE, MEDIA (klipy, unsplash,\n pexels). Virtual keys `tsk_live_*`, budgets, LiteLLM price map, spend ledger, credential pools with\n health-based failover that never crosses a category. Models are named the way their makers\n name them \u2014 `claude-sonnet-4-6`, `claude-haiku-4-5-20251001`, `gpt-6-astra`, `gpt-5.5`,\n `gpt-5.4-mini`, `gpt-5.4-nano`, `gemini-2.5-flash`, `gpt-image-2` ($0.10/image flat) \u2014 and a\n signed-in key may also name a model we do not host as `vendor/model`.\n- **Framework cross-product gate**: the user\'s self-updating `claude` CLI \xD7 the pinned Agent SDK,\n verified nightly across pinned CLI versions.\n\n## 5. Files, editors, viewers\n\n- **Finder-like browser**: list/grid/columns, breadcrumbs, bookmarks + OS favourites, **host\n switcher** (every op can be remote), new/rename (F2)/move/duplicate/cut-copy-paste/delete + undo,\n Get Info, send-to-machine, find-in-files, native drag in **and out** (macOS `NSFilePromiseProvider`\n \u2014 drag a not-yet-downloaded remote file to Finder).\n- **~20 typed viewers/editors**: Monaco source editor, PDF (view + edit), Word/docx, spreadsheets,\n presentations, markdown, data grid, hex, audio, video, font, HTML canvas, diff, info.\n- **Archives as folders**: ~20 formats (zip, 7z, tar, gz/bz2/xz/zst, rar, iso, wim, cab, cpio, lzh\u2026)\n browsed, extracted and **edited in place** from the same tree. `rar`/`iso`/`cab` are read-only.\n Encrypted archives prompt for a password and can remember it.\n- **Image editor**: layered canvas, 10 tools (marquee, lasso, move, crop, paint, eraser, fill,\n eyedropper, text, zoom), 25 rail controls, **200+ AI effect styles**, layers, adjust/resize, markup,\n and 3 AI ops (`prompt`/`inpaint`/`outpaint`), transparent-background output, animate\u2192video.\n- **Video editor**: EDL timeline (cut/trim/reorder/transitions/speed/crop/reframe/flip/reverse/colour\n effects/audio tracks), burned-in captions, **18 MCP tools** \u2014 probe, render, frame extract, silence\n detect, transcribe with diarization, extract/isolate audio, music generation, voice list/clone/TTS,\n avatars, caption export, effects, upscale (ffmpeg + local Real-ESRGAN free; fal-Topaz paid).\n- **Undo & time travel**: agent-driven **file rewind** (undo what a turn wrote), file-tree \u2318Z with a\n per-window trash, workspace snapshots and git checkpoints, canvas/design version history with\n diff-and-restore, and message deletion with uniform semantics across engines.\n- **Native inspectors**: **Flutter** widget inspector (tree, on-device tap-to-pick, properties,\n deterministic Dart source edits, hot reload) and **React Native** (source binding + AST edits).\n\n## 6. Create, Design Studio, Stage, Publish\n\n- **Create** \u2014 5 generative document formats (incl. infographic and poster), ~90 actions: outline\n ops, 10 insert kinds, card generation, AI layouts, export.\n- **Design Studio** \u2014 a 10-stage wizard (pick \u2192 launch/browse \u2192 preview \u2192 target \u2192 inspect \u2192 brief \u2192\n build \u2192 QA \u2192 deploy) over **254 templates across 19 industry verticals**, Figma import, in-studio\n theme/token editing.\n- **Stage** \u2014 presentation engine: decks, slides, transitions, **slide audio** (narration/music/sfx\n with music ducking under narration), a live assistant, presenter mode, zoom/blank. 8 present tools\n let the agent drive the deck; followers converge from absolute-state snapshots.\n- **Export**: PowerPoint (.pptx), deck and card export, PNG.\n- **Publish** \u2014 private/org/public visibility, server-rendered public pages on a 192-bit token, live\n data sources (SSRF-guarded), embeds; **community gallery** with explore/following/team/mine, like,\n follow and clone.\n- **Deploy** \u2014 one-click hosting to `*.tesseract.dev` in per-user hardened containers (cap-drop ALL,\n no-new-privileges, read-only, egress-locked), metered on compute/storage/egress. One of the few\n genuinely entitlement-gated features. A separate **per-user cloud agent** container is provisioned\n on demand so you have a machine in the fleet even with every laptop closed.\n\n## 7. Generative media\n\n| What | Notes |\n|---|---|\n| **Images** | 2 providers (OpenAI gpt-image-2, Google). Generate (4-up by default), edit, inpaint/outpaint, transparent background (inpaint + chroma-key). **$0.10/image**. Ungated, BYO key. |\n| **Stock images** | AI-ranked Unsplash/Pexels search as its own tab. Free tier, rate-limited. |\n| **Video** | Google Veo 3.1 \u2014 4/6/8s clips, 720p/1080p, 16:9 or 9:16, keyframe conditioning (first/last frame), native audio. Free on the bundled tier; otherwise cost-confirmed. Multi-scene storyboards chain clip-to-clip for longer videos. |\n| **Avatar video** | HeyGen talking presenter from a script. |\n| **Music / speech** | ElevenLabs music generation, TTS, and instant **voice cloning**. |\n| **Fonts & brand** | Prompt \u2192 AI glyph sheets \u2192 **vision QC** \u2192 vectorize \u2192 kerning/spacing \u2192 a real installable font. Plus logo/wordmark candidates, SVG lockups and a brand kit. Assembly/vectorize/build are local and free. |\n| **Trending effects** | One-tap video effects (hug/kiss, squish, bring-photo-to-life, age, anime restyle, 3D figurine, outfit change, consent-gated face-swap\u2026). |\n\n## 8. Voice\n\n- **3 realtime providers**: OpenAI Realtime, Gemini Live, ElevenLabs ConvAI \u2014 plus a non-realtime\n **STT\u2192LLM\u2192TTS pipeline cascade**. Audio goes **client\u2194provider direct**; the daemon only mints the\n ephemeral credential and runs the control loop.\n- Group calls, live captions, and the **\u2325Space voice widget**.\n- **Voice as a control modality**: the realtime model is the *operator*, Claude Code is the *worker*.\n It decomposes a spoken request into one small dispatched step at a time, all to the same agent\n session, and is explicitly forbidden from claiming an outcome the agent did not report \u2014 when\n unsure it dispatches a check. Its own screen view is a deliberately low-res ~1 fps grab.\n\n## 9. Computer control\n\n- **Two distinct MCP servers**: `tesseract-computer` (**26 tools** \u2014 raw control: move/click/drag/\n scroll/key/type, see_screen, read_text, read_ui (accessibility), clipboard, windows, apps, open\n url/path, notify, annotate, draw) and `tesseract-screen` (**15 tools** \u2014 a guided\n look \u2192 figure_out_next \u2192 perform_step \u2192 **verify** loop that can fail and retry).\n- Plus `tesseract-os-control`: processes, network, structured fs, AX tree + AX actions, preferred app\n and usage profile, screen overlays (arrow/bubble/highlight/text/popup/choice), and\n `request_user_input` / `confirm_action`.\n- **Click grounding** is AX-tree + a local Moondream vision sidecar (free); screenshots are\n Retina-aware and downscaled to point coordinates so clicks line up.\n- **Off by default** \u2014 `computerControlEnabled` must be turned on.\n- **\u2325Space co-pilot HUD** + **13 daemon-owned windows** (spotlight, pastebar, publisher, annotate,\n draw, overlay, input, choice, consent, control-bar, ai-cursor, rdesk call/client), the tray, screen-\n region capture with multi-display number flash, and `tesseract://` deep links. The HUD is\n deliberately **invisible to the AI\'s own screenshots**.\n\n## 10. Integrated browser\n\n- In-app browser tabs with a shared persist partition, per-tab zoom, OAuth popups, URL-safety and\n proxy routing.\n- **Agent control over CDP**: navigate, snapshot, screenshot (viewport + full page), click (synthetic\n and real trusted input), type, key, eval, cookies, raw CDP for any domain, buffered event draining.\n Drives the **user\'s real logged-in browser** via the companion extension, or the built-in engine.\n- **Inspectors**: DOM tree, properties, native inspector; markup pen; click-to-source (JSX elements\n resolve to their source line).\n- **6 Toolkit mission playbooks**: accessibility, GDPR/cookies, health, performance, SEO, UX review \u2014\n each configures, runs, and emits a structured report.\n- **`appbrowser` collaboration**: presence, cursors, comments and edits on a visible tab.\n\n## 11. Web search\n\n`serp_*` over **121 engines / 1,726 parameters**, ~19 tools grouped by family: web, news, images\n(incl. reverse-image and Google Lens), video (incl. YouTube transcripts), maps/local, shopping,\nmarketplaces (Amazon/eBay/Walmart/Home Depot/Zillow), travel (flights/hotels), places & reviews,\nacademic (Scholar/patents), jobs, finance & trends, app stores, ads transparency, social.\nBrokered free tier: **100 searches/month signed in, 10/month anonymous** \u2014 the only hard per-user\nquota in the product.\n\n## 12. Multi-machine\n\n- **Host registry & fleet**: every machine you sign into registers itself; pick one and run the turn\n there. Dual-role nodes are both client and host at once.\n- **Remote fs + terminals** over the relay (9 relayed channels: agent, signal, browser, frame, fs,\n term, editor, rdesk, present). A remote driver may only launch an enumerated interpreter.\n- **File Provider (macOS)**: remote machines appear as native **Finder locations** \u2014 browse, read,\n write, rename, move, Trash + Put Back, thumbnails, progress. Identity survives rename/move.\n- **Drops** \u2014 AirDrop-like sharing to your own devices or another account. E2E-sealed, blind fan-out\n (first device to accept wins; the sender never learns which), receive policies + receive codes,\n blocks and abuse reports that are deliberately **indistinguishable** from "nobody was there".\n- **Universal clipboard**: text/HTML/images fan out to your other machines; >512 KB syncs a thumbnail\n + reference and pulls the bytes on demand. A privacy gate blocks password-manager and secure-input\n content. Plus **paste history** (\u2318\u21E7V pastebar), clipboard over the rdesk channel, and mobile\n text-only sync.\n- **Peer-link**: agent\u2194agent direct transport with a 3-tier ladder (LAN TLS \u2192 observed public IP \u2192\n UDP hole-punch), cert-pinned, relayed only as a fallback.\n- **Mesh VPN**: own PKI with SAS verification, join tickets, recovery mnemonic, a policy bundle with a\n fail-closed freshness clock, an authenticated Noise data plane, disco/path selection, a 25-pair NAT\n punch matrix, and a privileged `netd` helper that **derives** every route itself (the IPC has no\n "add route" field, by design) with journal-based teardown after a crash or reboot.\n- **Remote desktop**: screen share and control. 3 grant paths (same-account registry, cross-account\n code, unattended password), 3 engines (native, VNC, RDP), display picker, quality, Ctrl+Alt+Del,\n in-session voice on the same peer connection, side chat, and a phone viewer.\n- **Present & collaboration**: a presenter drives followers across devices; join codes; live cursors,\n comments and captions.\n- **Co-view mirroring**: a second device with the same conversation open sees **26 allowlisted\n events**. Permission prompts are deliberately *not* mirrored \u2014 a card you can\'t answer is a dead\n button.\n- **Settings & session sync**: keys, tokens, active engine and model are account-wide; `localCli`\n paths are machine-local and must never cross. Plus continuous folder mirroring (active link).\n\n## 13. Team chat & conferencing\n\nSlack-class: spaces, categories, channels, DMs, threads, mentions, reactions, custom emoji, stickers,\nattachments, forum channels, pins, presence, search (Postgres **or** Elasticsearch), link unfurl,\nGIF/meme, bots + a bot API, incoming webhooks, automations, governance, retention and audit.\n**Huddles** over a self-hosted LiveKit SFU with captions and a summary posted back to the channel;\ntoken minting and webhooks work without the SFU, and captions still work when LiveKit is unconfigured.\n\n## 14. Vault (password manager)\n\nZero-knowledge, Argon2id + AES-GCM, server holds only opaque ciphertext. **5 item types** (logins,\npasskeys, payments, secure notes, personal info), ~28 daemon ops, **4 unlock paths** (master password,\ndevice, biometric, **QR from your phone**), sharing sealed to recipient device keys, transfer,\nimport/export (Chrome, Safari, zip), a generator, TOTP, the **macOS AutoFill provider**, and browser\nautofill through the extension.\n\n## 15. Extensions platform\n\nFamilies: **skills, code plugins, bundle plugins, MCP connectors** (3 transports: stdio/http/sse),\nplus **theme packs**. Marketplace discovery with a security verdict that gates install; enable/disable;\nper-extension encrypted secrets; updates; uninstall. Extensions contribute **tabs, panels, settings\npages, status items, menu items and reskins**. First-party skills are free; marketplace ones are\ngated \u2014 `plugins` is the one entitlement actually enforced.\n\n## 16. App Control \u2014 the AI operating Tesseract itself\n\n**144 capabilities across 19 domains** (`settings, navigation, engines, runners, runtimes,\nextensions, hosts, account, daemon, providers, image, voice, permissions, project, privacy, system,\nfonts, present, tour`), exposed as 2 meta-tools + one executor per domain, each input validated\nagainst its own schema. **There is no confirmation gate \u2014 actions happen immediately, by product\ndecision.**\n\n## 17. Platform\n\n- **Accounts**: invite-only (there is **no public sign-up**; Google sign-in on an unknown email is\n rejected), password + Google, password reset, device registration/claim/keys, a CLI device-code\n flow, and an offline-tolerance contract \u2014 only an explicit 401/403 signs you out.\n- **Plans**: `free`, `standard` (shown as **"Pro"**), `pro` (shown as **"Team"**) \u2014 17 feature flags,\n quotas on compute/storage/egress/video, seats, invites, orgs. Your effective plan is the best across\n every org you belong to.\n- **Missions, cron & unattended**: schedule agent turns that run with nobody present, with catch-up\n after downtime, background tasks and structured reports.\n- **Settings**: **23 sections, ~300 controls** \u2014 appearance, editor, general, runners, agent, voice,\n image editing, search, extensions, background tasks, account, team, sync, privacy, file drops,\n remote desktop, permissions, hooks (9 events), env, about, shortcuts (31 rebindable commands).\n- **Theming**: DTCG design tokens, theme packs with **8 independently switchable facets** (colors,\n shape, fonts, background, decorations, sounds, intro, extraCss) and a 3-entry-point **Safe Mode** to\n recover from a bad pack.\n- **Accessibility & motion**: light/dark \xD7 comfortable/compact density throughout, reduced-motion\n and sound-mute as separate switches, and labelled roles on every interactive element. Animation\n is a product requirement, not a preference \u2014 every show/hide, open/close and surface switch is\n animated (140\u2013220ms), and native unstyled controls are not used.\n- **OS permissions**: 7 tracked (microphone, camera, screen recording, full-disk access, accessibility,\n notifications, local network) with per-platform availability; three require a relaunch after grant.\n- **Observability**: crash/error reporting from 6 producers with separate crash and telemetry consent\n (**opt-out \u2014 on unless explicitly disabled**), fingerprinting and grouping, an error inspector, an\n alerting bridge, in-app issue submission, and a GDPR export-and-erase path.\n- **The always-on background service**: the desktop app *is* the daemon (merged process); the slim\n rdesk and mesh builds and the headless CLI keep the classic separate-service model, installed via\n launchd / systemd / Windows services. It self-heals silently, degrades from GUI to headless rather\n than dying, and only one daemon owns a machine at a time. This is why clipboard sync, remote\n access, scheduled turns and the \u2325Space HUD keep working with no app window open.\n- **Connectivity**: the relay is stateless and queues nothing \u2014 a dropped socket re-bootstraps rather\n than replaying. In-flight turns survive a disconnect and stay interruptible.\n- **Updates**: check \u2192 download \u2192 stage \u2192 apply \u2192 relaunch, with an external reaper, log rotation on\n version change and a What\'s New screen. System events (sleep/wake, lock, AC/battery, clock jump,\n displays, interfaces) drive recovery.\n\n## 18. Deliberately NOT built \u2014 do not promise these\n\n- **Create multiplayer co-editing / comments-in-Create** \u2014 deferred; the stores exist but are unwired.\n- **Marketplace** as a product \u2014 brainstorm only.\n- **Team chat**: voice messages, async video clips, keyword alerts, scheduled send, `/remind`, saved\n messages, guest/single-channel access, outgoing webhooks, AI catch-up/digest, public communities,\n nested threads, Block Kit, workflow builder, read receipts, E2E encryption for team chat.\n- **Create/Gamma parity gaps**: todo blocks, GIF/QR/illustrations, media library, form embeds, Google\n Slides export, theme gallery picker, share analytics, public generate API, custom domains, SEO\n toggle, password-protected publish, sites manager.\n- **Hosting**: the managed DB/auth/storage layer, secrets manager, git sync + 1-click Publish.\n- **Mobile**: file browsing, in-app browser, hosting an agent, rendering canvas/surface blocks.\n- **Web app**: undo-delete, local engines, runner configs, the errors panel, open/save-to-code for\n remote hosts.\n- **Mesh**: there is no VPN tunnel a user can turn on yet \u2014 PKI, protocol and data plane are built,\n route execution is not a shipped user feature. No Windows/macOS netd hosting.\n- **Other**: Homebrew formula, Chrome Web Store listing (the extension installs unpacked), Deepgram\n voice, Office (ZetaOffice) editing, AWS Bedrock and Google Vertex gateway routes, VNC clipboard,\n Wayland-specific clipboard handling, RN live widget tree (blocked upstream), the voice tutorial.\n\n## 19. Honest caveats\n\n- **Entitlements are almost entirely unenforced.** Only `plugins` is gated in production, and the\n desktop client is never gated at all. Both the API and the relay **fail open** on billing errors.\n- **Realtime voice has never run live against a provider** \u2014 treat first-run voice as unproven.\n- **HeyGen avatar video has no key configured** as shipped.\n- **The self-hosted web stack has no per-user data isolation** \u2014 auth there is a login wall over one\n shared workspace root.\n- `standard` = "Pro" and `pro` = "Team" \u2014 the plan id and the display name are inverted.\n';
|
|
33294
|
+
}
|
|
33295
|
+
});
|
|
33296
|
+
|
|
33297
|
+
// ../../packages/agent-core/dist/capabilities-tools.js
|
|
33298
|
+
import { tool as tool17 } from "@anthropic-ai/claude-agent-sdk";
|
|
33299
|
+
function capabilitySections(doc = CAPABILITIES_DOC) {
|
|
33300
|
+
const out = [];
|
|
33301
|
+
const re = /^## (\d+)\. (.+)$/gm;
|
|
33302
|
+
const heads = [];
|
|
33303
|
+
for (let m = re.exec(doc); m; m = re.exec(doc)) {
|
|
33304
|
+
heads.push({ n: Number(m[1]), title: m[2].trim(), at: m.index, end: re.lastIndex });
|
|
33305
|
+
}
|
|
33306
|
+
for (let i = 0; i < heads.length; i++) {
|
|
33307
|
+
const h = heads[i];
|
|
33308
|
+
const stop2 = i + 1 < heads.length ? heads[i + 1].at : doc.length;
|
|
33309
|
+
out.push({ n: h.n, title: h.title, body: doc.slice(h.at, stop2).trimEnd() });
|
|
33310
|
+
}
|
|
33311
|
+
return out;
|
|
33312
|
+
}
|
|
33313
|
+
function findSections(query2, doc = CAPABILITIES_DOC) {
|
|
33314
|
+
const secs = capabilitySections(doc);
|
|
33315
|
+
const q = query2.trim().toLowerCase();
|
|
33316
|
+
if (!q)
|
|
33317
|
+
return [];
|
|
33318
|
+
const asNum = Number(q.replace(/^§/, ""));
|
|
33319
|
+
if (Number.isInteger(asNum) && asNum > 0) {
|
|
33320
|
+
const hit = secs.find((s) => s.n === asNum);
|
|
33321
|
+
if (hit)
|
|
33322
|
+
return [hit];
|
|
33323
|
+
}
|
|
33324
|
+
const byTitle = secs.filter((s) => s.title.toLowerCase().includes(q));
|
|
33325
|
+
if (byTitle.length > 0)
|
|
33326
|
+
return byTitle;
|
|
33327
|
+
return secs.filter((s) => s.body.toLowerCase().includes(q));
|
|
33328
|
+
}
|
|
33329
|
+
function buildCapabilitiesTools() {
|
|
33330
|
+
const index = capabilitySections().map((s) => `${s.n}. ${s.title}`).join(" \xB7 ");
|
|
33331
|
+
return [
|
|
33332
|
+
tool17("tesseract_capabilities", prompt("tool.capabilities.tesseract_capabilities", { sections: index }), {
|
|
33333
|
+
section: external_exports.string().optional().describe('Optional filter: a section number ("12"), a title word ("voice", "vault", "media"), or any keyword to search the body ("rdesk", "clipboard", "figma"). Omit for the full map.')
|
|
33334
|
+
}, async (args) => {
|
|
33335
|
+
const q = args?.section?.trim();
|
|
33336
|
+
if (!q)
|
|
33337
|
+
return text10(CAPABILITIES_DOC);
|
|
33338
|
+
const hits = findSections(q);
|
|
33339
|
+
if (hits.length === 0) {
|
|
33340
|
+
return text10(`No section of Tesseract's capability map matches "${q}". Sections: ${index}. Call tesseract_capabilities with no arguments for the whole map.`);
|
|
33341
|
+
}
|
|
33342
|
+
return text10(hits.map((s) => s.body).join("\n\n"));
|
|
33343
|
+
})
|
|
33344
|
+
];
|
|
33345
|
+
}
|
|
33346
|
+
var text10;
|
|
33347
|
+
var init_capabilities_tools = __esm({
|
|
33348
|
+
"../../packages/agent-core/dist/capabilities-tools.js"() {
|
|
33349
|
+
"use strict";
|
|
33350
|
+
init_zod();
|
|
33351
|
+
init_prompts();
|
|
33352
|
+
init_capabilities_doc_generated();
|
|
33353
|
+
text10 = (t) => ({ content: [{ type: "text", text: t }] });
|
|
33354
|
+
}
|
|
33355
|
+
});
|
|
33356
|
+
|
|
32957
33357
|
// ../../packages/serpapi-core/dist/types.js
|
|
32958
33358
|
var init_types3 = __esm({
|
|
32959
33359
|
"../../packages/serpapi-core/dist/types.js"() {
|
|
@@ -33480,8 +33880,8 @@ function isAbort(e) {
|
|
|
33480
33880
|
const name = e?.name ?? "";
|
|
33481
33881
|
return name === "AbortError" || name === "TimeoutError" || /aborted|abort/i.test(String(e?.message ?? ""));
|
|
33482
33882
|
}
|
|
33483
|
-
function redactSecrets(
|
|
33484
|
-
let out =
|
|
33883
|
+
function redactSecrets(text13, secret) {
|
|
33884
|
+
let out = text13.replace(/((?:api_key|apikey|token|access_token|key)=)[^&\s"'<>]{6,}/gi, "$1***");
|
|
33485
33885
|
if (secret && secret.length >= 8)
|
|
33486
33886
|
out = out.split(secret).join("***");
|
|
33487
33887
|
return out;
|
|
@@ -33588,13 +33988,13 @@ var init_client = __esm({
|
|
|
33588
33988
|
*/
|
|
33589
33989
|
async searchMarkdown(engine, params, opts = {}) {
|
|
33590
33990
|
const url2 = await this.buildUrl(engine, params, { ...opts, output: "md" });
|
|
33591
|
-
const { res, text:
|
|
33991
|
+
const { res, text: text13, started: started2 } = await this.fetchWithRetry(url2, engine, opts, true);
|
|
33592
33992
|
this.opts.onUsage?.({ engine, cached: false, billed: true, ms: Date.now() - started2, status: res.status });
|
|
33593
|
-
const asError = messageFromBody(
|
|
33594
|
-
if (asError &&
|
|
33993
|
+
const asError = messageFromBody(text13) && redactSecrets(messageFromBody(text13), (await this.creds().catch(() => void 0))?.apiKey);
|
|
33994
|
+
if (asError && text13.trimStart().startsWith("{")) {
|
|
33595
33995
|
throw new SerpApiError(asError, classifySerpError(res.status, asError), { status: res.status, engine });
|
|
33596
33996
|
}
|
|
33597
|
-
return { markdown:
|
|
33997
|
+
return { markdown: text13 };
|
|
33598
33998
|
}
|
|
33599
33999
|
/**
|
|
33600
34000
|
* Follow a fully-formed SerpApi URL — specifically `serpapi_pagination.next`.
|
|
@@ -33632,8 +34032,8 @@ var init_client = __esm({
|
|
|
33632
34032
|
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, "locations.json");
|
|
33633
34033
|
u.searchParams.set("q", q);
|
|
33634
34034
|
u.searchParams.set("limit", String(Math.min(Math.max(1, limit), 10)));
|
|
33635
|
-
const { text:
|
|
33636
|
-
const body = JSON.parse(
|
|
34035
|
+
const { text: text13 } = await this.fetchWithRetry(u.toString(), "locations", {}, false);
|
|
34036
|
+
const body = JSON.parse(text13 || "[]");
|
|
33637
34037
|
return Array.isArray(body) ? body : [];
|
|
33638
34038
|
}
|
|
33639
34039
|
/** Retrieve a previously-run search by `search_metadata.id`. 31-day retention; also how you
|
|
@@ -33657,8 +34057,8 @@ var init_client = __esm({
|
|
|
33657
34057
|
throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
|
|
33658
34058
|
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.md`);
|
|
33659
34059
|
u.searchParams.set("api_key", apiKey);
|
|
33660
|
-
const { text:
|
|
33661
|
-
return { markdown:
|
|
34060
|
+
const { text: text13 } = await this.fetchWithRetry(u.toString(), "archive", {}, false);
|
|
34061
|
+
return { markdown: text13 };
|
|
33662
34062
|
}
|
|
33663
34063
|
/** Upload an image (≤500 KB, JPG/PNG/WebP) for use with Lens / reverse-image engines.
|
|
33664
34064
|
* The returned `image_id` expires after ~10 minutes. */
|
|
@@ -33757,9 +34157,9 @@ var init_client = __esm({
|
|
|
33757
34157
|
this.opts.onUsage?.({ engine, cached: false, billed, ms: Date.now() - started2, error: msg });
|
|
33758
34158
|
throw lastErr;
|
|
33759
34159
|
}
|
|
33760
|
-
const
|
|
34160
|
+
const text13 = await res.text();
|
|
33761
34161
|
if (!res.ok) {
|
|
33762
|
-
const bodyMsg = redactSecrets(messageFromBody(
|
|
34162
|
+
const bodyMsg = redactSecrets(messageFromBody(text13), secret);
|
|
33763
34163
|
const err2 = new SerpApiError(bodyMsg || `SerpApi ${engine} failed (${res.status}).`, classifySerpError(res.status, bodyMsg), { status: res.status, engine });
|
|
33764
34164
|
if (err2.retryable && attempt < maxRetries && Date.now() < deadline) {
|
|
33765
34165
|
lastErr = err2;
|
|
@@ -33769,7 +34169,7 @@ var init_client = __esm({
|
|
|
33769
34169
|
this.opts.onUsage?.({ engine, cached: false, billed, ms: Date.now() - started2, status: res.status, error: bodyMsg.slice(0, 200) });
|
|
33770
34170
|
throw err2;
|
|
33771
34171
|
}
|
|
33772
|
-
return { res, text:
|
|
34172
|
+
return { res, text: text13, started: started2 };
|
|
33773
34173
|
}
|
|
33774
34174
|
throw lastErr ?? new SerpApiError(`SerpApi ${engine} failed.`, "unknown", { engine });
|
|
33775
34175
|
}
|
|
@@ -33786,10 +34186,10 @@ var init_client = __esm({
|
|
|
33786
34186
|
if (hit)
|
|
33787
34187
|
this.cache.delete(key2);
|
|
33788
34188
|
}
|
|
33789
|
-
const { res, text:
|
|
34189
|
+
const { res, text: text13, started: started2 } = await this.fetchWithRetry(url2, engine, opts, billed);
|
|
33790
34190
|
let body;
|
|
33791
34191
|
try {
|
|
33792
|
-
body = JSON.parse(
|
|
34192
|
+
body = JSON.parse(text13);
|
|
33793
34193
|
} catch {
|
|
33794
34194
|
throw new SerpApiError(`SerpApi ${engine} returned a non-JSON body.`, "unknown", { status: res.status, engine });
|
|
33795
34195
|
}
|
|
@@ -34505,7 +34905,7 @@ var serpapi_tools_exports = {};
|
|
|
34505
34905
|
__export(serpapi_tools_exports, {
|
|
34506
34906
|
buildSerpTools: () => buildSerpTools
|
|
34507
34907
|
});
|
|
34508
|
-
import { tool as
|
|
34908
|
+
import { tool as tool18 } from "@anthropic-ai/claude-agent-sdk";
|
|
34509
34909
|
import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, statSync as statSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
34510
34910
|
import { basename as basename2 } from "node:path";
|
|
34511
34911
|
function imageKind(path6) {
|
|
@@ -34539,14 +34939,14 @@ function catalogOnce() {
|
|
|
34539
34939
|
}
|
|
34540
34940
|
function buildSerpTools(deps) {
|
|
34541
34941
|
const tools = [];
|
|
34542
|
-
tools.push(
|
|
34942
|
+
tools.push(tool18("serp_find", 'Search the SerpApi catalog of 121 search engines to find which one answers a question. Describe what you want in plain language ("hotel reviews", "who is advertising against my brand", "stock price") \u2014 engine ids are not guessable, so START HERE unless you already know the engine. Returns ranked engines with the family tool that runs them and their required parameters.', {
|
|
34543
34943
|
query: external_exports.string().describe("What you are trying to find out, in plain language."),
|
|
34544
34944
|
family: external_exports.string().optional().describe(`Restrict to one family: ${Object.keys(SERP_FAMILIES).join(", ")}.`),
|
|
34545
34945
|
limit: external_exports.number().int().min(1).max(30).optional().describe("How many engines to return (default 8).")
|
|
34546
34946
|
}, async (a) => {
|
|
34547
34947
|
const { query: query2, family, limit } = a ?? {};
|
|
34548
34948
|
if (family && !(family in SERP_FAMILIES)) {
|
|
34549
|
-
return
|
|
34949
|
+
return text11(`Unknown family "${family}". Valid families: ${Object.keys(SERP_FAMILIES).join(", ")}.`, true);
|
|
34550
34950
|
}
|
|
34551
34951
|
const r = await findEngines(query2 ?? "", catalogOnce().filter((e) => !UNAVAILABLE.has(e.id)), {
|
|
34552
34952
|
limit,
|
|
@@ -34561,7 +34961,7 @@ function buildSerpTools(deps) {
|
|
|
34561
34961
|
next: "Call serp_describe with an engine id for its full parameter list, then run it with the named family tool."
|
|
34562
34962
|
});
|
|
34563
34963
|
}));
|
|
34564
|
-
tools.push(
|
|
34964
|
+
tools.push(tool18("serp_describe", "Describe one or more SerpApi engines in full: every parameter with its meaning, which are required, allowed values, how the engine paginates, and which result keys it returns. Call this before running an engine whose parameters you are unsure about.", {
|
|
34565
34965
|
engines: external_exports.array(external_exports.string()).min(1).max(MAX_DESCRIBE_ENGINES).describe(`Engine ids, e.g. ["google_hotels", "google_maps"]. At most ${MAX_DESCRIBE_ENGINES} per call \u2014 a full schema is thousands of tokens, so ask for the ones you are actually about to use.`),
|
|
34566
34966
|
group: external_exports.string().optional().describe('Only describe parameters in this registry group (e.g. "search_query", "localization", "advanced_filters"), to keep the answer short.')
|
|
34567
34967
|
}, async (a) => {
|
|
@@ -34606,10 +35006,10 @@ function buildSerpTools(deps) {
|
|
|
34606
35006
|
}
|
|
34607
35007
|
return json2(out);
|
|
34608
35008
|
}));
|
|
34609
|
-
tools.push(
|
|
35009
|
+
tools.push(tool18("serp_account", "Check that SerpApi is configured and how many searches remain this month. This call is free and never consumes a search credit. Call it before a long series of searches, or when a search fails with a quota error.", {}, async () => {
|
|
34610
35010
|
const st = await deps.status();
|
|
34611
35011
|
if (!st.configured)
|
|
34612
|
-
return
|
|
35012
|
+
return text11(NO_KEY, true);
|
|
34613
35013
|
try {
|
|
34614
35014
|
const acct = await deps.client.account();
|
|
34615
35015
|
return json2({
|
|
@@ -34625,10 +35025,10 @@ function buildSerpTools(deps) {
|
|
|
34625
35025
|
...st.session ? { this_session: st.session } : {}
|
|
34626
35026
|
});
|
|
34627
35027
|
} catch (e) {
|
|
34628
|
-
return
|
|
35028
|
+
return text11(`Could not read the SerpApi account: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34629
35029
|
}
|
|
34630
35030
|
}));
|
|
34631
|
-
tools.push(
|
|
35031
|
+
tools.push(tool18("serp_locations", 'Resolve a place name to the canonical `location` string Google\'s engines expect (e.g. "Austin" \u2192 "Austin, Texas, United States"). Free \u2014 it does not consume a search credit. Use it before passing `location` to a Google engine; an unrecognised location is silently ignored and you get results for the wrong place.', {
|
|
34632
35032
|
query: external_exports.string().describe('Place name to resolve, e.g. "Chisinau" or "Austin".'),
|
|
34633
35033
|
limit: external_exports.number().int().min(1).max(10).optional().describe("Maximum matches (SerpApi caps this at 10).")
|
|
34634
35034
|
}, async (a) => {
|
|
@@ -34637,10 +35037,10 @@ function buildSerpTools(deps) {
|
|
|
34637
35037
|
const hits = await deps.client.locations(query2, limit ?? 5);
|
|
34638
35038
|
return json2(hits.map((h) => ({ canonical_name: h.canonical_name, country: h.country_code, type: h.target_type, reach: h.reach })));
|
|
34639
35039
|
} catch (e) {
|
|
34640
|
-
return
|
|
35040
|
+
return text11(`Location lookup failed: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34641
35041
|
}
|
|
34642
35042
|
}));
|
|
34643
|
-
tools.push(
|
|
35043
|
+
tools.push(tool18("serp_archive", "Re-read a search that was already run, by its `search_id` (returned as `_search_id` on every result, and by a `submit_async` submission). FREE \u2014 retrieval never re-runs the search and never spends a credit, and SerpApi keeps results for 31 days. Use it to collect an async submission, to re-read a large result you truncated, or to get the markdown rendering of something you already fetched as JSON \u2014 all without paying again.", {
|
|
34644
35044
|
search_id: external_exports.string().describe("The id from `_search_id`, or from a `submit_async` submission."),
|
|
34645
35045
|
format: external_exports.enum(["json", "markdown"]).optional().describe("`json` (default) is structured; `markdown` is roughly half the tokens but carries no chaining tokens."),
|
|
34646
35046
|
max_results: external_exports.number().int().min(1).max(100).optional().describe("How many items to keep per result list before truncating (default 10).")
|
|
@@ -34648,50 +35048,50 @@ function buildSerpTools(deps) {
|
|
|
34648
35048
|
const { search_id, format, max_results } = a ?? {};
|
|
34649
35049
|
const st = await deps.status();
|
|
34650
35050
|
if (!st.configured)
|
|
34651
|
-
return
|
|
35051
|
+
return text11(NO_KEY, true);
|
|
34652
35052
|
try {
|
|
34653
35053
|
if (format === "markdown") {
|
|
34654
35054
|
const { markdown } = await deps.client.archiveMarkdown(search_id);
|
|
34655
|
-
return
|
|
35055
|
+
return text11(markdown);
|
|
34656
35056
|
}
|
|
34657
35057
|
const body = await deps.client.archive(search_id);
|
|
34658
35058
|
const status2 = body.search_metadata?.status;
|
|
34659
35059
|
if (status2 && status2 !== "Success") {
|
|
34660
|
-
return
|
|
35060
|
+
return text11(`Search ${search_id} is ${status2}. This call was free \u2014 call serp_archive again in a moment.`);
|
|
34661
35061
|
}
|
|
34662
35062
|
return json2(compactResponse(body, { maxResults: max_results ?? 10 }));
|
|
34663
35063
|
} catch (e) {
|
|
34664
|
-
return
|
|
35064
|
+
return text11(`Could not read search ${search_id}: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34665
35065
|
}
|
|
34666
35066
|
}));
|
|
34667
|
-
tools.push(
|
|
35067
|
+
tools.push(tool18("serp_upload_image", "Upload a local image and get back an `image_id` for the engines that search BY an image rather than by text \u2014 `google_lens`, `google_reverse_image`, `bing_reverse_image`, `yandex_images`. Free; it spends no search credit. The id expires after about ten minutes, so upload immediately before the search that uses it. SerpApi accepts JPG, PNG and WebP up to 500 KB.", {
|
|
34668
35068
|
path: external_exports.string().describe("Absolute path to the image file on this machine.")
|
|
34669
35069
|
}, async (a) => {
|
|
34670
35070
|
const { path: path6 } = a ?? {};
|
|
34671
35071
|
const st = await deps.status();
|
|
34672
35072
|
if (!st.configured)
|
|
34673
|
-
return
|
|
35073
|
+
return text11(NO_KEY, true);
|
|
34674
35074
|
let bytes3;
|
|
34675
35075
|
try {
|
|
34676
35076
|
const size = statSync3(path6).size;
|
|
34677
35077
|
if (size === 0)
|
|
34678
|
-
return
|
|
35078
|
+
return text11(`${path6} is empty.`, true);
|
|
34679
35079
|
if (size > MAX_IMAGE_BYTES) {
|
|
34680
|
-
return
|
|
35080
|
+
return text11(`${path6} is ${Math.round(size / 1024)} KB; SerpApi accepts images up to 500 KB. Resize it first.`, true);
|
|
34681
35081
|
}
|
|
34682
35082
|
const kind = imageKind(path6);
|
|
34683
35083
|
if (!kind)
|
|
34684
|
-
return
|
|
35084
|
+
return text11(`${path6} is not a JPEG, PNG or WebP image \u2014 those are the formats SerpApi accepts, and this tool only uploads images.`, true);
|
|
34685
35085
|
bytes3 = readFileSync6(path6);
|
|
34686
35086
|
} catch (e) {
|
|
34687
|
-
return
|
|
35087
|
+
return text11(`Could not read ${path6}: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34688
35088
|
}
|
|
34689
35089
|
try {
|
|
34690
35090
|
const { image_id } = await deps.client.uploadImage(bytes3, basename2(path6));
|
|
34691
|
-
return
|
|
35091
|
+
return text11(`image_id: ${image_id}
|
|
34692
35092
|
Pass it as the image parameter of a reverse-image engine (google_lens uses \`url\`; call serp_describe for the exact field). It expires in about ten minutes.`);
|
|
34693
35093
|
} catch (e) {
|
|
34694
|
-
return
|
|
35094
|
+
return text11(`Image upload failed: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34695
35095
|
}
|
|
34696
35096
|
}));
|
|
34697
35097
|
for (const [family, info] of Object.entries(SERP_FAMILIES)) {
|
|
@@ -34701,7 +35101,7 @@ Pass it as the image parameter of a reverse-image engine (google_lens uses \`url
|
|
|
34701
35101
|
const ids = [...engines2];
|
|
34702
35102
|
const listing = engines2.map((id) => `${id} \u2014 ${ENGINE_INFO[id]?.purpose ?? ""}`).join("; ");
|
|
34703
35103
|
const trapped = engines2.filter((id) => ENGINE_INFO[id]?.traps?.length);
|
|
34704
|
-
tools.push(
|
|
35104
|
+
tools.push(tool18(info.tool, `${info.blurb} Pick an \`engine\` and pass its \`params\` (use serp_describe for the exact fields, or serp_find if you are not sure which engine). Each call spends one paid search credit. Engines: ${listing}${trapped.length ? ` \u2014 QUIRKS (serp_describe first): ${trapped.join(", ")}. Some reject the call; others accept a parameter and ignore it, returning confident results for the wrong place.` : ""}`, {
|
|
34705
35105
|
engine: external_exports.enum(ids).describe("Which engine to run."),
|
|
34706
35106
|
params: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("The engine's own parameters. Names differ per engine \u2014 Yahoo uses `p`, Yandex `text`, Naver `query`, Amazon `k`, eBay `_nkw`. Call serp_describe if unsure."),
|
|
34707
35107
|
...PAGE_ARGS,
|
|
@@ -34716,13 +35116,13 @@ Pass it as the image parameter of a reverse-image engine (google_lens uses \`url
|
|
|
34716
35116
|
async function runEngine(deps, args) {
|
|
34717
35117
|
const st = await deps.status();
|
|
34718
35118
|
if (!st.configured)
|
|
34719
|
-
return
|
|
35119
|
+
return text11(NO_KEY, true);
|
|
34720
35120
|
const spec = SERP_SPEC.engines[args.engine];
|
|
34721
35121
|
if (!spec)
|
|
34722
|
-
return
|
|
35122
|
+
return text11(`Unknown engine "${args.engine}". Call serp_find to locate the right one.`, true);
|
|
34723
35123
|
const info = ENGINE_INFO[args.engine];
|
|
34724
35124
|
if (info?.status) {
|
|
34725
|
-
return
|
|
35125
|
+
return text11(`\`${args.engine}\` is ${info.status.state} and cannot be used: ${info.status.detail} No credit was spent. ${info.purpose}`, true);
|
|
34726
35126
|
}
|
|
34727
35127
|
const strategy = pageStrategy(spec);
|
|
34728
35128
|
const rawParams = { ...args.params ?? {} };
|
|
@@ -34737,7 +35137,7 @@ async function runEngine(deps, args) {
|
|
|
34737
35137
|
v.warnings.push(`Both \`page_size\` (${args.page_size}) and \`${sizeParam}\` (${explicitSize}) were given; \`page_size\` wins.`);
|
|
34738
35138
|
}
|
|
34739
35139
|
if (!v.ok) {
|
|
34740
|
-
return
|
|
35140
|
+
return text11(`Cannot run \`${args.engine}\` \u2014 no credit spent.
|
|
34741
35141
|
${v.errors.map((e) => `\u2022 ${e}`).join("\n")}
|
|
34742
35142
|
|
|
34743
35143
|
Call serp_describe({engines:["${args.engine}"]}) for the full parameter list.`, true);
|
|
@@ -34755,8 +35155,8 @@ Call serp_describe({engines:["${args.engine}"]}) for the full parameter list.`,
|
|
|
34755
35155
|
const submitted = await deps.client.search(args.engine, { ...v.params, ...paging }, opts);
|
|
34756
35156
|
const id = submitted.search_metadata?.id;
|
|
34757
35157
|
if (!id)
|
|
34758
|
-
return
|
|
34759
|
-
return
|
|
35158
|
+
return text11(`\`${args.engine}\` was submitted but SerpApi returned no search id, so the result cannot be collected. Re-run it without submit_async.`, true);
|
|
35159
|
+
return text11(`Submitted \`${args.engine}\` \u2014 search_id: ${id}
|
|
34760
35160
|
The credit is already spent. Collect it with serp_archive({ search_id: "${id}" }); that call is free, so retry it until the status is Success.`);
|
|
34761
35161
|
}
|
|
34762
35162
|
if (args.format === "markdown") {
|
|
@@ -34764,7 +35164,7 @@ The credit is already spent. Collect it with serp_archive({ search_id: "${id}" }
|
|
|
34764
35164
|
const warn = v.warnings.length ? `${v.warnings.map((w) => `\u26A0 ${w}`).join("\n")}
|
|
34765
35165
|
|
|
34766
35166
|
` : "";
|
|
34767
|
-
return
|
|
35167
|
+
return text11(`${warn}${markdown}`);
|
|
34768
35168
|
}
|
|
34769
35169
|
const body = await deps.client.search(args.engine, { ...v.params, ...paging }, opts);
|
|
34770
35170
|
const compact2 = compactResponse(body, { maxResults: args.max_results ?? 10 });
|
|
@@ -34775,27 +35175,27 @@ The credit is already spent. Collect it with serp_archive({ search_id: "${id}" }
|
|
|
34775
35175
|
if (body._page?.hasNext && supportsPaging(spec)) {
|
|
34776
35176
|
parts.push(body._page.cursor ? `More results available \u2014 call again with cursor: "${body._page.cursor}".` : `More results available \u2014 call again with page: ${(args.page ?? 1) + 1}.`);
|
|
34777
35177
|
}
|
|
34778
|
-
return
|
|
35178
|
+
return text11(parts.join("\n\n"));
|
|
34779
35179
|
} catch (e) {
|
|
34780
35180
|
const msg = e instanceof Error ? e.message : String(e);
|
|
34781
|
-
return
|
|
35181
|
+
return text11(`\`${args.engine}\` failed: ${msg}`, true);
|
|
34782
35182
|
}
|
|
34783
35183
|
}
|
|
34784
|
-
var
|
|
35184
|
+
var text11, json2, UNAVAILABLE, MAX_DESCRIBE_ENGINES, MAX_PARAM_DESC, clip, MAX_IMAGE_BYTES, NO_KEY, PAGE_ARGS, OUTPUT_ARGS, cachedCatalog, brief;
|
|
34785
35185
|
var init_serpapi_tools = __esm({
|
|
34786
35186
|
"../../packages/agent-core/dist/serpapi/serpapi-tools.js"() {
|
|
34787
35187
|
"use strict";
|
|
34788
35188
|
init_zod();
|
|
34789
35189
|
init_dist4();
|
|
34790
|
-
|
|
35190
|
+
text11 = (t, isError = false) => ({
|
|
34791
35191
|
content: [{ type: "text", text: t }],
|
|
34792
35192
|
...isError ? { isError: true } : {}
|
|
34793
35193
|
});
|
|
34794
|
-
json2 = (v) =>
|
|
35194
|
+
json2 = (v) => text11(JSON.stringify(v, null, 2));
|
|
34795
35195
|
UNAVAILABLE = new Set(UNAVAILABLE_ENGINES);
|
|
34796
35196
|
MAX_DESCRIBE_ENGINES = 3;
|
|
34797
35197
|
MAX_PARAM_DESC = 400;
|
|
34798
|
-
clip = (
|
|
35198
|
+
clip = (text13, full) => !full && text13 && text13.length > MAX_PARAM_DESC ? `${text13.slice(0, MAX_PARAM_DESC)}\u2026 (truncated \u2014 ask for this engine on its own for the full text)` : text13;
|
|
34799
35199
|
MAX_IMAGE_BYTES = 500 * 1024;
|
|
34800
35200
|
NO_KEY = "SerpApi is not configured. Ask the user to add a SerpApi key in Settings \u2192 Search, or to sign in to use the bundled free tier.";
|
|
34801
35201
|
PAGE_ARGS = {
|
|
@@ -34822,13 +35222,13 @@ var init_serpapi_tools = __esm({
|
|
|
34822
35222
|
});
|
|
34823
35223
|
|
|
34824
35224
|
// ../../packages/agent-core/dist/report-tools.js
|
|
34825
|
-
import { tool as
|
|
35225
|
+
import { tool as tool19 } from "@anthropic-ai/claude-agent-sdk";
|
|
34826
35226
|
function slug(s) {
|
|
34827
35227
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "mission";
|
|
34828
35228
|
}
|
|
34829
35229
|
function buildReportTools(deps) {
|
|
34830
35230
|
return [
|
|
34831
|
-
|
|
35231
|
+
tool19("emit_report", prompt("tool.report.emit_report"), {
|
|
34832
35232
|
id: external_exports.string().optional().describe("Stable report id to UPDATE an existing report; omit on the first call to create one."),
|
|
34833
35233
|
playbookId: external_exports.string().describe("The playbook id this report belongs to."),
|
|
34834
35234
|
title: external_exports.string().describe("Report title (usually the playbook name)."),
|
|
@@ -34882,10 +35282,10 @@ var init_report_tools = __esm({
|
|
|
34882
35282
|
});
|
|
34883
35283
|
|
|
34884
35284
|
// ../../packages/agent-core/dist/interactive-ui-tools.js
|
|
34885
|
-
import { tool as
|
|
35285
|
+
import { tool as tool20 } from "@anthropic-ai/claude-agent-sdk";
|
|
34886
35286
|
function buildInteractiveUiTools(deps) {
|
|
34887
35287
|
return [
|
|
34888
|
-
|
|
35288
|
+
tool20("ask_form", prompt("tool.interactive-ui.ask_form"), {
|
|
34889
35289
|
title: external_exports.string().describe("Form heading (plain language)."),
|
|
34890
35290
|
description: external_exports.string().optional().describe("Short explanation shown above the fields."),
|
|
34891
35291
|
submitLabel: external_exports.string().optional().describe('Submit button label (default "Submit").'),
|
|
@@ -34899,7 +35299,7 @@ function buildInteractiveUiTools(deps) {
|
|
|
34899
35299
|
return { content: [{ type: "text", text: `The user submitted the form:
|
|
34900
35300
|
${JSON.stringify(res.values ?? {}, null, 2)}` }] };
|
|
34901
35301
|
}),
|
|
34902
|
-
|
|
35302
|
+
tool20("present_choices", prompt("tool.interactive-ui.present_choices"), {
|
|
34903
35303
|
title: external_exports.string().describe("The question / heading."),
|
|
34904
35304
|
description: external_exports.string().optional(),
|
|
34905
35305
|
options: external_exports.array(choiceOption).min(1),
|
|
@@ -34912,7 +35312,7 @@ ${JSON.stringify(res.values ?? {}, null, 2)}` }] };
|
|
|
34912
35312
|
return { content: [{ type: "text", text: "The user cancelled the choice (nothing selected)." }] };
|
|
34913
35313
|
return { content: [{ type: "text", text: `The user selected: ${JSON.stringify(res.selected ?? [])}` }] };
|
|
34914
35314
|
}),
|
|
34915
|
-
|
|
35315
|
+
tool20("update_progress", prompt("tool.interactive-ui.update_progress"), {
|
|
34916
35316
|
stages: external_exports.array(external_exports.object({
|
|
34917
35317
|
label: external_exports.string(),
|
|
34918
35318
|
status: external_exports.enum(["pending", "active", "done"])
|
|
@@ -35037,8 +35437,8 @@ async function exportSession(sessionId, fromCwd) {
|
|
|
35037
35437
|
function escapeRe(s) {
|
|
35038
35438
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
35039
35439
|
}
|
|
35040
|
-
function rekey(
|
|
35041
|
-
return
|
|
35440
|
+
function rekey(text13, fromCwd, toCwd) {
|
|
35441
|
+
return text13.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
|
|
35042
35442
|
}
|
|
35043
35443
|
async function importSession(exp, toCwd) {
|
|
35044
35444
|
const destDir = sessionDir(toCwd);
|
|
@@ -35311,13 +35711,13 @@ var init_narrator = __esm({
|
|
|
35311
35711
|
prompt("side-llm.narrator.activity", { activity }),
|
|
35312
35712
|
prompt("side-llm.narrator.ask")
|
|
35313
35713
|
].filter(Boolean).join("\n\n");
|
|
35314
|
-
const
|
|
35315
|
-
if (
|
|
35316
|
-
s.lastText =
|
|
35317
|
-
s.log.push(
|
|
35714
|
+
const text13 = (await cfg2.complete({ system, prompt: promptText, maxTokens: 48 }))?.trim().replace(/^["']|["']$/g, "");
|
|
35715
|
+
if (text13 && text13 !== s.lastText) {
|
|
35716
|
+
s.lastText = text13;
|
|
35717
|
+
s.log.push(text13);
|
|
35318
35718
|
if (s.log.length > LOG_CAP)
|
|
35319
35719
|
s.log.shift();
|
|
35320
|
-
this.emit(id,
|
|
35720
|
+
this.emit(id, text13, cfg2.engineLabel);
|
|
35321
35721
|
}
|
|
35322
35722
|
} catch {
|
|
35323
35723
|
} finally {
|
|
@@ -35459,15 +35859,15 @@ function recordVerificationDecision(entry) {
|
|
|
35459
35859
|
function readUnattendedDecisions(limit = 200, opts) {
|
|
35460
35860
|
const out = [];
|
|
35461
35861
|
for (const file2 of [rolledPath(), unattendedLogPath()]) {
|
|
35462
|
-
let
|
|
35862
|
+
let text13;
|
|
35463
35863
|
try {
|
|
35464
35864
|
if (!existsSync2(file2))
|
|
35465
35865
|
continue;
|
|
35466
|
-
|
|
35866
|
+
text13 = readFileSync7(file2, "utf8");
|
|
35467
35867
|
} catch {
|
|
35468
35868
|
continue;
|
|
35469
35869
|
}
|
|
35470
|
-
for (const line of
|
|
35870
|
+
for (const line of text13.split("\n")) {
|
|
35471
35871
|
if (!line.trim())
|
|
35472
35872
|
continue;
|
|
35473
35873
|
try {
|
|
@@ -36230,10 +36630,10 @@ function assistantContextOverflow(content, isContextOverflowFn) {
|
|
|
36230
36630
|
const blocks = content;
|
|
36231
36631
|
if (blocks.some((block2) => block2?.type !== "text"))
|
|
36232
36632
|
return false;
|
|
36233
|
-
const
|
|
36234
|
-
if (!
|
|
36633
|
+
const text13 = blocks.map((b) => typeof b.text === "string" ? b.text : "").join("\n").trim();
|
|
36634
|
+
if (!text13 || text13.length > 400)
|
|
36235
36635
|
return false;
|
|
36236
|
-
return isContextOverflowFn(
|
|
36636
|
+
return isContextOverflowFn(text13);
|
|
36237
36637
|
}
|
|
36238
36638
|
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE;
|
|
36239
36639
|
var init_context_recovery = __esm({
|
|
@@ -36343,8 +36743,8 @@ function pendingQueueRows(rows) {
|
|
|
36343
36743
|
}
|
|
36344
36744
|
return keep;
|
|
36345
36745
|
}
|
|
36346
|
-
function stripHostText(
|
|
36347
|
-
return stripRunDirective(
|
|
36746
|
+
function stripHostText(text13) {
|
|
36747
|
+
return stripRunDirective(text13).trimEnd();
|
|
36348
36748
|
}
|
|
36349
36749
|
function rejectedByApi(b) {
|
|
36350
36750
|
if (!b || typeof b !== "object")
|
|
@@ -36653,10 +37053,10 @@ function filterHistory(transcript, opts = {}) {
|
|
|
36653
37053
|
const parent = resolveParent2(r.parentUuid);
|
|
36654
37054
|
out.push(JSON.stringify(parent === (r.parentUuid ?? null) ? r : { ...r, parentUuid: parent }));
|
|
36655
37055
|
}
|
|
36656
|
-
const
|
|
37056
|
+
const text13 = out.join("\n") + (out.length ? "\n" : "");
|
|
36657
37057
|
stats.rowsOut = out.length;
|
|
36658
|
-
stats.bytesOut = Buffer.byteLength(
|
|
36659
|
-
return { text:
|
|
37058
|
+
stats.bytesOut = Buffer.byteLength(text13, "utf8");
|
|
37059
|
+
return { text: text13, stats, spills };
|
|
36660
37060
|
}
|
|
36661
37061
|
var DEFAULT_DROP_TYPES, DEFAULT_KEEP_LAST_TYPES, DEFAULT_KEEP_SYSTEM_SUBTYPES, DEFAULT_KEEP_LAST_ATTACHMENT, DEFAULT_OFFLOAD_RECENT_CALLS, MAX_INLINE_INPUT_BYTES, OFFLOAD_MARK, human;
|
|
36662
37062
|
var init_history_filter = __esm({
|
|
@@ -36689,9 +37089,9 @@ function archiveMetaPath(transcript) {
|
|
|
36689
37089
|
function offloadDirFor(transcript) {
|
|
36690
37090
|
return transcript.replace(/\.jsonl$/, "") + ".offload";
|
|
36691
37091
|
}
|
|
36692
|
-
function contentBytes(
|
|
37092
|
+
function contentBytes(text13, liveOnly = true) {
|
|
36693
37093
|
let n = 0;
|
|
36694
|
-
const all =
|
|
37094
|
+
const all = text13.split("\n");
|
|
36695
37095
|
for (const line of liveOnly ? all.slice(liveRegionStart(all)) : all) {
|
|
36696
37096
|
if (!line.trim())
|
|
36697
37097
|
continue;
|
|
@@ -36750,9 +37150,9 @@ async function slimTranscriptFile(transcript, opts = {}) {
|
|
|
36750
37150
|
const liveText = await readFile4(transcript, "utf8");
|
|
36751
37151
|
const liveLines = liveText.split("\n").filter((l) => l.trim().length > 0);
|
|
36752
37152
|
const offloadDir = offloadDirFor(transcript);
|
|
36753
|
-
const { text:
|
|
37153
|
+
const { text: text13, stats, spills } = filterHistory(liveText, { spillDir: offloadDir, ...opts });
|
|
36754
37154
|
const before = contentBytes(liveText);
|
|
36755
|
-
const after = contentBytes(
|
|
37155
|
+
const after = contentBytes(text13);
|
|
36756
37156
|
const changed = stats.droppedRows > 0 || stats.droppedThinking > 0 || stats.droppedToolUse > 0 || stats.droppedToolResult > 0 || stats.offloaded > 0 || stats.supersededAttachments > 0 || stats.repairedBlocks > 0;
|
|
36757
37157
|
if (!changed) {
|
|
36758
37158
|
return { slimmed: false, reason: "nothing to strip", contentBefore: before, contentAfter: after, stats };
|
|
@@ -36777,9 +37177,9 @@ async function slimTranscriptFile(transcript, opts = {}) {
|
|
|
36777
37177
|
return { slimmed: false, reason: "the transcript changed during the strip \u2014 left as is", contentBefore: before, contentAfter: after, stats };
|
|
36778
37178
|
}
|
|
36779
37179
|
const tmp = join11(dirname7(transcript), `.slim-${randomUUID2().slice(0, 8)}.tmp`);
|
|
36780
|
-
await writeFile4(tmp,
|
|
37180
|
+
await writeFile4(tmp, text13, { mode: 384 });
|
|
36781
37181
|
await rename(tmp, transcript);
|
|
36782
|
-
const outLines =
|
|
37182
|
+
const outLines = text13.split("\n").filter((l) => l.trim().length > 0);
|
|
36783
37183
|
await writeFile4(archiveMetaPath(transcript), JSON.stringify({ rows: outLines.length, tail: outLines[outLines.length - 1] ?? "" }), { mode: 384 });
|
|
36784
37184
|
return { slimmed: true, stats, contentBefore: before, contentAfter: after, archive, offloadDir };
|
|
36785
37185
|
}
|
|
@@ -36920,8 +37320,8 @@ async function labelFromTranscript(file2) {
|
|
|
36920
37320
|
if (row.type !== "user" && row.message?.role !== "user")
|
|
36921
37321
|
continue;
|
|
36922
37322
|
const c = row.message?.content;
|
|
36923
|
-
const
|
|
36924
|
-
const s = oneLine(
|
|
37323
|
+
const text13 = typeof c === "string" ? c : Array.isArray(c) ? c.find((b) => b.type === "text")?.text ?? "" : "";
|
|
37324
|
+
const s = oneLine(text13);
|
|
36925
37325
|
if (s)
|
|
36926
37326
|
return s;
|
|
36927
37327
|
}
|
|
@@ -37390,33 +37790,33 @@ function annotationIsOrphaned(e, removedUuids) {
|
|
|
37390
37790
|
return false;
|
|
37391
37791
|
return clearDanglingPointers(e, removedUuids) !== e;
|
|
37392
37792
|
}
|
|
37393
|
-
function isPromptEchoOf(e, removedUuids,
|
|
37793
|
+
function isPromptEchoOf(e, removedUuids, text13) {
|
|
37394
37794
|
if (e.type !== "last-prompt")
|
|
37395
37795
|
return false;
|
|
37396
37796
|
const leaf = typeof e.leafUuid === "string" ? e.leafUuid : void 0;
|
|
37397
37797
|
if (leaf && removedUuids.has(leaf))
|
|
37398
37798
|
return true;
|
|
37399
|
-
if (!
|
|
37799
|
+
if (!text13)
|
|
37400
37800
|
return false;
|
|
37401
37801
|
const echo = typeof e.lastPrompt === "string" ? e.lastPrompt : void 0;
|
|
37402
|
-
return echo ===
|
|
37802
|
+
return echo === text13;
|
|
37403
37803
|
}
|
|
37404
37804
|
function messageText(e) {
|
|
37405
37805
|
const content = e.message?.content;
|
|
37406
37806
|
if (typeof content === "string")
|
|
37407
37807
|
return content;
|
|
37408
37808
|
if (Array.isArray(content)) {
|
|
37409
|
-
const
|
|
37410
|
-
return
|
|
37809
|
+
const text13 = content.filter((b) => !!b && typeof b === "object" && b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
|
|
37810
|
+
return text13 || void 0;
|
|
37411
37811
|
}
|
|
37412
37812
|
return void 0;
|
|
37413
37813
|
}
|
|
37414
|
-
function findUserEntryByText(entries,
|
|
37814
|
+
function findUserEntryByText(entries, text13) {
|
|
37415
37815
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
37416
37816
|
const e = entries[i];
|
|
37417
37817
|
if (e.type !== "user" || !e.uuid)
|
|
37418
37818
|
continue;
|
|
37419
|
-
if (messageText(e) ===
|
|
37819
|
+
if (messageText(e) === text13)
|
|
37420
37820
|
return e;
|
|
37421
37821
|
}
|
|
37422
37822
|
return void 0;
|
|
@@ -37985,10 +38385,10 @@ async function toSessionInfo(s) {
|
|
|
37985
38385
|
const spoken = s.cwd ? await lastConversationTime(sessionFile(s.cwd, s.sessionId)) : null;
|
|
37986
38386
|
return { id: s.sessionId, title, lastModified: spoken ?? s.lastModified, cwd: s.cwd };
|
|
37987
38387
|
}
|
|
37988
|
-
function stripPromptPrefix(
|
|
37989
|
-
|
|
38388
|
+
function stripPromptPrefix(text13) {
|
|
38389
|
+
text13 = stripRunDirective(text13);
|
|
37990
38390
|
const isMetadata = (l) => l.startsWith("I'm working on the page:") || l.startsWith("Selected elements:") || l.startsWith("Element ") || l.startsWith(" DOM Path:") || l.startsWith(" XPath:") || l.startsWith(" CSS:") || l.startsWith(" HTML:") || l.startsWith(" Text:") || l.startsWith(" Position:") || l.startsWith("Use the xpath") || l.startsWith("[") && l.includes("image(s) attached");
|
|
37991
|
-
const userLines =
|
|
38391
|
+
const userLines = text13.split("\n").filter((l) => !isMetadata(l));
|
|
37992
38392
|
return userLines.join("\n").trim();
|
|
37993
38393
|
}
|
|
37994
38394
|
function extractBlocks(message) {
|
|
@@ -38007,13 +38407,13 @@ function extractBlocks(message) {
|
|
|
38007
38407
|
continue;
|
|
38008
38408
|
const b = block2;
|
|
38009
38409
|
if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
38010
|
-
const
|
|
38011
|
-
if (
|
|
38012
|
-
blocks.push({ kind: "thinking", content:
|
|
38410
|
+
const text13 = b.thinking.trim();
|
|
38411
|
+
if (text13)
|
|
38412
|
+
blocks.push({ kind: "thinking", content: text13 });
|
|
38013
38413
|
} else if (b.type === "text" && typeof b.text === "string") {
|
|
38014
|
-
const
|
|
38015
|
-
if (
|
|
38016
|
-
blocks.push({ kind: "text", content:
|
|
38414
|
+
const text13 = b.text.trim();
|
|
38415
|
+
if (text13 && !text13.startsWith("<ide_") && !text13.startsWith("<system-reminder>")) {
|
|
38416
|
+
blocks.push({ kind: "text", content: text13 });
|
|
38017
38417
|
}
|
|
38018
38418
|
} else if (b.type === "tool_use") {
|
|
38019
38419
|
const name = b.name ?? "tool";
|
|
@@ -38059,9 +38459,9 @@ ${input.command}
|
|
|
38059
38459
|
blocks.push({ kind: "tool_use", content: detail, name });
|
|
38060
38460
|
} else if (b.type === "advisor_tool_result") {
|
|
38061
38461
|
const c = b.content;
|
|
38062
|
-
const
|
|
38063
|
-
if (
|
|
38064
|
-
blocks.push({ kind: "advisor", content:
|
|
38462
|
+
const text13 = c?.type === "advisor_result" ? (c.text ?? "").trim() : "";
|
|
38463
|
+
if (text13)
|
|
38464
|
+
blocks.push({ kind: "advisor", content: text13 });
|
|
38065
38465
|
}
|
|
38066
38466
|
}
|
|
38067
38467
|
return blocks;
|
|
@@ -38403,8 +38803,8 @@ async function anthropicCall(args) {
|
|
|
38403
38803
|
});
|
|
38404
38804
|
if (res.ok) {
|
|
38405
38805
|
const j = await res.json();
|
|
38406
|
-
const
|
|
38407
|
-
return { text:
|
|
38806
|
+
const text13 = (j.content ?? []).filter((b) => b.type === "text").map((b) => b.text ?? "").join("").trim() || null;
|
|
38807
|
+
return { text: text13, rateLimited: false };
|
|
38408
38808
|
}
|
|
38409
38809
|
let errBody = "";
|
|
38410
38810
|
try {
|
|
@@ -38452,13 +38852,6 @@ async function anthropicCall(args) {
|
|
|
38452
38852
|
}
|
|
38453
38853
|
return { text: null, rateLimited: false };
|
|
38454
38854
|
}
|
|
38455
|
-
function isDirectAnthropic(env) {
|
|
38456
|
-
try {
|
|
38457
|
-
return /(^|\.)api\.anthropic\.com$/i.test(new URL(anthropicBaseUrl(env)).hostname);
|
|
38458
|
-
} catch {
|
|
38459
|
-
return false;
|
|
38460
|
-
}
|
|
38461
|
-
}
|
|
38462
38855
|
async function buildClaudeNarrationLlm(env) {
|
|
38463
38856
|
if (!await hasAnthropicCred(env))
|
|
38464
38857
|
return null;
|
|
@@ -38548,7 +38941,7 @@ async function buildClaudeVisionLlm(env) {
|
|
|
38548
38941
|
]
|
|
38549
38942
|
});
|
|
38550
38943
|
}
|
|
38551
|
-
var execFileP, USAGE_URL, FETCH_TIMEOUT_MS, cache, TTL_MS, RATE_LIMIT_BACKOFF_MS, inFlight, rateLimitedUntil, schemaUnsupported, schemaKey, SMART_TIMEOUT_MS, VISION_TIMEOUT_MS;
|
|
38944
|
+
var execFileP, USAGE_URL, FETCH_TIMEOUT_MS, cache, TTL_MS, RATE_LIMIT_BACKOFF_MS, inFlight, rateLimitedUntil, isDirectAnthropic, schemaUnsupported, schemaKey, SMART_TIMEOUT_MS, VISION_TIMEOUT_MS;
|
|
38552
38945
|
var init_session_usage = __esm({
|
|
38553
38946
|
"../../packages/agent-core/dist/session-usage.js"() {
|
|
38554
38947
|
"use strict";
|
|
@@ -38563,6 +38956,7 @@ var init_session_usage = __esm({
|
|
|
38563
38956
|
RATE_LIMIT_BACKOFF_MS = 5 * 6e4;
|
|
38564
38957
|
inFlight = null;
|
|
38565
38958
|
rateLimitedUntil = 0;
|
|
38959
|
+
isDirectAnthropic = isAnthropicEndpoint;
|
|
38566
38960
|
schemaUnsupported = /* @__PURE__ */ new Set();
|
|
38567
38961
|
schemaKey = (base, model) => `${base}|${model}`;
|
|
38568
38962
|
SMART_TIMEOUT_MS = RV_GRADE_TIMEOUT_MS;
|
|
@@ -38692,7 +39086,7 @@ var init_stream_stall = __esm({
|
|
|
38692
39086
|
// ../../packages/agent-core/dist/model-switch.js
|
|
38693
39087
|
function modelFamily(model) {
|
|
38694
39088
|
const id = (model ?? "").trim().toLowerCase();
|
|
38695
|
-
if (!id
|
|
39089
|
+
if (!id)
|
|
38696
39090
|
return void 0;
|
|
38697
39091
|
return FAMILIES2.find((family) => id.includes(family));
|
|
38698
39092
|
}
|
|
@@ -38728,8 +39122,8 @@ var init_model_switch = __esm({
|
|
|
38728
39122
|
|
|
38729
39123
|
// ../../packages/agent-core/dist/usage-limit.js
|
|
38730
39124
|
import { USAGE_LIMIT_ERROR_PREFIXES, USAGE_WARNING_PREFIXES, USAGE_TRANSITION_PREFIXES, ORG_POLICY_LIMIT_PREFIXES } from "@anthropic-ai/claude-agent-sdk";
|
|
38731
|
-
function classifyUsageMessage(
|
|
38732
|
-
const t = (
|
|
39125
|
+
function classifyUsageMessage(text13) {
|
|
39126
|
+
const t = (text13 ?? "").trim();
|
|
38733
39127
|
if (!t)
|
|
38734
39128
|
return void 0;
|
|
38735
39129
|
const hits = (list) => list.some((p) => t.startsWith(p));
|
|
@@ -38765,16 +39159,16 @@ function assistantUsageLimitFallback(content) {
|
|
|
38765
39159
|
const blocks = content;
|
|
38766
39160
|
if (blocks.some((block2) => block2?.type !== "text"))
|
|
38767
39161
|
return void 0;
|
|
38768
|
-
const
|
|
38769
|
-
if (!
|
|
39162
|
+
const text13 = blocks.map((block2) => typeof block2.text === "string" ? block2.text : "").join("\n").trim();
|
|
39163
|
+
if (!text13 || text13.length > 600)
|
|
38770
39164
|
return void 0;
|
|
38771
|
-
const signal2 = classifyUsageMessage(
|
|
39165
|
+
const signal2 = classifyUsageMessage(text13);
|
|
38772
39166
|
if (signal2 !== "limit" && signal2 !== "org-policy")
|
|
38773
39167
|
return void 0;
|
|
38774
|
-
const isoReset =
|
|
38775
|
-
const resetMatch =
|
|
39168
|
+
const isoReset = text13.match(/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z\b/i)?.[0];
|
|
39169
|
+
const resetMatch = text13.match(/(?:reset|resets|available again)(?:s| at| on| in)?\s+([^\n]+)/i);
|
|
38776
39170
|
const parsed = Date.parse(isoReset ?? resetMatch?.[1].trim() ?? "");
|
|
38777
|
-
return { retryAt: Number.isFinite(parsed) ? parsed : void 0, signal: signal2, scopeText:
|
|
39171
|
+
return { retryAt: Number.isFinite(parsed) ? parsed : void 0, signal: signal2, scopeText: text13 };
|
|
38778
39172
|
}
|
|
38779
39173
|
function usageLimitErrorMessage(rejection) {
|
|
38780
39174
|
if (rejection.signal === "org-policy") {
|
|
@@ -38789,16 +39183,30 @@ function usageLimitIsRotatable(rejection) {
|
|
|
38789
39183
|
function usageLimitScopedModel(rejection, current) {
|
|
38790
39184
|
if (rejection.signal === "org-policy")
|
|
38791
39185
|
return void 0;
|
|
38792
|
-
const
|
|
38793
|
-
if (!
|
|
39186
|
+
const text13 = (rejection.scopeText ?? "").trim();
|
|
39187
|
+
if (!text13)
|
|
38794
39188
|
return void 0;
|
|
38795
|
-
const named = /reached your ([A-Za-z0-9.\- ]{1,30}?) limit/i.exec(
|
|
39189
|
+
const named = /reached your ([A-Za-z0-9.\- ]{1,30}?) limit/i.exec(text13)?.[1]?.trim().toLowerCase();
|
|
38796
39190
|
if (!named)
|
|
38797
39191
|
return void 0;
|
|
38798
39192
|
if (current && !current.toLowerCase().includes(named))
|
|
38799
39193
|
return void 0;
|
|
38800
39194
|
return named;
|
|
38801
39195
|
}
|
|
39196
|
+
function providerIsServing(content) {
|
|
39197
|
+
if (typeof content === "string")
|
|
39198
|
+
return content.trim().length > 0;
|
|
39199
|
+
if (!Array.isArray(content))
|
|
39200
|
+
return false;
|
|
39201
|
+
return content.some((blk) => {
|
|
39202
|
+
const b = blk;
|
|
39203
|
+
if (!b || typeof b !== "object")
|
|
39204
|
+
return false;
|
|
39205
|
+
if (b.type === "text")
|
|
39206
|
+
return typeof b.text === "string" && b.text.trim().length > 0;
|
|
39207
|
+
return b.type === "tool_use" || b.type === "server_tool_use" || b.type === "thinking";
|
|
39208
|
+
});
|
|
39209
|
+
}
|
|
38802
39210
|
var init_usage_limit = __esm({
|
|
38803
39211
|
"../../packages/agent-core/dist/usage-limit.js"() {
|
|
38804
39212
|
"use strict";
|
|
@@ -38829,8 +39237,14 @@ function findUserInstalledClaude(binName) {
|
|
|
38829
39237
|
const home = homedir3();
|
|
38830
39238
|
const abs = [
|
|
38831
39239
|
join17(home, ".claude", "local", binName),
|
|
38832
|
-
//
|
|
39240
|
+
// legacy local npm install (older Claude Code)
|
|
38833
39241
|
join17(home, ".local", "bin", binName),
|
|
39242
|
+
// the native installer's launcher — where we install
|
|
39243
|
+
// A copy Tesseract itself installed back when it used `npm install -g --prefix`. The probe has
|
|
39244
|
+
// always searched here, this list never did, so such an install read as "installed" in Settings
|
|
39245
|
+
// while the spawn said "not installed". AFTER ~/.local/bin deliberately: a current native
|
|
39246
|
+
// install must win over a stale npm one.
|
|
39247
|
+
join17(home, ".tesseract", "runtimes", "bin", binName),
|
|
38834
39248
|
join17(home, ".bun", "bin", binName),
|
|
38835
39249
|
join17(home, ".volta", "bin", binName),
|
|
38836
39250
|
join17(home, "Library", "pnpm", binName),
|
|
@@ -38885,7 +39299,7 @@ function resolveClaudeCodeExecutable() {
|
|
|
38885
39299
|
return cachedClaudeExe = bundled;
|
|
38886
39300
|
}
|
|
38887
39301
|
}
|
|
38888
|
-
throw new Error("Claude Code isn\u2019t installed. Tesseract runs
|
|
39302
|
+
throw new Error("Claude Code isn\u2019t installed. Tesseract runs the agent framework you have installed rather than bundling one \u2014 install it with `curl -fsSL https://claude.ai/install.sh | bash` (Windows: `irm https://claude.ai/install.ps1 | iex`), or pick a different engine in Settings.");
|
|
38889
39303
|
}
|
|
38890
39304
|
function identityEnv() {
|
|
38891
39305
|
const out = {};
|
|
@@ -39077,12 +39491,14 @@ function sessionStoreFor(mode) {
|
|
|
39077
39491
|
function unattendedReportDirective(send5) {
|
|
39078
39492
|
return unattendedModeFor({ optedIn: send5.unattended, origin: send5.origin }) !== "off" ? prompt("agent.system.unattended-report") : "";
|
|
39079
39493
|
}
|
|
39080
|
-
function sdkModelId(model) {
|
|
39494
|
+
function sdkModelId(model, env) {
|
|
39081
39495
|
const id = model?.trim();
|
|
39082
39496
|
if (!id)
|
|
39083
39497
|
return void 0;
|
|
39084
39498
|
if (process.env.TESSERACT_DISABLE_1M_CONTEXT === "1")
|
|
39085
39499
|
return id;
|
|
39500
|
+
if (!isAnthropicEndpoint(env))
|
|
39501
|
+
return id;
|
|
39086
39502
|
if (/[/]/.test(id) || /^[a-z]{2,}\./i.test(id))
|
|
39087
39503
|
return id;
|
|
39088
39504
|
return withOneMillionContext(id) ?? id;
|
|
@@ -39262,8 +39678,8 @@ function traceFrame(message) {
|
|
|
39262
39678
|
const k = b?.type ?? "?";
|
|
39263
39679
|
kinds.set(k, (kinds.get(k) ?? 0) + 1);
|
|
39264
39680
|
}
|
|
39265
|
-
const
|
|
39266
|
-
what = [...kinds].map(([k, n]) => n > 1 ? `${k}\xD7${n}` : k).join(",") + (
|
|
39681
|
+
const text13 = c.find((b) => b?.type === "text")?.text;
|
|
39682
|
+
what = [...kinds].map(([k, n]) => n > 1 ? `${k}\xD7${n}` : k).join(",") + (text13 ? ` text:${JSON.stringify(text13.slice(0, 60))}` : "");
|
|
39267
39683
|
}
|
|
39268
39684
|
log(`frame user${parent}${flags.length ? " [" + flags.join(",") + "]" : ""}${what ? " \u2014 " + what : ""}`);
|
|
39269
39685
|
return;
|
|
@@ -39354,8 +39770,8 @@ function describeSystemSubtype(subtype, m) {
|
|
|
39354
39770
|
const updateKey = category === "hook" ? `hook:${String(m.hook_name ?? m.hook_event_name ?? subtype)}` : category === "task" ? `task:${String(m.task_id ?? subtype)}` : category === "telemetry" ? `sys:${subtype}` : void 0;
|
|
39355
39771
|
return { category, name: subtype, title: humanizeName(subtype), fields: salientFields(m), ...updateKey ? { updateKey } : {} };
|
|
39356
39772
|
}
|
|
39357
|
-
const
|
|
39358
|
-
return { category: "unknown", name: subtype, title: `system/${subtype}`, ...
|
|
39773
|
+
const text13 = extractHumanReadable(m);
|
|
39774
|
+
return { category: "unknown", name: subtype, title: `system/${subtype}`, ...text13 ? { detail: text13 } : {}, raw: rawFramePreview(m) };
|
|
39359
39775
|
}
|
|
39360
39776
|
function sstr(v) {
|
|
39361
39777
|
return typeof v === "string" ? v : "";
|
|
@@ -39375,24 +39791,24 @@ function prettifyModel(id) {
|
|
|
39375
39791
|
return known[id] ?? id.replace(/^claude-/, "").replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
39376
39792
|
}
|
|
39377
39793
|
function taskNotificationNotices(content) {
|
|
39378
|
-
let
|
|
39794
|
+
let text13 = "";
|
|
39379
39795
|
if (typeof content === "string")
|
|
39380
|
-
|
|
39796
|
+
text13 = content;
|
|
39381
39797
|
else if (Array.isArray(content)) {
|
|
39382
39798
|
for (const b of content) {
|
|
39383
39799
|
if (b && typeof b === "object" && b.type === "text")
|
|
39384
|
-
|
|
39800
|
+
text13 += `${sstr(b.text)}
|
|
39385
39801
|
`;
|
|
39386
39802
|
}
|
|
39387
39803
|
}
|
|
39388
|
-
if (!
|
|
39804
|
+
if (!text13.includes("<task-notification>"))
|
|
39389
39805
|
return [];
|
|
39390
39806
|
const tag = (xml3, name) => {
|
|
39391
39807
|
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(xml3);
|
|
39392
39808
|
return m ? m[1].trim() : "";
|
|
39393
39809
|
};
|
|
39394
39810
|
const specs = [];
|
|
39395
|
-
for (const m of
|
|
39811
|
+
for (const m of text13.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
|
|
39396
39812
|
const status2 = (tag(m[1], "status") || "completed").toLowerCase();
|
|
39397
39813
|
const summary = tag(m[1], "summary") || "Background task finished.";
|
|
39398
39814
|
const failed = /fail|error/.test(status2);
|
|
@@ -39406,10 +39822,10 @@ function taskNotificationNotices(content) {
|
|
|
39406
39822
|
function buildNotice(subtype, m) {
|
|
39407
39823
|
switch (subtype) {
|
|
39408
39824
|
case "notification": {
|
|
39409
|
-
const
|
|
39825
|
+
const text13 = sstr(m.text) || "Notification";
|
|
39410
39826
|
const priority = ["low", "medium", "high", "immediate"].includes(sstr(m.priority)) ? m.priority : "medium";
|
|
39411
39827
|
const level = priority === "immediate" ? "error" : priority === "high" ? "warning" : priority === "low" ? "info" : "notice";
|
|
39412
|
-
return { category: "notification", level, priority, title:
|
|
39828
|
+
return { category: "notification", level, priority, title: text13, toast: true, inline: true, ...typeof m.timeout_ms === "number" ? { timeoutMs: m.timeout_ms } : {} };
|
|
39413
39829
|
}
|
|
39414
39830
|
case "informational": {
|
|
39415
39831
|
const content = sstr(m.content).trim();
|
|
@@ -39440,9 +39856,9 @@ function buildNotice(subtype, m) {
|
|
|
39440
39856
|
return { category: "memory", level: "info", title: `Recalled ${memories.length} ${memories.length === 1 ? "memory" : "memories"}`, ...names.length ? { body: names.join(" \xB7 ") } : {}, toast: false, inline: true };
|
|
39441
39857
|
}
|
|
39442
39858
|
case "permission_denied": {
|
|
39443
|
-
const
|
|
39859
|
+
const tool22 = sstr(m.tool_name) || "a tool";
|
|
39444
39860
|
const reason = sstr(m.decision_reason) || sstr(m.message);
|
|
39445
|
-
return { category: "permission", level: "warning", title: `Blocked: ${
|
|
39861
|
+
return { category: "permission", level: "warning", title: `Blocked: ${tool22}`, ...reason ? { body: reason } : {}, ...sstr(m.tool_use_id) ? { toolUseId: sstr(m.tool_use_id) } : {}, toast: true, inline: true };
|
|
39446
39862
|
}
|
|
39447
39863
|
case "model_refusal_fallback": {
|
|
39448
39864
|
const orig = sstr(m.original_model);
|
|
@@ -39556,9 +39972,9 @@ ${plan}`;
|
|
|
39556
39972
|
return name;
|
|
39557
39973
|
}
|
|
39558
39974
|
}
|
|
39559
|
-
function computerToolPhrase(
|
|
39975
|
+
function computerToolPhrase(tool22, input) {
|
|
39560
39976
|
const s = (v) => typeof v === "string" ? v : "";
|
|
39561
|
-
switch (
|
|
39977
|
+
switch (tool22) {
|
|
39562
39978
|
case "see_screen":
|
|
39563
39979
|
return input.x1 !== void 0 ? "Looking closely at part of the screen" : "Looking at the screen";
|
|
39564
39980
|
case "click":
|
|
@@ -39601,15 +40017,15 @@ function assistantText(content) {
|
|
|
39601
40017
|
return content.filter((b) => !!b && typeof b === "object").filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
|
|
39602
40018
|
}
|
|
39603
40019
|
function flattenToolResultContent(content) {
|
|
39604
|
-
let
|
|
40020
|
+
let text13 = "";
|
|
39605
40021
|
if (typeof content === "string")
|
|
39606
|
-
|
|
40022
|
+
text13 = content;
|
|
39607
40023
|
else if (Array.isArray(content)) {
|
|
39608
|
-
|
|
40024
|
+
text13 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
|
|
39609
40025
|
}
|
|
39610
|
-
if (
|
|
39611
|
-
return { text:
|
|
39612
|
-
return { text:
|
|
40026
|
+
if (text13.length > TOOL_RESULT_CAP)
|
|
40027
|
+
return { text: text13.slice(0, TOOL_RESULT_CAP), truncated: true };
|
|
40028
|
+
return { text: text13, truncated: false };
|
|
39613
40029
|
}
|
|
39614
40030
|
function extractImages(content) {
|
|
39615
40031
|
if (!Array.isArray(content))
|
|
@@ -39791,6 +40207,7 @@ var init_agent_manager = __esm({
|
|
|
39791
40207
|
init_screen_control_tools();
|
|
39792
40208
|
init_computer_control_tools();
|
|
39793
40209
|
init_app_control_tools();
|
|
40210
|
+
init_capabilities_tools();
|
|
39794
40211
|
init_serpapi_tools();
|
|
39795
40212
|
init_report_tools();
|
|
39796
40213
|
init_interactive_ui_tools();
|
|
@@ -39920,7 +40337,9 @@ var init_agent_manager = __esm({
|
|
|
39920
40337
|
"await_jobs",
|
|
39921
40338
|
"job_output",
|
|
39922
40339
|
"job_list",
|
|
39923
|
-
"stop_job"
|
|
40340
|
+
"stop_job",
|
|
40341
|
+
// Returns an inlined constant. There is nothing to wait for.
|
|
40342
|
+
"tesseract_capabilities"
|
|
39924
40343
|
]);
|
|
39925
40344
|
STOP_HARD_KILL_AFTER_MS = 1200;
|
|
39926
40345
|
STREAM_STALL_MS = 20 * 6e4;
|
|
@@ -40186,8 +40605,37 @@ var init_agent_manager = __esm({
|
|
|
40186
40605
|
* (then recorded into cronTaskSessions). */
|
|
40187
40606
|
cronRequestTask = /* @__PURE__ */ new Map();
|
|
40188
40607
|
/** What each conversation last ran with for Unattended — its own choice, which a scheduled fire into it must
|
|
40189
|
-
* honour rather than the machine-wide switch (applyTurnPolicy records it; the cron fire above reads it).
|
|
40608
|
+
* honour rather than the machine-wide switch (applyTurnPolicy records it; the cron fire above reads it).
|
|
40609
|
+
* Bounded: a daemon that runs for months must not grow a row per conversation forever, and forgetting the
|
|
40610
|
+
* oldest is safe — an unknown conversation falls back to 'safe' rather than to the machine switch. */
|
|
40190
40611
|
unattendedByConversation = /* @__PURE__ */ new Map();
|
|
40612
|
+
/** How many conversations' Unattended choices are remembered. Generous — one small row each — and bounded
|
|
40613
|
+
* so a long-lived daemon cannot grow this without limit. */
|
|
40614
|
+
static MAX_REMEMBERED_UNATTENDED = 2e3;
|
|
40615
|
+
/**
|
|
40616
|
+
* Everything keyed by a conversation's id that must follow it when the CLI re-ids it mid-flight
|
|
40617
|
+
* (`conversation_reset`). It is the same conversation: the scheduler must keep firing into it rather than
|
|
40618
|
+
* opening a fresh overlapping one, and the Unattended choice made in it still stands — without this, a
|
|
40619
|
+
* reset quietly downgrades the next 3am fire to 'safe' in a conversation the person set up to run alone.
|
|
40620
|
+
*/
|
|
40621
|
+
carryConversationTo(prev, next) {
|
|
40622
|
+
for (const [taskId, mapped] of this.cronTaskSessions) {
|
|
40623
|
+
if (mapped === prev)
|
|
40624
|
+
this.cronTaskSessions.set(taskId, next);
|
|
40625
|
+
}
|
|
40626
|
+
const chosen = this.unattendedByConversation.get(prev);
|
|
40627
|
+
if (chosen !== void 0) {
|
|
40628
|
+
this.unattendedByConversation.delete(prev);
|
|
40629
|
+
this.rememberUnattended(next, chosen);
|
|
40630
|
+
}
|
|
40631
|
+
}
|
|
40632
|
+
rememberUnattended(sessionId, unattended) {
|
|
40633
|
+
this.unattendedByConversation.delete(sessionId);
|
|
40634
|
+
this.unattendedByConversation.set(sessionId, unattended);
|
|
40635
|
+
while (this.unattendedByConversation.size > _AgentManager.MAX_REMEMBERED_UNATTENDED) {
|
|
40636
|
+
this.unattendedByConversation.delete(this.unattendedByConversation.keys().next().value);
|
|
40637
|
+
}
|
|
40638
|
+
}
|
|
40191
40639
|
/** Set (or clear) the skills local-plugin exposed to NEW conversations (Epic H). */
|
|
40192
40640
|
setSkillsPlugin(config2) {
|
|
40193
40641
|
this.skillsPlugin = config2;
|
|
@@ -40383,6 +40831,12 @@ var init_agent_manager = __esm({
|
|
|
40383
40831
|
// never sent to in this daemon's life — is left ABSENT, which for a cron turn means 'safe':
|
|
40384
40832
|
// unanswerable prompts are declined rather than parked, and nothing is approved on anyone's behalf.
|
|
40385
40833
|
unattended: targetSessionId ? this.unattendedByConversation.get(targetSessionId) : cfg2.isUnattended?.(),
|
|
40834
|
+
// THE PERSON'S SETTINGS — their block rules, their always-ask rules, their hooks. A scheduled turn
|
|
40835
|
+
// carried NONE of them: a session this fire creates was built without the one layer that refuses
|
|
40836
|
+
// things, on the run nobody is watching. Read at fire time like the switches above, so a rule
|
|
40837
|
+
// written at 23:00 is in force at 03:00. (A conversation already live keeps the settings its
|
|
40838
|
+
// query was built with; this is what a cold or new one starts from.)
|
|
40839
|
+
settings: cfg2.settings?.(),
|
|
40386
40840
|
// Only for a conversation this fire is CREATING. Verification is per conversation and
|
|
40387
40841
|
// the machine-wide switch is merely the default a new one starts with, so stamping it
|
|
40388
40842
|
// onto an existing one overrode the choice the person made there — disarming a loop the
|
|
@@ -40449,7 +40903,7 @@ var init_agent_manager = __esm({
|
|
|
40449
40903
|
this.onBrowserRequest = onBrowserRequest;
|
|
40450
40904
|
const __dirname2 = dirname9(fileURLToPath(import.meta.url));
|
|
40451
40905
|
this.browserCliPath = join17(__dirname2, "browser-cli.js");
|
|
40452
|
-
this.narrator = new Narrator((sessionId,
|
|
40906
|
+
this.narrator = new Narrator((sessionId, text13, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text13, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
|
|
40453
40907
|
}
|
|
40454
40908
|
/** Inject (or clear) the cheap model used for the live status narration. The
|
|
40455
40909
|
* host resolves creds and builds the completion fn (keeping secrets host-side). */
|
|
@@ -40619,9 +41073,9 @@ var init_agent_manager = __esm({
|
|
|
40619
41073
|
const file2 = await resolveSessionFile(sid, live.cwd).catch(() => null);
|
|
40620
41074
|
if (!file2)
|
|
40621
41075
|
return false;
|
|
40622
|
-
let
|
|
41076
|
+
let text13;
|
|
40623
41077
|
try {
|
|
40624
|
-
|
|
41078
|
+
text13 = await readFile8(file2, "utf8");
|
|
40625
41079
|
} catch {
|
|
40626
41080
|
return false;
|
|
40627
41081
|
}
|
|
@@ -40629,7 +41083,7 @@ var init_agent_manager = __esm({
|
|
|
40629
41083
|
const v = leanReloadVerdict({
|
|
40630
41084
|
fillPct: usage2.percentage,
|
|
40631
41085
|
thresholdPct,
|
|
40632
|
-
leanBytes: contentBytes(
|
|
41086
|
+
leanBytes: contentBytes(text13),
|
|
40633
41087
|
strippedBytes: live.strippedContentBytes ?? 0
|
|
40634
41088
|
});
|
|
40635
41089
|
if (v.action === "skip") {
|
|
@@ -40864,7 +41318,7 @@ var init_agent_manager = __esm({
|
|
|
40864
41318
|
return false;
|
|
40865
41319
|
}
|
|
40866
41320
|
try {
|
|
40867
|
-
await live.query.setModel(sdkModelId(next));
|
|
41321
|
+
await live.query.setModel(sdkModelId(next, live.endpointEnv));
|
|
40868
41322
|
} catch (err2) {
|
|
40869
41323
|
log(`[model] ${turnSid}: could not switch to ${next}:`, err2 instanceof Error ? err2.message : String(err2));
|
|
40870
41324
|
return false;
|
|
@@ -41584,7 +42038,7 @@ ${full.slice(-8e3)}`;
|
|
|
41584
42038
|
applyTurnPolicy(live, p) {
|
|
41585
42039
|
live.unattended = unattendedModeFor({ optedIn: p.unattended, origin: p.origin });
|
|
41586
42040
|
if (p.unattended !== void 0 && live.sessionId)
|
|
41587
|
-
this.
|
|
42041
|
+
this.rememberUnattended(live.sessionId, p.unattended);
|
|
41588
42042
|
if (p.autoCompactPct !== void 0)
|
|
41589
42043
|
live.autoCompactPct = p.autoCompactPct;
|
|
41590
42044
|
live.autoDecisions = 0;
|
|
@@ -41763,10 +42217,10 @@ ${full.slice(-8e3)}`;
|
|
|
41763
42217
|
parts.push(`The user's current request:
|
|
41764
42218
|
${live.lastPrompt.slice(0, 1400)}`);
|
|
41765
42219
|
if (Array.isArray(live.lastAssistantContent)) {
|
|
41766
|
-
const
|
|
41767
|
-
if (
|
|
42220
|
+
const text13 = live.lastAssistantContent.filter((b) => b?.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
|
|
42221
|
+
if (text13)
|
|
41768
42222
|
parts.push(`What the assistant just said (leading to this question):
|
|
41769
|
-
${
|
|
42223
|
+
${text13.slice(0, 1600)}`);
|
|
41770
42224
|
}
|
|
41771
42225
|
return parts.join("\n\n") || "No additional context available beyond the question itself.";
|
|
41772
42226
|
}
|
|
@@ -42310,9 +42764,9 @@ ${lines}`;
|
|
|
42310
42764
|
const transcripts = [];
|
|
42311
42765
|
for (const sid of sessionIds) {
|
|
42312
42766
|
const msgs = await this.sessionStore.getSessionMessages(sid).catch(() => []);
|
|
42313
|
-
const
|
|
42314
|
-
if (
|
|
42315
|
-
transcripts.push(
|
|
42767
|
+
const text13 = transcriptToText(msgs);
|
|
42768
|
+
if (text13)
|
|
42769
|
+
transcripts.push(text13);
|
|
42316
42770
|
}
|
|
42317
42771
|
if (transcripts.length === 0)
|
|
42318
42772
|
return;
|
|
@@ -42399,7 +42853,7 @@ ${lines}`;
|
|
|
42399
42853
|
if (opts.permissionMode)
|
|
42400
42854
|
await live.query.setPermissionMode(sdkPermissionMode(opts.permissionMode));
|
|
42401
42855
|
if (opts.model !== void 0) {
|
|
42402
|
-
await live.query.setModel(sdkModelId(opts.model));
|
|
42856
|
+
await live.query.setModel(sdkModelId(opts.model, live.endpointEnv));
|
|
42403
42857
|
live.model = opts.model || void 0;
|
|
42404
42858
|
this.rememberSessionModel(live.sessionId, live.model);
|
|
42405
42859
|
}
|
|
@@ -42628,7 +43082,7 @@ ${lines}`;
|
|
|
42628
43082
|
live.windowId = params.windowId;
|
|
42629
43083
|
live.pendingTitle = params.message.trim().slice(0, 80);
|
|
42630
43084
|
if (params.model)
|
|
42631
|
-
void live.query.setModel(sdkModelId(params.model)).catch(() => {
|
|
43085
|
+
void live.query.setModel(sdkModelId(params.model, live.endpointEnv)).catch(() => {
|
|
42632
43086
|
});
|
|
42633
43087
|
if (params.permissionMode)
|
|
42634
43088
|
void live.query.setPermissionMode(sdkPermissionMode(params.permissionMode)).catch(() => {
|
|
@@ -42945,6 +43399,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
42945
43399
|
}
|
|
42946
43400
|
async createLiveSession(params) {
|
|
42947
43401
|
const spawnModel = this.modelForSpawn(params);
|
|
43402
|
+
const spawnEndpoint = { ...params.env ?? {}, ...params.engineEnv ?? {} };
|
|
42948
43403
|
this.rememberSessionModel(params.sessionId, spawnModel);
|
|
42949
43404
|
this.rememberSessionModel(params.clientRequestId, spawnModel);
|
|
42950
43405
|
const openProject = params.projectDir ?? this.projectDir ?? params.sources?.[0];
|
|
@@ -43106,7 +43561,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43106
43561
|
// `modelForSpawn`, not `params.model`: a resume that nobody sent a model with (a
|
|
43107
43562
|
// wake-up after a background task, a daemon-side continuation) would otherwise open a
|
|
43108
43563
|
// 1M conversation against 200k. See sessionModels.
|
|
43109
|
-
...spawnModel ? { model: sdkModelId(spawnModel) } : {},
|
|
43564
|
+
...spawnModel ? { model: sdkModelId(spawnModel, spawnEndpoint) } : {},
|
|
43110
43565
|
// Clamp to what THIS CLI accepts — an unsupported level is a hard exit-1, not
|
|
43111
43566
|
// a warning. See clampEffort.
|
|
43112
43567
|
...ultracodeEffort ? { effort: ultracodeEffort } : {},
|
|
@@ -43115,7 +43570,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43115
43570
|
// of surfacing an error the user has to act on.
|
|
43116
43571
|
// Same for the fallback: it REPLACES the main model on an overload, so a bare id here
|
|
43117
43572
|
// would quietly move a long conversation onto a 200k window mid-run.
|
|
43118
|
-
...params.fallbackModel ? { fallbackModel: sdkModelId(params.fallbackModel) } : {},
|
|
43573
|
+
...params.fallbackModel ? { fallbackModel: sdkModelId(params.fallbackModel, spawnEndpoint) } : {},
|
|
43119
43574
|
...params.enableFileCheckpointing ? { enableFileCheckpointing: true } : {},
|
|
43120
43575
|
// ON BY DEFAULT. This is what turns a silent helper into one that says what it is
|
|
43121
43576
|
// doing — a short present-tense line on each progress frame, written by forking the
|
|
@@ -43399,6 +43854,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43399
43854
|
if (this.computerControlProvider) {
|
|
43400
43855
|
mcp["tesseract-computer"] = createSdkMcpServer2({ name: "tesseract-computer", version: "0.1.0", tools: buildComputerControlSdkTools(this.computerControlProvider) });
|
|
43401
43856
|
}
|
|
43857
|
+
mcp["tesseract-capabilities"] = createSdkMcpServer2({ name: "tesseract-capabilities", version: "0.1.0", tools: buildCapabilitiesTools() });
|
|
43402
43858
|
if (this.appControlProvider) {
|
|
43403
43859
|
const appProvider = this.appControlProvider;
|
|
43404
43860
|
mcp["tesseract-app"] = createSdkMcpServer2({
|
|
@@ -43845,7 +44301,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43845
44301
|
// rather than the number in the run-mode menu.
|
|
43846
44302
|
...this.daemonCompactEnv(params.env),
|
|
43847
44303
|
// A GATEWAY MODEL ALIAS MUST NOT BE WINDOW-ENFORCED BY THE CLI. Routed through
|
|
43848
|
-
// our gateway
|
|
44304
|
+
// our gateway it may be a retired tier alias the CLI does not know. Harmless
|
|
43849
44305
|
// for an ordinary query; fatal for its INTERNAL compaction query, which never
|
|
43850
44306
|
// returns — no frame, 120s stall, killed as "connection went quiet", replayed
|
|
43851
44307
|
// by the client, and stalled again every two minutes for ever. MEASURED on a
|
|
@@ -43870,11 +44326,11 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43870
44326
|
});
|
|
43871
44327
|
let errSeen = 0;
|
|
43872
44328
|
child.stderr?.on("data", (chunk) => {
|
|
43873
|
-
const
|
|
44329
|
+
const text13 = String(chunk);
|
|
43874
44330
|
if (errSeen >= 8e3)
|
|
43875
44331
|
return;
|
|
43876
|
-
errSeen +=
|
|
43877
|
-
for (const line of
|
|
44332
|
+
errSeen += text13.length;
|
|
44333
|
+
for (const line of text13.split("\n")) {
|
|
43878
44334
|
const t = line.trim();
|
|
43879
44335
|
if (!t)
|
|
43880
44336
|
continue;
|
|
@@ -44153,9 +44609,9 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44153
44609
|
emit2({ type: "chat:stream", sessionId: sid, delta: "[thinking redacted]", messageId: message.uuid, kind: "thinking", ...parentField });
|
|
44154
44610
|
} else if (cbt === "advisor_tool_result") {
|
|
44155
44611
|
const res = event.content_block.content;
|
|
44156
|
-
const
|
|
44157
|
-
if (
|
|
44158
|
-
emit2({ type: "agent:advisor", sessionId: sid, text:
|
|
44612
|
+
const text13 = res?.type === "advisor_result" ? (res.text ?? "").trim() : "";
|
|
44613
|
+
if (text13 && parentToolUseId === void 0)
|
|
44614
|
+
emit2({ type: "agent:advisor", sessionId: sid, text: text13 });
|
|
44159
44615
|
}
|
|
44160
44616
|
}
|
|
44161
44617
|
if (event.type === "content_block_delta") {
|
|
@@ -44170,26 +44626,26 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44170
44626
|
}
|
|
44171
44627
|
}
|
|
44172
44628
|
if (event.delta?.type === "text_delta" && event.delta.text) {
|
|
44173
|
-
const
|
|
44174
|
-
if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(
|
|
44629
|
+
const text13 = event.delta.text;
|
|
44630
|
+
if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text13)) {
|
|
44175
44631
|
insideXmlByKey.set(key2, true);
|
|
44176
44632
|
break;
|
|
44177
44633
|
}
|
|
44178
44634
|
if (insideXmlByKey.get(key2)) {
|
|
44179
|
-
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(
|
|
44635
|
+
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text13)) {
|
|
44180
44636
|
insideXmlByKey.set(key2, false);
|
|
44181
44637
|
}
|
|
44182
44638
|
break;
|
|
44183
44639
|
}
|
|
44184
|
-
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(
|
|
44640
|
+
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text13))
|
|
44185
44641
|
break;
|
|
44186
|
-
if (/<parameter\s+name=/.test(
|
|
44642
|
+
if (/<parameter\s+name=/.test(text13))
|
|
44187
44643
|
break;
|
|
44188
|
-
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(
|
|
44644
|
+
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text13))
|
|
44189
44645
|
break;
|
|
44190
44646
|
if (parentToolUseId === void 0)
|
|
44191
44647
|
turnStreamed = true;
|
|
44192
|
-
const d = this.applyDeltaHook(
|
|
44648
|
+
const d = this.applyDeltaHook(text13, "text", sid);
|
|
44193
44649
|
if (d !== null)
|
|
44194
44650
|
emit2({ type: "chat:stream", sessionId: sid, delta: d, messageId: message.uuid, kind: "text", ...parentField });
|
|
44195
44651
|
}
|
|
@@ -44257,10 +44713,8 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44257
44713
|
live.sessionId = next;
|
|
44258
44714
|
this.rememberSessionModel(next, live.model);
|
|
44259
44715
|
this.liveSessions.set(next, live);
|
|
44260
|
-
|
|
44261
|
-
|
|
44262
|
-
this.cronTaskSessions.set(taskId, next);
|
|
44263
|
-
}
|
|
44716
|
+
if (prev)
|
|
44717
|
+
this.carryConversationTo(prev, next);
|
|
44264
44718
|
this.send({ type: "session:created", sessionId: next, clientRequestId: live.clientRequestId }, live.origin);
|
|
44265
44719
|
emitNotice({ category: "info", level: "notice", title: "This conversation was reset", body: "The agent started a fresh conversation; earlier messages are no longer in its context.", inline: true, toast: false });
|
|
44266
44720
|
break;
|
|
@@ -44310,7 +44764,9 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44310
44764
|
...typeof uc?.output_tokens === "number" ? { outputTokens: uc.output_tokens } : {}
|
|
44311
44765
|
});
|
|
44312
44766
|
}
|
|
44313
|
-
const
|
|
44767
|
+
const limitFromReply = r.subtype === "success" ? assistantUsageLimitFallback(live.lastAssistantContent) : void 0;
|
|
44768
|
+
const turnAnswered = r.subtype === "success" && r.is_error !== true && !limitFromReply;
|
|
44769
|
+
const limitRejection = turnAnswered ? void 0 : live.usageLimitRejection ?? limitFromReply;
|
|
44314
44770
|
const resultText = typeof r.result === "string" ? r.result : "";
|
|
44315
44771
|
const textOverflow = r.is_error === true && isContextOverflow(resultText) || live.lastAssistantSynthetic === true && assistantContextOverflow(live.lastAssistantContent, isContextOverflow);
|
|
44316
44772
|
const apiFailure = textOverflow ? null : classifyEngineApiError(resultText);
|
|
@@ -44780,6 +45236,10 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44780
45236
|
});
|
|
44781
45237
|
}
|
|
44782
45238
|
}
|
|
45239
|
+
if (live.usageLimitRejection && am.message?.model !== "<synthetic>" && providerIsServing(am.message?.content)) {
|
|
45240
|
+
log("Usage limit cleared by a reply that followed it:", sid);
|
|
45241
|
+
live.usageLimitRejection = void 0;
|
|
45242
|
+
}
|
|
44783
45243
|
if (am.uuid && parentToolUseId === void 0) {
|
|
44784
45244
|
live.lastAssistantUuid = am.uuid;
|
|
44785
45245
|
live.lastAssistantContent = am.message?.content;
|
|
@@ -44824,20 +45284,20 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44824
45284
|
const tn = toolNameByUseId.get(toolUseId);
|
|
44825
45285
|
if (tn === "Edit" || tn === "Write" || tn === "MultiEdit" || tn === "NotebookEdit")
|
|
44826
45286
|
continue;
|
|
44827
|
-
const { text:
|
|
45287
|
+
const { text: text13, truncated } = flattenToolResultContent(blk.content);
|
|
44828
45288
|
const images = extractImages(blk.content);
|
|
44829
45289
|
const isError = blk.is_error === true;
|
|
44830
|
-
if (!
|
|
45290
|
+
if (!text13 && images.length === 0 && !isError)
|
|
44831
45291
|
continue;
|
|
44832
|
-
emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output:
|
|
44833
|
-
const bg = parseBackgroundTaskResult(
|
|
45292
|
+
emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text13, images, truncated, ...agentId ? { agentId } : {} });
|
|
45293
|
+
const bg = parseBackgroundTaskResult(text13);
|
|
44834
45294
|
if (bg && !agentId) {
|
|
44835
45295
|
live.taskToolUse.set(bg.taskId, toolUseId);
|
|
44836
45296
|
emit2({ type: "agent:task", sessionId: sid, taskId: bg.taskId, phase: "progress", status: "running", ...this.taskIdentity(live, bg.taskId), toolUseId, outputPath: bg.outputPath, isBackgrounded: true });
|
|
44837
45297
|
this.startTaskTail(live, bg.taskId, bg.outputPath, toolUseId);
|
|
44838
45298
|
}
|
|
44839
45299
|
if (isError && !agentId) {
|
|
44840
|
-
const why = (
|
|
45300
|
+
const why = (text13 || "").replace(/```[\s\S]*?```/g, " ").replace(/[`*]/g, "").replace(/\s+/g, " ").trim().slice(0, 160);
|
|
44841
45301
|
this.narrator.observe(sid, `\u2192 that didn't work${why ? `: ${why}` : ""}`);
|
|
44842
45302
|
}
|
|
44843
45303
|
} else if (blk?.type === "web_search_tool_result") {
|
|
@@ -44869,12 +45329,12 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44869
45329
|
}
|
|
44870
45330
|
default: {
|
|
44871
45331
|
const m = message;
|
|
44872
|
-
const
|
|
45332
|
+
const text13 = extractHumanReadable(m);
|
|
44873
45333
|
emitEvent({
|
|
44874
45334
|
category: "unknown",
|
|
44875
45335
|
name: m.type || "unknown",
|
|
44876
45336
|
title: m.type || "unknown frame",
|
|
44877
|
-
...
|
|
45337
|
+
...text13 ? { detail: text13 } : {},
|
|
44878
45338
|
raw: rawFramePreview(m)
|
|
44879
45339
|
}, parentToolUseId);
|
|
44880
45340
|
log("unknown SDK message type surfaced with raw data:", m.type || "?");
|
|
@@ -46208,11 +46668,11 @@ Element ${i + 1}:`);
|
|
|
46208
46668
|
});
|
|
46209
46669
|
|
|
46210
46670
|
// ../../packages/agent-core/dist/present-tools.js
|
|
46211
|
-
import { tool as
|
|
46671
|
+
import { tool as tool21 } from "@anthropic-ai/claude-agent-sdk";
|
|
46212
46672
|
function buildPresentSdkTools(p) {
|
|
46213
|
-
return PRESENT_TOOL_SPECS.map((spec) =>
|
|
46214
|
-
const
|
|
46215
|
-
return { content: [{ type: "text", text:
|
|
46673
|
+
return PRESENT_TOOL_SPECS.map((spec) => tool21(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
|
|
46674
|
+
const text13 = await p.exec(spec.name, args ?? {});
|
|
46675
|
+
return { content: [{ type: "text", text: text13 || "Done." }] };
|
|
46216
46676
|
}));
|
|
46217
46677
|
}
|
|
46218
46678
|
function buildPresentPrompt(opts) {
|
|
@@ -46325,6 +46785,7 @@ __export(dist_exports2, {
|
|
|
46325
46785
|
APP_CONTROL_DOMAINS: () => APP_CONTROL_DOMAINS,
|
|
46326
46786
|
APP_CONTROL_GENERATED_MARKER: () => APP_CONTROL_GENERATED_MARKER,
|
|
46327
46787
|
AgentManager: () => AgentManager,
|
|
46788
|
+
CAPABILITIES_DOC: () => CAPABILITIES_DOC,
|
|
46328
46789
|
DEFAULT_OFFLOAD_RECENT_CALLS: () => DEFAULT_OFFLOAD_RECENT_CALLS,
|
|
46329
46790
|
DESIGN_CLAUDE_MD: () => DESIGN_CLAUDE_MD,
|
|
46330
46791
|
DESIGN_DIR: () => DESIGN_DIR,
|
|
@@ -46357,6 +46818,7 @@ __export(dist_exports2, {
|
|
|
46357
46818
|
archivePathFor: () => archivePathFor,
|
|
46358
46819
|
autoCompactEnvFor: () => autoCompactEnvFor,
|
|
46359
46820
|
buildAppControlTools: () => buildAppControlTools,
|
|
46821
|
+
buildCapabilitiesTools: () => buildCapabilitiesTools,
|
|
46360
46822
|
buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
|
|
46361
46823
|
buildClaudeSmartLlm: () => buildClaudeSmartLlm,
|
|
46362
46824
|
buildClaudeVisionLlm: () => buildClaudeVisionLlm,
|
|
@@ -46374,6 +46836,7 @@ __export(dist_exports2, {
|
|
|
46374
46836
|
bumpVersion: () => bumpVersion,
|
|
46375
46837
|
capabilitiesByDomain: () => capabilitiesByDomain,
|
|
46376
46838
|
capabilityById: () => capabilityById,
|
|
46839
|
+
capabilitySections: () => capabilitySections,
|
|
46377
46840
|
computerControlSpecs: () => computerControlSpecs,
|
|
46378
46841
|
computerOperatorPrompt: () => computerOperatorPrompt,
|
|
46379
46842
|
computerSpecParametersJsonSchema: () => computerSpecParametersJsonSchema,
|
|
@@ -46385,6 +46848,7 @@ __export(dist_exports2, {
|
|
|
46385
46848
|
engineMessageTokens: () => engineMessageTokens,
|
|
46386
46849
|
exportSession: () => exportSession,
|
|
46387
46850
|
filterHistory: () => filterHistory,
|
|
46851
|
+
findSections: () => findSections,
|
|
46388
46852
|
flattenForDisplay: () => flattenForDisplay,
|
|
46389
46853
|
getModelCatalog: () => getModelCatalog,
|
|
46390
46854
|
getTokenPath: () => getTokenPath,
|
|
@@ -46478,6 +46942,8 @@ var init_dist5 = __esm({
|
|
|
46478
46942
|
init_present_tools();
|
|
46479
46943
|
init_computer_control_tools();
|
|
46480
46944
|
init_support_tools();
|
|
46945
|
+
init_capabilities_tools();
|
|
46946
|
+
init_capabilities_doc_generated();
|
|
46481
46947
|
init_app_control_tools();
|
|
46482
46948
|
init_registry();
|
|
46483
46949
|
init_docs2();
|
|
@@ -47050,9 +47516,9 @@ function materializeClaudeAuthHome(contents) {
|
|
|
47050
47516
|
});
|
|
47051
47517
|
return home;
|
|
47052
47518
|
}
|
|
47053
|
-
function withClaudeModels(env, main2, fast) {
|
|
47519
|
+
function withClaudeModels(env, main2, fast, longWindow = true) {
|
|
47054
47520
|
if (main2) {
|
|
47055
|
-
env.ANTHROPIC_MODEL = withOneMillionContext(main2) ?? main2;
|
|
47521
|
+
env.ANTHROPIC_MODEL = (longWindow ? withOneMillionContext(main2) : main2) ?? main2;
|
|
47056
47522
|
}
|
|
47057
47523
|
if (fast)
|
|
47058
47524
|
env.ANTHROPIC_SMALL_FAST_MODEL = fast;
|
|
@@ -47099,7 +47565,7 @@ function resolveRunnerEnv(spec) {
|
|
|
47099
47565
|
if (!baseUrl.trim()) {
|
|
47100
47566
|
return { CCB_RUNNER_CONFIG_ERROR: `Set an address for ${provider.label} in Settings \u2192 Models & accounts.` };
|
|
47101
47567
|
}
|
|
47102
|
-
return withClaudeModels({ ANTHROPIC_BASE_URL: baseUrl, ANTHROPIC_AUTH_TOKEN: key2, ANTHROPIC_API_KEY: "" }, main2, fast);
|
|
47568
|
+
return withClaudeModels({ ANTHROPIC_BASE_URL: baseUrl, ANTHROPIC_AUTH_TOKEN: key2, ANTHROPIC_API_KEY: "" }, main2, fast, false);
|
|
47103
47569
|
}
|
|
47104
47570
|
const endpoint2 = routerEndpointSync({
|
|
47105
47571
|
providerId,
|
|
@@ -47173,7 +47639,10 @@ function readGatewayKey() {
|
|
|
47173
47639
|
baseUrl: raw.baseUrl,
|
|
47174
47640
|
apiKey: raw.apiKey,
|
|
47175
47641
|
models: raw.models,
|
|
47176
|
-
...raw.endpoints ? { endpoints: raw.endpoints } : {}
|
|
47642
|
+
...raw.endpoints ? { endpoints: raw.endpoints } : {},
|
|
47643
|
+
// Per-audience defaults (engine + model) travel through too — `tiers()` in shared
|
|
47644
|
+
// honours `defaults.model` on this headless spawn path exactly as the desktop does.
|
|
47645
|
+
...raw.defaults ? { defaults: raw.defaults } : {}
|
|
47177
47646
|
};
|
|
47178
47647
|
}
|
|
47179
47648
|
} catch {
|
|
@@ -47590,9 +48059,9 @@ function rememberedPath(engineId) {
|
|
|
47590
48059
|
}
|
|
47591
48060
|
}
|
|
47592
48061
|
function which(bin, path6) {
|
|
47593
|
-
const
|
|
48062
|
+
const tool22 = process.platform === "win32" ? "where" : "which";
|
|
47594
48063
|
try {
|
|
47595
|
-
const out = execFileSync2(
|
|
48064
|
+
const out = execFileSync2(tool22, [bin], { env: { ...process.env, PATH: path6 }, timeout: 4e3, encoding: "utf-8" });
|
|
47596
48065
|
return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
|
|
47597
48066
|
} catch {
|
|
47598
48067
|
return void 0;
|
|
@@ -47864,9 +48333,9 @@ function readBody2(req, limitBytes = 4 * 1024 * 1024) {
|
|
|
47864
48333
|
});
|
|
47865
48334
|
}
|
|
47866
48335
|
function send2(res, code, body, headers = {}) {
|
|
47867
|
-
const
|
|
47868
|
-
res.writeHead(code, { "content-type": "application/json", "content-length": Buffer.byteLength(
|
|
47869
|
-
res.end(
|
|
48336
|
+
const text13 = JSON.stringify(body);
|
|
48337
|
+
res.writeHead(code, { "content-type": "application/json", "content-length": Buffer.byteLength(text13), ...headers });
|
|
48338
|
+
res.end(text13);
|
|
47870
48339
|
}
|
|
47871
48340
|
function portFile() {
|
|
47872
48341
|
return join28(daemonDir2(), "mcp-endpoint.json");
|
|
@@ -47939,13 +48408,13 @@ async function startTesseractMcpEndpoint() {
|
|
|
47939
48408
|
return;
|
|
47940
48409
|
case "tools/call": {
|
|
47941
48410
|
const name = String(msg.params?.name ?? "");
|
|
47942
|
-
const
|
|
47943
|
-
if (!
|
|
48411
|
+
const tool22 = byName.get(name);
|
|
48412
|
+
if (!tool22) {
|
|
47944
48413
|
fail4(-32602, `Unknown tool "${name}"`);
|
|
47945
48414
|
return;
|
|
47946
48415
|
}
|
|
47947
48416
|
try {
|
|
47948
|
-
const out = await
|
|
48417
|
+
const out = await tool22.handler(msg.params?.arguments ?? {}, { sessionId: grant?.sessionId, nested: grant?.extensionId === NESTED_HOLDER });
|
|
47949
48418
|
reply3({ content: out.content, ...out.isError ? { isError: true } : {} });
|
|
47950
48419
|
} catch (e) {
|
|
47951
48420
|
reply3({ content: [{ type: "text", text: `${name} failed: ${e instanceof Error ? e.message : String(e)}` }], isError: true });
|
|
@@ -48099,11 +48568,11 @@ function wrapHostedAsyncTool(t, opts) {
|
|
|
48099
48568
|
}
|
|
48100
48569
|
if (raced.kind === "done") {
|
|
48101
48570
|
callEnded();
|
|
48102
|
-
return
|
|
48571
|
+
return text12(raced.out);
|
|
48103
48572
|
}
|
|
48104
48573
|
if (raced.kind === "error") {
|
|
48105
48574
|
callEnded();
|
|
48106
|
-
return
|
|
48575
|
+
return text12(raced.err instanceof Error ? raced.err.message : String(raced.err), true);
|
|
48107
48576
|
}
|
|
48108
48577
|
opts.learnedSlow?.add(t.name);
|
|
48109
48578
|
const sessionId = ctx2?.sessionId;
|
|
@@ -48116,7 +48585,7 @@ function wrapHostedAsyncTool(t, opts) {
|
|
|
48116
48585
|
});
|
|
48117
48586
|
opts.noteSession?.(job.id, sessionId, claim);
|
|
48118
48587
|
callEnded();
|
|
48119
|
-
return
|
|
48588
|
+
return text12([
|
|
48120
48589
|
`Started in the background: job \`${job.id}\`.`,
|
|
48121
48590
|
`Live output: ${job.logPath}`,
|
|
48122
48591
|
willNotify ? `You will be notified when it finishes \u2014 do not poll. Continue with other work, or call await_jobs(["${job.id}"]) if you cannot proceed without the result.` : `Call await_jobs(["${job.id}"]) when you need the result, or job_output("${job.id}") to read what it has produced so far.`
|
|
@@ -48153,12 +48622,12 @@ function buildHostedJobTools(registry3, opts = {}) {
|
|
|
48153
48622
|
handler: async (args, ctx2) => {
|
|
48154
48623
|
const ids = Array.isArray(args["job_ids"]) ? args["job_ids"].map(String) : [];
|
|
48155
48624
|
if (ids.length === 0)
|
|
48156
|
-
return
|
|
48625
|
+
return text12("await_jobs needs at least one job id.", true);
|
|
48157
48626
|
const unknown2 = ids.filter((id) => !registry3.list().some((j) => j.id === id) || !mine(id, ctx2?.sessionId));
|
|
48158
48627
|
if (unknown2.length)
|
|
48159
|
-
return
|
|
48628
|
+
return text12(`no such job: ${unknown2.join(", ")}`, true);
|
|
48160
48629
|
const jobs = await registry3.await(ids, typeof args["timeout_ms"] === "number" ? args["timeout_ms"] : 12e4);
|
|
48161
|
-
return
|
|
48630
|
+
return text12(jobs.map((j) => `${fmt(j)}
|
|
48162
48631
|
${registry3.output(j.id) || "(no output)"}`).join("\n\n"));
|
|
48163
48632
|
}
|
|
48164
48633
|
},
|
|
@@ -48179,10 +48648,10 @@ ${registry3.output(j.id) || "(no output)"}`).join("\n\n"));
|
|
|
48179
48648
|
const id = String(args["job_id"] ?? "");
|
|
48180
48649
|
const job = registry3.list().find((j) => j.id === id);
|
|
48181
48650
|
if (!job || !mine(id, ctx2?.sessionId))
|
|
48182
|
-
return
|
|
48651
|
+
return text12(`no such job: ${id}`, true);
|
|
48183
48652
|
const from = typeof args["from_offset"] === "number" ? args["from_offset"] : 0;
|
|
48184
48653
|
const out = registry3.output(id, from);
|
|
48185
|
-
return
|
|
48654
|
+
return text12(`${fmt(job)}
|
|
48186
48655
|
${out || "(nothing yet)"}`);
|
|
48187
48656
|
}
|
|
48188
48657
|
},
|
|
@@ -48193,7 +48662,7 @@ ${out || "(nothing yet)"}`);
|
|
|
48193
48662
|
annotations: { readOnlyHint: true },
|
|
48194
48663
|
handler: async (_args, ctx2) => {
|
|
48195
48664
|
const jobs = registry3.list().filter((j) => mine(j.id, ctx2?.sessionId)).sort((a, b) => Number(b.status === "running") - Number(a.status === "running"));
|
|
48196
|
-
return
|
|
48665
|
+
return text12(jobs.length ? jobs.map(fmt).join("\n\n") : "no jobs.");
|
|
48197
48666
|
}
|
|
48198
48667
|
},
|
|
48199
48668
|
{
|
|
@@ -48203,8 +48672,8 @@ ${out || "(nothing yet)"}`);
|
|
|
48203
48672
|
handler: async (args, ctx2) => {
|
|
48204
48673
|
const id = String(args["job_id"] ?? "");
|
|
48205
48674
|
if (!mine(id, ctx2?.sessionId))
|
|
48206
|
-
return
|
|
48207
|
-
return
|
|
48675
|
+
return text12(`job ${id} was not running.`);
|
|
48676
|
+
return text12(registry3.stop(id) ? `stopped job ${id}.` : `job ${id} was not running.`);
|
|
48208
48677
|
}
|
|
48209
48678
|
}
|
|
48210
48679
|
];
|
|
@@ -48435,12 +48904,12 @@ function createNoticeDispatcher(opts) {
|
|
|
48435
48904
|
}
|
|
48436
48905
|
};
|
|
48437
48906
|
}
|
|
48438
|
-
var
|
|
48907
|
+
var text12, NEVER_ASYNC;
|
|
48439
48908
|
var init_hosted_jobs = __esm({
|
|
48440
48909
|
"../../packages/host-core/dist/engines/hosted-jobs.js"() {
|
|
48441
48910
|
"use strict";
|
|
48442
48911
|
init_jobs();
|
|
48443
|
-
|
|
48912
|
+
text12 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
48444
48913
|
NEVER_ASYNC = /* @__PURE__ */ new Set(["await_jobs", "job_output", "job_list", "stop_job"]);
|
|
48445
48914
|
}
|
|
48446
48915
|
});
|
|
@@ -48719,7 +49188,7 @@ async function startHostedToolset(deps) {
|
|
|
48719
49188
|
return { endpoint: endpoint2, sendBrowserResponse, tasks, ...stopOwnedJob ? { stopJob: stopOwnedJob } : {}, ...rekeyOwnedJobs ? { rekeyJobs: rekeyOwnedJobs } : {}, ...jobProbe ? { jobProbe } : {}, refresh: build };
|
|
48720
49189
|
}
|
|
48721
49190
|
function buildHostTaskTools(registry3, run9) {
|
|
48722
|
-
const
|
|
49191
|
+
const text13 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
48723
49192
|
return [
|
|
48724
49193
|
{
|
|
48725
49194
|
name: "tesseract_spawn_subagent",
|
|
@@ -48736,25 +49205,25 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48736
49205
|
const description = String(args.description ?? "sub-task");
|
|
48737
49206
|
const prompt2 = String(args.prompt ?? "");
|
|
48738
49207
|
if (!prompt2.trim())
|
|
48739
|
-
return
|
|
49208
|
+
return text13("prompt is required", true);
|
|
48740
49209
|
if (ctx2?.nested) {
|
|
48741
|
-
return
|
|
49210
|
+
return text13("You are already a subagent: delegating again is not allowed. Do this work yourself, or report back to the agent that spawned you.", true);
|
|
48742
49211
|
}
|
|
48743
49212
|
const task = registry3.start("subagent", description);
|
|
48744
49213
|
task.messages.push({ role: "user", content: prompt2 });
|
|
48745
49214
|
try {
|
|
48746
49215
|
const out = await run9(prompt2, { signal: task.abort.signal, sessionId: ctx2?.sessionId });
|
|
48747
49216
|
if (task.status === "stopped")
|
|
48748
|
-
return
|
|
49217
|
+
return text13(`Subagent "${description}" was stopped.`, true);
|
|
48749
49218
|
task.status = "done";
|
|
48750
49219
|
task.result = out;
|
|
48751
49220
|
task.messages.push({ role: "assistant", content: out });
|
|
48752
|
-
return
|
|
49221
|
+
return text13(out || "(the subagent returned nothing)");
|
|
48753
49222
|
} catch (e) {
|
|
48754
49223
|
task.status = task.status === "stopped" ? "stopped" : "failed";
|
|
48755
49224
|
const why = e instanceof Error ? e.message : String(e);
|
|
48756
49225
|
task.result = why;
|
|
48757
|
-
return
|
|
49226
|
+
return text13(`Subagent "${description}" failed: ${why}`, true);
|
|
48758
49227
|
}
|
|
48759
49228
|
}
|
|
48760
49229
|
},
|
|
@@ -48765,8 +49234,8 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48765
49234
|
handler: async () => {
|
|
48766
49235
|
const rows = registry3.list();
|
|
48767
49236
|
if (!rows.length)
|
|
48768
|
-
return
|
|
48769
|
-
return
|
|
49237
|
+
return text13("No sub-tasks have been started.");
|
|
49238
|
+
return text13(rows.map((t) => `${t.id} ${t.status.padEnd(7)} ${t.description}`).join("\n"));
|
|
48770
49239
|
}
|
|
48771
49240
|
},
|
|
48772
49241
|
{
|
|
@@ -48779,7 +49248,7 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48779
49248
|
},
|
|
48780
49249
|
handler: async (args) => {
|
|
48781
49250
|
const id = String(args.taskId ?? "");
|
|
48782
|
-
return registry3.stop(id) ?
|
|
49251
|
+
return registry3.stop(id) ? text13(`Stopped ${id}.`) : text13(`${id} is not a running task (unknown, or already finished).`, true);
|
|
48783
49252
|
}
|
|
48784
49253
|
}
|
|
48785
49254
|
];
|
|
@@ -54120,24 +54589,24 @@ var require_text2 = __commonJS({
|
|
|
54120
54589
|
}
|
|
54121
54590
|
}
|
|
54122
54591
|
var latin1Regex = /^[\u0000-\u00FF]*$/;
|
|
54123
|
-
function validateLatin1(
|
|
54124
|
-
if (!latin1Regex.test(
|
|
54592
|
+
function validateLatin1(text13) {
|
|
54593
|
+
if (!latin1Regex.test(text13)) {
|
|
54125
54594
|
throw new Error("invalid latin1 text");
|
|
54126
54595
|
}
|
|
54127
54596
|
}
|
|
54128
|
-
function decodetEXt(
|
|
54597
|
+
function decodetEXt(text13, buffer, length) {
|
|
54129
54598
|
const keyword = readKeyword(buffer);
|
|
54130
|
-
|
|
54599
|
+
text13[keyword] = readLatin1(buffer, length - keyword.length - 1);
|
|
54131
54600
|
}
|
|
54132
|
-
function encodetEXt(buffer, keyword,
|
|
54601
|
+
function encodetEXt(buffer, keyword, text13) {
|
|
54133
54602
|
validateKeyword(keyword);
|
|
54134
|
-
validateLatin1(
|
|
54135
|
-
const length = keyword.length + 1 +
|
|
54603
|
+
validateLatin1(text13);
|
|
54604
|
+
const length = keyword.length + 1 + text13.length;
|
|
54136
54605
|
buffer.writeUint32(length);
|
|
54137
54606
|
buffer.writeChars(exports.textChunkName);
|
|
54138
54607
|
buffer.writeChars(keyword);
|
|
54139
54608
|
buffer.writeByte(NULL);
|
|
54140
|
-
buffer.writeChars(
|
|
54609
|
+
buffer.writeChars(text13);
|
|
54141
54610
|
(0, crc_1.writeCrc)(buffer, length + 4);
|
|
54142
54611
|
}
|
|
54143
54612
|
function readKeyword(buffer) {
|
|
@@ -54721,8 +55190,8 @@ var require_PngEncoder = __commonJS({
|
|
|
54721
55190
|
}
|
|
54722
55191
|
this.encodeData();
|
|
54723
55192
|
if (this._png.text) {
|
|
54724
|
-
for (const [keyword,
|
|
54725
|
-
(0, text_1.encodetEXt)(this, keyword,
|
|
55193
|
+
for (const [keyword, text13] of Object.entries(this._png.text)) {
|
|
55194
|
+
(0, text_1.encodetEXt)(this, keyword, text13);
|
|
54726
55195
|
}
|
|
54727
55196
|
}
|
|
54728
55197
|
this.encodeIEND();
|
|
@@ -58908,8 +59377,8 @@ var require_build = __commonJS({
|
|
|
58908
59377
|
var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
58909
59378
|
var BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
|
|
58910
59379
|
var Utf8Converter = class {
|
|
58911
|
-
static fromString(
|
|
58912
|
-
const s = unescape(encodeURIComponent(
|
|
59380
|
+
static fromString(text13) {
|
|
59381
|
+
const s = unescape(encodeURIComponent(text13));
|
|
58913
59382
|
const uintArray = new Uint8Array(s.length);
|
|
58914
59383
|
for (let i = 0; i < s.length; i++) {
|
|
58915
59384
|
uintArray[i] = s.charCodeAt(i);
|
|
@@ -58937,11 +59406,11 @@ var require_build = __commonJS({
|
|
|
58937
59406
|
}
|
|
58938
59407
|
return res;
|
|
58939
59408
|
}
|
|
58940
|
-
static fromString(
|
|
58941
|
-
const res = new ArrayBuffer(
|
|
59409
|
+
static fromString(text13, littleEndian = false) {
|
|
59410
|
+
const res = new ArrayBuffer(text13.length * 2);
|
|
58942
59411
|
const dataView = new DataView(res);
|
|
58943
|
-
for (let i = 0; i <
|
|
58944
|
-
dataView.setUint16(i * 2,
|
|
59412
|
+
for (let i = 0; i < text13.length; i++) {
|
|
59413
|
+
dataView.setUint16(i * 2, text13.charCodeAt(i), littleEndian);
|
|
58945
59414
|
}
|
|
58946
59415
|
return res;
|
|
58947
59416
|
}
|
|
@@ -59038,18 +59507,18 @@ var require_build = __commonJS({
|
|
|
59038
59507
|
static ToBase64Url(data) {
|
|
59039
59508
|
return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
|
|
59040
59509
|
}
|
|
59041
|
-
static FromUtf8String(
|
|
59510
|
+
static FromUtf8String(text13, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
|
|
59042
59511
|
switch (encoding) {
|
|
59043
59512
|
case "ascii":
|
|
59044
|
-
return this.FromBinary(
|
|
59513
|
+
return this.FromBinary(text13);
|
|
59045
59514
|
case "utf8":
|
|
59046
|
-
return Utf8Converter.fromString(
|
|
59515
|
+
return Utf8Converter.fromString(text13);
|
|
59047
59516
|
case "utf16":
|
|
59048
59517
|
case "utf16be":
|
|
59049
|
-
return Utf16Converter.fromString(
|
|
59518
|
+
return Utf16Converter.fromString(text13);
|
|
59050
59519
|
case "utf16le":
|
|
59051
59520
|
case "usc2":
|
|
59052
|
-
return Utf16Converter.fromString(
|
|
59521
|
+
return Utf16Converter.fromString(text13, true);
|
|
59053
59522
|
default:
|
|
59054
59523
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
59055
59524
|
}
|
|
@@ -59070,11 +59539,11 @@ var require_build = __commonJS({
|
|
|
59070
59539
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
59071
59540
|
}
|
|
59072
59541
|
}
|
|
59073
|
-
static FromBinary(
|
|
59074
|
-
const stringLength =
|
|
59542
|
+
static FromBinary(text13) {
|
|
59543
|
+
const stringLength = text13.length;
|
|
59075
59544
|
const resultView = new Uint8Array(stringLength);
|
|
59076
59545
|
for (let i = 0; i < stringLength; i++) {
|
|
59077
|
-
resultView[i] =
|
|
59546
|
+
resultView[i] = text13.charCodeAt(i);
|
|
59078
59547
|
}
|
|
59079
59548
|
return resultView.buffer;
|
|
59080
59549
|
}
|
|
@@ -59120,8 +59589,8 @@ var require_build = __commonJS({
|
|
|
59120
59589
|
static ToUtf16String(buffer, littleEndian = false) {
|
|
59121
59590
|
return Utf16Converter.toString(buffer, littleEndian);
|
|
59122
59591
|
}
|
|
59123
|
-
static FromUtf16String(
|
|
59124
|
-
return Utf16Converter.fromString(
|
|
59592
|
+
static FromUtf16String(text13, littleEndian = false) {
|
|
59593
|
+
return Utf16Converter.fromString(text13, littleEndian);
|
|
59125
59594
|
}
|
|
59126
59595
|
static Base64Padding(base643) {
|
|
59127
59596
|
const padCount = 4 - base643.length % 4;
|
|
@@ -62882,15 +63351,15 @@ var require_sequence = __commonJS({
|
|
|
62882
63351
|
}
|
|
62883
63352
|
return normalized;
|
|
62884
63353
|
}
|
|
62885
|
-
function encodeAscii(
|
|
62886
|
-
const bytes3 = new Uint8Array(
|
|
62887
|
-
for (let i = 0; i <
|
|
62888
|
-
bytes3[i] =
|
|
63354
|
+
function encodeAscii(text13) {
|
|
63355
|
+
const bytes3 = new Uint8Array(text13.length);
|
|
63356
|
+
for (let i = 0; i < text13.length; i++) {
|
|
63357
|
+
bytes3[i] = text13.charCodeAt(i) & 255;
|
|
62889
63358
|
}
|
|
62890
63359
|
return bytes3;
|
|
62891
63360
|
}
|
|
62892
|
-
function encodeUtf8(
|
|
62893
|
-
return new TextEncoder().encode(
|
|
63361
|
+
function encodeUtf8(text13) {
|
|
63362
|
+
return new TextEncoder().encode(text13);
|
|
62894
63363
|
}
|
|
62895
63364
|
function toPatternBytes(pattern, options) {
|
|
62896
63365
|
if (typeof pattern === "string") {
|
|
@@ -64265,15 +64734,15 @@ var require_binary = __commonJS({
|
|
|
64265
64734
|
}
|
|
64266
64735
|
return result;
|
|
64267
64736
|
}
|
|
64268
|
-
function decode3(
|
|
64269
|
-
const result = new Uint8Array(
|
|
64270
|
-
for (let i = 0; i <
|
|
64271
|
-
result[i] =
|
|
64737
|
+
function decode3(text13) {
|
|
64738
|
+
const result = new Uint8Array(text13.length);
|
|
64739
|
+
for (let i = 0; i < text13.length; i++) {
|
|
64740
|
+
result[i] = text13.charCodeAt(i) & 255;
|
|
64272
64741
|
}
|
|
64273
64742
|
return result;
|
|
64274
64743
|
}
|
|
64275
|
-
function is(
|
|
64276
|
-
return typeof
|
|
64744
|
+
function is(text13) {
|
|
64745
|
+
return typeof text13 === "string";
|
|
64277
64746
|
}
|
|
64278
64747
|
exports.binary = { encode: encode3, decode: decode3, is };
|
|
64279
64748
|
}
|
|
@@ -64308,31 +64777,31 @@ var require_hex = __commonJS({
|
|
|
64308
64777
|
throw new TypeError("Hex separators must be non-empty strings");
|
|
64309
64778
|
}
|
|
64310
64779
|
}
|
|
64311
|
-
function matchSeparator(
|
|
64780
|
+
function matchSeparator(text13, index, separators) {
|
|
64312
64781
|
for (const separator of separators) {
|
|
64313
|
-
if (
|
|
64782
|
+
if (text13.startsWith(separator, index)) {
|
|
64314
64783
|
return separator;
|
|
64315
64784
|
}
|
|
64316
64785
|
}
|
|
64317
64786
|
return void 0;
|
|
64318
64787
|
}
|
|
64319
|
-
function detectCase(
|
|
64320
|
-
const hasUpper = /[A-F]/.test(
|
|
64321
|
-
const hasLower = /[a-f]/.test(
|
|
64788
|
+
function detectCase(text13) {
|
|
64789
|
+
const hasUpper = /[A-F]/.test(text13);
|
|
64790
|
+
const hasLower = /[a-f]/.test(text13);
|
|
64322
64791
|
return hasUpper && !hasLower ? "upper" : "lower";
|
|
64323
64792
|
}
|
|
64324
|
-
function detectLineSeparator(
|
|
64325
|
-
const match = /\r\n|\n/.exec(
|
|
64793
|
+
function detectLineSeparator(text13) {
|
|
64794
|
+
const match = /\r\n|\n/.exec(text13);
|
|
64326
64795
|
if (!match) {
|
|
64327
64796
|
return void 0;
|
|
64328
64797
|
}
|
|
64329
64798
|
return match[0] === "\r\n" ? "\r\n" : "\n";
|
|
64330
64799
|
}
|
|
64331
|
-
function compactForDetection(
|
|
64332
|
-
return
|
|
64800
|
+
function compactForDetection(text13) {
|
|
64801
|
+
return text13.replace(/[^0-9a-f]/gi, "");
|
|
64333
64802
|
}
|
|
64334
|
-
function detectGroup(
|
|
64335
|
-
const segments =
|
|
64803
|
+
function detectGroup(text13) {
|
|
64804
|
+
const segments = text13.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
|
|
64336
64805
|
if (segments.length < 3) {
|
|
64337
64806
|
return void 0;
|
|
64338
64807
|
}
|
|
@@ -64360,8 +64829,8 @@ var require_hex = __commonJS({
|
|
|
64360
64829
|
separator
|
|
64361
64830
|
};
|
|
64362
64831
|
}
|
|
64363
|
-
function detectFormat(
|
|
64364
|
-
const trimmed =
|
|
64832
|
+
function detectFormat(text13) {
|
|
64833
|
+
const trimmed = text13.trim();
|
|
64365
64834
|
const prefix = /^0x/i.test(trimmed) ? "0x" : "";
|
|
64366
64835
|
const body = prefix ? trimmed.slice(2) : trimmed;
|
|
64367
64836
|
const lineSeparator = detectLineSeparator(body);
|
|
@@ -64386,13 +64855,13 @@ var require_hex = __commonJS({
|
|
|
64386
64855
|
}
|
|
64387
64856
|
return format2;
|
|
64388
64857
|
}
|
|
64389
|
-
function normalizeText(
|
|
64858
|
+
function normalizeText(text13, options) {
|
|
64390
64859
|
const allowPrefix = options.allowPrefix ?? true;
|
|
64391
64860
|
const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
|
|
64392
64861
|
for (const separator of separators) {
|
|
64393
64862
|
validateSeparator(separator);
|
|
64394
64863
|
}
|
|
64395
|
-
let working =
|
|
64864
|
+
let working = text13.trim();
|
|
64396
64865
|
if (/^0x/i.test(working)) {
|
|
64397
64866
|
if (!allowPrefix) {
|
|
64398
64867
|
throw new TypeError("Hexadecimal text must not include a 0x prefix");
|
|
@@ -64443,15 +64912,15 @@ var require_hex = __commonJS({
|
|
|
64443
64912
|
}
|
|
64444
64913
|
return chunks.join(group.separator);
|
|
64445
64914
|
}
|
|
64446
|
-
function normalize3(
|
|
64447
|
-
return normalizeText(
|
|
64915
|
+
function normalize3(text13, options = {}) {
|
|
64916
|
+
return normalizeText(text13, options);
|
|
64448
64917
|
}
|
|
64449
|
-
function is(
|
|
64450
|
-
if (typeof
|
|
64918
|
+
function is(text13, options = {}) {
|
|
64919
|
+
if (typeof text13 !== "string") {
|
|
64451
64920
|
return false;
|
|
64452
64921
|
}
|
|
64453
64922
|
try {
|
|
64454
|
-
normalize3(
|
|
64923
|
+
normalize3(text13, options);
|
|
64455
64924
|
return true;
|
|
64456
64925
|
} catch {
|
|
64457
64926
|
return false;
|
|
@@ -64461,8 +64930,8 @@ var require_hex = __commonJS({
|
|
|
64461
64930
|
const bytes3 = (0, index_js_1.toUint8Array)(data);
|
|
64462
64931
|
const casing = options.case ?? "lower";
|
|
64463
64932
|
const pairs = Array.from(bytes3, (byte) => {
|
|
64464
|
-
const
|
|
64465
|
-
return casing === "upper" ?
|
|
64933
|
+
const text13 = byte.toString(16).padStart(2, "0");
|
|
64934
|
+
return casing === "upper" ? text13.toUpperCase() : text13;
|
|
64466
64935
|
});
|
|
64467
64936
|
let body = "";
|
|
64468
64937
|
if (options.line) {
|
|
@@ -64481,19 +64950,19 @@ var require_hex = __commonJS({
|
|
|
64481
64950
|
}
|
|
64482
64951
|
return `${options.prefix ?? ""}${body}`;
|
|
64483
64952
|
}
|
|
64484
|
-
function decode3(
|
|
64485
|
-
const normalized = normalize3(
|
|
64953
|
+
function decode3(text13, options = {}) {
|
|
64954
|
+
const normalized = normalize3(text13, options);
|
|
64486
64955
|
const result = new Uint8Array(normalized.length / 2);
|
|
64487
64956
|
for (let i = 0; i < normalized.length; i += 2) {
|
|
64488
64957
|
result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
|
|
64489
64958
|
}
|
|
64490
64959
|
return result;
|
|
64491
64960
|
}
|
|
64492
|
-
function parse4(
|
|
64493
|
-
const normalized = normalize3(
|
|
64961
|
+
function parse4(text13, options = {}) {
|
|
64962
|
+
const normalized = normalize3(text13, options);
|
|
64494
64963
|
return {
|
|
64495
64964
|
bytes: decode3(normalized),
|
|
64496
|
-
format: detectFormat(
|
|
64965
|
+
format: detectFormat(text13),
|
|
64497
64966
|
normalized
|
|
64498
64967
|
};
|
|
64499
64968
|
}
|
|
@@ -64521,8 +64990,8 @@ var require_utf8 = __commonJS({
|
|
|
64521
64990
|
exports.encode = encode3;
|
|
64522
64991
|
exports.decode = decode3;
|
|
64523
64992
|
var index_js_1 = require_bytes();
|
|
64524
|
-
function encode3(
|
|
64525
|
-
return new TextEncoder().encode(
|
|
64993
|
+
function encode3(text13) {
|
|
64994
|
+
return new TextEncoder().encode(text13);
|
|
64526
64995
|
}
|
|
64527
64996
|
function decode3(data) {
|
|
64528
64997
|
return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
|
|
@@ -64540,11 +65009,11 @@ var require_utf16 = __commonJS({
|
|
|
64540
65009
|
exports.encode = encode3;
|
|
64541
65010
|
exports.decode = decode3;
|
|
64542
65011
|
var index_js_1 = require_bytes();
|
|
64543
|
-
function encode3(
|
|
64544
|
-
const result = new ArrayBuffer(
|
|
65012
|
+
function encode3(text13, options = {}) {
|
|
65013
|
+
const result = new ArrayBuffer(text13.length * 2);
|
|
64545
65014
|
const view = new DataView(result);
|
|
64546
|
-
for (let i = 0; i <
|
|
64547
|
-
view.setUint16(i * 2,
|
|
65015
|
+
for (let i = 0; i < text13.length; i++) {
|
|
65016
|
+
view.setUint16(i * 2, text13.charCodeAt(i), options.littleEndian ?? false);
|
|
64548
65017
|
}
|
|
64549
65018
|
return new Uint8Array(result);
|
|
64550
65019
|
}
|
|
@@ -64578,18 +65047,18 @@ var require_base64 = __commonJS({
|
|
|
64578
65047
|
function nodeBuffer() {
|
|
64579
65048
|
return globalThis.Buffer;
|
|
64580
65049
|
}
|
|
64581
|
-
function normalize3(
|
|
64582
|
-
return
|
|
65050
|
+
function normalize3(text13) {
|
|
65051
|
+
return text13.replace(/[\n\r\t ]/g, "");
|
|
64583
65052
|
}
|
|
64584
|
-
function pad2(
|
|
64585
|
-
const remainder =
|
|
64586
|
-
return remainder ?
|
|
65053
|
+
function pad2(text13) {
|
|
65054
|
+
const remainder = text13.length % 4;
|
|
65055
|
+
return remainder ? text13 + "=".repeat(4 - remainder) : text13;
|
|
64587
65056
|
}
|
|
64588
|
-
function is(
|
|
64589
|
-
if (typeof
|
|
65057
|
+
function is(text13) {
|
|
65058
|
+
if (typeof text13 !== "string") {
|
|
64590
65059
|
return false;
|
|
64591
65060
|
}
|
|
64592
|
-
const normalized = normalize3(
|
|
65061
|
+
const normalized = normalize3(text13);
|
|
64593
65062
|
return normalized === "" || BASE64_REGEX.test(normalized);
|
|
64594
65063
|
}
|
|
64595
65064
|
function encode3(data, _options) {
|
|
@@ -64600,8 +65069,8 @@ var require_base64 = __commonJS({
|
|
|
64600
65069
|
}
|
|
64601
65070
|
return btoa((0, binary_js_1.encode)(bytes3));
|
|
64602
65071
|
}
|
|
64603
|
-
function decode3(
|
|
64604
|
-
const normalized = normalize3(
|
|
65072
|
+
function decode3(text13, _options) {
|
|
65073
|
+
const normalized = normalize3(text13);
|
|
64605
65074
|
if (!is(normalized)) {
|
|
64606
65075
|
throw new TypeError("Input is not valid Base64 text");
|
|
64607
65076
|
}
|
|
@@ -64627,17 +65096,17 @@ var require_base64url = __commonJS({
|
|
|
64627
65096
|
exports.decode = decode3;
|
|
64628
65097
|
var base64_js_1 = require_base64();
|
|
64629
65098
|
var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
|
|
64630
|
-
function normalize3(
|
|
64631
|
-
return
|
|
65099
|
+
function normalize3(text13) {
|
|
65100
|
+
return text13.replace(/[\n\r\t ]/g, "");
|
|
64632
65101
|
}
|
|
64633
|
-
function is(
|
|
64634
|
-
return typeof
|
|
65102
|
+
function is(text13) {
|
|
65103
|
+
return typeof text13 === "string" && BASE64URL_REGEX.test(normalize3(text13));
|
|
64635
65104
|
}
|
|
64636
65105
|
function encode3(data, _options) {
|
|
64637
65106
|
return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
64638
65107
|
}
|
|
64639
|
-
function decode3(
|
|
64640
|
-
const normalized = normalize3(
|
|
65108
|
+
function decode3(text13, _options) {
|
|
65109
|
+
const normalized = normalize3(text13);
|
|
64641
65110
|
if (!is(normalized)) {
|
|
64642
65111
|
throw new TypeError("Input is not valid Base64Url text");
|
|
64643
65112
|
}
|
|
@@ -64758,8 +65227,8 @@ var require_ip_converter = __commonJS({
|
|
|
64758
65227
|
}
|
|
64759
65228
|
return ip;
|
|
64760
65229
|
}
|
|
64761
|
-
static parseCIDR(
|
|
64762
|
-
const [addr, prefixStr] =
|
|
65230
|
+
static parseCIDR(text13) {
|
|
65231
|
+
const [addr, prefixStr] = text13.split("/");
|
|
64763
65232
|
const prefix = parseInt(prefixStr, 10);
|
|
64764
65233
|
if (this.isIPv4(addr)) {
|
|
64765
65234
|
if (prefix < 0 || prefix > 32) {
|
|
@@ -64812,9 +65281,9 @@ var require_ip_converter = __commonJS({
|
|
|
64812
65281
|
}
|
|
64813
65282
|
return this.decodeIP(encoding_1.hex.encode(buf));
|
|
64814
65283
|
}
|
|
64815
|
-
static fromString(
|
|
64816
|
-
if (
|
|
64817
|
-
const [addr, prefix] = this.parseCIDR(
|
|
65284
|
+
static fromString(text13) {
|
|
65285
|
+
if (text13.includes("/")) {
|
|
65286
|
+
const [addr, prefix] = this.parseCIDR(text13);
|
|
64818
65287
|
const maskBytes = new Uint8Array(addr.length);
|
|
64819
65288
|
let bitsLeft = prefix;
|
|
64820
65289
|
for (let i = 0; i < maskBytes.length; i++) {
|
|
@@ -64831,7 +65300,7 @@ var require_ip_converter = __commonJS({
|
|
|
64831
65300
|
out.set(maskBytes, addr.length);
|
|
64832
65301
|
return out.buffer;
|
|
64833
65302
|
}
|
|
64834
|
-
const bytes3 = this.isIPv4(
|
|
65303
|
+
const bytes3 = this.isIPv4(text13) ? this.parseIPv4(text13) : this.parseIPv6(text13);
|
|
64835
65304
|
return new Uint8Array(bytes3).buffer;
|
|
64836
65305
|
}
|
|
64837
65306
|
};
|
|
@@ -72511,24 +72980,24 @@ var require_x509_cjs = __commonJS({
|
|
|
72511
72980
|
names.register("I", "2.5.4.43");
|
|
72512
72981
|
names.register("SN", "2.5.4.4");
|
|
72513
72982
|
names.register("T", "2.5.4.12");
|
|
72514
|
-
function replaceUnknownCharacter(
|
|
72983
|
+
function replaceUnknownCharacter(text13, char) {
|
|
72515
72984
|
return `\\${pvtsutils.Convert.ToHex(pvtsutils.Convert.FromUtf8String(char)).toUpperCase()}`;
|
|
72516
72985
|
}
|
|
72517
72986
|
function escape2(data) {
|
|
72518
72987
|
return data.replace(/([,+"\\<>;])/g, "\\$1").replace(/^([ #])/, "\\$1").replace(/([ ]$)/, "\\$1").replace(/([\r\n\t])/, replaceUnknownCharacter);
|
|
72519
72988
|
}
|
|
72520
72989
|
var Name = class _Name {
|
|
72521
|
-
static isASCII(
|
|
72522
|
-
for (let i = 0; i <
|
|
72523
|
-
const code =
|
|
72990
|
+
static isASCII(text13) {
|
|
72991
|
+
for (let i = 0; i < text13.length; i++) {
|
|
72992
|
+
const code = text13.charCodeAt(i);
|
|
72524
72993
|
if (code > 255) {
|
|
72525
72994
|
return false;
|
|
72526
72995
|
}
|
|
72527
72996
|
}
|
|
72528
72997
|
return true;
|
|
72529
72998
|
}
|
|
72530
|
-
static isPrintableString(
|
|
72531
|
-
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(
|
|
72999
|
+
static isPrintableString(text13) {
|
|
73000
|
+
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text13);
|
|
72532
73001
|
}
|
|
72533
73002
|
constructor(data, extraNames = {}) {
|
|
72534
73003
|
this.extraNames = new NameIdentifier();
|
|
@@ -77825,12 +78294,12 @@ function formatAddr(afi, addr) {
|
|
|
77825
78294
|
s = s + ":";
|
|
77826
78295
|
return s;
|
|
77827
78296
|
}
|
|
77828
|
-
function parsePrefix(
|
|
77829
|
-
const slash =
|
|
78297
|
+
function parsePrefix(text13) {
|
|
78298
|
+
const slash = text13.lastIndexOf("/");
|
|
77830
78299
|
if (slash < 0)
|
|
77831
|
-
throw new MeshCodecError("bad-value", `missing / in ${
|
|
77832
|
-
const host =
|
|
77833
|
-
const lenStr =
|
|
78300
|
+
throw new MeshCodecError("bad-value", `missing / in ${text13}`);
|
|
78301
|
+
const host = text13.slice(0, slash);
|
|
78302
|
+
const lenStr = text13.slice(slash + 1);
|
|
77834
78303
|
if (!/^\d{1,3}$/.test(lenStr))
|
|
77835
78304
|
throw new MeshCodecError("bad-value", `prefix len ${lenStr}`);
|
|
77836
78305
|
const len = Number(lenStr);
|
|
@@ -77839,15 +78308,15 @@ function parsePrefix(text12) {
|
|
|
77839
78308
|
throw new MeshCodecError("bad-value", `len ${len} for v${afi}`);
|
|
77840
78309
|
return makePrefix(afi, mask(addr, len), len);
|
|
77841
78310
|
}
|
|
77842
|
-
function parseAddr(
|
|
77843
|
-
if (
|
|
77844
|
-
return { afi: AFI_V6, addr: parseV6(
|
|
77845
|
-
return { afi: AFI_V4, addr: parseV4(
|
|
78311
|
+
function parseAddr(text13) {
|
|
78312
|
+
if (text13.includes(":"))
|
|
78313
|
+
return { afi: AFI_V6, addr: parseV6(text13) };
|
|
78314
|
+
return { afi: AFI_V4, addr: parseV4(text13) };
|
|
77846
78315
|
}
|
|
77847
|
-
function parseV4(
|
|
77848
|
-
const parts =
|
|
78316
|
+
function parseV4(text13) {
|
|
78317
|
+
const parts = text13.split(".");
|
|
77849
78318
|
if (parts.length !== 4)
|
|
77850
|
-
throw new MeshCodecError("bad-value", `bad IPv4 ${
|
|
78319
|
+
throw new MeshCodecError("bad-value", `bad IPv4 ${text13}`);
|
|
77851
78320
|
const out = new Uint8Array(4);
|
|
77852
78321
|
for (let i = 0; i < 4; i++) {
|
|
77853
78322
|
if (!/^(0|[1-9]\d{0,2})$/.test(parts[i]))
|
|
@@ -77859,22 +78328,22 @@ function parseV4(text12) {
|
|
|
77859
78328
|
}
|
|
77860
78329
|
return out;
|
|
77861
78330
|
}
|
|
77862
|
-
function parseV6(
|
|
77863
|
-
if (
|
|
77864
|
-
const halves =
|
|
78331
|
+
function parseV6(text13) {
|
|
78332
|
+
if (text13.includes("::")) {
|
|
78333
|
+
const halves = text13.split("::");
|
|
77865
78334
|
if (halves.length !== 2)
|
|
77866
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
78335
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
77867
78336
|
const head = halves[0] ? halves[0].split(":") : [];
|
|
77868
78337
|
const tail3 = halves[1] ? halves[1].split(":") : [];
|
|
77869
78338
|
if (head.length + tail3.length > 7)
|
|
77870
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
78339
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
77871
78340
|
const zeros = new Array(8 - head.length - tail3.length).fill("0");
|
|
77872
|
-
return groupsToBytes([...head, ...zeros, ...tail3],
|
|
78341
|
+
return groupsToBytes([...head, ...zeros, ...tail3], text13);
|
|
77873
78342
|
}
|
|
77874
|
-
const g =
|
|
78343
|
+
const g = text13.split(":");
|
|
77875
78344
|
if (g.length !== 8)
|
|
77876
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
77877
|
-
return groupsToBytes(g,
|
|
78345
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
78346
|
+
return groupsToBytes(g, text13);
|
|
77878
78347
|
}
|
|
77879
78348
|
function groupsToBytes(groups, orig) {
|
|
77880
78349
|
if (groups.length !== 8)
|
|
@@ -85802,13 +86271,18 @@ function scheduledTurn(a) {
|
|
|
85802
86271
|
// Absent ⇒ for a cron turn that is 'safe' (unattendedModeFor): declined rather than parked, and nothing
|
|
85803
86272
|
// approved on anyone's behalf.
|
|
85804
86273
|
unattended: a.target ? a.prev?.unattended : a.policy.unattended ? true : void 0,
|
|
85805
|
-
...a.target ? {} : { reinforcedVerification: a.policy.reinforcedVerification ? true : void 0 }
|
|
86274
|
+
...a.target ? {} : { reinforcedVerification: a.policy.reinforcedVerification ? true : void 0 },
|
|
86275
|
+
// THE PERSON'S SETTINGS — their block rules above all — on a fire that OPENS a conversation and so has
|
|
86276
|
+
// no last send to replay them from. Without this the 3am run, the one nobody is watching, is the one
|
|
86277
|
+
// turn their rules do not reach (permission-rules.ts enforces them from exactly this field).
|
|
86278
|
+
...a.target ? {} : { settings: a.policy.settings }
|
|
85806
86279
|
};
|
|
85807
86280
|
}
|
|
85808
86281
|
function createHostedScheduling(fire) {
|
|
85809
86282
|
let store = null;
|
|
85810
86283
|
let isUnattended;
|
|
85811
86284
|
let isVerified;
|
|
86285
|
+
let settings;
|
|
85812
86286
|
let stopScheduler = null;
|
|
85813
86287
|
let cronDeps = { pushEnabled: false };
|
|
85814
86288
|
let cron = null;
|
|
@@ -85832,6 +86306,7 @@ function createHostedScheduling(fire) {
|
|
|
85832
86306
|
stopScheduler = null;
|
|
85833
86307
|
isUnattended = cfg2.isUnattended ?? isUnattended;
|
|
85834
86308
|
isVerified = cfg2.isVerified ?? isVerified;
|
|
86309
|
+
settings = cfg2.settings ?? settings;
|
|
85835
86310
|
if (!cfg2.enabled) {
|
|
85836
86311
|
store = null;
|
|
85837
86312
|
cronTools = [];
|
|
@@ -85871,7 +86346,11 @@ function createHostedScheduling(fire) {
|
|
|
85871
86346
|
})();
|
|
85872
86347
|
},
|
|
85873
86348
|
policy() {
|
|
85874
|
-
return {
|
|
86349
|
+
return {
|
|
86350
|
+
unattended: isUnattended?.() === true,
|
|
86351
|
+
reinforcedVerification: isVerified?.() === true,
|
|
86352
|
+
settings: settings?.()
|
|
86353
|
+
};
|
|
85875
86354
|
},
|
|
85876
86355
|
beginFire(taskId) {
|
|
85877
86356
|
const id = `cron:${taskId}:${randomUUID12().slice(0, 8)}`;
|
|
@@ -85974,8 +86453,8 @@ function listOf(items) {
|
|
|
85974
86453
|
const words = items.map((i) => i.text);
|
|
85975
86454
|
return words.length === 1 ? words[0] : `${words.slice(0, -1).join(", ")} and ${words[words.length - 1]}`;
|
|
85976
86455
|
}
|
|
85977
|
-
function sentence(
|
|
85978
|
-
return `${
|
|
86456
|
+
function sentence(text13) {
|
|
86457
|
+
return `${text13[0].toUpperCase()}${text13.slice(1)}`;
|
|
85979
86458
|
}
|
|
85980
86459
|
function unappliedSettingsNotice(engineLabel, settings, at, inForce = {}) {
|
|
85981
86460
|
const { items, protective } = unappliedSettings(settings, inForce);
|
|
@@ -86011,24 +86490,24 @@ var SHELL_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell", "Shell"]);
|
|
|
86011
86490
|
var WRITE_TOOLS = /* @__PURE__ */ new Set(["Edit", "MultiEdit", "Write", "NotebookEdit"]);
|
|
86012
86491
|
var READ_TOOLS = /* @__PURE__ */ new Set(["Read", "NotebookRead"]);
|
|
86013
86492
|
var PATH_TOOLS = /* @__PURE__ */ new Set([...WRITE_TOOLS, ...READ_TOOLS]);
|
|
86014
|
-
function indexOfUnescaped(
|
|
86015
|
-
for (let i = 0; i <
|
|
86016
|
-
if (
|
|
86493
|
+
function indexOfUnescaped(text13, char) {
|
|
86494
|
+
for (let i = 0; i < text13.length; i++) {
|
|
86495
|
+
if (text13[i] !== char)
|
|
86017
86496
|
continue;
|
|
86018
86497
|
let back = 0;
|
|
86019
|
-
for (let j = i - 1; j >= 0 &&
|
|
86498
|
+
for (let j = i - 1; j >= 0 && text13[j] === "\\"; j--)
|
|
86020
86499
|
back++;
|
|
86021
86500
|
if (back % 2 === 0)
|
|
86022
86501
|
return i;
|
|
86023
86502
|
}
|
|
86024
86503
|
return -1;
|
|
86025
86504
|
}
|
|
86026
|
-
function lastIndexOfUnescaped(
|
|
86027
|
-
for (let i =
|
|
86028
|
-
if (
|
|
86505
|
+
function lastIndexOfUnescaped(text13, char) {
|
|
86506
|
+
for (let i = text13.length - 1; i >= 0; i--) {
|
|
86507
|
+
if (text13[i] !== char)
|
|
86029
86508
|
continue;
|
|
86030
86509
|
let back = 0;
|
|
86031
|
-
for (let j = i - 1; j >= 0 &&
|
|
86510
|
+
for (let j = i - 1; j >= 0 && text13[j] === "\\"; j--)
|
|
86032
86511
|
back++;
|
|
86033
86512
|
if (back % 2 === 0)
|
|
86034
86513
|
return i;
|
|
@@ -86092,12 +86571,12 @@ function rulesOutOfReach(rules, reach) {
|
|
|
86092
86571
|
return true;
|
|
86093
86572
|
});
|
|
86094
86573
|
}
|
|
86095
|
-
function ruleRequestFor(
|
|
86574
|
+
function ruleRequestFor(tool22, detail) {
|
|
86096
86575
|
const input = detail.input ?? {};
|
|
86097
86576
|
const command = commandText(input.command);
|
|
86098
86577
|
const changed = Array.isArray(input.changes) ? input.changes.map((c) => typeof c?.path === "string" ? c.path : void 0) : [];
|
|
86099
86578
|
const paths = [...detail.paths ?? [], detail.path, typeof input.path === "string" ? input.path : void 0, ...changed].filter((p) => typeof p === "string" && p.length > 0);
|
|
86100
|
-
return { tool:
|
|
86579
|
+
return { tool: tool22, ...command ? { command } : {}, ...paths.length ? { paths } : {} };
|
|
86101
86580
|
}
|
|
86102
86581
|
function commandText(command) {
|
|
86103
86582
|
if (typeof command === "string")
|
|
@@ -86111,9 +86590,9 @@ function describeRuleRequest(request2) {
|
|
|
86111
86590
|
return `\`${request2.command}\``;
|
|
86112
86591
|
const paths = request2.paths ?? [];
|
|
86113
86592
|
if (paths.length === 1)
|
|
86114
|
-
return paths[0]
|
|
86593
|
+
return `\`${paths[0]}\``;
|
|
86115
86594
|
if (paths.length > 1)
|
|
86116
|
-
return
|
|
86595
|
+
return `\`${paths[0]}\` and ${paths.length - 1} more`;
|
|
86117
86596
|
return `a ${request2.tool} call`;
|
|
86118
86597
|
}
|
|
86119
86598
|
function toolNameForRules(kind, name) {
|
|
@@ -86127,6 +86606,8 @@ function toolNameForRules(kind, name) {
|
|
|
86127
86606
|
case "write":
|
|
86128
86607
|
case "file":
|
|
86129
86608
|
case "filechange":
|
|
86609
|
+
case "delete":
|
|
86610
|
+
case "move":
|
|
86130
86611
|
return "Edit";
|
|
86131
86612
|
case "read":
|
|
86132
86613
|
return "Read";
|
|
@@ -86157,12 +86638,13 @@ function commandCandidates(command, depth = 0) {
|
|
|
86157
86638
|
add2(command);
|
|
86158
86639
|
for (const part of splitOnOperators(command)) {
|
|
86159
86640
|
add2(part);
|
|
86160
|
-
const bare
|
|
86161
|
-
|
|
86162
|
-
|
|
86163
|
-
|
|
86164
|
-
|
|
86165
|
-
|
|
86641
|
+
for (const bare of [part, ...wrapperPeels(part)]) {
|
|
86642
|
+
add2(bare);
|
|
86643
|
+
if (depth < 3)
|
|
86644
|
+
for (const inner of unwrapped(bare))
|
|
86645
|
+
for (const c of commandCandidates(inner, depth + 1))
|
|
86646
|
+
add2(c);
|
|
86647
|
+
}
|
|
86166
86648
|
}
|
|
86167
86649
|
return [...out];
|
|
86168
86650
|
}
|
|
@@ -86208,18 +86690,60 @@ function splitOnOperators(command) {
|
|
|
86208
86690
|
parts.push(current);
|
|
86209
86691
|
return parts.map((p) => p.trim()).filter(Boolean);
|
|
86210
86692
|
}
|
|
86211
|
-
|
|
86212
|
-
|
|
86213
|
-
|
|
86214
|
-
|
|
86215
|
-
|
|
86216
|
-
|
|
86217
|
-
|
|
86218
|
-
|
|
86219
|
-
|
|
86220
|
-
|
|
86693
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
86694
|
+
"sudo",
|
|
86695
|
+
"doas",
|
|
86696
|
+
"command",
|
|
86697
|
+
"builtin",
|
|
86698
|
+
"exec",
|
|
86699
|
+
"nohup",
|
|
86700
|
+
"stdbuf",
|
|
86701
|
+
"nice",
|
|
86702
|
+
"ionice",
|
|
86703
|
+
"env",
|
|
86704
|
+
"xargs",
|
|
86705
|
+
"time",
|
|
86706
|
+
"timeout"
|
|
86707
|
+
]);
|
|
86708
|
+
function wrapperPeels(command) {
|
|
86709
|
+
const ENV = /^[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S*)\s+/;
|
|
86710
|
+
const WORD = /^(\S+)\s+/;
|
|
86711
|
+
const out = [];
|
|
86712
|
+
const seen = /* @__PURE__ */ new Set();
|
|
86713
|
+
const queue3 = [command.trim()];
|
|
86714
|
+
while (queue3.length && out.length < 24) {
|
|
86715
|
+
const rest = queue3.shift();
|
|
86716
|
+
if (!rest || seen.has(rest))
|
|
86717
|
+
continue;
|
|
86718
|
+
seen.add(rest);
|
|
86719
|
+
const keep = (next2) => {
|
|
86720
|
+
if (next2) {
|
|
86721
|
+
out.push(next2);
|
|
86722
|
+
queue3.push(next2);
|
|
86723
|
+
}
|
|
86724
|
+
};
|
|
86725
|
+
const env = ENV.exec(rest);
|
|
86726
|
+
if (env) {
|
|
86727
|
+
keep(rest.slice(env[0].length));
|
|
86728
|
+
continue;
|
|
86729
|
+
}
|
|
86730
|
+
const word = WORD.exec(rest);
|
|
86731
|
+
if (!word)
|
|
86732
|
+
continue;
|
|
86733
|
+
const token4 = word[1];
|
|
86734
|
+
const isFlag = token4.startsWith("-");
|
|
86735
|
+
const isDuration = /^\d+(?:\.\d+)?[smhd]?$/.test(token4);
|
|
86736
|
+
if (!WRAPPERS.has(token4) && !isFlag && !isDuration)
|
|
86737
|
+
continue;
|
|
86738
|
+
const next = rest.slice(word[0].length);
|
|
86739
|
+
keep(next);
|
|
86740
|
+
if (isFlag) {
|
|
86741
|
+
const value = WORD.exec(next);
|
|
86742
|
+
if (value && !value[1].startsWith("-"))
|
|
86743
|
+
keep(next.slice(value[0].length));
|
|
86744
|
+
}
|
|
86221
86745
|
}
|
|
86222
|
-
return out
|
|
86746
|
+
return out;
|
|
86223
86747
|
}
|
|
86224
86748
|
function unwrapped(command) {
|
|
86225
86749
|
const out = [];
|
|
@@ -86231,8 +86755,8 @@ function unwrapped(command) {
|
|
|
86231
86755
|
out.push(stripQuotes(evaled[1]));
|
|
86232
86756
|
return out;
|
|
86233
86757
|
}
|
|
86234
|
-
function stripQuotes(
|
|
86235
|
-
const t =
|
|
86758
|
+
function stripQuotes(text13) {
|
|
86759
|
+
const t = text13.trim();
|
|
86236
86760
|
if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'"))
|
|
86237
86761
|
return t.slice(1, -1);
|
|
86238
86762
|
return t;
|
|
@@ -86259,14 +86783,14 @@ function hasWildcard(pattern) {
|
|
|
86259
86783
|
}
|
|
86260
86784
|
return false;
|
|
86261
86785
|
}
|
|
86262
|
-
function matchesWildcard(pattern,
|
|
86786
|
+
function matchesWildcard(pattern, text13) {
|
|
86263
86787
|
const STAR = `${MARK}S${MARK}`;
|
|
86264
86788
|
const BACK = `${MARK}B${MARK}`;
|
|
86265
86789
|
const processed = pattern.trim().replace(/\\\*/g, STAR).replace(/\\\\/g, BACK);
|
|
86266
86790
|
let regex = processed.replace(/[.+?^${}()|[\]\\'"]/g, "\\$&").replace(/\*/g, ".*").split(STAR).join("\\*").split(BACK).join("\\\\");
|
|
86267
86791
|
if (regex.endsWith(" .*") && (processed.match(/\*/g) ?? []).length === 1)
|
|
86268
86792
|
regex = `${regex.slice(0, -3)}( .*)?`;
|
|
86269
|
-
return new RegExp(`^${regex}$`, "s").test(
|
|
86793
|
+
return new RegExp(`^${regex}$`, "s").test(text13.trim());
|
|
86270
86794
|
}
|
|
86271
86795
|
var BLOCKED_BY_RULE_NOTICE_ID = "blocked-by-rule";
|
|
86272
86796
|
function blockedByRuleNotice(engineLabel, at, blocked) {
|
|
@@ -86303,10 +86827,6 @@ function opencodeBashDeny(rules) {
|
|
|
86303
86827
|
}
|
|
86304
86828
|
const prefix = /^(.+):\*$/.exec(content)?.[1];
|
|
86305
86829
|
const pattern = prefix !== void 0 ? `${prefix} *` : content;
|
|
86306
|
-
if (prefix === void 0 && !hasWildcard(content) && content.includes("*")) {
|
|
86307
|
-
untranslated.push(rule);
|
|
86308
|
-
continue;
|
|
86309
|
-
}
|
|
86310
86830
|
patterns.push(pattern, `sudo ${pattern}`, `xargs ${pattern}`);
|
|
86311
86831
|
expressed.push(rule);
|
|
86312
86832
|
}
|
|
@@ -86321,16 +86841,16 @@ function matchesPath(pattern, path6) {
|
|
|
86321
86841
|
}
|
|
86322
86842
|
|
|
86323
86843
|
// ../../packages/host-core/dist/engines/message-locator.js
|
|
86324
|
-
function newestSentMessageWithText(messages,
|
|
86325
|
-
if (!
|
|
86844
|
+
function newestSentMessageWithText(messages, text13) {
|
|
86845
|
+
if (!text13)
|
|
86326
86846
|
return void 0;
|
|
86327
86847
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
86328
86848
|
const m = messages[i];
|
|
86329
86849
|
if (m.role !== "user" || !m.id)
|
|
86330
86850
|
continue;
|
|
86331
|
-
if (m.text ===
|
|
86851
|
+
if (m.text === text13 || m.text.endsWith(`
|
|
86332
86852
|
|
|
86333
|
-
${
|
|
86853
|
+
${text13}`))
|
|
86334
86854
|
return m.id;
|
|
86335
86855
|
}
|
|
86336
86856
|
return void 0;
|
|
@@ -86394,9 +86914,9 @@ async function mergeSessionsVia(deps, sessionIds, opts) {
|
|
|
86394
86914
|
const transcripts = [];
|
|
86395
86915
|
for (const sid of sessionIds) {
|
|
86396
86916
|
const msgs = await deps.getMessages(sid, opts.projectDir).catch(() => []);
|
|
86397
|
-
const
|
|
86398
|
-
if (
|
|
86399
|
-
transcripts.push(
|
|
86917
|
+
const text13 = transcriptToText(msgs);
|
|
86918
|
+
if (text13)
|
|
86919
|
+
transcripts.push(text13);
|
|
86400
86920
|
}
|
|
86401
86921
|
if (transcripts.length === 0)
|
|
86402
86922
|
return false;
|
|
@@ -86419,11 +86939,11 @@ import { homedir as homedir5 } from "node:os";
|
|
|
86419
86939
|
function geminiChatsRoot(home = process.env.GEMINI_CLI_HOME || homedir5()) {
|
|
86420
86940
|
return join29(home, ".gemini", "tmp");
|
|
86421
86941
|
}
|
|
86422
|
-
function parseGeminiSessionFile(file2,
|
|
86942
|
+
function parseGeminiSessionFile(file2, text13) {
|
|
86423
86943
|
let header2 = null;
|
|
86424
86944
|
let seeded = false;
|
|
86425
86945
|
const messages = [];
|
|
86426
|
-
for (const line of
|
|
86946
|
+
for (const line of text13.split("\n")) {
|
|
86427
86947
|
if (!line.trim())
|
|
86428
86948
|
continue;
|
|
86429
86949
|
let o;
|
|
@@ -86468,8 +86988,8 @@ var fileForSession = /* @__PURE__ */ new Map();
|
|
|
86468
86988
|
async function findGeminiSessionFile(sessionId, root = geminiChatsRoot()) {
|
|
86469
86989
|
const known = fileForSession.get(sessionId);
|
|
86470
86990
|
if (known) {
|
|
86471
|
-
const
|
|
86472
|
-
const t =
|
|
86991
|
+
const text13 = await readFile10(known, "utf8").catch(() => null);
|
|
86992
|
+
const t = text13 === null ? null : parseGeminiSessionFile(known, text13);
|
|
86473
86993
|
if (t?.header.sessionId === sessionId)
|
|
86474
86994
|
return t;
|
|
86475
86995
|
fileForSession.delete(sessionId);
|
|
@@ -86484,10 +87004,10 @@ async function findGeminiSessionFile(sessionId, root = geminiChatsRoot()) {
|
|
|
86484
87004
|
if (!f.endsWith(".jsonl"))
|
|
86485
87005
|
continue;
|
|
86486
87006
|
const full = join29(chats, f);
|
|
86487
|
-
const
|
|
86488
|
-
if (
|
|
87007
|
+
const text13 = await readFile10(full, "utf8").catch(() => null);
|
|
87008
|
+
if (text13 === null)
|
|
86489
87009
|
continue;
|
|
86490
|
-
const t = parseGeminiSessionFile(full,
|
|
87010
|
+
const t = parseGeminiSessionFile(full, text13);
|
|
86491
87011
|
if (t?.header.sessionId === sessionId) {
|
|
86492
87012
|
fileForSession.set(sessionId, full);
|
|
86493
87013
|
return t;
|
|
@@ -86558,14 +87078,14 @@ function createHostedVerification(engineId) {
|
|
|
86558
87078
|
const anchor = plan?.trim() ? plan : finalText;
|
|
86559
87079
|
if (anchor.trim())
|
|
86560
87080
|
state3 = { ...state3, plan: anchor.slice(0, 4e3) };
|
|
86561
|
-
let
|
|
87081
|
+
let text13 = finalText;
|
|
86562
87082
|
let reviewText = "";
|
|
86563
87083
|
let phaseText = "";
|
|
86564
87084
|
for (let i = 0; i < rv.RV_MAX_CYCLES * 5 + 4; i++) {
|
|
86565
87085
|
const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
|
|
86566
87086
|
const still = outstanding?.() ?? [];
|
|
86567
87087
|
const pending2 = still.length ? still : void 0;
|
|
86568
|
-
const call3 = gate === "review" ? rv.reviewGrade(state3, reviewText ||
|
|
87088
|
+
const call3 = gate === "review" ? rv.reviewGrade(state3, reviewText || text13, todos, pending2) : gate === "phase" ? rv.phaseGrade(state3, state3.lastVerdict?.phaseName ?? "", phaseText || text13, todos, pending2) : rv.completenessGrade(state3, text13, todos, pending2);
|
|
86569
87089
|
let verdict = null;
|
|
86570
87090
|
try {
|
|
86571
87091
|
verdict = rv.parseVerdict(await grade({ model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema }));
|
|
@@ -86573,16 +87093,16 @@ function createHostedVerification(engineId) {
|
|
|
86573
87093
|
verdict = null;
|
|
86574
87094
|
}
|
|
86575
87095
|
if (gone())
|
|
86576
|
-
return
|
|
87096
|
+
return text13;
|
|
86577
87097
|
if (!verdict) {
|
|
86578
87098
|
standDown(state3.cycles, "The verifier did not return a usable verdict, so this run was not verified.");
|
|
86579
|
-
return
|
|
87099
|
+
return text13;
|
|
86580
87100
|
}
|
|
86581
87101
|
{
|
|
86582
87102
|
const why = halt();
|
|
86583
87103
|
if (why) {
|
|
86584
87104
|
standDown(state3.cycles, why);
|
|
86585
|
-
return
|
|
87105
|
+
return text13;
|
|
86586
87106
|
}
|
|
86587
87107
|
}
|
|
86588
87108
|
const action = rv.rvDecision(verdict, state3);
|
|
@@ -86603,45 +87123,45 @@ function createHostedVerification(engineId) {
|
|
|
86603
87123
|
summary: verdict.summary
|
|
86604
87124
|
});
|
|
86605
87125
|
if (action.kind === "done" || action.kind === "capped")
|
|
86606
|
-
return
|
|
87126
|
+
return text13;
|
|
86607
87127
|
try {
|
|
86608
87128
|
if (gone())
|
|
86609
|
-
return
|
|
87129
|
+
return text13;
|
|
86610
87130
|
{
|
|
86611
87131
|
const why = halt();
|
|
86612
87132
|
if (why) {
|
|
86613
87133
|
standDown(state3.cycles, why);
|
|
86614
|
-
return
|
|
87134
|
+
return text13;
|
|
86615
87135
|
}
|
|
86616
87136
|
}
|
|
86617
|
-
const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText :
|
|
87137
|
+
const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText : text13;
|
|
86618
87138
|
const reply3 = await reprompt(action.prompt);
|
|
86619
87139
|
if (gone())
|
|
86620
|
-
return
|
|
87140
|
+
return text13;
|
|
86621
87141
|
{
|
|
86622
87142
|
const why = halt();
|
|
86623
87143
|
if (why) {
|
|
86624
87144
|
standDown(state3.cycles, why);
|
|
86625
|
-
return
|
|
87145
|
+
return text13;
|
|
86626
87146
|
}
|
|
86627
87147
|
}
|
|
86628
87148
|
if (!reply3 || reply3 === before) {
|
|
86629
87149
|
standDown(state3.cycles, "The agent did not produce anything new when sent back, so this run was not verified.");
|
|
86630
|
-
return
|
|
87150
|
+
return text13;
|
|
86631
87151
|
}
|
|
86632
87152
|
if (action.kind === "review")
|
|
86633
87153
|
reviewText = reply3;
|
|
86634
87154
|
else if (action.kind === "phase-review")
|
|
86635
87155
|
phaseText = reply3;
|
|
86636
87156
|
else
|
|
86637
|
-
|
|
87157
|
+
text13 = reply3;
|
|
86638
87158
|
} catch {
|
|
86639
87159
|
standDown(state3.cycles, "Verification could not be completed, so this run was not verified.");
|
|
86640
|
-
return
|
|
87160
|
+
return text13;
|
|
86641
87161
|
}
|
|
86642
87162
|
}
|
|
86643
87163
|
emit2({ ...base, action: "capped", gate: "completeness", cycle: rv.RV_MAX_CYCLES });
|
|
86644
|
-
return
|
|
87164
|
+
return text13;
|
|
86645
87165
|
}
|
|
86646
87166
|
};
|
|
86647
87167
|
}
|
|
@@ -86952,7 +87472,7 @@ function createRunTracker(opts) {
|
|
|
86952
87472
|
}
|
|
86953
87473
|
return token4;
|
|
86954
87474
|
},
|
|
86955
|
-
turnEnded(handle3,
|
|
87475
|
+
turnEnded(handle3, text13) {
|
|
86956
87476
|
const token4 = handle3;
|
|
86957
87477
|
const c = convs.get(resolve16(token4.key));
|
|
86958
87478
|
if (!c)
|
|
@@ -86960,14 +87480,14 @@ function createRunTracker(opts) {
|
|
|
86960
87480
|
c.live.delete(token4.id);
|
|
86961
87481
|
const run9 = c.run;
|
|
86962
87482
|
if (run9 && !run9.closed && token4.request === run9.request) {
|
|
86963
|
-
if (
|
|
87483
|
+
if (text13 === null && token4.carried && run9.waiters.length > 0) {
|
|
86964
87484
|
opts.log?.(`[run] ${c.key}: the turn delivering a result failed \u2014 the run is not verified`);
|
|
86965
87485
|
closeRun(c, run9, { reason: NOT_DELIVERED });
|
|
86966
87486
|
gc(c);
|
|
86967
87487
|
return;
|
|
86968
87488
|
}
|
|
86969
|
-
if (token4.id !== run9.gradedTurn &&
|
|
86970
|
-
run9.lastText =
|
|
87489
|
+
if (token4.id !== run9.gradedTurn && text13 !== null)
|
|
87490
|
+
run9.lastText = text13;
|
|
86971
87491
|
if (!holdsRun(run9) && !ownTurnRunning(run9)) {
|
|
86972
87492
|
run9.finishedIdle = true;
|
|
86973
87493
|
finish2(c, { outcome: "finished", text: run9.lastText });
|
|
@@ -87012,7 +87532,7 @@ function createRunTracker(opts) {
|
|
|
87012
87532
|
return items.map((i) => describe3(c, i, t, ""));
|
|
87013
87533
|
return run9.waiters.length > 0 && ownTurnRunning(run9) ? ["the turn reporting the background work is still running"] : void 0;
|
|
87014
87534
|
},
|
|
87015
|
-
openRun(sessionId, task, turn,
|
|
87535
|
+
openRun(sessionId, task, turn, text13) {
|
|
87016
87536
|
const c = conv(resolve16(sessionId));
|
|
87017
87537
|
const token4 = turn;
|
|
87018
87538
|
const run9 = {
|
|
@@ -87023,7 +87543,7 @@ function createRunTracker(opts) {
|
|
|
87023
87543
|
conv: c,
|
|
87024
87544
|
closed: null,
|
|
87025
87545
|
waiters: [],
|
|
87026
|
-
lastText:
|
|
87546
|
+
lastText: text13,
|
|
87027
87547
|
finishedIdle: false
|
|
87028
87548
|
};
|
|
87029
87549
|
if (c.lastPersonTurn > token4.id) {
|
|
@@ -88159,25 +88679,25 @@ function validate(schema, value, path6 = "$", out = []) {
|
|
|
88159
88679
|
}
|
|
88160
88680
|
return out;
|
|
88161
88681
|
}
|
|
88162
|
-
function extractJson(
|
|
88163
|
-
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(
|
|
88164
|
-
const candidates = [fenced?.[1],
|
|
88682
|
+
function extractJson(text13) {
|
|
88683
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(text13);
|
|
88684
|
+
const candidates = [fenced?.[1], text13].filter((v) => typeof v === "string");
|
|
88165
88685
|
for (const c of candidates) {
|
|
88166
88686
|
try {
|
|
88167
88687
|
return JSON.parse(c.trim());
|
|
88168
88688
|
} catch {
|
|
88169
88689
|
}
|
|
88170
88690
|
}
|
|
88171
|
-
for (let start3 = 0; start3 <
|
|
88172
|
-
const open10 =
|
|
88691
|
+
for (let start3 = 0; start3 < text13.length; start3++) {
|
|
88692
|
+
const open10 = text13[start3];
|
|
88173
88693
|
if (open10 !== "{" && open10 !== "[")
|
|
88174
88694
|
continue;
|
|
88175
88695
|
const close = open10 === "{" ? "}" : "]";
|
|
88176
88696
|
let depth = 0;
|
|
88177
88697
|
let inStr = false;
|
|
88178
88698
|
let esc3 = false;
|
|
88179
|
-
for (let i = start3; i <
|
|
88180
|
-
const ch =
|
|
88699
|
+
for (let i = start3; i < text13.length; i++) {
|
|
88700
|
+
const ch = text13[i];
|
|
88181
88701
|
if (inStr) {
|
|
88182
88702
|
if (esc3)
|
|
88183
88703
|
esc3 = false;
|
|
@@ -88197,7 +88717,7 @@ function extractJson(text12) {
|
|
|
88197
88717
|
depth--;
|
|
88198
88718
|
if (depth === 0) {
|
|
88199
88719
|
try {
|
|
88200
|
-
return JSON.parse(
|
|
88720
|
+
return JSON.parse(text13.slice(start3, i + 1));
|
|
88201
88721
|
} catch {
|
|
88202
88722
|
break;
|
|
88203
88723
|
}
|
|
@@ -88296,11 +88816,11 @@ function createEngineHttpApi(port, host = "127.0.0.1") {
|
|
|
88296
88816
|
});
|
|
88297
88817
|
if (!res.ok)
|
|
88298
88818
|
return null;
|
|
88299
|
-
const
|
|
88300
|
-
if (!
|
|
88819
|
+
const text13 = await res.text();
|
|
88820
|
+
if (!text13.trim())
|
|
88301
88821
|
return true;
|
|
88302
88822
|
try {
|
|
88303
|
-
const parsed = JSON.parse(
|
|
88823
|
+
const parsed = JSON.parse(text13);
|
|
88304
88824
|
return parsed === null ? true : parsed;
|
|
88305
88825
|
} catch {
|
|
88306
88826
|
return true;
|
|
@@ -88549,7 +89069,7 @@ function createEngineTranscript(engineId) {
|
|
|
88549
89069
|
return blocks.length ? [row(sid, "assistant", blocks)] : [];
|
|
88550
89070
|
}
|
|
88551
89071
|
return {
|
|
88552
|
-
userTurn(sid, cwd,
|
|
89072
|
+
userTurn(sid, cwd, text13) {
|
|
88553
89073
|
if (!cwd)
|
|
88554
89074
|
return;
|
|
88555
89075
|
cwdOf.set(sid, cwd);
|
|
@@ -88557,23 +89077,23 @@ function createEngineTranscript(engineId) {
|
|
|
88557
89077
|
if (prev)
|
|
88558
89078
|
void write2(sid, flushAssistant(sid, prev, true));
|
|
88559
89079
|
open10.set(sid, { cwd, blocks: [], prose: "", reasoning: "", pending: /* @__PURE__ */ new Map() });
|
|
88560
|
-
void write2(sid, [row(sid, "user",
|
|
89080
|
+
void write2(sid, [row(sid, "user", text13)]);
|
|
88561
89081
|
},
|
|
88562
|
-
assistantText(sid,
|
|
89082
|
+
assistantText(sid, text13) {
|
|
88563
89083
|
const t = open10.get(sid);
|
|
88564
|
-
if (!t || !
|
|
89084
|
+
if (!t || !text13)
|
|
88565
89085
|
return;
|
|
88566
89086
|
if (t.reasoning)
|
|
88567
89087
|
fold(t);
|
|
88568
|
-
t.prose +=
|
|
89088
|
+
t.prose += text13;
|
|
88569
89089
|
},
|
|
88570
|
-
thinking(sid,
|
|
89090
|
+
thinking(sid, text13) {
|
|
88571
89091
|
const t = open10.get(sid);
|
|
88572
|
-
if (!t || !
|
|
89092
|
+
if (!t || !text13)
|
|
88573
89093
|
return;
|
|
88574
89094
|
if (t.prose)
|
|
88575
89095
|
fold(t);
|
|
88576
|
-
t.reasoning +=
|
|
89096
|
+
t.reasoning += text13;
|
|
88577
89097
|
},
|
|
88578
89098
|
toolUse(sid, id, name, input) {
|
|
88579
89099
|
const t = open10.get(sid);
|
|
@@ -88680,13 +89200,13 @@ function createEngineTranscript(engineId) {
|
|
|
88680
89200
|
if (!file2)
|
|
88681
89201
|
return false;
|
|
88682
89202
|
const run9 = (chain2.get(sid) ?? Promise.resolve()).then(async () => {
|
|
88683
|
-
let
|
|
89203
|
+
let text13;
|
|
88684
89204
|
try {
|
|
88685
|
-
|
|
89205
|
+
text13 = await readFile12(file2, "utf8");
|
|
88686
89206
|
} catch {
|
|
88687
89207
|
return false;
|
|
88688
89208
|
}
|
|
88689
|
-
const lines =
|
|
89209
|
+
const lines = text13.split("\n");
|
|
88690
89210
|
const cut = cutLine(lines, at);
|
|
88691
89211
|
if (cut < 0)
|
|
88692
89212
|
return false;
|
|
@@ -88735,8 +89255,8 @@ ${blk.text.trim()}`);
|
|
|
88735
89255
|
else if (blk.type === "tool_use")
|
|
88736
89256
|
parts.push(`[tool call: ${blk.name ?? "tool"}] ${JSON.stringify(blk.input ?? {})}`);
|
|
88737
89257
|
else if (blk.type === "tool_result") {
|
|
88738
|
-
const
|
|
88739
|
-
parts.push(`[tool result${blk.is_error ? " (error)" : ""}] ${
|
|
89258
|
+
const text13 = typeof blk.content === "string" ? blk.content : Array.isArray(blk.content) ? blk.content.map((x) => x?.text ?? "").join("\n") : "";
|
|
89259
|
+
parts.push(`[tool result${blk.is_error ? " (error)" : ""}] ${text13.trim()}`);
|
|
88740
89260
|
}
|
|
88741
89261
|
}
|
|
88742
89262
|
}
|
|
@@ -88877,8 +89397,8 @@ function readOutputFromLocation(u) {
|
|
|
88877
89397
|
if (!path6)
|
|
88878
89398
|
return "";
|
|
88879
89399
|
try {
|
|
88880
|
-
const
|
|
88881
|
-
return
|
|
89400
|
+
const text13 = readFileSync24(path6, "utf8");
|
|
89401
|
+
return text13.length > MAX_LOCATION_READ_BYTES ? text13.slice(0, MAX_LOCATION_READ_BYTES) : text13;
|
|
88882
89402
|
} catch {
|
|
88883
89403
|
return "";
|
|
88884
89404
|
}
|
|
@@ -88995,7 +89515,8 @@ var OPENCODE_ACP = {
|
|
|
88995
89515
|
const SAFE = `${READ},"glob":"allow","grep":"allow","lsp":"allow","todowrite":"allow"`;
|
|
88996
89516
|
const KEEP_DENY = '"question":"deny","plan_enter":"deny","plan_exit":"deny"';
|
|
88997
89517
|
const { patterns } = opencodeBashDeny(deny);
|
|
88998
|
-
const
|
|
89518
|
+
const BLOCKED = patterns.map((p) => `${JSON.stringify(p)}:"deny"`).join(",");
|
|
89519
|
+
const BLOCK = BLOCKED ? `,"bash":{${BLOCKED}}` : "";
|
|
88999
89520
|
switch (mode) {
|
|
89000
89521
|
// Everything asks except the harmless reads — this is the mode that means "supervise me".
|
|
89001
89522
|
case "default":
|
|
@@ -89008,10 +89529,12 @@ var OPENCODE_ACP = {
|
|
|
89008
89529
|
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"allow",${SAFE},${KEEP_DENY}${BLOCK}}` };
|
|
89009
89530
|
// Nothing may change on disk. `deny` rather than `ask` so there is no card offering to
|
|
89010
89531
|
// break the mode's promise, and no prompt for something plan mode should never do.
|
|
89011
|
-
//
|
|
89012
|
-
//
|
|
89532
|
+
// Plan denies every command already, so the block patterns add nothing — but they are listed ANYWAY,
|
|
89533
|
+
// inside the same `bash` object (`{"*":"deny"}` is what a bare `"deny"` means to its matcher), because
|
|
89534
|
+
// "the rules went to the engine" must be true in every mode. A special case here would make the notice
|
|
89535
|
+
// that reads it (`blockRulesInForce`) quietly wrong the day plan mode's ruleset changes.
|
|
89013
89536
|
case "plan":
|
|
89014
|
-
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"deny","bash":"deny",${SAFE},${KEEP_DENY}}` };
|
|
89537
|
+
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"deny","bash":{"*":"deny"${BLOCKED ? `,${BLOCKED}` : ""}},${SAFE},${KEEP_DENY}}` };
|
|
89015
89538
|
// bypassPermissions / dontAsk / unset ⇒ leave its own ruleset alone: both of those modes mean
|
|
89016
89539
|
// "never prompt, let it run", which is what OpenCode's shipped `"*": "allow"` already is. Except for
|
|
89017
89540
|
// what the person BLOCKED: Claude checks its block rules ahead of bypass (its own
|
|
@@ -89200,25 +89723,25 @@ function relFromFileUri(uri, dir2) {
|
|
|
89200
89723
|
}
|
|
89201
89724
|
function collectReplay(out, u) {
|
|
89202
89725
|
const kind = u.sessionUpdate;
|
|
89203
|
-
const
|
|
89204
|
-
if (kind === "user_message_chunk" && REPLAY_SCAFFOLD.test(
|
|
89726
|
+
const text13 = u.content?.text ?? "";
|
|
89727
|
+
if (kind === "user_message_chunk" && REPLAY_SCAFFOLD.test(text13))
|
|
89205
89728
|
return;
|
|
89206
89729
|
const role = kind === "user_message_chunk" ? "user" : kind === "agent_message_chunk" || kind === "agent_thought_chunk" ? "assistant" : null;
|
|
89207
|
-
if (!role || !
|
|
89730
|
+
if (!role || !text13)
|
|
89208
89731
|
return;
|
|
89209
89732
|
const blockKind = kind === "agent_thought_chunk" ? "thinking" : "text";
|
|
89210
89733
|
const last = out[out.length - 1];
|
|
89211
89734
|
if (last && last.role === role) {
|
|
89212
89735
|
const lastBlock = last.blocks?.[last.blocks.length - 1];
|
|
89213
89736
|
if (lastBlock && lastBlock.kind === blockKind)
|
|
89214
|
-
lastBlock.content +=
|
|
89737
|
+
lastBlock.content += text13;
|
|
89215
89738
|
else
|
|
89216
|
-
(last.blocks ??= []).push({ kind: blockKind, content:
|
|
89739
|
+
(last.blocks ??= []).push({ kind: blockKind, content: text13 });
|
|
89217
89740
|
if (blockKind === "text")
|
|
89218
|
-
last.content +=
|
|
89741
|
+
last.content += text13;
|
|
89219
89742
|
return;
|
|
89220
89743
|
}
|
|
89221
|
-
out.push({ role, content: blockKind === "text" ?
|
|
89744
|
+
out.push({ role, content: blockKind === "text" ? text13 : "", blocks: [{ kind: blockKind, content: text13 }] });
|
|
89222
89745
|
}
|
|
89223
89746
|
function readUsage(res) {
|
|
89224
89747
|
const r = res ?? {};
|
|
@@ -89481,19 +90004,19 @@ function createAcpBackend(engine, send5, resolve16, services) {
|
|
|
89481
90004
|
const origin = turn.origin;
|
|
89482
90005
|
switch (u.sessionUpdate) {
|
|
89483
90006
|
case "agent_message_chunk": {
|
|
89484
|
-
const
|
|
89485
|
-
if (
|
|
89486
|
-
turn.acc +=
|
|
89487
|
-
transcript.assistantText(sid,
|
|
89488
|
-
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta:
|
|
90007
|
+
const text13 = u.content?.text ?? "";
|
|
90008
|
+
if (text13) {
|
|
90009
|
+
turn.acc += text13;
|
|
90010
|
+
transcript.assistantText(sid, text13);
|
|
90011
|
+
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta: text13, kind: "text" }, origin);
|
|
89489
90012
|
}
|
|
89490
90013
|
break;
|
|
89491
90014
|
}
|
|
89492
90015
|
case "agent_thought_chunk": {
|
|
89493
|
-
const
|
|
89494
|
-
if (
|
|
89495
|
-
transcript.thinking(sid,
|
|
89496
|
-
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta:
|
|
90016
|
+
const text13 = u.content?.text ?? "";
|
|
90017
|
+
if (text13) {
|
|
90018
|
+
transcript.thinking(sid, text13);
|
|
90019
|
+
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta: text13, kind: "thinking" }, origin);
|
|
89497
90020
|
}
|
|
89498
90021
|
break;
|
|
89499
90022
|
}
|
|
@@ -90000,11 +90523,11 @@ function createAcpBackend(engine, send5, resolve16, services) {
|
|
|
90000
90523
|
return out;
|
|
90001
90524
|
}
|
|
90002
90525
|
function promptBlocks(params) {
|
|
90003
|
-
const
|
|
90526
|
+
const text13 = params.message.trim() === "/compact" && engine.compactCommand ? engine.compactCommand : params.message;
|
|
90004
90527
|
const seed = params.sessionId ? pendingSeed.get(params.sessionId) : void 0;
|
|
90005
90528
|
const blocks = [{ type: "text", text: seed ? `${seed}
|
|
90006
90529
|
|
|
90007
|
-
${
|
|
90530
|
+
${text13}` : text13 }];
|
|
90008
90531
|
const skipped = [];
|
|
90009
90532
|
if (!supportsCapability(declaredCaps, "attachments"))
|
|
90010
90533
|
return { blocks, skipped };
|
|
@@ -90109,8 +90632,8 @@ ${text12}` : text12 }];
|
|
|
90109
90632
|
}
|
|
90110
90633
|
async function summarizeOnScratch(conn, sessionId, projectDir) {
|
|
90111
90634
|
const rows = await backend2.getMessages(sessionId, projectDir).catch(() => []);
|
|
90112
|
-
const
|
|
90113
|
-
if (!
|
|
90635
|
+
const text13 = transcriptToText(rows, 6e4);
|
|
90636
|
+
if (!text13)
|
|
90114
90637
|
return null;
|
|
90115
90638
|
const fresh = await conn.t.request("session/new", { cwd: conn.cwd, mcpServers: [] }).catch(() => null);
|
|
90116
90639
|
const scratch = fresh?.sessionId;
|
|
@@ -90128,7 +90651,7 @@ ${text12}` : text12 }];
|
|
|
90128
90651
|
return await promptForText(conn.t, scratch, `${prompt("agent.session-summary")}
|
|
90129
90652
|
|
|
90130
90653
|
--- Conversation ---
|
|
90131
|
-
${
|
|
90654
|
+
${text13}`);
|
|
90132
90655
|
} finally {
|
|
90133
90656
|
knownSessions.delete(scratch);
|
|
90134
90657
|
sessionConfig.delete(scratch);
|
|
@@ -90612,8 +91135,11 @@ ${text12}`);
|
|
|
90612
91135
|
let finishing = null;
|
|
90613
91136
|
if (params.permissionMode)
|
|
90614
91137
|
sessionMode.set(sid, params.permissionMode);
|
|
90615
|
-
|
|
90616
|
-
|
|
91138
|
+
const denyNow = params.settings?.permissions?.deny;
|
|
91139
|
+
if (denyNow?.length)
|
|
91140
|
+
sessionDeny.set(sid, denyNow);
|
|
91141
|
+
else
|
|
91142
|
+
sessionDeny.delete(sid);
|
|
90617
91143
|
send5({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "running" }, origin);
|
|
90618
91144
|
const schema = supportsCapability(declared, "structuredOutput") ? params.jsonSchema : void 0;
|
|
90619
91145
|
const enforceable = schema ? canEnforce(schema) : { ok: false };
|
|
@@ -91200,13 +91726,13 @@ ${detail}` : detail, !overflow);
|
|
|
91200
91726
|
sessionCwd.set(sessionId, projectDir);
|
|
91201
91727
|
if (!conn)
|
|
91202
91728
|
return { ok: false, error: `${engineLabel} is not running.` };
|
|
91203
|
-
const
|
|
91729
|
+
const text13 = await summarizeOnScratch(conn, sessionId, projectDir) ?? await (async () => {
|
|
91204
91730
|
await ensureLoaded(conn, sessionId);
|
|
91205
91731
|
return promptForText(conn.t, sessionId, prompt("agent.session-summary"));
|
|
91206
91732
|
})();
|
|
91207
|
-
if (!
|
|
91733
|
+
if (!text13)
|
|
91208
91734
|
return { ok: false, error: `${engineLabel} could not summarise this conversation.` };
|
|
91209
|
-
const { title, summary } = parseSummaryReply(
|
|
91735
|
+
const { title, summary } = parseSummaryReply(text13);
|
|
91210
91736
|
if (title)
|
|
91211
91737
|
sessionTitles.set(sessionId, title);
|
|
91212
91738
|
if (title)
|
|
@@ -91474,8 +92000,8 @@ ${detail}` : detail, !overflow);
|
|
|
91474
92000
|
const seenIds = /* @__PURE__ */ new Set();
|
|
91475
92001
|
let idx = 0;
|
|
91476
92002
|
for (const m of log10.messages) {
|
|
91477
|
-
const
|
|
91478
|
-
if (!
|
|
92003
|
+
const text13 = geminiMessageText(m);
|
|
92004
|
+
if (!text13 || REPLAY_SCAFFOLD.test(text13))
|
|
91479
92005
|
continue;
|
|
91480
92006
|
if (m.id && seenIds.has(m.id))
|
|
91481
92007
|
continue;
|
|
@@ -91485,7 +92011,7 @@ ${detail}` : detail, !overflow);
|
|
|
91485
92011
|
const uuid3 = m.id ?? `acp-user-${idx}`;
|
|
91486
92012
|
if (role === "user")
|
|
91487
92013
|
idx++;
|
|
91488
|
-
rows.push({ role, content:
|
|
92014
|
+
rows.push({ role, content: text13, uuid: uuid3, blocks: [{ kind: "text", content: text13 }] });
|
|
91489
92015
|
}
|
|
91490
92016
|
if (rows.length > 0) {
|
|
91491
92017
|
const firstUser2 = rows.find((r) => r.role === "user")?.content?.trim();
|
|
@@ -91602,20 +92128,20 @@ function codexTranscriptRows(turns, textOf) {
|
|
|
91602
92128
|
const kind = String(it.type ?? "");
|
|
91603
92129
|
if (kind && kind !== "userMessage" && kind !== "agentMessage")
|
|
91604
92130
|
continue;
|
|
91605
|
-
const
|
|
91606
|
-
if (!
|
|
92131
|
+
const text13 = textOf(it);
|
|
92132
|
+
if (!text13)
|
|
91607
92133
|
continue;
|
|
91608
92134
|
const role = String(it.role ?? (kind === "userMessage" ? "user" : "assistant")) === "user" ? "user" : "assistant";
|
|
91609
92135
|
const last = rows[rows.length - 1];
|
|
91610
92136
|
if (last && last.role === role) {
|
|
91611
92137
|
last.content += `
|
|
91612
|
-
${
|
|
92138
|
+
${text13}`;
|
|
91613
92139
|
if (last.turns[last.turns.length - 1] !== ti)
|
|
91614
92140
|
last.turns.push(ti);
|
|
91615
92141
|
continue;
|
|
91616
92142
|
}
|
|
91617
92143
|
const uuid3 = typeof it.id === "string" && it.id ? it.id : void 0;
|
|
91618
|
-
rows.push({ role, content:
|
|
92144
|
+
rows.push({ role, content: text13, ...uuid3 ? { uuid: uuid3 } : {}, turns: [ti] });
|
|
91619
92145
|
}
|
|
91620
92146
|
});
|
|
91621
92147
|
return rows;
|
|
@@ -91833,9 +92359,9 @@ function itemToolName(item) {
|
|
|
91833
92359
|
case "webSearch":
|
|
91834
92360
|
return "WebSearch";
|
|
91835
92361
|
case "mcpToolCall": {
|
|
91836
|
-
const
|
|
92362
|
+
const tool22 = String(i.tool ?? "tool");
|
|
91837
92363
|
const server2 = String(i.server ?? "");
|
|
91838
|
-
return server2 ? `${server2}_${
|
|
92364
|
+
return server2 ? `${server2}_${tool22}` : tool22;
|
|
91839
92365
|
}
|
|
91840
92366
|
case "dynamicToolCall":
|
|
91841
92367
|
return String(i.tool ?? "tool");
|
|
@@ -92192,8 +92718,8 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92192
92718
|
subagentSinks.delete(scratch);
|
|
92193
92719
|
subagentDone.delete(scratch);
|
|
92194
92720
|
}
|
|
92195
|
-
const
|
|
92196
|
-
return
|
|
92721
|
+
const text13 = out.join("").trim();
|
|
92722
|
+
return text13 || null;
|
|
92197
92723
|
}
|
|
92198
92724
|
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
92199
92725
|
const pendingDialogs = /* @__PURE__ */ new Map();
|
|
@@ -92218,8 +92744,6 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92218
92744
|
const settled = turn ? runningTurnApprovalAnswer(modeNow, turn.sandbox) : "ask";
|
|
92219
92745
|
if (settled === "allow")
|
|
92220
92746
|
return Promise.resolve(allow);
|
|
92221
|
-
if (settled === "deny")
|
|
92222
|
-
return Promise.resolve(deny);
|
|
92223
92747
|
const requestId = randomUUID17();
|
|
92224
92748
|
return new Promise((resolveOutcome) => {
|
|
92225
92749
|
pendingApprovals.set(requestId, { resolve: resolveOutcome, threadId, allow, allowPersist, deny });
|
|
@@ -92547,7 +93071,11 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92547
93071
|
});
|
|
92548
93072
|
t.onRequest("item/fileChange/requestApproval", (raw) => {
|
|
92549
93073
|
const p = raw ?? {};
|
|
92550
|
-
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93074
|
+
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93075
|
+
title: p.reason,
|
|
93076
|
+
path: p.grantRoot,
|
|
93077
|
+
input: { changes: p.changes, path: p.path }
|
|
93078
|
+
});
|
|
92551
93079
|
});
|
|
92552
93080
|
t.onRequest("item/permissions/requestApproval", (raw) => parkApproval(raw, "Permissions", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, { title: "Codex is requesting additional permissions" }));
|
|
92553
93081
|
t.onRequest("execCommandApproval", (raw) => {
|
|
@@ -92556,7 +93084,11 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92556
93084
|
});
|
|
92557
93085
|
t.onRequest("applyPatchApproval", (raw) => {
|
|
92558
93086
|
const p = raw ?? {};
|
|
92559
|
-
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93087
|
+
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93088
|
+
title: p.reason,
|
|
93089
|
+
path: p.grantRoot,
|
|
93090
|
+
input: { changes: p.changes ?? p.fileChanges }
|
|
93091
|
+
});
|
|
92560
93092
|
});
|
|
92561
93093
|
t.onRequest("item/tool/requestUserInput", (raw) => {
|
|
92562
93094
|
const p = raw ?? {};
|
|
@@ -93610,13 +94142,13 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
93610
94142
|
*/
|
|
93611
94143
|
summarizeSession: async (sessionId, projectDir) => {
|
|
93612
94144
|
const msgs = await backend2.getMessages(sessionId, threadCwd.get(sessionId) ?? spawnedCwd ?? projectDir).catch(() => []);
|
|
93613
|
-
const
|
|
93614
|
-
if (!
|
|
94145
|
+
const text13 = transcriptToText(msgs, 6e4);
|
|
94146
|
+
if (!text13)
|
|
93615
94147
|
return { ok: false, error: "That conversation has nothing to summarise yet." };
|
|
93616
94148
|
const reply3 = await promptScratchThread(`${prompt("agent.session-summary")}
|
|
93617
94149
|
|
|
93618
94150
|
--- Conversation ---
|
|
93619
|
-
${
|
|
94151
|
+
${text13}`, threadCwd.get(sessionId) ?? spawnedCwd ?? projectDir);
|
|
93620
94152
|
if (!reply3)
|
|
93621
94153
|
return { ok: false, error: `${label} could not summarise this conversation.` };
|
|
93622
94154
|
const { title, summary } = parseSummaryReply(reply3);
|
|
@@ -93729,8 +94261,8 @@ var seq = 0;
|
|
|
93729
94261
|
var now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
93730
94262
|
var ctx = [];
|
|
93731
94263
|
var CTX_MAX = 60;
|
|
93732
|
-
function pushCtx(role,
|
|
93733
|
-
const t = (
|
|
94264
|
+
function pushCtx(role, text13) {
|
|
94265
|
+
const t = (text13 ?? "").trim();
|
|
93734
94266
|
if (!t)
|
|
93735
94267
|
return;
|
|
93736
94268
|
ctx.push({ role, text: t.length > 300 ? `${t.slice(0, 300)}\u2026` : t });
|
|
@@ -93996,23 +94528,23 @@ var HostPluginApi = class {
|
|
|
93996
94528
|
secret(envKey2) {
|
|
93997
94529
|
return this.secretResolver(this.pluginId, envKey2);
|
|
93998
94530
|
}
|
|
93999
|
-
registerTool(
|
|
94531
|
+
registerTool(tool22) {
|
|
94000
94532
|
const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
94001
|
-
const name =
|
|
94002
|
-
this.registry.tools.push({ ...
|
|
94533
|
+
const name = tool22.name.startsWith(`${prefix}_`) ? tool22.name : `${prefix}_${tool22.name}`;
|
|
94534
|
+
this.registry.tools.push({ ...tool22, name });
|
|
94003
94535
|
}
|
|
94004
|
-
registerUiTool(
|
|
94005
|
-
if (!this.requireGrant("surfaces", `UI tool "${
|
|
94536
|
+
registerUiTool(tool22) {
|
|
94537
|
+
if (!this.requireGrant("surfaces", `UI tool "${tool22.name}"`))
|
|
94006
94538
|
return;
|
|
94007
94539
|
const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
94008
|
-
const name =
|
|
94540
|
+
const name = tool22.name.startsWith(`${prefix}_`) ? tool22.name : `${prefix}_${tool22.name}`;
|
|
94009
94541
|
const tier = this.hasGrant("customUI") ? "verified" : "third-party";
|
|
94010
94542
|
this.registry.tools.push({
|
|
94011
94543
|
name,
|
|
94012
|
-
description:
|
|
94013
|
-
inputSchema:
|
|
94014
|
-
handler: async (args) => toResult(await
|
|
94015
|
-
__ctxHandler: async (args, ctx2) => toResult(await
|
|
94544
|
+
description: tool22.description,
|
|
94545
|
+
inputSchema: tool22.inputSchema,
|
|
94546
|
+
handler: async (args) => toResult(await tool22.handler(args, NOOP_UI_CTX)),
|
|
94547
|
+
__ctxHandler: async (args, ctx2) => toResult(await tool22.handler(args, ctx2)),
|
|
94016
94548
|
__tier: tier
|
|
94017
94549
|
});
|
|
94018
94550
|
}
|
|
@@ -94122,8 +94654,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
|
|
|
94122
94654
|
pluginId,
|
|
94123
94655
|
config: config2,
|
|
94124
94656
|
secret: (envKey2) => secretResolver(pluginId, envKey2),
|
|
94125
|
-
registerTool: (
|
|
94126
|
-
const got = typeof
|
|
94657
|
+
registerTool: (tool22) => {
|
|
94658
|
+
const got = typeof tool22 === "function" ? tool22({}) : tool22;
|
|
94127
94659
|
const arr = Array.isArray(got) ? got : got ? [got] : [];
|
|
94128
94660
|
for (const t of arr) {
|
|
94129
94661
|
const c = convertTool(t);
|
|
@@ -95589,8 +96121,8 @@ init_prompts();
|
|
|
95589
96121
|
// ../../packages/voice-core/dist/pipeline/history.js
|
|
95590
96122
|
function formatHistoryLines(turns, maxLineChars = 300) {
|
|
95591
96123
|
return turns.map((t) => {
|
|
95592
|
-
const
|
|
95593
|
-
const capped =
|
|
96124
|
+
const text13 = t.text.replace(/\s+/g, " ").trim();
|
|
96125
|
+
const capped = text13.length > maxLineChars ? text13.slice(0, maxLineChars - 1).trimEnd() + "\u2026" : text13;
|
|
95594
96126
|
return `${t.role.toUpperCase()}: ${capped}`;
|
|
95595
96127
|
}).join("\n");
|
|
95596
96128
|
}
|
|
@@ -95885,15 +96417,15 @@ ${truncate(input.result, 4e3)}`
|
|
|
95885
96417
|
}
|
|
95886
96418
|
};
|
|
95887
96419
|
function ruleBasedTurn(input) {
|
|
95888
|
-
const
|
|
95889
|
-
const lower =
|
|
96420
|
+
const text13 = input.result.trim();
|
|
96421
|
+
const lower = text13.toLowerCase();
|
|
95890
96422
|
let status2 = "done";
|
|
95891
96423
|
if (/\b(error|failed|could not|cannot|unable to)\b/.test(lower))
|
|
95892
96424
|
status2 = "error";
|
|
95893
|
-
else if (
|
|
96425
|
+
else if (text13.endsWith("?") || /\b(which|should i|do you want|would you like|please confirm|clarif)\b/.test(lower)) {
|
|
95894
96426
|
status2 = "needs_input";
|
|
95895
96427
|
}
|
|
95896
|
-
const line = firstSentences(stripForSpeech(
|
|
96428
|
+
const line = firstSentences(stripForSpeech(text13)) || input.recentActivity.slice(-1)[0] || "Done.";
|
|
95897
96429
|
return { line, status: status2 };
|
|
95898
96430
|
}
|
|
95899
96431
|
function stripForSpeech(s) {
|
|
@@ -95971,8 +96503,8 @@ var VoiceGuideOrchestrator = class {
|
|
|
95971
96503
|
/** The bridge feeds every finalized transcript line here (capped buffer). An
|
|
95972
96504
|
* assistant line means the guide finished speaking — drain the next queued
|
|
95973
96505
|
* update immediately instead of waiting out the gap timer. */
|
|
95974
|
-
noteTranscript(role,
|
|
95975
|
-
const t =
|
|
96506
|
+
noteTranscript(role, text13) {
|
|
96507
|
+
const t = text13.trim();
|
|
95976
96508
|
if (!t)
|
|
95977
96509
|
return;
|
|
95978
96510
|
this.conversation.push({ role, text: t });
|
|
@@ -96506,26 +97038,26 @@ Additional context: ${context}` : task;
|
|
|
96506
97038
|
this.deps.emit({ type: "voice:milestone", text: spoken });
|
|
96507
97039
|
this.say(spoken, { urgent: focused });
|
|
96508
97040
|
}
|
|
96509
|
-
speakMilestone(
|
|
96510
|
-
this.deps.emit({ type: "voice:milestone", text:
|
|
96511
|
-
this.say(
|
|
97041
|
+
speakMilestone(text13) {
|
|
97042
|
+
this.deps.emit({ type: "voice:milestone", text: text13 });
|
|
97043
|
+
this.say(text13);
|
|
96512
97044
|
}
|
|
96513
97045
|
// ── One mouth, N sessions: serialized speech ───────────────────────────────
|
|
96514
97046
|
/** Speak `text`, serializing non-urgent lines so concurrent sessions don't
|
|
96515
97047
|
* talk over each other. Urgent lines (blocking questions, the focused
|
|
96516
97048
|
* session's result, critical notices) always go out immediately. */
|
|
96517
|
-
say(
|
|
96518
|
-
if (!
|
|
97049
|
+
say(text13, opts = {}) {
|
|
97050
|
+
if (!text13)
|
|
96519
97051
|
return;
|
|
96520
97052
|
const now2 = this.now();
|
|
96521
97053
|
if (opts.urgent || this.sayQueue.length === 0 && now2 - this.lastSayAt >= SPEAK_GAP_MS) {
|
|
96522
97054
|
this.lastSayAt = now2;
|
|
96523
|
-
this.voice?.speakNow(
|
|
97055
|
+
this.voice?.speakNow(text13);
|
|
96524
97056
|
return;
|
|
96525
97057
|
}
|
|
96526
97058
|
if (this.sayQueue.length >= SPEAK_QUEUE_CAP)
|
|
96527
97059
|
this.sayQueue.shift();
|
|
96528
|
-
this.sayQueue.push(
|
|
97060
|
+
this.sayQueue.push(text13);
|
|
96529
97061
|
this.armSayTimer();
|
|
96530
97062
|
}
|
|
96531
97063
|
armSayTimer() {
|
|
@@ -96656,11 +97188,11 @@ var ClientProxyProvider = class {
|
|
|
96656
97188
|
/** Audio is client↔provider direct — the daemon never sees mic/model PCM. */
|
|
96657
97189
|
sendAudio(_pcm24k) {
|
|
96658
97190
|
}
|
|
96659
|
-
respondToTool(callId,
|
|
96660
|
-
this.deps.send({ type: "voice:cd:respondToTool", callId, text:
|
|
97191
|
+
respondToTool(callId, text13, isError) {
|
|
97192
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError });
|
|
96661
97193
|
}
|
|
96662
|
-
speakNow(
|
|
96663
|
-
this.deps.send({ type: "voice:cd:speak", text:
|
|
97194
|
+
speakNow(text13) {
|
|
97195
|
+
this.deps.send({ type: "voice:cd:speak", text: text13 });
|
|
96664
97196
|
}
|
|
96665
97197
|
close() {
|
|
96666
97198
|
this.settleConnect(new Error("closed before connect"));
|
|
@@ -96680,11 +97212,11 @@ var ClientProxyProvider = class {
|
|
|
96680
97212
|
handleToolCall(inv) {
|
|
96681
97213
|
this.cb.onToolCall(inv);
|
|
96682
97214
|
}
|
|
96683
|
-
handleTranscript(speaker,
|
|
97215
|
+
handleTranscript(speaker, text13) {
|
|
96684
97216
|
if (speaker === "user")
|
|
96685
|
-
this.cb.onUserTranscript(
|
|
97217
|
+
this.cb.onUserTranscript(text13);
|
|
96686
97218
|
else
|
|
96687
|
-
this.cb.onAgentTranscript(
|
|
97219
|
+
this.cb.onAgentTranscript(text13);
|
|
96688
97220
|
}
|
|
96689
97221
|
handleProviderEvent(event, message) {
|
|
96690
97222
|
switch (event) {
|
|
@@ -96916,10 +97448,10 @@ var VoiceControl = class {
|
|
|
96916
97448
|
* injection as a user turn and comments on every slide change, which is exactly the
|
|
96917
97449
|
* running commentary the silence contract forbids.
|
|
96918
97450
|
*/
|
|
96919
|
-
injectPresentContext(
|
|
97451
|
+
injectPresentContext(text13) {
|
|
96920
97452
|
if (this.ended)
|
|
96921
97453
|
return;
|
|
96922
|
-
this.deps.send({ type: "voice:cd:inject", text:
|
|
97454
|
+
this.deps.send({ type: "voice:cd:inject", text: text13, turnComplete: false });
|
|
96923
97455
|
}
|
|
96924
97456
|
/**
|
|
96925
97457
|
* A typed question from the phone, routed as if it had been spoken.
|
|
@@ -96927,33 +97459,33 @@ var VoiceControl = class {
|
|
|
96927
97459
|
* This one DOES form a turn (turnComplete left at its default): unlike slide context,
|
|
96928
97460
|
* the presenter is deliberately addressing the assistant and is waiting for an answer.
|
|
96929
97461
|
*/
|
|
96930
|
-
askPresent(
|
|
97462
|
+
askPresent(text13) {
|
|
96931
97463
|
if (this.ended)
|
|
96932
97464
|
return;
|
|
96933
|
-
this.deps.send({ type: "voice:cd:inject", text: `(The presenter asks you directly: ${
|
|
97465
|
+
this.deps.send({ type: "voice:cd:inject", text: `(The presenter asks you directly: ${text13})` });
|
|
96934
97466
|
}
|
|
96935
97467
|
async runPresentControl(callId, name, args) {
|
|
96936
|
-
let
|
|
97468
|
+
let text13 = "";
|
|
96937
97469
|
let silent = false;
|
|
96938
97470
|
let clearPlayback = false;
|
|
96939
97471
|
let isError = false;
|
|
96940
97472
|
try {
|
|
96941
97473
|
const r = await this.deps.execPresentControl(name, args);
|
|
96942
|
-
|
|
97474
|
+
text13 = r.text;
|
|
96943
97475
|
silent = r.silent;
|
|
96944
97476
|
clearPlayback = r.clearPlayback === true;
|
|
96945
97477
|
} catch (e) {
|
|
96946
|
-
|
|
97478
|
+
text13 = e instanceof Error ? e.message : "presentation action failed";
|
|
96947
97479
|
isError = true;
|
|
96948
97480
|
}
|
|
96949
|
-
log(`voice: present-control ${name} \u2192 ${isError ? "ERROR " : ""}${
|
|
96950
|
-
recordEvent("tool_result", { name, text:
|
|
97481
|
+
log(`voice: present-control ${name} \u2192 ${isError ? "ERROR " : ""}${text13}`);
|
|
97482
|
+
recordEvent("tool_result", { name, text: text13, isError });
|
|
96951
97483
|
if (clearPlayback && !isError)
|
|
96952
97484
|
this.deps.send({ type: "voice:clearPlayback" });
|
|
96953
|
-
this.deps.send({ type: "voice:cd:respondToTool", callId, text:
|
|
97485
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError, silent: silent && !isError });
|
|
96954
97486
|
}
|
|
96955
97487
|
async runScreenControl(callId, name, args) {
|
|
96956
|
-
let
|
|
97488
|
+
let text13;
|
|
96957
97489
|
let isError = false;
|
|
96958
97490
|
let finished = false, nudges = 0;
|
|
96959
97491
|
let slowTimer = null;
|
|
@@ -96969,18 +97501,18 @@ var VoiceControl = class {
|
|
|
96969
97501
|
};
|
|
96970
97502
|
scheduleNudge(2e4);
|
|
96971
97503
|
try {
|
|
96972
|
-
|
|
97504
|
+
text13 = await this.deps.execScreenControl(name, args);
|
|
96973
97505
|
} catch (e) {
|
|
96974
|
-
|
|
97506
|
+
text13 = e instanceof Error ? e.message : "screen action failed";
|
|
96975
97507
|
isError = true;
|
|
96976
97508
|
} finally {
|
|
96977
97509
|
finished = true;
|
|
96978
97510
|
if (slowTimer)
|
|
96979
97511
|
clearTimeout(slowTimer);
|
|
96980
97512
|
}
|
|
96981
|
-
log(`voice: screen-control ${name} \u2192 ${isError ? "ERROR " : ""}${
|
|
96982
|
-
recordEvent("tool_result", { name, text:
|
|
96983
|
-
this.deps.send({ type: "voice:cd:respondToTool", callId, text:
|
|
97513
|
+
log(`voice: screen-control ${name} \u2192 ${isError ? "ERROR " : ""}${text13}`);
|
|
97514
|
+
recordEvent("tool_result", { name, text: text13, isError });
|
|
97515
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError });
|
|
96984
97516
|
}
|
|
96985
97517
|
async start(msg) {
|
|
96986
97518
|
if (this.starting)
|
|
@@ -97118,13 +97650,13 @@ ${priorText}` : "";
|
|
|
97118
97650
|
const callbacks = {
|
|
97119
97651
|
onOutputAudio: () => {
|
|
97120
97652
|
},
|
|
97121
|
-
onUserTranscript: (
|
|
97122
|
-
orchestrator.noteTranscript("user",
|
|
97123
|
-
this.deps.send({ type: "voice:transcript", speaker: "user", text:
|
|
97653
|
+
onUserTranscript: (text13) => {
|
|
97654
|
+
orchestrator.noteTranscript("user", text13);
|
|
97655
|
+
this.deps.send({ type: "voice:transcript", speaker: "user", text: text13 });
|
|
97124
97656
|
},
|
|
97125
|
-
onAgentTranscript: (
|
|
97126
|
-
orchestrator.noteTranscript("assistant",
|
|
97127
|
-
this.deps.send({ type: "voice:transcript", speaker: "agent", text:
|
|
97657
|
+
onAgentTranscript: (text13) => {
|
|
97658
|
+
orchestrator.noteTranscript("assistant", text13);
|
|
97659
|
+
this.deps.send({ type: "voice:transcript", speaker: "agent", text: text13 });
|
|
97128
97660
|
},
|
|
97129
97661
|
onToolCall: (inv) => orchestrator.handleToolCall(inv),
|
|
97130
97662
|
onInterruption: () => this.deps.send({ type: "voice:clearPlayback" }),
|
|
@@ -97996,7 +98528,7 @@ var GeminiVeoProvider = class {
|
|
|
97996
98528
|
};
|
|
97997
98529
|
|
|
97998
98530
|
// ../../packages/video-core/dist/tesseract.js
|
|
97999
|
-
var DEFAULT_MODEL4 = "
|
|
98531
|
+
var DEFAULT_MODEL4 = "veo-3.1-fast-generate-preview";
|
|
98000
98532
|
var REQUEST_TIMEOUT_MS2 = 9e4;
|
|
98001
98533
|
var DOWNLOAD_TIMEOUT_MS2 = 18e4;
|
|
98002
98534
|
var withTimeout4 = (signal2, ms) => signal2 ?? AbortSignal.timeout(ms);
|
|
@@ -98490,7 +99022,7 @@ var fmtTime = (sec) => {
|
|
|
98490
99022
|
cs -= s * 100;
|
|
98491
99023
|
return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}.${String(cs).padStart(2, "0")}`;
|
|
98492
99024
|
};
|
|
98493
|
-
var escapeAss = (
|
|
99025
|
+
var escapeAss = (text13) => text13.replace(/\\/g, "\\\\").replace(/\{/g, "(").replace(/\}/g, ")").replace(/\r?\n/g, "\\N");
|
|
98494
99026
|
function buildAssSubtitles(cues, style, width, height) {
|
|
98495
99027
|
const base = Math.round(height / 14);
|
|
98496
99028
|
const styles = style === "tiktok-bold" ? `Style: Cap,Arial Black,${base},&H00FFFFFF,&H000000FF,&H00000000,&H96000000,-1,0,0,0,100,100,0,0,1,${Math.max(2, Math.round(base / 9))},0,2,60,60,${Math.round(height / 5)},1` : `Style: Cap,Arial,${Math.round(base * 0.72)},&H00FFFFFF,&H000000FF,&H00000000,&H64000000,-1,0,0,0,100,100,0,0,1,2,1,2,40,40,${Math.round(height / 12)},1`;
|
|
@@ -99101,7 +99633,7 @@ async function cloneVoiceElevenLabs(name, samples, cfg2, opts) {
|
|
|
99101
99633
|
throw new Error("ElevenLabs clone returned no voice_id.");
|
|
99102
99634
|
return { voiceId: j.voice_id, name: j.name ?? name };
|
|
99103
99635
|
}
|
|
99104
|
-
async function synthesizeSpeechElevenLabs(
|
|
99636
|
+
async function synthesizeSpeechElevenLabs(text13, voiceId, cfg2, opts) {
|
|
99105
99637
|
const base = (cfg2.baseUrl?.trim() || BASE_URL).replace(/\/+$/, "");
|
|
99106
99638
|
const settings = {};
|
|
99107
99639
|
if (cfg2.stability != null)
|
|
@@ -99115,7 +99647,7 @@ async function synthesizeSpeechElevenLabs(text12, voiceId, cfg2, opts) {
|
|
|
99115
99647
|
res = await fetch(`${base}/v1/text-to-speech/${encodeURIComponent(voiceId)}?output_format=mp3_44100_128`, {
|
|
99116
99648
|
method: "POST",
|
|
99117
99649
|
headers: { "xi-api-key": cfg2.apiKey, "Content-Type": "application/json" },
|
|
99118
|
-
body: JSON.stringify({ text:
|
|
99650
|
+
body: JSON.stringify({ text: text13, model_id: cfg2.model?.trim() || DEFAULT_TTS_MODEL, ...Object.keys(settings).length ? { voice_settings: settings } : {} }),
|
|
99119
99651
|
signal: opts?.signal ?? AbortSignal.timeout(12e4)
|
|
99120
99652
|
});
|
|
99121
99653
|
} catch (e) {
|
|
@@ -99207,8 +99739,8 @@ var VIDEO_PROVIDERS = [
|
|
|
99207
99739
|
{
|
|
99208
99740
|
id: "tesseract",
|
|
99209
99741
|
label: "Tesseract \xB7 free (no key)",
|
|
99210
|
-
defaultModel: "
|
|
99211
|
-
models: ["
|
|
99742
|
+
defaultModel: "veo-3.1-fast-generate-preview",
|
|
99743
|
+
models: ["veo-3.1-fast-generate-preview"],
|
|
99212
99744
|
keysUrl: "",
|
|
99213
99745
|
free: true
|
|
99214
99746
|
},
|
|
@@ -99474,7 +100006,7 @@ var IN_TURN_WAIT_MS = 8 * 6e4;
|
|
|
99474
100006
|
var HEARTBEAT_MS2 = 15e3;
|
|
99475
100007
|
var FAST_MODEL = VIDEO_PROVIDERS.find((p) => p.id === "google").defaultModel;
|
|
99476
100008
|
var STANDARD_MODEL = "veo-3.1-generate-preview";
|
|
99477
|
-
var FREE_MODEL = "
|
|
100009
|
+
var FREE_MODEL = "veo-3.1-fast-generate-preview";
|
|
99478
100010
|
var clampDuration2 = (n) => [4, 6, 8].reduce((best, d) => Math.abs(d - n) < Math.abs(best - n) ? d : best);
|
|
99479
100011
|
function creds2() {
|
|
99480
100012
|
return readDaemonAgentSettings().videoGen;
|
|
@@ -100518,11 +101050,11 @@ async function geminiJson(opts) {
|
|
|
100518
101050
|
const json3 = await res.json().catch(() => ({}));
|
|
100519
101051
|
if (!res.ok)
|
|
100520
101052
|
throw new Error(json3.error?.message ?? `Gemini request failed (${res.status})`);
|
|
100521
|
-
const
|
|
101053
|
+
const text13 = json3.candidates?.[0]?.content?.parts?.map((p) => p.text ?? "").join("") ?? "";
|
|
100522
101054
|
try {
|
|
100523
|
-
return JSON.parse(
|
|
101055
|
+
return JSON.parse(text13);
|
|
100524
101056
|
} catch {
|
|
100525
|
-
throw new Error(`Gemini returned non-JSON transcription output: ${
|
|
101057
|
+
throw new Error(`Gemini returned non-JSON transcription output: ${text13.slice(0, 200)}`);
|
|
100526
101058
|
}
|
|
100527
101059
|
}
|
|
100528
101060
|
async function transcribeMedia(opts) {
|
|
@@ -100656,7 +101188,7 @@ function resolveAvatarCreds(snap, keyFile, envKey2) {
|
|
|
100656
101188
|
function heygenCreds() {
|
|
100657
101189
|
return resolveAvatarCreds(readDaemonAgentSettings(), readDaemonKeyFile("heygen.key"), process.env.HEYGEN_API_KEY ?? null);
|
|
100658
101190
|
}
|
|
100659
|
-
var NO_AVATAR_CREDS = "Avatar videos need
|
|
101191
|
+
var NO_AVATAR_CREDS = "Avatar videos need a HeyGen API key \u2014 add one in Settings, or set HEYGEN_API_KEY. The free tier covers this only when you are signed in AND this server has HeyGen access; one of those is missing here.";
|
|
100660
101192
|
function readDaemonKeyFile(name) {
|
|
100661
101193
|
try {
|
|
100662
101194
|
const home = tesseractHome();
|
|
@@ -100875,12 +101407,12 @@ function createDaemonVideoEditRunner() {
|
|
|
100875
101407
|
return { ok: false, error: err(e) };
|
|
100876
101408
|
}
|
|
100877
101409
|
},
|
|
100878
|
-
async synthesizeSpeech(
|
|
101410
|
+
async synthesizeSpeech(text13, voiceId, outDir, opts) {
|
|
100879
101411
|
const apiKey = elevenLabsKey();
|
|
100880
101412
|
if (!apiKey)
|
|
100881
101413
|
return { ok: false, error: "Text-to-speech needs an ElevenLabs key (Settings \u2192 Voice)." };
|
|
100882
101414
|
try {
|
|
100883
|
-
const audio = await synthesizeSpeechElevenLabs(
|
|
101415
|
+
const audio = await synthesizeSpeechElevenLabs(text13, voiceId, { apiKey, stability: opts?.stability, similarityBoost: opts?.similarityBoost, speed: opts?.speed });
|
|
100884
101416
|
const dir2 = outDir ?? join48(musicDir2(), randomUUID24());
|
|
100885
101417
|
await mkdir9(dir2, { recursive: true });
|
|
100886
101418
|
const path6 = join48(dir2, "speech.mp3");
|
|
@@ -101009,8 +101541,8 @@ function createDaemonSupportSubmit() {
|
|
|
101009
101541
|
signal: AbortSignal.timeout(3e4)
|
|
101010
101542
|
});
|
|
101011
101543
|
if (!res.ok) {
|
|
101012
|
-
const
|
|
101013
|
-
throw new Error(`Report submission failed (${res.status}). ${
|
|
101544
|
+
const text13 = await res.text().catch(() => "");
|
|
101545
|
+
throw new Error(`Report submission failed (${res.status}). ${text13.slice(0, 200)}`);
|
|
101014
101546
|
}
|
|
101015
101547
|
const body = await res.json();
|
|
101016
101548
|
if (!body.issueUrl || typeof body.issueNumber !== "number")
|
|
@@ -101724,28 +102256,28 @@ async function execPresentControl(name, args) {
|
|
|
101724
102256
|
// ../../packages/host-core/dist/app-control-daemon.js
|
|
101725
102257
|
var DAEMON_TABLE = {
|
|
101726
102258
|
"present.state": async () => {
|
|
101727
|
-
const { text:
|
|
101728
|
-
return
|
|
102259
|
+
const { text: text13 } = await execPresentControl("deck_overview", {});
|
|
102260
|
+
return text13;
|
|
101729
102261
|
},
|
|
101730
102262
|
"present.deck": async () => {
|
|
101731
|
-
const { text:
|
|
101732
|
-
return
|
|
102263
|
+
const { text: text13 } = await execPresentControl("deck_overview", {});
|
|
102264
|
+
return text13;
|
|
101733
102265
|
},
|
|
101734
102266
|
"present.find_slide": async (input) => {
|
|
101735
|
-
const { text:
|
|
101736
|
-
return
|
|
102267
|
+
const { text: text13 } = await execPresentControl("find_slide", { query: String(input.query ?? "") });
|
|
102268
|
+
return text13;
|
|
101737
102269
|
},
|
|
101738
102270
|
"present.goto": async (input) => {
|
|
101739
|
-
const { text:
|
|
101740
|
-
return
|
|
102271
|
+
const { text: text13 } = await execPresentControl("goto_slide", { slide: Number(input.slide) });
|
|
102272
|
+
return text13;
|
|
101741
102273
|
},
|
|
101742
102274
|
"present.set_zoom": async (input) => {
|
|
101743
|
-
const { text:
|
|
101744
|
-
return
|
|
102275
|
+
const { text: text13 } = await execPresentControl("set_zoom", { level: Number(input.level) });
|
|
102276
|
+
return text13;
|
|
101745
102277
|
},
|
|
101746
102278
|
"present.set_blank": async (input) => {
|
|
101747
|
-
const { text:
|
|
101748
|
-
return
|
|
102279
|
+
const { text: text13 } = await execPresentControl("set_blank", { blanked: input.blanked === true });
|
|
102280
|
+
return text13;
|
|
101749
102281
|
},
|
|
101750
102282
|
"present.set_ai": async (input) => {
|
|
101751
102283
|
if (!isLive())
|
|
@@ -102306,7 +102838,10 @@ function refreshDaemonScheduling(b) {
|
|
|
102306
102838
|
// and a 3am fire would act on a switch the user changed days ago. The snapshot is
|
|
102307
102839
|
// already read fresh per turn everywhere else; this reads it fresh per fire.
|
|
102308
102840
|
isUnattended: () => readDaemonAgentSettings().unattended === true,
|
|
102309
|
-
isVerified: () => readDaemonAgentSettings().reinforcedVerification === true
|
|
102841
|
+
isVerified: () => readDaemonAgentSettings().reinforcedVerification === true,
|
|
102842
|
+
// The person's permission rules and hooks, for a fire that OPENS a conversation: it has no earlier turn
|
|
102843
|
+
// to replay them from, and it is the run nobody is watching. Read per fire, like the switches above.
|
|
102844
|
+
settings: () => readDaemonAgentSettings().settings
|
|
102310
102845
|
});
|
|
102311
102846
|
}
|
|
102312
102847
|
function daemonWorkspaceDir() {
|
|
@@ -102596,8 +103131,8 @@ async function linuxFavorites() {
|
|
|
102596
103131
|
];
|
|
102597
103132
|
for (const file2 of candidates) {
|
|
102598
103133
|
try {
|
|
102599
|
-
const
|
|
102600
|
-
const favs = finalize2(parseGtkBookmarks(
|
|
103134
|
+
const text13 = await readFile13(file2, "utf8");
|
|
103135
|
+
const favs = finalize2(parseGtkBookmarks(text13));
|
|
102601
103136
|
if (favs.length)
|
|
102602
103137
|
return favs;
|
|
102603
103138
|
} catch {
|
|
@@ -102605,9 +103140,9 @@ async function linuxFavorites() {
|
|
|
102605
103140
|
}
|
|
102606
103141
|
return [];
|
|
102607
103142
|
}
|
|
102608
|
-
function parseGtkBookmarks(
|
|
103143
|
+
function parseGtkBookmarks(text13) {
|
|
102609
103144
|
const out = [];
|
|
102610
|
-
for (const raw of
|
|
103145
|
+
for (const raw of text13.split(/\r?\n/)) {
|
|
102611
103146
|
const line = raw.trim();
|
|
102612
103147
|
if (!line.startsWith("file://"))
|
|
102613
103148
|
continue;
|
|
@@ -108807,8 +109342,8 @@ function safeJson(value) {
|
|
|
108807
109342
|
return "";
|
|
108808
109343
|
}
|
|
108809
109344
|
}
|
|
108810
|
-
function firstLine2(
|
|
108811
|
-
return
|
|
109345
|
+
function firstLine2(text13) {
|
|
109346
|
+
return text13.split("\n").map((l) => l.trim()).find(Boolean)?.slice(0, 80) ?? "";
|
|
108812
109347
|
}
|
|
108813
109348
|
function queryMatcher(query2) {
|
|
108814
109349
|
const q = query2.trim();
|
|
@@ -108816,11 +109351,11 @@ function queryMatcher(query2) {
|
|
|
108816
109351
|
return null;
|
|
108817
109352
|
return new RegExp(q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "iu");
|
|
108818
109353
|
}
|
|
108819
|
-
function snippetAt(
|
|
109354
|
+
function snippetAt(text13, at, length, radius = 60) {
|
|
108820
109355
|
const from = Math.max(0, at - radius);
|
|
108821
|
-
const to = Math.min(
|
|
108822
|
-
const body =
|
|
108823
|
-
return `${from > 0 ? "\u2026" : ""}${body}${to <
|
|
109356
|
+
const to = Math.min(text13.length, at + length + radius);
|
|
109357
|
+
const body = text13.slice(from, to).replace(/\s+/g, " ").trim();
|
|
109358
|
+
return `${from > 0 ? "\u2026" : ""}${body}${to < text13.length ? "\u2026" : ""}`;
|
|
108824
109359
|
}
|
|
108825
109360
|
|
|
108826
109361
|
// ../../packages/host-core/dist/session-search/text-cache.js
|
|
@@ -108876,10 +109411,10 @@ function createTextCache(baseDir) {
|
|
|
108876
109411
|
const nl = buf.lastIndexOf(10, end2 - 1);
|
|
108877
109412
|
end2 = nl >= at ? nl + 1 : Math.max(end2, buf.indexOf(10, end2) + 1 || buf.length);
|
|
108878
109413
|
}
|
|
108879
|
-
const { text:
|
|
109414
|
+
const { text: text13, bytes: bytes3 } = completeLines(buf.subarray(at, end2));
|
|
108880
109415
|
if (bytes3 === 0)
|
|
108881
109416
|
break;
|
|
108882
|
-
const out = extractSession(
|
|
109417
|
+
const out = extractSession(text13, { ...hints, text: "" });
|
|
108883
109418
|
if (out.text)
|
|
108884
109419
|
texts.push(out.text);
|
|
108885
109420
|
hints = out;
|
|
@@ -108887,9 +109422,9 @@ function createTextCache(baseDir) {
|
|
|
108887
109422
|
}
|
|
108888
109423
|
return { extraction: { ...hints, text: "", consumed: at }, texts, bytes: at };
|
|
108889
109424
|
}
|
|
108890
|
-
async function writeText(file2,
|
|
109425
|
+
async function writeText(file2, text13) {
|
|
108891
109426
|
const tmp = `${file2}.${process.pid}.${Date.now()}.tmp`;
|
|
108892
|
-
await writeFile14(tmp,
|
|
109427
|
+
await writeFile14(tmp, text13, { mode: 384 });
|
|
108893
109428
|
await rename5(tmp, file2);
|
|
108894
109429
|
}
|
|
108895
109430
|
async function extractWhole(file2, entry) {
|
|
@@ -108916,9 +109451,9 @@ function createTextCache(baseDir) {
|
|
|
108916
109451
|
return null;
|
|
108917
109452
|
}
|
|
108918
109453
|
const main2 = extractChunked(raw, fromArchive.extraction);
|
|
108919
|
-
const
|
|
109454
|
+
const text13 = [...fromArchive.texts, ...main2.texts].join("\n");
|
|
108920
109455
|
const textFile = entry?.textFile ?? textFileFor(file2.path);
|
|
108921
|
-
await writeText(join65(dir2, textFile),
|
|
109456
|
+
await writeText(join65(dir2, textFile), text13);
|
|
108922
109457
|
const { text: _t, consumed: _c, ...hints } = main2.extraction;
|
|
108923
109458
|
return {
|
|
108924
109459
|
path: file2.path,
|
|
@@ -109100,8 +109635,8 @@ function createSessionSearch(deps) {
|
|
|
109100
109635
|
continue;
|
|
109101
109636
|
const index = indexed.get(id);
|
|
109102
109637
|
const title = entry.hints.customTitle ?? index?.title ?? entry.hints.firstPrompt ?? entry.hints.aiTitle;
|
|
109103
|
-
const
|
|
109104
|
-
const inBody = matcher.exec(
|
|
109638
|
+
const text13 = await cache6.text(entry);
|
|
109639
|
+
const inBody = matcher.exec(text13);
|
|
109105
109640
|
const inTitle = title ? matcher.test(title) : false;
|
|
109106
109641
|
if (!inBody && !inTitle)
|
|
109107
109642
|
continue;
|
|
@@ -109113,7 +109648,7 @@ function createSessionSearch(deps) {
|
|
|
109113
109648
|
lastModified: entry.hints.lastTimestamp ?? entry.mtimeMs,
|
|
109114
109649
|
...cwd ? { cwd } : {},
|
|
109115
109650
|
engineId,
|
|
109116
|
-
...inBody ? { snippet: snippetAt(
|
|
109651
|
+
...inBody ? { snippet: snippetAt(text13, inBody.index, inBody[0].length) } : {}
|
|
109117
109652
|
};
|
|
109118
109653
|
run9.hits.push(hit);
|
|
109119
109654
|
found.push(hit);
|
|
@@ -111281,12 +111816,12 @@ var RdeskSessionManager = class {
|
|
|
111281
111816
|
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:muted", mic: !!mute.mic, systemAudio: !!mute.systemAudio });
|
|
111282
111817
|
}
|
|
111283
111818
|
/** Host operator → viewer: send an in-session chat line. No-op if the session is gone. */
|
|
111284
|
-
sendChat(sessionId,
|
|
111819
|
+
sendChat(sessionId, text13) {
|
|
111285
111820
|
const s = this.sessions.get(sessionId);
|
|
111286
111821
|
if (!s)
|
|
111287
111822
|
return;
|
|
111288
|
-
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:chat", text:
|
|
111289
|
-
this.audit({ event: "chat", sessionId, detail: `host: ${
|
|
111823
|
+
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:chat", text: text13, from: "host", at: Date.now() });
|
|
111824
|
+
this.audit({ event: "chat", sessionId, detail: `host: ${text13.slice(0, 80)}` });
|
|
111290
111825
|
}
|
|
111291
111826
|
/** Switch the captured display. */
|
|
111292
111827
|
async setMonitor(sessionId, monitorId) {
|
|
@@ -111318,9 +111853,9 @@ var RdeskSessionManager = class {
|
|
|
111318
111853
|
return this.sendKeys(sessionId, msg.combo);
|
|
111319
111854
|
if (msg.type === "rdesk:chat") {
|
|
111320
111855
|
const s = this.sessions.get(sessionId);
|
|
111321
|
-
const
|
|
111322
|
-
this.deps.onChat?.({ sessionId, viewerName: s?.viewer.name, text:
|
|
111323
|
-
this.audit({ event: "chat", sessionId, detail:
|
|
111856
|
+
const text13 = msg.text.slice(0, 4e3);
|
|
111857
|
+
this.deps.onChat?.({ sessionId, viewerName: s?.viewer.name, text: text13 });
|
|
111858
|
+
this.audit({ event: "chat", sessionId, detail: text13.slice(0, 80) });
|
|
111324
111859
|
return;
|
|
111325
111860
|
}
|
|
111326
111861
|
if (msg.type === "rdesk:av") {
|
|
@@ -111963,8 +112498,8 @@ function waylandInputRunner(p, screen) {
|
|
|
111963
112498
|
async scroll(o) {
|
|
111964
112499
|
p.pointerAxis(o.dx ?? 0, o.dy ?? 0);
|
|
111965
112500
|
},
|
|
111966
|
-
async typeText(
|
|
111967
|
-
for (const ch of
|
|
112501
|
+
async typeText(text13) {
|
|
112502
|
+
for (const ch of text13) {
|
|
111968
112503
|
const ks = charKeysym(ch);
|
|
111969
112504
|
if (!ks)
|
|
111970
112505
|
continue;
|
|
@@ -112138,11 +112673,11 @@ var TesseractEngine = class {
|
|
|
112138
112673
|
onInput: (ev) => void this.injector?.apply(ev),
|
|
112139
112674
|
// Clipboard sync (Phase 6): write the viewer's clipboard onto the host so ⌘V pastes
|
|
112140
112675
|
// into the remote machine. Gated by control access (view-only never writes).
|
|
112141
|
-
onClipboard: (
|
|
112676
|
+
onClipboard: (text13) => {
|
|
112142
112677
|
if (this.access === "control") {
|
|
112143
112678
|
const el2 = electronModule();
|
|
112144
112679
|
try {
|
|
112145
|
-
el2?.clipboard?.writeText(
|
|
112680
|
+
el2?.clipboard?.writeText(text13);
|
|
112146
112681
|
} catch {
|
|
112147
112682
|
}
|
|
112148
112683
|
}
|
|
@@ -114560,8 +115095,8 @@ async function startLocalServer(opts) {
|
|
|
114560
115095
|
if (!vc || !vc.isPresentMode)
|
|
114561
115096
|
return null;
|
|
114562
115097
|
return {
|
|
114563
|
-
injectContext: (
|
|
114564
|
-
ask: (
|
|
115098
|
+
injectContext: (text13) => vc.injectPresentContext(text13),
|
|
115099
|
+
ask: (text13) => vc.askPresent(text13)
|
|
114565
115100
|
};
|
|
114566
115101
|
});
|
|
114567
115102
|
const unregisterSink = registerAgentSink((msg, origin2) => {
|
|
@@ -115685,7 +116220,7 @@ async function getPeerIdentityPub(opts) {
|
|
|
115685
116220
|
}
|
|
115686
116221
|
|
|
115687
116222
|
// ../../packages/host-core/dist/mesh/node.js
|
|
115688
|
-
import { createSocket
|
|
116223
|
+
import { createSocket } from "node:dgram";
|
|
115689
116224
|
import { createRequire as createRequire4 } from "node:module";
|
|
115690
116225
|
init_credentials();
|
|
115691
116226
|
|
|
@@ -116212,6 +116747,8 @@ async function netdNodeStatus(meshId) {
|
|
|
116212
116747
|
relayed: strs("relayed"),
|
|
116213
116748
|
policyEpoch: num2("policyEpoch"),
|
|
116214
116749
|
revoked: b.revoked === true,
|
|
116750
|
+
lan: b.lan === true,
|
|
116751
|
+
lanError: typeof b.lanError === "string" ? b.lanError : null,
|
|
116215
116752
|
bundleStaleInMs: typeof b.bundleStaleInMs === "number" ? b.bundleStaleInMs : null,
|
|
116216
116753
|
lastError: typeof b.lastError === "string" ? b.lastError : null,
|
|
116217
116754
|
localStaticPub: Uint8Array.from(Buffer.from(pubHex, "hex")),
|
|
@@ -116394,6 +116931,15 @@ var NetdEngine = class {
|
|
|
116394
116931
|
get srflx() {
|
|
116395
116932
|
return this.#snapshot?.srflx ?? null;
|
|
116396
116933
|
}
|
|
116934
|
+
/** Whether the HELPER's LAN discovery joined the multicast group — it owns that socket
|
|
116935
|
+
* now, so this is the only honest source for it. */
|
|
116936
|
+
get lan() {
|
|
116937
|
+
return this.#snapshot?.lan === true;
|
|
116938
|
+
}
|
|
116939
|
+
/** Why LAN discovery is off, when it is — the helper records the step that failed. */
|
|
116940
|
+
get lanError() {
|
|
116941
|
+
return this.#snapshot?.lanError ?? null;
|
|
116942
|
+
}
|
|
116397
116943
|
/** The same over IPv6, advertised alongside rather than instead. */
|
|
116398
116944
|
get srflx6() {
|
|
116399
116945
|
return this.#snapshot?.srflx6 ?? null;
|
|
@@ -116489,127 +117035,6 @@ ${ts}`);
|
|
|
116489
117035
|
}
|
|
116490
117036
|
}
|
|
116491
117037
|
|
|
116492
|
-
// ../../packages/host-core/dist/mesh/lan.js
|
|
116493
|
-
import { createSocket } from "node:dgram";
|
|
116494
|
-
var MAGIC = Buffer.from("TSRL");
|
|
116495
|
-
var VERSION2 = 1;
|
|
116496
|
-
var LAN_GROUP_V4 = "224.0.0.251";
|
|
116497
|
-
var LAN_PORT = 5353;
|
|
116498
|
-
var BEACON_LEN = 4 + 1 + 3 + 32 + 32 + 2 + 8;
|
|
116499
|
-
var ANNOUNCE_MS = 5e3;
|
|
116500
|
-
function encodeBeacon(b) {
|
|
116501
|
-
const out = Buffer.alloc(BEACON_LEN);
|
|
116502
|
-
MAGIC.copy(out, 0);
|
|
116503
|
-
out[4] = VERSION2;
|
|
116504
|
-
b.genesisFp.copy(out, 8, 0, 32);
|
|
116505
|
-
b.staticPub.copy(out, 40, 0, 32);
|
|
116506
|
-
out.writeUInt16BE(b.port, 72);
|
|
116507
|
-
out.writeUInt32BE(Math.floor(b.epoch / 4294967296), 74);
|
|
116508
|
-
out.writeUInt32BE(b.epoch >>> 0, 78);
|
|
116509
|
-
return out;
|
|
116510
|
-
}
|
|
116511
|
-
function parseBeacon(buf) {
|
|
116512
|
-
if (buf.length !== BEACON_LEN)
|
|
116513
|
-
return null;
|
|
116514
|
-
if (!buf.subarray(0, 4).equals(MAGIC))
|
|
116515
|
-
return null;
|
|
116516
|
-
if (buf[4] !== VERSION2)
|
|
116517
|
-
return null;
|
|
116518
|
-
if (buf[5] !== 0 || buf[6] !== 0 || buf[7] !== 0)
|
|
116519
|
-
return null;
|
|
116520
|
-
const port = buf.readUInt16BE(72);
|
|
116521
|
-
if (port < 1)
|
|
116522
|
-
return null;
|
|
116523
|
-
const epoch2 = buf.readUInt32BE(74) * 4294967296 + buf.readUInt32BE(78);
|
|
116524
|
-
return {
|
|
116525
|
-
genesisFp: buf.subarray(8, 40),
|
|
116526
|
-
staticPub: buf.subarray(40, 72),
|
|
116527
|
-
port,
|
|
116528
|
-
epoch: epoch2
|
|
116529
|
-
};
|
|
116530
|
-
}
|
|
116531
|
-
var LanDiscovery = class {
|
|
116532
|
-
#sock = null;
|
|
116533
|
-
#timer = null;
|
|
116534
|
-
#joined = false;
|
|
116535
|
-
#opts;
|
|
116536
|
-
constructor(opts) {
|
|
116537
|
-
this.#opts = opts;
|
|
116538
|
-
}
|
|
116539
|
-
get active() {
|
|
116540
|
-
return this.#joined;
|
|
116541
|
-
}
|
|
116542
|
-
start() {
|
|
116543
|
-
if (this.#sock)
|
|
116544
|
-
return;
|
|
116545
|
-
const sock = createSocket({ type: "udp4", reuseAddr: true });
|
|
116546
|
-
sock.on("error", () => {
|
|
116547
|
-
this.stop();
|
|
116548
|
-
});
|
|
116549
|
-
sock.on("message", (msg, rinfo) => this.#onBeacon(msg, rinfo.address));
|
|
116550
|
-
sock.bind(LAN_PORT, () => {
|
|
116551
|
-
try {
|
|
116552
|
-
sock.addMembership(LAN_GROUP_V4);
|
|
116553
|
-
sock.setMulticastLoopback(true);
|
|
116554
|
-
sock.setMulticastTTL(1);
|
|
116555
|
-
this.#joined = true;
|
|
116556
|
-
this.#announce();
|
|
116557
|
-
} catch {
|
|
116558
|
-
this.stop();
|
|
116559
|
-
}
|
|
116560
|
-
});
|
|
116561
|
-
sock.unref?.();
|
|
116562
|
-
this.#sock = sock;
|
|
116563
|
-
this.#timer = setInterval(() => this.#announce(), ANNOUNCE_MS);
|
|
116564
|
-
this.#timer.unref?.();
|
|
116565
|
-
}
|
|
116566
|
-
stop() {
|
|
116567
|
-
if (this.#timer) {
|
|
116568
|
-
clearInterval(this.#timer);
|
|
116569
|
-
this.#timer = null;
|
|
116570
|
-
}
|
|
116571
|
-
if (this.#sock) {
|
|
116572
|
-
try {
|
|
116573
|
-
if (this.#joined)
|
|
116574
|
-
this.#sock.dropMembership(LAN_GROUP_V4);
|
|
116575
|
-
} catch {
|
|
116576
|
-
}
|
|
116577
|
-
try {
|
|
116578
|
-
this.#sock.close();
|
|
116579
|
-
} catch {
|
|
116580
|
-
}
|
|
116581
|
-
}
|
|
116582
|
-
this.#sock = null;
|
|
116583
|
-
this.#joined = false;
|
|
116584
|
-
}
|
|
116585
|
-
#announce() {
|
|
116586
|
-
const port = this.#opts.port();
|
|
116587
|
-
if (!this.#sock || !this.#joined || port === null)
|
|
116588
|
-
return;
|
|
116589
|
-
const frame = encodeBeacon({
|
|
116590
|
-
genesisFp: this.#opts.genesisFp,
|
|
116591
|
-
staticPub: this.#opts.staticPub,
|
|
116592
|
-
port,
|
|
116593
|
-
epoch: this.#opts.epoch()
|
|
116594
|
-
});
|
|
116595
|
-
try {
|
|
116596
|
-
this.#sock.send(frame, LAN_PORT, LAN_GROUP_V4, () => {
|
|
116597
|
-
});
|
|
116598
|
-
} catch {
|
|
116599
|
-
}
|
|
116600
|
-
}
|
|
116601
|
-
#onBeacon(msg, address) {
|
|
116602
|
-
const b = parseBeacon(msg);
|
|
116603
|
-
if (!b)
|
|
116604
|
-
return;
|
|
116605
|
-
if (!b.genesisFp.equals(this.#opts.genesisFp))
|
|
116606
|
-
return;
|
|
116607
|
-
if (b.staticPub.equals(this.#opts.staticPub))
|
|
116608
|
-
return;
|
|
116609
|
-
this.#opts.onPeer(Buffer.from(b.staticPub), address, b.port, b.epoch);
|
|
116610
|
-
}
|
|
116611
|
-
};
|
|
116612
|
-
|
|
116613
117038
|
// ../../packages/host-core/dist/mesh/endpoints.js
|
|
116614
117039
|
function inRange(range, addr) {
|
|
116615
117040
|
if (addr.length !== range.addr.length)
|
|
@@ -116886,7 +117311,6 @@ var MeshNode = class {
|
|
|
116886
117311
|
* can be offered a choice that has somewhere to go.
|
|
116887
117312
|
*/
|
|
116888
117313
|
#exitNodes = /* @__PURE__ */ new Map();
|
|
116889
|
-
#lan = null;
|
|
116890
117314
|
#offRejoin = null;
|
|
116891
117315
|
#statusTimer = null;
|
|
116892
117316
|
/**
|
|
@@ -116936,7 +117360,8 @@ var MeshNode = class {
|
|
|
116936
117360
|
enrolled: this.#identity !== null || this.#loadIdentity() !== null,
|
|
116937
117361
|
running: this.#engine !== null,
|
|
116938
117362
|
port: this.#port,
|
|
116939
|
-
lan: this.#lan
|
|
117363
|
+
lan: this.#engine instanceof NetdEngine ? this.#engine.lan : false,
|
|
117364
|
+
lanError: this.#engine instanceof NetdEngine ? this.#engine.lanError : null,
|
|
116940
117365
|
reachableAt: this.#engine instanceof NetdEngine ? [this.#engine.mapped, this.#engine.srflx, this.#engine.srflx6].filter((x) => x !== null).join(", ") || null : null,
|
|
116941
117366
|
// Only the helper publishes names: writing the machine's name table needs root, and
|
|
116942
117367
|
// the roster comes from the engine the helper runs. An in-process engine has a roster
|
|
@@ -117024,7 +117449,6 @@ var MeshNode = class {
|
|
|
117024
117449
|
onUp: (port) => {
|
|
117025
117450
|
this.#port = port;
|
|
117026
117451
|
this.#join();
|
|
117027
|
-
this.#startLan();
|
|
117028
117452
|
this.#publishStatus();
|
|
117029
117453
|
}
|
|
117030
117454
|
});
|
|
@@ -117051,7 +117475,6 @@ var MeshNode = class {
|
|
|
117051
117475
|
this.#identity = id;
|
|
117052
117476
|
if (!inNetd) {
|
|
117053
117477
|
this.#openSocket();
|
|
117054
|
-
this.#startLan();
|
|
117055
117478
|
}
|
|
117056
117479
|
this.#offRejoin = onMeshRejoin(() => this.#join());
|
|
117057
117480
|
this.#publishStatus();
|
|
@@ -117096,11 +117519,6 @@ var MeshNode = class {
|
|
|
117096
117519
|
this.#published = false;
|
|
117097
117520
|
}
|
|
117098
117521
|
this.#runningMeshDir = null;
|
|
117099
|
-
try {
|
|
117100
|
-
this.#lan?.stop();
|
|
117101
|
-
} catch {
|
|
117102
|
-
}
|
|
117103
|
-
this.#lan = null;
|
|
117104
117522
|
try {
|
|
117105
117523
|
this.#sock?.close();
|
|
117106
117524
|
} catch {
|
|
@@ -117141,7 +117559,7 @@ var MeshNode = class {
|
|
|
117141
117559
|
return Number.isInteger(port) && port > 0 ? { host: ep.slice(0, i), port } : null;
|
|
117142
117560
|
}
|
|
117143
117561
|
#openSocket() {
|
|
117144
|
-
const sock =
|
|
117562
|
+
const sock = createSocket({ type: "udp6", ipv6Only: false, reuseAddr: true });
|
|
117145
117563
|
sock.on("message", (msg, rinfo) => {
|
|
117146
117564
|
if (!this.#engine)
|
|
117147
117565
|
return;
|
|
@@ -117166,54 +117584,20 @@ var MeshNode = class {
|
|
|
117166
117584
|
sock.unref?.();
|
|
117167
117585
|
this.#sock = sock;
|
|
117168
117586
|
}
|
|
117169
|
-
|
|
117587
|
+
/* LAN discovery used to live here, as a multicast beacon in this process
|
|
117588
|
+
* (`./lan.ts`). It has MOVED INTO THE HELPER (`crates/tsmesh-netd/src/lan.rs`,
|
|
117589
|
+
* frame in `tsmesh_proto::lan`).
|
|
117170
117590
|
*
|
|
117171
|
-
*
|
|
117172
|
-
*
|
|
117173
|
-
*
|
|
117174
|
-
|
|
117175
|
-
|
|
117176
|
-
if (!engine)
|
|
117177
|
-
return;
|
|
117178
|
-
try {
|
|
117179
|
-
this.#lan = new LanDiscovery({
|
|
117180
|
-
genesisFp: Buffer.from(engine.meshId(), "hex"),
|
|
117181
|
-
staticPub: engine.localStaticPub(),
|
|
117182
|
-
port: () => this.#port,
|
|
117183
|
-
epoch: () => engine.policyEpoch(),
|
|
117184
|
-
onPeer: (staticPub, address, port, epoch2) => this.#learnLanPeer(staticPub, address, port, epoch2)
|
|
117185
|
-
});
|
|
117186
|
-
this.#lan.start();
|
|
117187
|
-
} catch {
|
|
117188
|
-
this.#lan = null;
|
|
117189
|
-
}
|
|
117190
|
-
}
|
|
117191
|
-
/** A beacon arrived. Treated exactly like a relay hint — a candidate, not a fact.
|
|
117591
|
+
* It had to. The beacon only ran while this app was running, so a headless machine --
|
|
117592
|
+
* a server, the thing the network exists to reach -- could not find a peer sharing its
|
|
117593
|
+
* switch. And on the netd path the app was announcing a port held by a different
|
|
117594
|
+
* process entirely. The helper starts at boot with no app and owns the socket, so the
|
|
117595
|
+
* beacon belongs beside it.
|
|
117192
117596
|
*
|
|
117193
|
-
*
|
|
117194
|
-
*
|
|
117195
|
-
*
|
|
117196
|
-
|
|
117197
|
-
* relay-dependent; without this they would find each other and then never agree on who
|
|
117198
|
-
* else exists. */
|
|
117199
|
-
#learnLanPeer(staticPub, address, port, epoch2 = 0) {
|
|
117200
|
-
const engine = this.#engine;
|
|
117201
|
-
if (!engine)
|
|
117202
|
-
return;
|
|
117203
|
-
const hex6 = staticPub.toString("hex");
|
|
117204
|
-
this.#offerBundleTo(hex6, epoch2);
|
|
117205
|
-
try {
|
|
117206
|
-
if (!this.#peers.has(hex6)) {
|
|
117207
|
-
engine.addPeer(staticPub, 0, Buffer.alloc(16));
|
|
117208
|
-
this.#peers.set(hex6, staticPub);
|
|
117209
|
-
}
|
|
117210
|
-
engine.addPath(staticPub, `${address}:${port}`, false);
|
|
117211
|
-
engine.ensureHandshake(staticPub, Date.now());
|
|
117212
|
-
this.#drain();
|
|
117213
|
-
} catch (e) {
|
|
117214
|
-
this.#lastError = e instanceof Error ? e.message : String(e);
|
|
117215
|
-
}
|
|
117216
|
-
}
|
|
117597
|
+
* Moved rather than duplicated: two implementations of a parser that reads
|
|
117598
|
+
* unauthenticated multicast from every device on the segment is the one risk
|
|
117599
|
+
* docs/MESH.md names as unacceptable.
|
|
117600
|
+
*/
|
|
117217
117601
|
#subscribe() {
|
|
117218
117602
|
this.#unsubscribe = onMesh((m) => this.#onHint(m));
|
|
117219
117603
|
}
|
|
@@ -117796,11 +118180,11 @@ async function call2(path6, init, auth = true) {
|
|
|
117796
118180
|
} catch (e) {
|
|
117797
118181
|
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
117798
118182
|
}
|
|
117799
|
-
const
|
|
118183
|
+
const text13 = await res.text();
|
|
117800
118184
|
if (!res.ok) {
|
|
117801
|
-
let detail =
|
|
118185
|
+
let detail = text13.slice(0, 500);
|
|
117802
118186
|
try {
|
|
117803
|
-
const parsed = JSON.parse(
|
|
118187
|
+
const parsed = JSON.parse(text13);
|
|
117804
118188
|
if (parsed.message)
|
|
117805
118189
|
detail = Array.isArray(parsed.message) ? parsed.message.join("; ") : parsed.message;
|
|
117806
118190
|
} catch {
|
|
@@ -117808,7 +118192,7 @@ async function call2(path6, init, auth = true) {
|
|
|
117808
118192
|
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
117809
118193
|
}
|
|
117810
118194
|
try {
|
|
117811
|
-
return { ok: true, data:
|
|
118195
|
+
return { ok: true, data: text13 ? JSON.parse(text13) : {} };
|
|
117812
118196
|
} catch {
|
|
117813
118197
|
return fail3("server", "the server sent something that is not JSON");
|
|
117814
118198
|
}
|
|
@@ -118010,18 +118394,18 @@ async function postJoin(origin, body) {
|
|
|
118010
118394
|
} catch (e) {
|
|
118011
118395
|
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
118012
118396
|
}
|
|
118013
|
-
const
|
|
118397
|
+
const text13 = await res.text();
|
|
118014
118398
|
if (!res.ok) {
|
|
118015
|
-
let detail =
|
|
118399
|
+
let detail = text13.slice(0, 500);
|
|
118016
118400
|
try {
|
|
118017
|
-
const parsed = JSON.parse(
|
|
118401
|
+
const parsed = JSON.parse(text13);
|
|
118018
118402
|
if (parsed.message)
|
|
118019
118403
|
detail = String(parsed.message);
|
|
118020
118404
|
} catch {
|
|
118021
118405
|
}
|
|
118022
118406
|
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
118023
118407
|
}
|
|
118024
|
-
return { ok: true, data: JSON.parse(
|
|
118408
|
+
return { ok: true, data: JSON.parse(text13) };
|
|
118025
118409
|
}
|
|
118026
118410
|
async function enrolWithCode(args) {
|
|
118027
118411
|
return enrolWith(args.name, async (staticPub, sigPub, name) => postJoin(args.origin, { code: args.code, name, staticPub, sigPub }), resolveOrigin(args.origin), args.fromHostname);
|
|
@@ -118881,9 +119265,9 @@ import { pipeline } from "node:stream/promises";
|
|
|
118881
119265
|
|
|
118882
119266
|
// ../../packages/host-core/dist/drops/crypto.js
|
|
118883
119267
|
import { Transform } from "node:stream";
|
|
118884
|
-
var
|
|
119268
|
+
var MAGIC = Buffer.from("TSD1", "ascii");
|
|
118885
119269
|
var NONCE_BYTES = 12;
|
|
118886
|
-
var HEADER_BYTES =
|
|
119270
|
+
var HEADER_BYTES = MAGIC.length + NONCE_BYTES;
|
|
118887
119271
|
var FRAME_BYTES = 1024 * 1024;
|
|
118888
119272
|
var TAG_BYTES = 16;
|
|
118889
119273
|
var MAX_FRAME_CIPHERTEXT = FRAME_BYTES + TAG_BYTES + 1024;
|
|
@@ -118964,9 +119348,9 @@ function decryptStream(source, keyRaw) {
|
|
|
118964
119348
|
cb();
|
|
118965
119349
|
return;
|
|
118966
119350
|
}
|
|
118967
|
-
if (!head.subarray(0,
|
|
119351
|
+
if (!head.subarray(0, MAGIC.length).equals(MAGIC))
|
|
118968
119352
|
throw new Error("not an encrypted drop");
|
|
118969
|
-
base = Buffer.from(head.subarray(
|
|
119353
|
+
base = Buffer.from(head.subarray(MAGIC.length, HEADER_BYTES));
|
|
118970
119354
|
q.consume(HEADER_BYTES);
|
|
118971
119355
|
key2 = await importKey(keyRaw);
|
|
118972
119356
|
}
|
|
@@ -119136,7 +119520,7 @@ function createChatAgentRunner(deps) {
|
|
|
119136
119520
|
const backend2 = await getSharedBackend();
|
|
119137
119521
|
const clientRequestId = `chat-agent-${randomUUID32()}`;
|
|
119138
119522
|
return new Promise((resolve16, reject) => {
|
|
119139
|
-
let
|
|
119523
|
+
let text13 = "";
|
|
119140
119524
|
let settled = false;
|
|
119141
119525
|
const finish2 = (fn) => {
|
|
119142
119526
|
if (settled)
|
|
@@ -119150,13 +119534,13 @@ function createChatAgentRunner(deps) {
|
|
|
119150
119534
|
}
|
|
119151
119535
|
fn();
|
|
119152
119536
|
};
|
|
119153
|
-
const timer2 = setTimeout(() => finish2(() =>
|
|
119537
|
+
const timer2 = setTimeout(() => finish2(() => text13.trim() ? resolve16(text13) : reject(new Error("the agent took too long"))), TURN_TIMEOUT_MS);
|
|
119154
119538
|
let posting = false;
|
|
119155
119539
|
let lastSent = "";
|
|
119156
119540
|
const tick = setInterval(() => {
|
|
119157
119541
|
if (posting || !onPartial)
|
|
119158
119542
|
return;
|
|
119159
|
-
const snapshot4 =
|
|
119543
|
+
const snapshot4 = text13.trim();
|
|
119160
119544
|
if (!snapshot4 || snapshot4 === lastSent)
|
|
119161
119545
|
return;
|
|
119162
119546
|
lastSent = snapshot4;
|
|
@@ -119172,9 +119556,9 @@ function createChatAgentRunner(deps) {
|
|
|
119172
119556
|
return;
|
|
119173
119557
|
if (m.type === "chat:stream") {
|
|
119174
119558
|
if ((m.kind === "text" || m.kind === void 0) && m.delta)
|
|
119175
|
-
|
|
119559
|
+
text13 += m.delta;
|
|
119176
119560
|
} else if (m.type === "chat:complete") {
|
|
119177
|
-
finish2(() => resolve16(
|
|
119561
|
+
finish2(() => resolve16(text13));
|
|
119178
119562
|
} else if (m.type === "chat:error") {
|
|
119179
119563
|
finish2(() => reject(new Error(m.message ?? m.error ?? "the agent errored")));
|
|
119180
119564
|
}
|
|
@@ -121334,7 +121718,7 @@ function backoff2() {
|
|
|
121334
121718
|
var daemonClipboardSync = null;
|
|
121335
121719
|
var REFRESH_INTERVAL_MS2 = 12 * 60 * 60 * 1e3;
|
|
121336
121720
|
async function runDaemon(opts = {}) {
|
|
121337
|
-
const
|
|
121721
|
+
const VERSION2 = opts.version ?? process.env.CCB_DAEMON_VERSION ?? "dev";
|
|
121338
121722
|
const TAG = opts.tag ?? "host-daemon";
|
|
121339
121723
|
const KIND = opts.kind ?? "app";
|
|
121340
121724
|
const log10 = (...args) => console.log(`[${TAG} ${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args);
|
|
@@ -121410,14 +121794,14 @@ async function runDaemon(opts = {}) {
|
|
|
121410
121794
|
if (!ownsMachine)
|
|
121411
121795
|
return;
|
|
121412
121796
|
try {
|
|
121413
|
-
writeFileSync44(statusFile2(), JSON.stringify({ pid: process.pid, startedAt: OUR_STARTED_AT, role: process.env.CCB_RDESK_ROLE ?? "host", kind: KIND, version:
|
|
121797
|
+
writeFileSync44(statusFile2(), JSON.stringify({ pid: process.pid, startedAt: OUR_STARTED_AT, role: process.env.CCB_RDESK_ROLE ?? "host", kind: KIND, version: VERSION2, execPath: process.env.CCB_DAEMON_EXECPATH ?? process.execPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), gui: daemonGuiTrayActive(), ...localInfo ?? {}, ...s }));
|
|
121414
121798
|
chmodSync8(statusFile2(), 384);
|
|
121415
121799
|
} catch {
|
|
121416
121800
|
}
|
|
121417
121801
|
}
|
|
121418
121802
|
const standaloneViewer = process.env.CCB_RDESK_ROLE === "client";
|
|
121419
121803
|
if (!standaloneViewer) {
|
|
121420
|
-
registerSelfAsDaemon(
|
|
121804
|
+
registerSelfAsDaemon(VERSION2);
|
|
121421
121805
|
if (KIND === "app") {
|
|
121422
121806
|
try {
|
|
121423
121807
|
await evictCliAgent(log10);
|
|
@@ -121625,7 +122009,7 @@ async function runDaemon(opts = {}) {
|
|
|
121625
122009
|
unregisterSelfAsDaemon();
|
|
121626
122010
|
process.exit(code);
|
|
121627
122011
|
}
|
|
121628
|
-
startSystemEvents({ version:
|
|
122012
|
+
startSystemEvents({ version: VERSION2, log: (m) => log10(m) });
|
|
121629
122013
|
const mergedProcess = opts.merged === true;
|
|
121630
122014
|
const deliberateMergedQuit = () => !!globalThis.__ccbDeliberateQuit;
|
|
121631
122015
|
const onTermSignal = (sig) => {
|
|
@@ -121892,7 +122276,7 @@ async function runDaemon(opts = {}) {
|
|
|
121892
122276
|
if (!creds3) {
|
|
121893
122277
|
timer2 = setInterval(() => writeStatus2({ deviceId: deviceId3, connected: false, localOnly: true }), 6e4);
|
|
121894
122278
|
writeStatus2({ deviceId: deviceId3, connected: false, localOnly: true });
|
|
121895
|
-
log10(`started LOCAL-ONLY (no identity yet) \u2014 local :${localInfo?.localPort ?? "off"}, version ${
|
|
122279
|
+
log10(`started LOCAL-ONLY (no identity yet) \u2014 local :${localInfo?.localPort ?? "off"}, version ${VERSION2}; will keep trying`);
|
|
121896
122280
|
const watch4 = watchForIdentity({ attempt: acquireIdentity, log: (m) => log10(m) });
|
|
121897
122281
|
identityWatch = watch4;
|
|
121898
122282
|
setDaemonIdentityReload(async () => {
|
|
@@ -122153,14 +122537,14 @@ async function runDaemon(opts = {}) {
|
|
|
122153
122537
|
// On macOS the notification carries an inline REPLY box (hasReply) whose text is sent
|
|
122154
122538
|
// straight back via sendChat — a full operator chat loop with no extra window. Off-mac (no
|
|
122155
122539
|
// hasReply) it's receive-only for now; the daemon log always records it as a fallback.
|
|
122156
|
-
onChat: ({ sessionId, viewerName, text:
|
|
122540
|
+
onChat: ({ sessionId, viewerName, text: text13 }) => {
|
|
122157
122541
|
const NotifCtor = electronModule()?.Notification;
|
|
122158
122542
|
if (!NotifCtor) {
|
|
122159
|
-
log10(`[rdesk chat] ${viewerName ?? "viewer"}: ${
|
|
122543
|
+
log10(`[rdesk chat] ${viewerName ?? "viewer"}: ${text13}`);
|
|
122160
122544
|
return;
|
|
122161
122545
|
}
|
|
122162
122546
|
try {
|
|
122163
|
-
const n = new NotifCtor({ title: `${viewerName ?? "Remote viewer"} \u2014 remote desktop`, body:
|
|
122547
|
+
const n = new NotifCtor({ title: `${viewerName ?? "Remote viewer"} \u2014 remote desktop`, body: text13, hasReply: true, replyPlaceholder: "Reply\u2026" });
|
|
122164
122548
|
n.on("reply", (_e, reply3) => {
|
|
122165
122549
|
const r = typeof reply3 === "string" ? reply3.trim() : "";
|
|
122166
122550
|
if (r)
|
|
@@ -122500,7 +122884,7 @@ async function runDaemon(opts = {}) {
|
|
|
122500
122884
|
log10("e2e responder init failed (staying plaintext)", err2.message);
|
|
122501
122885
|
}
|
|
122502
122886
|
}
|
|
122503
|
-
startControlLink({ deviceId: c.deviceId, power: createNodePowerController(), tokenSource, version:
|
|
122887
|
+
startControlLink({ deviceId: c.deviceId, power: createNodePowerController(), tokenSource, version: VERSION2, e2e }, hooks2);
|
|
122504
122888
|
offRecovery = onSystemEvent(({ event }) => {
|
|
122505
122889
|
const suspended = isSuspensionSignal(event);
|
|
122506
122890
|
if (suspended)
|
|
@@ -122601,7 +122985,7 @@ async function runDaemon(opts = {}) {
|
|
|
122601
122985
|
}
|
|
122602
122986
|
}
|
|
122603
122987
|
const who = c.userId ? `user ${c.userId}` : "no account (unclaimed machine)";
|
|
122604
|
-
log10(`started \u2014 device ${c.deviceId}, ${who}, relay ${c.backendOrigin}, local :${localInfo?.localPort ?? "off"}, version ${
|
|
122988
|
+
log10(`started \u2014 device ${c.deviceId}, ${who}, relay ${c.backendOrigin}, local :${localInfo?.localPort ?? "off"}, version ${VERSION2}`);
|
|
122605
122989
|
await refresh();
|
|
122606
122990
|
timer2 = setInterval(() => {
|
|
122607
122991
|
void refresh();
|
|
@@ -122709,8 +123093,8 @@ function installOwnerUid(env = process.env, self2 = typeof process.getuid === "f
|
|
|
122709
123093
|
}
|
|
122710
123094
|
return self2;
|
|
122711
123095
|
}
|
|
122712
|
-
function parseOwnerUid(
|
|
122713
|
-
const m = /--owner-uid(?:<\/string>)?[\s=]*(?:<string>)?(\d+)/.exec(
|
|
123096
|
+
function parseOwnerUid(text13) {
|
|
123097
|
+
const m = /--owner-uid(?:<\/string>)?[\s=]*(?:<string>)?(\d+)/.exec(text13);
|
|
122714
123098
|
if (!m)
|
|
122715
123099
|
return void 0;
|
|
122716
123100
|
const uid = Number(m[1]);
|
|
@@ -122767,8 +123151,8 @@ function bundleIdForExec(exec2) {
|
|
|
122767
123151
|
return void 0;
|
|
122768
123152
|
}
|
|
122769
123153
|
}
|
|
122770
|
-
function parseAssociatedBundleId(
|
|
122771
|
-
const m = /<key>AssociatedBundleIdentifiers<\/key>\s*(?:<array>\s*)?<string>([^<]*)<\/string>/.exec(
|
|
123154
|
+
function parseAssociatedBundleId(text13) {
|
|
123155
|
+
const m = /<key>AssociatedBundleIdentifiers<\/key>\s*(?:<array>\s*)?<string>([^<]*)<\/string>/.exec(text13);
|
|
122772
123156
|
const id = m?.[1]?.trim();
|
|
122773
123157
|
return id && looksLikeBundleId(id) ? id : void 0;
|
|
122774
123158
|
}
|
|
@@ -122829,10 +123213,25 @@ ${args}
|
|
|
122829
123213
|
<integer>30</integer>
|
|
122830
123214
|
<key>ProcessType</key>
|
|
122831
123215
|
<string>Interactive</string>
|
|
123216
|
+
<!-- /dev/null, NOT netd.log, and this is load-bearing.
|
|
123217
|
+
|
|
123218
|
+
These two keys used to point at netd.log, and launchd does not rotate what it
|
|
123219
|
+
redirects \u2014 so the file grew for the life of the install. The same omission on
|
|
123220
|
+
Windows reached 136 GB on a CI runner and hung two hours of release builds while
|
|
123221
|
+
looking like an npm problem; macOS had it too and nobody had looked.
|
|
123222
|
+
|
|
123223
|
+
netd now owns netd.log itself and rotates it (tsmesh_netd::logfile, 8 MiB, one
|
|
123224
|
+
previous generation). Leaving launchd pointed at the same path would be WORSE than
|
|
123225
|
+
the bug: after netd renames the file, launchd's descriptor still refers to the
|
|
123226
|
+
renamed inode, so it would append to the "previous generation" forever and no
|
|
123227
|
+
rotation could ever reclaim it. One writer, or none.
|
|
123228
|
+
|
|
123229
|
+
Nothing is lost by discarding this stream: everything netd logs goes through its own
|
|
123230
|
+
sink, and a panic is routed there too by a hook installed with the log file. -->
|
|
122832
123231
|
<key>StandardErrorPath</key>
|
|
122833
|
-
<string
|
|
123232
|
+
<string>/dev/null</string>
|
|
122834
123233
|
<key>StandardOutPath</key>
|
|
122835
|
-
<string
|
|
123234
|
+
<string>/dev/null</string>
|
|
122836
123235
|
</dict>
|
|
122837
123236
|
</plist>
|
|
122838
123237
|
`;
|
|
@@ -122920,9 +123319,9 @@ ${plist}TESSERACT_PLIST_EOF`,
|
|
|
122920
123319
|
async state() {
|
|
122921
123320
|
if (!existsSync50(PLIST))
|
|
122922
123321
|
return { installed: false, running: false };
|
|
122923
|
-
const
|
|
122924
|
-
const owner = parseOwnerUid(
|
|
122925
|
-
const assoc = parseAssociatedBundleId(
|
|
123322
|
+
const text13 = readFileSync59(PLIST, "utf8");
|
|
123323
|
+
const owner = parseOwnerUid(text13);
|
|
123324
|
+
const assoc = parseAssociatedBundleId(text13);
|
|
122926
123325
|
const running2 = await netdAvailable();
|
|
122927
123326
|
return {
|
|
122928
123327
|
installed: true,
|
|
@@ -123559,10 +123958,10 @@ import { dirname as dirname42, join as join94 } from "node:path";
|
|
|
123559
123958
|
import { homedir as homedir16, userInfo as userInfo2 } from "node:os";
|
|
123560
123959
|
|
|
123561
123960
|
// ../../packages/host-core/dist/service/legacy-label.js
|
|
123562
|
-
function definitionIsCli(
|
|
123563
|
-
if (!
|
|
123961
|
+
function definitionIsCli(text13) {
|
|
123962
|
+
if (!text13)
|
|
123564
123963
|
return false;
|
|
123565
|
-
return /node_modules[/\\]tesseract-agent[/\\]/.test(
|
|
123964
|
+
return /node_modules[/\\]tesseract-agent[/\\]/.test(text13) || /[/\\]bin[/\\]tesseract-agent(\.cmd|\.exe)?["'\s]*$/m.test(text13) || /[/\\]bin[/\\]tesseract-agent(\.cmd|\.exe)?[<"'\s]/.test(text13);
|
|
123566
123965
|
}
|
|
123567
123966
|
|
|
123568
123967
|
// ../../packages/host-core/dist/service/launchd.js
|
|
@@ -124689,7 +125088,9 @@ async function meshCommand(rest, flags) {
|
|
|
124689
125088
|
return;
|
|
124690
125089
|
}
|
|
124691
125090
|
console.log(`node: running on UDP port ${s.port ?? "?"}`);
|
|
124692
|
-
console.log(
|
|
125091
|
+
console.log(
|
|
125092
|
+
`node: LAN discovery ${s.lan ? "on" : `off \u2014 ${s.lanError ?? "no reason was recorded"}`}`
|
|
125093
|
+
);
|
|
124693
125094
|
if (!("reachableAt" in s)) {
|
|
124694
125095
|
console.log("reachable at: unknown \u2014 the background service predates this CLI; restart it and ask again");
|
|
124695
125096
|
} else {
|