@muzi3/herdr 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -30,7 +30,7 @@ extensions/
30
30
 
31
31
  每个扩展目录的入口都叫 `index.ts`,与 pi 自己的目录式扩展约定一致:扩展目录内可以再放内部模块,`pi.extensions` 只指向入口,不会误加载旁支文件。
32
32
 
33
- `herdr-agent-state/index.ts` 的目录名与 herdr 集成注入的文件同名,对齐上游时可以直接对比。内容分两段:官方集成正文(一直到文件末尾之前)与之后的「本包新增」段落。本包对官方正文只有**一处**改动:官方 `export default` 开头插入一行 `registerBlockedReporting(pi);` —— 该 default export 就是本扩展的唯一入口,blocked 上报只能挂在那里。重新同步上游时(`HERDR_INTEGRATION_VERSION` 从 8 往上升)重取注入文件替换官方正文并补回那一行;`diff` 应只有三处新增、零删除,漏帖那一行会被 `tests/herdr-agent-state.test.ts` 拦下。
33
+ `herdr-agent-state/index.ts` 的目录名与 herdr 集成注入的文件同名,对齐上游时可以直接对比。内容分两段:官方集成正文(一直到文件末尾之前)与之后的「本包新增」段落。本包对官方正文只有**一处**改动:官方 `export default` 开头插入一行 `registerBlockedReporting(pi);` —— 该 default export 就是本扩展的唯一入口,blocked 上报只能挂在那里。重新同步上游时(`HERDR_INTEGRATION_VERSION` 从 9 往上升)重取注入文件替换官方正文并补回那一行;`diff` 应只有三处新增、零删除,漏帖那一行会被 `tests/herdr-agent-state.test.ts` 拦下。
34
34
 
35
35
  ## 来源与许可
36
36
 
@@ -2,14 +2,14 @@
2
2
  // managed by herdr; reinstalling or updating the integration overwrites this file.
3
3
  // add custom hooks/plugins beside this file instead of editing it.
4
4
  // HERDR_INTEGRATION_ID=pi
5
- // HERDR_INTEGRATION_VERSION=8
5
+ // HERDR_INTEGRATION_VERSION=9
6
6
  // @ts-nocheck
7
7
  //
8
8
  // ---------------------------------------------------------------------------
9
9
  // 以下为本包(@muzi3/herdr)的说明,不属于 herdr 官方正文:
10
10
  //
11
11
  // 1. 本文件上方内容是 herdr 官方 pi 集成正文的副本,保留是为了将来能直接与上游重新同步:
12
- // 上游 `HERDR_INTEGRATION_VERSION` 从当前的 8 往上升时,重取 `herdr integration install pi`
12
+ // 上游 `HERDR_INTEGRATION_VERSION` 从当前的 9 往上升时,重取 `herdr integration install pi`
13
13
  // 注入的文件并替换本文件的官方段落即可(文件末尾的「本包新增」段落不受影响)。
14
14
  // 本包对官方段落只有**一处**改动:`export default` 开头插入一行
15
15
  // `registerBlockedReporting(pi);`(带「本包新增」标记)。因为官方的 default export 就是本
@@ -27,6 +27,7 @@
27
27
  // ---------------------------------------------------------------------------
28
28
 
29
29
  import net from "node:net";
30
+ import path from "node:path";
30
31
 
31
32
  const HERDR_ENV = process.env.HERDR_ENV;
32
33
  const socketPath = process.env.HERDR_SOCKET_PATH;
@@ -67,11 +68,11 @@ function sendRequestAttempt(request: unknown, timeoutMs: number): Promise<boolea
67
68
  });
68
69
  }
69
70
 
70
- async function sendRequest(request: unknown): Promise<void> {
71
+ async function sendRequest(request: unknown): Promise<boolean> {
71
72
  if (await sendRequestAttempt(request, 500)) {
72
- return;
73
+ return true;
73
74
  }
74
- await sendRequestAttempt(request, 1500);
75
+ return sendRequestAttempt(request, 1500);
75
76
  }
76
77
 
77
78
  type AgentState = "working" | "blocked" | "idle";
@@ -95,7 +96,10 @@ function updateSessionRef(ctx: any): void {
95
96
  try {
96
97
  const file = ctx?.sessionManager?.getSessionFile?.();
97
98
  currentAgentSessionPath =
98
- typeof file === "string" && file.startsWith("/") ? file : undefined;
99
+ typeof file === "string" &&
100
+ (path.posix.isAbsolute(file) || path.win32.isAbsolute(file))
101
+ ? file
102
+ : undefined;
99
103
  } catch {
100
104
  currentAgentSessionPath = undefined;
101
105
  }
@@ -165,6 +169,7 @@ function sendState(state: AgentState, message?: string, seq = nextReportSeq()):
165
169
 
166
170
  let sendInFlight = false;
167
171
  let queuedState: QueuedState | undefined;
172
+ let retryTimer: ReturnType<typeof setTimeout> | undefined;
168
173
 
169
174
  function queueState(state: AgentState, message?: string): void {
170
175
  queuedState = { state, message, seq: nextReportSeq() };
@@ -173,6 +178,17 @@ function queueState(state: AgentState, message?: string): void {
173
178
  }
174
179
  }
175
180
 
181
+ function scheduleStateRetry(): void {
182
+ if (retryTimer) {
183
+ return;
184
+ }
185
+ retryTimer = setTimeout(() => {
186
+ retryTimer = undefined;
187
+ void drainStateQueue();
188
+ }, 1000);
189
+ retryTimer.unref?.();
190
+ }
191
+
176
192
  async function drainStateQueue(): Promise<void> {
177
193
  if (sendInFlight) {
178
194
  return;
@@ -183,11 +199,18 @@ async function drainStateQueue(): Promise<void> {
183
199
  while (queuedState) {
184
200
  const next = queuedState;
185
201
  queuedState = undefined;
186
- await sendState(next.state, next.message, next.seq);
202
+ if (await sendState(next.state, next.message, next.seq)) {
203
+ continue;
204
+ }
205
+ if (!queuedState || queuedState.seq < next.seq) {
206
+ queuedState = next;
207
+ }
208
+ scheduleStateRetry();
209
+ break;
187
210
  }
188
211
  } finally {
189
212
  sendInFlight = false;
190
- if (queuedState) {
213
+ if (queuedState && !retryTimer) {
191
214
  void drainStateQueue();
192
215
  }
193
216
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muzi3/herdr",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Herdr for pi: three independent extensions (agent + blocked state reporting, /pi-hot-restart, and the herdr_overview / herdr_read / herdr_wait / herdr_prompt / herdr_run / herdr_create / herdr_agent_start / herdr_close manager tools aligned with dsh's herdr-tools plugin) plus the herdr-guide skill.",
5
5
  "keywords": [
6
6
  "pi-package",