@4fu/arbor-interfaces 0.0.0-stage → 0.1.0

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/judge.d.ts ADDED
@@ -0,0 +1,206 @@
1
+ /**
2
+ * The `Judge` interface: answer the host's decisions - filter, route, model
3
+ * tier, notice, broadcast, active set (docs/architecture.md#interfaces,
4
+ * docs/dispatch.md#judge-decisions).
5
+ *
6
+ * The judge decides whether, where and when. It never writes text; the model
7
+ * owns content. It is a classifier, not the main model.
8
+ *
9
+ * What is *not* here: the rule bounds and the fallbacks. Those live in code
10
+ * that never moves, in the service layer, so an unreachable judge changes
11
+ * nothing about the rules.
12
+ */
13
+ import type { Block } from "./blocks.ts";
14
+ import type { NoteRef, Ref, Target, TaskRef, WindowRef } from "./refs.ts";
15
+ export type JudgeMode = "off" | "shadow" | "on";
16
+ export type JudgeDecisionKind = "filter" | "route" | "model_tier" | "notice" | "broadcast" | "active_set";
17
+ /** A window's profile, assembled by the host with no extra model call. */
18
+ export interface CandidateWindow {
19
+ window: WindowRef;
20
+ /** Its board line. */
21
+ doing: string;
22
+ targets: readonly Target[];
23
+ expects: readonly string[];
24
+ state: "running" | "idle";
25
+ usage: {
26
+ used: number;
27
+ limit: number;
28
+ };
29
+ /** The tasks it has taken, newest first. */
30
+ tasks: readonly string[];
31
+ /** Its last inputs, by ref and opening words. */
32
+ lastInputs: ReadonlyArray<{
33
+ ref: Ref;
34
+ summary: string;
35
+ }>;
36
+ /** Whether it has had its final usage reminder. */
37
+ finalReminderSent: boolean;
38
+ }
39
+ /** A task as the judge sees it: its targets, its reason and its content. */
40
+ export interface JudgeTask {
41
+ ref: TaskRef;
42
+ kind: "batch" | "scheduled" | "service";
43
+ reason: string;
44
+ targets: readonly Target[];
45
+ content: readonly Block[];
46
+ time: number;
47
+ }
48
+ export interface FilterState {
49
+ task: JudgeTask;
50
+ /** Explicit requests always pass. */
51
+ explicit: boolean;
52
+ }
53
+ export interface RouteState {
54
+ task: JudgeTask;
55
+ /** The live windows that share a target, describe an expectation, or worked recently. */
56
+ candidates: readonly CandidateWindow[];
57
+ }
58
+ export interface ModelTierState {
59
+ task: JudgeTask;
60
+ /** Only configured tiers. */
61
+ tiers: readonly string[];
62
+ /**
63
+ * What each tier is for, as the question reads it: one line per tier name,
64
+ * from `settings.judge.tierCriteria`. A tier named here with no text falls
65
+ * back to the judge's own description of it.
66
+ */
67
+ criteria?: Record<string, string>;
68
+ }
69
+ export interface NoticeState {
70
+ /** The event that touched the target. */
71
+ event: {
72
+ ref: Ref;
73
+ kind: string;
74
+ target: Target;
75
+ summary: string;
76
+ };
77
+ /** Only windows that touched the event's target. */
78
+ candidates: readonly CandidateWindow[];
79
+ }
80
+ export interface BroadcastState {
81
+ broadcast: {
82
+ from: WindowRef | null;
83
+ summary: string;
84
+ refs: readonly Ref[];
85
+ };
86
+ candidates: readonly CandidateWindow[];
87
+ /** Environment deltas are never filtered. */
88
+ unfiltered?: boolean;
89
+ }
90
+ export interface ActiveSetState {
91
+ notes: ReadonlyArray<{
92
+ ref: NoteRef;
93
+ summary: string;
94
+ score: number;
95
+ }>;
96
+ budget: {
97
+ count: number;
98
+ tokens: number;
99
+ };
100
+ /** The bounded share the judge may add, which never outweighs the rule score. */
101
+ judgeShare: number;
102
+ }
103
+ export interface FilterRequest {
104
+ decision: "filter";
105
+ mode: JudgeMode;
106
+ state: FilterState;
107
+ criteria?: readonly string[];
108
+ }
109
+ export interface RouteRequest {
110
+ decision: "route";
111
+ mode: JudgeMode;
112
+ state: RouteState;
113
+ criteria?: readonly string[];
114
+ }
115
+ export interface ModelTierRequest {
116
+ decision: "model_tier";
117
+ mode: JudgeMode;
118
+ state: ModelTierState;
119
+ criteria?: readonly string[];
120
+ }
121
+ export interface NoticeRequest {
122
+ decision: "notice";
123
+ mode: JudgeMode;
124
+ state: NoticeState;
125
+ criteria?: readonly string[];
126
+ }
127
+ export interface BroadcastRequest {
128
+ decision: "broadcast";
129
+ mode: JudgeMode;
130
+ state: BroadcastState;
131
+ criteria?: readonly string[];
132
+ }
133
+ export interface ActiveSetRequest {
134
+ decision: "active_set";
135
+ mode: JudgeMode;
136
+ state: ActiveSetState;
137
+ criteria?: readonly string[];
138
+ }
139
+ export type JudgeRequest = FilterRequest | RouteRequest | ModelTierRequest | NoticeRequest | BroadcastRequest | ActiveSetRequest;
140
+ export interface FilterAnswer {
141
+ decision: "filter";
142
+ needsHandling: boolean;
143
+ /**
144
+ * The judge's own reading, on the question's own scale: a bool question's
145
+ * probability. The service layer owns the threshold and reads this when the
146
+ * answer carries one, so a judge that answers with a probability and one that
147
+ * answers with a bare boolean are read the same way.
148
+ */
149
+ score?: number;
150
+ reason?: string;
151
+ }
152
+ export interface RouteScore {
153
+ /** A window ref, or `new` for a new window. */
154
+ item: WindowRef | "new";
155
+ score: number;
156
+ reason?: string;
157
+ }
158
+ export interface RouteAnswer {
159
+ decision: "route";
160
+ scores: readonly RouteScore[];
161
+ best: WindowRef | "new";
162
+ }
163
+ export interface ModelTierAnswer {
164
+ decision: "model_tier";
165
+ tier: string;
166
+ }
167
+ export interface WindowDecision {
168
+ window: WindowRef;
169
+ needs: boolean;
170
+ /** The judge's own reading, for the service layer's threshold. */
171
+ score?: number;
172
+ reason?: string;
173
+ }
174
+ export interface NoticeAnswer {
175
+ decision: "notice";
176
+ windows: readonly WindowDecision[];
177
+ }
178
+ export interface BroadcastAnswer {
179
+ decision: "broadcast";
180
+ windows: readonly WindowDecision[];
181
+ }
182
+ export interface ActiveSetAnswer {
183
+ decision: "active_set";
184
+ keep: readonly NoteRef[];
185
+ drop: readonly NoteRef[];
186
+ /**
187
+ * Each candidate's level on the score question's own scale, for the service
188
+ * layer's own threshold. Absent from a judge that answers with the two lists
189
+ * alone.
190
+ */
191
+ scores?: readonly {
192
+ ref: NoteRef;
193
+ score: number;
194
+ }[];
195
+ }
196
+ export type JudgeAnswer = FilterAnswer | RouteAnswer | ModelTierAnswer | NoticeAnswer | BroadcastAnswer | ActiveSetAnswer;
197
+ export interface Judge {
198
+ readonly name: string;
199
+ /** Answer one decision. One request per decision, with its questions batched. */
200
+ decide(request: JudgeRequest): Promise<JudgeAnswer>;
201
+ }
202
+ /** Extra criteria a plugin registers for its own inputs. */
203
+ export interface JudgeCriteria {
204
+ decision: JudgeDecisionKind;
205
+ criteria: readonly string[];
206
+ }
package/judge.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The `Judge` interface: answer the host's decisions - filter, route, model
3
+ * tier, notice, broadcast, active set (docs/architecture.md#interfaces,
4
+ * docs/dispatch.md#judge-decisions).
5
+ *
6
+ * The judge decides whether, where and when. It never writes text; the model
7
+ * owns content. It is a classifier, not the main model.
8
+ *
9
+ * What is *not* here: the rule bounds and the fallbacks. Those live in code
10
+ * that never moves, in the service layer, so an unreachable judge changes
11
+ * nothing about the rules.
12
+ */
13
+ export {};
package/notes.d.ts ADDED
@@ -0,0 +1,215 @@
1
+ /**
2
+ * The `NoteStore` interface: notes are the long-term memory, one copy shared by
3
+ * every window, written only through the note tools (docs/memory.md).
4
+ */
5
+ import type { EventRef, NoteId, NoteRef, Ref, Target, WindowRef } from "./refs.ts";
6
+ import type { Page } from "./events.ts";
7
+ /**
8
+ * A note is `active` in the current epoch's active set, `archived` when it is
9
+ * not, and `deleted` once a delete wrote a tombstone: every revision and every
10
+ * ref to them keep resolving, but no list, search or active set returns it.
11
+ */
12
+ export type NoteStatus = "active" | "archived" | "deleted";
13
+ /** Where a revision happened. The host records it; the model never fills it in. */
14
+ export interface Anchor {
15
+ window: WindowRef;
16
+ event: EventRef;
17
+ evidence?: readonly Ref[];
18
+ range?: string;
19
+ }
20
+ /** What a write carries. A write, replace or delete names the revision it read. */
21
+ export interface NoteWriteInput {
22
+ /** Omit for a new note. */
23
+ id?: NoteId;
24
+ title: string;
25
+ /** At most 200 characters. */
26
+ summary?: string;
27
+ body: string;
28
+ /** The revision the writer read. A stale one is refused with what changed. */
29
+ expectedRevision?: number;
30
+ anchor?: Anchor;
31
+ refs?: readonly Ref[];
32
+ /** Replace the body, or delete the note. Both name the revision read. */
33
+ replace?: boolean;
34
+ delete?: boolean;
35
+ }
36
+ export interface Note {
37
+ ref: NoteRef;
38
+ id: NoteId;
39
+ title: string;
40
+ summary: string;
41
+ body: string | null;
42
+ status: NoteStatus;
43
+ revision: number;
44
+ anchor?: Anchor;
45
+ time: number;
46
+ window: WindowRef | null;
47
+ }
48
+ /** What a list shows: summaries, never bodies. */
49
+ export interface NoteSummary {
50
+ ref: NoteRef;
51
+ id: NoteId;
52
+ title: string;
53
+ summary: string;
54
+ status: NoteStatus;
55
+ revision: number;
56
+ time: number;
57
+ }
58
+ /** A paged body. */
59
+ export interface NoteBody {
60
+ ref: NoteRef;
61
+ revision: number;
62
+ body: string;
63
+ /** The whole body's length in characters, before the page cut. */
64
+ total: number;
65
+ nextCall: string;
66
+ }
67
+ export interface NoteRevision {
68
+ ref: NoteRef;
69
+ revision: number;
70
+ window: WindowRef | null;
71
+ time: number;
72
+ summary: string;
73
+ anchor?: Anchor;
74
+ refs: readonly Ref[];
75
+ }
76
+ /** What `notes.context(ref)` restores: the surroundings of a revision. */
77
+ export interface NoteContext {
78
+ ref: NoteRef;
79
+ revision: number;
80
+ anchor?: Anchor;
81
+ /** The events around the one the anchor names. */
82
+ events: readonly string[];
83
+ evidence: readonly Ref[];
84
+ }
85
+ export interface NoteQuery {
86
+ query?: string;
87
+ status?: NoteStatus;
88
+ /** Notes about a target. */
89
+ about?: Target;
90
+ linked?: Ref;
91
+ limit?: number;
92
+ offset?: number;
93
+ }
94
+ /** What a refused write carries: what changed since the revision it read. */
95
+ export interface NoteConflictInfo {
96
+ read: number;
97
+ current: number;
98
+ revisions: readonly NoteRevision[];
99
+ }
100
+ /** The active set's budget: a count and a token estimate (docs/memory.md). */
101
+ export interface ActiveSetBudget {
102
+ count: number;
103
+ tokens: number;
104
+ }
105
+ /** One candidate for the active set, with its usage score. */
106
+ export interface ActiveCandidate {
107
+ ref: NoteRef;
108
+ id: NoteId;
109
+ summary: string;
110
+ score: number;
111
+ }
112
+ /**
113
+ * What a use of a note carries. The host records it from the events it
114
+ * appends; the model never declares one (docs/memory.md#the-active-set).
115
+ */
116
+ export type NoteUseKind = "cite" | "evidence" | "read";
117
+ export interface NoteUseInput {
118
+ ref: NoteRef;
119
+ kind: NoteUseKind;
120
+ /** The window that used it. */
121
+ window?: WindowRef;
122
+ /** The event that used it, so one event is recorded once. */
123
+ event?: EventRef;
124
+ /** The link's weight; a bare cite is weaker than a declared one. */
125
+ weight?: number;
126
+ time?: number;
127
+ }
128
+ /** What `snapshot` takes. */
129
+ export interface SnapshotOptions {
130
+ /** Rebuild at most this often, in ms. 10 minutes. */
131
+ minIntervalMs?: number;
132
+ /** The active set's budget. */
133
+ budget?: ActiveSetBudget;
134
+ /**
135
+ * The notes the judge keeps, within its bounded share. The share is
136
+ * additive: the judge adds notes the rule score did not pick and never drops
137
+ * one it did, because it never outweighs the model's own use.
138
+ */
139
+ judgeKeep?: readonly NoteRef[];
140
+ /** The share of the budget the judge may add. */
141
+ judgeShare?: number;
142
+ }
143
+ /**
144
+ * One frozen memory snapshot: the active notes of one epoch, with the epoch's
145
+ * version (docs/windows.md#prompt-layout). Every window opened in one epoch
146
+ * freezes the same bytes; what changed since is `delta`.
147
+ */
148
+ export interface NotesSnapshot {
149
+ /** The epoch's version. */
150
+ epoch: number;
151
+ time: number;
152
+ /** The active notes, by summary, sorted by id. */
153
+ items: readonly NoteSummary[];
154
+ total: number;
155
+ limit: number;
156
+ nextCall: string;
157
+ budget: ActiveSetBudget;
158
+ }
159
+ /** What changed since an epoch: the notes written after it. */
160
+ export interface NoteDelta {
161
+ /** The epoch asked about; `0` for every note. */
162
+ since: number;
163
+ /** The current epoch. */
164
+ epoch: number;
165
+ items: readonly NoteDeltaItem[];
166
+ total: number;
167
+ limit: number;
168
+ nextCall: string;
169
+ }
170
+ export interface NoteDeltaItem {
171
+ ref: NoteRef;
172
+ id: NoteId;
173
+ revision: number;
174
+ title: string;
175
+ summary: string;
176
+ change: "created" | "revised" | "deleted";
177
+ window: WindowRef | null;
178
+ time: number;
179
+ }
180
+ export interface NoteStore {
181
+ /** Create, replace or delete. Names the revision it read; a stale one is refused. */
182
+ write(input: NoteWriteInput): Promise<Note>;
183
+ /** The body, paged. `n012` alone means the latest revision. */
184
+ read(ref: NoteRef, options?: {
185
+ offset?: number;
186
+ limit?: number;
187
+ }): Promise<NoteBody | null>;
188
+ /** The note's revisions, oldest first. */
189
+ revisions(ref: NoteRef): Promise<Page<NoteRevision>>;
190
+ search(query?: NoteQuery): Promise<Page<NoteSummary>>;
191
+ /** The active set, by summary: the memory snapshot of every window. */
192
+ active(): Promise<Page<NoteSummary>>;
193
+ /**
194
+ * The memory snapshot of one epoch, with the epoch's version
195
+ * (docs/windows.md#prompt-layout). A new epoch is built at most every
196
+ * `minIntervalMs`, and only when a note was written since the last one or the
197
+ * budget changed, so every window opened in one epoch freezes the same bytes.
198
+ */
199
+ snapshot(options?: SnapshotOptions): Promise<NotesSnapshot>;
200
+ /** What changed since an epoch: the notes written after it. */
201
+ delta(since: number, options?: {
202
+ limit?: number;
203
+ offset?: number;
204
+ }): Promise<NoteDelta>;
205
+ /** The active-set candidates with their usage scores, strongest first. */
206
+ score(options?: {
207
+ limit?: number;
208
+ offset?: number;
209
+ }): Promise<Page<ActiveCandidate>>;
210
+ /** Record that a window used a note: cited it, used it as evidence or read it. */
211
+ recordUse(input: NoteUseInput): Promise<void>;
212
+ /** Release the underlying store. */
213
+ close(): Promise<void>;
214
+ context(ref: NoteRef): Promise<NoteContext | null>;
215
+ }
package/notes.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The `NoteStore` interface: notes are the long-term memory, one copy shared by
3
+ * every window, written only through the note tools (docs/memory.md).
4
+ */
5
+ export {};
package/package.json CHANGED
@@ -1,6 +1,71 @@
1
1
  {
2
2
  "name": "@4fu/arbor-interfaces",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Every replaceable interface in arbor, and the core's own shapes.",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./index.d.ts",
9
+ "default": "./index.js"
10
+ }
11
+ },
12
+ "types": "./index.d.ts",
13
+ "main": "./index.js",
14
+ "files": [
15
+ "agent.d.ts",
16
+ "agent.js",
17
+ "blocks.d.ts",
18
+ "blocks.js",
19
+ "channel.d.ts",
20
+ "channel.js",
21
+ "effects.d.ts",
22
+ "effects.js",
23
+ "environment.d.ts",
24
+ "environment.js",
25
+ "events.d.ts",
26
+ "events.js",
27
+ "hooks.d.ts",
28
+ "hooks.js",
29
+ "index.d.ts",
30
+ "index.js",
31
+ "journal.d.ts",
32
+ "journal.js",
33
+ "judge.d.ts",
34
+ "judge.js",
35
+ "notes.d.ts",
36
+ "notes.js",
37
+ "plugin.d.ts",
38
+ "plugin.js",
39
+ "refs.d.ts",
40
+ "refs.js",
41
+ "scheduler.d.ts",
42
+ "scheduler.js",
43
+ "settings.d.ts",
44
+ "settings.js",
45
+ "supervisor.d.ts",
46
+ "supervisor.js",
47
+ "task.d.ts",
48
+ "task.js",
49
+ "tools.d.ts",
50
+ "tools.js",
51
+ "windows.d.ts",
52
+ "windows.js",
53
+ "workspace.d.ts",
54
+ "workspace.js"
55
+ ],
56
+ "engines": {
57
+ "node": ">=24"
58
+ },
59
+ "license": "MIT",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "git+https://github.com/4fuu/arbor.git",
63
+ "directory": "packages/interfaces"
64
+ },
65
+ "publishConfig": {
66
+ "access": "public"
67
+ },
68
+ "dependencies": {
69
+ "@4fu/arbor-errors": "0.1.0"
70
+ }
71
+ }
package/plugin.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The plugin surface (docs/architecture.md#plugins).
3
+ *
4
+ * A plugin is the one unit that extends the host. It bundles any of the parts
5
+ * below; every part is optional, so a plugin can be only a hook, only a skill,
6
+ * or a whole domain such as a chat channel or a code host.
7
+ *
8
+ * Capabilities are MCP servers, not tools: a plugin adds no direct tool or
9
+ * module of its own. What the model can do with it is an MCP server and skills
10
+ * in `/env`, which the model reads, changes and reinstalls with `reload` like
11
+ * any item.
12
+ */
13
+ import type { Block, BlockKindSpec, TextTable } from "./blocks.ts";
14
+ import type { Channel } from "./channel.ts";
15
+ import type { EffectExecutor } from "./effects.ts";
16
+ import type { EnvDraft } from "./environment.ts";
17
+ import type { JudgeCriteria } from "./judge.ts";
18
+ import type { Hooks } from "./hooks.ts";
19
+ import type { TaskSource } from "./task.ts";
20
+ /** Connections to the outside world. */
21
+ export interface PluginAdapters {
22
+ channels?: readonly Channel[];
23
+ taskSources?: readonly TaskSource[];
24
+ effectExecutors?: readonly EffectExecutor[];
25
+ }
26
+ /** One plugin section of the system prompt. */
27
+ export interface PromptSection {
28
+ /** The XML tag it renders in, named after the plugin. */
29
+ tag: string;
30
+ /** The block kinds its inputs use, which the renderer maps to text. */
31
+ blocks: readonly BlockKindSpec[];
32
+ /** Its content, as blocks. The plugin hands blocks, never finished text. */
33
+ content(): readonly Block[] | Promise<readonly Block[]>;
34
+ /**
35
+ * The fixed strings its own blocks write, merged into the host's text table.
36
+ * A plugin names no secret here, and writes no prompt text of its own: its
37
+ * blocks carry data, and the table carries the words.
38
+ */
39
+ text?: TextTable;
40
+ }
41
+ export interface Plugin {
42
+ readonly name: string;
43
+ adapters?: PluginAdapters;
44
+ /** MCP servers, installed into `/env/mcp` under the plugin's name. */
45
+ mcpServers?: readonly EnvDraft[];
46
+ /** Skills, installed into `/env/skills` under the plugin's name. */
47
+ skills?: readonly EnvDraft[];
48
+ hooks?: Hooks;
49
+ promptSection?: PromptSection;
50
+ /** Extra criteria or decisions for its own inputs. */
51
+ judgeCriteria?: readonly JudgeCriteria[];
52
+ }
package/plugin.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The plugin surface (docs/architecture.md#plugins).
3
+ *
4
+ * A plugin is the one unit that extends the host. It bundles any of the parts
5
+ * below; every part is optional, so a plugin can be only a hook, only a skill,
6
+ * or a whole domain such as a chat channel or a code host.
7
+ *
8
+ * Capabilities are MCP servers, not tools: a plugin adds no direct tool or
9
+ * module of its own. What the model can do with it is an MCP server and skills
10
+ * in `/env`, which the model reads, changes and reinstalls with `reload` like
11
+ * any item.
12
+ */
13
+ export {};
package/refs.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Refs: one reference format points at anything, in every tool argument and
3
+ * result (docs/journal.md#refs). A ref is a string; the prefixes below are the
4
+ * whole vocabulary. Nothing else in arbor is addressed by an opaque id.
5
+ */
6
+ /** An event: `r902`. Its number is the event's place in the one global order. */
7
+ export type EventRef = `r${number}`;
8
+ /** A window: `c41`. */
9
+ export type WindowRef = `c${number}`;
10
+ /** A note: `n012`, or one of its revisions: `n012@3`. Bare `n012` means latest. */
11
+ export type NoteId = `n${number}`;
12
+ export type NoteRef = NoteId | `${NoteId}@${number}`;
13
+ /** A task: `t9`. */
14
+ export type TaskRef = `t${number}`;
15
+ /** A message between windows: `m55`. */
16
+ export type MessageRef = `m${number}`;
17
+ /** A workspace: `ws3`. */
18
+ export type WorkspaceRef = `ws${number}`;
19
+ /** An environment revision: `e7`. */
20
+ export type EnvRef = `e${number}`;
21
+ /** A skill, MCP server, service or the settings, at a revision: `sk:deploy@4`, `set:settings@2`. */
22
+ export type EnvItemRef = `${"sk" | "mcp" | "svc" | "set"}:${string}@${number}`;
23
+ /**
24
+ * An item named without its revision, as `reload({ remove })` takes it:
25
+ * `skill:deploy`, `mcp:weather`, `service:crawler`, `set:settings`.
26
+ */
27
+ export type EnvItemName = `${"skill" | "sk" | "mcp" | "service" | "svc" | "settings" | "set"}:${string}`;
28
+ /** Media and files stored once by content beside the journal: `b7`. */
29
+ export type BlobRef = `b${number}`;
30
+ /** An outside message by its native id, with a short channel prefix: `qq:12345`. */
31
+ export type ExternalRef = `${string}:${string}`;
32
+ export type Ref = EventRef | WindowRef | NoteRef | TaskRef | MessageRef | WorkspaceRef | EnvRef | EnvItemRef | EnvItemName | BlobRef | ExternalRef;
33
+ /**
34
+ * A target is anything two windows can collide on: a conversation
35
+ * (`qq:group:123`), a file path (`file:src/cart.ts`), a note (`n012`), an
36
+ * outside item (`gh:issue:42`) or a service (`svc:crawler`). The host fills
37
+ * targets in; the model never does.
38
+ */
39
+ export type Target = string;
40
+ /** Event kinds the core defines. Later stages and plugins add their own. */
41
+ export type EventKind = "input" | "tool_call" | "tool_result" | "send" | "effect_result" | "note_revision" | "window_start" | "window_end" | "delivery" | "environment_revision" | "service_state" | "redaction" | "schedule" | (string & {});
42
+ /** Link kinds between refs. The host records them; the model never declares one. */
43
+ export type LinkKind = "cite" | "evidence" | "range" | "origin" | "revision" | "handoff" | "continuation" | "notice" | "reply" | (string & {});
44
+ /** How a search hit matched: an exact substring, or a word. */
45
+ export type MatchKind = "substring" | "word";
46
+ /** Page size default shared by every read that returns a page. */
47
+ export declare const DEFAULT_PAGE_LIMIT = 20;
48
+ /** Maximum page size any read returns. */
49
+ export declare const MAX_PAGE_LIMIT = 200;
package/refs.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Refs: one reference format points at anything, in every tool argument and
3
+ * result (docs/journal.md#refs). A ref is a string; the prefixes below are the
4
+ * whole vocabulary. Nothing else in arbor is addressed by an opaque id.
5
+ */
6
+ /** Page size default shared by every read that returns a page. */
7
+ export const DEFAULT_PAGE_LIMIT = 20;
8
+ /** Maximum page size any read returns. */
9
+ export const MAX_PAGE_LIMIT = 200;