network-ai 5.12.6 → 5.13.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.
Files changed (78) hide show
  1. package/INTEGRATION_GUIDE.md +2 -2
  2. package/README.md +59 -3
  3. package/SKILL.md +5 -3
  4. package/dist/adapters/anthropic-messages-adapter.d.ts +141 -0
  5. package/dist/adapters/anthropic-messages-adapter.d.ts.map +1 -0
  6. package/dist/adapters/anthropic-messages-adapter.js +218 -0
  7. package/dist/adapters/anthropic-messages-adapter.js.map +1 -0
  8. package/dist/adapters/index.d.ts +2 -0
  9. package/dist/adapters/index.d.ts.map +1 -1
  10. package/dist/adapters/index.js +6 -1
  11. package/dist/adapters/index.js.map +1 -1
  12. package/dist/esm/adapters/anthropic-messages-adapter.js +218 -0
  13. package/dist/esm/adapters/anthropic-messages-adapter.js.map +1 -0
  14. package/dist/esm/adapters/index.js +6 -1
  15. package/dist/esm/adapters/index.js.map +1 -1
  16. package/dist/esm/index.js +30 -1
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/lib/effort-policy.js +107 -0
  19. package/dist/esm/lib/effort-policy.js.map +1 -0
  20. package/dist/esm/lib/fan-out.js +47 -14
  21. package/dist/esm/lib/fan-out.js.map +1 -1
  22. package/dist/esm/lib/goal-decomposer.js +79 -10
  23. package/dist/esm/lib/goal-decomposer.js.map +1 -1
  24. package/dist/esm/lib/model-budget.js +167 -0
  25. package/dist/esm/lib/model-budget.js.map +1 -0
  26. package/dist/esm/lib/model-gateway.js +243 -0
  27. package/dist/esm/lib/model-gateway.js.map +1 -0
  28. package/dist/esm/lib/owasp-compliance.js +167 -0
  29. package/dist/esm/lib/owasp-compliance.js.map +1 -0
  30. package/dist/esm/lib/retry-budget.js +75 -0
  31. package/dist/esm/lib/retry-budget.js.map +1 -0
  32. package/dist/esm/lib/telemetry-provider.js +109 -1
  33. package/dist/esm/lib/telemetry-provider.js.map +1 -1
  34. package/dist/esm/lib/thinking-blocks.js +106 -0
  35. package/dist/esm/lib/thinking-blocks.js.map +1 -0
  36. package/dist/index.d.ts +16 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +30 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/lib/effort-policy.d.ts +88 -0
  41. package/dist/lib/effort-policy.d.ts.map +1 -0
  42. package/dist/lib/effort-policy.js +107 -0
  43. package/dist/lib/effort-policy.js.map +1 -0
  44. package/dist/lib/fan-out.d.ts +17 -0
  45. package/dist/lib/fan-out.d.ts.map +1 -1
  46. package/dist/lib/fan-out.js +47 -14
  47. package/dist/lib/fan-out.js.map +1 -1
  48. package/dist/lib/goal-decomposer.d.ts +18 -0
  49. package/dist/lib/goal-decomposer.d.ts.map +1 -1
  50. package/dist/lib/goal-decomposer.js +79 -10
  51. package/dist/lib/goal-decomposer.js.map +1 -1
  52. package/dist/lib/model-budget.d.ts +144 -0
  53. package/dist/lib/model-budget.d.ts.map +1 -0
  54. package/dist/lib/model-budget.js +167 -0
  55. package/dist/lib/model-budget.js.map +1 -0
  56. package/dist/lib/model-gateway.d.ts +252 -0
  57. package/dist/lib/model-gateway.d.ts.map +1 -0
  58. package/dist/lib/model-gateway.js +243 -0
  59. package/dist/lib/model-gateway.js.map +1 -0
  60. package/dist/lib/owasp-compliance.d.ts +57 -0
  61. package/dist/lib/owasp-compliance.d.ts.map +1 -0
  62. package/dist/lib/owasp-compliance.js +167 -0
  63. package/dist/lib/owasp-compliance.js.map +1 -0
  64. package/dist/lib/retry-budget.d.ts +51 -0
  65. package/dist/lib/retry-budget.d.ts.map +1 -0
  66. package/dist/lib/retry-budget.js +75 -0
  67. package/dist/lib/retry-budget.js.map +1 -0
  68. package/dist/lib/telemetry-provider.d.ts +72 -0
  69. package/dist/lib/telemetry-provider.d.ts.map +1 -1
  70. package/dist/lib/telemetry-provider.js +109 -1
  71. package/dist/lib/telemetry-provider.js.map +1 -1
  72. package/dist/lib/thinking-blocks.d.ts +77 -0
  73. package/dist/lib/thinking-blocks.d.ts.map +1 -0
  74. package/dist/lib/thinking-blocks.js +106 -0
  75. package/dist/lib/thinking-blocks.js.map +1 -0
  76. package/package.json +3 -2
  77. package/scripts/clawhub-check.js +176 -0
  78. package/socket.json +8 -0
