larkin 0.5.3 → 0.5.5
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/CHANGELOG.md +12 -0
- package/README.md +22 -1
- package/artifacts/release/THIRD_PARTY_NOTICES.txt +1 -100
- package/dist/agent/agent-cli-capabilities.cjs +1 -1
- package/dist/agent/agent-cli-capabilities.mjs +1 -1
- package/dist/agent/config-cli-contract.cjs +3 -1
- package/dist/agent/config-cli-contract.mjs +3 -1
- package/dist/agent/context-prompt.cjs +16 -17
- package/dist/agent/context-prompt.mjs +15 -16
- package/dist/agent/inbox-audit-heartbeat.cjs +157 -37
- package/dist/agent/inbox-audit-heartbeat.mjs +122 -36
- package/dist/agent/missed-outbound-scan.cjs +326 -54
- package/dist/agent/missed-outbound-scan.mjs +319 -53
- package/dist/app/agent-cli.mjs +37 -6
- package/dist/app/agent-config.mjs +36 -5
- package/dist/app/cli.mjs +1 -0
- package/dist/dashboard/dashboard-config-controller.mjs +15 -0
- package/dist/dashboard/web/assets/dashboard.css +1 -1
- package/dist/dashboard/web/assets/dashboard.js +15 -15
- package/dist/feishu/host-shell.cjs +63 -5
- package/dist/feishu/host-shell.mjs +66 -8
- package/dist/platform/config.cjs +173 -5
- package/dist/platform/config.mjs +167 -4
- package/dist/runtime/pi-state-dir.cjs +105 -0
- package/dist/runtime/pi-state-dir.mjs +94 -0
- package/dist/runtime/pi-tmux-extension.mjs +137 -0
- package/dist/runtime/pi-tmux-injection.mjs +49 -0
- package/dist/runtime/pi-tmux.bundle.js +600 -0
- package/dist/runtime/pi-tmux.mjs +408 -0
- package/dist/runtime/runtime-adapters.mjs +26 -113
- package/dist/runtime/runtime-host.cjs +3 -413
- package/dist/runtime/runtime-host.mjs +2 -412
- package/package.json +2 -8
- package/dist/runtime/pi-bash-timeout-extension.mjs +0 -60
- package/dist/runtime/pi-bash-timeout-injection.mjs +0 -54
- package/dist/runtime/pi-bash-timeout.bundle.js +0 -43
- package/dist/runtime/pi-extension-api.mjs +0 -1
- package/dist/runtime/pi-subagent-injection.mjs +0 -290
- package/dist/runtime/pi-subagent-ledger.cjs +0 -632
- package/dist/runtime/pi-subagent-ledger.mjs +0 -594
- package/dist/runtime/pi-subagent-record-watchdog-injection.mjs +0 -43
- package/dist/runtime/pi-subagent-record-watchdog.bundle.js +0 -183
- package/dist/runtime/pi-subagent-record-watchdog.mjs +0 -46
- package/dist/runtime/pi-subagents-notification.mjs +0 -175
- package/dist/runtime/pi-subagents.bundle.js +0 -9110
- package/dist/runtime/pi-supervised-command-extension.mjs +0 -72
- package/dist/runtime/pi-supervised-command.bundle.js +0 -4735
- package/dist/runtime/pi-supervised-command.mjs +0 -420
- package/patches/@tintinweb%2Fpi-subagents@0.14.3.patch +0 -945
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.5
|
|
4
|
+
|
|
5
|
+
Pi uses a small Larkin-owned tmux Bash extension when tmux is available on macOS/Linux. Commands preserve their working directory, including non-Git paths with spaces; a foreground wait can return while the same command continues. The returned task ID supports inspection and cancellation, and background completion resumes the Agent. Native Windows and environments without tmux retain Pi's native Bash.
|
|
6
|
+
|
|
7
|
+
Removed the injected subagent plugin, its ledger/watchdog and supervised-command infrastructure, the 60-second Bash hard-kill rule, and mandatory delegation guidance. Pi-owned turns now occupy Runtime busy state without a second host prompt. Historical subagent files are left untouched. Background commands survive Pi shutdown in tmux; notification recovery across Pi restarts is not provided. No third-party tmux plugin is installed or redistributed.
|
|
8
|
+
|
|
9
|
+
## 0.5.4
|
|
10
|
+
|
|
11
|
+
Inbox Audit is now optional and off by default. The Dashboard and CLI support global and per-Agent switches and inspection gaps. Saving a gap updates scheduling without replacing Runtime sessions; editing a gap alone does not enable auditing. Only originally wake-eligible human group/topic work is audited.
|
|
12
|
+
|
|
13
|
+
Audit reads no longer mark work complete. Agents explicitly confirm a receipt after checking; receipts are scoped to an observation generation, and durable canonical sequence ordering protects newer work from stale completion or deferred registration. Contended registrations are retried durably. Unproven legacy audit-index rows are ignored while ordinary Inbox and conversation history remain intact.
|
|
14
|
+
|
|
3
15
|
## 0.5.3
|
|
4
16
|
|
|
5
17
|
External Pi initialization now runs with bounded concurrency and recovers from isolated startup-probe timeouts through the existing retry policy. Shutdown waits for pending initialization and closes late sessions. Generic Runtime and delivery failures show unavailable instead of incompatible, while explicit prerequisite failures and useful provider diagnostics are preserved. Recovery workflow tests wait for delivery consumption and Inbox watermarks to converge and isolate temporary state.
|
package/README.md
CHANGED
|
@@ -91,7 +91,28 @@ Feishu (https://open.feishu.cn) and Lark (https://open.larksuite.com) are differ
|
|
|
91
91
|
|
|
92
92
|
During setup, choose one of the three externally installed runtimes: Pi (`pi`), Codex (`codex`), or Claude Code (`claude`). Larkin does not ship a runtime and does not store provider credentials. Install the runtime yourself and complete its own login (`pi` login flow, `codex login`, or `claude login`) before setup. Interactive setup lists each runtime as installed or not installed and refuses a missing binary; non-interactive setup requires `--runtime` and exits non-zero with the same missing-install message.
|
|
93
93
|
|
|
94
|
-
`larkin setup --model <id>` optionally stores a catalog model for that runtime. After setup, use `larkin model` and `larkin runtime` to inspect or switch. For Pi, Larkin talks to your installed `pi --mode rpc
|
|
94
|
+
`larkin setup --model <id>` optionally stores a catalog model for that runtime. After setup, use `larkin model` and `larkin runtime` to inspect or switch. For Pi, Larkin talks to your installed `pi --mode rpc` and verifies the RPC handshake and compaction capability contract.
|
|
95
|
+
|
|
96
|
+
### Optional Pi tmux-backed bash
|
|
97
|
+
|
|
98
|
+
On macOS and Linux with `tmux` 3.2 or newer installed, Larkin provides a small tmux-backed Bash tool. Commands run in their requested directory, including non-Git directories and paths with spaces. By default the tool waits up to 30 seconds, then returns a `taskId` while the same command continues; `background: true` returns immediately. The `tmux` tool lists, inspects and stops tasks owned by that Pi instance. Completed background commands notify the Agent. There is no Larkin-imposed 60-second kill or ten-minute command limit.
|
|
99
|
+
|
|
100
|
+
Without a supported tmux version, or on native Windows, Pi keeps native bash. After Pi shuts down, background commands remain in tmux, but automatic completion notifications are not restored; use `tmux list-sessions` to find the session containing the task ID and attach manually. Larkin does not require a third-party tmux plugin.
|
|
101
|
+
|
|
102
|
+
### Optional Inbox Audit
|
|
103
|
+
|
|
104
|
+
Inbox Audit is **off by default**. In the Dashboard, use **Global settings → Inbox 巡检** to configure the switch and inspection gap, or the selected Agent's **Configuration → Inbox 巡检** to override either value. The gap defaults to 15 minutes and supports 1 minute to 24 hours. Saving a gap alone keeps auditing disabled; saved settings survive restart and update later scheduling without replacing the Agent Runtime session.
|
|
105
|
+
|
|
106
|
+
The same settings are available through the CLI:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
larkin config inbox-audit global on --interval 15m
|
|
110
|
+
larkin config inbox-audit agent off --agent <App-ID>
|
|
111
|
+
larkin config inbox-audit agent inherit --agent <App-ID> --interval inherit
|
|
112
|
+
larkin config inbox-audit global off
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
When enabled, audit only revisits originally wake-eligible human group/topic work and does not wake a model for an empty work list. Reading an audit list does not complete it: the managed Agent follows the returned inspection instructions and explicitly confirms the receipt after checking. A failed check remains retryable; newer messages cannot be completed by an older receipt. Old audit-index records without proven eligibility or observation identity are ignored; ordinary Inbox messages and conversation history are preserved.
|
|
95
116
|
|
|
96
117
|
<details>
|
|
97
118
|
<summary>Windows support and optional autostart</summary>
|
|
@@ -4,7 +4,7 @@ Generated at release time from Larkin's installed runtime dependency closure.
|
|
|
4
4
|
Development-only dependencies are intentionally excluded. Packages without a bundled license file
|
|
5
5
|
use an explicitly audited, version- and hash-pinned license source and remain identified by locked package name and version.
|
|
6
6
|
|
|
7
|
-
Runtime package versions:
|
|
7
|
+
Runtime package versions: 97
|
|
8
8
|
|
|
9
9
|
| Package | Version | Relationship | Declared license | License texts (SHA-256) | Lock integrity |
|
|
10
10
|
| --- | ---: | --- | --- | --- | --- |
|
|
@@ -43,8 +43,6 @@ Runtime package versions: 101
|
|
|
43
43
|
| @radix-ui/react-use-controllable-state | 1.2.6 | runtime transitive | MIT | LICENSE (0e80a2d229d2fd4fc7e8636142ec5d0ff0bc031f14c15b682e2ac01dfd5b5138) | sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ== |
|
|
44
44
|
| @radix-ui/react-use-effect-event | 0.0.5 | runtime transitive | MIT | LICENSE (0e80a2d229d2fd4fc7e8636142ec5d0ff0bc031f14c15b682e2ac01dfd5b5138) | sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg== |
|
|
45
45
|
| @radix-ui/react-use-layout-effect | 1.1.4 | runtime transitive | MIT | LICENSE (0e80a2d229d2fd4fc7e8636142ec5d0ff0bc031f14c15b682e2ac01dfd5b5138) | sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw== |
|
|
46
|
-
| @sinclair/typebox | 0.34.52 | runtime transitive | MIT | license (411f1c560755e27b3dec9622c13b8b7a3ec1c83f4ffb8c56a8847528aa96911a) | sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw== |
|
|
47
|
-
| @tintinweb/pi-subagents | 0.14.3 | runtime direct | MIT | LICENSE (e7d9d11c28cce34f09dc7d2b0a3a6609ccba5fbc8e926e6d1bfdf060930e9f05) | sha512-iDqeadh6114AZvw8HYe1PEq8M0MZ9czJKTAIsklCPUbV9vUMS+g/LAV0vW3O9PiBXKNJh8hkrY8L6iIr8XNEqA== |
|
|
48
46
|
| agent-base | 6.0.2 | runtime transitive | MIT | AUDITED-agent-base@9.0.0-LICENSE (71368fd0f5b4129191e9afcd1e1ef2dc89a9090d3e4d80bbab92dafd032b3bef) | sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== |
|
|
49
47
|
| agent-base | 9.0.0 | runtime transitive | MIT | LICENSE (71368fd0f5b4129191e9afcd1e1ef2dc89a9090d3e4d80bbab92dafd032b3bef) | sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA== |
|
|
50
48
|
| aria-hidden | 1.2.6 | runtime transitive | MIT | LICENSE (30f0cfddf483d1128e3610205020f2041a6c5e837aa999e0aa82e5576187d4a9) | sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA== |
|
|
@@ -53,7 +51,6 @@ Runtime package versions: 101
|
|
|
53
51
|
| call-bind-apply-helpers | 1.0.2 | runtime transitive | MIT | LICENSE (5e325595b4ea8cfec3802f545b1def5d7b73e4a5b8e9ba63e32a320f67732292) | sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== |
|
|
54
52
|
| call-bound | 1.0.4 | runtime transitive | MIT | LICENSE (5e325595b4ea8cfec3802f545b1def5d7b73e4a5b8e9ba63e32a320f67732292) | sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== |
|
|
55
53
|
| combined-stream | 1.0.8 | runtime transitive | MIT | License (47eb8ca82c798246774946d1be0f9aa08f025fa8325ced0947aeeb4c05fe5547) | sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== |
|
|
56
|
-
| croner | 10.0.1 | runtime transitive | MIT | LICENSE (ad9aa40aaab4bee08121a0180096cc6a72abf29e19e606328b66c0178f41d267) | sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g== |
|
|
57
54
|
| debug | 4.4.3 | runtime transitive | MIT | LICENSE (23eb8602cd5902bcfca56b23aa08e8672a809f5a12eaf8bb56abfa9d44e1a4fd) | sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== |
|
|
58
55
|
| delayed-stream | 1.0.0 | runtime transitive | MIT | License (47eb8ca82c798246774946d1be0f9aa08f025fa8325ced0947aeeb4c05fe5547) | sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== |
|
|
59
56
|
| detect-node-es | 1.1.0 | runtime transitive | MIT | LICENSE (54b32293ea560d22cd9b62af9b2cda1a030d910a48c6601d227c5ff2338d95f8) | sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== |
|
|
@@ -84,7 +81,6 @@ Runtime package versions: 101
|
|
|
84
81
|
| mime-db | 1.52.0 | runtime transitive | MIT | LICENSE (cc1dfd4dafa27271e8212cd3b274eeb3f262e40a6fdab36ddc3f9696f706f58b) | sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== |
|
|
85
82
|
| mime-types | 2.1.35 | runtime transitive | MIT | LICENSE (71f83c4c0621102a56d9853812777b85751bce7e9726f686f5b056c1f8a4b0e6) | sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== |
|
|
86
83
|
| ms | 2.1.3 | runtime transitive | MIT | license.md (1662fae9b5314d11cf51284e2dcd1f006a354f7343f08712a730fcff9a359801) | sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== |
|
|
87
|
-
| nanoid | 5.1.16 | runtime transitive | MIT | LICENSE (4383cb2c3608397ce7a4159502614ed66890f8999c2a9c056dd3b1024d6721f0) | sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ== |
|
|
88
84
|
| object-inspect | 1.13.4 | runtime transitive | MIT | LICENSE (bd40cc437e28a3ad7bef2ad34e6b72e757b182e67bda1acadbab4ef0476f8232) | sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== |
|
|
89
85
|
| proper-lockfile | 4.1.2 | runtime direct | MIT | LICENSE (aaa78451b6fecd1b9c4594c796c133c0e90cad100372ff8bc6de615e9ef9adf1) | sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== |
|
|
90
86
|
| protobufjs | 7.6.5 | runtime transitive | BSD-3-Clause | LICENSE (49d6a1c9a623784c61c6cb70f773f3457faceb1914a13c8560a9823b7631950c) | sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw== |
|
|
@@ -414,55 +410,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
414
410
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
415
411
|
SOFTWARE.
|
|
416
412
|
|
|
417
|
-
--- SHA-256 411f1c560755e27b3dec9622c13b8b7a3ec1c83f4ffb8c56a8847528aa96911a ---
|
|
418
|
-
TypeBox
|
|
419
|
-
|
|
420
|
-
Json Schema Type Builder with Static Type Resolution for TypeScript
|
|
421
|
-
|
|
422
|
-
The MIT License (MIT)
|
|
423
|
-
|
|
424
|
-
Copyright (c) 2017-2026 Haydn Paterson
|
|
425
|
-
|
|
426
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
427
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
428
|
-
in the Software without restriction, including without limitation the rights
|
|
429
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
430
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
431
|
-
furnished to do so, subject to the following conditions:
|
|
432
|
-
|
|
433
|
-
The above copyright notice and this permission notice shall be included in
|
|
434
|
-
all copies or substantial portions of the Software.
|
|
435
|
-
|
|
436
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
437
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
438
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
439
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
440
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
441
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
442
|
-
THE SOFTWARE.
|
|
443
|
-
|
|
444
|
-
--- SHA-256 4383cb2c3608397ce7a4159502614ed66890f8999c2a9c056dd3b1024d6721f0 ---
|
|
445
|
-
The MIT License (MIT)
|
|
446
|
-
|
|
447
|
-
Copyright 2017 Andrey Sitnik <andrey@sitnik.es>
|
|
448
|
-
|
|
449
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
450
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
451
|
-
the Software without restriction, including without limitation the rights to
|
|
452
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
453
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
454
|
-
subject to the following conditions:
|
|
455
|
-
|
|
456
|
-
The above copyright notice and this permission notice shall be included in all
|
|
457
|
-
copies or substantial portions of the Software.
|
|
458
|
-
|
|
459
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
460
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
461
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
462
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
463
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
464
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
465
|
-
|
|
466
413
|
--- SHA-256 47eb8ca82c798246774946d1be0f9aa08f025fa8325ced0947aeeb4c05fe5547 ---
|
|
467
414
|
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
|
|
468
415
|
|
|
@@ -968,29 +915,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
968
915
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
969
916
|
SOFTWARE.
|
|
970
917
|
|
|
971
|
-
--- SHA-256 ad9aa40aaab4bee08121a0180096cc6a72abf29e19e606328b66c0178f41d267 ---
|
|
972
|
-
The MIT License (MIT)
|
|
973
|
-
|
|
974
|
-
Copyright (c) 2015-2021 Hexagon <github.com/Hexagon>
|
|
975
|
-
|
|
976
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
977
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
978
|
-
in the Software without restriction, including without limitation the rights
|
|
979
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
980
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
981
|
-
furnished to do so, subject to the following conditions:
|
|
982
|
-
|
|
983
|
-
The above copyright notice and this permission notice shall be included in all
|
|
984
|
-
copies or substantial portions of the Software.
|
|
985
|
-
|
|
986
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
987
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
988
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
989
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
990
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
991
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
992
|
-
SOFTWARE.
|
|
993
|
-
|
|
994
918
|
--- SHA-256 b495047bd93a9b06913511076f504daba17d5bbeb3e0650f3bb53a4220329c57 ---
|
|
995
919
|
ISC License
|
|
996
920
|
|
|
@@ -1711,29 +1635,6 @@ Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
|
|
1711
1635
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1712
1636
|
THE SOFTWARE.
|
|
1713
1637
|
|
|
1714
|
-
--- SHA-256 e7d9d11c28cce34f09dc7d2b0a3a6609ccba5fbc8e926e6d1bfdf060930e9f05 ---
|
|
1715
|
-
MIT License
|
|
1716
|
-
|
|
1717
|
-
Copyright (c) 2026 tintinweb
|
|
1718
|
-
|
|
1719
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1720
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
1721
|
-
in the Software without restriction, including without limitation the rights
|
|
1722
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1723
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
1724
|
-
furnished to do so, subject to the following conditions:
|
|
1725
|
-
|
|
1726
|
-
The above copyright notice and this permission notice shall be included in all
|
|
1727
|
-
copies or substantial portions of the Software.
|
|
1728
|
-
|
|
1729
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1730
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1731
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1732
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1733
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1734
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1735
|
-
SOFTWARE.
|
|
1736
|
-
|
|
1737
1638
|
--- SHA-256 e7dc37bf662d7f786efcb46c545615e70c1daf458a38385521c63cf6607cdfe1 ---
|
|
1738
1639
|
BSD 3-Clause License
|
|
1739
1640
|
|
|
@@ -32,7 +32,7 @@ function agentCliPromptCapabilities(executable = "larkin") {
|
|
|
32
32
|
const commands = Object.entries(exports.AGENT_CLI_CAPABILITIES.commands).flatMap(([group, operations]) => operations.map((operation) => ({
|
|
33
33
|
command: `${group} ${operation}`,
|
|
34
34
|
purpose: group === "inbox" ? (operation === "check" ? "Read pending target summaries without consuming messages."
|
|
35
|
-
: operation === "audit" ? "Read bounded observed group/topic audit targets
|
|
35
|
+
: operation === "audit" ? "Read bounded observed group/topic audit targets; inspect first, then explicitly confirm the returned receipt."
|
|
36
36
|
: "Poll full messages and direct-ack the returned batch.") :
|
|
37
37
|
group === "comment" ? "Reply once to the exact cloud-document comment bound by a polled Inbox message id." :
|
|
38
38
|
group === "reminder" ? "Manage this Agent's durable reminders." :
|
|
@@ -24,7 +24,7 @@ export function agentCliPromptCapabilities(executable = "larkin") {
|
|
|
24
24
|
const commands = Object.entries(AGENT_CLI_CAPABILITIES.commands).flatMap(([group, operations]) => operations.map((operation) => ({
|
|
25
25
|
command: `${group} ${operation}`,
|
|
26
26
|
purpose: group === "inbox" ? (operation === "check" ? "Read pending target summaries without consuming messages."
|
|
27
|
-
: operation === "audit" ? "Read bounded observed group/topic audit targets
|
|
27
|
+
: operation === "audit" ? "Read bounded observed group/topic audit targets; inspect first, then explicitly confirm the returned receipt."
|
|
28
28
|
: "Poll full messages and direct-ack the returned batch.") :
|
|
29
29
|
group === "comment" ? "Reply once to the exact cloud-document comment bound by a polled Inbox message id." :
|
|
30
30
|
group === "reminder" ? "Manage this Agent's durable reminders." :
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CONFIG_CLI_VALUES = exports.CONFIG_CLI_USAGE = exports.CONFIG_CLI_OPERATIONS = void 0;
|
|
4
|
-
exports.CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "apply"]);
|
|
4
|
+
exports.CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "apply"]);
|
|
5
5
|
exports.CONFIG_CLI_USAGE = Object.freeze([
|
|
6
6
|
"larkin config show [--agent <App ID>] [--chat <oc_id>] [--json]",
|
|
7
7
|
"larkin config runtime <runtime> [--model <model>] [--agent <App ID>]",
|
|
@@ -10,6 +10,8 @@ exports.CONFIG_CLI_USAGE = Object.freeze([
|
|
|
10
10
|
"larkin config mention global <require|free>",
|
|
11
11
|
"larkin config mention agent <inherit|require|free> [--agent <App ID>]",
|
|
12
12
|
"larkin config mention chat <oc_id> <inherit|require|free> [--agent <App ID>]",
|
|
13
|
+
"larkin config inbox-audit global <on|off> [--interval <15m|1h>]",
|
|
14
|
+
"larkin config inbox-audit agent <inherit|on|off> [--agent <App ID>] [--interval <15m|inherit>]",
|
|
13
15
|
"larkin config apply [--agent <App ID>]",
|
|
14
16
|
]);
|
|
15
17
|
exports.CONFIG_CLI_VALUES = Object.freeze({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "apply"]);
|
|
1
|
+
export const CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "apply"]);
|
|
2
2
|
export const CONFIG_CLI_USAGE = Object.freeze([
|
|
3
3
|
"larkin config show [--agent <App ID>] [--chat <oc_id>] [--json]",
|
|
4
4
|
"larkin config runtime <runtime> [--model <model>] [--agent <App ID>]",
|
|
@@ -7,6 +7,8 @@ export const CONFIG_CLI_USAGE = Object.freeze([
|
|
|
7
7
|
"larkin config mention global <require|free>",
|
|
8
8
|
"larkin config mention agent <inherit|require|free> [--agent <App ID>]",
|
|
9
9
|
"larkin config mention chat <oc_id> <inherit|require|free> [--agent <App ID>]",
|
|
10
|
+
"larkin config inbox-audit global <on|off> [--interval <15m|1h>]",
|
|
11
|
+
"larkin config inbox-audit agent <inherit|on|off> [--agent <App ID>] [--interval <15m|inherit>]",
|
|
10
12
|
"larkin config apply [--agent <App ID>]",
|
|
11
13
|
]);
|
|
12
14
|
export const CONFIG_CLI_VALUES = Object.freeze({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContextPromptBuilder = exports.AGENT_MENTION_GUIDANCE = exports.LARKIN_STANDING_PROMPT_VERSION = void 0;
|
|
3
|
+
exports.ContextPromptBuilder = exports.AGENT_MENTION_GUIDANCE = exports.PI_TMUX_BASH_GUIDANCE = exports.LARKIN_STANDING_PROMPT_VERSION = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const agent_cli_capabilities_js_1 = require("./agent-cli-capabilities.cjs");
|
|
6
6
|
/**
|
|
@@ -16,7 +16,18 @@ const agent_cli_capabilities_js_1 = require("./agent-cli-capabilities.cjs");
|
|
|
16
16
|
* 5. 版本化:每次实质改动 bump LARKIN_STANDING_PROMPT_VERSION,并同步 eval 数据集/graders/断言。
|
|
17
17
|
* 6. 用 eval 验证:行为变化必须配套固定场景 + rubric(evals/*、test/support/*-grader.mjs、live 测试)。
|
|
18
18
|
*/
|
|
19
|
-
exports.LARKIN_STANDING_PROMPT_VERSION = "larkin-standing-
|
|
19
|
+
exports.LARKIN_STANDING_PROMPT_VERSION = "larkin-standing-v30";
|
|
20
|
+
/**
|
|
21
|
+
* Pi 长命令引导的唯一来源。仅在当前工具列表出现 tmux-backed bash 时适用;
|
|
22
|
+
* 不声明 tmux 一定可用,也不复述扩展的工具细节。
|
|
23
|
+
* 工具拒绝当前 workspace 时只要求如实报告,不因此禁止其它已授权工具。
|
|
24
|
+
*/
|
|
25
|
+
exports.PI_TMUX_BASH_GUIDANCE = [
|
|
26
|
+
"If the current tools include a tmux-backed bash, long-running work may continue after a wait timeout. That timeout is not process failure.",
|
|
27
|
+
"Use the identifiers those tools return to inspect or stop the same process. When a command finishes, handle the completion notification in this originating conversation.",
|
|
28
|
+
"The user-installed extension owns tool names, arguments, and other details. Do not assume tmux or extra inspect/stop tools exist unless they appear in the current tool list.",
|
|
29
|
+
"If an available tool refuses the current workspace, report that limitation. Other authorized tools in the current list remain available. Do not assume the refusing tool works in every workspace.",
|
|
30
|
+
];
|
|
20
31
|
/**
|
|
21
32
|
* Agent 间协作唤醒引导(issue #75):纯文本 @ 不会产生飞书 mention 事件,
|
|
22
33
|
* 必须由模型直接构造真实的 mention 元素;`--mention` 扩展参数已移除。
|
|
@@ -123,21 +134,9 @@ class ContextPromptBuilder {
|
|
|
123
134
|
"Larkin Runtime Host is the only production runtime path. Do not start a second runtime or a legacy daemon.",
|
|
124
135
|
...(input.runtime === "pi" ? [
|
|
125
136
|
"",
|
|
126
|
-
"##
|
|
127
|
-
|
|
128
|
-
"
|
|
129
|
-
"Correct pattern:",
|
|
130
|
-
"1. Call Agent with arguments like {\"prompt\": \"<task>\", \"description\": \"<short label>\", \"run_in_background\": true}.",
|
|
131
|
-
"2. The tool returns an agent id immediately. Report it to the user and end the turn.",
|
|
132
|
-
"3. Do NOT poll or sleep; a completion notification arrives automatically.",
|
|
133
|
-
"4. On the notification, check the Inbox, then publish exactly one final summary.",
|
|
134
|
-
"If you explicitly use get_subagent_result with wait: true, make at most one bounded wait call per turn. If it returns timedOut: true, do not loop or call wait again in the same turn; yield and let the completion notification wake you.",
|
|
135
|
-
"Forbidden pattern (never acceptable): `nohup sh -c '...' > /tmp/x.out 2>&1 &`, `sleep N; cat ...`, disown, or any shell background substitute. These bypass subagent isolation.",
|
|
136
|
-
"Keep corrections, approvals, short commands, and Feishu writes in the foreground; do not delegate them.",
|
|
137
|
-
"Parallel independent tasks: when the user clearly asks for two or more independent tasks with no dependencies between them, delegate EACH task to its own background subagent in a single message with multiple Agent tool calls (one per task, all with run_in_background: true), report every job id, and end the turn. Do not run them one-by-one in the foreground and do not merge them into one subagent.",
|
|
138
|
-
"Sequential dependent tasks: when tasks depend on each other, sending the user an order message is a REQUIRED first step: before executing any follow-up work, send a message stating the execution order (for example: first I will do A, then B; I will report back after each step). Then execute in order and report as promised; never stay silent while chaining long work.",
|
|
139
|
-
"Reporting location: always report job ids and final summaries in the same conversation and thread where the user's message arrived (reply-in-thread when the request arrived in a thread). Never start a new conversation or DM for subagent status reports.",
|
|
140
|
-
""
|
|
137
|
+
"## Long-running commands (pi)",
|
|
138
|
+
...exports.PI_TMUX_BASH_GUIDANCE,
|
|
139
|
+
"",
|
|
141
140
|
] : []),
|
|
142
141
|
"",
|
|
143
142
|
"## Available Larkin agent commands",
|
|
@@ -13,7 +13,18 @@ import { agentCliPromptCapabilities } from "./agent-cli-capabilities.mjs";
|
|
|
13
13
|
* 5. 版本化:每次实质改动 bump LARKIN_STANDING_PROMPT_VERSION,并同步 eval 数据集/graders/断言。
|
|
14
14
|
* 6. 用 eval 验证:行为变化必须配套固定场景 + rubric(evals/*、test/support/*-grader.mjs、live 测试)。
|
|
15
15
|
*/
|
|
16
|
-
export const LARKIN_STANDING_PROMPT_VERSION = "larkin-standing-
|
|
16
|
+
export const LARKIN_STANDING_PROMPT_VERSION = "larkin-standing-v30";
|
|
17
|
+
/**
|
|
18
|
+
* Pi 长命令引导的唯一来源。仅在当前工具列表出现 tmux-backed bash 时适用;
|
|
19
|
+
* 不声明 tmux 一定可用,也不复述扩展的工具细节。
|
|
20
|
+
* 工具拒绝当前 workspace 时只要求如实报告,不因此禁止其它已授权工具。
|
|
21
|
+
*/
|
|
22
|
+
export const PI_TMUX_BASH_GUIDANCE = [
|
|
23
|
+
"If the current tools include a tmux-backed bash, long-running work may continue after a wait timeout. That timeout is not process failure.",
|
|
24
|
+
"Use the identifiers those tools return to inspect or stop the same process. When a command finishes, handle the completion notification in this originating conversation.",
|
|
25
|
+
"The user-installed extension owns tool names, arguments, and other details. Do not assume tmux or extra inspect/stop tools exist unless they appear in the current tool list.",
|
|
26
|
+
"If an available tool refuses the current workspace, report that limitation. Other authorized tools in the current list remain available. Do not assume the refusing tool works in every workspace.",
|
|
27
|
+
];
|
|
17
28
|
/**
|
|
18
29
|
* Agent 间协作唤醒引导(issue #75):纯文本 @ 不会产生飞书 mention 事件,
|
|
19
30
|
* 必须由模型直接构造真实的 mention 元素;`--mention` 扩展参数已移除。
|
|
@@ -120,21 +131,9 @@ export class ContextPromptBuilder {
|
|
|
120
131
|
"Larkin Runtime Host is the only production runtime path. Do not start a second runtime or a legacy daemon.",
|
|
121
132
|
...(input.runtime === "pi" ? [
|
|
122
133
|
"",
|
|
123
|
-
"##
|
|
124
|
-
|
|
125
|
-
"
|
|
126
|
-
"Correct pattern:",
|
|
127
|
-
"1. Call Agent with arguments like {\"prompt\": \"<task>\", \"description\": \"<short label>\", \"run_in_background\": true}.",
|
|
128
|
-
"2. The tool returns an agent id immediately. Report it to the user and end the turn.",
|
|
129
|
-
"3. Do NOT poll or sleep; a completion notification arrives automatically.",
|
|
130
|
-
"4. On the notification, check the Inbox, then publish exactly one final summary.",
|
|
131
|
-
"If you explicitly use get_subagent_result with wait: true, make at most one bounded wait call per turn. If it returns timedOut: true, do not loop or call wait again in the same turn; yield and let the completion notification wake you.",
|
|
132
|
-
"Forbidden pattern (never acceptable): `nohup sh -c '...' > /tmp/x.out 2>&1 &`, `sleep N; cat ...`, disown, or any shell background substitute. These bypass subagent isolation.",
|
|
133
|
-
"Keep corrections, approvals, short commands, and Feishu writes in the foreground; do not delegate them.",
|
|
134
|
-
"Parallel independent tasks: when the user clearly asks for two or more independent tasks with no dependencies between them, delegate EACH task to its own background subagent in a single message with multiple Agent tool calls (one per task, all with run_in_background: true), report every job id, and end the turn. Do not run them one-by-one in the foreground and do not merge them into one subagent.",
|
|
135
|
-
"Sequential dependent tasks: when tasks depend on each other, sending the user an order message is a REQUIRED first step: before executing any follow-up work, send a message stating the execution order (for example: first I will do A, then B; I will report back after each step). Then execute in order and report as promised; never stay silent while chaining long work.",
|
|
136
|
-
"Reporting location: always report job ids and final summaries in the same conversation and thread where the user's message arrived (reply-in-thread when the request arrived in a thread). Never start a new conversation or DM for subagent status reports.",
|
|
137
|
-
""
|
|
134
|
+
"## Long-running commands (pi)",
|
|
135
|
+
...PI_TMUX_BASH_GUIDANCE,
|
|
136
|
+
"",
|
|
138
137
|
] : []),
|
|
139
138
|
"",
|
|
140
139
|
"## Available Larkin agent commands",
|
|
@@ -1,62 +1,182 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InboxAuditHeartbeat = exports.INBOX_AUDIT_CADENCE_MS = void 0;
|
|
36
|
+
exports.InboxAuditHeartbeat = exports.MAX_INBOX_AUDIT_DIAGNOSTIC_CHARS = exports.INBOX_AUDIT_CADENCE_MS = void 0;
|
|
37
|
+
exports.boundedInboxAuditDiagnostic = boundedInboxAuditDiagnostic;
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
4
40
|
const inbox_projection_js_1 = require("./inbox-projection.cjs");
|
|
5
41
|
exports.INBOX_AUDIT_CADENCE_MS = 15 * 60_000;
|
|
6
|
-
|
|
42
|
+
exports.MAX_INBOX_AUDIT_DIAGNOSTIC_CHARS = 120;
|
|
43
|
+
function boundedInboxAuditDiagnostic(error) {
|
|
44
|
+
const max = exports.MAX_INBOX_AUDIT_DIAGNOSTIC_CHARS;
|
|
45
|
+
const code = error && typeof error === "object" && "code" in error && typeof error.code === "string"
|
|
46
|
+
? error.code.slice(0, max) : "";
|
|
47
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
48
|
+
const text = String(raw).slice(0, max).replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim();
|
|
49
|
+
return [code, text].filter(Boolean).join(" ").slice(0, max);
|
|
50
|
+
}
|
|
51
|
+
function safeIntervalMs(intervalMs) {
|
|
52
|
+
if (!Number.isSafeInteger(intervalMs) || intervalMs < 1)
|
|
53
|
+
throw new Error("inbox audit cadence must be a positive integer");
|
|
54
|
+
return intervalMs;
|
|
55
|
+
}
|
|
56
|
+
/** A Host-owned, config-file-reactive single timer per enabled Agent. */
|
|
7
57
|
class InboxAuditHeartbeat {
|
|
8
58
|
options;
|
|
9
|
-
|
|
59
|
+
timers = new Map();
|
|
60
|
+
generations = new Map();
|
|
10
61
|
running = false;
|
|
11
62
|
sequence = 0;
|
|
12
|
-
|
|
63
|
+
watcher = null;
|
|
64
|
+
refreshTimer = null;
|
|
13
65
|
constructor(options) {
|
|
14
66
|
this.options = options;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
throw new Error("inbox audit cadence must be a positive integer");
|
|
67
|
+
for (const agent of options.agents)
|
|
68
|
+
safeIntervalMs(options.schedule(agent).intervalMs);
|
|
18
69
|
}
|
|
19
70
|
start() {
|
|
20
71
|
if (this.running)
|
|
21
72
|
return;
|
|
22
73
|
this.running = true;
|
|
23
|
-
this.
|
|
74
|
+
for (const agent of this.options.agents)
|
|
75
|
+
this.reschedule(agent);
|
|
76
|
+
this.watchConfig();
|
|
24
77
|
}
|
|
25
78
|
stop() {
|
|
26
79
|
this.running = false;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
80
|
+
const clearTimer = this.options.clearTimer ?? clearTimeout;
|
|
81
|
+
for (const timer of this.timers.values())
|
|
82
|
+
clearTimer(timer);
|
|
83
|
+
this.timers.clear();
|
|
84
|
+
if (this.refreshTimer)
|
|
85
|
+
clearTimer(this.refreshTimer);
|
|
86
|
+
this.refreshTimer = null;
|
|
87
|
+
this.watcher?.close();
|
|
88
|
+
this.watcher = null;
|
|
89
|
+
}
|
|
90
|
+
/** Safe for a Host config watcher or a direct in-process config mutation hook. */
|
|
91
|
+
refresh() {
|
|
92
|
+
if (!this.running)
|
|
93
|
+
return;
|
|
94
|
+
for (const agent of this.options.agents)
|
|
95
|
+
this.reschedule(agent);
|
|
30
96
|
}
|
|
31
|
-
|
|
32
|
-
if (!this.
|
|
97
|
+
watchConfig() {
|
|
98
|
+
if (!this.options.configFile || this.watcher)
|
|
33
99
|
return;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
100
|
+
const file = path.resolve(this.options.configFile);
|
|
101
|
+
const parent = path.dirname(file);
|
|
102
|
+
const basename = path.basename(file);
|
|
103
|
+
try {
|
|
104
|
+
this.watcher = (this.options.watch ?? fs.watch)(parent, (_event, changed) => {
|
|
105
|
+
if (changed && String(changed) !== basename)
|
|
106
|
+
return;
|
|
107
|
+
this.scheduleRefresh();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.options.log?.(`inbox audit config watch failed: ${boundedInboxAuditDiagnostic(error)}`);
|
|
112
|
+
}
|
|
40
113
|
}
|
|
41
|
-
|
|
114
|
+
scheduleRefresh() {
|
|
115
|
+
if (!this.running || this.refreshTimer)
|
|
116
|
+
return;
|
|
117
|
+
this.refreshTimer = (this.options.setTimer ?? setTimeout)(() => {
|
|
118
|
+
this.refreshTimer = null;
|
|
119
|
+
this.refresh();
|
|
120
|
+
}, 30);
|
|
121
|
+
this.refreshTimer.unref?.();
|
|
122
|
+
}
|
|
123
|
+
reschedule(agent) {
|
|
124
|
+
const clearTimer = this.options.clearTimer ?? clearTimeout;
|
|
125
|
+
const prior = this.timers.get(agent.agentId);
|
|
126
|
+
if (prior)
|
|
127
|
+
clearTimer(prior);
|
|
128
|
+
this.timers.delete(agent.agentId);
|
|
129
|
+
const generation = (this.generations.get(agent.agentId) ?? 0) + 1;
|
|
130
|
+
this.generations.set(agent.agentId, generation);
|
|
131
|
+
let schedule;
|
|
132
|
+
try {
|
|
133
|
+
schedule = this.options.schedule(agent);
|
|
134
|
+
safeIntervalMs(schedule.intervalMs);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
this.options.log?.(`inbox audit schedule failed agent=${agent.agentId}: ${boundedInboxAuditDiagnostic(error)}`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Disabled means no future audit timer or model wake at all.
|
|
141
|
+
if (!schedule.enabled || !this.running)
|
|
142
|
+
return;
|
|
143
|
+
let timer;
|
|
144
|
+
timer = (this.options.setTimer ?? setTimeout)(() => {
|
|
145
|
+
// A cancelled callback can still be queued. It must not remove the
|
|
146
|
+
// replacement timer installed by a newer config revision.
|
|
147
|
+
if (this.timers.get(agent.agentId) === timer)
|
|
148
|
+
this.timers.delete(agent.agentId);
|
|
149
|
+
void this.fire(agent, generation).finally(() => {
|
|
150
|
+
if (this.running && this.generations.get(agent.agentId) === generation)
|
|
151
|
+
this.reschedule(agent);
|
|
152
|
+
});
|
|
153
|
+
}, schedule.intervalMs);
|
|
154
|
+
timer.unref?.();
|
|
155
|
+
this.timers.set(agent.agentId, timer);
|
|
156
|
+
}
|
|
157
|
+
async fire(agent, generation) {
|
|
158
|
+
if (this.generations.get(agent.agentId) !== generation)
|
|
159
|
+
return;
|
|
160
|
+
try {
|
|
161
|
+
const schedule = this.options.schedule(agent);
|
|
162
|
+
if (!schedule.enabled || !this.options.shouldDispatch(agent))
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
this.options.log?.(`inbox audit schedule failed agent=${agent.agentId}: ${boundedInboxAuditDiagnostic(error)}`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
42
169
|
const now = this.options.now ?? Date.now;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const appended = this.options.stateStore(agent).appendCanonicalInboxOnce(envelope);
|
|
54
|
-
if (appended.status === "appended")
|
|
55
|
-
await this.options.runtimeHost.deliver(agent.agentId, appended.envelope);
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
this.options.log?.(`inbox audit heartbeat failed agent=${agent.agentId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
59
|
-
}
|
|
170
|
+
const message_id = `rem_inbox_audit_${now()}_${++this.sequence}_${agent.agentId}`;
|
|
171
|
+
const envelope = { kind: "reminder", message_id, target: inbox_projection_js_1.RUNTIME_REMINDER_TARGET, wake: true,
|
|
172
|
+
content: "Internal inbox audit wake. Poll runtime:reminder, then run larkin inbox audit --json. Inspect first and explicitly complete its receipt; no finding stays silent." };
|
|
173
|
+
try {
|
|
174
|
+
const appended = this.options.stateStore(agent).appendCanonicalInboxOnce(envelope);
|
|
175
|
+
if (appended.status === "appended")
|
|
176
|
+
await this.options.runtimeHost.deliver(agent.agentId, appended.envelope);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
this.options.log?.(`inbox audit heartbeat failed agent=${agent.agentId}: ${boundedInboxAuditDiagnostic(error)}`);
|
|
60
180
|
}
|
|
61
181
|
}
|
|
62
182
|
}
|