perchai-cli 2.4.14 → 2.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/perch.mjs +51 -20
  2. package/package.json +4 -2
package/dist/perch.mjs CHANGED
@@ -75566,7 +75566,6 @@ 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";
75570
75569
  init_generateAPAuditPacket();
75571
75570
  init_inventoryFolder();
75572
75571
  init_loadBusinessTables();
@@ -213392,11 +213391,14 @@ var init_config2 = __esm({
213392
213391
 
213393
213392
  // features/perchTerminal/knowledge/knowledgeApiClient.ts
213394
213393
  async function searchKnowledgeViaApi(input, options = {}) {
213395
- const route = options.route ?? "/api/perch-terminal/knowledge/search";
213394
+ const route = resolveKnowledgeRoute(options.route ?? "/api/perch-terminal/knowledge/search");
213396
213395
  const fetchImpl = options.fetchImpl ?? fetch;
213396
+ const headers = { "content-type": "application/json" };
213397
+ const token = process.env.PERCH_MODEL_CALL_PROXY_TOKEN?.trim();
213398
+ if (token) headers.authorization = `Bearer ${token}`;
213397
213399
  const response = await fetchImpl(route, {
213398
213400
  method: "POST",
213399
- headers: { "content-type": "application/json" },
213401
+ headers,
213400
213402
  body: JSON.stringify(input)
213401
213403
  });
213402
213404
  const payload = await response.json().catch(() => ({}));
@@ -213408,6 +213410,13 @@ async function searchKnowledgeViaApi(input, options = {}) {
213408
213410
  }
213409
213411
  return payload;
213410
213412
  }
213413
+ function resolveKnowledgeRoute(route) {
213414
+ if (!route.startsWith("/")) return route;
213415
+ if (typeof window !== "undefined") return route;
213416
+ const appUrl = process.env.PERCH_MODEL_CALL_PROXY_URL?.trim() || process.env.PERCH_CLI_APP_URL?.trim() || process.env.PERCH_APP_URL?.trim();
213417
+ if (!appUrl) return route;
213418
+ return new URL(route, appUrl).toString();
213419
+ }
213411
213420
  var KnowledgeApiClientError;
213412
213421
  var init_knowledgeApiClient = __esm({
213413
213422
  "features/perchTerminal/knowledge/knowledgeApiClient.ts"() {
@@ -214630,13 +214639,22 @@ async function computeLiveSignals(store, strategyId, asOf) {
214630
214639
  }
214631
214640
  return out;
214632
214641
  }
214642
+ function ledgerFields(result2) {
214643
+ return result2.error ? { ledgerRecorded: result2.recorded, ledgerError: result2.error } : { ledgerRecorded: result2.recorded };
214644
+ }
214633
214645
  async function recordLedger(ctx, row) {
214634
- if (!ctx.supabase) return false;
214646
+ if (!ctx.supabase) {
214647
+ return { recorded: false, error: "supabase_unavailable" };
214648
+ }
214635
214649
  try {
214636
214650
  const { error } = await ctx.supabase.from("perch_ai_market_backtest_runs").insert(row);
214637
- return !error;
214638
- } catch {
214639
- return false;
214651
+ if (error) return { recorded: false, error: error.message };
214652
+ return { recorded: true };
214653
+ } catch (error) {
214654
+ return {
214655
+ recorded: false,
214656
+ error: error instanceof Error ? error.message : String(error)
214657
+ };
214640
214658
  }
214641
214659
  }
214642
214660
  var NOT_ADVICE, getMarketSignalTool, queryMarketSignalLogTool, explainMarketSignalTool, listMarketStrategiesTool, MAX_PERIOD_DAYS, ISO_DATE, runMarketBacktestTool, getMarketTrackRecordTool, marketDeskTools;
@@ -214900,7 +214918,8 @@ var init_marketDesk = __esm({
214900
214918
  holdout_acknowledged: acknowledgeHoldout,
214901
214919
  initiator: "tool",
214902
214920
  workspace_id: ctx.workspaceId ?? null,
214903
- thread_id: ctx.threadId ?? null
214921
+ thread_id: ctx.threadId ?? null,
214922
+ user_id: ctx.userId ?? null
214904
214923
  };
214905
214924
  const wf = args.walkForward && typeof args.walkForward === "object" ? args.walkForward : void 0;
214906
214925
  try {
@@ -214923,10 +214942,10 @@ var init_marketDesk = __esm({
214923
214942
  paramGrid
214924
214943
  });
214925
214944
  if (!result3.ok) {
214926
- await recordLedger(ctx, { ...ledgerBase, status: "failed", error: result3.error, holdout_overlap: false });
214927
- return { ok: false, errorCode: "walk_forward_failed", message: result3.error };
214945
+ const ledger3 = await recordLedger(ctx, { ...ledgerBase, status: "failed", error: result3.error, holdout_overlap: false });
214946
+ return { ok: false, errorCode: "walk_forward_failed", message: result3.error, ...ledgerFields(ledger3) };
214928
214947
  }
214929
- const ledgerRecorded2 = await recordLedger(ctx, {
214948
+ const ledger2 = await recordLedger(ctx, {
214930
214949
  ...ledgerBase,
214931
214950
  status: "completed",
214932
214951
  holdout_overlap: to >= resolveHoldoutStart(),
@@ -214951,17 +214970,17 @@ var init_marketDesk = __esm({
214951
214970
  testMaxDrawdown: round(f.testMetrics.maxDrawdown)
214952
214971
  })),
214953
214972
  oosMetrics: compactMetrics(result3.oosMetrics),
214954
- ledgerRecorded: ledgerRecorded2,
214973
+ ...ledgerFields(ledger2),
214955
214974
  note: "Out-of-sample (oosMetrics) is the only number that counts; train-window performance is selection, not evidence.",
214956
214975
  disclaimer: NOT_ADVICE
214957
214976
  };
214958
214977
  }
214959
214978
  const result2 = await runBacktest(store, backtestCfg);
214960
214979
  if (!result2.ok) {
214961
- await recordLedger(ctx, { ...ledgerBase, status: "failed", error: result2.error, holdout_overlap: false });
214962
- return { ok: false, errorCode: "backtest_failed", message: result2.error };
214980
+ const ledger2 = await recordLedger(ctx, { ...ledgerBase, status: "failed", error: result2.error, holdout_overlap: false });
214981
+ return { ok: false, errorCode: "backtest_failed", message: result2.error, ...ledgerFields(ledger2) };
214963
214982
  }
214964
- const ledgerRecorded = await recordLedger(ctx, {
214983
+ const ledger = await recordLedger(ctx, {
214965
214984
  ...ledgerBase,
214966
214985
  status: "completed",
214967
214986
  holdout_overlap: result2.holdout.overlapped,
@@ -214990,13 +215009,13 @@ var init_marketDesk = __esm({
214990
215009
  signalCounts: result2.signalCounts,
214991
215010
  equityCurve: downsample(result2.equityCurve, 60).map((p) => ({ date: p.date, equity: round(p.equity, 4) })),
214992
215011
  trades: { closed: result2.trades.filter((t) => t.netReturn !== null).length, open: result2.trades.filter((t) => t.exitDate === null && t.netReturn === null).length },
214993
- ledgerRecorded,
215012
+ ...ledgerFields(ledger),
214994
215013
  note: "Hypothetical backtest with modeled fees/slippage; past simulated performance does not predict future results. Every run (including this one) is recorded in the experiment ledger.",
214995
215014
  disclaimer: NOT_ADVICE
214996
215015
  };
214997
215016
  } catch (error) {
214998
215017
  if (error instanceof HoldoutViolationError) {
214999
- await recordLedger(ctx, {
215018
+ const ledger2 = await recordLedger(ctx, {
215000
215019
  ...ledgerBase,
215001
215020
  status: "failed",
215002
215021
  error: "holdout_violation",
@@ -215007,12 +215026,13 @@ var init_marketDesk = __esm({
215007
215026
  errorCode: "holdout_violation",
215008
215027
  message: error.message,
215009
215028
  holdoutStart: error.holdoutStart,
215010
- hint: "The holdout window is reserved for final evaluation. Re-run with acknowledgeHoldout: true ONLY if the user explicitly wants to spend a holdout look; the run gets flagged in the ledger either way."
215029
+ hint: "The holdout window is reserved for final evaluation. Re-run with acknowledgeHoldout: true ONLY if the user explicitly wants to spend a holdout look; the run gets flagged in the ledger either way.",
215030
+ ...ledgerFields(ledger2)
215011
215031
  };
215012
215032
  }
215013
215033
  const message = error instanceof Error ? error.message : String(error);
215014
- await recordLedger(ctx, { ...ledgerBase, status: "failed", error: message, holdout_overlap: false });
215015
- return { ok: false, errorCode: "backtest_error", message };
215034
+ const ledger = await recordLedger(ctx, { ...ledgerBase, status: "failed", error: message, holdout_overlap: false });
215035
+ return { ok: false, errorCode: "backtest_error", message, ...ledgerFields(ledger) };
215016
215036
  }
215017
215037
  }
215018
215038
  };
@@ -215190,11 +215210,22 @@ var init_registry5 = __esm({
215190
215210
  async function executeRegisteredTool(name, args, ctx) {
215191
215211
  const mod = getRegisteredTool(name);
215192
215212
  if (!mod) return { handled: false };
215213
+ if (MARKET_DESK_TOOL_NAMES.has(name) && !isMarketDeskEnabled()) {
215214
+ return {
215215
+ handled: true,
215216
+ result: {
215217
+ ok: false,
215218
+ errorCode: "market_desk_disabled",
215219
+ message: "Market Desk tools are disabled. Set PERCH_MARKET_DESK=1 to enable them."
215220
+ }
215221
+ };
215222
+ }
215193
215223
  return { handled: true, result: await mod.handler(args, ctx) };
215194
215224
  }
215195
215225
  var init_executeTool = __esm({
215196
215226
  "features/perchTerminal/runtime/toolSystem/executeTool.ts"() {
215197
215227
  "use strict";
215228
+ init_marketDeskAccess();
215198
215229
  init_registry5();
215199
215230
  }
215200
215231
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.14",
3
+ "version": "2.4.15",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"
@@ -12,7 +12,9 @@
12
12
  "LICENSE"
13
13
  ],
14
14
  "dependencies": {
15
- "@napi-rs/canvas": "^0.1.100"
15
+ "@mozilla/readability": "^0.6.0",
16
+ "@napi-rs/canvas": "^0.1.100",
17
+ "jsdom": "^29.1.1"
16
18
  },
17
19
  "engines": {
18
20
  "node": ">=20"