@clawling/clawchat-plugin-openclaw 2026.7.9-1 → 2026.7.9-4
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/dist/src/config.js +1 -5
- package/dist/src/liveware-sample.js +63 -16
- package/package.json +1 -1
- package/src/config.ts +1 -5
- package/src/liveware-sample.ts +70 -19
package/dist/src/config.js
CHANGED
|
@@ -353,11 +353,7 @@ export function resolveOpenclawClawlingAccount(cfg, env = process.env) {
|
|
|
353
353
|
const forwardToolCalls = typeof channel.forwardToolCalls === "boolean" ? channel.forwardToolCalls : false;
|
|
354
354
|
const richInteractions = typeof channel.richInteractions === "boolean" ? channel.richInteractions : false;
|
|
355
355
|
const awarenessNote = typeof channel.awarenessNote === "boolean" ? channel.awarenessNote : false;
|
|
356
|
-
|
|
357
|
-
// until the template distribution moves off raw.githubusercontent (rate
|
|
358
|
-
// limiting strands fresh agents). Flip the fallback back to true then.
|
|
359
|
-
// Explicit `livewareSample: true` in channel config still enables it.
|
|
360
|
-
const livewareSample = typeof channel.livewareSample === "boolean" ? channel.livewareSample : false;
|
|
356
|
+
const livewareSample = typeof channel.livewareSample === "boolean" ? channel.livewareSample : true;
|
|
361
357
|
return {
|
|
362
358
|
accountId: DEFAULT_ACCOUNT_ID,
|
|
363
359
|
name: CHANNEL_ID,
|
|
@@ -169,11 +169,52 @@ export function parseTunnelPublicUrl(output) {
|
|
|
169
169
|
}
|
|
170
170
|
return null;
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
/**
|
|
173
|
+
* One-shot upstream registration (CLI v0.0.11+): `tunnel bind` writes the
|
|
174
|
+
* app→local-upstream mapping to the control plane, prints the binding table
|
|
175
|
+
* and exits 0. The data plane is carried by the persistent `liveware agent`
|
|
176
|
+
* daemon (see startTunnelAgent) — bind itself no longer stays running.
|
|
177
|
+
*/
|
|
178
|
+
export async function tunnelBind(opts) {
|
|
179
|
+
const execFileFn = opts.execFileFn ?? nodeExecFile;
|
|
180
|
+
const output = await new Promise((resolve, reject) => {
|
|
181
|
+
execFileFn(opts.livewarePath, ["tunnel", "bind", opts.appId, `http://127.0.0.1:${opts.port}`], { timeout: CLI_TIMEOUT_MS }, (err, out, errOut) => {
|
|
182
|
+
if (err) {
|
|
183
|
+
reject(new Error(`liveware tunnel bind failed: ${errOut || out || String(err)}`.trim()));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
resolve(`${String(out ?? "")}\n${String(errOut ?? "")}`);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
const url = parseTunnelPublicUrl(output);
|
|
190
|
+
if (!url)
|
|
191
|
+
throw new Error(`liveware tunnel bind: cannot parse public URL from output: ${output.slice(0, 500)}`);
|
|
192
|
+
return url;
|
|
193
|
+
}
|
|
194
|
+
const AGENT_READY_MARKER = "relay grpc control connected";
|
|
195
|
+
/**
|
|
196
|
+
* Match the `liveware agent` ready signal: the daemon logs a JSON line once
|
|
197
|
+
* its gRPC control channel to the relay is up — only then can the public URL
|
|
198
|
+
* actually reach the local upstream.
|
|
199
|
+
*/
|
|
200
|
+
export function parseAgentReady(output) {
|
|
201
|
+
for (const ln of (output ?? "").split("\n")) {
|
|
202
|
+
if (ln.includes(AGENT_READY_MARKER))
|
|
203
|
+
return ln;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Spawn the persistent `liveware agent` data-plane daemon (CLI v0.0.11+;
|
|
209
|
+
* replaces the long-lived `tunnel bind` / sibling tunnel-agent binary). It
|
|
210
|
+
* authenticates from the token saved by `liveware login` and serves every
|
|
211
|
+
* app bound via `tunnel bind` for that account.
|
|
212
|
+
*/
|
|
213
|
+
export async function startTunnelAgent(opts) {
|
|
173
214
|
const spawnFn = opts.spawnFn ?? nodeSpawn;
|
|
174
|
-
const child = spawnFn(opts.livewarePath, ["
|
|
175
|
-
|
|
176
|
-
return { child
|
|
215
|
+
const child = spawnFn(opts.livewarePath, ["agent"], { stdio: ["ignore", "pipe", "pipe"] });
|
|
216
|
+
await waitForOutput(child, (acc) => parseAgentReady(acc), opts.timeoutMs ?? TUNNEL_START_TIMEOUT_MS, "liveware agent start");
|
|
217
|
+
return { child };
|
|
177
218
|
}
|
|
178
219
|
export async function livewareLogin(opts) {
|
|
179
220
|
const execFileFn = opts.execFileFn ?? nodeExecFile;
|
|
@@ -392,21 +433,24 @@ export class LivewareSampleSupervisor {
|
|
|
392
433
|
const appId = await livewareAppCreate({
|
|
393
434
|
livewarePath, name: LIVEWARE_SAMPLE_APP_NAME, execFileFn: deps.execFileFn,
|
|
394
435
|
});
|
|
395
|
-
const
|
|
396
|
-
livewarePath, appId, port: server.port,
|
|
436
|
+
const publicUrl = await tunnelBind({
|
|
437
|
+
livewarePath, appId, port: server.port, execFileFn: deps.execFileFn,
|
|
397
438
|
});
|
|
398
|
-
this.tunnelChild = tunnel.child;
|
|
399
439
|
if (this.bailIfStopped())
|
|
400
440
|
return;
|
|
401
|
-
await
|
|
441
|
+
const agent = await startTunnelAgent({ livewarePath, spawnFn: deps.spawnFn });
|
|
442
|
+
this.tunnelChild = agent.child;
|
|
443
|
+
if (this.bailIfStopped())
|
|
444
|
+
return;
|
|
445
|
+
await deps.registerApp({ name: LIVEWARE_SAMPLE_APP_NAME, appId, url: publicUrl });
|
|
402
446
|
deps.store.upsertLivewareSample({
|
|
403
447
|
platform: deps.platform, accountId: deps.accountId,
|
|
404
448
|
appId, appName: LIVEWARE_SAMPLE_APP_NAME, port: server.port,
|
|
405
|
-
publicUrl
|
|
449
|
+
publicUrl, sampleVersion: version, status: "active",
|
|
406
450
|
});
|
|
407
451
|
this.watchChildren();
|
|
408
452
|
await this.deliverIntro();
|
|
409
|
-
deps.log?.debug?.(`liveware-sample: bootstrap complete at ${
|
|
453
|
+
deps.log?.debug?.(`liveware-sample: bootstrap complete at ${publicUrl}`);
|
|
410
454
|
}
|
|
411
455
|
async relaunch(row) {
|
|
412
456
|
const { deps } = this;
|
|
@@ -456,21 +500,24 @@ export class LivewareSampleSupervisor {
|
|
|
456
500
|
this.serverChild = server.child;
|
|
457
501
|
if (this.bailIfStopped())
|
|
458
502
|
return;
|
|
459
|
-
const
|
|
460
|
-
livewarePath, appId: row.app_id, port: server.port,
|
|
503
|
+
const publicUrl = await tunnelBind({
|
|
504
|
+
livewarePath, appId: row.app_id, port: server.port, execFileFn: deps.execFileFn,
|
|
461
505
|
});
|
|
462
|
-
this.tunnelChild = tunnel.child;
|
|
463
506
|
if (this.bailIfStopped())
|
|
464
507
|
return;
|
|
465
|
-
|
|
508
|
+
const agent = await startTunnelAgent({ livewarePath, spawnFn: deps.spawnFn });
|
|
509
|
+
this.tunnelChild = agent.child;
|
|
510
|
+
if (this.bailIfStopped())
|
|
511
|
+
return;
|
|
512
|
+
if (publicUrl !== row.public_url) {
|
|
466
513
|
await deps.registerApp({
|
|
467
|
-
name: row.app_name, appId: row.app_id, url:
|
|
514
|
+
name: row.app_name, appId: row.app_id, url: publicUrl,
|
|
468
515
|
});
|
|
469
516
|
}
|
|
470
517
|
deps.store.upsertLivewareSample({
|
|
471
518
|
platform: deps.platform, accountId: deps.accountId,
|
|
472
519
|
appId: row.app_id, appName: row.app_name, port: server.port,
|
|
473
|
-
publicUrl
|
|
520
|
+
publicUrl, sampleVersion: version, status: "active",
|
|
474
521
|
});
|
|
475
522
|
this.watchChildren();
|
|
476
523
|
if (row.intro_sent === 0)
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -519,12 +519,8 @@ export function resolveOpenclawClawlingAccount(
|
|
|
519
519
|
typeof channel.richInteractions === "boolean" ? channel.richInteractions : false;
|
|
520
520
|
const awarenessNote =
|
|
521
521
|
typeof channel.awarenessNote === "boolean" ? channel.awarenessNote : false;
|
|
522
|
-
// TEMPORARY default-off: liveware-sample auto-boot is disabled by default
|
|
523
|
-
// until the template distribution moves off raw.githubusercontent (rate
|
|
524
|
-
// limiting strands fresh agents). Flip the fallback back to true then.
|
|
525
|
-
// Explicit `livewareSample: true` in channel config still enables it.
|
|
526
522
|
const livewareSample =
|
|
527
|
-
typeof channel.livewareSample === "boolean" ? channel.livewareSample :
|
|
523
|
+
typeof channel.livewareSample === "boolean" ? channel.livewareSample : true;
|
|
528
524
|
|
|
529
525
|
return {
|
|
530
526
|
accountId: DEFAULT_ACCOUNT_ID,
|
package/src/liveware-sample.ts
CHANGED
|
@@ -224,26 +224,73 @@ export function parseTunnelPublicUrl(output: string): string | null {
|
|
|
224
224
|
return null;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
/**
|
|
228
|
+
* One-shot upstream registration (CLI v0.0.11+): `tunnel bind` writes the
|
|
229
|
+
* app→local-upstream mapping to the control plane, prints the binding table
|
|
230
|
+
* and exits 0. The data plane is carried by the persistent `liveware agent`
|
|
231
|
+
* daemon (see startTunnelAgent) — bind itself no longer stays running.
|
|
232
|
+
*/
|
|
233
|
+
export async function tunnelBind(opts: {
|
|
228
234
|
livewarePath: string;
|
|
229
235
|
appId: string;
|
|
230
236
|
port: number;
|
|
237
|
+
execFileFn?: ExecFileLike;
|
|
238
|
+
}): Promise<string> {
|
|
239
|
+
const execFileFn = opts.execFileFn ?? nodeExecFile;
|
|
240
|
+
const output = await new Promise<string>((resolve, reject) => {
|
|
241
|
+
execFileFn(
|
|
242
|
+
opts.livewarePath,
|
|
243
|
+
["tunnel", "bind", opts.appId, `http://127.0.0.1:${opts.port}`],
|
|
244
|
+
{ timeout: CLI_TIMEOUT_MS },
|
|
245
|
+
(err, out, errOut) => {
|
|
246
|
+
if (err) { reject(new Error(`liveware tunnel bind failed: ${errOut || out || String(err)}`.trim())); return; }
|
|
247
|
+
resolve(`${String(out ?? "")}\n${String(errOut ?? "")}`);
|
|
248
|
+
},
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
const url = parseTunnelPublicUrl(output);
|
|
252
|
+
if (!url) throw new Error(`liveware tunnel bind: cannot parse public URL from output: ${output.slice(0, 500)}`);
|
|
253
|
+
return url;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const AGENT_READY_MARKER = "relay grpc control connected";
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Match the `liveware agent` ready signal: the daemon logs a JSON line once
|
|
260
|
+
* its gRPC control channel to the relay is up — only then can the public URL
|
|
261
|
+
* actually reach the local upstream.
|
|
262
|
+
*/
|
|
263
|
+
export function parseAgentReady(output: string): string | null {
|
|
264
|
+
for (const ln of (output ?? "").split("\n")) {
|
|
265
|
+
if (ln.includes(AGENT_READY_MARKER)) return ln;
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Spawn the persistent `liveware agent` data-plane daemon (CLI v0.0.11+;
|
|
272
|
+
* replaces the long-lived `tunnel bind` / sibling tunnel-agent binary). It
|
|
273
|
+
* authenticates from the token saved by `liveware login` and serves every
|
|
274
|
+
* app bound via `tunnel bind` for that account.
|
|
275
|
+
*/
|
|
276
|
+
export async function startTunnelAgent(opts: {
|
|
277
|
+
livewarePath: string;
|
|
231
278
|
spawnFn?: SpawnLike;
|
|
232
279
|
timeoutMs?: number;
|
|
233
|
-
}): Promise<{ child: ChildProcess
|
|
280
|
+
}): Promise<{ child: ChildProcess }> {
|
|
234
281
|
const spawnFn = opts.spawnFn ?? nodeSpawn;
|
|
235
282
|
const child = spawnFn(
|
|
236
283
|
opts.livewarePath,
|
|
237
|
-
["
|
|
284
|
+
["agent"],
|
|
238
285
|
{ stdio: ["ignore", "pipe", "pipe"] },
|
|
239
286
|
);
|
|
240
|
-
|
|
287
|
+
await waitForOutput(
|
|
241
288
|
child,
|
|
242
|
-
(acc) =>
|
|
289
|
+
(acc) => parseAgentReady(acc),
|
|
243
290
|
opts.timeoutMs ?? TUNNEL_START_TIMEOUT_MS,
|
|
244
|
-
"liveware
|
|
291
|
+
"liveware agent start",
|
|
245
292
|
);
|
|
246
|
-
return { child
|
|
293
|
+
return { child };
|
|
247
294
|
}
|
|
248
295
|
|
|
249
296
|
export async function livewareLogin(opts: {
|
|
@@ -499,20 +546,22 @@ export class LivewareSampleSupervisor {
|
|
|
499
546
|
const appId = await livewareAppCreate({
|
|
500
547
|
livewarePath, name: LIVEWARE_SAMPLE_APP_NAME, execFileFn: deps.execFileFn,
|
|
501
548
|
});
|
|
502
|
-
const
|
|
503
|
-
livewarePath, appId, port: server.port,
|
|
549
|
+
const publicUrl = await tunnelBind({
|
|
550
|
+
livewarePath, appId, port: server.port, execFileFn: deps.execFileFn,
|
|
504
551
|
});
|
|
505
|
-
this.tunnelChild = tunnel.child;
|
|
506
552
|
if (this.bailIfStopped()) return;
|
|
507
|
-
await
|
|
553
|
+
const agent = await startTunnelAgent({ livewarePath, spawnFn: deps.spawnFn });
|
|
554
|
+
this.tunnelChild = agent.child;
|
|
555
|
+
if (this.bailIfStopped()) return;
|
|
556
|
+
await deps.registerApp({ name: LIVEWARE_SAMPLE_APP_NAME, appId, url: publicUrl });
|
|
508
557
|
deps.store.upsertLivewareSample({
|
|
509
558
|
platform: deps.platform, accountId: deps.accountId,
|
|
510
559
|
appId, appName: LIVEWARE_SAMPLE_APP_NAME, port: server.port,
|
|
511
|
-
publicUrl
|
|
560
|
+
publicUrl, sampleVersion: version, status: "active",
|
|
512
561
|
});
|
|
513
562
|
this.watchChildren();
|
|
514
563
|
await this.deliverIntro();
|
|
515
|
-
deps.log?.debug?.(`liveware-sample: bootstrap complete at ${
|
|
564
|
+
deps.log?.debug?.(`liveware-sample: bootstrap complete at ${publicUrl}`);
|
|
516
565
|
}
|
|
517
566
|
|
|
518
567
|
private async relaunch(row: LivewareSampleRow): Promise<void> {
|
|
@@ -554,20 +603,22 @@ export class LivewareSampleSupervisor {
|
|
|
554
603
|
});
|
|
555
604
|
this.serverChild = server.child;
|
|
556
605
|
if (this.bailIfStopped()) return;
|
|
557
|
-
const
|
|
558
|
-
livewarePath, appId: row.app_id, port: server.port,
|
|
606
|
+
const publicUrl = await tunnelBind({
|
|
607
|
+
livewarePath, appId: row.app_id, port: server.port, execFileFn: deps.execFileFn,
|
|
559
608
|
});
|
|
560
|
-
this.tunnelChild = tunnel.child;
|
|
561
609
|
if (this.bailIfStopped()) return;
|
|
562
|
-
|
|
610
|
+
const agent = await startTunnelAgent({ livewarePath, spawnFn: deps.spawnFn });
|
|
611
|
+
this.tunnelChild = agent.child;
|
|
612
|
+
if (this.bailIfStopped()) return;
|
|
613
|
+
if (publicUrl !== row.public_url) {
|
|
563
614
|
await deps.registerApp({
|
|
564
|
-
name: row.app_name, appId: row.app_id, url:
|
|
615
|
+
name: row.app_name, appId: row.app_id, url: publicUrl,
|
|
565
616
|
});
|
|
566
617
|
}
|
|
567
618
|
deps.store.upsertLivewareSample({
|
|
568
619
|
platform: deps.platform, accountId: deps.accountId,
|
|
569
620
|
appId: row.app_id, appName: row.app_name, port: server.port,
|
|
570
|
-
publicUrl
|
|
621
|
+
publicUrl, sampleVersion: version, status: "active",
|
|
571
622
|
});
|
|
572
623
|
this.watchChildren();
|
|
573
624
|
if (row.intro_sent === 0) await this.deliverIntro();
|