@walkeros/mcp 4.8.0 → 4.8.1-next-1792019907609

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/index.d.ts CHANGED
@@ -1,732 +1,11 @@
1
- import { ListFlowsOptions, ListPreviewsOptions, GetPreviewOptions, CreatePreviewOptions, DeletePreviewOptions, ListSecretsOptions, CreateSecretOptions, UpdateSecretOptions, DeleteSecretOptions, DeployOptions, ListDeploymentsOptions, DeviceAuthorization, DeviceLoginResult, ContractComparison, FeedbackOptions, BundleStats, PushResult } from '@walkeros/cli';
2
- import { Journey, JourneyGap, JourneyUnattributed, Flow, Ingest, WalkerOS, Simulation } from '@walkeros/core';
3
- import { ZodRawShape, z } from 'zod';
4
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
2
  export { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
- import { WebStandardStreamableHTTPServerTransportOptions } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
7
-
8
- /**
9
- * Mint a fresh, origin-bound activation grant for an existing preview. All
10
- * fields are opaque identifiers/strings — no host-internal shape leaks into
11
- * this public interface. `origins` are bare `https://host[:port]` values the
12
- * grant may activate on; the returned `activationUrl` targets the first.
13
- */
14
- interface RegrantPreviewOptions {
15
- projectId: string;
16
- flowId: string;
17
- previewId: string;
18
- origins: string[];
19
- /** Observe session id — binds the minted grant to that session so
20
- * forwarded events reach its container. Opaque identifier. */
21
- sessionId?: string;
22
- }
23
- /**
24
- * The assembled cross-runtime journeys for a flow's active Observe session,
25
- * mirroring the app's flowId-keyed REST envelope. `sessionId` is null when the
26
- * flow has no active session (the empty result an agent gets when the flow is
27
- * not currently being observed). `journeys`/`gaps`/`unattributed` are the pure
28
- * `assembleJourneys` output; typed against core's `Journey`/`JourneyGap`/
29
- * `JourneyUnattributed` since `@walkeros/mcp` already depends on
30
- * `@walkeros/core`.
31
- */
32
- interface JourneysResult {
33
- sessionId: string | null;
34
- flowId: string;
35
- assembledAt: string;
36
- journeys: Journey[];
37
- gaps: JourneyGap[];
38
- /**
39
- * Records that belonged to an event run but could not be attributed to any
40
- * event, per platform. Absent when there are none, and session-level like
41
- * `gaps`: `traceId`/`limit` narrow `journeys` only.
42
- */
43
- unattributed?: JourneyUnattributed[];
44
- }
45
- /** Observation verbosity a session's container is provisioned with. */
46
- type ObserveLevel = 'off' | 'standard' | 'trace';
47
- /**
48
- * The session's web part. Present once a preview arm is attached; null while
49
- * the window has no web half. `credential` and the server `env` trio are
50
- * connect secrets: the tool layer reads the part for arm presence and never
51
- * surfaces them.
52
- */
53
- interface ObserveSessionWebPart {
54
- activationUrl: string | null;
55
- credential: string;
56
- previewEnabled: boolean;
57
- bundleUrl: string;
58
- /** Observer both arms post to, in the field name a `config.observe` declares. */
59
- url?: string;
60
- /** Project binding the collector cross-checks an arriving credential against. */
61
- binding?: string;
62
- }
63
- /** The session's container part. Present once a container arm is provisioned. */
64
- interface ObserveSessionServerPart {
65
- endpoint: string | null;
66
- env: {
67
- WALKEROS_OBSERVER_URL: string;
68
- WALKEROS_DEPLOYMENT_ID: string;
69
- WALKEROS_INGEST_TOKEN: string;
70
- };
71
- }
72
- /**
73
- * One Observe session: a time-boxed window on a flow that runtimes attach to
74
- * as arms. `observedFlowName`/`serverFlowName` name the settings each arm runs;
75
- * `web`/`server` being non-null is what makes an arm attached. Mirrors the
76
- * app's session envelope.
77
- */
78
- interface ObserveSessionResult {
79
- id: string;
80
- projectId: string;
81
- flowId: string;
82
- status: string;
83
- errorMessage: string | null;
84
- /** The flow config the session was opened on, as the app snapshotted it. */
85
- configSnapshot: Record<string, unknown>;
86
- observedFlowName: string | null;
87
- serverFlowName: string | null;
88
- /** Legacy mirror of `server.endpoint`, kept for published readers; read `server.endpoint`. */
89
- serverEndpoint: string | null;
90
- web: ObserveSessionWebPart | null;
91
- server: ObserveSessionServerPart | null;
92
- expiresAt: string;
93
- recordsReceived: number;
94
- /** Id of the user who opened the session. */
95
- createdBy: string;
96
- createdAt: string;
97
- }
98
- /**
99
- * Start a session on one flow. `settingsName` is the single knob the window is
100
- * opened on: the flow's topology under that name decides which arms the app
101
- * provisions, so the tool layer translates its arms input into this one field.
102
- */
103
- interface StartObserveSessionOptions {
104
- projectId: string;
105
- flowId: string;
106
- settingsName: string;
107
- origins?: string[];
108
- level?: ObserveLevel;
109
- replace?: boolean;
110
- }
111
- interface ObserveSessionRef {
112
- projectId: string;
113
- flowId: string;
114
- sessionId: string;
115
- }
116
- type ThreadAnchorType = 'step' | 'entity_action' | 'release' | 'contract' | 'tag';
117
- type StoredAnchorType = ThreadAnchorType | 'page';
118
- type ThreadStatus = 'open' | 'resolved';
119
- type ReleaseRef = {
120
- versionId: string;
121
- } | {
122
- versionNumber: number;
123
- };
124
- interface ReleaseRationaleSummaryWire {
125
- hasHumanText: boolean;
126
- hasGeneratedSummary: boolean;
127
- firstLine: string | null;
128
- }
129
- interface FlowReleaseWire {
130
- id: string;
131
- deploymentId: string;
132
- deploymentSlug: string | null;
133
- deploymentType: string | null;
134
- versionNumber: number;
135
- flowVersionId: string | null;
136
- flowVersionNumber: number | null;
137
- status: string;
138
- source: string;
139
- errorCode: string | null;
140
- createdAt: string;
141
- createdBy: string | null;
142
- createdByLabel: string | null;
143
- /** Present only on a read that asked for rationale. */
144
- rationale?: ReleaseRationaleSummaryWire | null;
145
- }
146
- interface ReleaseIndexWire {
147
- releases: FlowReleaseWire[];
148
- total: number;
149
- limit: number;
150
- offset: number;
151
- }
152
- interface VersionAnnotationWire {
153
- versionId: string;
154
- humanText: string | null;
155
- generatedSummary: string | null;
156
- author: string;
157
- createdAt: string;
158
- updatedAt: string;
159
- }
160
- interface ReleaseDiffWire {
161
- prevVersionId: string;
162
- prevVersionNumber: number;
163
- text: string;
164
- contentIdentical: boolean;
165
- }
166
- interface ReleaseDetailWire {
167
- versionId: string;
168
- versionNumber: number;
169
- contentHash: string | null;
170
- createdAt: string;
171
- createdBy: string;
172
- rationale: VersionAnnotationWire | null;
173
- diff: ReleaseDiffWire | null;
174
- }
175
- interface StepHistoryEntryWire {
176
- versionId: string;
177
- versionNumber: number;
178
- createdAt: string;
179
- flow: string | null;
180
- change: 'added' | 'removed' | 'changed';
181
- humanText: string | null;
182
- generatedSummary: string | null;
183
- }
184
- interface StepHistoryWire {
185
- step: string;
186
- flow: string | null;
187
- entries: StepHistoryEntryWire[];
188
- scanned: number;
189
- truncated: boolean;
190
- entriesTruncated: boolean;
191
- knownSteps?: string[];
192
- }
193
- interface HubMessageWire {
194
- id: string;
195
- author: string;
196
- text: string;
197
- createdAt: string;
198
- }
199
- interface HubThreadWire {
200
- id: string;
201
- anchorType: ThreadAnchorType;
202
- anchorKey: string;
203
- anchorLabel: string;
204
- status: ThreadStatus;
205
- resolvedByVersionId: string | null;
206
- resolvedByVersionNumber: number | null;
207
- resolvedAt: string | null;
208
- resolvedBy: string | null;
209
- createdBy: string;
210
- createdAt: string;
211
- updatedAt: string;
212
- messageCount: number;
213
- messages?: HubMessageWire[];
214
- hasMoreMessages?: boolean;
215
- }
216
- interface ListThreadsWire {
217
- threads: HubThreadWire[];
218
- hasMoreThreads: boolean;
219
- }
220
- type KnowledgeValidityWire = {
221
- tier: 'release';
222
- versionId: string;
223
- versionNumber: number;
224
- promoted: boolean;
225
- } | {
226
- tier: 'draft';
227
- versionId?: string;
228
- } | {
229
- tier: 'none';
230
- };
231
- interface KnowledgeAuthorWire {
232
- kind: 'user' | 'preview' | 'agent';
233
- id: string | null;
234
- label: string;
235
- }
236
- interface KnowledgeMessageWire {
237
- id: string;
238
- author: string;
239
- authorLabel: string;
240
- text: string;
241
- createdAt: string;
242
- clientMessageId: string | null;
243
- }
244
- interface KnowledgeEntryBaseWire {
245
- id: string;
246
- anchorKey: string;
247
- anchorLabel: string;
248
- frameId: string | null;
249
- frameName: string | null;
250
- flowId: string | null;
251
- subjectKey: string | null;
252
- /** Opaque DOM anchor plus a fractional point. Never surfaced by a tool. */
253
- spatial: {
254
- at: {
255
- x: number;
256
- y: number;
257
- };
258
- element?: Record<string, unknown>;
259
- } | null;
260
- validity: KnowledgeValidityWire;
261
- freshness: 'current' | 'subject_changed' | 'unknown';
262
- author: KnowledgeAuthorWire;
263
- source: 'tag_mode' | 'hub' | 'mcp';
264
- updatedAt: string;
265
- }
266
- interface KnowledgeThreadWire extends KnowledgeEntryBaseWire {
267
- kind: 'thread';
268
- anchorType: StoredAnchorType;
269
- status: ThreadStatus;
270
- createdAt: string;
271
- messageCount: number;
272
- messages?: KnowledgeMessageWire[];
273
- hasMoreMessages?: boolean;
274
- }
275
- interface KnowledgeDescriptionWire extends KnowledgeEntryBaseWire {
276
- kind: 'description';
277
- anchorType: 'tag' | 'page';
278
- body: string;
279
- }
280
- type KnowledgeEntryWire = KnowledgeThreadWire | KnowledgeDescriptionWire;
281
- interface ListKnowledgeWire {
282
- entries: KnowledgeEntryWire[];
283
- hasMoreEntries: boolean;
284
- }
285
- interface PlanSizeWire {
286
- width: number;
287
- height: number;
288
- }
289
- interface PlanRectWire {
290
- x: number;
291
- y: number;
292
- w: number;
293
- h: number;
294
- }
295
- interface FramePlacementWire {
296
- id: string;
297
- rect: PlanRectWire;
298
- selector?: string;
299
- anchor?: Record<string, unknown>;
300
- }
301
- type FrameSourceWire = {
302
- kind: 'page';
303
- key: string;
304
- url: string;
305
- } | {
306
- kind: 'figma';
307
- fileKey: string;
308
- nodeId: string;
309
- } | {
310
- kind: 'image';
311
- };
312
- interface FrameScreenshotWire {
313
- assetId: string;
314
- capturedAt: string;
315
- size: PlanSizeWire;
316
- dpr: number;
317
- capturedRect: PlanRectWire;
318
- }
319
- interface FrameLeanWire {
320
- id: string;
321
- projectId: string;
322
- name: string;
323
- parentId: string | null;
324
- placements: FramePlacementWire[];
325
- size: PlanSizeWire;
326
- extends: string | null;
327
- source: FrameSourceWire | null;
328
- origin: 'drawn' | 'imported' | 'observed';
329
- flowId: string;
330
- screenshot: FrameScreenshotWire | null;
331
- version: number;
332
- createdAt: string;
333
- updatedAt: string;
334
- createdBy: string;
335
- updatedBy: string;
336
- deletedAt: string | null;
337
- }
338
- interface FrameWire extends FrameLeanWire {
339
- marks: Record<string, unknown>;
340
- }
341
- interface FrameListWire {
342
- frames: FrameWire[];
343
- }
344
- interface FrameLeanListWire {
345
- frames: FrameLeanWire[];
346
- }
347
- /**
348
- * Transport-agnostic client for network-reach MCP tools. The stdio build
349
- * plugs in HttpToolClient (talks to the walkerOS app over HTTPS via the
350
- * CLI's programmatic API). In-process hosts (e.g. the app itself) can plug
351
- * in a direct client that calls database helpers without HTTP overhead.
352
- */
353
- interface ToolClient {
354
- listProjects(options?: {
355
- cursor?: string;
356
- limit?: number;
357
- }): Promise<unknown>;
358
- getProject(options: {
359
- projectId?: string;
360
- }): Promise<unknown>;
361
- createProject(options: {
362
- name: string;
363
- }): Promise<unknown>;
364
- updateProject(options: {
365
- projectId?: string;
366
- name: string;
367
- }): Promise<unknown>;
368
- deleteProject(options: {
369
- projectId?: string;
370
- }): Promise<unknown>;
371
- setDefaultProject(projectId: string): void;
372
- getDefaultProject(): string | null;
373
- /** Every project's flows, as an array of `{ project: { id, name }, flows }`
374
- * groups whose `flows` are the rows `listFlows` answers for that project. */
375
- listAllFlows(options?: {
376
- sort?: string;
377
- order?: 'asc' | 'desc';
378
- includeDeleted?: boolean;
379
- cursor?: string;
380
- limit?: number;
381
- }): Promise<unknown>;
382
- listFlows(options: ListFlowsOptions): Promise<unknown>;
383
- getFlow(options: {
384
- flowId: string;
385
- projectId?: string;
386
- fields?: string[];
387
- }): Promise<unknown>;
388
- createFlow(options: {
389
- name: string;
390
- content: Record<string, unknown>;
391
- projectId?: string;
392
- }): Promise<unknown>;
393
- updateFlow(options: {
394
- flowId: string;
395
- projectId?: string;
396
- name?: string;
397
- content?: Record<string, unknown>;
398
- mergePatch?: boolean;
399
- }): Promise<unknown>;
400
- deleteFlow(options: {
401
- flowId: string;
402
- projectId?: string;
403
- }): Promise<unknown>;
404
- duplicateFlow(options: {
405
- flowId: string;
406
- name?: string;
407
- projectId?: string;
408
- }): Promise<unknown>;
409
- listPreviews(options: ListPreviewsOptions): Promise<unknown>;
410
- getPreview(options: GetPreviewOptions): Promise<unknown>;
411
- createPreview(options: CreatePreviewOptions & {
412
- siteUrl?: string;
413
- }): Promise<unknown>;
414
- deletePreview(options: DeletePreviewOptions): Promise<unknown>;
415
- /**
416
- * Mint a fresh, origin-bound activation grant for an existing preview.
417
- * OPTIONAL: clients that cannot mint grants may omit it, and the
418
- * flow_manage handler guards on its presence before calling. Clients may
419
- * return their raw API response; the flow_manage handler whitelists the
420
- * fields it surfaces (never the ingest token or project id).
421
- */
422
- regrantPreview?(options: RegrantPreviewOptions): Promise<unknown>;
423
- listSecrets(options: ListSecretsOptions): Promise<unknown>;
424
- createSecret(options: CreateSecretOptions): Promise<unknown>;
425
- updateSecret(options: UpdateSecretOptions): Promise<unknown>;
426
- deleteSecret(options: DeleteSecretOptions): Promise<unknown>;
427
- deploy(options: DeployOptions): Promise<unknown>;
428
- listDeployments(options: ListDeploymentsOptions): Promise<unknown>;
429
- getDeploymentBySlug(options: {
430
- slug: string;
431
- projectId?: string;
432
- }): Promise<unknown>;
433
- deleteDeployment(options: {
434
- slug: string;
435
- projectId?: string;
436
- }): Promise<unknown>;
437
- listJourneys(options: {
438
- flowId: string;
439
- projectId?: string;
440
- traceId?: string;
441
- limit?: number;
442
- }): Promise<JourneysResult>;
443
- /**
444
- * Observe session lifecycle. OPTIONAL as a trio: a client that cannot reach
445
- * the session endpoints omits all three, and the `observe_session` handler
446
- * guards on presence before calling. Reads stay with `listJourneys`, which
447
- * doubles as the flow-to-live-window resolver (`observe_sessions.flow_id` is
448
- * UNIQUE, so its `sessionId` IS the flow's live window).
449
- */
450
- startObserveSession?(options: StartObserveSessionOptions): Promise<ObserveSessionResult>;
451
- getObserveSession?(options: ObserveSessionRef): Promise<ObserveSessionResult>;
452
- endObserveSession?(options: ObserveSessionRef): Promise<void>;
453
- listReleases(options: {
454
- projectId: string;
455
- flowId: string;
456
- limit?: number;
457
- offset?: number;
458
- }): Promise<ReleaseIndexWire>;
459
- getRelease(options: {
460
- projectId: string;
461
- flowId: string;
462
- ref: ReleaseRef;
463
- }): Promise<ReleaseDetailWire>;
464
- listStepHistory(options: {
465
- projectId: string;
466
- flowId: string;
467
- step: string;
468
- flow?: string;
469
- limit?: number;
470
- }): Promise<StepHistoryWire>;
471
- setReleaseRationale(options: {
472
- projectId: string;
473
- flowId: string;
474
- versionId: string;
475
- text: string;
476
- }): Promise<VersionAnnotationWire>;
477
- listThreads(options: {
478
- projectId: string;
479
- flowId: string;
480
- anchorType?: ThreadAnchorType;
481
- anchorKey?: string;
482
- status?: ThreadStatus;
483
- includeMessages: boolean;
484
- limit?: number;
485
- }): Promise<ListThreadsWire>;
486
- createThread(options: {
487
- projectId: string;
488
- flowId: string;
489
- anchorType: ThreadAnchorType;
490
- anchorKey: string;
491
- anchorLabel?: string;
492
- text: string;
493
- }): Promise<HubThreadWire>;
494
- addThreadMessage(options: {
495
- projectId: string;
496
- flowId: string;
497
- threadId: string;
498
- text: string;
499
- }): Promise<HubThreadWire>;
500
- listKnowledge(options: {
501
- projectId: string;
502
- pageKey?: string;
503
- frameId?: string;
504
- markId?: string;
505
- includeMessages: boolean;
506
- limit?: number;
507
- }): Promise<ListKnowledgeWire>;
508
- listFrames(options: {
509
- projectId: string;
510
- flowId: string;
511
- }): Promise<FrameLeanListWire>;
512
- listPageFrames(options: {
513
- projectId: string;
514
- flowId: string;
515
- pageKey: string;
516
- }): Promise<FrameListWire>;
517
- getFrame(options: {
518
- projectId: string;
519
- flowId: string;
520
- frameId: string;
521
- }): Promise<FrameWire>;
522
- requestDeviceCode(): Promise<DeviceAuthorization>;
523
- /**
524
- * Finish an authorization already under way. Returns a status only: the
525
- * session it establishes is stored by the implementation, so a tool never
526
- * holds token material.
527
- */
528
- pollForToken(deviceCode: string, options?: {
529
- timeoutMs?: number;
530
- }): Promise<DeviceLoginResult>;
531
- whoami(): Promise<unknown>;
532
- /**
533
- * Where a credential would come from, without resolving or refreshing it:
534
- * `'env'` (`WALKEROS_TOKEN`), `'config'` (a stored login), `'host'` (the
535
- * door is served inside a host that authenticates every request itself, so
536
- * this process holds no login to start or end), or null (none).
537
- */
538
- credentialSource(): 'env' | 'config' | 'host' | null;
539
- /**
540
- * Retire the session. Where the credential was issued to this process, that
541
- * means revoking it with the server before dropping it locally; a plane
542
- * holding a bearer it did not issue reports nothing deleted. `envCleared`
543
- * reports that the door also dropped a `WALKEROS_TOKEN` from its own process
544
- * environment, which only a door that owns its process does. The `auth`
545
- * tool never calls this on a `'host'` door.
546
- */
547
- logout(): Promise<{
548
- deleted: boolean;
549
- envCleared?: boolean;
550
- }>;
551
- /**
552
- * The base URL of the walkerOS app this door talks to, without a trailing
553
- * slash. REQUIRED: a tool that puts a link in front of a person has to name
554
- * the backend it actually reached, and a door that cannot name itself would
555
- * emit links into a chat transcript that point somewhere else. Making it
556
- * required means the compiler, not a runtime surprise, catches that.
557
- *
558
- * Each door answers from its own world: the CLI-backed client resolves the
559
- * user's machine (`WALKEROS_APP_URL`, then the CLI config file, then the
560
- * built-in default), while an in-process host returns the URL it is served
561
- * on. Never derive this from the local CLI inside a tool.
562
- */
563
- appBaseUrl(): string;
564
- checkHealth?(): Promise<{
565
- reachable: boolean;
566
- status?: string;
567
- version?: string;
568
- error?: string;
569
- }>;
570
- /**
571
- * The API contract verdict for this door against the app it talks to
572
- * (`appBaseUrl()`). A door that calls the app over HTTP compares per
573
- * operation; a door served inside the app answers `in-process`. Optional:
574
- * without it, diagnostics reports `unknown`.
575
- */
576
- checkContract?(): Promise<ContractComparison>;
577
- /**
578
- * The live OpenAPI document of the app this door talks to, served as the
579
- * `walkeros://reference/openapi` resource. Rejects when it cannot be read.
580
- * Optional: without it, the resource states that it is unavailable.
581
- */
582
- openapiDocument?(): Promise<unknown>;
583
- submitFeedback(text: string, options?: FeedbackOptions): Promise<void>;
584
- getFeedbackPreference(): boolean | undefined;
585
- setFeedbackPreference(anonymous: boolean): void;
586
- }
587
-
588
- interface ToolAnnotations {
589
- readOnlyHint: boolean;
590
- destructiveHint: boolean;
591
- idempotentHint: boolean;
592
- openWorldHint: boolean;
593
- }
594
- interface ToolDefinition {
595
- name: string;
596
- title: string;
597
- description: string;
598
- inputSchema: ZodRawShape;
599
- annotations: ToolAnnotations;
600
- }
601
- /**
602
- * Declarative registry mirroring the inputSchema + annotations of every tool
603
- * registered in `createWalkerOSMcpServer`. Use this to bridge tools into
604
- * non-MCP runtimes (e.g., Vercel AI SDK adapters) without booting an
605
- * `McpServer`. Tool handlers are not included here, they require a
606
- * `ToolClient`, which the caller provides.
607
- */
608
- declare const TOOL_DEFINITIONS: readonly ToolDefinition[];
609
-
610
- /**
611
- * A full tool specification: metadata + executable handler.
612
- *
613
- * Produced by each `create<Name>ToolSpec(...)` factory and by the aggregate
614
- * `createToolHandlers(client)`. Consumers without an `McpServer` (e.g., the
615
- * walkerOS app's chat route wrapping tools as Vercel AI SDK tools) use this
616
- * directly; the server factory uses it to call `McpServer.registerTool`.
617
- */
618
- interface ToolSpec {
619
- name: string;
620
- title: string;
621
- description: string;
622
- inputSchema: ZodRawShape;
623
- annotations: ToolAnnotations;
624
- handler: (input: unknown) => Promise<unknown>;
625
- }
626
-
627
- /**
628
- * The capability seam between the flow tools and the machine they run on.
629
- *
630
- * Every file read, URL fetch, bundle, simulation and push a tool performs goes
631
- * through a `FlowRuntime` and nothing else, so the runtime alone decides what
632
- * the process it lives in may do:
633
- *
634
- * - `createLocalRuntime()` keeps every capability. It is for the user's own
635
- * machine (stdio, the developer CLI), where the user is responsible for what
636
- * runs there.
637
- * - `createHostedRuntime(client)` is least privilege for a shared, network
638
- * reached process: it loads inline JSON and saved flow ids only, refuses
639
- * local paths and URLs, and has no `bundle`, `simulate` or `push` at all.
640
- *
641
- * A tool whose operation the runtime does not provide refuses with a hint that
642
- * names only out-of-process routes.
643
- */
644
- interface FlowRuntime {
645
- /**
646
- * Resolve a config input to parsed JSON. Local: a file path, an http(s) URL
647
- * or inline JSON. Hosted: inline JSON or a saved `flow_`/`cfg_` id; a local
648
- * path or URL is refused with a `RuntimeRefusal`.
649
- */
650
- load(input: string): Promise<unknown>;
651
- /**
652
- * The directory local `path` packages of a loaded input resolve against:
653
- * the input file's directory. Absent on a runtime without a filesystem,
654
- * where such packages stay a reported skip.
655
- */
656
- baseDir?(input: string): string | undefined;
657
- /** Compile a flow. Absent on a runtime that must not build in its process. */
658
- bundle?(input: string, opts: BundleOptions): Promise<BundleStats | void>;
659
- /** Build and run one step of a flow. Absent where that must not happen. */
660
- simulate?(input: string, opts: SimulateOptions): Promise<Simulation.Result>;
661
- /**
662
- * The values of the secrets a flow config references (`$secret.NAME`),
663
- * masked wherever a simulation or push result egresses. Read by the tools
664
- * only on a runtime without `loadRun`; a read that fails stops the run.
665
- */
666
- knownSecrets?(input: string): Promise<string[]>;
667
- /**
668
- * Read a push or simulate input once: the config and the values of the
669
- * secrets it references. A prebuilt bundle yields no config. A read that
670
- * fails rejects. Absent with `simulate` and `push`.
671
- */
672
- loadRun?(input: string): Promise<LoadedRun>;
673
- /** Build and run a flow against real destinations. Absent where forbidden. */
674
- push?(input: string, event: Record<string, unknown>, opts: PushOptions): Promise<PushResult>;
675
- }
676
- interface BundleOptions {
677
- flowName?: string;
678
- stats?: boolean;
679
- output?: string;
680
- }
681
- type SimulateStepType = 'source' | 'transformer' | 'collector' | 'destination';
682
- interface SimulateOptions {
683
- stepType: SimulateStepType;
684
- stepId: string;
685
- event: unknown;
686
- flow?: string;
687
- /** The config from `loadRun`: the runtime does not read the input again. */
688
- config?: Flow.Json;
689
- /**
690
- * Transformer, collector and destination steps: pipeline context the step
691
- * reads via `ctx.ingest`. Source steps ignore it.
692
- */
693
- ingest?: Omit<Ingest, '_meta'>;
694
- /**
695
- * Collector state the step starts from. `consent` applies to every step
696
- * (the collector's starting consent); `user`, `globals` and `timing` to
697
- * collector steps only.
698
- */
699
- state?: {
700
- consent?: WalkerOS.Consent;
701
- user?: WalkerOS.User;
702
- globals?: WalkerOS.Properties;
703
- timing?: number;
704
- };
705
- /**
706
- * Destination steps only: run this collector command with `event` as its
707
- * data instead of pushing it (a step example with `command`).
708
- */
709
- command?: Flow.StepCommand;
710
- }
711
- /** A push or simulate input as read once by `loadRun`. */
712
- interface LoadedRun {
713
- config?: Flow.Json;
714
- knownSecrets: string[];
715
- }
716
- interface PushOptions {
717
- flow?: string;
718
- platform?: 'web' | 'server';
719
- /** The config from `loadRun`: the runtime does not read the input again. */
720
- config?: Flow.Json;
721
- }
722
- /**
723
- * Thrown by a runtime when it refuses an input on principle rather than on a
724
- * fault. Carries the hint a tool should surface next to the message.
725
- */
726
- declare class RuntimeRefusal extends Error {
727
- readonly hint: string;
728
- constructor(message: string, hint: string);
729
- }
3
+ import { FlowRuntime, LocalToolSpecs, ToolSpec } from './specs.js';
4
+ export { BundleOptions, KNOWLEDGE_RESOURCES, LoadedRun, PROMPTS, PromptMessage, PromptSpec, PushOptions, RedactOptions, ResourceContent, ResourceListEntry, ResourceSpec, RuntimeRefusal, STRUCTURAL_KEYS, SimulateOptions, SimulateStepType, StaticResourceSpec, TemplateResourceSpec, ToolAnnotations, createLocalToolSpecs, keepStructural, redactDisplayNames, redactNestedStrings, wrapListedRecord, wrapUserData } from './specs.js';
5
+ import '@walkeros/core';
6
+ import '@walkeros/cli';
7
+ import 'zod';
8
+ import '@modelcontextprotocol/sdk/types.js';
730
9
 
731
10
  interface Logger {
732
11
  debug?(message: string, meta?: Record<string, unknown>): void;
@@ -735,261 +14,24 @@ interface Logger {
735
14
  error?(message: string, meta?: Record<string, unknown>): void;
736
15
  }
737
16
  interface CreateServerOptions {
738
- client: ToolClient;
739
- logger?: Logger;
17
+ /** Required: the runtime decides what the process may read and run. */
18
+ runtime: FlowRuntime;
740
19
  version?: string;
741
- catalogBaseUrl?: string;
742
- /**
743
- * The capability runtime the flow tools read, build and run flows through.
744
- * Omitted, the HOSTED runtime is used, the safe default for any shared or
745
- * network-reached process: inline JSON and saved flow ids only, no local
746
- * files, no URLs, no in-process bundle, simulate or push. Pass
747
- * `createLocalRuntime()` only on the user's own machine (stdio, the CLI) to
748
- * keep local file, URL and execution behaviour. See `FlowRuntime`.
749
- */
750
- runtime?: FlowRuntime;
20
+ logger?: Logger;
751
21
  }
752
22
  declare function createWalkerOSMcpServer(opts: CreateServerOptions): McpServer;
753
23
 
754
24
  /**
755
- * Default ToolClient implementation backed by @walkeros/cli. Every method
756
- * delegates to the CLI's programmatic API, which in turn talks to the
757
- * walkerOS app over HTTPS via openapi-fetch. Token resolution and the
758
- * base URL come from the CLI's config file and environment
759
- * (WALKEROS_TOKEN, WALKEROS_APP_URL), so no constructor args are required.
25
+ * The eight tools of the local server, keyed by name, over one runtime: the
26
+ * five shared specs plus the three that run caller code. A type alias, not an
27
+ * interface, so it is assignable to Record<string, ToolSpec>.
760
28
  */
761
- declare class HttpToolClient implements ToolClient {
762
- listProjects(options?: {
763
- cursor?: string;
764
- limit?: number;
765
- }): Promise<unknown>;
766
- getProject(options: {
767
- projectId?: string;
768
- }): Promise<unknown>;
769
- createProject(options: {
770
- name: string;
771
- }): Promise<unknown>;
772
- updateProject(options: {
773
- projectId?: string;
774
- name: string;
775
- }): Promise<unknown>;
776
- deleteProject(options: {
777
- projectId?: string;
778
- }): Promise<unknown>;
779
- /** Refuses while `WALKEROS_PROJECT_ID` names another project (see the CLI). */
780
- setDefaultProject(projectId: string): void;
781
- /**
782
- * `WALKEROS_PROJECT_ID`, then the CLI config's default, through the same
783
- * resolution the CLI's own commands use. Read here, at the door that owns
784
- * this process's environment, never in the shared tool layer: a hosted door
785
- * runs in a server process whose variables are no person's selection.
786
- */
787
- getDefaultProject(): string | null;
788
- listAllFlows(options?: {
789
- sort?: string;
790
- order?: 'asc' | 'desc';
791
- includeDeleted?: boolean;
792
- cursor?: string;
793
- limit?: number;
794
- }): Promise<unknown>;
795
- listFlows(options: ListFlowsOptions): Promise<unknown>;
796
- getFlow(options: {
797
- flowId: string;
798
- projectId?: string;
799
- fields?: string[];
800
- }): Promise<unknown>;
801
- createFlow(options: {
802
- name: string;
803
- content: Record<string, unknown>;
804
- projectId?: string;
805
- }): Promise<unknown>;
806
- updateFlow(options: {
807
- flowId: string;
808
- projectId?: string;
809
- name?: string;
810
- content?: Record<string, unknown>;
811
- mergePatch?: boolean;
812
- }): Promise<unknown>;
813
- deleteFlow(options: {
814
- flowId: string;
815
- projectId?: string;
816
- }): Promise<unknown>;
817
- duplicateFlow(options: {
818
- flowId: string;
819
- name?: string;
820
- projectId?: string;
821
- }): Promise<unknown>;
822
- listPreviews(options: ListPreviewsOptions): Promise<unknown>;
823
- getPreview(options: GetPreviewOptions): Promise<unknown>;
824
- createPreview(options: CreatePreviewOptions & {
825
- siteUrl?: string;
826
- }): Promise<unknown>;
827
- deletePreview(options: DeletePreviewOptions): Promise<unknown>;
828
- regrantPreview(options: RegrantPreviewOptions): Promise<unknown>;
829
- listSecrets(options: ListSecretsOptions): Promise<unknown>;
830
- createSecret(options: CreateSecretOptions): Promise<unknown>;
831
- updateSecret(options: UpdateSecretOptions): Promise<unknown>;
832
- deleteSecret(options: DeleteSecretOptions): Promise<unknown>;
833
- deploy(options: DeployOptions): Promise<unknown>;
834
- listDeployments(options: ListDeploymentsOptions): Promise<unknown>;
835
- getDeploymentBySlug(options: {
836
- slug: string;
837
- projectId?: string;
838
- }): Promise<unknown>;
839
- deleteDeployment(options: {
840
- slug: string;
841
- projectId?: string;
842
- }): Promise<unknown>;
843
- listJourneys(options: {
844
- flowId: string;
845
- projectId?: string;
846
- traceId?: string;
847
- limit?: number;
848
- }): Promise<JourneysResult>;
849
- /**
850
- * Observe session lifecycle over the CLI's authenticated boundary. The trio
851
- * routes through the same `apiFetch` as every other method here, so token
852
- * resolution, base URL, and `ApiError` shaping (which
853
- * `isAuthenticationError` reads) stay identical to the rest of the client.
854
- */
855
- startObserveSession(options: StartObserveSessionOptions): Promise<ObserveSessionResult>;
856
- getObserveSession(options: ObserveSessionRef): Promise<ObserveSessionResult>;
857
- endObserveSession(options: ObserveSessionRef): Promise<void>;
858
- listReleases(options: {
859
- projectId: string;
860
- flowId: string;
861
- limit?: number;
862
- offset?: number;
863
- }): Promise<ReleaseIndexWire>;
864
- getRelease(options: {
865
- projectId: string;
866
- flowId: string;
867
- ref: ReleaseRef;
868
- }): Promise<ReleaseDetailWire>;
869
- listStepHistory(options: {
870
- projectId: string;
871
- flowId: string;
872
- step: string;
873
- flow?: string;
874
- limit?: number;
875
- }): Promise<StepHistoryWire>;
876
- setReleaseRationale(options: {
877
- projectId: string;
878
- flowId: string;
879
- versionId: string;
880
- text: string;
881
- }): Promise<VersionAnnotationWire>;
882
- listThreads(options: {
883
- projectId: string;
884
- flowId: string;
885
- anchorType?: ThreadAnchorType;
886
- anchorKey?: string;
887
- status?: ThreadStatus;
888
- includeMessages: boolean;
889
- limit?: number;
890
- }): Promise<ListThreadsWire>;
891
- createThread(options: {
892
- projectId: string;
893
- flowId: string;
894
- anchorType: ThreadAnchorType;
895
- anchorKey: string;
896
- anchorLabel?: string;
897
- text: string;
898
- }): Promise<HubThreadWire>;
899
- addThreadMessage(options: {
900
- projectId: string;
901
- flowId: string;
902
- threadId: string;
903
- text: string;
904
- }): Promise<HubThreadWire>;
905
- listKnowledge(options: {
906
- projectId: string;
907
- pageKey?: string;
908
- frameId?: string;
909
- markId?: string;
910
- includeMessages: boolean;
911
- limit?: number;
912
- }): Promise<ListKnowledgeWire>;
913
- listFrames(options: {
914
- projectId: string;
915
- flowId: string;
916
- }): Promise<FrameLeanListWire>;
917
- listPageFrames(options: {
918
- projectId: string;
919
- flowId: string;
920
- pageKey: string;
921
- }): Promise<FrameListWire>;
922
- getFrame(options: {
923
- projectId: string;
924
- flowId: string;
925
- frameId: string;
926
- }): Promise<FrameWire>;
927
- requestDeviceCode(): Promise<DeviceAuthorization>;
928
- pollForToken(deviceCode: string, options?: {
929
- timeoutMs?: number;
930
- }): Promise<DeviceLoginResult>;
931
- whoami(): Promise<unknown>;
932
- credentialSource(): 'env' | 'config' | null;
933
- /**
934
- * Revoke and drop the stored session, then clear a `WALKEROS_TOKEN` from
935
- * this process: the local door owns its environment, so a later call in the
936
- * same session no longer authenticates with it.
937
- */
938
- logout(): Promise<{
939
- deleted: boolean;
940
- superseded: boolean;
941
- envCleared: boolean;
942
- }>;
943
- /**
944
- * The app this local door talks to: `WALKEROS_APP_URL`, then the CLI config
945
- * file, then the built-in default, which is exactly the chain every other
946
- * method here already resolves its base URL through. Normalized, because
947
- * neither the env var nor the config file is obliged to omit a trailing
948
- * slash and the interface promises a base without one.
949
- */
950
- appBaseUrl(): string;
951
- /**
952
- * Unauthenticated reachability probe of the app's PUBLIC health route
953
- * (`GET /api/health`) at `appBaseUrl()`, through the CLI's `fetchHealth`.
954
- * Sends no credential, so diagnostics works logged-out. Resolves
955
- * `{ reachable: false, error }` only on a real network/timeout failure.
956
- */
957
- checkHealth(): Promise<{
958
- reachable: boolean;
959
- status?: string;
960
- version?: string;
961
- error?: string;
962
- }>;
963
- /**
964
- * The contract verdict for this MCP against `appBaseUrl()`, per operation,
965
- * naming `@walkeros/mcp` as the client.
966
- */
967
- checkContract(): Promise<ContractComparison>;
968
- /** The live public OpenAPI document of `appBaseUrl()`, without a credential. */
969
- openapiDocument(): Promise<unknown>;
970
- submitFeedback(text: string, options?: FeedbackOptions): Promise<void>;
971
- getFeedbackPreference(): boolean | undefined;
972
- setFeedbackPreference(anonymous: boolean): void;
973
- }
974
-
975
- interface CreateStreamableHttpHandlerOptions extends WebStandardStreamableHTTPServerTransportOptions {
976
- /**
977
- * Called after a session is initialized. Wraps onsessioninitialized.
978
- */
979
- onSessionInitialized?: (sessionId: string) => void | Promise<void>;
980
- }
981
- /**
982
- * Returns a Fetch-style handler: `(Request) => Promise<Response>`.
983
- *
984
- * Single call creates a dedicated transport instance and connects it to the
985
- * given `McpServer`. The handler holds that transport for its entire
986
- * lifetime, call `createStreamableHttpHandler` once per app lifecycle, not
987
- * per request. For multi-session hosting (different users, persistent
988
- * sessions), instantiate one handler per session keyed by `Mcp-Session-Id`
989
- * at the Route Handler layer; this factory is the session-agnostic
990
- * building block.
991
- */
992
- declare function createStreamableHttpHandler(server: McpServer, opts?: CreateStreamableHttpHandlerOptions): (request: Request) => Promise<Response>;
29
+ type LocalServerToolSpecs = LocalToolSpecs & {
30
+ flow_bundle: ToolSpec;
31
+ flow_simulate: ToolSpec;
32
+ flow_push: ToolSpec;
33
+ };
34
+ declare function createToolHandlers(runtime: FlowRuntime): LocalServerToolSpecs;
993
35
 
994
36
  /**
995
37
  * The full-capability runtime for the user's own machine (stdio, the developer
@@ -1003,377 +45,6 @@ declare function createStreamableHttpHandler(server: McpServer, opts?: CreateStr
1003
45
  */
1004
46
  declare function createLocalRuntime(): FlowRuntime;
1005
47
 
1006
- /**
1007
- * The least-privilege runtime for a shared, network-reached process: the app's
1008
- * OAuth door, in-app chat, and any third-party HTTP host.
1009
- *
1010
- * It never touches the filesystem or the network on the caller's behalf. A
1011
- * saved `flow_`/`cfg_` id is resolved through the access-scoped tool client, a
1012
- * document is parsed inline, and everything else is refused. `bundle`,
1013
- * `simulate` and `push` are deliberately absent: compiling or importing a
1014
- * caller's flow pulls that caller's code (inline or by package name) into this
1015
- * process, and no input shape makes that safe here.
1016
- */
1017
- declare function createHostedRuntime(client: Pick<ToolClient, 'getFlow'>): FlowRuntime;
1018
-
1019
- /**
1020
- * Exported so the hosted plane can assert parity against this exact string
1021
- * instead of retyping it.
1022
- */
1023
- declare const DESCRIPTION: string;
1024
- /**
1025
- * Hints carry the verb ladder rather than the description. Module constants so
1026
- * the wording is one string per idea, quotable verbatim, and identical across
1027
- * planes. Exported so the hosted plane imports them instead of retyping them,
1028
- * which makes cross-plane parity a compiler concern.
1029
- */
1030
- declare const HINT_SIMULATE_FIRST = "Simulate before preview: flow_simulate checks mapping with no browser.";
1031
- declare const HINT_PREVIEW_STREAMS = "Preview streams into this session: mint a link with flow_manage preview_regrant, then open it on your site.";
1032
- declare const HINT_READ = "Read with observe_journeys (flowId); it is the only read.";
1033
- declare const HINT_STOP = "End both arms with observe_session stop.";
1034
- declare const HINT_EMPTY_FEED = "recordsReceived is 0: nothing has reached the feed yet. Drive traffic on an attached arm.";
1035
- declare const HINT_ENDED = "Session ended and both arms detached. Start a new one with observe_session start.";
1036
- declare const HINT_NO_WINDOW = "No Observe session on this flow. Open one with observe_session start.";
1037
-
1038
- /**
1039
- * Exported so a host asserts parity against this exact string instead of
1040
- * retyping it.
1041
- */
1042
- declare const HUB_MANAGE_DESCRIPTION: string;
1043
- /**
1044
- * One flat schema with an `action` enum and per-action optional fields, the
1045
- * shape `flow_manage`, `project_manage`, and `secret_manage` already use.
1046
- * Per-action requirements are enforced in the handler, so later actions add a
1047
- * field and an enum member without reshaping what callers already send.
1048
- *
1049
- * Exported so the declarative registry holds the same object rather than a
1050
- * second copy of it.
1051
- */
1052
- declare const HUB_MANAGE_INPUT_SCHEMA: {
1053
- action: z.ZodEnum<{
1054
- releases: "releases";
1055
- release_get: "release_get";
1056
- step_history: "step_history";
1057
- rationale_set: "rationale_set";
1058
- threads: "threads";
1059
- note_add: "note_add";
1060
- knowledge: "knowledge";
1061
- }>;
1062
- projectId: z.ZodOptional<z.ZodString>;
1063
- flowId: z.ZodOptional<z.ZodString>;
1064
- versionId: z.ZodOptional<z.ZodString>;
1065
- versionNumber: z.ZodOptional<z.ZodNumber>;
1066
- step: z.ZodOptional<z.ZodString>;
1067
- flow: z.ZodOptional<z.ZodString>;
1068
- text: z.ZodOptional<z.ZodString>;
1069
- limit: z.ZodOptional<z.ZodNumber>;
1070
- offset: z.ZodOptional<z.ZodNumber>;
1071
- anchorType: z.ZodOptional<z.ZodEnum<{
1072
- step: "step";
1073
- entity_action: "entity_action";
1074
- release: "release";
1075
- contract: "contract";
1076
- tag: "tag";
1077
- }>>;
1078
- anchorKey: z.ZodOptional<z.ZodString>;
1079
- anchorLabel: z.ZodOptional<z.ZodString>;
1080
- threadId: z.ZodOptional<z.ZodString>;
1081
- status: z.ZodOptional<z.ZodEnum<{
1082
- open: "open";
1083
- resolved: "resolved";
1084
- }>>;
1085
- pageKey: z.ZodOptional<z.ZodString>;
1086
- frameId: z.ZodOptional<z.ZodString>;
1087
- markId: z.ZodOptional<z.ZodString>;
1088
- };
1089
- /**
1090
- * Hints carry the verb ladder rather than the description. One constant per
1091
- * sentence the tool can emit, so the surface fixture pins wording and ordering
1092
- * by name and a reword fails a test instead of drifting.
1093
- */
1094
- declare const HUB_HINT_RELEASE_GET = "Use action \"release_get\" with a versionId or versionNumber to read one release in full, with its diff.";
1095
- declare const HUB_HINT_ROWS_ARE_DEPLOYMENTS = "Rows are deployments, not releases: the same versionId on several rows is a redeploy of identical content, so count distinct versionId values, and note that total counts deployments.";
1096
- declare const HUB_HINT_STEP_HISTORY = "Use action \"step_history\" to see which releases touched one step.";
1097
- declare const HUB_HINT_MASKED_ONLY = "The diff is empty because the only changes are inside masked values. Say that the change is not visible here rather than that nothing changed.";
1098
- declare const HUB_HINT_TRACE_STEP = "Use action \"step_history\" to trace one step across releases.";
1099
- declare const HUB_HINT_WRITE_RATIONALE = "This release has no human rationale. Read the diff, then use action \"rationale_set\" to record why it changed.";
1100
- declare const HUB_HINT_SCAN_CAPPED = "The scan stopped at the entry cap, so older releases were not compared. Narrow with \"flow\" to see the whole history of one occurrence.";
1101
- declare const HUB_HINT_NO_MATCH = "No scanned release touched this step. Check the step key against knownSteps, or raise limit to scan further back.";
1102
- declare const HUB_HINT_OPEN_RELEASE = "Use action \"release_get\" on one of these versionIds to read the full diff and rationale.";
1103
- declare const HUB_HINT_RATIONALE_VISIBLE = "The rationale is now visible on this release in the app.";
1104
- declare const HUB_HINT_CONFIRM_INDEX = "Use action \"releases\" to confirm it appears in the index.";
1105
- declare const HUB_HINT_THREADS_PAGE_CAPPED = "More threads match than were returned (the page is capped at 20 when messages are attached). Narrow with anchorType and anchorKey, or with status, rather than treating this as the complete list.";
1106
- declare const HUB_HINT_NOTHING_DISCUSSED = "Nothing is being discussed on this flow. Use action \"note_add\" with a versionId to start a thread on a release.";
1107
- declare const HUB_HINT_NO_THREAD_ON_ANCHOR = "No thread hangs on this anchor yet. Use action \"note_add\" to open one.";
1108
- declare const HUB_HINT_THREADS_INDEX = "This is an index: message bodies are omitted. Pass a versionId, or anchorType with anchorKey, to read one discussion in full.";
1109
- declare const HUB_HINT_MESSAGES_TRUNCATED = "A thread here is marked hasMoreMessages: only its newest messages were returned. Say the discussion is longer than what you read rather than summarizing it as complete.";
1110
- declare const HUB_HINT_REPLY_OR_OPEN = "Use action \"note_add\" with a threadId to reply in one of these threads, or without one to open another.";
1111
- declare const HUB_HINT_RESOLVE_IN_APP = "Resolving a thread into a release is done by a person in the app, not through this tool.";
1112
- declare const HUB_HINT_MESSAGE_VISIBLE = "The message is now visible in this thread in the app.";
1113
- declare const HUB_HINT_STAYS_RESOLVED = "This thread is resolved and stayed resolved: a reply never retracts the release link.";
1114
- declare const HUB_HINT_READ_BACK = "Use action \"threads\" to read the discussion back.";
1115
- declare const HUB_HINT_THREAD_OPEN = "The thread is now open on this anchor in the app.";
1116
- declare const HUB_HINT_KEEP_ONE_THREAD = "Pass its threadId back to action \"note_add\" to keep the conversation in one place instead of opening another thread.";
1117
- declare const HUB_HINT_KNOWLEDGE_PAGE_CAPPED = "More knowledge matches than was returned. Narrow with pageKey, then frameId, then markId, rather than treating this as everything that was written.";
1118
- declare const HUB_HINT_NOTHING_WRITTEN = "Nothing has been written here. Notes are left on the page in Tag Mode, not through this tool.";
1119
- declare const HUB_HINT_KNOWLEDGE_INDEX = "This is an index: message bodies are omitted. Pass markId with frameId to read one mark in full.";
1120
- declare const HUB_HINT_ENTRY_NAMES_FLOW = "An entry names the flow it was written against in flowId, and validity says which release was live at the time.";
1121
- declare const HUB_HINT_KNOWLEDGE_READ_ONLY = "This tool only reads knowledge. Answering a note, and settling it, are done by a person in the app.";
1122
- declare const HUB_HINT_READ_FRAME = "Use frame_manage action \"get\" with the frameId to read the frame and its marks.";
1123
- declare const HUB_NOT_FOUND_HINT = "Use action \"releases\" to find version ids and action \"threads\" to find thread ids.";
1124
-
1125
- /**
1126
- * Exported so a host asserts parity against this exact string instead of
1127
- * retyping it.
1128
- */
1129
- declare const FRAME_MANAGE_DESCRIPTION: string;
1130
- /**
1131
- * Exported so the declarative registry holds the same object rather than a
1132
- * second copy of it.
1133
- */
1134
- declare const FRAME_MANAGE_INPUT_SCHEMA: {
1135
- action: z.ZodEnum<{
1136
- page: "page";
1137
- get: "get";
1138
- list: "list";
1139
- }>;
1140
- projectId: z.ZodOptional<z.ZodString>;
1141
- flowId: z.ZodOptional<z.ZodString>;
1142
- pageKey: z.ZodOptional<z.ZodString>;
1143
- frameId: z.ZodOptional<z.ZodString>;
1144
- };
1145
- /**
1146
- * Hints carry the verb ladder rather than the description. One constant per
1147
- * sentence the tool can emit, so the surface fixture pins wording and ordering
1148
- * by name and a reword fails a test instead of drifting.
1149
- */
1150
- declare const FRAME_HINT_OPEN_PAGE_OR_GET = "Use action \"page\" with a pageKey (a frame\u2019s source.key) to read a page with marks, or action \"get\" with a frameId.";
1151
- declare const FRAME_HINT_NAMES_ARE_DOCUMENTATION = "Frame names are documentation; the marks inside a frame carry the meaning.";
1152
- declare const FRAME_HINT_NONE_YET = "This flow has no frames yet. Frames are drawn in Tag Mode or the app, not through this tool.";
1153
- declare const FRAME_HINT_MARK_SPACE = "Tag geometry is fractional: a rect is 0..1 of its frame, and an at is 0..1 of its parent tag\u2019s box, or of the frame for a root tag; a child frame sits inside its parent through placements[].rect.";
1154
- declare const FRAME_HINT_READ_KNOWLEDGE = "Use hub_manage action \"knowledge\" with frameId (and markId) to read what people wrote here. A markId is a tag id from these marks, and a tag\u2019s threadRef is the id of its thread entry there.";
1155
- declare const FRAME_HINT_NONE_ON_PAGE = "No frames on this page. Check the pageKey against the source.key values from action \"list\".";
1156
- declare const FRAME_HINT_EXTENDS_BASE = "This frame extends another and stores only what it adds; read the base frame (extends) for the rest.";
1157
- declare const FRAME_NOT_FOUND_HINT = "Use action \"list\" or \"page\" to find frame ids.";
1158
-
1159
- /** The code every door answers a plan or project gate with. */
1160
- declare const FEATURE_NOT_AVAILABLE = "FEATURE_NOT_AVAILABLE";
1161
- /** The features a door can refuse a whole tool for. */
1162
- type GatedFeature = 'hub' | 'frames';
1163
- /**
1164
- * A denial is recognised by its code, never by its wording: the two doors phrase
1165
- * the refusal differently and only the code is contractual.
1166
- */
1167
- declare function isFeatureDenial(error: unknown): boolean;
1168
- /**
1169
- * Names the feature so an agent can tell the person what is missing. Enabling
1170
- * it is a plan or project entitlement change made in the app, never something
1171
- * a tool can do, and the hint says so instead of inviting a retry.
1172
- */
1173
- declare function featureDenialHint(feature: GatedFeature): string;
1174
-
1175
- /**
1176
- * Wraps a user-writable string in `<user_data>…</user_data>` so the chat
1177
- * assistant treats it as data, never as instructions. Inner `</user_data>`
1178
- * sequences are mangled (`</user_data_>`) so a malicious string can't close
1179
- * the envelope early.
1180
- *
1181
- * Idempotent: a string that is already a well-formed envelope with no inner
1182
- * `</user_data>` is returned unchanged.
1183
- */
1184
- declare function wrapUserData(s: string): string;
1185
- interface RedactOptions {
1186
- /** Return `true` to skip wrapping for a given object key. Only invoked for
1187
- * string values on object entries — not for array elements or scalar
1188
- * roots. Use to keep ids / slugs / dates literal. */
1189
- skip?: (key: string) => boolean;
1190
- }
1191
- /**
1192
- * Recursively walks `value` and returns a deep-copied structure where every
1193
- * string leaf has been passed through `wrapUserData`. Pass `skip` to exclude
1194
- * specific keys (e.g. `id`) from wrapping.
1195
- */
1196
- declare function redactNestedStrings<T>(value: T, opts?: RedactOptions): T;
1197
-
1198
- type SuggestionTile = {
1199
- label: string;
1200
- description?: string;
1201
- prompt: string;
1202
- autoSend?: boolean;
1203
- };
1204
- interface FlowCanvasPayload {
1205
- flowId?: string;
1206
- configName: string;
1207
- platform: 'web' | 'server';
1208
- flowConfig: Record<string, unknown>;
1209
- highlight?: {
1210
- stepAddress: string;
1211
- reason: string;
1212
- };
1213
- suggestions?: SuggestionTile[];
1214
- /**
1215
- * Absolute link to this flow's page in the app, from `links.flow`.
1216
- *
1217
- * Named for the `appBaseUrl()` seam it is built from, and never `url`: that
1218
- * is a field several app responses already use for something of their own
1219
- * (a deployment's `url` is where it SERVES), and one key meaning one thing
1220
- * across every tool is what keeps a link from ever landing on top of it.
1221
- *
1222
- * Optional because a tool that cannot name the project or the flow emits no
1223
- * link rather than a guess, and because the in-app chat renders the canvas
1224
- * itself and has no use for a link to the page it is already on.
1225
- */
1226
- appUrl?: string;
1227
- }
1228
- interface FlowCanvasToolResult extends FlowCanvasPayload {
1229
- kind: 'flow-canvas';
1230
- }
1231
- /**
1232
- * Tool-result helper that marks a response as renderable as a FlowCanvas.
1233
- * The chat UI inspects `structuredContent.kind === 'flow-canvas'` and mounts
1234
- * a `FlowCanvasBubble` instead of the generic JSON fallback. The `content[0]`
1235
- * text is the same JSON stringified — the LLM sees a self-describing object.
1236
- */
1237
- declare function flowCanvasResult(payload: FlowCanvasPayload): {
1238
- content: {
1239
- type: "text";
1240
- text: string;
1241
- }[];
1242
- structuredContent: Record<string, unknown> & {
1243
- kind: "flow-canvas";
1244
- };
1245
- };
1246
- declare function isFlowCanvasResult(v: unknown): v is FlowCanvasToolResult;
1247
-
1248
- /**
1249
- * Addresses of walkerOS app screens, built in one place so every tool hands a
1250
- * person the same link for the same screen.
1251
- *
1252
- * WHY THIS EXISTS. A tool that names a release, a step, or a deployment in
1253
- * prose leaves the person to go find it. A link ends that: the answer and the
1254
- * screen it is about arrive together. Building the address in each tool would
1255
- * instead give as many spellings of `/projects/.../flows/...` as there are
1256
- * emission points, and the first one to drift would send someone to a 404 that
1257
- * no test here could see.
1258
- *
1259
- * THE BASE URL IS CONSUMED RAW. `client.appBaseUrl()` is already normalized by
1260
- * the door that answers it (the CLI-backed door wraps `resolveAppUrl()` in
1261
- * `normalizeBaseUrl`; the hosted door returns the same expression it publishes
1262
- * as its OAuth issuer, which cannot carry a trailing slash). Normalizing again
1263
- * here would put a second opinion about the shape in the system, which is
1264
- * exactly what one normalization point per door exists to prevent.
1265
- *
1266
- * ONE DEFINITION, BOTH DOORS. Nothing here branches on which door is calling.
1267
- * The base URL is the only thing that differs between them, and it arrives as
1268
- * an argument.
1269
- *
1270
- * EVERY LINK IS ABSOLUTE. These land in a chat transcript, where a path
1271
- * relative to nothing is useless.
1272
- *
1273
- * AN UNBUILDABLE LINK IS `undefined`, NEVER A GUESS. Every builder returns
1274
- * `undefined` when it cannot name a screen that exists, and callers spread the
1275
- * field conditionally so the result simply carries no link. A link that lands
1276
- * on a 404, or on the app's "can't open that" notice, is worse than no link:
1277
- * it costs the person a click and teaches them the tool's links are unreliable.
1278
- *
1279
- * THE URL SHAPES ARE THE APP'S, NOT OURS. They mirror what the app routes
1280
- * today: `/projects/{projectId}/flows/{flowId}` and
1281
- * `/projects/{projectId}/deployments/{deploymentId}`, with a view on the flow
1282
- * page addressed by the `view` query param whose value names a SUBJECT
1283
- * (`variables`, `secrets`, `contract`, `history`, `releases`, `knowledge`,
1284
- * `step`). A step is `?view=step&flow=<named flow>&step=<type.name>`, the same
1285
- * vocabulary `hub_manage` already takes as its `flow` and `step` params.
1286
- */
1287
- /** A flow page: the address every flow-scoped view hangs off. */
1288
- interface FlowLinkTarget {
1289
- /** From `client.appBaseUrl()`. Consumed as given. */
1290
- baseUrl: string;
1291
- projectId: string;
1292
- flowId: string;
1293
- }
1294
- /**
1295
- * One step inside a flow. `flow` is the named flow within the config ("web",
1296
- * "server"); `step` is `"type.name"`, e.g. `"destination.ga4"`.
1297
- */
1298
- interface StepLinkTarget extends FlowLinkTarget {
1299
- step: string;
1300
- /**
1301
- * Null and undefined both mean "the caller did not name one", which is the
1302
- * shape `hub_manage`'s step history answers with when it was not filtered by
1303
- * flow.
1304
- */
1305
- flow?: string | null;
1306
- }
1307
- /** One discussion thread, addressed by what it hangs on. */
1308
- interface ThreadLinkTarget extends FlowLinkTarget {
1309
- anchorType: string;
1310
- }
1311
- /**
1312
- * One deployment.
1313
- *
1314
- * Pass the `dep_...` id, not the slug. The detail route resolves either, but
1315
- * the page's live-status stream matches on the id alone, so a slug link opens a
1316
- * page whose status stream fails while the deployment is still deploying. This
1317
- * builder does not inspect the value: naming the id is the caller's job.
1318
- */
1319
- interface DeploymentLinkTarget {
1320
- baseUrl: string;
1321
- projectId: string;
1322
- deploymentId: string;
1323
- }
1324
- declare const links: {
1325
- /** The flow page itself. `undefined` when any part of the address is empty. */
1326
- flow(target: FlowLinkTarget): string | undefined;
1327
- /**
1328
- * The screen showing one step.
1329
- *
1330
- * A `contract` step, in any of its spellings, is answered with the CONTRACT
1331
- * view rather than a step address. `?view=step&step=contract.checkout` is a
1332
- * legitimate address in the vocabulary this tool speaks, but the app has
1333
- * deliberately deferred opening ONE contract entry and refuses that link with
1334
- * a notice. `?view=contract` opens the contract editor the entry lives in,
1335
- * which is the nearest screen that actually exists. A `flow` alongside a
1336
- * contract step is a caller mistake (contract entries are top-level) and is
1337
- * ignored rather than turned into a refused link.
1338
- *
1339
- * Otherwise a step needs its named flow: `type.name` alone is not unique in a
1340
- * config holding both a web and a server flow, and the app resolves an
1341
- * address without one to nothing and says so on screen. So an unnamed flow
1342
- * yields `undefined` here. Callers that want the link can re-ask with `flow`.
1343
- *
1344
- * What this cannot check is whether the step is still IN that flow. The
1345
- * address is resolved against the live config when the page opens, and a step
1346
- * since renamed or removed gets a notice there rather than a broken screen.
1347
- */
1348
- step(target: StepLinkTarget): string | undefined;
1349
- /**
1350
- * The release history of a flow.
1351
- *
1352
- * The app has no address for ONE release: `?view=releases` declares no params
1353
- * and opens the list the release is a row of. That is the screen a person
1354
- * asking about a release wants to be on, so this takes the flow and nothing
1355
- * else rather than pretending to a precision the app does not have.
1356
- */
1357
- release(target: FlowLinkTarget): string | undefined;
1358
- /**
1359
- * The screen a thread is read on.
1360
- *
1361
- * Only a release anchor can be addressed from the wire shape this tool
1362
- * holds. The app renders release-anchored discussions inside the release
1363
- * history, beside the release they hang on. Step and entity-action anchors
1364
- * have no surface at all yet. A TAG anchor does have one, the knowledge list
1365
- * on `?view=knowledge`, but only when the thread was captured in Tag Mode
1366
- * and carries a frame: `HubThreadWire` has no `frameId`, so nothing here can
1367
- * tell such a thread from one written over MCP against a null frame, and a
1368
- * knowledge link would open a list the thread may be absent from. So
1369
- * everything but a release anchor gets no link rather than a possibly empty
1370
- * one.
1371
- */
1372
- thread(target: ThreadLinkTarget): string | undefined;
1373
- /** One deployment's detail page. */
1374
- deployment(target: DeploymentLinkTarget): string | undefined;
1375
- };
1376
-
1377
48
  declare module '@walkeros/core' {
1378
49
  interface SourceMap {
1379
50
  mcp: {
@@ -1384,19 +55,4 @@ declare module '@walkeros/core' {
1384
55
  }
1385
56
  }
1386
57
 
1387
- /**
1388
- * Handler-bearing spec for every tool `createWalkerOSMcpServer` registers.
1389
- *
1390
- * Consumers that need to drive the tools WITHOUT an `McpServer` (e.g., the
1391
- * walkerOS app's chat route wrapping them as Vercel AI SDK tools) should call
1392
- * `createToolHandlers(client, packageVersion)` and iterate the returned record.
1393
- * Handlers are closed over `client`, so the caller can bind a single
1394
- * `ToolClient` (such as the zero-hop `ServiceToolClient`) once per session.
1395
- * `packageVersion` is reported by the `diagnostics` tool and defaults to
1396
- * `'0.0.0'` when omitted. `runtime` defaults to the hosted runtime, the safe
1397
- * choice for any shared process; pass `createLocalRuntime()` only on the
1398
- * user's own machine.
1399
- */
1400
- declare function createToolHandlers(client: ToolClient, packageVersion?: string, runtime?: FlowRuntime): Record<string, ToolSpec>;
1401
-
1402
- export { type BundleOptions, type CreateServerOptions, type CreateStreamableHttpHandlerOptions, type DeploymentLinkTarget, FEATURE_NOT_AVAILABLE, FRAME_HINT_EXTENDS_BASE, FRAME_HINT_MARK_SPACE, FRAME_HINT_NAMES_ARE_DOCUMENTATION, FRAME_HINT_NONE_ON_PAGE, FRAME_HINT_NONE_YET, FRAME_HINT_OPEN_PAGE_OR_GET, FRAME_HINT_READ_KNOWLEDGE, FRAME_MANAGE_DESCRIPTION, FRAME_MANAGE_INPUT_SCHEMA, FRAME_NOT_FOUND_HINT, type FlowCanvasPayload, type FlowCanvasToolResult, type FlowLinkTarget, type FlowRuntime, type FrameLeanListWire, type FrameLeanWire, type FrameListWire, type FrameWire, type GatedFeature, HINT_EMPTY_FEED, HINT_ENDED, HINT_NO_WINDOW, HINT_PREVIEW_STREAMS, HINT_READ, HINT_SIMULATE_FIRST, HINT_STOP, HUB_HINT_CONFIRM_INDEX, HUB_HINT_ENTRY_NAMES_FLOW, HUB_HINT_KEEP_ONE_THREAD, HUB_HINT_KNOWLEDGE_INDEX, HUB_HINT_KNOWLEDGE_PAGE_CAPPED, HUB_HINT_KNOWLEDGE_READ_ONLY, HUB_HINT_MASKED_ONLY, HUB_HINT_MESSAGES_TRUNCATED, HUB_HINT_MESSAGE_VISIBLE, HUB_HINT_NOTHING_DISCUSSED, HUB_HINT_NOTHING_WRITTEN, HUB_HINT_NO_MATCH, HUB_HINT_NO_THREAD_ON_ANCHOR, HUB_HINT_OPEN_RELEASE, HUB_HINT_RATIONALE_VISIBLE, HUB_HINT_READ_BACK, HUB_HINT_READ_FRAME, HUB_HINT_RELEASE_GET, HUB_HINT_REPLY_OR_OPEN, HUB_HINT_RESOLVE_IN_APP, HUB_HINT_ROWS_ARE_DEPLOYMENTS, HUB_HINT_SCAN_CAPPED, HUB_HINT_STAYS_RESOLVED, HUB_HINT_STEP_HISTORY, HUB_HINT_THREADS_INDEX, HUB_HINT_THREADS_PAGE_CAPPED, HUB_HINT_THREAD_OPEN, HUB_HINT_TRACE_STEP, HUB_HINT_WRITE_RATIONALE, HUB_MANAGE_DESCRIPTION, HUB_MANAGE_INPUT_SCHEMA, HUB_NOT_FOUND_HINT, HttpToolClient, type HubThreadWire, type JourneysResult, type KnowledgeEntryWire, type ListKnowledgeWire, type ListThreadsWire, type Logger, DESCRIPTION as OBSERVE_SESSION_DESCRIPTION, type PushOptions, type RedactOptions, type ReleaseDetailWire, type ReleaseIndexWire, type ReleaseRef, RuntimeRefusal, type SimulateOptions, type SimulateStepType, type StepHistoryWire, type StepLinkTarget, type SuggestionTile, TOOL_DEFINITIONS, type ThreadLinkTarget, type ToolAnnotations, type ToolClient, type ToolDefinition, type ToolSpec, type VersionAnnotationWire, createHostedRuntime, createLocalRuntime, createStreamableHttpHandler, createToolHandlers, createWalkerOSMcpServer, featureDenialHint, flowCanvasResult, isFeatureDenial, isFlowCanvasResult, links, redactNestedStrings, wrapUserData };
58
+ export { type CreateServerOptions, FlowRuntime, type LocalServerToolSpecs, LocalToolSpecs, type Logger, ToolSpec, createLocalRuntime, createToolHandlers, createWalkerOSMcpServer };