pi-freeflow 1.4.2 → 1.4.4
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.
- package/README.md +323 -279
- package/package.json +1 -1
- package/src/catalog.ts +250 -207
- package/src/commands.ts +670 -618
- package/src/config.ts +144 -145
- package/src/deploy.ts +496 -126
- package/src/index.ts +301 -277
- package/src/models.ts +355 -399
- package/src/proxy.ts +493 -500
- package/src/relay.ts +213 -210
- package/src/stream-pipe.ts +265 -263
package/src/config.ts
CHANGED
|
@@ -1,145 +1,144 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration and path resolution for pi-freeflow
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { randomUUID } from "node:crypto";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
import type { Upstream } from "./types.ts";
|
|
10
|
-
|
|
11
|
-
// ── Upstream endpoints ──────────────────────────────────────────────
|
|
12
|
-
export const UPSTREAM_OPENCODE = "https://opencode.ai/zen";
|
|
13
|
-
export const KILO_CHAT_URL = "https://api.kilo.ai/api/gateway/chat/completions";
|
|
14
|
-
export const OPENCODE_API_URL = `${UPSTREAM_OPENCODE}/v1`;
|
|
15
|
-
|
|
16
|
-
// ── Network & Server defaults ───────────────────────────────────────
|
|
17
|
-
export const DEFAULT_PORT = 18080;
|
|
18
|
-
export const HOST = "127.0.0.1";
|
|
19
|
-
export const DEFAULT_HOST = "127.0.0.1";
|
|
20
|
-
|
|
21
|
-
export function resolvePort(): number {
|
|
22
|
-
const envPort = process.env.FREEFLOW_PORT;
|
|
23
|
-
if (envPort) {
|
|
24
|
-
const parsed = Number(envPort);
|
|
25
|
-
if (Number.isFinite(parsed) && parsed > 0 && parsed <= 65535) {
|
|
26
|
-
return parsed;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return DEFAULT_PORT;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const PORT = resolvePort();
|
|
33
|
-
|
|
34
|
-
// ── OpenCode client headers ─────────────────────────────────────────
|
|
35
|
-
export const OPENCODE_USER_AGENT = "opencode/latest/1.14.50/cli";
|
|
36
|
-
export const OPENCODE_CLIENT = "cli";
|
|
37
|
-
export const OPENCODE_PROJECT = "default";
|
|
38
|
-
export const OPENCODE_SESSION = randomUUID();
|
|
39
|
-
|
|
40
|
-
export function opencodeHeaders(): Record<string, string> {
|
|
41
|
-
return {
|
|
42
|
-
"User-Agent": OPENCODE_USER_AGENT,
|
|
43
|
-
"x-opencode-client": OPENCODE_CLIENT,
|
|
44
|
-
"x-opencode-project": OPENCODE_PROJECT,
|
|
45
|
-
"x-opencode-session": OPENCODE_SESSION,
|
|
46
|
-
"x-opencode-request": randomUUID(),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ── Relay and Deployment constants ──────────────────────────────────
|
|
51
|
-
export const DEFAULT_RELAY_URL = "";
|
|
52
|
-
export const VERCEL_API = "https://api.vercel.com";
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
export const
|
|
57
|
-
export const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export const
|
|
68
|
-
export const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"x-forwarded-
|
|
76
|
-
"x-forwarded-
|
|
77
|
-
"x-
|
|
78
|
-
"x-
|
|
79
|
-
"x-
|
|
80
|
-
"
|
|
81
|
-
"cookie",
|
|
82
|
-
"
|
|
83
|
-
"proxy-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export const
|
|
143
|
-
export const
|
|
144
|
-
export const
|
|
145
|
-
export const DEBUG_STATE_FILE = resolveDebugStatePath();
|
|
1
|
+
/**
|
|
2
|
+
* Configuration and path resolution for pi-freeflow
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import type { Upstream } from "./types.ts";
|
|
10
|
+
|
|
11
|
+
// ── Upstream endpoints ──────────────────────────────────────────────
|
|
12
|
+
export const UPSTREAM_OPENCODE = "https://opencode.ai/zen";
|
|
13
|
+
export const KILO_CHAT_URL = "https://api.kilo.ai/api/gateway/chat/completions";
|
|
14
|
+
export const OPENCODE_API_URL = `${UPSTREAM_OPENCODE}/v1`;
|
|
15
|
+
|
|
16
|
+
// ── Network & Server defaults ───────────────────────────────────────
|
|
17
|
+
export const DEFAULT_PORT = 18080;
|
|
18
|
+
export const HOST = "127.0.0.1";
|
|
19
|
+
export const DEFAULT_HOST = "127.0.0.1";
|
|
20
|
+
|
|
21
|
+
export function resolvePort(): number {
|
|
22
|
+
const envPort = process.env.FREEFLOW_PORT;
|
|
23
|
+
if (envPort) {
|
|
24
|
+
const parsed = Number(envPort);
|
|
25
|
+
if (Number.isFinite(parsed) && parsed > 0 && parsed <= 65535) {
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return DEFAULT_PORT;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const PORT = resolvePort();
|
|
33
|
+
|
|
34
|
+
// ── OpenCode client headers ─────────────────────────────────────────
|
|
35
|
+
export const OPENCODE_USER_AGENT = "opencode/latest/1.14.50/cli";
|
|
36
|
+
export const OPENCODE_CLIENT = "cli";
|
|
37
|
+
export const OPENCODE_PROJECT = "default";
|
|
38
|
+
export const OPENCODE_SESSION = randomUUID();
|
|
39
|
+
|
|
40
|
+
export function opencodeHeaders(): Record<string, string> {
|
|
41
|
+
return {
|
|
42
|
+
"User-Agent": OPENCODE_USER_AGENT,
|
|
43
|
+
"x-opencode-client": OPENCODE_CLIENT,
|
|
44
|
+
"x-opencode-project": OPENCODE_PROJECT,
|
|
45
|
+
"x-opencode-session": OPENCODE_SESSION,
|
|
46
|
+
"x-opencode-request": randomUUID(),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Relay and Deployment constants ──────────────────────────────────
|
|
51
|
+
export const DEFAULT_RELAY_URL = "";
|
|
52
|
+
export const VERCEL_API = "https://api.vercel.com";
|
|
53
|
+
|
|
54
|
+
// ── Catalog & Logging constants ─────────────────────────────────────
|
|
55
|
+
export const CATALOG_CACHE_TTL_MS = 86_400_000; // 24 hours — delegate to host fetchDynamicModels
|
|
56
|
+
export const LOG_MAX_BYTES = 5 * 1024 * 1024; // 5MB
|
|
57
|
+
export const LOG_MAX_FILES = 3;
|
|
58
|
+
|
|
59
|
+
// ── Rate Limit Maxima ───────────────────────────────────────────────
|
|
60
|
+
export const RATE_LIMIT_MAX: Record<Upstream, number> = {
|
|
61
|
+
opencode: 200, // public free quota: requests per UTC day per IP
|
|
62
|
+
kilo: 200, // documented gateway quota: requests per 1-hour window per IP
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// ── Whitelists & Security ───────────────────────────────────────────
|
|
66
|
+
export const ALLOWED_PATH_PATTERN = /^\/v1\/[a-zA-Z0-9/_.,\-?&=]*$/;
|
|
67
|
+
export const PATH_TRAVERSAL_PATTERN = /\.\./;
|
|
68
|
+
export const ALLOWED_METHODS = new Set(["GET", "POST", "OPTIONS", "HEAD"]);
|
|
69
|
+
|
|
70
|
+
export const STRIP_HEADERS = new Set([
|
|
71
|
+
"authorization",
|
|
72
|
+
"host",
|
|
73
|
+
"content-length",
|
|
74
|
+
"x-forwarded-for",
|
|
75
|
+
"x-forwarded-host",
|
|
76
|
+
"x-forwarded-proto",
|
|
77
|
+
"x-real-ip",
|
|
78
|
+
"x-client-ip",
|
|
79
|
+
"x-originate-ip",
|
|
80
|
+
"cookie",
|
|
81
|
+
"set-cookie",
|
|
82
|
+
"proxy-connection",
|
|
83
|
+
"proxy-authorization",
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
// ── File Path Resolvers ─────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
export function resolveRelayStatePath(): string {
|
|
89
|
+
try {
|
|
90
|
+
return path.join(homedir(), ".pi", "agent", "pi-freeflow-relay-state.json");
|
|
91
|
+
} catch {
|
|
92
|
+
return path.join(
|
|
93
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
94
|
+
"..",
|
|
95
|
+
".relay-state.json",
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function resolveLogFilePath(): string {
|
|
101
|
+
try {
|
|
102
|
+
return path.join(homedir(), ".pi", "agent", "pi-freeflow.log");
|
|
103
|
+
} catch {
|
|
104
|
+
return path.join(
|
|
105
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
106
|
+
"..",
|
|
107
|
+
"pi-freeflow.log",
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function resolveCatalogCachePath(): string {
|
|
113
|
+
try {
|
|
114
|
+
return path.join(
|
|
115
|
+
homedir(),
|
|
116
|
+
".pi",
|
|
117
|
+
"agent",
|
|
118
|
+
"pi-freeflow-catalog-cache.json",
|
|
119
|
+
);
|
|
120
|
+
} catch {
|
|
121
|
+
return path.join(
|
|
122
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
123
|
+
"..",
|
|
124
|
+
".catalog-cache.json",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function resolveDebugStatePath(): string {
|
|
130
|
+
try {
|
|
131
|
+
return path.join(homedir(), ".pi", "agent", "pi-freeflow-debug.json");
|
|
132
|
+
} catch {
|
|
133
|
+
return path.join(
|
|
134
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
135
|
+
"..",
|
|
136
|
+
".debug-state.json",
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const RELAY_STATE_FILE = resolveRelayStatePath();
|
|
142
|
+
export const LOG_FILE = resolveLogFilePath();
|
|
143
|
+
export const CATALOG_CACHE_FILE = resolveCatalogCachePath();
|
|
144
|
+
export const DEBUG_STATE_FILE = resolveDebugStatePath();
|