perchai-cli 2.4.22 → 2.4.23
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/perch.mjs +781 -23
- package/package.json +1 -1
package/dist/perch.mjs
CHANGED
|
@@ -75566,6 +75566,7 @@ var init_payroll = __esm({
|
|
|
75566
75566
|
// lib/perchBusinessTools/index.ts
|
|
75567
75567
|
var init_perchBusinessTools = __esm({
|
|
75568
75568
|
"lib/perchBusinessTools/index.ts"() {
|
|
75569
|
+
"use strict";
|
|
75569
75570
|
init_generateAPAuditPacket();
|
|
75570
75571
|
init_inventoryFolder();
|
|
75571
75572
|
init_loadBusinessTables();
|
|
@@ -75899,7 +75900,6 @@ function isTurnAbortedError(error) {
|
|
|
75899
75900
|
var TURN_STOPPED_BY_USER_MESSAGE;
|
|
75900
75901
|
var init_turnAbort = __esm({
|
|
75901
75902
|
"features/perchTerminal/runtime/turnAbort.ts"() {
|
|
75902
|
-
"use strict";
|
|
75903
75903
|
TURN_STOPPED_BY_USER_MESSAGE = "Turn stopped by user.";
|
|
75904
75904
|
}
|
|
75905
75905
|
});
|
|
@@ -85560,7 +85560,6 @@ Final answers lead with findings, name artifacts or delivery status, and give on
|
|
|
85560
85560
|
var MARKET_DESK_TOOL_NAMES;
|
|
85561
85561
|
var init_marketDeskAccess = __esm({
|
|
85562
85562
|
"features/perchTerminal/runtime/marketDesk/marketDeskAccess.ts"() {
|
|
85563
|
-
"use strict";
|
|
85564
85563
|
init_toolNames();
|
|
85565
85564
|
MARKET_DESK_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
85566
85565
|
TOOL_NAMES.getMarketSignal,
|
|
@@ -86717,7 +86716,7 @@ var init_managedWorkflowRegistry = __esm({
|
|
|
86717
86716
|
"name": "AP Suite Publisher",
|
|
86718
86717
|
"description": "Publishes the final AP operator suite envelope from analyst output. Writes findings CSV and report to the output folder.",
|
|
86719
86718
|
"lane": "writer",
|
|
86720
|
-
"systemPrompt": '# AP Suite Publisher\n\nYou receive the analyst\'s structured output from the deterministic AP extraction. Your job is to write deliverable files to disk and return their paths \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `findings.csv`** \u2014 one row per finding from `priorOutput.sandboxArtifact.findings` + analyst `thematicBlocks`:\n```\nid,severity,category,title,financial_exposure,evidence\nfinding-1,critical,duplicate_invoice,"INV-88421 matches INV-77209 same vendor same amount",12400,invoices/INV-88421.csv\n```\n\n**2. `report.md`** \u2014 a structured markdown report:\n```markdown\n# AP Audit Report \u2014 {folderPath leaf}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary \u2014 2\u20134 sentences, verbatim from analyst output}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## Findings ({N} total)\n{For each thematic block: ### {title}, severity badge, narrative, finding IDs}\n\n## Recommendations\n{Numbered list from analyst recommendations}\n\n## Data Coverage\n- Records processed: {metrics.recordsNormalized}\n- Tables loaded: {metrics.tablesLoaded}\n- Findings: {metrics.findingsCount}\n{warnings if any}\n```\n\n## Rules\n\n1. **Write the files first, return the paths.** Don\'t summarize in your response \u2014 the files are the deliverable.\n2. Use the folderPath from context. If it\'s not in priorOutput, use the folder name you can infer from evidence paths.\n3. Never fabricate findings not in `sandboxArtifact` or analyst output.\n4. If `sandboxArtifact` is null or analyst output is empty, write a report.md explaining what failed and why.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "findings": "{folderPath}/perch-output/findings.csv",\n "report": "{folderPath}/perch-output/report.md"\n },\n "findingsCount": 0,\n "topFinding": "string or null"\n}\n```\n\n---\n\n
|
|
86719
|
+
"systemPrompt": '# AP Suite Publisher\n\nYou receive the analyst\'s structured output from the deterministic AP extraction. Your job is to write deliverable files to disk and return their paths \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `findings.csv`** \u2014 one row per finding from `priorOutput.sandboxArtifact.findings` + analyst `thematicBlocks`:\n```\nid,severity,category,title,financial_exposure,evidence\nfinding-1,critical,duplicate_invoice,"INV-88421 matches INV-77209 same vendor same amount",12400,invoices/INV-88421.csv\n```\n\n**2. `report.md`** \u2014 a structured markdown report:\n```markdown\n# AP Audit Report \u2014 {folderPath leaf}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary \u2014 2\u20134 sentences, verbatim from analyst output}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## Findings ({N} total)\n{For each thematic block: ### {title}, severity badge, narrative, finding IDs}\n\n## Recommendations\n{Numbered list from analyst recommendations}\n\n## Data Coverage\n- Records processed: {metrics.recordsNormalized}\n- Tables loaded: {metrics.tablesLoaded}\n- Findings: {metrics.findingsCount}\n{warnings if any}\n```\n\n## Rules\n\n1. **Write the files first, return the paths.** Don\'t summarize in your response \u2014 the files are the deliverable.\n2. Use the folderPath from context. If it\'s not in priorOutput, use the folder name you can infer from evidence paths.\n3. Never fabricate findings not in `sandboxArtifact` or analyst output.\n4. If `sandboxArtifact` is null or analyst output is empty, write a report.md explaining what failed and why.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "findings": "{folderPath}/perch-output/findings.csv",\n "report": "{folderPath}/perch-output/report.md"\n },\n "findingsCount": 0,\n "topFinding": "string or null"\n}\n```\n\n---\n\n# Core Perch skill: spreadsheets\n\n\n# spreadsheets\n\nUse this skill when the user asks for a spreadsheet artifact, spreadsheet inspection, import-ready CSV, formulas, reconciliation tabs, exception tabs, or workbook-quality output.\n\n## Operating Rules\n\n- Profile incoming sheets before changing them: row counts, columns, types, key IDs, totals, and empty fields.\n- Preserve identifiers as text when they are invoice numbers, account numbers, vendor IDs, employee IDs, tickers, or other non-math values.\n- Put source values on input tabs and formulas on analysis tabs when producing XLSX workbooks.\n- Add checks for totals, row counts, formulas, and exception counts when the workbook drives a decision.\n- Use deterministic code or workbook inspection for fragile calculations; do not hand-wave formula behavior.\n\n## Verification\n\nBefore delivery, verify that the file exists, formulas are present where expected, totals reconcile, and CSV exports keep exact values. See `references/workbook-quality.md`.\n\n---\n\n---\nname: csv-findings\ndescription: Produce clean findings CSV files that spreadsheet tools can open reliably.\n---\n\n# csv-findings\n\nUse this skill for required findings, exceptions, reconciliation, or signal CSV deliverables.\n\n## Output contract\n\n- Write CSV files to `{folderPath}/perch-output/`.\n- Use deterministic column order from the base prompt.\n- Return the CSV path in `outputFiles`.\n\n## How to build the CSV\n\nPrefer writing a small Python script to `/tmp/<workflow>-csv-findings.py` and running it with Bash when quoting, commas, newlines, or currency values could be tricky. Use the standard library `csv` module, create `{folderPath}/perch-output/`, and verify with `ls -l "{folderPath}/perch-output/"`.\n\n```python\nimport csv\nfrom pathlib import Path\n\nout_dir = Path(folder_path) / "perch-output"\nout_dir.mkdir(parents=True, exist_ok=True)\nwith (out_dir / "findings.csv").open("w", newline="", encoding="utf-8") as f:\n writer = csv.DictWriter(f, fieldnames=["id", "severity", "category", "title", "financial_exposure", "evidence"])\n writer.writeheader()\n writer.writerows(rows)\n```\n\n## Conventions\n\n- Preserve exact IDs, names, amounts, accounts, dates, and source filenames from the analyst or sandbox output.\n- Quote fields through the CSV writer; do not hand-escape rows.\n- Use blank cells for missing values rather than invented values.\n- If there are no findings, still write the header row.',
|
|
86721
86720
|
"allowedTools": [
|
|
86722
86721
|
"writeLocalFile",
|
|
86723
86722
|
"bash",
|
|
@@ -87024,7 +87023,7 @@ var init_managedWorkflowRegistry = __esm({
|
|
|
87024
87023
|
"name": "Earnings Publisher",
|
|
87025
87024
|
"description": "Writes the earnings review findings and memo to the output folder.",
|
|
87026
87025
|
"lane": "writer",
|
|
87027
|
-
"systemPrompt": '# Earnings Publisher\n\nYou receive the analyst\'s structured earnings output. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `earnings-findings.csv`** \u2014 key metrics and conflicts, one row per signal:\n```\ntype,metric,value,source,conflict,detail\nrevenue,Q1_2026,$125M,earnings-release.html,no,"Revenue $125M in-line"\nconflict,revenue,$412M vs $125M,transcript.txt vs release.html,yes,"Two sources disagree \u2014 transcript shows $412M"\nguidance,FY_2026,raised,call-transcript.md,no,"Guidance raised to $520M"\n```\n\n**2. `earnings-memo.md`** \u2014 analyst memo format:\n```markdown\n# Earnings Review \u2014 {company / folder name}\nGenerated: {ISO date}\n\n## Headline\n{1-sentence: period, revenue, beat/miss, guidance direction}\n\n## Key Metrics\n| Metric | Value | vs Consensus | Source |\n|--------|-------|--------------|--------|\n{rows from analyst output \u2014 exact figures}\n\n## Conflicts & Risk Signals\n{Any cross-source discrepancies with both values and file names}\n\n## Guidance\n{Changes, raised/lowered/withdrawn, exact figures}\n\n## Coverage\n{Files reviewed, any gaps}\n```\n\nThe `folderPath` is in `priorOutput.folderPath`.\n\n## Rules\n\n1. **Write files first, return paths.** The memo is what the analyst team reads \u2014 not a chat message.\n2. Revenue, EPS, and margin figures must be exact from analyst output \u2014 never round or paraphrase.\n3. If two sources disagree, include both values and both file names in the conflict row.\n4. Never fabricate signals not in the analyst output.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "findings": "{folderPath}/perch-output/earnings-findings.csv",\n "memo": "{folderPath}/perch-output/earnings-memo.md"\n },\n "keyMetric": "Revenue $125M, beat 3%",\n "conflictsFound": 0\n}\n```\n\n---\n\n
|
|
87026
|
+
"systemPrompt": '# Earnings Publisher\n\nYou receive the analyst\'s structured earnings output. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `earnings-findings.csv`** \u2014 key metrics and conflicts, one row per signal:\n```\ntype,metric,value,source,conflict,detail\nrevenue,Q1_2026,$125M,earnings-release.html,no,"Revenue $125M in-line"\nconflict,revenue,$412M vs $125M,transcript.txt vs release.html,yes,"Two sources disagree \u2014 transcript shows $412M"\nguidance,FY_2026,raised,call-transcript.md,no,"Guidance raised to $520M"\n```\n\n**2. `earnings-memo.md`** \u2014 analyst memo format:\n```markdown\n# Earnings Review \u2014 {company / folder name}\nGenerated: {ISO date}\n\n## Headline\n{1-sentence: period, revenue, beat/miss, guidance direction}\n\n## Key Metrics\n| Metric | Value | vs Consensus | Source |\n|--------|-------|--------------|--------|\n{rows from analyst output \u2014 exact figures}\n\n## Conflicts & Risk Signals\n{Any cross-source discrepancies with both values and file names}\n\n## Guidance\n{Changes, raised/lowered/withdrawn, exact figures}\n\n## Coverage\n{Files reviewed, any gaps}\n```\n\nThe `folderPath` is in `priorOutput.folderPath`.\n\n## Rules\n\n1. **Write files first, return paths.** The memo is what the analyst team reads \u2014 not a chat message.\n2. Revenue, EPS, and margin figures must be exact from analyst output \u2014 never round or paraphrase.\n3. If two sources disagree, include both values and both file names in the conflict row.\n4. Never fabricate signals not in the analyst output.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "findings": "{folderPath}/perch-output/earnings-findings.csv",\n "memo": "{folderPath}/perch-output/earnings-memo.md"\n },\n "keyMetric": "Revenue $125M, beat 3%",\n "conflictsFound": 0\n}\n```\n\n---\n\n# Core Perch skill: spreadsheets\n\n\n# spreadsheets\n\nUse this skill when the user asks for a spreadsheet artifact, spreadsheet inspection, import-ready CSV, formulas, reconciliation tabs, exception tabs, or workbook-quality output.\n\n## Operating Rules\n\n- Profile incoming sheets before changing them: row counts, columns, types, key IDs, totals, and empty fields.\n- Preserve identifiers as text when they are invoice numbers, account numbers, vendor IDs, employee IDs, tickers, or other non-math values.\n- Put source values on input tabs and formulas on analysis tabs when producing XLSX workbooks.\n- Add checks for totals, row counts, formulas, and exception counts when the workbook drives a decision.\n- Use deterministic code or workbook inspection for fragile calculations; do not hand-wave formula behavior.\n\n## Verification\n\nBefore delivery, verify that the file exists, formulas are present where expected, totals reconcile, and CSV exports keep exact values. See `references/workbook-quality.md`.\n\n---\n\n---\nname: csv-findings\ndescription: Produce clean findings CSV files that spreadsheet tools can open reliably.\n---\n\n# csv-findings\n\nUse this skill for required findings, exceptions, reconciliation, or signal CSV deliverables.\n\n## Output contract\n\n- Write CSV files to `{folderPath}/perch-output/`.\n- Use deterministic column order from the base prompt.\n- Return the CSV path in `outputFiles`.\n\n## How to build the CSV\n\nPrefer writing a small Python script to `/tmp/<workflow>-csv-findings.py` and running it with Bash when quoting, commas, newlines, or currency values could be tricky. Use the standard library `csv` module, create `{folderPath}/perch-output/`, and verify with `ls -l "{folderPath}/perch-output/"`.\n\n```python\nimport csv\nfrom pathlib import Path\n\nout_dir = Path(folder_path) / "perch-output"\nout_dir.mkdir(parents=True, exist_ok=True)\nwith (out_dir / "findings.csv").open("w", newline="", encoding="utf-8") as f:\n writer = csv.DictWriter(f, fieldnames=["id", "severity", "category", "title", "financial_exposure", "evidence"])\n writer.writeheader()\n writer.writerows(rows)\n```\n\n## Conventions\n\n- Preserve exact IDs, names, amounts, accounts, dates, and source filenames from the analyst or sandbox output.\n- Quote fields through the CSV writer; do not hand-escape rows.\n- Use blank cells for missing values rather than invented values.\n- If there are no findings, still write the header row.',
|
|
87028
87027
|
"allowedTools": [
|
|
87029
87028
|
"writeLocalFile",
|
|
87030
87029
|
"bash",
|
|
@@ -87183,7 +87182,7 @@ var init_managedWorkflowRegistry = __esm({
|
|
|
87183
87182
|
"name": "GL Resolver",
|
|
87184
87183
|
"description": "Receives the analyst output and writes the GL exception report to the output folder.",
|
|
87185
87184
|
"lane": "writer",
|
|
87186
|
-
"systemPrompt": '# GL Resolver\n\nYou receive the analyst\'s structured output from the deterministic GL reconciliation. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `gl-exceptions.csv`** \u2014 one row per finding:\n```\nid,severity,category,account,entry_id,financial_exposure,detail\ngl-suspense-1,high,suspense_aging,9999,,47500,"Account 9999 carries $47,500 balance"\ngl-unmatched-suspense-2,high,unmatched_suspense,9999,JE-2026-0315,47500,"JE-2026-0315 debits suspense with no offset"\n```\n\n**2. `gl-report.md`** \u2014 structured markdown:\n```markdown\n# GL Reconciliation Report \u2014 {folderPath leaf}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## Exception Detail\n{For each thematic block: ### {title}, findings with account IDs and entry IDs}\n\n## Recommended Actions\n{Numbered list \u2014 e.g. "Clear suspense 9999 by allocating JE-2026-0315 to cost center X"}\n\n## Coverage\n- Trial balance rows: {metrics.trialBalanceRows}\n- Journal entries: {metrics.journalEntryCount}\n- Suspense accounts: {metrics.suspenseAccountCount}\n```\n\n## Rules\n\n1. **Write files first, return paths.** The CSV is the deliverable \u2014 accounting needs to sort and filter it, not read a chat message.\n2. Account IDs and entry IDs must appear verbatim from the findings \u2014 don\'t paraphrase.\n3. Never fabricate breaks not in `sandboxArtifact`.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "exceptions": "{folderPath}/perch-output/gl-exceptions.csv",\n "report": "{folderPath}/perch-output/gl-report.md"\n },\n "exceptionsCount": 0,\n "topException": "string or null"\n}\n```\n\n---\n\n
|
|
87185
|
+
"systemPrompt": '# GL Resolver\n\nYou receive the analyst\'s structured output from the deterministic GL reconciliation. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `gl-exceptions.csv`** \u2014 one row per finding:\n```\nid,severity,category,account,entry_id,financial_exposure,detail\ngl-suspense-1,high,suspense_aging,9999,,47500,"Account 9999 carries $47,500 balance"\ngl-unmatched-suspense-2,high,unmatched_suspense,9999,JE-2026-0315,47500,"JE-2026-0315 debits suspense with no offset"\n```\n\n**2. `gl-report.md`** \u2014 structured markdown:\n```markdown\n# GL Reconciliation Report \u2014 {folderPath leaf}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## Exception Detail\n{For each thematic block: ### {title}, findings with account IDs and entry IDs}\n\n## Recommended Actions\n{Numbered list \u2014 e.g. "Clear suspense 9999 by allocating JE-2026-0315 to cost center X"}\n\n## Coverage\n- Trial balance rows: {metrics.trialBalanceRows}\n- Journal entries: {metrics.journalEntryCount}\n- Suspense accounts: {metrics.suspenseAccountCount}\n```\n\n## Rules\n\n1. **Write files first, return paths.** The CSV is the deliverable \u2014 accounting needs to sort and filter it, not read a chat message.\n2. Account IDs and entry IDs must appear verbatim from the findings \u2014 don\'t paraphrase.\n3. Never fabricate breaks not in `sandboxArtifact`.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "exceptions": "{folderPath}/perch-output/gl-exceptions.csv",\n "report": "{folderPath}/perch-output/gl-report.md"\n },\n "exceptionsCount": 0,\n "topException": "string or null"\n}\n```\n\n---\n\n# Core Perch skill: spreadsheets\n\n\n# spreadsheets\n\nUse this skill when the user asks for a spreadsheet artifact, spreadsheet inspection, import-ready CSV, formulas, reconciliation tabs, exception tabs, or workbook-quality output.\n\n## Operating Rules\n\n- Profile incoming sheets before changing them: row counts, columns, types, key IDs, totals, and empty fields.\n- Preserve identifiers as text when they are invoice numbers, account numbers, vendor IDs, employee IDs, tickers, or other non-math values.\n- Put source values on input tabs and formulas on analysis tabs when producing XLSX workbooks.\n- Add checks for totals, row counts, formulas, and exception counts when the workbook drives a decision.\n- Use deterministic code or workbook inspection for fragile calculations; do not hand-wave formula behavior.\n\n## Verification\n\nBefore delivery, verify that the file exists, formulas are present where expected, totals reconcile, and CSV exports keep exact values. See `references/workbook-quality.md`.\n\n---\n\n---\nname: csv-findings\ndescription: Produce clean findings CSV files that spreadsheet tools can open reliably.\n---\n\n# csv-findings\n\nUse this skill for required findings, exceptions, reconciliation, or signal CSV deliverables.\n\n## Output contract\n\n- Write CSV files to `{folderPath}/perch-output/`.\n- Use deterministic column order from the base prompt.\n- Return the CSV path in `outputFiles`.\n\n## How to build the CSV\n\nPrefer writing a small Python script to `/tmp/<workflow>-csv-findings.py` and running it with Bash when quoting, commas, newlines, or currency values could be tricky. Use the standard library `csv` module, create `{folderPath}/perch-output/`, and verify with `ls -l "{folderPath}/perch-output/"`.\n\n```python\nimport csv\nfrom pathlib import Path\n\nout_dir = Path(folder_path) / "perch-output"\nout_dir.mkdir(parents=True, exist_ok=True)\nwith (out_dir / "findings.csv").open("w", newline="", encoding="utf-8") as f:\n writer = csv.DictWriter(f, fieldnames=["id", "severity", "category", "title", "financial_exposure", "evidence"])\n writer.writeheader()\n writer.writerows(rows)\n```\n\n## Conventions\n\n- Preserve exact IDs, names, amounts, accounts, dates, and source filenames from the analyst or sandbox output.\n- Quote fields through the CSV writer; do not hand-escape rows.\n- Use blank cells for missing values rather than invented values.\n- If there are no findings, still write the header row.',
|
|
87187
87186
|
"allowedTools": [
|
|
87188
87187
|
"writeLocalFile",
|
|
87189
87188
|
"bash",
|
|
@@ -89181,7 +89180,7 @@ var init_managedWorkflowRegistry = __esm({
|
|
|
89181
89180
|
"name": "Payroll Publisher",
|
|
89182
89181
|
"description": "Publishes a payroll approval memo from deterministic run artifacts without recalculating payroll.",
|
|
89183
89182
|
"lane": "writer",
|
|
89184
|
-
"systemPrompt": "# Payroll Publisher\n\nYou publish an approval memo for a completed payroll run.\n\nUse only the deterministic payroll artifact and the analyst output. You may write a short `payroll_output/approval_cover_memo.md` if asked by the coordinator, but you must not alter gross pay, tax cells, deductions, provider import files, or source timesheets.\n\nIf the run is blocked, the memo must say provider import files are not safe to upload until the listed exceptions are fixed and the suite is rerun.\n\nReturn valid JSON matching `schemas/payroll-publisher-output.json
|
|
89183
|
+
"systemPrompt": "# Payroll Publisher\n\nYou publish an approval memo for a completed payroll run.\n\nUse only the deterministic payroll artifact and the analyst output. You may write a short `payroll_output/approval_cover_memo.md` if asked by the coordinator, but you must not alter gross pay, tax cells, deductions, provider import files, or source timesheets.\n\nIf the run is blocked, the memo must say provider import files are not safe to upload until the listed exceptions are fixed and the suite is rerun.\n\nReturn valid JSON matching `schemas/payroll-publisher-output.json`.\n\n---\n\n# Core Perch skill: documents\n\n\n# documents\n\nUse this skill when the user asks Perch to create, revise, review, redline, or deliver a document-shaped artifact.\n\n## Operating Rules\n\n- For long documents, outline the structure before writing the full body.\n- Keep the output as a real deliverable: DOCX, Markdown, Google Doc, or another explicitly requested document target.\n- Preserve source-grounded claims. Load `research`, `pdf`, or `workspace` when citations, page evidence, local files, or source packets drive the content.\n- For Google Docs, use a verified Google Docs shortcut when it can return proof, or hand off to `browser-operator` for live browser editing.\n- Do not claim a header, footer, comment, tracked edit, or page layout feature if the current surface cannot verify it.\n\n## Verification\n\nBefore delivery, check title, body, section order, missing placeholders, citation handoff, and saved file state. Use `references/verification.md` for the compact QA checklist.",
|
|
89185
89184
|
"allowedTools": [
|
|
89186
89185
|
"writeLocalFile",
|
|
89187
89186
|
"readLocalSourceFile",
|
|
@@ -89858,7 +89857,7 @@ var init_managedWorkflowRegistry = __esm({
|
|
|
89858
89857
|
"name": "Statement Publisher",
|
|
89859
89858
|
"description": "Writes the statement audit findings and reconciliation to the output folder.",
|
|
89860
89859
|
"lane": "writer",
|
|
89861
|
-
"systemPrompt": '# Statement Publisher\n\nYou receive the analyst\'s structured output. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `nav-reconciliation.csv`** \u2014 one row per finding from `sandboxArtifact.findings`:\n```\nid,severity,investor,lp_nav,admin_nav,gap,detail\nstmt-nav-mismatch-1,critical,Alpha Capital,200000,115000,85000,"LP ending $200k vs fund admin $115k"\n```\n\n**2. `statement-report.md`** \u2014 structured markdown:\n```markdown\n# LP Statement Audit Report \u2014 {folder name}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## NAV Reconciliation\n{For each finding: investor name, LP NAV, admin NAV, gap amount, source files}\n\n## Recommended Actions\n{Numbered list \u2014 e.g. "Reconcile Alpha Capital $85,000 gap with fund admin before LP distribution"}\n\n## Coverage\n- LP statement records: {metrics.lpStatementRecords}\n- Fund admin records: {metrics.fundAdminRecords}\n- Total findings: {metrics.findingsCount}\n```\n\nThe `folderPath` is in `priorOutput.folderPath`. Use it to build output paths.\n\n## Rules\n\n1. **Write files first, return paths.** The CSV is what compliance reviews.\n2. Investor names and NAV figures must be verbatim from findings \u2014 never paraphrase amounts.\n3. Never fabricate mismatches not in `sandboxArtifact`.\n4. If sandboxArtifact or analyst output is missing, write a report.md explaining what failed.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "reconciliation": "{folderPath}/perch-output/nav-reconciliation.csv",\n "report": "{folderPath}/perch-output/statement-report.md"\n },\n "findingsCount": 0,\n "topFinding": "string or null"\n}\n```\n\n---\n\n
|
|
89860
|
+
"systemPrompt": '# Statement Publisher\n\nYou receive the analyst\'s structured output. Your job is to write deliverable files to disk \u2014 not to summarize in prose.\n\n## What to write\n\nUsing `writeLocalFile`, write two files to `{folderPath}/perch-output/`:\n\n**1. `nav-reconciliation.csv`** \u2014 one row per finding from `sandboxArtifact.findings`:\n```\nid,severity,investor,lp_nav,admin_nav,gap,detail\nstmt-nav-mismatch-1,critical,Alpha Capital,200000,115000,85000,"LP ending $200k vs fund admin $115k"\n```\n\n**2. `statement-report.md`** \u2014 structured markdown:\n```markdown\n# LP Statement Audit Report \u2014 {folder name}\nGenerated: {ISO date}\n\n## Executive Summary\n{analyst executiveSummary}\n\n## Risk Assessment\n**Level:** {level} \u2014 {justification}\n\n## NAV Reconciliation\n{For each finding: investor name, LP NAV, admin NAV, gap amount, source files}\n\n## Recommended Actions\n{Numbered list \u2014 e.g. "Reconcile Alpha Capital $85,000 gap with fund admin before LP distribution"}\n\n## Coverage\n- LP statement records: {metrics.lpStatementRecords}\n- Fund admin records: {metrics.fundAdminRecords}\n- Total findings: {metrics.findingsCount}\n```\n\nThe `folderPath` is in `priorOutput.folderPath`. Use it to build output paths.\n\n## Rules\n\n1. **Write files first, return paths.** The CSV is what compliance reviews.\n2. Investor names and NAV figures must be verbatim from findings \u2014 never paraphrase amounts.\n3. Never fabricate mismatches not in `sandboxArtifact`.\n4. If sandboxArtifact or analyst output is missing, write a report.md explaining what failed.\n\n## Producing Office Files\n\nThe markdown and CSV instructions above still apply. When an Excel workbook is requested or useful for review, produce it as an additional artifact:\n\n1. Use `writeLocalFile` to write a Python script under `/tmp/`.\n2. Run the script with Bash (`python3 /tmp/<script>.py`) using `bash` or `runBashTerminalCommand`.\n3. Save outputs under `{folderPath}/perch-output/`.\n4. Verify the files exist with `ls -l "{folderPath}/perch-output/"`.\n5. Return the verified path in `outputFiles`.\n\nIf the Python Office library is unavailable, fall back to a CSV artifact and return that path clearly.\n\n## Output Schema\n\n```json\n{\n "status": "completed|partial|failed",\n "outputFiles": {\n "reconciliation": "{folderPath}/perch-output/nav-reconciliation.csv",\n "report": "{folderPath}/perch-output/statement-report.md"\n },\n "findingsCount": 0,\n "topFinding": "string or null"\n}\n```\n\n---\n\n# Core Perch skill: spreadsheets\n\n\n# spreadsheets\n\nUse this skill when the user asks for a spreadsheet artifact, spreadsheet inspection, import-ready CSV, formulas, reconciliation tabs, exception tabs, or workbook-quality output.\n\n## Operating Rules\n\n- Profile incoming sheets before changing them: row counts, columns, types, key IDs, totals, and empty fields.\n- Preserve identifiers as text when they are invoice numbers, account numbers, vendor IDs, employee IDs, tickers, or other non-math values.\n- Put source values on input tabs and formulas on analysis tabs when producing XLSX workbooks.\n- Add checks for totals, row counts, formulas, and exception counts when the workbook drives a decision.\n- Use deterministic code or workbook inspection for fragile calculations; do not hand-wave formula behavior.\n\n## Verification\n\nBefore delivery, verify that the file exists, formulas are present where expected, totals reconcile, and CSV exports keep exact values. See `references/workbook-quality.md`.\n\n---\n\n---\nname: csv-findings\ndescription: Produce clean findings CSV files that spreadsheet tools can open reliably.\n---\n\n# csv-findings\n\nUse this skill for required findings, exceptions, reconciliation, or signal CSV deliverables.\n\n## Output contract\n\n- Write CSV files to `{folderPath}/perch-output/`.\n- Use deterministic column order from the base prompt.\n- Return the CSV path in `outputFiles`.\n\n## How to build the CSV\n\nPrefer writing a small Python script to `/tmp/<workflow>-csv-findings.py` and running it with Bash when quoting, commas, newlines, or currency values could be tricky. Use the standard library `csv` module, create `{folderPath}/perch-output/`, and verify with `ls -l "{folderPath}/perch-output/"`.\n\n```python\nimport csv\nfrom pathlib import Path\n\nout_dir = Path(folder_path) / "perch-output"\nout_dir.mkdir(parents=True, exist_ok=True)\nwith (out_dir / "findings.csv").open("w", newline="", encoding="utf-8") as f:\n writer = csv.DictWriter(f, fieldnames=["id", "severity", "category", "title", "financial_exposure", "evidence"])\n writer.writeheader()\n writer.writerows(rows)\n```\n\n## Conventions\n\n- Preserve exact IDs, names, amounts, accounts, dates, and source filenames from the analyst or sandbox output.\n- Quote fields through the CSV writer; do not hand-escape rows.\n- Use blank cells for missing values rather than invented values.\n- If there are no findings, still write the header row.',
|
|
89862
89861
|
"allowedTools": [
|
|
89863
89862
|
"writeLocalFile",
|
|
89864
89863
|
"bash",
|
|
@@ -92161,6 +92160,607 @@ Final message: concise for findings and receipts, usually 10 lines or fewer; con
|
|
|
92161
92160
|
}
|
|
92162
92161
|
});
|
|
92163
92162
|
|
|
92163
|
+
// generated/agentSkillRegistry.ts
|
|
92164
|
+
function getAgentSkillManifest(id) {
|
|
92165
|
+
return AGENT_SKILL_INDEX.get(id) ?? null;
|
|
92166
|
+
}
|
|
92167
|
+
function listAgentSkillMetadataRows() {
|
|
92168
|
+
return AGENT_SKILL_REGISTRY.map((skill) => ({
|
|
92169
|
+
id: skill.id,
|
|
92170
|
+
name: skill.name,
|
|
92171
|
+
description: skill.description,
|
|
92172
|
+
surface: skill.surface,
|
|
92173
|
+
triggerHints: skill.triggerHints.slice()
|
|
92174
|
+
}));
|
|
92175
|
+
}
|
|
92176
|
+
var AGENT_SKILL_REGISTRY, AGENT_SKILL_INDEX;
|
|
92177
|
+
var init_agentSkillRegistry = __esm({
|
|
92178
|
+
"generated/agentSkillRegistry.ts"() {
|
|
92179
|
+
"use strict";
|
|
92180
|
+
AGENT_SKILL_REGISTRY = [
|
|
92181
|
+
{
|
|
92182
|
+
"id": "browser-operator",
|
|
92183
|
+
"name": "browser-operator",
|
|
92184
|
+
"description": "Operate Perch's logged-in browser surface using visual state, semantic DOM targets, and coordinate actions when available.",
|
|
92185
|
+
"path": "features/perchTerminal/agentPlatform/skills/browser-operator/SKILL.md",
|
|
92186
|
+
"body": "\n# browser-operator\n\nUse this skill when Perch must operate a live browser page, especially logged-in apps like Google Docs, Gmail, Calendar, SaaS portals, admin consoles, and forms.\n\n## Operating Loop\n\n1. Observe the current page before acting.\n2. For a short multi-step job, use `browser_execute_task` with `goal`, `requiredValues`, `successCriteria`, and a bounded `steps` list.\n3. For a one-off recovery action, decide whether the next action is semantic or visual.\n4. Take one action.\n5. Observe again and verify the result before continuing.\n6. Stop with a clear blocker when the required action surface is missing.\n\n## Tool Choice\n\n- Use semantic tools for normal web controls: buttons, links, menus, named fields, and visible labels.\n- Prefer `browser_execute_task` when the sequence includes fill \u2192 verify \u2192 submit/save/send. Put the exact recipient, subject, body excerpt, title, date/time, or other must-land values in `requiredValues`.\n- Use `browser_visual_click` or `browser_focus_type` for canvas, iframe, whiteboard, document-body, drag/drop, or visually obvious targets that are not exposed as DOM elements.\n- If coordinate tools are unavailable and the target is only visually reachable, do not loop semantic clicks. Report the missing visual-action capability.\n- For text entry, first focus the target, then type into the focused surface. Do not assume a successful keypress means the text landed.\n\n## Google Docs Rules\n\n- Do not inspect, open, or change the Docs mode dropdown during normal writing. New Docs should already start in Editing mode.\n- If the visible toolbar is already read-only, `Viewing mode`, or `Suggesting mode`, stop and report a permission/mode blocker instead of trying to switch modes yourself.\n- Never click the eye/pencil/mode control or hidden zero-size `Viewing mode` entries. Treat those as fragile controls, not recovery targets.\n- Collapse Document tabs / outline panels before typing if they cover the page.\n- Do not rely on DOM text readback for the document body. Google Docs Kix can show text visually while DOM snapshots stay blank.\n- Body writing should use `browser_focus_type`: visual click into the paper area plus focused typing/key events.\n- Verify by URL, title, save status, and screenshot/visual proof. Treat DOM body text as optional evidence only.\n- Never keep retrying `browser_click` with an empty target. If the paper body is only reachable by coordinate, use coordinate click or stop.\n\n## Completion Proof\n\nReturn success only when there is visible proof, such as:\n\n- a saved/created/sent status,\n- a stable URL,\n- a title or body marker visible in the screenshot,\n- a sent toast or delivery receipt.\n\nIf proof is missing, continue with the next valid recovery path or report the blocker. Do not claim completion from intent alone.",
|
|
92187
|
+
"surface": {
|
|
92188
|
+
"gui": "supported",
|
|
92189
|
+
"cli": "limited"
|
|
92190
|
+
},
|
|
92191
|
+
"triggerHints": [
|
|
92192
|
+
"browser",
|
|
92193
|
+
"web app",
|
|
92194
|
+
"logged-in app",
|
|
92195
|
+
"browser google docs",
|
|
92196
|
+
"gmail browser",
|
|
92197
|
+
"calendar browser",
|
|
92198
|
+
"saas portal",
|
|
92199
|
+
"browser form"
|
|
92200
|
+
],
|
|
92201
|
+
"companionSkills": [
|
|
92202
|
+
"documents",
|
|
92203
|
+
"research",
|
|
92204
|
+
"workspace"
|
|
92205
|
+
],
|
|
92206
|
+
"preferredTools": [
|
|
92207
|
+
"browser_execute_task",
|
|
92208
|
+
"browser_observe",
|
|
92209
|
+
"browser_click",
|
|
92210
|
+
"browser_type",
|
|
92211
|
+
"browser_visual_click",
|
|
92212
|
+
"browser_focus_type",
|
|
92213
|
+
"browser_press_key",
|
|
92214
|
+
"browser_read",
|
|
92215
|
+
"browser_wait",
|
|
92216
|
+
"browser_navigate"
|
|
92217
|
+
]
|
|
92218
|
+
},
|
|
92219
|
+
{
|
|
92220
|
+
"id": "data-quality",
|
|
92221
|
+
"name": "data-quality",
|
|
92222
|
+
"description": "Profile messy data, find anomalies, reconcile systems, explain exceptions, score risk, and produce audit-ready evidence through deterministic math before narrative.",
|
|
92223
|
+
"path": "features/perchTerminal/agentPlatform/skills/data-quality/SKILL.md",
|
|
92224
|
+
"body": "\n# data-quality\n\nUse this skill when the user asks for anomalies, duplicates, reconciliations, risk scoring, exception analysis, or audit-ready data evidence.\n\n## Operating Rules\n\n- Run deterministic math before narrative whenever source tables or files are available.\n- Profile schemas, row counts, nulls, key fields, duplicate keys, totals, and join coverage.\n- Preserve exact identifiers, dates, amounts, source filenames, and exception IDs.\n- Explain each exception with evidence and uncertainty, not only a risk label.\n- Use `spreadsheets` for workbook deliverables and `diagrams` for relationship or network outputs.\n\n## Verification\n\nTie totals, duplicate counts, exception rows, and risk outputs back to deterministic evidence. See `references/reconciliation.md`.",
|
|
92225
|
+
"surface": {
|
|
92226
|
+
"gui": "supported",
|
|
92227
|
+
"cli": "supported"
|
|
92228
|
+
},
|
|
92229
|
+
"triggerHints": [
|
|
92230
|
+
"data quality",
|
|
92231
|
+
"anomaly",
|
|
92232
|
+
"reconciliation",
|
|
92233
|
+
"duplicate payment",
|
|
92234
|
+
"duplicate invoice",
|
|
92235
|
+
"tie out",
|
|
92236
|
+
"row totals",
|
|
92237
|
+
"audit exceptions",
|
|
92238
|
+
"vendor risk",
|
|
92239
|
+
"outlier",
|
|
92240
|
+
"missing receipt",
|
|
92241
|
+
"cost anomaly"
|
|
92242
|
+
],
|
|
92243
|
+
"companionSkills": [
|
|
92244
|
+
"spreadsheets",
|
|
92245
|
+
"workspace",
|
|
92246
|
+
"pdf",
|
|
92247
|
+
"diagrams"
|
|
92248
|
+
],
|
|
92249
|
+
"preferredTools": [
|
|
92250
|
+
"run_sandbox_code",
|
|
92251
|
+
"runSandboxAnalysis",
|
|
92252
|
+
"prepareSandboxInputs",
|
|
92253
|
+
"generateAPAuditPacket",
|
|
92254
|
+
"render_ap_control_graph",
|
|
92255
|
+
"readLocalFile",
|
|
92256
|
+
"writeLocalFile"
|
|
92257
|
+
]
|
|
92258
|
+
},
|
|
92259
|
+
{
|
|
92260
|
+
"id": "diagrams",
|
|
92261
|
+
"name": "diagrams",
|
|
92262
|
+
"description": "Create, edit, and verify diagrams, graphs, workflows, org charts, entity networks, control graphs, architecture maps, and evidence-backed visual structures.",
|
|
92263
|
+
"path": "features/perchTerminal/agentPlatform/skills/diagrams/SKILL.md",
|
|
92264
|
+
"body": "\n# diagrams\n\nUse this skill when the user asks for a diagram, graph, workflow, architecture map, network, org chart, or visual relationship model.\n\n## Operating Rules\n\n- Choose diagram format by use: Mermaid for simple structural diagrams, richer rendered artifacts for shareable or visually complex output.\n- Keep charts and diagrams distinct. Charts quantify data; diagrams explain structure, flow, responsibility, or relationships.\n- Tie graph nodes and edges to evidence when the diagram represents real entities, controls, risks, or findings.\n- Use `data-quality` for anomaly and reconciliation networks, and `presentations` or `documents` when the diagram needs to land in a deck or memo.\n\n## Verification\n\nRender or inspect complex diagrams before delivery. Confirm labels are readable, layout is not tangled, and evidence-backed nodes are traceable. See `references/diagram-quality.md`.",
|
|
92265
|
+
"surface": {
|
|
92266
|
+
"gui": "supported",
|
|
92267
|
+
"cli": "supported"
|
|
92268
|
+
},
|
|
92269
|
+
"triggerHints": [
|
|
92270
|
+
"diagram",
|
|
92271
|
+
"mermaid",
|
|
92272
|
+
"drawio",
|
|
92273
|
+
"workflow graph",
|
|
92274
|
+
"org chart",
|
|
92275
|
+
"entity network",
|
|
92276
|
+
"control graph",
|
|
92277
|
+
"architecture map",
|
|
92278
|
+
"vendor-risk graph",
|
|
92279
|
+
"node edge"
|
|
92280
|
+
],
|
|
92281
|
+
"companionSkills": [
|
|
92282
|
+
"data-quality",
|
|
92283
|
+
"documents",
|
|
92284
|
+
"presentations",
|
|
92285
|
+
"workspace"
|
|
92286
|
+
],
|
|
92287
|
+
"preferredTools": [
|
|
92288
|
+
"render_ap_control_graph",
|
|
92289
|
+
"createTextArtifact",
|
|
92290
|
+
"writeLocalFile",
|
|
92291
|
+
"run_sandbox_code",
|
|
92292
|
+
"visionInspect"
|
|
92293
|
+
]
|
|
92294
|
+
},
|
|
92295
|
+
{
|
|
92296
|
+
"id": "documents",
|
|
92297
|
+
"name": "documents",
|
|
92298
|
+
"description": "Create, edit, verify, and deliver professional document artifacts such as DOCX, Google Docs, memos, letters, reports, redlines, and formal written deliverables.",
|
|
92299
|
+
"path": "features/perchTerminal/agentPlatform/skills/documents/SKILL.md",
|
|
92300
|
+
"body": "\n# documents\n\nUse this skill when the user asks Perch to create, revise, review, redline, or deliver a document-shaped artifact.\n\n## Operating Rules\n\n- For long documents, outline the structure before writing the full body.\n- Keep the output as a real deliverable: DOCX, Markdown, Google Doc, or another explicitly requested document target.\n- Preserve source-grounded claims. Load `research`, `pdf`, or `workspace` when citations, page evidence, local files, or source packets drive the content.\n- For Google Docs, use a verified Google Docs shortcut when it can return proof, or hand off to `browser-operator` for live browser editing.\n- Do not claim a header, footer, comment, tracked edit, or page layout feature if the current surface cannot verify it.\n\n## Verification\n\nBefore delivery, check title, body, section order, missing placeholders, citation handoff, and saved file state. Use `references/verification.md` for the compact QA checklist.",
|
|
92301
|
+
"surface": {
|
|
92302
|
+
"gui": "supported",
|
|
92303
|
+
"cli": "supported"
|
|
92304
|
+
},
|
|
92305
|
+
"triggerHints": [
|
|
92306
|
+
"document",
|
|
92307
|
+
"docx",
|
|
92308
|
+
"word file",
|
|
92309
|
+
"google doc",
|
|
92310
|
+
"memo",
|
|
92311
|
+
"letter",
|
|
92312
|
+
"report",
|
|
92313
|
+
"redline",
|
|
92314
|
+
"tracked changes",
|
|
92315
|
+
"policy",
|
|
92316
|
+
"formal artifact"
|
|
92317
|
+
],
|
|
92318
|
+
"companionSkills": [
|
|
92319
|
+
"research",
|
|
92320
|
+
"pdf",
|
|
92321
|
+
"workspace",
|
|
92322
|
+
"browser-operator"
|
|
92323
|
+
],
|
|
92324
|
+
"preferredTools": [
|
|
92325
|
+
"createDocumentArtifact",
|
|
92326
|
+
"writeLocalFile",
|
|
92327
|
+
"google_docs_create_verified",
|
|
92328
|
+
"google_docs_create",
|
|
92329
|
+
"browser_execute_task",
|
|
92330
|
+
"readLocalFile",
|
|
92331
|
+
"visionInspect"
|
|
92332
|
+
]
|
|
92333
|
+
},
|
|
92334
|
+
{
|
|
92335
|
+
"id": "pdf",
|
|
92336
|
+
"name": "pdf",
|
|
92337
|
+
"description": "Extract, summarize, cite, split, merge, create, inspect, and verify PDF content, including text PDFs, scanned PDFs, tables, forms, page citations, and generated reports.",
|
|
92338
|
+
"path": "features/perchTerminal/agentPlatform/skills/pdf/SKILL.md",
|
|
92339
|
+
"body": "\n# pdf\n\nUse this skill when PDF content is the source, destination, or verification target.\n\n## Operating Rules\n\n- Preserve page awareness. Cite exact pages when answering from a PDF.\n- Treat PDF-to-Markdown and OCR as intermediate views, not final truth.\n- Use table-aware extraction or deterministic code when numbers, rows, or column alignment matter.\n- For scanned PDFs, use visual or OCR fallback and report uncertainty when text is unreadable.\n- Do not invent citations, fields, signatures, or form values.\n\n## Verification\n\nCheck that cited pages support the answer, table values are not flattened incorrectly, and generated PDFs render as expected. See `references/page-citations.md`.",
|
|
92340
|
+
"surface": {
|
|
92341
|
+
"gui": "supported",
|
|
92342
|
+
"cli": "supported"
|
|
92343
|
+
},
|
|
92344
|
+
"triggerHints": [
|
|
92345
|
+
"pdf",
|
|
92346
|
+
"annual report pdf",
|
|
92347
|
+
"scanned pdf",
|
|
92348
|
+
"page citation",
|
|
92349
|
+
"pdf table",
|
|
92350
|
+
"split pdf",
|
|
92351
|
+
"merge pdf",
|
|
92352
|
+
"form pdf",
|
|
92353
|
+
"ocr",
|
|
92354
|
+
"pdf report"
|
|
92355
|
+
],
|
|
92356
|
+
"companionSkills": [
|
|
92357
|
+
"research",
|
|
92358
|
+
"documents",
|
|
92359
|
+
"workspace",
|
|
92360
|
+
"data-quality"
|
|
92361
|
+
],
|
|
92362
|
+
"preferredTools": [
|
|
92363
|
+
"extractDocument",
|
|
92364
|
+
"extractDocumentSection",
|
|
92365
|
+
"visionInspect",
|
|
92366
|
+
"readLocalFile",
|
|
92367
|
+
"run_sandbox_code",
|
|
92368
|
+
"webFetch"
|
|
92369
|
+
]
|
|
92370
|
+
},
|
|
92371
|
+
{
|
|
92372
|
+
"id": "presentations",
|
|
92373
|
+
"name": "presentations",
|
|
92374
|
+
"description": "Build executive decks, board decks, sales decks, research summaries, and visual narratives as PPTX or shareable slide artifacts with verified layout and source-backed content.",
|
|
92375
|
+
"path": "features/perchTerminal/agentPlatform/skills/presentations/SKILL.md",
|
|
92376
|
+
"body": "\n# presentations\n\nUse this skill when the user asks for slides, a deck, a board packet, a pitch, or a visual narrative.\n\n## Operating Rules\n\n- Start with audience, decision, and slide outline before building a long deck.\n- Each slide should carry one takeaway; supporting charts, tables, and bullets must serve that takeaway.\n- Source every important number or claim from provided evidence, workspace files, research, or companion skills.\n- Use `spreadsheets` for chart data, `diagrams` for networks and workflows, and `pdf` when source packets are page-cited.\n- Prefer real deck files when requested. HTML slide experiences are acceptable only when design iteration or sharing calls for them.\n\n## Verification\n\nCheck slide count, readable text, non-overflowing layout, chart/image rendering, and file existence before delivery. See `references/deck-quality.md`.",
|
|
92377
|
+
"surface": {
|
|
92378
|
+
"gui": "supported",
|
|
92379
|
+
"cli": "supported"
|
|
92380
|
+
},
|
|
92381
|
+
"triggerHints": [
|
|
92382
|
+
"deck",
|
|
92383
|
+
"pptx",
|
|
92384
|
+
"powerpoint",
|
|
92385
|
+
"board deck",
|
|
92386
|
+
"slide deck",
|
|
92387
|
+
"presentation",
|
|
92388
|
+
"executive deck",
|
|
92389
|
+
"pitch deck",
|
|
92390
|
+
"sales deck",
|
|
92391
|
+
"speaker notes",
|
|
92392
|
+
"chart slide"
|
|
92393
|
+
],
|
|
92394
|
+
"companionSkills": [
|
|
92395
|
+
"documents",
|
|
92396
|
+
"spreadsheets",
|
|
92397
|
+
"research",
|
|
92398
|
+
"diagrams",
|
|
92399
|
+
"pdf",
|
|
92400
|
+
"workspace"
|
|
92401
|
+
],
|
|
92402
|
+
"preferredTools": [
|
|
92403
|
+
"writeLocalFile",
|
|
92404
|
+
"run_sandbox_code",
|
|
92405
|
+
"createDocumentArtifact",
|
|
92406
|
+
"visionInspect",
|
|
92407
|
+
"readLocalFile"
|
|
92408
|
+
]
|
|
92409
|
+
},
|
|
92410
|
+
{
|
|
92411
|
+
"id": "research",
|
|
92412
|
+
"name": "research",
|
|
92413
|
+
"description": "Gather, compare, rank, and cite evidence from public web sources, scholarly sources, workspace files, source packets, Qdrant knowledge, and attached local folders.",
|
|
92414
|
+
"path": "features/perchTerminal/agentPlatform/skills/research/SKILL.md",
|
|
92415
|
+
"body": "\n# research\n\nUse this skill when the user asks Perch to gather, compare, verify, or cite evidence.\n\n## Operating Rules\n\n- Choose the source lane intentionally: current public questions use web; attached folders use workspace or local sources; internal product questions use repo/workspace evidence; stored examples use knowledge.\n- Do not use knowledge retrieval as a catch-all when a domain or workspace tool is more direct.\n- Rank sources by authority, recency, relevance, and proximity to the claim.\n- Surface contradictions instead of averaging them away.\n- Keep citations concise and visibly tied to titles, URLs, files, pages, or evidence IDs.\n\n## Verification\n\nCheck freshness requirements, cite the actual sources used, and label uncertainty when sources are missing or disagree. See `references/source-quality.md`.",
|
|
92416
|
+
"surface": {
|
|
92417
|
+
"gui": "supported",
|
|
92418
|
+
"cli": "supported"
|
|
92419
|
+
},
|
|
92420
|
+
"triggerHints": [
|
|
92421
|
+
"research",
|
|
92422
|
+
"web research",
|
|
92423
|
+
"credible sources",
|
|
92424
|
+
"current source",
|
|
92425
|
+
"citation",
|
|
92426
|
+
"source comparison",
|
|
92427
|
+
"filing",
|
|
92428
|
+
"scholarly source",
|
|
92429
|
+
"public web",
|
|
92430
|
+
"fact check",
|
|
92431
|
+
"latest"
|
|
92432
|
+
],
|
|
92433
|
+
"companionSkills": [
|
|
92434
|
+
"pdf",
|
|
92435
|
+
"documents",
|
|
92436
|
+
"workspace",
|
|
92437
|
+
"data-quality"
|
|
92438
|
+
],
|
|
92439
|
+
"preferredTools": [
|
|
92440
|
+
"webSearch",
|
|
92441
|
+
"webFetch",
|
|
92442
|
+
"scholarSearch",
|
|
92443
|
+
"searchKnowledge",
|
|
92444
|
+
"searchWorkspaceSources",
|
|
92445
|
+
"readLocalSourceFile",
|
|
92446
|
+
"listLocalSources"
|
|
92447
|
+
]
|
|
92448
|
+
},
|
|
92449
|
+
{
|
|
92450
|
+
"id": "skill-creator",
|
|
92451
|
+
"name": "skill-creator",
|
|
92452
|
+
"description": "Create, validate, package, and test Perch skills with frontmatter checks, trigger collision detection, reference validation, surface metadata, and acceptance tasks.",
|
|
92453
|
+
"path": "features/perchTerminal/agentPlatform/skills/skill-creator/SKILL.md",
|
|
92454
|
+
"body": "\n# skill-creator\n\nUse this skill when creating, updating, validating, or evaluating Perch skills.\n\n## Operating Rules\n\n- Keep each skill as one reusable workflow unit with `SKILL.md`, optional `references/`, optional `scripts/`, and optional `assets/`.\n- Frontmatter must include `name`, `description`, and Perch metadata for GUI and CLI surface support.\n- Trigger hints should be precise enough to activate the skill without colliding with unrelated skills.\n- Put detailed reusable rules in reference files and fragile deterministic checks in scripts.\n- Add at least one acceptance task for each supported surface when the skill is productized.\n\n## Verification\n\nRun skill codegen and registry tests after edits. Use `references/validation-checklist.md` before declaring a skill ready.",
|
|
92455
|
+
"surface": {
|
|
92456
|
+
"gui": "supported",
|
|
92457
|
+
"cli": "supported"
|
|
92458
|
+
},
|
|
92459
|
+
"triggerHints": [
|
|
92460
|
+
"skill creator",
|
|
92461
|
+
"create skill",
|
|
92462
|
+
"skill.md",
|
|
92463
|
+
"agent skill",
|
|
92464
|
+
"skill validation",
|
|
92465
|
+
"trigger collision",
|
|
92466
|
+
"skill test",
|
|
92467
|
+
"skill authoring",
|
|
92468
|
+
"perch skill"
|
|
92469
|
+
],
|
|
92470
|
+
"companionSkills": [
|
|
92471
|
+
"workspace",
|
|
92472
|
+
"data-quality"
|
|
92473
|
+
],
|
|
92474
|
+
"preferredTools": [
|
|
92475
|
+
"glob",
|
|
92476
|
+
"grep",
|
|
92477
|
+
"readLocalFile",
|
|
92478
|
+
"writeLocalFile",
|
|
92479
|
+
"bash"
|
|
92480
|
+
]
|
|
92481
|
+
},
|
|
92482
|
+
{
|
|
92483
|
+
"id": "spreadsheets",
|
|
92484
|
+
"name": "spreadsheets",
|
|
92485
|
+
"description": "Create, inspect, clean, calculate, format, and verify spreadsheet artifacts such as XLSX, CSV, TSV, Google Sheets, formulas, pivots, charts, and reconciliation workbooks.",
|
|
92486
|
+
"path": "features/perchTerminal/agentPlatform/skills/spreadsheets/SKILL.md",
|
|
92487
|
+
"body": "\n# spreadsheets\n\nUse this skill when the user asks for a spreadsheet artifact, spreadsheet inspection, import-ready CSV, formulas, reconciliation tabs, exception tabs, or workbook-quality output.\n\n## Operating Rules\n\n- Profile incoming sheets before changing them: row counts, columns, types, key IDs, totals, and empty fields.\n- Preserve identifiers as text when they are invoice numbers, account numbers, vendor IDs, employee IDs, tickers, or other non-math values.\n- Put source values on input tabs and formulas on analysis tabs when producing XLSX workbooks.\n- Add checks for totals, row counts, formulas, and exception counts when the workbook drives a decision.\n- Use deterministic code or workbook inspection for fragile calculations; do not hand-wave formula behavior.\n\n## Verification\n\nBefore delivery, verify that the file exists, formulas are present where expected, totals reconcile, and CSV exports keep exact values. See `references/workbook-quality.md`.",
|
|
92488
|
+
"surface": {
|
|
92489
|
+
"gui": "supported",
|
|
92490
|
+
"cli": "supported"
|
|
92491
|
+
},
|
|
92492
|
+
"triggerHints": [
|
|
92493
|
+
"spreadsheet",
|
|
92494
|
+
"xlsx",
|
|
92495
|
+
"excel workbook",
|
|
92496
|
+
"csv",
|
|
92497
|
+
"tsv",
|
|
92498
|
+
"google sheet",
|
|
92499
|
+
"formula",
|
|
92500
|
+
"pivot",
|
|
92501
|
+
"reconciliation tab",
|
|
92502
|
+
"exception tab",
|
|
92503
|
+
"import template",
|
|
92504
|
+
"row count",
|
|
92505
|
+
"workbook check"
|
|
92506
|
+
],
|
|
92507
|
+
"companionSkills": [
|
|
92508
|
+
"data-quality",
|
|
92509
|
+
"workspace",
|
|
92510
|
+
"pdf",
|
|
92511
|
+
"research"
|
|
92512
|
+
],
|
|
92513
|
+
"preferredTools": [
|
|
92514
|
+
"inspectWorkbookSheets",
|
|
92515
|
+
"google_sheets_create",
|
|
92516
|
+
"google_sheets_append_rows",
|
|
92517
|
+
"writeLocalFile",
|
|
92518
|
+
"run_sandbox_code",
|
|
92519
|
+
"bash",
|
|
92520
|
+
"readLocalFile"
|
|
92521
|
+
]
|
|
92522
|
+
},
|
|
92523
|
+
{
|
|
92524
|
+
"id": "workspace",
|
|
92525
|
+
"name": "workspace",
|
|
92526
|
+
"description": "Navigate, inspect, search, summarize, and safely edit local workspaces, attached folders, source inventories, project files, and codebases with exact file-grounded evidence.",
|
|
92527
|
+
"path": "features/perchTerminal/agentPlatform/skills/workspace/SKILL.md",
|
|
92528
|
+
"body": "\n# workspace\n\nUse this skill when the task requires local files, attached folders, repo search, safe edits, or source inventory.\n\n## Operating Rules\n\n- Start with inventory or targeted search before reading many files.\n- Cite exact files when answering codebase or workspace questions.\n- Distinguish direct filesystem reads, indexed local source retrieval, Supabase source packets, and Qdrant knowledge.\n- Do not say Perch cannot access a file path when the local runtime and permissions make it accessible.\n- For edits, keep changes scoped and preserve unrelated user work.\n\n## Verification\n\nCheck file existence, paths, and write results before reporting completion. Use `references/source-boundaries.md` to keep source lanes clear.",
|
|
92529
|
+
"surface": {
|
|
92530
|
+
"gui": "supported",
|
|
92531
|
+
"cli": "supported"
|
|
92532
|
+
},
|
|
92533
|
+
"triggerHints": [
|
|
92534
|
+
"repo",
|
|
92535
|
+
"codebase",
|
|
92536
|
+
"local folder",
|
|
92537
|
+
"workspace",
|
|
92538
|
+
"find file",
|
|
92539
|
+
"inspect folder",
|
|
92540
|
+
"search files",
|
|
92541
|
+
"edit file",
|
|
92542
|
+
"source inventory",
|
|
92543
|
+
"project files"
|
|
92544
|
+
],
|
|
92545
|
+
"companionSkills": [
|
|
92546
|
+
"research",
|
|
92547
|
+
"pdf",
|
|
92548
|
+
"data-quality",
|
|
92549
|
+
"skill-creator"
|
|
92550
|
+
],
|
|
92551
|
+
"preferredTools": [
|
|
92552
|
+
"glob",
|
|
92553
|
+
"grep",
|
|
92554
|
+
"readLocalFile",
|
|
92555
|
+
"writeLocalFile",
|
|
92556
|
+
"statPath",
|
|
92557
|
+
"listLocalSources",
|
|
92558
|
+
"readLocalSourceFile",
|
|
92559
|
+
"bash"
|
|
92560
|
+
]
|
|
92561
|
+
}
|
|
92562
|
+
];
|
|
92563
|
+
AGENT_SKILL_INDEX = /* @__PURE__ */ new Map();
|
|
92564
|
+
for (const skill of AGENT_SKILL_REGISTRY) {
|
|
92565
|
+
if (AGENT_SKILL_INDEX.has(skill.id)) {
|
|
92566
|
+
throw new Error(`generated registry duplicate skill id: ${skill.id}`);
|
|
92567
|
+
}
|
|
92568
|
+
AGENT_SKILL_INDEX.set(skill.id, skill);
|
|
92569
|
+
}
|
|
92570
|
+
}
|
|
92571
|
+
});
|
|
92572
|
+
|
|
92573
|
+
// features/perchTerminal/agentPlatform/skills/skillSelector.ts
|
|
92574
|
+
function normalizeText(input) {
|
|
92575
|
+
return input.toLowerCase().replace(/\s+/g, " ").trim();
|
|
92576
|
+
}
|
|
92577
|
+
function escapeRegExp2(input) {
|
|
92578
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
92579
|
+
}
|
|
92580
|
+
function triggerMatches(text, trigger) {
|
|
92581
|
+
const normalized = normalizeText(trigger);
|
|
92582
|
+
if (!normalized) return false;
|
|
92583
|
+
return new RegExp(`(^|[^a-z0-9])${escapeRegExp2(normalized)}([^a-z0-9]|$)`, "i").test(text);
|
|
92584
|
+
}
|
|
92585
|
+
function skillMatches(skill, text) {
|
|
92586
|
+
if (skill.triggerHints.some((trigger) => triggerMatches(text, trigger))) {
|
|
92587
|
+
return true;
|
|
92588
|
+
}
|
|
92589
|
+
return (INTENT_PATTERNS[skill.id] ?? []).some(
|
|
92590
|
+
(pattern) => pattern.test(text)
|
|
92591
|
+
);
|
|
92592
|
+
}
|
|
92593
|
+
function isMarketDeskSignalTask(text, availableToolNames) {
|
|
92594
|
+
const hasMarketDeskTool = [...MARKET_DESK_TOOL_NAMES].some(
|
|
92595
|
+
(toolName) => availableToolNames.has(toolName)
|
|
92596
|
+
);
|
|
92597
|
+
return hasMarketDeskTool && /\b(market\s+desk|signal|strategy|backtest|track\s+record)\b/i.test(text) && /\b[A-Z]{1,5}\b/.test(text);
|
|
92598
|
+
}
|
|
92599
|
+
function selectionText(input) {
|
|
92600
|
+
return [
|
|
92601
|
+
input.userMessage,
|
|
92602
|
+
input.currentMode ?? "",
|
|
92603
|
+
input.personaId ?? "",
|
|
92604
|
+
input.selectedFolder ?? "",
|
|
92605
|
+
...input.selectedFiles ?? [],
|
|
92606
|
+
input.sourceSummary ?? ""
|
|
92607
|
+
].filter(Boolean).join("\n");
|
|
92608
|
+
}
|
|
92609
|
+
function canUseSkillOnSurface(skill, input, availableToolNames) {
|
|
92610
|
+
if (skill.surface[input.surface] === "unsupported") {
|
|
92611
|
+
return `${input.surface.toUpperCase()} surface is unsupported`;
|
|
92612
|
+
}
|
|
92613
|
+
if (skill.id === "browser-operator" && ![...availableToolNames].some((toolName) => BROWSER_TOOL_NAMES.has(toolName))) {
|
|
92614
|
+
return "browser operator tools are not available this turn";
|
|
92615
|
+
}
|
|
92616
|
+
return null;
|
|
92617
|
+
}
|
|
92618
|
+
function priorityIndex(skillId) {
|
|
92619
|
+
const index = CORE_PRIORITY.indexOf(skillId);
|
|
92620
|
+
return index === -1 ? CORE_PRIORITY.length : index;
|
|
92621
|
+
}
|
|
92622
|
+
function sortSkillIds(ids) {
|
|
92623
|
+
return [...ids].sort(
|
|
92624
|
+
(a, b2) => priorityIndex(a) - priorityIndex(b2) || a.localeCompare(b2)
|
|
92625
|
+
);
|
|
92626
|
+
}
|
|
92627
|
+
function selectAgentSkills(input) {
|
|
92628
|
+
const maxSelected = Math.max(
|
|
92629
|
+
0,
|
|
92630
|
+
input.maxSelectedSkills ?? DEFAULT_MAX_SELECTED_SKILLS
|
|
92631
|
+
);
|
|
92632
|
+
const availableToolNames = new Set(input.availableToolNames ?? []);
|
|
92633
|
+
const text = selectionText(input);
|
|
92634
|
+
const normalizedText = normalizeText(text);
|
|
92635
|
+
const byId = new Map(AGENT_SKILL_REGISTRY.map((skill) => [skill.id, skill]));
|
|
92636
|
+
const metadataRows = AGENT_SKILL_REGISTRY.map((skill) => ({
|
|
92637
|
+
id: skill.id,
|
|
92638
|
+
name: skill.name,
|
|
92639
|
+
description: skill.description
|
|
92640
|
+
}));
|
|
92641
|
+
const omitted = [];
|
|
92642
|
+
const explicit = /* @__PURE__ */ new Set();
|
|
92643
|
+
for (const skill of AGENT_SKILL_REGISTRY) {
|
|
92644
|
+
if (skillMatches(skill, normalizedText)) explicit.add(skill.id);
|
|
92645
|
+
}
|
|
92646
|
+
if (/\bgoogle\s+docs?\b/i.test(text) && availableToolNames.has("browser_execute_task")) {
|
|
92647
|
+
explicit.add("documents");
|
|
92648
|
+
explicit.add("browser-operator");
|
|
92649
|
+
}
|
|
92650
|
+
if (/\b(this|attached|local)\s+folder\b/i.test(text) || Boolean(input.selectedFolder) && /\bfolder\b/i.test(text)) {
|
|
92651
|
+
explicit.add("workspace");
|
|
92652
|
+
}
|
|
92653
|
+
if (/\b(ap|accounts?\s+payable)\b/i.test(text)) {
|
|
92654
|
+
explicit.add("data-quality");
|
|
92655
|
+
}
|
|
92656
|
+
if (isMarketDeskSignalTask(text, availableToolNames)) {
|
|
92657
|
+
explicit.delete("research");
|
|
92658
|
+
omitted.push({
|
|
92659
|
+
id: "research",
|
|
92660
|
+
reason: "market-desk signal tasks should use Market Desk tools before public research"
|
|
92661
|
+
});
|
|
92662
|
+
}
|
|
92663
|
+
const companionExpanded = /* @__PURE__ */ new Set();
|
|
92664
|
+
for (const id of sortSkillIds(explicit)) {
|
|
92665
|
+
const skill = byId.get(id);
|
|
92666
|
+
if (!skill) continue;
|
|
92667
|
+
for (const companionId of skill.companionSkills) {
|
|
92668
|
+
if (!explicit.has(companionId)) companionExpanded.add(companionId);
|
|
92669
|
+
}
|
|
92670
|
+
}
|
|
92671
|
+
const selected = [];
|
|
92672
|
+
for (const id of [
|
|
92673
|
+
...sortSkillIds(explicit),
|
|
92674
|
+
...sortSkillIds(companionExpanded)
|
|
92675
|
+
]) {
|
|
92676
|
+
const skill = byId.get(id);
|
|
92677
|
+
if (!skill) continue;
|
|
92678
|
+
const omittedReason = canUseSkillOnSurface(skill, input, availableToolNames);
|
|
92679
|
+
if (omittedReason) {
|
|
92680
|
+
omitted.push({ id, reason: omittedReason });
|
|
92681
|
+
continue;
|
|
92682
|
+
}
|
|
92683
|
+
if (selected.length >= maxSelected) {
|
|
92684
|
+
omitted.push({ id, reason: `max selected skills reached (${maxSelected})` });
|
|
92685
|
+
continue;
|
|
92686
|
+
}
|
|
92687
|
+
selected.push(skill);
|
|
92688
|
+
}
|
|
92689
|
+
return { metadataRows, selected, omitted };
|
|
92690
|
+
}
|
|
92691
|
+
var DEFAULT_MAX_SELECTED_SKILLS, BROWSER_TOOL_NAMES, CORE_PRIORITY, INTENT_PATTERNS;
|
|
92692
|
+
var init_skillSelector = __esm({
|
|
92693
|
+
"features/perchTerminal/agentPlatform/skills/skillSelector.ts"() {
|
|
92694
|
+
init_agentSkillRegistry();
|
|
92695
|
+
init_marketDeskAccess();
|
|
92696
|
+
DEFAULT_MAX_SELECTED_SKILLS = 4;
|
|
92697
|
+
BROWSER_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
92698
|
+
"browser_execute_task",
|
|
92699
|
+
"browser_observe",
|
|
92700
|
+
"browser_click",
|
|
92701
|
+
"browser_type",
|
|
92702
|
+
"browser_visual_click",
|
|
92703
|
+
"browser_focus_type",
|
|
92704
|
+
"browser_press_key",
|
|
92705
|
+
"browser_read",
|
|
92706
|
+
"browser_wait",
|
|
92707
|
+
"browser_navigate"
|
|
92708
|
+
]);
|
|
92709
|
+
CORE_PRIORITY = [
|
|
92710
|
+
"data-quality",
|
|
92711
|
+
"presentations",
|
|
92712
|
+
"spreadsheets",
|
|
92713
|
+
"documents",
|
|
92714
|
+
"pdf",
|
|
92715
|
+
"research",
|
|
92716
|
+
"diagrams",
|
|
92717
|
+
"workspace",
|
|
92718
|
+
"browser-operator",
|
|
92719
|
+
"skill-creator"
|
|
92720
|
+
];
|
|
92721
|
+
INTENT_PATTERNS = {
|
|
92722
|
+
"browser-operator": [
|
|
92723
|
+
/\b(browser|web\s+app|logged[-\s]?in|saas|portal|form)\b/i,
|
|
92724
|
+
/\b(gmail|google\s+docs?|google\s+calendar|notion|salesforce)\b/i
|
|
92725
|
+
],
|
|
92726
|
+
documents: [
|
|
92727
|
+
/\b(docx|word\s+file|google\s+docs?|memo|letter|report|redline|tracked\s+changes?|policy|formal\s+artifact)\b/i,
|
|
92728
|
+
/\b(create|write|draft|revise|edit|publish|deliver)\b.{0,48}\b(document|doc|memo|report|letter)\b/i
|
|
92729
|
+
],
|
|
92730
|
+
spreadsheets: [
|
|
92731
|
+
/\b(spreadsheet|xlsx|excel|workbook|csv|tsv|google\s+sheet|formula|pivot|reconciliation\s+tab|exception\s+tab|import\s+template)\b/i,
|
|
92732
|
+
/\b(row\s+count|totals?|tie[-\s]?out|sheet)\b/i
|
|
92733
|
+
],
|
|
92734
|
+
presentations: [
|
|
92735
|
+
/\b(deck|pptx|powerpoint|slides?|presentation|board\s+deck|executive\s+deck|pitch\s+deck|sales\s+deck|speaker\s+notes?)\b/i
|
|
92736
|
+
],
|
|
92737
|
+
pdf: [
|
|
92738
|
+
/\b(pdf|scanned\s+pdf|page\s+citation|pdf\s+table|split\s+pdf|merge\s+pdf|ocr|annual\s+report)\b/i,
|
|
92739
|
+
/\.pdf\b/i
|
|
92740
|
+
],
|
|
92741
|
+
research: [
|
|
92742
|
+
/\b(research|credible\s+sources?|current\s+source|citations?|source\s+comparison|scholarly|public\s+web|fact[-\s]?check|latest|recent|filing)\b/i,
|
|
92743
|
+
/\b(find|gather|compare|verify)\b.{0,48}\b(sources?|evidence|filings?)\b/i
|
|
92744
|
+
],
|
|
92745
|
+
diagrams: [
|
|
92746
|
+
/\b(diagram|mermaid|drawio|workflow\s+graph|org\s+chart|entity\s+network|control\s+graph|architecture\s+map|vendor[-\s]?risk\s+graph|nodes?\s+and\s+edges?)\b/i,
|
|
92747
|
+
/\b(graph|map)\b.{0,32}\b(risk|workflow|architecture|network|relationship)\b/i
|
|
92748
|
+
],
|
|
92749
|
+
workspace: [
|
|
92750
|
+
/\b(repo|codebase|local\s+folder|workspace|find\s+file|inspect\s+folder|search\s+files?|edit\s+file|source\s+inventory|project\s+files?)\b/i,
|
|
92751
|
+
/\b(this\s+repo|this\s+folder|attached\s+folder|in\s+this\s+workspace)\b/i
|
|
92752
|
+
],
|
|
92753
|
+
"data-quality": [
|
|
92754
|
+
/\b(data\s+quality|anomal(?:y|ies)|reconciliation|duplicate\s+(?:payment|invoice)|tie[-\s]?out|row\s+totals?|audit\s+exceptions?|vendor\s+risk|outliers?|missing\s+receipt|cost\s+anomal(?:y|ies))\b/i,
|
|
92755
|
+
/\b(audit|reconcile|profile|clean)\b.{0,56}\b(ap|accounts?\s+payable|payments?|invoices?|vendors?|data|folder)\b/i
|
|
92756
|
+
],
|
|
92757
|
+
"skill-creator": [
|
|
92758
|
+
/\b(skill\s+creator|create\s+(?:a\s+)?skill|skill\.md|agent\s+skill|skill\s+validation|trigger\s+collision|skill\s+test|skill\s+authoring|perch\s+skill)\b/i
|
|
92759
|
+
]
|
|
92760
|
+
};
|
|
92761
|
+
}
|
|
92762
|
+
});
|
|
92763
|
+
|
|
92164
92764
|
// features/perchTerminal/runtime/context/tokenEstimates.ts
|
|
92165
92765
|
function estimateTokensForLane(text, lane, modelTokenize) {
|
|
92166
92766
|
return countTokensForLane(
|
|
@@ -92237,6 +92837,26 @@ function assembleContext(input) {
|
|
|
92237
92837
|
const contextCompaction = input.threadId ? getThreadSessionFromMemory(input.threadId)?.contextCompaction ?? null : null;
|
|
92238
92838
|
const threadSession = input.threadId ? getThreadSessionFromMemory(input.threadId) : null;
|
|
92239
92839
|
const coreSystem = buildCoreSystemSection(input);
|
|
92840
|
+
const selectedSkillPack = selectAgentSkills({
|
|
92841
|
+
userMessage: input.trimmedInput,
|
|
92842
|
+
currentMode: input.chatMode,
|
|
92843
|
+
personaId: input.personaId ?? null,
|
|
92844
|
+
selectedFiles: [
|
|
92845
|
+
...input.workspaceFileResolution?.matchedFiles.map(
|
|
92846
|
+
(file) => file.relativePath
|
|
92847
|
+
) ?? [],
|
|
92848
|
+
...(input.localSources ?? []).slice(0, 12).map((source) => source.relativePath || source.fileName)
|
|
92849
|
+
],
|
|
92850
|
+
selectedFolder: input.activeRootPath,
|
|
92851
|
+
sourceSummary: [
|
|
92852
|
+
input.selectedSourceId ? `selected source ${input.selectedSourceId}` : "",
|
|
92853
|
+
input.folderIndexSummary ? `folder indexed ${input.folderIndexSummary.totalFiles} files` : "",
|
|
92854
|
+
input.selectedSourceBundle?.fileName ?? ""
|
|
92855
|
+
].filter(Boolean).join("\n"),
|
|
92856
|
+
availableToolNames: input.enabledToolNames ?? [],
|
|
92857
|
+
surface: input.skillSelectionSurface ?? (input.cliLocalTools === true && !input.desktopConnected ? "cli" : "gui")
|
|
92858
|
+
});
|
|
92859
|
+
const selectedSkillsSection = buildSelectedSkillsSection(selectedSkillPack);
|
|
92240
92860
|
const selectedModelSection = buildSelectedModelSection(
|
|
92241
92861
|
input.selectedModel ?? null
|
|
92242
92862
|
);
|
|
@@ -92300,6 +92920,7 @@ function assembleContext(input) {
|
|
|
92300
92920
|
content: coreSystem,
|
|
92301
92921
|
reason: "Core operator instructions for the current turn."
|
|
92302
92922
|
},
|
|
92923
|
+
selectedSkillsSection,
|
|
92303
92924
|
...toolsJson ? [
|
|
92304
92925
|
{
|
|
92305
92926
|
id: "tool-schemas",
|
|
@@ -92401,6 +93022,7 @@ function assembleContext(input) {
|
|
|
92401
93022
|
});
|
|
92402
93023
|
const systemPrompt = systemSections.filter((row) => row.trim()).join("\n\n");
|
|
92403
93024
|
const sectionBreakdown = buildSectionBreakdown(rows);
|
|
93025
|
+
const selectedSkillIds = selectedSkillPack.selected.map((skill) => skill.id);
|
|
92404
93026
|
const totalContextTokens = rows.filter((row) => row.status !== "reserved").reduce((sum, row) => sum + row.estimatedTokens, 0);
|
|
92405
93027
|
const compactedCount = rows.filter(
|
|
92406
93028
|
(row) => row.status === "sent_compacted"
|
|
@@ -92439,7 +93061,9 @@ function assembleContext(input) {
|
|
|
92439
93061
|
activeRootPath: input.activeRootPath,
|
|
92440
93062
|
recentMessageCount: input.recentMessages.length,
|
|
92441
93063
|
selectedModel: input.selectedModel ?? null,
|
|
92442
|
-
untrustedContextPresent
|
|
93064
|
+
untrustedContextPresent,
|
|
93065
|
+
selectedSkills: selectedSkillIds,
|
|
93066
|
+
omittedSkills: selectedSkillPack.omitted
|
|
92443
93067
|
},
|
|
92444
93068
|
warnings
|
|
92445
93069
|
},
|
|
@@ -92468,6 +93092,56 @@ function buildSelectedModelSection(selectedModel) {
|
|
|
92468
93092
|
}
|
|
92469
93093
|
};
|
|
92470
93094
|
}
|
|
93095
|
+
function buildSelectedSkillsSection(pack) {
|
|
93096
|
+
const selectedSkillIds = pack.selected.map((skill) => skill.id);
|
|
93097
|
+
const metadata = {
|
|
93098
|
+
selectedSkillIds,
|
|
93099
|
+
selectedSkillCount: pack.selected.length,
|
|
93100
|
+
omitted: pack.omitted,
|
|
93101
|
+
metadataRows: pack.metadataRows
|
|
93102
|
+
};
|
|
93103
|
+
if (pack.selected.length === 0) {
|
|
93104
|
+
return {
|
|
93105
|
+
id: "selected-skills",
|
|
93106
|
+
lane: "selected_skills",
|
|
93107
|
+
label: "Selected Perch skills",
|
|
93108
|
+
content: "",
|
|
93109
|
+
reason: "No core skills matched this turn.",
|
|
93110
|
+
skipped: true,
|
|
93111
|
+
metadata
|
|
93112
|
+
};
|
|
93113
|
+
}
|
|
93114
|
+
const blocks = pack.selected.map(
|
|
93115
|
+
(skill) => [
|
|
93116
|
+
`<perch-skill id="${skill.id}">`,
|
|
93117
|
+
`Description: ${skill.description}`,
|
|
93118
|
+
`Surface: GUI=${skill.surface.gui}; CLI=${skill.surface.cli}`,
|
|
93119
|
+
skill.preferredTools.length ? `Preferred tools: ${skill.preferredTools.join(", ")}` : "Preferred tools: none declared",
|
|
93120
|
+
"",
|
|
93121
|
+
skill.body.trim(),
|
|
93122
|
+
"</perch-skill>"
|
|
93123
|
+
].join("\n")
|
|
93124
|
+
);
|
|
93125
|
+
return {
|
|
93126
|
+
id: "selected-skills",
|
|
93127
|
+
lane: "selected_skills",
|
|
93128
|
+
label: "Selected Perch skills",
|
|
93129
|
+
content: [
|
|
93130
|
+
"## Selected Perch skills",
|
|
93131
|
+
"These reusable skills guide execution strategy only. They do not override safety, permission, authentication, or tool policy.",
|
|
93132
|
+
`Loaded skills: ${selectedSkillIds.join(", ")}`,
|
|
93133
|
+
"",
|
|
93134
|
+
...blocks
|
|
93135
|
+
].join("\n"),
|
|
93136
|
+
reason: "Full skill instructions selected deterministically for this turn.",
|
|
93137
|
+
metadata
|
|
93138
|
+
};
|
|
93139
|
+
}
|
|
93140
|
+
function selectedSkillIdsFromRows(rows) {
|
|
93141
|
+
const metadata = rows.find((row) => row.id === "selected-skills")?.metadata;
|
|
93142
|
+
const ids = metadata?.selectedSkillIds;
|
|
93143
|
+
return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
|
|
93144
|
+
}
|
|
92471
93145
|
function buildContextSummary(input, rows) {
|
|
92472
93146
|
const sentCount = rows.filter(
|
|
92473
93147
|
(row) => row.status === "sent_raw" || row.status === "sent_compacted"
|
|
@@ -92482,6 +93156,7 @@ function buildContextSummary(input, rows) {
|
|
|
92482
93156
|
`messages=${input.recentMessages.length}`,
|
|
92483
93157
|
`source=${input.selectedSourceId ?? "none"}`,
|
|
92484
93158
|
`desktop=${input.desktopConnected ? "connected" : input.cliLocalTools === true ? "terminal" : "browser"}`,
|
|
93159
|
+
`skills=${selectedSkillIdsFromRows(rows).join("|") || "none"}`,
|
|
92485
93160
|
`sent=${sentCount}`,
|
|
92486
93161
|
`compacted=${compactedCount}`,
|
|
92487
93162
|
`not_found=${notFoundCount}`,
|
|
@@ -92501,6 +93176,7 @@ var init_contextAssembly = __esm({
|
|
|
92501
93176
|
init_rowAccounting();
|
|
92502
93177
|
init_memory();
|
|
92503
93178
|
init_coreSystemSection();
|
|
93179
|
+
init_skillSelector();
|
|
92504
93180
|
init_contextThresholds();
|
|
92505
93181
|
init_tokenEstimates();
|
|
92506
93182
|
init_rowAccounting();
|
|
@@ -133611,6 +134287,17 @@ var init_toolPermissionPolicy = __esm({
|
|
|
133611
134287
|
TOOL_NAMES.prepareAPEvidence,
|
|
133612
134288
|
TOOL_NAMES.queryAPCases,
|
|
133613
134289
|
TOOL_NAMES.renderAPControlGraph,
|
|
134290
|
+
TOOL_NAMES.runManagedPlaybook,
|
|
134291
|
+
TOOL_NAMES.runSuite,
|
|
134292
|
+
TOOL_NAMES.listSuiteCatalog,
|
|
134293
|
+
TOOL_NAMES.proposeSuitePlan,
|
|
134294
|
+
TOOL_NAMES.executeSuitePlan,
|
|
134295
|
+
TOOL_NAMES.proposeWork,
|
|
134296
|
+
TOOL_NAMES.executeWork,
|
|
134297
|
+
TOOL_NAMES.sendWorkerMessage,
|
|
134298
|
+
TOOL_NAMES.taskStop,
|
|
134299
|
+
TOOL_NAMES.spawnWorker,
|
|
134300
|
+
TOOL_NAMES.dispatchAgent,
|
|
133614
134301
|
TOOL_NAMES.runSandboxCode
|
|
133615
134302
|
];
|
|
133616
134303
|
CLI_LOCAL_TOOL_NAME_SET = new Set(CLI_LOCAL_TOOL_NAMES);
|
|
@@ -168151,7 +168838,7 @@ function template(text, settings, oldSettings) {
|
|
|
168151
168838
|
var index = 0;
|
|
168152
168839
|
var source = "__p+='";
|
|
168153
168840
|
text.replace(matcher2, function(match, escape4, interpolate, evaluate, offset) {
|
|
168154
|
-
source += text.slice(index, offset).replace(
|
|
168841
|
+
source += text.slice(index, offset).replace(escapeRegExp3, escapeChar);
|
|
168155
168842
|
index = offset + match.length;
|
|
168156
168843
|
if (escape4) {
|
|
168157
168844
|
source += "'+\n((__t=(" + escape4 + "))==null?'':_.escape(__t))+\n'";
|
|
@@ -168186,7 +168873,7 @@ function template(text, settings, oldSettings) {
|
|
|
168186
168873
|
template2.source = "function(" + argument + "){\n" + source + "}";
|
|
168187
168874
|
return template2;
|
|
168188
168875
|
}
|
|
168189
|
-
var noMatch, escapes,
|
|
168876
|
+
var noMatch, escapes, escapeRegExp3, bareIdentifier;
|
|
168190
168877
|
var init_template = __esm({
|
|
168191
168878
|
"node_modules/underscore/modules/template.js"() {
|
|
168192
168879
|
init_defaults();
|
|
@@ -168201,7 +168888,7 @@ var init_template = __esm({
|
|
|
168201
168888
|
"\u2028": "u2028",
|
|
168202
168889
|
"\u2029": "u2029"
|
|
168203
168890
|
};
|
|
168204
|
-
|
|
168891
|
+
escapeRegExp3 = /\\|'|\r|\n|\u2028|\u2029/g;
|
|
168205
168892
|
bareIdentifier = /^\s*(\w|\$)+\s*$/;
|
|
168206
168893
|
}
|
|
168207
168894
|
});
|
|
@@ -199949,7 +200636,6 @@ function containsBrowserDeliveryTask(tasks) {
|
|
|
199949
200636
|
var BROWSER_DELIVERY_ROLE_IDS;
|
|
199950
200637
|
var init_browserDeliveryLock = __esm({
|
|
199951
200638
|
"features/perchTerminal/agentPlatform/browserDeliveryLock.ts"() {
|
|
199952
|
-
"use strict";
|
|
199953
200639
|
BROWSER_DELIVERY_ROLE_IDS = /* @__PURE__ */ new Set([
|
|
199954
200640
|
"doc_writer",
|
|
199955
200641
|
"email_sender",
|
|
@@ -201862,7 +202548,7 @@ function lifecycleState(ctx) {
|
|
|
201862
202548
|
}
|
|
201863
202549
|
return state;
|
|
201864
202550
|
}
|
|
201865
|
-
function
|
|
202551
|
+
function normalizeText2(value) {
|
|
201866
202552
|
if (typeof value === "string") return value.toLowerCase().replace(/\s+/g, " ").trim();
|
|
201867
202553
|
if (value === null || value === void 0) return "";
|
|
201868
202554
|
try {
|
|
@@ -201873,7 +202559,7 @@ function normalizeText(value) {
|
|
|
201873
202559
|
}
|
|
201874
202560
|
function explicitRetryRequested(tasks) {
|
|
201875
202561
|
const text = tasks.map((task) => `${task.objective}
|
|
201876
|
-
${
|
|
202562
|
+
${normalizeText2(task.context)}`).join("\n");
|
|
201877
202563
|
return /\b(retry|re-run|rerun|run again|fresh pass|fresh read|repeat|redo)\b/i.test(text);
|
|
201878
202564
|
}
|
|
201879
202565
|
function isSourceReaderLifecycleRole(roleId) {
|
|
@@ -201884,7 +202570,7 @@ function isSourceReaderLifecycleRole(roleId) {
|
|
|
201884
202570
|
}
|
|
201885
202571
|
function extractSourceScopes(task) {
|
|
201886
202572
|
const text = `${task.objective}
|
|
201887
|
-
${
|
|
202573
|
+
${normalizeText2(task.context)}`;
|
|
201888
202574
|
const scopes = /* @__PURE__ */ new Set();
|
|
201889
202575
|
const pathPattern = /\b(?:\d{2}-[a-z0-9_-]+|[a-z0-9_-]+\/[a-z0-9_ .&/-]+)(?:\/[a-z0-9_ .&-]+)*/gi;
|
|
201890
202576
|
for (const match of text.matchAll(pathPattern)) {
|
|
@@ -201894,14 +202580,14 @@ ${normalizeText(task.context)}`;
|
|
|
201894
202580
|
}
|
|
201895
202581
|
if (raw.length >= 4) scopes.add(raw.toLowerCase());
|
|
201896
202582
|
}
|
|
201897
|
-
if (scopes.size === 0) scopes.add(
|
|
202583
|
+
if (scopes.size === 0) scopes.add(normalizeText2(task.objective).slice(0, 120));
|
|
201898
202584
|
return [...scopes].sort();
|
|
201899
202585
|
}
|
|
201900
202586
|
function taskSignature(task) {
|
|
201901
202587
|
return JSON.stringify({
|
|
201902
202588
|
roleId: task.roleId,
|
|
201903
|
-
objective:
|
|
201904
|
-
context:
|
|
202589
|
+
objective: normalizeText2(task.objective),
|
|
202590
|
+
context: normalizeText2(task.context)
|
|
201905
202591
|
});
|
|
201906
202592
|
}
|
|
201907
202593
|
function batchSignature(tasks) {
|
|
@@ -217660,7 +218346,7 @@ function isBrowserSnapshotToolResult(messages, index) {
|
|
|
217660
218346
|
const toolName = toolNameForMessage(messages, index);
|
|
217661
218347
|
const text = messageContentText(msg);
|
|
217662
218348
|
if (!text.includes("snapshot")) return false;
|
|
217663
|
-
if (toolName &&
|
|
218349
|
+
if (toolName && BROWSER_TOOL_NAMES2.has(toolName)) return true;
|
|
217664
218350
|
try {
|
|
217665
218351
|
const parsed = JSON.parse(text);
|
|
217666
218352
|
return typeof parsed.snapshot === "string" && parsed.snapshot.length > 200;
|
|
@@ -218135,7 +218821,7 @@ async function prepareLoopMessagesForSend(input) {
|
|
|
218135
218821
|
microcompactedToolResults
|
|
218136
218822
|
};
|
|
218137
218823
|
}
|
|
218138
|
-
var OPERATOR_SCREENSHOT_MARKER2, KEPT_SNAPSHOT_MAX_CHARS, KEPT_SNAPSHOT_TRUNCATED_MARKER,
|
|
218824
|
+
var OPERATOR_SCREENSHOT_MARKER2, KEPT_SNAPSHOT_MAX_CHARS, KEPT_SNAPSHOT_TRUNCATED_MARKER, BROWSER_TOOL_NAMES2, RECENT_MESSAGES_KEEP_COUNT, RECENT_TOOL_RESULTS_KEEP_COUNT, POST_COMPACT_TARGET_TOKENS, POST_COMPACT_MIN_TARGET_TOKENS, POST_COMPACT_MAX_TARGET_TOKENS, POST_COMPACT_RECENT_TAIL_MIN_TOKENS, POST_COMPACT_RECENT_TAIL_MAX_TOKENS, MICROCOMPACT_CLEARED_MARKER, COMPACT_SUMMARY_RESERVE_TOKENS, COMPACT_SYSTEM_PROMPT;
|
|
218139
218825
|
var init_contextLoopCompaction = __esm({
|
|
218140
218826
|
"features/perchTerminal/runtime/services/contextLoopCompaction.ts"() {
|
|
218141
218827
|
"use strict";
|
|
@@ -218150,7 +218836,7 @@ var init_contextLoopCompaction = __esm({
|
|
|
218150
218836
|
OPERATOR_SCREENSHOT_MARKER2 = "[operator-screen]";
|
|
218151
218837
|
KEPT_SNAPSHOT_MAX_CHARS = 12e3;
|
|
218152
218838
|
KEPT_SNAPSHOT_TRUNCATED_MARKER = "[snapshot truncated]";
|
|
218153
|
-
|
|
218839
|
+
BROWSER_TOOL_NAMES2 = /* @__PURE__ */ new Set([
|
|
218154
218840
|
TOOL_NAMES.browserNavigate,
|
|
218155
218841
|
TOOL_NAMES.browserObserve,
|
|
218156
218842
|
TOOL_NAMES.browserClick,
|
|
@@ -221650,7 +222336,7 @@ var init_preTurnRetrieval = __esm({
|
|
|
221650
222336
|
// features/perchTerminal/rag/chunking.ts
|
|
221651
222337
|
import { createHash as createHash2 } from "crypto";
|
|
221652
222338
|
function buildRetrievalChunks(text, metadata, options = {}) {
|
|
221653
|
-
const normalized =
|
|
222339
|
+
const normalized = normalizeText3(text);
|
|
221654
222340
|
if (!normalized) return [];
|
|
221655
222341
|
const targetChars = Math.max(400, (options.targetTokens ?? DEFAULT_TARGET_TOKENS) * APPROX_CHARS_PER_TOKEN);
|
|
221656
222342
|
const overlapChars = Math.max(0, Math.min(targetChars / 2, (options.overlapTokens ?? DEFAULT_OVERLAP_TOKENS) * APPROX_CHARS_PER_TOKEN));
|
|
@@ -221680,7 +222366,7 @@ function buildRetrievalChunks(text, metadata, options = {}) {
|
|
|
221680
222366
|
return chunk2;
|
|
221681
222367
|
});
|
|
221682
222368
|
}
|
|
221683
|
-
function
|
|
222369
|
+
function normalizeText3(text) {
|
|
221684
222370
|
return text.replace(/\r\n/g, "\n").replace(/[ \t]+/g, " ").replace(/\n[ \t]+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
221685
222371
|
}
|
|
221686
222372
|
function stableContentHash(value) {
|
|
@@ -224323,6 +225009,8 @@ function buildClientContextSnapshot(input) {
|
|
|
224323
225009
|
compacted: context.snapshot.compacted,
|
|
224324
225010
|
chatMode: input.input.chatMode,
|
|
224325
225011
|
selectedSourceId: input.input.selectedSourceId,
|
|
225012
|
+
selectedSkills: extractSelectedSkills(context),
|
|
225013
|
+
omittedSkills: extractOmittedSkills(context),
|
|
224326
225014
|
desktopConnected: input.input.desktopConnected,
|
|
224327
225015
|
cliLocalTools: input.input.cliLocalTools === true,
|
|
224328
225016
|
sectionBreakdown: context.snapshot.sectionBreakdown,
|
|
@@ -224361,6 +225049,23 @@ function buildClientContextSnapshot(input) {
|
|
|
224361
225049
|
} : {}
|
|
224362
225050
|
};
|
|
224363
225051
|
}
|
|
225052
|
+
function extractSelectedSkills(context) {
|
|
225053
|
+
const metadata = context.snapshot.rows.find(
|
|
225054
|
+
(row) => row.id === "selected-skills"
|
|
225055
|
+
)?.metadata;
|
|
225056
|
+
const ids = metadata?.selectedSkillIds;
|
|
225057
|
+
return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
|
|
225058
|
+
}
|
|
225059
|
+
function extractOmittedSkills(context) {
|
|
225060
|
+
const metadata = context.snapshot.rows.find(
|
|
225061
|
+
(row) => row.id === "selected-skills"
|
|
225062
|
+
)?.metadata;
|
|
225063
|
+
const omitted = metadata?.omitted;
|
|
225064
|
+
if (!Array.isArray(omitted)) return [];
|
|
225065
|
+
return omitted.filter(
|
|
225066
|
+
(item) => typeof item === "object" && item !== null && typeof item.id === "string" && typeof item.reason === "string"
|
|
225067
|
+
);
|
|
225068
|
+
}
|
|
224364
225069
|
var init_turnContextSnapshot = __esm({
|
|
224365
225070
|
"features/perchTerminal/runtime/turn/turnContextSnapshot.ts"() {
|
|
224366
225071
|
"use strict";
|
|
@@ -283119,6 +283824,10 @@ ${HELP_TEXT}`);
|
|
|
283119
283824
|
if (parsed.domain === "auth") {
|
|
283120
283825
|
return runAuthCommand(parsed, writer);
|
|
283121
283826
|
}
|
|
283827
|
+
if (parsed.domain === "skills") {
|
|
283828
|
+
writer.stdout(renderCliSkills(parsed.name));
|
|
283829
|
+
return 0;
|
|
283830
|
+
}
|
|
283122
283831
|
if (parsed.domain === "run") {
|
|
283123
283832
|
const connectModelProxy = deps.connectModelProxy ?? connectCliModelProxy;
|
|
283124
283833
|
const connection = await connectModelProxy({ appUrl: parsed.appUrl });
|
|
@@ -283225,6 +283934,7 @@ function parsePerchCli(argv) {
|
|
|
283225
283934
|
if (domain === "login") return { ok: true, domain: "auth", action: "login", ...global2.appUrl ? { appUrl: global2.appUrl } : {} };
|
|
283226
283935
|
if (domain === "logout") return { ok: true, domain: "auth", action: "logout" };
|
|
283227
283936
|
if (domain === "status") return { ok: true, domain: "auth", action: "status" };
|
|
283937
|
+
if (domain === "skills") return { ok: true, domain: "skills", ...action ? { name: action } : {} };
|
|
283228
283938
|
if (domain !== "ap" && domain !== "test") return { ok: false, error: `Unknown domain: ${domain ?? "(missing)"}` };
|
|
283229
283939
|
if (domain === "test") {
|
|
283230
283940
|
if (action !== "ap") return { ok: false, error: `Unknown test command: ${action ?? "(missing)"}` };
|
|
@@ -284259,6 +284969,9 @@ async function runInteractiveSlashCommand(input) {
|
|
|
284259
284969
|
));
|
|
284260
284970
|
return "continue";
|
|
284261
284971
|
}
|
|
284972
|
+
case "skills":
|
|
284973
|
+
input.writer.stdout(renderCliSkills(parsed.value));
|
|
284974
|
+
return "continue";
|
|
284262
284975
|
case "context":
|
|
284263
284976
|
input.writer.stdout(renderCliContextDetails(input.state.contextSnapshot));
|
|
284264
284977
|
return "continue";
|
|
@@ -284378,6 +285091,8 @@ function parseInteractiveSlashCommand(input) {
|
|
|
284378
285091
|
return { ok: true, kind: "help" };
|
|
284379
285092
|
case "status":
|
|
284380
285093
|
return { ok: true, kind: "status" };
|
|
285094
|
+
case "skills":
|
|
285095
|
+
return { ok: true, kind: "skills", ...value ? { value } : {} };
|
|
284381
285096
|
case "context":
|
|
284382
285097
|
return { ok: true, kind: "context" };
|
|
284383
285098
|
case "memory-audit":
|
|
@@ -284433,6 +285148,7 @@ function renderInteractiveStatus(state, connection, session, workspaceId) {
|
|
|
284433
285148
|
["connection", connectionStatus],
|
|
284434
285149
|
["memory", renderCliMemoryAvailability(state.cwd, workspaceId ?? null, signedIn)],
|
|
284435
285150
|
["tools", renderCliCapabilityCount(state, workspaceId ?? null)],
|
|
285151
|
+
["skills", renderCliLoadedSkills(state.contextSnapshot)],
|
|
284436
285152
|
["permission", state.permissionMode],
|
|
284437
285153
|
["mode", state.chatMode],
|
|
284438
285154
|
["persona", state.personaId],
|
|
@@ -284463,6 +285179,43 @@ function renderCliCapabilityCount(state, workspaceId) {
|
|
|
284463
285179
|
}).length;
|
|
284464
285180
|
return `${count} visible`;
|
|
284465
285181
|
}
|
|
285182
|
+
function renderCliLoadedSkills(snapshot) {
|
|
285183
|
+
const skills = snapshot?.selectedSkills ?? [];
|
|
285184
|
+
return skills.length > 0 ? skills.join(", ") : "none loaded";
|
|
285185
|
+
}
|
|
285186
|
+
function renderCliSkills(name) {
|
|
285187
|
+
const color = shouldUseCliColor();
|
|
285188
|
+
if (name) {
|
|
285189
|
+
const skill = getAgentSkillManifest(name);
|
|
285190
|
+
if (!skill) {
|
|
285191
|
+
return `Unknown skill: ${name}
|
|
285192
|
+
Run /skills to list available skills.
|
|
285193
|
+
`;
|
|
285194
|
+
}
|
|
285195
|
+
return [
|
|
285196
|
+
`${paint(skill.name, "accent", color)}`,
|
|
285197
|
+
skill.description,
|
|
285198
|
+
`surface: GUI=${skill.surface.gui}; CLI=${skill.surface.cli}`,
|
|
285199
|
+
skill.triggerHints.length ? `triggers: ${skill.triggerHints.join(", ")}` : "triggers: none",
|
|
285200
|
+
skill.companionSkills.length ? `companions: ${skill.companionSkills.join(", ")}` : "companions: none",
|
|
285201
|
+
"",
|
|
285202
|
+
skill.body.trim(),
|
|
285203
|
+
""
|
|
285204
|
+
].join("\n");
|
|
285205
|
+
}
|
|
285206
|
+
const rows = listAgentSkillMetadataRows();
|
|
285207
|
+
return [
|
|
285208
|
+
"Perch core skills",
|
|
285209
|
+
...rows.map(
|
|
285210
|
+
(skill) => [
|
|
285211
|
+
`- ${skill.id}`,
|
|
285212
|
+
` ${skill.description}`,
|
|
285213
|
+
` surface: GUI=${skill.surface.gui}; CLI=${skill.surface.cli}`
|
|
285214
|
+
].join("\n")
|
|
285215
|
+
),
|
|
285216
|
+
""
|
|
285217
|
+
].join("\n");
|
|
285218
|
+
}
|
|
284466
285219
|
function renderInteractiveStartup(state, connection) {
|
|
284467
285220
|
const color = shouldUseCliColor();
|
|
284468
285221
|
const auth = renderCliAuthSummary(connection);
|
|
@@ -285514,6 +286267,7 @@ var init_perch_cli = __esm({
|
|
|
285514
286267
|
init_learningMemory();
|
|
285515
286268
|
init_toolDefinitions();
|
|
285516
286269
|
init_nodeLocalBridge();
|
|
286270
|
+
init_agentSkillRegistry();
|
|
285517
286271
|
execFileAsync3 = promisify3(execFile3);
|
|
285518
286272
|
DEFAULT_CLI_LOGIN_APP_URL = "https://app.perchai.app";
|
|
285519
286273
|
CLI_PACKAGE_VERSION = readCliPackageVersion();
|
|
@@ -285547,6 +286301,7 @@ Usage:
|
|
|
285547
286301
|
perch login
|
|
285548
286302
|
perch status
|
|
285549
286303
|
perch logout
|
|
286304
|
+
perch skills [name]
|
|
285550
286305
|
perch run "<task>" [--json] [--thread <id>] [--cwd <dir>] [--mode ask|agents|plan] [--persona saffron|quill]
|
|
285551
286306
|
perch ap evidence <folder> [--json] [--out <dir>] [--timestamp <id>]
|
|
285552
286307
|
perch ap packet <folder> [--json] [--out <dir>] [--timestamp <id>]
|
|
@@ -285557,6 +286312,7 @@ Commands:
|
|
|
285557
286312
|
login Open browser sign-in and save this terminal's Perch session.
|
|
285558
286313
|
status Show the saved CLI auth/app connection status.
|
|
285559
286314
|
logout Clear the saved CLI auth session.
|
|
286315
|
+
skills List Perch core skills, or show one skill body.
|
|
285560
286316
|
run Run a natural-language Perch turn through the shared runtime.
|
|
285561
286317
|
ap evidence Prepare AP evidence, cases, metrics, and graph artifacts.
|
|
285562
286318
|
ap packet Generate the full AP audit packet and report artifacts.
|
|
@@ -285566,6 +286322,7 @@ Commands:
|
|
|
285566
286322
|
While Perch is working: type steering text and press Enter; Ctrl-C stops; Ctrl-E expands details.
|
|
285567
286323
|
/help Show this list.
|
|
285568
286324
|
/status Show cwd, auth, mode, persona, permission, and thread.
|
|
286325
|
+
/skills [name] List Perch core skills, or show one skill body.
|
|
285569
286326
|
/cwd [dir] Show or change the working directory.
|
|
285570
286327
|
/permission [mode] Show or set default, auto_review, take_the_wheel, or plan.
|
|
285571
286328
|
/permissions [mode] Alias for /permission.
|
|
@@ -285616,6 +286373,7 @@ Commands:
|
|
|
285616
286373
|
];
|
|
285617
286374
|
PERCH_SPLASH_COMMANDS = [
|
|
285618
286375
|
["/status", "show auth, route, tools, and thread"],
|
|
286376
|
+
["/skills", "show reusable operator skills"],
|
|
285619
286377
|
["/persona", "swap saffron or quill"],
|
|
285620
286378
|
["/permission", "change autonomy for the next turns"],
|
|
285621
286379
|
["/login", "connect your Perch account"]
|