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.
- package/dist/index.js +53 -48
- 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
|
|
4730
|
-
if (fs6.existsSync(DEVICE_FILE))
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
}
|
|
4737
|
-
}
|
|
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
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
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 });
|