@@ -163,4 +163,76 @@ export declare class CapturingTelemetryProvider implements ITelemetryProvider {
163
163
  * semantics of `StreamingBaseAdapter`.
164
164
  */
165
165
  export declare function createOtelHooks(provider: ITelemetryProvider): ExecutionHook[];
166
+ /** Span/event name emitted for a classifier refusal. */
167
+ export declare const REFUSAL_EVENT = "model.refusal";
168
+ /** Span/event name emitted when a fallback model serves a turn. */
169
+ export declare const FALLBACK_SERVED_EVENT = "model.fallback_served";
170
+ /** Argument to {@link RefusalTelemetry.recordRefusal}. */
171
+ export interface RefusalEventInfo {
172
+ model: string;
173
+ category: string | null;
174
+ agentId?: string;
175
+ }
176
+ /** Argument to {@link RefusalTelemetry.recordFallbackServed}. */
177
+ export interface FallbackServedInfo {
178
+ requestedModel: string;
179
+ servedModel: string;
180
+ agentId?: string;
181
+ }
182
+ /** Point-in-time counters from {@link RefusalTelemetry.snapshot}. */
183
+ export interface RefusalSnapshot {
184
+ refusals: number;
185
+ fallbackServed: number;
186
+ /** Refusals never served by a fallback — the gap to alert on. */
187
+ unservedRefusals: number;
188
+ byCategory: Record<string, number>;
189
+ byModel: Record<string, number>;
190
+ }
191
+ /**
192
+ * Refusal/fallback observability.
193
+ *
194
+ * A classifier refusal is a successful **HTTP 200**, so monitoring built on
195
+ * error rates or 5xx responses never sees it. `RefusalTelemetry` records each
196
+ * refusal and each fallback-served response as discrete **non-error** signals,
197
+ * keeps counters, and exposes the gap between them (`unservedRefusalCount`) so
198
+ * you can alert when refusals are not being served by a fallback.
199
+ *
200
+ * It satisfies the `RefusalTelemetrySink` contract consumed by
201
+ * {@link ../lib/model-gateway!GovernedModelGateway}. Pass an
202
+ * {@link ITelemetryProvider} to also emit spans to your tracing backend.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const refusals = new RefusalTelemetry(new CapturingTelemetryProvider());
207
+ * const gateway = new GovernedModelGateway({ caller, primaryModel, fallbackModels, telemetry: refusals });
208
+ * // ...later
209
+ * if (refusals.unservedRefusalCount > 0) alert('refusals are reaching users');
210
+ * ```
211
+ */
212
+ export declare class RefusalTelemetry {
213
+ private readonly provider;
214
+ private _refusals;
215
+ private _fallbackServed;
216
+ private readonly _byCategory;
217
+ private readonly _byModel;
218
+ constructor(provider?: ITelemetryProvider);
219
+ /** Record a classifier refusal (counted as a signal, never as an error). */
220
+ recordRefusal(info: RefusalEventInfo): void;
221
+ /** Record that a fallback model served a turn the primary declined. */
222
+ recordFallbackServed(info: FallbackServedInfo): void;
223
+ /** Total refusals observed. */
224
+ get refusalCount(): number;
225
+ /** Total fallback-served responses observed. */
226
+ get fallbackServedCount(): number;
227
+ /** Refusals that were never served by a fallback (the gap to alert on). */
228
+ get unservedRefusalCount(): number;
229
+ /** Refusal counts keyed by classifier category. */
230
+ byCategory(): Record<string, number>;
231
+ /** A full counter snapshot. */
232
+ snapshot(): RefusalSnapshot;
233
+ /** Reset all counters. */
234
+ reset(): void;
235
+ /** Emit a discrete non-error span for a refusal/fallback signal. @internal */
236
+ private emit;
237
+ }
166
238
  //# sourceMappingURL=telemetry-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-provider.d.ts","sourceRoot":"","sources":["../../lib/telemetry-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AAMlE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACtD;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC;IACxB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,cAAc,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzE;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAE7D;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,OAAO,EAAE,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAEnF;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CAC9E;AAMD;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,kBAAkB;IAClB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,MAAM;IAC9D,kBAAkB;IAClB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,OAAO,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI;IACrF,kBAAkB;IAClB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI;CAChF;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,0BAA2B,YAAW,kBAAkB;IACnE,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAM;IACpC,OAAO,CAAC,OAAO,CAAK;IAEpB,kBAAkB;IAClB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,cAAmB,GAAG,MAAM;IAMhE,kBAAkB;IAClB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,OAAO,EAAE,UAAU,GAAE,cAAmB,GAAG,IAAI;IAQtF,kBAAkB;IAClB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,cAAmB,GAAG,IAAI;IAMhF,sDAAsD;IACtD,KAAK,IAAI,IAAI;CAId;AASD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,kBAAkB,GAAG,aAAa,EAAE,CAyD7E"}
1
+ {"version":3,"file":"telemetry-provider.d.ts","sourceRoot":"","sources":["../../lib/telemetry-provider.ts"],"names":[],"mappings":"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"}
@@ -48,7 +48,7 @@
48
48
  * ```
49
49
  */
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
- exports.CapturingTelemetryProvider = exports.NullTelemetryProvider = void 0;
51
+ exports.RefusalTelemetry = exports.FALLBACK_SERVED_EVENT = exports.REFUSAL_EVENT = exports.CapturingTelemetryProvider = exports.NullTelemetryProvider = void 0;
52
52
  exports.createOtelHooks = createOtelHooks;
53
53
  // ============================================================================
54
54
  // NULL PROVIDER (default — zero overhead when no telemetry is configured)
@@ -204,4 +204,112 @@ function createOtelHooks(provider) {
204
204
  },
205
205
  ];
206
206
  }
207
+ // ============================================================================
208
+ // REFUSAL OBSERVABILITY
209
+ // ============================================================================
210
+ /** Span/event name emitted for a classifier refusal. */
211
+ exports.REFUSAL_EVENT = 'model.refusal';
212
+ /** Span/event name emitted when a fallback model serves a turn. */
213
+ exports.FALLBACK_SERVED_EVENT = 'model.fallback_served';
214
+ /**
215
+ * Refusal/fallback observability.
216
+ *
217
+ * A classifier refusal is a successful **HTTP 200**, so monitoring built on
218
+ * error rates or 5xx responses never sees it. `RefusalTelemetry` records each
219
+ * refusal and each fallback-served response as discrete **non-error** signals,
220
+ * keeps counters, and exposes the gap between them (`unservedRefusalCount`) so
221
+ * you can alert when refusals are not being served by a fallback.
222
+ *
223
+ * It satisfies the `RefusalTelemetrySink` contract consumed by
224
+ * {@link ../lib/model-gateway!GovernedModelGateway}. Pass an
225
+ * {@link ITelemetryProvider} to also emit spans to your tracing backend.
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * const refusals = new RefusalTelemetry(new CapturingTelemetryProvider());
230
+ * const gateway = new GovernedModelGateway({ caller, primaryModel, fallbackModels, telemetry: refusals });
231
+ * // ...later
232
+ * if (refusals.unservedRefusalCount > 0) alert('refusals are reaching users');
233
+ * ```
234
+ */
235
+ class RefusalTelemetry {
236
+ provider;
237
+ _refusals = 0;
238
+ _fallbackServed = 0;
239
+ _byCategory = new Map();
240
+ _byModel = new Map();
241
+ constructor(provider) {
242
+ this.provider = provider;
243
+ }
244
+ /** Record a classifier refusal (counted as a signal, never as an error). */
245
+ recordRefusal(info) {
246
+ this._refusals++;
247
+ const cat = info.category ?? 'unspecified';
248
+ this._byCategory.set(cat, (this._byCategory.get(cat) ?? 0) + 1);
249
+ this._byModel.set(info.model, (this._byModel.get(info.model) ?? 0) + 1);
250
+ this.emit(exports.REFUSAL_EVENT, { model: info.model, category: cat, agentId: info.agentId ?? '' });
251
+ }
252
+ /** Record that a fallback model served a turn the primary declined. */
253
+ recordFallbackServed(info) {
254
+ this._fallbackServed++;
255
+ this.emit(exports.FALLBACK_SERVED_EVENT, {
256
+ requestedModel: info.requestedModel,
257
+ servedModel: info.servedModel,
258
+ agentId: info.agentId ?? '',
259
+ });
260
+ }
261
+ /** Total refusals observed. */
262
+ get refusalCount() {
263
+ return this._refusals;
264
+ }
265
+ /** Total fallback-served responses observed. */
266
+ get fallbackServedCount() {
267
+ return this._fallbackServed;
268
+ }
269
+ /** Refusals that were never served by a fallback (the gap to alert on). */
270
+ get unservedRefusalCount() {
271
+ return Math.max(0, this._refusals - this._fallbackServed);
272
+ }
273
+ /** Refusal counts keyed by classifier category. */
274
+ byCategory() {
275
+ const out = {};
276
+ for (const [k, v] of this._byCategory)
277
+ out[k] = v;
278
+ return out;
279
+ }
280
+ /** A full counter snapshot. */
281
+ snapshot() {
282
+ const byModel = {};
283
+ for (const [k, v] of this._byModel)
284
+ byModel[k] = v;
285
+ return {
286
+ refusals: this._refusals,
287
+ fallbackServed: this._fallbackServed,
288
+ unservedRefusals: this.unservedRefusalCount,
289
+ byCategory: this.byCategory(),
290
+ byModel,
291
+ };
292
+ }
293
+ /** Reset all counters. */
294
+ reset() {
295
+ this._refusals = 0;
296
+ this._fallbackServed = 0;
297
+ this._byCategory.clear();
298
+ this._byModel.clear();
299
+ }
300
+ /** Emit a discrete non-error span for a refusal/fallback signal. @internal */
301
+ emit(name, attributes) {
302
+ if (!this.provider)
303
+ return;
304
+ try {
305
+ const id = this.provider.startSpan(name, attributes);
306
+ // A refusal is a successful HTTP 200 — close the span 'ok', never 'error'.
307
+ this.provider.endSpan(id, 'ok', attributes);
308
+ }
309
+ catch {
310
+ // Telemetry must never throw.
311
+ }
312
+ }
313
+ }
314
+ exports.RefusalTelemetry = RefusalTelemetry;
207
315
  //# sourceMappingURL=telemetry-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-provider.js","sourceRoot":"","sources":["../../lib/telemetry-provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;;;AAsKH,0CAyDC;AA5JD,+EAA+E;AAC/E,0EAA0E;AAC1E,+EAA+E;AAE/E;;;;GAIG;AACH,MAAa,qBAAqB;IAChC,kBAAkB;IAClB,SAAS,CAAC,KAAa,EAAE,WAA4B,IAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7E,kBAAkB;IAClB,OAAO,CAAC,OAAe,EAAE,OAAuB,EAAE,WAA4B,IAAS,CAAC;IACxF,kBAAkB;IAClB,WAAW,CAAC,OAAe,EAAE,KAAa,EAAE,WAA4B,IAAS,CAAC;CACnF;AAPD,sDAOC;AAED,+EAA+E;AAC/E,mCAAmC;AACnC,+EAA+E;AAE/E;;;;;;;;;;;;;GAaG;AACH,MAAa,0BAA0B;IACrC,8DAA8D;IACrD,KAAK,GAAmB,EAAE,CAAC;IAC5B,OAAO,GAAG,CAAC,CAAC;IAEpB,kBAAkB;IAClB,SAAS,CAAC,IAAY,EAAE,aAA6B,EAAE;QACrD,MAAM,MAAM,GAAG,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACpG,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,kBAAkB;IAClB,OAAO,CAAC,MAAc,EAAE,MAAsB,EAAE,aAA6B,EAAE;QAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED,kBAAkB;IAClB,WAAW,CAAC,MAAc,EAAE,IAAY,EAAE,aAA6B,EAAE;QACvE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,sDAAsD;IACtD,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IACnB,CAAC;CACF;AAjCD,gEAiCC;AAED,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,eAAe,CAAC,QAA4B;IAC1D,OAAO;QACL;YACE,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,GAAG;YACb,OAAO,CAAC,GAAgB;gBACtB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,iBAAiB,EAAE;wBACnD,OAAO,EAAE,GAAG,CAAC,OAAO;wBACpB,MAAM,EAAG,GAAG,CAAC,OAA+B,CAAC,MAAM,IAAI,EAAE;wBACzD,KAAK,EAAE,GAAG,CAAC,KAAK;qBACjB,CAAC,CAAC;oBACH,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC;gBAC1C,CAAC;gBAAC,MAAM,CAAC;oBACP,uCAAuC;gBACzC,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;SACF;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,cAAc;YACrB,QAAQ,EAAE,GAAG;YACb,OAAO,CAAC,GAAgB;gBACtB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAuB,CAAC;oBACpE,IAAI,MAAM,EAAE,CAAC;wBACX,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE;4BAC7B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;yBACtC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,QAAQ;gBACV,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;SACF;QACD;YACE,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,GAAG;YACb,OAAO,CAAC,GAAgB;gBACtB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAuB,CAAC;oBACpE,IAAI,MAAM,EAAE,CAAC;wBACX,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;4BAChC,YAAY,EAAG,GAAG,CAAC,KAA2B,EAAE,OAAO,IAAI,SAAS;yBACrE,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,QAAQ;gBACV,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"telemetry-provider.js","sourceRoot":"","sources":["../../lib/telemetry-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * ThinkingBlockManager — thinking-block lifecycle across model switches.
3
+ *
4
+ * Frontier models with always-on adaptive thinking return `thinking` blocks
5
+ * whose `signature` ties them to the producing model. Two rules follow:
6
+ *
7
+ * - **Same model, multi-turn:** pass thinking blocks back *unchanged* (the
8
+ * signature is validated server-side).
9
+ * - **Switching models (e.g. a refusal fallback):** *strip* `thinking` and
10
+ * `redacted_thinking` blocks from prior turns — another model ignores them
11
+ * but still bills them as input tokens.
12
+ *
13
+ * It also guards prompts against the `reasoning_extraction` refusal: asking a
14
+ * model to reproduce its internal reasoning as response text can be declined.
15
+ *
16
+ * Satisfies the `ThinkingSink` contract consumed by
17
+ * {@link ../lib/model-gateway!GovernedModelGateway}, which calls
18
+ * {@link ThinkingBlockManager.stripForModelSwitch} on a cross-model retry — but
19
+ * only when it is *not* redeeming a fallback credit (credit redemption requires
20
+ * an exact body match, so blocks stay).
21
+ *
22
+ * @module ThinkingBlockManager
23
+ * @version 1.0.0
24
+ * @license MIT
25
+ */
26
+ import type { ModelMessage } from './model-gateway';
27
+ /** Result of {@link ThinkingBlockManager.guardAgainstReasoningExtraction}. */
28
+ export interface ReasoningExtractionCheck {
29
+ /** Whether any reasoning-extraction phrasing was detected. */
30
+ flagged: boolean;
31
+ /** The matched substrings, for surfacing to the caller. */
32
+ matches: string[];
33
+ }
34
+ /**
35
+ * Manages thinking blocks across same-model turns and cross-model fallbacks.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const thinking = new ThinkingBlockManager();
40
+ * const gateway = new GovernedModelGateway({ caller, primaryModel, fallbackModels, thinking });
41
+ *
42
+ * // Guard a system prompt before sending it to a refusal-prone model:
43
+ * const check = thinking.guardAgainstReasoningExtraction(systemPrompt);
44
+ * if (check.flagged) console.warn('reasoning-extraction risk:', check.matches);
45
+ * ```
46
+ */
47
+ export declare class ThinkingBlockManager {
48
+ /**
49
+ * Strip model-bound thinking blocks from prior assistant turns before a
50
+ * cross-model retry. `fallback`, `text`, and tool blocks are preserved; only
51
+ * `thinking` / `redacted_thinking` blocks are removed. Messages whose content
52
+ * is not a block array are returned untouched.
53
+ *
54
+ * @param messages The conversation to clean.
55
+ * @returns A new array with model-bound blocks removed.
56
+ */
57
+ stripForModelSwitch(messages: ModelMessage[]): ModelMessage[];
58
+ /**
59
+ * Identity transform documenting the same-model rule: thinking blocks must be
60
+ * passed back **unchanged** when continuing on the same model.
61
+ *
62
+ * @param messages The conversation.
63
+ * @returns The same messages, unchanged.
64
+ */
65
+ preserveForSameModel(messages: ModelMessage[]): ModelMessage[];
66
+ /** Whether any message carries a model-bound thinking block. */
67
+ hasThinkingBlocks(messages: ModelMessage[]): boolean;
68
+ /**
69
+ * Detect prompt text that asks a model to reproduce its internal reasoning as
70
+ * response text — which can trigger a `reasoning_extraction` refusal. Read the
71
+ * structured `thinking` blocks instead of prompting for reasoning in the body.
72
+ *
73
+ * @param text The prompt or instruction to inspect.
74
+ */
75
+ guardAgainstReasoningExtraction(text: string): ReasoningExtractionCheck;
76
+ }
77
+ //# sourceMappingURL=thinking-blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinking-blocks.d.ts","sourceRoot":"","sources":["../../lib/thinking-blocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,iBAAiB,CAAC;AAavE,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAE/B;;;;;;;;OAQG;IACH,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE;IAU7D;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE;IAI9D,gEAAgE;IAChE,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO;IAMpD;;;;;;OAMG;IACH,+BAA+B,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB;CAUxE"}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * ThinkingBlockManager — thinking-block lifecycle across model switches.
4
+ *
5
+ * Frontier models with always-on adaptive thinking return `thinking` blocks
6
+ * whose `signature` ties them to the producing model. Two rules follow:
7
+ *
8
+ * - **Same model, multi-turn:** pass thinking blocks back *unchanged* (the
9
+ * signature is validated server-side).
10
+ * - **Switching models (e.g. a refusal fallback):** *strip* `thinking` and
11
+ * `redacted_thinking` blocks from prior turns — another model ignores them
12
+ * but still bills them as input tokens.
13
+ *
14
+ * It also guards prompts against the `reasoning_extraction` refusal: asking a
15
+ * model to reproduce its internal reasoning as response text can be declined.
16
+ *
17
+ * Satisfies the `ThinkingSink` contract consumed by
18
+ * {@link ../lib/model-gateway!GovernedModelGateway}, which calls
19
+ * {@link ThinkingBlockManager.stripForModelSwitch} on a cross-model retry — but
20
+ * only when it is *not* redeeming a fallback credit (credit redemption requires
21
+ * an exact body match, so blocks stay).
22
+ *
23
+ * @module ThinkingBlockManager
24
+ * @version 1.0.0
25
+ * @license MIT
26
+ */
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.ThinkingBlockManager = void 0;
29
+ /** Block types tied to the producing model — dropped on a model switch. */
30
+ const MODEL_BOUND_BLOCK_TYPES = new Set(['thinking', 'redacted_thinking']);
31
+ /** Phrases that ask a model to reproduce its internal reasoning as response text. */
32
+ const REASONING_EXTRACTION_PATTERNS = [
33
+ /\b(show|share|reveal|expose|print|output|reproduce|transcribe|echo|repeat)\b[^.?!]{0,40}\b(your|the)\b[^.?!]{0,20}\b(reasoning|thinking|thought process|chain[- ]of[- ]thought|inner monologue|scratchpad)\b/i,
34
+ /\b(explain|describe|walk me through|narrate)\b[^.?!]{0,30}\b(your|the)\b[^.?!]{0,20}\b(internal|raw|verbatim)\b[^.?!]{0,20}\b(reasoning|thinking|thoughts?)\b/i,
35
+ /\bthink(ing)?\b[^.?!]{0,20}\bout loud\b[^.?!]{0,30}\b(in|within|as part of)\b[^.?!]{0,20}\b(the )?(response|answer|output|final message)\b/i,
36
+ /\b(include|put|place)\b[^.?!]{0,20}\b(your|the)\b[^.?!]{0,20}\b(chain[- ]of[- ]thought|reasoning|thinking)\b[^.?!]{0,20}\bin\b[^.?!]{0,20}\b(the )?(response|answer|output)\b/i,
37
+ ];
38
+ /**
39
+ * Manages thinking blocks across same-model turns and cross-model fallbacks.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const thinking = new ThinkingBlockManager();
44
+ * const gateway = new GovernedModelGateway({ caller, primaryModel, fallbackModels, thinking });
45
+ *
46
+ * // Guard a system prompt before sending it to a refusal-prone model:
47
+ * const check = thinking.guardAgainstReasoningExtraction(systemPrompt);
48
+ * if (check.flagged) console.warn('reasoning-extraction risk:', check.matches);
49
+ * ```
50
+ */
51
+ class ThinkingBlockManager {
52
+ /**
53
+ * Strip model-bound thinking blocks from prior assistant turns before a
54
+ * cross-model retry. `fallback`, `text`, and tool blocks are preserved; only
55
+ * `thinking` / `redacted_thinking` blocks are removed. Messages whose content
56
+ * is not a block array are returned untouched.
57
+ *
58
+ * @param messages The conversation to clean.
59
+ * @returns A new array with model-bound blocks removed.
60
+ */
61
+ stripForModelSwitch(messages) {
62
+ return messages.map((msg) => {
63
+ if (!Array.isArray(msg.content))
64
+ return msg;
65
+ const blocks = msg.content;
66
+ const kept = blocks.filter((b) => !(b && typeof b === 'object' && MODEL_BOUND_BLOCK_TYPES.has(b.type)));
67
+ if (kept.length === blocks.length)
68
+ return msg;
69
+ return { ...msg, content: kept };
70
+ });
71
+ }
72
+ /**
73
+ * Identity transform documenting the same-model rule: thinking blocks must be
74
+ * passed back **unchanged** when continuing on the same model.
75
+ *
76
+ * @param messages The conversation.
77
+ * @returns The same messages, unchanged.
78
+ */
79
+ preserveForSameModel(messages) {
80
+ return messages;
81
+ }
82
+ /** Whether any message carries a model-bound thinking block. */
83
+ hasThinkingBlocks(messages) {
84
+ return messages.some((m) => Array.isArray(m.content) && m.content.some((b) => b && typeof b === 'object' && MODEL_BOUND_BLOCK_TYPES.has(b.type)));
85
+ }
86
+ /**
87
+ * Detect prompt text that asks a model to reproduce its internal reasoning as
88
+ * response text — which can trigger a `reasoning_extraction` refusal. Read the
89
+ * structured `thinking` blocks instead of prompting for reasoning in the body.
90
+ *
91
+ * @param text The prompt or instruction to inspect.
92
+ */
93
+ guardAgainstReasoningExtraction(text) {
94
+ const matches = [];
95
+ if (typeof text === 'string' && text.length > 0) {
96
+ for (const re of REASONING_EXTRACTION_PATTERNS) {
97
+ const m = text.match(re);
98
+ if (m && m[0])
99
+ matches.push(m[0].trim());
100
+ }
101
+ }
102
+ return { flagged: matches.length > 0, matches };
103
+ }
104
+ }
105
+ exports.ThinkingBlockManager = ThinkingBlockManager;
106
+ //# sourceMappingURL=thinking-blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinking-blocks.js","sourceRoot":"","sources":["../../lib/thinking-blocks.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAIH,2EAA2E;AAC3E,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAE3E,qFAAqF;AACrF,MAAM,6BAA6B,GAAa;IAC9C,+MAA+M;IAC/M,gKAAgK;IAChK,6IAA6I;IAC7I,gLAAgL;CACjL,CAAC;AAUF;;;;;;;;;;;;GAYG;AACH,MAAa,oBAAoB;IAE/B;;;;;;;;OAQG;IACH,mBAAmB,CAAC,QAAwB;QAC1C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,OAAO,GAAG,CAAC;YAC5C,MAAM,MAAM,GAAG,GAAG,CAAC,OAA8B,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxG,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;gBAAE,OAAO,GAAG,CAAC;YAC9C,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAwB;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gEAAgE;IAChE,iBAAiB,CAAC,QAAwB;QACxC,OAAO,QAAQ,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAK,CAAC,CAAC,OAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CACrJ,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,+BAA+B,CAAC,IAAY;QAC1C,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,KAAK,MAAM,EAAE,IAAI,6BAA6B,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;CACF;AAxDD,oDAwDC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "network-ai",
3
- "version": "5.12.6",
3
+ "version": "5.13.0",
4
4
  "description": "AI agent orchestration framework for TypeScript/Node.js - 29 adapters (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw, A2A, Codex, MiniMax, NemoClaw, APS, Copilot, LangGraph, Anthropic Computer Use, OpenAI Agents SDK, Vertex AI, Pydantic AI, Browser Agent, Hermes, Orchestrator, RLM + streaming variants). Built-in CLI, security, swarm intelligence, real-time streaming, and agentic workflow patterns.",
5
5
  "homepage": "https://network-ai.org",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,8 @@
72
72
  "revoke-token": "python scripts/revoke_token.py",
73
73
  "socket:check": "node scripts/socket-check.js",
74
74
  "socket:check:local": "node scripts/socket-check.js --local",
75
- "codeql:check": "node scripts/codeql-check.js"
75
+ "codeql:check": "node scripts/codeql-check.js",
76
+ "clawhub:check": "node scripts/clawhub-check.js"
76
77
  },
