@sage-protocol/pi-adapter 0.5.3 → 0.5.5

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/README.md CHANGED
@@ -109,7 +109,7 @@ interface SageP2Config {
109
109
  enableRlmFeedback?: boolean;
110
110
  enableSecurityHooks?: boolean;
111
111
  securityFailurePolicy?: "warn" | "block"; // default: "warn"; what to do when a scan cannot decide
112
- source?: string; // default: "pi"
112
+ source?: string; // default: "pi"; capture/feedback attribution, not the scan protocol
113
113
  // Inherited mode: both exact Glove values are required, with no legacy fields.
114
114
  gloveLocalServiceFdsV1?: string; // exact JSON alias-to-FD map
115
115
  gloveGuestChannelServiceAlias?: string; // exact wallet service alias
@@ -128,6 +128,22 @@ interface SageP2Config {
128
128
  }
129
129
  ```
130
130
 
131
+ ## Security hook contract
132
+
133
+ Pre/post-tool scans run `sage security scan-hook` and honour only the structured
134
+ `decision` field (`allow` / `warn` / `block`; `deny` maps to `block`).
135
+
136
+ - An explicit `block` survives a non-zero exit, a timeout, or a stdin delivery
137
+ failure, because the decision is read from whatever the child already wrote.
138
+ - A scan that cannot decide never becomes an explicit `allow`. It follows
139
+ `securityFailurePolicy`: `warn` continues with a warning notice, `block`
140
+ refuses the call. Choose `block` for fail-closed operation.
141
+ - Incomplete stdin delivery counts as a failed run even when the child exits 0.
142
+ - Payloads that cannot be serialized (BigInt, cycles, throwing getters or
143
+ `toJSON`) follow the same failure policy. The thrown value is never inspected
144
+ or echoed.
145
+ - Scans always request the Pi wire protocol; `source` stays capture attribution.
146
+
131
147
  ## Migrating to 0.4
132
148
 
133
149
  Version 0.4 moves Pi skill discovery and loading to Pi's native skill surface.
package/USAGE.md CHANGED
@@ -154,7 +154,7 @@ registration API. Do not put definitions in a `tools` option.
154
154
  | `SAGE_BIN` | `sage` | Path to Sage CLI |
155
155
  | `SAGE_PROFILE` | — | Sage config profile (for example `testnet`) |
156
156
  | `SAGE_SECURITY_HOOKS` | `1` | Enable pre/post-tool security scanning |
157
- | `SAGE_SECURITY_FAILURE_POLICY` | `warn` | When a scan cannot decide (timeout, non-zero exit, error decision, unparseable output): `warn` allows the call with a visible warning, `block` refuses it. Never a silent allow. A post-tool `block` withholds the tool output. |
157
+ | `SAGE_SECURITY_FAILURE_POLICY` | `warn` | When a scan cannot decide (timeout, non-zero exit, error decision, unparseable or empty output; only an explicit `{"decision":"allow"}` counts as scanned and allowed): `warn` allows the call with a visible warning, `block` refuses it. Never a silent allow. A post-tool `block` withholds the tool output. |
158
158
  | `SAGE_RLM_FEEDBACK` | `1` | Enable prompt/response capture and native-use receipts |
159
159
  | `SAGE_SHOW_HOOK_MESSAGES` | `0` | Display SessionStart hook messages in the chat UI |
160
160
  | `SAGE_ALLOW_BASH_CLI` | `1` | Allow direct `sage ...` bash calls |
@@ -24,6 +24,7 @@ export declare function formatInboxList(source: unknown, options: InboxListView)
24
24
  truncated: boolean;
25
25
  labelsTruncated: boolean;
26
26
  sourceIncomplete: boolean;
27
+ skippedCount: number;
27
28
  pagination: string;
28
29
  };
29
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"inbox-output.d.ts","sourceRoot":"","sources":["../src/inbox-output.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,QAAW,CAAC;AAC3C,eAAO,MAAM,mBAAmB,2JAA2J,CAAC;AAE5L,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAY5E;AAsBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa;cAcrD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;;;;;;;;;;;;;;;;EA4C1C"}
1
+ {"version":3,"file":"inbox-output.d.ts","sourceRoot":"","sources":["../src/inbox-output.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,QAAW,CAAC;AAC3C,eAAO,MAAM,mBAAmB,2JAA2J,CAAC;AAE5L,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAY5E;AAyBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa;cAuBrD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;;;;;;;;;;;;;;;;;EA8C1C"}
package/dist/index.js CHANGED
@@ -133,23 +133,32 @@ function label(value, maxBytes) {
133
133
  }
134
134
  return { text, changed };
135
135
  }
136
+ var SESSION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
137
+ var PAGE_CAP = 200;
136
138
  function formatInboxList(source, options) {
137
139
  if (!source || typeof source !== "object") throw new Error("Invalid inbox discovery page");
138
140
  const raw = source;
139
- if (!Array.isArray(raw.sessions) || raw.sessions.length > 200) throw new Error("Invalid inbox discovery page");
141
+ if (!Array.isArray(raw.sessions)) throw new Error("Invalid inbox discovery page");
142
+ const overPageCap = raw.sessions.length > PAGE_CAP;
140
143
  const seen = /* @__PURE__ */ new Set();
141
- const peers = raw.sessions.map((value) => {
142
- if (!value || typeof value !== "object") throw new Error("Invalid inbox peer");
143
- const peer = value;
144
- if (typeof peer.sessionId !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(peer.sessionId) || typeof peer.live !== "boolean" || typeof peer.busy !== "boolean" || seen.has(peer.sessionId)) throw new Error("Invalid or duplicate inbox peer identity");
145
- seen.add(peer.sessionId);
146
- return peer;
147
- });
144
+ const peers = [];
145
+ let skippedCount = 0;
146
+ for (const value of overPageCap ? raw.sessions.slice(0, PAGE_CAP) : raw.sessions) {
147
+ const peer = value && typeof value === "object" ? value : void 0;
148
+ const id = typeof peer?.sessionId === "string" ? peer.sessionId.trim().toLowerCase() : "";
149
+ if (!peer || !SESSION_ID.test(id) || typeof peer.live !== "boolean" || typeof peer.busy !== "boolean" || seen.has(id)) {
150
+ skippedCount++;
151
+ continue;
152
+ }
153
+ seen.add(id);
154
+ peers.push({ ...peer, sessionId: id });
155
+ }
156
+ const brokerHasMore = raw.hasMore === true;
148
157
  const matches = peers.filter((peer) => (options.includeOffline || peer.live) && (options.project === void 0 || peer.project === options.project) && (options.harness === void 0 || peer.harness === options.harness));
149
158
  const result = {
150
159
  sessions: [],
151
160
  // hasMore retains its broker meaning; local omissions are reported below.
152
- hasMore: raw.hasMore !== false,
161
+ hasMore: brokerHasMore,
153
162
  labelsProvenance: INBOX_LABELS_NOTICE,
154
163
  view: {
155
164
  scope: "received-broker-page",
@@ -161,7 +170,9 @@ function formatInboxList(source, options) {
161
170
  omittedCount: matches.length,
162
171
  truncated: matches.length > 0,
163
172
  labelsTruncated: false,
164
- sourceIncomplete: raw.hasMore !== false,
173
+ // Incomplete when the broker has more, or when this adapter cut or skipped rows.
174
+ sourceIncomplete: brokerHasMore || overPageCap || skippedCount > 0,
175
+ skippedCount,
165
176
  pagination: "unsupported"
166
177
  }
167
178
  };
@@ -3771,6 +3782,12 @@ function formatSageCommand(command, args) {
3771
3782
  });
3772
3783
  return quoted.join(" ");
3773
3784
  }
3785
+ var SAGE_SCAN_PROTOCOL_SOURCE = "pi";
3786
+ function securityWarnNotice(decision) {
3787
+ const reason = decision.reason?.trim();
3788
+ if (decision.scanUnavailable) return `Sage ${reason || "security scan unavailable"}`;
3789
+ return reason || "Sage security warning: treat this input with caution.";
3790
+ }
3774
3791
  function securityBlockMessage(toolName, reason, fallback) {
3775
3792
  const text = reason?.trim();
3776
3793
  if (text && /^Sage security blocked\b/i.test(text)) return text;
@@ -4110,6 +4127,13 @@ function normalizeAction(aliasesByDomain, domain, action) {
4110
4127
  if (!domainAliases) return normalizedAction;
4111
4128
  return domainAliases[normalizedAction] ?? normalizedAction;
4112
4129
  }
4130
+ var SCAN_FAILURE_DETAIL_MAX_CHARS = 200;
4131
+ function boundScanFailureDetail(stderr) {
4132
+ const flat = stderr.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2066-\u2069\ufeff]/g, " ").replace(/\s+/g, " ").trim();
4133
+ if (!flat) return "unknown error";
4134
+ if (flat.length <= SCAN_FAILURE_DETAIL_MAX_CHARS) return flat;
4135
+ return `\u2026${flat.slice(-SCAN_FAILURE_DETAIL_MAX_CHARS)}`;
4136
+ }
4113
4137
  async function defaultSageCommandRunner(request) {
4114
4138
  return new Promise((resolve2, reject) => {
4115
4139
  const proc = spawn(request.command, request.args, {
@@ -4122,34 +4146,51 @@ async function defaultSageCommandRunner(request) {
4122
4146
  let timedOut = false;
4123
4147
  let settled = false;
4124
4148
  let killEscalation = null;
4149
+ let killSettlement = null;
4150
+ let stdinFailure = null;
4151
+ const describeStderr = () => stdinFailure ? `${stderr}${stderr ? "\n" : ""}${stdinFailure.message}` : stderr;
4125
4152
  const timeout = setTimeout(() => {
4126
4153
  timedOut = true;
4127
4154
  proc.kill("SIGTERM");
4128
4155
  killEscalation = setTimeout(() => {
4129
4156
  if (settled) return;
4157
+ killSettlement = setTimeout(() => {
4158
+ finish({
4159
+ exitCode: -1,
4160
+ stdout,
4161
+ stderr: describeStderr(),
4162
+ timedOut,
4163
+ stdinFailed: stdinFailure !== null
4164
+ });
4165
+ }, SAGE_COMMAND_TIMEOUT_KILL_GRACE_MS);
4130
4166
  proc.kill("SIGKILL");
4131
4167
  }, SAGE_COMMAND_TIMEOUT_KILL_GRACE_MS);
4132
4168
  }, request.timeoutMs);
4169
+ const clearTimers = () => {
4170
+ clearTimeout(timeout);
4171
+ if (killEscalation) clearTimeout(killEscalation);
4172
+ if (killSettlement) clearTimeout(killSettlement);
4173
+ };
4133
4174
  const finish = (result) => {
4134
4175
  if (settled) return;
4135
4176
  settled = true;
4136
- clearTimeout(timeout);
4137
- if (killEscalation) clearTimeout(killEscalation);
4177
+ clearTimers();
4138
4178
  resolve2(result);
4139
4179
  };
4140
4180
  const fail = (err) => {
4141
4181
  if (settled) return;
4142
4182
  settled = true;
4143
- clearTimeout(timeout);
4144
- if (killEscalation) clearTimeout(killEscalation);
4183
+ clearTimers();
4145
4184
  reject(err);
4146
4185
  };
4186
+ const noteStdinFailure = (err) => {
4187
+ if (stdinFailure) return;
4188
+ stdinFailure = err instanceof Error ? err : new Error(String(err));
4189
+ };
4147
4190
  proc.on("error", (err) => {
4148
4191
  fail(err);
4149
4192
  });
4150
- proc.stdin.on("error", (err) => {
4151
- fail(err instanceof Error ? err : new Error(String(err)));
4152
- });
4193
+ proc.stdin.on("error", noteStdinFailure);
4153
4194
  proc.stdout.setEncoding("utf8");
4154
4195
  proc.stderr.setEncoding("utf8");
4155
4196
  proc.stdout.on("data", (chunk) => {
@@ -4160,10 +4201,13 @@ async function defaultSageCommandRunner(request) {
4160
4201
  });
4161
4202
  proc.on("close", (code) => {
4162
4203
  finish({
4163
- exitCode: code ?? -1,
4204
+ // Incomplete stdin delivery is a failed run even if the child exited 0:
4205
+ // it may have skipped or truncated work because input never arrived.
4206
+ exitCode: stdinFailure ? -1 : code ?? -1,
4164
4207
  stdout,
4165
- stderr,
4166
- timedOut
4208
+ stderr: describeStderr(),
4209
+ timedOut,
4210
+ stdinFailed: stdinFailure !== null
4167
4211
  });
4168
4212
  });
4169
4213
  if (!request.stdin) {
@@ -4176,7 +4220,7 @@ async function defaultSageCommandRunner(request) {
4176
4220
  }
4177
4221
  proc.stdin.end(request.stdin, (err) => {
4178
4222
  if (!err) return;
4179
- fail(err instanceof Error ? err : new Error(String(err)));
4223
+ noteStdinFailure(err);
4180
4224
  });
4181
4225
  });
4182
4226
  }
@@ -4827,6 +4871,13 @@ function parseSecurityDecision(stdout) {
4827
4871
  }
4828
4872
  return null;
4829
4873
  }
4874
+ function serializeScanPayload(payload) {
4875
+ try {
4876
+ return { json: JSON.stringify(payload) };
4877
+ } catch {
4878
+ return { serializationFailed: true };
4879
+ }
4880
+ }
4830
4881
  var SageMcpBridge = class {
4831
4882
  constructor(command, args, env = {}, requestTimeoutMs = 2e4) {
4832
4883
  this.command = command;
@@ -5133,17 +5184,64 @@ var SageHookRuntime = class {
5133
5184
  });
5134
5185
  console.warn(`${message}${suffix}`);
5135
5186
  }
5136
- async getSessionContext(sessionId) {
5187
+ /** This CLI rejected `--model-endpoint` once; stop sending it. */
5188
+ modelEndpointUnsupported = false;
5189
+ /**
5190
+ * Sage routing context for a session. `modelEndpoint` is the base URL of
5191
+ * the session's model: with `suggest.context.mode = auto`, a local model
5192
+ * (loopback endpoint) gets the compact context.
5193
+ */
5194
+ async getSessionContext(sessionId, modelEndpoint) {
5137
5195
  const cacheKey = sessionId?.trim() || "__default__";
5138
- const result = await this.run(
5139
- ["skill", "context", "--format", "pi"],
5140
- { SAGE_SESSION_ID: sessionId ?? "" },
5141
- void 0,
5142
- {
5143
- failurePolicy: "warn",
5144
- timeoutMs: this.getSoftTimeout(SAGE_HOOK_TIMEOUTS.sessionContext)
5196
+ const session = sessionId?.trim();
5197
+ let endpoint;
5198
+ try {
5199
+ const origin = modelEndpoint?.trim() ? new URL(modelEndpoint.trim()).origin : "";
5200
+ endpoint = origin && origin !== "null" ? origin : void 0;
5201
+ } catch {
5202
+ endpoint = void 0;
5203
+ }
5204
+ const args = [
5205
+ "skill",
5206
+ "context",
5207
+ "--format",
5208
+ "pi",
5209
+ "--source",
5210
+ this.config.source ?? "pi",
5211
+ ...session ? ["--session", session] : []
5212
+ ];
5213
+ const env = { SAGE_SESSION_ID: sessionId ?? "" };
5214
+ const timeoutMs = this.getSoftTimeout(SAGE_HOOK_TIMEOUTS.sessionContext);
5215
+ let result = null;
5216
+ const useFlag = Boolean(endpoint) && !this.modelEndpointUnsupported;
5217
+ let rejectedFlag = false;
5218
+ if (useFlag) {
5219
+ let failure;
5220
+ result = await this.run([...args, `--model-endpoint=${endpoint}`], env, void 0, {
5221
+ failurePolicy: "silent",
5222
+ timeoutMs,
5223
+ onFailure: (f) => {
5224
+ failure = f;
5225
+ }
5226
+ });
5227
+ if (!result && failure) {
5228
+ rejectedFlag = /--model-endpoint/.test(failure.stderr ?? "");
5229
+ if (rejectedFlag) {
5230
+ this.modelEndpointUnsupported = true;
5231
+ } else {
5232
+ const commandText = formatSageCommand(this.config.sageBin, args);
5233
+ const detail = (failure.stderr || failure.stdout || "").trim();
5234
+ this.logSoftFailure(
5235
+ commandText,
5236
+ failure.timedOut ? `[sage-pi-adapter] Sage command timed out: ${commandText}` : `[sage-pi-adapter] Sage command failed (${failure.exitCode}): ${commandText}${detail ? `
5237
+ ${detail}` : ""}`
5238
+ );
5239
+ }
5145
5240
  }
5146
- );
5241
+ }
5242
+ if (!useFlag || rejectedFlag) {
5243
+ result = await this.run(args, env, void 0, { failurePolicy: "warn", timeoutMs });
5244
+ }
5147
5245
  const context = result?.stdout.trim() ?? "";
5148
5246
  if (context) {
5149
5247
  this.sessionContextCache.set(cacheKey, context);
@@ -5516,21 +5614,25 @@ var SageHookRuntime = class {
5516
5614
  }
5517
5615
  /**
5518
5616
  * Run `sage security scan-hook` and turn every outcome into a decision.
5519
- * An explicit decision in stdout wins, even when the CLI exits non-zero. A
5520
- * scan that cannot decide follows `securityFailurePolicy` and is never a
5521
- * silent allow. Completely empty stdout with exit 0 still means allow: that is
5522
- * what a CLI without structured allow output prints.
5617
+ * An explicit block or warn in stdout wins, even when the run failed; an
5618
+ * allow counts only from a clean run. A scan that cannot decide (failed run,
5619
+ * empty or unparseable stdout) follows `securityFailurePolicy` and is never
5620
+ * a silent allow.
5523
5621
  */
5524
5622
  async runSecurityScan(payload, sessionId) {
5525
5623
  if (this.config.enableSecurityHooks === false) return null;
5624
+ const serialized = serializeScanPayload(payload);
5625
+ if ("serializationFailed" in serialized) {
5626
+ return this.securityFailureDecision("could not serialize scan payload");
5627
+ }
5526
5628
  const captured = {};
5527
5629
  const result = await this.run(
5528
5630
  ["security", "scan-hook"],
5529
5631
  {
5530
- SAGE_SOURCE: this.config.source ?? "pi",
5632
+ SAGE_SOURCE: SAGE_SCAN_PROTOCOL_SOURCE,
5531
5633
  SAGE_SESSION_ID: sessionId ?? ""
5532
5634
  },
5533
- JSON.stringify(payload),
5635
+ serialized.json,
5534
5636
  {
5535
5637
  failurePolicy: "warn",
5536
5638
  timeoutMs: this.getSoftTimeout(SAGE_HOOK_TIMEOUTS.securityScan),
@@ -5554,8 +5656,10 @@ var SageHookRuntime = class {
5554
5656
  return parsed;
5555
5657
  }
5556
5658
  }
5557
- if (!failure && !parsed && !stdout.trim()) return null;
5558
- const detail = failure ? failure.timedOut ? "timed out" : failure.exitCode === -1 ? `could not run: ${failure.stderr.trim() || "unknown error"}` : `exit ${failure.exitCode}` : parsed?.decision === "error" ? `scan error: ${parsed.reason ?? "no detail"}` : "unparseable scan output";
5659
+ const detail = failure ? failure.timedOut ? "timed out" : failure.stdinFailed ? (
5660
+ // The scanner may echo the payload it rejected; never surface it.
5661
+ "could not deliver scan input"
5662
+ ) : failure.exitCode === -1 ? `could not run: ${boundScanFailureDetail(failure.stderr)}` : `exit ${failure.exitCode}` : parsed?.decision === "error" ? `scan error: ${parsed.reason ?? "no detail"}` : stdout.trim() ? "unparseable scan output" : "empty scan output";
5559
5663
  return this.securityFailureDecision(detail);
5560
5664
  }
5561
5665
  securityFailureDecision(detail) {
@@ -5742,8 +5846,11 @@ function createSageSearchTool(mcpBridge) {
5742
5846
  "Prefer Sage tools. When an operation is unavailable through them, use the installed Sage CLI with the same approval and credential safeguards.",
5743
5847
  "Prefer sage_search for Sage read/discovery flows such as help.list, prompts.search, behaviors.show, meta.get_project_context, meta.suggest, hub.list_servers/status, wallet.balance/address, and external.search",
5744
5848
  "Use sage_search({ domain: 'help', action: 'list', params: {} }) before guessing unknown Sage domains or actions",
5849
+ "Start from the user's job: skills supply procedures, external tools perform operations, and collaborators supply complementary help. Search only the missing capability; do not tour every domain or start servers automatically.",
5850
+ "Collaboration is channel-neutral: use the existing authorized Sage Chat, Telegram, X, Buzz or other conversation and its advertised read/reply schema. Discovery does not authorize a send, installation, payment or cross-post.",
5851
+ "After resume or compaction, use the current callable inventory. Distinguish not advertised, rejected, and not attempted; one relevant read is a better probe than repeated shell echoes. A denial must not trigger a fallback bypass.",
5745
5852
  "Use sage_search({ domain: 'hub', action: 'list_servers', params: {} }) for MCP server inventory; use domain='external', action='list_servers' only to inspect running external servers and tool exposure",
5746
- "If Sage classifies an action as a mutation or non-search inspect action, prefer sage_execute; use the CLI fallback if that operation is unavailable through the tools",
5853
+ "Full-body content and inspection reads stay on sage_search. Only supported unsigned mutations use sage_execute; signed actions need the approved CLI route",
5747
5854
  "A security or approval denial is not tool unavailability. Do not switch surfaces to bypass it; preserve the active profile, required approvals, dry runs, and credential protections."
5748
5855
  ],
5749
5856
  description: "Route read-only Sage code-mode requests across prompts, behaviors, skills, builder, governance, chat, social, RLM, security, meta, hub, activation, wallet, library, help, and external services. Start with domain='help', action='list' when you do not know the route. Use domain='meta', action='get_project_context' for local Sage state and domain='meta', action='suggest' with params={goal:'...'} when you need route suggestions. Use domain='hub' for MCP hub inventory/status and domain='external' for external tool discovery/search. Full-body reads such as prompts.get, skills.get, and library.skill_get are read-only and should use sage_search.",
@@ -6283,6 +6390,7 @@ function wrapToolsWithSageSecurity(tools, options) {
6283
6390
  )
6284
6391
  }
6285
6392
  ],
6393
+ structuredContent: void 0,
6286
6394
  details: {
6287
6395
  blockedBySageSecurity: true,
6288
6396
  reason: pre.reason,
@@ -6307,18 +6415,18 @@ function wrapToolsWithSageSecurity(tools, options) {
6307
6415
  if (post?.decision === "block") {
6308
6416
  return {
6309
6417
  content: [{ type: "text", text: `${securityBlockMessage(tool.name, post.reason, "high-risk output detected")} The original tool output was withheld.` }],
6418
+ structuredContent: void 0,
6310
6419
  details: { blockedBySageSecurity: true },
6311
6420
  isError: true
6312
6421
  };
6313
6422
  }
6423
+ const notices = [];
6424
+ if (pre?.decision === "warn") notices.push(securityWarnNotice(pre));
6314
6425
  if (post?.decision === "warn") {
6315
- return appendText(
6316
- // Force text fallback so typed callers cannot skip the warning.
6317
- { ...result, structuredContent: void 0 },
6318
- `Sage security warn: ${post.reason ?? "treat this output as untrusted content."}`
6319
- );
6426
+ notices.push(`Sage security warn: ${post.reason ?? "treat this output as untrusted content."}`);
6320
6427
  }
6321
- return result;
6428
+ if (notices.length === 0) return result;
6429
+ return notices.reduce(appendText, { ...result, structuredContent: void 0 });
6322
6430
  }
6323
6431
  };
6324
6432
  });
@@ -6818,6 +6926,7 @@ export {
6818
6926
  PiIntercom,
6819
6927
  SageHookRuntime,
6820
6928
  SageMcpBridge,
6929
+ boundScanFailureDetail,
6821
6930
  clampLineToWidth,
6822
6931
  cliInboxTransport,
6823
6932
  createHubListServersTool,
@@ -6837,6 +6946,7 @@ export {
6837
6946
  parseSecurityDecision,
6838
6947
  resolveBehaviorPlan,
6839
6948
  securityBlockMessage,
6949
+ securityWarnNotice,
6840
6950
  truncateLineToWidth,
6841
6951
  unicodeSafe,
6842
6952
  visibleWidthOf,
@@ -94,6 +94,8 @@ export interface SageCommandResult {
94
94
  stdout: string;
95
95
  stderr: string;
96
96
  timedOut: boolean;
97
+ /** Stdin was not fully delivered (for example EPIPE after an early exit). */
98
+ stdinFailed?: boolean;
97
99
  }
98
100
  export interface SkillVisibilityResult {
99
101
  summary: string;
@@ -157,11 +159,25 @@ export type SecurityDecision = {
157
159
  type ParsedSecurityDecision = Omit<SecurityDecision, "decision"> & {
158
160
  decision: SecurityDecision["decision"] | "error";
159
161
  };
162
+ /**
163
+ * Text for a pre-tool warn. A warn produced by the failure policy already says
164
+ * "security scan unavailable"; a scanner warn carries the scanner's own reason.
165
+ */
166
+ export declare function securityWarnNotice(decision: {
167
+ reason?: string;
168
+ scanUnavailable?: boolean;
169
+ }): string;
160
170
  /**
161
171
  * Message for a blocked call. The CLI reason may already start with
162
172
  * "Sage security blocked ..."; do not prefix it a second time.
163
173
  */
164
174
  export declare function securityBlockMessage(toolName: string, reason: string | undefined, fallback: string): string;
175
+ /**
176
+ * Render scanner stderr for a user-facing reason: control and bidi characters
177
+ * are replaced, whitespace is collapsed, and only the tail is kept (the error
178
+ * that ended the run is last).
179
+ */
180
+ export declare function boundScanFailureDetail(stderr: string): string;
165
181
  export declare function defaultSageCommandRunner(request: SageCommandRequest): Promise<SageCommandResult>;
166
182
  /** Return terminal-visible width while ignoring ANSI SGR sequences. */
167
183
  export declare function visibleWidthOf(line: string): number;
@@ -235,7 +251,14 @@ export declare class SageHookRuntime {
235
251
  private getSoftTimeout;
236
252
  private clearSoftFailure;
237
253
  private logSoftFailure;
238
- getSessionContext(sessionId?: string): Promise<string>;
254
+ /** This CLI rejected `--model-endpoint` once; stop sending it. */
255
+ private modelEndpointUnsupported;
256
+ /**
257
+ * Sage routing context for a session. `modelEndpoint` is the base URL of
258
+ * the session's model: with `suggest.context.mode = auto`, a local model
259
+ * (loopback endpoint) gets the compact context.
260
+ */
261
+ getSessionContext(sessionId?: string, modelEndpoint?: string): Promise<string>;
239
262
  /**
240
263
  * Gather skill visibility summary for user-facing display.
241
264
  *
@@ -278,10 +301,10 @@ export declare class SageHookRuntime {
278
301
  scanPostTool(toolName: string, toolInput: Record<string, unknown>, toolResult: unknown, sessionId?: string): Promise<SecurityDecision | null>;
279
302
  /**
280
303
  * Run `sage security scan-hook` and turn every outcome into a decision.
281
- * An explicit decision in stdout wins, even when the CLI exits non-zero. A
282
- * scan that cannot decide follows `securityFailurePolicy` and is never a
283
- * silent allow. Completely empty stdout with exit 0 still means allow: that is
284
- * what a CLI without structured allow output prints.
304
+ * An explicit block or warn in stdout wins, even when the run failed; an
305
+ * allow counts only from a clean run. A scan that cannot decide (failed run,
306
+ * empty or unparseable stdout) follows `securityFailurePolicy` and is never
307
+ * a silent allow.
285
308
  */
286
309
  private runSecurityScan;
287
310
  private securityFailureDecision;
@@ -1 +1 @@
1
- {"version":3,"file":"sage-pi-adapter.d.ts","sourceRoot":"","sources":["../src/sage-pi-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sage-pi-adapter.d.ts","sourceRoot":"","sources":["../src/sage-pi-adapter.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@ import {
15
15
  createOptionalSageWalletStatusTool,
16
16
  createSageSearchTool,
17
17
  createSageStatusTool,
18
+ securityBlockMessage,
19
+ securityWarnNotice,
18
20
  unicodeSafe,
19
21
  type SageP2Config,
20
22
  type BehaviorPlan,
@@ -73,21 +75,6 @@ class SageWidgetState {
73
75
  }
74
76
  }
75
77
 
76
- /**
77
- * Message for a blocked call. The scan reason may already start with
78
- * "Sage security blocked ..."; do not prefix it a second time. Kept here (not
79
- * imported from the adapter build) so the hook handlers stay self-contained.
80
- */
81
- function securityBlockMessage(
82
- toolName: string,
83
- reason: string | undefined,
84
- fallback: string,
85
- ): string {
86
- const text = reason?.trim();
87
- if (text && /^Sage security blocked\b/i.test(text)) return text;
88
- return `Sage security blocked ${toolName}: ${text || fallback}`;
89
- }
90
-
91
78
  function parseBoolean(value: string | undefined, fallback: boolean): boolean {
92
79
  if (value === undefined) return fallback;
93
80
  const normalized = value.trim().toLowerCase();
@@ -686,6 +673,8 @@ export default function sagePiAdapterExtension(pi: ExtensionApi): void {
686
673
  // System prompt injection: Sage-first routing for Pi sessions
687
674
  // ---------------------------------------------------------------------------
688
675
  const injectToolDocs = parseBoolean(process.env.SAGE_INJECT_TOOL_DOCS, true);
676
+ /** Sage context for the current session, rendered into the system prompt. */
677
+ let sessionContextBlock = "";
689
678
 
690
679
  // Tier 1: Tool-level docs via promptSnippet/promptGuidelines (always active, ~200 tokens).
691
680
  // Tier 2: Full usage patterns injected once at session_start (below).
@@ -768,6 +757,8 @@ Use these tools proactively when the user asks for documentation, current inform
768
757
  const skillPathToName = new Map<string, string>();
769
758
  let pendingReadToolSkills = new Map<string, PendingSkillRead>();
770
759
  let pendingSageSkillLoads = new Map<string, { key: string; bareKey: string; action: "get" | "skill_get" }>();
760
+ // Pre-tool warns that had no UI to show them; delivered on the tool's result.
761
+ let pendingPreToolWarnings = new Map<string, string>();
771
762
  let loadedSkillsInSession = new Map<string, string>();
772
763
  let guidedUseSkillsThisTurn = new Map<string, string>();
773
764
  let currentTurnId: string | undefined;
@@ -789,6 +780,7 @@ Use these tools proactively when the user asks for documentation, current inform
789
780
  currentSessionId = sessionId;
790
781
  pendingReadToolSkills = new Map();
791
782
  pendingSageSkillLoads = new Map();
783
+ pendingPreToolWarnings = new Map();
792
784
  loadedSkillsInSession = new Map<string, string>();
793
785
  receiptedSkillsInSession = new Set<string>();
794
786
  receiptWritesInFlight = new Set<string>();
@@ -1113,26 +1105,25 @@ Use these tools proactively when the user asks for documentation, current inform
1113
1105
  lastUi = ctx?.ui ?? lastUi;
1114
1106
  updateSageHealthStatus(ctx?.ui);
1115
1107
 
1116
- // Inject full Sage protocol context once at session start.
1117
- let fullContext = SAGE_SESSION_CONTEXT;
1108
+ // Fetch the full Sage context once per session. It is rendered into the
1109
+ // system prompt on every turn (before_agent_start), ahead of the user's
1110
+ // prompt, so it is part of the cacheable prefix: a hidden message
1111
+ // delivered after the first prompt was reprocessed in every session.
1112
+ sessionContextBlock = SAGE_SESSION_CONTEXT;
1118
1113
  try {
1119
- const dynamicContext = await hookRuntime.getSessionContext(sessionId);
1114
+ // Size the context to the session's model (compact for a local model).
1115
+ const modelEndpoint =
1116
+ typeof ctx?.model?.baseUrl === "string" ? ctx.model.baseUrl : undefined;
1117
+ const dynamicContext = modelEndpoint
1118
+ ? await hookRuntime.getSessionContext(sessionId, modelEndpoint)
1119
+ : await hookRuntime.getSessionContext(sessionId);
1120
1120
  if (dynamicContext.trim()) {
1121
- fullContext = dynamicContext.trim() + "\n\n" + SAGE_PER_TURN_GUARDRAIL;
1121
+ sessionContextBlock = dynamicContext.trim();
1122
1122
  }
1123
1123
  } catch {
1124
1124
  // Keep static SAGE_SESSION_CONTEXT as fallback.
1125
1125
  }
1126
1126
 
1127
- pi.sendMessage(
1128
- {
1129
- customType: "sage-session-context",
1130
- content: fullContext,
1131
- display: false,
1132
- },
1133
- { deliverAs: "nextTurn" },
1134
- );
1135
-
1136
1127
  // Loaded inventory goes to the pi footer status (next to the health
1137
1128
  // dot); the editor widget stays reserved for subagent skill resolution.
1138
1129
  try {
@@ -1184,6 +1175,7 @@ Use these tools proactively when the user asks for documentation, current inform
1184
1175
  loadedSkillsInSession = new Map();
1185
1176
  pendingReadToolSkills = new Map();
1186
1177
  pendingSageSkillLoads = new Map();
1178
+ pendingPreToolWarnings = new Map();
1187
1179
  });
1188
1180
 
1189
1181
  pi.on("before_agent_start", async (event, ctx) => {
@@ -1206,6 +1198,7 @@ Use these tools proactively when the user asks for documentation, current inform
1206
1198
  }
1207
1199
  pendingReadToolSkills = new Map();
1208
1200
  pendingSageSkillLoads = new Map();
1201
+ pendingPreToolWarnings = new Map();
1209
1202
  guidedUseSkillsThisTurn = new Map<string, string>();
1210
1203
  currentTurnId = randomUUID();
1211
1204
  sageWidget.clear();
@@ -1217,14 +1210,16 @@ Use these tools proactively when the user asks for documentation, current inform
1217
1210
  // so we must always return the modified prompt to keep the compact Sage
1218
1211
  // guardrail active. Keep this block small: the full Sage context is sent
1219
1212
  // once during session_start.
1213
+ // Order matters for prompt caching: the base prompt, then the session's
1214
+ // Sage context, then the guardrail, identical on every turn.
1220
1215
  let modifiedSystemPrompt: string | undefined;
1221
- if (injectToolDocs) {
1222
- const currentSystemPrompt =
1223
- typeof event?.systemPrompt === "string" ? event.systemPrompt : "";
1224
- if (currentSystemPrompt) {
1225
- const docs = SAGE_PER_TURN_GUARDRAIL;
1226
- modifiedSystemPrompt = currentSystemPrompt + "\n\n" + docs;
1227
- }
1216
+ const currentSystemPrompt =
1217
+ typeof event?.systemPrompt === "string" ? event.systemPrompt : "";
1218
+ if (currentSystemPrompt) {
1219
+ const parts = [currentSystemPrompt];
1220
+ if (sessionContextBlock) parts.push(sessionContextBlock);
1221
+ if (injectToolDocs) parts.push(SAGE_PER_TURN_GUARDRAIL);
1222
+ if (parts.length > 1) modifiedSystemPrompt = parts.join("\n\n");
1228
1223
  }
1229
1224
 
1230
1225
  // --- Skill auto-resolution for subagents ---
@@ -1234,7 +1229,9 @@ Use these tools proactively when the user asks for documentation, current inform
1234
1229
  process.env.SAGE_AUTO_RESOLVE_SKILLS,
1235
1230
  true,
1236
1231
  );
1237
- if (enableSkillResolve && modifiedSystemPrompt) {
1232
+ // Auto-resolve rides on the tool docs, as before the Sage context moved
1233
+ // into the system prompt: SAGE_INJECT_TOOL_DOCS=0 keeps it off.
1234
+ if (enableSkillResolve && injectToolDocs && modifiedSystemPrompt) {
1238
1235
  // Match patterns like: "Skills not found: foo, bar" or explicit skill refs
1239
1236
  const skillNotFoundMatch = prompt.match(
1240
1237
  /skills?\s+not\s+found:\s*([^\n]+)/i,
@@ -1337,6 +1334,7 @@ Use these tools proactively when the user asks for documentation, current inform
1337
1334
  await flushCapture(ctx);
1338
1335
  pendingReadToolSkills = new Map();
1339
1336
  pendingSageSkillLoads = new Map();
1337
+ pendingPreToolWarnings = new Map();
1340
1338
  currentTurnId = undefined;
1341
1339
  });
1342
1340
 
@@ -1397,8 +1395,6 @@ Use these tools proactively when the user asks for documentation, current inform
1397
1395
  }
1398
1396
  }
1399
1397
 
1400
- if (toolName.startsWith("sage_")) return;
1401
-
1402
1398
  // --- Intercept bash calls to sage CLI and redirect to sage_search/sage_execute ---
1403
1399
  if (toolName === "bash") {
1404
1400
  const command =
@@ -1515,8 +1511,14 @@ Use these tools proactively when the user asks for documentation, current inform
1515
1511
  reason: securityBlockMessage(toolName, pre.reason, "high-risk request"),
1516
1512
  };
1517
1513
  }
1518
- if (pre?.decision === "warn" && pre.scanUnavailable) {
1519
- ctx?.ui?.notify?.(`Sage ${pre.reason}`, "warning");
1514
+ if (pre?.decision === "warn") {
1515
+ const notice = securityWarnNotice(pre);
1516
+ if (typeof ctx?.ui?.notify === "function") {
1517
+ ctx.ui.notify(notice, "warning");
1518
+ } else if (toolCallId) {
1519
+ // Headless: no UI, so the user sees it on the tool's result.
1520
+ pendingPreToolWarnings.set(toolCallId, notice);
1521
+ }
1520
1522
  }
1521
1523
  });
1522
1524
 
@@ -1558,8 +1560,6 @@ Use these tools proactively when the user asks for documentation, current inform
1558
1560
  if (toolCallId) pendingSageSkillLoads.delete(toolCallId);
1559
1561
  }
1560
1562
 
1561
- if (toolName.startsWith("sage_")) return;
1562
-
1563
1563
  const toolInput =
1564
1564
  event?.input && typeof event.input === "object"
1565
1565
  ? (event.input as Record<string, unknown>)
@@ -1579,6 +1579,14 @@ Use these tools proactively when the user asks for documentation, current inform
1579
1579
  toolResult,
1580
1580
  sessionId,
1581
1581
  );
1582
+ const preNotice = toolCallId ? pendingPreToolWarnings.get(toolCallId) : undefined;
1583
+ if (toolCallId) pendingPreToolWarnings.delete(toolCallId);
1584
+ if (post?.decision !== "block" && preNotice && (!post || post.decision === "allow")) {
1585
+ return {
1586
+ content: [...(Array.isArray(event?.content) ? event.content : []), { type: "text", text: preNotice }],
1587
+ structuredContent: undefined,
1588
+ };
1589
+ }
1582
1590
  if (!post || post.decision === "allow") return;
1583
1591
 
1584
1592
  if (post.decision === "block") {
@@ -1602,8 +1610,8 @@ Use these tools proactively when the user asks for documentation, current inform
1602
1610
  };
1603
1611
 
1604
1612
  const content = Array.isArray(event?.content)
1605
- ? [...event.content, warning]
1606
- : [warning];
1613
+ ? [...event.content, ...(preNotice ? [{ type: "text", text: preNotice }] : []), warning]
1614
+ : [...(preNotice ? [{ type: "text", text: preNotice }] : []), warning];
1607
1615
  return { content, structuredContent: undefined };
1608
1616
  });
1609
1617
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-protocol/pi-adapter",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Sage Protocol MCP integration for pi coding agent",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",