@shawnowen/comet-mcp 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +86 -19
  2. package/dist/alert-dispatcher.d.ts +23 -0
  3. package/dist/alert-dispatcher.js +101 -0
  4. package/dist/bound-session.d.ts +23 -0
  5. package/dist/bound-session.js +119 -0
  6. package/dist/bridge-config.d.ts +6 -0
  7. package/dist/bridge-config.js +78 -0
  8. package/dist/cdp-client.d.ts +40 -4
  9. package/dist/cdp-client.js +502 -155
  10. package/dist/comet-ai.d.ts +15 -0
  11. package/dist/comet-ai.js +114 -38
  12. package/dist/delegate-binding.d.ts +19 -0
  13. package/dist/delegate-binding.js +73 -0
  14. package/dist/discovery/capability-entry.d.ts +215 -0
  15. package/dist/discovery/capability-entry.js +13 -0
  16. package/dist/discovery/description-template.d.ts +40 -0
  17. package/dist/discovery/description-template.js +61 -0
  18. package/dist/discovery/golden-queries.fixture.d.ts +22 -0
  19. package/dist/discovery/golden-queries.fixture.js +137 -0
  20. package/dist/discovery/mcp-source.d.ts +38 -0
  21. package/dist/discovery/mcp-source.js +70 -0
  22. package/dist/discovery/metadata-completeness.d.ts +48 -0
  23. package/dist/discovery/metadata-completeness.js +83 -0
  24. package/dist/discovery/registry.d.ts +35 -0
  25. package/dist/discovery/registry.js +35 -0
  26. package/dist/discovery/safety.d.ts +44 -0
  27. package/dist/discovery/safety.js +59 -0
  28. package/dist/discovery/schema-validator.d.ts +36 -0
  29. package/dist/discovery/schema-validator.js +257 -0
  30. package/dist/discovery/source-error.d.ts +47 -0
  31. package/dist/discovery/source-error.js +95 -0
  32. package/dist/discovery/tool-meta.d.ts +41 -0
  33. package/dist/discovery/tool-meta.js +229 -0
  34. package/dist/discovery/virtual-tools.d.ts +20 -0
  35. package/dist/discovery/virtual-tools.js +69 -0
  36. package/dist/http-server.js +2067 -47
  37. package/dist/index.js +3163 -710
  38. package/dist/observer.d.ts +47 -0
  39. package/dist/observer.js +516 -0
  40. package/dist/session-registry.d.ts +57 -0
  41. package/dist/session-registry.js +500 -0
  42. package/dist/sidecar-artifacts.d.ts +49 -0
  43. package/dist/sidecar-artifacts.js +146 -0
  44. package/dist/snapshot-capture.d.ts +3 -0
  45. package/dist/snapshot-capture.js +91 -0
  46. package/dist/tab-group-archive.js +3 -1
  47. package/dist/tab-groups.d.ts +7 -0
  48. package/dist/tab-groups.js +21 -3
  49. package/dist/task-thread-aggregator.d.ts +34 -0
  50. package/dist/task-thread-aggregator.js +480 -0
  51. package/dist/task-thread-canonical.d.ts +142 -0
  52. package/dist/task-thread-canonical.js +116 -0
  53. package/dist/types.d.ts +237 -0
  54. package/dist/window-bindings.d.ts +112 -0
  55. package/dist/window-bindings.js +476 -0
  56. package/extension/background.js +1556 -300
  57. package/extension/icons/icon.svg +9 -0
  58. package/extension/icons/icon128.png +0 -0
  59. package/extension/icons/icon16.png +0 -0
  60. package/extension/icons/icon48.png +0 -0
  61. package/extension/manifest.json +19 -4
  62. package/extension/session-logic.js +2383 -0
  63. package/extension/session-manager.html +299 -0
  64. package/extension/sidepanel.css +5323 -528
  65. package/extension/sidepanel.html +282 -2
  66. package/extension/sidepanel.js +10075 -951
  67. package/extension/window-policy.js +162 -0
  68. package/package.json +10 -7
  69. package/vendor/lifecycle-mcp-adapter.mjs +103 -0
  70. package/vendor/lifecycle-metadata.mjs +252 -0
  71. package/vendor/readiness-report.mjs +742 -0
  72. package/dist/cdp-client.d.ts.map +0 -1
  73. package/dist/cdp-client.js.map +0 -1
  74. package/dist/comet-ai.d.ts.map +0 -1
  75. package/dist/comet-ai.js.map +0 -1
  76. package/dist/http-server.d.ts.map +0 -1
  77. package/dist/http-server.js.map +0 -1
  78. package/dist/index.d.ts.map +0 -1
  79. package/dist/index.js.map +0 -1
  80. package/dist/tab-group-archive.d.ts.map +0 -1
  81. package/dist/tab-group-archive.js.map +0 -1
  82. package/dist/tab-groups.d.ts.map +0 -1
  83. package/dist/tab-groups.js.map +0 -1
  84. package/dist/types.d.ts.map +0 -1
  85. package/dist/types.js.map +0 -1
