perchai-cli 2.4.16 → 2.4.17

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.
Files changed (2) hide show
  1. package/dist/perch.mjs +564 -336
  2. package/package.json +1 -1
package/dist/perch.mjs CHANGED
@@ -76005,7 +76005,188 @@ var init_userFacingErrors = __esm({
76005
76005
  }
76006
76006
  });
76007
76007
 
76008
- // lib/perchTerminal/toolDisplayNames.ts
76008
+ // features/perchTerminal/runtime/toolNames.ts
76009
+ var TOOL_NAMES, BROWSER_OPERATOR_TOOL_NAMES, BROWSER_RESEARCH_TOOL_NAMES, VERIFIED_SURFACE_SKILL_NAMES, DELIVERY_OPERATOR_TOOL_NAMES;
76010
+ var init_toolNames = __esm({
76011
+ "features/perchTerminal/runtime/toolNames.ts"() {
76012
+ "use strict";
76013
+ TOOL_NAMES = {
76014
+ // Desktop tools (require Perch AI Desktop; filesystem policy validates paths per call)
76015
+ validateWorkspaceRoot: "validateWorkspaceRoot",
76016
+ bash: "bash",
76017
+ runBashTerminalCommand: "runBashTerminalCommand",
76018
+ glob: "glob",
76019
+ grep: "grep",
76020
+ readLocalFile: "readLocalFile",
76021
+ writeLocalFile: "writeLocalFile",
76022
+ moveLocalFile: "moveLocalFile",
76023
+ copyLocalFile: "copyLocalFile",
76024
+ createDirectory: "createDirectory",
76025
+ deleteLocalFile: "deleteLocalFile",
76026
+ printFile: "printFile",
76027
+ editLocalFile: "editLocalFile",
76028
+ statPath: "statPath",
76029
+ prepareSandboxInputs: "prepareSandboxInputs",
76030
+ readProjectMemory: "readProjectMemory",
76031
+ saveToMemory: "saveToMemory",
76032
+ addProjectRule: "addProjectRule",
76033
+ writePerchManual: "writePerchManual",
76034
+ getProjectRules: "getProjectRules",
76035
+ listLocalSources: "listLocalSources",
76036
+ readLocalSourceFile: "readLocalSourceFile",
76037
+ generateAPAuditPacket: "generateAPAuditPacket",
76038
+ prepareAPEvidence: "prepare_ap_evidence",
76039
+ queryAPCases: "query_ap_cases",
76040
+ renderAPControlGraph: "render_ap_control_graph",
76041
+ runManagedPlaybook: "runManagedPlaybook",
76042
+ runSuite: "run_suite",
76043
+ listSuiteCatalog: "list_suite_catalog",
76044
+ proposeSuitePlan: "propose_suite_plan",
76045
+ executeSuitePlan: "execute_suite_plan",
76046
+ proposeWork: "propose_work",
76047
+ executeWork: "execute_work",
76048
+ sendWorkerMessage: "send_worker_message",
76049
+ taskStop: "task_stop",
76050
+ spawnWorker: "spawn_worker",
76051
+ dispatchAgent: "dispatch_agent",
76052
+ runSandboxAnalysis: "runSandboxAnalysis",
76053
+ runSandboxCode: "run_sandbox_code",
76054
+ safeBrowserAction: "safeBrowserAction",
76055
+ // Operator primitives — drive the browser turn-by-turn (observe→act). Each
76056
+ // result embeds a fresh accessibility snapshot + URL so the model re-observes
76057
+ // after every action. Clipboard-free: typing uses direct key events.
76058
+ browserNavigate: "browser_navigate",
76059
+ browserExecuteTask: "browser_execute_task",
76060
+ browserObserve: "browser_observe",
76061
+ browserClick: "browser_click",
76062
+ browserType: "browser_type",
76063
+ browserVisualClick: "browser_visual_click",
76064
+ browserFocusType: "browser_focus_type",
76065
+ browserPressKey: "browser_press_key",
76066
+ browserRead: "browser_read",
76067
+ browserWait: "browser_wait",
76068
+ browserHandleDialog: "browser_handle_dialog",
76069
+ // Browser research tools — higher-level web research through the browser operator
76070
+ browserSearchWeb: "browser_search_web",
76071
+ browserReadPage: "browser_read_page",
76072
+ browserCollectSources: "browser_collect_sources",
76073
+ gmailSendEmail: "gmail_send_email",
76074
+ gmailSaveDraft: "gmail_save_draft",
76075
+ googleDocsCreate: "google_docs_create",
76076
+ googleDocsAppend: "google_docs_append",
76077
+ googleCalendarCreateEvent: "google_calendar_create_event",
76078
+ googleSheetsCreate: "google_sheets_create",
76079
+ googleSheetsAppendRows: "google_sheets_append_rows",
76080
+ // Verified surface skills — optional shortcuts for Google Workspace delivery.
76081
+ // Operator-first workers default to browser primitives and may use these
76082
+ // adapter wrappers once when they can return proof-based receipt verification.
76083
+ gmailSendEmailVerified: "gmail_send_email_verified",
76084
+ gmailSaveDraftVerified: "gmail_save_draft_verified",
76085
+ googleDocsCreateVerified: "google_docs_create_verified",
76086
+ googleCalendarCreateEventVerified: "google_calendar_create_event_verified",
76087
+ // Market desk tools (flag-gated: PERCH_MARKET_DESK=1)
76088
+ getMarketSignal: "get_market_signal",
76089
+ queryMarketSignalLog: "query_market_signal_log",
76090
+ explainMarketSignal: "explain_market_signal",
76091
+ listMarketStrategies: "list_market_strategies",
76092
+ runMarketBacktest: "run_market_backtest",
76093
+ getMarketTrackRecord: "get_market_track_record",
76094
+ // Native tools (always available; executed locally without Desktop bridge)
76095
+ ctxInspect: "ctxInspect",
76096
+ toolSearch: "toolSearch",
76097
+ configInspect: "configInspect",
76098
+ syntheticOutput: "syntheticOutput",
76099
+ todoWrite: "todoWrite",
76100
+ askUserQuestion: "askUserQuestion",
76101
+ proposePlan: "propose_plan",
76102
+ enterPlanMode: "enterPlanMode",
76103
+ exitPlanMode: "exitPlanMode",
76104
+ brief: "brief",
76105
+ listMcpServers: "listMcpServers",
76106
+ searchKnowledge: "searchKnowledge",
76107
+ // Unavailable tools (not executable in Perch Terminal Desktop; Supabase/web/sandbox)
76108
+ listSources: "listSources",
76109
+ readSource: "readSource",
76110
+ analyzeWorkbook: "analyzeWorkbook",
76111
+ extractDocument: "extractDocument",
76112
+ searchSources: "searchSources",
76113
+ semanticSearch: "semanticSearch",
76114
+ retrieveContext: "retrieveContext",
76115
+ diagnoseWorkspaceAccess: "diagnoseWorkspaceAccess",
76116
+ listIndexedSources: "listIndexedSources",
76117
+ searchWorkspaceSources: "searchWorkspaceSources",
76118
+ resolveSourceCandidates: "resolveSourceCandidates",
76119
+ inspectDocument: "inspectDocument",
76120
+ visionInspect: "visionInspect",
76121
+ extractDocumentSection: "extractDocumentSection",
76122
+ inspectWorkbookSheets: "inspectWorkbookSheets",
76123
+ compareEvidenceAcrossSources: "compareEvidenceAcrossSources",
76124
+ listArtifacts: "listArtifacts",
76125
+ webSearch: "webSearch",
76126
+ webFetch: "webFetch",
76127
+ scholarSearch: "scholarSearch",
76128
+ runLocalCommand: "runLocalCommand",
76129
+ createTextArtifact: "createTextArtifact",
76130
+ createDocumentArtifact: "createDocumentArtifact",
76131
+ artifactCapabilityReport: "artifactCapabilityReport",
76132
+ writingEnvironmentCheck: "writingEnvironmentCheck"
76133
+ };
76134
+ BROWSER_OPERATOR_TOOL_NAMES = [
76135
+ TOOL_NAMES.browserNavigate,
76136
+ TOOL_NAMES.browserExecuteTask,
76137
+ TOOL_NAMES.browserObserve,
76138
+ TOOL_NAMES.browserClick,
76139
+ TOOL_NAMES.browserType,
76140
+ TOOL_NAMES.browserVisualClick,
76141
+ TOOL_NAMES.browserFocusType,
76142
+ TOOL_NAMES.browserPressKey,
76143
+ TOOL_NAMES.browserRead,
76144
+ TOOL_NAMES.browserWait,
76145
+ TOOL_NAMES.browserHandleDialog
76146
+ ];
76147
+ BROWSER_RESEARCH_TOOL_NAMES = [
76148
+ TOOL_NAMES.browserSearchWeb,
76149
+ TOOL_NAMES.browserReadPage,
76150
+ TOOL_NAMES.browserCollectSources
76151
+ ];
76152
+ VERIFIED_SURFACE_SKILL_NAMES = [
76153
+ TOOL_NAMES.gmailSendEmailVerified,
76154
+ TOOL_NAMES.gmailSaveDraftVerified,
76155
+ TOOL_NAMES.googleDocsCreateVerified,
76156
+ TOOL_NAMES.googleCalendarCreateEventVerified
76157
+ ];
76158
+ DELIVERY_OPERATOR_TOOL_NAMES = [
76159
+ ...BROWSER_OPERATOR_TOOL_NAMES,
76160
+ ...VERIFIED_SURFACE_SKILL_NAMES
76161
+ ];
76162
+ }
76163
+ });
76164
+
76165
+ // features/perchTerminal/runtime/toolSystem/catalog.ts
76166
+ function isEnabledToolName(name) {
76167
+ return Object.values(TOOL_NAMES).includes(name);
76168
+ }
76169
+ function getToolRiskLevel(name) {
76170
+ if (!isEnabledToolName(name)) return null;
76171
+ return TOOL_RISK[name];
76172
+ }
76173
+ function getCatalogToolOwner(name) {
76174
+ if (!isEnabledToolName(name)) return null;
76175
+ return NON_MODULE_TOOL_OWNERS[name] ?? "module";
76176
+ }
76177
+ function getToolCatalogEntry(name) {
76178
+ if (!isEnabledToolName(name)) return null;
76179
+ const owner = getCatalogToolOwner(name);
76180
+ if (!owner) return null;
76181
+ const riskLevel = getToolRiskLevel(name);
76182
+ if (!riskLevel) return null;
76183
+ return {
76184
+ name,
76185
+ owner,
76186
+ riskLevel,
76187
+ displayName: getToolDisplayName(name)
76188
+ };
76189
+ }
76009
76190
  function humanizeToolSlug(toolName) {
76010
76191
  const stripped = toolName.replace(/^mcp__[^_]+__/, "");
76011
76192
  if (stripped !== toolName) {
@@ -76013,14 +76194,150 @@ function humanizeToolSlug(toolName) {
76013
76194
  }
76014
76195
  return toolName.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
76015
76196
  }
76016
- function displayToolName(toolName) {
76197
+ function getToolDisplayName(toolName) {
76017
76198
  return TOOL_DISPLAY_NAMES[toolName] ?? humanizeToolSlug(toolName);
76018
76199
  }
76019
- var TOOL_DISPLAY_NAMES;
76020
- var init_toolDisplayNames = __esm({
76021
- "lib/perchTerminal/toolDisplayNames.ts"() {
76200
+ var NON_MODULE_TOOL_OWNERS, TOOL_RISK, TOOL_DISPLAY_NAMES;
76201
+ var init_catalog = __esm({
76202
+ "features/perchTerminal/runtime/toolSystem/catalog.ts"() {
76203
+ init_toolNames();
76204
+ NON_MODULE_TOOL_OWNERS = {
76205
+ [TOOL_NAMES.listSources]: "lane",
76206
+ [TOOL_NAMES.readSource]: "lane",
76207
+ [TOOL_NAMES.searchSources]: "lane",
76208
+ [TOOL_NAMES.semanticSearch]: "lane",
76209
+ [TOOL_NAMES.retrieveContext]: "lane",
76210
+ [TOOL_NAMES.diagnoseWorkspaceAccess]: "lane",
76211
+ [TOOL_NAMES.listIndexedSources]: "lane",
76212
+ [TOOL_NAMES.searchWorkspaceSources]: "lane",
76213
+ [TOOL_NAMES.resolveSourceCandidates]: "lane",
76214
+ [TOOL_NAMES.webSearch]: "lane",
76215
+ [TOOL_NAMES.webFetch]: "lane",
76216
+ [TOOL_NAMES.scholarSearch]: "lane",
76217
+ [TOOL_NAMES.analyzeWorkbook]: "external",
76218
+ [TOOL_NAMES.extractDocument]: "external",
76219
+ [TOOL_NAMES.inspectDocument]: "external",
76220
+ [TOOL_NAMES.extractDocumentSection]: "external",
76221
+ [TOOL_NAMES.inspectWorkbookSheets]: "external",
76222
+ [TOOL_NAMES.compareEvidenceAcrossSources]: "external",
76223
+ [TOOL_NAMES.listArtifacts]: "external",
76224
+ [TOOL_NAMES.runLocalCommand]: "external",
76225
+ [TOOL_NAMES.createTextArtifact]: "external",
76226
+ [TOOL_NAMES.createDocumentArtifact]: "external",
76227
+ [TOOL_NAMES.artifactCapabilityReport]: "external",
76228
+ [TOOL_NAMES.writingEnvironmentCheck]: "external"
76229
+ };
76230
+ TOOL_RISK = {
76231
+ [TOOL_NAMES.validateWorkspaceRoot]: "read",
76232
+ [TOOL_NAMES.bash]: "command",
76233
+ [TOOL_NAMES.runBashTerminalCommand]: "command",
76234
+ [TOOL_NAMES.glob]: "read",
76235
+ [TOOL_NAMES.grep]: "read",
76236
+ [TOOL_NAMES.readLocalFile]: "read",
76237
+ [TOOL_NAMES.writeLocalFile]: "write",
76238
+ [TOOL_NAMES.moveLocalFile]: "write",
76239
+ [TOOL_NAMES.copyLocalFile]: "write",
76240
+ [TOOL_NAMES.createDirectory]: "write",
76241
+ [TOOL_NAMES.deleteLocalFile]: "write",
76242
+ [TOOL_NAMES.printFile]: "write",
76243
+ [TOOL_NAMES.editLocalFile]: "write",
76244
+ [TOOL_NAMES.statPath]: "read",
76245
+ [TOOL_NAMES.prepareSandboxInputs]: "read",
76246
+ [TOOL_NAMES.readProjectMemory]: "read",
76247
+ [TOOL_NAMES.saveToMemory]: "write",
76248
+ [TOOL_NAMES.addProjectRule]: "write",
76249
+ [TOOL_NAMES.writePerchManual]: "write",
76250
+ [TOOL_NAMES.getProjectRules]: "read",
76251
+ [TOOL_NAMES.listLocalSources]: "read",
76252
+ [TOOL_NAMES.readLocalSourceFile]: "read",
76253
+ [TOOL_NAMES.generateAPAuditPacket]: "command",
76254
+ [TOOL_NAMES.prepareAPEvidence]: "command",
76255
+ [TOOL_NAMES.queryAPCases]: "read",
76256
+ [TOOL_NAMES.renderAPControlGraph]: "read",
76257
+ [TOOL_NAMES.runManagedPlaybook]: "command",
76258
+ [TOOL_NAMES.runSuite]: "command",
76259
+ [TOOL_NAMES.listSuiteCatalog]: "read",
76260
+ [TOOL_NAMES.proposeSuitePlan]: "command",
76261
+ [TOOL_NAMES.executeSuitePlan]: "command",
76262
+ [TOOL_NAMES.proposeWork]: "command",
76263
+ [TOOL_NAMES.executeWork]: "command",
76264
+ [TOOL_NAMES.sendWorkerMessage]: "command",
76265
+ [TOOL_NAMES.taskStop]: "command",
76266
+ [TOOL_NAMES.spawnWorker]: "command",
76267
+ [TOOL_NAMES.dispatchAgent]: "command",
76268
+ [TOOL_NAMES.runSandboxAnalysis]: "command",
76269
+ [TOOL_NAMES.runSandboxCode]: "command",
76270
+ [TOOL_NAMES.safeBrowserAction]: "write",
76271
+ [TOOL_NAMES.browserNavigate]: "write",
76272
+ [TOOL_NAMES.browserExecuteTask]: "write",
76273
+ [TOOL_NAMES.browserObserve]: "read",
76274
+ [TOOL_NAMES.browserClick]: "write",
76275
+ [TOOL_NAMES.browserType]: "write",
76276
+ [TOOL_NAMES.browserVisualClick]: "write",
76277
+ [TOOL_NAMES.browserFocusType]: "write",
76278
+ [TOOL_NAMES.browserPressKey]: "write",
76279
+ [TOOL_NAMES.browserRead]: "read",
76280
+ [TOOL_NAMES.browserWait]: "read",
76281
+ [TOOL_NAMES.browserHandleDialog]: "write",
76282
+ [TOOL_NAMES.browserSearchWeb]: "read",
76283
+ [TOOL_NAMES.browserReadPage]: "read",
76284
+ [TOOL_NAMES.browserCollectSources]: "read",
76285
+ [TOOL_NAMES.gmailSendEmail]: "write",
76286
+ [TOOL_NAMES.gmailSaveDraft]: "write",
76287
+ [TOOL_NAMES.googleDocsCreate]: "write",
76288
+ [TOOL_NAMES.googleDocsAppend]: "write",
76289
+ [TOOL_NAMES.googleCalendarCreateEvent]: "write",
76290
+ [TOOL_NAMES.googleSheetsCreate]: "write",
76291
+ [TOOL_NAMES.googleSheetsAppendRows]: "write",
76292
+ [TOOL_NAMES.gmailSendEmailVerified]: "write",
76293
+ [TOOL_NAMES.gmailSaveDraftVerified]: "write",
76294
+ [TOOL_NAMES.googleDocsCreateVerified]: "write",
76295
+ [TOOL_NAMES.googleCalendarCreateEventVerified]: "write",
76296
+ [TOOL_NAMES.getMarketSignal]: "read",
76297
+ [TOOL_NAMES.queryMarketSignalLog]: "read",
76298
+ [TOOL_NAMES.explainMarketSignal]: "read",
76299
+ [TOOL_NAMES.listMarketStrategies]: "read",
76300
+ [TOOL_NAMES.runMarketBacktest]: "command",
76301
+ [TOOL_NAMES.getMarketTrackRecord]: "read",
76302
+ [TOOL_NAMES.ctxInspect]: "read",
76303
+ [TOOL_NAMES.toolSearch]: "read",
76304
+ [TOOL_NAMES.configInspect]: "read",
76305
+ [TOOL_NAMES.syntheticOutput]: "read",
76306
+ [TOOL_NAMES.todoWrite]: "read",
76307
+ [TOOL_NAMES.askUserQuestion]: "read",
76308
+ [TOOL_NAMES.proposePlan]: "read",
76309
+ [TOOL_NAMES.enterPlanMode]: "read",
76310
+ [TOOL_NAMES.exitPlanMode]: "read",
76311
+ [TOOL_NAMES.brief]: "read",
76312
+ [TOOL_NAMES.listMcpServers]: "read",
76313
+ [TOOL_NAMES.searchKnowledge]: "read",
76314
+ [TOOL_NAMES.listSources]: "read",
76315
+ [TOOL_NAMES.readSource]: "read",
76316
+ [TOOL_NAMES.analyzeWorkbook]: "read",
76317
+ [TOOL_NAMES.extractDocument]: "read",
76318
+ [TOOL_NAMES.searchSources]: "read",
76319
+ [TOOL_NAMES.semanticSearch]: "read",
76320
+ [TOOL_NAMES.retrieveContext]: "read",
76321
+ [TOOL_NAMES.diagnoseWorkspaceAccess]: "read",
76322
+ [TOOL_NAMES.listIndexedSources]: "read",
76323
+ [TOOL_NAMES.searchWorkspaceSources]: "read",
76324
+ [TOOL_NAMES.resolveSourceCandidates]: "read",
76325
+ [TOOL_NAMES.inspectDocument]: "read",
76326
+ [TOOL_NAMES.visionInspect]: "read",
76327
+ [TOOL_NAMES.extractDocumentSection]: "read",
76328
+ [TOOL_NAMES.inspectWorkbookSheets]: "read",
76329
+ [TOOL_NAMES.compareEvidenceAcrossSources]: "read",
76330
+ [TOOL_NAMES.listArtifacts]: "read",
76331
+ [TOOL_NAMES.webSearch]: "read",
76332
+ [TOOL_NAMES.webFetch]: "read",
76333
+ [TOOL_NAMES.scholarSearch]: "read",
76334
+ [TOOL_NAMES.runLocalCommand]: "command",
76335
+ [TOOL_NAMES.createTextArtifact]: "write",
76336
+ [TOOL_NAMES.createDocumentArtifact]: "write",
76337
+ [TOOL_NAMES.artifactCapabilityReport]: "read",
76338
+ [TOOL_NAMES.writingEnvironmentCheck]: "read"
76339
+ };
76022
76340
  TOOL_DISPLAY_NAMES = {
76023
- // ── Desktop / workspace ─────────────────────────────────────────────────────
76024
76341
  validateWorkspaceRoot: "Local folder access",
76025
76342
  bash: "Shell command",
76026
76343
  runBashTerminalCommand: "Terminal command",
@@ -76050,7 +76367,6 @@ var init_toolDisplayNames = __esm({
76050
76367
  query_ap_cases: "Query AP cases",
76051
76368
  render_ap_control_graph: "Render AP graph",
76052
76369
  runSandboxAnalysis: "Sandbox analysis",
76053
- // ── Workflows & specialists ───────────────────────────────────────────────
76054
76370
  run_suite: "Run workflow suite",
76055
76371
  list_suite_catalog: "Browse workflows",
76056
76372
  propose_suite_plan: "Propose workflow plan",
@@ -76062,7 +76378,6 @@ var init_toolDisplayNames = __esm({
76062
76378
  spawn_worker: "Run specialist",
76063
76379
  send_worker_message: "Message specialist",
76064
76380
  task_stop: "Stop specialist",
76065
- // ── Native / meta ─────────────────────────────────────────────────────────
76066
76381
  ctxInspect: "Inspect context",
76067
76382
  toolSearch: "Search tools",
76068
76383
  configInspect: "Inspect config",
@@ -76074,7 +76389,6 @@ var init_toolDisplayNames = __esm({
76074
76389
  exitPlanMode: "Exit plan mode",
76075
76390
  brief: "Brief",
76076
76391
  listMcpServers: "List integrations",
76077
- // ── Sources & retrieval (web / indexed) ───────────────────────────────────
76078
76392
  listSources: "List sources",
76079
76393
  readSource: "Read source",
76080
76394
  analyzeWorkbook: "Analyze workbook",
@@ -76100,7 +76414,6 @@ var init_toolDisplayNames = __esm({
76100
76414
  createDocumentArtifact: "Create document",
76101
76415
  artifactCapabilityReport: "Artifact capabilities",
76102
76416
  writingEnvironmentCheck: "Writing environment",
76103
- // ── Playwright Google Workspace adapters ─────────────────────────────────
76104
76417
  safeBrowserAction: "Browser action",
76105
76418
  browser_navigate: "Open page",
76106
76419
  browser_execute_task: "Browser task",
@@ -76127,7 +76440,12 @@ var init_toolDisplayNames = __esm({
76127
76440
  google_calendar_create_event: "Create calendar event",
76128
76441
  google_sheets_create: "Create Google Sheet",
76129
76442
  google_sheets_append_rows: "Append to Google Sheet",
76130
- // ── Playwright MCP ────────────────────────────────────────────────────────
76443
+ get_market_signal: "Reading market signal",
76444
+ query_market_signal_log: "Querying signal log",
76445
+ explain_market_signal: "Explaining signal",
76446
+ list_market_strategies: "Listing strategies",
76447
+ run_market_backtest: "Running backtest",
76448
+ get_market_track_record: "Computing track record",
76131
76449
  "mcp__playwright__browser_navigate": "Open page",
76132
76450
  "mcp__playwright__browser_snapshot": "Read page",
76133
76451
  "mcp__playwright__browser_click": "Click",
@@ -76146,7 +76464,6 @@ var init_toolDisplayNames = __esm({
76146
76464
  "mcp__playwright__browser_fill_form": "Fill form",
76147
76465
  "mcp__playwright__browser_press_key": "Keyboard",
76148
76466
  "mcp__playwright__browser_resize": "Resize window",
76149
- // ── CourtListener MCP ─────────────────────────────────────────────────────
76150
76467
  "mcp__courtlistener__search_cases_by_problem": "Searching case law",
76151
76468
  "mcp__courtlistener__search_cases": "Searching case law",
76152
76469
  "mcp__courtlistener__search_opinions": "Searching case law",
@@ -76161,19 +76478,18 @@ var init_toolDisplayNames = __esm({
76161
76478
  "mcp__courtlistener__lookup_citation": "Looking up citation",
76162
76479
  "mcp__courtlistener__validate_citations": "Verifying legal citations",
76163
76480
  "mcp__courtlistener__courtlistener_verify_citation": "Verifying legal citations",
76164
- // ── Market desk ──────────────────────────────────────────────────────────
76165
- get_market_signal: "Reading market signal",
76166
- query_market_signal_log: "Querying signal log",
76167
- explain_market_signal: "Explaining signal",
76168
- list_market_strategies: "Listing strategies",
76169
- run_market_backtest: "Running backtest",
76170
- get_market_track_record: "Computing track record",
76171
- // ── Future MCP slots (route to GenericCard until dedicated cards ship) ───
76172
76481
  "mcp__slack__post_message": "Post Slack message"
76173
76482
  };
76174
76483
  }
76175
76484
  });
76176
76485
 
76486
+ // lib/perchTerminal/toolDisplayNames.ts
76487
+ var init_toolDisplayNames = __esm({
76488
+ "lib/perchTerminal/toolDisplayNames.ts"() {
76489
+ init_catalog();
76490
+ }
76491
+ });
76492
+
76177
76493
  // features/perchTerminal/runtime/toolCallNormalizer.ts
76178
76494
  function normalizeToolCalls(modelResponse) {
76179
76495
  const calls = [];
@@ -77232,7 +77548,7 @@ function buildTranscriptSegments(state) {
77232
77548
  segments.push({
77233
77549
  kind: "executor_event",
77234
77550
  label: ev.title,
77235
- detail: ev.toolName ? `Started ${displayToolName(ev.toolName)}` : "Started",
77551
+ detail: ev.toolName ? `Started ${getToolDisplayName(ev.toolName)}` : "Started",
77236
77552
  status: "running",
77237
77553
  seq: seq++,
77238
77554
  timestamp: ev.ts
@@ -77244,7 +77560,7 @@ function buildTranscriptSegments(state) {
77244
77560
  segments.push({
77245
77561
  kind: "executor_event",
77246
77562
  label: ev.title,
77247
- detail: ev.resultSummary ?? (ev.toolName ? `Completed ${displayToolName(ev.toolName)}` : "Completed"),
77563
+ detail: ev.resultSummary ?? (ev.toolName ? `Completed ${getToolDisplayName(ev.toolName)}` : "Completed"),
77248
77564
  status: "completed",
77249
77565
  seq: seq++,
77250
77566
  timestamp: ev.ts
@@ -81351,163 +81667,6 @@ Tool strengths:
81351
81667
  }
81352
81668
  });
81353
81669
 
81354
- // features/perchTerminal/runtime/toolNames.ts
81355
- var TOOL_NAMES, BROWSER_OPERATOR_TOOL_NAMES, BROWSER_RESEARCH_TOOL_NAMES, VERIFIED_SURFACE_SKILL_NAMES, DELIVERY_OPERATOR_TOOL_NAMES;
81356
- var init_toolNames = __esm({
81357
- "features/perchTerminal/runtime/toolNames.ts"() {
81358
- "use strict";
81359
- TOOL_NAMES = {
81360
- // Desktop tools (require Perch AI Desktop; filesystem policy validates paths per call)
81361
- validateWorkspaceRoot: "validateWorkspaceRoot",
81362
- bash: "bash",
81363
- runBashTerminalCommand: "runBashTerminalCommand",
81364
- glob: "glob",
81365
- grep: "grep",
81366
- readLocalFile: "readLocalFile",
81367
- writeLocalFile: "writeLocalFile",
81368
- moveLocalFile: "moveLocalFile",
81369
- copyLocalFile: "copyLocalFile",
81370
- createDirectory: "createDirectory",
81371
- deleteLocalFile: "deleteLocalFile",
81372
- printFile: "printFile",
81373
- editLocalFile: "editLocalFile",
81374
- statPath: "statPath",
81375
- prepareSandboxInputs: "prepareSandboxInputs",
81376
- readProjectMemory: "readProjectMemory",
81377
- saveToMemory: "saveToMemory",
81378
- addProjectRule: "addProjectRule",
81379
- writePerchManual: "writePerchManual",
81380
- getProjectRules: "getProjectRules",
81381
- listLocalSources: "listLocalSources",
81382
- readLocalSourceFile: "readLocalSourceFile",
81383
- generateAPAuditPacket: "generateAPAuditPacket",
81384
- prepareAPEvidence: "prepare_ap_evidence",
81385
- queryAPCases: "query_ap_cases",
81386
- renderAPControlGraph: "render_ap_control_graph",
81387
- runManagedPlaybook: "runManagedPlaybook",
81388
- runSuite: "run_suite",
81389
- listSuiteCatalog: "list_suite_catalog",
81390
- proposeSuitePlan: "propose_suite_plan",
81391
- executeSuitePlan: "execute_suite_plan",
81392
- proposeWork: "propose_work",
81393
- executeWork: "execute_work",
81394
- sendWorkerMessage: "send_worker_message",
81395
- taskStop: "task_stop",
81396
- spawnWorker: "spawn_worker",
81397
- dispatchAgent: "dispatch_agent",
81398
- runSandboxAnalysis: "runSandboxAnalysis",
81399
- runSandboxCode: "run_sandbox_code",
81400
- safeBrowserAction: "safeBrowserAction",
81401
- // Operator primitives — drive the browser turn-by-turn (observe→act). Each
81402
- // result embeds a fresh accessibility snapshot + URL so the model re-observes
81403
- // after every action. Clipboard-free: typing uses direct key events.
81404
- browserNavigate: "browser_navigate",
81405
- browserExecuteTask: "browser_execute_task",
81406
- browserObserve: "browser_observe",
81407
- browserClick: "browser_click",
81408
- browserType: "browser_type",
81409
- browserVisualClick: "browser_visual_click",
81410
- browserFocusType: "browser_focus_type",
81411
- browserPressKey: "browser_press_key",
81412
- browserRead: "browser_read",
81413
- browserWait: "browser_wait",
81414
- browserHandleDialog: "browser_handle_dialog",
81415
- // Browser research tools — higher-level web research through the browser operator
81416
- browserSearchWeb: "browser_search_web",
81417
- browserReadPage: "browser_read_page",
81418
- browserCollectSources: "browser_collect_sources",
81419
- gmailSendEmail: "gmail_send_email",
81420
- gmailSaveDraft: "gmail_save_draft",
81421
- googleDocsCreate: "google_docs_create",
81422
- googleDocsAppend: "google_docs_append",
81423
- googleCalendarCreateEvent: "google_calendar_create_event",
81424
- googleSheetsCreate: "google_sheets_create",
81425
- googleSheetsAppendRows: "google_sheets_append_rows",
81426
- // Verified surface skills — optional shortcuts for Google Workspace delivery.
81427
- // Operator-first workers default to browser primitives and may use these
81428
- // adapter wrappers once when they can return proof-based receipt verification.
81429
- gmailSendEmailVerified: "gmail_send_email_verified",
81430
- gmailSaveDraftVerified: "gmail_save_draft_verified",
81431
- googleDocsCreateVerified: "google_docs_create_verified",
81432
- googleCalendarCreateEventVerified: "google_calendar_create_event_verified",
81433
- // Market desk tools (flag-gated: PERCH_MARKET_DESK=1)
81434
- getMarketSignal: "get_market_signal",
81435
- queryMarketSignalLog: "query_market_signal_log",
81436
- explainMarketSignal: "explain_market_signal",
81437
- listMarketStrategies: "list_market_strategies",
81438
- runMarketBacktest: "run_market_backtest",
81439
- getMarketTrackRecord: "get_market_track_record",
81440
- // Native tools (always available; executed locally without Desktop bridge)
81441
- ctxInspect: "ctxInspect",
81442
- toolSearch: "toolSearch",
81443
- configInspect: "configInspect",
81444
- syntheticOutput: "syntheticOutput",
81445
- todoWrite: "todoWrite",
81446
- askUserQuestion: "askUserQuestion",
81447
- proposePlan: "propose_plan",
81448
- enterPlanMode: "enterPlanMode",
81449
- exitPlanMode: "exitPlanMode",
81450
- brief: "brief",
81451
- listMcpServers: "listMcpServers",
81452
- searchKnowledge: "searchKnowledge",
81453
- // Unavailable tools (not executable in Perch Terminal Desktop; Supabase/web/sandbox)
81454
- listSources: "listSources",
81455
- readSource: "readSource",
81456
- analyzeWorkbook: "analyzeWorkbook",
81457
- extractDocument: "extractDocument",
81458
- searchSources: "searchSources",
81459
- semanticSearch: "semanticSearch",
81460
- retrieveContext: "retrieveContext",
81461
- diagnoseWorkspaceAccess: "diagnoseWorkspaceAccess",
81462
- listIndexedSources: "listIndexedSources",
81463
- searchWorkspaceSources: "searchWorkspaceSources",
81464
- resolveSourceCandidates: "resolveSourceCandidates",
81465
- inspectDocument: "inspectDocument",
81466
- visionInspect: "visionInspect",
81467
- extractDocumentSection: "extractDocumentSection",
81468
- inspectWorkbookSheets: "inspectWorkbookSheets",
81469
- compareEvidenceAcrossSources: "compareEvidenceAcrossSources",
81470
- listArtifacts: "listArtifacts",
81471
- webSearch: "webSearch",
81472
- webFetch: "webFetch",
81473
- scholarSearch: "scholarSearch",
81474
- runLocalCommand: "runLocalCommand",
81475
- createTextArtifact: "createTextArtifact",
81476
- createDocumentArtifact: "createDocumentArtifact",
81477
- artifactCapabilityReport: "artifactCapabilityReport",
81478
- writingEnvironmentCheck: "writingEnvironmentCheck"
81479
- };
81480
- BROWSER_OPERATOR_TOOL_NAMES = [
81481
- TOOL_NAMES.browserNavigate,
81482
- TOOL_NAMES.browserExecuteTask,
81483
- TOOL_NAMES.browserObserve,
81484
- TOOL_NAMES.browserClick,
81485
- TOOL_NAMES.browserType,
81486
- TOOL_NAMES.browserVisualClick,
81487
- TOOL_NAMES.browserFocusType,
81488
- TOOL_NAMES.browserPressKey,
81489
- TOOL_NAMES.browserRead,
81490
- TOOL_NAMES.browserWait,
81491
- TOOL_NAMES.browserHandleDialog
81492
- ];
81493
- BROWSER_RESEARCH_TOOL_NAMES = [
81494
- TOOL_NAMES.browserSearchWeb,
81495
- TOOL_NAMES.browserReadPage,
81496
- TOOL_NAMES.browserCollectSources
81497
- ];
81498
- VERIFIED_SURFACE_SKILL_NAMES = [
81499
- TOOL_NAMES.gmailSendEmailVerified,
81500
- TOOL_NAMES.gmailSaveDraftVerified,
81501
- TOOL_NAMES.googleDocsCreateVerified,
81502
- TOOL_NAMES.googleCalendarCreateEventVerified
81503
- ];
81504
- DELIVERY_OPERATOR_TOOL_NAMES = [
81505
- ...BROWSER_OPERATOR_TOOL_NAMES,
81506
- ...VERIFIED_SURFACE_SKILL_NAMES
81507
- ];
81508
- }
81509
- });
81510
-
81511
81670
  // features/perchTerminal/runtime/marketDesk/marketDeskAccess.ts
81512
81671
  function isMarketDeskEnabled() {
81513
81672
  return process.env.PERCH_MARKET_DESK === "1";
@@ -83131,6 +83290,7 @@ function truncateHistoryLine(value, max2) {
83131
83290
  }
83132
83291
  var init_operatorTruth = __esm({
83133
83292
  "features/perchTerminal/runtime/operatorTruth.ts"() {
83293
+ "use strict";
83134
83294
  }
83135
83295
  });
83136
83296
 
@@ -130788,24 +130948,36 @@ async function callModelRouterViaServer(request, opts, endpoint = "/api/perch-te
130788
130948
  signal: _signal,
130789
130949
  ...serializableRequest
130790
130950
  } = request;
130791
- const response = await fetch(endpoint, {
130951
+ const body = JSON.stringify({
130952
+ request: serializableRequest,
130953
+ runId: opts?.runId,
130954
+ lane: opts?.lane ?? "chat",
130955
+ strictManual: opts?.strictManual ?? false,
130956
+ raceMode: opts?.raceMode,
130957
+ preferredModelId: opts?.preferredModelId ?? null,
130958
+ avoidModelIds: opts?.avoidModelIds ?? [],
130959
+ attribution: opts?.attribution ?? null
130960
+ });
130961
+ const response = await fetchModelProxyWithRetry(endpoint, {
130792
130962
  method: "POST",
130793
130963
  headers: {
130794
130964
  "Content-Type": "application/json",
130795
130965
  ...hasStreamingHandler ? { Accept: "text/event-stream" } : {},
130796
130966
  ...nodeModelProxyAuthHeader()
130797
130967
  },
130798
- body: JSON.stringify({
130799
- request: serializableRequest,
130800
- runId: opts?.runId,
130801
- lane: opts?.lane ?? "chat",
130802
- strictManual: opts?.strictManual ?? false,
130803
- raceMode: opts?.raceMode,
130804
- preferredModelId: opts?.preferredModelId ?? null,
130805
- avoidModelIds: opts?.avoidModelIds ?? [],
130806
- attribution: opts?.attribution ?? null
130807
- }),
130968
+ body,
130808
130969
  signal: _signal
130970
+ }, {
130971
+ onRetry: (attempt, statusOrError) => {
130972
+ onStreamEvent?.({
130973
+ type: "model_call_failed",
130974
+ provider: "model_proxy",
130975
+ modelId: "app-proxy",
130976
+ lane: opts?.lane ?? "chat",
130977
+ error: `Model proxy retry ${attempt + 1}/${MODEL_PROXY_MAX_ATTEMPTS}: ${statusOrError}`,
130978
+ errorCategory: "proxy_transient"
130979
+ });
130980
+ }
130809
130981
  });
130810
130982
  if (!hasStreamingHandler) {
130811
130983
  return await response.json();
@@ -130913,6 +131085,46 @@ async function callModelRouterViaServer(request, opts, endpoint = "/api/perch-te
130913
131085
  durationMs: 0
130914
131086
  };
130915
131087
  }
131088
+ async function fetchModelProxyWithRetry(endpoint, init, options) {
131089
+ const maxAttempts = Math.max(1, options?.maxAttempts ?? MODEL_PROXY_MAX_ATTEMPTS);
131090
+ let lastError = null;
131091
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
131092
+ try {
131093
+ const response = await fetch(endpoint, init);
131094
+ if (!isRetriableModelProxyStatus(response.status) || attempt === maxAttempts - 1) {
131095
+ return response;
131096
+ }
131097
+ options?.onRetry?.(attempt, `HTTP ${response.status}`);
131098
+ await response.body?.cancel().catch(() => void 0);
131099
+ await waitForModelProxyRetry(attempt, init.signal);
131100
+ } catch (error) {
131101
+ if (isAbortLikeError(error) || attempt === maxAttempts - 1) throw error;
131102
+ lastError = error;
131103
+ options?.onRetry?.(attempt, error instanceof Error ? error.message : String(error));
131104
+ await waitForModelProxyRetry(attempt, init.signal);
131105
+ }
131106
+ }
131107
+ throw lastError instanceof Error ? lastError : new Error(String(lastError ?? "Model proxy request failed"));
131108
+ }
131109
+ function isRetriableModelProxyStatus(status) {
131110
+ return status === 408 || status === 425 || status >= 500 && status <= 599;
131111
+ }
131112
+ function isAbortLikeError(error) {
131113
+ if (!(error instanceof Error)) return false;
131114
+ return error.name === "AbortError" || error.message.toLowerCase().includes("abort");
131115
+ }
131116
+ function waitForModelProxyRetry(attempt, signal) {
131117
+ const delayMs = MODEL_PROXY_RETRY_BASE_MS * 2 ** attempt;
131118
+ if (signal?.aborted) return Promise.reject(new DOMException("Aborted", "AbortError"));
131119
+ return new Promise((resolve5, reject2) => {
131120
+ const timer = setTimeout(resolve5, delayMs);
131121
+ const onAbort = () => {
131122
+ clearTimeout(timer);
131123
+ reject2(new DOMException("Aborted", "AbortError"));
131124
+ };
131125
+ signal?.addEventListener("abort", onAbort, { once: true });
131126
+ });
131127
+ }
130916
131128
  function resolveNodeModelCallProxyUrl() {
130917
131129
  if (typeof process === "undefined") return null;
130918
131130
  const raw = process.env[MODEL_CALL_PROXY_ENV]?.trim();
@@ -131002,7 +131214,7 @@ function safeParseObject2(text) {
131002
131214
  function objectRecord(value) {
131003
131215
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
131004
131216
  }
131005
- var MODEL_CALL_PROXY_ENV, MODEL_CALL_PROXY_TOKEN_ENV;
131217
+ var MODEL_CALL_PROXY_ENV, MODEL_CALL_PROXY_TOKEN_ENV, MODEL_PROXY_MAX_ATTEMPTS, MODEL_PROXY_RETRY_BASE_MS;
131006
131218
  var init_modelRouter = __esm({
131007
131219
  "features/perchTerminal/runtime/modelRouter.ts"() {
131008
131220
  "use strict";
@@ -131014,6 +131226,8 @@ var init_modelRouter = __esm({
131014
131226
  init_toolCallNormalizer();
131015
131227
  MODEL_CALL_PROXY_ENV = "PERCH_MODEL_CALL_PROXY_URL";
131016
131228
  MODEL_CALL_PROXY_TOKEN_ENV = "PERCH_MODEL_CALL_PROXY_TOKEN";
131229
+ MODEL_PROXY_MAX_ATTEMPTS = 3;
131230
+ MODEL_PROXY_RETRY_BASE_MS = 350;
131017
131231
  }
131018
131232
  });
131019
131233
 
@@ -133606,10 +133820,18 @@ function classifyTool(name) {
133606
133820
  message: `Unknown tool: ${name}`
133607
133821
  };
133608
133822
  }
133823
+ const riskLevel = getToolRiskLevel(name);
133824
+ if (!riskLevel) {
133825
+ return {
133826
+ ok: false,
133827
+ code: "tool_unknown",
133828
+ message: `Tool is not cataloged: ${name}`
133829
+ };
133830
+ }
133609
133831
  return {
133610
133832
  ok: true,
133611
133833
  toolName: name,
133612
- riskLevel: TOOL_RISK[name]
133834
+ riskLevel
133613
133835
  };
133614
133836
  }
133615
133837
  function validateToolCallPolicy(input) {
@@ -133860,9 +134082,6 @@ function classifyIrreversibleOrOutboundAction(toolName, args) {
133860
134082
  return null;
133861
134083
  }
133862
134084
  }
133863
- function isEnabledToolName(name) {
133864
- return Object.values(TOOL_NAMES).includes(name);
133865
- }
133866
134085
  function countEmailRecipients(args) {
133867
134086
  const countValue = (value) => {
133868
134087
  if (Array.isArray(value)) return value.filter((item) => String(item).trim()).length;
@@ -134303,128 +134522,77 @@ function isSafeSandboxInputRef(value) {
134303
134522
  if (typeof value !== "string") return false;
134304
134523
  return isSafeLocalSourceId(value) || isSafeFilePath(value);
134305
134524
  }
134306
- var TOOL_RISK;
134307
134525
  var init_toolPolicy = __esm({
134308
134526
  "features/perchTerminal/runtime/toolPolicy.ts"() {
134309
134527
  "use strict";
134310
134528
  init_toolNames();
134529
+ init_catalog();
134311
134530
  init_toolPermissionPolicy();
134312
134531
  init_permissionModes();
134313
134532
  init_localCommandPolicy();
134314
- TOOL_RISK = {
134315
- // Desktop tools
134316
- [TOOL_NAMES.validateWorkspaceRoot]: "read",
134317
- [TOOL_NAMES.bash]: "command",
134318
- [TOOL_NAMES.runBashTerminalCommand]: "command",
134319
- [TOOL_NAMES.glob]: "read",
134320
- [TOOL_NAMES.grep]: "read",
134321
- [TOOL_NAMES.readLocalFile]: "read",
134322
- [TOOL_NAMES.writeLocalFile]: "write",
134323
- [TOOL_NAMES.moveLocalFile]: "write",
134324
- [TOOL_NAMES.copyLocalFile]: "write",
134325
- [TOOL_NAMES.createDirectory]: "write",
134326
- [TOOL_NAMES.deleteLocalFile]: "write",
134327
- [TOOL_NAMES.printFile]: "write",
134328
- [TOOL_NAMES.editLocalFile]: "write",
134329
- [TOOL_NAMES.statPath]: "read",
134330
- [TOOL_NAMES.prepareSandboxInputs]: "read",
134331
- [TOOL_NAMES.readProjectMemory]: "read",
134332
- [TOOL_NAMES.saveToMemory]: "write",
134333
- [TOOL_NAMES.addProjectRule]: "write",
134334
- [TOOL_NAMES.writePerchManual]: "write",
134335
- [TOOL_NAMES.getProjectRules]: "read",
134336
- [TOOL_NAMES.listLocalSources]: "read",
134337
- [TOOL_NAMES.readLocalSourceFile]: "read",
134338
- [TOOL_NAMES.generateAPAuditPacket]: "command",
134339
- [TOOL_NAMES.prepareAPEvidence]: "command",
134340
- [TOOL_NAMES.queryAPCases]: "read",
134341
- [TOOL_NAMES.renderAPControlGraph]: "read",
134342
- [TOOL_NAMES.runManagedPlaybook]: "command",
134343
- [TOOL_NAMES.runSuite]: "command",
134344
- [TOOL_NAMES.listSuiteCatalog]: "read",
134345
- [TOOL_NAMES.proposeSuitePlan]: "command",
134346
- [TOOL_NAMES.executeSuitePlan]: "command",
134347
- [TOOL_NAMES.proposeWork]: "command",
134348
- [TOOL_NAMES.executeWork]: "command",
134349
- [TOOL_NAMES.sendWorkerMessage]: "command",
134350
- [TOOL_NAMES.taskStop]: "command",
134351
- [TOOL_NAMES.spawnWorker]: "command",
134352
- [TOOL_NAMES.dispatchAgent]: "command",
134353
- [TOOL_NAMES.runSandboxAnalysis]: "command",
134354
- [TOOL_NAMES.runSandboxCode]: "command",
134355
- [TOOL_NAMES.safeBrowserAction]: "write",
134356
- [TOOL_NAMES.browserNavigate]: "write",
134357
- [TOOL_NAMES.browserExecuteTask]: "write",
134358
- [TOOL_NAMES.browserObserve]: "read",
134359
- [TOOL_NAMES.browserClick]: "write",
134360
- [TOOL_NAMES.browserType]: "write",
134361
- [TOOL_NAMES.browserVisualClick]: "write",
134362
- [TOOL_NAMES.browserFocusType]: "write",
134363
- [TOOL_NAMES.browserPressKey]: "write",
134364
- [TOOL_NAMES.browserRead]: "read",
134365
- [TOOL_NAMES.browserWait]: "read",
134366
- [TOOL_NAMES.browserHandleDialog]: "write",
134367
- [TOOL_NAMES.browserSearchWeb]: "read",
134368
- [TOOL_NAMES.browserReadPage]: "read",
134369
- [TOOL_NAMES.browserCollectSources]: "read",
134370
- [TOOL_NAMES.gmailSendEmail]: "write",
134371
- [TOOL_NAMES.gmailSaveDraft]: "write",
134372
- [TOOL_NAMES.googleDocsCreate]: "write",
134373
- [TOOL_NAMES.googleDocsAppend]: "write",
134374
- [TOOL_NAMES.googleCalendarCreateEvent]: "write",
134375
- [TOOL_NAMES.googleSheetsCreate]: "write",
134376
- [TOOL_NAMES.googleSheetsAppendRows]: "write",
134377
- [TOOL_NAMES.gmailSendEmailVerified]: "write",
134378
- [TOOL_NAMES.gmailSaveDraftVerified]: "write",
134379
- [TOOL_NAMES.googleDocsCreateVerified]: "write",
134380
- [TOOL_NAMES.googleCalendarCreateEventVerified]: "write",
134381
- // Market desk tools
134382
- [TOOL_NAMES.getMarketSignal]: "read",
134383
- [TOOL_NAMES.queryMarketSignalLog]: "read",
134384
- [TOOL_NAMES.explainMarketSignal]: "read",
134385
- [TOOL_NAMES.listMarketStrategies]: "read",
134386
- [TOOL_NAMES.runMarketBacktest]: "command",
134387
- [TOOL_NAMES.getMarketTrackRecord]: "read",
134388
- // Native tools
134389
- [TOOL_NAMES.ctxInspect]: "read",
134390
- [TOOL_NAMES.toolSearch]: "read",
134391
- [TOOL_NAMES.configInspect]: "read",
134392
- [TOOL_NAMES.syntheticOutput]: "read",
134393
- [TOOL_NAMES.todoWrite]: "read",
134394
- [TOOL_NAMES.askUserQuestion]: "read",
134395
- [TOOL_NAMES.proposePlan]: "read",
134396
- [TOOL_NAMES.enterPlanMode]: "read",
134397
- [TOOL_NAMES.exitPlanMode]: "read",
134398
- [TOOL_NAMES.brief]: "read",
134399
- [TOOL_NAMES.listMcpServers]: "read",
134400
- [TOOL_NAMES.searchKnowledge]: "read",
134401
- // Unavailable tools (handled in executor, mapped to read for policy purposes)
134402
- [TOOL_NAMES.listSources]: "read",
134403
- [TOOL_NAMES.readSource]: "read",
134404
- [TOOL_NAMES.analyzeWorkbook]: "read",
134405
- [TOOL_NAMES.extractDocument]: "read",
134406
- [TOOL_NAMES.searchSources]: "read",
134407
- [TOOL_NAMES.semanticSearch]: "read",
134408
- [TOOL_NAMES.retrieveContext]: "read",
134409
- [TOOL_NAMES.diagnoseWorkspaceAccess]: "read",
134410
- [TOOL_NAMES.listIndexedSources]: "read",
134411
- [TOOL_NAMES.searchWorkspaceSources]: "read",
134412
- [TOOL_NAMES.resolveSourceCandidates]: "read",
134413
- [TOOL_NAMES.inspectDocument]: "read",
134414
- [TOOL_NAMES.visionInspect]: "read",
134415
- [TOOL_NAMES.extractDocumentSection]: "read",
134416
- [TOOL_NAMES.inspectWorkbookSheets]: "read",
134417
- [TOOL_NAMES.compareEvidenceAcrossSources]: "read",
134418
- [TOOL_NAMES.listArtifacts]: "read",
134419
- [TOOL_NAMES.webSearch]: "read",
134420
- [TOOL_NAMES.webFetch]: "read",
134421
- [TOOL_NAMES.scholarSearch]: "read",
134422
- [TOOL_NAMES.runLocalCommand]: "command",
134423
- [TOOL_NAMES.createTextArtifact]: "write",
134424
- [TOOL_NAMES.createDocumentArtifact]: "write",
134425
- [TOOL_NAMES.artifactCapabilityReport]: "read",
134426
- [TOOL_NAMES.writingEnvironmentCheck]: "read"
134427
- };
134533
+ }
134534
+ });
134535
+
134536
+ // features/perchTerminal/runtime/toolSystem/schemaCatalog.ts
134537
+ function buildToolSchemaCatalog(sections) {
134538
+ const byName = /* @__PURE__ */ new Map();
134539
+ const definitions = [];
134540
+ for (const section of sections) {
134541
+ for (const definition of section.definitions) {
134542
+ const name = definition.function.name;
134543
+ const existing = byName.get(name);
134544
+ if (existing) {
134545
+ throw new Error(
134546
+ `Duplicate model tool schema "${name}" in schema section "${section.id}".`
134547
+ );
134548
+ }
134549
+ if (section.owner !== "mcp") {
134550
+ const entry = getToolCatalogEntry(name);
134551
+ if (!entry) {
134552
+ throw new Error(
134553
+ `Model tool schema "${name}" in schema section "${section.id}" is missing from the tool catalog.`
134554
+ );
134555
+ }
134556
+ if (entry.owner !== section.owner) {
134557
+ throw new Error(
134558
+ `Model tool schema "${name}" declares owner "${section.owner}" but catalog owner is "${entry.owner}".`
134559
+ );
134560
+ }
134561
+ }
134562
+ byName.set(name, definition);
134563
+ definitions.push(definition);
134564
+ }
134565
+ }
134566
+ return {
134567
+ definitions,
134568
+ byName,
134569
+ sections
134570
+ };
134571
+ }
134572
+ function groupSchemaDefinitionsByCatalogOwner(idPrefix, definitions) {
134573
+ const groups = /* @__PURE__ */ new Map();
134574
+ for (const definition of definitions) {
134575
+ const name = definition.function.name;
134576
+ const entry = getToolCatalogEntry(name);
134577
+ if (!entry) {
134578
+ throw new Error(
134579
+ `Model tool schema "${name}" in schema group "${idPrefix}" is missing from the tool catalog.`
134580
+ );
134581
+ }
134582
+ const defs = groups.get(entry.owner) ?? [];
134583
+ defs.push(definition);
134584
+ groups.set(entry.owner, defs);
134585
+ }
134586
+ return [...groups.entries()].map(([owner, groupedDefinitions]) => ({
134587
+ id: `${idPrefix}:${owner}`,
134588
+ owner,
134589
+ definitions: groupedDefinitions
134590
+ }));
134591
+ }
134592
+ var init_schemaCatalog = __esm({
134593
+ "features/perchTerminal/runtime/toolSystem/schemaCatalog.ts"() {
134594
+ "use strict";
134595
+ init_catalog();
134428
134596
  }
134429
134597
  });
134430
134598
 
@@ -136543,7 +136711,7 @@ function buildFullRegistry(desktopConnected, cliLocalTools, activeRootPath, supa
136543
136711
  const baseUnavailable = UNAVAILABLE_TOOLS.filter(
136544
136712
  (t) => !dynamicSupabaseNames.has(t.name)
136545
136713
  );
136546
- return [
136714
+ return dedupeFullRegistryEntries([
136547
136715
  ...desktopEntries,
136548
136716
  ...nativeEntries,
136549
136717
  ...knowledgeEntries,
@@ -136552,7 +136720,17 @@ function buildFullRegistry(desktopConnected, cliLocalTools, activeRootPath, supa
136552
136720
  ...docWorkbookEntries,
136553
136721
  ...artifactEntries,
136554
136722
  ...baseUnavailable
136555
- ];
136723
+ ]);
136724
+ }
136725
+ function dedupeFullRegistryEntries(entries) {
136726
+ const byName = /* @__PURE__ */ new Map();
136727
+ for (const entry of entries) {
136728
+ const existing = byName.get(entry.name);
136729
+ if (!existing || entry.available && !existing.available) {
136730
+ byName.set(entry.name, entry);
136731
+ }
136732
+ }
136733
+ return [...byName.values()];
136556
136734
  }
136557
136735
  function getFullToolRegistry(opts) {
136558
136736
  return buildFullRegistry(
@@ -136588,46 +136766,53 @@ function filterToolDefinitionsForNames(definitions, allowedToolNames) {
136588
136766
  (definition) => allowed.has(definition.function.name)
136589
136767
  );
136590
136768
  }
136591
- function getEnabledToolDefinitions(opts) {
136769
+ function getEnabledToolSchemaSections(opts) {
136592
136770
  const native = getNativeToolDefinitions();
136593
136771
  const knowledgeTools = getKnowledgeToolDefinitions();
136594
136772
  const webTools = getWebToolDefinitions();
136595
136773
  const marketDeskDefs = isMarketDeskEnabled() ? getMarketDeskToolDefinitions() : [];
136596
- const supabaseDefs = getSupabaseToolDefinitions(
136597
- opts.supabaseConfigured,
136598
- opts.workspaceId
136599
- );
136600
136774
  const mcpDefs = filterModelFacingMcpTools(opts.mcpTools ?? []);
136775
+ const supabaseSections = groupSchemaDefinitionsByCatalogOwner(
136776
+ "supabase",
136777
+ getSupabaseToolDefinitions(opts.supabaseConfigured, opts.workspaceId)
136778
+ );
136601
136779
  if (!opts.desktopConnected) {
136602
136780
  const cliLocalDesktop = opts.cliLocalTools === true ? getDesktopToolDefinitions().filter(
136603
136781
  (definition) => isCliLocalToolName(definition.function.name)
136604
136782
  ) : [];
136605
136783
  return [
136606
- ...cliLocalDesktop,
136607
- ...native,
136608
- ...knowledgeTools,
136609
- ...webTools,
136610
- ...marketDeskDefs,
136611
- ...supabaseDefs,
136612
- ...mcpDefs
136784
+ { id: "desktop:cli-local", owner: "module", definitions: cliLocalDesktop },
136785
+ { id: "native", owner: "module", definitions: native },
136786
+ { id: "knowledge", owner: "module", definitions: knowledgeTools },
136787
+ { id: "web", owner: "lane", definitions: webTools },
136788
+ { id: "market-desk", owner: "module", definitions: marketDeskDefs },
136789
+ ...supabaseSections,
136790
+ { id: "mcp", owner: "mcp", definitions: mcpDefs }
136613
136791
  ];
136614
136792
  }
136615
136793
  const desktop = getDesktopToolDefinitions();
136616
136794
  const desktopNames = new Set(desktop.map((d) => d.function.name));
136795
+ const supabaseDefs = getSupabaseToolDefinitions(
136796
+ opts.supabaseConfigured,
136797
+ opts.workspaceId
136798
+ );
136617
136799
  const supabaseFiltered = supabaseDefs.filter((d) => !desktopNames.has(d.function.name));
136618
136800
  const hasVisionInspect = desktopNames.has(TOOL_NAMES.visionInspect) || supabaseFiltered.some((d) => d.function.name === TOOL_NAMES.visionInspect);
136619
136801
  const desktopVisionInspect = hasVisionInspect ? [] : [getVisionInspectToolDefinition()];
136620
136802
  return [
136621
- ...desktop,
136622
- ...native,
136623
- ...knowledgeTools,
136624
- ...webTools,
136625
- ...marketDeskDefs,
136626
- ...desktopVisionInspect,
136627
- ...supabaseFiltered,
136628
- ...mcpDefs
136803
+ { id: "desktop", owner: "module", definitions: desktop },
136804
+ { id: "native", owner: "module", definitions: native },
136805
+ { id: "knowledge", owner: "module", definitions: knowledgeTools },
136806
+ { id: "web", owner: "lane", definitions: webTools },
136807
+ { id: "market-desk", owner: "module", definitions: marketDeskDefs },
136808
+ { id: "desktop:vision-fallback", owner: "module", definitions: desktopVisionInspect },
136809
+ ...groupSchemaDefinitionsByCatalogOwner("supabase", supabaseFiltered),
136810
+ { id: "mcp", owner: "mcp", definitions: mcpDefs }
136629
136811
  ];
136630
136812
  }
136813
+ function getEnabledToolDefinitions(opts) {
136814
+ return buildToolSchemaCatalog(getEnabledToolSchemaSections(opts)).definitions;
136815
+ }
136631
136816
  function filterModelFacingMcpTools(mcpTools) {
136632
136817
  return mcpTools.filter((tool) => !tool.function.name.startsWith("mcp__playwright__"));
136633
136818
  }
@@ -136779,6 +136964,7 @@ var init_toolDefinitions = __esm({
136779
136964
  init_toolAvailability();
136780
136965
  init_toolPolicy();
136781
136966
  init_marketDeskAccess();
136967
+ init_schemaCatalog();
136782
136968
  init_toolNames();
136783
136969
  init_toolPermissionPolicy();
136784
136970
  init_toolPermissionPolicy();
@@ -199727,6 +199913,7 @@ function containsBrowserDeliveryTask(tasks) {
199727
199913
  var BROWSER_DELIVERY_ROLE_IDS;
199728
199914
  var init_browserDeliveryLock = __esm({
199729
199915
  "features/perchTerminal/agentPlatform/browserDeliveryLock.ts"() {
199916
+ "use strict";
199730
199917
  BROWSER_DELIVERY_ROLE_IDS = /* @__PURE__ */ new Set([
199731
199918
  "doc_writer",
199732
199919
  "email_sender",
@@ -206574,6 +206761,8 @@ var init_operatorPrimitives = __esm({
206574
206761
  operatorPrimitive(TOOL_NAMES.browserObserve),
206575
206762
  operatorPrimitive(TOOL_NAMES.browserClick),
206576
206763
  operatorPrimitive(TOOL_NAMES.browserType),
206764
+ operatorPrimitive(TOOL_NAMES.browserVisualClick),
206765
+ operatorPrimitive(TOOL_NAMES.browserFocusType),
206577
206766
  operatorPrimitive(TOOL_NAMES.browserPressKey),
206578
206767
  operatorPrimitive(TOOL_NAMES.browserRead),
206579
206768
  operatorPrimitive(TOOL_NAMES.browserWait),
@@ -215146,9 +215335,21 @@ var init_marketDesk = __esm({
215146
215335
  });
215147
215336
 
215148
215337
  // features/perchTerminal/runtime/toolSystem/registry.ts
215338
+ var registry_exports = {};
215339
+ __export(registry_exports, {
215340
+ getRegisteredTool: () => getRegisteredTool,
215341
+ getRegisteredToolNames: () => getRegisteredToolNames,
215342
+ isRegisteredTool: () => isRegisteredTool
215343
+ });
215149
215344
  function getRegisteredTool(name) {
215150
215345
  return REGISTRY.get(name) ?? null;
215151
215346
  }
215347
+ function isRegisteredTool(name) {
215348
+ return REGISTRY.has(name);
215349
+ }
215350
+ function getRegisteredToolNames() {
215351
+ return [...REGISTRY.keys()];
215352
+ }
215152
215353
  var TOOL_MODULES, REGISTRY;
215153
215354
  var init_registry5 = __esm({
215154
215355
  "features/perchTerminal/runtime/toolSystem/registry.ts"() {
@@ -215206,8 +215407,16 @@ var init_registry5 = __esm({
215206
215407
  });
215207
215408
 
215208
215409
  // features/perchTerminal/runtime/toolSystem/executeTool.ts
215410
+ async function loadToolRegistry() {
215411
+ if (typeof window !== "undefined") return null;
215412
+ registryPromise ??= Promise.resolve().then(() => (init_registry5(), registry_exports));
215413
+ return registryPromise;
215414
+ }
215209
215415
  async function executeRegisteredTool(name, args, ctx) {
215210
- const mod = getRegisteredTool(name);
215416
+ const registry2 = await loadToolRegistry();
215417
+ if (!registry2) return { handled: false };
215418
+ const { getRegisteredTool: getRegisteredTool2 } = registry2;
215419
+ const mod = getRegisteredTool2(name);
215211
215420
  if (!mod) return { handled: false };
215212
215421
  if (MARKET_DESK_TOOL_NAMES.has(name) && !isMarketDeskEnabled()) {
215213
215422
  return {
@@ -215221,11 +215430,12 @@ async function executeRegisteredTool(name, args, ctx) {
215221
215430
  }
215222
215431
  return { handled: true, result: await mod.handler(args, ctx) };
215223
215432
  }
215433
+ var registryPromise;
215224
215434
  var init_executeTool = __esm({
215225
215435
  "features/perchTerminal/runtime/toolSystem/executeTool.ts"() {
215226
215436
  "use strict";
215227
215437
  init_marketDeskAccess();
215228
- init_registry5();
215438
+ registryPromise = null;
215229
215439
  }
215230
215440
  });
215231
215441
 
@@ -282014,12 +282224,27 @@ async function runInkInteractivePerchCli(writer, deps, options) {
282014
282224
  const [pulse, setPulse] = React11.useState(0);
282015
282225
  const [, refresh] = React11.useState(0);
282016
282226
  const liveTextRef = React11.useRef("");
282227
+ const liveTextFlushTimerRef = React11.useRef(null);
282017
282228
  const activeRunRef = React11.useRef(null);
282018
282229
  const toolInputsById = React11.useRef(/* @__PURE__ */ new Map());
282019
282230
  const richToolIds = React11.useRef(/* @__PURE__ */ new Set());
282020
282231
  const terminalCommandItems = React11.useRef(/* @__PURE__ */ new Map());
282021
282232
  const sandboxRunItems = React11.useRef(/* @__PURE__ */ new Map());
282022
282233
  const sandboxRunMeta = React11.useRef(/* @__PURE__ */ new Map());
282234
+ const clearLiveTextFlushTimer = React11.useCallback(() => {
282235
+ if (liveTextFlushTimerRef.current) {
282236
+ clearTimeout(liveTextFlushTimerRef.current);
282237
+ liveTextFlushTimerRef.current = null;
282238
+ }
282239
+ }, []);
282240
+ const scheduleLiveTextPaint = React11.useCallback(() => {
282241
+ if (liveTextFlushTimerRef.current) return;
282242
+ liveTextFlushTimerRef.current = setTimeout(() => {
282243
+ liveTextFlushTimerRef.current = null;
282244
+ setLiveText(liveTextRef.current);
282245
+ }, 33);
282246
+ }, []);
282247
+ React11.useEffect(() => clearLiveTextFlushTimer, [clearLiveTextFlushTimer]);
282023
282248
  React11.useEffect(() => {
282024
282249
  if (!working) return void 0;
282025
282250
  const timer = setInterval(() => setPulse((value) => value + 1), 120);
@@ -282118,6 +282343,7 @@ async function runInkInteractivePerchCli(writer, deps, options) {
282118
282343
  }
282119
282344
  setWorking(true);
282120
282345
  setWorkingText("thinking");
282346
+ clearLiveTextFlushTimer();
282121
282347
  setLiveText("");
282122
282348
  liveTextRef.current = "";
282123
282349
  const toolNamesById = /* @__PURE__ */ new Map();
@@ -282164,7 +282390,7 @@ async function runInkInteractivePerchCli(writer, deps, options) {
282164
282390
  case "content_delta":
282165
282391
  case "streaming_text":
282166
282392
  liveTextRef.current += event.text;
282167
- setLiveText(liveTextRef.current);
282393
+ scheduleLiveTextPaint();
282168
282394
  break;
282169
282395
  case "assistant_preamble":
282170
282396
  case "activity_delta":
@@ -282412,6 +282638,7 @@ async function runInkInteractivePerchCli(writer, deps, options) {
282412
282638
  }
282413
282639
  }
282414
282640
  });
282641
+ clearLiveTextFlushTimer();
282415
282642
  setLiveText("");
282416
282643
  const assistantText = result2.assistantText.trim() || liveTextRef.current.trim();
282417
282644
  if (assistantText) {
@@ -282448,12 +282675,13 @@ async function runInkInteractivePerchCli(writer, deps, options) {
282448
282675
  if (activeRunRef.current?.runId === clientRunId) {
282449
282676
  activeRunRef.current = null;
282450
282677
  }
282678
+ clearLiveTextFlushTimer();
282451
282679
  setWorking(false);
282452
282680
  setWorkingText("ready");
282453
282681
  setLiveText("");
282454
282682
  liveTextRef.current = "";
282455
282683
  }
282456
- }, [addItem, app, appendItemDetails, patchItem, reconnect, runTurn, updateToolItem, working]);
282684
+ }, [addItem, app, appendItemDetails, clearLiveTextFlushTimer, patchItem, reconnect, runTurn, scheduleLiveTextPaint, updateToolItem, working]);
282457
282685
  Ink2.useInput((input, key) => {
282458
282686
  if (working) {
282459
282687
  if (key.ctrl && input === "e") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.16",
3
+ "version": "2.4.17",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"