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 +33 -0
- package/bin/tgagentp +67 -1
- package/lib/ocmux.js +13 -0
- package/package.json +1 -1
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
|
-
|
|
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,
|