@@ -0,0 +1,3 @@
1
+ import type { AgentSession, TaskThreadSnapshot, SnapshotReason, TaskThreadStatus } from "./types.js";
2
+ export declare function captureTaskThreadSnapshot(session: AgentSession, reason: SnapshotReason, taskStatus?: TaskThreadStatus): Promise<TaskThreadSnapshot>;
3
+ //# sourceMappingURL=snapshot-capture.d.ts.map
@@ -0,0 +1,91 @@
1
+ // Snapshot Capture — Task Thread state preservation before automated closure (Spec 016, FR-003)
2
+ // Captures all tabs, Sidecar threads, window metadata, and task status.
3
+ // Atomic write: temp file → rename to prevent partial captures.
4
+ // If capture fails, caller MUST NOT proceed with close (fail safe).
5
+ import { writeFileSync, renameSync, mkdirSync } from "fs";
6
+ import { join } from "path";
7
+ import { loadBridgeConfig } from "./bridge-config.js";
8
+ export async function captureTaskThreadSnapshot(session, reason, taskStatus = "abandoned") {
9
+ const config = loadBridgeConfig();
10
+ const tabs = [];
11
+ const sidecarThreads = [];
12
+ let windowMetadata = null;
13
+ // Query tabs in this session's tab group via extension messaging
14
+ try {
15
+ const { tabGroupsClient } = await import("./tab-groups.js");
16
+ const allTabs = await tabGroupsClient.listTabs();
17
+ // Filter to tabs in this session's tab group, or by ownership if no group (extension degradation)
18
+ const sessionTabs = session.tabGroupId !== null
19
+ ? allTabs.filter((t) => t.groupId === session.tabGroupId)
20
+ : allTabs.filter((t) => t.id === session.chromeTabId);
21
+ for (const tab of sessionTabs) {
22
+ tabs.push({
23
+ url: tab.url,
24
+ title: tab.title,
25
+ chromeTabId: tab.id,
26
+ targetId: session.targetId,
27
+ active: tab.active,
28
+ });
29
+ // Check if tab has a Sidecar thread (Perplexity assistant panel)
30
+ if (tab.url?.includes("perplexity.ai")) {
31
+ sidecarThreads.push({
32
+ threadUrl: tab.url,
33
+ parentTabUrl: tab.url,
34
+ lastQuery: null,
35
+ });
36
+ }
37
+ }
38
+ // Capture window metadata
39
+ const groups = await tabGroupsClient.listGroups();
40
+ const sessionGroup = groups.find((g) => g.id === session.tabGroupId);
41
+ if (sessionGroup) {
42
+ windowMetadata = {
43
+ windowId: sessionGroup.windowId,
44
+ x: 0,
45
+ y: -1440,
46
+ width: 2560,
47
+ height: 1440,
48
+ displayIndex: 0,
49
+ };
50
+ }
51
+ }
52
+ catch (extErr) {
53
+ // Extension not available — capture what we can from CDP
54
+ console.warn(`[comet-bridge] Snapshot degraded for ${session.sessionKey}: extension unavailable (${extErr instanceof Error ? extErr.message : extErr})`);
55
+ tabs.push({
56
+ url: "unknown (extension unavailable)",
57
+ title: session.taskThreadId,
58
+ chromeTabId: session.chromeTabId ?? 0,
59
+ targetId: session.targetId,
60
+ active: true,
61
+ });
62
+ }
63
+ const snapshot = {
64
+ sessionKey: session.sessionKey,
65
+ agentId: session.agentId,
66
+ taskThreadId: session.taskThreadId,
67
+ capturedAt: new Date().toISOString(),
68
+ reason,
69
+ taskStatus,
70
+ tabs,
71
+ sidecarThreads,
72
+ windowMetadata,
73
+ tabGroupId: session.tabGroupId,
74
+ tabGroupColor: session.tabGroupColor,
75
+ };
76
+ // Atomic write: temp file → rename (T026)
77
+ const snapshotDir = config.cleanup.snapshotDir;
78
+ mkdirSync(snapshotDir, { recursive: true });
79
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
80
+ const safeAgentId = session.agentId.replace(/[^a-zA-Z0-9_-]/g, "_");
81
+ const safeThreadId = session.taskThreadId.replace(/[^a-zA-Z0-9_-]/g, "_");
82
+ const filename = `${safeAgentId}_${safeThreadId}_${timestamp}.json`;
83
+ const finalPath = join(snapshotDir, filename);
84
+ const tempPath = finalPath + ".tmp";
85
+ // Write to temp file first — if this fails, no partial snapshot exists
86
+ writeFileSync(tempPath, JSON.stringify(snapshot, null, 2));
87
+ // Atomic rename — if this fails, temp file exists but final doesn't
88
+ renameSync(tempPath, finalPath);
89
+ return snapshot;
90
+ }
91
+ //# sourceMappingURL=snapshot-capture.js.map
@@ -11,7 +11,9 @@ let writeQueue = Promise.resolve();
11
11
  function serialized(fn) {
12
12
  const prev = writeQueue;
13
13
  let resolve;
14
- writeQueue = new Promise((r) => { resolve = r; });
14
+ writeQueue = new Promise((r) => {
15
+ resolve = r;
16
+ });
15
17
  return prev.then(fn).finally(() => resolve());
16
18
  }
