@gendigital/sage-opencode 0.14.0 → 0.15.0

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/index.js CHANGED
@@ -1,324 +1,48 @@
1
1
  /**
2
2
  * Sage OpenCode plugin.
3
3
  * Intercepts tool calls and uses @gendigital/sage-core to enforce security verdicts.
4
- */
5
- import { mkdirSync, watchFile } from "node:fs";
6
- import { dirname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
- import { ApprovalStore, approveAction, checkAllowlistMigration, createOperationalLogger, foreignSourceRuntime, formatAllowlistMigrationWarning, formatConfigurationWarnings, formatNoticeById, getConfigurationWarnings, loadConfig, loadSkillVerdictCache, resolveBranding, resolvePath, } from "@gendigital/sage-core";
9
- import { tool } from "@opencode-ai/plugin/tool";
10
- import { getBundledDataDirs } from "./bundled-dirs.js";
11
- import { createSessionScanHandler } from "./startup-scan.js";
12
- import { createToolHandlers } from "./tool-handler.js";
13
- const APPROVAL_STORE_CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
14
- const DEFAULT_TOAST_DURATION_MS = 5000;
15
- // The startup security summary lists every risky skill, so it's shown longer to
16
- // give the user time to read the list before it dismisses.
17
- const STARTUP_SUMMARY_DURATION_MS = 10_000;
18
- // Module-scoped so repeated SagePlugin instantiations (OpenCode may load the
19
- // plugin more than once) share a single watcher and one notified-set, instead
20
- // of each instance attaching its own watcher and toasting the same verdict.
21
- const notifiedSkillVerdicts = new Set();
22
- let skillWatcherAttached = false;
23
- // One scan per session, shared across instances: the entry guards against
24
- // re-running the scan when session.updated fires repeatedly or on more than one
25
- // plugin instance.
26
- const sessionScanPromises = new Map();
27
- const toastQueue = [];
28
- let toastPumpRunning = false;
29
- // Bound to a live client's showToast by the first instance (see SagePlugin).
30
- let displayToast;
31
- async function pumpToasts() {
32
- if (toastPumpRunning)
33
- return;
34
- toastPumpRunning = true;
35
- try {
36
- while (toastQueue.length > 0) {
37
- const next = toastQueue[0];
38
- // No client bound yet — leave the item queued; a later enqueue resumes.
39
- if (!displayToast || !next)
40
- break;
41
- displayToast(next.message, next.variant, next.durationMs);
42
- toastQueue.shift();
43
- // Hold the slot for this toast's full duration before showing the next,
44
- // so a following toast can't replace it early (showToast overwrites).
45
- await new Promise((resolve) => setTimeout(resolve, next.durationMs));
46
- }
47
- }
48
- finally {
49
- toastPumpRunning = false;
50
- }
51
- }
52
- function enqueueToast(message, variant, durationMs = DEFAULT_TOAST_DURATION_MS) {
53
- toastQueue.push({ message, variant, durationMs });
54
- void pumpToasts();
55
- }
56
- // Shared dedup key across the two surfacing paths: the scan-findings popup keys
57
- // on `finding.artifact` (which is `skillId.slice(0, 16)`), and the cache watcher
58
- // keys on the full skillId — so both reduce to this 16-char content-hash prefix
59
- // and `notifiedSkillVerdicts` never double-announces the same skill version.
60
- function shortSkillId(skillId) {
61
- return skillId.slice(0, 16);
62
- }
63
- /**
64
- * Read `~/.sage/skill_verdict_cache.json` and return every HIGH/CRITICAL verdict
65
- * relevant to this runtime — one per cache entry, NOT deduped, since dedup is
66
- * caller-specific (the popup keys on current content, the toast queue on
67
- * skillId). HIGH maps to the "WARNING" label. Verdicts sourced only from other
68
- * agent runtimes are skipped so one host doesn't echo another's finds.
69
- */
70
- async function collectRiskySkills(agentRuntime) {
71
- const cache = await loadSkillVerdictCache();
72
- const out = [];
73
- for (const [skillId, verdict] of Object.entries(cache.entries)) {
74
- const risk = (verdict.verdict ?? "").toUpperCase();
75
- if (risk !== "HIGH" && risk !== "CRITICAL")
76
- continue;
77
- if (foreignSourceRuntime(verdict.sources, agentRuntime))
78
- continue;
79
- const key = verdict.sources?.find((s) => s.containerKey)?.containerKey ||
80
- verdict.skillName ||
81
- skillId.slice(0, 16);
82
- out.push({
83
- skillId,
84
- key,
85
- severity: risk === "CRITICAL" ? "CRITICAL" : "WARNING",
86
- summary: verdict.summary?.trim(),
87
- });
88
- }
89
- return out;
90
- }
91
- /**
92
- * Watch `~/.sage/skill_verdict_cache.json` and queue one toast per verdict the
93
- * upload worker writes mid-session (it writes asynchronously, ~one session after
94
- * discovery). The serial queue shows them one at a time so two skills finishing
95
- * together are both seen.
96
4
  *
97
- * Verdicts cached by earlier sessions are *seeded silently* on attach — marked
98
- * notified without a toast — because the plugin initialises before the TUI is
99
- * ready to render toasts. Those are surfaced instead by the session-start
100
- * summary popup (see `surfaceStartupSummary`), which runs after the scan when
101
- * the TUI is up.
5
+ * One entry point serves both OpenCode generations:
6
+ * - v1 (`opencode` 1.x) reads `default.server` (the `{ id, server }` module
7
+ * shape) and calls it with `(input, options)`.
8
+ * - v2 (opencode2 / `@opencode-ai/core`) decodes `default` as `{ id, setup }`
9
+ * and calls `setup(context)`; extra keys are ignored by both loaders.
102
10
  *
103
- * Dedup keys on `skillId` (content hash), not the container key, so editing a
104
- * skill — which yields a new hash under the same key — is treated as a new
105
- * finding and re-announced rather than silently collapsed into the old one.
11
+ * The default export must stay a plain object: v2 rejects a function there.
12
+ * Keep every other export a v1 plugin function — legacy v1 loaders call each
13
+ * module export as a plugin and throw on anything else.
106
14
  */
107
- function setupSkillFindingsWatcher(logger, agentRuntime) {
108
- if (skillWatcherAttached)
109
- return;
110
- const sageDir = resolvePath("~/.sage");
111
- const seedNotified = async () => {
112
- try {
113
- for (const s of await collectRiskySkills(agentRuntime)) {
114
- notifiedSkillVerdicts.add(shortSkillId(s.skillId));
115
- }
116
- }
117
- catch (e) {
118
- logger.debug("Skill verdict seed failed", { error: String(e) });
119
- }
120
- };
121
- // Mid-session: queue one toast per newly written (not-yet-notified) verdict.
122
- const announceNew = async () => {
123
- try {
124
- for (const s of await collectRiskySkills(agentRuntime)) {
125
- const short = shortSkillId(s.skillId);
126
- if (notifiedSkillVerdicts.has(short))
127
- continue;
128
- notifiedSkillVerdicts.add(short);
129
- const detail = s.summary ? `${s.key} — ${s.summary}` : `${s.key} detected`;
130
- logger.debug("Skill finding toast queued", { key: s.key, severity: s.severity });
131
- enqueueToast(`${detail} (${s.severity})`, s.severity === "CRITICAL" ? "error" : "warning");
132
- }
133
- }
134
- catch (e) {
135
- logger.debug("Skill verdict watcher scan failed", { error: String(e) });
136
- }
137
- };
138
- try {
139
- mkdirSync(sageDir, { recursive: true });
140
- void seedNotified();
141
- // Poll the cache file with watchFile rather than watch() the directory.
142
- // On Windows, fs.watch aborts the whole process (an uncatchable libuv
143
- // assertion in fs-event.c) when the watched path is an 8.3 short name
144
- // (e.g. an os.tmpdir() like C:\Users\FOO~1.BAR\...) or symlinked home.
145
- // watchFile is stat-based polling — immune to that. A few seconds of
146
- // latency for mid-session verdicts is fine (matches the statusline poll
147
- // cadence used elsewhere). Handles a not-yet-existent file (polls until
148
- // it appears).
149
- const cacheFile = join(sageDir, "skill_verdict_cache.json");
150
- const watcher = watchFile(cacheFile, { interval: 3000 }, (curr, prev) => {
151
- if (curr.mtimeMs !== prev.mtimeMs)
152
- void announceNew();
153
- });
154
- watcher.unref?.();
155
- skillWatcherAttached = true;
156
- logger.debug("Skill findings watcher attached", { cacheFile });
157
- }
158
- catch (e) {
159
- // ~/.sage/ may be unwritable — no watcher, no notifications (fail-open).
160
- logger.debug("Skill findings watcher setup failed", { error: String(e) });
161
- }
162
- }
15
+ import { tool } from "@opencode-ai/plugin/tool";
16
+ import { approvalPatterns, createSageController, SAGE_MCP_SERVER_NAME, SAGE_PLUGIN_ID, sageMcpServerConfig, } from "./shared.js";
17
+ import { setupV2 } from "./v2.js";
18
+ const DEFAULT_TOAST_DURATION_MS = 5000;
19
+ /** OpenCode v1 plugin function (`(input, options) => Hooks`). */
163
20
  export const SagePlugin = async ({ client, directory }) => {
164
- const config = await loadConfig();
165
- const operationalLogger = createOperationalLogger(config.operational_logging, "opencode");
166
- const logger = operationalLogger.forComponent("plugin");
167
- const toolLogger = operationalLogger.forComponent("tool-handler");
168
- const scanLogger = operationalLogger.forComponent("startup-scan");
169
- const branding = resolveBranding(config.brand_key, logger);
170
- const showToast = (msg, variant, durationMs = DEFAULT_TOAST_DURATION_MS) => {
171
- client.tui
172
- .showToast({
173
- body: { title: branding.name, message: msg, variant, duration: durationMs },
174
- })
175
- .catch(() => { });
176
- };
177
- // Bind the module-scoped skill-toast queue to this (first) instance's client.
178
- // The queue passes each item's own duration, which showToast honors.
179
- displayToast ??= showToast;
180
- const warningMessage = formatConfigurationWarnings(await getConfigurationWarnings(undefined, logger), branding);
181
- if (warningMessage) {
182
- client.tui
183
- .showToast({
184
- body: {
185
- title: branding.name,
186
- message: warningMessage,
187
- variant: "warning",
188
- duration: DEFAULT_TOAST_DURATION_MS,
189
- },
190
- })
191
- .catch(() => { });
192
- }
193
- const allowlistMigration = await checkAllowlistMigration();
194
- if (allowlistMigration.needed) {
21
+ const createNotifier = (branding) => (msg, variant, durationMs = DEFAULT_TOAST_DURATION_MS) => {
195
22
  client.tui
196
- .showToast({
197
- body: {
198
- title: branding.name,
199
- message: formatAllowlistMigrationWarning(allowlistMigration.entryTypes, branding),
200
- variant: "warning",
201
- duration: 8000,
202
- },
203
- })
23
+ .showToast({ body: { title: branding.name, message: msg, variant, duration: durationMs } })
204
24
  .catch(() => { });
205
- }
206
- const { threatsDir, trustedDomainsDir } = getBundledDataDirs();
207
- const approvalStore = new ApprovalStore();
208
- // Watch for verdicts the upload worker writes mid-session (queued toasts).
209
- // Verdicts cached by earlier sessions are surfaced by surfaceStartupSummary.
210
- setupSkillFindingsWatcher(logger, "opencode");
211
- // Surface the scan's structured findings after the scan (TUI ready). Findings
212
- // are install- and content-accurate: the scan hashes current on-disk content
213
- // and looks up its verdict, so a deleted skill isn't discovered and an edited
214
- // skill is matched by its new hash — no cache re-derivation needed.
215
- //
216
- // Single startup surface: one summary toast listing every risky skill from
217
- // this scan. Summarized skills are marked notified so the cache watcher does
218
- // not also announce them per-skill; verdicts that land *after* the scan
219
- // (worker uploads) are still surfaced individually by the watcher.
220
- const surfaceStartupSummary = (scanResults) => {
221
- try {
222
- const skills = [];
223
- const seen = new Set();
224
- for (const result of scanResults) {
225
- for (const finding of result.findings) {
226
- if (finding.threatId !== "SKILL_CHECK")
227
- continue;
228
- if (finding.severity !== "critical" && finding.severity !== "warning")
229
- continue;
230
- if (seen.has(result.plugin.key))
231
- continue;
232
- seen.add(result.plugin.key);
233
- skills.push({
234
- key: result.plugin.key,
235
- severity: finding.severity === "critical" ? "CRITICAL" : "WARNING",
236
- finding,
237
- });
238
- }
239
- }
240
- if (skills.length === 0)
241
- return;
242
- // Mark every summarized skill as notified so the cache watcher doesn't
243
- // also announce it per-skill. `finding.artifact` is the 16-char short
244
- // hash — the same key the watcher dedups on. Verdicts that land after
245
- // this scan (worker uploads) are still surfaced individually.
246
- for (const s of skills) {
247
- if (s.finding.artifact)
248
- notifiedSkillVerdicts.add(s.finding.artifact);
249
- }
250
- // The summary: a single toast listing every risky skill, shown longer.
251
- const hasCritical = skills.some((s) => s.severity === "CRITICAL");
252
- const body = skills.map((s) => `${s.key} (${s.severity})`).join("\n");
253
- enqueueToast(`${branding.name} detected ${skills.length} malicious/suspicious skill(s):\n${body}`, hasCritical ? "error" : "warning", STARTUP_SUMMARY_DURATION_MS);
254
- }
255
- catch (e) {
256
- logger.debug("Skill summary popup failed", { error: String(e) });
257
- }
258
- };
259
- // Set up the cron job that cleans up the approval store.
260
- const interval = setInterval(() => {
261
- approvalStore.cleanup();
262
- }, APPROVAL_STORE_CLEANUP_INTERVAL_MS);
263
- interval.unref?.();
264
- const toolHandlers = createToolHandlers(toolLogger, approvalStore, threatsDir, trustedDomainsDir, { showToast }, branding);
265
- /**
266
- * Run the session scan exactly once per session and cache the promise. The
267
- * cached promise is the dedupe guard — a second call (repeated
268
- * `session.updated`, or another plugin instance) returns the same
269
- * in-flight/settled promise instead of re-scanning. The scan's structured
270
- * findings drive the summary popup (see `surfaceStartupSummary`).
271
- */
272
- const scanSession = (sessionID) => {
273
- if (sessionID === "unknown")
274
- return Promise.resolve();
275
- const existing = sessionScanPromises.get(sessionID);
276
- if (existing)
277
- return existing;
278
- const promise = (async () => {
279
- logger.debug(`${branding.name}: starting session scan`, { sessionID });
280
- const scanHandler = createSessionScanHandler(scanLogger, directory,
281
- // After the scan (TUI ready): summary popup from the structured findings.
282
- surfaceStartupSummary, branding,
283
- // One-time notices (e.g. skill-upload consent) as info toasts.
284
- (noticeIds) => {
285
- for (const id of noticeIds) {
286
- const text = formatNoticeById(id, branding);
287
- if (text)
288
- enqueueToast(text, "info", STARTUP_SUMMARY_DURATION_MS);
289
- }
290
- });
291
- await scanHandler();
292
- })();
293
- sessionScanPromises.set(sessionID, promise);
294
- return promise;
295
25
  };
26
+ const sage = await createSageController({ directory, createNotifier, host: "v1" });
296
27
  return {
297
28
  /**
298
29
  * Register the Sage MCP server so sage_report_false_positive /
299
30
  * sage_list_audit_entries are available as agent tools. OpenCode runs
300
31
  * config hooks before MCP init, so mutating cfg.mcp here is sufficient.
301
- * ??= ensures a user-supplied override in opencode.json is never clobbered.
32
+ * A user-supplied `sage` entry in opencode.json is never clobbered.
302
33
  */
303
34
  config: async (cfg) => {
304
- const dir = dirname(fileURLToPath(import.meta.url));
305
- const serverPath = join(dir, "mcp-server.cjs");
306
35
  // biome-ignore lint/suspicious/noExplicitAny: OpenCode Config.mcp types not exported
307
36
  const mcp = cfg.mcp;
308
- if (mcp?.sage)
37
+ if (mcp?.[SAGE_MCP_SERVER_NAME])
309
38
  return;
310
39
  // biome-ignore lint/suspicious/noExplicitAny: assigning McpLocalConfig without importing its type
311
40
  cfg.mcp = {
312
41
  ...mcp,
313
- sage: {
314
- type: "local",
315
- command: [process.execPath, serverPath],
316
- environment: { BUN_BE_BUN: "1", SAGE_AGENT_RUNTIME: "opencode" },
317
- enabled: true,
318
- },
42
+ [SAGE_MCP_SERVER_NAME]: { ...sageMcpServerConfig(), enabled: true },
319
43
  };
320
44
  },
321
- "tool.execute.before": toolHandlers["tool.execute.before"],
45
+ "tool.execute.before": sage.beforeToolUse,
322
46
  // Run the session scan on the first session.updated event. It discovers
323
47
  // skills, populates the verdict cache, and (post-scan, once the TUI is up)
324
48
  // shows the summary popup. OpenCode >=1.3 replaced session.created with
@@ -329,46 +53,38 @@ export const SagePlugin = async ({ client, directory }) => {
329
53
  // biome-ignore lint/suspicious/noExplicitAny: Event types from SDK not fully typed
330
54
  const props = event.properties;
331
55
  const sessionID = props?.sessionID ?? props?.info?.id ?? "unknown";
332
- await scanSession(sessionID);
56
+ await sage.scanSession(sessionID);
333
57
  },
334
58
  tool: {
335
59
  sage_approve: tool({
336
- description: `Review a ${branding.name}-flagged tool call. Shows a native approval dialog to the user. Call this immediately when ${branding.name} flags an action — do NOT ask the user in chat first.`,
60
+ description: sage.approveToolDescription,
337
61
  args: {
338
- actionId: tool.schema
339
- .string()
340
- .describe(`Action ID from ${branding.name} flagged message`),
62
+ actionId: tool.schema.string().describe(sage.approveArgDescription),
341
63
  },
342
64
  async execute(args, context) {
343
- const pending = approvalStore.getPending(args.actionId);
344
- if (!pending) {
345
- return `No pending ${branding.name} approval found for this action ID.`;
346
- }
347
- try {
65
+ return sage.resolveApproval(args.actionId, async (pending) => {
348
66
  // "doom_loop" is the only permission OpenCode always gates with an ask dialog,
349
67
  // bypassing wildcard `*: allow` defaults. If OpenCode changes this, the dialog silently stops appearing.
350
68
  await context.ask({
351
69
  permission: "doom_loop",
352
- patterns: pending.artifacts.map((a) => `[${a.type}] ${a.value}`),
70
+ patterns: approvalPatterns(pending),
353
71
  always: [],
354
72
  metadata: {},
355
73
  });
356
- }
357
- catch (error) {
358
- logger.debug(`${branding.name}: approval dialog failed`, {
359
- actionId: args.actionId,
360
- error: String(error),
361
- });
362
- approvalStore.deletePending(args.actionId);
363
- logger.debug("OpenCode approval rejected", { actionId: args.actionId });
364
- return "Rejected by user.";
365
- }
366
- logger.info("OpenCode approval accepted", { actionId: args.actionId });
367
- return approveAction(approvalStore, args.actionId, branding);
74
+ });
368
75
  },
369
76
  }),
370
77
  },
371
78
  };
372
79
  };
373
- export default SagePlugin;
80
+ /**
81
+ * Dual-host plugin definition: `server` for OpenCode v1, `setup` for v2,
82
+ * both behind the same stable `id`.
83
+ */
84
+ const sagePluginModule = {
85
+ id: SAGE_PLUGIN_ID,
86
+ server: SagePlugin,
87
+ setup: setupV2,
88
+ };
89
+ export default sagePluginModule;
374
90
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -4241,7 +4241,7 @@ var init_zod = __esm({
4241
4241
  });
4242
4242
 
4243
4243
  // ../core/dist/types.js
4244
- var nullLogger, ArtifactTypeSchema, ArtifactSchema, VerdictSeveritySchema, ThreatSchema, DecisionSchema, SensitivitySchema, UrlCheckConfigSchema, CacheConfigSchema, LoggingConfigSchema, OperationalLogLevelSchema, OperationalLoggingConfigSchema, FileCheckConfigSchema, PackageCheckConfigSchema, AmsiCheckConfigSchema, SkillCheckConfigSchema, PiCheckConfigSchema, ExceptionDecisionSchema, ExceptionMatchSchema, ExceptionRuleSchema, ExceptionsFileSchema, ExceptionsConfigSchema, ConfigSchema, HookTypeSchema;
4244
+ var nullLogger, ArtifactTypeSchema, ArtifactSchema, VerdictSeveritySchema, ThreatSchema, DecisionSchema, SensitivitySchema, UrlCheckConfigSchema, CacheConfigSchema, LoggingConfigSchema, OperationalLogLevelSchema, OperationalLoggingConfigSchema, FileCheckConfigSchema, PackageCheckConfigSchema, AmsiCheckConfigSchema, SkillCheckConfigSchema, DEFAULT_PI_MEDIUM_RISK_THRESHOLD, PiCheckConfigSchema, ExceptionDecisionSchema, ExceptionMatchSchema, ExceptionRuleSchema, ExceptionsFileSchema, ExceptionsConfigSchema, ConfigSchema, HookTypeSchema;
4245
4245
  var init_types2 = __esm({
4246
4246
  "../core/dist/types.js"() {
4247
4247
  "use strict";
@@ -4330,6 +4330,7 @@ var init_types2 = __esm({
4330
4330
  */
4331
4331
  upload_enabled: external_exports.boolean().default(true)
4332
4332
  });
4333
+ DEFAULT_PI_MEDIUM_RISK_THRESHOLD = 0.5;
4333
4334
  PiCheckConfigSchema = external_exports.object({
4334
4335
  enabled: external_exports.boolean().default(false),
4335
4336
  max_content_length: external_exports.number().default(16384),
@@ -20593,7 +20594,11 @@ function safeTruncate(value, maxLen) {
20593
20594
  return value.slice(0, cutIndex);
20594
20595
  }
20595
20596
 
20597
+ // ../core/dist/model-storage.js
20598
+ init_config();
20599
+
20596
20600
  // ../core/dist/detection-names.js
20601
+ init_types2();
20597
20602
  var REPORTING_ENGINE_SHORTHANDS = {
20598
20603
  package: "sgpk",
20599
20604
  amsi: "sgam",
@@ -20876,7 +20881,7 @@ init_file_utils();
20876
20881
  var import_meta = {};
20877
20882
  function resolveVersion() {
20878
20883
  if (true)
20879
- return "0.14.0";
20884
+ return "0.15.0";
20880
20885
  try {
20881
20886
  const pkgPath = (0, import_node_path4.join)((0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
20882
20887
  const pkg = JSON.parse(getFileContentSync(pkgPath));
@@ -20888,9 +20893,6 @@ function resolveVersion() {
20888
20893
  }
20889
20894
  var VERSION = resolveVersion();
20890
20895
 
20891
- // ../core/dist/model-storage.js
20892
- init_config();
20893
-
20894
20896
  // ../core/dist/clients/model-downloader.js
20895
20897
  init_types2();
20896
20898
  var STALE_LOCK_MS = 60 * 60 * 1e3;
@@ -21214,6 +21216,12 @@ init_types2();
21214
21216
  // ../core/dist/evaluator.js
21215
21217
  init_config();
21216
21218
 
21219
+ // ../core/dist/extractors.js
21220
+ var MAX_CONTENT_SIZE = 64 * 1024;
21221
+
21222
+ // ../core/dist/deobfuscate.js
21223
+ var REPLACEMENT_CHAR = String.fromCharCode(65533);
21224
+
21217
21225
  // ../core/dist/exceptions.js
21218
21226
  init_config();
21219
21227
  init_file_utils();
@@ -21226,9 +21234,6 @@ init_types2();
21226
21234
  // ../core/dist/exceptions.js
21227
21235
  init_types2();
21228
21236
 
21229
- // ../core/dist/extractors.js
21230
- var MAX_CONTENT_SIZE = 64 * 1024;
21231
-
21232
21237
  // ../core/dist/package-checker.js
21233
21238
  init_types2();
21234
21239
 
@@ -21236,17 +21241,43 @@ init_types2();
21236
21241
  init_config();
21237
21242
  init_file_utils();
21238
21243
 
21244
+ // ../core/dist/submit-limits.js
21245
+ init_config();
21246
+ init_file_utils();
21247
+ init_types2();
21248
+ var SUBMIT_WINDOW_MS = 24 * 60 * 60 * 1e3;
21249
+
21239
21250
  // ../core/dist/threat-loader.js
21240
21251
  var import_yaml2 = __toESM(require_dist(), 1);
21252
+ init_config();
21241
21253
  init_file_utils();
21242
21254
  init_types2();
21243
21255
 
21244
21256
  // ../core/dist/evaluator.js
21245
21257
  init_types2();
21258
+ function hasReportableDetectionSignals(value) {
21259
+ if (!value || typeof value !== "object" || Array.isArray(value))
21260
+ return false;
21261
+ const signals = value;
21262
+ const hasEntries = (key) => {
21263
+ const entries = signals[key];
21264
+ return Array.isArray(entries) && entries.length > 0;
21265
+ };
21266
+ return Boolean(hasEntries("heuristics") || hasEntries("url_checks") || hasEntries("file_checks") || hasEntries("package_checks") || hasEntries("amsi_checks") || Array.isArray(signals.pi_checks) && signals.pi_checks.some((result) => {
21267
+ if (!result || typeof result !== "object" || Array.isArray(result))
21268
+ return false;
21269
+ const risk = result.risk;
21270
+ return typeof risk === "number" && Number.isFinite(risk) && risk >= DEFAULT_PI_MEDIUM_RISK_THRESHOLD;
21271
+ }));
21272
+ }
21246
21273
 
21247
21274
  // ../core/dist/index.js
21248
21275
  init_file_utils();
21249
21276
 
21277
+ // ../core/dist/format.js
21278
+ var FP_REPORT_TOOL_NAME = "sage_report_false_positive";
21279
+ var SESSION_START_FP_HINT = `If this is a false positive, ask your agent to report it with the ${FP_REPORT_TOOL_NAME} MCP tool.`;
21280
+
21250
21281
  // ../core/dist/guard.js
21251
21282
  init_config();
21252
21283
  init_types2();
@@ -31641,7 +31672,8 @@ function readContentSnippet(entry) {
31641
31672
  function isRuntimeVerdictEntry(v) {
31642
31673
  if (!v || typeof v !== "object" || Array.isArray(v))
31643
31674
  return false;
31644
- return v.type === "runtime_verdict";
31675
+ const entry = v;
31676
+ return entry.type === "runtime_verdict" && (entry.custom_threat_matched !== true || entry.non_custom_detection_matched === true || hasReportableDetectionSignals(parseRuntimeAuditSignals(entry.signals)));
31645
31677
  }
31646
31678
  function isAnalyzedSkillVerdictEntry(v) {
31647
31679
  if (!v || typeof v !== "object" || Array.isArray(v))
@@ -32192,7 +32224,7 @@ async function main() {
32192
32224
  );
32193
32225
  const branding = resolveBranding(config2.brand_key, logger);
32194
32226
  await runSageMcpServerStdio({
32195
- version: "0.14.0",
32227
+ version: "0.15.0",
32196
32228
  logger,
32197
32229
  branding
32198
32230
  });