zigmini 0.8.0-beta.5 → 0.8.0-beta.7

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 (57) hide show
  1. package/README.ko.md +78 -19
  2. package/README.md +79 -19
  3. package/assets/agent/gateway-request-rules.md +1 -0
  4. package/assets/agent/gateway-rules.md +6 -0
  5. package/assets/android/zigmini.apk +0 -0
  6. package/assets/android/zigmini.apk.json +3 -3
  7. package/assets/build.json +1 -1
  8. package/docs/manual.ko.md +25 -2
  9. package/docs/manual.md +25 -2
  10. package/host/omo-bridge/task-control.ts +4 -0
  11. package/host/omo-check/patches/omo-5.1.35-compaction-idle.patch +77 -0
  12. package/host/omo-check/patches/omo-5.1.35-compaction-intent.patch +212 -0
  13. package/host/omo-check/patches/omo-5.1.35-compaction-model.patch +299 -0
  14. package/host/omo-check/patches/omo-5.1.35-compaction-preservation.patch +1063 -0
  15. package/host/omo-check/patches/omo-5.1.35-compaction-refusal.patch +83 -0
  16. package/host/omo-check/patches/omo-5.1.35-gateway-port.manifest.json +171 -8
  17. package/host/omo-check/patches/omo-5.1.35-phantom-attach.patch +31 -0
  18. package/host/omo-check/patches/omo-5.1.35-request-rules.patch +109 -0
  19. package/host/omo-check/patches/omo-5.1.35-turn-stats.patch +76 -0
  20. package/package.json +4 -1
  21. package/scripts/secret-rules.ts +101 -0
  22. package/scripts/secret-scan.allow.json +155 -0
  23. package/scripts/secret-scan.rules.json +30 -0
  24. package/src/agent-request-rules.ts +82 -0
  25. package/src/cli/access.ts +31 -34
  26. package/src/cli/launchd.ts +30 -4
  27. package/src/cli/main.ts +13 -39
  28. package/src/cli/messages.ts +160 -0
  29. package/src/cli/pair.ts +32 -25
  30. package/src/cli/rotate-main.ts +411 -0
  31. package/src/cli/setup.ts +164 -75
  32. package/src/decisions.ts +20 -1
  33. package/src/hub.ts +140 -30
  34. package/src/main.ts +45 -4
  35. package/src/omo/client.ts +28 -0
  36. package/src/protocol.ts +33 -1
  37. package/src/reply-notifications.ts +144 -0
  38. package/src/runtime/paths.ts +2 -0
  39. package/src/security-check.ts +241 -0
  40. package/src/store.ts +71 -1
  41. package/src/turn-stats.ts +49 -0
  42. package/src/work-watch.ts +36 -10
  43. package/src/work.ts +29 -4
  44. package/web/app.js +197 -10
  45. package/web/decisions.js +3 -0
  46. package/web/gc.d.ts +2 -0
  47. package/web/gc.js +11 -0
  48. package/web/index.html +26 -10
  49. package/web/notifications.d.ts +25 -0
  50. package/web/notifications.js +118 -0
  51. package/web/style.css +16 -0
  52. package/web/tooltip.d.ts +0 -6
  53. package/web/tooltip.js +8 -11
  54. package/web/turn-stats.d.ts +26 -0
  55. package/web/turn-stats.js +58 -0
  56. package/web/update.d.ts +1 -1
  57. package/web/update.js +10 -3
