@nimbalyst/extension-sdk 0.5.0 → 0.6.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/__tests__/fileDirectoryTree.test.js +34 -0
  3. package/dist/__tests__/gitOperationLog.test.d.ts +2 -0
  4. package/dist/__tests__/gitOperationLog.test.d.ts.map +1 -0
  5. package/dist/__tests__/gitOperationLog.test.js +51 -0
  6. package/dist/agents/AgentProtocol.d.ts +8 -0
  7. package/dist/agents/AgentProtocol.d.ts.map +1 -1
  8. package/dist/agents/AgentProtocolHost.d.ts +1 -1
  9. package/dist/agents/AgentProtocolHost.d.ts.map +1 -1
  10. package/dist/createReadOnlyHost.d.ts +11 -1
  11. package/dist/createReadOnlyHost.d.ts.map +1 -1
  12. package/dist/createReadOnlyHost.js +3 -0
  13. package/dist/externalsPlugin.d.ts.map +1 -1
  14. package/dist/externalsPlugin.js +1 -5
  15. package/dist/fileDirectoryTree.d.ts +9 -2
  16. package/dist/fileDirectoryTree.d.ts.map +1 -1
  17. package/dist/fileDirectoryTree.js +82 -14
  18. package/dist/gitOperationLog.d.ts +104 -0
  19. package/dist/gitOperationLog.d.ts.map +1 -0
  20. package/dist/gitOperationLog.js +88 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -0
  24. package/dist/types/collab.d.ts +31 -2
  25. package/dist/types/collab.d.ts.map +1 -1
  26. package/dist/types/comments.d.ts +104 -0
  27. package/dist/types/comments.d.ts.map +1 -0
  28. package/dist/types/comments.js +2 -0
  29. package/dist/types/editor.d.ts +87 -0
  30. package/dist/types/editor.d.ts.map +1 -1
  31. package/dist/types/extension.d.ts +16 -0
  32. package/dist/types/extension.d.ts.map +1 -1
  33. package/dist/types/index.d.ts +1 -0
  34. package/dist/types/index.d.ts.map +1 -1
  35. package/dist/types/index.js +1 -0
  36. package/dist/types/panel.d.ts +21 -0
  37. package/dist/types/panel.d.ts.map +1 -1
  38. package/package.json +14 -2
package/CHANGELOG.md CHANGED
@@ -8,6 +8,7 @@ The SDK is versioned independently of the Nimbalyst app. Each release declares i
8
8
 
9
9
  | SDK version | Minimum Nimbalyst app version |
10
10
  | --- | --- |
11
+ | 0.6.0 | 0.78.0 |
11
12
  | 0.5.0 | 0.70.0 |
12
13
  | 0.4.0 | 0.70.0 |
13
14
  | 0.3.0 | 0.70.0 |
@@ -19,6 +20,29 @@ The SDK is versioned independently of the Nimbalyst app. Each release declares i
19
20
 
20
21
  ## [Unreleased]
21
22
 
23
+ ## [0.6.0] - 2026-09-14
24
+
25
+ Requires Nimbalyst 0.78.0, available on the alpha channel at publication, for the complete host API including native screenshots.
26
+
27
+ ### Added
28
+
29
+ - `CollaborationCommentsService`, `CommentAnchor`, and codec-level `commentAnchors` let collaborative editors mount the platform comment experience and resolve structured anchors both live and headlessly.
30
+ - `host.registerViewport()` and `EditorViewport` let an editor expose proportional scroll position to hosts that carry the reader's place between related documents; `createReadOnlyHost()` can receive those registrations.
31
+ - `contributions.customEditors[].collaboration.documentType` lets a host identify a collaborative document type from the manifest before its extension bundle and codec are loaded.
32
+ - `screenshotService` exposes host-provided element and file screenshots, including unopened documents.
33
+ - `PanelHost.getWorkspaceFolders()` and `getPrimaryFolderPath()` expose multiple workspace roots; file-tree helpers accept those roots.
34
+ - `EditorHost.getAssetUrl()` and the `assetUrls` capability let media editors stream local files through a host-provided URL.
35
+ - The `agents`, `types/editor`, and `git-operation-log` entry points expose agent contracts, editor types, and Git operation selectors.
36
+ - `ProtocolSession.appliedModel` and `deliveredMcpServerCount` report the model and MCP servers actually used by an agent.
37
+
38
+ ### Changed
39
+
40
+ - `CollabCodec` documents file-form fallback for headless agent edits when no structured patch pair exists, while recommending structured edits for minimal concurrent deltas.
41
+
42
+ ### Fixed
43
+
44
+ - Agent host declarations use a Node-compatible relative import for consumers using Node16 or NodeNext module resolution.
45
+
22
46
  ## [0.5.0]
23
47
 
24
48
  Still runs on Nimbalyst 0.70.0: a host that declares no capabilities is treated as fully capable, so an extension written against this release keeps working on older desktop builds.
@@ -56,4 +56,38 @@ describe('buildFileDirectoryTree', () => {
56
56
  expect(tree.fileCount).toBe(1);
57
57
  expect(tree.files).toHaveLength(1);
58
58
  });
59
+ describe('multi-root workspaces', () => {
60
+ const ROOTS = ['/repo', '/other/collab'];
61
+ it('leaves primary-root paths bare and names the attached root', () => {
62
+ expect(getWorkspaceRelativeFilePath('/repo/src/index.ts', ROOTS)).toBe('src/index.ts');
63
+ expect(getWorkspaceRelativeFilePath('/other/collab/src/index.ts', ROOTS))
64
+ .toBe('collab/src/index.ts');
65
+ });
66
+ it('keeps same-named files in different roots in separate groups', () => {
67
+ const tree = buildTree(['/repo/src/index.ts', '/other/collab/src/index.ts'], ROOTS);
68
+ // `collab/src` is the collapsed single-child chain; the point is that the
69
+ // two `src` directories do not merge into one group.
70
+ expect(getFileDirectoryPaths(tree)).toEqual(['src', 'collab/src']);
71
+ expect(tree.subdirectories.get('src')?.fileCount).toBe(1);
72
+ expect(tree.subdirectories.get('collab')?.fileCount).toBe(1);
73
+ });
74
+ it('prefers the deepest root for a root nested inside another root', () => {
75
+ expect(getWorkspaceRelativeFilePath('/repo/vendor/lib/a.ts', ['/repo', '/repo/vendor/lib']))
76
+ .toBe('lib/a.ts');
77
+ });
78
+ it('falls back to the absolute path for a file in no root', () => {
79
+ expect(getWorkspaceRelativeFilePath('/elsewhere/a.ts', ROOTS)).toBe('/elsewhere/a.ts');
80
+ });
81
+ it('disambiguates attached roots that share a basename', () => {
82
+ // `/app/api` and `/infra/api` are an ordinary pair, and a bare basename
83
+ // would collapse both repos into one `api` group in the tree.
84
+ const roots = ['/repo', '/app/api', '/infra/api'];
85
+ expect(getWorkspaceRelativeFilePath('/app/api/src/a.ts', roots)).toBe('app/api/src/a.ts');
86
+ expect(getWorkspaceRelativeFilePath('/infra/api/src/a.ts', roots)).toBe('infra/api/src/a.ts');
87
+ });
88
+ it('matches single-root behaviour when given one root', () => {
89
+ expect(getWorkspaceRelativeFilePath('/repo/src/index.ts', ['/repo']))
90
+ .toBe(getWorkspaceRelativeFilePath('/repo/src/index.ts', '/repo'));
91
+ });
92
+ });
59
93
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gitOperationLog.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitOperationLog.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/gitOperationLog.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { mergeGitOperationEntries, normalizeGitOperationEntry, selectLatestRunningGitOperation, selectLatestTerminalGitOperation, selectRunningGitOperations, } from '../gitOperationLog';
3
+ function entry(overrides) {
4
+ return {
5
+ timestamp: 1000,
6
+ updatedAt: 1000,
7
+ command: 'git status',
8
+ executable: 'git',
9
+ args: ['status'],
10
+ cwd: '/repo',
11
+ status: 'running',
12
+ output: '',
13
+ stdout: '',
14
+ stderr: '',
15
+ ...overrides,
16
+ };
17
+ }
18
+ describe('git operation log selectors', () => {
19
+ it('keeps a live terminal event that landed while hydration was in flight', () => {
20
+ // The `git:operation-log:get` response is older than upserts that arrived
21
+ // after it was requested. Applying it blindly rewinds a finished push back
22
+ // to running, which is exactly the stale indicator this ordering prevents.
23
+ const hydrated = [entry({ id: 'a', status: 'running', updatedAt: 1000 })];
24
+ const live = [entry({ id: 'a', status: 'success', updatedAt: 2000 })];
25
+ expect(mergeGitOperationEntries(hydrated, live)[0].status).toBe('success');
26
+ expect(mergeGitOperationEntries(live, hydrated)[0].status).toBe('success');
27
+ });
28
+ it('names the newest running command and counts the rest', () => {
29
+ const entries = [
30
+ entry({ id: 'push', timestamp: 1000, command: 'git push' }),
31
+ entry({ id: 'fetch', timestamp: 3000, command: 'git fetch origin' }),
32
+ entry({ id: 'done', timestamp: 2000, status: 'success', updatedAt: 5000 }),
33
+ ];
34
+ expect(selectLatestRunningGitOperation(entries)?.id).toBe('fetch');
35
+ expect(selectRunningGitOperations(entries).map((e) => e.id)).toEqual(['push', 'fetch']);
36
+ expect(selectLatestTerminalGitOperation(entries)?.id).toBe('done');
37
+ });
38
+ it('reads a journal written before source metadata existed as app-owned direct git', () => {
39
+ const legacy = entry({ id: 'legacy' });
40
+ delete legacy.source;
41
+ delete legacy.executor;
42
+ const normalized = normalizeGitOperationEntry(legacy);
43
+ expect(normalized.source).toBe('nimbalyst');
44
+ expect(normalized.executor).toBe('git');
45
+ });
46
+ it('does not let an agent entry inherit the app-owned default', () => {
47
+ const agent = entry({ id: 'agent', source: 'agent', executor: 'shell', sessionId: 's1' });
48
+ expect(normalizeGitOperationEntry(agent).source).toBe('agent');
49
+ expect(normalizeGitOperationEntry(agent).executor).toBe('shell');
50
+ });
51
+ });
@@ -129,6 +129,14 @@ export interface ProtocolSession {
129
129
  platform: string;
130
130
  /** Platform-specific session data (for internal use) */
131
131
  raw?: RawProtocolSession;
132
+ /** Number of host-supplied MCP servers this protocol actually delivered. */
133
+ deliveredMcpServerCount?: number;
134
+ /**
135
+ * Model the agent is actually running, when the protocol can observe it.
136
+ * Absent means "the protocol has no say"; the host then reports the model it
137
+ * asked for. Never report a requested model a protocol knows was not applied.
138
+ */
139
+ appliedModel?: string;
132
140
  }
