@openagents-org/agent-launcher 0.2.130 → 0.2.132

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/src/tui.js CHANGED
@@ -120,25 +120,10 @@ function describeHealth(health) {
120
120
  }
121
121
 
122
122
  function loadCatalog(connector) {
123
- const { execSync } = require('child_process');
124
123
  const entries = connector.registry.getCatalogSync();
125
124
  return entries.map(e => {
126
125
  let installed = false;
127
-
128
- // If a verify command exists, use it for accurate detection
129
- const verifyCmd = IS_WINDOWS ? (e.install && e.install.verify_win) : (e.install && e.install.verify);
130
- if (verifyCmd) {
131
- try { execSync(verifyCmd, { stdio: 'ignore', timeout: 5000 }); installed = true; } catch {}
132
- } else {
133
- try { const { whichBinary } = require('./paths'); installed = !!whichBinary((e.install && e.install.binary) || e.name); } catch {}
134
- }
135
-
136
- if (!installed) {
137
- try {
138
- const f = path.join(connector._configDir, 'installed_agents.json');
139
- if (fs.existsSync(f)) installed = !!JSON.parse(fs.readFileSync(f, 'utf-8'))[e.name];
140
- } catch {}
141
- }
126
+ try { installed = !!connector.installer.getInstallInfo(e.name).installed; } catch {}
142
127
  return {
143
128
  name: e.name,
144
129
  label: e.label || e.name,
@@ -17,7 +17,7 @@ const { execSync, spawnSync } = require('child_process');
17
17
 
18
18
  const PKG_NAME = '@openagents-org/agent-launcher';
19
19
  const CACHE_FILE = path.join(os.homedir(), '.openagents', '.update-check.json');
20
- const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
20
+ const CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes
21
21
 
22
22
  function currentVersion() {
23
23
  return require('../package.json').version;
@@ -161,8 +161,8 @@ function promptYes(question, timeoutMs = 30000) {
161
161
  }
162
162
 
163
163
  /**
164
- * Check, notify, and offer to update. Exits the process on successful update.
165
- * Safe to call at the top of any user-facing CLI command.
164
+ * Check and print a warning if a newer version is available.
165
+ * Never prompts or auto-updates — users run `agn update` explicitly.
166
166
  */
167
167
  async function notifyAndMaybeUpdate() {
168
168
  let info;
@@ -170,29 +170,9 @@ async function notifyAndMaybeUpdate() {
170
170
  if (!info || !info.isNewer) return;
171
171
 
172
172
  process.stderr.write(
173
- `\n[launcher] Update available: ${info.current} → ${info.latest}\n`
173
+ `\n[launcher] Update available: ${info.current} → ${info.latest}\n` +
174
+ '[launcher] Run `agn update` to upgrade.\n\n'
174
175
  );
175
-
176
- const interactive = process.stdin.isTTY && process.stdout.isTTY;
177
- if (!interactive) {
178
- process.stderr.write(
179
- '[launcher] Run `agn update` (or re-run install.sh) to upgrade.\n\n'
180
- );
181
- return;
182
- }
183
-
184
- const accepted = await promptYes('[launcher] Update now? [Y/n] ');
185
- if (!accepted) {
186
- process.stderr.write('[launcher] Skipped. Run `agn update` later to upgrade.\n\n');
187
- return;
188
- }
189
-
190
- const ok = runUpdate();
191
- if (ok) {
192
- process.stderr.write(`[launcher] Updated to ${info.latest}. Re-run your command.\n`);
193
- process.exit(0);
194
- }
195
- process.stderr.write('[launcher] Update failed — continuing with current version.\n\n');
196
176
  }
197
177
 
198
178
  module.exports = {
@@ -271,7 +271,7 @@ class WorkspaceClient {
271
271
  * Poll for pending messages targeted at an agent via GET /v1/events.
272
272
  * Returns { messages, cursor } where cursor is the last event ID.
273
273
  */
274
- async pollPending(workspaceId, agentName, token, { after, limit = 50 } = {}) {
274
+ async pollPending(workspaceId, agentName, token, { after, limit = 500 } = {}) {
275
275
  const params = new URLSearchParams({
276
276
  network: workspaceId,
277
277
  type: 'workspace.message.posted',
@@ -333,7 +333,28 @@ class WorkspaceClient {
333
333
  }
334
334
  }
335
335
 
336
- return { messages, cursor };
336
+ const composing = !!(result && result.composing);
337
+ return { messages, cursor, composing };
338
+ }
339
+
340
+ /**
341
+ * Get the workspace's top-level metadata via GET /v1/workspaces/{id}.
342
+ *
343
+ * Returns the full data block from the backend — adapters care about
344
+ * `browserEnabled` today, but more keys may be surfaced over time. On
345
+ * error, returns null so callers can fall back to defaults rather than
346
+ * crashing.
347
+ */
348
+ async getWorkspaceMetadata(workspaceId, token) {
349
+ try {
350
+ const data = await this._get(
351
+ `/v1/workspaces/${workspaceId}`,
352
+ this._wsHeaders(token),
353
+ );
354
+ return data.data || data || {};
355
+ } catch {
356
+ return null;
357
+ }
337
358
  }
338
359
 
339
360
  /**
@@ -412,6 +433,7 @@ class WorkspaceClient {
412
433
  agentName: (a.address || '').replace('openagents:', ''),
413
434
  role: a.role || 'member',
414
435
  status: a.status || 'offline',
436
+ enabledSkills: a.enabled_skills || null,
415
437
  }));
416
438
  }
417
439
 
@@ -606,17 +628,22 @@ class WorkspaceClient {
606
628
 
607
629
  // ── Routines ──
608
630
 
609
- async createRoutine(workspaceId, channelName, token, { name, message, hour, minute, days, source } = {}) {
631
+ async createRoutine(workspaceId, channelName, token, { name, message, context, hour, minute, days, interval_minutes, source } = {}) {
610
632
  const body = {
611
633
  name,
612
634
  message,
613
- hour,
614
- minute,
635
+ context: context || '',
615
636
  network: workspaceId,
616
637
  channel: channelName,
617
638
  source: source || 'openagents:unknown',
618
639
  };
619
- if (days) body.days = days;
640
+ if (interval_minutes != null) {
641
+ body.interval_minutes = interval_minutes;
642
+ } else {
643
+ body.hour = hour;
644
+ body.minute = minute;
645
+ if (days) body.days = days;
646
+ }
620
647
  const data = await this._post('/v1/routines', body, this._wsHeaders(token));
621
648
  return data.data || data;
622
649
  }
@@ -633,6 +660,74 @@ class WorkspaceClient {
633
660
  return data.data || data;
634
661
  }
635
662
 
663
+ // ── Notifications ──
664
+
665
+ async createNotification(workspaceId, token, { title, message, priority, channel, source } = {}) {
666
+ const body = {
667
+ title,
668
+ message,
669
+ priority: priority || 'normal',
670
+ network: workspaceId,
671
+ source: source || 'openagents:unknown',
672
+ };
673
+ if (channel) body.channel = channel;
674
+ const data = await this._post('/v1/notifications', body, this._wsHeaders(token));
675
+ return data.data || data;
676
+ }
677
+
678
+ async listNotifications(workspaceId, token, { limit = 50 } = {}) {
679
+ const params = new URLSearchParams({
680
+ network: workspaceId,
681
+ limit: String(limit),
682
+ });
683
+ const data = await this._get(`/v1/notifications?${params}`, this._wsHeaders(token));
684
+ return data.data || data;
685
+ }
686
+
687
+ // ── Knowledge Base ──
688
+
689
+ async listKnowledge(workspaceId, token, { limit = 100 } = {}) {
690
+ const params = new URLSearchParams({
691
+ network: workspaceId,
692
+ limit: String(limit),
693
+ });
694
+ const data = await this._get(`/v1/knowledge?${params}`, this._wsHeaders(token));
695
+ return data.data || data;
696
+ }
697
+
698
+ async getKnowledge(workspaceId, token, entryId) {
699
+ const params = new URLSearchParams({ network: workspaceId });
700
+ const data = await this._get(`/v1/knowledge/${entryId}?${params}`, this._wsHeaders(token));
701
+ return data.data || data;
702
+ }
703
+
704
+ async getKnowledgeBySlug(workspaceId, token, slug) {
705
+ const params = new URLSearchParams({ network: workspaceId });
706
+ const data = await this._get(`/v1/knowledge/by-slug/${slug}?${params}`, this._wsHeaders(token));
707
+ return data.data || data;
708
+ }
709
+
710
+ async createKnowledge(workspaceId, token, { title, content, description, source } = {}) {
711
+ const body = { title, content, network: workspaceId, source: source || 'openagents:unknown' };
712
+ if (description) body.description = description;
713
+ const data = await this._post('/v1/knowledge', body, this._wsHeaders(token));
714
+ return data.data || data;
715
+ }
716
+
717
+ async updateKnowledge(workspaceId, token, entryId, { title, content, description, source } = {}) {
718
+ const body = { network: workspaceId, source: source || 'openagents:unknown' };
719
+ if (title !== undefined) body.title = title;
720
+ if (content !== undefined) body.content = content;
721
+ if (description !== undefined) body.description = description;
722
+ const data = await this._put(`/v1/knowledge/${entryId}`, body, this._wsHeaders(token));
723
+ return data.data || data;
724
+ }
725
+
726
+ async deleteKnowledge(workspaceId, token, entryId) {
727
+ const data = await this._delete(`/v1/knowledge/${entryId}`, this._wsHeaders(token), workspaceId);
728
+ return data.data || data;
729
+ }
730
+
636
731
  // ── Internal helpers ──
637
732
 
638
733
  /**