neuralos 3.3.7 → 3.3.8

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/bin/gybackend.cjs CHANGED
@@ -377393,6 +377393,7 @@ function pickBackendSnapshot(raw) {
377393
377393
  nats: raw.nats,
377394
377394
  synapse: raw.synapse,
377395
377395
  numbat: raw.numbat,
377396
+ monid: raw.monid,
377396
377397
  gateway: raw.gateway,
377397
377398
  layout: raw.layout,
377398
377399
  recursionLimit: raw.recursionLimit,
@@ -377476,6 +377477,7 @@ function normalizeBackendSettings(settings) {
377476
377477
  next.nats = normalizeNatsSettings(next.nats);
377477
377478
  next.synapse = normalizeSynapseSettings(next.synapse);
377478
377479
  next.numbat = normalizeNumbatSettings(next.numbat);
377480
+ next.monid = normalizeMonidSettings(next.monid);
377479
377481
  next.schemaVersion = BACKEND_SETTINGS_SCHEMA_VERSION;
377480
377482
  return next;
377481
377483
  }
@@ -377730,6 +377732,16 @@ function normalizeNumbatSettings(raw) {
377730
377732
  ...minSeverity ? { minSeverity } : {}
377731
377733
  };
377732
377734
  }
377735
+ function normalizeMonidSettings(raw) {
377736
+ const src = isObject5(raw) ? raw : {};
377737
+ const binaryPath = typeof src.binaryPath === "string" && src.binaryPath.trim() ? src.binaryPath.trim() : void 0;
377738
+ const keyLabel = typeof src.keyLabel === "string" && src.keyLabel.trim() ? src.keyLabel.trim() : void 0;
377739
+ return {
377740
+ enabled: src.enabled !== false,
377741
+ ...binaryPath ? { binaryPath } : {},
377742
+ ...keyLabel ? { keyLabel } : {}
377743
+ };
377744
+ }
377733
377745
  function migrateBackendToV3(settings) {
377734
377746
  const next = { ...settings };
377735
377747
  delete next.language;
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neuralos",
3
- "version": "3.3.7",
3
+ "version": "3.3.8",
4
4
  "description": "AI-native terminal & agentic-AI operations platform for Forward Deployed Engineers & SREs: AIOps closed-loop remediation, AI SRE, self-healing infrastructure, runbook automation, ChatOps; executes over SSH/WinRM/serial under policy with tamper-evident audit.",
5
5
  "keywords": [
6
6
  "forward-deployed-engineer",
@@ -0,0 +1,136 @@
1
+ /**
2
+ * monid-bridge — thin wrapper around the official Monid CLI.
3
+ *
4
+ * Settings → Plugins → Monid (settings.monid):
5
+ * enabled, binaryPath, keyLabel
6
+ * The API key is NEVER stored in settings.json. Saving a key in the UI runs
7
+ * `monid keys add -k <key> -l <label>` (see applyMonidApiKey).
8
+ *
9
+ * Agent tools: monid_health, monid_discover, monid_run.
10
+ */
11
+
12
+ import { createRequire } from 'node:module'
13
+
14
+ const require = createRequire(import.meta.url)
15
+
16
+ export function resolveConfig(ctx = {}, env = process.env) {
17
+ const s = (typeof ctx.getSettings === 'function' ? ctx.getSettings() : ctx.settings) || {}
18
+ const b = s.monid || {}
19
+ return {
20
+ enabled: b.enabled !== false,
21
+ binaryPath: b.binaryPath || env.MONID_BIN || 'monid',
22
+ keyLabel: b.keyLabel || 'rterm',
23
+ }
24
+ }
25
+
26
+ /** Build argv for a monid subcommand. Pure. */
27
+ export function buildMonidArgv(sub, params = {}) {
28
+ switch (sub) {
29
+ case 'version':
30
+ return ['--version']
31
+ case 'keys-list':
32
+ return ['keys', 'list']
33
+ case 'discover': {
34
+ const q = String(params.query || '').trim()
35
+ if (!q) throw new Error('monid_discover needs a query')
36
+ return ['discover', q]
37
+ }
38
+ case 'run': {
39
+ const tool = String(params.tool || '').trim()
40
+ if (!tool) throw new Error('monid_run needs a tool name')
41
+ const argv = ['run', tool]
42
+ if (params.input != null && String(params.input).trim()) {
43
+ argv.push('--input', String(params.input))
44
+ }
45
+ return argv
46
+ }
47
+ default:
48
+ throw new Error(`unknown monid subcommand: ${sub}`)
49
+ }
50
+ }
51
+
52
+ async function runMonid(ctx, cfg, argv) {
53
+ if (typeof ctx.runCommand === 'function') {
54
+ const cmdline = [cfg.binaryPath, ...argv].map((a) => (/\s/.test(a) ? `"${a}"` : a)).join(' ')
55
+ return ctx.runCommand({ command: cmdline })
56
+ }
57
+ if (typeof ctx.exec === 'function') {
58
+ const cmdline = [cfg.binaryPath, ...argv].map((a) => (/\s/.test(a) ? `"${a}"` : a)).join(' ')
59
+ return ctx.exec(cmdline)
60
+ }
61
+ const { execFile } = require('node:child_process')
62
+ return new Promise((resolve) => {
63
+ execFile(cfg.binaryPath, argv, { timeout: 120000, env: { ...process.env, NO_COLOR: '1' } }, (err, stdout, stderr) => {
64
+ resolve({
65
+ ok: !err,
66
+ exitCode: err?.code ?? 0,
67
+ stdout: String(stdout ?? ''),
68
+ stderr: String(stderr ?? ''),
69
+ error: err ? String(err.message) : undefined,
70
+ })
71
+ })
72
+ })
73
+ }
74
+
75
+ async function guarded(fn, log) {
76
+ try {
77
+ return await fn()
78
+ } catch (e) {
79
+ const msg = e?.message ?? String(e)
80
+ log?.(`[monid] ${msg}`)
81
+ return {
82
+ error: msg,
83
+ hint: 'Install @monid-ai/cli (`npm i -g @monid-ai/cli`) and paste an API key in Settings → Plugins → Monid (https://app.monid.ai/access/api-keys).',
84
+ }
85
+ }
86
+ }
87
+
88
+ export function register(ctx) {
89
+ const { registerTool, log } = ctx
90
+ const cfg = resolveConfig(ctx)
91
+ if (!cfg.enabled) {
92
+ log?.('[monid] disabled in settings.monid.enabled')
93
+ return
94
+ }
95
+
96
+ registerTool({
97
+ name: 'monid_health',
98
+ description: 'Check the Monid CLI is installed and list configured key labels (never the secret).',
99
+ params: {},
100
+ handler: async () =>
101
+ guarded(async () => {
102
+ const ver = await runMonid(ctx, cfg, buildMonidArgv('version'))
103
+ const keys = await runMonid(ctx, cfg, buildMonidArgv('keys-list'))
104
+ return { binaryPath: cfg.binaryPath, keyLabel: cfg.keyLabel, version: ver, keys }
105
+ }, log),
106
+ })
107
+
108
+ registerTool({
109
+ name: 'monid_discover',
110
+ description: 'Discover Monid tools/endpoints for a task (web data, enrichment, social, company/people). Use before writing a scraper or when a generic fetch is not enough.',
111
+ params: {
112
+ query: { type: 'string', description: 'What you need (e.g. "linkedin company employees")' },
113
+ },
114
+ handler: async (p) =>
115
+ guarded(async () => {
116
+ const argv = buildMonidArgv('discover', p)
117
+ const r = await runMonid(ctx, cfg, argv)
118
+ return { argv: [cfg.binaryPath, ...argv], ...r }
119
+ }, log),
120
+ })
121
+
122
+ registerTool({
123
+ name: 'monid_run',
124
+ description: 'Run a named Monid tool with optional JSON/text input. Prefer this over hand-rolled scrapers when discover returned a tool.',
125
+ params: {
126
+ tool: { type: 'string', description: 'Tool name from monid_discover' },
127
+ input: { type: 'string', description: 'JSON or text input for the tool', optional: true },
128
+ },
129
+ handler: async (p) =>
130
+ guarded(async () => {
131
+ const argv = buildMonidArgv('run', p)
132
+ const r = await runMonid(ctx, cfg, argv)
133
+ return { argv: [cfg.binaryPath, ...argv], ...r }
134
+ }, log),
135
+ })
136
+ }
@@ -0,0 +1,27 @@
1
+ import { buildMonidArgv, resolveConfig } from './index.mjs'
2
+
3
+ const assert = (c, m) => {
4
+ if (!c) throw new Error(`assert failed: ${m}`)
5
+ }
6
+
7
+ assert(resolveConfig({ settings: {} }).enabled === true, 'enabled default')
8
+ assert(resolveConfig({ settings: { monid: { enabled: false } } }).enabled === false, 'disabled')
9
+ assert(resolveConfig({ settings: { monid: { binaryPath: '/opt/monid' } } }).binaryPath === '/opt/monid', 'bin')
10
+ assert(resolveConfig({}, { MONID_BIN: 'custom-monid' }).binaryPath === 'custom-monid', 'env bin')
11
+
12
+ assert(buildMonidArgv('version').join(' ') === '--version', 'version')
13
+ assert(buildMonidArgv('keys-list').join(' ') === 'keys list', 'keys list')
14
+ assert(buildMonidArgv('discover', { query: 'company news' }).join(' ') === 'discover company news', 'discover')
15
+ assert(buildMonidArgv('run', { tool: 'foo', input: '{"a":1}' }).join(' ') === 'run foo --input {"a":1}', 'run')
16
+
17
+ let threw = false
18
+ try { buildMonidArgv('discover', { query: '' }) } catch { threw = true }
19
+ assert(threw, 'discover requires query')
20
+ threw = false
21
+ try { buildMonidArgv('run', {}) } catch { threw = true }
22
+ assert(threw, 'run requires tool')
23
+ threw = false
24
+ try { buildMonidArgv('nope') } catch { threw = true }
25
+ assert(threw, 'unknown sub')
26
+
27
+ console.log('monid-bridge: all cases passed')
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "monid-bridge",
3
+ "version": "1.0.0",
4
+ "description": "Thin Monid CLI bridge: paste an API key in Settings → Plugins; agents get monid_discover / monid_run / monid_health wrapping the official CLI. Does not reimplement TinyFish.",
5
+ "entry": "index.mjs",
6
+ "tools": [
7
+ "monid_health",
8
+ "monid_discover",
9
+ "monid_run"
10
+ ],
11
+ "permissions": [
12
+ "exec"
13
+ ]
14
+ }
Binary file