@nathapp/nax 0.73.3 → 0.73.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.
Files changed (2) hide show
  1. package/dist/nax.js +368 -20
  2. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -17283,6 +17283,53 @@ var init_schemas_infra = __esm(() => {
17283
17283
  });
17284
17284
  });
17285
17285
 
17286
+ // src/config/schemas-reporters.ts
17287
+ var HeadersSchema, ReporterEventSchema, WebhookReporterConfigSchema, OtelReporterConfigSchema, ReportersConfigSchema;
17288
+ var init_schemas_reporters = __esm(() => {
17289
+ init_zod();
17290
+ HeadersSchema = exports_external.record(exports_external.string(), exports_external.string()).default({});
17291
+ ReporterEventSchema = exports_external.enum(["onRunStart", "onStoryComplete", "onRunEnd"]);
17292
+ WebhookReporterConfigSchema = exports_external.object({
17293
+ enabled: exports_external.boolean().default(false),
17294
+ url: exports_external.string().url().optional(),
17295
+ headers: HeadersSchema,
17296
+ events: exports_external.array(ReporterEventSchema).optional(),
17297
+ timeoutMs: exports_external.number().int().positive().default(5000)
17298
+ }).default({
17299
+ enabled: false,
17300
+ headers: {},
17301
+ timeoutMs: 5000
17302
+ });
17303
+ OtelReporterConfigSchema = exports_external.object({
17304
+ enabled: exports_external.boolean().default(false),
17305
+ endpoint: exports_external.string().url().optional(),
17306
+ headers: HeadersSchema,
17307
+ serviceName: exports_external.string().default("nax"),
17308
+ timeoutMs: exports_external.number().int().positive().default(5000)
17309
+ }).default({
17310
+ enabled: false,
17311
+ headers: {},
17312
+ serviceName: "nax",
17313
+ timeoutMs: 5000
17314
+ });
17315
+ ReportersConfigSchema = exports_external.object({
17316
+ webhook: WebhookReporterConfigSchema,
17317
+ otel: OtelReporterConfigSchema
17318
+ }).default({
17319
+ webhook: {
17320
+ enabled: false,
17321
+ headers: {},
17322
+ timeoutMs: 5000
17323
+ },
17324
+ otel: {
17325
+ enabled: false,
17326
+ headers: {},
17327
+ serviceName: "nax",
17328
+ timeoutMs: 5000
17329
+ }
17330
+ });
17331
+ });
17332
+
17286
17333
  // src/config/schemas-review.ts
17287
17334
  var SemanticReviewConfigSchema, AdversarialReviewConfigSchema, ReviewConfigSchema;
