@agfpd/iapeer 0.2.77 → 0.2.78
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/LICENSE +202 -0
- package/README.md +2 -2
- package/package.json +21 -2
- package/src/cli/index.ts +47 -48
- package/src/connect/index.ts +4 -4
- package/src/core/constants.ts +3 -3
- package/src/core/normalize.ts +2 -2
- package/src/create/index.ts +1 -1
- package/src/daemon/index.ts +5 -5
- package/src/daemon/main.ts +9 -9
- package/src/enable/index.ts +19 -18
- package/src/enable/provisionCommand.ts +10 -10
- package/src/identity/index.ts +2 -2
- package/src/identity/profileStandard.ts +8 -8
- package/src/init/index.ts +10 -10
- package/src/install/index.ts +2 -2
- package/src/install/signing.ts +3 -4
- package/src/launch/adapters/claude.ts +7 -7
- package/src/launch/adapters/codex.ts +5 -6
- package/src/launch/canary.ts +8 -8
- package/src/launch/cmdlog.ts +3 -3
- package/src/launch/composeSystemPrompt.ts +2 -1
- package/src/launch/index.ts +5 -6
- package/src/launch/invocation.ts +1 -1
- package/src/launch/launchd.ts +14 -15
- package/src/launch/launchdRun.ts +6 -6
- package/src/launch/nativeMemory.ts +9 -9
- package/src/launch/ptyHost.ts +1 -1
- package/src/launch/readyGateModel.ts +3 -3
- package/src/launch/types.ts +7 -7
- package/src/lifecycle/eventlog.ts +2 -2
- package/src/lifecycle/index.ts +21 -21
- package/src/lifecycle/queue.ts +1 -1
- package/src/onboard/index.ts +19 -13
- package/src/onboard/memory.ts +5 -5
- package/src/onboard/steps.ts +8 -9
- package/src/provision/index.ts +2 -3
- package/src/runtime/deploy.ts +2 -2
- package/src/runtime/index.ts +4 -4
- package/src/shadow/gate.ts +6 -6
- package/src/shadow/index.ts +2 -2
- package/src/status/index.ts +11 -11
- package/src/storage/index.ts +1 -1
- package/src/supervisor/daemon.ts +14 -8
- package/src/transport/index.ts +11 -11
- package/src/update/index.ts +4 -4
- package/src/cli/cli.test.ts +0 -603
- package/src/cli/listTui.test.ts +0 -71
- package/src/codec/codec.test.ts +0 -271
- package/src/connect/connect.test.ts +0 -163
- package/src/core/constants.test.ts +0 -32
- package/src/core/normalize.test.ts +0 -98
- package/src/create/create.test.ts +0 -143
- package/src/daemon/daemon-http.test.ts +0 -114
- package/src/daemon/daemon.test.ts +0 -267
- package/src/daemon/main.test.ts +0 -413
- package/src/enable/enable.test.ts +0 -95
- package/src/enable/provisionCommand.test.ts +0 -107
- package/src/identity/identity.test.ts +0 -279
- package/src/identity/profileStandard.test.ts +0 -204
- package/src/init/init.test.ts +0 -215
- package/src/init/runtime-resolve.test.ts +0 -49
- package/src/install/install.test.ts +0 -66
- package/src/install/signing.test.ts +0 -84
- package/src/launch/bootdeliver.test.ts +0 -108
- package/src/launch/bootstrap.test.ts +0 -56
- package/src/launch/canary.test.ts +0 -346
- package/src/launch/cmdlog.test.ts +0 -94
- package/src/launch/codexHooksTrust.test.ts +0 -248
- package/src/launch/composeSystemPrompt.layers.test.ts +0 -445
- package/src/launch/composeSystemPrompt.test.ts +0 -145
- package/src/launch/hostComposerOccupied.test.ts +0 -63
- package/src/launch/invocation.test.ts +0 -174
- package/src/launch/launch.test.ts +0 -359
- package/src/launch/launchd.test.ts +0 -499
- package/src/launch/nativeMemory.test.ts +0 -193
- package/src/launch/ptyHost.test.ts +0 -38
- package/src/launch/readyGateModel.test.ts +0 -72
- package/src/launch/sockdir.test.ts +0 -74
- package/src/lifecycle/eventlog.test.ts +0 -114
- package/src/lifecycle/lifecycle.test.ts +0 -1056
- package/src/lifecycle/queue.test.ts +0 -185
- package/src/onboard/memory.test.ts +0 -157
- package/src/onboard/onboard.test.ts +0 -39
- package/src/onboard/steps.test.ts +0 -201
- package/src/provision/provision.test.ts +0 -288
- package/src/registry/registry.test.ts +0 -432
- package/src/runtime/runtime.test.ts +0 -226
- package/src/runtime/update.test.ts +0 -192
- package/src/shadow/enumerate-skip.test.ts +0 -67
- package/src/shadow/gate.test.ts +0 -286
- package/src/shadow/install.test.ts +0 -153
- package/src/shadow/shadow.test.ts +0 -42
- package/src/status/status.test.ts +0 -208
- package/src/storage/peers-home.test.ts +0 -34
- package/src/storage/rotatelog.test.ts +0 -44
- package/src/storage/storage.test.ts +0 -65
- package/src/supervisor/attached-marker.test.ts +0 -84
- package/src/supervisor/boot.test.ts +0 -66
- package/src/supervisor/client.attach.test.ts +0 -107
- package/src/supervisor/daemon.test.ts +0 -213
- package/src/supervisor/deliver.test.ts +0 -58
- package/src/supervisor/panelog.test.ts +0 -95
- package/src/supervisor/protocol.test.ts +0 -222
- package/src/supervisor/selfargv.test.ts +0 -22
- package/src/supervisor/spinner-strip.test.ts +0 -52
- package/src/transport/compactDone.test.ts +0 -144
- package/src/transport/composerQueue.test.ts +0 -204
- package/src/transport/hostControl.test.ts +0 -87
- package/src/transport/hostDeliver.test.ts +0 -137
- package/src/transport/hostLive.test.ts +0 -50
- package/src/transport/routesend-wake.test.ts +0 -357
- package/src/update/update.test.ts +0 -208
package/src/status/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// by the PROVIDER's own init/uninstall — the core only ever READS it. An absent or
|
|
5
5
|
// unreadable file is the EMPTY slot — a fully valid state (bare core), never an
|
|
6
6
|
// error (fail-open). The core never acts on heartbeat staleness — it only REPORTS
|
|
7
|
-
// it (healing the provider's daemon is the provider's job
|
|
7
|
+
// it (healing the provider's daemon is the provider's job).
|
|
8
8
|
|
|
9
9
|
import { closeSync, openSync, readFileSync, statSync } from 'fs'
|
|
10
10
|
import { join } from 'path'
|
|
@@ -18,18 +18,18 @@ import { iapeerBinPath } from '../install/index.ts'
|
|
|
18
18
|
export const MEMORY_PROVIDER_FILE = 'memory-provider.json'
|
|
19
19
|
|
|
20
20
|
// NB: the v1.1 `plugin` block (MemoryProviderPlugin + its parser) was REMOVED
|
|
21
|
-
//
|
|
22
|
-
//
|
|
21
|
+
// (the plugin form was retired ecosystem-wide; contract §Плагин провайдера is a
|
|
22
|
+
// tombstone). An unknown `plugin` key in a legacy
|
|
23
23
|
// declaration is simply ignored — the same fail-open as any unknown block.
|
|
24
24
|
|
|
25
25
|
/** The provider's provision command (declaration v1.2, контракт §Provision
|
|
26
|
-
* провайдера —
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
26
|
+
* провайдера — inversion of the surface-list model). The slot declares not
|
|
27
|
+
* surfaces but a COMMAND the core shells into at the lifecycle joints (birth /
|
|
28
|
+
* verb sweeps / remove); surface forms and their uninstall accounting live
|
|
29
|
+
* entirely with the provider. The `command` must be ABSOLUTE (the daemon runs
|
|
30
|
+
* under launchd's minimal PATH); `args` get PER-ARG placeholder substitution
|
|
31
|
+
* ({cwd}/{runtime}/{personality}/{occasion}) and are spawned WITHOUT a shell
|
|
32
|
+
* (injection/quoting class). */
|
|
33
33
|
export interface MemoryProviderProvision {
|
|
34
34
|
/** Absolute path to the provider's executable. */
|
|
35
35
|
command: string
|
|
@@ -179,7 +179,7 @@ export function formatHostStatus(s: HostStatus): string {
|
|
|
179
179
|
const daemon = s.daemon.healthy
|
|
180
180
|
? `healthy${s.daemon.url ? ` @ ${s.daemon.url}` : ''}${s.daemon.sock ? ` + ${s.daemon.sock}` : ''}`
|
|
181
181
|
: 'NOT healthy (socket not accepting connections)'
|
|
182
|
-
// Heartbeat interpretation (slot contract, provider semantics
|
|
182
|
+
// Heartbeat interpretation (slot contract, provider semantics):
|
|
183
183
|
// file REMOVED on graceful shutdown → declared-but-absent = daemon not running;
|
|
184
184
|
// present = age shown. The core only REPORTS — staleness healing is the
|
|
185
185
|
// provider's own job (its verify/repair), never the core's.
|
package/src/storage/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// peers.ts (resolveGlobalRoot/resolvePeersPaths/ensureGlobalIapScaffold) +
|
|
5
5
|
// identity.ts (ensureLocalIapScaffold/ensureLocalRuntimeScopes/peerProfilePath).
|
|
6
6
|
//
|
|
7
|
-
// Structural invariant (#3
|
|
7
|
+
// Structural invariant (#3): peers-profiles.json is
|
|
8
8
|
// the registry's exclusive, locked write target. `writeFileAtomic` REFUSES that
|
|
9
9
|
// basename so no module can write the registry file out from under the lock by
|
|
10
10
|
// reaching for the generic atomic-write primitive. The registry keeps its own
|
package/src/supervisor/daemon.ts
CHANGED
|
@@ -27,11 +27,17 @@ import { modelToPlainText } from '../shadow/render.ts'
|
|
|
27
27
|
import { codexAdapter } from '../launch/adapters/codex.ts'
|
|
28
28
|
import { claudeAdapter } from '../launch/adapters/claude.ts'
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
/** Resolve a runtime launcher from the host AT CALL TIME — env override (IAPEER_<RT>_BIN, the same
|
|
31
|
+
* knob the rest of the foundation uses) → PATH lookup — never a baked machine-specific path. Returns
|
|
32
|
+
* undefined for an unknown runtime, incl. the hermetic `tick` test stream (which uses TICK_CMD, so the
|
|
33
|
+
* spawn/attach/reattach tests never need a real claude/codex on the box). */
|
|
34
|
+
function knownLauncher(runtime: string): string | undefined {
|
|
35
|
+
const override =
|
|
36
|
+
runtime === 'claude' ? process.env.IAPEER_CLAUDE_BIN
|
|
37
|
+
: runtime === 'codex' ? process.env.IAPEER_CODEX_BIN
|
|
38
|
+
: undefined
|
|
39
|
+
if (override?.trim()) return override.trim()
|
|
40
|
+
return Bun.which(runtime) ?? undefined
|
|
35
41
|
}
|
|
36
42
|
const TICK_CMD = ['sh', '-c', 'i=0; while true; do printf "STREAMTICK_%d\\r\\n" "$i"; i=$((i+1)); sleep 0.3; done']
|
|
37
43
|
|
|
@@ -84,7 +90,7 @@ export interface SupervisorDaemonOptions {
|
|
|
84
90
|
runDir: string
|
|
85
91
|
/** Child working directory (default: runDir — a throwaway scratch for dark validation). */
|
|
86
92
|
cwd?: string
|
|
87
|
-
/** Override the runtime launcher (else
|
|
93
|
+
/** Override the runtime launcher (else resolved from env override / PATH, else the bare name). */
|
|
88
94
|
bin?: string
|
|
89
95
|
/** SERVING SEAM (slice b): the composed runtime argv (buildLaunchInvocation). When set, the daemon
|
|
90
96
|
* serves THIS verbatim instead of the bare [bin] — the supervisor is a HOST, not a composer
|
|
@@ -127,7 +133,7 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
|
|
|
127
133
|
const ser = new SerializeAddon()
|
|
128
134
|
xterm.loadAddon(ser)
|
|
129
135
|
|
|
130
|
-
const bin = opts.bin ?? (
|
|
136
|
+
const bin = opts.bin ?? knownLauncher(runtime) ?? runtime
|
|
131
137
|
// SERVING SEAM (slice b): opts.argv (launch-composed, carries the system-prompt swap + PEER_START_ARGS)
|
|
132
138
|
// is served verbatim; else the bare conduit ([bin], or the deterministic tick stream for tests).
|
|
133
139
|
const CMD = opts.argv ?? (runtime === 'tick' ? TICK_CMD : [bin])
|
|
@@ -170,7 +176,7 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
|
|
|
170
176
|
/* */
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
|
-
// CRASH-ROBUSTNESS
|
|
179
|
+
// CRASH-ROBUSTNESS: a crashed predecessor daemon skips shutdown-cleanup, so a STALE
|
|
174
180
|
// `.attached` could survive into this fresh daemon — and a stale-present marker would make the
|
|
175
181
|
// warm-deliver gate believe a human is attached when none is, holding deliveries forever (the
|
|
176
182
|
// anti-bug inverted). A fresh daemon has ZERO clients, so clear the marker on START (idempotent).
|
package/src/transport/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// ViaTmux byte layout) is ported BYTE-FOR-BYTE — it is the validated 0.7.6
|
|
9
9
|
// deterministic submit and must not be refactored (anti-regression of the
|
|
10
10
|
// Enter-swallow flap; blueprint §5 "submit-надёжность"). The ONLY contract-
|
|
11
|
-
// sanctioned change (
|
|
11
|
+
// sanctioned change (docs/Рантайм-адаптеры): the prompt glyphs /
|
|
12
12
|
// paste patterns are no longer a hardcoded union here — they come from the target
|
|
13
13
|
// runtime's adapter.deliveryMarkers. The poll/re-press logic is untouched; only the
|
|
14
14
|
// marker SOURCE moved, so the timing behaviour is identical.
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
import { buildEnvelope } from '../codec/index.ts'
|
|
39
39
|
import { findPeer, readPeersIndex, type PeerRecord } from '../registry/index.ts'
|
|
40
40
|
import type { ResolvedCaller } from '../identity/index.ts'
|
|
41
|
-
// Delivery markers are OWNED by the runtime adapter
|
|
41
|
+
// Delivery markers are OWNED by the runtime adapter. transport
|
|
42
42
|
// reads them from getAdapter(target.runtime) for the tui submit path. One-way
|
|
43
43
|
// dependency: launch does NOT import transport, so no cycle.
|
|
44
44
|
import { getAdapter } from '../launch/index.ts'
|
|
@@ -480,7 +480,7 @@ export function deliverViaTmux(target: DeliveryTarget, envelope: string, cwd?: s
|
|
|
480
480
|
// transcript — only a model turn does), so an advance afterwards proves a busy
|
|
481
481
|
// session is alive. null proxy / no cwd → 0 (the advance check is skipped below).
|
|
482
482
|
const baselineMtime = cwd ? adapter.newestActivityMtime(cwd) ?? 0 : 0
|
|
483
|
-
// Submit markers come from the target runtime's adapter
|
|
483
|
+
// Submit markers come from the target runtime's adapter.
|
|
484
484
|
const confirmed = submitIntoTui(target.socketPath, target.address, envelope, adapter.deliveryMarkers)
|
|
485
485
|
tmux(target.socketPath, 'delete-buffer', '-b', bufferName)
|
|
486
486
|
if (confirmed) return ok(undefined) // idle session accepted the submit
|
|
@@ -794,8 +794,8 @@ function compactReadyGraceMs(env: NodeJS.ProcessEnv | undefined): number {
|
|
|
794
794
|
* Idle-composer (`isInputReady`) is treated as a FAST-PATH confirmation, NOT a
|
|
795
795
|
* requirement. A healthy large-context session auto-continues into a working turn
|
|
796
796
|
* right after compact — its composer is legitimately busy (not idle) for a while, so
|
|
797
|
-
* requiring idle here false-failed a finished compact (
|
|
798
|
-
*
|
|
797
|
+
* requiring idle here false-failed a finished compact (marker seen, but the first
|
|
798
|
+
* post-compact idle only arrived hundreds of seconds later, past the ~290s gate).
|
|
799
799
|
* Therefore: marker seen + composer idle → 'transcript+ready' (clean); marker seen +
|
|
800
800
|
* composer still busy past a short grace → 'transcript' (busy-but-done, still SUCCESS).
|
|
801
801
|
*
|
|
@@ -1079,8 +1079,8 @@ export interface RouteDeps {
|
|
|
1079
1079
|
* wake, so it held «the topic the session woke with», while the resolver's
|
|
1080
1080
|
* semantics want «the topic the session last worked on». A long-lived executor
|
|
1081
1081
|
* that took live-delivered messages of topic B all day then false-FRESHED on
|
|
1082
|
-
* stop→start→wake with topic B (
|
|
1083
|
-
*
|
|
1082
|
+
* stop→start→wake with topic B (a day of context lost to
|
|
1083
|
+
* cause=idle-reaped-new-topic). Injected so transport never
|
|
1084
1084
|
* imports lifecycle (layering — main.ts is where the two meet); call sites
|
|
1085
1085
|
* swallow hook errors (a hook must never fail a delivered message). */
|
|
1086
1086
|
noteLiveTopic?: (identity: string, topic: string) => void
|
|
@@ -1324,12 +1324,12 @@ function validateAttachments(value: readonly string[] = []): Result<string[]> {
|
|
|
1324
1324
|
return ok(out)
|
|
1325
1325
|
}
|
|
1326
1326
|
|
|
1327
|
-
// ─── Telegram-domain sender policy
|
|
1327
|
+
// ─── Telegram-domain sender policy ─
|
|
1328
1328
|
|
|
1329
1329
|
/** A SENDER face in the telegram domain: a non-empty interfaces.telegram.bot (the
|
|
1330
1330
|
* bot machine-key) in the peer's registry passport. Deliberately bot-ONLY, not
|
|
1331
|
-
* bot|user_id — the bridge picks the SENDING bot from the sender's bot key
|
|
1332
|
-
*
|
|
1331
|
+
* bot|user_id — the bridge picks the SENDING bot from the sender's bot key:
|
|
1332
|
+
* a user_id grants a receive/operator
|
|
1333
1333
|
* identity but no ability to send, so a user_id-only sender passing the guard
|
|
1334
1334
|
* would still die at the bridge — a late asynchronous failure where the guard
|
|
1335
1335
|
* exists to give a synchronous one. The guard passes exactly what the bridge can
|
|
@@ -1360,7 +1360,7 @@ function telegramSenderGuard(
|
|
|
1360
1360
|
if (targetRuntime !== 'telegram') return ok(undefined)
|
|
1361
1361
|
if (hasTelegramPresence(caller.record)) return ok(undefined)
|
|
1362
1362
|
return err(
|
|
1363
|
-
`telegram policy: sender "${caller.personality}" has no telegram face (no interfaces.telegram.bot in its passport) — message to "${targetPersonality}" NOT delivered; route via a telegram
|
|
1363
|
+
`telegram policy: sender "${caller.personality}" has no telegram face (no interfaces.telegram.bot in its passport) — message to "${targetPersonality}" NOT delivered; route via a peer that has a telegram bot in its passport, or provision a bot for this sender`,
|
|
1364
1364
|
)
|
|
1365
1365
|
}
|
|
1366
1366
|
|
package/src/update/index.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// Scope: the foundation ONLY (the @agfpd/iapeer binary + its daemon + launchd
|
|
18
18
|
// registrations of foundation-owned infra jobs that point at that binary). It never
|
|
19
19
|
// rewrites those plists, never updates runtime packages (telegram-runtime /
|
|
20
|
-
// notifier-runtime /
|
|
20
|
+
// notifier-runtime / capability plugins), and never touches foreign / persistent-peer fleet
|
|
21
21
|
// plists — only sentinel-marked foundation-owned com.iapeer.* jobs are recycled.
|
|
22
22
|
//
|
|
23
23
|
// updateIapeer takes its three side-effects as INJECTED deps so the version-gate is
|
|
@@ -184,7 +184,7 @@ function defaultResolveVersion(spec: string, env: NodeJS.ProcessEnv): string | n
|
|
|
184
184
|
* install) npx resolves that bin NAME to the COMPILED binary already on PATH and
|
|
185
185
|
* runs ITS `install` — which cannot rebuild itself from source (`bun build --compile`
|
|
186
186
|
* gets a `/$bunfs/root` entrypoint → FileNotFound) — instead of fetching + running the
|
|
187
|
-
* freshly-published source. Verified reproducible
|
|
187
|
+
* freshly-published source. Verified reproducible: with NO
|
|
188
188
|
* `iapeer` on PATH the same npx invocation prints `command not found` — it never
|
|
189
189
|
* installs the package — so this is a structural bin-name collision, NOT the
|
|
190
190
|
* publish-propagation transient (waiting/retry does not cure it).
|
|
@@ -287,8 +287,8 @@ export function updateIapeer(deps: UpdateDeps = {}): UpdateResult {
|
|
|
287
287
|
if (!runInstall(desired, env)) {
|
|
288
288
|
// NB: the installer is the DETERMINISTIC pack+build path (no npx — see
|
|
289
289
|
// defaultRunInstall); the most common cause right after a publish is the npm
|
|
290
|
-
// CDN tarball lagging the version metadata (
|
|
291
|
-
//
|
|
290
|
+
// CDN tarball lagging the version metadata (`npm view` can already show the
|
|
291
|
+
// version while `npm pack` still fails; a retry ~1 min later succeeds).
|
|
292
292
|
return {
|
|
293
293
|
status: 'failed',
|
|
294
294
|
from,
|