@agfpd/iapeer-memory 0.2.7 → 0.2.8
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 +2 -2
- package/src/cli.ts +9 -7
- package/src/commands/dream-collect.ts +645 -0
- package/src/commands/init.ts +11 -2
- package/src/commands/update.ts +13 -2
- package/src/commands/verify.ts +20 -3
- package/src/fleet.ts +1 -1
- package/src/paths.ts +4 -0
- package/src/provision.ts +14 -0
- package/src/templates/roles-en.ts +82 -56
- package/src/templates/roles-ru.ts +80 -51
- package/src/watcher.ts +56 -14
- package/src/commands/dream-paths.ts +0 -153
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `iapeer-memory dream-paths [--iapeer-bin P]` — tick-time resolution of the
|
|
3
|
-
* DreamWeaver fan-out (P5 §4.3, boris-accepted form (б) + source (1)).
|
|
4
|
-
*
|
|
5
|
-
* The weekly DREAM_TICK lands in a FRESH index session; the Index shells
|
|
6
|
-
* THIS verb and fans DreamWeaver out over its output — one agent-memory
|
|
7
|
-
* subfolder per task, transcript globs riding along. Resolution happens AT
|
|
8
|
-
* THE TICK, never baked into the timer registration: a baked snapshot
|
|
9
|
-
* re-creates the «фаза D мертва, glob-skip маскирует» class one layer down.
|
|
10
|
-
*
|
|
11
|
-
* SOURCE = the LIVE registry (`iapeer list --json`), not fleet.json — the
|
|
12
|
-
* freshness proof (facts, 11.06): birth-provision does NOT touch fleet.json
|
|
13
|
-
* (writeFleetMap call sites: init/update/verify --repair only) and the
|
|
14
|
-
* SessionStart kick is heartbeat-gated (silent on a healthy host), so a
|
|
15
|
-
* peer born after the last update is INVISIBLE to fleet.json for weeks —
|
|
16
|
-
* the live registry is the only source that sees it. Read-as-egress: a
|
|
17
|
-
* legitimate live channel of the prod CLI (the refusing test handle blocks
|
|
18
|
-
* it; hermetic tests pass --iapeer-bin).
|
|
19
|
-
*
|
|
20
|
-
* READ-ONLY by contract: one registry list spawn + vault readdir +
|
|
21
|
-
* realpath. No writes, no signals, no detached spawns.
|
|
22
|
-
*
|
|
23
|
-
* Transcript path forms (host facts):
|
|
24
|
-
* claude — `~/.claude/projects/<slug(cwd)>/*.jsonl`; slug = every
|
|
25
|
-
* non-alphanumeric of the REGISTRY cwd → '-' (live form:
|
|
26
|
-
* /Users/macmini/.iapeer/peers/index → -Users-macmini--iapeer-peers-index;
|
|
27
|
-
* the registry cwd verbatim, NOT realpath — claude slugs the path the
|
|
28
|
-
* session launched in);
|
|
29
|
-
* codex — `~/.codex/sessions/**\/rollout-*.jsonl` (HOST-WIDE pool) +
|
|
30
|
-
* `cwdFilter` = realpath(cwd): the worker matches the payload's
|
|
31
|
-
* session_meta.cwd — the iapeer-contract realpath rule.
|
|
32
|
-
*
|
|
33
|
-
* Folders without a live peer get `transcripts: []` — phase D skips them
|
|
34
|
-
* honestly (A–C still run); peers without a memory subfolder are not in
|
|
35
|
-
* the fan-out (nothing to consolidate).
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
import fs from "node:fs";
|
|
39
|
-
import os from "node:os";
|
|
40
|
-
import path from "node:path";
|
|
41
|
-
import { getTaxonomy, isLocaleId } from "@agfpd/iapeer-memory-core";
|
|
42
|
-
import type { Egress } from "../egress.js";
|
|
43
|
-
import { queryRegistry, type FleetPeer } from "../fleet.js";
|
|
44
|
-
|
|
45
|
-
/** Claude projects-dir slug — the live disk form (ls ~/.claude/projects). */
|
|
46
|
-
export function claudeProjectSlug(cwd: string): string {
|
|
47
|
-
return cwd.replace(/[^A-Za-z0-9]/g, "-");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export type TranscriptSpec = {
|
|
51
|
-
runtime: "claude" | "codex";
|
|
52
|
-
glob: string;
|
|
53
|
-
/** codex only: the worker filters the HOST-WIDE pool by the payload's
|
|
54
|
-
* session_meta.cwd against this realpath (iapeer contract). */
|
|
55
|
-
cwdFilter?: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export function transcriptSpecs(peer: FleetPeer, home: string): TranscriptSpec[] {
|
|
59
|
-
const specs: TranscriptSpec[] = [];
|
|
60
|
-
if (peer.runtimes.includes("claude")) {
|
|
61
|
-
specs.push({
|
|
62
|
-
runtime: "claude",
|
|
63
|
-
glob: path.join(home, ".claude", "projects", claudeProjectSlug(peer.cwd), "*.jsonl"),
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
if (peer.runtimes.includes("codex")) {
|
|
67
|
-
let real = peer.cwd;
|
|
68
|
-
try {
|
|
69
|
-
real = fs.realpathSync(peer.cwd);
|
|
70
|
-
} catch {
|
|
71
|
-
// vanished cwd — keep the registry form; the filter simply matches nothing
|
|
72
|
-
}
|
|
73
|
-
specs.push({
|
|
74
|
-
runtime: "codex",
|
|
75
|
-
glob: path.join(home, ".codex", "sessions", "**", "rollout-*.jsonl"),
|
|
76
|
-
cwdFilter: real,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
return specs;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export type DreamFolder = {
|
|
83
|
-
agent: string;
|
|
84
|
-
path: string;
|
|
85
|
-
transcripts: TranscriptSpec[];
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export function buildDreamPaths(opts: {
|
|
89
|
-
vault: string;
|
|
90
|
-
agentMemoryFolder: string;
|
|
91
|
-
peers: FleetPeer[];
|
|
92
|
-
home: string;
|
|
93
|
-
}): DreamFolder[] {
|
|
94
|
-
const memoryRoot = path.join(opts.vault, opts.agentMemoryFolder);
|
|
95
|
-
let entries: fs.Dirent[];
|
|
96
|
-
try {
|
|
97
|
-
entries = fs.readdirSync(memoryRoot, { withFileTypes: true });
|
|
98
|
-
} catch {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
const byPersonality = new Map(opts.peers.map((p) => [p.personality, p]));
|
|
102
|
-
return entries
|
|
103
|
-
.filter((e) => e.isDirectory() && !e.name.startsWith("."))
|
|
104
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
105
|
-
.map((e) => {
|
|
106
|
-
const peer = byPersonality.get(e.name);
|
|
107
|
-
return {
|
|
108
|
-
agent: e.name,
|
|
109
|
-
path: path.join(memoryRoot, e.name),
|
|
110
|
-
transcripts: peer ? transcriptSpecs(peer, opts.home) : [],
|
|
111
|
-
};
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function cmdDreamPaths(argv: string[], egress: Egress): number {
|
|
116
|
-
let iapeerBin: string | undefined;
|
|
117
|
-
for (let i = 0; i < argv.length; i++) {
|
|
118
|
-
const a = argv[i];
|
|
119
|
-
if (a === "--iapeer-bin") iapeerBin = argv[++i];
|
|
120
|
-
else {
|
|
121
|
-
console.error(`iapeer-memory dream-paths: unknown flag: ${a}`);
|
|
122
|
-
return 2;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const vault = process.env.IAPEER_MEMORY_VAULT_PATH ?? "";
|
|
127
|
-
if (!vault) {
|
|
128
|
-
console.error("iapeer-memory dream-paths: IAPEER_MEMORY_VAULT_PATH is not set — not provisioned");
|
|
129
|
-
return 1;
|
|
130
|
-
}
|
|
131
|
-
const localeRaw = process.env.IAPEER_MEMORY_LOCALE || "en";
|
|
132
|
-
if (!isLocaleId(localeRaw)) {
|
|
133
|
-
console.error(`iapeer-memory dream-paths: unknown locale "${localeRaw}"`);
|
|
134
|
-
return 1;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const q = queryRegistry(egress, { iapeerBin });
|
|
138
|
-
if ("error" in q) {
|
|
139
|
-
// LOUD: a silent empty fan-out would re-create the masked-dead-phase
|
|
140
|
-
// class — the Index sees this line and reports instead of guessing.
|
|
141
|
-
console.error(`iapeer-memory dream-paths: live registry unavailable — ${q.error}`);
|
|
142
|
-
return 1;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const folders = buildDreamPaths({
|
|
146
|
-
vault,
|
|
147
|
-
agentMemoryFolder: getTaxonomy(localeRaw).folders.agentMemory,
|
|
148
|
-
peers: q.peers,
|
|
149
|
-
home: os.homedir(),
|
|
150
|
-
});
|
|
151
|
-
console.log(JSON.stringify({ vault, folders }, null, 2));
|
|
152
|
-
return 0;
|
|
153
|
-
}
|