@slycode/slycode 0.2.20 → 0.2.21

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 (37) hide show
  1. package/dist/bridge/pty-handler.js +58 -12
  2. package/dist/bridge/pty-handler.js.map +1 -1
  3. package/dist/messaging/index.js +6 -6
  4. package/dist/messaging/index.js.map +1 -1
  5. package/dist/messaging/stt.d.ts +1 -1
  6. package/dist/messaging/stt.js +41 -9
  7. package/dist/messaging/stt.js.map +1 -1
  8. package/dist/web/.next/BUILD_ID +1 -1
  9. package/dist/web/.next/build-manifest.json +2 -2
  10. package/dist/web/.next/server/app/_global-error.html +2 -2
  11. package/dist/web/.next/server/app/_global-error.rsc +1 -1
  12. package/dist/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  13. package/dist/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/dist/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  15. package/dist/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  16. package/dist/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/dist/web/.next/server/app/_not-found.html +1 -1
  18. package/dist/web/.next/server/app/_not-found.rsc +1 -1
  19. package/dist/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  20. package/dist/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  21. package/dist/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  22. package/dist/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  23. package/dist/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  24. package/dist/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/dist/web/.next/server/app/project/[id]/page_client-reference-manifest.js +1 -1
  26. package/dist/web/.next/server/chunks/[root-of-the-server]__f3e501b6._.js +1 -1
  27. package/dist/web/.next/server/chunks/ssr/src_components_c4135402._.js +1 -1
  28. package/dist/web/.next/server/pages/404.html +1 -1
  29. package/dist/web/.next/server/pages/500.html +2 -2
  30. package/dist/web/.next/static/chunks/{8cb404d087e9f3c7.js → 4049cceee6a49323.js} +1 -1
  31. package/dist/web/src/app/api/projects/route.ts +11 -2
  32. package/dist/web/src/components/CardModal.tsx +31 -24
  33. package/package.json +2 -2
  34. package/templates/kanban-seed.json +1 -1
  35. /package/dist/web/.next/static/{tQdF18XbrwPnmXEMVlcfU → 0sPAbk-Qw-InZ0rdHjHnC}/_buildManifest.js +0 -0
  36. /package/dist/web/.next/static/{tQdF18XbrwPnmXEMVlcfU → 0sPAbk-Qw-InZ0rdHjHnC}/_clientMiddlewareManifest.json +0 -0
  37. /package/dist/web/.next/static/{tQdF18XbrwPnmXEMVlcfU → 0sPAbk-Qw-InZ0rdHjHnC}/_ssgManifest.js +0 -0
@@ -11,6 +11,8 @@ const execFileAsync = promisify(execFile);
11
11
  export const dynamic = 'force-dynamic';
12
12
 
13
13
  function expandTilde(p: string): string {
14
+ // Normalize Unicode tildes (U+02DC small tilde, U+FF5E fullwidth tilde) to ASCII
15
+ p = p.replace(/^[\u02dc\uff5e]/, '~');
14
16
  if (p.startsWith('~/') || p === '~') {
15
17
  return p.replace(/^~/, os.homedir());
16
18
  }
@@ -55,8 +57,15 @@ export async function POST(request: Request) {
55
57
  );
56
58
  }
57
59
 
58
- // Resolve tilde and make absolute
59
- const resolvedPath = path.resolve(expandTilde(projectPath));
60
+ // Resolve tilde and validate absolute path
61
+ const expanded = expandTilde(projectPath);
62
+ if (!path.isAbsolute(expanded)) {
63
+ return NextResponse.json(
64
+ { error: 'Please enter an absolute path (e.g. ~/Dev/myproject or /home/user/Dev/myproject)' },
65
+ { status: 400 }
66
+ );
67
+ }
68
+ const resolvedPath = path.resolve(expanded);
60
69
 
61
70
  const registry = await loadRegistry();
62
71
  const projectId = toKebabCase(name);