17288
17335
  var init_schemas_review = __esm(() => {
@@ -17369,6 +17416,7 @@ var init_schemas3 = __esm(() => {
17369
17416
  init_schemas_execution();
17370
17417
  init_schemas_infra();
17371
17418
  init_schemas_model();
17419
+ init_schemas_reporters();
17372
17420
  init_schemas_review();
17373
17421
  init_schemas_infra();
17374
17422
  init_schemas_review();
@@ -17739,6 +17787,7 @@ var init_schemas3 = __esm(() => {
17739
17787
  enabled: exports_external.boolean().default(false),
17740
17788
  draft: exports_external.boolean().default(true)
17741
17789
  }).optional().default({ enabled: false, draft: true }),
17790
+ reporters: ReportersConfigSchema,
17742
17791
  profile: exports_external.string().default("default"),
17743
17792
  profileChain: exports_external.array(exports_external.string()).default([])
17744
17793
  }).refine((data) => data.version === 1, {
@@ -38977,9 +39026,10 @@ var init_full_suite_rectify_op = __esm(() => {
38977
39026
  });
38978
39027
 
38979
39028
  // src/operations/full-suite-rectify.ts
38980
- function makeFullSuiteRectifyStrategy(story, config2, sink) {
38981
- const appliesTo = (finding) => finding.source === "test-runner" && (finding.category === "failed-test" || finding.category === "execution-failed");
39029
+ function makeFullSuiteRectifyStrategy(story, config2, sink, hasTestWriterDrainer) {
39030
+ const claimsFailingTest = (finding) => finding.source === "test-runner" && (finding.category === "failed-test" || finding.category === "execution-failed");
38982
39031
  if (sink) {
39032
+ const appliesTo = (finding) => claimsFailingTest(finding) && !(hasTestWriterDrainer === true && sink.mockHandoffs.length > 0);
38983
39033
  return {
38984
39034
  name: "full-suite-rectify",
38985
39035
  appliesTo,
@@ -39007,7 +39057,7 @@ function makeFullSuiteRectifyStrategy(story, config2, sink) {
39007
39057
  }
39008
39058
  return {
39009
39059
  name: "full-suite-rectify",
39010
- appliesTo,
39060
+ appliesTo: claimsFailingTest,
39011
39061
  fixOp: implementerOp,
39012
39062
  buildInput: (findings) => ({
39013
39063
  story,
@@ -41765,7 +41815,7 @@ var package_default;
41765
41815
  var init_package = __esm(() => {
41766
41816
  package_default = {
41767
41817
  name: "@nathapp/nax",
41768
- version: "0.73.3",
41818
+ version: "0.73.5",
41769
41819
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
41770
41820
  type: "module",
41771
41821
  bin: {
@@ -41866,8 +41916,8 @@ var init_version = __esm(() => {
41866
41916
  NAX_VERSION = package_default.version;
41867
41917
  NAX_COMMIT = (() => {
41868
41918
  try {
41869
- if (/^[0-9a-f]{6,10}$/.test("a98a211e"))
41870
- return "a98a211e";
41919
+ if (/^[0-9a-f]{6,10}$/.test("6aa6f9d9"))
41920
+ return "6aa6f9d9";
41871
41921
  } catch {}
41872
41922
  try {
41873
41923
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -57846,15 +57896,26 @@ function recordOscillations(store, storyId, delta) {
57846
57896
  function getOscillations(store, storyId) {
57847
57897
  return store.get(storyId) ?? 0;
57848
57898
  }
57899
+ function sourceSet(findings) {
57900
+ return new Set((Array.isArray(findings) ? findings : []).map((f) => f.source));
57901
+ }
57849
57902
  function countOscillationOutcomes(iterations) {
57903
+ const resolvedSources = new Set;
57850
57904
  let count = 0;
57851
57905
  for (const iteration of iterations) {
57852
- if (iteration.outcome === OSCILLATION_OUTCOME)
57853
- count += 1;
57906
+ const beforeSources = sourceSet(iteration.findingsBefore);
57907
+ const afterSources = sourceSet(iteration.findingsAfter);
57908
+ for (const source of afterSources) {
57909
+ if (resolvedSources.has(source))
57910
+ count += 1;
57911
+ }
57912
+ for (const source of beforeSources) {
57913
+ if (!afterSources.has(source))
57914
+ resolvedSources.add(source);
57915
+ }
57854
57916
  }
57855
57917
  return count;
57856
57918
  }
57857
- var OSCILLATION_OUTCOME = "regressed-different-source";
57858
57919
 
57859
57920
  // src/execution/checkpoint/resume-plan.ts
57860
57921
  function buildResumePlan(cp, current) {
@@ -58944,7 +59005,7 @@ async function buildPlanForStrategy(ctx, story, config2, testStrategy, inputs) {
58944
59005
  const fullSuiteGatePhasePresent = Boolean(inputs.fullSuiteGate) && (isThreeSession || regressionMode === "per-story");
58945
59006
  const verifyScopedPhasePresent = !isThreeSession && Boolean(inputs.verifyScoped);
58946
59007
  if (fullSuiteGatePhasePresent || verifyScopedPhasePresent) {
58947
- strategies.push(makeFullSuiteRectifyStrategy(story, config2, sink));
59008
+ strategies.push(makeFullSuiteRectifyStrategy(story, config2, sink, isThreeSession));
58948
59009
  }
58949
59010
  if (config2.quality.autofix?.enabled !== false) {
58950
59011
  strategies.push(makeAutofixImplementerStrategy(story, config2, sink, {
@@ -59014,7 +59075,8 @@ async function buildPlanForStrategy(ctx, story, config2, testStrategy, inputs) {
59014
59075
  promptSeverityFloor: "info"
59015
59076
  }));
59016
59077
  }
59017
- nbStrategies.push(makeFullSuiteRectifyStrategy(story, config2, nbSink));
59078
+ const nbHasTestWriterDrainer = isThreeSession && nbf.scope !== "source";
59079
+ nbStrategies.push(makeFullSuiteRectifyStrategy(story, config2, nbSink, nbHasTestWriterDrainer));
59018
59080
  const nbPostValidate = async (findings, validateCtx) => {
59019
59081
  if (nbSink.testEdits.length === 0 && nbSink.mockHandoffs.length === 0)
59020
59082
  return findings;
@@ -63422,6 +63484,264 @@ var init_curator = __esm(() => {
63422
63484
  };
63423
63485
  });
63424
63486
 
63487
+ // src/plugins/builtin/reporter-shared/interpolate.ts
63488
+ function interpolateHeaders(headers, env2 = process.env) {
63489
+ const resolved = {};
63490
+ const missing = new Set;
63491
+ for (const [key, value] of Object.entries(headers)) {
63492
+ resolved[key] = value.replace(ENV_PLACEHOLDER, (_match, name) => {
63493
+ const v = env2[name];
63494
+ if (v === undefined) {
63495
+ missing.add(name);
63496
+ return "";
63497
+ }
63498
+ return v;
63499
+ });
63500
+ }
63501
+ return { resolved, missing: [...missing] };
63502
+ }
63503
+ var ENV_PLACEHOLDER;
63504
+ var init_interpolate = __esm(() => {
63505
+ ENV_PLACEHOLDER = /\$\{([A-Z0-9_]+)\}/g;
63506
+ });
63507
+
63508
+ // src/plugins/builtin/reporter-shared/post-json.ts
63509
+ async function postJson(url2, body, opts) {
63510
+ const deps = opts.deps ?? _postJsonDeps;
63511
+ const logger = getSafeLogger();
63512
+ try {
63513
+ const res = await deps.fetch(url2, {
63514
+ method: "POST",
63515
+ headers: { "Content-Type": "application/json", ...opts.headers },
63516
+ body: JSON.stringify(body),
63517
+ signal: AbortSignal.timeout(opts.timeoutMs)
63518
+ });
63519
+ if (!res.ok) {
63520
+ logger?.warn(opts.stage, "Telemetry POST returned non-2xx", { url: url2, status: res.status });
63521
+ return false;
63522
+ }
63523
+ return true;
63524
+ } catch (err) {
63525
+ logger?.warn(opts.stage, "Telemetry POST failed", { url: url2, error: errorMessage(err) });
63526
+ return false;
63527
+ }
63528
+ }
63529
+ var _postJsonDeps;
63530
+ var init_post_json = __esm(() => {
63531
+ init_logger2();
63532
+ _postJsonDeps = { fetch: globalThis.fetch };
63533
+ });
63534
+
63535
+ // src/plugins/builtin/reporter-shared/index.ts
63536
+ var init_reporter_shared = __esm(() => {
63537
+ init_interpolate();
63538
+ init_post_json();
63539
+ });
63540
+
63541
+ // src/plugins/builtin/otel-reporter/ids.ts
63542
+ function randomHex(bytes) {
63543
+ const arr = new Uint8Array(bytes);
63544
+ crypto.getRandomValues(arr);
63545
+ let out = "";
63546
+ for (const b of arr)
63547
+ out += b.toString(16).padStart(2, "0");
63548
+ return out;
63549
+ }
63550
+ var newTraceId = () => randomHex(16), newSpanId = () => randomHex(8);
63551
+
63552
+ // src/plugins/builtin/otel-reporter/otlp.ts
63553
+ function attr(key, value) {
63554
+ return typeof value === "number" ? { key, value: { doubleValue: value } } : { key, value: { stringValue: value } };
63555
+ }
63556
+ function msToUnixNano(ms) {
63557
+ return (BigInt(Math.round(ms)) * 1000000n).toString();
63558
+ }
63559
+ function buildTracesPayload(p) {
63560
+ const span = {
63561
+ traceId: p.traceId,
63562
+ spanId: p.spanId,
63563
+ name: "nax.run",
63564
+ kind: 1,
63565
+ startTimeUnixNano: p.startUnixNano,
63566
+ endTimeUnixNano: p.endUnixNano,
63567
+ attributes: [
63568
+ attr("feature", p.feature),
63569
+ attr("runId", p.runId),
63570
+ attr("stories.completed", p.storySummary.completed),
63571
+ attr("stories.failed", p.storySummary.failed),
63572
+ attr("stories.skipped", p.storySummary.skipped),
63573
+ attr("stories.paused", p.storySummary.paused),
63574
+ attr("cost.total", p.totalCost)
63575
+ ],
63576
+ events: p.events,
63577
+ status: { code: p.storySummary.failed > 0 ? 2 : 1 }
63578
+ };
63579
+ return {
63580
+ resourceSpans: [
63581
+ {
63582
+ resource: { attributes: [attr("service.name", p.serviceName)] },
63583
+ scopeSpans: [{ scope: { name: "nax" }, spans: [span] }]
63584
+ }
63585
+ ]
63586
+ };
63587
+ }
63588
+ function buildMetricsPayload(p) {
63589
+ const statusEntries = Object.entries(p.storySummary).filter(([, n]) => n > 0);
63590
+ const storiesSum = {
63591
+ name: "nax.stories.total",
63592
+ sum: {
63593
+ aggregationTemporality: 2,
63594
+ isMonotonic: true,
63595
+ dataPoints: statusEntries.map(([status, count]) => ({
63596
+ asInt: String(count),
63597
+ timeUnixNano: p.timeUnixNano,
63598
+ attributes: [attr("status", status)]
63599
+ }))
63600
+ }
63601
+ };
63602
+ const gauge = (name, value) => ({
63603
+ name,
63604
+ gauge: { dataPoints: [{ asDouble: value, timeUnixNano: p.timeUnixNano }] }
63605
+ });
63606
+ return {
63607
+ resourceMetrics: [
63608
+ {
63609
+ resource: { attributes: [attr("service.name", p.serviceName)] },
63610
+ scopeMetrics: [
63611
+ {
63612
+ scope: { name: "nax" },
63613
+ metrics: [storiesSum, gauge("nax.run.cost", p.totalCost), gauge("nax.run.duration_ms", p.totalDurationMs)]
63614
+ }
63615
+ ]
63616
+ }
63617
+ ]
63618
+ };
63619
+ }
63620
+
63621
+ // src/plugins/builtin/otel-reporter/index.ts
63622
+ function createOtelReporterPlugin(cfg, deps) {
63623
+ const states = new Map;
63624
+ const base = cfg.endpoint?.replace(/\/$/, "");
63625
+ const flush = async (st, endMs, e) => {
63626
+ if (!base)
63627
+ return;
63628
+ const { resolved, missing } = interpolateHeaders(cfg.headers);
63629
+ if (missing.length > 0) {
63630
+ getSafeLogger()?.warn(STAGE, "Skipping OTLP export \u2014 unresolved env vars", { missing });
63631
+ return;
63632
+ }
63633
+ const startUnixNano = msToUnixNano(st.startMs);
63634
+ const endUnixNano = msToUnixNano(endMs);
63635
+ const traces = buildTracesPayload({
63636
+ serviceName: cfg.serviceName,
63637
+ traceId: st.traceId,
63638
+ spanId: st.spanId,
63639
+ startUnixNano,
63640
+ endUnixNano,
63641
+ feature: st.feature,
63642
+ runId: e.runId,
63643
+ storySummary: e.storySummary,
63644
+ totalCost: e.totalCost,
63645
+ events: st.events
63646
+ });
63647
+ const metrics = buildMetricsPayload({
63648
+ serviceName: cfg.serviceName,
63649
+ runId: e.runId,
63650
+ timeUnixNano: endUnixNano,
63651
+ storySummary: e.storySummary,
63652
+ totalCost: e.totalCost,
63653
+ totalDurationMs: e.totalDurationMs
63654
+ });
63655
+ const opts = { headers: resolved, timeoutMs: cfg.timeoutMs, stage: STAGE, deps };
63656
+ await postJson(`${base}/v1/traces`, traces, opts);
63657
+ await postJson(`${base}/v1/metrics`, metrics, opts);
63658
+ };
63659
+ const reporter = {
63660
+ name: STAGE,
63661
+ async onRunStart(event) {
63662
+ states.set(event.runId, {
63663
+ traceId: newTraceId(),
63664
+ spanId: newSpanId(),
63665
+ startMs: Date.parse(event.startTime),
63666
+ feature: event.feature,
63667
+ events: []
63668
+ });
63669
+ },
63670
+ async onStoryComplete(event) {
63671
+ const st = states.get(event.runId);
63672
+ if (!st)
63673
+ return;
63674
+ st.events.push({
63675
+ timeUnixNano: msToUnixNano(st.startMs + event.runElapsedMs),
63676
+ name: "story.complete",
63677
+ attributes: [
63678
+ attr("storyId", event.storyId),
63679
+ attr("status", event.status),
63680
+ attr("cost", event.cost),
63681
+ attr("tier", event.tier),
63682
+ attr("testStrategy", event.testStrategy)
63683
+ ]
63684
+ });
63685
+ },
63686
+ async onRunEnd(event) {
63687
+ const existing = states.get(event.runId);
63688
+ const startMs = existing?.startMs ?? Date.now() - event.totalDurationMs;
63689
+ const st = existing ?? {
63690
+ traceId: newTraceId(),
63691
+ spanId: newSpanId(),
63692
+ startMs,
63693
+ feature: "",
63694
+ events: []
63695
+ };
63696
+ states.delete(event.runId);
63697
+ await flush(st, startMs + event.totalDurationMs, event);
63698
+ }
63699
+ };
63700
+ return {
63701
+ name: STAGE,
63702
+ version: "1.0.0",
63703
+ provides: ["reporter"],
63704
+ extensions: { reporter }
63705
+ };
63706
+ }
63707
+ var STAGE = "otel-reporter";
63708
+ var init_otel_reporter = __esm(() => {
63709
+ init_logger2();
63710
+ init_reporter_shared();
63711
+ });
63712
+
63713
+ // src/plugins/builtin/webhook-reporter/index.ts
63714
+ function createWebhookReporterPlugin(cfg, deps) {
63715
+ const enabledEvent = (event) => cfg.events === undefined || cfg.events.includes(event);
63716
+ const emit = async (type, data) => {
63717
+ if (!cfg.url || !enabledEvent(type))
63718
+ return;
63719
+ const { resolved, missing } = interpolateHeaders(cfg.headers);
63720
+ if (missing.length > 0) {
63721
+ getSafeLogger()?.warn(STAGE2, "Skipping webhook \u2014 unresolved env vars", { missing });
63722
+ return;
63723
+ }
63724
+ await postJson(cfg.url, { type, emittedAt: new Date().toISOString(), data }, { headers: resolved, timeoutMs: cfg.timeoutMs, stage: STAGE2, deps });
63725
+ };
63726
+ const reporter = {
63727
+ name: STAGE2,
63728
+ onRunStart: (event) => emit("onRunStart", event),
63729
+ onStoryComplete: (event) => emit("onStoryComplete", event),
63730
+ onRunEnd: (event) => emit("onRunEnd", event)
63731
+ };
63732
+ return {
63733
+ name: STAGE2,
63734
+ version: "1.0.0",
63735
+ provides: ["reporter"],
63736
+ extensions: { reporter }
63737
+ };
63738
+ }
63739
+ var STAGE2 = "webhook-reporter";
63740
+ var init_webhook_reporter = __esm(() => {
63741
+ init_logger2();
63742
+ init_reporter_shared();
63743
+ });
63744
+
63425
63745
  // src/plugins/plugin-logger.ts
63426
63746
  function createPluginLogger(pluginName) {
63427
63747
  const stage = `plugin:${pluginName}`;
@@ -63777,7 +64097,7 @@ function extractPluginName(pluginPath) {
63777
64097
  }
63778
64098
  return basename12.replace(/\.(ts|js|mjs)$/, "");
63779
64099
  }
63780
- async function loadPlugins(globalDir, projectDir, configPlugins, projectRoot, disabledPlugins, isTestFileFn) {
64100
+ async function loadPlugins(globalDir, projectDir, configPlugins, projectRoot, disabledPlugins, isTestFileFn, reporters) {
63781
64101
  const loadedPlugins = [];
63782
64102
  const builtinPostRunActions = [];
63783
64103
  const effectiveProjectRoot = projectRoot || projectDir;
@@ -63821,6 +64141,32 @@ async function loadPlugins(globalDir, projectDir, configPlugins, projectRoot, di
63821
64141
  } else {
63822
64142
  logger?.info("plugins", `Skipping disabled plugin: '${autoRoutePlugin.name}' (built-in)`);
63823
64143
  }
64144
+ const reporterFactories = reporters ? [
64145
+ {
64146
+ name: "webhook-reporter",
64147
+ enabled: reporters.webhook.enabled,
64148
+ make: () => createWebhookReporterPlugin(reporters.webhook)
64149
+ },
64150
+ {
64151
+ name: "otel-reporter",
64152
+ enabled: reporters.otel.enabled,
64153
+ make: () => createOtelReporterPlugin(reporters.otel)
64154
+ }
64155
+ ] : [];
64156
+ for (const { name, enabled: reporterEnabled, make } of reporterFactories) {
64157
+ if (!reporterEnabled)
64158
+ continue;
64159
+ if (disabledSet.has(name)) {
64160
+ logger?.info("plugins", `Skipping disabled plugin: '${name}' (built-in)`);
64161
+ continue;
64162
+ }
64163
+ const plugin = make();
64164
+ if (plugin.setup) {
64165
+ await plugin.setup({}, createPluginLogger(plugin.name));
64166
+ }
64167
+ loadedPlugins.push({ plugin, source: { type: "builtin", path: plugin.name } });
64168
+ pluginNames.add(plugin.name);
64169
+ }
63824
64170
  const globalPlugins = await discoverPlugins(globalDir, isTestFileFn);
63825
64171
  for (const plugin of globalPlugins) {
63826
64172
  const pluginName = extractPluginName(plugin.path);
@@ -63985,6 +64331,8 @@ var init_loader4 = __esm(() => {
63985
64331
  init_auto_pr();
63986
64332
  init_auto_route();
63987
64333
  init_curator();
64334
+ init_otel_reporter();
64335
+ init_webhook_reporter();
63988
64336
  init_plugin_logger();
63989
64337
  init_registry5();
63990
64338
  init_validator();
@@ -70674,7 +71022,7 @@ async function setupRun(options) {
70674
71022
  const configPlugins = config2.plugins || [];
70675
71023
  const resolvedPatterns = await resolveTestFilePatterns(config2, workdir);
70676
71024
  const isTestFileFn = (filename) => resolvedPatterns.regex.some((re) => re.test(filename));
70677
- const pluginRegistry = await loadPlugins(globalPluginsDir, projectPluginsDir, configPlugins, workdir, config2.disabledPlugins, isTestFileFn);
71025
+ const pluginRegistry = await loadPlugins(globalPluginsDir, projectPluginsDir, configPlugins, workdir, config2.disabledPlugins, isTestFileFn, config2.reporters);
70678
71026
  clearCache();
70679
71027
  logger?.info("plugins", `Loaded ${pluginRegistry.plugins.length} plugins`, {
70680
71028
  plugins: pluginRegistry.plugins.map((p) => ({ name: p.name, version: p.version, provides: p.provides }))
@@ -86662,13 +87010,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
86662
87010
  return false;
86663
87011
  }
86664
87012
  function utils_getInObject(object2, path31) {
86665
- return path31.reduce(function(reduced, attr) {
87013
+ return path31.reduce(function(reduced, attr2) {
86666
87014
  if (reduced) {
86667
- if (utils_hasOwnProperty.call(reduced, attr)) {
86668
- return reduced[attr];
87015
+ if (utils_hasOwnProperty.call(reduced, attr2)) {
87016
+ return reduced[attr2];
86669
87017
  }
86670
87018
  if (typeof reduced[Symbol.iterator] === "function") {
86671
- return Array.from(reduced)[attr];
87019
+ return Array.from(reduced)[attr2];
86672
87020
  }
86673
87021
  }
86674
87022
  return null;
@@ -97663,9 +98011,9 @@ The error thrown in the component is:
97663
98011
  getEnvironmentNames
97664
98012
  }, internalMcpFunctions);
97665
98013
  }
97666
- function decorate(object2, attr, fn) {
97667
- var old = object2[attr];
97668
- object2[attr] = function(instance2) {
98014
+ function decorate(object2, attr2, fn) {
98015
+ var old = object2[attr2];
98016
+ object2[attr2] = function(instance2) {
97669
98017
  return fn.call(this, old, arguments);
97670
98018
  };
97671
98019
  return old;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.73.3",
3
+ "version": "0.73.5",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {