pi-kot 0.1.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.
Files changed (222) hide show
  1. package/README.md +30 -0
  2. package/bin/pi-kot.mjs +125 -0
  3. package/dist/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  4. package/dist/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  5. package/dist/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  6. package/dist/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  7. package/dist/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  8. package/dist/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  9. package/dist/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  10. package/dist/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  11. package/dist/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  12. package/dist/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  13. package/dist/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  14. package/dist/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  15. package/dist/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  16. package/dist/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  17. package/dist/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  18. package/dist/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  19. package/dist/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  20. package/dist/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  21. package/dist/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  22. package/dist/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  23. package/dist/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  24. package/dist/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  25. package/dist/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  26. package/dist/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  27. package/dist/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  28. package/dist/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  29. package/dist/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  30. package/dist/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  31. package/dist/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  32. package/dist/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  33. package/dist/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  34. package/dist/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  35. package/dist/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  36. package/dist/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  37. package/dist/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  38. package/dist/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  39. package/dist/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  40. package/dist/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  41. package/dist/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  42. package/dist/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  43. package/dist/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  44. package/dist/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  45. package/dist/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  46. package/dist/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  47. package/dist/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  48. package/dist/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  49. package/dist/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  50. package/dist/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  51. package/dist/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  52. package/dist/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  53. package/dist/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  54. package/dist/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  55. package/dist/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  56. package/dist/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  57. package/dist/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  58. package/dist/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  59. package/dist/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  60. package/dist/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  61. package/dist/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  62. package/dist/client/assets/index-UJgsBs6a.js +361 -0
  63. package/dist/client/assets/index-UJgsBs6a.js.map +1 -0
  64. package/dist/client/assets/index-ZuTc_0YY.css +1 -0
  65. package/dist/client/index.html +14 -0
  66. package/dist/server/ask-user-question/envelope.d.ts +11 -0
  67. package/dist/server/ask-user-question/envelope.d.ts.map +1 -0
  68. package/dist/server/ask-user-question/envelope.js +41 -0
  69. package/dist/server/ask-user-question/envelope.js.map +1 -0
  70. package/dist/server/ask-user-question/prompt-strings.d.ts +4 -0
  71. package/dist/server/ask-user-question/prompt-strings.d.ts.map +1 -0
  72. package/dist/server/ask-user-question/prompt-strings.js +18 -0
  73. package/dist/server/ask-user-question/prompt-strings.js.map +1 -0
  74. package/dist/server/ask-user-question/registry.d.ts +39 -0
  75. package/dist/server/ask-user-question/registry.d.ts.map +1 -0
  76. package/dist/server/ask-user-question/registry.js +124 -0
  77. package/dist/server/ask-user-question/registry.js.map +1 -0
  78. package/dist/server/ask-user-question/tool.d.ts +4 -0
  79. package/dist/server/ask-user-question/tool.d.ts.map +1 -0
  80. package/dist/server/ask-user-question/tool.js +68 -0
  81. package/dist/server/ask-user-question/tool.js.map +1 -0
  82. package/dist/server/ask-user-question/types.d.ts +50 -0
  83. package/dist/server/ask-user-question/types.d.ts.map +1 -0
  84. package/dist/server/ask-user-question/types.js +7 -0
  85. package/dist/server/ask-user-question/types.js.map +1 -0
  86. package/dist/server/ask-user-question/validate.d.ts +3 -0
  87. package/dist/server/ask-user-question/validate.d.ts.map +1 -0
  88. package/dist/server/ask-user-question/validate.js +67 -0
  89. package/dist/server/ask-user-question/validate.js.map +1 -0
  90. package/dist/server/config-manager.d.ts +47 -0
  91. package/dist/server/config-manager.d.ts.map +1 -0
  92. package/dist/server/config-manager.js +182 -0
  93. package/dist/server/config-manager.js.map +1 -0
  94. package/dist/server/config.d.ts +20 -0
  95. package/dist/server/config.d.ts.map +1 -0
  96. package/dist/server/config.js +58 -0
  97. package/dist/server/config.js.map +1 -0
  98. package/dist/server/extension-manager.d.ts +70 -0
  99. package/dist/server/extension-manager.d.ts.map +1 -0
  100. package/dist/server/extension-manager.js +401 -0
  101. package/dist/server/extension-manager.js.map +1 -0
  102. package/dist/server/extension-ui-bridge.d.ts +35 -0
  103. package/dist/server/extension-ui-bridge.d.ts.map +1 -0
  104. package/dist/server/extension-ui-bridge.js +228 -0
  105. package/dist/server/extension-ui-bridge.js.map +1 -0
  106. package/dist/server/file-manager.d.ts +79 -0
  107. package/dist/server/file-manager.d.ts.map +1 -0
  108. package/dist/server/file-manager.js +526 -0
  109. package/dist/server/file-manager.js.map +1 -0
  110. package/dist/server/file-searcher.d.ts +29 -0
  111. package/dist/server/file-searcher.d.ts.map +1 -0
  112. package/dist/server/file-searcher.js +318 -0
  113. package/dist/server/file-searcher.js.map +1 -0
  114. package/dist/server/git-clone.d.ts +56 -0
  115. package/dist/server/git-clone.d.ts.map +1 -0
  116. package/dist/server/git-clone.js +173 -0
  117. package/dist/server/git-clone.js.map +1 -0
  118. package/dist/server/index.d.ts +22 -0
  119. package/dist/server/index.d.ts.map +1 -0
  120. package/dist/server/index.js +196 -0
  121. package/dist/server/index.js.map +1 -0
  122. package/dist/server/lifecycle-notifications.d.ts +28 -0
  123. package/dist/server/lifecycle-notifications.d.ts.map +1 -0
  124. package/dist/server/lifecycle-notifications.js +38 -0
  125. package/dist/server/lifecycle-notifications.js.map +1 -0
  126. package/dist/server/orchestration/config.d.ts +5 -0
  127. package/dist/server/orchestration/config.d.ts.map +1 -0
  128. package/dist/server/orchestration/config.js +35 -0
  129. package/dist/server/orchestration/config.js.map +1 -0
  130. package/dist/server/orchestration/event-bridge.d.ts +32 -0
  131. package/dist/server/orchestration/event-bridge.d.ts.map +1 -0
  132. package/dist/server/orchestration/event-bridge.js +110 -0
  133. package/dist/server/orchestration/event-bridge.js.map +1 -0
  134. package/dist/server/orchestration/inbox.d.ts +9 -0
  135. package/dist/server/orchestration/inbox.d.ts.map +1 -0
  136. package/dist/server/orchestration/inbox.js +186 -0
  137. package/dist/server/orchestration/inbox.js.map +1 -0
  138. package/dist/server/orchestration/init.d.ts +2 -0
  139. package/dist/server/orchestration/init.d.ts.map +1 -0
  140. package/dist/server/orchestration/init.js +22 -0
  141. package/dist/server/orchestration/init.js.map +1 -0
  142. package/dist/server/orchestration/store.d.ts +33 -0
  143. package/dist/server/orchestration/store.d.ts.map +1 -0
  144. package/dist/server/orchestration/store.js +331 -0
  145. package/dist/server/orchestration/store.js.map +1 -0
  146. package/dist/server/orchestration/tools.d.ts +15 -0
  147. package/dist/server/orchestration/tools.d.ts.map +1 -0
  148. package/dist/server/orchestration/tools.js +621 -0
  149. package/dist/server/orchestration/tools.js.map +1 -0
  150. package/dist/server/orchestration/types.d.ts +68 -0
  151. package/dist/server/orchestration/types.d.ts.map +1 -0
  152. package/dist/server/orchestration/types.js +43 -0
  153. package/dist/server/orchestration/types.js.map +1 -0
  154. package/dist/server/orchestration/worker-lifecycle.d.ts +15 -0
  155. package/dist/server/orchestration/worker-lifecycle.d.ts.map +1 -0
  156. package/dist/server/orchestration/worker-lifecycle.js +45 -0
  157. package/dist/server/orchestration/worker-lifecycle.js.map +1 -0
  158. package/dist/server/project-manager.d.ts +25 -0
  159. package/dist/server/project-manager.d.ts.map +1 -0
  160. package/dist/server/project-manager.js +157 -0
  161. package/dist/server/project-manager.js.map +1 -0
  162. package/dist/server/routes/_schemas.d.ts +16 -0
  163. package/dist/server/routes/_schemas.d.ts.map +1 -0
  164. package/dist/server/routes/_schemas.js +12 -0
  165. package/dist/server/routes/_schemas.js.map +1 -0
  166. package/dist/server/routes/ask-user-question.d.ts +3 -0
  167. package/dist/server/routes/ask-user-question.d.ts.map +1 -0
  168. package/dist/server/routes/ask-user-question.js +105 -0
  169. package/dist/server/routes/ask-user-question.js.map +1 -0
  170. package/dist/server/routes/auth.d.ts +7 -0
  171. package/dist/server/routes/auth.d.ts.map +1 -0
  172. package/dist/server/routes/auth.js +126 -0
  173. package/dist/server/routes/auth.js.map +1 -0
  174. package/dist/server/routes/config.d.ts +3 -0
  175. package/dist/server/routes/config.d.ts.map +1 -0
  176. package/dist/server/routes/config.js +203 -0
  177. package/dist/server/routes/config.js.map +1 -0
  178. package/dist/server/routes/control.d.ts +3 -0
  179. package/dist/server/routes/control.d.ts.map +1 -0
  180. package/dist/server/routes/control.js +180 -0
  181. package/dist/server/routes/control.js.map +1 -0
  182. package/dist/server/routes/extension-commands.d.ts +22 -0
  183. package/dist/server/routes/extension-commands.d.ts.map +1 -0
  184. package/dist/server/routes/extension-commands.js +178 -0
  185. package/dist/server/routes/extension-commands.js.map +1 -0
  186. package/dist/server/routes/extensions.d.ts +8 -0
  187. package/dist/server/routes/extensions.d.ts.map +1 -0
  188. package/dist/server/routes/extensions.js +169 -0
  189. package/dist/server/routes/extensions.js.map +1 -0
  190. package/dist/server/routes/files.d.ts +3 -0
  191. package/dist/server/routes/files.d.ts.map +1 -0
  192. package/dist/server/routes/files.js +549 -0
  193. package/dist/server/routes/files.js.map +1 -0
  194. package/dist/server/routes/orchestration.d.ts +3 -0
  195. package/dist/server/routes/orchestration.d.ts.map +1 -0
  196. package/dist/server/routes/orchestration.js +251 -0
  197. package/dist/server/routes/orchestration.js.map +1 -0
  198. package/dist/server/routes/projects.d.ts +3 -0
  199. package/dist/server/routes/projects.d.ts.map +1 -0
  200. package/dist/server/routes/projects.js +412 -0
  201. package/dist/server/routes/projects.js.map +1 -0
  202. package/dist/server/routes/prompt.d.ts +3 -0
  203. package/dist/server/routes/prompt.d.ts.map +1 -0
  204. package/dist/server/routes/prompt.js +192 -0
  205. package/dist/server/routes/prompt.js.map +1 -0
  206. package/dist/server/routes/sessions.d.ts +3 -0
  207. package/dist/server/routes/sessions.d.ts.map +1 -0
  208. package/dist/server/routes/sessions.js +581 -0
  209. package/dist/server/routes/sessions.js.map +1 -0
  210. package/dist/server/routes/stream.d.ts +3 -0
  211. package/dist/server/routes/stream.d.ts.map +1 -0
  212. package/dist/server/routes/stream.js +109 -0
  213. package/dist/server/routes/stream.js.map +1 -0
  214. package/dist/server/session-registry.d.ts +151 -0
  215. package/dist/server/session-registry.d.ts.map +1 -0
  216. package/dist/server/session-registry.js +655 -0
  217. package/dist/server/session-registry.js.map +1 -0
  218. package/dist/server/sse-bridge.d.ts +31 -0
  219. package/dist/server/sse-bridge.d.ts.map +1 -0
  220. package/dist/server/sse-bridge.js +126 -0
  221. package/dist/server/sse-bridge.js.map +1 -0
  222. package/package.json +69 -0
