turtlecode 0.1.1 → 0.1.3

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 (2) hide show
  1. package/bin/cli.mjs +39 -3
  2. package/package.json +1 -1
package/bin/cli.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { createServer, request as httpRequest } from "node:http"
4
- import { readFileSync, existsSync, statSync } from "node:fs"
4
+ import { readFileSync, existsSync, statSync, mkdirSync } from "node:fs"
5
5
  import { join, extname, dirname, resolve } from "node:path"
6
6
  import { fileURLToPath } from "node:url"
7
7
  import { exec, spawn } from "node:child_process"
8
+ import { homedir } from "node:os"
8
9
 
9
10
  const root = join(dirname(fileURLToPath(import.meta.url)), "..", "assets")
10
11
 
@@ -49,6 +50,23 @@ function encode(str) {
49
50
  return Buffer.from(str).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")
50
51
  }
51
52
 
53
+ // Extract directory from base64-encoded path segment, returns { pathname, directory }
54
+ function extractDir(path) {
55
+ const match = path.match(/^\/([A-Za-z0-9_-]{10,})(\/.*)?$/)
56
+ if (!match) return { pathname: path }
57
+
58
+ const encoded = match[1]
59
+ const rest = match[2] || "/"
60
+
61
+ try {
62
+ const normalized = encoded.replace(/-/g, "+").replace(/_/g, "/")
63
+ const decoded = Buffer.from(normalized, "base64").toString("utf-8")
64
+ return { pathname: rest, directory: decoded }
65
+ } catch {
66
+ return { pathname: path }
67
+ }
68
+ }
69
+
52
70
  function probe(origin) {
53
71
  return new Promise((ok) => {
54
72
  const req = httpRequest(origin, { method: "HEAD", timeout: 1000 }, (res) => {
@@ -130,6 +148,16 @@ if (!existsSync(join(root, "index.html"))) {
130
148
 
131
149
  const spawned = await boot(backend.origin)
132
150
 
151
+ // Ensure ~/.turtlecode exists for new project creation
152
+ const projectsDir = join(homedir(), ".turtlecode")
153
+ if (!existsSync(projectsDir)) {
154
+ try {
155
+ mkdirSync(projectsDir, { recursive: true })
156
+ } catch {
157
+ // Ignore errors (permissions, etc.) - backend will handle them
158
+ }
159
+ }
160
+
133
161
  // Determine whether a request should be proxied to the backend.
134
162
  // Static assets are served directly; browser navigation gets the SPA
135
163
  // index.html; everything else (API calls, SSE, etc.) is proxied.
@@ -150,9 +178,13 @@ function shouldProxy(req, file) {
150
178
 
151
179
  function proxy(req, res) {
152
180
  const url = new URL(req.url, `http://localhost:${port}`)
153
- const target = `${backend.origin}${url.pathname}${url.search}`
154
181
 
182
+ // Extract directory from base64 path segment and add header for backend
183
+ const { pathname, directory } = extractDir(url.pathname)
155
184
  const headers = { ...req.headers, host: backend.host }
185
+ if (directory) headers["x-opencode-directory"] = directory
186
+
187
+ const target = `${backend.origin}${pathname}${url.search}`
156
188
 
157
189
  const proxyReq = httpRequest(target, { method: req.method, headers }, (proxyRes) => {
158
190
  res.writeHead(proxyRes.statusCode, proxyRes.headers)
@@ -200,9 +232,13 @@ const server = createServer((req, res) => {
200
232
  // Handle WebSocket upgrade (used by PTY terminal connections)
201
233
  server.on("upgrade", (req, socket, head) => {
202
234
  const url = new URL(req.url, `http://localhost:${port}`)
203
- const target = `${backend.origin}${url.pathname}${url.search}`
235
+
236
+ // Extract directory from base64 path segment and add header (same logic as proxy function)
237
+ const { pathname, directory } = extractDir(url.pathname)
204
238
  const headers = { ...req.headers, host: backend.host }
239
+ if (directory) headers["x-opencode-directory"] = directory
205
240
 
241
+ const target = `${backend.origin}${pathname}${url.search}`
206
242
  const proxyReq = httpRequest(target, { method: "GET", headers })
207
243
 
208
244
  proxyReq.on("upgrade", (proxyRes, proxySocket, proxyHead) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turtlecode",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "AI-powered creative workspace — launch with npx turtlecode",
5
5
  "type": "module",
6
6
  "bin": {