wtt-connect 0.2.32 → 0.2.34
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 +1 -1
- package/src/main.js +68 -0
- package/src/runner.js +4 -3
- package/src/wtt-api.js +1 -0
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -35,6 +35,7 @@ export async function main(args) {
|
|
|
35
35
|
if (cmd === 'smoke-chat') return smokeChat(loadConfig(argv), argv);
|
|
36
36
|
if (cmd === 'upload-file' || cmd === 'send-file') return uploadFile(loadConfig(argv), argv);
|
|
37
37
|
if (cmd === 'upload-artifact' || cmd === 'opendesign-upload') return uploadArtifact(loadConfig(argv), argv);
|
|
38
|
+
if (cmd === 'preview-port' || cmd === 'sandbox-preview') return previewPort(loadConfig(argv), argv);
|
|
38
39
|
if (cmd === 'start') {
|
|
39
40
|
const config = loadConfig(argv);
|
|
40
41
|
if (!config.agentId) throw new Error('WTT_AGENT_ID is required');
|
|
@@ -91,6 +92,9 @@ function parseArgs(args) {
|
|
|
91
92
|
else if (a === '--title') out.title = args[++i];
|
|
92
93
|
else if (a === '--entry') out.entry = args[++i];
|
|
93
94
|
else if (a === '--type') out.type = args[++i];
|
|
95
|
+
else if (a === '--port') out.port = Number(args[++i]);
|
|
96
|
+
else if (a === '--preview-name') out.previewName = args[++i];
|
|
97
|
+
else if (a === '--preview-token') out.previewToken = args[++i];
|
|
94
98
|
else if (a === '--timeout') out.timeout = Number(args[++i]) * 1000;
|
|
95
99
|
else if (a === '--sender-agent-id') out.senderAgentId = args[++i];
|
|
96
100
|
else if (a === '--sender-token') out.senderToken = args[++i];
|
|
@@ -128,10 +132,74 @@ Commands:
|
|
|
128
132
|
upload-artifact --dir <path> Upload an OpenDesign/artifact directory to WTT
|
|
129
133
|
opendesign-upload --dir <path>
|
|
130
134
|
Alias for upload-artifact
|
|
135
|
+
preview-port --port <port> [--topic-id <id>]
|
|
136
|
+
Create a Cloud Sandbox port preview URL through sandbox outbox
|
|
131
137
|
help Show this help
|
|
132
138
|
`);
|
|
133
139
|
}
|
|
134
140
|
|
|
141
|
+
async function previewPort(config, argv) {
|
|
142
|
+
const port = Number(argv.port || argv._[0]);
|
|
143
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
144
|
+
throw new Error('preview-port requires --port <1-65535>');
|
|
145
|
+
}
|
|
146
|
+
const preview = await createSandboxPreviewFromOutbox(config, port, {
|
|
147
|
+
name: String(argv.previewName || argv.title || '').trim(),
|
|
148
|
+
token: String(argv.previewToken || '').trim(),
|
|
149
|
+
timeoutMs: Number(argv.timeout || 15000),
|
|
150
|
+
});
|
|
151
|
+
const url = preview.preview_url || preview.url;
|
|
152
|
+
if (!url) throw new Error('Cloud Sandbox preview API returned no URL');
|
|
153
|
+
const markdown = preview.markdown || `[preview_url](${url})`;
|
|
154
|
+
const topicId = String(argv.topicId || argv.sourceId || '').trim();
|
|
155
|
+
let published = null;
|
|
156
|
+
if (topicId) {
|
|
157
|
+
const wtt = new WTTClient(config, async () => {});
|
|
158
|
+
try {
|
|
159
|
+
await wtt.connectForActions();
|
|
160
|
+
published = await wtt.publish(topicId, markdown, argv.semanticType || 'CHAT_REPLY', {
|
|
161
|
+
type: 'cloud_sandbox_preview',
|
|
162
|
+
port,
|
|
163
|
+
preview_url: url,
|
|
164
|
+
});
|
|
165
|
+
} finally {
|
|
166
|
+
await wtt.close();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
console.log(JSON.stringify({ ok: true, port, url, preview_url: url, markdown, published }, null, 2));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function createSandboxPreviewFromOutbox(config, port, { name = '', token = '', timeoutMs = 15000 } = {}) {
|
|
173
|
+
if (!config.cloudSandbox && !process.env.WTT_SANDBOX_OUTBOX_URL) {
|
|
174
|
+
throw new Error('preview-port is only available inside a WTT Cloud Sandbox');
|
|
175
|
+
}
|
|
176
|
+
const base = String(process.env.WTT_SANDBOX_OUTBOX_URL || 'http://wtt.preview').replace(/\/+$/, '');
|
|
177
|
+
const response = await fetch(`${base}/preview-port`, {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
headers: { 'content-type': 'application/json' },
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
agent_id: config.agentId,
|
|
182
|
+
port,
|
|
183
|
+
...(name ? { name } : {}),
|
|
184
|
+
...(token ? { token } : {}),
|
|
185
|
+
}),
|
|
186
|
+
signal: AbortSignal.timeout(Math.max(1000, Math.min(Number(timeoutMs || 15000), 60000))),
|
|
187
|
+
});
|
|
188
|
+
const text = await response.text();
|
|
189
|
+
let data = {};
|
|
190
|
+
if (text) {
|
|
191
|
+
try {
|
|
192
|
+
data = JSON.parse(text);
|
|
193
|
+
} catch {
|
|
194
|
+
data = { detail: text };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!response.ok) {
|
|
198
|
+
throw new Error(`Cloud Sandbox outbox preview failed: ${data.detail || data.error || response.statusText || response.status}`);
|
|
199
|
+
}
|
|
200
|
+
return data;
|
|
201
|
+
}
|
|
202
|
+
|
|
135
203
|
async function uploadFile(config, argv) {
|
|
136
204
|
const topicId = String(argv.topicId || argv.sourceId || '').trim();
|
|
137
205
|
if (!topicId) throw new Error('upload-file requires --topic-id <topic_id>');
|
package/src/runner.js
CHANGED
|
@@ -221,7 +221,7 @@ export class Runner {
|
|
|
221
221
|
'',
|
|
222
222
|
staged.promptBlock,
|
|
223
223
|
renderTranscriptBlock(transcripts),
|
|
224
|
-
renderCloudSandboxStorageInstruction(this.config),
|
|
224
|
+
renderCloudSandboxStorageInstruction(this.config, topicId),
|
|
225
225
|
renderGeneratedFileArtifactInstruction(this.config, topicId),
|
|
226
226
|
'Reply naturally and concisely unless the user asks for detail.',
|
|
227
227
|
].filter(Boolean).join('\n');
|
|
@@ -917,7 +917,7 @@ function renderGeneratedFileArtifactInstruction(config, topicId = '') {
|
|
|
917
917
|
].join('\n');
|
|
918
918
|
}
|
|
919
919
|
|
|
920
|
-
function renderCloudSandboxStorageInstruction(config) {
|
|
920
|
+
function renderCloudSandboxStorageInstruction(config, topicId = '') {
|
|
921
921
|
if (!config.cloudSandbox) return '';
|
|
922
922
|
const workDir = config.workDir || process.cwd();
|
|
923
923
|
const persistentDir = String(config.persistentOutputDir || '').trim();
|
|
@@ -937,6 +937,7 @@ function renderCloudSandboxStorageInstruction(config) {
|
|
|
937
937
|
'- Do not install large dependencies, clone large repositories, download datasets, or write bulky generated files into the workspace unless the user explicitly asks for local temporary storage.',
|
|
938
938
|
'- Keep only source edits, small manifests, notes, and temporary scratch files in the workspace.',
|
|
939
939
|
'- If a generated user-facing file is stored in R2/persistent output storage and should appear in WTT chat, still publish it with `wtt-connect upload-file` or a WTT artifact marker.',
|
|
940
|
+
`- If you start a web server in the sandbox and the user should preview it, expose that port with: wtt-connect preview-port --port <port>${topicId ? ` --topic-id ${topicId}` : ' --topic-id <topic_id>'}. This calls the Cloudflare Sandbox outbound Worker directly to create a preview URL and does not use WTT backend preview or legacy artifact/media preview flows.`,
|
|
940
941
|
);
|
|
941
942
|
return lines.join('\n');
|
|
942
943
|
}
|
|
@@ -1381,7 +1382,7 @@ function buildTaskPrompt(task, config, staged = { promptBlock: '' }, transcripts
|
|
|
1381
1382
|
renderTranscriptBlock(transcripts),
|
|
1382
1383
|
'',
|
|
1383
1384
|
config.requireCommitPush ? 'For code changes, commit and push before final response, and include commit id.' : '',
|
|
1384
|
-
renderCloudSandboxStorageInstruction(config),
|
|
1385
|
+
renderCloudSandboxStorageInstruction(config, task.topic_id || task.topicId || ''),
|
|
1385
1386
|
renderGeneratedFileArtifactInstruction(config, task.topic_id || task.topicId || ''),
|
|
1386
1387
|
'Return a concise final summary with evidence, changed files, tests, artifacts, and blockers.',
|
|
1387
1388
|
].filter(Boolean).join('\n');
|