dsh-agentic-pet 0.4.2 → 0.4.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.
@@ -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
  }
@@ -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
- // 空值删键(回落默认)。一次编辑 = 至多一次 update = 至多一条 [改名]。
120
+ // 提交一次改名(失焦/回车调用):与当前生效名比较,无变化零开销。
121
+ // 清空或改回内置名 = 发空串,宿主据此删掉 pet-name.json、回落到默认名。
122
+ // 早先这里删键后发的是 {},而宿主是按 patch 里的键逐个写的——空对象等于
123
+ // 零次写入,"改回默认名"因此是一次静默的空操作。
122
124
  var commitName = function (id, raw) {
123
125
  var v = (raw || '').trim()
124
- var next = Object.assign({}, (settings.names || {}))
125
- var current = next[id]
126
- if (v !== '' && v !== defaultName(id)) {
127
- if (current === v) return
128
- next[id] = v
129
- } else {
130
- if (current === undefined) return
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
- h('input', { style: Object.assign({}, inputStyle, { width: 120, fontWeight: 700 }), defaultValue: petName(p.id), title: '改名后点击空白处或回车生效;清空恢复默认',
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
@@ -2,7 +2,7 @@ import { c as globalFilePath, d as readJsonl, f as readPetName, h as writePetNam
2
2
  import { createRequire } from "node:module";
3
3
  import { spawn } from "node:child_process";
4
4
  import { createHash } from "node:crypto";
5
- import { existsSync, readFileSync } from "node:fs";
5
+ import { appendFileSync, existsSync, 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,57 @@ 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
- const child = spawn(electronBinary, [carrierDir], {
654
- env: {
655
- ...stripRunAsNode(process.env),
656
- DSH_PET_URL: url,
657
- DSH_PET_RUNTIME_PID: String(process.pid)
658
- },
659
- detached: true,
660
- stdio: [
661
- "ignore",
662
- "pipe",
663
- "pipe"
664
- ]
665
- });
659
+ const launchArgs = [carrierDir];
660
+ if (process.env.DSH_PET_NO_SANDBOX === "1") launchArgs.push("--no-sandbox");
661
+ logCarrier(`spawn binary=${electronBinary} args=${JSON.stringify(launchArgs)} pid=${String(process.pid)}`);
662
+ const child = (() => {
663
+ try {
664
+ return spawn(electronBinary, launchArgs, {
665
+ env: {
666
+ ...stripRunAsNode(process.env),
667
+ DSH_PET_URL: url,
668
+ DSH_PET_RUNTIME_PID: String(process.pid)
669
+ },
670
+ detached: true,
671
+ stdio: [
672
+ "ignore",
673
+ "pipe",
674
+ "pipe"
675
+ ]
676
+ });
677
+ } catch (error) {
678
+ logCarrier(`spawn threw: ${error instanceof Error ? error.message : String(error)}`);
679
+ return;
680
+ }
681
+ })();
682
+ if (child === void 0) return;
683
+ logCarrier(`spawned pid=${String(child.pid ?? "unknown")}`);
684
+ let stderrTail = "";
666
685
  child.stdout?.setEncoding("utf8");
667
686
  child.stdout?.on("data", (chunk) => {
668
687
  process.stdout.write(`[pet-carrier] ${chunk}`);
669
688
  });
670
689
  child.stderr?.setEncoding("utf8");
671
690
  child.stderr?.on("data", (chunk) => {
691
+ stderrTail = (stderrTail + chunk).slice(-2e3);
672
692
  process.stderr.write(`[pet-carrier] ${chunk}`);
673
693
  });
694
+ child.on("error", (error) => {
695
+ logCarrier(`child error: ${error.message}`);
696
+ });
697
+ child.on("exit", (code, signal) => {
698
+ logCarrier(`child exit code=${String(code)} signal=${String(signal)} stderr=${JSON.stringify(stderrTail.slice(-700))}`);
699
+ });
674
700
  child.unref();
675
701
  ctx.effect(() => () => {
676
702
  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.2",
4
+ "version": "0.4.4",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },