tabby-tabbyspaces 0.1.0 → 0.2.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 (76) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/.github/workflows/ci.yml +26 -0
  3. package/.github/workflows/claude-code-review.yml +44 -0
  4. package/.github/workflows/claude.yml +81 -0
  5. package/.github/workflows/release.yml +30 -0
  6. package/CHANGELOG.md +46 -0
  7. package/CLAUDE.md +33 -0
  8. package/CONTRIBUTING.md +3 -1
  9. package/README.md +21 -18
  10. package/TODO.md +5 -0
  11. package/dist/build-config.d.ts +3 -3
  12. package/dist/components/deleteConfirmModal.component.d.ts +7 -0
  13. package/dist/components/deleteConfirmModal.component.d.ts.map +1 -0
  14. package/dist/components/paneEditor.component.d.ts +9 -18
  15. package/dist/components/paneEditor.component.d.ts.map +1 -1
  16. package/dist/components/splitPreview.component.d.ts +50 -50
  17. package/dist/components/splitPreview.component.d.ts.map +1 -1
  18. package/dist/components/workspaceEditor.component.d.ts +61 -54
  19. package/dist/components/workspaceEditor.component.d.ts.map +1 -1
  20. package/dist/components/workspaceList.component.d.ts +56 -39
  21. package/dist/components/workspaceList.component.d.ts.map +1 -1
  22. package/dist/index.d.ts +6 -6
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.LICENSE.txt +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/models/workspace.model.d.ts +118 -78
  28. package/dist/models/workspace.model.d.ts.map +1 -1
  29. package/dist/package.json +1 -1
  30. package/dist/providers/config.provider.d.ts +8 -8
  31. package/dist/providers/settings.provider.d.ts +7 -7
  32. package/dist/providers/toolbar.provider.d.ts +23 -15
  33. package/dist/providers/toolbar.provider.d.ts.map +1 -1
  34. package/dist/services/startupCommand.service.d.ts +27 -19
  35. package/dist/services/startupCommand.service.d.ts.map +1 -1
  36. package/dist/services/workspaceBackground.service.d.ts +38 -0
  37. package/dist/services/workspaceBackground.service.d.ts.map +1 -0
  38. package/dist/services/workspaceEditor.service.d.ts +46 -32
  39. package/dist/services/workspaceEditor.service.d.ts.map +1 -1
  40. package/docs/DESIGN.md +57 -0
  41. package/docs/SESSION-2026-01-14-S1-DESIGN.md +134 -0
  42. package/mockups/index.html +162 -0
  43. package/mockups/s1-tight-sharp.html +522 -0
  44. package/mockups/shared/base.css +216 -0
  45. package/mockups/v06-tabbed.html +643 -0
  46. package/package.json +2 -1
  47. package/screenshots/editor.png +0 -0
  48. package/scripts/build-dev.js +2 -1
  49. package/scripts/build-prod.js +2 -1
  50. package/src/components/deleteConfirmModal.component.ts +23 -0
  51. package/src/components/paneEditor.component.pug +27 -43
  52. package/src/components/paneEditor.component.scss +37 -85
  53. package/src/components/paneEditor.component.ts +4 -32
  54. package/src/components/splitPreview.component.pug +0 -9
  55. package/src/components/splitPreview.component.scss +46 -70
  56. package/src/components/splitPreview.component.ts +15 -25
  57. package/src/components/workspaceEditor.component.pug +140 -112
  58. package/src/components/workspaceEditor.component.scss +270 -202
  59. package/src/components/workspaceEditor.component.ts +161 -85
  60. package/src/components/workspaceList.component.pug +31 -51
  61. package/src/components/workspaceList.component.scss +86 -77
  62. package/src/components/workspaceList.component.ts +89 -34
  63. package/src/index.ts +4 -0
  64. package/src/models/workspace.model.ts +80 -2
  65. package/src/providers/toolbar.provider.ts +78 -9
  66. package/src/services/startupCommand.service.ts +30 -32
  67. package/src/services/workspaceBackground.service.ts +167 -0
  68. package/src/services/workspaceEditor.service.ts +77 -40
  69. package/src/styles/_index.scss +3 -0
  70. package/src/styles/_mixins.scss +180 -0
  71. package/src/styles/_variables.scss +67 -0
  72. package/TEST_MCP.md +0 -176
  73. package/cdp-click.js +0 -22
  74. package/cdp-test.js +0 -28
  75. package/screenshots/pane-edit.png +0 -0
  76. package/test_cdp.py +0 -50
