@agfpd/iapeer 0.4.70 → 0.4.71
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/package.json
CHANGED
package/src/core/constants.ts
CHANGED
|
@@ -65,6 +65,27 @@ export function defaultIntelligenceForRuntime(runtime: string): Intelligence {
|
|
|
65
65
|
return 'artificial'
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The intelligences a runtime may LEGITIMATELY carry (the single Ф0 source; provision
|
|
70
|
+
* validates against it, the launch gate enforces it). Identity (natural/absent/artificial)
|
|
71
|
+
* is ORTHOGONAL to the channel: a human-channel runtime can carry a HUMAN (natural) OR a
|
|
72
|
+
* FACELESS SERVICE bot (absent) — e.g. a Telegram approval-card bot — but never an LLM agent
|
|
73
|
+
* (artificial) on that channel. A service-only runtime carries services (absent). An agentic
|
|
74
|
+
* runtime carries an LLM (artificial). The DEFAULT (defaultIntelligenceForRuntime) stays the
|
|
75
|
+
* first of each set, so an existing peer with no explicit nature is unchanged — `absent` on a
|
|
76
|
+
* channel runtime is strictly OPT-IN (an explicit `--intelligence absent` / manifest decl).
|
|
77
|
+
*/
|
|
78
|
+
export function allowedIntelligencesForRuntime(runtime: string): readonly Intelligence[] {
|
|
79
|
+
if (NATURAL_RUNTIMES.has(runtime)) return ['natural', 'absent']
|
|
80
|
+
if (ABSENT_RUNTIMES.has(runtime)) return ['absent']
|
|
81
|
+
return ['artificial']
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Is `intelligence` a legitimate nature for `runtime`? (provision fail-loud + launch gate.) */
|
|
85
|
+
export function isIntelligenceAllowedForRuntime(runtime: string, intelligence: Intelligence): boolean {
|
|
86
|
+
return allowedIntelligencesForRuntime(runtime).includes(intelligence)
|
|
87
|
+
}
|
|
88
|
+
|
|
68
89
|
// Infra runtimes are ALWAYS-ON (held live by launchd KeepAlive), as opposed to the
|
|
69
90
|
// warm-on-demand agentic runtimes (claude/codex, woken by the daemon). Liveness is
|
|
70
91
|
// a property of the RUNTIME, not the personality (zone Идентичность). Infra runtimes
|
package/src/identity/index.ts
CHANGED
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
IAPEER_DIR,
|
|
12
12
|
PEER_PROFILE_FILE,
|
|
13
13
|
NAME_RE,
|
|
14
|
+
allowedIntelligencesForRuntime,
|
|
14
15
|
defaultIntelligenceForRuntime,
|
|
15
16
|
isInfraRuntime,
|
|
17
|
+
isIntelligenceAllowedForRuntime,
|
|
16
18
|
isRuntime,
|
|
17
19
|
isValidName,
|
|
18
20
|
normalizeIntelligenceValue,
|
|
@@ -131,6 +133,12 @@ export interface EnsurePeerProfileOptions {
|
|
|
131
133
|
* always-on plist so launchd's minimal PATH resolves it. Forwarded to
|
|
132
134
|
* installAlwaysOnPlist; ignored for warm-on-demand runtimes. */
|
|
133
135
|
runtimeBin?: string
|
|
136
|
+
/** Explicit peer nature (natural/absent/artificial). OPT-IN override of the runtime
|
|
137
|
+
* default (defaultIntelligenceForRuntime): a channel runtime defaults `natural` but may be
|
|
138
|
+
* provisioned `absent` for a FACELESS SERVICE bot (e.g. a Telegram approval-card bot).
|
|
139
|
+
* Validated against allowedIntelligencesForRuntime — an out-of-set value fails LOUD. Absent
|
|
140
|
+
* (undefined) ⇒ the runtime default (unchanged for every existing peer). */
|
|
141
|
+
intelligence?: Intelligence
|
|
134
142
|
/** В36 — peer description, persisted into the LOCAL profile (the source of truth the
|
|
135
143
|
* registry is reindexed FROM). Writing it only to the registry made it a stale copy:
|
|
136
144
|
* the first reindexFromLocals (addRuntime on a dual-runtime create, connect telegram,
|
|
@@ -503,6 +511,21 @@ export function ensurePeerProfile(options: EnsurePeerProfileOptions): PeerProfil
|
|
|
503
511
|
const peers = options.peers ?? []
|
|
504
512
|
ensureLocalIapScaffold(cwd)
|
|
505
513
|
const discoveredRuntimes = discoverPeerRuntimes(cwd, options.runtime)
|
|
514
|
+
// Nature = the EXPLICIT intelligence when supplied (validated against the runtime's allowed
|
|
515
|
+
// set — an out-of-set value, e.g. artificial on telegram, fails LOUD), else the runtime
|
|
516
|
+
// default. This is where a FACELESS SERVICE bot (absent) on a channel runtime becomes
|
|
517
|
+
// first-class (docs/Идентичность); an omitted intelligence keeps every existing peer's
|
|
518
|
+
// default nature unchanged.
|
|
519
|
+
const resolvedIntelligence = (rt: Runtime): Intelligence => {
|
|
520
|
+
const explicit = options.intelligence
|
|
521
|
+
if (explicit === undefined) return defaultIntelligenceForRuntime(rt)
|
|
522
|
+
if (!isIntelligenceAllowedForRuntime(rt, explicit)) {
|
|
523
|
+
throw new IapError(
|
|
524
|
+
`intelligence "${explicit}" is not valid for runtime "${rt}" — allowed: ${allowedIntelligencesForRuntime(rt).join(', ')}`,
|
|
525
|
+
)
|
|
526
|
+
}
|
|
527
|
+
return explicit
|
|
528
|
+
}
|
|
506
529
|
const existing = readPeerProfile(cwd)
|
|
507
530
|
if (!existing) {
|
|
508
531
|
let personality: string
|
|
@@ -550,7 +573,7 @@ export function ensurePeerProfile(options: EnsurePeerProfileOptions): PeerProfil
|
|
|
550
573
|
// В36 — the description lands in the LOCAL profile at birth (source of truth);
|
|
551
574
|
// the registry row is a projection of this file, not the other way around.
|
|
552
575
|
description: options.description?.trim() ?? '',
|
|
553
|
-
intelligence:
|
|
576
|
+
intelligence: resolvedIntelligence(options.runtime),
|
|
554
577
|
}
|
|
555
578
|
ensureLocalRuntimeScopes(cwd, profile.runtimes)
|
|
556
579
|
// INFRA runtime → provision the always-on launchd plist that holds it live.
|
|
@@ -607,7 +630,10 @@ export function ensurePeerProfile(options: EnsurePeerProfileOptions): PeerProfil
|
|
|
607
630
|
runtimeBin: options.runtimeBin,
|
|
608
631
|
env: options.env,
|
|
609
632
|
})
|
|
610
|
-
|
|
633
|
+
// Re-provision honors an EXPLICIT nature (a manifest-declared absent service bot survives
|
|
634
|
+
// update-runtime re-provision), else the runtime default (the legacy vocab-flip this fix
|
|
635
|
+
// preserved). resolvedIntelligence validates the explicit against the runtime's allowed set.
|
|
636
|
+
intelligence = resolvedIntelligence(options.runtime)
|
|
611
637
|
}
|
|
612
638
|
// В36 — an explicit description on RE-provision updates the local profile too (H1 in
|
|
613
639
|
// writePeerProfileAtomic still guards: absent/empty never wipes an existing value).
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
// that is install-time (blueprint §0.6 fast-wake), not session bring-up.
|
|
24
24
|
|
|
25
25
|
import type { ControlCommand, ControlPlan, LaunchAdapterConfig, LaunchSpec, RuntimeAdapter } from '../types.ts'
|
|
26
|
+
import { allowedIntelligencesForRuntime } from '../../core/constants.ts'
|
|
26
27
|
|
|
27
28
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
29
|
// telegramAdapter
|
|
@@ -38,13 +39,14 @@ export const telegramAdapter: RuntimeAdapter = {
|
|
|
38
39
|
deliveryMarkers: { promptGlyphs: [] },
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
|
-
* telegram
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
42
|
+
* telegram carries a HUMAN (natural) OR a FACELESS SERVICE bot (absent) — but never an
|
|
43
|
+
* LLM agent (artificial), which would route a human's channel to an agent/script. Launch
|
|
44
|
+
* REFUSES anything outside this set (fail-loud), the persistent-peer FATAL guard relaxed to
|
|
45
|
+
* first-class faceless service bots (e.g. a Telegram approval-card bot). Sourced from the
|
|
46
|
+
* single Ф0 truth (allowedIntelligencesForRuntime); enforced by the launch primitive against
|
|
47
|
+
* LaunchSpec.intelligence. Source of intelligence → docs/Идентичность.
|
|
46
48
|
*/
|
|
47
|
-
|
|
49
|
+
allowedIntelligences: allowedIntelligencesForRuntime('telegram'),
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
52
|
* argv = telegramBin + 'run' + extraArgs (telegram-start.sh:119,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
//
|
|
10
10
|
// voicetalk is a presence-runtime for a HUMAN (the owner's voice channel), modelled on
|
|
11
11
|
// telegram per the foundation presence-runtime contract: kind:'router',
|
|
12
|
-
// usesDoctrine:false,
|
|
12
|
+
// usesDoctrine:false, allowedIntelligences:['natural','absent'], argv = `<bin> run <extra>`. The
|
|
13
13
|
// STT/TTS engines and providers live in a shared voice service (voice-connect), NOT in
|
|
14
14
|
// this adapter and NOT in the peer passport — interfaces.voicetalk carries only the
|
|
15
15
|
// binding ({wake_word, device}), opaque to the foundation.
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
// bring-up.
|
|
20
20
|
|
|
21
21
|
import type { ControlCommand, ControlPlan, LaunchAdapterConfig, LaunchSpec, RuntimeAdapter } from '../types.ts'
|
|
22
|
+
import { allowedIntelligencesForRuntime } from '../../core/constants.ts'
|
|
22
23
|
|
|
23
24
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
25
|
// voicetalkAdapter
|
|
@@ -34,13 +35,12 @@ export const voicetalkAdapter: RuntimeAdapter = {
|
|
|
34
35
|
deliveryMarkers: { promptGlyphs: [] },
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
|
-
* voicetalk
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* source of intelligence → docs/Идентичность.
|
|
38
|
+
* voicetalk carries a HUMAN (natural) OR a FACELESS SERVICE bot (absent) — never an LLM
|
|
39
|
+
* agent (artificial), which would route the owner's voice channel to an agent/script. Same
|
|
40
|
+
* nature gate as telegram, sourced from the single Ф0 truth (allowedIntelligencesForRuntime);
|
|
41
|
+
* enforced by the launch primitive against LaunchSpec.intelligence. Source → docs/Идентичность.
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
allowedIntelligences: allowedIntelligencesForRuntime('voicetalk'),
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* argv = voicetalkBin + 'run' + extraArgs.
|
package/src/launch/index.ts
CHANGED
|
@@ -131,14 +131,16 @@ export const launch: LaunchFn = async (
|
|
|
131
131
|
const { identity, socketPath: sock, cwd } = spec
|
|
132
132
|
const env = cfg.env ?? process.env
|
|
133
133
|
|
|
134
|
-
// (0) Intelligence gate (fail-loud BEFORE any
|
|
135
|
-
//
|
|
136
|
-
// not
|
|
137
|
-
//
|
|
138
|
-
|
|
134
|
+
// (0) Intelligence gate (fail-loud BEFORE any bring-up work): an adapter that declares
|
|
135
|
+
// allowedIntelligences (telegram/voicetalk → ['natural','absent']) refuses a peer whose
|
|
136
|
+
// nature is not IN the set — and refuses too when the nature is unknown (cannot confirm).
|
|
137
|
+
// A channel runtime carries a human (natural) OR a faceless service bot (absent), never an
|
|
138
|
+
// LLM agent (artificial). Ports the persistent-peer FATAL human-channel guard, relaxed to
|
|
139
|
+
// first-class faceless service bots (docs/Рантайм-адаптеры).
|
|
140
|
+
if (adapter.allowedIntelligences && (spec.intelligence == null || !adapter.allowedIntelligences.includes(spec.intelligence))) {
|
|
139
141
|
return fail(
|
|
140
142
|
identity,
|
|
141
|
-
`runtime "${spec.runtime}" requires intelligence
|
|
143
|
+
`runtime "${spec.runtime}" requires intelligence ∈ {${adapter.allowedIntelligences.join(', ')}}, ` +
|
|
142
144
|
`peer "${spec.personality}" is ${spec.intelligence ?? 'unknown'} — refusing to launch`,
|
|
143
145
|
)
|
|
144
146
|
}
|
package/src/launch/types.ts
CHANGED
|
@@ -160,9 +160,9 @@ export interface LaunchSpec {
|
|
|
160
160
|
/** Free-form extra CLI args (PEER_START_ARGS). */
|
|
161
161
|
extraArgs?: string[]
|
|
162
162
|
/** Peer intelligence (artificial/natural/absent). Used to enforce an adapter's
|
|
163
|
-
* intelligence gate at launch (telegram
|
|
164
|
-
* less throwaway may omit it, but an adapter that declares
|
|
165
|
-
* then refuses (cannot confirm the
|
|
163
|
+
* intelligence gate at launch (telegram allows natural|absent). Optional: a doctrine-
|
|
164
|
+
* less throwaway may omit it, but an adapter that declares allowedIntelligences
|
|
165
|
+
* then refuses (cannot confirm the nature is in the set). */
|
|
166
166
|
intelligence?: Intelligence
|
|
167
167
|
/** Human-approval mode (docs/17): `yolo` (default/omitted) launches with the
|
|
168
168
|
* runtime bypass flag (current fleet behavior); `gated` launches WITHOUT bypass
|
|
@@ -273,13 +273,14 @@ export interface RuntimeAdapter {
|
|
|
273
273
|
deliveryConfirm?: 'transcript' | 'socket-ack'
|
|
274
274
|
|
|
275
275
|
/**
|
|
276
|
-
* If set, launch REFUSES unless the peer's intelligence
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
276
|
+
* If set, launch REFUSES unless the peer's intelligence is IN this set (fail-loud —
|
|
277
|
+
* also when the nature is unknown). A channel runtime carries a HUMAN (natural) OR a
|
|
278
|
+
* FACELESS SERVICE bot (absent) but never an LLM agent (artificial): telegram/voicetalk →
|
|
279
|
+
* ['natural','absent'] (sourced from allowedIntelligencesForRuntime — the single Ф0 truth).
|
|
280
|
+
* Most adapters omit it (no nature gate — claude/codex/notifier). Source of intelligence →
|
|
280
281
|
* docs/Идентичность; enforced by the launch primitive against LaunchSpec.intelligence.
|
|
281
282
|
*/
|
|
282
|
-
|
|
283
|
+
allowedIntelligences?: readonly Intelligence[]
|
|
283
284
|
|
|
284
285
|
/**
|
|
285
286
|
* Build the runtime argv: binary + flags, wiring systemPromptFile per-runtime
|
package/src/provision/index.ts
CHANGED
|
@@ -89,6 +89,11 @@ export async function provisionPeer(opts: ProvisionPeerOptions): Promise<Provisi
|
|
|
89
89
|
peers,
|
|
90
90
|
personality: opts.personality,
|
|
91
91
|
runtimeBin,
|
|
92
|
+
// The EXPLICIT nature now reaches the LOCAL profile too (A1) — previously it landed only
|
|
93
|
+
// in the registry upsert below, so a `--intelligence absent` telegram bot got a natural
|
|
94
|
+
// local profile (split-brain) and its plist crash-looped the natural gate. Validated
|
|
95
|
+
// against the runtime's allowed set inside ensurePeerProfile.
|
|
96
|
+
intelligence: opts.intelligence,
|
|
92
97
|
// В36 — description goes into the LOCAL profile (source of truth); the registry
|
|
93
98
|
// upsert below then persists a value reindexFromLocals can no longer wipe.
|
|
94
99
|
description: opts.description,
|