@papi-ai/server 0.7.42 → 0.7.44

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.
@@ -73,7 +73,7 @@ __export(git_exports, {
73
73
  taskBranchName: () => taskBranchName,
74
74
  withBaseBranchSync: () => withBaseBranchSync
75
75
  });
76
- import { execFileSync } from "child_process";
76
+ import { execFileSync, spawnSync } from "child_process";
77
77
  function isGitAvailable() {
78
78
  try {
79
79
  execFileSync("git", ["--version"], { stdio: "ignore" });
@@ -317,21 +317,24 @@ function gitPull(cwd) {
317
317
  }
318
318
  }
319
319
  function gitPush(cwd, branch) {
320
- try {
321
- execFileSync("git", ["push", "-u", "origin", branch], {
322
- cwd,
323
- encoding: "utf-8",
324
- timeout: GIT_NETWORK_TIMEOUT_MS
325
- });
326
- return { success: true, message: `Pushed branch '${branch}' to origin.` };
327
- } catch (err) {
328
- const msg = err instanceof Error ? err.message : String(err);
329
- const isTimeout = msg.includes("ETIMEDOUT") || msg.includes("killed");
330
- return {
331
- success: false,
332
- message: isTimeout ? `Push timed out after 30s.` : `Push failed: ${msg}`
333
- };
320
+ const result = spawnSync("git", ["push", "-u", "origin", branch], {
321
+ cwd,
322
+ encoding: "utf-8",
323
+ timeout: GIT_NETWORK_TIMEOUT_MS
324
+ });
325
+ if (result.error) {
326
+ const msg = result.error.message;
327
+ const isTimeout = msg.includes("ETIMEDOUT") || result.signal === "SIGTERM" || msg.includes("killed");
328
+ return { success: false, pushed: false, message: isTimeout ? "Push timed out after 30s." : `Push failed: ${msg}` };
329
+ }
330
+ const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
331
+ if (result.status !== 0) {
332
+ return { success: false, pushed: false, message: `Push failed: ${output || `git exited ${result.status}`}` };
333
+ }
334
+ if (/Everything up-to-date/i.test(output)) {
335
+ return { success: true, pushed: false, message: `'${branch}' already up to date on origin \u2014 nothing to push.` };
334
336
  }
337
+ return { success: true, pushed: true, message: `Pushed '${branch}' to origin.` };
335
338
  }
336
339
  function isGhAvailable() {
337
340
  try {
@@ -1057,7 +1060,9 @@ var init_telemetry = __esm({
1057
1060
  // src/proxy-adapter.ts
1058
1061
  var proxy_adapter_exports = {};
1059
1062
  __export(proxy_adapter_exports, {
1060
- ProxyPapiAdapter: () => ProxyPapiAdapter
1063
+ ProxyPapiAdapter: () => ProxyPapiAdapter,
1064
+ createProxyAdapter: () => createProxyAdapter,
1065
+ wrapWithForwarding: () => wrapWithForwarding
1061
1066
  });
1062
1067
  function snakeToCamel(str) {
1063
1068
  return str.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
@@ -1096,7 +1101,22 @@ function fixDisplayIdEntities(data) {
1096
1101
  if (data && typeof data === "object") return fixDisplayIdEntity(data);
1097
1102
  return data;
1098
1103
  }
1099
- var JSONB_PASSTHROUGH_KEYS, DISPLAY_ID_METHODS, ProxyPapiAdapter;
1104
+ function wrapWithForwarding(instance) {
1105
+ return new Proxy(instance, {
1106
+ get(target, prop, receiver) {
1107
+ const existing = Reflect.get(target, prop, receiver);
1108
+ if (existing !== void 0) return existing;
1109
+ if (typeof prop !== "string" || prop === "then" || prop.startsWith("_") || NO_FORWARD.has(prop)) {
1110
+ return existing;
1111
+ }
1112
+ return (...args) => target.forward(prop, args);
1113
+ }
1114
+ });
1115
+ }
1116
+ function createProxyAdapter(config) {
1117
+ return wrapWithForwarding(new ProxyPapiAdapter(config));
1118
+ }
1119
+ var JSONB_PASSTHROUGH_KEYS, DISPLAY_ID_METHODS, NO_FORWARD, ProxyPapiAdapter;
1100
1120
  var init_proxy_adapter = __esm({
1101
1121
  "src/proxy-adapter.ts"() {
1102
1122
  "use strict";
@@ -1120,6 +1140,30 @@ var init_proxy_adapter = __esm({
1120
1140
  "getRecentReviews",
1121
1141
  "getActiveDecisions"
1122
1142
  ]);
1143
+ NO_FORWARD = /* @__PURE__ */ new Set([
1144
+ // (1) local-only
1145
+ "close",
1146
+ "initRls",
1147
+ // (2) not-yet-wired hosted gaps — shrink as data-proxy handlers land (task-2390).
1148
+ // getToolCallCount + updatePhaseStatus are ABSENT: they now have edge handlers and
1149
+ // are served through the forwarder (getToolCallCount = SUP-2026-026 handler #1).
1150
+ "createOwnerAction",
1151
+ "findPendingDocActionsForTask",
1152
+ "getContributorRole",
1153
+ "getDecisionScorePatterns",
1154
+ "getModuleEstimationStats",
1155
+ "correctLatestBuildReportEffort",
1156
+ "recordContributorReleasePr",
1157
+ "setContributorReleasePrStatus",
1158
+ "listContributorReleasePrs",
1159
+ "resolveLearningsForDoneTasks",
1160
+ "markCycleLearningResolved",
1161
+ "updateStageExitCriteria",
1162
+ "updateDocAction",
1163
+ "claimReview",
1164
+ "getSiblingAds",
1165
+ "getSiblingRepoTasks"
1166
+ ]);
1123
1167
  ProxyPapiAdapter = class _ProxyPapiAdapter {
1124
1168
  endpoint;
1125
1169
  apiKey;
@@ -1141,11 +1185,11 @@ var init_proxy_adapter = __esm({
1141
1185
  * data-proxy's validateProjectAccess re-checks server-side regardless.
1142
1186
  */
1143
1187
  withProject(projectId) {
1144
- return new _ProxyPapiAdapter({
1188
+ return wrapWithForwarding(new _ProxyPapiAdapter({
1145
1189
  endpoint: this.endpoint,
1146
1190
  apiKey: this.apiKey,
1147
1191
  projectId
1148
- });
1192
+ }));
1149
1193
  }
1150
1194
  /**
1151
1195
  * Ensure the authenticated user has a project. If none exists, auto-creates one.
@@ -1257,6 +1301,17 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
1257
1301
  }
1258
1302
  return result;
1259
1303
  }
1304
+ /**
1305
+ * Generic forward for the allowlist-driven proxy trap (SUP-2026-026). Any
1306
+ * PapiAdapter method with no explicit wrapper here — and not in NO_FORWARD — is
1307
+ * served through this single path, so a NEW adapter method needs only a data-proxy
1308
+ * case handler, never a hand-written wrapper. Routes through invoke() so the
1309
+ * transformKeys / DISPLAY_ID fixups apply identically to wrapped methods. This is
1310
+ * the structural cure for the pg→proxy drift that caused SUP-2026-026.
1311
+ */
1312
+ forward(method, args) {
1313
+ return this.invoke(method, args);
1314
+ }
1260
1315
  /** Check if the proxy is reachable. */
1261
1316
  async probeConnection() {
1262
1317
  try {
@@ -1573,6 +1628,19 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
1573
1628
  getStrategyReviews(limit, includeFullAnalysis) {
1574
1629
  return this.invoke("getStrategyReviews", [limit, includeFullAnalysis]);
1575
1630
  }
1631
+ // --- Strategy Review Agenda (SUP-2026-026 — hosted parity) ---
1632
+ // Present on the pg/md adapters since C302 but never forwarded here, so
1633
+ // `strategy_agenda` failed for every hosted user. The proxy-parity guard missed
1634
+ // it because it only checked forwarded⊆allowed, never pg⊆forwarded (now fixed).
1635
+ addAgendaTopic(input) {
1636
+ return this.invoke("addAgendaTopic", [input]);
1637
+ }
1638
+ getPendingAgendaTopics() {
1639
+ return this.invoke("getPendingAgendaTopics");
1640
+ }
1641
+ markAgendaTopicsAddressed(ids, cycleNumber) {
1642
+ return this.invoke("markAgendaTopicsAddressed", [ids, cycleNumber]);
1643
+ }
1576
1644
  // --- Dogfood ---
1577
1645
  writeDogfoodEntries(entries) {
1578
1646
  return this.invoke("writeDogfoodEntries", [entries]);
@@ -1811,12 +1879,12 @@ import { pathToFileURL } from "url";
1811
1879
  import path2 from "path";
1812
1880
  import { execSync } from "child_process";
1813
1881
 
1814
- // ../adapter-md/dist/index.js
1882
+ // ../../../../../packages/adapter-md/dist/index.js
1815
1883
  import { readFile, writeFile, access } from "fs/promises";
1816
1884
  import { randomUUID as randomUUID6 } from "crypto";
1817
1885
  import { join } from "path";
1818
1886
 
1819
- // ../shared/dist/index.js
1887
+ // ../../../../../packages/shared/dist/index.js
1820
1888
  var VALID_TRANSITIONS = {
1821
1889
  "Backlog": ["In Cycle", "Ready", "In Progress", "Blocked", "Cancelled", "Deferred", "Done"],
1822
1890
  "In Cycle": ["In Progress", "Backlog", "Blocked", "Cancelled"],
@@ -1835,7 +1903,7 @@ function isLiveDecision(d) {
1835
1903
  return true;
1836
1904
  }
1837
1905
 
1838
- // ../adapter-md/dist/index.js
1906
+ // ../../../../../packages/adapter-md/dist/index.js
1839
1907
  import { randomUUID } from "crypto";
1840
1908
  import { randomUUID as randomUUID3 } from "crypto";
1841
1909
  import yaml from "js-yaml";
@@ -4330,7 +4398,7 @@ async function createAdapter(optionsOrType, maybePapiDir) {
4330
4398
  return adapter;
4331
4399
  }
4332
4400
  case "proxy": {
4333
- const { ProxyPapiAdapter: ProxyPapiAdapter2 } = await Promise.resolve().then(() => (init_proxy_adapter(), proxy_adapter_exports));
4401
+ const { ProxyPapiAdapter: ProxyPapiAdapter2, wrapWithForwarding: wrapWithForwarding2 } = await Promise.resolve().then(() => (init_proxy_adapter(), proxy_adapter_exports));
4334
4402
  const dashboardUrl = process.env["PAPI_DASHBOARD_URL"] || "https://getpapi.ai";
4335
4403
  const projectId = process.env["PAPI_PROJECT_ID"];
4336
4404
  const dataApiKey = process.env["PAPI_DATA_API_KEY"];
@@ -4433,7 +4501,7 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
4433
4501
  console.error("[papi] Set PAPI_PROJECT_ID in .mcp.json to connect to an existing project.");
4434
4502
  }
4435
4503
  }
4436
- return adapter;
4504
+ return wrapWithForwarding2(adapter);
4437
4505
  }
4438
4506
  default: {
4439
4507
  const _exhaustive = adapterType;