package/TEST_MCP.md DELETED
@@ -1,176 +0,0 @@
1
- # MCP Testiranje TabbySpaces
2
-
3
- Uputstvo za Claude da testira plugin kroz tabby-mcp.
4
-
5
- ## Pre-requisites
6
-
7
- 1. Build plugin: `npm run build:dev`
8
- 2. Pokreni NOVI Tabby instance sa debug portom:
9
- ```bash
10
- cmd.exe /c start "" "C:\Program Files (x86)\Tabby\Tabby.exe" --remote-debugging-port=9222
11
- ```
12
-
13
- ## Test 1: Proveri da nema orphaned profila
14
-
15
- ```javascript
16
- // Očekivano: Nema split-layout:tabbyspaces_dev: profila u config
17
- mcp__tabby__execute_js(target: -1, code: `
18
- const profiles = window.require('tabby-core').ConfigService.store.profiles || []
19
- const orphaned = profiles.filter(p => p.id?.startsWith('split-layout:tabbyspaces'))
20
- JSON.stringify({ total: profiles.length, orphaned: orphaned.length, ids: orphaned.map(p => p.id) })
21
- `)
22
- ```
23
-
24
- **Očekivan rezultat:** `orphaned: 0`
25
-
26
- ## Test 2: Otvori Settings i proveri plugin
27
-
28
- ```javascript
29
- // Klikni na Settings
30
- mcp__tabby__execute_js(target: -1, code: `
31
- document.querySelector('[title="Settings"]')?.click()
32
- 'Settings opened'
33
- `)
34
-
35
- // Sačekaj 500ms, pa klikni na TabbySpaces DEV tab
36
- mcp__tabby__execute_js(target: -1, code: `
37
- const tabs = Array.from(document.querySelectorAll('.nav-link'))
38
- const devTab = tabs.find(t => t.textContent.includes('TabbySpaces DEV'))
39
- devTab?.click()
40
- devTab ? 'TabbySpaces DEV tab clicked' : 'Tab not found'
41
- `)
42
- ```
43
-
44
- ## Test 3: Kreiraj test workspace
45
-
46
- ```javascript
47
- // Klikni New Workspace
48
- mcp__tabby__execute_js(target: -1, code: `
49
- const btn = Array.from(document.querySelectorAll('button')).find(b => b.textContent.includes('New Workspace'))
50
- btn?.click()
51
- btn ? 'New Workspace clicked' : 'Button not found'
52
- `)
53
-
54
- // Unesi ime
55
- mcp__tabby__execute_js(target: -1, code: `
56
- const input = document.querySelector('.name-input')
57
- if (input) {
58
- input.value = 'MCP Test Workspace'
59
- input.dispatchEvent(new Event('input', { bubbles: true }))
60
- 'Name set'
61
- } else 'Input not found'
62
- `)
63
-
64
- // Sačuvaj
65
- mcp__tabby__execute_js(target: -1, code: `
66
- const saveBtn = Array.from(document.querySelectorAll('button')).find(b => b.textContent.includes('Save'))
67
- saveBtn?.click()
68
- saveBtn ? 'Saved' : 'Save button not found'
69
- `)
70
- ```
71
-
72
- ## Test 4: Proveri da NIJE kreiran profil u config.store.profiles
73
-
74
- ```javascript
75
- mcp__tabby__execute_js(target: -1, code: `
76
- const profiles = window.require('tabby-core').ConfigService.store.profiles || []
77
- const wsProfiles = profiles.filter(p => p.id?.includes('mcp-test-workspace'))
78
- JSON.stringify({ found: wsProfiles.length, message: wsProfiles.length === 0 ? 'PASS - No profile created' : 'FAIL - Profile was created' })
79
- `)
80
- ```
81
-
82
- **Očekivan rezultat:** `found: 0, message: "PASS - No profile created"`
83
-
84
- ## Test 5: Testiraj CWD injection (Shell Detection)
85
-
86
- ```javascript
87
- // Testiraj shell detection funkciju
88
- mcp__tabby__execute_js(target: -1, code: `
89
- // Simuliraj shell detection
90
- function detectShellType(command) {
91
- const cmd = command.toLowerCase()
92
- if (cmd.includes('nu.exe') || cmd.includes('nushell') || cmd.endsWith('/nu')) return 'nushell'
93
- if (cmd.includes('powershell') || cmd.includes('pwsh')) return 'powershell'
94
- if (cmd.includes('cmd.exe') || cmd.endsWith('\\\\cmd')) return 'cmd'
95
- if (cmd.includes('bash') || cmd.includes('zsh') || cmd.includes('fish') || cmd.includes('/sh')) return 'posix'
96
- return 'unknown'
97
- }
98
-
99
- const tests = [
100
- { cmd: 'C:\\\\Programs\\\\nu\\\\bin\\\\nu.exe', expected: 'nushell' },
101
- { cmd: 'C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe', expected: 'powershell' },
102
- { cmd: 'pwsh.exe', expected: 'powershell' },
103
- { cmd: 'C:\\\\Windows\\\\System32\\\\cmd.exe', expected: 'cmd' },
104
- { cmd: '/usr/bin/bash', expected: 'posix' },
105
- { cmd: '/bin/zsh', expected: 'posix' },
106
- ]
107
-
108
- const results = tests.map(t => ({
109
- cmd: t.cmd,
110
- expected: t.expected,
111
- actual: detectShellType(t.cmd),
112
- pass: detectShellType(t.cmd) === t.expected
113
- }))
114
-
115
- JSON.stringify({ passed: results.filter(r => r.pass).length, total: results.length, results }, null, 2)
116
- `)
117
- ```
118
-
119
- **Očekivan rezultat:** `passed: 6, total: 6`
120
-
121
- ## Test 6: Otvori workspace iz toolbar-a
122
-
123
- ```javascript
124
- // Klikni na TabbySpaces toolbar button (4 squares icon)
125
- mcp__tabby__execute_js(target: -1, code: `
126
- const toolbarBtns = document.querySelectorAll('toolbar-button')
127
- const wsBtn = Array.from(toolbarBtns).find(b => b.querySelector('svg rect'))
128
- wsBtn?.click()
129
- wsBtn ? 'Toolbar button clicked' : 'Button not found'
130
- `)
131
-
132
- // Selektuj workspace iz liste
133
- mcp__tabby__execute_js(target: -1, code: `
134
- const options = document.querySelectorAll('.selector-option')
135
- const testWs = Array.from(options).find(o => o.textContent.includes('MCP Test'))
136
- testWs?.click()
137
- testWs ? 'Workspace selected' : 'Workspace not found in selector'
138
- `)
139
- ```
140
-
141
- ## Test 7: Proveri otvorene tabove
142
-
143
- ```javascript
144
- mcp__tabby__execute_js(target: -1, code: `
145
- const tabs = document.querySelectorAll('.tab')
146
- const tabInfo = Array.from(tabs).map(t => ({
147
- title: t.querySelector('.tab-title')?.textContent || 'unknown',
148
- active: t.classList.contains('active')
149
- }))
150
- JSON.stringify(tabInfo)
151
- `)
152
- ```
153
-
154
- ## Cleanup
155
-
156
- ```javascript
157
- // Zatvori test tab
158
- mcp__tabby__execute_js(target: -1, code: `
159
- const closeBtn = document.querySelector('.tab.active .btn-close')
160
- closeBtn?.click()
161
- 'Tab closed'
162
- `)
163
- ```
164
-
165
- ## Quick Full Test Sequence
166
-
167
- ```
168
- 1. mcp__tabby__list_targets (uzmi poslednji target)
169
- 2. Test 1: Proveri orphaned profile
170
- 3. Test 5: Shell detection
171
- 4. Test 2: Otvori settings
172
- 5. Test 3: Kreiraj workspace
173
- 6. Test 4: Proveri da nema profila
174
- 7. Test 6: Otvori workspace
175
- 8. Test 7: Proveri tabove
176
- ```
package/cdp-click.js DELETED
@@ -1,22 +0,0 @@
1
- const CDP = require('chrome-remote-interface');
2
-
3
- (async () => {
4
- const client = await CDP({port: 9222});
5
- const {Runtime, DOM, Input} = client;
6
-
7
- // Click on "TabbySpaces DEV" link
8
- const result = await Runtime.evaluate({
9
- expression: `
10
- const link = Array.from(document.querySelectorAll('a')).find(a => a.innerText.includes('TabbySpaces DEV'));
11
- if (link) {
12
- link.click();
13
- 'Clicked TabbySpaces DEV';
14
- } else {
15
- 'TabbySpaces DEV link not found';
16
- }
17
- `
18
- });
19
- console.log('Result:', result.result.value);
20
-
21
- await client.close();
22
- })().catch(e => console.error('Error:', e.message));
package/cdp-test.js DELETED
@@ -1,28 +0,0 @@
1
- const CDP = require('chrome-remote-interface');
2
-
3
- (async () => {
4
- const client = await CDP({port: 9222});
5
- const {Runtime, DOM} = client;
6
-
7
- // Get page title
8
- const title = await Runtime.evaluate({expression: 'document.title'});
9
- console.log('Title:', title.result.value);
10
-
11
- // Get all clickable elements
12
- const clickables = await Runtime.evaluate({
13
- expression: `
14
- Array.from(document.querySelectorAll('button, [role=button], .btn, a, [ng-click]'))
15
- .map(el => ({
16
- tag: el.tagName,
17
- text: (el.innerText || el.textContent || '').trim().substring(0, 50),
18
- class: (el.className || '').substring(0, 50)
19
- }))
20
- .slice(0, 30)
21
- `,
22
- returnByValue: true
23
- });
24
- console.log('Clickable elements:');
25
- console.log(JSON.stringify(clickables.result.value, null, 2));
26
-
27
- await client.close();
28
- })().catch(e => console.error('Error:', e.message));
Binary file
package/test_cdp.py DELETED
@@ -1,50 +0,0 @@
1
- """Test CDP connection to Tabby - click on TabbySpaces settings"""
2
- import pychrome
3
- import time
4
-
5
- # Connect to Tabby
6
- browser = pychrome.Browser(url="http://localhost:9222")
7
- tabs = browser.list_tab()
8
- print(f"Found {len(tabs)} tabs")
9
-
10
- # Get the first tab (main Tabby window)
11
- tab = tabs[0]
12
- print(f"Using first tab")
13
- tab.start()
14
-
15
- # Click on TabbySpaces link
16
- print("\nClicking on 'TabbySpaces' link...")
17
- result = tab.Runtime.evaluate(expression="""
18
- const link = Array.from(document.querySelectorAll('a.nav-link'))
19
- .find(a => a.innerText.trim() === 'TabbySpaces');
20
- if (link) {
21
- link.click();
22
- 'Clicked TabbySpaces!';
23
- } else {
24
- 'TabbySpaces link not found';
25
- }
26
- """)
27
- print(f"Result: {result.get('result', {}).get('value')}")
28
-
29
- time.sleep(0.3)
30
-
31
- # Verify we're on TabbySpaces page - look for workspace elements
32
- result = tab.Runtime.evaluate(expression="""
33
- // Check for TabbySpaces specific content
34
- const content = document.body.innerText;
35
- const hasWorkspaces = content.includes('Workspace') || content.includes('workspace');
36
- const activeLink = document.querySelector('a.nav-link.active');
37
- ({
38
- activePage: activeLink ? activeLink.innerText.trim() : 'unknown',
39
- hasWorkspaceContent: hasWorkspaces,
40
- pageSnippet: content.substring(0, 500)
41
- });
42
- """, returnByValue=True)
43
-
44
- data = result.get('result', {}).get('value', {})
45
- print(f"\nActive page: {data.get('activePage')}")
46
- print(f"Has workspace content: {data.get('hasWorkspaceContent')}")
47
- print(f"\nPage snippet:\n{data.get('pageSnippet', '')[:300]}...")
48
-
49
- tab.stop()
50
- print("\nDone!")