wtt-connect 0.2.28 → 0.2.29
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/package.json +3 -2
- package/src/adapters/codex.js +2 -8
- package/src/runner.js +14 -21
- package/src/slash.js +22 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wtt-connect",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.29",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "WTT-native connector daemon for Codex, Claude Code, Cursor, Gemini, ACP, and other coding agent surfaces.",
|
|
6
6
|
"type": "module",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"setup": "node ./bin/wtt-connect.js setup",
|
|
14
14
|
"smoke:task": "node ./bin/wtt-connect.js smoke-task",
|
|
15
15
|
"smoke:chat": "node ./bin/wtt-connect.js smoke-chat",
|
|
16
|
-
"start": "node ./bin/wtt-connect.js start"
|
|
16
|
+
"start": "node ./bin/wtt-connect.js start",
|
|
17
|
+
"test": "node --test test/*.test.js"
|
|
17
18
|
},
|
|
18
19
|
"engines": {
|
|
19
20
|
"node": ">=22"
|
package/src/adapters/codex.js
CHANGED
|
@@ -3,6 +3,7 @@ import { execFile } from 'node:child_process';
|
|
|
3
3
|
import readline from 'node:readline';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import { log } from '../logger.js';
|
|
6
|
+
import { parseSlashCommand } from '../slash.js';
|
|
6
7
|
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
|
|
@@ -74,7 +75,7 @@ export class CodexAdapter {
|
|
|
74
75
|
case '/init':
|
|
75
76
|
return this.runInit(context, sessionKey);
|
|
76
77
|
default:
|
|
77
|
-
return
|
|
78
|
+
return null;
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -179,13 +180,6 @@ export class CodexAdapter {
|
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
182
|
|
|
182
|
-
function parseSlashCommand(text) {
|
|
183
|
-
const trimmed = String(text || '').trim();
|
|
184
|
-
if (!trimmed.startsWith('/')) return null;
|
|
185
|
-
const [command, ...rest] = trimmed.split(/\s+/);
|
|
186
|
-
return { command: command.toLowerCase(), args: rest.join(' ') };
|
|
187
|
-
}
|
|
188
|
-
|
|
189
183
|
async function commandOutput(bin, args, cwd, timeoutMs = 30000, maxChars = 8000) {
|
|
190
184
|
try {
|
|
191
185
|
const { stdout, stderr } = await execFileAsync(bin, args, { cwd, timeout: timeoutMs, maxBuffer: Math.max(maxChars * 4, 1024 * 1024) });
|
package/src/runner.js
CHANGED
|
@@ -20,6 +20,7 @@ import { buildRuntimeInfo } from './runtime-info.js';
|
|
|
20
20
|
import { runShellCommand } from './shell-runner.js';
|
|
21
21
|
import { TerminalSessionManager } from './terminal-session.js';
|
|
22
22
|
import { isModelSwitcherEnabled, switchModelProvider } from './model-switcher.js';
|
|
23
|
+
import { isAgentSlashCommand, parseSlashCommand } from './slash.js';
|
|
23
24
|
|
|
24
25
|
const TERMINAL_STATUSES = new Set(['review', 'done', 'approved', 'cancelled']);
|
|
25
26
|
const GENERATED_FILE_EXTENSIONS = new Set([
|
|
@@ -335,21 +336,26 @@ export class Runner {
|
|
|
335
336
|
if (parsed.command === '/upgrade') {
|
|
336
337
|
return this.handleUpgradeCommand(parsed.args);
|
|
337
338
|
}
|
|
338
|
-
if (adapter.name === 'codex' && typeof adapter.handleSlashCommand === 'function') {
|
|
339
|
-
return adapter.handleSlashCommand(content, context);
|
|
340
|
-
}
|
|
341
339
|
if (parsed.command === '/status') {
|
|
342
340
|
return this.runtimeStatusText(adapter, context);
|
|
343
341
|
}
|
|
344
|
-
if (
|
|
345
|
-
this.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
342
|
+
if (['/clear', '/new', '/reset', '/new-session', '/new-thread'].includes(parsed.command)) {
|
|
343
|
+
return this.clearAdapterSession(adapter, context.sessionKey || 'default', parsed.command);
|
|
344
|
+
}
|
|
345
|
+
if (adapter.name === 'codex' && typeof adapter.handleSlashCommand === 'function') {
|
|
346
|
+
const handled = await adapter.handleSlashCommand(content, context);
|
|
347
|
+
if (handled !== null && handled !== undefined) return handled;
|
|
349
348
|
}
|
|
350
349
|
return null;
|
|
351
350
|
}
|
|
352
351
|
|
|
352
|
+
clearAdapterSession(adapter, sessionKey, command) {
|
|
353
|
+
this.store.clearSession(sessionKey, { adapter: adapter.name, clearedBy: command });
|
|
354
|
+
if (adapter.threadBySession?.delete) adapter.threadBySession.delete(sessionKey);
|
|
355
|
+
if (adapter.sessionByKey?.delete) adapter.sessionByKey.delete(sessionKey);
|
|
356
|
+
return `${adapterDisplayName(adapter.name)} session cleared for this WTT topic. The next turn starts a fresh agent thread/session.`;
|
|
357
|
+
}
|
|
358
|
+
|
|
353
359
|
runtimeStatusText(adapter, context = {}) {
|
|
354
360
|
const runtime = this.runtimeInfo();
|
|
355
361
|
const modelConfig = context.modelConfig || {};
|
|
@@ -518,13 +524,6 @@ function adapterDisplayName(name) {
|
|
|
518
524
|
return name || 'Agent';
|
|
519
525
|
}
|
|
520
526
|
|
|
521
|
-
function parseSlashCommand(text) {
|
|
522
|
-
const trimmed = String(text || '').trim();
|
|
523
|
-
if (!trimmed.startsWith('/')) return null;
|
|
524
|
-
const [command, ...rest] = trimmed.split(/\s+/);
|
|
525
|
-
return { command: command.toLowerCase(), args: rest.join(' ') };
|
|
526
|
-
}
|
|
527
|
-
|
|
528
527
|
function wttSlashHelp() {
|
|
529
528
|
return [
|
|
530
529
|
'WTT slash commands:',
|
|
@@ -903,12 +902,6 @@ function stripWttSourceIdentity(content) {
|
|
|
903
902
|
return String(content || '').replace(/^┌─ 来源标识[^\n]*\n(?:│[^\n]*\n)?└[^\n]*\n?/, '');
|
|
904
903
|
}
|
|
905
904
|
|
|
906
|
-
function isAgentSlashCommand(message) {
|
|
907
|
-
const meta = parseMetadata(message?.metadata || message?.msg_metadata || message?.meta);
|
|
908
|
-
const slashType = String(meta?.slash_type || meta?.slashType || '').trim().toLowerCase();
|
|
909
|
-
return slashType === 'agent_passthrough';
|
|
910
|
-
}
|
|
911
|
-
|
|
912
905
|
function messageTopicType(m) {
|
|
913
906
|
return String(m.topic_type || metadataValue(m.metadata, 'topic_type') || metadataValue(m.metadata, 'topicType') || '').toLowerCase();
|
|
914
907
|
}
|
package/src/slash.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function parseSlashCommand(text) {
|
|
2
|
+
const trimmed = String(text || '').trim();
|
|
3
|
+
if (!trimmed.startsWith('/')) return null;
|
|
4
|
+
const [command, ...rest] = trimmed.split(/\s+/);
|
|
5
|
+
return { command: command.toLowerCase(), args: rest.join(' ') };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function parseMetadata(metadata) {
|
|
9
|
+
if (!metadata) return null;
|
|
10
|
+
let obj = metadata;
|
|
11
|
+
if (typeof metadata === 'string') {
|
|
12
|
+
try { obj = JSON.parse(metadata); } catch { return null; }
|
|
13
|
+
}
|
|
14
|
+
return obj && typeof obj === 'object' ? obj : null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isAgentSlashCommand(message = {}, content = '') {
|
|
18
|
+
const meta = parseMetadata(message?.metadata || message?.msg_metadata || message?.meta);
|
|
19
|
+
const slashType = String(meta?.slash_type || meta?.slashType || '').trim().toLowerCase();
|
|
20
|
+
if (slashType === 'agent_passthrough') return true;
|
|
21
|
+
return String(content || message?.content || '').trim().startsWith('/');
|
|
22
|
+
}
|