agentp 0.11.5 → 0.11.6

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/ocmux CHANGED
@@ -22,6 +22,7 @@ const {
22
22
  logfileFor,
23
23
  URL_RE,
24
24
  resurrectServer,
25
+ getActiveServer,
25
26
  } = require('../lib/ocmux');
26
27
 
27
28
  // ---------------------------------------------------------------------------
@@ -186,6 +187,7 @@ function printHelp() {
186
187
  console.error('');
187
188
  console.error('Options:');
188
189
  console.error(' -l Long output: append " → <dir>" after the URL (serve/default).');
190
+ console.error(' --last Print the URL of the active tmux window (last used server).');
189
191
  console.error(' --print-logs Pass --print-logs to opencode serve (prints server logs to stderr).');
190
192
  console.error(' --version Show version');
191
193
  console.error(' -h Show this help');
@@ -445,12 +447,15 @@ function main() {
445
447
  let longMode = false;
446
448
  let gitMode = null;
447
449
  let printLogs = false;
450
+ let lastMode = false;
448
451
  const positional = [];
449
452
  let dirIsForced = false;
450
453
 
451
454
  for (const arg of process.argv.slice(2)) {
452
455
  if (arg === '-l') {
453
456
  longMode = true;
457
+ } else if (arg === '--last') {
458
+ lastMode = true;
454
459
  } else if (arg === '--print-logs') {
455
460
  printLogs = true;
456
461
  } else if (arg === '--git') {
@@ -516,6 +521,34 @@ function main() {
516
521
  if (!targetDir) targetDir = process.cwd();
517
522
 
518
523
  // Dispatch
524
+ if (lastMode) {
525
+ if (gitMode) {
526
+ console.error("Error: '--last' cannot be combined with '--git' or '--GIT'.");
527
+ process.exit(1);
528
+ }
529
+ if (printLogs) {
530
+ console.error("Error: '--last' cannot be combined with '--print-logs'.");
531
+ process.exit(1);
532
+ }
533
+ if (subcommand) {
534
+ console.error(`Error: '--last' cannot be combined with subcommand '${subcommand}'.`);
535
+ process.exit(1);
536
+ }
537
+ if (targetDir !== process.cwd()) {
538
+ console.error("Error: '--last' does not accept a directory path.");
539
+ process.exit(1);
540
+ }
541
+ ensureSession();
542
+ const url = getActiveServer();
543
+ if (!url) {
544
+ console.error('Error: no active opencode server found in tmux.');
545
+ console.error("Run 'ocmux serve' to create a server, or switch to an existing one.");
546
+ process.exit(1);
547
+ }
548
+ outputUrl(url, null, longMode);
549
+ return;
550
+ }
551
+
519
552
  if (subcommand === 'list') {
520
553
  if (gitMode) {
521
554
  console.error("Error: '--git' and '--GIT' are only valid with 'serve'.");
package/bin/tgagentp CHANGED
@@ -1813,6 +1813,18 @@ async function main() {
1813
1813
  const intro = 'The following information is for your awareness. Reply with only "Ack" and do not take any action:';
1814
1814
  const noteText = intro + '\n\n' + text;
1815
1815
  if (st.busy) {
1816
+ // Experimental: try async injection instead of queuing
1817
+ if (st.activeSessionId) {
1818
+ try {
1819
+ log.debug(` → /note: attempting async injection into session ${st.activeSessionId}`);
1820
+ await sendToSessionAsync(url, st.activeSessionId, noteText, st.activeAgentName);
1821
+ await sendLongMessage(token, chatState, '💉 Note injected into ongoing session.');
1822
+ log.debug(` → /note: async injection succeeded`);
1823
+ return;
1824
+ } catch (err) {
1825
+ log.debug(` → /note: async injection failed (${err.message}), falling back to queue`);
1826
+ }
1827
+ }
1816
1828
  if (!st.messageQueue) st.messageQueue = [];
1817
1829
  st.messageQueue.push({ text: noteText, replyTo: null });
1818
1830
  await sendLongMessage(token, chatState, `⏳ Server is busy. Note queued (#${st.messageQueue.length}).`);
@@ -2084,7 +2096,25 @@ async function main() {
2084
2096
 
2085
2097
  if (typeof msg.text !== 'string') continue;
2086
2098
 
2087
- const text = msg.text;
2099
+ let text = msg.text;
2100
+
2101
+ // !! wildcard: replace with the previous user message text
2102
+ if (text.includes('!!')) {
2103
+ const prevMsg = msg.reply_to_message;
2104
+ if (prevMsg && prevMsg.text) {
2105
+ text = text.replace(/!!/g, prevMsg.text);
2106
+ } else {
2107
+ // Fallback: look up the last user message from the ring buffer
2108
+ const ring = getChatState(chatId, threadId).ring;
2109
+ const lastUserMsg = ring.messages.slice().reverse().find(m => m.role === 'user');
2110
+ if (lastUserMsg) {
2111
+ text = text.replace(/!!/g, lastUserMsg.text);
2112
+ } else {
2113
+ await sendLongMessage(token, cs, '⚠️ No previous message found to replace !!');
2114
+ continue;
2115
+ }
2116
+ }
2117
+ }
2088
2118
 
2089
2119
  log.debug(`[chat ${chatId}] ${from}: ${text}`);
2090
2120
  msgLog('in', chatId, from, text);
@@ -2092,6 +2122,42 @@ async function main() {
2092
2122
  // Build reply context if this message is a Telegram reply
2093
2123
  const replyContext = quoteReply(msg);
2094
2124
 
2125
+ // Download on reply: if the user replies to a file message, download it
2126
+ if (msg.reply_to_message && (msg.reply_to_message.document || msg.reply_to_message.photo)) {
2127
+ if (!cs.serverBase) {
2128
+ await sendLongMessage(token, cs, '🔌 Not connected to any server. Cannot download file.');
2129
+ } else {
2130
+ const projectDir = serverDir(cs.serverBase);
2131
+ if (!projectDir) {
2132
+ await sendLongMessage(token, cs, '❌ Could not find project directory for this server.');
2133
+ } else {
2134
+ try {
2135
+ const replyMsg = msg.reply_to_message;
2136
+ let fileId, fileName, fileSize;
2137
+ if (replyMsg.document) {
2138
+ fileId = replyMsg.document.file_id;
2139
+ fileName = replyMsg.document.file_name || 'download.bin';
2140
+ fileSize = replyMsg.document.file_size || 0;
2141
+ } else if (replyMsg.photo) {
2142
+ const largest = replyMsg.photo[replyMsg.photo.length - 1];
2143
+ fileId = largest.file_id;
2144
+ fileName = 'photo.jpg';
2145
+ fileSize = largest.file_size || 0;
2146
+ }
2147
+ const fileData = await downloadTelegramFile(token, fileId);
2148
+ ensureSharedDir(projectDir);
2149
+ const relativePath = saveUploadedFile(projectDir, fileName, fileData);
2150
+ const sizeStr = fileSize > 0 ? ` (${formatFileSize(fileSize)})` : '';
2151
+ await sendLongMessage(token, cs, `📎 File downloaded: \`${relativePath}\`${sizeStr}`);
2152
+ } catch (err) {
2153
+ log.error(`Download on reply error: ${err.message}`);
2154
+ await sendLongMessage(token, cs, `❌ File download failed: ${err.message}`);
2155
+ }
2156
+ }
2157
+ }
2158
+ continue;
2159
+ }
2160
+
2095
2161
  // Intercept //commands (raw TUI passthrough via tmux send-keys)
2096
2162
  if (text.startsWith('//')) {
2097
2163
  const tuiCmd = text.slice(1);
package/lib/ocmux.js CHANGED
@@ -92,6 +92,18 @@ function activeWindowIndex() {
92
92
  return null;
93
93
  }
94
94
 
95
+ // Get the URL of the active tmux window (the one currently selected in the Opencode session).
96
+ function getActiveServer() {
97
+ const idx = activeWindowIndex();
98
+ if (idx == null) return null;
99
+ const dir = windowNameByIndex(idx);
100
+ if (!dir) return null;
101
+ const sf = statefileFor(dir);
102
+ if (!fs.existsSync(sf)) return null;
103
+ const state = readState(sf);
104
+ return state && state.url ? state.url : null;
105
+ }
106
+
95
107
  function paneCount(windowIndex) {
96
108
  const r = _tmux(['list-panes', '-t', `${SESSION}:${windowIndex}`, '-F', '#{pane_id}']);
97
109
  if (r.status !== 0) return 0;
@@ -259,6 +271,7 @@ module.exports = {
259
271
  paneCount,
260
272
  listServers,
261
273
  activateServer,
274
+ getActiveServer,
262
275
  hashDir,
263
276
  logfileFor,
264
277
  sleep,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentp",
3
- "version": "0.11.5",
3
+ "version": "0.11.6",
4
4
  "description": "Pipe prompts into a running OpenCode TUI session and stream the final answer",
5
5
  "bin": {
6
6
  "agentp": "bin/agentp",