@critical-path/svelte 0.10.2 → 0.11.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.
@@ -0,0 +1,26 @@
1
+ import type { CriticalPathClient } from '@critical-path/client';
2
+ export interface WebMcpStateOptions {
3
+ projectId?: string;
4
+ tools?: string[];
5
+ autoRegister?: boolean;
6
+ document?: any;
7
+ navigator?: any;
8
+ window?: any;
9
+ onToolExecuted?: (toolName: string, input: any, result: any) => void;
10
+ }
11
+ export declare class WebMcpState {
12
+ private client;
13
+ private options;
14
+ registered: boolean;
15
+ activeProjectId: string | undefined;
16
+ tools: string[];
17
+ error: Error | null;
18
+ private handle;
19
+ private abortController;
20
+ constructor(client: CriticalPathClient, options?: WebMcpStateOptions);
21
+ register(): void;
22
+ unregister(): void;
23
+ setProjectId(projectId?: string): void;
24
+ }
25
+ export declare function createWebMcpState(client: CriticalPathClient, options?: WebMcpStateOptions): WebMcpState;
26
+ //# sourceMappingURL=webmcp-state.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webmcp-state.svelte.d.ts","sourceRoot":"","sources":["../src/webmcp-state.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACtE;AAED,qBAAa,WAAW;IASV,OAAO,CAAC,MAAM;IAAsB,OAAO,CAAC,OAAO;IAR/D,UAAU,UAA0B;IACpC,eAAe,qBAAyC;IACxD,KAAK,WAAwB;IAC7B,KAAK,eAA8B;IAEnC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,eAAe,CAAgC;gBAEnC,MAAM,EAAE,kBAAkB,EAAU,OAAO,GAAE,kBAAuB;IAOxF,QAAQ,IAAI,IAAI;IA0BhB,UAAU,IAAI,IAAI;IAUlB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;CAQvC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAEvG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@critical-path/svelte",
3
- "version": "0.10.2",
3
+ "version": "0.11.0",
4
4
  "description": "Svelte 5 Runes state and reactive integrations for Critical Path headless project management framework",
5
5
  "author": "Jack James",
6
6
  "license": "MIT",
@@ -18,8 +18,9 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
+ "@critical-path/core": "0.15.2",
21
22
  "@critical-path/client": "0.9.2",
22
- "@critical-path/core": "0.15.2"
23
+ "@critical-path/mcp": "0.2.0"
23
24
  },
24
25
  "peerDependencies": {
25
26
  "svelte": "^5.0.0"
package/src/index.test.ts CHANGED
@@ -14,7 +14,9 @@ import {
14
14
  TaskActivityState,
15
15
  createTaskActivityState,
16
16
  DeliverableState,
17
- createDeliverableState
17
+ createDeliverableState,
18
+ WebMcpState,
19
+ createWebMcpState
18
20
  } from './index.js';
19
21
  import type { CriticalPathClient } from '@critical-path/client';
20
22
  import type { Project, Task, Workflow, Comment, Attachment, Deliverable, DeliverableSummary } from '@critical-path/core';
@@ -408,5 +410,51 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
408
410
  expect(state.data).toEqual([]);
409
411
  });
410
412
  });
413
+
414
+ describe('WebMcpState', () => {
415
+ it('manages WebMCP registration, project scoping, and unregistration', async () => {
416
+ const mockDoc: any = {};
417
+ const mockWin: any = {};
418
+
419
+ const mockClient = {
420
+ getTasks: vi.fn().mockResolvedValue([]),
421
+ createTask: vi.fn().mockImplementation((input) => Promise.resolve({ id: 't1', ...input }))
422
+ } as unknown as CriticalPathClient;
423
+
424
+ const mcpState = createWebMcpState(mockClient, {
425
+ projectId: 'proj_svelte',
426
+ document: mockDoc,
427
+ window: mockWin
428
+ });
429
+
430
+ expect(mcpState.registered).toBe(true);
431
+ expect(mcpState.activeProjectId).toBe('proj_svelte');
432
+ expect(mcpState.tools.length).toBeGreaterThan(0);
433
+ expect(mockDoc.modelContext).toBeDefined();
434
+
435
+ // Execute tool via modelContext
436
+ const created = await mockDoc.modelContext.executeTool('create_task', {
437
+ title: 'Svelte 5 Task'
438
+ });
439
+ expect(created.projectId).toBe('proj_svelte');
440
+ expect(created.title).toBe('Svelte 5 Task');
441
+
442
+ // Update project ID dynamically
443
+ mcpState.setProjectId('proj_svelte_2');
444
+ expect(mcpState.activeProjectId).toBe('proj_svelte_2');
445
+ expect(mcpState.registered).toBe(true);
446
+
447
+ const created2 = await mockDoc.modelContext.executeTool('create_task', {
448
+ title: 'Svelte 5 Task 2'
449
+ });
450
+ expect(created2.projectId).toBe('proj_svelte_2');
451
+
452
+ // Unregister
453
+ mcpState.unregister();
454
+ expect(mcpState.registered).toBe(false);
455
+ expect(mcpState.tools).toEqual([]);
456
+ });
457
+ });
411
458
  });
