pi-roundtable 0.7.18 → 0.7.19
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 +6 -0
- package/docs/plugins.md +1 -0
- package/package.json +1 -1
- package/src/core/builtin/stores.ts +29 -14
- package/src/core/modules/memory/owner-memory.ts +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.7.19] - 2026-10-07
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Behavior change: in a conversation outside the agent server, such as a plugin's persona conversation run through `context.turns`, a member or admin speaker now reads and changes their own memory. Before, every such turn carried the owner's core facts and upcoming events in its system prompt, whoever spoke, and `memory_add`, `memory_search`, and `memory_remove` (member-tier tools, when a turn's selection offered them) read and changed the owner's memory. The prompt section of such a turn is headed `Memory of <name>` and lists only that speaker's facts. A speaker of the owner tier, the owner or remote MCP's speaker, keeps the owner's memory, and the owner's own conversations, agent conversations, and every tool description read as before. No data moves: facts a member stored before this release sit in the owner's memory, and the owner may remove them with `memory_remove`.
|
|
13
|
+
|
|
8
14
|
## [0.7.18] - 2026-10-05
|
|
9
15
|
|
|
10
16
|
### Fixed
|
package/docs/plugins.md
CHANGED
|
@@ -1658,6 +1658,7 @@ The runtime reads `prompt()` when it creates the conversation's session, so mess
|
|
|
1658
1658
|
The host merges every plugin's list and keeps each name once.
|
|
1659
1659
|
- A turn whose kind has no persona is refused with an error naming `personas`.
|
|
1660
1660
|
The Pi runtime refuses when it makes the session; a runtime of your own does the same, as the example's does.
|
|
1661
|
+
- With the memory addon on, a turn's `speaker` decides whose memory the system prompt carries and the memory tools change: a member's or an admin's own, and the owner's for a speaker of the owner tier.
|
|
1661
1662
|
|
|
1662
1663
|
Call `context.turns.run(input)` inside your claim's queue task to run a turn in a conversation it owns.
|
|
1663
1664
|
It shows typing and the stop control on the channel's surface, runs the turn, and emits `turnStarted` and `turnEnded` with the turn's `kind`.
|
package/package.json
CHANGED
|
@@ -4,7 +4,8 @@ import { PgMemoryStore } from "../modules/memory/owner-memory-store.ts";
|
|
|
4
4
|
import { memoryPrecheckRegistry } from "../modules/schedules/prechecks.ts";
|
|
5
5
|
import { PgScheduleStore } from "../modules/schedules/schedule-store.ts";
|
|
6
6
|
import type { RoundtablePlugin } from "../plugin.ts";
|
|
7
|
-
import { MEMORY, PRECHECKS, SCHEDULES } from "../services.ts";
|
|
7
|
+
import { MEMORY, type MemoryStore, PRECHECKS, SCHEDULES } from "../services.ts";
|
|
8
|
+
import type { SessionTool } from "../sessions.ts";
|
|
8
9
|
import { THE_SPEAKER, type Tier } from "../speakers.ts";
|
|
9
10
|
import { fixed } from "./session-tool.ts";
|
|
10
11
|
|
|
@@ -14,12 +15,37 @@ export interface MemoryOptions {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/** Each speaker keeps a memory of their own, so every tier may use the tools; the owner's reaches only the owner's turns. */
|
|
17
|
-
const MEMORY_TIERS: Readonly<Record<string, Tier>> = {
|
|
18
|
+
export const MEMORY_TIERS: Readonly<Record<string, Tier>> = {
|
|
18
19
|
memory_add: "member",
|
|
19
20
|
memory_search: "member",
|
|
20
21
|
memory_remove: "member",
|
|
21
22
|
};
|
|
22
23
|
|
|
24
|
+
/** The memory tools and prompt block of every conversation, over the given store. */
|
|
25
|
+
export function memorySessionTool(
|
|
26
|
+
memory: MemoryStore,
|
|
27
|
+
owner: MemoryOptions["owner"],
|
|
28
|
+
): SessionTool {
|
|
29
|
+
return fixed("owner-memory", (session) => {
|
|
30
|
+
// An agent session serves every speaker, so its tools name none.
|
|
31
|
+
if (session.agent)
|
|
32
|
+
return ownerMemoryExtension(
|
|
33
|
+
memory,
|
|
34
|
+
owner.id,
|
|
35
|
+
THE_SPEAKER,
|
|
36
|
+
session.speaker,
|
|
37
|
+
);
|
|
38
|
+
// Any other conversation may admit a member or an admin, who reads and changes their own
|
|
39
|
+
// memory; an owner-tier speaker, such as remote MCP, speaks as the owner.
|
|
40
|
+
const speaker = () => {
|
|
41
|
+
const current = session.speaker();
|
|
42
|
+
return current?.tier === "owner" ? undefined : current;
|
|
43
|
+
};
|
|
44
|
+
// Its tools keep the owner's words, so the owner's own chats read as before.
|
|
45
|
+
return ownerMemoryExtension(memory, owner.id, owner, speaker, false);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
23
49
|
/**
|
|
24
50
|
* The remembered facts of each speaker: the table, the store over it provided as `MEMORY`, and
|
|
25
51
|
* the memory tools and prompt block of every conversation. An addon; `memory: false` leaves it
|
|
@@ -35,18 +61,7 @@ export function memoryPlugin(options: MemoryOptions): RoundtablePlugin {
|
|
|
35
61
|
const memory = PgMemoryStore.attach(database(), owner.id);
|
|
36
62
|
services.provide(MEMORY, memory);
|
|
37
63
|
return {
|
|
38
|
-
sessionTools: [
|
|
39
|
-
fixed("owner-memory", (session) =>
|
|
40
|
-
ownerMemoryExtension(
|
|
41
|
-
memory,
|
|
42
|
-
owner.id,
|
|
43
|
-
// An agent session serves every speaker, so its tools name none.
|
|
44
|
-
session.agent ? THE_SPEAKER : owner,
|
|
45
|
-
// The owner's own chats have one speaker; the agent server's have several.
|
|
46
|
-
session.agent ? session.speaker : undefined,
|
|
47
|
-
),
|
|
48
|
-
),
|
|
49
|
-
],
|
|
64
|
+
sessionTools: [memorySessionTool(memory, owner)],
|
|
50
65
|
toolTiers: MEMORY_TIERS,
|
|
51
66
|
};
|
|
52
67
|
},
|
|
@@ -47,10 +47,12 @@ export function ownerMemoryExtension(
|
|
|
47
47
|
ownerId: string,
|
|
48
48
|
owner: OwnerIdentity,
|
|
49
49
|
/**
|
|
50
|
-
* The person the running turn is for,
|
|
51
|
-
* the owner's, is what the turn reads and changes; without it every turn is the owner's.
|
|
50
|
+
* The person the running turn is for, when it may be someone other than the owner. Their
|
|
51
|
+
* memory, not the owner's, is what the turn reads and changes; without it every turn is the owner's.
|
|
52
52
|
*/
|
|
53
53
|
speaker?: () => Speaker | undefined,
|
|
54
|
+
/** Whether the tools tell the model that each speaker has a memory of their own. */
|
|
55
|
+
describesSpeakers = speaker !== undefined,
|
|
54
56
|
): ExtensionFactory {
|
|
55
57
|
const o = ownerWords(owner);
|
|
56
58
|
/** The running turn's other speaker; undefined when the owner's own memory applies. */
|
|
@@ -59,7 +61,7 @@ export function ownerMemoryExtension(
|
|
|
59
61
|
return current && current.id !== ownerId ? current : undefined;
|
|
60
62
|
};
|
|
61
63
|
const storeOf = () => memories.forSpeaker(other()?.id ?? ownerId);
|
|
62
|
-
const shared =
|
|
64
|
+
const shared = describesSpeakers
|
|
63
65
|
? " Whoever is speaking has a memory of their own, shared by every agent; this reads and changes theirs, not someone else's."
|
|
64
66
|
: "";
|
|
65
67
|
return (pi) => {
|