@@ -0,0 +1,83 @@
1
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/refusal.js
2
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/refusal.js
3
+ @@ -25,7 +25,14 @@
4
+ const details = refusalDetails(message);
5
+ return details ? new ClaudeSdkRefusalError(details.content, details.category) : undefined;
6
+ }
7
+ -export function isClaudeSdkRefusal(error) {
8
+ - return error instanceof ClaudeSdkRefusalError;
9
+ -}
10
+ +export function isClaudeSdkRefusal(error) {
11
+ + return getClaudeSdkRefusal(error) !== undefined;
12
+ +}
13
+ +export function getClaudeSdkRefusal(error) {
14
+ + if (error instanceof ClaudeSdkRefusalError)
15
+ + return error;
16
+ + if (error !== null && typeof error === "object" && "original" in error)
17
+ + return getClaudeSdkRefusal(error.original);
18
+ + return undefined;
19
+ +}
20
+ //# sourceMappingURL=refusal.js.map
21
+
22
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/errors.js
23
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/errors.js
24
+ @@ -1,4 +1,5 @@
25
+ -import { rateLimitModelFamily } from "../../../credential-pool/model-scope.js";
26
+ +import { rateLimitModelFamily } from "../../../credential-pool/model-scope.js";
27
+ +import { isClaudeSdkRefusal } from "./refusal.js";
28
+ const SDK_ERROR_CLASSIFICATIONS = {
29
+ authentication_failed: { kind: "auth_error", retryable: true },
30
+ oauth_org_not_allowed: { kind: "org_not_allowed", retryable: true },
31
+ @@ -75,8 +76,10 @@
32
+ return new Error(text ? (message.error === "unknown" ? text : `${text} (${message.error})`) : message.error);
33
+ }
34
+ /** Classifies Anthropic Subscription error codes and HTTP-shaped fallback text in one place. */
35
+ -export function classifySdkError(error) {
36
+ - const classification = classifyErrorKind(error);
37
+ +export function classifySdkError(error) {
38
+ + if (isClaudeSdkRefusal(error))
39
+ + return OTHER_ERROR;
40
+ + const classification = classifyErrorKind(error);
41
+ if (classification.kind !== "rate_limit")
42
+ return classification;
43
+ const modelFamily = rateLimitModelFamily(errorText(error));
44
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/stream.js
45
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/stream.js
46
+ @@ -9,7 +9,7 @@
47
+ import { buildDeferredPromptStream, buildPromptBlocks } from "./prompt-bridge.js";
48
+ import { pinOneShotPromptCacheTtl } from "./prompt-cache-ttl.js";
49
+ import { dedupeUltraworkBlocks } from "./prompt-directive-dedupe.js";
50
+ -import { refusalError } from "./refusal.js";
51
+ +import { getClaudeSdkRefusal, refusalError } from "./refusal.js";
52
+ import { getSdkBoundary, loadClaudeAgentSdk } from "./sdk-boundary.js";
53
+ import { emitContinuityObservation } from "./session-observability.js";
54
+ import { forgetBinding } from "./session-reattach.js";
55
+ @@ -244,8 +244,11 @@
56
+ // senpi's own history instead of resuming that rewritten transcript.
57
+ if (nativeCompactionStopped && options?.sessionId)
58
+ forgetBinding(options.sessionId);
59
+ - output.stopReason = options?.signal?.aborted ? "aborted" : "error";
60
+ - // A failed result still bills its tokens; managed and resident lanes
61
+ + output.stopReason = options?.signal?.aborted ? "aborted" : "error";
62
+ + const refusal = getClaudeSdkRefusal(error);
63
+ + if (refusal)
64
+ + output.stopDetails = { type: "refusal", explanation: refusal.message };
65
+ + // A failed result still bills its tokens; managed and resident lanes
66
+ // throw before the result reaches this loop, so account for it here.
67
+ const billed = sdkResultFailureUsage(error);
68
+ if (billed)
69
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/deterministic-fallback.js
70
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/deterministic-fallback.js
71
+ @@ -97,8 +97,10 @@
72
+ return true;
73
+ return error instanceof SummaryRequestError && !error.transient && !error.refused && error.failureKind === undefined;
74
+ }
75
+ -export function classifyRequiredCompactionFallbackFailure(error) {
76
+ - if (error instanceof UnsafeRetainedSuffixError)
77
+ +export function classifyRequiredCompactionFallbackFailure(error) {
78
+ + if (error instanceof SummaryRequestError && error.refused)
79
+ + return undefined;
80
+ + if (error instanceof UnsafeRetainedSuffixError)
81
+ return "unsafe-retained-content";
82
+ if (error instanceof StreamDurationBudgetError ||
83
+ error instanceof StreamIdleTimeoutError ||
@@ -1,29 +1,37 @@
1
1
  {
2
2
  "schema": 1,
3
- "revision": 3,
3
+ "revision": 8,
4
4
  "upstream": {
5
5
  "omo": "5.1.35",
6
6
  "senpi": "2026.10.16"
7
7
  },
8
- "candidate": "<zigmini home>/omo/5.1.35-zgw",
8
+ "candidate": "<zigmini home>/omo/5.1.35-zgw.8",
9
9
  "pristine": "<zigmini home>/omo/5.1.35",
10
10
  "entrypoint": "node_modules/@code-yeongyu/senpi/dist/cli.js",
11
11
  "patchRoot": "node_modules",
12
12
  "patches": [
13
13
  "omo-5.1.35-gateway-port.patch",
14
14
  "omo-5.1.35-image-replay.patch",
15
- "omo-5.1.35-question-capability.patch"
15
+ "omo-5.1.35-question-capability.patch",
16
+ "omo-5.1.35-phantom-attach.patch",
17
+ "omo-5.1.35-request-rules.patch",
18
+ "omo-5.1.35-compaction-model.patch",
19
+ "omo-5.1.35-compaction-refusal.patch",
20
+ "omo-5.1.35-compaction-preservation.patch",
21
+ "omo-5.1.35-compaction-intent.patch",
22
+ "omo-5.1.35-compaction-idle.patch",
23
+ "omo-5.1.35-turn-stats.patch"
16
24
  ],
17
25
  "files": [
18
26
  {
19
27
  "path": "node_modules/@code-yeongyu/senpi/dist/core/agent-session.d.ts",
20
28
  "originalSha256": "f824b37b0d19f07e182254d0133cf57526b6a6fde9c8cfad62b6ba5af50cd119",
21
- "patchedSha256": "d669bdf3c71d5bef8d4491c912e83fc4229704b0fccfb42932d8a1f924edc8c6"
29
+ "patchedSha256": "b2457c6da97d27285671cf38de1c2eb48f61a50cbcae6b79b42b0604d9f98bd5"
22
30
  },
23
31
  {
24
32
  "path": "node_modules/@code-yeongyu/senpi/dist/core/agent-session.js",
25
33
  "originalSha256": "d861188c06f5354b8279d3158b8e7db1a7d86053a3dfe3b581c4fef52a1bcbbc",
26
- "patchedSha256": "8843671f6eff07ceaeb7d90cca3617321fe926efd8e1d48941075f9e6e36d761"
34
+ "patchedSha256": "60e22e74fb4b607f3a2fc07fbbe4fd773973414e58cf9fb54dec06c0fd1456cb"
27
35
  },
28
36
  {
29
37
  "path": "node_modules/@code-yeongyu/senpi/dist/core/auth-storage.js",
@@ -40,16 +48,46 @@
40
48
  "originalSha256": "2f6a8601aa879e11e37322d939ebd0f31ed21b51735d0f71f6833ee85d3b1c75",
41
49
  "patchedSha256": "dd2427652a7a1b0bf07a18bddfc9ffc2f48140376eb6349e7ff3c350d508c447"
42
50
  },
51
+ {
52
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/compaction/compaction.js",
53
+ "originalSha256": "1c24c48064542867c58371cf469af8e98984bd44861c464dbd122b79683c4a21",
54
+ "patchedSha256": "655797b41847962657bc355835d1f08e88d06f21c4b00535aa2d693685c72660"
55
+ },
43
56
  {
44
57
  "path": "node_modules/@code-yeongyu/senpi/dist/core/credential-accounts.js",
45
58
  "originalSha256": "f98f1758e934135084d2765f73b20e4c22f6a74dce344569c6dfbfe9dc250cbc",
46
59
  "patchedSha256": "218862c77a0df2691a521ae99c95e99acc64a8547dd6d6e627ebd98369d34fe0"
47
60
  },
61
+ {
62
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.d.ts",
63
+ "originalSha256": "6a4536363e0c71add5c61f969f1880503df02249914d294412dcf5b284b58f16",
64
+ "patchedSha256": "7858496cdf2c89533810f310156915f5d3be578a22a81a38de34b8d8d194c8cd"
65
+ },
66
+ {
67
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js",
68
+ "originalSha256": "8fd122e765b0f8f395a1d1c14a41f538a46816b9d68b1404004cb604f17bf038",
69
+ "patchedSha256": "877361fa222bf908c735bc7c8e22028ad6604c36d07c11928c27217d3fb9dad6"
70
+ },
48
71
  {
49
72
  "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/cold-seed-images.js",
50
73
  "originalSha256": "f40ff494a945bc5188dca010476cac76ae60f178f67d5391457a04e7f266c16e",
51
74
  "patchedSha256": "7c042bc1bfc0240cfd576cdc989f174dd248270219cc834788d22c9df3aa6903"
52
75
  },
76
+ {
77
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/errors.js",
78
+ "originalSha256": "e4fce0dbc87e7d9b19844319a5064c4fbc0681db8574279a67e2094285b41934",
79
+ "patchedSha256": "52efe8a368e29e425ba75453870f9c72a50889a60a9fdacdcc9339ac3fb75025"
80
+ },
81
+ {
82
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/refusal.js",
83
+ "originalSha256": "d13ad77fff8128a833494dfd1eb95760bca3f57621c9e3cb36b0370407e58c46",
84
+ "patchedSha256": "1b4673286c40d615752ec4acfd0fdd17e645c3af275232d9c6b8fad2ace10445"
85
+ },
86
+ {
87
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/stream.js",
88
+ "originalSha256": "477ec59462bd11ab89b5fcbe018e8f505b7a79a2550aa23f76d0b04e48026d22",
89
+ "patchedSha256": "edf9fc8a5779ddc92d81d879b7a18214e20be0ec7895c481c09d37d47b390892"
90
+ },
53
91
  {
54
92
  "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/ask-user/pending.js",
55
93
  "originalSha256": "0f8156f0cdd1fbc4bb08486d0b8b6ff5f821b9ac5df4cf5056714689fb2bb0c5",
@@ -70,6 +108,116 @@
70
108
  "originalSha256": "2e6cb7dd518e11b49b04275bf2e7d8014c834814b05a7cfc2232d1f970f51df9",
71
109
  "patchedSha256": "61ed013b8e33a3c4e1d4a9c9e491d0193811721a27afba11fb8cebb089cd805e"
72
110
  },
111
+ {
112
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/context-pipeline.js",
113
+ "originalSha256": "9af989447ef4145f25e58fb421a42d98af5a544b5297c1b66f9577ca285c2fe9",
114
+ "patchedSha256": "4d87236638509c1e28b29e6964fbab92f91fa477543ecca48d3bd87c6a422cc7"
115
+ },
116
+ {
117
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/context-reduction-handoff.js",
118
+ "originalSha256": "e02c76847d5060bf9f1527786c0a545143bfc7c5a77ecc194341d48564ebaed1",
119
+ "patchedSha256": "df205aa25d56439e56ac275e6c903e4dccd812e1b5a2aea5450ae645115c2e76"
120
+ },
121
+ {
122
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/context-reduction-lifecycle.js",
123
+ "originalSha256": "8ff27c815d2a33f1afbd23dd800157e3abad4324914d9cd776883122697ba003",
124
+ "patchedSha256": "c27cabce3751e2db42054bf51473673126366ce9aae5ed48dfeeef7066164f50"
125
+ },
126
+ {
127
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/deterministic-fallback.js",
128
+ "originalSha256": "2e33f9e1afc7320070e1566f5ef52a0b6ecb5e6adc59d9a0c4633773e8fb4b14",
129
+ "patchedSha256": "c00f5fadcf0d445a5fbe4e542a2a1b6e1c0dca5509822a65602d0fc32dbdde29"
130
+ },
131
+ {
132
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/emergency-prune.js",
133
+ "originalSha256": "64487d2e21273bd5a735485507e12a10c1039e6ecde548722e8e2c4e4d3b4773",
134
+ "patchedSha256": "00b8ce5b493f8605abc2f96b1270f40e532f4bc94532c3bf06b18baa81d3b2fe"
135
+ },
136
+ {
137
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/extension-wiring.js",
138
+ "originalSha256": "0612dc35d11ccee5b4b630dae9504f829ab81bf0aa4c8eab35d1aba617174a3f",
139
+ "patchedSha256": "c521dfa0dd9b6281ae84cd40e4bbfd2eea50874222a74c89fef97e88a93813d1"
140
+ },
141
+ {
142
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/index.js",
143
+ "originalSha256": "0ad15ac2a16c8ab7edf986b6a4653f9302c1945e66a1a6f48d6b9ca24ed54b7f",
144
+ "patchedSha256": "aadd59a28f75ecd99b375ba2e2ca180b73dc3b6553f35508aec6590304f4e487"
145
+ },
146
+ {
147
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/lane-policy.js",
148
+ "originalSha256": "e701d15afac3e70e880b544e761c378b8a1d7bf7b68f6e21495a010c3bad3406",
149
+ "patchedSha256": "d16359d291f4c1ddce5f5a2c8d48f09e4c0b14418f3ffc5293a2c22814cbb316"
150
+ },
151
+ {
152
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote-convert.js",
153
+ "originalSha256": "a2eae1acead0a92eaddaa9a0bea56902a05bd33656635dd90b8d7fe84d9d24a0",
154
+ "patchedSha256": "cbe0df338fcb246e96c840bf006d6c1ad74bade810850018c9eba2e843997d5c"
155
+ },
156
+ {
157
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote-responses-v2.js",
158
+ "originalSha256": "9f937de797e3bdabaade5cf1b9dea1f87c7919c93edefe142cd8b2453669a7c4",
159
+ "patchedSha256": "7cc4498b874e94457c15affae32026db219a066a449c7175075a1ae2e23f654e"
160
+ },
161
+ {
162
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote-schema.js",
163
+ "originalSha256": "5154b38ef8fa50626edc444d2111ed931dc72bd3616a5845776995012f501e8e",
164
+ "patchedSha256": "c00d15f2f3cad40f48bffab524ce33afa617a3cd85622b235b2cd105bbbd939c"
165
+ },
166
+ {
167
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote-timeout.d.ts",
168
+ "originalSha256": "f31c61df9f81ff3b7bacf4565463fc5f582b604cc40a5cd81b2f72c5fe2015db",
169
+ "patchedSha256": "63f2cac427f164e65feb58fcd413d6b09f6c4010d8b176971ee716f3a75201bc"
170
+ },
171
+ {
172
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote-timeout.js",
173
+ "originalSha256": "357781e9fc41f840c2048958a784be075595c1dce9c5cf716940bdfe771681d1",
174
+ "patchedSha256": "93702b16d3e351c812631cf541c175c85a8be1ba2515e8eedad08f54c4bdfcc1"
175
+ },
176
+ {
177
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote.d.ts",
178
+ "originalSha256": "d4ea95dbd8f857dfeb5120e5bec35865d78cbb79fe4d59f5cae2ffbe4baa1e66",
179
+ "patchedSha256": "b4873967e45f53cf0647301a486176263e6a5db0843028002990d7f192b443cf"
180
+ },
181
+ {
182
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/openai-remote.js",
183
+ "originalSha256": "889de1c53e7fc891a099136866c831bd5dfe8ecc15b2dda8d354657e0ec1377b",
184
+ "patchedSha256": "657c9132ab806490c8a07fdc09639621ba7e63a2c1cf93b6bdf0484d896e02f7"
185
+ },
186
+ {
187
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/prompts.js",
188
+ "originalSha256": "5bf074aea446baa51204f29ec00758a93a9cbfc89caa62ffe0a4078dcca0e6b3",
189
+ "patchedSha256": "2178bdcd1f9acfadc07815309c44a8b35741f1243543333795b5e9e64403a197"
190
+ },
191
+ {
192
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/rejected-recovery.d.ts",
193
+ "originalSha256": "40e74e75a77ac0f89ef931385e0f88c3a5d188e2aed06ac295ddfac598ea4464",
194
+ "patchedSha256": "54c5c03818a56d0e6560dcba1fca3bc5163dd29205ddb874f2d5e74f2e76473a"
195
+ },
196
+ {
197
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/rejected-recovery.js",
198
+ "originalSha256": "dccd1cba630ed1674343fae06b21bc081712668481969692ec6e4a246107ca22",
199
+ "patchedSha256": "d6fa0fd69d6532647a3f7db7a35cde499a10fc833e593c5dca96e5e49a4476f5"
200
+ },
201
+ {
202
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/speculative-summary.js",
203
+ "originalSha256": "25dc617e8b999f7b38e638287df81790768279aa78a607e692ccd2b108b88ada",
204
+ "patchedSha256": "ea31110fdc12aee77dc47114efd9d7d230443b735cef300f60e03a27bfbe4779"
205
+ },
206
+ {
207
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/speculative.d.ts",
208
+ "originalSha256": "826ec46e212f2378a68bf55fa2ba1b406d6a225e81549983361cf54480388f32",
209
+ "patchedSha256": "99d2702cf752b45c1d46ffbbf231a9bc1007cdeb919571f7d497b01cada7f931"
210
+ },
211
+ {
212
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/speculative.js",
213
+ "originalSha256": "99ac70e0088f2b66538b76c4b2acef5c13e5290e3e1645fea71b8a70c41799b4",
214
+ "patchedSha256": "a41786f41d838c679f8be6e14d8831458c7acb9d43e5aa44d7030e22470b47e3"
215
+ },
216
+ {
217
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/compaction/task-intent.js",
218
+ "originalSha256": "3d78e7e232c172a57af0e919cf0b0b34c98282f235c2d400e4c0bba7f47d545d",
219
+ "patchedSha256": "85a396201b2b248b74cd9eebb362bd96c713806577b179df8ad99c4ac095889f"
220
+ },
73
221
  {
74
222
  "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/permission-system/events.d.ts",
75
223
  "originalSha256": "8fb12fba44abc0066360248855951833eca3684b0d340579db3409afe8a2c767",
@@ -105,10 +253,20 @@
105
253
  "originalSha256": "78865611f2018bbd8bcde160bcb7c517e743394cb0c0e0a3f774e55cd7f25b2f",
106
254
  "patchedSha256": "11f5b99fbd59963d7426e659c6db4764580d7c89aee8bb3a7d1beab12fba9b72"
107
255
  },
256
+ {
257
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/runner.js",
258
+ "originalSha256": "5bbc9de01f7ec0f4d52ade362c9acba8a27d14ecaef4af06593b04451ce9ebe3",
259
+ "patchedSha256": "d1fab450b98c832239424fbffa616690678e44527e36ce6299a300fccb123778"
260
+ },
108
261
  {
109
262
  "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/types.d.ts",
110
263
  "originalSha256": "990653c416a88b76c5338b75cb58e2d8843b4ca528722571b18ef1fdb9d10cc2",
111
- "patchedSha256": "5a646947a3573698bf956cec3395cfc362903fa100ba0920d80e6095add54148"
264
+ "patchedSha256": "4c914b28970084777b31da70f1199c1a744226c6e7beba516bcfa7cb9d3f011a"
265
+ },
266
+ {
267
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/model-runtime.js",
268
+ "originalSha256": "e43ff1363e3284a5b3495d5eaaf4b9b6bcefcd6a60f2f8e7f91b98e1ce69c446",
269
+ "patchedSha256": "350688afcb9da83938130eceda83f033a8cbc7c318e8e44886396826d967ea21"
112
270
  },
113
271
  {
114
272
  "path": "node_modules/@code-yeongyu/senpi/dist/modes/rpc/client-input-handler.js",
@@ -148,7 +306,7 @@
148
306
  {
149
307
  "path": "node_modules/@code-yeongyu/senpi/dist/modes/rpc/session-command-router.js",
150
308
  "originalSha256": "3f952631024884c893a6e37549c2861e25b0bddc2387222006b77dcbaad78c9b",
151
- "patchedSha256": "95515f802619da5e54352b8d996b8b71c6db91f1574470626239de2764367f9b"
309
+ "patchedSha256": "a2ea46300a8d7b4cb46413afd5389ad8df37707c2852f3f4b826011a28eea6ef"
152
310
  },
153
311
  {
154
312
  "path": "node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts",
@@ -163,12 +321,17 @@
163
321
  {
164
322
  "path": "node_modules/@earendil-works/pi-ai/dist/types.d.ts",
165
323
  "originalSha256": "5440ea974e52f4413f38240dc3f6c435e5e90796e7477fc5de6a500c3c2226c7",
166
- "patchedSha256": "64f7fee8c3ddff79facba8dd5eff14777b1aebef188899aca86379e54cfb9656"
324
+ "patchedSha256": "f8ebe662ba115f2e31b30c2b32d8e3d46581440a87b56c5acf50f853649ea4a4"
167
325
  },
168
326
  {
169
327
  "path": "node_modules/omo-ai/bin/lib/package-paths.js",
170
328
  "originalSha256": "da57bd6016ab85a0f65f53cde53ca3b2e8606e2efc515bcb592d637c24401e67",
171
329
  "patchedSha256": "b99f4ea56abecc7950f06c67fb0f538148e9baae4027c9b55f5debf130479686"
330
+ },
331
+ {
332
+ "path": "node_modules/@code-yeongyu/senpi/dist/core/extensions/builtin/tps.js",
333
+ "originalSha256": "c1a22d2520e84f136aa91a770eb49bd42cfbcce57864bfa263e491f45bb08f65",
334
+ "patchedSha256": "c72d51910bf8e61452cc11d57702075be96d3b5e51c00c30678eb499f2551509"
172
335
  }
173
336
  ]
174
337
  }
@@ -0,0 +1,31 @@
1
+ diff --git a/@code-yeongyu/senpi/dist/modes/rpc/session-command-router.js b/@code-yeongyu/senpi/dist/modes/rpc/session-command-router.js
2
+ --- a/@code-yeongyu/senpi/dist/modes/rpc/session-command-router.js
3
+ +++ b/@code-yeongyu/senpi/dist/modes/rpc/session-command-router.js
4
+ @@ -584,7 +584,17 @@
5
+ * the failure response otherwise, exactly as an open does.
6
+ */
7
+ reopenParked(entry) {
8
+ - return this.open(parkedOpenCommand(entry), undefined, { reply: false, defaults: false });
9
+ + return this.open(parkedOpenCommand(entry), undefined, { reply: false, defaults: false, releaseUnowned: true });
10
+ + }
11
+ + /**
12
+ + * zgw (rotation after a handoff): the registry counts one attachment for every open, and an owner-less reopen has no
13
+ + * connection that could ever release it, so a later close by the real owner left the session open. Release it as a
14
+ + * detach: a retained entry stays open at zero attachments, exactly as when its last client leaves.
15
+ + */
16
+ + releaseUnownedReopen(sessionId) {
17
+ + if (this.draining || this.registry.peek(sessionId)?.retainOnDisconnect !== true)
18
+ + return false;
19
+ + return this.tryClaimClose(sessionId, { drainAttachments: false, detach: true }) !== undefined;
20
+ }
21
+ async open(command, owner, options) {
22
+ // A parked session's reopen replays what its park recorded; a field it left empty stays empty
23
+ @@ -729,6 +739,8 @@
24
+ this.releaseOwnerAttachment(owner, openedSession.sessionId);
25
+ await this.releaseOwnedSession(openedSession.sessionId);
26
+ }
27
+ + if (owner === undefined && options?.releaseUnowned === true)
28
+ + this.releaseUnownedReopen(openedSession.sessionId);
29
+ const replyState = entry.worker?.snapshot?.state ?? (entry.runtime ? buildRpcSessionState(entry.runtime.session) : undefined);
30
+ if (!replyState)
31
+ throw new Error("Session state was not created");
@@ -0,0 +1,109 @@
1
+ --- a/@code-yeongyu/senpi/dist/core/model-runtime.js
2
+ +++ b/@code-yeongyu/senpi/dist/core/model-runtime.js
3
+ @@ -72,7 +72,8 @@
4
+ ...options,
5
+ onPayload: async (payload, providerModel) => await onPayload(payload, providerModel, {
6
+ model,
7
+ - headers: options.headers ?? {},
8
+ + headers: options.headers ?? {},
9
+ + streamKind: options.streamKind,
10
+ }),
11
+ };
12
+ }
13
+ --- a/@earendil-works/pi-ai/dist/types.d.ts
14
+ +++ b/@earendil-works/pi-ai/dist/types.d.ts
15
+ @@ -84,9 +84,10 @@
16
+ /** Effective model and fully transformed headers for a request payload hook. */
17
+ export type ProviderRequestMetadata = {
18
+ model: Model<Api>;
19
+ - headers: ProviderHeaders;
20
+ -};
21
+ -export type FetchFunction = typeof globalThis.fetch;
22
+ + headers: ProviderHeaders;
23
+ + streamKind?: "main" | "auxiliary";
24
+ +};
25
+ +export type FetchFunction = typeof globalThis.fetch;
26
+ export interface ProviderResponse {
27
+ status: number;
28
+ headers: Record<string, string>;
29
+ --- a/@code-yeongyu/senpi/dist/core/extensions/runner.js
30
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/runner.js
31
+ @@ -1614,7 +1614,7 @@
32
+ const event = {
33
+ type: "before_provider_request",
34
+ payload: currentPayload,
35
+ - ...(request ? { model: request.model, headers: request.headers } : {}),
36
+ + ...(request ? { model: request.model, headers: request.headers, streamKind: request.streamKind } : {}),
37
+ };
38
+ const handlerResult = await handler(event, this.createContext(ext.path));
39
+ if (handlerResult !== undefined) {
40
+ --- a/@code-yeongyu/senpi/dist/core/extensions/types.d.ts
41
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/types.d.ts
42
+ @@ -1137,10 +1137,11 @@
43
+ /** Effective request model after auth/base-url/upstream-model resolution. */
44
+ model?: Model<Api>;
45
+ /** Final header transform output for this request. Values are never persisted. */
46
+ - headers?: ProviderHeaders;
47
+ -}
48
+ -/**
49
+ - * Fired after request headers are assembled, before the provider HTTP call.
50
+ + headers?: ProviderHeaders;
51
+ + streamKind?: "main" | "auxiliary";
52
+ +}
53
+ +/**
54
+ + * Fired after request headers are assembled, before the provider HTTP call.
55
+ * Handlers mutate `headers` in place (e.g. to inject tracing/session headers);
56
+ * the return value is ignored. A `null` value deletes that header.
57
+ */
58
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/stream.js
59
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/stream.js
60
+ @@ -74,7 +74,7 @@
61
+ claudeCodeRun = resolveClaudeCodeRun(defaultExecutableDeps());
62
+ const executable = claudeCodeRun.executable;
63
+ let oneShotCacheTtl;
64
+ - const buildOptions = (authLane) => {
65
+ + const buildOptions = async (authLane) => {
66
+ const queryOptions = buildAnthropicSubscriptionQueryOptions({
67
+ model,
68
+ context,
69
+ @@ -97,7 +97,8 @@
70
+ if (!useResidentSession) {
71
+ oneShotCacheTtl = pinOneShotPromptCacheTtl(queryOptions, authLane ?? providerSettings.tokenInjection ?? "ambient", { ...process.env, ...options?.env });
72
+ }
73
+ - return queryOptions;
74
+ + const replacement = await options?.onPayload?.(queryOptions, model);
75
+ + return replacement === undefined ? queryOptions : replacement;
76
+ };
77
+ const recordContinuity = (observation) => {
78
+ // Not a failure: carry the observation as details only, with no synthesized error.
79
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js
80
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js
81
+ @@ -186,7 +186,7 @@
82
+ }
83
+ // Lane-owned variables from buildOptions (the compaction-owner overlay) win over the host.
84
+ const ambientAttempt = async () => {
85
+ - const options = input.buildOptions("ambient");
86
+ + const options = await input.buildOptions("ambient");
87
+ options.env = { ...ambientEnvironment, ...options.env };
88
+ return createAttemptMessages(input, { accountName: "ambient", accounts: [], authLane: "ambient", options });
89
+ };
90
+ @@ -215,7 +215,7 @@
91
+ ...(input.model === undefined ? {} : { model: input.model }),
92
+ }),
93
+ runAttempt: async (slot) => {
94
+ - const options = input.buildOptions(pool.lane);
95
+ + const options = await input.buildOptions(pool.lane);
96
+ const accounts = pool.accounts.map((account) => ({ ...account }));
97
+ const prepared = await prepareSlot(pool, slot, signal);
98
+ options.env = { ...prepared.env, ...options.env };
99
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.d.ts
100
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/anthropic-subscription/auth-lane.d.ts
101
+ @@ -18,7 +18,7 @@
102
+ export type AuthenticatedQueryInput = {
103
+ prompt: Parameters<SdkQuery>[0]["prompt"];
104
+ query: SdkQuery;
105
+ - buildOptions: (lane: AnthropicSubscriptionTokenInjection) => Options;
106
+ + buildOptions: (lane: AnthropicSubscriptionTokenInjection) => Options | Promise<Options>;
107
+ providerSettings: AnthropicSubscriptionProviderSettings;
108
+ /** Effective request auth environment; overrides the host for account discovery and SDK spawn. */
109
+ env?: Record<string, string>;
@@ -0,0 +1,76 @@
1
+ --- a/@code-yeongyu/senpi/dist/core/extensions/builtin/tps.js
2
+ +++ b/@code-yeongyu/senpi/dist/core/extensions/builtin/tps.js
3
+ @@ -23,6 +23,8 @@
4
+ let lastDeltaMs = null;
5
+ let generationMs = 0;
6
+ let streamedOutput = 0;
7
+ + let turnId = null;
8
+ + let completedMessages = [];
9
+ const finishActiveAssistantTiming = () => {
10
+ if (activeAssistantStartMs === null)
11
+ return;
12
+ @@ -41,7 +43,11 @@
13
+ lastDeltaMs = null;
14
+ thinkingStreamed = false;
15
+ };
16
+ + pi.on("agent_start", (_event, ctx) => {
17
+ + turnId = ctx.mode === "rpc" ? crypto.randomUUID() : null;
18
+ + completedMessages = [];
19
+ + if (turnId !== null)
20
+ + pi.rpc.emit("zgw.turn_started", { version: 1, turnId });
21
+ - pi.on("agent_start", () => {
22
+ activeAssistantStartMs = null;
23
+ assistantElapsedMs = 0;
24
+ generationMs = 0;
25
+ @@ -76,6 +82,7 @@
26
+ // counted in usage.output may be hidden or only summarised after it finished, so it was generated
27
+ // before the first delta. Such a message (usage.reasoning, or a thinking block whose text never
28
+ // streamed: Bedrock and omitted display report no reasoning count) is timed from its start.
29
+ + completedMessages.push(event.message);
30
+ const output = event.message.usage?.output ?? 0;
31
+ const windowStart = reasonedBeforeFirstDelta(event.message, thinkingStreamed) ? messageStartMs : firstDeltaMs;
32
+ const counted = event.message.stopReason !== "aborted" && event.message.stopReason !== "error" && output > 0;
33
+ @@ -90,6 +97,43 @@
34
+ const elapsedMs = assistantElapsedMs;
35
+ const measuredGenerationMs = generationMs;
36
+ const measuredOutput = streamedOutput;
37
+ + // Structured RPC metadata stays out of messages and extension_ui_request notifications.
38
+ + const completedTurnId = turnId;
39
+ + turnId = null;
40
+ + const messages = completedMessages;
41
+ + completedMessages = [];
42
+ + const finalMessage = messages.at(-1);
43
+ + const lastAssistant = event.messages.findLast(isAssistantMessage);
44
+ + if (ctx.mode === "rpc" && completedTurnId !== null && !event.aborted && !event.willRetry && !event.abortSource && !ctx.signal?.aborted
45
+ + && finalMessage && (finalMessage.stopReason === "stop" || finalMessage.stopReason === "length")
46
+ + && Number.isInteger(finalMessage.timestamp) && finalMessage.timestamp > 0
47
+ + && lastAssistant?.timestamp === finalMessage.timestamp
48
+ + && !messages.some((message) => message.stopReason === "error" || message.stopReason === "aborted")) {
49
+ + const stats = {};
50
+ + const hasOutput = messages.some((message) => Number.isFinite(message.usage?.output) && message.usage.output > 0);
51
+ + if (hasOutput) {
52
+ + if (Number.isFinite(elapsedMs) && elapsedMs > 0)
53
+ + stats.modelDurationMs = elapsedMs;
54
+ + const rate = measuredOutput / (measuredGenerationMs / 1000);
55
+ + if (measuredGenerationMs >= MIN_GENERATION_MS && Number.isFinite(rate) && rate > 0)
56
+ + stats.tokensPerSecond = rate;
57
+ + // Unknown usage must not look like a measured zero-percent cache hit.
58
+ + if (messages.every((message) => [message.usage?.input, message.usage?.cacheRead, message.usage?.cacheWrite]
59
+ + .every((value) => Number.isFinite(value) && value >= 0))) {
60
+ + let promptTokens = 0;
61
+ + let cacheRead = 0;
62
+ + for (const message of messages) {
63
+ + promptTokens += message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
64
+ + cacheRead += message.usage.cacheRead;
65
+ + }
66
+ + const hit = cacheRead / promptTokens * 100;
67
+ + if (Number.isFinite(promptTokens) && Number.isFinite(cacheRead) && Number.isFinite(hit) && hit >= 0 && hit <= 100)
68
+ + stats.cacheHitPercent = hit;
69
+ + }
70
+ + }
71
+ + if (Object.keys(stats).length > 0)
72
+ + pi.rpc.emit("zgw.turn_stats", { version: 1, turnId: completedTurnId, finalMessageTimestamp: finalMessage.timestamp, finalMessageIndex: messages.length, stats });
73
+ + }
74
+ activeAssistantStartMs = null;
75
+ assistantElapsedMs = 0;
76
+ generationMs = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigmini",
3
- "version": "0.8.0-beta.5",
3
+ "version": "0.8.0-beta.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zigmini": "bin/zigmini"
@@ -21,6 +21,9 @@
21
21
  "!host/omo-check/*.ts",
22
22
  "!host/omo-check/patches/README.md",
23
23
  "assets/",
24
+ "scripts/secret-rules.ts",
25
+ "scripts/secret-scan.rules.json",
26
+ "scripts/secret-scan.allow.json",
24
27
  "docs/manual.md",
25
28
  "docs/manual.ko.md",
26
29
  "LICENSE.md",