77
78
  "keywords": [
78
79
  "ai-agents",
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * clawhub-check.js — ClawHub bundle hygiene guard for network-ai
4
+ *
5
+ * Verifies that a `clawhub publish .` from the repo root would bundle ONLY the
6
+ * intended Python-skill files — no draft notes, secrets, logs, TypeScript/npm
7
+ * docs, or Node tooling.
8
+ *
9
+ * ClawHub honours `.clawhubignore` (gitignore-style denylist) — NOT `.clawignore`
10
+ * and NOT `.gitignore`. This script replicates that exclusion against the repo,
11
+ * then asserts the surviving set is exactly the allowlist below. Any extra file
12
+ * is a leak that SkillSpector (NVIDIA, run by ClawHub on every publish) will
13
+ * scan — so we fail BEFORE publishing, not after.
14
+ *
15
+ * Usage: node scripts/clawhub-check.js | npm run clawhub:check
16
+ * Exit: 0 = bundle clean 1 = leak, secret, or missing required file
17
+ */
18
+
19
+ 'use strict';
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ const ROOT = path.join(__dirname, '..');
25
+
26
+ // Files that SHOULD be in the published ClawHub skill bundle.
27
+ const ALLOW_FILES = new Set([
28
+ 'SKILL.md',
29
+ 'swarm-blackboard.md',
30
+ 'requirements.txt',
31
+ 'skill.json',
32
+ '.clawhubignore',
33
+ '.clawignore',
34
+ 'scripts/blackboard.py',
35
+ 'scripts/check_permission.py',
36
+ 'scripts/context_manager.py',
37
+ 'scripts/revoke_token.py',
38
+ 'scripts/swarm_guard.py',
39
+ 'scripts/validate_token.py',
40
+ ]);
41
+
42
+ // Directories allowed in the bundle (descended into for per-file checks).
43
+ const ALLOW_DIRS = new Set(['scripts']);
44
+
45
+ // Files that MUST be present (and not excluded) for the skill to function.
46
+ const REQUIRED = [
47
+ 'SKILL.md',
48
+ 'swarm-blackboard.md',
49
+ 'requirements.txt',
50
+ 'scripts/blackboard.py',
51
+ 'scripts/check_permission.py',
52
+ 'scripts/context_manager.py',
53
+ 'scripts/revoke_token.py',
54
+ 'scripts/swarm_guard.py',
55
+ 'scripts/validate_token.py',
56
+ ];
57
+
58
+ // Hard-deny: these must NEVER appear in a bundle, even if mis-allowlisted.
59
+ const SECRET_RE = /(^|\/)\.env(\.|$)|\.(log|pem|key|p12|pfx)$/i;
60
+
61
+ // Directories never walked (and excluded by .clawhubignore anyway).
62
+ const SKIP_DIRS = new Set(['.git', 'node_modules', 'dist']);
63
+
64
+ const c = {
65
+ reset: '\x1b[0m', bold: '\x1b[1m', red: '\x1b[31m',
66
+ green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m', gray: '\x1b[90m',
67
+ };
68
+
69
+ // ── Load .clawhubignore ──────────────────────────────────────────────────────
70
+
71
+ const ignPath = path.join(ROOT, '.clawhubignore');
72
+ if (!fs.existsSync(ignPath)) {
73
+ console.error(`${c.red}.clawhubignore not found — cannot verify bundle.${c.reset}`);
74
+ process.exit(1);
75
+ }
76
+ const patterns = fs.readFileSync(ignPath, 'utf8')
77
+ .split(/\r?\n/)
78
+ .map(l => l.trim())
79
+ .filter(l => l && !l.startsWith('#'));
80
+
81
+ /** Convert a simple glob (only `*` is special, no `/`) to an anchored RegExp. */
82
+ function globToRe(glob) {
83
+ let re = '';
84
+ for (const ch of glob) {
85
+ if (ch === '*') re += '[^/]*';
86
+ else re += ch.replace(/[.+^${}()|[\]\\?]/g, '\\$&');
87
+ }
88
+ return new RegExp('^' + re + '$');
89
+ }
90
+
91
+ /** Mirror .clawhubignore (gitignore-style) exclusion for one repo-relative path. */
92
+ function isExcluded(relPath, isDir) {
93
+ const base = relPath.split('/').pop();
94
+ for (const pat of patterns) {
95
+ const dirPat = pat.endsWith('/');
96
+ const core = dirPat ? pat.slice(0, -1) : pat;
97
+ if (core.includes('/')) {
98
+ // Full-path pattern (e.g. "scripts/*.js")
99
+ if (globToRe(core).test(relPath)) return true;
100
+ if (relPath.startsWith(core + '/')) return true;
101
+ } else {
102
+ // Basename pattern (e.g. "*.ts", "comment.txt", "assets/")
103
+ if (core === base || core === relPath) return true;
104
+ if (core.includes('*') && globToRe(core).test(base)) return true;
105
+ if (dirPat && isDir && core === base) return true;
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+
111
+ // ── Walk repo (root depth-1 + allowed subdirs) ───────────────────────────────
112
+
113
+ const bundle = [];
114
+ const leaks = [];
115
+
116
+ for (const name of fs.readdirSync(ROOT)) {
117
+ if (SKIP_DIRS.has(name)) continue;
118
+ const isDir = fs.statSync(path.join(ROOT, name)).isDirectory();
119
+
120
+ if (isExcluded(name, isDir)) continue;
121
+
122
+ if (isDir) {
123
+ if (ALLOW_DIRS.has(name)) {
124
+ for (const child of fs.readdirSync(path.join(ROOT, name))) {
125
+ const crel = `${name}/${child}`;
126
+ const cIsDir = fs.statSync(path.join(ROOT, name, child)).isDirectory();
127
+ if (isExcluded(crel, cIsDir)) continue;
128
+ bundle.push(crel);
129
+ if (!ALLOW_FILES.has(crel)) leaks.push(crel);
130
+ }
131
+ } else {
132
+ // A non-allowlisted directory survived exclusion → leak.
133
+ bundle.push(name + '/');
134
+ leaks.push(name + '/ (directory — exclude in .clawhubignore)');
135
+ }
136
+ } else {
137
+ bundle.push(name);
138
+ if (!ALLOW_FILES.has(name)) leaks.push(name);
139
+ }
140
+ }
141
+
142
+ // ── Report ───────────────────────────────────────────────────────────────────
143
+
144
+ console.log(`\n${c.bold}${c.cyan}ClawHub Bundle Hygiene Check${c.reset}`);
145
+ console.log(`${c.gray}${'─'.repeat(50)}${c.reset}`);
146
+ console.log(`Would publish ${bundle.length} item(s):`);
147
+ const leakSet = new Set(leaks.map(l => l.split(' ')[0]));
148
+ for (const b of [...bundle].sort()) {
149
+ const ok = !leakSet.has(b);
150
+ console.log(` ${ok ? c.green + '✓' + c.reset : c.red + '✗' + c.reset} ${b}`);
151
+ }
152
+
153
+ const secretLeaks = bundle.filter(b => SECRET_RE.test(b));
154
+ const missing = REQUIRED.filter(r => !fs.existsSync(path.join(ROOT, r)) || isExcluded(r, false));
155
+
156
+ console.log(`\n${c.gray}${'─'.repeat(50)}${c.reset}`);
157
+ let fail = false;
158
+
159
+ if (leaks.length) {
160
+ fail = true;
161
+ console.log(`${c.red}${c.bold}LEAK${c.reset} — ${leaks.length} unintended item(s) would be published:`);
162
+ for (const l of leaks) console.log(` ${c.red}• ${l}${c.reset}`);
163
+ console.log(` ${c.gray}Add each to .clawhubignore (or to ALLOW_FILES here if genuinely intended).${c.reset}`);
164
+ }
165
+ if (secretLeaks.length) {
166
+ fail = true;
167
+ console.log(`${c.red}${c.bold}SECRET${c.reset} — secret/log file(s) in bundle: ${secretLeaks.join(', ')}`);
168
+ }
169
+ if (missing.length) {
170
+ fail = true;
171
+ console.log(`${c.red}${c.bold}MISSING${c.reset} — required skill file(s) absent or excluded: ${missing.join(', ')}`);
172
+ }
173
+
174
+ if (fail) process.exit(1);
175
+ console.log(`${c.green}${c.bold}PASS${c.reset} — bundle contains only the intended Python-skill files.`);
176
+ process.exit(0);
package/socket.json CHANGED
@@ -417,6 +417,14 @@
417
417
  {
418
418
  "path": "dist/esm/run.js",
419
419
  "reason": "Intentional — ESM build output of run.ts. Same as dist/run.js — bootstraps the local orchestrator demo workflow when invoked directly by the operator."
420
+ },
421
+ {
422
+ "path": "scripts/socket-check.js",
423
+ "reason": "Intentional — dev/CI-only QA script. Uses child_process (spawnSync, shell:false) to invoke the Socket CLI via npx for supply-chain scanning. Never imported by the library and never executed by installing the package; runs only when a maintainer runs `npm run socket:check`."
424
+ },
425
+ {
426
+ "path": "scripts/codeql-check.js",
427
+ "reason": "Intentional — dev/CI-only QA script. Uses child_process (spawnSync, shell:false) to invoke the GitHub CLI (`gh api`) to query CodeQL code-scanning alerts. Never imported by the library and never executed by installing the package; runs only when a maintainer runs `npm run codeql:check`."
420
428
  }
421
429
  ],
422
430
  "filesystemAccess": [