tide-commander 0.77.0 → 0.78.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.
@@ -1 +1 @@
1
- import{W as s}from"./main-VR06Nfll.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react-uS-d4TUT.js";import"./vendor-three-DJ4p3FLF.js";class f extends s{constructor(){super(...arguments),this.pending=[],this.deliveredNotifications=[],this.hasNotificationSupport=()=>{if(!("Notification"in window)||!Notification.requestPermission)return!1;if(Notification.permission!=="granted")try{new Notification("")}catch(i){if(i instanceof Error&&i.name==="TypeError")return!1}return!0}}async getDeliveredNotifications(){const i=[];for(const t of this.deliveredNotifications){const e={title:t.title,id:parseInt(t.tag),body:t.body};i.push(e)}return{notifications:i}}async removeDeliveredNotifications(i){for(const t of i.notifications){const e=this.deliveredNotifications.find(n=>n.tag===String(t.id));e==null||e.close(),this.deliveredNotifications=this.deliveredNotifications.filter(()=>!e)}}async removeAllDeliveredNotifications(){for(const i of this.deliveredNotifications)i.close();this.deliveredNotifications=[]}async createChannel(){throw this.unimplemented("Not implemented on web.")}async deleteChannel(){throw this.unimplemented("Not implemented on web.")}async listChannels(){throw this.unimplemented("Not implemented on web.")}async schedule(i){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");for(const t of i.notifications)this.sendNotification(t);return{notifications:i.notifications.map(t=>({id:t.id}))}}async getPending(){return{notifications:this.pending}}async registerActionTypes(){throw this.unimplemented("Not implemented on web.")}async cancel(i){this.pending=this.pending.filter(t=>!i.notifications.find(e=>e.id===t.id))}async areEnabled(){const{display:i}=await this.checkPermissions();return{value:i==="granted"}}async changeExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async checkExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async requestPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(await Notification.requestPermission())}}async checkPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(Notification.permission)}}transformNotificationPermission(i){switch(i){case"granted":return"granted";case"denied":return"denied";default:return"prompt"}}sendPending(){var i;const t=[],e=new Date().getTime();for(const n of this.pending)!((i=n.schedule)===null||i===void 0)&&i.at&&n.schedule.at.getTime()<=e&&(this.buildNotification(n),t.push(n));this.pending=this.pending.filter(n=>!t.find(o=>o===n))}sendNotification(i){var t;if(!((t=i.schedule)===null||t===void 0)&&t.at){const e=i.schedule.at.getTime()-new Date().getTime();this.pending.push(i),setTimeout(()=>{this.sendPending()},e);return}this.buildNotification(i)}buildNotification(i){const t=new Notification(i.title,{body:i.body,tag:String(i.id)});return t.addEventListener("click",this.onClick.bind(this,i),!1),t.addEventListener("show",this.onShow.bind(this,i),!1),t.addEventListener("close",()=>{this.deliveredNotifications=this.deliveredNotifications.filter(()=>!this)},!1),this.deliveredNotifications.push(t),t}onClick(i){const t={actionId:"tap",notification:i};this.notifyListeners("localNotificationActionPerformed",t)}onShow(i){this.notifyListeners("localNotificationReceived",i)}}export{f as LocalNotificationsWeb};
1
+ import{W as s}from"./main-CNF5ilVy.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react-uS-d4TUT.js";import"./vendor-three-DJ4p3FLF.js";class f extends s{constructor(){super(...arguments),this.pending=[],this.deliveredNotifications=[],this.hasNotificationSupport=()=>{if(!("Notification"in window)||!Notification.requestPermission)return!1;if(Notification.permission!=="granted")try{new Notification("")}catch(i){if(i instanceof Error&&i.name==="TypeError")return!1}return!0}}async getDeliveredNotifications(){const i=[];for(const t of this.deliveredNotifications){const e={title:t.title,id:parseInt(t.tag),body:t.body};i.push(e)}return{notifications:i}}async removeDeliveredNotifications(i){for(const t of i.notifications){const e=this.deliveredNotifications.find(n=>n.tag===String(t.id));e==null||e.close(),this.deliveredNotifications=this.deliveredNotifications.filter(()=>!e)}}async removeAllDeliveredNotifications(){for(const i of this.deliveredNotifications)i.close();this.deliveredNotifications=[]}async createChannel(){throw this.unimplemented("Not implemented on web.")}async deleteChannel(){throw this.unimplemented("Not implemented on web.")}async listChannels(){throw this.unimplemented("Not implemented on web.")}async schedule(i){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");for(const t of i.notifications)this.sendNotification(t);return{notifications:i.notifications.map(t=>({id:t.id}))}}async getPending(){return{notifications:this.pending}}async registerActionTypes(){throw this.unimplemented("Not implemented on web.")}async cancel(i){this.pending=this.pending.filter(t=>!i.notifications.find(e=>e.id===t.id))}async areEnabled(){const{display:i}=await this.checkPermissions();return{value:i==="granted"}}async changeExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async checkExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async requestPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(await Notification.requestPermission())}}async checkPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(Notification.permission)}}transformNotificationPermission(i){switch(i){case"granted":return"granted";case"denied":return"denied";default:return"prompt"}}sendPending(){var i;const t=[],e=new Date().getTime();for(const n of this.pending)!((i=n.schedule)===null||i===void 0)&&i.at&&n.schedule.at.getTime()<=e&&(this.buildNotification(n),t.push(n));this.pending=this.pending.filter(n=>!t.find(o=>o===n))}sendNotification(i){var t;if(!((t=i.schedule)===null||t===void 0)&&t.at){const e=i.schedule.at.getTime()-new Date().getTime();this.pending.push(i),setTimeout(()=>{this.sendPending()},e);return}this.buildNotification(i)}buildNotification(i){const t=new Notification(i.title,{body:i.body,tag:String(i.id)});return t.addEventListener("click",this.onClick.bind(this,i),!1),t.addEventListener("show",this.onShow.bind(this,i),!1),t.addEventListener("close",()=>{this.deliveredNotifications=this.deliveredNotifications.filter(()=>!this)},!1),this.deliveredNotifications.push(t),t}onClick(i){const t={actionId:"tap",notification:i};this.notifyListeners("localNotificationActionPerformed",t)}onShow(i){this.notifyListeners("localNotificationReceived",i)}}export{f as LocalNotificationsWeb};
package/dist/index.html CHANGED
@@ -22,11 +22,11 @@
22
22
  <link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png" />
23
23
  <link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon.png" />
24
24
  <title>Tide Commander</title>
25
- <script type="module" crossorigin src="/assets/main-VR06Nfll.js"></script>
25
+ <script type="module" crossorigin src="/assets/main-CNF5ilVy.js"></script>
26
26
  <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
27
27
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-uS-d4TUT.js">
28
28
  <link rel="modulepreload" crossorigin href="/assets/vendor-three-DJ4p3FLF.js">
29
- <link rel="stylesheet" crossorigin href="/assets/main-DrUT6gJW.css">
29
+ <link rel="stylesheet" crossorigin href="/assets/main-D893RHwB.css">
30
30
  </head>
31
31
  <body>
32
32
  <div id="app"></div>
@@ -13,6 +13,7 @@ import { streamingExec } from './streaming-exec.js';
13
13
  import { bitbucketPR } from './bitbucket-pr.js';
14
14
  import { pm2Logs } from './pm2-logs.js';
15
15
  import { createBuilding } from './create-building.js';
16
+ import { releasePipeline } from './release-pipeline.js';
16
17
  /**
17
18
  * All built-in skills that ship with Tide Commander
18
19
  */
@@ -25,6 +26,7 @@ export const BUILTIN_SKILLS = [
25
26
  bitbucketPR,
26
27
  pm2Logs,
27
28
  createBuilding,
29
+ releasePipeline,
28
30
  ];
29
31
  /**
30
32
  * Get the ID for a built-in skill based on its slug
@@ -0,0 +1,341 @@
1
+ export const releasePipeline = {
2
+ slug: 'release-pipeline',
3
+ name: 'TC Release Pipeline',
4
+ description: 'Full release workflow: lint, type-check, test, build, APK, version bump, changelog, git tag, GitHub release. Use when asked to release, publish, ship, or do a full build pipeline.',
5
+ allowedTools: [
6
+ 'Bash(git:*)',
7
+ 'Bash(npm:*)',
8
+ 'Bash(make:*)',
9
+ 'Bash(gh:*)',
10
+ 'Bash(curl:*)',
11
+ 'Bash(npx:*)',
12
+ 'Read',
13
+ 'Edit',
14
+ 'Grep',
15
+ 'Glob',
16
+ ],
17
+ content: `# Release Pipeline
18
+
19
+ Full release workflow for Tide Commander. Runs quality checks, builds everything, bumps the version, updates the changelog, tags, pushes, creates a GitHub release, and optionally attaches the APK.
20
+
21
+ ## Core Principles
22
+
23
+ 1. **Fail fast** - If any quality gate fails, STOP and report to the user. Do NOT attempt to fix issues automatically.
24
+ 2. **Never force push** to shared branches (main, master, develop)
25
+ 3. **Never auto-resolve conflicts** - report them to the user
26
+ 4. **Always verify** the current branch before any operation
27
+ 5. **NEVER add Co-Authored-By trailers** to commits
28
+
29
+ ---
30
+
31
+ ## Full Release Workflow
32
+
33
+ When asked to "release", "ship", "publish", "do a full release", or similar:
34
+
35
+ ### Phase 1: Pre-Flight Checks
36
+
37
+ \`\`\`bash
38
+ # Verify branch and clean state
39
+ git status
40
+ git branch --show-current
41
+ \`\`\`
42
+
43
+ - If there are uncommitted changes, list them and ask the user if they should be included.
44
+ - If not on the expected branch (usually \`master\`), warn the user.
45
+
46
+ \`\`\`bash
47
+ # Pull latest to avoid conflicts
48
+ git pull --rebase origin $(git branch --show-current)
49
+ \`\`\`
50
+
51
+ **If conflicts occur:** STOP immediately and report to user. Do NOT auto-resolve.
52
+
53
+ ---
54
+
55
+ ### Phase 2: Quality Gates (ALL must pass)
56
+
57
+ Run each gate sequentially. If ANY gate fails, STOP and report the failure to the user. Do NOT try to fix issues.
58
+
59
+ Use the Streaming Exec API for all long-running commands so the user can see live output:
60
+
61
+ \`\`\`bash
62
+ curl -s -X POST http://localhost:5174/api/exec \\
63
+ -H "Content-Type: application/json" \\
64
+ -d '{"agentId":"YOUR_AGENT_ID","command":"COMMAND"}'
65
+ \`\`\`
66
+
67
+ #### Gate 1: ESLint (zero warnings)
68
+
69
+ \`\`\`bash
70
+ curl -s -X POST http://localhost:5174/api/exec \\
71
+ -H "Content-Type: application/json" \\
72
+ -d '{"agentId":"YOUR_AGENT_ID","command":"npm run lint"}'
73
+ \`\`\`
74
+
75
+ Check the output. If there are **any warnings or errors**, STOP and report them to the user.
76
+
77
+ #### Gate 2: TypeScript Type Check (zero errors)
78
+
79
+ \`\`\`bash
80
+ curl -s -X POST http://localhost:5174/api/exec \\
81
+ -H "Content-Type: application/json" \\
82
+ -d '{"agentId":"YOUR_AGENT_ID","command":"npm run lint:types"}'
83
+ \`\`\`
84
+
85
+ If there are type errors, STOP and report them.
86
+
87
+ #### Gate 3: Tests (all passing)
88
+
89
+ \`\`\`bash
90
+ curl -s -X POST http://localhost:5174/api/exec \\
91
+ -H "Content-Type: application/json" \\
92
+ -d '{"agentId":"YOUR_AGENT_ID","command":"npm test"}'
93
+ \`\`\`
94
+
95
+ If any tests fail, STOP and report them.
96
+
97
+ ---
98
+
99
+ ### Phase 3: Build
100
+
101
+ #### Build Web App
102
+
103
+ \`\`\`bash
104
+ curl -s -X POST http://localhost:5174/api/exec \\
105
+ -H "Content-Type: application/json" \\
106
+ -d '{"agentId":"YOUR_AGENT_ID","command":"npm run build"}'
107
+ \`\`\`
108
+
109
+ If the build fails, STOP and report the error.
110
+
111
+ #### Build Android APK (optional - ask user)
112
+
113
+ Ask the user: "Do you want to build the Android APK as part of this release?"
114
+
115
+ If yes, build the **release** APK:
116
+
117
+ \`\`\`bash
118
+ curl -s -X POST http://localhost:5174/api/exec \\
119
+ -H "Content-Type: application/json" \\
120
+ -d '{"agentId":"YOUR_AGENT_ID","command":"make apk-release"}'
121
+ \`\`\`
122
+
123
+ This runs: \`npm run build\` + \`npx cap sync\` + \`gradlew assembleRelease\`
124
+
125
+ Output APK location: \`android/app/build/outputs/apk/release/app-release-unsigned.apk\`
126
+
127
+ For a **debug** APK instead:
128
+
129
+ \`\`\`bash
130
+ curl -s -X POST http://localhost:5174/api/exec \\
131
+ -H "Content-Type: application/json" \\
132
+ -d '{"agentId":"YOUR_AGENT_ID","command":"make apk"}'
133
+ \`\`\`
134
+
135
+ Output: \`android/app/build/outputs/apk/debug/app-debug.apk\`
136
+
137
+ If the APK build fails, STOP and report the error.
138
+
139
+ ---
140
+
141
+ ### Phase 4: Version Bump
142
+
143
+ #### Determine Version Type
144
+
145
+ Read the current version:
146
+ \`\`\`bash
147
+ npm pkg get version
148
+ \`\`\`
149
+
150
+ Ask the user or infer from changes:
151
+ - **patch** (0.0.X): Bug fixes, small changes, performance tweaks
152
+ - **minor** (0.X.0): New features, non-breaking changes
153
+ - **major** (X.0.0): Breaking changes, major rewrites
154
+
155
+ #### Bump the Version
156
+
157
+ \`\`\`bash
158
+ npm version <patch|minor|major> --no-git-tag-version
159
+ \`\`\`
160
+
161
+ ---
162
+
163
+ ### Phase 5: Update Changelog
164
+
165
+ Read recent commits since the last tag:
166
+
167
+ \`\`\`bash
168
+ git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~20")..HEAD
169
+ \`\`\`
170
+
171
+ Update \`CHANGELOG.md\` with the new version entry at the top (below the header). Use the Keep a Changelog format:
172
+
173
+ \`\`\`markdown
174
+ ## [X.Y.Z] - YYYY-MM-DD
175
+
176
+ ### Added
177
+ - New features (from \`feat:\` or \`add:\` commits)
178
+
179
+ ### Changed
180
+ - Changes to existing functionality (from \`change:\`, \`update:\`, \`refactor:\`, \`perf:\` commits)
181
+
182
+ ### Fixed
183
+ - Bug fixes (from \`fix:\` or \`bugfix:\` commits)
184
+
185
+ ### Removed
186
+ - Removed features (from \`remove:\` or \`delete:\` commits)
187
+ \`\`\`
188
+
189
+ Only include sections that have entries. Write concise, user-facing descriptions.
190
+
191
+ ---
192
+
193
+ ### Phase 6: Commit, Tag, Push
194
+
195
+ #### Stage and Commit
196
+
197
+ \`\`\`bash
198
+ git add package.json package-lock.json CHANGELOG.md
199
+ git add -A # include any other changed files
200
+
201
+ git diff --cached --stat # show what will be committed
202
+ \`\`\`
203
+
204
+ Show the staged changes summary to the user before committing.
205
+
206
+ \`\`\`bash
207
+ git commit -m "chore(release): v<VERSION>
208
+
209
+ - Summary of main changes
210
+ - Another change"
211
+ \`\`\`
212
+
213
+ #### Create Annotated Tag
214
+
215
+ \`\`\`bash
216
+ git tag -a v<VERSION> -m "Release v<VERSION>
217
+
218
+ Highlights:
219
+ - Main feature or fix
220
+ - Another highlight"
221
+ \`\`\`
222
+
223
+ #### Push to Remote
224
+
225
+ \`\`\`bash
226
+ git push origin $(git branch --show-current)
227
+ git push origin v<VERSION>
228
+ \`\`\`
229
+
230
+ ---
231
+
232
+ ### Phase 7: GitHub Release
233
+
234
+ Create the GitHub release using the \`gh\` CLI:
235
+
236
+ \`\`\`bash
237
+ gh release create v<VERSION> --title "v<VERSION>" --notes "<RELEASE_NOTES>"
238
+ \`\`\`
239
+
240
+ **Release notes format:**
241
+ \`\`\`markdown
242
+ ## What's New
243
+
244
+ ### Added
245
+ - Feature descriptions
246
+
247
+ ### Changed
248
+ - Changes and improvements
249
+
250
+ ### Fixed
251
+ - Bug fixes
252
+
253
+ ## Technical Details
254
+ - Implementation notes
255
+ - Architecture changes
256
+ \`\`\`
257
+
258
+ #### Attach APK to Release (if built)
259
+
260
+ If an APK was built, attach it to the GitHub release:
261
+
262
+ \`\`\`bash
263
+ gh release upload v<VERSION> android/app/build/outputs/apk/release/app-release-unsigned.apk --clobber
264
+ \`\`\`
265
+
266
+ Or for debug APK:
267
+ \`\`\`bash
268
+ gh release upload v<VERSION> android/app/build/outputs/apk/debug/app-debug.apk --clobber
269
+ \`\`\`
270
+
271
+ ---
272
+
273
+ ## Partial Workflows
274
+
275
+ The skill also supports running individual phases:
276
+
277
+ ### Quality Check Only
278
+
279
+ When asked to "check quality", "run checks", "lint and test", or "pre-release check":
280
+
281
+ Run Phase 2 only (lint, type-check, tests). Report results without proceeding further.
282
+
283
+ ### Build Only
284
+
285
+ When asked to "build", "build everything", or "build apk":
286
+
287
+ Run Phase 3 only. Skip version bump and release.
288
+
289
+ ### Tag and Release Only
290
+
291
+ When asked to "tag", "create release", or "push release" (when version is already bumped):
292
+
293
+ Skip Phases 2-4, run Phases 5-7 only.
294
+
295
+ ---
296
+
297
+ ## Failure Handling
298
+
299
+ - **Lint warnings/errors**: STOP, report the lint output, do NOT auto-fix
300
+ - **Type errors**: STOP, report the errors, do NOT auto-fix
301
+ - **Test failures**: STOP, report failing tests, do NOT auto-fix
302
+ - **Build failure**: STOP, report the build error
303
+ - **APK build failure**: STOP, report the error (often SDK/Gradle issues)
304
+ - **Git conflicts**: STOP, list conflicting files, ask user to resolve manually
305
+ - **Push rejected**: STOP, report the rejection reason (likely needs pull first)
306
+
307
+ **Critical rule**: When any step fails, do NOT proceed to subsequent steps. Report the failure clearly and wait for user instructions.
308
+
309
+ ---
310
+
311
+ ## Quick Reference
312
+
313
+ | Phase | Command | Gate |
314
+ |-------|---------|------|
315
+ | Lint | \`npm run lint\` | Zero warnings |
316
+ | Types | \`npm run lint:types\` | Zero errors |
317
+ | Tests | \`npm test\` | All passing |
318
+ | Build | \`npm run build\` | Exit code 0 |
319
+ | APK Debug | \`make apk\` | Exit code 0 |
320
+ | APK Release | \`make apk-release\` | Exit code 0 |
321
+ | Version | \`npm version <type> --no-git-tag-version\` | - |
322
+ | Tag | \`git tag -a v<VER> -m "..."\` | - |
323
+ | Push | \`git push origin <branch> && git push origin v<VER>\` | - |
324
+ | GH Release | \`gh release create v<VER> --notes "..."\` | - |
325
+ | Attach APK | \`gh release upload v<VER> <apk-path> --clobber\` | - |
326
+
327
+ ---
328
+
329
+ ## Version Guidelines
330
+
331
+ - **0.x.x** - Pre-release, API may change
332
+ - **1.0.0** - First stable release
333
+ - **x.Y.0** - New features (backwards compatible)
334
+ - **x.x.Z** - Bug fixes only
335
+
336
+ When unsure about version type, ask the user:
337
+ > "What type of release is this?
338
+ > - **patch** (bug fixes only)
339
+ > - **minor** (new features, no breaking changes)
340
+ > - **major** (breaking changes)"`,
341
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "0.77.0",
3
+ "version": "0.78.0",
4
4
  "description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
5
5
  "repository": {
6
6
  "type": "git",