17
19
  function resolveArchivePaths(archiveDir) {
@@ -15,6 +15,11 @@ export interface TabInfo {
15
15
  url: string;
16
16
  active: boolean;
17
17
  }
18
+ export interface WindowTabInfo {
19
+ tabId: number;
20
+ windowId: number;
21
+ url: string;
22
+ }
18
23
  export interface CreateGroupOptions {
19
24
  tabIds: number[];
20
25
  title?: string;
@@ -68,6 +73,8 @@ export declare class TabGroupsClient {
68
73
  groupId: number;
69
74
  group: TabGroup;
70
75
  }>;
76
+ /** Create a managed browser window locked to the top display fullscreen policy. */
77
+ createTopDisplayFullscreenWindowWithTab(url: string): Promise<WindowTabInfo>;
71
78
  /** Update an existing tab group's title, color, or collapsed state. */
72
79
  updateGroup(options: UpdateGroupOptions): Promise<TabGroup>;
73
80
  /** Move a tab group to a new position. */
@@ -116,8 +116,7 @@ export class TabGroupsClient {
116
116
  returnByValue: true,
117
117
  });
118
118
  if (result.exceptionDetails) {
119
- const msg = result.exceptionDetails.exception?.description ||
120
- result.exceptionDetails.text;
119
+ const msg = result.exceptionDetails.exception?.description || result.exceptionDetails.text;
121
120
  throw new Error(`Extension eval error: ${msg}`);
122
121
  }
123
122
  return result.result.value;
@@ -163,7 +162,10 @@ export class TabGroupsClient {
163
162
  if (Object.keys(updateProps).length > 0) {
164
163
  await chrome.tabGroups.update(groupId, updateProps);
165
164
  }
166
- const g = await chrome.tabGroups.get(groupId);
165
+ const enforced = await self.CometWindowPolicy.ensureOneGroupPerWindow(groupId, {
166
+ markChangedWindowManaged: true
167
+ });
168
+ const g = enforced?.group || (await chrome.tabGroups.get(groupId));
167
169
  return {
168
170
  groupId: g.id,
169
171
  group: {
@@ -174,6 +176,22 @@ export class TabGroupsClient {
174
176
  })()
175
177
  `);
176
178
  }
179
+ /** Create a managed browser window locked to the top display fullscreen policy. */
180
+ async createTopDisplayFullscreenWindowWithTab(url) {
181
+ return await this.evaluate(`
182
+ (async () => {
183
+ const win = await self.CometWindowPolicy.createTopDisplayFullscreenWindow({
184
+ url: ${JSON.stringify(url)}
185
+ });
186
+ const tab = win.tabs?.[0] || (await chrome.tabs.query({ windowId: win.id }))[0];
187
+ return {
188
+ tabId: tab.id,
189
+ windowId: win.id,
190
+ url: tab.url || tab.pendingUrl || ${JSON.stringify(url)}
191
+ };
192
+ })()
193
+ `);
194
+ }
177
195
  /** Update an existing tab group's title, color, or collapsed state. */
178
196
  async updateGroup(options) {
179
197
  const props = [];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Task Thread Aggregator — Phase A
3
+ *
4
+ * Reads all 5 local layers (lifecycle JSONL, session manifest, archive store,
5
+ * snapshots, alert log) and synthesises a CanonicalTaskThread for each known
6
+ * taskThreadId. Exposes the TaskThreadProvider interface so Phase B can swap
7
+ * the implementation for an equa-taskthreads core API client without touching
8
+ * any consumers (FR-040).
9
+ *
10
+ * Spec: specs/041-task-thread-sync/spec.md
11
+ * Plan: specs/041-task-thread-sync/plan.md §Layer Aggregator
12
+ */
13
+ import { CanonicalStatus, CanonicalTaskThread } from "./task-thread-canonical.js";
14
+ /**
15
+ * The single interface all HTTP route handlers and extension-facing code depends
16
+ * on. Phase B replaces the LocalTaskThreadAggregator with a CoreAPITaskThreadProvider
17
+ * without changing any consumer code.
18
+ */
19
+ export interface TaskThreadProvider {
20
+ listAll(): Promise<CanonicalTaskThread[]>;
21
+ get(id: string): Promise<CanonicalTaskThread | null>;
22
+ executeTransition(id: string, action: string, reason?: string): Promise<{
23
+ newStatus: CanonicalStatus;
24
+ }>;
25
+ }
26
+ export declare class LocalTaskThreadAggregator implements TaskThreadProvider {
27
+ listAll(): Promise<CanonicalTaskThread[]>;
28
+ get(id: string): Promise<CanonicalTaskThread | null>;
29
+ executeTransition(id: string, action: string, reason?: string): Promise<{
30
+ newStatus: CanonicalStatus;
31
+ }>;
32
+ }
33
+ export declare const aggregator: TaskThreadProvider;
34
+ //# sourceMappingURL=task-thread-aggregator.d.ts.map