dsh-agentic-pet 0.4.1 → 0.4.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/carrier/lib/main.js +8 -1
- package/client/pet-settings.js +14 -13
- package/lib/index.js +63 -15
- package/package.json +10 -2
package/carrier/lib/main.js
CHANGED
|
@@ -1022,13 +1022,20 @@ async function main() {
|
|
|
1022
1022
|
// kill only runs on the runtime's graceful shutdown; a terminated runtime
|
|
1023
1023
|
// leaves a detached pet orphaned on the desktop. Poll the spawning
|
|
1024
1024
|
// runtime's pid and exit with it.
|
|
1025
|
+
//
|
|
1026
|
+
// Only ESRCH means gone: a confined carrier can run at a lower integrity
|
|
1027
|
+
// level than the runtime, where probing a heavier process answers EPERM —
|
|
1028
|
+
// "it exists, you may not signal it". Counting that as death made the pet
|
|
1029
|
+
// quit ten seconds after an otherwise fine start.
|
|
1025
1030
|
const runtimePid = Number(process.env.DSH_PET_RUNTIME_PID);
|
|
1026
1031
|
if (Number.isInteger(runtimePid) && runtimePid > 0) {
|
|
1027
1032
|
setInterval(() => {
|
|
1028
1033
|
try {
|
|
1029
1034
|
process.kill(runtimePid, 0);
|
|
1030
1035
|
}
|
|
1031
|
-
catch {
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
if (error.code !== 'ESRCH')
|
|
1038
|
+
return;
|
|
1032
1039
|
console.log('[pet] the spawning runtime is gone; exiting');
|
|
1033
1040
|
app.quit();
|
|
1034
1041
|
}
|
package/client/pet-settings.js
CHANGED
|
@@ -117,20 +117,19 @@ window.__ModuleLoader__.load({
|
|
|
117
117
|
var custom = settings.names && settings.names[id]
|
|
118
118
|
return custom ? String(custom) : defaultName(id)
|
|
119
119
|
}
|
|
120
|
-
//
|
|
121
|
-
//
|
|
120
|
+
// 提交一次改名(失焦/回车调用):与当前生效名比较,无变化零开销。
|
|
121
|
+
// 清空或改回内置名 = 发空串,宿主据此删掉 pet-name.json、回落到默认名。
|
|
122
|
+
// 早先这里删键后发的是 {},而宿主是按 patch 里的键逐个写的——空对象等于
|
|
123
|
+
// 零次写入,"改回默认名"因此是一次静默的空操作。
|
|
122
124
|
var commitName = function (id, raw) {
|
|
123
125
|
var v = (raw || '').trim()
|
|
124
|
-
var next =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
delete next[id]
|
|
132
|
-
}
|
|
133
|
-
update({ names: next })
|
|
126
|
+
var next = v === '' || v === defaultName(id) ? '' : v
|
|
127
|
+
// 比较"生效名"而不是 patch:本来就用默认名时,清空/再输默认名是一次
|
|
128
|
+
// 无变化的编辑,不该发请求(否则每次点进输入框失焦都会 POST 一遍)。
|
|
129
|
+
if ((next === '' ? defaultName(id) : next) === petName(id)) return
|
|
130
|
+
var patch = {}
|
|
131
|
+
patch[id] = next
|
|
132
|
+
update({ names: patch })
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
function update(patch, doneMessage) { act(UPDATE, { patch: patch }, doneMessage) }
|
|
@@ -189,7 +188,9 @@ window.__ModuleLoader__.load({
|
|
|
189
188
|
// Uncontrolled + commit-on-blur/Enter: typing is LOCAL until the
|
|
190
189
|
// edit completes — a per-keystroke update would fire a [改名]
|
|
191
190
|
// turn per character.清空 + 失焦 = 恢复默认名。
|
|
192
|
-
|
|
191
|
+
// key 钉在当前生效名上:设置异步到达或改名成功后重挂,输入框
|
|
192
|
+
// 才不会停在首帧的默认值上(曾显示"鲸鱼娘"而实际存着自定义名)。
|
|
193
|
+
h('input', { key: 'name-' + petName(p.id), style: Object.assign({}, inputStyle, { width: 120, fontWeight: 700 }), defaultValue: petName(p.id), title: '改名后点击空白处或回车生效;清空恢复默认',
|
|
193
194
|
onBlur: function (e) { commitName(p.id, e.target.value) },
|
|
194
195
|
onKeyDown: function (e) { if (e.key === 'Enter') { commitName(p.id, e.target.value); e.target.blur() } } }),
|
|
195
196
|
p.online
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { c as globalFilePath, d as readJsonl, f as readPetName, h as writePetName, i as installPetDriver, l as readAffectionRaw, m as writeGlobalJson, n as installPetService, p as writeAffectionRaw, r as petHome, s as eventsFile, u as readGlobalJson } from "./service-BjTawwUn.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import { spawn } from "node:child_process";
|
|
3
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
6
6
|
import { mkdir, readFile, rm, unlink, writeFile } from "node:fs/promises";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { dirname, extname, join, normalize, resolve, sep } from "node:path";
|
|
@@ -646,31 +646,79 @@ function apply(ctx) {
|
|
|
646
646
|
} catch {}
|
|
647
647
|
return process.versions.electron !== void 0 ? process.execPath : void 0;
|
|
648
648
|
};
|
|
649
|
+
/** Carrier spawn diagnostics; the packaged host's stderr is not visible. */
|
|
650
|
+
const logCarrier = (line) => {
|
|
651
|
+
try {
|
|
652
|
+
appendFileSync(join(dirname(petLocatorPath()), "carrier-spawn.log"), `${(/* @__PURE__ */ new Date()).toISOString()} ${line}\n`, "utf8");
|
|
653
|
+
} catch {}
|
|
654
|
+
};
|
|
649
655
|
const spawnPetCarrier = (url) => {
|
|
650
656
|
const carrierDir = resolve(join(dirname(fileURLToPath(import.meta.url)), "..", "carrier"));
|
|
651
657
|
const electronBinary = resolveElectronBinary();
|
|
652
658
|
if (process.env.DSH_PET_NO_SPAWN === "1" || electronBinary === void 0 || !existsSync(join(carrierDir, "package.json"))) return;
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
659
|
+
let probeStatus = "unstarted";
|
|
660
|
+
const startsSandboxed = (() => {
|
|
661
|
+
try {
|
|
662
|
+
const probe = spawnSync(electronBinary, ["--version"], {
|
|
663
|
+
env: stripRunAsNode(process.env),
|
|
664
|
+
stdio: "ignore",
|
|
665
|
+
timeout: 5e3
|
|
666
|
+
});
|
|
667
|
+
probeStatus = probe.error === void 0 ? `status=${String(probe.status)}` : `error=${String(probe.error.code ?? probe.error.message)}`;
|
|
668
|
+
return probe.status === 0;
|
|
669
|
+
} catch (error) {
|
|
670
|
+
probeStatus = `throw=${error instanceof Error ? error.message : String(error)}`;
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
})();
|
|
674
|
+
const launchArgs = [carrierDir];
|
|
675
|
+
if (!startsSandboxed) {
|
|
676
|
+
console.error("pet-surface: this machine cannot start a sandboxed Electron; launching the carrier with --no-sandbox");
|
|
677
|
+
const carrierUserData = join(dirname(petLocatorPath()), "carrier-userdata");
|
|
678
|
+
try {
|
|
679
|
+
mkdirSync(carrierUserData, { recursive: true });
|
|
680
|
+
} catch {}
|
|
681
|
+
launchArgs.push("--no-sandbox", `--user-data-dir=${carrierUserData}`);
|
|
682
|
+
}
|
|
683
|
+
logCarrier(`spawn binary=${electronBinary} args=${JSON.stringify(launchArgs)} probe=${probeStatus} pid=${String(process.pid)}`);
|
|
684
|
+
const child = (() => {
|
|
685
|
+
try {
|
|
686
|
+
return spawn(electronBinary, launchArgs, {
|
|
687
|
+
env: {
|
|
688
|
+
...stripRunAsNode(process.env),
|
|
689
|
+
DSH_PET_URL: url,
|
|
690
|
+
DSH_PET_RUNTIME_PID: String(process.pid)
|
|
691
|
+
},
|
|
692
|
+
detached: true,
|
|
693
|
+
stdio: [
|
|
694
|
+
"ignore",
|
|
695
|
+
"pipe",
|
|
696
|
+
"pipe"
|
|
697
|
+
]
|
|
698
|
+
});
|
|
699
|
+
} catch (error) {
|
|
700
|
+
logCarrier(`spawn threw: ${error instanceof Error ? error.message : String(error)}`);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
})();
|
|
704
|
+
if (child === void 0) return;
|
|
705
|
+
logCarrier(`spawned pid=${String(child.pid ?? "unknown")}`);
|
|
706
|
+
let stderrTail = "";
|
|
666
707
|
child.stdout?.setEncoding("utf8");
|
|
667
708
|
child.stdout?.on("data", (chunk) => {
|
|
668
709
|
process.stdout.write(`[pet-carrier] ${chunk}`);
|
|
669
710
|
});
|
|
670
711
|
child.stderr?.setEncoding("utf8");
|
|
671
712
|
child.stderr?.on("data", (chunk) => {
|
|
713
|
+
stderrTail = (stderrTail + chunk).slice(-2e3);
|
|
672
714
|
process.stderr.write(`[pet-carrier] ${chunk}`);
|
|
673
715
|
});
|
|
716
|
+
child.on("error", (error) => {
|
|
717
|
+
logCarrier(`child error: ${error.message}`);
|
|
718
|
+
});
|
|
719
|
+
child.on("exit", (code, signal) => {
|
|
720
|
+
logCarrier(`child exit code=${String(code)} signal=${String(signal)} stderr=${JSON.stringify(stderrTail.slice(-700))}`);
|
|
721
|
+
});
|
|
674
722
|
child.unref();
|
|
675
723
|
ctx.effect(() => () => {
|
|
676
724
|
child.kill();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agentic-pet",
|
|
3
3
|
"description": "The pet-surface bundle: serves the desktop pet renderer over the web composition, turning dsh into a surface the desktop pet attaches to as an authenticated client",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.3",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -57,5 +57,13 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@deepseek-ai/cordis": "^4.0.5"
|
|
60
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"repository": {
|
|
62
|
+
"type": "git",
|
|
63
|
+
"url": "git+https://github.com/beyondgjc/dsh-agentic-pet.git"
|
|
64
|
+
},
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/beyondgjc/dsh-agentic-pet/issues"
|
|
67
|
+
},
|
|
68
|
+
"homepage": "https://github.com/beyondgjc/dsh-agentic-pet#readme"
|
|
61
69
|
}
|