133
141
  /**
134
142
  * Event types emitted during message streaming
@@ -1 +1 @@
1
- {"version":3,"file":"AgentProtocol.d.ts","sourceRoot":"","sources":["../../src/agents/AgentProtocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentProtocol.d.ts","sourceRoot":"","sources":["../../src/agents/AgentProtocol.ts"],"names":[],"mappings":"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"}
@@ -39,7 +39,7 @@
39
39
  * See `docs/EXTENSION_ARCHITECTURE.md` and the Phase 4 SDK design doc
40
40
  * (Section 4.3) for the full host contract.
41
41
  */
42
- import type { MCPServerConfig } from './index';
42
+ import type { MCPServerConfig } from './index.js';
43
43
  /**
44
44
  * Permission posture the host has set for the current turn.
45
45
  *
@@ -1 +1 @@
1
- {"version":3,"file":"AgentProtocolHost.d.ts","sourceRoot":"","sources":["../../src/agents/AgentProtocolHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAGhC,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAIjC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wDAAwD;IACxD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAElC,yDAAyD;IACzD,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAI/C;;;;;;;;;;;OAWG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,GAAG,QAAQ,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;;;OAQG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE3D;;;;;;;OAOG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAErD;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D"}
1
+ {"version":3,"file":"AgentProtocolHost.d.ts","sourceRoot":"","sources":["../../src/agents/AgentProtocolHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAGhC,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAIjC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wDAAwD;IACxD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAElC,yDAAyD;IACzD,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAI/C;;;;;;;;;;;OAWG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,GAAG,QAAQ,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;;;OAQG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE3D;;;;;;;OAOG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAErD;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D"}
@@ -21,7 +21,7 @@
21
21
  * host.setTheme('light');
22
22
  * ```
23
23
  */