412
459
 
460
+
package/src/index.ts CHANGED
@@ -11,4 +11,5 @@ export * from './comment-state.svelte.js';
11
11
  export * from './attachment-state.svelte.js';
12
12
  export * from './activity-state.svelte.js';
13
13
  export * from './deliverable-state.svelte.js';
14
+ export * from './webmcp-state.svelte.js';
14
15
 
@@ -0,0 +1,78 @@
1
+ import type { CriticalPathClient } from '@critical-path/client';
2
+ import { registerWebMcpTools, type WebMcpRegistryHandle } from '@critical-path/mcp/web';
3
+
4
+ export interface WebMcpStateOptions {
5
+ projectId?: string;
6
+ tools?: string[];
7
+ autoRegister?: boolean;
8
+ document?: any;
9
+ navigator?: any;
10
+ window?: any;
11
+ onToolExecuted?: (toolName: string, input: any, result: any) => void;
12
+ }
13
+
14
+ export class WebMcpState {
15
+ registered = $state<boolean>(false);
16
+ activeProjectId = $state<string | undefined>(undefined);
17
+ tools = $state<string[]>([]);
18
+ error = $state<Error | null>(null);
19
+
20
+ private handle: WebMcpRegistryHandle | null = null;
21
+ private abortController: AbortController | null = null;
22
+
23
+ constructor(private client: CriticalPathClient, private options: WebMcpStateOptions = {}) {
24
+ this.activeProjectId = options.projectId;
25
+ if (options.autoRegister ?? true) {
26
+ this.register();
27
+ }
28
+ }
29
+
30
+ register(): void {
31
+ if (this.registered) return;
32
+ this.error = null;
33
+
34
+ try {
35
+ this.abortController = new AbortController();
36
+ this.handle = registerWebMcpTools({
37
+ client: this.client,
38
+ projectId: this.activeProjectId,
39
+ tools: this.options.tools,
40
+ signal: this.abortController.signal,
41
+ document: this.options.document,
42
+ navigator: this.options.navigator,
43
+ window: this.options.window,
44
+ onToolExecuted: (name, input, result) => {
45
+ this.options.onToolExecuted?.(name, input, result);
46
+ }
47
+ });
48
+ this.tools = this.handle.getRegisteredTools().map((t) => t.name);
49
+ this.registered = true;
50
+ } catch (err) {
51
+ this.error = err instanceof Error ? err : new Error(String(err));
52
+ this.registered = false;
53
+ }
54
+ }
55
+
56
+ unregister(): void {
57
+ if (!this.registered) return;
58
+ this.abortController?.abort();
59
+ this.handle?.unregister();
60
+ this.handle = null;
61
+ this.abortController = null;
62
+ this.registered = false;
63
+ this.tools = [];
64
+ }
65
+
66
+ setProjectId(projectId?: string): void {
67
+ if (this.activeProjectId === projectId) return;
68
+ this.activeProjectId = projectId;
69
+ if (this.registered) {
70
+ this.unregister();
71
+ this.register();
72
+ }
73
+ }
74
+ }
75
+
76
+ export function createWebMcpState(client: CriticalPathClient, options?: WebMcpStateOptions): WebMcpState {
77
+ return new WebMcpState(client, options);
78
+ }