tesseract-agent 0.11.14 → 0.11.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-bundle/cli.js +1254 -858
- 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({
|
|
@@ -24347,9 +24454,9 @@ function withRunDirective(userText, directive) {
|
|
|
24347
24454
|
return `${head}${RUN_DIRECTIVE_MARK}
|
|
24348
24455
|
${directive}`;
|
|
24349
24456
|
}
|
|
24350
|
-
function stripRunDirective(
|
|
24351
|
-
const at =
|
|
24352
|
-
return at < 0 ?
|
|
24457
|
+
function stripRunDirective(text13) {
|
|
24458
|
+
const at = text13.indexOf(RUN_DIRECTIVE_MARK);
|
|
24459
|
+
return at < 0 ? text13 : text13.slice(0, at).trimEnd();
|
|
24353
24460
|
}
|
|
24354
24461
|
var RUN_DIRECTIVE_MARK;
|
|
24355
24462
|
var init_run_directive = __esm({
|
|
@@ -24397,6 +24504,13 @@ var init_digit_recall = __esm({
|
|
|
24397
24504
|
}
|
|
24398
24505
|
});
|
|
24399
24506
|
|
|
24507
|
+
// ../../packages/shared/dist/tab-nav.js
|
|
24508
|
+
var init_tab_nav = __esm({
|
|
24509
|
+
"../../packages/shared/dist/tab-nav.js"() {
|
|
24510
|
+
"use strict";
|
|
24511
|
+
}
|
|
24512
|
+
});
|
|
24513
|
+
|
|
24400
24514
|
// ../../packages/shared/dist/telemetry.js
|
|
24401
24515
|
var TELEMETRY_EVENTS, EVENT_CATEGORY;
|
|
24402
24516
|
var init_telemetry = __esm({
|
|
@@ -24697,6 +24811,7 @@ var NO_QUOTAS, NO_FEATURES, PLAN_CATALOG;
|
|
|
24697
24811
|
var init_plans = __esm({
|
|
24698
24812
|
"../../packages/shared/dist/plans.js"() {
|
|
24699
24813
|
"use strict";
|
|
24814
|
+
init_platform_availability();
|
|
24700
24815
|
NO_QUOTAS = { computeHours: 0, storageGb: 0, egressGb: 0, videoSeconds: 0 };
|
|
24701
24816
|
NO_FEATURES = {
|
|
24702
24817
|
sync: false,
|
|
@@ -24725,7 +24840,7 @@ var init_plans = __esm({
|
|
|
24725
24840
|
tagline: "Your machine, your phone, your voice.",
|
|
24726
24841
|
features: [
|
|
24727
24842
|
"Unlimited agent usage",
|
|
24728
|
-
"
|
|
24843
|
+
"It operates this computer \u2014 screen, files and browser",
|
|
24729
24844
|
"Voice mode",
|
|
24730
24845
|
"Mobile app \u2014 reach your computer from your phone",
|
|
24731
24846
|
"Cloud workspace \u2014 your machine and recent projects in one view",
|
|
@@ -24744,9 +24859,11 @@ var init_plans = __esm({
|
|
|
24744
24859
|
features: [
|
|
24745
24860
|
"Everything in Free",
|
|
24746
24861
|
"Unlimited machines \u2014 run agents on all of them",
|
|
24747
|
-
"Tesseract cloud server \u2014 a managed always-on agent in the cloud",
|
|
24748
|
-
|
|
24749
|
-
|
|
24862
|
+
...CLOUD_SERVER_AVAILABLE ? ["Tesseract cloud server \u2014 a managed always-on agent in the cloud"] : [],
|
|
24863
|
+
...HOSTING_AVAILABLE ? [
|
|
24864
|
+
"Deploy to the cloud \u2014 your app on a *.tesseract.dev URL",
|
|
24865
|
+
"Includes ~1 always-on service + 20 GB storage + 100 GB bandwidth (overage metered)"
|
|
24866
|
+
] : [],
|
|
24750
24867
|
"Premium missions \u2014 GDPR, security, UX, performance audits that fix & verify",
|
|
24751
24868
|
"Sync settings across your devices",
|
|
24752
24869
|
"Email support"
|
|
@@ -24756,10 +24873,10 @@ var init_plans = __esm({
|
|
|
24756
24873
|
sync: true,
|
|
24757
24874
|
mobile: true,
|
|
24758
24875
|
cloudWorkspace: true,
|
|
24759
|
-
cloudServer:
|
|
24876
|
+
cloudServer: CLOUD_SERVER_AVAILABLE,
|
|
24760
24877
|
remoteAgents: true,
|
|
24761
24878
|
voice: true,
|
|
24762
|
-
hosting:
|
|
24879
|
+
hosting: HOSTING_AVAILABLE,
|
|
24763
24880
|
plugins: true,
|
|
24764
24881
|
missions: true,
|
|
24765
24882
|
scheduling: true,
|
|
@@ -24780,26 +24897,27 @@ var init_plans = __esm({
|
|
|
24780
24897
|
"Parallel agents",
|
|
24781
24898
|
"Advanced browser automation",
|
|
24782
24899
|
"API access",
|
|
24783
|
-
"
|
|
24784
|
-
"
|
|
24900
|
+
...SSO_AVAILABLE ? ["Company sign-on and audit log"] : [],
|
|
24901
|
+
"Centralized billing across seats",
|
|
24902
|
+
...HOSTING_AVAILABLE ? ["Pooled cloud hosting \u2014 bigger shared quota"] : [],
|
|
24785
24903
|
"Priority support"
|
|
24786
24904
|
],
|
|
24787
24905
|
featurePolicy: {
|
|
24788
24906
|
sync: true,
|
|
24789
24907
|
mobile: true,
|
|
24790
24908
|
cloudWorkspace: true,
|
|
24791
|
-
cloudServer:
|
|
24909
|
+
cloudServer: CLOUD_SERVER_AVAILABLE,
|
|
24792
24910
|
remoteAgents: true,
|
|
24793
24911
|
voice: true,
|
|
24794
24912
|
team: true,
|
|
24795
24913
|
parallelAgents: true,
|
|
24796
24914
|
advancedBrowser: true,
|
|
24797
|
-
hosting:
|
|
24915
|
+
hosting: HOSTING_AVAILABLE,
|
|
24798
24916
|
plugins: true,
|
|
24799
24917
|
missions: true,
|
|
24800
24918
|
scheduling: true,
|
|
24801
24919
|
api: true,
|
|
24802
|
-
sso:
|
|
24920
|
+
sso: SSO_AVAILABLE,
|
|
24803
24921
|
seats: 2,
|
|
24804
24922
|
maxMachines: 0
|
|
24805
24923
|
},
|
|
@@ -24856,12 +24974,15 @@ function isAnthropicModelId(model) {
|
|
|
24856
24974
|
const id = (model ?? "").trim().toLowerCase();
|
|
24857
24975
|
if (!id)
|
|
24858
24976
|
return false;
|
|
24977
|
+
if (TIER_ALIAS.test(id))
|
|
24978
|
+
return false;
|
|
24859
24979
|
return /(^|[/.\-])(claude|opus|sonnet|haiku|fable)([/.\-]|$)/.test(id) || /^(opus|sonnet|haiku|fable)\b/.test(id);
|
|
24860
24980
|
}
|
|
24861
|
-
var ONE_MILLION_FAMILIES, SUFFIX;
|
|
24981
|
+
var TIER_ALIAS, ONE_MILLION_FAMILIES, SUFFIX;
|
|
24862
24982
|
var init_model_long_context = __esm({
|
|
24863
24983
|
"../../packages/shared/dist/model-long-context.js"() {
|
|
24864
24984
|
"use strict";
|
|
24985
|
+
TIER_ALIAS = /^tsr-/i;
|
|
24865
24986
|
ONE_MILLION_FAMILIES = [
|
|
24866
24987
|
/(^|[/.])claude-sonnet-(4-6|4-7|4-8|5)\b/i,
|
|
24867
24988
|
/(^|[/.])claude-opus-(4-6|4-7|4-8|5)\b/i,
|
|
@@ -25520,8 +25641,26 @@ var init_engines = __esm({
|
|
|
25520
25641
|
capabilities: CLAUDE_CAPABILITIES,
|
|
25521
25642
|
runModeTiming: CLAUDE_RUN_MODE_TIMING,
|
|
25522
25643
|
homepageUrl: "https://docs.claude.com/en/docs/claude-code",
|
|
25523
|
-
|
|
25524
|
-
|
|
25644
|
+
// The NATIVE installer, not npm. Two reasons, in order of how often they bite:
|
|
25645
|
+
// 1. npm needs a Node toolchain the machine may simply not have — and a GUI-launched app
|
|
25646
|
+
// sees PATH=/usr/bin:/bin:/usr/sbin:/sbin, so even an nvm-managed node is invisible.
|
|
25647
|
+
// The native installer needs only curl/wget and a shell.
|
|
25648
|
+
// 2. npm would land under our own `--prefix` (~/.tesseract/runtimes/bin), which the thing
|
|
25649
|
+
// that SPAWNS claude (agent-core's findUserInstalledClaude) does not search — so the
|
|
25650
|
+
// install would "succeed" and the engine would still read as missing. The native
|
|
25651
|
+
// installer writes ~/.local/bin/claude, which both the probe and the spawner know.
|
|
25652
|
+
// `install.sh` hard-refuses Windows, and `irm | iex` cannot take the version argument, so
|
|
25653
|
+
// Windows gets the documented scriptblock form rather than a quoting variant.
|
|
25654
|
+
installCommand: "curl -fsSL https://claude.ai/install.sh | bash -s {version}",
|
|
25655
|
+
installCommandWin: "& ([scriptblock]::Create((irm https://claude.ai/install.ps1))) {version}",
|
|
25656
|
+
// Its own updater. A copy managed by brew/winget reports "up to date" and does nothing —
|
|
25657
|
+
// which autoFixUnusable surfaces honestly via its post-update re-check rather than
|
|
25658
|
+
// claiming success.
|
|
25659
|
+
updateCommand: "claude update",
|
|
25660
|
+
// The documented uninstall. Both halves: the launcher and the versions directory.
|
|
25661
|
+
removeCommand: "rm -f ~/.local/bin/claude && rm -rf ~/.local/share/claude",
|
|
25662
|
+
removeCommandWin: 'Remove-Item -Path "$env:USERPROFILE\\.local\\bin\\claude.exe" -Force; Remove-Item -Path "$env:USERPROFILE\\.local\\share\\claude" -Recurse -Force',
|
|
25663
|
+
installHint: "Tesseract runs the Claude Code CLI you have installed rather than bundling one; install it to use this engine."
|
|
25525
25664
|
},
|
|
25526
25665
|
"openai-codex": {
|
|
25527
25666
|
id: "openai-codex",
|
|
@@ -26071,6 +26210,7 @@ var init_runner_compat = __esm({
|
|
|
26071
26210
|
"use strict";
|
|
26072
26211
|
init_engines();
|
|
26073
26212
|
init_providers();
|
|
26213
|
+
init_model_catalog();
|
|
26074
26214
|
GATEWAY_WIRES = {
|
|
26075
26215
|
"claude-code": { kind: "anthropic-env" },
|
|
26076
26216
|
"openai-codex": { kind: "codex-home" },
|
|
@@ -26337,6 +26477,10 @@ var init_runtimes = __esm({
|
|
|
26337
26477
|
label: ENGINE_CATALOG[id].label,
|
|
26338
26478
|
cliBinary: ENGINE_CATALOG[id].cliBinary,
|
|
26339
26479
|
installCommand: ENGINE_CATALOG[id].installCommand,
|
|
26480
|
+
installCommandWin: ENGINE_CATALOG[id].installCommandWin,
|
|
26481
|
+
updateCommand: ENGINE_CATALOG[id].updateCommand,
|
|
26482
|
+
removeCommand: ENGINE_CATALOG[id].removeCommand,
|
|
26483
|
+
removeCommandWin: ENGINE_CATALOG[id].removeCommandWin,
|
|
26340
26484
|
kind: "engine"
|
|
26341
26485
|
})),
|
|
26342
26486
|
{ id: "ollama", label: "Ollama", cliBinary: "ollama", installCommand: "curl -fsSL https://ollama.com/install.sh | sh", kind: "tool" },
|
|
@@ -26482,26 +26626,46 @@ function providerBase(key2, which2) {
|
|
|
26482
26626
|
return fromServer;
|
|
26483
26627
|
return which2 === "anthropic" ? gatewayAnthropicBaseUrl(key2.baseUrl) : which2 === "openai" ? gatewayOpenAiBaseUrl(key2.baseUrl) : gatewayGeminiBaseUrl(key2.baseUrl);
|
|
26484
26628
|
}
|
|
26629
|
+
function aliasProviders(key2) {
|
|
26630
|
+
const out = /* @__PURE__ */ new Map();
|
|
26631
|
+
for (const slot of Object.keys(TIER_PROVIDER)) {
|
|
26632
|
+
const id = key2.models[slot];
|
|
26633
|
+
if (id)
|
|
26634
|
+
out.set(id, TIER_PROVIDER[slot]);
|
|
26635
|
+
}
|
|
26636
|
+
return out;
|
|
26637
|
+
}
|
|
26485
26638
|
function tiers(engineId, key2, models) {
|
|
26486
|
-
const
|
|
26487
|
-
const
|
|
26639
|
+
const provider = gatewayProviderForEngine(engineId);
|
|
26640
|
+
const preference = provider ? TIER_PREFERENCE[provider] : void 0;
|
|
26641
|
+
const byAlias = aliasProviders(key2);
|
|
26488
26642
|
const asked = (v) => {
|
|
26489
26643
|
const t = v?.trim();
|
|
26490
26644
|
if (!t)
|
|
26491
26645
|
return void 0;
|
|
26492
26646
|
if (t.includes("/"))
|
|
26493
26647
|
return t;
|
|
26494
|
-
return
|
|
26648
|
+
return byAlias.get(t) === provider ? t : void 0;
|
|
26495
26649
|
};
|
|
26496
|
-
const
|
|
26497
|
-
|
|
26498
|
-
|
|
26650
|
+
const pick3 = (slots) => {
|
|
26651
|
+
for (const slot of slots) {
|
|
26652
|
+
const id = key2.models[slot];
|
|
26653
|
+
if (id)
|
|
26654
|
+
return id;
|
|
26655
|
+
}
|
|
26656
|
+
return void 0;
|
|
26657
|
+
};
|
|
26658
|
+
const main2 = asked(models.main) || preference && pick3(preference.main);
|
|
26659
|
+
const fast = asked(models.fast) || preference && pick3(preference.fast) || main2;
|
|
26660
|
+
return { main: main2 || void 0, fast: fast || void 0 };
|
|
26499
26661
|
}
|
|
26500
26662
|
function planGatewayRun(engineId, key2, models, homeBase) {
|
|
26501
26663
|
const wire = gatewayWireFor(engineId);
|
|
26502
26664
|
if (!wire)
|
|
26503
26665
|
return void 0;
|
|
26504
26666
|
const { main: main2, fast } = tiers(engineId, key2, models);
|
|
26667
|
+
if (!main2 || !fast)
|
|
26668
|
+
return void 0;
|
|
26505
26669
|
const effort = ENGINE_CATALOG[engineId]?.modelControls.reasoningEfforts?.includes(models.reasoningEffort ?? "") ? models.reasoningEffort : void 0;
|
|
26506
26670
|
return planEndpointRun(wire.kind, {
|
|
26507
26671
|
baseUrl: wire.kind === "anthropic-env" ? providerBase(key2, "anthropic") : wire.kind === "gemini-env" ? providerBase(key2, "gemini") : providerBase(key2, "openai"),
|
|
@@ -26515,13 +26679,30 @@ function planGatewayRun(engineId, key2, models, homeBase) {
|
|
|
26515
26679
|
homeKey: HOME_DIR_NAME[engineId]
|
|
26516
26680
|
}, homeBase);
|
|
26517
26681
|
}
|
|
26518
|
-
var HOME_DIR_NAME;
|
|
26682
|
+
var TIER_PROVIDER, TIER_PREFERENCE, HOME_DIR_NAME;
|
|
26519
26683
|
var init_gateway_plan = __esm({
|
|
26520
26684
|
"../../packages/shared/dist/gateway-plan.js"() {
|
|
26521
26685
|
"use strict";
|
|
26522
26686
|
init_runner_compat();
|
|
26523
26687
|
init_engine_endpoint();
|
|
26524
26688
|
init_engines();
|
|
26689
|
+
TIER_PROVIDER = {
|
|
26690
|
+
low: "openai",
|
|
26691
|
+
high: "openai",
|
|
26692
|
+
image: "openai",
|
|
26693
|
+
codex: "openai",
|
|
26694
|
+
gpt: "openai",
|
|
26695
|
+
vision: "google-ai",
|
|
26696
|
+
claude: "anthropic",
|
|
26697
|
+
claudeFast: "anthropic"
|
|
26698
|
+
};
|
|
26699
|
+
TIER_PREFERENCE = {
|
|
26700
|
+
// No fast rung of its own on the OpenAI side: Codex is one model plus a reasoning dial,
|
|
26701
|
+
// and `tsr-low` remains the cheap fallback for anything that asks for one.
|
|
26702
|
+
openai: { main: ["codex", "gpt", "high"], fast: ["low", "high"] },
|
|
26703
|
+
anthropic: { main: ["claude"], fast: ["claudeFast", "claude"] },
|
|
26704
|
+
"google-ai": { main: ["vision"], fast: ["vision"] }
|
|
26705
|
+
};
|
|
26525
26706
|
HOME_DIR_NAME = {
|
|
26526
26707
|
opencode: "opencode-bundled",
|
|
26527
26708
|
"openai-codex": "gateway-openai-codex"
|
|
@@ -27637,6 +27818,14 @@ var init_stage_types = __esm({
|
|
|
27637
27818
|
}
|
|
27638
27819
|
});
|
|
27639
27820
|
|
|
27821
|
+
// ../../packages/shared/dist/deck-package.js
|
|
27822
|
+
var init_deck_package = __esm({
|
|
27823
|
+
"../../packages/shared/dist/deck-package.js"() {
|
|
27824
|
+
"use strict";
|
|
27825
|
+
init_stage_types();
|
|
27826
|
+
}
|
|
27827
|
+
});
|
|
27828
|
+
|
|
27640
27829
|
// ../../packages/shared/dist/rdesk-client-ipc.js
|
|
27641
27830
|
var init_rdesk_client_ipc = __esm({
|
|
27642
27831
|
"../../packages/shared/dist/rdesk-client-ipc.js"() {
|
|
@@ -27662,10 +27851,10 @@ var init_user_dialog = __esm({
|
|
|
27662
27851
|
});
|
|
27663
27852
|
|
|
27664
27853
|
// ../../packages/shared/dist/session-ops.js
|
|
27665
|
-
function cleanTaskNotifications(
|
|
27666
|
-
if (!
|
|
27667
|
-
return
|
|
27668
|
-
return
|
|
27854
|
+
function cleanTaskNotifications(text13) {
|
|
27855
|
+
if (!text13.includes("<task-notification>"))
|
|
27856
|
+
return text13;
|
|
27857
|
+
return text13.replace(/<task-notification>([\s\S]*?)<\/task-notification>/g, (_all, inner) => {
|
|
27669
27858
|
const g = (name) => {
|
|
27670
27859
|
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(inner);
|
|
27671
27860
|
return m ? m[1].trim() : "";
|
|
@@ -27676,8 +27865,8 @@ function cleanTaskNotifications(text12) {
|
|
|
27676
27865
|
}).trim();
|
|
27677
27866
|
}
|
|
27678
27867
|
function transcriptToText(msgs, cap = MERGE_PER_SOURCE_CAP) {
|
|
27679
|
-
const
|
|
27680
|
-
return
|
|
27868
|
+
const text13 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${cleanTaskNotifications(m.content)}`).join("\n").slice(0, cap);
|
|
27869
|
+
return text13.trim() ? text13 : "";
|
|
27681
27870
|
}
|
|
27682
27871
|
function buildMergeSeed(transcripts) {
|
|
27683
27872
|
return [
|
|
@@ -27689,10 +27878,10 @@ function buildMergeSeed(transcripts) {
|
|
|
27689
27878
|
${t}`)
|
|
27690
27879
|
].join("\n\n");
|
|
27691
27880
|
}
|
|
27692
|
-
function parseSummaryReply(
|
|
27693
|
-
const m = /^\s*TITLE:\s*(.+?)\s*\n-{3,}\s*\n([\s\S]+)$/.exec(
|
|
27881
|
+
function parseSummaryReply(text13) {
|
|
27882
|
+
const m = /^\s*TITLE:\s*(.+?)\s*\n-{3,}\s*\n([\s\S]+)$/.exec(text13);
|
|
27694
27883
|
const title = m?.[1]?.trim();
|
|
27695
|
-
const summary = (m?.[2] ??
|
|
27884
|
+
const summary = (m?.[2] ?? text13).trim();
|
|
27696
27885
|
return title ? { title, summary } : { summary };
|
|
27697
27886
|
}
|
|
27698
27887
|
var MERGE_PER_SOURCE_CAP;
|
|
@@ -27797,6 +27986,7 @@ var init_dist2 = __esm({
|
|
|
27797
27986
|
"use strict";
|
|
27798
27987
|
init_surface_merge();
|
|
27799
27988
|
init_permissions();
|
|
27989
|
+
init_platform_availability();
|
|
27800
27990
|
init_app_elements();
|
|
27801
27991
|
init_ws_protocol();
|
|
27802
27992
|
init_context_overflow();
|
|
@@ -27807,6 +27997,7 @@ var init_dist2 = __esm({
|
|
|
27807
27997
|
init_run_directive();
|
|
27808
27998
|
init_proactive_compaction();
|
|
27809
27999
|
init_digit_recall();
|
|
28000
|
+
init_tab_nav();
|
|
27810
28001
|
init_telemetry();
|
|
27811
28002
|
init_error_report();
|
|
27812
28003
|
init_eula();
|
|
@@ -27849,6 +28040,7 @@ var init_dist2 = __esm({
|
|
|
27849
28040
|
init_chat_slash();
|
|
27850
28041
|
init_present_protocol();
|
|
27851
28042
|
init_stage_types();
|
|
28043
|
+
init_deck_package();
|
|
27852
28044
|
init_rdesk_client_ipc();
|
|
27853
28045
|
init_user_dialog();
|
|
27854
28046
|
init_session_ops();
|
|
@@ -30539,8 +30731,8 @@ function makeApi(deps, toolId, tier) {
|
|
|
30539
30731
|
await h.close();
|
|
30540
30732
|
return r.cancelled ? null : r.value ?? [];
|
|
30541
30733
|
},
|
|
30542
|
-
notify: async (
|
|
30543
|
-
await api.open({ kind: "markdown", initial: { markdown:
|
|
30734
|
+
notify: async (text13, opts) => {
|
|
30735
|
+
await api.open({ kind: "markdown", initial: { markdown: text13, level: opts?.level } });
|
|
30544
30736
|
}
|
|
30545
30737
|
};
|
|
30546
30738
|
return api;
|
|
@@ -30551,11 +30743,11 @@ function buildToolCtx(deps, sessionId, toolId, log10 = NOOP_LOG, tier = "third-p
|
|
|
30551
30743
|
return getSid();
|
|
30552
30744
|
}, toolId, log: log10 };
|
|
30553
30745
|
}
|
|
30554
|
-
function wrapCtxTool(
|
|
30555
|
-
const raw =
|
|
30746
|
+
function wrapCtxTool(tool22, ctx2) {
|
|
30747
|
+
const raw = tool22.__ctxHandler;
|
|
30556
30748
|
if (typeof raw !== "function")
|
|
30557
|
-
return
|
|
30558
|
-
return { ...
|
|
30749
|
+
return tool22;
|
|
30750
|
+
return { ...tool22, handler: async (args) => raw(args, ctx2) };
|
|
30559
30751
|
}
|
|
30560
30752
|
var NOOP_LOG;
|
|
30561
30753
|
var init_surface_ctx = __esm({
|
|
@@ -30713,11 +30905,11 @@ var init_hook_bus = __esm({
|
|
|
30713
30905
|
// ../../packages/agent-core/dist/jobs/file-tailer.js
|
|
30714
30906
|
import { statSync } from "node:fs";
|
|
30715
30907
|
import { open } from "node:fs/promises";
|
|
30716
|
-
function parseBackgroundTaskResult(
|
|
30717
|
-
if (!
|
|
30908
|
+
function parseBackgroundTaskResult(text13) {
|
|
30909
|
+
if (!text13 || !text13.includes(".output"))
|
|
30718
30910
|
return null;
|
|
30719
|
-
const id = /\bID:\s*([A-Za-z0-9_-]+)/.exec(
|
|
30720
|
-
const path6 = /Output is being written to:\s*([^\s]+\.output)/.exec(
|
|
30911
|
+
const id = /\bID:\s*([A-Za-z0-9_-]+)/.exec(text13);
|
|
30912
|
+
const path6 = /Output is being written to:\s*([^\s]+\.output)/.exec(text13);
|
|
30721
30913
|
if (!id?.[1] || !path6?.[1])
|
|
30722
30914
|
return null;
|
|
30723
30915
|
return { taskId: id[1], outputPath: path6[1] };
|
|
@@ -31737,6 +31929,8 @@ var init_parallel_tools = __esm({
|
|
|
31737
31929
|
"browser_events",
|
|
31738
31930
|
"capture_element_styles",
|
|
31739
31931
|
// ── Listings, capability probes and status reads.
|
|
31932
|
+
// tesseract_capabilities returns an inlined constant — concurrent calls are indistinguishable.
|
|
31933
|
+
"tesseract_capabilities",
|
|
31740
31934
|
"list_effects",
|
|
31741
31935
|
"list_upscale_models",
|
|
31742
31936
|
"list_voices",
|
|
@@ -31789,8 +31983,8 @@ var init_tool_spec = __esm({
|
|
|
31789
31983
|
import { tool as tool14 } from "@anthropic-ai/claude-agent-sdk";
|
|
31790
31984
|
function buildScreenControlSdkTools(p) {
|
|
31791
31985
|
return screenControlSpecs().map((spec) => tool14(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
|
|
31792
|
-
const
|
|
31793
|
-
return { content: [{ type: "text", text:
|
|
31986
|
+
const text13 = await p.exec(spec.name, args ?? {});
|
|
31987
|
+
return { content: [{ type: "text", text: text13 || "Done." }] };
|
|
31794
31988
|
}));
|
|
31795
31989
|
}
|
|
31796
31990
|
var ANNOTATE_STYLES, SCREEN_CONTROL_SHAPES, screenControlSpecs;
|
|
@@ -32596,6 +32790,10 @@ ${JSON.stringify(r, null, 2)}`
|
|
|
32596
32790
|
{ 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
32791
|
{ 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
32792
|
{ 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" } },
|
|
32793
|
+
// Whether the FREE brokered tier can serve an avatar video HERE — the user's own key is
|
|
32794
|
+
// the other half, above. Worth asking before drafting a script: the deployment may hold
|
|
32795
|
+
// no HeyGen account, and generate_avatar_video then fails at submit with the work done.
|
|
32796
|
+
{ 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
32797
|
{ 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
32798
|
{ 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
32799
|
{ 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 +32958,134 @@ ${JSON.stringify(r, null, 2)}`
|
|
|
32760
32958
|
availability: "desktop",
|
|
32761
32959
|
binding: { kind: "command", command: "app.openStage" }
|
|
32762
32960
|
},
|
|
32961
|
+
// ── The presentation LIBRARY: authoring, not driving ──────────────────────────────────
|
|
32962
|
+
// Everything above drives a deck that is already running, and lives in the daemon because
|
|
32963
|
+
// a phone remote reaches it. These WRITE FILES, so they are 'desktop': the library is a
|
|
32964
|
+
// folder in the user's Documents, and only the desktop process can touch it.
|
|
32965
|
+
//
|
|
32966
|
+
// A deck is TSX — the same slide contract the app's own decks use — so the model authors
|
|
32967
|
+
// by writing files and then calling `validate_deck` until it comes back clean. That loop
|
|
32968
|
+
// is the whole design: without it the first sign of a stray bracket on slide 14 is a
|
|
32969
|
+
// blank rectangle at the front of a room.
|
|
32970
|
+
{
|
|
32971
|
+
id: "present.list_decks",
|
|
32972
|
+
domain: "present",
|
|
32973
|
+
title: "List presentations",
|
|
32974
|
+
input: external_exports.object({}),
|
|
32975
|
+
mutation: "read",
|
|
32976
|
+
availability: "desktop",
|
|
32977
|
+
binding: { kind: "ipc", channel: "decklib", verb: "list" }
|
|
32978
|
+
},
|
|
32979
|
+
{
|
|
32980
|
+
id: "present.create_deck",
|
|
32981
|
+
domain: "present",
|
|
32982
|
+
title: "Create a presentation",
|
|
32983
|
+
input: external_exports.object({
|
|
32984
|
+
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."),
|
|
32985
|
+
description: external_exports.string().optional().describe("One line about what it is for."),
|
|
32986
|
+
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" }.')
|
|
32987
|
+
}),
|
|
32988
|
+
mutation: "write",
|
|
32989
|
+
availability: "desktop",
|
|
32990
|
+
binding: { kind: "ipc", channel: "decklib", verb: "create" },
|
|
32991
|
+
summarize: (r) => `Created the presentation "${r?.title ?? ""}".`
|
|
32992
|
+
},
|
|
32993
|
+
{
|
|
32994
|
+
id: "present.write_slide",
|
|
32995
|
+
domain: "present",
|
|
32996
|
+
title: "Write a slide",
|
|
32997
|
+
input: external_exports.object({
|
|
32998
|
+
deck: external_exports.string().describe("The deck folder, exactly as `list_decks` or `create_deck` returned it (ends in .tessdeck)."),
|
|
32999
|
+
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.'),
|
|
33000
|
+
source: external_exports.string().describe("The whole file. A slide exports `meta` ({ id, title, summary?, notes?, transition?, builds? }) and a default React component.")
|
|
33001
|
+
}),
|
|
33002
|
+
mutation: "write",
|
|
33003
|
+
availability: "desktop",
|
|
33004
|
+
binding: { kind: "ipc", channel: "decklib", verb: "writeFile" },
|
|
33005
|
+
summarize: (_r, i) => `Wrote ${i.path ?? "a slide"}.`
|
|
33006
|
+
},
|
|
33007
|
+
{
|
|
33008
|
+
id: "present.read_slide",
|
|
33009
|
+
domain: "present",
|
|
33010
|
+
title: "Read a slide",
|
|
33011
|
+
input: external_exports.object({
|
|
33012
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33013
|
+
path: external_exports.string().describe('Path inside the presentation, e.g. "slides/03-pricing.tsx".')
|
|
33014
|
+
}),
|
|
33015
|
+
mutation: "read",
|
|
33016
|
+
availability: "desktop",
|
|
33017
|
+
binding: { kind: "ipc", channel: "decklib", verb: "readFile" }
|
|
33018
|
+
},
|
|
33019
|
+
{
|
|
33020
|
+
id: "present.delete_slide",
|
|
33021
|
+
domain: "present",
|
|
33022
|
+
title: "Delete a slide",
|
|
33023
|
+
input: external_exports.object({
|
|
33024
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33025
|
+
path: external_exports.string().describe("Path inside the presentation.")
|
|
33026
|
+
}),
|
|
33027
|
+
mutation: "write",
|
|
33028
|
+
availability: "desktop",
|
|
33029
|
+
binding: { kind: "ipc", channel: "decklib", verb: "deleteFile" },
|
|
33030
|
+
summarize: (_r, i) => `Deleted ${i.path ?? "a slide"}.`
|
|
33031
|
+
},
|
|
33032
|
+
{
|
|
33033
|
+
id: "present.validate_deck",
|
|
33034
|
+
domain: "present",
|
|
33035
|
+
title: "Check a presentation",
|
|
33036
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33037
|
+
mutation: "read",
|
|
33038
|
+
availability: "desktop",
|
|
33039
|
+
binding: { kind: "ipc", channel: "decklib", verb: "validate" },
|
|
33040
|
+
summarize: (r) => typeof r === "string" ? r : "Checked the presentation."
|
|
33041
|
+
},
|
|
33042
|
+
{
|
|
33043
|
+
id: "present.set_deck_theme",
|
|
33044
|
+
domain: "present",
|
|
33045
|
+
title: "Set a presentation\u2019s theme",
|
|
33046
|
+
input: external_exports.object({
|
|
33047
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33048
|
+
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.`)
|
|
33049
|
+
}),
|
|
33050
|
+
mutation: "write",
|
|
33051
|
+
availability: "desktop",
|
|
33052
|
+
binding: { kind: "ipc", channel: "decklib", verb: "setTheme" },
|
|
33053
|
+
summarize: () => "Updated the presentation\u2019s theme."
|
|
33054
|
+
},
|
|
33055
|
+
{
|
|
33056
|
+
id: "present.add_asset",
|
|
33057
|
+
domain: "present",
|
|
33058
|
+
title: "Add an image to a presentation",
|
|
33059
|
+
input: external_exports.object({
|
|
33060
|
+
deck: external_exports.string().describe("The deck folder."),
|
|
33061
|
+
source_path: external_exports.string().describe("Absolute path of the file to copy in \u2014 a generated image, a photo, an audio clip."),
|
|
33062
|
+
name: external_exports.string().optional().describe("Filename to use inside the presentation.")
|
|
33063
|
+
}),
|
|
33064
|
+
mutation: "write",
|
|
33065
|
+
availability: "desktop",
|
|
33066
|
+
binding: { kind: "ipc", channel: "decklib", verb: "addAsset" },
|
|
33067
|
+
summarize: (r) => `Added ${typeof r === "string" ? r : "an asset"} to the presentation.`
|
|
33068
|
+
},
|
|
33069
|
+
{
|
|
33070
|
+
id: "present.open_deck",
|
|
33071
|
+
domain: "present",
|
|
33072
|
+
title: "Open a presentation",
|
|
33073
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33074
|
+
mutation: "write",
|
|
33075
|
+
availability: "desktop",
|
|
33076
|
+
binding: { kind: "ipc", channel: "decklib", verb: "open" },
|
|
33077
|
+
summarize: () => "Opened the presentation in Stage."
|
|
33078
|
+
},
|
|
33079
|
+
{
|
|
33080
|
+
id: "present.delete_deck",
|
|
33081
|
+
domain: "present",
|
|
33082
|
+
title: "Delete a presentation",
|
|
33083
|
+
input: external_exports.object({ deck: external_exports.string().describe("The deck folder.") }),
|
|
33084
|
+
mutation: "write",
|
|
33085
|
+
availability: "desktop",
|
|
33086
|
+
binding: { kind: "ipc", channel: "decklib", verb: "delete" },
|
|
33087
|
+
summarize: (_r, i) => `Deleted the presentation ${i.deck ?? ""}.`
|
|
33088
|
+
},
|
|
32763
33089
|
{
|
|
32764
33090
|
id: "present.end",
|
|
32765
33091
|
domain: "present",
|
|
@@ -32954,6 +33280,75 @@ var init_app_control_tools = __esm({
|
|
|
32954
33280
|
}
|
|
32955
33281
|
});
|
|
32956
33282
|
|
|
33283
|
+
// ../../packages/agent-core/dist/capabilities-doc.generated.js
|
|
33284
|
+
var CAPABILITIES_DOC;
|
|
33285
|
+
var init_capabilities_doc_generated = __esm({
|
|
33286
|
+
"../../packages/agent-core/dist/capabilities-doc.generated.js"() {
|
|
33287
|
+
"use strict";
|
|
33288
|
+
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. Model aliases: `tsr-low`, `tsr-high`,\n `tsr-vision`, `tsr-claude`, `tsr-claude-fast`, `tsr-image` ($0.10/image flat).\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';
|
|
33289
|
+
}
|
|
33290
|
+
});
|
|
33291
|
+
|
|
33292
|
+
// ../../packages/agent-core/dist/capabilities-tools.js
|
|
33293
|
+
import { tool as tool17 } from "@anthropic-ai/claude-agent-sdk";
|
|
33294
|
+
function capabilitySections(doc = CAPABILITIES_DOC) {
|
|
33295
|
+
const out = [];
|
|
33296
|
+
const re = /^## (\d+)\. (.+)$/gm;
|
|
33297
|
+
const heads = [];
|
|
33298
|
+
for (let m = re.exec(doc); m; m = re.exec(doc)) {
|
|
33299
|
+
heads.push({ n: Number(m[1]), title: m[2].trim(), at: m.index, end: re.lastIndex });
|
|
33300
|
+
}
|
|
33301
|
+
for (let i = 0; i < heads.length; i++) {
|
|
33302
|
+
const h = heads[i];
|
|
33303
|
+
const stop2 = i + 1 < heads.length ? heads[i + 1].at : doc.length;
|
|
33304
|
+
out.push({ n: h.n, title: h.title, body: doc.slice(h.at, stop2).trimEnd() });
|
|
33305
|
+
}
|
|
33306
|
+
return out;
|
|
33307
|
+
}
|
|
33308
|
+
function findSections(query2, doc = CAPABILITIES_DOC) {
|
|
33309
|
+
const secs = capabilitySections(doc);
|
|
33310
|
+
const q = query2.trim().toLowerCase();
|
|
33311
|
+
if (!q)
|
|
33312
|
+
return [];
|
|
33313
|
+
const asNum = Number(q.replace(/^§/, ""));
|
|
33314
|
+
if (Number.isInteger(asNum) && asNum > 0) {
|
|
33315
|
+
const hit = secs.find((s) => s.n === asNum);
|
|
33316
|
+
if (hit)
|
|
33317
|
+
return [hit];
|
|
33318
|
+
}
|
|
33319
|
+
const byTitle = secs.filter((s) => s.title.toLowerCase().includes(q));
|
|
33320
|
+
if (byTitle.length > 0)
|
|
33321
|
+
return byTitle;
|
|
33322
|
+
return secs.filter((s) => s.body.toLowerCase().includes(q));
|
|
33323
|
+
}
|
|
33324
|
+
function buildCapabilitiesTools() {
|
|
33325
|
+
const index = capabilitySections().map((s) => `${s.n}. ${s.title}`).join(" \xB7 ");
|
|
33326
|
+
return [
|
|
33327
|
+
tool17("tesseract_capabilities", prompt("tool.capabilities.tesseract_capabilities", { sections: index }), {
|
|
33328
|
+
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.')
|
|
33329
|
+
}, async (args) => {
|
|
33330
|
+
const q = args?.section?.trim();
|
|
33331
|
+
if (!q)
|
|
33332
|
+
return text10(CAPABILITIES_DOC);
|
|
33333
|
+
const hits = findSections(q);
|
|
33334
|
+
if (hits.length === 0) {
|
|
33335
|
+
return text10(`No section of Tesseract's capability map matches "${q}". Sections: ${index}. Call tesseract_capabilities with no arguments for the whole map.`);
|
|
33336
|
+
}
|
|
33337
|
+
return text10(hits.map((s) => s.body).join("\n\n"));
|
|
33338
|
+
})
|
|
33339
|
+
];
|
|
33340
|
+
}
|
|
33341
|
+
var text10;
|
|
33342
|
+
var init_capabilities_tools = __esm({
|
|
33343
|
+
"../../packages/agent-core/dist/capabilities-tools.js"() {
|
|
33344
|
+
"use strict";
|
|
33345
|
+
init_zod();
|
|
33346
|
+
init_prompts();
|
|
33347
|
+
init_capabilities_doc_generated();
|
|
33348
|
+
text10 = (t) => ({ content: [{ type: "text", text: t }] });
|
|
33349
|
+
}
|
|
33350
|
+
});
|
|
33351
|
+
|
|
32957
33352
|
// ../../packages/serpapi-core/dist/types.js
|
|
32958
33353
|
var init_types3 = __esm({
|
|
32959
33354
|
"../../packages/serpapi-core/dist/types.js"() {
|
|
@@ -33480,8 +33875,8 @@ function isAbort(e) {
|
|
|
33480
33875
|
const name = e?.name ?? "";
|
|
33481
33876
|
return name === "AbortError" || name === "TimeoutError" || /aborted|abort/i.test(String(e?.message ?? ""));
|
|
33482
33877
|
}
|
|
33483
|
-
function redactSecrets(
|
|
33484
|
-
let out =
|
|
33878
|
+
function redactSecrets(text13, secret) {
|
|
33879
|
+
let out = text13.replace(/((?:api_key|apikey|token|access_token|key)=)[^&\s"'<>]{6,}/gi, "$1***");
|
|
33485
33880
|
if (secret && secret.length >= 8)
|
|
33486
33881
|
out = out.split(secret).join("***");
|
|
33487
33882
|
return out;
|
|
@@ -33588,13 +33983,13 @@ var init_client = __esm({
|
|
|
33588
33983
|
*/
|
|
33589
33984
|
async searchMarkdown(engine, params, opts = {}) {
|
|
33590
33985
|
const url2 = await this.buildUrl(engine, params, { ...opts, output: "md" });
|
|
33591
|
-
const { res, text:
|
|
33986
|
+
const { res, text: text13, started: started2 } = await this.fetchWithRetry(url2, engine, opts, true);
|
|
33592
33987
|
this.opts.onUsage?.({ engine, cached: false, billed: true, ms: Date.now() - started2, status: res.status });
|
|
33593
|
-
const asError = messageFromBody(
|
|
33594
|
-
if (asError &&
|
|
33988
|
+
const asError = messageFromBody(text13) && redactSecrets(messageFromBody(text13), (await this.creds().catch(() => void 0))?.apiKey);
|
|
33989
|
+
if (asError && text13.trimStart().startsWith("{")) {
|
|
33595
33990
|
throw new SerpApiError(asError, classifySerpError(res.status, asError), { status: res.status, engine });
|
|
33596
33991
|
}
|
|
33597
|
-
return { markdown:
|
|
33992
|
+
return { markdown: text13 };
|
|
33598
33993
|
}
|
|
33599
33994
|
/**
|
|
33600
33995
|
* Follow a fully-formed SerpApi URL — specifically `serpapi_pagination.next`.
|
|
@@ -33632,8 +34027,8 @@ var init_client = __esm({
|
|
|
33632
34027
|
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, "locations.json");
|
|
33633
34028
|
u.searchParams.set("q", q);
|
|
33634
34029
|
u.searchParams.set("limit", String(Math.min(Math.max(1, limit), 10)));
|
|
33635
|
-
const { text:
|
|
33636
|
-
const body = JSON.parse(
|
|
34030
|
+
const { text: text13 } = await this.fetchWithRetry(u.toString(), "locations", {}, false);
|
|
34031
|
+
const body = JSON.parse(text13 || "[]");
|
|
33637
34032
|
return Array.isArray(body) ? body : [];
|
|
33638
34033
|
}
|
|
33639
34034
|
/** Retrieve a previously-run search by `search_metadata.id`. 31-day retention; also how you
|
|
@@ -33657,8 +34052,8 @@ var init_client = __esm({
|
|
|
33657
34052
|
throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
|
|
33658
34053
|
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.md`);
|
|
33659
34054
|
u.searchParams.set("api_key", apiKey);
|
|
33660
|
-
const { text:
|
|
33661
|
-
return { markdown:
|
|
34055
|
+
const { text: text13 } = await this.fetchWithRetry(u.toString(), "archive", {}, false);
|
|
34056
|
+
return { markdown: text13 };
|
|
33662
34057
|
}
|
|
33663
34058
|
/** Upload an image (≤500 KB, JPG/PNG/WebP) for use with Lens / reverse-image engines.
|
|
33664
34059
|
* The returned `image_id` expires after ~10 minutes. */
|
|
@@ -33757,9 +34152,9 @@ var init_client = __esm({
|
|
|
33757
34152
|
this.opts.onUsage?.({ engine, cached: false, billed, ms: Date.now() - started2, error: msg });
|
|
33758
34153
|
throw lastErr;
|
|
33759
34154
|
}
|
|
33760
|
-
const
|
|
34155
|
+
const text13 = await res.text();
|
|
33761
34156
|
if (!res.ok) {
|
|
33762
|
-
const bodyMsg = redactSecrets(messageFromBody(
|
|
34157
|
+
const bodyMsg = redactSecrets(messageFromBody(text13), secret);
|
|
33763
34158
|
const err2 = new SerpApiError(bodyMsg || `SerpApi ${engine} failed (${res.status}).`, classifySerpError(res.status, bodyMsg), { status: res.status, engine });
|
|
33764
34159
|
if (err2.retryable && attempt < maxRetries && Date.now() < deadline) {
|
|
33765
34160
|
lastErr = err2;
|
|
@@ -33769,7 +34164,7 @@ var init_client = __esm({
|
|
|
33769
34164
|
this.opts.onUsage?.({ engine, cached: false, billed, ms: Date.now() - started2, status: res.status, error: bodyMsg.slice(0, 200) });
|
|
33770
34165
|
throw err2;
|
|
33771
34166
|
}
|
|
33772
|
-
return { res, text:
|
|
34167
|
+
return { res, text: text13, started: started2 };
|
|
33773
34168
|
}
|
|
33774
34169
|
throw lastErr ?? new SerpApiError(`SerpApi ${engine} failed.`, "unknown", { engine });
|
|
33775
34170
|
}
|
|
@@ -33786,10 +34181,10 @@ var init_client = __esm({
|
|
|
33786
34181
|
if (hit)
|
|
33787
34182
|
this.cache.delete(key2);
|
|
33788
34183
|
}
|
|
33789
|
-
const { res, text:
|
|
34184
|
+
const { res, text: text13, started: started2 } = await this.fetchWithRetry(url2, engine, opts, billed);
|
|
33790
34185
|
let body;
|
|
33791
34186
|
try {
|
|
33792
|
-
body = JSON.parse(
|
|
34187
|
+
body = JSON.parse(text13);
|
|
33793
34188
|
} catch {
|
|
33794
34189
|
throw new SerpApiError(`SerpApi ${engine} returned a non-JSON body.`, "unknown", { status: res.status, engine });
|
|
33795
34190
|
}
|
|
@@ -34505,7 +34900,7 @@ var serpapi_tools_exports = {};
|
|
|
34505
34900
|
__export(serpapi_tools_exports, {
|
|
34506
34901
|
buildSerpTools: () => buildSerpTools
|
|
34507
34902
|
});
|
|
34508
|
-
import { tool as
|
|
34903
|
+
import { tool as tool18 } from "@anthropic-ai/claude-agent-sdk";
|
|
34509
34904
|
import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, statSync as statSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
34510
34905
|
import { basename as basename2 } from "node:path";
|
|
34511
34906
|
function imageKind(path6) {
|
|
@@ -34539,14 +34934,14 @@ function catalogOnce() {
|
|
|
34539
34934
|
}
|
|
34540
34935
|
function buildSerpTools(deps) {
|
|
34541
34936
|
const tools = [];
|
|
34542
|
-
tools.push(
|
|
34937
|
+
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
34938
|
query: external_exports.string().describe("What you are trying to find out, in plain language."),
|
|
34544
34939
|
family: external_exports.string().optional().describe(`Restrict to one family: ${Object.keys(SERP_FAMILIES).join(", ")}.`),
|
|
34545
34940
|
limit: external_exports.number().int().min(1).max(30).optional().describe("How many engines to return (default 8).")
|
|
34546
34941
|
}, async (a) => {
|
|
34547
34942
|
const { query: query2, family, limit } = a ?? {};
|
|
34548
34943
|
if (family && !(family in SERP_FAMILIES)) {
|
|
34549
|
-
return
|
|
34944
|
+
return text11(`Unknown family "${family}". Valid families: ${Object.keys(SERP_FAMILIES).join(", ")}.`, true);
|
|
34550
34945
|
}
|
|
34551
34946
|
const r = await findEngines(query2 ?? "", catalogOnce().filter((e) => !UNAVAILABLE.has(e.id)), {
|
|
34552
34947
|
limit,
|
|
@@ -34561,7 +34956,7 @@ function buildSerpTools(deps) {
|
|
|
34561
34956
|
next: "Call serp_describe with an engine id for its full parameter list, then run it with the named family tool."
|
|
34562
34957
|
});
|
|
34563
34958
|
}));
|
|
34564
|
-
tools.push(
|
|
34959
|
+
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
34960
|
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
34961
|
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
34962
|
}, async (a) => {
|
|
@@ -34606,10 +35001,10 @@ function buildSerpTools(deps) {
|
|
|
34606
35001
|
}
|
|
34607
35002
|
return json2(out);
|
|
34608
35003
|
}));
|
|
34609
|
-
tools.push(
|
|
35004
|
+
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
35005
|
const st = await deps.status();
|
|
34611
35006
|
if (!st.configured)
|
|
34612
|
-
return
|
|
35007
|
+
return text11(NO_KEY, true);
|
|
34613
35008
|
try {
|
|
34614
35009
|
const acct = await deps.client.account();
|
|
34615
35010
|
return json2({
|
|
@@ -34625,10 +35020,10 @@ function buildSerpTools(deps) {
|
|
|
34625
35020
|
...st.session ? { this_session: st.session } : {}
|
|
34626
35021
|
});
|
|
34627
35022
|
} catch (e) {
|
|
34628
|
-
return
|
|
35023
|
+
return text11(`Could not read the SerpApi account: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34629
35024
|
}
|
|
34630
35025
|
}));
|
|
34631
|
-
tools.push(
|
|
35026
|
+
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
35027
|
query: external_exports.string().describe('Place name to resolve, e.g. "Chisinau" or "Austin".'),
|
|
34633
35028
|
limit: external_exports.number().int().min(1).max(10).optional().describe("Maximum matches (SerpApi caps this at 10).")
|
|
34634
35029
|
}, async (a) => {
|
|
@@ -34637,10 +35032,10 @@ function buildSerpTools(deps) {
|
|
|
34637
35032
|
const hits = await deps.client.locations(query2, limit ?? 5);
|
|
34638
35033
|
return json2(hits.map((h) => ({ canonical_name: h.canonical_name, country: h.country_code, type: h.target_type, reach: h.reach })));
|
|
34639
35034
|
} catch (e) {
|
|
34640
|
-
return
|
|
35035
|
+
return text11(`Location lookup failed: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34641
35036
|
}
|
|
34642
35037
|
}));
|
|
34643
|
-
tools.push(
|
|
35038
|
+
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
35039
|
search_id: external_exports.string().describe("The id from `_search_id`, or from a `submit_async` submission."),
|
|
34645
35040
|
format: external_exports.enum(["json", "markdown"]).optional().describe("`json` (default) is structured; `markdown` is roughly half the tokens but carries no chaining tokens."),
|
|
34646
35041
|
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 +35043,50 @@ function buildSerpTools(deps) {
|
|
|
34648
35043
|
const { search_id, format, max_results } = a ?? {};
|
|
34649
35044
|
const st = await deps.status();
|
|
34650
35045
|
if (!st.configured)
|
|
34651
|
-
return
|
|
35046
|
+
return text11(NO_KEY, true);
|
|
34652
35047
|
try {
|
|
34653
35048
|
if (format === "markdown") {
|
|
34654
35049
|
const { markdown } = await deps.client.archiveMarkdown(search_id);
|
|
34655
|
-
return
|
|
35050
|
+
return text11(markdown);
|
|
34656
35051
|
}
|
|
34657
35052
|
const body = await deps.client.archive(search_id);
|
|
34658
35053
|
const status2 = body.search_metadata?.status;
|
|
34659
35054
|
if (status2 && status2 !== "Success") {
|
|
34660
|
-
return
|
|
35055
|
+
return text11(`Search ${search_id} is ${status2}. This call was free \u2014 call serp_archive again in a moment.`);
|
|
34661
35056
|
}
|
|
34662
35057
|
return json2(compactResponse(body, { maxResults: max_results ?? 10 }));
|
|
34663
35058
|
} catch (e) {
|
|
34664
|
-
return
|
|
35059
|
+
return text11(`Could not read search ${search_id}: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34665
35060
|
}
|
|
34666
35061
|
}));
|
|
34667
|
-
tools.push(
|
|
35062
|
+
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
35063
|
path: external_exports.string().describe("Absolute path to the image file on this machine.")
|
|
34669
35064
|
}, async (a) => {
|
|
34670
35065
|
const { path: path6 } = a ?? {};
|
|
34671
35066
|
const st = await deps.status();
|
|
34672
35067
|
if (!st.configured)
|
|
34673
|
-
return
|
|
35068
|
+
return text11(NO_KEY, true);
|
|
34674
35069
|
let bytes3;
|
|
34675
35070
|
try {
|
|
34676
35071
|
const size = statSync3(path6).size;
|
|
34677
35072
|
if (size === 0)
|
|
34678
|
-
return
|
|
35073
|
+
return text11(`${path6} is empty.`, true);
|
|
34679
35074
|
if (size > MAX_IMAGE_BYTES) {
|
|
34680
|
-
return
|
|
35075
|
+
return text11(`${path6} is ${Math.round(size / 1024)} KB; SerpApi accepts images up to 500 KB. Resize it first.`, true);
|
|
34681
35076
|
}
|
|
34682
35077
|
const kind = imageKind(path6);
|
|
34683
35078
|
if (!kind)
|
|
34684
|
-
return
|
|
35079
|
+
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
35080
|
bytes3 = readFileSync6(path6);
|
|
34686
35081
|
} catch (e) {
|
|
34687
|
-
return
|
|
35082
|
+
return text11(`Could not read ${path6}: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34688
35083
|
}
|
|
34689
35084
|
try {
|
|
34690
35085
|
const { image_id } = await deps.client.uploadImage(bytes3, basename2(path6));
|
|
34691
|
-
return
|
|
35086
|
+
return text11(`image_id: ${image_id}
|
|
34692
35087
|
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
35088
|
} catch (e) {
|
|
34694
|
-
return
|
|
35089
|
+
return text11(`Image upload failed: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
34695
35090
|
}
|
|
34696
35091
|
}));
|
|
34697
35092
|
for (const [family, info] of Object.entries(SERP_FAMILIES)) {
|
|
@@ -34701,7 +35096,7 @@ Pass it as the image parameter of a reverse-image engine (google_lens uses \`url
|
|
|
34701
35096
|
const ids = [...engines2];
|
|
34702
35097
|
const listing = engines2.map((id) => `${id} \u2014 ${ENGINE_INFO[id]?.purpose ?? ""}`).join("; ");
|
|
34703
35098
|
const trapped = engines2.filter((id) => ENGINE_INFO[id]?.traps?.length);
|
|
34704
|
-
tools.push(
|
|
35099
|
+
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
35100
|
engine: external_exports.enum(ids).describe("Which engine to run."),
|
|
34706
35101
|
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
35102
|
...PAGE_ARGS,
|
|
@@ -34716,13 +35111,13 @@ Pass it as the image parameter of a reverse-image engine (google_lens uses \`url
|
|
|
34716
35111
|
async function runEngine(deps, args) {
|
|
34717
35112
|
const st = await deps.status();
|
|
34718
35113
|
if (!st.configured)
|
|
34719
|
-
return
|
|
35114
|
+
return text11(NO_KEY, true);
|
|
34720
35115
|
const spec = SERP_SPEC.engines[args.engine];
|
|
34721
35116
|
if (!spec)
|
|
34722
|
-
return
|
|
35117
|
+
return text11(`Unknown engine "${args.engine}". Call serp_find to locate the right one.`, true);
|
|
34723
35118
|
const info = ENGINE_INFO[args.engine];
|
|
34724
35119
|
if (info?.status) {
|
|
34725
|
-
return
|
|
35120
|
+
return text11(`\`${args.engine}\` is ${info.status.state} and cannot be used: ${info.status.detail} No credit was spent. ${info.purpose}`, true);
|
|
34726
35121
|
}
|
|
34727
35122
|
const strategy = pageStrategy(spec);
|
|
34728
35123
|
const rawParams = { ...args.params ?? {} };
|
|
@@ -34737,7 +35132,7 @@ async function runEngine(deps, args) {
|
|
|
34737
35132
|
v.warnings.push(`Both \`page_size\` (${args.page_size}) and \`${sizeParam}\` (${explicitSize}) were given; \`page_size\` wins.`);
|
|
34738
35133
|
}
|
|
34739
35134
|
if (!v.ok) {
|
|
34740
|
-
return
|
|
35135
|
+
return text11(`Cannot run \`${args.engine}\` \u2014 no credit spent.
|
|
34741
35136
|
${v.errors.map((e) => `\u2022 ${e}`).join("\n")}
|
|
34742
35137
|
|
|
34743
35138
|
Call serp_describe({engines:["${args.engine}"]}) for the full parameter list.`, true);
|
|
@@ -34755,8 +35150,8 @@ Call serp_describe({engines:["${args.engine}"]}) for the full parameter list.`,
|
|
|
34755
35150
|
const submitted = await deps.client.search(args.engine, { ...v.params, ...paging }, opts);
|
|
34756
35151
|
const id = submitted.search_metadata?.id;
|
|
34757
35152
|
if (!id)
|
|
34758
|
-
return
|
|
34759
|
-
return
|
|
35153
|
+
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);
|
|
35154
|
+
return text11(`Submitted \`${args.engine}\` \u2014 search_id: ${id}
|
|
34760
35155
|
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
35156
|
}
|
|
34762
35157
|
if (args.format === "markdown") {
|
|
@@ -34764,7 +35159,7 @@ The credit is already spent. Collect it with serp_archive({ search_id: "${id}" }
|
|
|
34764
35159
|
const warn = v.warnings.length ? `${v.warnings.map((w) => `\u26A0 ${w}`).join("\n")}
|
|
34765
35160
|
|
|
34766
35161
|
` : "";
|
|
34767
|
-
return
|
|
35162
|
+
return text11(`${warn}${markdown}`);
|
|
34768
35163
|
}
|
|
34769
35164
|
const body = await deps.client.search(args.engine, { ...v.params, ...paging }, opts);
|
|
34770
35165
|
const compact2 = compactResponse(body, { maxResults: args.max_results ?? 10 });
|
|
@@ -34775,27 +35170,27 @@ The credit is already spent. Collect it with serp_archive({ search_id: "${id}" }
|
|
|
34775
35170
|
if (body._page?.hasNext && supportsPaging(spec)) {
|
|
34776
35171
|
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
35172
|
}
|
|
34778
|
-
return
|
|
35173
|
+
return text11(parts.join("\n\n"));
|
|
34779
35174
|
} catch (e) {
|
|
34780
35175
|
const msg = e instanceof Error ? e.message : String(e);
|
|
34781
|
-
return
|
|
35176
|
+
return text11(`\`${args.engine}\` failed: ${msg}`, true);
|
|
34782
35177
|
}
|
|
34783
35178
|
}
|
|
34784
|
-
var
|
|
35179
|
+
var text11, json2, UNAVAILABLE, MAX_DESCRIBE_ENGINES, MAX_PARAM_DESC, clip, MAX_IMAGE_BYTES, NO_KEY, PAGE_ARGS, OUTPUT_ARGS, cachedCatalog, brief;
|
|
34785
35180
|
var init_serpapi_tools = __esm({
|
|
34786
35181
|
"../../packages/agent-core/dist/serpapi/serpapi-tools.js"() {
|
|
34787
35182
|
"use strict";
|
|
34788
35183
|
init_zod();
|
|
34789
35184
|
init_dist4();
|
|
34790
|
-
|
|
35185
|
+
text11 = (t, isError = false) => ({
|
|
34791
35186
|
content: [{ type: "text", text: t }],
|
|
34792
35187
|
...isError ? { isError: true } : {}
|
|
34793
35188
|
});
|
|
34794
|
-
json2 = (v) =>
|
|
35189
|
+
json2 = (v) => text11(JSON.stringify(v, null, 2));
|
|
34795
35190
|
UNAVAILABLE = new Set(UNAVAILABLE_ENGINES);
|
|
34796
35191
|
MAX_DESCRIBE_ENGINES = 3;
|
|
34797
35192
|
MAX_PARAM_DESC = 400;
|
|
34798
|
-
clip = (
|
|
35193
|
+
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
35194
|
MAX_IMAGE_BYTES = 500 * 1024;
|
|
34800
35195
|
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
35196
|
PAGE_ARGS = {
|
|
@@ -34822,13 +35217,13 @@ var init_serpapi_tools = __esm({
|
|
|
34822
35217
|
});
|
|
34823
35218
|
|
|
34824
35219
|
// ../../packages/agent-core/dist/report-tools.js
|
|
34825
|
-
import { tool as
|
|
35220
|
+
import { tool as tool19 } from "@anthropic-ai/claude-agent-sdk";
|
|
34826
35221
|
function slug(s) {
|
|
34827
35222
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "mission";
|
|
34828
35223
|
}
|
|
34829
35224
|
function buildReportTools(deps) {
|
|
34830
35225
|
return [
|
|
34831
|
-
|
|
35226
|
+
tool19("emit_report", prompt("tool.report.emit_report"), {
|
|
34832
35227
|
id: external_exports.string().optional().describe("Stable report id to UPDATE an existing report; omit on the first call to create one."),
|
|
34833
35228
|
playbookId: external_exports.string().describe("The playbook id this report belongs to."),
|
|
34834
35229
|
title: external_exports.string().describe("Report title (usually the playbook name)."),
|
|
@@ -34882,10 +35277,10 @@ var init_report_tools = __esm({
|
|
|
34882
35277
|
});
|
|
34883
35278
|
|
|
34884
35279
|
// ../../packages/agent-core/dist/interactive-ui-tools.js
|
|
34885
|
-
import { tool as
|
|
35280
|
+
import { tool as tool20 } from "@anthropic-ai/claude-agent-sdk";
|
|
34886
35281
|
function buildInteractiveUiTools(deps) {
|
|
34887
35282
|
return [
|
|
34888
|
-
|
|
35283
|
+
tool20("ask_form", prompt("tool.interactive-ui.ask_form"), {
|
|
34889
35284
|
title: external_exports.string().describe("Form heading (plain language)."),
|
|
34890
35285
|
description: external_exports.string().optional().describe("Short explanation shown above the fields."),
|
|
34891
35286
|
submitLabel: external_exports.string().optional().describe('Submit button label (default "Submit").'),
|
|
@@ -34899,7 +35294,7 @@ function buildInteractiveUiTools(deps) {
|
|
|
34899
35294
|
return { content: [{ type: "text", text: `The user submitted the form:
|
|
34900
35295
|
${JSON.stringify(res.values ?? {}, null, 2)}` }] };
|
|
34901
35296
|
}),
|
|
34902
|
-
|
|
35297
|
+
tool20("present_choices", prompt("tool.interactive-ui.present_choices"), {
|
|
34903
35298
|
title: external_exports.string().describe("The question / heading."),
|
|
34904
35299
|
description: external_exports.string().optional(),
|
|
34905
35300
|
options: external_exports.array(choiceOption).min(1),
|
|
@@ -34912,7 +35307,7 @@ ${JSON.stringify(res.values ?? {}, null, 2)}` }] };
|
|
|
34912
35307
|
return { content: [{ type: "text", text: "The user cancelled the choice (nothing selected)." }] };
|
|
34913
35308
|
return { content: [{ type: "text", text: `The user selected: ${JSON.stringify(res.selected ?? [])}` }] };
|
|
34914
35309
|
}),
|
|
34915
|
-
|
|
35310
|
+
tool20("update_progress", prompt("tool.interactive-ui.update_progress"), {
|
|
34916
35311
|
stages: external_exports.array(external_exports.object({
|
|
34917
35312
|
label: external_exports.string(),
|
|
34918
35313
|
status: external_exports.enum(["pending", "active", "done"])
|
|
@@ -35037,8 +35432,8 @@ async function exportSession(sessionId, fromCwd) {
|
|
|
35037
35432
|
function escapeRe(s) {
|
|
35038
35433
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
35039
35434
|
}
|
|
35040
|
-
function rekey(
|
|
35041
|
-
return
|
|
35435
|
+
function rekey(text13, fromCwd, toCwd) {
|
|
35436
|
+
return text13.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
|
|
35042
35437
|
}
|
|
35043
35438
|
async function importSession(exp, toCwd) {
|
|
35044
35439
|
const destDir = sessionDir(toCwd);
|
|
@@ -35311,13 +35706,13 @@ var init_narrator = __esm({
|
|
|
35311
35706
|
prompt("side-llm.narrator.activity", { activity }),
|
|
35312
35707
|
prompt("side-llm.narrator.ask")
|
|
35313
35708
|
].filter(Boolean).join("\n\n");
|
|
35314
|
-
const
|
|
35315
|
-
if (
|
|
35316
|
-
s.lastText =
|
|
35317
|
-
s.log.push(
|
|
35709
|
+
const text13 = (await cfg2.complete({ system, prompt: promptText, maxTokens: 48 }))?.trim().replace(/^["']|["']$/g, "");
|
|
35710
|
+
if (text13 && text13 !== s.lastText) {
|
|
35711
|
+
s.lastText = text13;
|
|
35712
|
+
s.log.push(text13);
|
|
35318
35713
|
if (s.log.length > LOG_CAP)
|
|
35319
35714
|
s.log.shift();
|
|
35320
|
-
this.emit(id,
|
|
35715
|
+
this.emit(id, text13, cfg2.engineLabel);
|
|
35321
35716
|
}
|
|
35322
35717
|
} catch {
|
|
35323
35718
|
} finally {
|
|
@@ -35459,15 +35854,15 @@ function recordVerificationDecision(entry) {
|
|
|
35459
35854
|
function readUnattendedDecisions(limit = 200, opts) {
|
|
35460
35855
|
const out = [];
|
|
35461
35856
|
for (const file2 of [rolledPath(), unattendedLogPath()]) {
|
|
35462
|
-
let
|
|
35857
|
+
let text13;
|
|
35463
35858
|
try {
|
|
35464
35859
|
if (!existsSync2(file2))
|
|
35465
35860
|
continue;
|
|
35466
|
-
|
|
35861
|
+
text13 = readFileSync7(file2, "utf8");
|
|
35467
35862
|
} catch {
|
|
35468
35863
|
continue;
|
|
35469
35864
|
}
|
|
35470
|
-
for (const line of
|
|
35865
|
+
for (const line of text13.split("\n")) {
|
|
35471
35866
|
if (!line.trim())
|
|
35472
35867
|
continue;
|
|
35473
35868
|
try {
|
|
@@ -36230,10 +36625,10 @@ function assistantContextOverflow(content, isContextOverflowFn) {
|
|
|
36230
36625
|
const blocks = content;
|
|
36231
36626
|
if (blocks.some((block2) => block2?.type !== "text"))
|
|
36232
36627
|
return false;
|
|
36233
|
-
const
|
|
36234
|
-
if (!
|
|
36628
|
+
const text13 = blocks.map((b) => typeof b.text === "string" ? b.text : "").join("\n").trim();
|
|
36629
|
+
if (!text13 || text13.length > 400)
|
|
36235
36630
|
return false;
|
|
36236
|
-
return isContextOverflowFn(
|
|
36631
|
+
return isContextOverflowFn(text13);
|
|
36237
36632
|
}
|
|
36238
36633
|
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE;
|
|
36239
36634
|
var init_context_recovery = __esm({
|
|
@@ -36343,8 +36738,8 @@ function pendingQueueRows(rows) {
|
|
|
36343
36738
|
}
|
|
36344
36739
|
return keep;
|
|
36345
36740
|
}
|
|
36346
|
-
function stripHostText(
|
|
36347
|
-
return stripRunDirective(
|
|
36741
|
+
function stripHostText(text13) {
|
|
36742
|
+
return stripRunDirective(text13).trimEnd();
|
|
36348
36743
|
}
|
|
36349
36744
|
function rejectedByApi(b) {
|
|
36350
36745
|
if (!b || typeof b !== "object")
|
|
@@ -36653,10 +37048,10 @@ function filterHistory(transcript, opts = {}) {
|
|
|
36653
37048
|
const parent = resolveParent2(r.parentUuid);
|
|
36654
37049
|
out.push(JSON.stringify(parent === (r.parentUuid ?? null) ? r : { ...r, parentUuid: parent }));
|
|
36655
37050
|
}
|
|
36656
|
-
const
|
|
37051
|
+
const text13 = out.join("\n") + (out.length ? "\n" : "");
|
|
36657
37052
|
stats.rowsOut = out.length;
|
|
36658
|
-
stats.bytesOut = Buffer.byteLength(
|
|
36659
|
-
return { text:
|
|
37053
|
+
stats.bytesOut = Buffer.byteLength(text13, "utf8");
|
|
37054
|
+
return { text: text13, stats, spills };
|
|
36660
37055
|
}
|
|
36661
37056
|
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
37057
|
var init_history_filter = __esm({
|
|
@@ -36689,9 +37084,9 @@ function archiveMetaPath(transcript) {
|
|
|
36689
37084
|
function offloadDirFor(transcript) {
|
|
36690
37085
|
return transcript.replace(/\.jsonl$/, "") + ".offload";
|
|
36691
37086
|
}
|
|
36692
|
-
function contentBytes(
|
|
37087
|
+
function contentBytes(text13, liveOnly = true) {
|
|
36693
37088
|
let n = 0;
|
|
36694
|
-
const all =
|
|
37089
|
+
const all = text13.split("\n");
|
|
36695
37090
|
for (const line of liveOnly ? all.slice(liveRegionStart(all)) : all) {
|
|
36696
37091
|
if (!line.trim())
|
|
36697
37092
|
continue;
|
|
@@ -36750,9 +37145,9 @@ async function slimTranscriptFile(transcript, opts = {}) {
|
|
|
36750
37145
|
const liveText = await readFile4(transcript, "utf8");
|
|
36751
37146
|
const liveLines = liveText.split("\n").filter((l) => l.trim().length > 0);
|
|
36752
37147
|
const offloadDir = offloadDirFor(transcript);
|
|
36753
|
-
const { text:
|
|
37148
|
+
const { text: text13, stats, spills } = filterHistory(liveText, { spillDir: offloadDir, ...opts });
|
|
36754
37149
|
const before = contentBytes(liveText);
|
|
36755
|
-
const after = contentBytes(
|
|
37150
|
+
const after = contentBytes(text13);
|
|
36756
37151
|
const changed = stats.droppedRows > 0 || stats.droppedThinking > 0 || stats.droppedToolUse > 0 || stats.droppedToolResult > 0 || stats.offloaded > 0 || stats.supersededAttachments > 0 || stats.repairedBlocks > 0;
|
|
36757
37152
|
if (!changed) {
|
|
36758
37153
|
return { slimmed: false, reason: "nothing to strip", contentBefore: before, contentAfter: after, stats };
|
|
@@ -36777,9 +37172,9 @@ async function slimTranscriptFile(transcript, opts = {}) {
|
|
|
36777
37172
|
return { slimmed: false, reason: "the transcript changed during the strip \u2014 left as is", contentBefore: before, contentAfter: after, stats };
|
|
36778
37173
|
}
|
|
36779
37174
|
const tmp = join11(dirname7(transcript), `.slim-${randomUUID2().slice(0, 8)}.tmp`);
|
|
36780
|
-
await writeFile4(tmp,
|
|
37175
|
+
await writeFile4(tmp, text13, { mode: 384 });
|
|
36781
37176
|
await rename(tmp, transcript);
|
|
36782
|
-
const outLines =
|
|
37177
|
+
const outLines = text13.split("\n").filter((l) => l.trim().length > 0);
|
|
36783
37178
|
await writeFile4(archiveMetaPath(transcript), JSON.stringify({ rows: outLines.length, tail: outLines[outLines.length - 1] ?? "" }), { mode: 384 });
|
|
36784
37179
|
return { slimmed: true, stats, contentBefore: before, contentAfter: after, archive, offloadDir };
|
|
36785
37180
|
}
|
|
@@ -36920,8 +37315,8 @@ async function labelFromTranscript(file2) {
|
|
|
36920
37315
|
if (row.type !== "user" && row.message?.role !== "user")
|
|
36921
37316
|
continue;
|
|
36922
37317
|
const c = row.message?.content;
|
|
36923
|
-
const
|
|
36924
|
-
const s = oneLine(
|
|
37318
|
+
const text13 = typeof c === "string" ? c : Array.isArray(c) ? c.find((b) => b.type === "text")?.text ?? "" : "";
|
|
37319
|
+
const s = oneLine(text13);
|
|
36925
37320
|
if (s)
|
|
36926
37321
|
return s;
|
|
36927
37322
|
}
|
|
@@ -37390,33 +37785,33 @@ function annotationIsOrphaned(e, removedUuids) {
|
|
|
37390
37785
|
return false;
|
|
37391
37786
|
return clearDanglingPointers(e, removedUuids) !== e;
|
|
37392
37787
|
}
|
|
37393
|
-
function isPromptEchoOf(e, removedUuids,
|
|
37788
|
+
function isPromptEchoOf(e, removedUuids, text13) {
|
|
37394
37789
|
if (e.type !== "last-prompt")
|
|
37395
37790
|
return false;
|
|
37396
37791
|
const leaf = typeof e.leafUuid === "string" ? e.leafUuid : void 0;
|
|
37397
37792
|
if (leaf && removedUuids.has(leaf))
|
|
37398
37793
|
return true;
|
|
37399
|
-
if (!
|
|
37794
|
+
if (!text13)
|
|
37400
37795
|
return false;
|
|
37401
37796
|
const echo = typeof e.lastPrompt === "string" ? e.lastPrompt : void 0;
|
|
37402
|
-
return echo ===
|
|
37797
|
+
return echo === text13;
|
|
37403
37798
|
}
|
|
37404
37799
|
function messageText(e) {
|
|
37405
37800
|
const content = e.message?.content;
|
|
37406
37801
|
if (typeof content === "string")
|
|
37407
37802
|
return content;
|
|
37408
37803
|
if (Array.isArray(content)) {
|
|
37409
|
-
const
|
|
37410
|
-
return
|
|
37804
|
+
const text13 = content.filter((b) => !!b && typeof b === "object" && b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
|
|
37805
|
+
return text13 || void 0;
|
|
37411
37806
|
}
|
|
37412
37807
|
return void 0;
|
|
37413
37808
|
}
|
|
37414
|
-
function findUserEntryByText(entries,
|
|
37809
|
+
function findUserEntryByText(entries, text13) {
|
|
37415
37810
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
37416
37811
|
const e = entries[i];
|
|
37417
37812
|
if (e.type !== "user" || !e.uuid)
|
|
37418
37813
|
continue;
|
|
37419
|
-
if (messageText(e) ===
|
|
37814
|
+
if (messageText(e) === text13)
|
|
37420
37815
|
return e;
|
|
37421
37816
|
}
|
|
37422
37817
|
return void 0;
|
|
@@ -37985,10 +38380,10 @@ async function toSessionInfo(s) {
|
|
|
37985
38380
|
const spoken = s.cwd ? await lastConversationTime(sessionFile(s.cwd, s.sessionId)) : null;
|
|
37986
38381
|
return { id: s.sessionId, title, lastModified: spoken ?? s.lastModified, cwd: s.cwd };
|
|
37987
38382
|
}
|
|
37988
|
-
function stripPromptPrefix(
|
|
37989
|
-
|
|
38383
|
+
function stripPromptPrefix(text13) {
|
|
38384
|
+
text13 = stripRunDirective(text13);
|
|
37990
38385
|
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 =
|
|
38386
|
+
const userLines = text13.split("\n").filter((l) => !isMetadata(l));
|
|
37992
38387
|
return userLines.join("\n").trim();
|
|
37993
38388
|
}
|
|
37994
38389
|
function extractBlocks(message) {
|
|
@@ -38007,13 +38402,13 @@ function extractBlocks(message) {
|
|
|
38007
38402
|
continue;
|
|
38008
38403
|
const b = block2;
|
|
38009
38404
|
if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
38010
|
-
const
|
|
38011
|
-
if (
|
|
38012
|
-
blocks.push({ kind: "thinking", content:
|
|
38405
|
+
const text13 = b.thinking.trim();
|
|
38406
|
+
if (text13)
|
|
38407
|
+
blocks.push({ kind: "thinking", content: text13 });
|
|
38013
38408
|
} else if (b.type === "text" && typeof b.text === "string") {
|
|
38014
|
-
const
|
|
38015
|
-
if (
|
|
38016
|
-
blocks.push({ kind: "text", content:
|
|
38409
|
+
const text13 = b.text.trim();
|
|
38410
|
+
if (text13 && !text13.startsWith("<ide_") && !text13.startsWith("<system-reminder>")) {
|
|
38411
|
+
blocks.push({ kind: "text", content: text13 });
|
|
38017
38412
|
}
|
|
38018
38413
|
} else if (b.type === "tool_use") {
|
|
38019
38414
|
const name = b.name ?? "tool";
|
|
@@ -38059,9 +38454,9 @@ ${input.command}
|
|
|
38059
38454
|
blocks.push({ kind: "tool_use", content: detail, name });
|
|
38060
38455
|
} else if (b.type === "advisor_tool_result") {
|
|
38061
38456
|
const c = b.content;
|
|
38062
|
-
const
|
|
38063
|
-
if (
|
|
38064
|
-
blocks.push({ kind: "advisor", content:
|
|
38457
|
+
const text13 = c?.type === "advisor_result" ? (c.text ?? "").trim() : "";
|
|
38458
|
+
if (text13)
|
|
38459
|
+
blocks.push({ kind: "advisor", content: text13 });
|
|
38065
38460
|
}
|
|
38066
38461
|
}
|
|
38067
38462
|
return blocks;
|
|
@@ -38403,8 +38798,8 @@ async function anthropicCall(args) {
|
|
|
38403
38798
|
});
|
|
38404
38799
|
if (res.ok) {
|
|
38405
38800
|
const j = await res.json();
|
|
38406
|
-
const
|
|
38407
|
-
return { text:
|
|
38801
|
+
const text13 = (j.content ?? []).filter((b) => b.type === "text").map((b) => b.text ?? "").join("").trim() || null;
|
|
38802
|
+
return { text: text13, rateLimited: false };
|
|
38408
38803
|
}
|
|
38409
38804
|
let errBody = "";
|
|
38410
38805
|
try {
|
|
@@ -38728,8 +39123,8 @@ var init_model_switch = __esm({
|
|
|
38728
39123
|
|
|
38729
39124
|
// ../../packages/agent-core/dist/usage-limit.js
|
|
38730
39125
|
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 = (
|
|
39126
|
+
function classifyUsageMessage(text13) {
|
|
39127
|
+
const t = (text13 ?? "").trim();
|
|
38733
39128
|
if (!t)
|
|
38734
39129
|
return void 0;
|
|
38735
39130
|
const hits = (list) => list.some((p) => t.startsWith(p));
|
|
@@ -38765,16 +39160,16 @@ function assistantUsageLimitFallback(content) {
|
|
|
38765
39160
|
const blocks = content;
|
|
38766
39161
|
if (blocks.some((block2) => block2?.type !== "text"))
|
|
38767
39162
|
return void 0;
|
|
38768
|
-
const
|
|
38769
|
-
if (!
|
|
39163
|
+
const text13 = blocks.map((block2) => typeof block2.text === "string" ? block2.text : "").join("\n").trim();
|
|
39164
|
+
if (!text13 || text13.length > 600)
|
|
38770
39165
|
return void 0;
|
|
38771
|
-
const signal2 = classifyUsageMessage(
|
|
39166
|
+
const signal2 = classifyUsageMessage(text13);
|
|
38772
39167
|
if (signal2 !== "limit" && signal2 !== "org-policy")
|
|
38773
39168
|
return void 0;
|
|
38774
|
-
const isoReset =
|
|
38775
|
-
const resetMatch =
|
|
39169
|
+
const isoReset = text13.match(/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z\b/i)?.[0];
|
|
39170
|
+
const resetMatch = text13.match(/(?:reset|resets|available again)(?:s| at| on| in)?\s+([^\n]+)/i);
|
|
38776
39171
|
const parsed = Date.parse(isoReset ?? resetMatch?.[1].trim() ?? "");
|
|
38777
|
-
return { retryAt: Number.isFinite(parsed) ? parsed : void 0, signal: signal2, scopeText:
|
|
39172
|
+
return { retryAt: Number.isFinite(parsed) ? parsed : void 0, signal: signal2, scopeText: text13 };
|
|
38778
39173
|
}
|
|
38779
39174
|
function usageLimitErrorMessage(rejection) {
|
|
38780
39175
|
if (rejection.signal === "org-policy") {
|
|
@@ -38789,16 +39184,30 @@ function usageLimitIsRotatable(rejection) {
|
|
|
38789
39184
|
function usageLimitScopedModel(rejection, current) {
|
|
38790
39185
|
if (rejection.signal === "org-policy")
|
|
38791
39186
|
return void 0;
|
|
38792
|
-
const
|
|
38793
|
-
if (!
|
|
39187
|
+
const text13 = (rejection.scopeText ?? "").trim();
|
|
39188
|
+
if (!text13)
|
|
38794
39189
|
return void 0;
|
|
38795
|
-
const named = /reached your ([A-Za-z0-9.\- ]{1,30}?) limit/i.exec(
|
|
39190
|
+
const named = /reached your ([A-Za-z0-9.\- ]{1,30}?) limit/i.exec(text13)?.[1]?.trim().toLowerCase();
|
|
38796
39191
|
if (!named)
|
|
38797
39192
|
return void 0;
|
|
38798
39193
|
if (current && !current.toLowerCase().includes(named))
|
|
38799
39194
|
return void 0;
|
|
38800
39195
|
return named;
|
|
38801
39196
|
}
|
|
39197
|
+
function providerIsServing(content) {
|
|
39198
|
+
if (typeof content === "string")
|
|
39199
|
+
return content.trim().length > 0;
|
|
39200
|
+
if (!Array.isArray(content))
|
|
39201
|
+
return false;
|
|
39202
|
+
return content.some((blk) => {
|
|
39203
|
+
const b = blk;
|
|
39204
|
+
if (!b || typeof b !== "object")
|
|
39205
|
+
return false;
|
|
39206
|
+
if (b.type === "text")
|
|
39207
|
+
return typeof b.text === "string" && b.text.trim().length > 0;
|
|
39208
|
+
return b.type === "tool_use" || b.type === "server_tool_use" || b.type === "thinking";
|
|
39209
|
+
});
|
|
39210
|
+
}
|
|
38802
39211
|
var init_usage_limit = __esm({
|
|
38803
39212
|
"../../packages/agent-core/dist/usage-limit.js"() {
|
|
38804
39213
|
"use strict";
|
|
@@ -38829,8 +39238,14 @@ function findUserInstalledClaude(binName) {
|
|
|
38829
39238
|
const home = homedir3();
|
|
38830
39239
|
const abs = [
|
|
38831
39240
|
join17(home, ".claude", "local", binName),
|
|
38832
|
-
//
|
|
39241
|
+
// legacy local npm install (older Claude Code)
|
|
38833
39242
|
join17(home, ".local", "bin", binName),
|
|
39243
|
+
// the native installer's launcher — where we install
|
|
39244
|
+
// A copy Tesseract itself installed back when it used `npm install -g --prefix`. The probe has
|
|
39245
|
+
// always searched here, this list never did, so such an install read as "installed" in Settings
|
|
39246
|
+
// while the spawn said "not installed". AFTER ~/.local/bin deliberately: a current native
|
|
39247
|
+
// install must win over a stale npm one.
|
|
39248
|
+
join17(home, ".tesseract", "runtimes", "bin", binName),
|
|
38834
39249
|
join17(home, ".bun", "bin", binName),
|
|
38835
39250
|
join17(home, ".volta", "bin", binName),
|
|
38836
39251
|
join17(home, "Library", "pnpm", binName),
|
|
@@ -38885,7 +39300,7 @@ function resolveClaudeCodeExecutable() {
|
|
|
38885
39300
|
return cachedClaudeExe = bundled;
|
|
38886
39301
|
}
|
|
38887
39302
|
}
|
|
38888
|
-
throw new Error("Claude Code isn\u2019t installed. Tesseract runs
|
|
39303
|
+
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
39304
|
}
|
|
38890
39305
|
function identityEnv() {
|
|
38891
39306
|
const out = {};
|
|
@@ -39262,8 +39677,8 @@ function traceFrame(message) {
|
|
|
39262
39677
|
const k = b?.type ?? "?";
|
|
39263
39678
|
kinds.set(k, (kinds.get(k) ?? 0) + 1);
|
|
39264
39679
|
}
|
|
39265
|
-
const
|
|
39266
|
-
what = [...kinds].map(([k, n]) => n > 1 ? `${k}\xD7${n}` : k).join(",") + (
|
|
39680
|
+
const text13 = c.find((b) => b?.type === "text")?.text;
|
|
39681
|
+
what = [...kinds].map(([k, n]) => n > 1 ? `${k}\xD7${n}` : k).join(",") + (text13 ? ` text:${JSON.stringify(text13.slice(0, 60))}` : "");
|
|
39267
39682
|
}
|
|
39268
39683
|
log(`frame user${parent}${flags.length ? " [" + flags.join(",") + "]" : ""}${what ? " \u2014 " + what : ""}`);
|
|
39269
39684
|
return;
|
|
@@ -39354,8 +39769,8 @@ function describeSystemSubtype(subtype, m) {
|
|
|
39354
39769
|
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
39770
|
return { category, name: subtype, title: humanizeName(subtype), fields: salientFields(m), ...updateKey ? { updateKey } : {} };
|
|
39356
39771
|
}
|
|
39357
|
-
const
|
|
39358
|
-
return { category: "unknown", name: subtype, title: `system/${subtype}`, ...
|
|
39772
|
+
const text13 = extractHumanReadable(m);
|
|
39773
|
+
return { category: "unknown", name: subtype, title: `system/${subtype}`, ...text13 ? { detail: text13 } : {}, raw: rawFramePreview(m) };
|
|
39359
39774
|
}
|
|
39360
39775
|
function sstr(v) {
|
|
39361
39776
|
return typeof v === "string" ? v : "";
|
|
@@ -39375,24 +39790,24 @@ function prettifyModel(id) {
|
|
|
39375
39790
|
return known[id] ?? id.replace(/^claude-/, "").replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
39376
39791
|
}
|
|
39377
39792
|
function taskNotificationNotices(content) {
|
|
39378
|
-
let
|
|
39793
|
+
let text13 = "";
|
|
39379
39794
|
if (typeof content === "string")
|
|
39380
|
-
|
|
39795
|
+
text13 = content;
|
|
39381
39796
|
else if (Array.isArray(content)) {
|
|
39382
39797
|
for (const b of content) {
|
|
39383
39798
|
if (b && typeof b === "object" && b.type === "text")
|
|
39384
|
-
|
|
39799
|
+
text13 += `${sstr(b.text)}
|
|
39385
39800
|
`;
|
|
39386
39801
|
}
|
|
39387
39802
|
}
|
|
39388
|
-
if (!
|
|
39803
|
+
if (!text13.includes("<task-notification>"))
|
|
39389
39804
|
return [];
|
|
39390
39805
|
const tag = (xml3, name) => {
|
|
39391
39806
|
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(xml3);
|
|
39392
39807
|
return m ? m[1].trim() : "";
|
|
39393
39808
|
};
|
|
39394
39809
|
const specs = [];
|
|
39395
|
-
for (const m of
|
|
39810
|
+
for (const m of text13.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
|
|
39396
39811
|
const status2 = (tag(m[1], "status") || "completed").toLowerCase();
|
|
39397
39812
|
const summary = tag(m[1], "summary") || "Background task finished.";
|
|
39398
39813
|
const failed = /fail|error/.test(status2);
|
|
@@ -39406,10 +39821,10 @@ function taskNotificationNotices(content) {
|
|
|
39406
39821
|
function buildNotice(subtype, m) {
|
|
39407
39822
|
switch (subtype) {
|
|
39408
39823
|
case "notification": {
|
|
39409
|
-
const
|
|
39824
|
+
const text13 = sstr(m.text) || "Notification";
|
|
39410
39825
|
const priority = ["low", "medium", "high", "immediate"].includes(sstr(m.priority)) ? m.priority : "medium";
|
|
39411
39826
|
const level = priority === "immediate" ? "error" : priority === "high" ? "warning" : priority === "low" ? "info" : "notice";
|
|
39412
|
-
return { category: "notification", level, priority, title:
|
|
39827
|
+
return { category: "notification", level, priority, title: text13, toast: true, inline: true, ...typeof m.timeout_ms === "number" ? { timeoutMs: m.timeout_ms } : {} };
|
|
39413
39828
|
}
|
|
39414
39829
|
case "informational": {
|
|
39415
39830
|
const content = sstr(m.content).trim();
|
|
@@ -39440,9 +39855,9 @@ function buildNotice(subtype, m) {
|
|
|
39440
39855
|
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
39856
|
}
|
|
39442
39857
|
case "permission_denied": {
|
|
39443
|
-
const
|
|
39858
|
+
const tool22 = sstr(m.tool_name) || "a tool";
|
|
39444
39859
|
const reason = sstr(m.decision_reason) || sstr(m.message);
|
|
39445
|
-
return { category: "permission", level: "warning", title: `Blocked: ${
|
|
39860
|
+
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
39861
|
}
|
|
39447
39862
|
case "model_refusal_fallback": {
|
|
39448
39863
|
const orig = sstr(m.original_model);
|
|
@@ -39556,9 +39971,9 @@ ${plan}`;
|
|
|
39556
39971
|
return name;
|
|
39557
39972
|
}
|
|
39558
39973
|
}
|
|
39559
|
-
function computerToolPhrase(
|
|
39974
|
+
function computerToolPhrase(tool22, input) {
|
|
39560
39975
|
const s = (v) => typeof v === "string" ? v : "";
|
|
39561
|
-
switch (
|
|
39976
|
+
switch (tool22) {
|
|
39562
39977
|
case "see_screen":
|
|
39563
39978
|
return input.x1 !== void 0 ? "Looking closely at part of the screen" : "Looking at the screen";
|
|
39564
39979
|
case "click":
|
|
@@ -39601,15 +40016,15 @@ function assistantText(content) {
|
|
|
39601
40016
|
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
40017
|
}
|
|
39603
40018
|
function flattenToolResultContent(content) {
|
|
39604
|
-
let
|
|
40019
|
+
let text13 = "";
|
|
39605
40020
|
if (typeof content === "string")
|
|
39606
|
-
|
|
40021
|
+
text13 = content;
|
|
39607
40022
|
else if (Array.isArray(content)) {
|
|
39608
|
-
|
|
40023
|
+
text13 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
|
|
39609
40024
|
}
|
|
39610
|
-
if (
|
|
39611
|
-
return { text:
|
|
39612
|
-
return { text:
|
|
40025
|
+
if (text13.length > TOOL_RESULT_CAP)
|
|
40026
|
+
return { text: text13.slice(0, TOOL_RESULT_CAP), truncated: true };
|
|
40027
|
+
return { text: text13, truncated: false };
|
|
39613
40028
|
}
|
|
39614
40029
|
function extractImages(content) {
|
|
39615
40030
|
if (!Array.isArray(content))
|
|
@@ -39791,6 +40206,7 @@ var init_agent_manager = __esm({
|
|
|
39791
40206
|
init_screen_control_tools();
|
|
39792
40207
|
init_computer_control_tools();
|
|
39793
40208
|
init_app_control_tools();
|
|
40209
|
+
init_capabilities_tools();
|
|
39794
40210
|
init_serpapi_tools();
|
|
39795
40211
|
init_report_tools();
|
|
39796
40212
|
init_interactive_ui_tools();
|
|
@@ -39920,7 +40336,9 @@ var init_agent_manager = __esm({
|
|
|
39920
40336
|
"await_jobs",
|
|
39921
40337
|
"job_output",
|
|
39922
40338
|
"job_list",
|
|
39923
|
-
"stop_job"
|
|
40339
|
+
"stop_job",
|
|
40340
|
+
// Returns an inlined constant. There is nothing to wait for.
|
|
40341
|
+
"tesseract_capabilities"
|
|
39924
40342
|
]);
|
|
39925
40343
|
STOP_HARD_KILL_AFTER_MS = 1200;
|
|
39926
40344
|
STREAM_STALL_MS = 20 * 6e4;
|
|
@@ -40186,8 +40604,37 @@ var init_agent_manager = __esm({
|
|
|
40186
40604
|
* (then recorded into cronTaskSessions). */
|
|
40187
40605
|
cronRequestTask = /* @__PURE__ */ new Map();
|
|
40188
40606
|
/** 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).
|
|
40607
|
+
* honour rather than the machine-wide switch (applyTurnPolicy records it; the cron fire above reads it).
|
|
40608
|
+
* Bounded: a daemon that runs for months must not grow a row per conversation forever, and forgetting the
|
|
40609
|
+
* oldest is safe — an unknown conversation falls back to 'safe' rather than to the machine switch. */
|
|
40190
40610
|
unattendedByConversation = /* @__PURE__ */ new Map();
|
|
40611
|
+
/** How many conversations' Unattended choices are remembered. Generous — one small row each — and bounded
|
|
40612
|
+
* so a long-lived daemon cannot grow this without limit. */
|
|
40613
|
+
static MAX_REMEMBERED_UNATTENDED = 2e3;
|
|
40614
|
+
/**
|
|
40615
|
+
* Everything keyed by a conversation's id that must follow it when the CLI re-ids it mid-flight
|
|
40616
|
+
* (`conversation_reset`). It is the same conversation: the scheduler must keep firing into it rather than
|
|
40617
|
+
* opening a fresh overlapping one, and the Unattended choice made in it still stands — without this, a
|
|
40618
|
+
* reset quietly downgrades the next 3am fire to 'safe' in a conversation the person set up to run alone.
|
|
40619
|
+
*/
|
|
40620
|
+
carryConversationTo(prev, next) {
|
|
40621
|
+
for (const [taskId, mapped] of this.cronTaskSessions) {
|
|
40622
|
+
if (mapped === prev)
|
|
40623
|
+
this.cronTaskSessions.set(taskId, next);
|
|
40624
|
+
}
|
|
40625
|
+
const chosen = this.unattendedByConversation.get(prev);
|
|
40626
|
+
if (chosen !== void 0) {
|
|
40627
|
+
this.unattendedByConversation.delete(prev);
|
|
40628
|
+
this.rememberUnattended(next, chosen);
|
|
40629
|
+
}
|
|
40630
|
+
}
|
|
40631
|
+
rememberUnattended(sessionId, unattended) {
|
|
40632
|
+
this.unattendedByConversation.delete(sessionId);
|
|
40633
|
+
this.unattendedByConversation.set(sessionId, unattended);
|
|
40634
|
+
while (this.unattendedByConversation.size > _AgentManager.MAX_REMEMBERED_UNATTENDED) {
|
|
40635
|
+
this.unattendedByConversation.delete(this.unattendedByConversation.keys().next().value);
|
|
40636
|
+
}
|
|
40637
|
+
}
|
|
40191
40638
|
/** Set (or clear) the skills local-plugin exposed to NEW conversations (Epic H). */
|
|
40192
40639
|
setSkillsPlugin(config2) {
|
|
40193
40640
|
this.skillsPlugin = config2;
|
|
@@ -40383,6 +40830,12 @@ var init_agent_manager = __esm({
|
|
|
40383
40830
|
// never sent to in this daemon's life — is left ABSENT, which for a cron turn means 'safe':
|
|
40384
40831
|
// unanswerable prompts are declined rather than parked, and nothing is approved on anyone's behalf.
|
|
40385
40832
|
unattended: targetSessionId ? this.unattendedByConversation.get(targetSessionId) : cfg2.isUnattended?.(),
|
|
40833
|
+
// THE PERSON'S SETTINGS — their block rules, their always-ask rules, their hooks. A scheduled turn
|
|
40834
|
+
// carried NONE of them: a session this fire creates was built without the one layer that refuses
|
|
40835
|
+
// things, on the run nobody is watching. Read at fire time like the switches above, so a rule
|
|
40836
|
+
// written at 23:00 is in force at 03:00. (A conversation already live keeps the settings its
|
|
40837
|
+
// query was built with; this is what a cold or new one starts from.)
|
|
40838
|
+
settings: cfg2.settings?.(),
|
|
40386
40839
|
// Only for a conversation this fire is CREATING. Verification is per conversation and
|
|
40387
40840
|
// the machine-wide switch is merely the default a new one starts with, so stamping it
|
|
40388
40841
|
// onto an existing one overrode the choice the person made there — disarming a loop the
|
|
@@ -40449,7 +40902,7 @@ var init_agent_manager = __esm({
|
|
|
40449
40902
|
this.onBrowserRequest = onBrowserRequest;
|
|
40450
40903
|
const __dirname2 = dirname9(fileURLToPath(import.meta.url));
|
|
40451
40904
|
this.browserCliPath = join17(__dirname2, "browser-cli.js");
|
|
40452
|
-
this.narrator = new Narrator((sessionId,
|
|
40905
|
+
this.narrator = new Narrator((sessionId, text13, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text13, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
|
|
40453
40906
|
}
|
|
40454
40907
|
/** Inject (or clear) the cheap model used for the live status narration. The
|
|
40455
40908
|
* host resolves creds and builds the completion fn (keeping secrets host-side). */
|
|
@@ -40619,9 +41072,9 @@ var init_agent_manager = __esm({
|
|
|
40619
41072
|
const file2 = await resolveSessionFile(sid, live.cwd).catch(() => null);
|
|
40620
41073
|
if (!file2)
|
|
40621
41074
|
return false;
|
|
40622
|
-
let
|
|
41075
|
+
let text13;
|
|
40623
41076
|
try {
|
|
40624
|
-
|
|
41077
|
+
text13 = await readFile8(file2, "utf8");
|
|
40625
41078
|
} catch {
|
|
40626
41079
|
return false;
|
|
40627
41080
|
}
|
|
@@ -40629,7 +41082,7 @@ var init_agent_manager = __esm({
|
|
|
40629
41082
|
const v = leanReloadVerdict({
|
|
40630
41083
|
fillPct: usage2.percentage,
|
|
40631
41084
|
thresholdPct,
|
|
40632
|
-
leanBytes: contentBytes(
|
|
41085
|
+
leanBytes: contentBytes(text13),
|
|
40633
41086
|
strippedBytes: live.strippedContentBytes ?? 0
|
|
40634
41087
|
});
|
|
40635
41088
|
if (v.action === "skip") {
|
|
@@ -41584,7 +42037,7 @@ ${full.slice(-8e3)}`;
|
|
|
41584
42037
|
applyTurnPolicy(live, p) {
|
|
41585
42038
|
live.unattended = unattendedModeFor({ optedIn: p.unattended, origin: p.origin });
|
|
41586
42039
|
if (p.unattended !== void 0 && live.sessionId)
|
|
41587
|
-
this.
|
|
42040
|
+
this.rememberUnattended(live.sessionId, p.unattended);
|
|
41588
42041
|
if (p.autoCompactPct !== void 0)
|
|
41589
42042
|
live.autoCompactPct = p.autoCompactPct;
|
|
41590
42043
|
live.autoDecisions = 0;
|
|
@@ -41763,10 +42216,10 @@ ${full.slice(-8e3)}`;
|
|
|
41763
42216
|
parts.push(`The user's current request:
|
|
41764
42217
|
${live.lastPrompt.slice(0, 1400)}`);
|
|
41765
42218
|
if (Array.isArray(live.lastAssistantContent)) {
|
|
41766
|
-
const
|
|
41767
|
-
if (
|
|
42219
|
+
const text13 = live.lastAssistantContent.filter((b) => b?.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
|
|
42220
|
+
if (text13)
|
|
41768
42221
|
parts.push(`What the assistant just said (leading to this question):
|
|
41769
|
-
${
|
|
42222
|
+
${text13.slice(0, 1600)}`);
|
|
41770
42223
|
}
|
|
41771
42224
|
return parts.join("\n\n") || "No additional context available beyond the question itself.";
|
|
41772
42225
|
}
|
|
@@ -42310,9 +42763,9 @@ ${lines}`;
|
|
|
42310
42763
|
const transcripts = [];
|
|
42311
42764
|
for (const sid of sessionIds) {
|
|
42312
42765
|
const msgs = await this.sessionStore.getSessionMessages(sid).catch(() => []);
|
|
42313
|
-
const
|
|
42314
|
-
if (
|
|
42315
|
-
transcripts.push(
|
|
42766
|
+
const text13 = transcriptToText(msgs);
|
|
42767
|
+
if (text13)
|
|
42768
|
+
transcripts.push(text13);
|
|
42316
42769
|
}
|
|
42317
42770
|
if (transcripts.length === 0)
|
|
42318
42771
|
return;
|
|
@@ -43399,6 +43852,7 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43399
43852
|
if (this.computerControlProvider) {
|
|
43400
43853
|
mcp["tesseract-computer"] = createSdkMcpServer2({ name: "tesseract-computer", version: "0.1.0", tools: buildComputerControlSdkTools(this.computerControlProvider) });
|
|
43401
43854
|
}
|
|
43855
|
+
mcp["tesseract-capabilities"] = createSdkMcpServer2({ name: "tesseract-capabilities", version: "0.1.0", tools: buildCapabilitiesTools() });
|
|
43402
43856
|
if (this.appControlProvider) {
|
|
43403
43857
|
const appProvider = this.appControlProvider;
|
|
43404
43858
|
mcp["tesseract-app"] = createSdkMcpServer2({
|
|
@@ -43870,11 +44324,11 @@ ${prompt("agent.system.long-running")}`;
|
|
|
43870
44324
|
});
|
|
43871
44325
|
let errSeen = 0;
|
|
43872
44326
|
child.stderr?.on("data", (chunk) => {
|
|
43873
|
-
const
|
|
44327
|
+
const text13 = String(chunk);
|
|
43874
44328
|
if (errSeen >= 8e3)
|
|
43875
44329
|
return;
|
|
43876
|
-
errSeen +=
|
|
43877
|
-
for (const line of
|
|
44330
|
+
errSeen += text13.length;
|
|
44331
|
+
for (const line of text13.split("\n")) {
|
|
43878
44332
|
const t = line.trim();
|
|
43879
44333
|
if (!t)
|
|
43880
44334
|
continue;
|
|
@@ -44153,9 +44607,9 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44153
44607
|
emit2({ type: "chat:stream", sessionId: sid, delta: "[thinking redacted]", messageId: message.uuid, kind: "thinking", ...parentField });
|
|
44154
44608
|
} else if (cbt === "advisor_tool_result") {
|
|
44155
44609
|
const res = event.content_block.content;
|
|
44156
|
-
const
|
|
44157
|
-
if (
|
|
44158
|
-
emit2({ type: "agent:advisor", sessionId: sid, text:
|
|
44610
|
+
const text13 = res?.type === "advisor_result" ? (res.text ?? "").trim() : "";
|
|
44611
|
+
if (text13 && parentToolUseId === void 0)
|
|
44612
|
+
emit2({ type: "agent:advisor", sessionId: sid, text: text13 });
|
|
44159
44613
|
}
|
|
44160
44614
|
}
|
|
44161
44615
|
if (event.type === "content_block_delta") {
|
|
@@ -44170,26 +44624,26 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44170
44624
|
}
|
|
44171
44625
|
}
|
|
44172
44626
|
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(
|
|
44627
|
+
const text13 = event.delta.text;
|
|
44628
|
+
if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text13)) {
|
|
44175
44629
|
insideXmlByKey.set(key2, true);
|
|
44176
44630
|
break;
|
|
44177
44631
|
}
|
|
44178
44632
|
if (insideXmlByKey.get(key2)) {
|
|
44179
|
-
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(
|
|
44633
|
+
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text13)) {
|
|
44180
44634
|
insideXmlByKey.set(key2, false);
|
|
44181
44635
|
}
|
|
44182
44636
|
break;
|
|
44183
44637
|
}
|
|
44184
|
-
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(
|
|
44638
|
+
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text13))
|
|
44185
44639
|
break;
|
|
44186
|
-
if (/<parameter\s+name=/.test(
|
|
44640
|
+
if (/<parameter\s+name=/.test(text13))
|
|
44187
44641
|
break;
|
|
44188
|
-
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(
|
|
44642
|
+
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text13))
|
|
44189
44643
|
break;
|
|
44190
44644
|
if (parentToolUseId === void 0)
|
|
44191
44645
|
turnStreamed = true;
|
|
44192
|
-
const d = this.applyDeltaHook(
|
|
44646
|
+
const d = this.applyDeltaHook(text13, "text", sid);
|
|
44193
44647
|
if (d !== null)
|
|
44194
44648
|
emit2({ type: "chat:stream", sessionId: sid, delta: d, messageId: message.uuid, kind: "text", ...parentField });
|
|
44195
44649
|
}
|
|
@@ -44257,10 +44711,8 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44257
44711
|
live.sessionId = next;
|
|
44258
44712
|
this.rememberSessionModel(next, live.model);
|
|
44259
44713
|
this.liveSessions.set(next, live);
|
|
44260
|
-
|
|
44261
|
-
|
|
44262
|
-
this.cronTaskSessions.set(taskId, next);
|
|
44263
|
-
}
|
|
44714
|
+
if (prev)
|
|
44715
|
+
this.carryConversationTo(prev, next);
|
|
44264
44716
|
this.send({ type: "session:created", sessionId: next, clientRequestId: live.clientRequestId }, live.origin);
|
|
44265
44717
|
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
44718
|
break;
|
|
@@ -44310,7 +44762,9 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44310
44762
|
...typeof uc?.output_tokens === "number" ? { outputTokens: uc.output_tokens } : {}
|
|
44311
44763
|
});
|
|
44312
44764
|
}
|
|
44313
|
-
const
|
|
44765
|
+
const limitFromReply = r.subtype === "success" ? assistantUsageLimitFallback(live.lastAssistantContent) : void 0;
|
|
44766
|
+
const turnAnswered = r.subtype === "success" && r.is_error !== true && !limitFromReply;
|
|
44767
|
+
const limitRejection = turnAnswered ? void 0 : live.usageLimitRejection ?? limitFromReply;
|
|
44314
44768
|
const resultText = typeof r.result === "string" ? r.result : "";
|
|
44315
44769
|
const textOverflow = r.is_error === true && isContextOverflow(resultText) || live.lastAssistantSynthetic === true && assistantContextOverflow(live.lastAssistantContent, isContextOverflow);
|
|
44316
44770
|
const apiFailure = textOverflow ? null : classifyEngineApiError(resultText);
|
|
@@ -44780,6 +45234,10 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44780
45234
|
});
|
|
44781
45235
|
}
|
|
44782
45236
|
}
|
|
45237
|
+
if (live.usageLimitRejection && am.message?.model !== "<synthetic>" && providerIsServing(am.message?.content)) {
|
|
45238
|
+
log("Usage limit cleared by a reply that followed it:", sid);
|
|
45239
|
+
live.usageLimitRejection = void 0;
|
|
45240
|
+
}
|
|
44783
45241
|
if (am.uuid && parentToolUseId === void 0) {
|
|
44784
45242
|
live.lastAssistantUuid = am.uuid;
|
|
44785
45243
|
live.lastAssistantContent = am.message?.content;
|
|
@@ -44824,20 +45282,20 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44824
45282
|
const tn = toolNameByUseId.get(toolUseId);
|
|
44825
45283
|
if (tn === "Edit" || tn === "Write" || tn === "MultiEdit" || tn === "NotebookEdit")
|
|
44826
45284
|
continue;
|
|
44827
|
-
const { text:
|
|
45285
|
+
const { text: text13, truncated } = flattenToolResultContent(blk.content);
|
|
44828
45286
|
const images = extractImages(blk.content);
|
|
44829
45287
|
const isError = blk.is_error === true;
|
|
44830
|
-
if (!
|
|
45288
|
+
if (!text13 && images.length === 0 && !isError)
|
|
44831
45289
|
continue;
|
|
44832
|
-
emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output:
|
|
44833
|
-
const bg = parseBackgroundTaskResult(
|
|
45290
|
+
emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text13, images, truncated, ...agentId ? { agentId } : {} });
|
|
45291
|
+
const bg = parseBackgroundTaskResult(text13);
|
|
44834
45292
|
if (bg && !agentId) {
|
|
44835
45293
|
live.taskToolUse.set(bg.taskId, toolUseId);
|
|
44836
45294
|
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
45295
|
this.startTaskTail(live, bg.taskId, bg.outputPath, toolUseId);
|
|
44838
45296
|
}
|
|
44839
45297
|
if (isError && !agentId) {
|
|
44840
|
-
const why = (
|
|
45298
|
+
const why = (text13 || "").replace(/```[\s\S]*?```/g, " ").replace(/[`*]/g, "").replace(/\s+/g, " ").trim().slice(0, 160);
|
|
44841
45299
|
this.narrator.observe(sid, `\u2192 that didn't work${why ? `: ${why}` : ""}`);
|
|
44842
45300
|
}
|
|
44843
45301
|
} else if (blk?.type === "web_search_tool_result") {
|
|
@@ -44869,12 +45327,12 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
44869
45327
|
}
|
|
44870
45328
|
default: {
|
|
44871
45329
|
const m = message;
|
|
44872
|
-
const
|
|
45330
|
+
const text13 = extractHumanReadable(m);
|
|
44873
45331
|
emitEvent({
|
|
44874
45332
|
category: "unknown",
|
|
44875
45333
|
name: m.type || "unknown",
|
|
44876
45334
|
title: m.type || "unknown frame",
|
|
44877
|
-
...
|
|
45335
|
+
...text13 ? { detail: text13 } : {},
|
|
44878
45336
|
raw: rawFramePreview(m)
|
|
44879
45337
|
}, parentToolUseId);
|
|
44880
45338
|
log("unknown SDK message type surfaced with raw data:", m.type || "?");
|
|
@@ -46208,11 +46666,11 @@ Element ${i + 1}:`);
|
|
|
46208
46666
|
});
|
|
46209
46667
|
|
|
46210
46668
|
// ../../packages/agent-core/dist/present-tools.js
|
|
46211
|
-
import { tool as
|
|
46669
|
+
import { tool as tool21 } from "@anthropic-ai/claude-agent-sdk";
|
|
46212
46670
|
function buildPresentSdkTools(p) {
|
|
46213
|
-
return PRESENT_TOOL_SPECS.map((spec) =>
|
|
46214
|
-
const
|
|
46215
|
-
return { content: [{ type: "text", text:
|
|
46671
|
+
return PRESENT_TOOL_SPECS.map((spec) => tool21(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
|
|
46672
|
+
const text13 = await p.exec(spec.name, args ?? {});
|
|
46673
|
+
return { content: [{ type: "text", text: text13 || "Done." }] };
|
|
46216
46674
|
}));
|
|
46217
46675
|
}
|
|
46218
46676
|
function buildPresentPrompt(opts) {
|
|
@@ -46325,6 +46783,7 @@ __export(dist_exports2, {
|
|
|
46325
46783
|
APP_CONTROL_DOMAINS: () => APP_CONTROL_DOMAINS,
|
|
46326
46784
|
APP_CONTROL_GENERATED_MARKER: () => APP_CONTROL_GENERATED_MARKER,
|
|
46327
46785
|
AgentManager: () => AgentManager,
|
|
46786
|
+
CAPABILITIES_DOC: () => CAPABILITIES_DOC,
|
|
46328
46787
|
DEFAULT_OFFLOAD_RECENT_CALLS: () => DEFAULT_OFFLOAD_RECENT_CALLS,
|
|
46329
46788
|
DESIGN_CLAUDE_MD: () => DESIGN_CLAUDE_MD,
|
|
46330
46789
|
DESIGN_DIR: () => DESIGN_DIR,
|
|
@@ -46357,6 +46816,7 @@ __export(dist_exports2, {
|
|
|
46357
46816
|
archivePathFor: () => archivePathFor,
|
|
46358
46817
|
autoCompactEnvFor: () => autoCompactEnvFor,
|
|
46359
46818
|
buildAppControlTools: () => buildAppControlTools,
|
|
46819
|
+
buildCapabilitiesTools: () => buildCapabilitiesTools,
|
|
46360
46820
|
buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
|
|
46361
46821
|
buildClaudeSmartLlm: () => buildClaudeSmartLlm,
|
|
46362
46822
|
buildClaudeVisionLlm: () => buildClaudeVisionLlm,
|
|
@@ -46374,6 +46834,7 @@ __export(dist_exports2, {
|
|
|
46374
46834
|
bumpVersion: () => bumpVersion,
|
|
46375
46835
|
capabilitiesByDomain: () => capabilitiesByDomain,
|
|
46376
46836
|
capabilityById: () => capabilityById,
|
|
46837
|
+
capabilitySections: () => capabilitySections,
|
|
46377
46838
|
computerControlSpecs: () => computerControlSpecs,
|
|
46378
46839
|
computerOperatorPrompt: () => computerOperatorPrompt,
|
|
46379
46840
|
computerSpecParametersJsonSchema: () => computerSpecParametersJsonSchema,
|
|
@@ -46385,6 +46846,7 @@ __export(dist_exports2, {
|
|
|
46385
46846
|
engineMessageTokens: () => engineMessageTokens,
|
|
46386
46847
|
exportSession: () => exportSession,
|
|
46387
46848
|
filterHistory: () => filterHistory,
|
|
46849
|
+
findSections: () => findSections,
|
|
46388
46850
|
flattenForDisplay: () => flattenForDisplay,
|
|
46389
46851
|
getModelCatalog: () => getModelCatalog,
|
|
46390
46852
|
getTokenPath: () => getTokenPath,
|
|
@@ -46478,6 +46940,8 @@ var init_dist5 = __esm({
|
|
|
46478
46940
|
init_present_tools();
|
|
46479
46941
|
init_computer_control_tools();
|
|
46480
46942
|
init_support_tools();
|
|
46943
|
+
init_capabilities_tools();
|
|
46944
|
+
init_capabilities_doc_generated();
|
|
46481
46945
|
init_app_control_tools();
|
|
46482
46946
|
init_registry();
|
|
46483
46947
|
init_docs2();
|
|
@@ -47590,9 +48054,9 @@ function rememberedPath(engineId) {
|
|
|
47590
48054
|
}
|
|
47591
48055
|
}
|
|
47592
48056
|
function which(bin, path6) {
|
|
47593
|
-
const
|
|
48057
|
+
const tool22 = process.platform === "win32" ? "where" : "which";
|
|
47594
48058
|
try {
|
|
47595
|
-
const out = execFileSync2(
|
|
48059
|
+
const out = execFileSync2(tool22, [bin], { env: { ...process.env, PATH: path6 }, timeout: 4e3, encoding: "utf-8" });
|
|
47596
48060
|
return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
|
|
47597
48061
|
} catch {
|
|
47598
48062
|
return void 0;
|
|
@@ -47864,9 +48328,9 @@ function readBody2(req, limitBytes = 4 * 1024 * 1024) {
|
|
|
47864
48328
|
});
|
|
47865
48329
|
}
|
|
47866
48330
|
function send2(res, code, body, headers = {}) {
|
|
47867
|
-
const
|
|
47868
|
-
res.writeHead(code, { "content-type": "application/json", "content-length": Buffer.byteLength(
|
|
47869
|
-
res.end(
|
|
48331
|
+
const text13 = JSON.stringify(body);
|
|
48332
|
+
res.writeHead(code, { "content-type": "application/json", "content-length": Buffer.byteLength(text13), ...headers });
|
|
48333
|
+
res.end(text13);
|
|
47870
48334
|
}
|
|
47871
48335
|
function portFile() {
|
|
47872
48336
|
return join28(daemonDir2(), "mcp-endpoint.json");
|
|
@@ -47939,13 +48403,13 @@ async function startTesseractMcpEndpoint() {
|
|
|
47939
48403
|
return;
|
|
47940
48404
|
case "tools/call": {
|
|
47941
48405
|
const name = String(msg.params?.name ?? "");
|
|
47942
|
-
const
|
|
47943
|
-
if (!
|
|
48406
|
+
const tool22 = byName.get(name);
|
|
48407
|
+
if (!tool22) {
|
|
47944
48408
|
fail4(-32602, `Unknown tool "${name}"`);
|
|
47945
48409
|
return;
|
|
47946
48410
|
}
|
|
47947
48411
|
try {
|
|
47948
|
-
const out = await
|
|
48412
|
+
const out = await tool22.handler(msg.params?.arguments ?? {}, { sessionId: grant?.sessionId, nested: grant?.extensionId === NESTED_HOLDER });
|
|
47949
48413
|
reply3({ content: out.content, ...out.isError ? { isError: true } : {} });
|
|
47950
48414
|
} catch (e) {
|
|
47951
48415
|
reply3({ content: [{ type: "text", text: `${name} failed: ${e instanceof Error ? e.message : String(e)}` }], isError: true });
|
|
@@ -48099,11 +48563,11 @@ function wrapHostedAsyncTool(t, opts) {
|
|
|
48099
48563
|
}
|
|
48100
48564
|
if (raced.kind === "done") {
|
|
48101
48565
|
callEnded();
|
|
48102
|
-
return
|
|
48566
|
+
return text12(raced.out);
|
|
48103
48567
|
}
|
|
48104
48568
|
if (raced.kind === "error") {
|
|
48105
48569
|
callEnded();
|
|
48106
|
-
return
|
|
48570
|
+
return text12(raced.err instanceof Error ? raced.err.message : String(raced.err), true);
|
|
48107
48571
|
}
|
|
48108
48572
|
opts.learnedSlow?.add(t.name);
|
|
48109
48573
|
const sessionId = ctx2?.sessionId;
|
|
@@ -48116,7 +48580,7 @@ function wrapHostedAsyncTool(t, opts) {
|
|
|
48116
48580
|
});
|
|
48117
48581
|
opts.noteSession?.(job.id, sessionId, claim);
|
|
48118
48582
|
callEnded();
|
|
48119
|
-
return
|
|
48583
|
+
return text12([
|
|
48120
48584
|
`Started in the background: job \`${job.id}\`.`,
|
|
48121
48585
|
`Live output: ${job.logPath}`,
|
|
48122
48586
|
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 +48617,12 @@ function buildHostedJobTools(registry3, opts = {}) {
|
|
|
48153
48617
|
handler: async (args, ctx2) => {
|
|
48154
48618
|
const ids = Array.isArray(args["job_ids"]) ? args["job_ids"].map(String) : [];
|
|
48155
48619
|
if (ids.length === 0)
|
|
48156
|
-
return
|
|
48620
|
+
return text12("await_jobs needs at least one job id.", true);
|
|
48157
48621
|
const unknown2 = ids.filter((id) => !registry3.list().some((j) => j.id === id) || !mine(id, ctx2?.sessionId));
|
|
48158
48622
|
if (unknown2.length)
|
|
48159
|
-
return
|
|
48623
|
+
return text12(`no such job: ${unknown2.join(", ")}`, true);
|
|
48160
48624
|
const jobs = await registry3.await(ids, typeof args["timeout_ms"] === "number" ? args["timeout_ms"] : 12e4);
|
|
48161
|
-
return
|
|
48625
|
+
return text12(jobs.map((j) => `${fmt(j)}
|
|
48162
48626
|
${registry3.output(j.id) || "(no output)"}`).join("\n\n"));
|
|
48163
48627
|
}
|
|
48164
48628
|
},
|
|
@@ -48179,10 +48643,10 @@ ${registry3.output(j.id) || "(no output)"}`).join("\n\n"));
|
|
|
48179
48643
|
const id = String(args["job_id"] ?? "");
|
|
48180
48644
|
const job = registry3.list().find((j) => j.id === id);
|
|
48181
48645
|
if (!job || !mine(id, ctx2?.sessionId))
|
|
48182
|
-
return
|
|
48646
|
+
return text12(`no such job: ${id}`, true);
|
|
48183
48647
|
const from = typeof args["from_offset"] === "number" ? args["from_offset"] : 0;
|
|
48184
48648
|
const out = registry3.output(id, from);
|
|
48185
|
-
return
|
|
48649
|
+
return text12(`${fmt(job)}
|
|
48186
48650
|
${out || "(nothing yet)"}`);
|
|
48187
48651
|
}
|
|
48188
48652
|
},
|
|
@@ -48193,7 +48657,7 @@ ${out || "(nothing yet)"}`);
|
|
|
48193
48657
|
annotations: { readOnlyHint: true },
|
|
48194
48658
|
handler: async (_args, ctx2) => {
|
|
48195
48659
|
const jobs = registry3.list().filter((j) => mine(j.id, ctx2?.sessionId)).sort((a, b) => Number(b.status === "running") - Number(a.status === "running"));
|
|
48196
|
-
return
|
|
48660
|
+
return text12(jobs.length ? jobs.map(fmt).join("\n\n") : "no jobs.");
|
|
48197
48661
|
}
|
|
48198
48662
|
},
|
|
48199
48663
|
{
|
|
@@ -48203,8 +48667,8 @@ ${out || "(nothing yet)"}`);
|
|
|
48203
48667
|
handler: async (args, ctx2) => {
|
|
48204
48668
|
const id = String(args["job_id"] ?? "");
|
|
48205
48669
|
if (!mine(id, ctx2?.sessionId))
|
|
48206
|
-
return
|
|
48207
|
-
return
|
|
48670
|
+
return text12(`job ${id} was not running.`);
|
|
48671
|
+
return text12(registry3.stop(id) ? `stopped job ${id}.` : `job ${id} was not running.`);
|
|
48208
48672
|
}
|
|
48209
48673
|
}
|
|
48210
48674
|
];
|
|
@@ -48435,12 +48899,12 @@ function createNoticeDispatcher(opts) {
|
|
|
48435
48899
|
}
|
|
48436
48900
|
};
|
|
48437
48901
|
}
|
|
48438
|
-
var
|
|
48902
|
+
var text12, NEVER_ASYNC;
|
|
48439
48903
|
var init_hosted_jobs = __esm({
|
|
48440
48904
|
"../../packages/host-core/dist/engines/hosted-jobs.js"() {
|
|
48441
48905
|
"use strict";
|
|
48442
48906
|
init_jobs();
|
|
48443
|
-
|
|
48907
|
+
text12 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
48444
48908
|
NEVER_ASYNC = /* @__PURE__ */ new Set(["await_jobs", "job_output", "job_list", "stop_job"]);
|
|
48445
48909
|
}
|
|
48446
48910
|
});
|
|
@@ -48719,7 +49183,7 @@ async function startHostedToolset(deps) {
|
|
|
48719
49183
|
return { endpoint: endpoint2, sendBrowserResponse, tasks, ...stopOwnedJob ? { stopJob: stopOwnedJob } : {}, ...rekeyOwnedJobs ? { rekeyJobs: rekeyOwnedJobs } : {}, ...jobProbe ? { jobProbe } : {}, refresh: build };
|
|
48720
49184
|
}
|
|
48721
49185
|
function buildHostTaskTools(registry3, run9) {
|
|
48722
|
-
const
|
|
49186
|
+
const text13 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
48723
49187
|
return [
|
|
48724
49188
|
{
|
|
48725
49189
|
name: "tesseract_spawn_subagent",
|
|
@@ -48736,25 +49200,25 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48736
49200
|
const description = String(args.description ?? "sub-task");
|
|
48737
49201
|
const prompt2 = String(args.prompt ?? "");
|
|
48738
49202
|
if (!prompt2.trim())
|
|
48739
|
-
return
|
|
49203
|
+
return text13("prompt is required", true);
|
|
48740
49204
|
if (ctx2?.nested) {
|
|
48741
|
-
return
|
|
49205
|
+
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
49206
|
}
|
|
48743
49207
|
const task = registry3.start("subagent", description);
|
|
48744
49208
|
task.messages.push({ role: "user", content: prompt2 });
|
|
48745
49209
|
try {
|
|
48746
49210
|
const out = await run9(prompt2, { signal: task.abort.signal, sessionId: ctx2?.sessionId });
|
|
48747
49211
|
if (task.status === "stopped")
|
|
48748
|
-
return
|
|
49212
|
+
return text13(`Subagent "${description}" was stopped.`, true);
|
|
48749
49213
|
task.status = "done";
|
|
48750
49214
|
task.result = out;
|
|
48751
49215
|
task.messages.push({ role: "assistant", content: out });
|
|
48752
|
-
return
|
|
49216
|
+
return text13(out || "(the subagent returned nothing)");
|
|
48753
49217
|
} catch (e) {
|
|
48754
49218
|
task.status = task.status === "stopped" ? "stopped" : "failed";
|
|
48755
49219
|
const why = e instanceof Error ? e.message : String(e);
|
|
48756
49220
|
task.result = why;
|
|
48757
|
-
return
|
|
49221
|
+
return text13(`Subagent "${description}" failed: ${why}`, true);
|
|
48758
49222
|
}
|
|
48759
49223
|
}
|
|
48760
49224
|
},
|
|
@@ -48765,8 +49229,8 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48765
49229
|
handler: async () => {
|
|
48766
49230
|
const rows = registry3.list();
|
|
48767
49231
|
if (!rows.length)
|
|
48768
|
-
return
|
|
48769
|
-
return
|
|
49232
|
+
return text13("No sub-tasks have been started.");
|
|
49233
|
+
return text13(rows.map((t) => `${t.id} ${t.status.padEnd(7)} ${t.description}`).join("\n"));
|
|
48770
49234
|
}
|
|
48771
49235
|
},
|
|
48772
49236
|
{
|
|
@@ -48779,7 +49243,7 @@ function buildHostTaskTools(registry3, run9) {
|
|
|
48779
49243
|
},
|
|
48780
49244
|
handler: async (args) => {
|
|
48781
49245
|
const id = String(args.taskId ?? "");
|
|
48782
|
-
return registry3.stop(id) ?
|
|
49246
|
+
return registry3.stop(id) ? text13(`Stopped ${id}.`) : text13(`${id} is not a running task (unknown, or already finished).`, true);
|
|
48783
49247
|
}
|
|
48784
49248
|
}
|
|
48785
49249
|
];
|
|
@@ -54120,24 +54584,24 @@ var require_text2 = __commonJS({
|
|
|
54120
54584
|
}
|
|
54121
54585
|
}
|
|
54122
54586
|
var latin1Regex = /^[\u0000-\u00FF]*$/;
|
|
54123
|
-
function validateLatin1(
|
|
54124
|
-
if (!latin1Regex.test(
|
|
54587
|
+
function validateLatin1(text13) {
|
|
54588
|
+
if (!latin1Regex.test(text13)) {
|
|
54125
54589
|
throw new Error("invalid latin1 text");
|
|
54126
54590
|
}
|
|
54127
54591
|
}
|
|
54128
|
-
function decodetEXt(
|
|
54592
|
+
function decodetEXt(text13, buffer, length) {
|
|
54129
54593
|
const keyword = readKeyword(buffer);
|
|
54130
|
-
|
|
54594
|
+
text13[keyword] = readLatin1(buffer, length - keyword.length - 1);
|
|
54131
54595
|
}
|
|
54132
|
-
function encodetEXt(buffer, keyword,
|
|
54596
|
+
function encodetEXt(buffer, keyword, text13) {
|
|
54133
54597
|
validateKeyword(keyword);
|
|
54134
|
-
validateLatin1(
|
|
54135
|
-
const length = keyword.length + 1 +
|
|
54598
|
+
validateLatin1(text13);
|
|
54599
|
+
const length = keyword.length + 1 + text13.length;
|
|
54136
54600
|
buffer.writeUint32(length);
|
|
54137
54601
|
buffer.writeChars(exports.textChunkName);
|
|
54138
54602
|
buffer.writeChars(keyword);
|
|
54139
54603
|
buffer.writeByte(NULL);
|
|
54140
|
-
buffer.writeChars(
|
|
54604
|
+
buffer.writeChars(text13);
|
|
54141
54605
|
(0, crc_1.writeCrc)(buffer, length + 4);
|
|
54142
54606
|
}
|
|
54143
54607
|
function readKeyword(buffer) {
|
|
@@ -54721,8 +55185,8 @@ var require_PngEncoder = __commonJS({
|
|
|
54721
55185
|
}
|
|
54722
55186
|
this.encodeData();
|
|
54723
55187
|
if (this._png.text) {
|
|
54724
|
-
for (const [keyword,
|
|
54725
|
-
(0, text_1.encodetEXt)(this, keyword,
|
|
55188
|
+
for (const [keyword, text13] of Object.entries(this._png.text)) {
|
|
55189
|
+
(0, text_1.encodetEXt)(this, keyword, text13);
|
|
54726
55190
|
}
|
|
54727
55191
|
}
|
|
54728
55192
|
this.encodeIEND();
|
|
@@ -58908,8 +59372,8 @@ var require_build = __commonJS({
|
|
|
58908
59372
|
var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
58909
59373
|
var BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
|
|
58910
59374
|
var Utf8Converter = class {
|
|
58911
|
-
static fromString(
|
|
58912
|
-
const s = unescape(encodeURIComponent(
|
|
59375
|
+
static fromString(text13) {
|
|
59376
|
+
const s = unescape(encodeURIComponent(text13));
|
|
58913
59377
|
const uintArray = new Uint8Array(s.length);
|
|
58914
59378
|
for (let i = 0; i < s.length; i++) {
|
|
58915
59379
|
uintArray[i] = s.charCodeAt(i);
|
|
@@ -58937,11 +59401,11 @@ var require_build = __commonJS({
|
|
|
58937
59401
|
}
|
|
58938
59402
|
return res;
|
|
58939
59403
|
}
|
|
58940
|
-
static fromString(
|
|
58941
|
-
const res = new ArrayBuffer(
|
|
59404
|
+
static fromString(text13, littleEndian = false) {
|
|
59405
|
+
const res = new ArrayBuffer(text13.length * 2);
|
|
58942
59406
|
const dataView = new DataView(res);
|
|
58943
|
-
for (let i = 0; i <
|
|
58944
|
-
dataView.setUint16(i * 2,
|
|
59407
|
+
for (let i = 0; i < text13.length; i++) {
|
|
59408
|
+
dataView.setUint16(i * 2, text13.charCodeAt(i), littleEndian);
|
|
58945
59409
|
}
|
|
58946
59410
|
return res;
|
|
58947
59411
|
}
|
|
@@ -59038,18 +59502,18 @@ var require_build = __commonJS({
|
|
|
59038
59502
|
static ToBase64Url(data) {
|
|
59039
59503
|
return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
|
|
59040
59504
|
}
|
|
59041
|
-
static FromUtf8String(
|
|
59505
|
+
static FromUtf8String(text13, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
|
|
59042
59506
|
switch (encoding) {
|
|
59043
59507
|
case "ascii":
|
|
59044
|
-
return this.FromBinary(
|
|
59508
|
+
return this.FromBinary(text13);
|
|
59045
59509
|
case "utf8":
|
|
59046
|
-
return Utf8Converter.fromString(
|
|
59510
|
+
return Utf8Converter.fromString(text13);
|
|
59047
59511
|
case "utf16":
|
|
59048
59512
|
case "utf16be":
|
|
59049
|
-
return Utf16Converter.fromString(
|
|
59513
|
+
return Utf16Converter.fromString(text13);
|
|
59050
59514
|
case "utf16le":
|
|
59051
59515
|
case "usc2":
|
|
59052
|
-
return Utf16Converter.fromString(
|
|
59516
|
+
return Utf16Converter.fromString(text13, true);
|
|
59053
59517
|
default:
|
|
59054
59518
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
59055
59519
|
}
|
|
@@ -59070,11 +59534,11 @@ var require_build = __commonJS({
|
|
|
59070
59534
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
59071
59535
|
}
|
|
59072
59536
|
}
|
|
59073
|
-
static FromBinary(
|
|
59074
|
-
const stringLength =
|
|
59537
|
+
static FromBinary(text13) {
|
|
59538
|
+
const stringLength = text13.length;
|
|
59075
59539
|
const resultView = new Uint8Array(stringLength);
|
|
59076
59540
|
for (let i = 0; i < stringLength; i++) {
|
|
59077
|
-
resultView[i] =
|
|
59541
|
+
resultView[i] = text13.charCodeAt(i);
|
|
59078
59542
|
}
|
|
59079
59543
|
return resultView.buffer;
|
|
59080
59544
|
}
|
|
@@ -59120,8 +59584,8 @@ var require_build = __commonJS({
|
|
|
59120
59584
|
static ToUtf16String(buffer, littleEndian = false) {
|
|
59121
59585
|
return Utf16Converter.toString(buffer, littleEndian);
|
|
59122
59586
|
}
|
|
59123
|
-
static FromUtf16String(
|
|
59124
|
-
return Utf16Converter.fromString(
|
|
59587
|
+
static FromUtf16String(text13, littleEndian = false) {
|
|
59588
|
+
return Utf16Converter.fromString(text13, littleEndian);
|
|
59125
59589
|
}
|
|
59126
59590
|
static Base64Padding(base643) {
|
|
59127
59591
|
const padCount = 4 - base643.length % 4;
|
|
@@ -62882,15 +63346,15 @@ var require_sequence = __commonJS({
|
|
|
62882
63346
|
}
|
|
62883
63347
|
return normalized;
|
|
62884
63348
|
}
|
|
62885
|
-
function encodeAscii(
|
|
62886
|
-
const bytes3 = new Uint8Array(
|
|
62887
|
-
for (let i = 0; i <
|
|
62888
|
-
bytes3[i] =
|
|
63349
|
+
function encodeAscii(text13) {
|
|
63350
|
+
const bytes3 = new Uint8Array(text13.length);
|
|
63351
|
+
for (let i = 0; i < text13.length; i++) {
|
|
63352
|
+
bytes3[i] = text13.charCodeAt(i) & 255;
|
|
62889
63353
|
}
|
|
62890
63354
|
return bytes3;
|
|
62891
63355
|
}
|
|
62892
|
-
function encodeUtf8(
|
|
62893
|
-
return new TextEncoder().encode(
|
|
63356
|
+
function encodeUtf8(text13) {
|
|
63357
|
+
return new TextEncoder().encode(text13);
|
|
62894
63358
|
}
|
|
62895
63359
|
function toPatternBytes(pattern, options) {
|
|
62896
63360
|
if (typeof pattern === "string") {
|
|
@@ -64265,15 +64729,15 @@ var require_binary = __commonJS({
|
|
|
64265
64729
|
}
|
|
64266
64730
|
return result;
|
|
64267
64731
|
}
|
|
64268
|
-
function decode3(
|
|
64269
|
-
const result = new Uint8Array(
|
|
64270
|
-
for (let i = 0; i <
|
|
64271
|
-
result[i] =
|
|
64732
|
+
function decode3(text13) {
|
|
64733
|
+
const result = new Uint8Array(text13.length);
|
|
64734
|
+
for (let i = 0; i < text13.length; i++) {
|
|
64735
|
+
result[i] = text13.charCodeAt(i) & 255;
|
|
64272
64736
|
}
|
|
64273
64737
|
return result;
|
|
64274
64738
|
}
|
|
64275
|
-
function is(
|
|
64276
|
-
return typeof
|
|
64739
|
+
function is(text13) {
|
|
64740
|
+
return typeof text13 === "string";
|
|
64277
64741
|
}
|
|
64278
64742
|
exports.binary = { encode: encode3, decode: decode3, is };
|
|
64279
64743
|
}
|
|
@@ -64308,31 +64772,31 @@ var require_hex = __commonJS({
|
|
|
64308
64772
|
throw new TypeError("Hex separators must be non-empty strings");
|
|
64309
64773
|
}
|
|
64310
64774
|
}
|
|
64311
|
-
function matchSeparator(
|
|
64775
|
+
function matchSeparator(text13, index, separators) {
|
|
64312
64776
|
for (const separator of separators) {
|
|
64313
|
-
if (
|
|
64777
|
+
if (text13.startsWith(separator, index)) {
|
|
64314
64778
|
return separator;
|
|
64315
64779
|
}
|
|
64316
64780
|
}
|
|
64317
64781
|
return void 0;
|
|
64318
64782
|
}
|
|
64319
|
-
function detectCase(
|
|
64320
|
-
const hasUpper = /[A-F]/.test(
|
|
64321
|
-
const hasLower = /[a-f]/.test(
|
|
64783
|
+
function detectCase(text13) {
|
|
64784
|
+
const hasUpper = /[A-F]/.test(text13);
|
|
64785
|
+
const hasLower = /[a-f]/.test(text13);
|
|
64322
64786
|
return hasUpper && !hasLower ? "upper" : "lower";
|
|
64323
64787
|
}
|
|
64324
|
-
function detectLineSeparator(
|
|
64325
|
-
const match = /\r\n|\n/.exec(
|
|
64788
|
+
function detectLineSeparator(text13) {
|
|
64789
|
+
const match = /\r\n|\n/.exec(text13);
|
|
64326
64790
|
if (!match) {
|
|
64327
64791
|
return void 0;
|
|
64328
64792
|
}
|
|
64329
64793
|
return match[0] === "\r\n" ? "\r\n" : "\n";
|
|
64330
64794
|
}
|
|
64331
|
-
function compactForDetection(
|
|
64332
|
-
return
|
|
64795
|
+
function compactForDetection(text13) {
|
|
64796
|
+
return text13.replace(/[^0-9a-f]/gi, "");
|
|
64333
64797
|
}
|
|
64334
|
-
function detectGroup(
|
|
64335
|
-
const segments =
|
|
64798
|
+
function detectGroup(text13) {
|
|
64799
|
+
const segments = text13.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
|
|
64336
64800
|
if (segments.length < 3) {
|
|
64337
64801
|
return void 0;
|
|
64338
64802
|
}
|
|
@@ -64360,8 +64824,8 @@ var require_hex = __commonJS({
|
|
|
64360
64824
|
separator
|
|
64361
64825
|
};
|
|
64362
64826
|
}
|
|
64363
|
-
function detectFormat(
|
|
64364
|
-
const trimmed =
|
|
64827
|
+
function detectFormat(text13) {
|
|
64828
|
+
const trimmed = text13.trim();
|
|
64365
64829
|
const prefix = /^0x/i.test(trimmed) ? "0x" : "";
|
|
64366
64830
|
const body = prefix ? trimmed.slice(2) : trimmed;
|
|
64367
64831
|
const lineSeparator = detectLineSeparator(body);
|
|
@@ -64386,13 +64850,13 @@ var require_hex = __commonJS({
|
|
|
64386
64850
|
}
|
|
64387
64851
|
return format2;
|
|
64388
64852
|
}
|
|
64389
|
-
function normalizeText(
|
|
64853
|
+
function normalizeText(text13, options) {
|
|
64390
64854
|
const allowPrefix = options.allowPrefix ?? true;
|
|
64391
64855
|
const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
|
|
64392
64856
|
for (const separator of separators) {
|
|
64393
64857
|
validateSeparator(separator);
|
|
64394
64858
|
}
|
|
64395
|
-
let working =
|
|
64859
|
+
let working = text13.trim();
|
|
64396
64860
|
if (/^0x/i.test(working)) {
|
|
64397
64861
|
if (!allowPrefix) {
|
|
64398
64862
|
throw new TypeError("Hexadecimal text must not include a 0x prefix");
|
|
@@ -64443,15 +64907,15 @@ var require_hex = __commonJS({
|
|
|
64443
64907
|
}
|
|
64444
64908
|
return chunks.join(group.separator);
|
|
64445
64909
|
}
|
|
64446
|
-
function normalize3(
|
|
64447
|
-
return normalizeText(
|
|
64910
|
+
function normalize3(text13, options = {}) {
|
|
64911
|
+
return normalizeText(text13, options);
|
|
64448
64912
|
}
|
|
64449
|
-
function is(
|
|
64450
|
-
if (typeof
|
|
64913
|
+
function is(text13, options = {}) {
|
|
64914
|
+
if (typeof text13 !== "string") {
|
|
64451
64915
|
return false;
|
|
64452
64916
|
}
|
|
64453
64917
|
try {
|
|
64454
|
-
normalize3(
|
|
64918
|
+
normalize3(text13, options);
|
|
64455
64919
|
return true;
|
|
64456
64920
|
} catch {
|
|
64457
64921
|
return false;
|
|
@@ -64461,8 +64925,8 @@ var require_hex = __commonJS({
|
|
|
64461
64925
|
const bytes3 = (0, index_js_1.toUint8Array)(data);
|
|
64462
64926
|
const casing = options.case ?? "lower";
|
|
64463
64927
|
const pairs = Array.from(bytes3, (byte) => {
|
|
64464
|
-
const
|
|
64465
|
-
return casing === "upper" ?
|
|
64928
|
+
const text13 = byte.toString(16).padStart(2, "0");
|
|
64929
|
+
return casing === "upper" ? text13.toUpperCase() : text13;
|
|
64466
64930
|
});
|
|
64467
64931
|
let body = "";
|
|
64468
64932
|
if (options.line) {
|
|
@@ -64481,19 +64945,19 @@ var require_hex = __commonJS({
|
|
|
64481
64945
|
}
|
|
64482
64946
|
return `${options.prefix ?? ""}${body}`;
|
|
64483
64947
|
}
|
|
64484
|
-
function decode3(
|
|
64485
|
-
const normalized = normalize3(
|
|
64948
|
+
function decode3(text13, options = {}) {
|
|
64949
|
+
const normalized = normalize3(text13, options);
|
|
64486
64950
|
const result = new Uint8Array(normalized.length / 2);
|
|
64487
64951
|
for (let i = 0; i < normalized.length; i += 2) {
|
|
64488
64952
|
result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
|
|
64489
64953
|
}
|
|
64490
64954
|
return result;
|
|
64491
64955
|
}
|
|
64492
|
-
function parse4(
|
|
64493
|
-
const normalized = normalize3(
|
|
64956
|
+
function parse4(text13, options = {}) {
|
|
64957
|
+
const normalized = normalize3(text13, options);
|
|
64494
64958
|
return {
|
|
64495
64959
|
bytes: decode3(normalized),
|
|
64496
|
-
format: detectFormat(
|
|
64960
|
+
format: detectFormat(text13),
|
|
64497
64961
|
normalized
|
|
64498
64962
|
};
|
|
64499
64963
|
}
|
|
@@ -64521,8 +64985,8 @@ var require_utf8 = __commonJS({
|
|
|
64521
64985
|
exports.encode = encode3;
|
|
64522
64986
|
exports.decode = decode3;
|
|
64523
64987
|
var index_js_1 = require_bytes();
|
|
64524
|
-
function encode3(
|
|
64525
|
-
return new TextEncoder().encode(
|
|
64988
|
+
function encode3(text13) {
|
|
64989
|
+
return new TextEncoder().encode(text13);
|
|
64526
64990
|
}
|
|
64527
64991
|
function decode3(data) {
|
|
64528
64992
|
return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
|
|
@@ -64540,11 +65004,11 @@ var require_utf16 = __commonJS({
|
|
|
64540
65004
|
exports.encode = encode3;
|
|
64541
65005
|
exports.decode = decode3;
|
|
64542
65006
|
var index_js_1 = require_bytes();
|
|
64543
|
-
function encode3(
|
|
64544
|
-
const result = new ArrayBuffer(
|
|
65007
|
+
function encode3(text13, options = {}) {
|
|
65008
|
+
const result = new ArrayBuffer(text13.length * 2);
|
|
64545
65009
|
const view = new DataView(result);
|
|
64546
|
-
for (let i = 0; i <
|
|
64547
|
-
view.setUint16(i * 2,
|
|
65010
|
+
for (let i = 0; i < text13.length; i++) {
|
|
65011
|
+
view.setUint16(i * 2, text13.charCodeAt(i), options.littleEndian ?? false);
|
|
64548
65012
|
}
|
|
64549
65013
|
return new Uint8Array(result);
|
|
64550
65014
|
}
|
|
@@ -64578,18 +65042,18 @@ var require_base64 = __commonJS({
|
|
|
64578
65042
|
function nodeBuffer() {
|
|
64579
65043
|
return globalThis.Buffer;
|
|
64580
65044
|
}
|
|
64581
|
-
function normalize3(
|
|
64582
|
-
return
|
|
65045
|
+
function normalize3(text13) {
|
|
65046
|
+
return text13.replace(/[\n\r\t ]/g, "");
|
|
64583
65047
|
}
|
|
64584
|
-
function pad2(
|
|
64585
|
-
const remainder =
|
|
64586
|
-
return remainder ?
|
|
65048
|
+
function pad2(text13) {
|
|
65049
|
+
const remainder = text13.length % 4;
|
|
65050
|
+
return remainder ? text13 + "=".repeat(4 - remainder) : text13;
|
|
64587
65051
|
}
|
|
64588
|
-
function is(
|
|
64589
|
-
if (typeof
|
|
65052
|
+
function is(text13) {
|
|
65053
|
+
if (typeof text13 !== "string") {
|
|
64590
65054
|
return false;
|
|
64591
65055
|
}
|
|
64592
|
-
const normalized = normalize3(
|
|
65056
|
+
const normalized = normalize3(text13);
|
|
64593
65057
|
return normalized === "" || BASE64_REGEX.test(normalized);
|
|
64594
65058
|
}
|
|
64595
65059
|
function encode3(data, _options) {
|
|
@@ -64600,8 +65064,8 @@ var require_base64 = __commonJS({
|
|
|
64600
65064
|
}
|
|
64601
65065
|
return btoa((0, binary_js_1.encode)(bytes3));
|
|
64602
65066
|
}
|
|
64603
|
-
function decode3(
|
|
64604
|
-
const normalized = normalize3(
|
|
65067
|
+
function decode3(text13, _options) {
|
|
65068
|
+
const normalized = normalize3(text13);
|
|
64605
65069
|
if (!is(normalized)) {
|
|
64606
65070
|
throw new TypeError("Input is not valid Base64 text");
|
|
64607
65071
|
}
|
|
@@ -64627,17 +65091,17 @@ var require_base64url = __commonJS({
|
|
|
64627
65091
|
exports.decode = decode3;
|
|
64628
65092
|
var base64_js_1 = require_base64();
|
|
64629
65093
|
var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
|
|
64630
|
-
function normalize3(
|
|
64631
|
-
return
|
|
65094
|
+
function normalize3(text13) {
|
|
65095
|
+
return text13.replace(/[\n\r\t ]/g, "");
|
|
64632
65096
|
}
|
|
64633
|
-
function is(
|
|
64634
|
-
return typeof
|
|
65097
|
+
function is(text13) {
|
|
65098
|
+
return typeof text13 === "string" && BASE64URL_REGEX.test(normalize3(text13));
|
|
64635
65099
|
}
|
|
64636
65100
|
function encode3(data, _options) {
|
|
64637
65101
|
return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
64638
65102
|
}
|
|
64639
|
-
function decode3(
|
|
64640
|
-
const normalized = normalize3(
|
|
65103
|
+
function decode3(text13, _options) {
|
|
65104
|
+
const normalized = normalize3(text13);
|
|
64641
65105
|
if (!is(normalized)) {
|
|
64642
65106
|
throw new TypeError("Input is not valid Base64Url text");
|
|
64643
65107
|
}
|
|
@@ -64758,8 +65222,8 @@ var require_ip_converter = __commonJS({
|
|
|
64758
65222
|
}
|
|
64759
65223
|
return ip;
|
|
64760
65224
|
}
|
|
64761
|
-
static parseCIDR(
|
|
64762
|
-
const [addr, prefixStr] =
|
|
65225
|
+
static parseCIDR(text13) {
|
|
65226
|
+
const [addr, prefixStr] = text13.split("/");
|
|
64763
65227
|
const prefix = parseInt(prefixStr, 10);
|
|
64764
65228
|
if (this.isIPv4(addr)) {
|
|
64765
65229
|
if (prefix < 0 || prefix > 32) {
|
|
@@ -64812,9 +65276,9 @@ var require_ip_converter = __commonJS({
|
|
|
64812
65276
|
}
|
|
64813
65277
|
return this.decodeIP(encoding_1.hex.encode(buf));
|
|
64814
65278
|
}
|
|
64815
|
-
static fromString(
|
|
64816
|
-
if (
|
|
64817
|
-
const [addr, prefix] = this.parseCIDR(
|
|
65279
|
+
static fromString(text13) {
|
|
65280
|
+
if (text13.includes("/")) {
|
|
65281
|
+
const [addr, prefix] = this.parseCIDR(text13);
|
|
64818
65282
|
const maskBytes = new Uint8Array(addr.length);
|
|
64819
65283
|
let bitsLeft = prefix;
|
|
64820
65284
|
for (let i = 0; i < maskBytes.length; i++) {
|
|
@@ -64831,7 +65295,7 @@ var require_ip_converter = __commonJS({
|
|
|
64831
65295
|
out.set(maskBytes, addr.length);
|
|
64832
65296
|
return out.buffer;
|
|
64833
65297
|
}
|
|
64834
|
-
const bytes3 = this.isIPv4(
|
|
65298
|
+
const bytes3 = this.isIPv4(text13) ? this.parseIPv4(text13) : this.parseIPv6(text13);
|
|
64835
65299
|
return new Uint8Array(bytes3).buffer;
|
|
64836
65300
|
}
|
|
64837
65301
|
};
|
|
@@ -72511,24 +72975,24 @@ var require_x509_cjs = __commonJS({
|
|
|
72511
72975
|
names.register("I", "2.5.4.43");
|
|
72512
72976
|
names.register("SN", "2.5.4.4");
|
|
72513
72977
|
names.register("T", "2.5.4.12");
|
|
72514
|
-
function replaceUnknownCharacter(
|
|
72978
|
+
function replaceUnknownCharacter(text13, char) {
|
|
72515
72979
|
return `\\${pvtsutils.Convert.ToHex(pvtsutils.Convert.FromUtf8String(char)).toUpperCase()}`;
|
|
72516
72980
|
}
|
|
72517
72981
|
function escape2(data) {
|
|
72518
72982
|
return data.replace(/([,+"\\<>;])/g, "\\$1").replace(/^([ #])/, "\\$1").replace(/([ ]$)/, "\\$1").replace(/([\r\n\t])/, replaceUnknownCharacter);
|
|
72519
72983
|
}
|
|
72520
72984
|
var Name = class _Name {
|
|
72521
|
-
static isASCII(
|
|
72522
|
-
for (let i = 0; i <
|
|
72523
|
-
const code =
|
|
72985
|
+
static isASCII(text13) {
|
|
72986
|
+
for (let i = 0; i < text13.length; i++) {
|
|
72987
|
+
const code = text13.charCodeAt(i);
|
|
72524
72988
|
if (code > 255) {
|
|
72525
72989
|
return false;
|
|
72526
72990
|
}
|
|
72527
72991
|
}
|
|
72528
72992
|
return true;
|
|
72529
72993
|
}
|
|
72530
|
-
static isPrintableString(
|
|
72531
|
-
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(
|
|
72994
|
+
static isPrintableString(text13) {
|
|
72995
|
+
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text13);
|
|
72532
72996
|
}
|
|
72533
72997
|
constructor(data, extraNames = {}) {
|
|
72534
72998
|
this.extraNames = new NameIdentifier();
|
|
@@ -77825,12 +78289,12 @@ function formatAddr(afi, addr) {
|
|
|
77825
78289
|
s = s + ":";
|
|
77826
78290
|
return s;
|
|
77827
78291
|
}
|
|
77828
|
-
function parsePrefix(
|
|
77829
|
-
const slash =
|
|
78292
|
+
function parsePrefix(text13) {
|
|
78293
|
+
const slash = text13.lastIndexOf("/");
|
|
77830
78294
|
if (slash < 0)
|
|
77831
|
-
throw new MeshCodecError("bad-value", `missing / in ${
|
|
77832
|
-
const host =
|
|
77833
|
-
const lenStr =
|
|
78295
|
+
throw new MeshCodecError("bad-value", `missing / in ${text13}`);
|
|
78296
|
+
const host = text13.slice(0, slash);
|
|
78297
|
+
const lenStr = text13.slice(slash + 1);
|
|
77834
78298
|
if (!/^\d{1,3}$/.test(lenStr))
|
|
77835
78299
|
throw new MeshCodecError("bad-value", `prefix len ${lenStr}`);
|
|
77836
78300
|
const len = Number(lenStr);
|
|
@@ -77839,15 +78303,15 @@ function parsePrefix(text12) {
|
|
|
77839
78303
|
throw new MeshCodecError("bad-value", `len ${len} for v${afi}`);
|
|
77840
78304
|
return makePrefix(afi, mask(addr, len), len);
|
|
77841
78305
|
}
|
|
77842
|
-
function parseAddr(
|
|
77843
|
-
if (
|
|
77844
|
-
return { afi: AFI_V6, addr: parseV6(
|
|
77845
|
-
return { afi: AFI_V4, addr: parseV4(
|
|
78306
|
+
function parseAddr(text13) {
|
|
78307
|
+
if (text13.includes(":"))
|
|
78308
|
+
return { afi: AFI_V6, addr: parseV6(text13) };
|
|
78309
|
+
return { afi: AFI_V4, addr: parseV4(text13) };
|
|
77846
78310
|
}
|
|
77847
|
-
function parseV4(
|
|
77848
|
-
const parts =
|
|
78311
|
+
function parseV4(text13) {
|
|
78312
|
+
const parts = text13.split(".");
|
|
77849
78313
|
if (parts.length !== 4)
|
|
77850
|
-
throw new MeshCodecError("bad-value", `bad IPv4 ${
|
|
78314
|
+
throw new MeshCodecError("bad-value", `bad IPv4 ${text13}`);
|
|
77851
78315
|
const out = new Uint8Array(4);
|
|
77852
78316
|
for (let i = 0; i < 4; i++) {
|
|
77853
78317
|
if (!/^(0|[1-9]\d{0,2})$/.test(parts[i]))
|
|
@@ -77859,22 +78323,22 @@ function parseV4(text12) {
|
|
|
77859
78323
|
}
|
|
77860
78324
|
return out;
|
|
77861
78325
|
}
|
|
77862
|
-
function parseV6(
|
|
77863
|
-
if (
|
|
77864
|
-
const halves =
|
|
78326
|
+
function parseV6(text13) {
|
|
78327
|
+
if (text13.includes("::")) {
|
|
78328
|
+
const halves = text13.split("::");
|
|
77865
78329
|
if (halves.length !== 2)
|
|
77866
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
78330
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
77867
78331
|
const head = halves[0] ? halves[0].split(":") : [];
|
|
77868
78332
|
const tail3 = halves[1] ? halves[1].split(":") : [];
|
|
77869
78333
|
if (head.length + tail3.length > 7)
|
|
77870
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
78334
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
77871
78335
|
const zeros = new Array(8 - head.length - tail3.length).fill("0");
|
|
77872
|
-
return groupsToBytes([...head, ...zeros, ...tail3],
|
|
78336
|
+
return groupsToBytes([...head, ...zeros, ...tail3], text13);
|
|
77873
78337
|
}
|
|
77874
|
-
const g =
|
|
78338
|
+
const g = text13.split(":");
|
|
77875
78339
|
if (g.length !== 8)
|
|
77876
|
-
throw new MeshCodecError("bad-value", `bad IPv6 ${
|
|
77877
|
-
return groupsToBytes(g,
|
|
78340
|
+
throw new MeshCodecError("bad-value", `bad IPv6 ${text13}`);
|
|
78341
|
+
return groupsToBytes(g, text13);
|
|
77878
78342
|
}
|
|
77879
78343
|
function groupsToBytes(groups, orig) {
|
|
77880
78344
|
if (groups.length !== 8)
|
|
@@ -85802,13 +86266,18 @@ function scheduledTurn(a) {
|
|
|
85802
86266
|
// Absent ⇒ for a cron turn that is 'safe' (unattendedModeFor): declined rather than parked, and nothing
|
|
85803
86267
|
// approved on anyone's behalf.
|
|
85804
86268
|
unattended: a.target ? a.prev?.unattended : a.policy.unattended ? true : void 0,
|
|
85805
|
-
...a.target ? {} : { reinforcedVerification: a.policy.reinforcedVerification ? true : void 0 }
|
|
86269
|
+
...a.target ? {} : { reinforcedVerification: a.policy.reinforcedVerification ? true : void 0 },
|
|
86270
|
+
// THE PERSON'S SETTINGS — their block rules above all — on a fire that OPENS a conversation and so has
|
|
86271
|
+
// no last send to replay them from. Without this the 3am run, the one nobody is watching, is the one
|
|
86272
|
+
// turn their rules do not reach (permission-rules.ts enforces them from exactly this field).
|
|
86273
|
+
...a.target ? {} : { settings: a.policy.settings }
|
|
85806
86274
|
};
|
|
85807
86275
|
}
|
|
85808
86276
|
function createHostedScheduling(fire) {
|
|
85809
86277
|
let store = null;
|
|
85810
86278
|
let isUnattended;
|
|
85811
86279
|
let isVerified;
|
|
86280
|
+
let settings;
|
|
85812
86281
|
let stopScheduler = null;
|
|
85813
86282
|
let cronDeps = { pushEnabled: false };
|
|
85814
86283
|
let cron = null;
|
|
@@ -85832,6 +86301,7 @@ function createHostedScheduling(fire) {
|
|
|
85832
86301
|
stopScheduler = null;
|
|
85833
86302
|
isUnattended = cfg2.isUnattended ?? isUnattended;
|
|
85834
86303
|
isVerified = cfg2.isVerified ?? isVerified;
|
|
86304
|
+
settings = cfg2.settings ?? settings;
|
|
85835
86305
|
if (!cfg2.enabled) {
|
|
85836
86306
|
store = null;
|
|
85837
86307
|
cronTools = [];
|
|
@@ -85871,7 +86341,11 @@ function createHostedScheduling(fire) {
|
|
|
85871
86341
|
})();
|
|
85872
86342
|
},
|
|
85873
86343
|
policy() {
|
|
85874
|
-
return {
|
|
86344
|
+
return {
|
|
86345
|
+
unattended: isUnattended?.() === true,
|
|
86346
|
+
reinforcedVerification: isVerified?.() === true,
|
|
86347
|
+
settings: settings?.()
|
|
86348
|
+
};
|
|
85875
86349
|
},
|
|
85876
86350
|
beginFire(taskId) {
|
|
85877
86351
|
const id = `cron:${taskId}:${randomUUID12().slice(0, 8)}`;
|
|
@@ -85974,8 +86448,8 @@ function listOf(items) {
|
|
|
85974
86448
|
const words = items.map((i) => i.text);
|
|
85975
86449
|
return words.length === 1 ? words[0] : `${words.slice(0, -1).join(", ")} and ${words[words.length - 1]}`;
|
|
85976
86450
|
}
|
|
85977
|
-
function sentence(
|
|
85978
|
-
return `${
|
|
86451
|
+
function sentence(text13) {
|
|
86452
|
+
return `${text13[0].toUpperCase()}${text13.slice(1)}`;
|
|
85979
86453
|
}
|
|
85980
86454
|
function unappliedSettingsNotice(engineLabel, settings, at, inForce = {}) {
|
|
85981
86455
|
const { items, protective } = unappliedSettings(settings, inForce);
|
|
@@ -86011,24 +86485,24 @@ var SHELL_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell", "Shell"]);
|
|
|
86011
86485
|
var WRITE_TOOLS = /* @__PURE__ */ new Set(["Edit", "MultiEdit", "Write", "NotebookEdit"]);
|
|
86012
86486
|
var READ_TOOLS = /* @__PURE__ */ new Set(["Read", "NotebookRead"]);
|
|
86013
86487
|
var PATH_TOOLS = /* @__PURE__ */ new Set([...WRITE_TOOLS, ...READ_TOOLS]);
|
|
86014
|
-
function indexOfUnescaped(
|
|
86015
|
-
for (let i = 0; i <
|
|
86016
|
-
if (
|
|
86488
|
+
function indexOfUnescaped(text13, char) {
|
|
86489
|
+
for (let i = 0; i < text13.length; i++) {
|
|
86490
|
+
if (text13[i] !== char)
|
|
86017
86491
|
continue;
|
|
86018
86492
|
let back = 0;
|
|
86019
|
-
for (let j = i - 1; j >= 0 &&
|
|
86493
|
+
for (let j = i - 1; j >= 0 && text13[j] === "\\"; j--)
|
|
86020
86494
|
back++;
|
|
86021
86495
|
if (back % 2 === 0)
|
|
86022
86496
|
return i;
|
|
86023
86497
|
}
|
|
86024
86498
|
return -1;
|
|
86025
86499
|
}
|
|
86026
|
-
function lastIndexOfUnescaped(
|
|
86027
|
-
for (let i =
|
|
86028
|
-
if (
|
|
86500
|
+
function lastIndexOfUnescaped(text13, char) {
|
|
86501
|
+
for (let i = text13.length - 1; i >= 0; i--) {
|
|
86502
|
+
if (text13[i] !== char)
|
|
86029
86503
|
continue;
|
|
86030
86504
|
let back = 0;
|
|
86031
|
-
for (let j = i - 1; j >= 0 &&
|
|
86505
|
+
for (let j = i - 1; j >= 0 && text13[j] === "\\"; j--)
|
|
86032
86506
|
back++;
|
|
86033
86507
|
if (back % 2 === 0)
|
|
86034
86508
|
return i;
|
|
@@ -86092,12 +86566,12 @@ function rulesOutOfReach(rules, reach) {
|
|
|
86092
86566
|
return true;
|
|
86093
86567
|
});
|
|
86094
86568
|
}
|
|
86095
|
-
function ruleRequestFor(
|
|
86569
|
+
function ruleRequestFor(tool22, detail) {
|
|
86096
86570
|
const input = detail.input ?? {};
|
|
86097
86571
|
const command = commandText(input.command);
|
|
86098
86572
|
const changed = Array.isArray(input.changes) ? input.changes.map((c) => typeof c?.path === "string" ? c.path : void 0) : [];
|
|
86099
86573
|
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:
|
|
86574
|
+
return { tool: tool22, ...command ? { command } : {}, ...paths.length ? { paths } : {} };
|
|
86101
86575
|
}
|
|
86102
86576
|
function commandText(command) {
|
|
86103
86577
|
if (typeof command === "string")
|
|
@@ -86111,9 +86585,9 @@ function describeRuleRequest(request2) {
|
|
|
86111
86585
|
return `\`${request2.command}\``;
|
|
86112
86586
|
const paths = request2.paths ?? [];
|
|
86113
86587
|
if (paths.length === 1)
|
|
86114
|
-
return paths[0]
|
|
86588
|
+
return `\`${paths[0]}\``;
|
|
86115
86589
|
if (paths.length > 1)
|
|
86116
|
-
return
|
|
86590
|
+
return `\`${paths[0]}\` and ${paths.length - 1} more`;
|
|
86117
86591
|
return `a ${request2.tool} call`;
|
|
86118
86592
|
}
|
|
86119
86593
|
function toolNameForRules(kind, name) {
|
|
@@ -86127,6 +86601,8 @@ function toolNameForRules(kind, name) {
|
|
|
86127
86601
|
case "write":
|
|
86128
86602
|
case "file":
|
|
86129
86603
|
case "filechange":
|
|
86604
|
+
case "delete":
|
|
86605
|
+
case "move":
|
|
86130
86606
|
return "Edit";
|
|
86131
86607
|
case "read":
|
|
86132
86608
|
return "Read";
|
|
@@ -86157,12 +86633,13 @@ function commandCandidates(command, depth = 0) {
|
|
|
86157
86633
|
add2(command);
|
|
86158
86634
|
for (const part of splitOnOperators(command)) {
|
|
86159
86635
|
add2(part);
|
|
86160
|
-
const bare
|
|
86161
|
-
|
|
86162
|
-
|
|
86163
|
-
|
|
86164
|
-
|
|
86165
|
-
|
|
86636
|
+
for (const bare of [part, ...wrapperPeels(part)]) {
|
|
86637
|
+
add2(bare);
|
|
86638
|
+
if (depth < 3)
|
|
86639
|
+
for (const inner of unwrapped(bare))
|
|
86640
|
+
for (const c of commandCandidates(inner, depth + 1))
|
|
86641
|
+
add2(c);
|
|
86642
|
+
}
|
|
86166
86643
|
}
|
|
86167
86644
|
return [...out];
|
|
86168
86645
|
}
|
|
@@ -86208,18 +86685,60 @@ function splitOnOperators(command) {
|
|
|
86208
86685
|
parts.push(current);
|
|
86209
86686
|
return parts.map((p) => p.trim()).filter(Boolean);
|
|
86210
86687
|
}
|
|
86211
|
-
|
|
86212
|
-
|
|
86213
|
-
|
|
86214
|
-
|
|
86215
|
-
|
|
86216
|
-
|
|
86217
|
-
|
|
86218
|
-
|
|
86219
|
-
|
|
86220
|
-
|
|
86688
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
86689
|
+
"sudo",
|
|
86690
|
+
"doas",
|
|
86691
|
+
"command",
|
|
86692
|
+
"builtin",
|
|
86693
|
+
"exec",
|
|
86694
|
+
"nohup",
|
|
86695
|
+
"stdbuf",
|
|
86696
|
+
"nice",
|
|
86697
|
+
"ionice",
|
|
86698
|
+
"env",
|
|
86699
|
+
"xargs",
|
|
86700
|
+
"time",
|
|
86701
|
+
"timeout"
|
|
86702
|
+
]);
|
|
86703
|
+
function wrapperPeels(command) {
|
|
86704
|
+
const ENV = /^[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S*)\s+/;
|
|
86705
|
+
const WORD = /^(\S+)\s+/;
|
|
86706
|
+
const out = [];
|
|
86707
|
+
const seen = /* @__PURE__ */ new Set();
|
|
86708
|
+
const queue3 = [command.trim()];
|
|
86709
|
+
while (queue3.length && out.length < 24) {
|
|
86710
|
+
const rest = queue3.shift();
|
|
86711
|
+
if (!rest || seen.has(rest))
|
|
86712
|
+
continue;
|
|
86713
|
+
seen.add(rest);
|
|
86714
|
+
const keep = (next2) => {
|
|
86715
|
+
if (next2) {
|
|
86716
|
+
out.push(next2);
|
|
86717
|
+
queue3.push(next2);
|
|
86718
|
+
}
|
|
86719
|
+
};
|
|
86720
|
+
const env = ENV.exec(rest);
|
|
86721
|
+
if (env) {
|
|
86722
|
+
keep(rest.slice(env[0].length));
|
|
86723
|
+
continue;
|
|
86724
|
+
}
|
|
86725
|
+
const word = WORD.exec(rest);
|
|
86726
|
+
if (!word)
|
|
86727
|
+
continue;
|
|
86728
|
+
const token4 = word[1];
|
|
86729
|
+
const isFlag = token4.startsWith("-");
|
|
86730
|
+
const isDuration = /^\d+(?:\.\d+)?[smhd]?$/.test(token4);
|
|
86731
|
+
if (!WRAPPERS.has(token4) && !isFlag && !isDuration)
|
|
86732
|
+
continue;
|
|
86733
|
+
const next = rest.slice(word[0].length);
|
|
86734
|
+
keep(next);
|
|
86735
|
+
if (isFlag) {
|
|
86736
|
+
const value = WORD.exec(next);
|
|
86737
|
+
if (value && !value[1].startsWith("-"))
|
|
86738
|
+
keep(next.slice(value[0].length));
|
|
86739
|
+
}
|
|
86221
86740
|
}
|
|
86222
|
-
return out
|
|
86741
|
+
return out;
|
|
86223
86742
|
}
|
|
86224
86743
|
function unwrapped(command) {
|
|
86225
86744
|
const out = [];
|
|
@@ -86231,8 +86750,8 @@ function unwrapped(command) {
|
|
|
86231
86750
|
out.push(stripQuotes(evaled[1]));
|
|
86232
86751
|
return out;
|
|
86233
86752
|
}
|
|
86234
|
-
function stripQuotes(
|
|
86235
|
-
const t =
|
|
86753
|
+
function stripQuotes(text13) {
|
|
86754
|
+
const t = text13.trim();
|
|
86236
86755
|
if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'"))
|
|
86237
86756
|
return t.slice(1, -1);
|
|
86238
86757
|
return t;
|
|
@@ -86259,14 +86778,14 @@ function hasWildcard(pattern) {
|
|
|
86259
86778
|
}
|
|
86260
86779
|
return false;
|
|
86261
86780
|
}
|
|
86262
|
-
function matchesWildcard(pattern,
|
|
86781
|
+
function matchesWildcard(pattern, text13) {
|
|
86263
86782
|
const STAR = `${MARK}S${MARK}`;
|
|
86264
86783
|
const BACK = `${MARK}B${MARK}`;
|
|
86265
86784
|
const processed = pattern.trim().replace(/\\\*/g, STAR).replace(/\\\\/g, BACK);
|
|
86266
86785
|
let regex = processed.replace(/[.+?^${}()|[\]\\'"]/g, "\\$&").replace(/\*/g, ".*").split(STAR).join("\\*").split(BACK).join("\\\\");
|
|
86267
86786
|
if (regex.endsWith(" .*") && (processed.match(/\*/g) ?? []).length === 1)
|
|
86268
86787
|
regex = `${regex.slice(0, -3)}( .*)?`;
|
|
86269
|
-
return new RegExp(`^${regex}$`, "s").test(
|
|
86788
|
+
return new RegExp(`^${regex}$`, "s").test(text13.trim());
|
|
86270
86789
|
}
|
|
86271
86790
|
var BLOCKED_BY_RULE_NOTICE_ID = "blocked-by-rule";
|
|
86272
86791
|
function blockedByRuleNotice(engineLabel, at, blocked) {
|
|
@@ -86303,10 +86822,6 @@ function opencodeBashDeny(rules) {
|
|
|
86303
86822
|
}
|
|
86304
86823
|
const prefix = /^(.+):\*$/.exec(content)?.[1];
|
|
86305
86824
|
const pattern = prefix !== void 0 ? `${prefix} *` : content;
|
|
86306
|
-
if (prefix === void 0 && !hasWildcard(content) && content.includes("*")) {
|
|
86307
|
-
untranslated.push(rule);
|
|
86308
|
-
continue;
|
|
86309
|
-
}
|
|
86310
86825
|
patterns.push(pattern, `sudo ${pattern}`, `xargs ${pattern}`);
|
|
86311
86826
|
expressed.push(rule);
|
|
86312
86827
|
}
|
|
@@ -86321,16 +86836,16 @@ function matchesPath(pattern, path6) {
|
|
|
86321
86836
|
}
|
|
86322
86837
|
|
|
86323
86838
|
// ../../packages/host-core/dist/engines/message-locator.js
|
|
86324
|
-
function newestSentMessageWithText(messages,
|
|
86325
|
-
if (!
|
|
86839
|
+
function newestSentMessageWithText(messages, text13) {
|
|
86840
|
+
if (!text13)
|
|
86326
86841
|
return void 0;
|
|
86327
86842
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
86328
86843
|
const m = messages[i];
|
|
86329
86844
|
if (m.role !== "user" || !m.id)
|
|
86330
86845
|
continue;
|
|
86331
|
-
if (m.text ===
|
|
86846
|
+
if (m.text === text13 || m.text.endsWith(`
|
|
86332
86847
|
|
|
86333
|
-
${
|
|
86848
|
+
${text13}`))
|
|
86334
86849
|
return m.id;
|
|
86335
86850
|
}
|
|
86336
86851
|
return void 0;
|
|
@@ -86394,9 +86909,9 @@ async function mergeSessionsVia(deps, sessionIds, opts) {
|
|
|
86394
86909
|
const transcripts = [];
|
|
86395
86910
|
for (const sid of sessionIds) {
|
|
86396
86911
|
const msgs = await deps.getMessages(sid, opts.projectDir).catch(() => []);
|
|
86397
|
-
const
|
|
86398
|
-
if (
|
|
86399
|
-
transcripts.push(
|
|
86912
|
+
const text13 = transcriptToText(msgs);
|
|
86913
|
+
if (text13)
|
|
86914
|
+
transcripts.push(text13);
|
|
86400
86915
|
}
|
|
86401
86916
|
if (transcripts.length === 0)
|
|
86402
86917
|
return false;
|
|
@@ -86419,11 +86934,11 @@ import { homedir as homedir5 } from "node:os";
|
|
|
86419
86934
|
function geminiChatsRoot(home = process.env.GEMINI_CLI_HOME || homedir5()) {
|
|
86420
86935
|
return join29(home, ".gemini", "tmp");
|
|
86421
86936
|
}
|
|
86422
|
-
function parseGeminiSessionFile(file2,
|
|
86937
|
+
function parseGeminiSessionFile(file2, text13) {
|
|
86423
86938
|
let header2 = null;
|
|
86424
86939
|
let seeded = false;
|
|
86425
86940
|
const messages = [];
|
|
86426
|
-
for (const line of
|
|
86941
|
+
for (const line of text13.split("\n")) {
|
|
86427
86942
|
if (!line.trim())
|
|
86428
86943
|
continue;
|
|
86429
86944
|
let o;
|
|
@@ -86468,8 +86983,8 @@ var fileForSession = /* @__PURE__ */ new Map();
|
|
|
86468
86983
|
async function findGeminiSessionFile(sessionId, root = geminiChatsRoot()) {
|
|
86469
86984
|
const known = fileForSession.get(sessionId);
|
|
86470
86985
|
if (known) {
|
|
86471
|
-
const
|
|
86472
|
-
const t =
|
|
86986
|
+
const text13 = await readFile10(known, "utf8").catch(() => null);
|
|
86987
|
+
const t = text13 === null ? null : parseGeminiSessionFile(known, text13);
|
|
86473
86988
|
if (t?.header.sessionId === sessionId)
|
|
86474
86989
|
return t;
|
|
86475
86990
|
fileForSession.delete(sessionId);
|
|
@@ -86484,10 +86999,10 @@ async function findGeminiSessionFile(sessionId, root = geminiChatsRoot()) {
|
|
|
86484
86999
|
if (!f.endsWith(".jsonl"))
|
|
86485
87000
|
continue;
|
|
86486
87001
|
const full = join29(chats, f);
|
|
86487
|
-
const
|
|
86488
|
-
if (
|
|
87002
|
+
const text13 = await readFile10(full, "utf8").catch(() => null);
|
|
87003
|
+
if (text13 === null)
|
|
86489
87004
|
continue;
|
|
86490
|
-
const t = parseGeminiSessionFile(full,
|
|
87005
|
+
const t = parseGeminiSessionFile(full, text13);
|
|
86491
87006
|
if (t?.header.sessionId === sessionId) {
|
|
86492
87007
|
fileForSession.set(sessionId, full);
|
|
86493
87008
|
return t;
|
|
@@ -86558,14 +87073,14 @@ function createHostedVerification(engineId) {
|
|
|
86558
87073
|
const anchor = plan?.trim() ? plan : finalText;
|
|
86559
87074
|
if (anchor.trim())
|
|
86560
87075
|
state3 = { ...state3, plan: anchor.slice(0, 4e3) };
|
|
86561
|
-
let
|
|
87076
|
+
let text13 = finalText;
|
|
86562
87077
|
let reviewText = "";
|
|
86563
87078
|
let phaseText = "";
|
|
86564
87079
|
for (let i = 0; i < rv.RV_MAX_CYCLES * 5 + 4; i++) {
|
|
86565
87080
|
const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
|
|
86566
87081
|
const still = outstanding?.() ?? [];
|
|
86567
87082
|
const pending2 = still.length ? still : void 0;
|
|
86568
|
-
const call3 = gate === "review" ? rv.reviewGrade(state3, reviewText ||
|
|
87083
|
+
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
87084
|
let verdict = null;
|
|
86570
87085
|
try {
|
|
86571
87086
|
verdict = rv.parseVerdict(await grade({ model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema }));
|
|
@@ -86573,16 +87088,16 @@ function createHostedVerification(engineId) {
|
|
|
86573
87088
|
verdict = null;
|
|
86574
87089
|
}
|
|
86575
87090
|
if (gone())
|
|
86576
|
-
return
|
|
87091
|
+
return text13;
|
|
86577
87092
|
if (!verdict) {
|
|
86578
87093
|
standDown(state3.cycles, "The verifier did not return a usable verdict, so this run was not verified.");
|
|
86579
|
-
return
|
|
87094
|
+
return text13;
|
|
86580
87095
|
}
|
|
86581
87096
|
{
|
|
86582
87097
|
const why = halt();
|
|
86583
87098
|
if (why) {
|
|
86584
87099
|
standDown(state3.cycles, why);
|
|
86585
|
-
return
|
|
87100
|
+
return text13;
|
|
86586
87101
|
}
|
|
86587
87102
|
}
|
|
86588
87103
|
const action = rv.rvDecision(verdict, state3);
|
|
@@ -86603,45 +87118,45 @@ function createHostedVerification(engineId) {
|
|
|
86603
87118
|
summary: verdict.summary
|
|
86604
87119
|
});
|
|
86605
87120
|
if (action.kind === "done" || action.kind === "capped")
|
|
86606
|
-
return
|
|
87121
|
+
return text13;
|
|
86607
87122
|
try {
|
|
86608
87123
|
if (gone())
|
|
86609
|
-
return
|
|
87124
|
+
return text13;
|
|
86610
87125
|
{
|
|
86611
87126
|
const why = halt();
|
|
86612
87127
|
if (why) {
|
|
86613
87128
|
standDown(state3.cycles, why);
|
|
86614
|
-
return
|
|
87129
|
+
return text13;
|
|
86615
87130
|
}
|
|
86616
87131
|
}
|
|
86617
|
-
const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText :
|
|
87132
|
+
const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText : text13;
|
|
86618
87133
|
const reply3 = await reprompt(action.prompt);
|
|
86619
87134
|
if (gone())
|
|
86620
|
-
return
|
|
87135
|
+
return text13;
|
|
86621
87136
|
{
|
|
86622
87137
|
const why = halt();
|
|
86623
87138
|
if (why) {
|
|
86624
87139
|
standDown(state3.cycles, why);
|
|
86625
|
-
return
|
|
87140
|
+
return text13;
|
|
86626
87141
|
}
|
|
86627
87142
|
}
|
|
86628
87143
|
if (!reply3 || reply3 === before) {
|
|
86629
87144
|
standDown(state3.cycles, "The agent did not produce anything new when sent back, so this run was not verified.");
|
|
86630
|
-
return
|
|
87145
|
+
return text13;
|
|
86631
87146
|
}
|
|
86632
87147
|
if (action.kind === "review")
|
|
86633
87148
|
reviewText = reply3;
|
|
86634
87149
|
else if (action.kind === "phase-review")
|
|
86635
87150
|
phaseText = reply3;
|
|
86636
87151
|
else
|
|
86637
|
-
|
|
87152
|
+
text13 = reply3;
|
|
86638
87153
|
} catch {
|
|
86639
87154
|
standDown(state3.cycles, "Verification could not be completed, so this run was not verified.");
|
|
86640
|
-
return
|
|
87155
|
+
return text13;
|
|
86641
87156
|
}
|
|
86642
87157
|
}
|
|
86643
87158
|
emit2({ ...base, action: "capped", gate: "completeness", cycle: rv.RV_MAX_CYCLES });
|
|
86644
|
-
return
|
|
87159
|
+
return text13;
|
|
86645
87160
|
}
|
|
86646
87161
|
};
|
|
86647
87162
|
}
|
|
@@ -86952,7 +87467,7 @@ function createRunTracker(opts) {
|
|
|
86952
87467
|
}
|
|
86953
87468
|
return token4;
|
|
86954
87469
|
},
|
|
86955
|
-
turnEnded(handle3,
|
|
87470
|
+
turnEnded(handle3, text13) {
|
|
86956
87471
|
const token4 = handle3;
|
|
86957
87472
|
const c = convs.get(resolve16(token4.key));
|
|
86958
87473
|
if (!c)
|
|
@@ -86960,14 +87475,14 @@ function createRunTracker(opts) {
|
|
|
86960
87475
|
c.live.delete(token4.id);
|
|
86961
87476
|
const run9 = c.run;
|
|
86962
87477
|
if (run9 && !run9.closed && token4.request === run9.request) {
|
|
86963
|
-
if (
|
|
87478
|
+
if (text13 === null && token4.carried && run9.waiters.length > 0) {
|
|
86964
87479
|
opts.log?.(`[run] ${c.key}: the turn delivering a result failed \u2014 the run is not verified`);
|
|
86965
87480
|
closeRun(c, run9, { reason: NOT_DELIVERED });
|
|
86966
87481
|
gc(c);
|
|
86967
87482
|
return;
|
|
86968
87483
|
}
|
|
86969
|
-
if (token4.id !== run9.gradedTurn &&
|
|
86970
|
-
run9.lastText =
|
|
87484
|
+
if (token4.id !== run9.gradedTurn && text13 !== null)
|
|
87485
|
+
run9.lastText = text13;
|
|
86971
87486
|
if (!holdsRun(run9) && !ownTurnRunning(run9)) {
|
|
86972
87487
|
run9.finishedIdle = true;
|
|
86973
87488
|
finish2(c, { outcome: "finished", text: run9.lastText });
|
|
@@ -87012,7 +87527,7 @@ function createRunTracker(opts) {
|
|
|
87012
87527
|
return items.map((i) => describe3(c, i, t, ""));
|
|
87013
87528
|
return run9.waiters.length > 0 && ownTurnRunning(run9) ? ["the turn reporting the background work is still running"] : void 0;
|
|
87014
87529
|
},
|
|
87015
|
-
openRun(sessionId, task, turn,
|
|
87530
|
+
openRun(sessionId, task, turn, text13) {
|
|
87016
87531
|
const c = conv(resolve16(sessionId));
|
|
87017
87532
|
const token4 = turn;
|
|
87018
87533
|
const run9 = {
|
|
@@ -87023,7 +87538,7 @@ function createRunTracker(opts) {
|
|
|
87023
87538
|
conv: c,
|
|
87024
87539
|
closed: null,
|
|
87025
87540
|
waiters: [],
|
|
87026
|
-
lastText:
|
|
87541
|
+
lastText: text13,
|
|
87027
87542
|
finishedIdle: false
|
|
87028
87543
|
};
|
|
87029
87544
|
if (c.lastPersonTurn > token4.id) {
|
|
@@ -88159,25 +88674,25 @@ function validate(schema, value, path6 = "$", out = []) {
|
|
|
88159
88674
|
}
|
|
88160
88675
|
return out;
|
|
88161
88676
|
}
|
|
88162
|
-
function extractJson(
|
|
88163
|
-
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(
|
|
88164
|
-
const candidates = [fenced?.[1],
|
|
88677
|
+
function extractJson(text13) {
|
|
88678
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(text13);
|
|
88679
|
+
const candidates = [fenced?.[1], text13].filter((v) => typeof v === "string");
|
|
88165
88680
|
for (const c of candidates) {
|
|
88166
88681
|
try {
|
|
88167
88682
|
return JSON.parse(c.trim());
|
|
88168
88683
|
} catch {
|
|
88169
88684
|
}
|
|
88170
88685
|
}
|
|
88171
|
-
for (let start3 = 0; start3 <
|
|
88172
|
-
const open10 =
|
|
88686
|
+
for (let start3 = 0; start3 < text13.length; start3++) {
|
|
88687
|
+
const open10 = text13[start3];
|
|
88173
88688
|
if (open10 !== "{" && open10 !== "[")
|
|
88174
88689
|
continue;
|
|
88175
88690
|
const close = open10 === "{" ? "}" : "]";
|
|
88176
88691
|
let depth = 0;
|
|
88177
88692
|
let inStr = false;
|
|
88178
88693
|
let esc3 = false;
|
|
88179
|
-
for (let i = start3; i <
|
|
88180
|
-
const ch =
|
|
88694
|
+
for (let i = start3; i < text13.length; i++) {
|
|
88695
|
+
const ch = text13[i];
|
|
88181
88696
|
if (inStr) {
|
|
88182
88697
|
if (esc3)
|
|
88183
88698
|
esc3 = false;
|
|
@@ -88197,7 +88712,7 @@ function extractJson(text12) {
|
|
|
88197
88712
|
depth--;
|
|
88198
88713
|
if (depth === 0) {
|
|
88199
88714
|
try {
|
|
88200
|
-
return JSON.parse(
|
|
88715
|
+
return JSON.parse(text13.slice(start3, i + 1));
|
|
88201
88716
|
} catch {
|
|
88202
88717
|
break;
|
|
88203
88718
|
}
|
|
@@ -88296,11 +88811,11 @@ function createEngineHttpApi(port, host = "127.0.0.1") {
|
|
|
88296
88811
|
});
|
|
88297
88812
|
if (!res.ok)
|
|
88298
88813
|
return null;
|
|
88299
|
-
const
|
|
88300
|
-
if (!
|
|
88814
|
+
const text13 = await res.text();
|
|
88815
|
+
if (!text13.trim())
|
|
88301
88816
|
return true;
|
|
88302
88817
|
try {
|
|
88303
|
-
const parsed = JSON.parse(
|
|
88818
|
+
const parsed = JSON.parse(text13);
|
|
88304
88819
|
return parsed === null ? true : parsed;
|
|
88305
88820
|
} catch {
|
|
88306
88821
|
return true;
|
|
@@ -88549,7 +89064,7 @@ function createEngineTranscript(engineId) {
|
|
|
88549
89064
|
return blocks.length ? [row(sid, "assistant", blocks)] : [];
|
|
88550
89065
|
}
|
|
88551
89066
|
return {
|
|
88552
|
-
userTurn(sid, cwd,
|
|
89067
|
+
userTurn(sid, cwd, text13) {
|
|
88553
89068
|
if (!cwd)
|
|
88554
89069
|
return;
|
|
88555
89070
|
cwdOf.set(sid, cwd);
|
|
@@ -88557,23 +89072,23 @@ function createEngineTranscript(engineId) {
|
|
|
88557
89072
|
if (prev)
|
|
88558
89073
|
void write2(sid, flushAssistant(sid, prev, true));
|
|
88559
89074
|
open10.set(sid, { cwd, blocks: [], prose: "", reasoning: "", pending: /* @__PURE__ */ new Map() });
|
|
88560
|
-
void write2(sid, [row(sid, "user",
|
|
89075
|
+
void write2(sid, [row(sid, "user", text13)]);
|
|
88561
89076
|
},
|
|
88562
|
-
assistantText(sid,
|
|
89077
|
+
assistantText(sid, text13) {
|
|
88563
89078
|
const t = open10.get(sid);
|
|
88564
|
-
if (!t || !
|
|
89079
|
+
if (!t || !text13)
|
|
88565
89080
|
return;
|
|
88566
89081
|
if (t.reasoning)
|
|
88567
89082
|
fold(t);
|
|
88568
|
-
t.prose +=
|
|
89083
|
+
t.prose += text13;
|
|
88569
89084
|
},
|
|
88570
|
-
thinking(sid,
|
|
89085
|
+
thinking(sid, text13) {
|
|
88571
89086
|
const t = open10.get(sid);
|
|
88572
|
-
if (!t || !
|
|
89087
|
+
if (!t || !text13)
|
|
88573
89088
|
return;
|
|
88574
89089
|
if (t.prose)
|
|
88575
89090
|
fold(t);
|
|
88576
|
-
t.reasoning +=
|
|
89091
|
+
t.reasoning += text13;
|
|
88577
89092
|
},
|
|
88578
89093
|
toolUse(sid, id, name, input) {
|
|
88579
89094
|
const t = open10.get(sid);
|
|
@@ -88680,13 +89195,13 @@ function createEngineTranscript(engineId) {
|
|
|
88680
89195
|
if (!file2)
|
|
88681
89196
|
return false;
|
|
88682
89197
|
const run9 = (chain2.get(sid) ?? Promise.resolve()).then(async () => {
|
|
88683
|
-
let
|
|
89198
|
+
let text13;
|
|
88684
89199
|
try {
|
|
88685
|
-
|
|
89200
|
+
text13 = await readFile12(file2, "utf8");
|
|
88686
89201
|
} catch {
|
|
88687
89202
|
return false;
|
|
88688
89203
|
}
|
|
88689
|
-
const lines =
|
|
89204
|
+
const lines = text13.split("\n");
|
|
88690
89205
|
const cut = cutLine(lines, at);
|
|
88691
89206
|
if (cut < 0)
|
|
88692
89207
|
return false;
|
|
@@ -88735,8 +89250,8 @@ ${blk.text.trim()}`);
|
|
|
88735
89250
|
else if (blk.type === "tool_use")
|
|
88736
89251
|
parts.push(`[tool call: ${blk.name ?? "tool"}] ${JSON.stringify(blk.input ?? {})}`);
|
|
88737
89252
|
else if (blk.type === "tool_result") {
|
|
88738
|
-
const
|
|
88739
|
-
parts.push(`[tool result${blk.is_error ? " (error)" : ""}] ${
|
|
89253
|
+
const text13 = typeof blk.content === "string" ? blk.content : Array.isArray(blk.content) ? blk.content.map((x) => x?.text ?? "").join("\n") : "";
|
|
89254
|
+
parts.push(`[tool result${blk.is_error ? " (error)" : ""}] ${text13.trim()}`);
|
|
88740
89255
|
}
|
|
88741
89256
|
}
|
|
88742
89257
|
}
|
|
@@ -88877,8 +89392,8 @@ function readOutputFromLocation(u) {
|
|
|
88877
89392
|
if (!path6)
|
|
88878
89393
|
return "";
|
|
88879
89394
|
try {
|
|
88880
|
-
const
|
|
88881
|
-
return
|
|
89395
|
+
const text13 = readFileSync24(path6, "utf8");
|
|
89396
|
+
return text13.length > MAX_LOCATION_READ_BYTES ? text13.slice(0, MAX_LOCATION_READ_BYTES) : text13;
|
|
88882
89397
|
} catch {
|
|
88883
89398
|
return "";
|
|
88884
89399
|
}
|
|
@@ -88995,7 +89510,8 @@ var OPENCODE_ACP = {
|
|
|
88995
89510
|
const SAFE = `${READ},"glob":"allow","grep":"allow","lsp":"allow","todowrite":"allow"`;
|
|
88996
89511
|
const KEEP_DENY = '"question":"deny","plan_enter":"deny","plan_exit":"deny"';
|
|
88997
89512
|
const { patterns } = opencodeBashDeny(deny);
|
|
88998
|
-
const
|
|
89513
|
+
const BLOCKED = patterns.map((p) => `${JSON.stringify(p)}:"deny"`).join(",");
|
|
89514
|
+
const BLOCK = BLOCKED ? `,"bash":{${BLOCKED}}` : "";
|
|
88999
89515
|
switch (mode) {
|
|
89000
89516
|
// Everything asks except the harmless reads — this is the mode that means "supervise me".
|
|
89001
89517
|
case "default":
|
|
@@ -89008,10 +89524,12 @@ var OPENCODE_ACP = {
|
|
|
89008
89524
|
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"allow",${SAFE},${KEEP_DENY}${BLOCK}}` };
|
|
89009
89525
|
// Nothing may change on disk. `deny` rather than `ask` so there is no card offering to
|
|
89010
89526
|
// break the mode's promise, and no prompt for something plan mode should never do.
|
|
89011
|
-
//
|
|
89012
|
-
//
|
|
89527
|
+
// Plan denies every command already, so the block patterns add nothing — but they are listed ANYWAY,
|
|
89528
|
+
// inside the same `bash` object (`{"*":"deny"}` is what a bare `"deny"` means to its matcher), because
|
|
89529
|
+
// "the rules went to the engine" must be true in every mode. A special case here would make the notice
|
|
89530
|
+
// that reads it (`blockRulesInForce`) quietly wrong the day plan mode's ruleset changes.
|
|
89013
89531
|
case "plan":
|
|
89014
|
-
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"deny","bash":"deny",${SAFE},${KEEP_DENY}}` };
|
|
89532
|
+
return { OPENCODE_PERMISSION: `{"*":"ask","edit":"deny","bash":{"*":"deny"${BLOCKED ? `,${BLOCKED}` : ""}},${SAFE},${KEEP_DENY}}` };
|
|
89015
89533
|
// bypassPermissions / dontAsk / unset ⇒ leave its own ruleset alone: both of those modes mean
|
|
89016
89534
|
// "never prompt, let it run", which is what OpenCode's shipped `"*": "allow"` already is. Except for
|
|
89017
89535
|
// what the person BLOCKED: Claude checks its block rules ahead of bypass (its own
|
|
@@ -89200,25 +89718,25 @@ function relFromFileUri(uri, dir2) {
|
|
|
89200
89718
|
}
|
|
89201
89719
|
function collectReplay(out, u) {
|
|
89202
89720
|
const kind = u.sessionUpdate;
|
|
89203
|
-
const
|
|
89204
|
-
if (kind === "user_message_chunk" && REPLAY_SCAFFOLD.test(
|
|
89721
|
+
const text13 = u.content?.text ?? "";
|
|
89722
|
+
if (kind === "user_message_chunk" && REPLAY_SCAFFOLD.test(text13))
|
|
89205
89723
|
return;
|
|
89206
89724
|
const role = kind === "user_message_chunk" ? "user" : kind === "agent_message_chunk" || kind === "agent_thought_chunk" ? "assistant" : null;
|
|
89207
|
-
if (!role || !
|
|
89725
|
+
if (!role || !text13)
|
|
89208
89726
|
return;
|
|
89209
89727
|
const blockKind = kind === "agent_thought_chunk" ? "thinking" : "text";
|
|
89210
89728
|
const last = out[out.length - 1];
|
|
89211
89729
|
if (last && last.role === role) {
|
|
89212
89730
|
const lastBlock = last.blocks?.[last.blocks.length - 1];
|
|
89213
89731
|
if (lastBlock && lastBlock.kind === blockKind)
|
|
89214
|
-
lastBlock.content +=
|
|
89732
|
+
lastBlock.content += text13;
|
|
89215
89733
|
else
|
|
89216
|
-
(last.blocks ??= []).push({ kind: blockKind, content:
|
|
89734
|
+
(last.blocks ??= []).push({ kind: blockKind, content: text13 });
|
|
89217
89735
|
if (blockKind === "text")
|
|
89218
|
-
last.content +=
|
|
89736
|
+
last.content += text13;
|
|
89219
89737
|
return;
|
|
89220
89738
|
}
|
|
89221
|
-
out.push({ role, content: blockKind === "text" ?
|
|
89739
|
+
out.push({ role, content: blockKind === "text" ? text13 : "", blocks: [{ kind: blockKind, content: text13 }] });
|
|
89222
89740
|
}
|
|
89223
89741
|
function readUsage(res) {
|
|
89224
89742
|
const r = res ?? {};
|
|
@@ -89481,19 +89999,19 @@ function createAcpBackend(engine, send5, resolve16, services) {
|
|
|
89481
89999
|
const origin = turn.origin;
|
|
89482
90000
|
switch (u.sessionUpdate) {
|
|
89483
90001
|
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:
|
|
90002
|
+
const text13 = u.content?.text ?? "";
|
|
90003
|
+
if (text13) {
|
|
90004
|
+
turn.acc += text13;
|
|
90005
|
+
transcript.assistantText(sid, text13);
|
|
90006
|
+
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta: text13, kind: "text" }, origin);
|
|
89489
90007
|
}
|
|
89490
90008
|
break;
|
|
89491
90009
|
}
|
|
89492
90010
|
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:
|
|
90011
|
+
const text13 = u.content?.text ?? "";
|
|
90012
|
+
if (text13) {
|
|
90013
|
+
transcript.thinking(sid, text13);
|
|
90014
|
+
send5({ type: "chat:stream", sessionId: sid, clientRequestId: turn.clientRequestId, messageId: turn.messageId, delta: text13, kind: "thinking" }, origin);
|
|
89497
90015
|
}
|
|
89498
90016
|
break;
|
|
89499
90017
|
}
|
|
@@ -90000,11 +90518,11 @@ function createAcpBackend(engine, send5, resolve16, services) {
|
|
|
90000
90518
|
return out;
|
|
90001
90519
|
}
|
|
90002
90520
|
function promptBlocks(params) {
|
|
90003
|
-
const
|
|
90521
|
+
const text13 = params.message.trim() === "/compact" && engine.compactCommand ? engine.compactCommand : params.message;
|
|
90004
90522
|
const seed = params.sessionId ? pendingSeed.get(params.sessionId) : void 0;
|
|
90005
90523
|
const blocks = [{ type: "text", text: seed ? `${seed}
|
|
90006
90524
|
|
|
90007
|
-
${
|
|
90525
|
+
${text13}` : text13 }];
|
|
90008
90526
|
const skipped = [];
|
|
90009
90527
|
if (!supportsCapability(declaredCaps, "attachments"))
|
|
90010
90528
|
return { blocks, skipped };
|
|
@@ -90109,8 +90627,8 @@ ${text12}` : text12 }];
|
|
|
90109
90627
|
}
|
|
90110
90628
|
async function summarizeOnScratch(conn, sessionId, projectDir) {
|
|
90111
90629
|
const rows = await backend2.getMessages(sessionId, projectDir).catch(() => []);
|
|
90112
|
-
const
|
|
90113
|
-
if (!
|
|
90630
|
+
const text13 = transcriptToText(rows, 6e4);
|
|
90631
|
+
if (!text13)
|
|
90114
90632
|
return null;
|
|
90115
90633
|
const fresh = await conn.t.request("session/new", { cwd: conn.cwd, mcpServers: [] }).catch(() => null);
|
|
90116
90634
|
const scratch = fresh?.sessionId;
|
|
@@ -90128,7 +90646,7 @@ ${text12}` : text12 }];
|
|
|
90128
90646
|
return await promptForText(conn.t, scratch, `${prompt("agent.session-summary")}
|
|
90129
90647
|
|
|
90130
90648
|
--- Conversation ---
|
|
90131
|
-
${
|
|
90649
|
+
${text13}`);
|
|
90132
90650
|
} finally {
|
|
90133
90651
|
knownSessions.delete(scratch);
|
|
90134
90652
|
sessionConfig.delete(scratch);
|
|
@@ -90612,8 +91130,11 @@ ${text12}`);
|
|
|
90612
91130
|
let finishing = null;
|
|
90613
91131
|
if (params.permissionMode)
|
|
90614
91132
|
sessionMode.set(sid, params.permissionMode);
|
|
90615
|
-
|
|
90616
|
-
|
|
91133
|
+
const denyNow = params.settings?.permissions?.deny;
|
|
91134
|
+
if (denyNow?.length)
|
|
91135
|
+
sessionDeny.set(sid, denyNow);
|
|
91136
|
+
else
|
|
91137
|
+
sessionDeny.delete(sid);
|
|
90617
91138
|
send5({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "running" }, origin);
|
|
90618
91139
|
const schema = supportsCapability(declared, "structuredOutput") ? params.jsonSchema : void 0;
|
|
90619
91140
|
const enforceable = schema ? canEnforce(schema) : { ok: false };
|
|
@@ -91200,13 +91721,13 @@ ${detail}` : detail, !overflow);
|
|
|
91200
91721
|
sessionCwd.set(sessionId, projectDir);
|
|
91201
91722
|
if (!conn)
|
|
91202
91723
|
return { ok: false, error: `${engineLabel} is not running.` };
|
|
91203
|
-
const
|
|
91724
|
+
const text13 = await summarizeOnScratch(conn, sessionId, projectDir) ?? await (async () => {
|
|
91204
91725
|
await ensureLoaded(conn, sessionId);
|
|
91205
91726
|
return promptForText(conn.t, sessionId, prompt("agent.session-summary"));
|
|
91206
91727
|
})();
|
|
91207
|
-
if (!
|
|
91728
|
+
if (!text13)
|
|
91208
91729
|
return { ok: false, error: `${engineLabel} could not summarise this conversation.` };
|
|
91209
|
-
const { title, summary } = parseSummaryReply(
|
|
91730
|
+
const { title, summary } = parseSummaryReply(text13);
|
|
91210
91731
|
if (title)
|
|
91211
91732
|
sessionTitles.set(sessionId, title);
|
|
91212
91733
|
if (title)
|
|
@@ -91474,8 +91995,8 @@ ${detail}` : detail, !overflow);
|
|
|
91474
91995
|
const seenIds = /* @__PURE__ */ new Set();
|
|
91475
91996
|
let idx = 0;
|
|
91476
91997
|
for (const m of log10.messages) {
|
|
91477
|
-
const
|
|
91478
|
-
if (!
|
|
91998
|
+
const text13 = geminiMessageText(m);
|
|
91999
|
+
if (!text13 || REPLAY_SCAFFOLD.test(text13))
|
|
91479
92000
|
continue;
|
|
91480
92001
|
if (m.id && seenIds.has(m.id))
|
|
91481
92002
|
continue;
|
|
@@ -91485,7 +92006,7 @@ ${detail}` : detail, !overflow);
|
|
|
91485
92006
|
const uuid3 = m.id ?? `acp-user-${idx}`;
|
|
91486
92007
|
if (role === "user")
|
|
91487
92008
|
idx++;
|
|
91488
|
-
rows.push({ role, content:
|
|
92009
|
+
rows.push({ role, content: text13, uuid: uuid3, blocks: [{ kind: "text", content: text13 }] });
|
|
91489
92010
|
}
|
|
91490
92011
|
if (rows.length > 0) {
|
|
91491
92012
|
const firstUser2 = rows.find((r) => r.role === "user")?.content?.trim();
|
|
@@ -91602,20 +92123,20 @@ function codexTranscriptRows(turns, textOf) {
|
|
|
91602
92123
|
const kind = String(it.type ?? "");
|
|
91603
92124
|
if (kind && kind !== "userMessage" && kind !== "agentMessage")
|
|
91604
92125
|
continue;
|
|
91605
|
-
const
|
|
91606
|
-
if (!
|
|
92126
|
+
const text13 = textOf(it);
|
|
92127
|
+
if (!text13)
|
|
91607
92128
|
continue;
|
|
91608
92129
|
const role = String(it.role ?? (kind === "userMessage" ? "user" : "assistant")) === "user" ? "user" : "assistant";
|
|
91609
92130
|
const last = rows[rows.length - 1];
|
|
91610
92131
|
if (last && last.role === role) {
|
|
91611
92132
|
last.content += `
|
|
91612
|
-
${
|
|
92133
|
+
${text13}`;
|
|
91613
92134
|
if (last.turns[last.turns.length - 1] !== ti)
|
|
91614
92135
|
last.turns.push(ti);
|
|
91615
92136
|
continue;
|
|
91616
92137
|
}
|
|
91617
92138
|
const uuid3 = typeof it.id === "string" && it.id ? it.id : void 0;
|
|
91618
|
-
rows.push({ role, content:
|
|
92139
|
+
rows.push({ role, content: text13, ...uuid3 ? { uuid: uuid3 } : {}, turns: [ti] });
|
|
91619
92140
|
}
|
|
91620
92141
|
});
|
|
91621
92142
|
return rows;
|
|
@@ -91833,9 +92354,9 @@ function itemToolName(item) {
|
|
|
91833
92354
|
case "webSearch":
|
|
91834
92355
|
return "WebSearch";
|
|
91835
92356
|
case "mcpToolCall": {
|
|
91836
|
-
const
|
|
92357
|
+
const tool22 = String(i.tool ?? "tool");
|
|
91837
92358
|
const server2 = String(i.server ?? "");
|
|
91838
|
-
return server2 ? `${server2}_${
|
|
92359
|
+
return server2 ? `${server2}_${tool22}` : tool22;
|
|
91839
92360
|
}
|
|
91840
92361
|
case "dynamicToolCall":
|
|
91841
92362
|
return String(i.tool ?? "tool");
|
|
@@ -92192,8 +92713,8 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92192
92713
|
subagentSinks.delete(scratch);
|
|
92193
92714
|
subagentDone.delete(scratch);
|
|
92194
92715
|
}
|
|
92195
|
-
const
|
|
92196
|
-
return
|
|
92716
|
+
const text13 = out.join("").trim();
|
|
92717
|
+
return text13 || null;
|
|
92197
92718
|
}
|
|
92198
92719
|
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
92199
92720
|
const pendingDialogs = /* @__PURE__ */ new Map();
|
|
@@ -92218,8 +92739,6 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92218
92739
|
const settled = turn ? runningTurnApprovalAnswer(modeNow, turn.sandbox) : "ask";
|
|
92219
92740
|
if (settled === "allow")
|
|
92220
92741
|
return Promise.resolve(allow);
|
|
92221
|
-
if (settled === "deny")
|
|
92222
|
-
return Promise.resolve(deny);
|
|
92223
92742
|
const requestId = randomUUID17();
|
|
92224
92743
|
return new Promise((resolveOutcome) => {
|
|
92225
92744
|
pendingApprovals.set(requestId, { resolve: resolveOutcome, threadId, allow, allowPersist, deny });
|
|
@@ -92547,7 +93066,11 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92547
93066
|
});
|
|
92548
93067
|
t.onRequest("item/fileChange/requestApproval", (raw) => {
|
|
92549
93068
|
const p = raw ?? {};
|
|
92550
|
-
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93069
|
+
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93070
|
+
title: p.reason,
|
|
93071
|
+
path: p.grantRoot,
|
|
93072
|
+
input: { changes: p.changes, path: p.path }
|
|
93073
|
+
});
|
|
92551
93074
|
});
|
|
92552
93075
|
t.onRequest("item/permissions/requestApproval", (raw) => parkApproval(raw, "Permissions", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, { title: "Codex is requesting additional permissions" }));
|
|
92553
93076
|
t.onRequest("execCommandApproval", (raw) => {
|
|
@@ -92556,7 +93079,11 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
92556
93079
|
});
|
|
92557
93080
|
t.onRequest("applyPatchApproval", (raw) => {
|
|
92558
93081
|
const p = raw ?? {};
|
|
92559
|
-
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93082
|
+
return parkApproval(raw, "Edit", { decision: "accept" }, { decision: "acceptForSession" }, { decision: "decline" }, {
|
|
93083
|
+
title: p.reason,
|
|
93084
|
+
path: p.grantRoot,
|
|
93085
|
+
input: { changes: p.changes ?? p.fileChanges }
|
|
93086
|
+
});
|
|
92560
93087
|
});
|
|
92561
93088
|
t.onRequest("item/tool/requestUserInput", (raw) => {
|
|
92562
93089
|
const p = raw ?? {};
|
|
@@ -93610,13 +94137,13 @@ function createCodexAppServerBackend(send5, resolve16, services) {
|
|
|
93610
94137
|
*/
|
|
93611
94138
|
summarizeSession: async (sessionId, projectDir) => {
|
|
93612
94139
|
const msgs = await backend2.getMessages(sessionId, threadCwd.get(sessionId) ?? spawnedCwd ?? projectDir).catch(() => []);
|
|
93613
|
-
const
|
|
93614
|
-
if (!
|
|
94140
|
+
const text13 = transcriptToText(msgs, 6e4);
|
|
94141
|
+
if (!text13)
|
|
93615
94142
|
return { ok: false, error: "That conversation has nothing to summarise yet." };
|
|
93616
94143
|
const reply3 = await promptScratchThread(`${prompt("agent.session-summary")}
|
|
93617
94144
|
|
|
93618
94145
|
--- Conversation ---
|
|
93619
|
-
${
|
|
94146
|
+
${text13}`, threadCwd.get(sessionId) ?? spawnedCwd ?? projectDir);
|
|
93620
94147
|
if (!reply3)
|
|
93621
94148
|
return { ok: false, error: `${label} could not summarise this conversation.` };
|
|
93622
94149
|
const { title, summary } = parseSummaryReply(reply3);
|
|
@@ -93729,8 +94256,8 @@ var seq = 0;
|
|
|
93729
94256
|
var now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
93730
94257
|
var ctx = [];
|
|
93731
94258
|
var CTX_MAX = 60;
|
|
93732
|
-
function pushCtx(role,
|
|
93733
|
-
const t = (
|
|
94259
|
+
function pushCtx(role, text13) {
|
|
94260
|
+
const t = (text13 ?? "").trim();
|
|
93734
94261
|
if (!t)
|
|
93735
94262
|
return;
|
|
93736
94263
|
ctx.push({ role, text: t.length > 300 ? `${t.slice(0, 300)}\u2026` : t });
|
|
@@ -93996,23 +94523,23 @@ var HostPluginApi = class {
|
|
|
93996
94523
|
secret(envKey2) {
|
|
93997
94524
|
return this.secretResolver(this.pluginId, envKey2);
|
|
93998
94525
|
}
|
|
93999
|
-
registerTool(
|
|
94526
|
+
registerTool(tool22) {
|
|
94000
94527
|
const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
94001
|
-
const name =
|
|
94002
|
-
this.registry.tools.push({ ...
|
|
94528
|
+
const name = tool22.name.startsWith(`${prefix}_`) ? tool22.name : `${prefix}_${tool22.name}`;
|
|
94529
|
+
this.registry.tools.push({ ...tool22, name });
|
|
94003
94530
|
}
|
|
94004
|
-
registerUiTool(
|
|
94005
|
-
if (!this.requireGrant("surfaces", `UI tool "${
|
|
94531
|
+
registerUiTool(tool22) {
|
|
94532
|
+
if (!this.requireGrant("surfaces", `UI tool "${tool22.name}"`))
|
|
94006
94533
|
return;
|
|
94007
94534
|
const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
94008
|
-
const name =
|
|
94535
|
+
const name = tool22.name.startsWith(`${prefix}_`) ? tool22.name : `${prefix}_${tool22.name}`;
|
|
94009
94536
|
const tier = this.hasGrant("customUI") ? "verified" : "third-party";
|
|
94010
94537
|
this.registry.tools.push({
|
|
94011
94538
|
name,
|
|
94012
|
-
description:
|
|
94013
|
-
inputSchema:
|
|
94014
|
-
handler: async (args) => toResult(await
|
|
94015
|
-
__ctxHandler: async (args, ctx2) => toResult(await
|
|
94539
|
+
description: tool22.description,
|
|
94540
|
+
inputSchema: tool22.inputSchema,
|
|
94541
|
+
handler: async (args) => toResult(await tool22.handler(args, NOOP_UI_CTX)),
|
|
94542
|
+
__ctxHandler: async (args, ctx2) => toResult(await tool22.handler(args, ctx2)),
|
|
94016
94543
|
__tier: tier
|
|
94017
94544
|
});
|
|
94018
94545
|
}
|
|
@@ -94122,8 +94649,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
|
|
|
94122
94649
|
pluginId,
|
|
94123
94650
|
config: config2,
|
|
94124
94651
|
secret: (envKey2) => secretResolver(pluginId, envKey2),
|
|
94125
|
-
registerTool: (
|
|
94126
|
-
const got = typeof
|
|
94652
|
+
registerTool: (tool22) => {
|
|
94653
|
+
const got = typeof tool22 === "function" ? tool22({}) : tool22;
|
|
94127
94654
|
const arr = Array.isArray(got) ? got : got ? [got] : [];
|
|
94128
94655
|
for (const t of arr) {
|
|
94129
94656
|
const c = convertTool(t);
|
|
@@ -95589,8 +96116,8 @@ init_prompts();
|
|
|
95589
96116
|
// ../../packages/voice-core/dist/pipeline/history.js
|
|
95590
96117
|
function formatHistoryLines(turns, maxLineChars = 300) {
|
|
95591
96118
|
return turns.map((t) => {
|
|
95592
|
-
const
|
|
95593
|
-
const capped =
|
|
96119
|
+
const text13 = t.text.replace(/\s+/g, " ").trim();
|
|
96120
|
+
const capped = text13.length > maxLineChars ? text13.slice(0, maxLineChars - 1).trimEnd() + "\u2026" : text13;
|
|
95594
96121
|
return `${t.role.toUpperCase()}: ${capped}`;
|
|
95595
96122
|
}).join("\n");
|
|
95596
96123
|
}
|
|
@@ -95885,15 +96412,15 @@ ${truncate(input.result, 4e3)}`
|
|
|
95885
96412
|
}
|
|
95886
96413
|
};
|
|
95887
96414
|
function ruleBasedTurn(input) {
|
|
95888
|
-
const
|
|
95889
|
-
const lower =
|
|
96415
|
+
const text13 = input.result.trim();
|
|
96416
|
+
const lower = text13.toLowerCase();
|
|
95890
96417
|
let status2 = "done";
|
|
95891
96418
|
if (/\b(error|failed|could not|cannot|unable to)\b/.test(lower))
|
|
95892
96419
|
status2 = "error";
|
|
95893
|
-
else if (
|
|
96420
|
+
else if (text13.endsWith("?") || /\b(which|should i|do you want|would you like|please confirm|clarif)\b/.test(lower)) {
|
|
95894
96421
|
status2 = "needs_input";
|
|
95895
96422
|
}
|
|
95896
|
-
const line = firstSentences(stripForSpeech(
|
|
96423
|
+
const line = firstSentences(stripForSpeech(text13)) || input.recentActivity.slice(-1)[0] || "Done.";
|
|
95897
96424
|
return { line, status: status2 };
|
|
95898
96425
|
}
|
|
95899
96426
|
function stripForSpeech(s) {
|
|
@@ -95971,8 +96498,8 @@ var VoiceGuideOrchestrator = class {
|
|
|
95971
96498
|
/** The bridge feeds every finalized transcript line here (capped buffer). An
|
|
95972
96499
|
* assistant line means the guide finished speaking — drain the next queued
|
|
95973
96500
|
* update immediately instead of waiting out the gap timer. */
|
|
95974
|
-
noteTranscript(role,
|
|
95975
|
-
const t =
|
|
96501
|
+
noteTranscript(role, text13) {
|
|
96502
|
+
const t = text13.trim();
|
|
95976
96503
|
if (!t)
|
|
95977
96504
|
return;
|
|
95978
96505
|
this.conversation.push({ role, text: t });
|
|
@@ -96506,26 +97033,26 @@ Additional context: ${context}` : task;
|
|
|
96506
97033
|
this.deps.emit({ type: "voice:milestone", text: spoken });
|
|
96507
97034
|
this.say(spoken, { urgent: focused });
|
|
96508
97035
|
}
|
|
96509
|
-
speakMilestone(
|
|
96510
|
-
this.deps.emit({ type: "voice:milestone", text:
|
|
96511
|
-
this.say(
|
|
97036
|
+
speakMilestone(text13) {
|
|
97037
|
+
this.deps.emit({ type: "voice:milestone", text: text13 });
|
|
97038
|
+
this.say(text13);
|
|
96512
97039
|
}
|
|
96513
97040
|
// ── One mouth, N sessions: serialized speech ───────────────────────────────
|
|
96514
97041
|
/** Speak `text`, serializing non-urgent lines so concurrent sessions don't
|
|
96515
97042
|
* talk over each other. Urgent lines (blocking questions, the focused
|
|
96516
97043
|
* session's result, critical notices) always go out immediately. */
|
|
96517
|
-
say(
|
|
96518
|
-
if (!
|
|
97044
|
+
say(text13, opts = {}) {
|
|
97045
|
+
if (!text13)
|
|
96519
97046
|
return;
|
|
96520
97047
|
const now2 = this.now();
|
|
96521
97048
|
if (opts.urgent || this.sayQueue.length === 0 && now2 - this.lastSayAt >= SPEAK_GAP_MS) {
|
|
96522
97049
|
this.lastSayAt = now2;
|
|
96523
|
-
this.voice?.speakNow(
|
|
97050
|
+
this.voice?.speakNow(text13);
|
|
96524
97051
|
return;
|
|
96525
97052
|
}
|
|
96526
97053
|
if (this.sayQueue.length >= SPEAK_QUEUE_CAP)
|
|
96527
97054
|
this.sayQueue.shift();
|
|
96528
|
-
this.sayQueue.push(
|
|
97055
|
+
this.sayQueue.push(text13);
|
|
96529
97056
|
this.armSayTimer();
|
|
96530
97057
|
}
|
|
96531
97058
|
armSayTimer() {
|
|
@@ -96656,11 +97183,11 @@ var ClientProxyProvider = class {
|
|
|
96656
97183
|
/** Audio is client↔provider direct — the daemon never sees mic/model PCM. */
|
|
96657
97184
|
sendAudio(_pcm24k) {
|
|
96658
97185
|
}
|
|
96659
|
-
respondToTool(callId,
|
|
96660
|
-
this.deps.send({ type: "voice:cd:respondToTool", callId, text:
|
|
97186
|
+
respondToTool(callId, text13, isError) {
|
|
97187
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError });
|
|
96661
97188
|
}
|
|
96662
|
-
speakNow(
|
|
96663
|
-
this.deps.send({ type: "voice:cd:speak", text:
|
|
97189
|
+
speakNow(text13) {
|
|
97190
|
+
this.deps.send({ type: "voice:cd:speak", text: text13 });
|
|
96664
97191
|
}
|
|
96665
97192
|
close() {
|
|
96666
97193
|
this.settleConnect(new Error("closed before connect"));
|
|
@@ -96680,11 +97207,11 @@ var ClientProxyProvider = class {
|
|
|
96680
97207
|
handleToolCall(inv) {
|
|
96681
97208
|
this.cb.onToolCall(inv);
|
|
96682
97209
|
}
|
|
96683
|
-
handleTranscript(speaker,
|
|
97210
|
+
handleTranscript(speaker, text13) {
|
|
96684
97211
|
if (speaker === "user")
|
|
96685
|
-
this.cb.onUserTranscript(
|
|
97212
|
+
this.cb.onUserTranscript(text13);
|
|
96686
97213
|
else
|
|
96687
|
-
this.cb.onAgentTranscript(
|
|
97214
|
+
this.cb.onAgentTranscript(text13);
|
|
96688
97215
|
}
|
|
96689
97216
|
handleProviderEvent(event, message) {
|
|
96690
97217
|
switch (event) {
|
|
@@ -96916,10 +97443,10 @@ var VoiceControl = class {
|
|
|
96916
97443
|
* injection as a user turn and comments on every slide change, which is exactly the
|
|
96917
97444
|
* running commentary the silence contract forbids.
|
|
96918
97445
|
*/
|
|
96919
|
-
injectPresentContext(
|
|
97446
|
+
injectPresentContext(text13) {
|
|
96920
97447
|
if (this.ended)
|
|
96921
97448
|
return;
|
|
96922
|
-
this.deps.send({ type: "voice:cd:inject", text:
|
|
97449
|
+
this.deps.send({ type: "voice:cd:inject", text: text13, turnComplete: false });
|
|
96923
97450
|
}
|
|
96924
97451
|
/**
|
|
96925
97452
|
* A typed question from the phone, routed as if it had been spoken.
|
|
@@ -96927,33 +97454,33 @@ var VoiceControl = class {
|
|
|
96927
97454
|
* This one DOES form a turn (turnComplete left at its default): unlike slide context,
|
|
96928
97455
|
* the presenter is deliberately addressing the assistant and is waiting for an answer.
|
|
96929
97456
|
*/
|
|
96930
|
-
askPresent(
|
|
97457
|
+
askPresent(text13) {
|
|
96931
97458
|
if (this.ended)
|
|
96932
97459
|
return;
|
|
96933
|
-
this.deps.send({ type: "voice:cd:inject", text: `(The presenter asks you directly: ${
|
|
97460
|
+
this.deps.send({ type: "voice:cd:inject", text: `(The presenter asks you directly: ${text13})` });
|
|
96934
97461
|
}
|
|
96935
97462
|
async runPresentControl(callId, name, args) {
|
|
96936
|
-
let
|
|
97463
|
+
let text13 = "";
|
|
96937
97464
|
let silent = false;
|
|
96938
97465
|
let clearPlayback = false;
|
|
96939
97466
|
let isError = false;
|
|
96940
97467
|
try {
|
|
96941
97468
|
const r = await this.deps.execPresentControl(name, args);
|
|
96942
|
-
|
|
97469
|
+
text13 = r.text;
|
|
96943
97470
|
silent = r.silent;
|
|
96944
97471
|
clearPlayback = r.clearPlayback === true;
|
|
96945
97472
|
} catch (e) {
|
|
96946
|
-
|
|
97473
|
+
text13 = e instanceof Error ? e.message : "presentation action failed";
|
|
96947
97474
|
isError = true;
|
|
96948
97475
|
}
|
|
96949
|
-
log(`voice: present-control ${name} \u2192 ${isError ? "ERROR " : ""}${
|
|
96950
|
-
recordEvent("tool_result", { name, text:
|
|
97476
|
+
log(`voice: present-control ${name} \u2192 ${isError ? "ERROR " : ""}${text13}`);
|
|
97477
|
+
recordEvent("tool_result", { name, text: text13, isError });
|
|
96951
97478
|
if (clearPlayback && !isError)
|
|
96952
97479
|
this.deps.send({ type: "voice:clearPlayback" });
|
|
96953
|
-
this.deps.send({ type: "voice:cd:respondToTool", callId, text:
|
|
97480
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError, silent: silent && !isError });
|
|
96954
97481
|
}
|
|
96955
97482
|
async runScreenControl(callId, name, args) {
|
|
96956
|
-
let
|
|
97483
|
+
let text13;
|
|
96957
97484
|
let isError = false;
|
|
96958
97485
|
let finished = false, nudges = 0;
|
|
96959
97486
|
let slowTimer = null;
|
|
@@ -96969,18 +97496,18 @@ var VoiceControl = class {
|
|
|
96969
97496
|
};
|
|
96970
97497
|
scheduleNudge(2e4);
|
|
96971
97498
|
try {
|
|
96972
|
-
|
|
97499
|
+
text13 = await this.deps.execScreenControl(name, args);
|
|
96973
97500
|
} catch (e) {
|
|
96974
|
-
|
|
97501
|
+
text13 = e instanceof Error ? e.message : "screen action failed";
|
|
96975
97502
|
isError = true;
|
|
96976
97503
|
} finally {
|
|
96977
97504
|
finished = true;
|
|
96978
97505
|
if (slowTimer)
|
|
96979
97506
|
clearTimeout(slowTimer);
|
|
96980
97507
|
}
|
|
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:
|
|
97508
|
+
log(`voice: screen-control ${name} \u2192 ${isError ? "ERROR " : ""}${text13}`);
|
|
97509
|
+
recordEvent("tool_result", { name, text: text13, isError });
|
|
97510
|
+
this.deps.send({ type: "voice:cd:respondToTool", callId, text: text13, isError });
|
|
96984
97511
|
}
|
|
96985
97512
|
async start(msg) {
|
|
96986
97513
|
if (this.starting)
|
|
@@ -97118,13 +97645,13 @@ ${priorText}` : "";
|
|
|
97118
97645
|
const callbacks = {
|
|
97119
97646
|
onOutputAudio: () => {
|
|
97120
97647
|
},
|
|
97121
|
-
onUserTranscript: (
|
|
97122
|
-
orchestrator.noteTranscript("user",
|
|
97123
|
-
this.deps.send({ type: "voice:transcript", speaker: "user", text:
|
|
97648
|
+
onUserTranscript: (text13) => {
|
|
97649
|
+
orchestrator.noteTranscript("user", text13);
|
|
97650
|
+
this.deps.send({ type: "voice:transcript", speaker: "user", text: text13 });
|
|
97124
97651
|
},
|
|
97125
|
-
onAgentTranscript: (
|
|
97126
|
-
orchestrator.noteTranscript("assistant",
|
|
97127
|
-
this.deps.send({ type: "voice:transcript", speaker: "agent", text:
|
|
97652
|
+
onAgentTranscript: (text13) => {
|
|
97653
|
+
orchestrator.noteTranscript("assistant", text13);
|
|
97654
|
+
this.deps.send({ type: "voice:transcript", speaker: "agent", text: text13 });
|
|
97128
97655
|
},
|
|
97129
97656
|
onToolCall: (inv) => orchestrator.handleToolCall(inv),
|
|
97130
97657
|
onInterruption: () => this.deps.send({ type: "voice:clearPlayback" }),
|
|
@@ -98490,7 +99017,7 @@ var fmtTime = (sec) => {
|
|
|
98490
99017
|
cs -= s * 100;
|
|
98491
99018
|
return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}.${String(cs).padStart(2, "0")}`;
|
|
98492
99019
|
};
|
|
98493
|
-
var escapeAss = (
|
|
99020
|
+
var escapeAss = (text13) => text13.replace(/\\/g, "\\\\").replace(/\{/g, "(").replace(/\}/g, ")").replace(/\r?\n/g, "\\N");
|
|
98494
99021
|
function buildAssSubtitles(cues, style, width, height) {
|
|
98495
99022
|
const base = Math.round(height / 14);
|
|
98496
99023
|
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 +99628,7 @@ async function cloneVoiceElevenLabs(name, samples, cfg2, opts) {
|
|
|
99101
99628
|
throw new Error("ElevenLabs clone returned no voice_id.");
|
|
99102
99629
|
return { voiceId: j.voice_id, name: j.name ?? name };
|
|
99103
99630
|
}
|
|
99104
|
-
async function synthesizeSpeechElevenLabs(
|
|
99631
|
+
async function synthesizeSpeechElevenLabs(text13, voiceId, cfg2, opts) {
|
|
99105
99632
|
const base = (cfg2.baseUrl?.trim() || BASE_URL).replace(/\/+$/, "");
|
|
99106
99633
|
const settings = {};
|
|
99107
99634
|
if (cfg2.stability != null)
|
|
@@ -99115,7 +99642,7 @@ async function synthesizeSpeechElevenLabs(text12, voiceId, cfg2, opts) {
|
|
|
99115
99642
|
res = await fetch(`${base}/v1/text-to-speech/${encodeURIComponent(voiceId)}?output_format=mp3_44100_128`, {
|
|
99116
99643
|
method: "POST",
|
|
99117
99644
|
headers: { "xi-api-key": cfg2.apiKey, "Content-Type": "application/json" },
|
|
99118
|
-
body: JSON.stringify({ text:
|
|
99645
|
+
body: JSON.stringify({ text: text13, model_id: cfg2.model?.trim() || DEFAULT_TTS_MODEL, ...Object.keys(settings).length ? { voice_settings: settings } : {} }),
|
|
99119
99646
|
signal: opts?.signal ?? AbortSignal.timeout(12e4)
|
|
99120
99647
|
});
|
|
99121
99648
|
} catch (e) {
|
|
@@ -100518,11 +101045,11 @@ async function geminiJson(opts) {
|
|
|
100518
101045
|
const json3 = await res.json().catch(() => ({}));
|
|
100519
101046
|
if (!res.ok)
|
|
100520
101047
|
throw new Error(json3.error?.message ?? `Gemini request failed (${res.status})`);
|
|
100521
|
-
const
|
|
101048
|
+
const text13 = json3.candidates?.[0]?.content?.parts?.map((p) => p.text ?? "").join("") ?? "";
|
|
100522
101049
|
try {
|
|
100523
|
-
return JSON.parse(
|
|
101050
|
+
return JSON.parse(text13);
|
|
100524
101051
|
} catch {
|
|
100525
|
-
throw new Error(`Gemini returned non-JSON transcription output: ${
|
|
101052
|
+
throw new Error(`Gemini returned non-JSON transcription output: ${text13.slice(0, 200)}`);
|
|
100526
101053
|
}
|
|
100527
101054
|
}
|
|
100528
101055
|
async function transcribeMedia(opts) {
|
|
@@ -100656,7 +101183,7 @@ function resolveAvatarCreds(snap, keyFile, envKey2) {
|
|
|
100656
101183
|
function heygenCreds() {
|
|
100657
101184
|
return resolveAvatarCreds(readDaemonAgentSettings(), readDaemonKeyFile("heygen.key"), process.env.HEYGEN_API_KEY ?? null);
|
|
100658
101185
|
}
|
|
100659
|
-
var NO_AVATAR_CREDS = "Avatar videos need
|
|
101186
|
+
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
101187
|
function readDaemonKeyFile(name) {
|
|
100661
101188
|
try {
|
|
100662
101189
|
const home = tesseractHome();
|
|
@@ -100875,12 +101402,12 @@ function createDaemonVideoEditRunner() {
|
|
|
100875
101402
|
return { ok: false, error: err(e) };
|
|
100876
101403
|
}
|
|
100877
101404
|
},
|
|
100878
|
-
async synthesizeSpeech(
|
|
101405
|
+
async synthesizeSpeech(text13, voiceId, outDir, opts) {
|
|
100879
101406
|
const apiKey = elevenLabsKey();
|
|
100880
101407
|
if (!apiKey)
|
|
100881
101408
|
return { ok: false, error: "Text-to-speech needs an ElevenLabs key (Settings \u2192 Voice)." };
|
|
100882
101409
|
try {
|
|
100883
|
-
const audio = await synthesizeSpeechElevenLabs(
|
|
101410
|
+
const audio = await synthesizeSpeechElevenLabs(text13, voiceId, { apiKey, stability: opts?.stability, similarityBoost: opts?.similarityBoost, speed: opts?.speed });
|
|
100884
101411
|
const dir2 = outDir ?? join48(musicDir2(), randomUUID24());
|
|
100885
101412
|
await mkdir9(dir2, { recursive: true });
|
|
100886
101413
|
const path6 = join48(dir2, "speech.mp3");
|
|
@@ -101009,8 +101536,8 @@ function createDaemonSupportSubmit() {
|
|
|
101009
101536
|
signal: AbortSignal.timeout(3e4)
|
|
101010
101537
|
});
|
|
101011
101538
|
if (!res.ok) {
|
|
101012
|
-
const
|
|
101013
|
-
throw new Error(`Report submission failed (${res.status}). ${
|
|
101539
|
+
const text13 = await res.text().catch(() => "");
|
|
101540
|
+
throw new Error(`Report submission failed (${res.status}). ${text13.slice(0, 200)}`);
|
|
101014
101541
|
}
|
|
101015
101542
|
const body = await res.json();
|
|
101016
101543
|
if (!body.issueUrl || typeof body.issueNumber !== "number")
|
|
@@ -101724,28 +102251,28 @@ async function execPresentControl(name, args) {
|
|
|
101724
102251
|
// ../../packages/host-core/dist/app-control-daemon.js
|
|
101725
102252
|
var DAEMON_TABLE = {
|
|
101726
102253
|
"present.state": async () => {
|
|
101727
|
-
const { text:
|
|
101728
|
-
return
|
|
102254
|
+
const { text: text13 } = await execPresentControl("deck_overview", {});
|
|
102255
|
+
return text13;
|
|
101729
102256
|
},
|
|
101730
102257
|
"present.deck": async () => {
|
|
101731
|
-
const { text:
|
|
101732
|
-
return
|
|
102258
|
+
const { text: text13 } = await execPresentControl("deck_overview", {});
|
|
102259
|
+
return text13;
|
|
101733
102260
|
},
|
|
101734
102261
|
"present.find_slide": async (input) => {
|
|
101735
|
-
const { text:
|
|
101736
|
-
return
|
|
102262
|
+
const { text: text13 } = await execPresentControl("find_slide", { query: String(input.query ?? "") });
|
|
102263
|
+
return text13;
|
|
101737
102264
|
},
|
|
101738
102265
|
"present.goto": async (input) => {
|
|
101739
|
-
const { text:
|
|
101740
|
-
return
|
|
102266
|
+
const { text: text13 } = await execPresentControl("goto_slide", { slide: Number(input.slide) });
|
|
102267
|
+
return text13;
|
|
101741
102268
|
},
|
|
101742
102269
|
"present.set_zoom": async (input) => {
|
|
101743
|
-
const { text:
|
|
101744
|
-
return
|
|
102270
|
+
const { text: text13 } = await execPresentControl("set_zoom", { level: Number(input.level) });
|
|
102271
|
+
return text13;
|
|
101745
102272
|
},
|
|
101746
102273
|
"present.set_blank": async (input) => {
|
|
101747
|
-
const { text:
|
|
101748
|
-
return
|
|
102274
|
+
const { text: text13 } = await execPresentControl("set_blank", { blanked: input.blanked === true });
|
|
102275
|
+
return text13;
|
|
101749
102276
|
},
|
|
101750
102277
|
"present.set_ai": async (input) => {
|
|
101751
102278
|
if (!isLive())
|
|
@@ -102306,7 +102833,10 @@ function refreshDaemonScheduling(b) {
|
|
|
102306
102833
|
// and a 3am fire would act on a switch the user changed days ago. The snapshot is
|
|
102307
102834
|
// already read fresh per turn everywhere else; this reads it fresh per fire.
|
|
102308
102835
|
isUnattended: () => readDaemonAgentSettings().unattended === true,
|
|
102309
|
-
isVerified: () => readDaemonAgentSettings().reinforcedVerification === true
|
|
102836
|
+
isVerified: () => readDaemonAgentSettings().reinforcedVerification === true,
|
|
102837
|
+
// The person's permission rules and hooks, for a fire that OPENS a conversation: it has no earlier turn
|
|
102838
|
+
// to replay them from, and it is the run nobody is watching. Read per fire, like the switches above.
|
|
102839
|
+
settings: () => readDaemonAgentSettings().settings
|
|
102310
102840
|
});
|
|
102311
102841
|
}
|
|
102312
102842
|
function daemonWorkspaceDir() {
|
|
@@ -102596,8 +103126,8 @@ async function linuxFavorites() {
|
|
|
102596
103126
|
];
|
|
102597
103127
|
for (const file2 of candidates) {
|
|
102598
103128
|
try {
|
|
102599
|
-
const
|
|
102600
|
-
const favs = finalize2(parseGtkBookmarks(
|
|
103129
|
+
const text13 = await readFile13(file2, "utf8");
|
|
103130
|
+
const favs = finalize2(parseGtkBookmarks(text13));
|
|
102601
103131
|
if (favs.length)
|
|
102602
103132
|
return favs;
|
|
102603
103133
|
} catch {
|
|
@@ -102605,9 +103135,9 @@ async function linuxFavorites() {
|
|
|
102605
103135
|
}
|
|
102606
103136
|
return [];
|
|
102607
103137
|
}
|
|
102608
|
-
function parseGtkBookmarks(
|
|
103138
|
+
function parseGtkBookmarks(text13) {
|
|
102609
103139
|
const out = [];
|
|
102610
|
-
for (const raw of
|
|
103140
|
+
for (const raw of text13.split(/\r?\n/)) {
|
|
102611
103141
|
const line = raw.trim();
|
|
102612
103142
|
if (!line.startsWith("file://"))
|
|
102613
103143
|
continue;
|
|
@@ -108807,8 +109337,8 @@ function safeJson(value) {
|
|
|
108807
109337
|
return "";
|
|
108808
109338
|
}
|
|
108809
109339
|
}
|
|
108810
|
-
function firstLine2(
|
|
108811
|
-
return
|
|
109340
|
+
function firstLine2(text13) {
|
|
109341
|
+
return text13.split("\n").map((l) => l.trim()).find(Boolean)?.slice(0, 80) ?? "";
|
|
108812
109342
|
}
|
|
108813
109343
|
function queryMatcher(query2) {
|
|
108814
109344
|
const q = query2.trim();
|
|
@@ -108816,11 +109346,11 @@ function queryMatcher(query2) {
|
|
|
108816
109346
|
return null;
|
|
108817
109347
|
return new RegExp(q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "iu");
|
|
108818
109348
|
}
|
|
108819
|
-
function snippetAt(
|
|
109349
|
+
function snippetAt(text13, at, length, radius = 60) {
|
|
108820
109350
|
const from = Math.max(0, at - radius);
|
|
108821
|
-
const to = Math.min(
|
|
108822
|
-
const body =
|
|
108823
|
-
return `${from > 0 ? "\u2026" : ""}${body}${to <
|
|
109351
|
+
const to = Math.min(text13.length, at + length + radius);
|
|
109352
|
+
const body = text13.slice(from, to).replace(/\s+/g, " ").trim();
|
|
109353
|
+
return `${from > 0 ? "\u2026" : ""}${body}${to < text13.length ? "\u2026" : ""}`;
|
|
108824
109354
|
}
|
|
108825
109355
|
|
|
108826
109356
|
// ../../packages/host-core/dist/session-search/text-cache.js
|
|
@@ -108876,10 +109406,10 @@ function createTextCache(baseDir) {
|
|
|
108876
109406
|
const nl = buf.lastIndexOf(10, end2 - 1);
|
|
108877
109407
|
end2 = nl >= at ? nl + 1 : Math.max(end2, buf.indexOf(10, end2) + 1 || buf.length);
|
|
108878
109408
|
}
|
|
108879
|
-
const { text:
|
|
109409
|
+
const { text: text13, bytes: bytes3 } = completeLines(buf.subarray(at, end2));
|
|
108880
109410
|
if (bytes3 === 0)
|
|
108881
109411
|
break;
|
|
108882
|
-
const out = extractSession(
|
|
109412
|
+
const out = extractSession(text13, { ...hints, text: "" });
|
|
108883
109413
|
if (out.text)
|
|
108884
109414
|
texts.push(out.text);
|
|
108885
109415
|
hints = out;
|
|
@@ -108887,9 +109417,9 @@ function createTextCache(baseDir) {
|
|
|
108887
109417
|
}
|
|
108888
109418
|
return { extraction: { ...hints, text: "", consumed: at }, texts, bytes: at };
|
|
108889
109419
|
}
|
|
108890
|
-
async function writeText(file2,
|
|
109420
|
+
async function writeText(file2, text13) {
|
|
108891
109421
|
const tmp = `${file2}.${process.pid}.${Date.now()}.tmp`;
|
|
108892
|
-
await writeFile14(tmp,
|
|
109422
|
+
await writeFile14(tmp, text13, { mode: 384 });
|
|
108893
109423
|
await rename5(tmp, file2);
|
|
108894
109424
|
}
|
|
108895
109425
|
async function extractWhole(file2, entry) {
|
|
@@ -108916,9 +109446,9 @@ function createTextCache(baseDir) {
|
|
|
108916
109446
|
return null;
|
|
108917
109447
|
}
|
|
108918
109448
|
const main2 = extractChunked(raw, fromArchive.extraction);
|
|
108919
|
-
const
|
|
109449
|
+
const text13 = [...fromArchive.texts, ...main2.texts].join("\n");
|
|
108920
109450
|
const textFile = entry?.textFile ?? textFileFor(file2.path);
|
|
108921
|
-
await writeText(join65(dir2, textFile),
|
|
109451
|
+
await writeText(join65(dir2, textFile), text13);
|
|
108922
109452
|
const { text: _t, consumed: _c, ...hints } = main2.extraction;
|
|
108923
109453
|
return {
|
|
108924
109454
|
path: file2.path,
|
|
@@ -109100,8 +109630,8 @@ function createSessionSearch(deps) {
|
|
|
109100
109630
|
continue;
|
|
109101
109631
|
const index = indexed.get(id);
|
|
109102
109632
|
const title = entry.hints.customTitle ?? index?.title ?? entry.hints.firstPrompt ?? entry.hints.aiTitle;
|
|
109103
|
-
const
|
|
109104
|
-
const inBody = matcher.exec(
|
|
109633
|
+
const text13 = await cache6.text(entry);
|
|
109634
|
+
const inBody = matcher.exec(text13);
|
|
109105
109635
|
const inTitle = title ? matcher.test(title) : false;
|
|
109106
109636
|
if (!inBody && !inTitle)
|
|
109107
109637
|
continue;
|
|
@@ -109113,7 +109643,7 @@ function createSessionSearch(deps) {
|
|
|
109113
109643
|
lastModified: entry.hints.lastTimestamp ?? entry.mtimeMs,
|
|
109114
109644
|
...cwd ? { cwd } : {},
|
|
109115
109645
|
engineId,
|
|
109116
|
-
...inBody ? { snippet: snippetAt(
|
|
109646
|
+
...inBody ? { snippet: snippetAt(text13, inBody.index, inBody[0].length) } : {}
|
|
109117
109647
|
};
|
|
109118
109648
|
run9.hits.push(hit);
|
|
109119
109649
|
found.push(hit);
|
|
@@ -111281,12 +111811,12 @@ var RdeskSessionManager = class {
|
|
|
111281
111811
|
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:muted", mic: !!mute.mic, systemAudio: !!mute.systemAudio });
|
|
111282
111812
|
}
|
|
111283
111813
|
/** Host operator → viewer: send an in-session chat line. No-op if the session is gone. */
|
|
111284
|
-
sendChat(sessionId,
|
|
111814
|
+
sendChat(sessionId, text13) {
|
|
111285
111815
|
const s = this.sessions.get(sessionId);
|
|
111286
111816
|
if (!s)
|
|
111287
111817
|
return;
|
|
111288
|
-
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:chat", text:
|
|
111289
|
-
this.audit({ event: "chat", sessionId, detail: `host: ${
|
|
111818
|
+
this.deps.sendControl(sessionId, s.viewer.clientId, { type: "rdesk:chat", text: text13, from: "host", at: Date.now() });
|
|
111819
|
+
this.audit({ event: "chat", sessionId, detail: `host: ${text13.slice(0, 80)}` });
|
|
111290
111820
|
}
|
|
111291
111821
|
/** Switch the captured display. */
|
|
111292
111822
|
async setMonitor(sessionId, monitorId) {
|
|
@@ -111318,9 +111848,9 @@ var RdeskSessionManager = class {
|
|
|
111318
111848
|
return this.sendKeys(sessionId, msg.combo);
|
|
111319
111849
|
if (msg.type === "rdesk:chat") {
|
|
111320
111850
|
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:
|
|
111851
|
+
const text13 = msg.text.slice(0, 4e3);
|
|
111852
|
+
this.deps.onChat?.({ sessionId, viewerName: s?.viewer.name, text: text13 });
|
|
111853
|
+
this.audit({ event: "chat", sessionId, detail: text13.slice(0, 80) });
|
|
111324
111854
|
return;
|
|
111325
111855
|
}
|
|
111326
111856
|
if (msg.type === "rdesk:av") {
|
|
@@ -111963,8 +112493,8 @@ function waylandInputRunner(p, screen) {
|
|
|
111963
112493
|
async scroll(o) {
|
|
111964
112494
|
p.pointerAxis(o.dx ?? 0, o.dy ?? 0);
|
|
111965
112495
|
},
|
|
111966
|
-
async typeText(
|
|
111967
|
-
for (const ch of
|
|
112496
|
+
async typeText(text13) {
|
|
112497
|
+
for (const ch of text13) {
|
|
111968
112498
|
const ks = charKeysym(ch);
|
|
111969
112499
|
if (!ks)
|
|
111970
112500
|
continue;
|
|
@@ -112138,11 +112668,11 @@ var TesseractEngine = class {
|
|
|
112138
112668
|
onInput: (ev) => void this.injector?.apply(ev),
|
|
112139
112669
|
// Clipboard sync (Phase 6): write the viewer's clipboard onto the host so ⌘V pastes
|
|
112140
112670
|
// into the remote machine. Gated by control access (view-only never writes).
|
|
112141
|
-
onClipboard: (
|
|
112671
|
+
onClipboard: (text13) => {
|
|
112142
112672
|
if (this.access === "control") {
|
|
112143
112673
|
const el2 = electronModule();
|
|
112144
112674
|
try {
|
|
112145
|
-
el2?.clipboard?.writeText(
|
|
112675
|
+
el2?.clipboard?.writeText(text13);
|
|
112146
112676
|
} catch {
|
|
112147
112677
|
}
|
|
112148
112678
|
}
|
|
@@ -114560,8 +115090,8 @@ async function startLocalServer(opts) {
|
|
|
114560
115090
|
if (!vc || !vc.isPresentMode)
|
|
114561
115091
|
return null;
|
|
114562
115092
|
return {
|
|
114563
|
-
injectContext: (
|
|
114564
|
-
ask: (
|
|
115093
|
+
injectContext: (text13) => vc.injectPresentContext(text13),
|
|
115094
|
+
ask: (text13) => vc.askPresent(text13)
|
|
114565
115095
|
};
|
|
114566
115096
|
});
|
|
114567
115097
|
const unregisterSink = registerAgentSink((msg, origin2) => {
|
|
@@ -115685,7 +116215,7 @@ async function getPeerIdentityPub(opts) {
|
|
|
115685
116215
|
}
|
|
115686
116216
|
|
|
115687
116217
|
// ../../packages/host-core/dist/mesh/node.js
|
|
115688
|
-
import { createSocket
|
|
116218
|
+
import { createSocket } from "node:dgram";
|
|
115689
116219
|
import { createRequire as createRequire4 } from "node:module";
|
|
115690
116220
|
init_credentials();
|
|
115691
116221
|
|
|
@@ -116212,6 +116742,8 @@ async function netdNodeStatus(meshId) {
|
|
|
116212
116742
|
relayed: strs("relayed"),
|
|
116213
116743
|
policyEpoch: num2("policyEpoch"),
|
|
116214
116744
|
revoked: b.revoked === true,
|
|
116745
|
+
lan: b.lan === true,
|
|
116746
|
+
lanError: typeof b.lanError === "string" ? b.lanError : null,
|
|
116215
116747
|
bundleStaleInMs: typeof b.bundleStaleInMs === "number" ? b.bundleStaleInMs : null,
|
|
116216
116748
|
lastError: typeof b.lastError === "string" ? b.lastError : null,
|
|
116217
116749
|
localStaticPub: Uint8Array.from(Buffer.from(pubHex, "hex")),
|
|
@@ -116394,6 +116926,15 @@ var NetdEngine = class {
|
|
|
116394
116926
|
get srflx() {
|
|
116395
116927
|
return this.#snapshot?.srflx ?? null;
|
|
116396
116928
|
}
|
|
116929
|
+
/** Whether the HELPER's LAN discovery joined the multicast group — it owns that socket
|
|
116930
|
+
* now, so this is the only honest source for it. */
|
|
116931
|
+
get lan() {
|
|
116932
|
+
return this.#snapshot?.lan === true;
|
|
116933
|
+
}
|
|
116934
|
+
/** Why LAN discovery is off, when it is — the helper records the step that failed. */
|
|
116935
|
+
get lanError() {
|
|
116936
|
+
return this.#snapshot?.lanError ?? null;
|
|
116937
|
+
}
|
|
116397
116938
|
/** The same over IPv6, advertised alongside rather than instead. */
|
|
116398
116939
|
get srflx6() {
|
|
116399
116940
|
return this.#snapshot?.srflx6 ?? null;
|
|
@@ -116489,127 +117030,6 @@ ${ts}`);
|
|
|
116489
117030
|
}
|
|
116490
117031
|
}
|
|
116491
117032
|
|
|
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
117033
|
// ../../packages/host-core/dist/mesh/endpoints.js
|
|
116614
117034
|
function inRange(range, addr) {
|
|
116615
117035
|
if (addr.length !== range.addr.length)
|
|
@@ -116886,7 +117306,6 @@ var MeshNode = class {
|
|
|
116886
117306
|
* can be offered a choice that has somewhere to go.
|
|
116887
117307
|
*/
|
|
116888
117308
|
#exitNodes = /* @__PURE__ */ new Map();
|
|
116889
|
-
#lan = null;
|
|
116890
117309
|
#offRejoin = null;
|
|
116891
117310
|
#statusTimer = null;
|
|
116892
117311
|
/**
|
|
@@ -116936,7 +117355,8 @@ var MeshNode = class {
|
|
|
116936
117355
|
enrolled: this.#identity !== null || this.#loadIdentity() !== null,
|
|
116937
117356
|
running: this.#engine !== null,
|
|
116938
117357
|
port: this.#port,
|
|
116939
|
-
lan: this.#lan
|
|
117358
|
+
lan: this.#engine instanceof NetdEngine ? this.#engine.lan : false,
|
|
117359
|
+
lanError: this.#engine instanceof NetdEngine ? this.#engine.lanError : null,
|
|
116940
117360
|
reachableAt: this.#engine instanceof NetdEngine ? [this.#engine.mapped, this.#engine.srflx, this.#engine.srflx6].filter((x) => x !== null).join(", ") || null : null,
|
|
116941
117361
|
// Only the helper publishes names: writing the machine's name table needs root, and
|
|
116942
117362
|
// the roster comes from the engine the helper runs. An in-process engine has a roster
|
|
@@ -117024,7 +117444,6 @@ var MeshNode = class {
|
|
|
117024
117444
|
onUp: (port) => {
|
|
117025
117445
|
this.#port = port;
|
|
117026
117446
|
this.#join();
|
|
117027
|
-
this.#startLan();
|
|
117028
117447
|
this.#publishStatus();
|
|
117029
117448
|
}
|
|
117030
117449
|
});
|
|
@@ -117051,7 +117470,6 @@ var MeshNode = class {
|
|
|
117051
117470
|
this.#identity = id;
|
|
117052
117471
|
if (!inNetd) {
|
|
117053
117472
|
this.#openSocket();
|
|
117054
|
-
this.#startLan();
|
|
117055
117473
|
}
|
|
117056
117474
|
this.#offRejoin = onMeshRejoin(() => this.#join());
|
|
117057
117475
|
this.#publishStatus();
|
|
@@ -117096,11 +117514,6 @@ var MeshNode = class {
|
|
|
117096
117514
|
this.#published = false;
|
|
117097
117515
|
}
|
|
117098
117516
|
this.#runningMeshDir = null;
|
|
117099
|
-
try {
|
|
117100
|
-
this.#lan?.stop();
|
|
117101
|
-
} catch {
|
|
117102
|
-
}
|
|
117103
|
-
this.#lan = null;
|
|
117104
117517
|
try {
|
|
117105
117518
|
this.#sock?.close();
|
|
117106
117519
|
} catch {
|
|
@@ -117141,7 +117554,7 @@ var MeshNode = class {
|
|
|
117141
117554
|
return Number.isInteger(port) && port > 0 ? { host: ep.slice(0, i), port } : null;
|
|
117142
117555
|
}
|
|
117143
117556
|
#openSocket() {
|
|
117144
|
-
const sock =
|
|
117557
|
+
const sock = createSocket({ type: "udp6", ipv6Only: false, reuseAddr: true });
|
|
117145
117558
|
sock.on("message", (msg, rinfo) => {
|
|
117146
117559
|
if (!this.#engine)
|
|
117147
117560
|
return;
|
|
@@ -117166,54 +117579,20 @@ var MeshNode = class {
|
|
|
117166
117579
|
sock.unref?.();
|
|
117167
117580
|
this.#sock = sock;
|
|
117168
117581
|
}
|
|
117169
|
-
|
|
117582
|
+
/* LAN discovery used to live here, as a multicast beacon in this process
|
|
117583
|
+
* (`./lan.ts`). It has MOVED INTO THE HELPER (`crates/tsmesh-netd/src/lan.rs`,
|
|
117584
|
+
* frame in `tsmesh_proto::lan`).
|
|
117170
117585
|
*
|
|
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.
|
|
117586
|
+
* It had to. The beacon only ran while this app was running, so a headless machine --
|
|
117587
|
+
* a server, the thing the network exists to reach -- could not find a peer sharing its
|
|
117588
|
+
* switch. And on the netd path the app was announcing a port held by a different
|
|
117589
|
+
* process entirely. The helper starts at boot with no app and owns the socket, so the
|
|
117590
|
+
* beacon belongs beside it.
|
|
117192
117591
|
*
|
|
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
|
-
}
|
|
117592
|
+
* Moved rather than duplicated: two implementations of a parser that reads
|
|
117593
|
+
* unauthenticated multicast from every device on the segment is the one risk
|
|
117594
|
+
* docs/MESH.md names as unacceptable.
|
|
117595
|
+
*/
|
|
117217
117596
|
#subscribe() {
|
|
117218
117597
|
this.#unsubscribe = onMesh((m) => this.#onHint(m));
|
|
117219
117598
|
}
|
|
@@ -117796,11 +118175,11 @@ async function call2(path6, init, auth = true) {
|
|
|
117796
118175
|
} catch (e) {
|
|
117797
118176
|
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
117798
118177
|
}
|
|
117799
|
-
const
|
|
118178
|
+
const text13 = await res.text();
|
|
117800
118179
|
if (!res.ok) {
|
|
117801
|
-
let detail =
|
|
118180
|
+
let detail = text13.slice(0, 500);
|
|
117802
118181
|
try {
|
|
117803
|
-
const parsed = JSON.parse(
|
|
118182
|
+
const parsed = JSON.parse(text13);
|
|
117804
118183
|
if (parsed.message)
|
|
117805
118184
|
detail = Array.isArray(parsed.message) ? parsed.message.join("; ") : parsed.message;
|
|
117806
118185
|
} catch {
|
|
@@ -117808,7 +118187,7 @@ async function call2(path6, init, auth = true) {
|
|
|
117808
118187
|
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
117809
118188
|
}
|
|
117810
118189
|
try {
|
|
117811
|
-
return { ok: true, data:
|
|
118190
|
+
return { ok: true, data: text13 ? JSON.parse(text13) : {} };
|
|
117812
118191
|
} catch {
|
|
117813
118192
|
return fail3("server", "the server sent something that is not JSON");
|
|
117814
118193
|
}
|
|
@@ -118010,18 +118389,18 @@ async function postJoin(origin, body) {
|
|
|
118010
118389
|
} catch (e) {
|
|
118011
118390
|
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
118012
118391
|
}
|
|
118013
|
-
const
|
|
118392
|
+
const text13 = await res.text();
|
|
118014
118393
|
if (!res.ok) {
|
|
118015
|
-
let detail =
|
|
118394
|
+
let detail = text13.slice(0, 500);
|
|
118016
118395
|
try {
|
|
118017
|
-
const parsed = JSON.parse(
|
|
118396
|
+
const parsed = JSON.parse(text13);
|
|
118018
118397
|
if (parsed.message)
|
|
118019
118398
|
detail = String(parsed.message);
|
|
118020
118399
|
} catch {
|
|
118021
118400
|
}
|
|
118022
118401
|
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
118023
118402
|
}
|
|
118024
|
-
return { ok: true, data: JSON.parse(
|
|
118403
|
+
return { ok: true, data: JSON.parse(text13) };
|
|
118025
118404
|
}
|
|
118026
118405
|
async function enrolWithCode(args) {
|
|
118027
118406
|
return enrolWith(args.name, async (staticPub, sigPub, name) => postJoin(args.origin, { code: args.code, name, staticPub, sigPub }), resolveOrigin(args.origin), args.fromHostname);
|
|
@@ -118881,9 +119260,9 @@ import { pipeline } from "node:stream/promises";
|
|
|
118881
119260
|
|
|
118882
119261
|
// ../../packages/host-core/dist/drops/crypto.js
|
|
118883
119262
|
import { Transform } from "node:stream";
|
|
118884
|
-
var
|
|
119263
|
+
var MAGIC = Buffer.from("TSD1", "ascii");
|
|
118885
119264
|
var NONCE_BYTES = 12;
|
|
118886
|
-
var HEADER_BYTES =
|
|
119265
|
+
var HEADER_BYTES = MAGIC.length + NONCE_BYTES;
|
|
118887
119266
|
var FRAME_BYTES = 1024 * 1024;
|
|
118888
119267
|
var TAG_BYTES = 16;
|
|
118889
119268
|
var MAX_FRAME_CIPHERTEXT = FRAME_BYTES + TAG_BYTES + 1024;
|
|
@@ -118964,9 +119343,9 @@ function decryptStream(source, keyRaw) {
|
|
|
118964
119343
|
cb();
|
|
118965
119344
|
return;
|
|
118966
119345
|
}
|
|
118967
|
-
if (!head.subarray(0,
|
|
119346
|
+
if (!head.subarray(0, MAGIC.length).equals(MAGIC))
|
|
118968
119347
|
throw new Error("not an encrypted drop");
|
|
118969
|
-
base = Buffer.from(head.subarray(
|
|
119348
|
+
base = Buffer.from(head.subarray(MAGIC.length, HEADER_BYTES));
|
|
118970
119349
|
q.consume(HEADER_BYTES);
|
|
118971
119350
|
key2 = await importKey(keyRaw);
|
|
118972
119351
|
}
|
|
@@ -119136,7 +119515,7 @@ function createChatAgentRunner(deps) {
|
|
|
119136
119515
|
const backend2 = await getSharedBackend();
|
|
119137
119516
|
const clientRequestId = `chat-agent-${randomUUID32()}`;
|
|
119138
119517
|
return new Promise((resolve16, reject) => {
|
|
119139
|
-
let
|
|
119518
|
+
let text13 = "";
|
|
119140
119519
|
let settled = false;
|
|
119141
119520
|
const finish2 = (fn) => {
|
|
119142
119521
|
if (settled)
|
|
@@ -119150,13 +119529,13 @@ function createChatAgentRunner(deps) {
|
|
|
119150
119529
|
}
|
|
119151
119530
|
fn();
|
|
119152
119531
|
};
|
|
119153
|
-
const timer2 = setTimeout(() => finish2(() =>
|
|
119532
|
+
const timer2 = setTimeout(() => finish2(() => text13.trim() ? resolve16(text13) : reject(new Error("the agent took too long"))), TURN_TIMEOUT_MS);
|
|
119154
119533
|
let posting = false;
|
|
119155
119534
|
let lastSent = "";
|
|
119156
119535
|
const tick = setInterval(() => {
|
|
119157
119536
|
if (posting || !onPartial)
|
|
119158
119537
|
return;
|
|
119159
|
-
const snapshot4 =
|
|
119538
|
+
const snapshot4 = text13.trim();
|
|
119160
119539
|
if (!snapshot4 || snapshot4 === lastSent)
|
|
119161
119540
|
return;
|
|
119162
119541
|
lastSent = snapshot4;
|
|
@@ -119172,9 +119551,9 @@ function createChatAgentRunner(deps) {
|
|
|
119172
119551
|
return;
|
|
119173
119552
|
if (m.type === "chat:stream") {
|
|
119174
119553
|
if ((m.kind === "text" || m.kind === void 0) && m.delta)
|
|
119175
|
-
|
|
119554
|
+
text13 += m.delta;
|
|
119176
119555
|
} else if (m.type === "chat:complete") {
|
|
119177
|
-
finish2(() => resolve16(
|
|
119556
|
+
finish2(() => resolve16(text13));
|
|
119178
119557
|
} else if (m.type === "chat:error") {
|
|
119179
119558
|
finish2(() => reject(new Error(m.message ?? m.error ?? "the agent errored")));
|
|
119180
119559
|
}
|
|
@@ -121334,7 +121713,7 @@ function backoff2() {
|
|
|
121334
121713
|
var daemonClipboardSync = null;
|
|
121335
121714
|
var REFRESH_INTERVAL_MS2 = 12 * 60 * 60 * 1e3;
|
|
121336
121715
|
async function runDaemon(opts = {}) {
|
|
121337
|
-
const
|
|
121716
|
+
const VERSION2 = opts.version ?? process.env.CCB_DAEMON_VERSION ?? "dev";
|
|
121338
121717
|
const TAG = opts.tag ?? "host-daemon";
|
|
121339
121718
|
const KIND = opts.kind ?? "app";
|
|
121340
121719
|
const log10 = (...args) => console.log(`[${TAG} ${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args);
|
|
@@ -121410,14 +121789,14 @@ async function runDaemon(opts = {}) {
|
|
|
121410
121789
|
if (!ownsMachine)
|
|
121411
121790
|
return;
|
|
121412
121791
|
try {
|
|
121413
|
-
writeFileSync44(statusFile2(), JSON.stringify({ pid: process.pid, startedAt: OUR_STARTED_AT, role: process.env.CCB_RDESK_ROLE ?? "host", kind: KIND, version:
|
|
121792
|
+
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
121793
|
chmodSync8(statusFile2(), 384);
|
|
121415
121794
|
} catch {
|
|
121416
121795
|
}
|
|
121417
121796
|
}
|
|
121418
121797
|
const standaloneViewer = process.env.CCB_RDESK_ROLE === "client";
|
|
121419
121798
|
if (!standaloneViewer) {
|
|
121420
|
-
registerSelfAsDaemon(
|
|
121799
|
+
registerSelfAsDaemon(VERSION2);
|
|
121421
121800
|
if (KIND === "app") {
|
|
121422
121801
|
try {
|
|
121423
121802
|
await evictCliAgent(log10);
|
|
@@ -121625,7 +122004,7 @@ async function runDaemon(opts = {}) {
|
|
|
121625
122004
|
unregisterSelfAsDaemon();
|
|
121626
122005
|
process.exit(code);
|
|
121627
122006
|
}
|
|
121628
|
-
startSystemEvents({ version:
|
|
122007
|
+
startSystemEvents({ version: VERSION2, log: (m) => log10(m) });
|
|
121629
122008
|
const mergedProcess = opts.merged === true;
|
|
121630
122009
|
const deliberateMergedQuit = () => !!globalThis.__ccbDeliberateQuit;
|
|
121631
122010
|
const onTermSignal = (sig) => {
|
|
@@ -121892,7 +122271,7 @@ async function runDaemon(opts = {}) {
|
|
|
121892
122271
|
if (!creds3) {
|
|
121893
122272
|
timer2 = setInterval(() => writeStatus2({ deviceId: deviceId3, connected: false, localOnly: true }), 6e4);
|
|
121894
122273
|
writeStatus2({ deviceId: deviceId3, connected: false, localOnly: true });
|
|
121895
|
-
log10(`started LOCAL-ONLY (no identity yet) \u2014 local :${localInfo?.localPort ?? "off"}, version ${
|
|
122274
|
+
log10(`started LOCAL-ONLY (no identity yet) \u2014 local :${localInfo?.localPort ?? "off"}, version ${VERSION2}; will keep trying`);
|
|
121896
122275
|
const watch4 = watchForIdentity({ attempt: acquireIdentity, log: (m) => log10(m) });
|
|
121897
122276
|
identityWatch = watch4;
|
|
121898
122277
|
setDaemonIdentityReload(async () => {
|
|
@@ -122153,14 +122532,14 @@ async function runDaemon(opts = {}) {
|
|
|
122153
122532
|
// On macOS the notification carries an inline REPLY box (hasReply) whose text is sent
|
|
122154
122533
|
// straight back via sendChat — a full operator chat loop with no extra window. Off-mac (no
|
|
122155
122534
|
// hasReply) it's receive-only for now; the daemon log always records it as a fallback.
|
|
122156
|
-
onChat: ({ sessionId, viewerName, text:
|
|
122535
|
+
onChat: ({ sessionId, viewerName, text: text13 }) => {
|
|
122157
122536
|
const NotifCtor = electronModule()?.Notification;
|
|
122158
122537
|
if (!NotifCtor) {
|
|
122159
|
-
log10(`[rdesk chat] ${viewerName ?? "viewer"}: ${
|
|
122538
|
+
log10(`[rdesk chat] ${viewerName ?? "viewer"}: ${text13}`);
|
|
122160
122539
|
return;
|
|
122161
122540
|
}
|
|
122162
122541
|
try {
|
|
122163
|
-
const n = new NotifCtor({ title: `${viewerName ?? "Remote viewer"} \u2014 remote desktop`, body:
|
|
122542
|
+
const n = new NotifCtor({ title: `${viewerName ?? "Remote viewer"} \u2014 remote desktop`, body: text13, hasReply: true, replyPlaceholder: "Reply\u2026" });
|
|
122164
122543
|
n.on("reply", (_e, reply3) => {
|
|
122165
122544
|
const r = typeof reply3 === "string" ? reply3.trim() : "";
|
|
122166
122545
|
if (r)
|
|
@@ -122500,7 +122879,7 @@ async function runDaemon(opts = {}) {
|
|
|
122500
122879
|
log10("e2e responder init failed (staying plaintext)", err2.message);
|
|
122501
122880
|
}
|
|
122502
122881
|
}
|
|
122503
|
-
startControlLink({ deviceId: c.deviceId, power: createNodePowerController(), tokenSource, version:
|
|
122882
|
+
startControlLink({ deviceId: c.deviceId, power: createNodePowerController(), tokenSource, version: VERSION2, e2e }, hooks2);
|
|
122504
122883
|
offRecovery = onSystemEvent(({ event }) => {
|
|
122505
122884
|
const suspended = isSuspensionSignal(event);
|
|
122506
122885
|
if (suspended)
|
|
@@ -122601,7 +122980,7 @@ async function runDaemon(opts = {}) {
|
|
|
122601
122980
|
}
|
|
122602
122981
|
}
|
|
122603
122982
|
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 ${
|
|
122983
|
+
log10(`started \u2014 device ${c.deviceId}, ${who}, relay ${c.backendOrigin}, local :${localInfo?.localPort ?? "off"}, version ${VERSION2}`);
|
|
122605
122984
|
await refresh();
|
|
122606
122985
|
timer2 = setInterval(() => {
|
|
122607
122986
|
void refresh();
|
|
@@ -122709,8 +123088,8 @@ function installOwnerUid(env = process.env, self2 = typeof process.getuid === "f
|
|
|
122709
123088
|
}
|
|
122710
123089
|
return self2;
|
|
122711
123090
|
}
|
|
122712
|
-
function parseOwnerUid(
|
|
122713
|
-
const m = /--owner-uid(?:<\/string>)?[\s=]*(?:<string>)?(\d+)/.exec(
|
|
123091
|
+
function parseOwnerUid(text13) {
|
|
123092
|
+
const m = /--owner-uid(?:<\/string>)?[\s=]*(?:<string>)?(\d+)/.exec(text13);
|
|
122714
123093
|
if (!m)
|
|
122715
123094
|
return void 0;
|
|
122716
123095
|
const uid = Number(m[1]);
|
|
@@ -122767,8 +123146,8 @@ function bundleIdForExec(exec2) {
|
|
|
122767
123146
|
return void 0;
|
|
122768
123147
|
}
|
|
122769
123148
|
}
|
|
122770
|
-
function parseAssociatedBundleId(
|
|
122771
|
-
const m = /<key>AssociatedBundleIdentifiers<\/key>\s*(?:<array>\s*)?<string>([^<]*)<\/string>/.exec(
|
|
123149
|
+
function parseAssociatedBundleId(text13) {
|
|
123150
|
+
const m = /<key>AssociatedBundleIdentifiers<\/key>\s*(?:<array>\s*)?<string>([^<]*)<\/string>/.exec(text13);
|
|
122772
123151
|
const id = m?.[1]?.trim();
|
|
122773
123152
|
return id && looksLikeBundleId(id) ? id : void 0;
|
|
122774
123153
|
}
|
|
@@ -122829,10 +123208,25 @@ ${args}
|
|
|
122829
123208
|
<integer>30</integer>
|
|
122830
123209
|
<key>ProcessType</key>
|
|
122831
123210
|
<string>Interactive</string>
|
|
123211
|
+
<!-- /dev/null, NOT netd.log, and this is load-bearing.
|
|
123212
|
+
|
|
123213
|
+
These two keys used to point at netd.log, and launchd does not rotate what it
|
|
123214
|
+
redirects \u2014 so the file grew for the life of the install. The same omission on
|
|
123215
|
+
Windows reached 136 GB on a CI runner and hung two hours of release builds while
|
|
123216
|
+
looking like an npm problem; macOS had it too and nobody had looked.
|
|
123217
|
+
|
|
123218
|
+
netd now owns netd.log itself and rotates it (tsmesh_netd::logfile, 8 MiB, one
|
|
123219
|
+
previous generation). Leaving launchd pointed at the same path would be WORSE than
|
|
123220
|
+
the bug: after netd renames the file, launchd's descriptor still refers to the
|
|
123221
|
+
renamed inode, so it would append to the "previous generation" forever and no
|
|
123222
|
+
rotation could ever reclaim it. One writer, or none.
|
|
123223
|
+
|
|
123224
|
+
Nothing is lost by discarding this stream: everything netd logs goes through its own
|
|
123225
|
+
sink, and a panic is routed there too by a hook installed with the log file. -->
|
|
122832
123226
|
<key>StandardErrorPath</key>
|
|
122833
|
-
<string
|
|
123227
|
+
<string>/dev/null</string>
|
|
122834
123228
|
<key>StandardOutPath</key>
|
|
122835
|
-
<string
|
|
123229
|
+
<string>/dev/null</string>
|
|
122836
123230
|
</dict>
|
|
122837
123231
|
</plist>
|
|
122838
123232
|
`;
|
|
@@ -122920,9 +123314,9 @@ ${plist}TESSERACT_PLIST_EOF`,
|
|
|
122920
123314
|
async state() {
|
|
122921
123315
|
if (!existsSync50(PLIST))
|
|
122922
123316
|
return { installed: false, running: false };
|
|
122923
|
-
const
|
|
122924
|
-
const owner = parseOwnerUid(
|
|
122925
|
-
const assoc = parseAssociatedBundleId(
|
|
123317
|
+
const text13 = readFileSync59(PLIST, "utf8");
|
|
123318
|
+
const owner = parseOwnerUid(text13);
|
|
123319
|
+
const assoc = parseAssociatedBundleId(text13);
|
|
122926
123320
|
const running2 = await netdAvailable();
|
|
122927
123321
|
return {
|
|
122928
123322
|
installed: true,
|
|
@@ -123559,10 +123953,10 @@ import { dirname as dirname42, join as join94 } from "node:path";
|
|
|
123559
123953
|
import { homedir as homedir16, userInfo as userInfo2 } from "node:os";
|
|
123560
123954
|
|
|
123561
123955
|
// ../../packages/host-core/dist/service/legacy-label.js
|
|
123562
|
-
function definitionIsCli(
|
|
123563
|
-
if (!
|
|
123956
|
+
function definitionIsCli(text13) {
|
|
123957
|
+
if (!text13)
|
|
123564
123958
|
return false;
|
|
123565
|
-
return /node_modules[/\\]tesseract-agent[/\\]/.test(
|
|
123959
|
+
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
123960
|
}
|
|
123567
123961
|
|
|
123568
123962
|
// ../../packages/host-core/dist/service/launchd.js
|
|
@@ -124689,7 +125083,9 @@ async function meshCommand(rest, flags) {
|
|
|
124689
125083
|
return;
|
|
124690
125084
|
}
|
|
124691
125085
|
console.log(`node: running on UDP port ${s.port ?? "?"}`);
|
|
124692
|
-
console.log(
|
|
125086
|
+
console.log(
|
|
125087
|
+
`node: LAN discovery ${s.lan ? "on" : `off \u2014 ${s.lanError ?? "no reason was recorded"}`}`
|
|
125088
|
+
);
|
|
124693
125089
|
if (!("reachableAt" in s)) {
|
|
124694
125090
|
console.log("reachable at: unknown \u2014 the background service predates this CLI; restart it and ask again");
|
|
124695
125091
|
} else {
|