@lovelybunch/api 1.0.22 → 1.0.24

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,13 +1,25 @@
1
1
  /**
2
- * Find the .gait directory by traversing up from the current working directory
3
- * If GAIT_DATA_PATH is set (from CLI), use that instead
2
+ * Get the base path for .gait directory based on environment
3
+ *
4
+ * Priority order:
5
+ * 1. Explicit basePath parameter
6
+ * 2. Dev mode: GAIT_DEV_ROOT environment variable
7
+ * 3. Production mode: GAIT_DATA_PATH environment variable
8
+ * 4. Fallback: current working directory
4
9
  */
5
- export declare function findGaitDirectory(startDir?: string): Promise<string | null>;
10
+ export declare function getGaitBasePath(basePath?: string): string;
6
11
  /**
7
- * Get the path to a context file, automatically finding the .gait directory
12
+ * Get the full path to a specific .gait subdirectory
8
13
  */
9
- export declare function getContextFilePath(fileName: string): Promise<string | null>;
14
+ export declare function getGaitPath(subdirectory: string, basePath?: string): string;
10
15
  /**
11
- * Get the .gait config to read storage path settings
16
+ * Common .gait subdirectories
12
17
  */
13
- export declare function getGaitConfig(): Promise<any | null>;
18
+ export declare const GAIT_PATHS: {
19
+ readonly proposals: () => string;
20
+ readonly context: () => string;
21
+ readonly agents: () => string;
22
+ readonly resources: () => string;
23
+ readonly chats: () => string;
24
+ readonly config: () => string;
25
+ };
@@ -1,57 +1,45 @@
1
- import { promises as fs } from 'fs';
2
1
  import path from 'path';
3
2
  /**
4
- * Find the .gait directory by traversing up from the current working directory
5
- * If GAIT_DATA_PATH is set (from CLI), use that instead
3
+ * Get the base path for .gait directory based on environment
4
+ *
5
+ * Priority order:
6
+ * 1. Explicit basePath parameter
7
+ * 2. Dev mode: GAIT_DEV_ROOT environment variable
8
+ * 3. Production mode: GAIT_DATA_PATH environment variable
9
+ * 4. Fallback: current working directory
6
10
  */
