pi-roundtable 0.13.0 → 0.14.1
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
CHANGED
|
@@ -5,6 +5,18 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.14.1] - 2026-10-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- A host with `discord` configured and no `agents` (an empty first team) starts again. `defineRoundtable` always added the `seeds` plugin, which had nothing to seed, and the registry refuses a plugin that adds nothing ("plugin seeds adds nothing"); the plugin now joins only when at least one agent is configured.
|
|
13
|
+
|
|
14
|
+
## [0.14.0] - 2026-10-14
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `attachmentsOf(message, dir, logger, fetchImpl?, limits?)` (`pi-roundtable/kit`) takes `limits.prepareImages?: boolean` (default `true`). `false` downloads the files only, with no `modelImagesOf`: `images` is empty and an image that cannot be decoded is not reported as a failure, so a host that hands the files to the attachment store does not decode twice or report an image failure twice. Download failures are reported as before.
|
|
19
|
+
|
|
8
20
|
## [0.13.0] - 2026-10-13
|
|
9
21
|
|
|
10
22
|
### Added
|
package/docs/plugins.md
CHANGED
|
@@ -556,7 +556,8 @@ A key the contract does not have stops the start and names the closest one.
|
|
|
556
556
|
### `context.attachments`: files from outside a turn
|
|
557
557
|
|
|
558
558
|
A surface that takes a file as it arrives, such as Discord, hands the core a link, and the core downloads it into the conversation's attachment directory.
|
|
559
|
-
The downloads of one message and of the message it replies to share a 60 second deadline, and a file that sends no byte for 10 seconds (the wait for its headers counts) is given up at once, so a stalled download costs 10 seconds, not the whole deadline. A file still to come when the deadline passes, a file that went quiet (`download failed: idle_timeout`), or one whose directory cannot be made, is reported as `download failed` and the turn goes on without it. `attachmentsOf(message, dir, logger, fetch?, { deadlineMs?, idleMs?, signal? })` takes both limits; on the agent server they are `discord.attachmentDownload: { deadlineMs?, idleMs? }` (each 1,000 to 600,000 ms; defaults 60,000 and 10,000), for a host on a slow link or with large files. A failure reason carries a code only (`download failed: ENOTDIR`, `download failed: TimeoutError`, `download failed: error`), never the error's text, which could quote a path of the host.
|
|
559
|
+
The downloads of one message and of the message it replies to share a 60 second deadline, and a file that sends no byte for 10 seconds (the wait for its headers counts) is given up at once, so a stalled download costs 10 seconds, not the whole deadline. A file still to come when the deadline passes, a file that went quiet (`download failed: idle_timeout`), or one whose directory cannot be made, is reported as `download failed` and the turn goes on without it. `attachmentsOf(message, dir, logger, fetch?, { deadlineMs?, idleMs?, signal?, prepareImages? })` takes both limits; on the agent server they are `discord.attachmentDownload: { deadlineMs?, idleMs? }` (each 1,000 to 600,000 ms; defaults 60,000 and 10,000), for a host on a slow link or with large files. A failure reason carries a code only (`download failed: ENOTDIR`, `download failed: TimeoutError`, `download failed: error`), never the error's text, which could quote a path of the host.
|
|
560
|
+
`prepareImages: false` (default `true`) downloads the files only: `images` is empty and an image that cannot be decoded is not reported, for a host that hands the files to the attachment store, which prepares the images itself, so they are not decoded twice and a failure is not reported twice.
|
|
560
561
|
A plugin whose clients upload a file themselves, over HTTP for instance, has the file before any turn exists.
|
|
561
562
|
`context.attachments` keeps such a file for the conversation until a turn uses it:
|
|
562
563
|
|
package/package.json
CHANGED
|
@@ -23,6 +23,12 @@ export async function collectAttachments(
|
|
|
23
23
|
idleMs?: number;
|
|
24
24
|
/** Aborts the downloads, as the deadline does. */
|
|
25
25
|
signal?: AbortSignal;
|
|
26
|
+
/**
|
|
27
|
+
* Whether images are decoded for the model; default true. False downloads the files only:
|
|
28
|
+
* `images` is empty and an image that cannot be decoded is no failure, for a host that hands
|
|
29
|
+
* the files on to something that prepares them itself.
|
|
30
|
+
*/
|
|
31
|
+
prepareImages?: boolean;
|
|
26
32
|
},
|
|
27
33
|
): Promise<TurnAttachments> {
|
|
28
34
|
const { fetchImpl, logger } = options;
|
|
@@ -57,7 +63,10 @@ export async function collectAttachments(
|
|
|
57
63
|
);
|
|
58
64
|
const files = [...own.files, ...referenced.files];
|
|
59
65
|
const failures = [...own.failures, ...referenced.failures];
|
|
60
|
-
const prepared =
|
|
66
|
+
const prepared =
|
|
67
|
+
options.prepareImages === false
|
|
68
|
+
? { images: [], failures: [] }
|
|
69
|
+
: await modelImagesOf(files, logger);
|
|
61
70
|
const images = prepared.images;
|
|
62
71
|
failures.push(...prepared.failures);
|
|
63
72
|
if (files.length > 0 || failures.length > 0) {
|
|
@@ -74,13 +83,21 @@ export async function collectAttachments(
|
|
|
74
83
|
return { files, images, failures };
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Collects a message's attachments into `dir`, reporting the files that failed. `prepareImages:
|
|
88
|
+
* false` downloads the files only, without decoding the images for the model.
|
|
89
|
+
*/
|
|
78
90
|
export function attachmentsOf(
|
|
79
91
|
message: InboundMessage,
|
|
80
92
|
dir: string,
|
|
81
93
|
logger: Logger,
|
|
82
94
|
fetchImpl?: typeof fetch,
|
|
83
|
-
limits: {
|
|
95
|
+
limits: {
|
|
96
|
+
deadlineMs?: number;
|
|
97
|
+
idleMs?: number;
|
|
98
|
+
signal?: AbortSignal;
|
|
99
|
+
prepareImages?: boolean;
|
|
100
|
+
} = {},
|
|
84
101
|
): Promise<TurnAttachments> {
|
|
85
102
|
return collectAttachments(message, dir, {
|
|
86
103
|
logger,
|
|
@@ -137,7 +137,8 @@ interface DiscordAssembly {
|
|
|
137
137
|
admin: RoundtablePlugin[];
|
|
138
138
|
skills: RoundtablePlugin[];
|
|
139
139
|
agentServer: RoundtablePlugin;
|
|
140
|
-
|
|
140
|
+
/** Absent when no agent is configured: a plugin that adds nothing is refused by the registry. */
|
|
141
|
+
seeds?: RoundtablePlugin;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
function discordAssembly(
|
|
@@ -215,7 +216,7 @@ function discordAssembly(
|
|
|
215
216
|
? { errorReporter }
|
|
216
217
|
: {}),
|
|
217
218
|
}),
|
|
218
|
-
seeds: seedsPlugin(config.agents),
|
|
219
|
+
...(config.agents.length > 0 ? { seeds: seedsPlugin(config.agents) } : {}),
|
|
219
220
|
};
|
|
220
221
|
}
|
|
221
222
|
|
|
@@ -334,7 +335,9 @@ export async function defineRoundtable(
|
|
|
334
335
|
memory: config.memory,
|
|
335
336
|
...(crowd ? { crowd } : {}),
|
|
336
337
|
}),
|
|
337
|
-
...(assembly
|
|
338
|
+
...(assembly
|
|
339
|
+
? [assembly.agentServer, ...(assembly.seeds ? [assembly.seeds] : [])]
|
|
340
|
+
: []),
|
|
338
341
|
...config.plugins,
|
|
339
342
|
schedulerPlugin(),
|
|
340
343
|
],
|