@rallycry/conveyor-mcp 5.0.17 → 5.0.18
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/dist/{chunk-IRVUONC3.js → chunk-BOAMGYLU.js} +3 -3
- package/dist/{chunk-OPZL4NDT.js → chunk-J7LQ5DAT.js} +80 -5
- package/dist/{chunk-6JLKJUYV.js → chunk-XLNIBIX4.js} +14 -0
- package/dist/cli.js +13 -6
- package/dist/{connection-Ctg-QM1s.d.ts → connection-C2qTFync.d.ts} +29 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/site-assets-cli.js +2 -2
- package/dist/tunnel-cli.js +1 -1
- package/dist/tunnel.d.ts +1 -1
- package/dist/wait-cli.js +2 -2
- package/dist/wait-runner.d.ts +23 -4
- package/dist/wait-runner.js +1 -1
- package/dist/wait.d.ts +9 -5
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../shared/dist/chunk-
|
|
1
|
+
// ../shared/dist/chunk-RSAY7FNH.js
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { z as z2 } from "zod";
|
|
4
4
|
var DEFAULT_SONNET_MODEL = "claude-sonnet-5-5";
|
|
@@ -500,9 +500,9 @@ var searchFilterFields = {
|
|
|
500
500
|
desc: "Only return cards with no assignee (mutually exclusive with assigneeId)"
|
|
501
501
|
})
|
|
502
502
|
),
|
|
503
|
-
limit: f.optional(f.number({ desc: "Max results to return (default 20)" }))
|
|
503
|
+
limit: f.optional(f.number({ desc: "Max results to return (default 20, at most 200)" }))
|
|
504
504
|
};
|
|
505
|
-
var searchResultNote = "Every result lists the tags it carries, so you can see why it matched. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.";
|
|
505
|
+
var searchResultNote = "Every result lists the tags it carries, so you can see why it matched. Searches every status, Complete and Cancelled included, unless statusFilters narrows it. Returns at most 200 results. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.";
|
|
506
506
|
var searchTasksContract = defineToolContract({
|
|
507
507
|
name: "search_tasks",
|
|
508
508
|
agent: {
|
|
@@ -4,10 +4,26 @@ import {
|
|
|
4
4
|
} from "./chunk-D3Q2QZJA.js";
|
|
5
5
|
|
|
6
6
|
// src/wait-runner.ts
|
|
7
|
+
var STATE_PAGE_LIMIT = 1e3;
|
|
8
|
+
var STATE_MAX_PAGES = 50;
|
|
7
9
|
var SNAPSHOT_PAGE_LIMIT = 500;
|
|
8
10
|
var SNAPSHOT_MAX_PAGES = 20;
|
|
9
11
|
var RESYNC_ATTEMPTS = 4;
|
|
10
12
|
var RESYNC_RETRY_DELAY_MS = 3e3;
|
|
13
|
+
function isLeanSeedUnsupported(error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
return /^Request timed out: listCardStates$|^Validation error|unknown method/i.test(message);
|
|
16
|
+
}
|
|
17
|
+
function toWaitCardFromState(row) {
|
|
18
|
+
return {
|
|
19
|
+
id: row.id,
|
|
20
|
+
slug: row.slug ?? null,
|
|
21
|
+
title: row.title ?? null,
|
|
22
|
+
type: row.type ?? null,
|
|
23
|
+
status: row.status ?? null,
|
|
24
|
+
assignedUserId: row.assignedUserId ?? null
|
|
25
|
+
};
|
|
26
|
+
}
|
|
11
27
|
var WaitSession = class {
|
|
12
28
|
constructor(options) {
|
|
13
29
|
this.options = options;
|
|
@@ -23,6 +39,14 @@ var WaitSession = class {
|
|
|
23
39
|
buffered = [];
|
|
24
40
|
seeded = false;
|
|
25
41
|
done = false;
|
|
42
|
+
/** Flips off once the API shows it lacks `listCardStates`. */
|
|
43
|
+
leanSeed = true;
|
|
44
|
+
/**
|
|
45
|
+
* Set once a `listCardStates` call has answered. From then on the method
|
|
46
|
+
* exists, so a failure is transient and goes to the resync retry — it never
|
|
47
|
+
* downgrades the session to the walk.
|
|
48
|
+
*/
|
|
49
|
+
leanSeedConfirmed = false;
|
|
26
50
|
offDelta;
|
|
27
51
|
offReconnect;
|
|
28
52
|
timer;
|
|
@@ -118,8 +142,57 @@ var WaitSession = class {
|
|
|
118
142
|
break;
|
|
119
143
|
}
|
|
120
144
|
}
|
|
121
|
-
/**
|
|
145
|
+
/** The lean seed while the API has `listCardStates`, else the collection walk. */
|
|
122
146
|
async snapshotAll() {
|
|
147
|
+
if (this.leanSeed) {
|
|
148
|
+
const lean = await this.leanSnapshot();
|
|
149
|
+
if (lean) return lean;
|
|
150
|
+
}
|
|
151
|
+
if (this.done) return { cards: [], complete: false, pages: 0 };
|
|
152
|
+
return this.walkCollection();
|
|
153
|
+
}
|
|
154
|
+
fetchStates(cursor) {
|
|
155
|
+
const { source, projectId, filter, statePageLimit = STATE_PAGE_LIMIT } = this.options;
|
|
156
|
+
return source.listCardStates(projectId, {
|
|
157
|
+
statuses: filter.statuses,
|
|
158
|
+
types: filter.types,
|
|
159
|
+
cursor,
|
|
160
|
+
limit: statePageLimit
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Join the scope room, then page the cards in the watched statuses and
|
|
165
|
+
* types. Returns null when the first `listCardStates` call of the session
|
|
166
|
+
* fails the way an older API does: the session then walks the collection
|
|
167
|
+
* for the rest of its life.
|
|
168
|
+
*/
|
|
169
|
+
async leanSnapshot() {
|
|
170
|
+
const { source, projectId, stateMaxPages = STATE_MAX_PAGES, log } = this.options;
|
|
171
|
+
await source.subscribeToCardCollection(projectId, { limit: 1 });
|
|
172
|
+
let page;
|
|
173
|
+
try {
|
|
174
|
+
page = await this.fetchStates(null);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (this.leanSeedConfirmed || !isLeanSeedUnsupported(error)) throw error;
|
|
177
|
+
this.leanSeed = false;
|
|
178
|
+
if (!this.done) {
|
|
179
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
180
|
+
log?.(`listCardStates did not answer (${message}) \u2014 walking the board instead.`);
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
this.leanSeedConfirmed = true;
|
|
185
|
+
const cards = page.items.map(toWaitCardFromState);
|
|
186
|
+
let pages = 1;
|
|
187
|
+
while (page.nextCursor !== null && pages < stateMaxPages) {
|
|
188
|
+
page = await this.fetchStates(page.nextCursor);
|
|
189
|
+
pages++;
|
|
190
|
+
cards.push(...page.items.map(toWaitCardFromState));
|
|
191
|
+
}
|
|
192
|
+
return { cards, complete: page.nextCursor === null, pages };
|
|
193
|
+
}
|
|
194
|
+
/** The fallback: walk the collection to the end, or until the page cap stops us. */
|
|
195
|
+
async walkCollection() {
|
|
123
196
|
const {
|
|
124
197
|
source,
|
|
125
198
|
projectId,
|
|
@@ -129,11 +202,13 @@ var WaitSession = class {
|
|
|
129
202
|
const cards = [];
|
|
130
203
|
let cursor = null;
|
|
131
204
|
let complete = false;
|
|
132
|
-
|
|
205
|
+
let pages = 0;
|
|
206
|
+
while (pages < maxPages) {
|
|
133
207
|
const result = await source.subscribeToCardCollection(projectId, {
|
|
134
208
|
cursor,
|
|
135
209
|
limit: pageLimit
|
|
136
210
|
});
|
|
211
|
+
pages++;
|
|
137
212
|
for (const item of result.items ?? []) cards.push(toWaitCard(item));
|
|
138
213
|
cursor = result.nextCursor ?? null;
|
|
139
214
|
if (cursor === null) {
|
|
@@ -141,16 +216,16 @@ var WaitSession = class {
|
|
|
141
216
|
break;
|
|
142
217
|
}
|
|
143
218
|
}
|
|
144
|
-
return { cards, complete };
|
|
219
|
+
return { cards, complete, pages };
|
|
145
220
|
}
|
|
146
221
|
async seedOrResync(initial) {
|
|
147
222
|
this.seeded = false;
|
|
148
|
-
const { cards, complete } = await this.snapshotAll();
|
|
223
|
+
const { cards, complete, pages } = await this.snapshotAll();
|
|
149
224
|
if (this.done) return;
|
|
150
225
|
if (initial) {
|
|
151
226
|
this.tracker.seed(cards);
|
|
152
227
|
this.options.log?.(
|
|
153
|
-
`
|
|
228
|
+
`Seeded ${cards.length} card(s) from ${pages} page(s) \u2014 ${this.tracker.size} already match; waiting for new work.`
|
|
154
229
|
);
|
|
155
230
|
} else {
|
|
156
231
|
const triggers = this.tracker.reseed(cards, complete);
|
|
@@ -1104,6 +1104,20 @@ var ConveyorConnection = class {
|
|
|
1104
1104
|
limit: opts.limit
|
|
1105
1105
|
});
|
|
1106
1106
|
}
|
|
1107
|
+
/**
|
|
1108
|
+
* A lean, status-filtered page of a project's cards, ordered by id — the
|
|
1109
|
+
* conveyor-wait seed. An API from before this method never acks the call,
|
|
1110
|
+
* so callers on an older server see a timeout (see `wait-runner.ts`).
|
|
1111
|
+
*/
|
|
1112
|
+
listCardStates(projectId, opts) {
|
|
1113
|
+
return this.call("listCardStates", {
|
|
1114
|
+
projectId,
|
|
1115
|
+
statuses: opts.statuses,
|
|
1116
|
+
types: opts.types,
|
|
1117
|
+
cursor: opts.cursor ?? null,
|
|
1118
|
+
limit: opts.limit
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1107
1121
|
/**
|
|
1108
1122
|
* Listen for card collection deltas on a project scope. The event name is
|
|
1109
1123
|
* the room name by design — no id parsing client-side. Returns an
|
package/dist/cli.js
CHANGED
|
@@ -81,13 +81,13 @@ import {
|
|
|
81
81
|
uploadAttachmentContract,
|
|
82
82
|
uploadSiteAssetsContract,
|
|
83
83
|
voteDecisionContract
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-BOAMGYLU.js";
|
|
85
85
|
import {
|
|
86
86
|
installLifecycle
|
|
87
87
|
} from "./chunk-5KU3QS6A.js";
|
|
88
88
|
import {
|
|
89
89
|
ConveyorConnection
|
|
90
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-XLNIBIX4.js";
|
|
91
91
|
|
|
92
92
|
// src/cli.ts
|
|
93
93
|
import { createRequire } from "module";
|
|
@@ -552,7 +552,7 @@ function summarizeTask(task) {
|
|
|
552
552
|
const { plan, description, ...rest } = task;
|
|
553
553
|
const summary = { ...rest };
|
|
554
554
|
summary.description = typeof description === "string" && description.length > DESCRIPTION_PREVIEW_CHARS ? `${description.slice(0, DESCRIPTION_PREVIEW_CHARS)}\u2026 [truncated \u2014 use get_task for the full description]` : description ?? null;
|
|
555
|
-
summary.hasPlan = typeof plan === "string"
|
|
555
|
+
summary.hasPlan = typeof plan === "string" ? plan.length > 0 : rest.hasPlan === true;
|
|
556
556
|
return summary;
|
|
557
557
|
}
|
|
558
558
|
|
|
@@ -579,10 +579,10 @@ function registerListTasks(server2, conn2) {
|
|
|
579
579
|
registerHotTool(
|
|
580
580
|
server2,
|
|
581
581
|
"list_tasks",
|
|
582
|
-
"List project cards, optionally filtered by card type, status, or assignment (a specific assignee, or unassigned tasks). Defaults to type=task \u2014 pass typeFilters to list incidents, suggestions or decisions. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Pass projectId to target a specific project; otherwise the configured default project is used. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.",
|
|
582
|
+
"List project cards, optionally filtered by card type, status, or assignment (a specific assignee, or unassigned tasks). Defaults to type=task \u2014 pass typeFilters to list incidents, suggestions or decisions. Without a status, Complete and Cancelled cards are left out \u2014 pass status to list one of them, or use search_tasks, which covers every status. Returns at most 200 cards. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Pass projectId to target a specific project; otherwise the configured default project is used. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.",
|
|
583
583
|
{
|
|
584
584
|
projectId: z5.string().optional().describe("Target Conveyor project ID"),
|
|
585
|
-
status: z5.enum(STATUS_ENUM).optional().describe("Filter by task status"),
|
|
585
|
+
status: z5.enum(STATUS_ENUM).optional().describe("Filter by task status. Omit for every status except Complete and Cancelled."),
|
|
586
586
|
typeFilters: z5.array(z5.enum(CARD_TYPE_ENUM)).optional().describe(
|
|
587
587
|
'Card types to include, e.g. ["incident"] or ["task", "incident"]. Omit for tasks only.'
|
|
588
588
|
),
|
|
@@ -590,7 +590,7 @@ function registerListTasks(server2, conn2) {
|
|
|
590
590
|
unassigned: z5.boolean().optional().describe("Only return tasks with no assignee (mutually exclusive with assigneeId)"),
|
|
591
591
|
subProjectId: BOARD_FILTER,
|
|
592
592
|
onHold: z5.boolean().optional().describe("true = only cards on hold, false = exclude them, omit = both"),
|
|
593
|
-
limit: z5.number().optional().describe("Max tasks to return (default 50)")
|
|
593
|
+
limit: z5.number().optional().describe("Max tasks to return (default 50, at most 200)")
|
|
594
594
|
},
|
|
595
595
|
async (params) => {
|
|
596
596
|
const tasks = await conn2.listTasks(params);
|
|
@@ -2272,6 +2272,13 @@ var ListProjectTasksRequestSchema = z72.object({
|
|
|
2272
2272
|
}).refine((p) => !(p.unassigned && p.assigneeId), {
|
|
2273
2273
|
message: "Pass either assigneeId or unassigned, not both"
|
|
2274
2274
|
});
|
|
2275
|
+
var ListCardStatesRequestSchema = z72.object({
|
|
2276
|
+
projectId: z72.string(),
|
|
2277
|
+
statuses: z72.array(z72.string()).min(1).max(32),
|
|
2278
|
+
types: z72.array(z72.string()).optional(),
|
|
2279
|
+
cursor: z72.string().nullable().optional(),
|
|
2280
|
+
limit: z72.number().int().positive().optional().default(500)
|
|
2281
|
+
});
|
|
2275
2282
|
var GetProjectTaskRequestSchema = z72.object({
|
|
2276
2283
|
projectId: z72.string(),
|
|
2277
2284
|
taskId: z72.string()
|
|
@@ -130,6 +130,23 @@ interface CardCollectionPage {
|
|
|
130
130
|
nextCursor: string | null;
|
|
131
131
|
totalCount: number;
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* One `listCardStates` row: the six fields conveyor-wait filters on and
|
|
135
|
+
* prints, with a flat assignee id. Mirrors `CardStateDTO` in @project/shared.
|
|
136
|
+
*/
|
|
137
|
+
interface CardStateRow {
|
|
138
|
+
id: string;
|
|
139
|
+
slug: string | null;
|
|
140
|
+
title: string | null;
|
|
141
|
+
type: string | null;
|
|
142
|
+
status: string | null;
|
|
143
|
+
assignedUserId: string | null;
|
|
144
|
+
}
|
|
145
|
+
/** One page of `listCardStates`, ordered by id. */
|
|
146
|
+
interface CardStatePage {
|
|
147
|
+
items: CardStateRow[];
|
|
148
|
+
nextCursor: string | null;
|
|
149
|
+
}
|
|
133
150
|
/**
|
|
134
151
|
* A quickdraw collection change on a card scope. `added` vs `updated` is
|
|
135
152
|
* cosmetic — most card writes go through a hand-rolled upsert that always
|
|
@@ -1099,6 +1116,17 @@ declare class ConveyorConnection {
|
|
|
1099
1116
|
cursor?: string | null;
|
|
1100
1117
|
limit?: number;
|
|
1101
1118
|
}): Promise<CardCollectionPage>;
|
|
1119
|
+
/**
|
|
1120
|
+
* A lean, status-filtered page of a project's cards, ordered by id — the
|
|
1121
|
+
* conveyor-wait seed. An API from before this method never acks the call,
|
|
1122
|
+
* so callers on an older server see a timeout (see `wait-runner.ts`).
|
|
1123
|
+
*/
|
|
1124
|
+
listCardStates(projectId: string, opts: {
|
|
1125
|
+
statuses: string[];
|
|
1126
|
+
types?: string[];
|
|
1127
|
+
cursor?: string | null;
|
|
1128
|
+
limit?: number;
|
|
1129
|
+
}): Promise<CardStatePage>;
|
|
1102
1130
|
/**
|
|
1103
1131
|
* Listen for card collection deltas on a project scope. The event name is
|
|
1104
1132
|
* the room name by design — no id parsing client-side. Returns an
|
|
@@ -1115,4 +1143,4 @@ declare class ConveyorConnection {
|
|
|
1115
1143
|
disconnect(): void;
|
|
1116
1144
|
}
|
|
1117
1145
|
|
|
1118
|
-
export { type ActivePtySession as A, type CardCollectionPage as C, type PtyAttachSnapshot as P, type
|
|
1146
|
+
export { type ActivePtySession as A, type CardCollectionPage as C, type PtyAttachSnapshot as P, type CardStatePage as a, type CardCollectionDelta as b, type CardCollectionItem as c, type PtyDataChunk as d, ConveyorConnection as e, type ConveyorMcpConfig as f };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ActivePtySession,
|
|
1
|
+
export { A as ActivePtySession, e as ConveyorConnection, f as ConveyorMcpConfig, P as PtyAttachSnapshot, d as PtyDataChunk } from './connection-C2qTFync.js';
|
|
2
2
|
export { AttachTunnelOptions, ResolvedPtySession, RunTunnelOptions, TunnelConnection, TunnelHandle, TunnelSession, TunnelTty, WaitForPtySessionOptions, attachTunnel, runTunnel, waitForPtySession } from './tunnel.js';
|
|
3
3
|
import 'socket.io-client';
|
|
4
4
|
import '@project/shared';
|
package/dist/index.js
CHANGED
package/dist/site-assets-cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
transferSiteAsset
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BOAMGYLU.js";
|
|
5
5
|
import {
|
|
6
6
|
ConveyorConnection
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XLNIBIX4.js";
|
|
8
8
|
|
|
9
9
|
// src/site-assets-cli.ts
|
|
10
10
|
import crypto from "crypto";
|
package/dist/tunnel-cli.js
CHANGED
package/dist/tunnel.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as ActivePtySession, P as PtyAttachSnapshot,
|
|
1
|
+
import { A as ActivePtySession, P as PtyAttachSnapshot, d as PtyDataChunk } from './connection-C2qTFync.js';
|
|
2
2
|
import 'socket.io-client';
|
|
3
3
|
import '@project/shared';
|
|
4
4
|
|
package/dist/wait-cli.js
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-5KU3QS6A.js";
|
|
5
5
|
import {
|
|
6
6
|
ConveyorConnection
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XLNIBIX4.js";
|
|
8
8
|
import {
|
|
9
9
|
runWait
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-J7LQ5DAT.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_WAIT_SCOPES,
|
|
13
13
|
DEFAULT_WAIT_STATUSES,
|
package/dist/wait-runner.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CardCollectionPage, a as CardCollectionDelta } from './connection-
|
|
1
|
+
import { C as CardCollectionPage, a as CardStatePage, b as CardCollectionDelta } from './connection-C2qTFync.js';
|
|
2
2
|
import { WaitFilter, WaitResult } from './wait.js';
|
|
3
3
|
import 'socket.io-client';
|
|
4
4
|
import '@project/shared';
|
|
@@ -7,9 +7,16 @@ import '@project/shared';
|
|
|
7
7
|
* `conveyor-wait` runner — the live half of the engine.
|
|
8
8
|
*
|
|
9
9
|
* `wait.ts` decides what "matching" means; this module owns the socket-shaped
|
|
10
|
-
* lifecycle around it: seed
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* lifecycle around it: seed, apply deltas, re-seed after a `reset` or a
|
|
11
|
+
* reconnect, and settle on the first card that enters the filter (or on the
|
|
12
|
+
* deadline).
|
|
13
|
+
*
|
|
14
|
+
* A seed is two calls, not a walk of the board. A cursor-less collection
|
|
15
|
+
* subscribe with `limit: 1` joins the scope room, which is what makes deltas
|
|
16
|
+
* flow; its one item is ignored. `listCardStates` then pages just the cards in
|
|
17
|
+
* the watched statuses and types — six fields each, usually one page. An API
|
|
18
|
+
* from before `listCardStates` gets today's walk of the collection instead
|
|
19
|
+
* (conveyor-mcp publishes ahead of the API release).
|
|
13
20
|
*
|
|
14
21
|
* It talks to a narrow `CardCollectionSource` rather than a socket, so the
|
|
15
22
|
* reconnect, reset, and paging paths are unit-testable without a server.
|
|
@@ -24,6 +31,12 @@ interface CardCollectionSource {
|
|
|
24
31
|
cursor?: string | null;
|
|
25
32
|
limit?: number;
|
|
26
33
|
}): Promise<CardCollectionPage>;
|
|
34
|
+
listCardStates(projectId: string, opts: {
|
|
35
|
+
statuses: string[];
|
|
36
|
+
types?: string[];
|
|
37
|
+
cursor?: string | null;
|
|
38
|
+
limit?: number;
|
|
39
|
+
}): Promise<CardStatePage>;
|
|
27
40
|
onCardDelta(projectId: string, handler: (delta: CardCollectionDelta) => void): () => void;
|
|
28
41
|
onReconnect(handler: () => void): () => void;
|
|
29
42
|
}
|
|
@@ -32,7 +45,13 @@ interface RunWaitOptions {
|
|
|
32
45
|
projectId: string;
|
|
33
46
|
filter: WaitFilter;
|
|
34
47
|
timeoutMs: number;
|
|
48
|
+
/** Rows per `listCardStates` page. */
|
|
49
|
+
statePageLimit?: number;
|
|
50
|
+
/** Page cap for one `listCardStates` seed. */
|
|
51
|
+
stateMaxPages?: number;
|
|
52
|
+
/** Items per page of the fallback collection walk. */
|
|
35
53
|
pageLimit?: number;
|
|
54
|
+
/** Page cap for the fallback collection walk. */
|
|
36
55
|
maxPages?: number;
|
|
37
56
|
/** Backoff between re-snapshot attempts. Overridable so tests stay fast. */
|
|
38
57
|
resyncRetryDelayMs?: number;
|
package/dist/wait-runner.js
CHANGED
package/dist/wait.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as CardCollectionItem } from './connection-C2qTFync.js';
|
|
2
2
|
import 'socket.io-client';
|
|
3
3
|
import '@project/shared';
|
|
4
4
|
|
|
@@ -14,10 +14,14 @@ import '@project/shared';
|
|
|
14
14
|
* - **Creates arrive as `updated` deltas.** Most card writes go through the
|
|
15
15
|
* service's hand-rolled upsert choke point, which always emits `updated`.
|
|
16
16
|
* "New work" is therefore a set diff, never a delta-type check.
|
|
17
|
-
* - **The
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* - **The seed is not the collection snapshot.** A snapshot ack is one page
|
|
18
|
+
* of full cards, and a large project's scope runs to thousands of them. The
|
|
19
|
+
* seed instead pages `listCardStates`: only the watched statuses and types,
|
|
20
|
+
* six fields a row. The collection subscribe (with `limit: 1`) only joins
|
|
21
|
+
* the delta room. An older API without `listCardStates` falls back to
|
|
22
|
+
* walking the collection's `nextCursor` to the end. When either walk is
|
|
23
|
+
* capped we merge instead of replacing, because dropping an unseen id would
|
|
24
|
+
* make it look newly-matching on the next delta.
|
|
21
25
|
*
|
|
22
26
|
* The live half — snapshot paging, reconnect, and settling — lives in
|
|
23
27
|
* `wait-runner.ts`; this module is the pure filter and set-diff logic it uses.
|