@virtue-ai/gateway-connect 0.3.1 → 0.3.3
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/README.md +2 -8
- package/dist/trajectory-plugin.js +47 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,12 +26,6 @@ openclaw models auth paste-token --provider openai
|
|
|
26
26
|
npx @virtue-ai/gateway-connect --gateway-url https://virtueai-agent-gtw-xxxx.ngrok.io
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
To use a specific model:
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npx @virtue-ai/gateway-connect --gateway-url https://virtueai-agent-gtw-xxxx.ngrok.io --model openai/gpt-4o
|
|
33
|
-
```
|
|
34
|
-
|
|
35
29
|
This will:
|
|
36
30
|
|
|
37
31
|
1. Open your browser for OAuth login
|
|
@@ -52,7 +46,7 @@ Interactive TUI mode:
|
|
|
52
46
|
|
|
53
47
|
```bash
|
|
54
48
|
# Terminal 1: start the OpenClaw gateway
|
|
55
|
-
openclaw gateway
|
|
49
|
+
openclaw gateway --allow-unconfigured
|
|
56
50
|
|
|
57
51
|
# Terminal 2: open the TUI
|
|
58
52
|
openclaw tui
|
|
@@ -69,7 +63,7 @@ openclaw gateway stop
|
|
|
69
63
|
In TUI mode, use slash commands to switch models on the fly:
|
|
70
64
|
|
|
71
65
|
```
|
|
72
|
-
/model openai/gpt-
|
|
66
|
+
/model openai/gpt-5.2
|
|
73
67
|
/model anthropic/claude-opus-4-6
|
|
74
68
|
/models # opens model picker
|
|
75
69
|
```
|
|
@@ -26,7 +26,7 @@ const DEFAULT_GUARD_UUID = '3a2389709528a539a12ba6239e402ef159ecffa88f99af6e1323
|
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
function buildPluginSource() {
|
|
28
28
|
return `\
|
|
29
|
-
import { readFileSync } from "fs";
|
|
29
|
+
import { readFileSync, appendFileSync, mkdirSync } from "fs";
|
|
30
30
|
import { join } from "path";
|
|
31
31
|
import { homedir } from "os";
|
|
32
32
|
|
|
@@ -40,6 +40,7 @@ import { homedir } from "os";
|
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
const MCP_CONFIG_PATH = join(homedir(), ".openclaw", "mcp-gateway.json");
|
|
43
|
+
const TRAJECTORY_LOG_DIR = join(homedir(), ".openclaw", "logs", "trajectory");
|
|
43
44
|
const DEFAULT_GUARD_UUID =
|
|
44
45
|
"${DEFAULT_GUARD_UUID}";
|
|
45
46
|
|
|
@@ -72,6 +73,19 @@ function truncate(s, max = 2000) {
|
|
|
72
73
|
return s.length > max ? s.slice(0, max) + "..." : s;
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Strip OpenClaw's sender metadata prefix from the raw prompt.
|
|
78
|
+
* The prompt arrives as:
|
|
79
|
+
* Sender (untrusted metadata):\\n{json}\\n\\n[timestamp] actual message
|
|
80
|
+
* We want just "actual message".
|
|
81
|
+
*/
|
|
82
|
+
function stripSenderMetadata(prompt) {
|
|
83
|
+
if (!prompt || typeof prompt !== "string") return prompt;
|
|
84
|
+
// Match the "Sender (untrusted metadata):" block + JSON + timestamp prefix
|
|
85
|
+
const match = prompt.match(/^Sender \\(untrusted metadata\\):[\\s\\S]*?\\n\\n(?:\\[.*?\\]\\s*)?(.*)$/s);
|
|
86
|
+
return match ? match[1].trim() : prompt.trim();
|
|
87
|
+
}
|
|
88
|
+
|
|
75
89
|
const plugin = {
|
|
76
90
|
id: "${PLUGIN_ID}",
|
|
77
91
|
name: "VirtueAI Trajectory",
|
|
@@ -87,8 +101,19 @@ const plugin = {
|
|
|
87
101
|
let gatewaySessionId = null;
|
|
88
102
|
let endpointDisabled = false;
|
|
89
103
|
const endpoint = config.apiUrl + "/api/prompt-guard/topic_guard";
|
|
104
|
+
const localSessionId = "local_" + Date.now().toString(36);
|
|
105
|
+
|
|
106
|
+
try { mkdirSync(TRAJECTORY_LOG_DIR, { recursive: true }); } catch {}
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
function writeLocal(role, content) {
|
|
109
|
+
try {
|
|
110
|
+
const entry = { timestamp: new Date().toISOString(), session_id: gatewaySessionId || localSessionId, role, content };
|
|
111
|
+
const logFile = join(TRAJECTORY_LOG_DIR, (gatewaySessionId || localSessionId) + ".jsonl");
|
|
112
|
+
appendFileSync(logFile, JSON.stringify(entry) + "\\n");
|
|
113
|
+
} catch {}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
api.logger.info("[virtueai-trajectory] Plugin registered, sending to " + config.apiUrl);
|
|
92
117
|
|
|
93
118
|
async function sendStep(role, content) {
|
|
94
119
|
if (endpointDisabled) return;
|
|
@@ -133,34 +158,46 @@ const plugin = {
|
|
|
133
158
|
}
|
|
134
159
|
}
|
|
135
160
|
|
|
136
|
-
// Hook: user prompt sent to LLM
|
|
137
161
|
api.on("llm_input", (event) => {
|
|
138
|
-
if (event.
|
|
139
|
-
|
|
162
|
+
if (event.systemPrompt) {
|
|
163
|
+
writeLocal("system", event.systemPrompt);
|
|
164
|
+
}
|
|
165
|
+
const cleaned = stripSenderMetadata(event.prompt);
|
|
166
|
+
api.logger.info("[virtueai-trajectory] llm_input fired, prompt=" + (cleaned ?? "").slice(0, 80));
|
|
167
|
+
if (cleaned) {
|
|
168
|
+
writeLocal("user", cleaned);
|
|
169
|
+
sendStep("user", cleaned);
|
|
140
170
|
}
|
|
141
171
|
});
|
|
142
172
|
|
|
143
|
-
// Hook: LLM response received
|
|
144
173
|
api.on("llm_output", (event) => {
|
|
174
|
+
api.logger.info("[virtueai-trajectory] llm_output fired, assistantTexts.length=" + (event.assistantTexts?.length ?? "undefined") + ", keys=" + Object.keys(event).join(","));
|
|
145
175
|
const text = (event.assistantTexts ?? []).join("\\n").trim();
|
|
146
176
|
if (text) {
|
|
177
|
+
api.logger.info("[virtueai-trajectory] llm_output sending agent text, len=" + text.length);
|
|
178
|
+
writeLocal("agent", text);
|
|
147
179
|
sendStep("agent", text);
|
|
180
|
+
} else {
|
|
181
|
+
api.logger.warn("[virtueai-trajectory] llm_output fired but assistantTexts empty");
|
|
148
182
|
}
|
|
149
183
|
});
|
|
150
184
|
|
|
151
|
-
// Hook: tool call completed
|
|
152
185
|
api.on("after_tool_call", (event) => {
|
|
153
|
-
|
|
186
|
+
api.logger.info("[virtueai-trajectory] after_tool_call fired, tool=" + event.toolName);
|
|
187
|
+
const toolParams = event.params
|
|
154
188
|
? Object.entries(event.params)
|
|
155
189
|
.map(([k, v]) => k + "=" + JSON.stringify(v))
|
|
156
190
|
.join(", ")
|
|
157
191
|
: "";
|
|
158
|
-
const callStr = event.toolName + "(" +
|
|
192
|
+
const callStr = event.toolName + "(" + toolParams + ")";
|
|
159
193
|
const resultStr = event.result != null ? truncate(event.result, 500) : (event.error ?? "no result");
|
|
194
|
+
writeLocal("tool", callStr + " → " + resultStr);
|
|
160
195
|
sendStep("agent", callStr + " → " + resultStr);
|
|
161
196
|
});
|
|
162
197
|
|
|
163
|
-
api.
|
|
198
|
+
api.on("agent_end", (event) => {
|
|
199
|
+
api.logger.info("[virtueai-trajectory] agent_end fired, success=" + event.success + ", durationMs=" + event.durationMs);
|
|
200
|
+
});
|
|
164
201
|
},
|
|
165
202
|
};
|
|
166
203
|
|