@4fu/arbor-prompt 2026.1107.0 → 2026.1107.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.
Files changed (3) hide show
  1. package/package.json +2 -2
  2. package/system.d.ts +16 -7
  3. package/system.js +18 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4fu/arbor-prompt",
3
- "version": "2026.1107.0",
3
+ "version": "2026.1107.1",
4
4
  "type": "module",
5
5
  "description": "Typed prompt blocks, the one deterministic renderer, the replaceable Chinese text table and the system prompt sections.",
6
6
  "exports": {
@@ -49,6 +49,6 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@4fu/arbor-errors": "2026.1107.0",
52
- "@4fu/arbor-interfaces": "2026.1107.0"
52
+ "@4fu/arbor-interfaces": "2026.1107.1"
53
53
  }
54
54
  }
package/system.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * with the snapshot epoch, and rendering is deterministic: no timestamps or
7
7
  * counters reach it.
8
8
  */
9
- import type { DirectToolSpec, EnvItem, ModuleSpec, PromptSection, Settings } from "@4fu/arbor-interfaces";
9
+ import type { DirectToolSpec, EnvItem, ModuleSpec, PromptSection, Settings, WindowRef } from "@4fu/arbor-interfaces";
10
10
  import { Renderer } from "./render.ts";
11
11
  /** What one epoch's system prompt is built from. */
12
12
  export interface SystemPromptInput {
@@ -55,17 +55,26 @@ export declare function sectionRevision(section: PromptSection): Promise<string>
55
55
  * One plugin's prompt section, rendered in its tag, with what it produced. The
56
56
  * revision it reports is what a later call compares against, so an unchanged
57
57
  * section is never rendered twice.
58
+ *
59
+ * `window` is the window this render is for: a section that serves several
60
+ * sessions answers for that one, and a section whose content is the same
61
+ * everywhere renders the same text for each
62
+ * (docs/prompting.md#plugin-sections-that-change).
58
63
  */
59
- export declare function renderPluginSection(section: PromptSection, renderer: Renderer): Promise<RenderedPluginSection>;
64
+ export declare function renderPluginSection(section: PromptSection, renderer: Renderer, window?: WindowRef): Promise<RenderedPluginSection>;
60
65
  /**
61
- * Every plugin section, rendered once, in the order they registered. A section
62
- * whose content renders to nothing is still listed - with empty text - so a
63
- * later call can tell a section that stayed empty from one that appeared.
66
+ * Every plugin section, rendered once, in the order they registered, for the
67
+ * window they are rendered for. A section whose content renders to nothing is
68
+ * still listed - with empty text - so a later call can tell a section that
69
+ * stayed empty from one that appeared.
64
70
  */
65
- export declare function renderPluginSections(plugins: readonly PromptSection[], renderer: Renderer): Promise<readonly RenderedPluginSection[]>;
71
+ export declare function renderPluginSections(plugins: readonly PromptSection[], renderer: Renderer, window?: WindowRef): Promise<readonly RenderedPluginSection[]>;
66
72
  /**
67
73
  * Build the frozen prefix. `plugins` are rendered first because their content
68
74
  * is produced per epoch, their sections render in a tag named after the plugin,
69
75
  * and one of them being outside is what puts the precedence rule into `<agent>`.
76
+ *
77
+ * `window` is the window the prefix is built for, when it is built for one: a
78
+ * section that renders per window makes this prefix that window's own.
70
79
  */
71
- export declare function renderSystemPrompt(input: SystemPromptInput, renderer: Renderer): Promise<RenderedSystemPrompt>;
80
+ export declare function renderSystemPrompt(input: SystemPromptInput, renderer: Renderer, window?: WindowRef): Promise<RenderedSystemPrompt>;
package/system.js CHANGED
@@ -93,9 +93,14 @@ function outsideBlock(content) {
93
93
  * One plugin's prompt section, rendered in its tag, with what it produced. The
94
94
  * revision it reports is what a later call compares against, so an unchanged
95
95
  * section is never rendered twice.
96
+ *
97
+ * `window` is the window this render is for: a section that serves several
98
+ * sessions answers for that one, and a section whose content is the same
99
+ * everywhere renders the same text for each
100
+ * (docs/prompting.md#plugin-sections-that-change).
96
101
  */
97
- export async function renderPluginSection(section, renderer) {
98
- const content = await section.content();
102
+ export async function renderPluginSection(section, renderer, window) {
103
+ const content = await section.content(window);
99
104
  return {
100
105
  tag: section.tag,
101
106
  text: renderer.render(section.outside === true ? [outsideBlock(content)] : content),
@@ -104,24 +109,28 @@ export async function renderPluginSection(section, renderer) {
104
109
  };
105
110
  }
106
111
  /**
107
- * Every plugin section, rendered once, in the order they registered. A section
108
- * whose content renders to nothing is still listed - with empty text - so a
109
- * later call can tell a section that stayed empty from one that appeared.
112
+ * Every plugin section, rendered once, in the order they registered, for the
113
+ * window they are rendered for. A section whose content renders to nothing is
114
+ * still listed - with empty text - so a later call can tell a section that
115
+ * stayed empty from one that appeared.
110
116
  */
111
- export async function renderPluginSections(plugins, renderer) {
117
+ export async function renderPluginSections(plugins, renderer, window) {
112
118
  const rendered = [];
113
119
  for (const plugin of plugins)
114
- rendered.push(await renderPluginSection(plugin, renderer));
120
+ rendered.push(await renderPluginSection(plugin, renderer, window));
115
121
  return rendered;
116
122
  }
117
123
  /**
118
124
  * Build the frozen prefix. `plugins` are rendered first because their content
119
125
  * is produced per epoch, their sections render in a tag named after the plugin,
120
126
  * and one of them being outside is what puts the precedence rule into `<agent>`.
127
+ *
128
+ * `window` is the window the prefix is built for, when it is built for one: a
129
+ * section that renders per window makes this prefix that window's own.
121
130
  */
122
- export async function renderSystemPrompt(input, renderer) {
131
+ export async function renderSystemPrompt(input, renderer, window) {
123
132
  const table = renderer.table;
124
- const sections = await renderPluginSections(input.plugins ?? [], renderer);
133
+ const sections = await renderPluginSections(input.plugins ?? [], renderer, window);
125
134
  const parts = sectionsOf(input, table, sections.some((section) => section.outside)).map((section) => [`<${section.tag}>`, ...section.lines, `</${section.tag}>`].join("\n"));
126
135
  for (const section of sections) {
127
136
  if (section.text === "")