24
- import type { EditorHost } from './types/editor.js';
24
+ import type { EditorHost, EditorViewport } from './types/editor.js';
25
25
  export interface ReadOnlyHostOptions {
26
26
  /** Current theme name (e.g., 'dark', 'light') */
27
27
  theme: string;
@@ -34,6 +34,16 @@ export interface ReadOnlyHostOptions {
34
34
  * When true, extensions may suppress chrome that doesn't fit inline contexts.
35
35
  */
36
36
  embedded?: boolean;
37
+ /**
38
+ * Receives the editor's scroll viewport when it publishes one.
39
+ *
40
+ * Supplied only by a surface that shows several documents in sequence and
41
+ * wants to carry the reader's place between them -- the feedback detail
42
+ * popover comparing design alternatives. Absent, `registerViewport` is
43
+ * absent too, so an extension that checks before registering gets a straight
44
+ * answer rather than a silent no-op.
45
+ */
46
+ onViewportRegistered?(viewport: EditorViewport | null): void;
37
47
  }
38
48
  export interface ReadOnlyHost extends EditorHost {
39
49
  /** Update the theme (call from viewer chrome's theme toggle) */
@@ -1 +1 @@
1
- {"version":3,"file":"createReadOnlyHost.d.ts","sourceRoot":"","sources":["../src/createReadOnlyHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,mBAAmB,CAAC;AAEnF,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IAEjB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,GACxB,YAAY,CA8Dd"}
1
+ {"version":3,"file":"createReadOnlyHost.d.ts","sourceRoot":"","sources":["../src/createReadOnlyHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAEV,UAAU,EAEV,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IAEjB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,GACxB,YAAY,CAiEd"}
@@ -60,6 +60,9 @@ export function createReadOnlyHost(content, opts) {
60
60
  openHistory: () => { },
61
61
  registerMenuItems: (_items) => { },
62
62
  registerEditorAPI: () => { },
63
+ ...(opts.onViewportRegistered
64
+ ? { registerViewport: opts.onViewportRegistered }
65
+ : {}),
63
66
  setEditorContext: (_context) => { },
64
67
  setEditorContextItems: () => { },
65
68
  // -- Storage (in-memory, non-persistent) --
@@ -1 +1 @@
1
- {"version":3,"file":"externalsPlugin.d.ts","sourceRoot":"","sources":["../src/externalsPlugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAqDnC;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAyDjD"}
1
+ {"version":3,"file":"externalsPlugin.d.ts","sourceRoot":"","sources":["../src/externalsPlugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAoDnC;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAyDjD"}
@@ -45,7 +45,6 @@ const EXTERNALS_MAP = {
45
45
  '@nimbalyst/editor-context': '@nimbalyst/editor-context',
46
46
  '@nimbalyst/runtime/ui/icons/MaterialSymbol': '@nimbalyst/runtime/ui/icons/MaterialSymbol',
47
47
  '@nimbalyst/screenshot-service': '@nimbalyst/screenshot-service',
48
- '@nimbalyst/datamodel-platform-service': '@nimbalyst/datamodel-platform-service',
49
48
  // Shared libraries
50
49
  'pdfjs-dist': 'pdfjs-dist',
51
50
  virtua: 'virtua',
@@ -230,7 +229,7 @@ function generateCommonExports(externalKey) {
230
229
  }
231
230
  else if (externalKey === '@nimbalyst/runtime') {
232
231
  exports = [
233
- 'MaterialSymbol', 'useDocumentPath', 'useEditorLifecycle',
232
+ 'MaterialSymbol', 'useDocumentPath', 'useEditorLifecycle', 'screenshotService',
234
233
  'useCollaborativeEditor', 'COLLAB_INIT_ORIGIN',
235
234
  'setTranscriptMarkdownContributions', 'clearTranscriptMarkdownContributions',
236
235
  'MarkdownEditor', 'MonacoEditor', 'MonacoCodeEditor',
@@ -241,9 +240,6 @@ function generateCommonExports(externalKey) {
241
240
  else if (externalKey === '@nimbalyst/screenshot-service') {
242
241
  exports = ['screenshotService'];
243
242
  }
244
- else if (externalKey === '@nimbalyst/datamodel-platform-service') {
245
- exports = ['DataModelPlatformServiceImpl', 'getInstance'];
246
- }
247
243
  else if (externalKey === 'pdfjs-dist') {
248
244
  exports = ['getDocument', 'GlobalWorkerOptions', 'version'];
249
245
  }
@@ -11,9 +11,16 @@ export declare function getFilePathBasename(filePath: string): string;
11
11
  /**
12
12
  * Return a forward-slash path relative to the workspace when the file is inside it.
13
13
  * Windows drive paths are compared case-insensitively to match filesystem behavior.
14
+ *
15
+ * A multi-root workspace passes every root, primary first. The primary root
16
+ * still yields a bare relative path, so a single-folder workspace is unchanged;
17
+ * a file in an attached root is prefixed with that root's heading, which is
18
+ * what groups it under its own heading in the directory tree instead of
19
+ * spelling out an absolute path. Deepest matching root wins, so a root checked
20
+ * out inside another root keeps its own prefix.
14
21
  */
15
- export declare function getWorkspaceRelativeFilePath(filePath: string, workspacePath?: string): string;
22
+ export declare function getWorkspaceRelativeFilePath(filePath: string, workspacePath?: string | string[]): string;
16
23
  /** Build a collapsed directory tree for arbitrary file records. */
17
- export declare function buildFileDirectoryTree<T>(files: T[], getFilePath: (file: T) => string, workspacePath?: string): FileDirectoryNode<T>;
24
+ export declare function buildFileDirectoryTree<T>(files: T[], getFilePath: (file: T) => string, workspacePath?: string | string[]): FileDirectoryNode<T>;
18
25
  export declare function getFileDirectoryPaths<T>(node: FileDirectoryNode<T>): string[];
19
26
  //# sourceMappingURL=fileDirectoryTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileDirectoryTree.d.ts","sourceRoot":"","sources":["../src/fileDirectoryTree.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB7F;AA6BD,mEAAmE;AACnE,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EACV,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAChC,aAAa,CAAC,EAAE,MAAM,GACrB,iBAAiB,CAAC,CAAC,CAAC,CAwCtB;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAM7E"}
1
+ {"version":3,"file":"fileDirectoryTree.d.ts","sourceRoot":"","sources":["../src/fileDirectoryTree.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG5D;AAwDD;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,MAAM,CAwBR;AA6BD,mEAAmE;AACnE,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EACV,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAChC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,iBAAiB,CAAC,CAAC,CAAC,CAwCtB;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAM7E"}
@@ -6,27 +6,95 @@ export function getFilePathBasename(filePath) {
6
6
  const normalizedPath = normalizeFilePath(filePath).replace(/\/+$/, '');
7
7
  return normalizedPath.slice(normalizedPath.lastIndexOf('/') + 1);
8
8
  }
9
+ /** Relative to one root, or null when the file is not inside it. */
10
+ function relativeToRoot(normalizedFile, rootPath) {
11
+ const normalizedRoot = normalizeFilePath(rootPath).replace(/\/$/, '');
12
+ if (!normalizedRoot)
13
+ return null;
14
+ const windowsDrivePath = /^[A-Za-z]:\//.test(normalizedFile)
15
+ && /^[A-Za-z]:\//.test(normalizedRoot);
16
+ const comparableFile = windowsDrivePath ? normalizedFile.toLowerCase() : normalizedFile;
17
+ const comparableRoot = windowsDrivePath ? normalizedRoot.toLowerCase() : normalizedRoot;
18
+ if (comparableFile === comparableRoot)
19
+ return '';
20
+ if (comparableFile.startsWith(`${comparableRoot}/`)) {
21
+ return normalizedFile.slice(normalizedRoot.length + 1);
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Heading for each attached root, unique within the root list.
27
+ *
28
+ * Two roots sharing a basename is ordinary -- `app/api` and `infra/api`, or two
29
+ * checkouts of the same repo -- and a bare basename would collapse both into
30
+ * one directory group. Colliding roots grow parent segments until they differ;
31
+ * everything else stays the bare folder name. The primary root has no heading,
32
+ * so it never competes.
33
+ */
34
+ function attachedRootLabels(roots) {
35
+ const segmentsPerRoot = roots.map((rootPath) => normalizeFilePath(rootPath).replace(/\/+$/, '').split('/').filter(Boolean));
36
+ const labels = roots.map((_, index) => segmentsPerRoot[index].slice(-1).join('/'));
37
+ // Grow every still-colliding label by one more parent segment per pass. A
38
+ // root can only run out of segments once it is the filesystem root, at which
39
+ // point its label is already unique.
40
+ for (let depth = 2; depth <= 16; depth++) {
41
+ const counts = new Map();
42
+ for (let index = 1; index < labels.length; index++) {
43
+ counts.set(labels[index], (counts.get(labels[index]) ?? 0) + 1);
44
+ }
45
+ if ([...counts.values()].every((count) => count < 2))
46
+ break;
47
+ let grew = false;
48
+ for (let index = 1; index < labels.length; index++) {
49
+ if ((counts.get(labels[index]) ?? 0) < 2)
50
+ continue;
51
+ if (segmentsPerRoot[index].length < depth)
52
+ continue;
53
+ labels[index] = segmentsPerRoot[index].slice(-depth).join('/');
54
+ grew = true;
55
+ }
56
+ if (!grew)
57
+ break;
58
+ }
59
+ return labels;
60
+ }
9
61
  /**
10
62
  * Return a forward-slash path relative to the workspace when the file is inside it.
11
63
  * Windows drive paths are compared case-insensitively to match filesystem behavior.
64
+ *
65
+ * A multi-root workspace passes every root, primary first. The primary root
66
+ * still yields a bare relative path, so a single-folder workspace is unchanged;
67
+ * a file in an attached root is prefixed with that root's heading, which is
68
+ * what groups it under its own heading in the directory tree instead of
69
+ * spelling out an absolute path. Deepest matching root wins, so a root checked
70
+ * out inside another root keeps its own prefix.
12
71
  */
13
72
  export function getWorkspaceRelativeFilePath(filePath, workspacePath) {
14
73
  const normalizedFile = normalizeFilePath(filePath);
15
- if (!workspacePath)
74
+ const roots = typeof workspacePath === 'string' ? [workspacePath] : workspacePath;
75
+ if (!roots || roots.length === 0)
16
76
  return normalizedFile;
17
- const normalizedWorkspace = normalizeFilePath(workspacePath).replace(/\/$/, '');
18
- const windowsDrivePath = /^[A-Za-z]:\//.test(normalizedFile)
19
- && /^[A-Za-z]:\//.test(normalizedWorkspace);
20
- const comparableFile = windowsDrivePath ? normalizedFile.toLowerCase() : normalizedFile;
21
- const comparableWorkspace = windowsDrivePath
22
- ? normalizedWorkspace.toLowerCase()
23
- : normalizedWorkspace;
24
- if (comparableFile === comparableWorkspace)
25
- return '';
26
- if (comparableFile.startsWith(`${comparableWorkspace}/`)) {
27
- return normalizedFile.slice(normalizedWorkspace.length + 1);
28
- }
29
- return normalizedFile;
77
+ let bestIndex = -1;
78
+ let bestRelative = null;
79
+ let bestRootLength = -1;
80
+ roots.forEach((rootPath, index) => {
81
+ const relative = relativeToRoot(normalizedFile, rootPath);
82
+ if (relative === null)
83
+ return;
84
+ const rootLength = normalizeFilePath(rootPath).replace(/\/$/, '').length;
85
+ if (rootLength <= bestRootLength)
86
+ return;
87
+ bestIndex = index;
88
+ bestRelative = relative;
89
+ bestRootLength = rootLength;
90
+ });
91
+ if (bestRelative === null)
92
+ return normalizedFile;
93
+ if (bestIndex === 0)
94
+ return bestRelative;
95
+ // Attached root: name it, so two files called `src/index.ts` in two repos do
96
+ // not collapse into one directory group.
97
+ return `${attachedRootLabels(roots)[bestIndex]}/${bestRelative}`;
30
98
  }
31
99
  function collapseDirectoryTree(node) {
32
100
  node.subdirectories.forEach((subdirectory, key) => {
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Wire contract and pure selectors for the host's Git operation journal.
3
+ *
4
+ * The journal lives in the Electron main process and is published over two host
5
+ * channels: `git:operation-log:get` (hydration) and `git:operation-log-changed`
6
+ * (live upsert/clear). Both the Git extension's Output tab and Nimbalyst's own
7
+ * menu-bar indicator project the same journal, so the merge and "what is running
8
+ * right now" rules have to agree exactly -- two surfaces disagreeing about
9
+ * whether a push is still in flight is the bug this module exists to prevent.
10
+ *
11
+ * Everything here is pure: no React, no IPC, no host runtime.
12
+ */
13
+ /** Terminal states are everything except `running`. */
14
+ export type GitOperationStatus = 'running' | 'success' | 'error' | 'interrupted';
15
+ /** Who started the command. Absent on journals written before agent activity existed. */
16
+ export type GitOperationSource = 'nimbalyst' | 'agent';
17
+ /**
18
+ * How the command reached Git. `git` is an app-owned direct invocation with a
19
+ * meaningful `args` array; `shell` is an observed command line whose Git segment
20
+ * we detected but did not spawn ourselves.
21
+ */
22
+ export type GitOperationExecutor = 'git' | 'shell';
23
+ /** An entry exactly as it crosses the IPC boundary (timestamps are epoch ms). */
24
+ export interface GitOperationLogWireEntry {
25
+ id: string;
26
+ timestamp: number;
27
+ updatedAt: number;
28
+ /** Redacted, display-ready command text. */
29
+ command: string;
30
+ executable: 'git';
31
+ args: string[];
32
+ cwd: string;
33
+ status: GitOperationStatus;
34
+ output: string;
35
+ stdout: string;
36
+ stderr: string;
37
+ error?: string;
38
+ exitCode?: number;
39
+ durationMs?: number;
40
+ source?: GitOperationSource;
41
+ executor?: GitOperationExecutor;
42
+ sessionId?: string;
43
+ provider?: string;
44
+ providerToolCallId?: string;
45
+ }
46
+ export type GitOperationLogEvent = {
47
+ workspacePath: string;
48
+ type: 'upsert';
49
+ entry: GitOperationLogWireEntry;
50
+ } | {
51
+ workspacePath: string;
52
+ type: 'clear';
53
+ };
54
+ /**
55
+ * Window CustomEvent the host dispatches when the user asks to see Git activity
56
+ * detail (for example from the menu-bar indicator's running-command row).
57
+ *
58
+ * The Git panel owns which tab is showing, and that state is private to the
59
+ * extension bundle. Rather than let the host reach into it, the host states the
60
+ * intent and the panel decides how to honour it. `detail.workspacePath` lets a
61
+ * panel bound to a different workspace ignore the request.
62
+ */
63
+ export declare const GIT_SHOW_OUTPUT_REQUEST_EVENT = "nimbalyst:git-show-output";
64
+ export interface GitShowOutputRequestDetail {
65
+ workspacePath: string;
66
+ }
67
+ /** The minimum shape the selectors below need. */
68
+ interface MergeableEntry {
69
+ id: string;
70
+ timestamp: number | Date;
71
+ updatedAt: number;
72
+ status: GitOperationStatus;
73
+ }
74
+ /**
75
+ * Fill in metadata that predates the field. A journal written before agent
76
+ * activity existed only ever recorded app-owned direct `git` invocations, so
77
+ * that is what an absent `source`/`executor` means -- resolved here at the
78
+ * projection boundary rather than by rewriting the persisted journal.
79
+ */
80
+ export declare function normalizeGitOperationEntry(entry: GitOperationLogWireEntry): GitOperationLogWireEntry & {
81
+ source: GitOperationSource;
82
+ executor: GitOperationExecutor;
83
+ };
84
+ /**
85
+ * Fold incoming entries into the current list, newest write per id wins.
86
+ *
87
+ * `updatedAt` is the tiebreak rather than arrival order because hydration and
88
+ * the live subscription race: a `git:operation-log:get` response can land after
89
+ * upserts it predates, and applying it blindly would rewind a finished
90
+ * operation back to `running`.
91
+ */
92
+ export declare function mergeGitOperationEntries<T extends MergeableEntry>(current: T[], incoming: T[]): T[];
93
+ /** Every entry still in flight, oldest first. */
94
+ export declare function selectRunningGitOperations<T extends MergeableEntry>(entries: T[]): T[];
95
+ /**
96
+ * The entry a single-line indicator should name. Newest start wins: when an
97
+ * agent kicks off a fetch while a push is already running, the thing the user
98
+ * just caused is the more informative label.
99
+ */
100
+ export declare function selectLatestRunningGitOperation<T extends MergeableEntry>(entries: T[]): T | undefined;
101
+ /** The most recently updated entry that has already settled, if any. */
102
+ export declare function selectLatestTerminalGitOperation<T extends MergeableEntry>(entries: T[]): T | undefined;
103
+ export {};
104
+ //# sourceMappingURL=gitOperationLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitOperationLog.d.ts","sourceRoot":"","sources":["../src/gitOperationLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uDAAuD;AACvD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEjF,yFAAyF;AACzF,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,OAAO,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnD,iFAAiF;AACjF,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,wBAAwB,CAAA;CAAE,GAC1E;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7C;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AAEzE,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,kDAAkD;AAClD,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAMD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,wBAAwB,GAC9B,wBAAwB,GAAG;IAC5B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,oBAAoB,CAAC;CAChC,CAMA;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,cAAc,EAC/D,OAAO,EAAE,CAAC,EAAE,EACZ,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE,CAWL;AAED,iDAAiD;AACjD,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,CAAC,SAAS,cAAc,EACtE,OAAO,EAAE,CAAC,EAAE,GACX,CAAC,GAAG,SAAS,CASf;AAED,wEAAwE;AACxE,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,cAAc,EACvE,OAAO,EAAE,CAAC,EAAE,GACX,CAAC,GAAG,SAAS,CASf"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Wire contract and pure selectors for the host's Git operation journal.
3
+ *
4
+ * The journal lives in the Electron main process and is published over two host
5
+ * channels: `git:operation-log:get` (hydration) and `git:operation-log-changed`
6
+ * (live upsert/clear). Both the Git extension's Output tab and Nimbalyst's own
7
+ * menu-bar indicator project the same journal, so the merge and "what is running
8
+ * right now" rules have to agree exactly -- two surfaces disagreeing about
9
+ * whether a push is still in flight is the bug this module exists to prevent.
10
+ *
11
+ * Everything here is pure: no React, no IPC, no host runtime.
12
+ */
13
+ /**
14
+ * Window CustomEvent the host dispatches when the user asks to see Git activity
15
+ * detail (for example from the menu-bar indicator's running-command row).
16
+ *
17
+ * The Git panel owns which tab is showing, and that state is private to the
18
+ * extension bundle. Rather than let the host reach into it, the host states the
19
+ * intent and the panel decides how to honour it. `detail.workspacePath` lets a
20
+ * panel bound to a different workspace ignore the request.
21
+ */
22
+ export const GIT_SHOW_OUTPUT_REQUEST_EVENT = 'nimbalyst:git-show-output';
23
+ function toMillis(timestamp) {
24
+ return typeof timestamp === 'number' ? timestamp : timestamp.getTime();
25
+ }
26
+ /**
27
+ * Fill in metadata that predates the field. A journal written before agent
28
+ * activity existed only ever recorded app-owned direct `git` invocations, so
29
+ * that is what an absent `source`/`executor` means -- resolved here at the
30
+ * projection boundary rather than by rewriting the persisted journal.
31
+ */
32
+ export function normalizeGitOperationEntry(entry) {
33
+ return {
34
+ ...entry,
35
+ source: entry.source ?? 'nimbalyst',
36
+ executor: entry.executor ?? 'git',
37
+ };
38
+ }
39
+ /**
40
+ * Fold incoming entries into the current list, newest write per id wins.
41
+ *
42
+ * `updatedAt` is the tiebreak rather than arrival order because hydration and
43
+ * the live subscription race: a `git:operation-log:get` response can land after
44
+ * upserts it predates, and applying it blindly would rewind a finished
45
+ * operation back to `running`.
46
+ */
47
+ export function mergeGitOperationEntries(current, incoming) {
48
+ const byId = new Map(current.map((entry) => [entry.id, entry]));
49
+ for (const entry of incoming) {
50
+ const existing = byId.get(entry.id);
51
+ if (!existing || entry.updatedAt >= existing.updatedAt) {
52
+ byId.set(entry.id, entry);
53
+ }
54
+ }
55
+ return Array.from(byId.values()).sort((a, b) => toMillis(a.timestamp) - toMillis(b.timestamp));
56
+ }
57
+ /** Every entry still in flight, oldest first. */
58
+ export function selectRunningGitOperations(entries) {
59
+ return entries.filter((entry) => entry.status === 'running');
60
+ }
61
+ /**
62
+ * The entry a single-line indicator should name. Newest start wins: when an
63
+ * agent kicks off a fetch while a push is already running, the thing the user
64
+ * just caused is the more informative label.
65
+ */
66
+ export function selectLatestRunningGitOperation(entries) {
67
+ let latest;
68
+ for (const entry of entries) {
69
+ if (entry.status !== 'running')
70
+ continue;
71
+ if (!latest || toMillis(entry.timestamp) >= toMillis(latest.timestamp)) {
72
+ latest = entry;
73
+ }
74
+ }
75
+ return latest;
76
+ }
77
+ /** The most recently updated entry that has already settled, if any. */
78
+ export function selectLatestTerminalGitOperation(entries) {
79
+ let latest;
80
+ for (const entry of entries) {
81
+ if (entry.status === 'running')
82
+ continue;
83
+ if (!latest || entry.updatedAt >= latest.updatedAt) {
84
+ latest = entry;
85
+ }
86
+ }
87
+ return latest;
88
+ }
package/dist/index.d.ts CHANGED
@@ -38,4 +38,5 @@ export { buildFileDirectoryTree, getFileDirectoryPaths, getFilePathBasename, get
38
38
  export { validateExtensionBundle, printValidationResult, type ValidationResult, } from './validate.js';
39
39
  export { validateBackendModules, assertBackendModulesValid, effectiveModulePermissions, validateAgentProviders, assertAgentProvidersValid, extractBackendModuleIds, MAX_AGENT_PROVIDERS_PER_EXTENSION, type BackendModuleValidationIssue, type AgentProviderValidationIssue, } from './manifestValidation.js';
40
40
  export type { AgentProtocol, ProtocolEvent, ProtocolMessage, ProtocolSession, SessionOptions, ProtocolEventType, ToolResult as ProtocolToolResult, MCPServerConfig, RawProtocolSession, AgentProtocolHost, PermissionMode, McpToolDefinition, } from './agents/index.js';
41
+ export { screenshotService } from '@nimbalyst/runtime';
41
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,SAAS,GACf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,8BAA8B,EAC9B,6CAA6C,EAC7C,yBAAyB,EACzB,KAAK,+BAA+B,GACrC,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,KAAK,aAAa,GACnB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,eAAe,EACf,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGhE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,EAC5B,iBAAiB,EACjB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,iCAAiC,EACjC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,GAClC,MAAM,yBAAyB,CAAC;AAYjC,YAAY,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,UAAU,IAAI,kBAAkB,EAChC,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,SAAS,GACf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,8BAA8B,EAC9B,6CAA6C,EAC7C,yBAAyB,EACzB,KAAK,+BAA+B,GACrC,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,KAAK,aAAa,GACnB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,eAAe,EACf,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGhE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,EAC5B,iBAAiB,EACjB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,iCAAiC,EACjC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,GAClC,MAAM,yBAAyB,CAAC;AAYjC,YAAY,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,UAAU,IAAI,kBAAkB,EAChC,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -47,3 +47,5 @@ export { buildFileDirectoryTree, getFileDirectoryPaths, getFilePathBasename, get
47
47
  // Re-export validation
48
48
  export { validateExtensionBundle, printValidationResult, } from './validate.js';
49
49
  export { validateBackendModules, assertBackendModulesValid, effectiveModulePermissions, validateAgentProviders, assertAgentProvidersValid, extractBackendModuleIds, MAX_AGENT_PROVIDERS_PER_EXTENSION, } from './manifestValidation.js';
50
+ // Host-owned native screenshots for every built-in and extension editor.
51
+ export { screenshotService } from '@nimbalyst/runtime';