7
- export async function findGaitDirectory(startDir) {
8
- // If running from CLI (gait serve), use the directory where command was run
9
- if (process.env.GAIT_DATA_PATH) {
10
- const gaitPath = path.join(process.env.GAIT_DATA_PATH, '.gait');
11
- try {
12
- await fs.access(gaitPath);
13
- return gaitPath;
14
- }
15
- catch {
16
- // Fall through to directory traversal
17
- }
11
+ export function getGaitBasePath(basePath) {
12
+ if (basePath) {
13
+ return basePath;
18
14
  }
19
- // Otherwise traverse up from start directory
20
- let currentDir = startDir || process.cwd();
21
- while (currentDir !== path.parse(currentDir).root) {
22
- const gaitPath = path.join(currentDir, '.gait');
23
- try {
24
- await fs.access(gaitPath);
25
- return gaitPath;
26
- }
27
- catch {
28
- currentDir = path.dirname(currentDir);
29
- }
15
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
16
+ // Dev mode: use project root .gait directory
17
+ return process.env.GAIT_DEV_ROOT;
18
+ }
19
+ else if (process.env.GAIT_DATA_PATH) {
20
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
21
+ return path.resolve(process.env.GAIT_DATA_PATH, '.gait');
22
+ }
23
+ else {
24
+ // Fallback: use current directory .gait
25
+ return path.resolve(process.cwd(), '.gait');
30
26
  }
31
- return null;
32
27
  }
33
28
  /**
34
- * Get the path to a context file, automatically finding the .gait directory
29
+ * Get the full path to a specific .gait subdirectory
35
30
  */
36
- export async function getContextFilePath(fileName) {
37
- const gaitDir = await findGaitDirectory();
38
- if (!gaitDir)
39
- return null;
40
- return path.join(gaitDir, 'context', fileName);
31
+ export function getGaitPath(subdirectory, basePath) {
32
+ const base = getGaitBasePath(basePath);
33
+ return path.join(base, subdirectory);
41
34
  }
42
35
  /**
43
- * Get the .gait config to read storage path settings
36
+ * Common .gait subdirectories
44
37
  */
45
- export async function getGaitConfig() {
46
- const gaitDir = await findGaitDirectory();
47
- if (!gaitDir)
48
- return null;
49
- const configPath = path.join(gaitDir, 'config.json');
50
- try {
51
- const config = await fs.readFile(configPath, 'utf-8');
52
- return JSON.parse(config);
53
- }
54
- catch {
55
- return null;
56
- }
57
- }
38
+ export const GAIT_PATHS = {
39
+ proposals: () => getGaitPath('proposals'),
40
+ context: () => getGaitPath('context'),
41
+ agents: () => getGaitPath('agents'),
42
+ resources: () => getGaitPath('resources'),
43
+ chats: () => getGaitPath('chats'),
44
+ config: () => getGaitPath(''),
45
+ };
@@ -2,13 +2,11 @@ import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
3
  import matter from 'gray-matter';
4
4
  import Fuse from 'fuse.js';
5
+ import { getGaitPath } from '../gait-path.js';
5
6
  export class FileStorageAdapter {
6
7
  basePath;
7
8
  constructor(basePath) {
8
- // Use environment variable if available (for web server), otherwise default to .gait
9
- this.basePath = basePath || (process.env.GAIT_DATA_PATH ?
10
- path.join(process.env.GAIT_DATA_PATH, '.gait') :
11
- '.gait');
9
+ this.basePath = basePath || getGaitPath('proposals');
12
10
  }
13
11
  async ensureDirectories() {
14
12
  const dirs = ['proposals', 'specs', 'flags', 'experiments', 'templates'];
@@ -4,9 +4,19 @@ import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  const app = new Hono();
6
6
  function getAgentsPath() {
7
- const basePath = process.env.GAIT_DATA_PATH ?
8
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
- path.resolve(process.cwd(), '.gait');
7
+ let basePath;
8
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
+ // Dev mode: use project root .gait directory
10
+ basePath = process.env.GAIT_DEV_ROOT;
11
+ }
12
+ else if (process.env.GAIT_DATA_PATH) {
13
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ }
16
+ else {
17
+ // Fallback: use current directory .gait
18
+ basePath = path.resolve(process.cwd(), '.gait');
19
+ }
10
20
  return path.join(basePath, 'agents');
11
21
  }
12
22
  function generateFilename(name) {
@@ -4,9 +4,19 @@ import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  const app = new Hono();
6
6
  function getAgentsPath() {
7
- const basePath = process.env.GAIT_DATA_PATH ?
8
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
- path.resolve(process.cwd(), '.gait');
7
+ let basePath;
8
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
+ // Dev mode: use project root .gait directory
10
+ basePath = process.env.GAIT_DEV_ROOT;
11
+ }
12
+ else if (process.env.GAIT_DATA_PATH) {
13
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ }
16
+ else {
17
+ // Fallback: use current directory .gait
18
+ basePath = path.resolve(process.cwd(), '.gait');
19
+ }
10
20
  return path.join(basePath, 'agents');
11
21
  }
12
22
  function generateFilename(name) {
@@ -1,6 +1,22 @@
1
1
  import { readFile, unlink } from "fs/promises";
2
- import { join } from "path";
3
- const CHATS_DIR = join(process.cwd(), ".gait", "chats");
2
+ import { join, resolve } from "path";
3
+ function getChatsPath() {
4
+ let basePath;
5
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
+ // Dev mode: use project root .gait directory
7
+ basePath = process.env.GAIT_DEV_ROOT;
8
+ }
9
+ else if (process.env.GAIT_DATA_PATH) {
10
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
11
+ basePath = resolve(process.env.GAIT_DATA_PATH, '.gait');
12
+ }
13
+ else {
14
+ // Fallback: use current directory .gait
15
+ basePath = resolve(process.cwd(), '.gait');
16
+ }
17
+ return join(basePath, 'chats');
18
+ }
19
+ const CHATS_DIR = getChatsPath();
4
20
  export async function GET(c) {
5
21
  try {
6
22
  const id = c.req.param('id');
@@ -1,6 +1,22 @@
1
1
  import { writeFile, readdir, readFile, mkdir } from "fs/promises";
2
- import { join } from "path";
3
- const CHATS_DIR = join(process.cwd(), ".gait", "chats");
2
+ import { join, resolve } from "path";
3
+ function getChatsPath() {
4
+ let basePath;
5
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
+ // Dev mode: use project root .gait directory
7
+ basePath = process.env.GAIT_DEV_ROOT;
8
+ }
9
+ else if (process.env.GAIT_DATA_PATH) {
10
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
11
+ basePath = resolve(process.env.GAIT_DATA_PATH, '.gait');
12
+ }
13
+ else {
14
+ // Fallback: use current directory .gait
15
+ basePath = resolve(process.cwd(), '.gait');
16
+ }
17
+ return join(basePath, 'chats');
18
+ }
19
+ const CHATS_DIR = getChatsPath();
4
20
  export async function GET(c) {
5
21
  try {
6
22
  // Ensure chats directory exists
@@ -2,9 +2,19 @@ import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
3
  async function getConfigPath() {
4
4
  // Use the same approach as FileStorageAdapter for consistency
5
- const basePath = process.env.GAIT_DATA_PATH ?
6
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
7
- path.resolve(process.cwd(), '.gait');
5
+ let basePath;
6
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
7
+ // Dev mode: use project root .gait directory
8
+ basePath = process.env.GAIT_DEV_ROOT;
9
+ }
10
+ else if (process.env.GAIT_DATA_PATH) {
11
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
12
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
13
+ }
14
+ else {
15
+ // Fallback: use current directory .gait
16
+ basePath = path.resolve(process.cwd(), '.gait');
17
+ }
8
18
  return path.join(basePath, 'config.json');
9
19
  }
10
20
  export async function GET(c) {
@@ -4,9 +4,19 @@ import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  const app = new Hono();
6
6
  function getArchitecturePath() {
7
- const basePath = process.env.GAIT_DATA_PATH ?
8
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
- path.resolve(process.cwd(), '.gait');
7
+ let basePath;
8
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
+ // Dev mode: use project root .gait directory
10
+ basePath = process.env.GAIT_DEV_ROOT;
11
+ }
12
+ else if (process.env.GAIT_DATA_PATH) {
13
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ }
16
+ else {
17
+ // Fallback: use current directory .gait
18
+ basePath = path.resolve(process.cwd(), '.gait');
19
+ }
10
20
  return path.join(basePath, 'context');
11
21
  }
12
22
  /**
@@ -4,9 +4,19 @@ import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  const app = new Hono();
6
6
  function getKnowledgePath() {
7
- const basePath = process.env.GAIT_DATA_PATH ?
8
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
- path.resolve(process.cwd(), '.gait');
7
+ let basePath;
8
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
+ // Dev mode: use project root .gait directory
10
+ basePath = process.env.GAIT_DEV_ROOT;
11
+ }
12
+ else if (process.env.GAIT_DATA_PATH) {
13
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ }
16
+ else {
17
+ // Fallback: use current directory .gait
18
+ basePath = path.resolve(process.cwd(), '.gait');
19
+ }
10
20
  return path.join(basePath, 'context', 'knowledge');
11
21
  }
12
22
  function generateFilename(title) {
@@ -5,9 +5,19 @@ import matter from 'gray-matter';
5
5
  import filenameRoute from './[filename]/index.js';
6
6
  const app = new Hono();
7
7
  function getKnowledgePath() {
8
- const basePath = process.env.GAIT_DATA_PATH ?
9
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
10
- path.resolve(process.cwd(), '.gait');
8
+ let basePath;
9
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
10
+ // Dev mode: use project root .gait directory
11
+ basePath = process.env.GAIT_DEV_ROOT;
12
+ }
13
+ else if (process.env.GAIT_DATA_PATH) {
14
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
15
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
16
+ }
17
+ else {
18
+ // Fallback: use current directory .gait
19
+ basePath = path.resolve(process.cwd(), '.gait');
20
+ }
11
21
  return path.join(basePath, 'context', 'knowledge');
12
22
  }
13
23
  function generateFilename(title) {
@@ -4,9 +4,19 @@ import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  const app = new Hono();
6
6
  function getProjectPath() {
7
- const basePath = process.env.GAIT_DATA_PATH ?
8
- path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
- path.resolve(process.cwd(), '.gait');
7
+ let basePath;
8
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
+ // Dev mode: use project root .gait directory
10
+ basePath = process.env.GAIT_DEV_ROOT;
11
+ }
12
+ else if (process.env.GAIT_DATA_PATH) {
13
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ }
16
+ else {
17
+ // Fallback: use current directory .gait
18
+ basePath = path.resolve(process.cwd(), '.gait');
19
+ }
10
20
  return path.join(basePath, 'context');
11
21
  }
12
22
  /**
@@ -1,6 +1,22 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
- const RESOURCES_DIR = '.gait/resources';
3
+ function getResourcesPath() {
4
+ let basePath;
5
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
+ // Dev mode: use project root .gait directory
7
+ basePath = process.env.GAIT_DEV_ROOT;
8
+ }
9
+ else if (process.env.GAIT_DATA_PATH) {
10
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
11
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
12
+ }
13
+ else {
14
+ // Fallback: use current directory .gait
15
+ basePath = path.resolve(process.cwd(), '.gait');
16
+ }
17
+ return path.join(basePath, 'resources');
18
+ }
19
+ const RESOURCES_DIR = getResourcesPath();
4
20
  const FILES_DIR = path.join(RESOURCES_DIR, 'files');
5
21
  const METADATA_DIR = path.join(RESOURCES_DIR, 'metadata');
6
22
  async function getResourceMetadata(id) {
@@ -1,6 +1,22 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
- const RESOURCES_DIR = '.gait/resources';
3
+ function getResourcesPath() {
4
+ let basePath;
5
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
+ // Dev mode: use project root .gait directory
7
+ basePath = process.env.GAIT_DEV_ROOT;
8
+ }
9
+ else if (process.env.GAIT_DATA_PATH) {
10
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
11
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
12
+ }
13
+ else {
14
+ // Fallback: use current directory .gait
15
+ basePath = path.resolve(process.cwd(), '.gait');
16
+ }
17
+ return path.join(basePath, 'resources');
18
+ }
19
+ const RESOURCES_DIR = getResourcesPath();
4
20
  const METADATA_DIR = path.join(RESOURCES_DIR, 'metadata');
5
21
  const THUMBNAILS_DIR = path.join(RESOURCES_DIR, 'thumbnails');
6
22
  async function getResourceMetadata(id) {
@@ -4,7 +4,23 @@ import path from 'path';
4
4
  function generateId() {
5
5
  return `res-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
6
6
  }
7
- const RESOURCES_DIR = '.gait/resources';
7
+ function getResourcesPath() {
8
+ let basePath;
9
+ if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
10
+ // Dev mode: use project root .gait directory
11
+ basePath = process.env.GAIT_DEV_ROOT;
12
+ }
13
+ else if (process.env.GAIT_DATA_PATH) {
14
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
15
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
16
+ }
17
+ else {
18
+ // Fallback: use current directory .gait
19
+ basePath = path.resolve(process.cwd(), '.gait');
20
+ }
21
+ return path.join(basePath, 'resources');
22
+ }
23
+ const RESOURCES_DIR = getResourcesPath();
8
24
  const FILES_DIR = path.join(RESOURCES_DIR, 'files');
9
25
  const METADATA_DIR = path.join(RESOURCES_DIR, 'metadata');
10
26
  const THUMBNAILS_DIR = path.join(RESOURCES_DIR, 'thumbnails');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -12,7 +12,7 @@
12
12
  "static/**/*"
13
13
  ],
14
14
  "scripts": {
15
- "dev": "tsx watch src/server.ts",
15
+ "dev": "NODE_ENV=development GAIT_DEV_ROOT=../../.gait tsx watch src/server.ts",
16
16
  "build": "tsc",
17
17
  "build:bundle": "tsc && node scripts/bundle-frontend.js",
18
18
  "start": "node dist/server-with-static.js",
@@ -32,8 +32,8 @@
32
32
  "dependencies": {
33
33
  "@hono/node-server": "^1.13.7",
34
34
  "@hono/node-ws": "^1.0.6",
35
- "@lovelybunch/core": "^1.0.22",
36
- "@lovelybunch/types": "^1.0.22",
35
+ "@lovelybunch/core": "^1.0.24",
36
+ "@lovelybunch/types": "^1.0.24",
37
37
  "dotenv": "^17.2.1",
38
38
  "fuse.js": "^7.0.0",
39
39
  "gray-matter": "^4.0.3",