agentlife 1.1.6 → 1.1.8

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.
Files changed (2) hide show
  1. package/dist/index.js +53 -48
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1265,6 +1265,10 @@ Do NOT call agentlife.createAgent. Do NOT write workspace files. Do NOT spawn su
1265
1265
 
1266
1266
  When you receive \`[system:dismiss-requested] surfaceId=vision-{slug}\` — this is vision-specific dismiss handling. It is a third mode, distinct from agent creation and from dashboard bootstrap, and it OVERRIDES the general dismiss-alt protocol described elsewhere.
1267
1267
 
1268
+ **CRITICAL — session scope:** this section applies ONLY on your DIRECT session (where the user is live and can see widgets). The platform also notifies your INTERNAL session with the same \`[system:dismiss-requested]\` message as a cleanup hook AFTER the widget is already deleted. If you see this message on an internal session, do NOT push a dismiss-alt, do NOT run the steps below — the widget is gone and pushing a questionnaire creates a ghost surface that nobody can interact with. On internal sessions, output "done" and stop.
1269
+
1270
+ Direct session vs internal session: internal sessions receive the "Internal Session — Self-Improvement Protocol" preamble at the top of their system prompt. If you see that preamble in your context, you are on an internal session; this Vision Dismiss section does NOT apply to you, output "done".
1271
+
1268
1272
  The general dismiss-alt rule says "craft 2-3 contextual alternatives from the widget's goal." For vision posters that rule does NOT apply. Vision posters are aspirational content with a closed ontology of failure modes — the user is rejecting either the dream itself, its framing, its timing, or its dashboard placement. Improvising alternatives per dismiss would produce inconsistent wording across dismissals, which reads as broken UX. Use the fixed wording below verbatim.
1269
1273
 
1270
1274
  ### Step 1 — Push the dismiss-alt input surface
@@ -4726,16 +4730,24 @@ function ensureDirs() {
4726
4730
  if (!fs6.existsSync(BIN_DIR))
4727
4731
  fs6.mkdirSync(BIN_DIR, { recursive: true, mode: 448 });
4728
4732
  }
4729
- function loadOrCreateDeviceIdentity() {
4730
- if (fs6.existsSync(DEVICE_FILE)) {
4731
- try {
4732
- const raw = fs6.readFileSync(DEVICE_FILE, "utf-8");
4733
- const parsed = JSON.parse(raw);
4734
- if (typeof parsed.deviceId === "string" && typeof parsed.deviceSecret === "string") {
4735
- return { deviceId: parsed.deviceId, deviceSecret: parsed.deviceSecret };
4736
- }
4737
- } catch {}
4733
+ function loadDeviceIdentity() {
4734
+ if (!fs6.existsSync(DEVICE_FILE))
4735
+ return null;
4736
+ try {
4737
+ const raw = fs6.readFileSync(DEVICE_FILE, "utf-8");
4738
+ const parsed = JSON.parse(raw);
4739
+ if (typeof parsed.deviceId === "string" && typeof parsed.deviceSecret === "string") {
4740
+ return { deviceId: parsed.deviceId, deviceSecret: parsed.deviceSecret };
4741
+ }
4742
+ return null;
4743
+ } catch {
4744
+ return null;
4738
4745
  }
4746
+ }
4747
+ function loadOrCreateDeviceIdentity() {
4748
+ const existing = loadDeviceIdentity();
4749
+ if (existing)
4750
+ return existing;
4739
4751
  const identity = {
4740
4752
  deviceId: crypto2.randomUUID(),
4741
4753
  deviceSecret: crypto2.randomBytes(32).toString("base64url")
@@ -4747,6 +4759,7 @@ function loadOrCreateDeviceIdentity() {
4747
4759
  console.log(`[cloudflared-supervisor] generated new device identity (deviceId=${identity.deviceId})`);
4748
4760
  return identity;
4749
4761
  }
4762
+ var AGENTLIFE_API_BASE = API_BASE;
4750
4763
  function loadCachedTunnel() {
4751
4764
  if (!fs6.existsSync(TUNNEL_FILE))
4752
4765
  return null;
@@ -5124,57 +5137,22 @@ function registerWebApp(api) {
5124
5137
 
5125
5138
  // services/pairing.ts
5126
5139
  var TUNNEL_READY_TIMEOUT_MS = 90000;
5127
- async function detectTunnelUrl(port) {
5128
- try {
5129
- const cfgPath = path10.join(os6.homedir(), ".cloudflared", "config.yml");
5130
- if (!fsSync3.existsSync(cfgPath))
5131
- return null;
5132
- const cfg = fsSync3.readFileSync(cfgPath, "utf-8");
5133
- const lines = cfg.split(`
5134
- `);
5135
- for (let i = 0;i < lines.length; i++) {
5136
- const hostMatch = lines[i].match(/hostname:\s*(.+)/);
5137
- if (hostMatch) {
5138
- const nextLine = lines[i + 1] || "";
5139
- const svcMatch = nextLine.match(/service:\s*http:\/\/localhost:(\d+)/);
5140
- if (svcMatch && parseInt(svcMatch[1]) === port) {
5141
- return `wss://${hostMatch[1].trim()}`;
5142
- }
5143
- }
5144
- }
5145
- return null;
5146
- } catch {
5147
- return null;
5148
- }
5149
- }
5150
5140
  function registerPairingServices(api) {
5151
5141
  api.registerService({
5152
5142
  id: "agentlife-pairing-qr",
5153
5143
  start: async (_ctx) => {
5154
5144
  try {
5155
5145
  const cfg = api.runtime.config.loadConfig();
5156
- const bind = cfg.gateway?.bind ?? "loopback";
5157
5146
  const port = cfg.gateway?.port ?? 18789;
5158
5147
  const token = cfg.gateway?.auth?.token;
5159
5148
  if (!token)
5160
5149
  return;
5161
5150
  const supervisorTunnel = await awaitTunnelReady(TUNNEL_READY_TIMEOUT_MS) ?? getTunnelInfo();
5162
- let url;
5163
- if (supervisorTunnel?.tunnelUrl) {
5164
- url = supervisorTunnel.tunnelUrl;
5165
- } else {
5166
- console.warn("[agentlife] Tunnel not ready after " + TUNNEL_READY_TIMEOUT_MS / 1000 + "s — falling back to LAN URL. Phone pairing will only work on the same Wi-Fi.");
5167
- const userTunnel = await detectTunnelUrl(port);
5168
- if (userTunnel) {
5169
- url = userTunnel;
5170
- } else if (bind === "lan" || bind === "auto" || bind === "custom") {
5171
- const nets = os6.networkInterfaces();
5172
- const lanIp = Object.values(nets).flat().find((n) => n && !n.internal && n.family === "IPv4")?.address;
5173
- url = `ws://${lanIp ?? "127.0.0.1"}:${port}`;
5174
- } else {
5175
- url = `ws://127.0.0.1:${port}`;
5176
- }
5151
+ if (!supervisorTunnel?.tunnelUrl) {
5152
+ console.warn(`[agentlife] Cloudflared tunnel did not come up within ${TUNNEL_READY_TIMEOUT_MS / 1000}s — ` + `pairing QR will not be emitted. Check cloudflared-supervisor logs in the gateway output.`);
5153
+ return;
5177
5154
  }
5155
+ const url = supervisorTunnel.tunnelUrl;
5178
5156
  const bootstrapToken = mintBootstrapToken();
5179
5157
  const payload = JSON.stringify({ url, bootstrapToken });
5180
5158
  const setupCode = Buffer.from(payload).toString("base64url");
@@ -6709,6 +6687,33 @@ function registerAdminGateway(api, state2) {
6709
6687
  try {
6710
6688
  const cleaned = [];
6711
6689
  const baseDir = state2.agentlifeStateDir ?? path12.join(os7.homedir(), ".openclaw", "agentlife");
6690
+ const identity = loadDeviceIdentity();
6691
+ if (!identity) {
6692
+ cleaned.push("server deprovision skipped (no device identity)");
6693
+ } else {
6694
+ try {
6695
+ const res = await fetch(`${AGENTLIFE_API_BASE}/api/v1/devices/deprovision`, {
6696
+ method: "POST",
6697
+ headers: { "Content-Type": "application/json" },
6698
+ body: JSON.stringify({
6699
+ deviceId: identity.deviceId,
6700
+ deviceSecret: identity.deviceSecret
6701
+ }),
6702
+ signal: AbortSignal.timeout(1e4)
6703
+ });
6704
+ if (res.ok) {
6705
+ cleaned.push("deprovisioned tunnel on server");
6706
+ } else if (res.status === 404) {
6707
+ cleaned.push("server had no record of this device (already gone)");
6708
+ } else {
6709
+ cleaned.push(`server deprovision returned HTTP ${res.status} (continuing)`);
6710
+ console.warn(`[agentlife] uninstall: deprovision HTTP ${res.status}, continuing with local cleanup`);
6711
+ }
6712
+ } catch (err) {
6713
+ cleaned.push(`server deprovision failed (continuing): ${err?.message ?? "unknown error"}`);
6714
+ console.warn(`[agentlife] uninstall: deprovision failed (${err?.message ?? err}), continuing with local cleanup`);
6715
+ }
6716
+ }
6712
6717
  if (state2.runCommand) {
6713
6718
  try {
6714
6719
  const result = await state2.runCommand(["openclaw", "cron", "list", "--json"], { timeoutMs: 1e4 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlife",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "bun build index.ts --outfile dist/index.js --target node --external openclaw/plugin-sdk",