@@ -649,33 +649,40 @@ export function CardModal({ card, stage, projectId, projectPath, onClose, onUpda
649
649
  };
650
650
  const currentDocPath = getDocPath(activeTab);
651
651
 
652
- // Track loaded docs by path to avoid reloading
652
+ // Track loaded docs by path
653
653
  const [loadedDocs, setLoadedDocs] = useState<Record<string, string>>({});
654
654
  const [docErrors, setDocErrors] = useState<Record<string, string>>({});
655
655
 
656
- // Load document when a doc tab is selected
656
+ // Re-fetch document every time a doc tab is selected (always show latest from disk)
657
657
  useEffect(() => {
658
658
  const isDocTab = activeTab === 'design' || activeTab === 'feature' || activeTab === 'test';
659
- if (isDocTab && currentDocPath && !loadedDocs[currentDocPath] && !docLoading) {
660
- // eslint-disable-next-line react-hooks/set-state-in-effect -- gating fetch with loading flag
661
- setDocLoading(true);
662
- fetch(`/api/file?path=${encodeURIComponent(currentDocPath)}&projectId=${encodeURIComponent(projectId)}`)
663
- .then((res) => res.json())
664
- .then((data) => {
665
- if (data.error) {
666
- setDocErrors((prev) => ({ ...prev, [currentDocPath!]: data.error }));
667
- } else {
668
- setLoadedDocs((prev) => ({ ...prev, [currentDocPath!]: data.content }));
669
- }
670
- })
671
- .catch((err) => {
672
- setDocErrors((prev) => ({ ...prev, [currentDocPath!]: err.message }));
673
- })
674
- .finally(() => {
675
- setDocLoading(false);
676
- });
677
- }
678
- }, [activeTab, currentDocPath, loadedDocs, docLoading, projectId]);
659
+ if (!isDocTab || !currentDocPath) return;
660
+
661
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- gating fetch with loading flag
662
+ setDocLoading(true);
663
+ const fetchPath = currentDocPath;
664
+ fetch(`/api/file?path=${encodeURIComponent(fetchPath)}&projectId=${encodeURIComponent(projectId)}`)
665
+ .then((res) => res.json())
666
+ .then((data) => {
667
+ if (data.error) {
668
+ setDocErrors((prev) => ({ ...prev, [fetchPath]: data.error }));
669
+ } else {
670
+ setDocErrors((prev) => {
671
+ const next = { ...prev };
672
+ delete next[fetchPath];
673
+ return next;
674
+ });
675
+ setLoadedDocs((prev) => ({ ...prev, [fetchPath]: data.content }));
676
+ }
677
+ })
678
+ .catch((err) => {
679
+ setDocErrors((prev) => ({ ...prev, [fetchPath]: err.message }));
680
+ })
681
+ .finally(() => {
682
+ setDocLoading(false);
683
+ });
684
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally re-fetch on every tab switch
685
+ }, [activeTab, currentDocPath, projectId]);
679
686
 
680
687
  const handleTitleSave = () => {
681
688
  if (editedTitle.trim() && editedTitle !== card.title) {
@@ -1623,12 +1630,12 @@ export function CardModal({ card, stage, projectId, projectPath, onClose, onUpda
1623
1630
  )}
1624
1631
  </button>
1625
1632
  )}
1626
- {docLoading && !loadedDocs[currentDocPath!] && (
1633
+ {docLoading && !loadedDocs[currentDocPath!] && !docErrors[currentDocPath!] && (
1627
1634
  <div className="flex items-center justify-center py-8">
1628
1635
  <div className="text-void-500">Loading document...</div>
1629
1636
  </div>
1630
1637
  )}
1631
- {currentDocPath && docErrors[currentDocPath] && (
1638
+ {currentDocPath && docErrors[currentDocPath] && !loadedDocs[currentDocPath] && (
1632
1639
  <div className="rounded-lg bg-red-50 p-4 text-red-700 dark:bg-red-900/20 dark:text-red-300">
1633
1640
  Error loading document: {docErrors[currentDocPath]}
1634
1641
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slycode/slycode",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
4
4
  "description": "AI-powered development workspace with kanban, terminal bridge, and skill management",
5
5
  "bin": {
6
6
  "slycode": "bin/slycode.js",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "build": "tsc",
24
24
  "dev": "tsc --watch",
25
- "postinstall": "node -e \"const fs=require('fs'),path=require('path'); const d=path.join(__dirname,'..','node-pty','prebuilds'); if(!fs.existsSync(d))process.exit(0); fs.readdirSync(d).filter(f=>f.startsWith('darwin')).forEach(f=>{const h=path.join(d,f,'spawn-helper'); if(fs.existsSync(h))fs.chmodSync(h,0o755);})\""
25
+ "postinstall": "node -e \"const fs=require('fs'),p=require('path'); try{const d=p.join(p.dirname(require.resolve('node-pty/package.json')),'prebuilds'); fs.readdirSync(d).filter(f=>f.startsWith('darwin')).forEach(f=>{const h=p.join(d,f,'spawn-helper'); if(fs.existsSync(h)){fs.chmodSync(h,0o755);console.log('[slycode] Fixed node-pty spawn-helper permissions:',h)}})}catch{}\""
26
26
  },
27
27
  "keywords": [
28
28
  "slycode",
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "cards": [],
4
- "lastUpdated": "2026-03-25T07:44:19.892Z"
4
+ "lastUpdated": "2026-03-28T22:34:01.687Z"
5
5
  }