@@ -0,0 +1,126 @@
1
+ import { randomBytes, timingSafeEqual, createHash } from "node:crypto";
2
+ import { config } from "../config.js";
3
+ /**
4
+ * Minimal JWT-like token for auth. Uses HMAC-SHA256 with a server-generated
5
+ * secret (rotated on restart since sessions are ephemeral).
6
+ *
7
+ * Simplified from pi-forge's auth.ts — Phase 1a uses a basic API key or
8
+ * JWT pattern. In production, pi-forge uses proper jsonwebtoken + scrypt.
9
+ */
10
+ const TOKEN_SECRET = randomBytes(32).toString("hex");
11
+ function signHmac(payload) {
12
+ const hmac = createHash("sha256")
13
+ .update(payload + TOKEN_SECRET)
14
+ .digest("hex");
15
+ return `${Buffer.from(payload).toString("base64url")}.${hmac}`;
16
+ }
17
+ export function verifyHmac(token) {
18
+ const dot = token.lastIndexOf(".");
19
+ if (dot === -1)
20
+ return undefined;
21
+ const payloadB64 = token.slice(0, dot);
22
+ const sig = token.slice(dot + 1);
23
+ const payload = Buffer.from(payloadB64, "base64url").toString("utf8");
24
+ const expected = createHash("sha256")
25
+ .update(payload + TOKEN_SECRET)
26
+ .digest("hex");
27
+ if (sig.length !== expected.length)
28
+ return undefined;
29
+ try {
30
+ if (!timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
31
+ return undefined;
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ return payload;
37
+ }
38
+ export function extractBearer(header) {
39
+ if (header === undefined)
40
+ return undefined;
41
+ const match = header.match(/^Bearer\s+(.+)$/i);
42
+ return match?.[1];
43
+ }
44
+ export function authEnabled() {
45
+ return config.uiPassword !== undefined || config.apiKey !== undefined;
46
+ }
47
+ export const healthRoutes = async (fastify) => {
48
+ // GET /api/v1/health — public, no auth
49
+ fastify.get("/health", {
50
+ config: { public: true },
51
+ schema: {
52
+ description: "Health check — no auth required.",
53
+ tags: ["health"],
54
+ security: [],
55
+ response: {
56
+ 200: {
57
+ type: "object",
58
+ required: ["status"],
59
+ properties: {
60
+ status: { type: "string", enum: ["ok"] },
61
+ activeSessions: { type: "integer", minimum: 0 },
62
+ },
63
+ },
64
+ },
65
+ },
66
+ }, async () => {
67
+ const { sessionCount } = await import("../session-registry.js");
68
+ return { status: "ok", activeSessions: sessionCount() };
69
+ });
70
+ };
71
+ export const authRoutes = async (fastify) => {
72
+ // GET /api/v1/auth/status — public
73
+ fastify.get("/auth/status", {
74
+ config: { public: true },
75
+ schema: {
76
+ description: "Whether auth is enabled.",
77
+ tags: ["auth"],
78
+ security: [],
79
+ response: {
80
+ 200: {
81
+ type: "object",
82
+ required: ["authEnabled"],
83
+ properties: { authEnabled: { type: "boolean" } },
84
+ },
85
+ },
86
+ },
87
+ }, async () => ({ authEnabled: authEnabled() }));
88
+ // POST /api/v1/auth/login — public (rate-limited)
89
+ fastify.post("/auth/login", {
90
+ config: { public: true },
91
+ schema: {
92
+ description: "Login with password → JWT token.",
93
+ tags: ["auth"],
94
+ security: [],
95
+ body: {
96
+ type: "object",
97
+ required: ["password"],
98
+ properties: { password: { type: "string" } },
99
+ },
100
+ response: {
101
+ 200: {
102
+ type: "object",
103
+ required: ["token"],
104
+ properties: { token: { type: "string" } },
105
+ },
106
+ 401: {
107
+ type: "object",
108
+ properties: { error: { type: "string" } },
109
+ },
110
+ },
111
+ },
112
+ }, async (req, reply) => {
113
+ if (!authEnabled()) {
114
+ return reply.code(401).send({ error: "auth_not_configured" });
115
+ }
116
+ const { password } = req.body;
117
+ const valid = (config.uiPassword !== undefined && password === config.uiPassword) ||
118
+ (config.apiKey !== undefined && password === config.apiKey);
119
+ if (!valid) {
120
+ return reply.code(401).send({ error: "invalid_credentials" });
121
+ }
122
+ const token = signHmac(`user:${Date.now()}`);
123
+ return { token };
124
+ });
125
+ };
126
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type FastifyPluginAsync } from "fastify";
2
+ export declare const configRoutes: FastifyPluginAsync;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAyDlD,eAAO,MAAM,YAAY,EAAE,kBAqM1B,CAAC"}
@@ -0,0 +1,203 @@
1
+ import { liveProvidersListing, readAuthSummary, writeApiKey, removeApiKey, readSettings, updateSettings, readModelsJsonRedacted, writeModelsJson, AuthProviderNotFoundError, } from "../config-manager.js";
2
+ // ── Schema ────────────────────────────────────────────────────────────────
3
+ const errorSchema = {
4
+ type: "object",
5
+ required: ["error"],
6
+ properties: { error: { type: "string" } },
7
+ };
8
+ const authSummarySchema = {
9
+ type: "object",
10
+ required: ["providers"],
11
+ properties: {
12
+ providers: {
13
+ type: "object",
14
+ additionalProperties: {
15
+ type: "object",
16
+ required: ["configured"],
17
+ properties: {
18
+ configured: { type: "boolean" },
19
+ source: { type: "string" },
20
+ label: { type: "string" },
21
+ },
22
+ },
23
+ },
24
+ },
25
+ };
26
+ const settingsSchema = {
27
+ type: "object",
28
+ additionalProperties: true,
29
+ };
30
+ const modelsJsonSchema = {
31
+ type: "object",
32
+ required: ["providers"],
33
+ additionalProperties: true,
34
+ properties: {
35
+ providers: { type: "object", additionalProperties: true },
36
+ },
37
+ };
38
+ // ── Routes ────────────────────────────────────────────────────────────────
39
+ export const configRoutes = async (fastify) => {
40
+ // ── Providers (live listing) ──────────────────────────────────────────
41
+ fastify.get("/config/providers", {
42
+ schema: {
43
+ description: "Live provider + model listing assembled from the SDK's ModelRegistry.",
44
+ tags: ["config"],
45
+ response: { 200: { type: "object", required: ["providers"], properties: { providers: { type: "array" } } }, 500: errorSchema },
46
+ },
47
+ }, async (_req, reply) => {
48
+ try {
49
+ return liveProvidersListing();
50
+ }
51
+ catch (err) {
52
+ fastify.log.error(err);
53
+ return reply.code(500).send({ error: "internal_error" });
54
+ }
55
+ });
56
+ // ── Auth presence ─────────────────────────────────────────────────────
57
+ fastify.get("/config/auth", {
58
+ schema: {
59
+ description: "Provider credential presence map. Never includes actual key values.",
60
+ tags: ["config"],
61
+ response: { 200: authSummarySchema, 500: errorSchema },
62
+ },
63
+ }, async (_req, reply) => {
64
+ try {
65
+ return readAuthSummary();
66
+ }
67
+ catch (err) {
68
+ fastify.log.error(err);
69
+ return reply.code(500).send({ error: "internal_error" });
70
+ }
71
+ });
72
+ // ── Set API key ───────────────────────────────────────────────────────
73
+ fastify.put("/config/auth/:provider", {
74
+ schema: {
75
+ description: "Store an API key for a provider.",
76
+ tags: ["config"],
77
+ params: {
78
+ type: "object",
79
+ required: ["provider"],
80
+ properties: { provider: { type: "string", minLength: 1 } },
81
+ },
82
+ body: {
83
+ type: "object",
84
+ required: ["apiKey"],
85
+ additionalProperties: false,
86
+ properties: { apiKey: { type: "string", minLength: 1 } },
87
+ },
88
+ response: {
89
+ 200: {
90
+ type: "object",
91
+ required: ["provider", "configured"],
92
+ properties: {
93
+ provider: { type: "string" },
94
+ configured: { type: "boolean", const: true },
95
+ },
96
+ },
97
+ 500: errorSchema,
98
+ },
99
+ },
100
+ }, async (req, reply) => {
101
+ try {
102
+ writeApiKey(req.params.provider, req.body.apiKey);
103
+ return { provider: req.params.provider, configured: true };
104
+ }
105
+ catch (err) {
106
+ fastify.log.error(err);
107
+ return reply.code(500).send({ error: "internal_error" });
108
+ }
109
+ });
110
+ // ── Remove API key ────────────────────────────────────────────────────
111
+ fastify.delete("/config/auth/:provider", {
112
+ schema: {
113
+ description: "Remove credentials for a provider.",
114
+ tags: ["config"],
115
+ params: {
116
+ type: "object",
117
+ required: ["provider"],
118
+ properties: { provider: { type: "string", minLength: 1 } },
119
+ },
120
+ response: { 204: { type: "null" }, 404: errorSchema, 500: errorSchema },
121
+ },
122
+ }, async (req, reply) => {
123
+ try {
124
+ removeApiKey(req.params.provider);
125
+ return reply.code(204).send();
126
+ }
127
+ catch (err) {
128
+ if (err instanceof AuthProviderNotFoundError) {
129
+ return reply.code(404).send({ error: "auth_provider_not_found" });
130
+ }
131
+ fastify.log.error(err);
132
+ return reply.code(500).send({ error: "internal_error" });
133
+ }
134
+ });
135
+ // ── Read settings ─────────────────────────────────────────────────────
136
+ fastify.get("/config/settings", {
137
+ schema: {
138
+ description: "Read settings.json (default provider/model, modes, etc).",
139
+ tags: ["config"],
140
+ response: { 200: settingsSchema, 500: errorSchema },
141
+ },
142
+ }, async (_req, reply) => {
143
+ try {
144
+ return readSettings();
145
+ }
146
+ catch (err) {
147
+ fastify.log.error(err);
148
+ return reply.code(500).send({ error: "internal_error" });
149
+ }
150
+ });
151
+ // ── Update settings ───────────────────────────────────────────────────
152
+ fastify.put("/config/settings", {
153
+ schema: {
154
+ description: "Partial-merge update for settings.json. Sending null for any key deletes it.",
155
+ tags: ["config"],
156
+ body: settingsSchema,
157
+ response: { 200: settingsSchema, 500: errorSchema },
158
+ },
159
+ }, async (req, reply) => {
160
+ try {
161
+ return updateSettings(req.body);
162
+ }
163
+ catch (err) {
164
+ fastify.log.error(err);
165
+ return reply.code(500).send({ error: "internal_error" });
166
+ }
167
+ });
168
+ // ── Read models.json (redacted) ───────────────────────────────────────
169
+ fastify.get("/config/models", {
170
+ schema: {
171
+ description: "Read models.json with API keys redacted.",
172
+ tags: ["config"],
173
+ response: { 200: modelsJsonSchema, 500: errorSchema },
174
+ },
175
+ }, async (_req, reply) => {
176
+ try {
177
+ return await readModelsJsonRedacted();
178
+ }
179
+ catch (err) {
180
+ fastify.log.error(err);
181
+ return reply.code(500).send({ error: "internal_error" });
182
+ }
183
+ });
184
+ // ── Write models.json ─────────────────────────────────────────────────
185
+ fastify.put("/config/models", {
186
+ schema: {
187
+ description: "Replace models.json atomically.",
188
+ tags: ["config"],
189
+ body: modelsJsonSchema,
190
+ response: { 200: modelsJsonSchema, 500: errorSchema },
191
+ },
192
+ }, async (req, reply) => {
193
+ try {
194
+ await writeModelsJson(req.body);
195
+ return req.body;
196
+ }
197
+ catch (err) {
198
+ fastify.log.error(err);
199
+ return reply.code(500).send({ error: "internal_error" });
200
+ }
201
+ });
202
+ };
203
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type FastifyPluginAsync } from "fastify";
2
+ export declare const controlRoutes: FastifyPluginAsync;
3
+ //# sourceMappingURL=control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../src/routes/control.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAqBlD,eAAO,MAAM,aAAa,EAAE,kBA2M3B,CAAC"}
@@ -0,0 +1,180 @@
1
+ import { join } from "node:path";
2
+ import { AuthStorage, ModelRegistry, } from "@earendil-works/pi-coding-agent";
3
+ import { getSession } from "../session-registry.js";
4
+ import { config } from "../config.js";
5
+ import { readSettings, writeSettings } from "../config-manager.js";
6
+ /**
7
+ * Auth storage backed by ~/.pi/agent/auth.json.
8
+ * ⚠️ AuthStorage.create() expects a FILE path, not a directory.
9
+ * Passing a directory causes the ReadFileSync to fail silently,
10
+ * leaving authStorage.data empty and hasAuth() always returning false.
11
+ * This was the root cause of the "No API key configured" error.
12
+ * Pattern from pi-forge's config-manager.ts: AUTH_FILE path.
13
+ */
14
+ function authStorage() {
15
+ return AuthStorage.create(join(config.piConfigDir, "auth.json"));
16
+ }
17
+ export const controlRoutes = async (fastify) => {
18
+ // POST /sessions/:id/model — set per-session model override
19
+ fastify.post("/sessions/:id/model", {
20
+ schema: {
21
+ description: "Set the model for a session. Provider + modelId are validated " +
22
+ "against the SDK's ModelRegistry. Returns an error if the provider " +
23
+ "or model is unknown, or if no API key is configured for the provider.",
24
+ tags: ["sessions"],
25
+ params: {
26
+ type: "object",
27
+ required: ["id"],
28
+ properties: { id: { type: "string" } },
29
+ },
30
+ body: {
31
+ type: "object",
32
+ required: ["provider", "modelId"],
33
+ properties: {
34
+ provider: { type: "string" },
35
+ modelId: { type: "string" },
36
+ },
37
+ },
38
+ response: {
39
+ 200: {
40
+ type: "object",
41
+ required: ["provider", "modelId"],
42
+ properties: {
43
+ provider: { type: "string" },
44
+ modelId: { type: "string" },
45
+ },
46
+ },
47
+ 400: {
48
+ type: "object",
49
+ required: ["error"],
50
+ properties: {
51
+ error: { type: "string" },
52
+ message: { type: "string" },
53
+ },
54
+ },
55
+ 404: {
56
+ type: "object",
57
+ properties: { error: { type: "string" } },
58
+ },
59
+ },
60
+ },
61
+ }, async (req, reply) => {
62
+ const live = getSession(req.params.id);
63
+ if (live === undefined) {
64
+ return reply.code(404).send({ error: "session_not_found" });
65
+ }
66
+ const { provider, modelId } = req.body;
67
+ // Build fresh ModelRegistry (reads latest auth.json + models.json)
68
+ const store = authStorage();
69
+ const modelsFile = `${config.piConfigDir}/models.json`;
70
+ const registry = ModelRegistry.create(store, modelsFile);
71
+ // Check provider exists
72
+ const providerKnown = registry.getAll().some((m) => m.provider === provider);
73
+ if (!providerKnown) {
74
+ return reply.code(400).send({
75
+ error: "unknown_provider",
76
+ message: `Provider "${provider}" not found. Check available providers via GET /config/providers.`,
77
+ });
78
+ }
79
+ // Check model exists under that provider
80
+ const model = registry.find(provider, modelId);
81
+ if (model === undefined) {
82
+ return reply.code(400).send({
83
+ error: "unknown_model",
84
+ message: `Model "${modelId}" not found under provider "${provider}".`,
85
+ });
86
+ }
87
+ // Check auth is configured for this model
88
+ const hasAuth = registry.hasConfiguredAuth(model);
89
+ if (!hasAuth) {
90
+ return reply.code(400).send({
91
+ error: "auth_not_configured",
92
+ message: `No API key configured for provider "${provider}". Add one via PUT /api/v1/config/auth/${provider}.`,
93
+ });
94
+ }
95
+ const result = await (async () => {
96
+ let priorSettings;
97
+ try {
98
+ priorSettings = readSettings();
99
+ }
100
+ catch {
101
+ // settings.json missing / unreadable — skip restore
102
+ }
103
+ try {
104
+ // Refresh the session's internal ModelRegistry so it picks up
105
+ // any API keys added after session creation.
106
+ live.session.modelRegistry.authStorage.reload();
107
+ live.session.modelRegistry.refresh();
108
+ // Pass the full model object from the registry, not a {provider, id} stub.
109
+ // ⚠️ The SDK's setModel() stores the model object in agent.state.model, and
110
+ // the agent later reads fields like `api`, `baseUrl`, `contextWindow`,
111
+ // `maxTokens` from it to route LLM requests. Passing a stub with only
112
+ // `provider` + `id` leaves those fields as undefined, which silently
113
+ // breaks every subsequent prompt — the session appears "dead."
114
+ // Pattern from pi-forge: pass the full model from registry.find().
115
+ await live.session.setModel(model);
116
+ }
117
+ catch (err) {
118
+ return {
119
+ ok: false,
120
+ status: 400,
121
+ body: {
122
+ error: "set_model_failed",
123
+ message: err instanceof Error ? err.message : String(err),
124
+ },
125
+ };
126
+ }
127
+ // Restore prior settings to undo setModel's side effect
128
+ if (priorSettings !== undefined) {
129
+ try {
130
+ await writeSettings(priorSettings);
131
+ }
132
+ catch (err) {
133
+ req.log.warn({ err }, "failed to restore settings after per-session setModel");
134
+ }
135
+ }
136
+ return { ok: true };
137
+ })();
138
+ if (!result.ok) {
139
+ return reply.code(result.status).send(result.body);
140
+ }
141
+ return { provider, modelId };
142
+ });
143
+ // GET /sessions/:id/model — get current model info
144
+ fastify.get("/sessions/:id/model", {
145
+ schema: {
146
+ description: "Get the currently configured model for a session.",
147
+ tags: ["sessions"],
148
+ params: {
149
+ type: "object",
150
+ required: ["id"],
151
+ properties: { id: { type: "string" } },
152
+ },
153
+ response: {
154
+ 200: {
155
+ type: "object",
156
+ required: ["provider", "modelId"],
157
+ properties: {
158
+ provider: { type: "string" },
159
+ modelId: { type: "string" },
160
+ },
161
+ },
162
+ 404: {
163
+ type: "object",
164
+ properties: { error: { type: "string" } },
165
+ },
166
+ },
167
+ },
168
+ }, async (req, reply) => {
169
+ const live = getSession(req.params.id);
170
+ if (live === undefined) {
171
+ return reply.code(404).send({ error: "session_not_found" });
172
+ }
173
+ const model = live.session.model;
174
+ if (model === undefined) {
175
+ return reply.code(200).send({ provider: "", modelId: "" });
176
+ }
177
+ return { provider: model.provider, modelId: model.id };
178
+ });
179
+ };
180
+ //# sourceMappingURL=control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.js","sourceRoot":"","sources":["../../src/routes/control.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Extension Command Routes — invoke registered extension commands
3
+ * (`/rewind`, etc.) through the extension runner's command system, with
4
+ * `ctx.ui` bridged to the browser GUI via SSE events + REST callbacks.
5
+ *
6
+ * This is the generic mechanism: any extension that registers a command
7
+ * with `pi.registerCommand()` automatically becomes available through
8
+ * the web GUI without pi-kot-specific integration code.
9
+ *
10
+ * Flow:
11
+ * 1. GUI sends `POST /sessions/:id/command { command: "rewind" }`
12
+ * 2. Server looks up the command in the extension runner
13
+ * 3. Server installs a bridge `ExtensionUIContext` that sends
14
+ * `extension_ui_select` / `extension_ui_confirm` / etc. over SSE
15
+ * 4. Extension calls `ctx.ui.select()` → bridge creates a pending
16
+ * promise, sends SSE event → GUI renders selector → user responds
17
+ * via `POST /extension-ui/respond` → promise resolves
18
+ * 5. Extension completes → `extension_ui_done` SSE event sent
19
+ */
20
+ import type { FastifyPluginAsync } from "fastify";
21
+ export declare const extensionCommandRoutes: FastifyPluginAsync;
22
+ //# sourceMappingURL=extension-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-commands.d.ts","sourceRoot":"","sources":["../../src/routes/extension-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AASlD,eAAO,MAAM,sBAAsB,EAAE,kBA8KpC,CAAC"}