@senpiper/sp-agent 0.1.9 → 0.1.11

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 (107) hide show
  1. package/INSTALL.md +37 -26
  2. package/README.md +13 -13
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +4 -4
  5. package/dist/cli.js.map +1 -1
  6. package/dist/distribution.d.ts +2 -2
  7. package/dist/distribution.d.ts.map +1 -1
  8. package/dist/distribution.js +2 -3
  9. package/dist/distribution.js.map +1 -1
  10. package/dist/extension-identity.generated.d.ts +3 -3
  11. package/dist/extension-identity.generated.d.ts.map +1 -1
  12. package/dist/extension-identity.generated.js +3 -3
  13. package/dist/extension-identity.generated.js.map +1 -1
  14. package/dist/install-sp.sh +9 -9
  15. package/dist/release-manager.d.ts.map +1 -1
  16. package/dist/release-manager.js +2 -2
  17. package/dist/release-manager.js.map +1 -1
  18. package/dist/runtime-cli.d.ts.map +1 -1
  19. package/dist/runtime-cli.js +4 -4
  20. package/dist/runtime-cli.js.map +1 -1
  21. package/dist/sdk.d.ts +1 -1
  22. package/dist/sdk.d.ts.map +1 -1
  23. package/dist/sdk.js +5 -5
  24. package/dist/sdk.js.map +1 -1
  25. package/dist/session-manager.d.ts +1 -1
  26. package/dist/session-manager.d.ts.map +1 -1
  27. package/dist/session-manager.js +15 -15
  28. package/dist/session-manager.js.map +1 -1
  29. package/dist/sp-web.d.ts.map +1 -1
  30. package/dist/sp-web.js +2 -2
  31. package/dist/sp-web.js.map +1 -1
  32. package/dist/version.d.ts +1 -1
  33. package/dist/version.d.ts.map +1 -1
  34. package/dist/version.js +1 -1
  35. package/dist/version.js.map +1 -1
  36. package/node_modules/@senpiper/pi-coding-agent/dist/bundle/chunks/{chunk-IK73Y232.js → chunk-VVKE4QZJ.js} +1 -1
  37. package/node_modules/@senpiper/pi-coding-agent/dist/bundle/cli.js +1 -1
  38. package/node_modules/@senpiper/pi-coding-agent/dist/bundle/index.js +1 -1
  39. package/node_modules/@senpiper/pi-coding-agent/dist/bundle/rpc-entry.js +1 -1
  40. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  41. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  42. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  43. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  44. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  45. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -1
  46. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  47. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  48. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  49. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
  50. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
  51. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  52. package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  53. package/node_modules/@senpiper/pi-coding-agent/package.json +1 -1
  54. package/node_modules/@senpiper/sp-agent-extensions/CHANGELOG.md +17 -0
  55. package/node_modules/@senpiper/sp-agent-extensions/CONCURRENT_SESSIONS.md +9 -9
  56. package/node_modules/@senpiper/sp-agent-extensions/TERMINAL_WEB_BRIDGE.md +29 -10
  57. package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.d.ts +0 -6
  58. package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.d.ts.map +1 -1
  59. package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.js +7 -86
  60. package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.js.map +1 -1
  61. package/node_modules/@senpiper/sp-agent-extensions/dist/commands.d.ts +2 -2
  62. package/node_modules/@senpiper/sp-agent-extensions/dist/commands.d.ts.map +1 -1
  63. package/node_modules/@senpiper/sp-agent-extensions/dist/commands.js +2 -2
  64. package/node_modules/@senpiper/sp-agent-extensions/dist/commands.js.map +1 -1
  65. package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.d.ts +1 -1
  66. package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.d.ts.map +1 -1
  67. package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.js +28 -17
  68. package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.js.map +1 -1
  69. package/node_modules/@senpiper/sp-agent-extensions/dist/index.d.ts +1 -3
  70. package/node_modules/@senpiper/sp-agent-extensions/dist/index.d.ts.map +1 -1
  71. package/node_modules/@senpiper/sp-agent-extensions/dist/index.js +1 -3
  72. package/node_modules/@senpiper/sp-agent-extensions/dist/index.js.map +1 -1
  73. package/node_modules/@senpiper/sp-agent-extensions/dist/interactions.d.ts +0 -2
  74. package/node_modules/@senpiper/sp-agent-extensions/dist/interactions.d.ts.map +1 -1
  75. package/node_modules/@senpiper/sp-agent-extensions/dist/interactions.js +0 -3
  76. package/node_modules/@senpiper/sp-agent-extensions/dist/interactions.js.map +1 -1
  77. package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.d.ts.map +1 -1
  78. package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.js +10 -20
  79. package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.js.map +1 -1
  80. package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.d.ts +27 -0
  81. package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.d.ts.map +1 -1
  82. package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.js +270 -28
  83. package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.js.map +1 -1
  84. package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.d.ts.map +1 -1
  85. package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.js +13 -20
  86. package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.js.map +1 -1
  87. package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.d.ts +1 -1
  88. package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.d.ts.map +1 -1
  89. package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.js +11 -9
  90. package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.js.map +1 -1
  91. package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.d.ts.map +1 -1
  92. package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.js +36 -10
  93. package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.js.map +1 -1
  94. package/node_modules/@senpiper/sp-agent-extensions/package.json +3 -5
  95. package/package.json +7 -6
  96. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-command.d.ts +0 -4
  97. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-command.d.ts.map +0 -1
  98. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-command.js +0 -67
  99. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-command.js.map +0 -1
  100. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-installation.d.ts +0 -14
  101. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-installation.d.ts.map +0 -1
  102. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-installation.js +0 -32
  103. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding-installation.js.map +0 -1
  104. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding.d.ts +0 -39
  105. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding.d.ts.map +0 -1
  106. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding.js +0 -311
  107. package/node_modules/@senpiper/sp-agent-extensions/dist/onboarding.js.map +0 -1
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  export const SP_GATEWAY_PROVIDER_ID = "sp-gateway";
5
5
  export const LEGACY_SP_GATEWAY_PROVIDER_ID = "sengateway";
6
- export const SP_GATEWAY_PROVIDER_NAME = "sp-gateway";
6
+ export const SP_GATEWAY_PROVIDER_NAME = "Senpiper Gateway";
7
7
  export const SP_USER_AGENT = "sp";
8
8
  export const SP_CLIENT_NAME = "sp-agent";
9
9
  let gatewayWarning;
@@ -203,13 +203,13 @@ export async function fetchSpGatewayModels(baseUrl, apiKey, signal) {
203
203
  if (!response.ok) {
204
204
  const body = await response.text().catch(() => "");
205
205
  const suffix = body.trim() ? `: ${body.trim().slice(0, 300)}` : "";
206
- throw new Error(`sp-gateway rejected /v1/models (${response.status} ${response.statusText})${suffix}`);
206
+ throw new Error(`Senpiper Gateway rejected /v1/models (${response.status} ${response.statusText})${suffix}`);
207
207
  }
208
208
  const payload = (await response.json());
209
209
  if (!isRecord(payload) || !Array.isArray(payload.data)) {
210
- throw new Error("sp-gateway returned an invalid /v1/models envelope.");
210
+ throw new Error("Senpiper Gateway returned an invalid /v1/models envelope.");
211
211
  }
212
- return parseModelCatalog(payload.data, "sp-gateway /v1/models response");
212
+ return parseModelCatalog(payload.data, "Senpiper Gateway /v1/models response");
213
213
  }
214
214
  function readLegacySpGatewayState(agentDir) {
215
215
  const path = getLegacyModelsPath(agentDir);
@@ -224,7 +224,7 @@ function readLegacySpGatewayState(agentDir) {
224
224
  return {
225
225
  schemaVersion: 1,
226
226
  baseUrl: normalizeSpGatewayBaseUrl(provider.baseUrl),
227
- models: parseModelCatalog(provider.models, `legacy sp-gateway cache ${path}`),
227
+ models: parseModelCatalog(provider.models, `legacy Senpiper Gateway cache ${path}`),
228
228
  };
229
229
  }
230
230
  export function readSpGatewayState(agentDir = getSpAgentDir()) {
@@ -236,23 +236,23 @@ export function readSpGatewayState(agentDir = getSpAgentDir()) {
236
236
  writeSpGatewayState(legacy.baseUrl, legacy.models, agentDir);
237
237
  gatewayWarning = {
238
238
  kind: "legacy_cache_imported",
239
- message: `Imported the legacy sp-gateway model cache from ${getLegacyModelsPath(agentDir)}.`,
239
+ message: `Imported the legacy Senpiper Gateway model cache from ${getLegacyModelsPath(agentDir)}.`,
240
240
  at: new Date().toISOString(),
241
241
  };
242
242
  return legacy;
243
243
  }
244
244
  const value = readJsonFile(path);
245
245
  if (value.schemaVersion !== 1 || typeof value.baseUrl !== "string" || !Array.isArray(value.models)) {
246
- throw new Error(`Invalid sp-gateway configuration: ${path}`);
246
+ throw new Error(`Invalid Senpiper Gateway configuration: ${path}`);
247
247
  }
248
248
  return {
249
249
  schemaVersion: 1,
250
250
  baseUrl: normalizeSpGatewayBaseUrl(value.baseUrl),
251
- models: parseModelCatalog(value.models, `sp-gateway configuration ${path}`),
251
+ models: parseModelCatalog(value.models, `Senpiper Gateway configuration ${path}`),
252
252
  };
253
253
  }
254
254
  export function writeSpGatewayState(baseUrl, models, agentDir = getSpAgentDir()) {
255
- const validatedModels = parseModelCatalog(models, "sp-gateway state");
255
+ const validatedModels = parseModelCatalog(models, "Senpiper Gateway state");
256
256
  writePrivateJson(getSpGatewayStatePath(agentDir), {
257
257
  schemaVersion: 1,
258
258
  baseUrl: normalizeSpGatewayBaseUrl(baseUrl),
@@ -310,7 +310,7 @@ export function clearSpGatewayWarning() {
310
310
  gatewayWarning = undefined;
311
311
  }
312
312
  export function createSpGatewayProviderConfig(baseUrl, models, agentDir = getSpAgentDir()) {
313
- let currentModels = parseModelCatalog(models, "sp-gateway provider configuration");
313
+ let currentModels = parseModelCatalog(models, "Senpiper Gateway provider configuration");
314
314
  return {
315
315
  name: SP_GATEWAY_PROVIDER_NAME,
316
316
  baseUrl,
@@ -344,7 +344,7 @@ export function createSpGatewayProviderConfig(baseUrl, models, agentDir = getSpA
344
344
  catch (error) {
345
345
  gatewayWarning = {
346
346
  kind: "refresh_failed",
347
- message: `sp-gateway model refresh failed; using ${currentModels.length} cached model${currentModels.length === 1 ? "" : "s"}: ${error instanceof Error ? error.message : String(error)}`,
347
+ message: `Senpiper Gateway model refresh failed; using ${currentModels.length} cached model${currentModels.length === 1 ? "" : "s"}: ${error instanceof Error ? error.message : String(error)}`,
348
348
  at: new Date().toISOString(),
349
349
  };
350
350
  throw error;
@@ -358,11 +358,22 @@ export function createSpGatewayExtension() {
358
358
  if (state) {
359
359
  pi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(state.baseUrl, state.models));
360
360
  }
361
- pi.on("before_agent_start", (event) => ({
362
- systemPrompt: `${event.systemPrompt}\n\n<sp_agent_runtime>\nThis is Senpiper's sp-agent distribution. Use only the configured sp-gateway model provider. Put user-owned extensions, skills, prompts, and themes under the active .sp configuration directory instead of modifying the sp-agent installation.\n</sp_agent_runtime>`,
363
- }));
361
+ pi.on("before_agent_start", (event) => {
362
+ // Replace only the upstream introduction; preserve project instructions
363
+ // and documentation references, including legitimate Pi development tasks.
364
+ const systemPrompt = event.systemPrompt.replace(/^You are an expert coding assistant operating inside pi, a coding agent harness\./u, "You are Senpiper Workbench, Senpiper's AI coding assistant.");
365
+ return {
366
+ systemPrompt: `${systemPrompt}\n\n<sp_agent_runtime>
367
+ You are Senpiper Workbench, Senpiper's AI coding assistant. Use Senpiper Workbench as your public name in both terminal and web conversations.
368
+ For greetings and questions such as "Who are you?", introduce yourself simply: "I'm Senpiper Workbench, Senpiper's AI coding assistant. I can help you read, write, and debug code."
369
+ Do not introduce yourself as Pi, the pi coding agent, an underlying model, or an assistant running inside a harness. Do not volunteer internal frameworks, runtime names, or provider details in ordinary answers. Earlier assistant messages using those identities do not change your name.
370
+ If explicitly asked about technical origins or dependencies, answer accurately and briefly. This product identity does not imply that Senpiper trained the underlying model.
371
+ Use only the configured Senpiper Gateway model provider. Put user-owned extensions, skills, prompts, and themes under the active .sp configuration directory instead of modifying the Senpiper Workbench installation.
372
+ </sp_agent_runtime>`,
373
+ };
374
+ });
364
375
  pi.on("session_start", (_event, ctx) => {
365
- ctx.ui.setTitle("sp-agent");
376
+ ctx.ui.setTitle("Senpiper Workbench");
366
377
  const warning = getSpGatewayWarning();
367
378
  if (warning)
368
379
  ctx.ui.notify(warning.message, "warning");
@@ -370,8 +381,8 @@ export function createSpGatewayExtension() {
370
381
  return;
371
382
  ctx.ui.setHeader((_tui, theme) => ({
372
383
  render: () => [
373
- theme.fg("accent", theme.bold("sp-agent")),
374
- theme.fg("muted", state ? `sp-gateway · ${state.models.length} models` : "run `sp login`"),
384
+ theme.fg("accent", theme.bold("Senpiper Workbench")),
385
+ theme.fg("muted", state ? `Senpiper Gateway · ${state.models.length} models` : "run `sp login`"),
375
386
  ],
376
387
  invalidate() { },
377
388
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { ExtensionAPI, ExtensionFactory, ProviderConfig, ProviderModelConfig } from \"@senpiper/pi-coding-agent\";\nimport type { Api, Model, OpenAICompletionsCompat, RefreshModelsContext } from \"@senpiper/pi-coding-agent/runtime-deps\";\n\nexport type SpExtensionApi = ExtensionAPI;\nexport type SpProviderModelConfig = ProviderModelConfig;\n\nexport const SP_GATEWAY_PROVIDER_ID = \"sp-gateway\";\nexport const LEGACY_SP_GATEWAY_PROVIDER_ID = \"sengateway\";\nexport const SP_GATEWAY_PROVIDER_NAME = \"sp-gateway\";\nexport const SP_USER_AGENT = \"sp\";\nexport const SP_CLIENT_NAME = \"sp-agent\";\n\nexport interface SpGatewayState {\n\tschemaVersion: 1;\n\tbaseUrl: string;\n\tmodels: SpProviderModelConfig[];\n}\n\nexport interface SpGatewayWarning {\n\tkind: \"refresh_failed\" | \"legacy_cache_imported\";\n\tmessage: string;\n\tat: string;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nlet gatewayWarning: SpGatewayWarning | undefined;\n\nfunction isRecord(value: unknown): value is JsonRecord {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringValue(value: unknown) {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction finiteNumber(value: unknown) {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction positiveInteger(value: unknown) {\n\tconst number = finiteNumber(value);\n\treturn number !== undefined && number > 0 ? Math.floor(number) : undefined;\n}\n\nfunction nonNegativeNumber(value: unknown) {\n\tconst number = finiteNumber(value);\n\treturn number !== undefined && number >= 0 ? number : undefined;\n}\n\nfunction booleanValue(value: unknown) {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nexport function getSpAgentDir() {\n\treturn process.env.SP_CODING_AGENT_DIR || join(homedir(), \".sp\", \"agent\");\n}\n\nexport function getSpGatewayStatePath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"sp-gateway.json\");\n}\n\nexport function getLegacyModelsPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"models.json\");\n}\n\nexport function getSpAuthPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"auth.json\");\n}\n\nexport function getSpSettingsPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"settings.json\");\n}\n\nfunction readJsonFile(path: string): JsonRecord {\n\tif (!existsSync(path)) return {};\n\tconst content = readFileSync(path, \"utf8\").trim();\n\tif (!content) return {};\n\tconst parsed = JSON.parse(content) as unknown;\n\tif (!isRecord(parsed)) throw new Error(`Expected an object in ${path}`);\n\treturn parsed;\n}\n\nfunction writePrivateJson(path: string, value: unknown) {\n\tmkdirSync(dirname(path), { recursive: true });\n\tconst temporaryPath = `${path}.${process.pid}.tmp`;\n\twriteFileSync(temporaryPath, `${JSON.stringify(value, null, \"\\t\")}\\n`, { encoding: \"utf8\", mode: 0o600 });\n\tif (process.platform !== \"win32\") chmodSync(temporaryPath, 0o600);\n\trenameSync(temporaryPath, path);\n\tif (process.platform !== \"win32\") chmodSync(path, 0o600);\n}\n\nexport function normalizeSpGatewayBaseUrl(input: string) {\n\tconst trimmed = input.trim();\n\tif (!trimmed) throw new Error(\"Gateway URL cannot be empty.\");\n\tconst withScheme = /^[a-z][a-z0-9+.-]*:\\/\\//iu.test(trimmed) ? trimmed : `https://${trimmed}`;\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(withScheme);\n\t} catch {\n\t\tthrow new Error(`Invalid gateway URL: ${input}`);\n\t}\n\tif (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n\t\tthrow new Error(\"Gateway URL must use HTTPS or HTTP.\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\");\n\tif (!url.pathname.endsWith(\"/v1\")) url.pathname = `${url.pathname}/v1`.replace(/\\/+/gu, \"/\");\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nfunction parseInput(value: unknown): (\"text\" | \"image\")[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst input = value.filter((entry): entry is \"text\" | \"image\" => entry === \"text\" || entry === \"image\");\n\treturn input.length > 0 ? [...new Set(input)] : undefined;\n}\n\nfunction parseCost(value: unknown): SpProviderModelConfig[\"cost\"] | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst input = nonNegativeNumber(value.input);\n\tconst output = nonNegativeNumber(value.output);\n\tconst cacheRead = nonNegativeNumber(value.cacheRead);\n\tconst cacheWrite = nonNegativeNumber(value.cacheWrite);\n\tif (input === undefined && output === undefined && cacheRead === undefined && cacheWrite === undefined)\n\t\treturn undefined;\n\treturn { input: input ?? 0, output: output ?? 0, cacheRead: cacheRead ?? 0, cacheWrite: cacheWrite ?? 0 };\n}\n\nfunction parseThinkingLevelMap(value: unknown): SpProviderModelConfig[\"thinkingLevelMap\"] {\n\tif (!isRecord(value)) return undefined;\n\tconst result: NonNullable<SpProviderModelConfig[\"thinkingLevelMap\"]> = {};\n\tfor (const key of [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const) {\n\t\tconst entry = value[key];\n\t\tif (typeof entry === \"string\" || entry === null) result[key] = entry;\n\t}\n\treturn Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction thinkingFormat(value: unknown): OpenAICompletionsCompat[\"thinkingFormat\"] {\n\tswitch (value) {\n\t\tcase \"openai\":\n\t\tcase \"openrouter\":\n\t\tcase \"deepseek\":\n\t\tcase \"together\":\n\t\tcase \"zai\":\n\t\tcase \"qwen\":\n\t\tcase \"chat-template\":\n\t\tcase \"qwen-chat-template\":\n\t\tcase \"string-thinking\":\n\t\tcase \"ant-ling\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction sessionAffinityFormat(value: unknown): OpenAICompletionsCompat[\"sessionAffinityFormat\"] {\n\treturn value === \"openai\" || value === \"openai-nosession\" || value === \"openrouter\" ? value : undefined;\n}\n\nfunction parseCompat(value: unknown): OpenAICompletionsCompat {\n\tconst record = isRecord(value) ? value : {};\n\tconst maxTokensField =\n\t\trecord.maxTokensField === \"max_completion_tokens\" || record.maxTokensField === \"max_tokens\"\n\t\t\t? record.maxTokensField\n\t\t\t: undefined;\n\tconst compat = {\n\t\tsupportsStore: booleanValue(record.supportsStore) ?? false,\n\t\tsupportsDeveloperRole: booleanValue(record.supportsDeveloperRole),\n\t\tsupportsReasoningEffort: booleanValue(record.supportsReasoningEffort),\n\t\tsupportsUsageInStreaming: booleanValue(record.supportsUsageInStreaming),\n\t\tmaxTokensField,\n\t\trequiresToolResultName: booleanValue(record.requiresToolResultName),\n\t\trequiresAssistantAfterToolResult: booleanValue(record.requiresAssistantAfterToolResult),\n\t\trequiresThinkingAsText: booleanValue(record.requiresThinkingAsText),\n\t\trequiresReasoningContentOnAssistantMessages: booleanValue(record.requiresReasoningContentOnAssistantMessages),\n\t\tthinkingFormat: thinkingFormat(record.thinkingFormat),\n\t\tsupportsStrictMode: booleanValue(record.supportsStrictMode),\n\t\tsendSessionAffinityHeaders: booleanValue(record.sendSessionAffinityHeaders),\n\t\tsessionAffinityFormat: sessionAffinityFormat(record.sessionAffinityFormat),\n\t\tsupportsLongCacheRetention: booleanValue(record.supportsLongCacheRetention),\n\t} satisfies OpenAICompletionsCompat;\n\treturn compat;\n}\n\nfunction parseGatewayModel(value: unknown): SpProviderModelConfig | undefined {\n\tconst record = typeof value === \"string\" ? { id: value } : isRecord(value) ? value : undefined;\n\tif (!record) return undefined;\n\tconst id = stringValue(record.id);\n\tif (!id || id.length > 256 || /[\\u0000-\\u001f\\u007f]/u.test(id)) return undefined;\n\tconst metadata = isRecord(record.metadata) ? record.metadata : {};\n\tconst field = (name: string) => metadata[name] ?? record[name];\n\tconst reasoning = field(\"reasoning\");\n\treturn {\n\t\tid,\n\t\tname: stringValue(field(\"name\")) ?? id,\n\t\treasoning: typeof reasoning === \"boolean\" ? reasoning : false,\n\t\tthinkingLevelMap: parseThinkingLevelMap(field(\"thinkingLevelMap\")),\n\t\tinput: parseInput(field(\"input\")) ?? [\"text\"],\n\t\tcost: parseCost(field(\"cost\")) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: positiveInteger(field(\"contextWindow\")) ?? 128_000,\n\t\tmaxTokens: positiveInteger(field(\"maxTokens\")) ?? 32_000,\n\t\tcompat: parseCompat(field(\"compat\")),\n\t};\n}\n\nfunction parseModelCatalog(values: readonly unknown[], source: string) {\n\tconst models = values.map(parseGatewayModel).filter((model): model is SpProviderModelConfig => model !== undefined);\n\tif (models.length === 0) throw new Error(`${source} contains no valid models.`);\n\tconst ids = new Set<string>();\n\tfor (const model of models) {\n\t\tif (ids.has(model.id)) throw new Error(`${source} contains duplicate model id ${model.id}.`);\n\t\tids.add(model.id);\n\t}\n\treturn models;\n}\n\nexport async function fetchSpGatewayModels(baseUrl: string, apiKey: string, signal?: AbortSignal) {\n\tconst response = await fetch(`${baseUrl.replace(/\\/$/u, \"\")}/models`, {\n\t\tsignal,\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\tAccept: \"application/json\",\n\t\t\t\"User-Agent\": SP_USER_AGENT,\n\t\t\t\"X-Senpiper-Client\": SP_CLIENT_NAME,\n\t\t},\n\t});\n\tif (!response.ok) {\n\t\tconst body = await response.text().catch(() => \"\");\n\t\tconst suffix = body.trim() ? `: ${body.trim().slice(0, 300)}` : \"\";\n\t\tthrow new Error(`sp-gateway rejected /v1/models (${response.status} ${response.statusText})${suffix}`);\n\t}\n\tconst payload = (await response.json()) as unknown;\n\tif (!isRecord(payload) || !Array.isArray(payload.data)) {\n\t\tthrow new Error(\"sp-gateway returned an invalid /v1/models envelope.\");\n\t}\n\treturn parseModelCatalog(payload.data, \"sp-gateway /v1/models response\");\n}\n\nfunction readLegacySpGatewayState(agentDir: string): SpGatewayState | undefined {\n\tconst path = getLegacyModelsPath(agentDir);\n\tif (!existsSync(path)) return undefined;\n\tconst root = readJsonFile(path);\n\tconst providers = isRecord(root.providers) ? root.providers : undefined;\n\tconst providerValue = providers?.[SP_GATEWAY_PROVIDER_ID] ?? providers?.[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\tconst provider = isRecord(providerValue) ? providerValue : undefined;\n\tif (!provider || typeof provider.baseUrl !== \"string\" || !Array.isArray(provider.models)) return undefined;\n\treturn {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(provider.baseUrl),\n\t\tmodels: parseModelCatalog(provider.models, `legacy sp-gateway cache ${path}`),\n\t};\n}\n\nexport function readSpGatewayState(agentDir = getSpAgentDir()): SpGatewayState | undefined {\n\tconst path = getSpGatewayStatePath(agentDir);\n\tif (!existsSync(path)) {\n\t\tconst legacy = readLegacySpGatewayState(agentDir);\n\t\tif (!legacy) return undefined;\n\t\twriteSpGatewayState(legacy.baseUrl, legacy.models, agentDir);\n\t\tgatewayWarning = {\n\t\t\tkind: \"legacy_cache_imported\",\n\t\t\tmessage: `Imported the legacy sp-gateway model cache from ${getLegacyModelsPath(agentDir)}.`,\n\t\t\tat: new Date().toISOString(),\n\t\t};\n\t\treturn legacy;\n\t}\n\tconst value = readJsonFile(path);\n\tif (value.schemaVersion !== 1 || typeof value.baseUrl !== \"string\" || !Array.isArray(value.models)) {\n\t\tthrow new Error(`Invalid sp-gateway configuration: ${path}`);\n\t}\n\treturn {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(value.baseUrl),\n\t\tmodels: parseModelCatalog(value.models, `sp-gateway configuration ${path}`),\n\t};\n}\n\nexport function writeSpGatewayState(baseUrl: string, models: SpProviderModelConfig[], agentDir = getSpAgentDir()) {\n\tconst validatedModels = parseModelCatalog(models, \"sp-gateway state\");\n\twritePrivateJson(getSpGatewayStatePath(agentDir), {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(baseUrl),\n\t\tmodels: validatedModels,\n\t} satisfies SpGatewayState);\n}\n\nexport function readSpGatewayApiKey(agentDir = getSpAgentDir()) {\n\tconst path = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(path);\n\tlet credential = auth[SP_GATEWAY_PROVIDER_ID];\n\tif (!credential && auth[LEGACY_SP_GATEWAY_PROVIDER_ID]) {\n\t\tcredential = auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\t\tauth[SP_GATEWAY_PROVIDER_ID] = credential;\n\t\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\t\twritePrivateJson(path, auth);\n\t}\n\treturn isRecord(credential) && credential.type === \"api_key\" && typeof credential.key === \"string\"\n\t\t? credential.key\n\t\t: undefined;\n}\n\nexport function writeSpGatewayLogin(apiKey: string, firstModelId: string, agentDir = getSpAgentDir()) {\n\tconst authPath = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(authPath);\n\tauth[SP_GATEWAY_PROVIDER_ID] = { type: \"api_key\", key: apiKey };\n\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\twritePrivateJson(authPath, auth);\n\n\tconst settingsPath = getSpSettingsPath(agentDir);\n\tconst settings = readJsonFile(settingsPath);\n\tsettings.defaultProvider = SP_GATEWAY_PROVIDER_ID;\n\tsettings.defaultModel = firstModelId;\n\twritePrivateJson(settingsPath, settings);\n}\n\nexport function removeSpGatewayLogin(agentDir = getSpAgentDir()) {\n\tconst path = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(path);\n\tdelete auth[SP_GATEWAY_PROVIDER_ID];\n\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\twritePrivateJson(path, auth);\n}\n\nfunction credentialKey(context: RefreshModelsContext) {\n\treturn context.credential?.type === \"api_key\" ? context.credential.key : undefined;\n}\n\nfunction storedModels(models: readonly SpProviderModelConfig[], baseUrl: string): Model<Api>[] {\n\treturn models.map((model) => ({\n\t\t...model,\n\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\tbaseUrl,\n\t\tapi: \"openai-completions\",\n\t}));\n}\n\nexport function getSpGatewayWarning() {\n\treturn gatewayWarning;\n}\n\nexport function clearSpGatewayWarning() {\n\tgatewayWarning = undefined;\n}\n\nexport function createSpGatewayProviderConfig(\n\tbaseUrl: string,\n\tmodels: SpProviderModelConfig[],\n\tagentDir = getSpAgentDir(),\n): ProviderConfig {\n\tlet currentModels = parseModelCatalog(models, \"sp-gateway provider configuration\");\n\treturn {\n\t\tname: SP_GATEWAY_PROVIDER_NAME,\n\t\tbaseUrl,\n\t\tapi: \"openai-completions\",\n\t\tauthHeader: true,\n\t\theaders: {\n\t\t\t\"User-Agent\": SP_USER_AGENT,\n\t\t\t\"X-Senpiper-Client\": SP_CLIENT_NAME,\n\t\t},\n\t\tmodels: currentModels,\n\t\tasync refreshModels(context) {\n\t\t\tif (!context.allowNetwork) return currentModels;\n\t\t\tconst apiKey = credentialKey(context);\n\t\t\tif (!apiKey) return currentModels;\n\t\t\ttry {\n\t\t\t\tconst refreshed = await fetchSpGatewayModels(baseUrl, apiKey, context.signal);\n\t\t\t\tif (context.signal.aborted) return currentModels;\n\t\t\t\tawait context.publish({\n\t\t\t\t\tpersist: { models: storedModels(refreshed, baseUrl), checkedAt: Date.now() },\n\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\twriteSpGatewayState(baseUrl, refreshed, agentDir);\n\t\t\t\t\t\tcurrentModels = refreshed;\n\t\t\t\t\t\tgatewayWarning = undefined;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn currentModels;\n\t\t\t} catch (error) {\n\t\t\t\tgatewayWarning = {\n\t\t\t\t\tkind: \"refresh_failed\",\n\t\t\t\t\tmessage: `sp-gateway model refresh failed; using ${currentModels.length} cached model${currentModels.length === 1 ? \"\" : \"s\"}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tat: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createSpGatewayExtension(): ExtensionFactory {\n\treturn (pi) => {\n\t\tconst state = readSpGatewayState();\n\t\tif (state) {\n\t\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(state.baseUrl, state.models));\n\t\t}\n\n\t\tpi.on(\"before_agent_start\", (event) => ({\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n<sp_agent_runtime>\\nThis is Senpiper's sp-agent distribution. Use only the configured sp-gateway model provider. Put user-owned extensions, skills, prompts, and themes under the active .sp configuration directory instead of modifying the sp-agent installation.\\n</sp_agent_runtime>`,\n\t\t}));\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\tctx.ui.setTitle(\"sp-agent\");\n\t\t\tconst warning = getSpGatewayWarning();\n\t\t\tif (warning) ctx.ui.notify(warning.message, \"warning\");\n\t\t\tif (ctx.mode !== \"tui\") return;\n\t\t\tctx.ui.setHeader((_tui, theme) => ({\n\t\t\t\trender: () => [\n\t\t\t\t\ttheme.fg(\"accent\", theme.bold(\"sp-agent\")),\n\t\t\t\t\ttheme.fg(\"muted\", state ? `sp-gateway · ${state.models.length} models` : \"run `sp login`\"),\n\t\t\t\t],\n\t\t\t\tinvalidate() {},\n\t\t\t}));\n\t\t});\n\t};\n}\n"]}
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAO1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AACnD,MAAM,CAAC,MAAM,6BAA6B,GAAG,YAAY,CAAC;AAC1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AAgBzC,IAAI,cAA4C,CAAC;AAEjD,SAAS,QAAQ,CAAC,KAAc,EAAuB;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAAA,CAC5E;AAED,SAAS,WAAW,CAAC,KAAc,EAAE;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC5E;AAED,SAAS,YAAY,CAAC,KAAc,EAAE;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC/E;AAED,SAAS,eAAe,CAAC,KAAc,EAAE;IACxC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC3E;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE;IAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAChE;AAED,SAAS,YAAY,CAAC,KAAc,EAAE;IACrC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACtD;AAED,MAAM,UAAU,aAAa,GAAG;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,CAC1E;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IACjE,OAAO,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAAA,CACzC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IAC/D,OAAO,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAAA,CACrC;AAED,MAAM,UAAU,aAAa,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IACzD,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAAA,CACnC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IAC7D,OAAO,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AAAA,CACvC;AAED,SAAS,YAAY,CAAC,IAAY,EAAc;IAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;IAC9C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAc,EAAE;IACvD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IACnD,aAAa,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1G,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAClE,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAAA,CACzD;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAa,EAAE;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,OAAO,EAAE,CAAC;IAC9F,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxD,CAAC;IACD,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACd,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAChB,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,GAAG,CAAC,QAAQ,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7F,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAAA,CAC1C;AAED,SAAS,UAAU,CAAC,KAAc,EAAoC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,CAAC,CAAC;IACxG,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC1D;AAED,SAAS,SAAS,CAAC,KAAc,EAA6C;IAC7E,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS;QACrG,OAAO,SAAS,CAAC;IAClB,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,IAAI,CAAC,EAAE,CAAC;AAAA,CAC1G;AAED,SAAS,qBAAqB,CAAC,KAAc,EAA6C;IACzF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,MAAM,GAA2D,EAAE,CAAC;IAC1E,KAAK,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAU,EAAE,CAAC;QACxF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC3D;AAED,SAAS,cAAc,CAAC,KAAc,EAA6C;IAClF,QAAQ,KAAK,EAAE,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY,CAAC;QAClB,KAAK,UAAU,CAAC;QAChB,KAAK,UAAU,CAAC;QAChB,KAAK,KAAK,CAAC;QACX,KAAK,MAAM,CAAC;QACZ,KAAK,eAAe,CAAC;QACrB,KAAK,oBAAoB,CAAC;QAC1B,KAAK,iBAAiB,CAAC;QACvB,KAAK,UAAU;YACd,OAAO,KAAK,CAAC;QACd;YACC,OAAO,SAAS,CAAC;IACnB,CAAC;AAAA,CACD;AAED,SAAS,qBAAqB,CAAC,KAAc,EAAoD;IAChG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,kBAAkB,IAAI,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACxG;AAED,SAAS,WAAW,CAAC,KAAc,EAA2B;IAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,MAAM,cAAc,GACnB,MAAM,CAAC,cAAc,KAAK,uBAAuB,IAAI,MAAM,CAAC,cAAc,KAAK,YAAY;QAC1F,CAAC,CAAC,MAAM,CAAC,cAAc;QACvB,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,MAAM,GAAG;QACd,aAAa,EAAE,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK;QAC1D,qBAAqB,EAAE,YAAY,CAAC,MAAM,CAAC,qBAAqB,CAAC;QACjE,uBAAuB,EAAE,YAAY,CAAC,MAAM,CAAC,uBAAuB,CAAC;QACrE,wBAAwB,EAAE,YAAY,CAAC,MAAM,CAAC,wBAAwB,CAAC;QACvE,cAAc;QACd,sBAAsB,EAAE,YAAY,CAAC,MAAM,CAAC,sBAAsB,CAAC;QACnE,gCAAgC,EAAE,YAAY,CAAC,MAAM,CAAC,gCAAgC,CAAC;QACvF,sBAAsB,EAAE,YAAY,CAAC,MAAM,CAAC,sBAAsB,CAAC;QACnE,2CAA2C,EAAE,YAAY,CAAC,MAAM,CAAC,2CAA2C,CAAC;QAC7G,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC;QACrD,kBAAkB,EAAE,YAAY,CAAC,MAAM,CAAC,kBAAkB,CAAC;QAC3D,0BAA0B,EAAE,YAAY,CAAC,MAAM,CAAC,0BAA0B,CAAC;QAC3E,qBAAqB,EAAE,qBAAqB,CAAC,MAAM,CAAC,qBAAqB,CAAC;QAC1E,0BAA0B,EAAE,YAAY,CAAC,MAAM,CAAC,0BAA0B,CAAC;KACzC,CAAC;IACpC,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAqC;IAC7E,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IAClF,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACrC,OAAO;QACN,EAAE;QACF,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QACtC,SAAS,EAAE,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;QAC7D,gBAAgB,EAAE,qBAAqB,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAClE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7C,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;QACtF,aAAa,EAAE,eAAe,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,OAAO;QACjE,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,MAAM;QACxD,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;KACpC,CAAC;AAAA,CACF;AAED,SAAS,iBAAiB,CAAC,MAA0B,EAAE,MAAc,EAAE;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAkC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACpH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,4BAA4B,CAAC,CAAC;IAChF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,gCAAgC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7F,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAe,EAAE,MAAc,EAAE,MAAoB,EAAE;IACjG,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,EAAE;QACrE,MAAM;QACN,OAAO,EAAE;YACR,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,MAAM,EAAE,kBAAkB;YAC1B,YAAY,EAAE,aAAa;YAC3B,mBAAmB,EAAE,cAAc;SACnC;KACD,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,CAAC;IAC9G,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,sCAAsC,CAAC,CAAC;AAAA,CAC/E;AAED,SAAS,wBAAwB,CAAC,QAAgB,EAA8B;IAC/E,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,aAAa,GAAG,SAAS,EAAE,CAAC,sBAAsB,CAAC,IAAI,SAAS,EAAE,CAAC,6BAA6B,CAAC,CAAC;IACxG,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3G,OAAO;QACN,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,OAAO,CAAC;QACpD,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,iCAAiC,IAAI,EAAE,CAAC;KACnF,CAAC;AAAA,CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAA8B;IAC1F,MAAM,IAAI,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC9B,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7D,cAAc,GAAG;YAChB,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,yDAAyD,mBAAmB,CAAC,QAAQ,CAAC,GAAG;YAClG,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC5B,CAAC;QACF,OAAO,MAAM,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACpG,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO;QACN,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC;QACjD,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,kCAAkC,IAAI,EAAE,CAAC;KACjF,CAAC;AAAA,CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,MAA+B,EAAE,QAAQ,GAAG,aAAa,EAAE,EAAE;IACjH,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAC5E,gBAAgB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE;QACjD,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,yBAAyB,CAAC,OAAO,CAAC;QAC3C,MAAM,EAAE,eAAe;KACE,CAAC,CAAC;AAAA,CAC5B;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IAC/D,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,UAAU,GAAG,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,6BAA6B,CAAC,EAAE,CAAC;QACxD,UAAU,GAAG,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACjD,IAAI,CAAC,sBAAsB,CAAC,GAAG,UAAU,CAAC;QAC1C,OAAO,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC3C,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,QAAQ;QACjG,CAAC,CAAC,UAAU,CAAC,GAAG;QAChB,CAAC,CAAC,SAAS,CAAC;AAAA,CACb;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,YAAoB,EAAE,QAAQ,GAAG,aAAa,EAAE,EAAE;IACrG,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,sBAAsB,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAChE,OAAO,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC3C,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAEjC,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC5C,QAAQ,CAAC,eAAe,GAAG,sBAAsB,CAAC;IAClD,QAAQ,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,gBAAgB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAAA,CACzC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAQ,GAAG,aAAa,EAAE,EAAE;IAChE,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC3C,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAAA,CAC7B;AAED,SAAS,aAAa,CAAC,OAA6B,EAAE;IACrD,OAAO,OAAO,CAAC,UAAU,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACnF;AAED,SAAS,YAAY,CAAC,MAAwC,EAAE,OAAe,EAAgB;IAC9F,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7B,GAAG,KAAK;QACR,QAAQ,EAAE,sBAAsB;QAChC,OAAO;QACP,GAAG,EAAE,oBAAoB;KACzB,CAAC,CAAC,CAAC;AAAA,CACJ;AAED,MAAM,UAAU,mBAAmB,GAAG;IACrC,OAAO,cAAc,CAAC;AAAA,CACtB;AAED,MAAM,UAAU,qBAAqB,GAAG;IACvC,cAAc,GAAG,SAAS,CAAC;AAAA,CAC3B;AAED,MAAM,UAAU,6BAA6B,CAC5C,OAAe,EACf,MAA+B,EAC/B,QAAQ,GAAG,aAAa,EAAE,EACT;IACjB,IAAI,aAAa,GAAG,iBAAiB,CAAC,MAAM,EAAE,yCAAyC,CAAC,CAAC;IACzF,OAAO;QACN,IAAI,EAAE,wBAAwB;QAC9B,OAAO;QACP,GAAG,EAAE,oBAAoB;QACzB,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE;YACR,YAAY,EAAE,aAAa;YAC3B,mBAAmB,EAAE,cAAc;SACnC;QACD,MAAM,EAAE,aAAa;QACrB,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE;YAC5B,IAAI,CAAC,OAAO,CAAC,YAAY;gBAAE,OAAO,aAAa,CAAC;YAChD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM;gBAAE,OAAO,aAAa,CAAC;YAClC,IAAI,CAAC;gBACJ,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC9E,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;oBAAE,OAAO,aAAa,CAAC;gBACjD,MAAM,OAAO,CAAC,OAAO,CAAC;oBACrB,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;oBAC5E,MAAM,EAAE,GAAG,EAAE,CAAC;wBACb,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;wBAClD,aAAa,GAAG,SAAS,CAAC;wBAC1B,cAAc,GAAG,SAAS,CAAC;oBAAA,CAC3B;iBACD,CAAC,CAAC;gBACH,OAAO,aAAa,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,cAAc,GAAG;oBAChB,IAAI,EAAE,gBAAgB;oBACtB,OAAO,EAAE,gDAAgD,aAAa,CAAC,MAAM,gBAAgB,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;oBAC/L,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBAC5B,CAAC;gBACF,MAAM,KAAK,CAAC;YACb,CAAC;QAAA,CACD;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,wBAAwB,GAAqB;IAC5D,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACX,EAAE,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACzG,CAAC;QAED,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;YACtC,wEAAwE;YACxE,2EAA2E;YAC3E,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAC9C,oFAAoF,EACpF,6DAA6D,CAC7D,CAAC;YACF,OAAO;gBACN,YAAY,EAAE,GAAG,YAAY;;;;;;oBAMb;aAChB,CAAC;QAAA,CACF,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;YACvC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;YACtC,IAAI,OAAO;gBAAE,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK;gBAAE,OAAO;YAC/B,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM,EAAE,GAAG,EAAE,CAAC;oBACb,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;oBACpD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,uBAAsB,KAAK,CAAC,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC;iBAChG;gBACD,UAAU,GAAG,EAAC,CAAC;aACf,CAAC,CAAC,CAAC;QAAA,CACJ,CAAC,CAAC;IAAA,CACH,CAAC;AAAA,CACF","sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { ExtensionAPI, ExtensionFactory, ProviderConfig, ProviderModelConfig } from \"@senpiper/pi-coding-agent\";\nimport type { Api, Model, OpenAICompletionsCompat, RefreshModelsContext } from \"@senpiper/pi-coding-agent/runtime-deps\";\n\nexport type SpExtensionApi = ExtensionAPI;\nexport type SpProviderModelConfig = ProviderModelConfig;\n\nexport const SP_GATEWAY_PROVIDER_ID = \"sp-gateway\";\nexport const LEGACY_SP_GATEWAY_PROVIDER_ID = \"sengateway\";\nexport const SP_GATEWAY_PROVIDER_NAME = \"Senpiper Gateway\";\nexport const SP_USER_AGENT = \"sp\";\nexport const SP_CLIENT_NAME = \"sp-agent\";\n\nexport interface SpGatewayState {\n\tschemaVersion: 1;\n\tbaseUrl: string;\n\tmodels: SpProviderModelConfig[];\n}\n\nexport interface SpGatewayWarning {\n\tkind: \"refresh_failed\" | \"legacy_cache_imported\";\n\tmessage: string;\n\tat: string;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nlet gatewayWarning: SpGatewayWarning | undefined;\n\nfunction isRecord(value: unknown): value is JsonRecord {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringValue(value: unknown) {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction finiteNumber(value: unknown) {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction positiveInteger(value: unknown) {\n\tconst number = finiteNumber(value);\n\treturn number !== undefined && number > 0 ? Math.floor(number) : undefined;\n}\n\nfunction nonNegativeNumber(value: unknown) {\n\tconst number = finiteNumber(value);\n\treturn number !== undefined && number >= 0 ? number : undefined;\n}\n\nfunction booleanValue(value: unknown) {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nexport function getSpAgentDir() {\n\treturn process.env.SP_CODING_AGENT_DIR || join(homedir(), \".sp\", \"agent\");\n}\n\nexport function getSpGatewayStatePath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"sp-gateway.json\");\n}\n\nexport function getLegacyModelsPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"models.json\");\n}\n\nexport function getSpAuthPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"auth.json\");\n}\n\nexport function getSpSettingsPath(agentDir = getSpAgentDir()) {\n\treturn join(agentDir, \"settings.json\");\n}\n\nfunction readJsonFile(path: string): JsonRecord {\n\tif (!existsSync(path)) return {};\n\tconst content = readFileSync(path, \"utf8\").trim();\n\tif (!content) return {};\n\tconst parsed = JSON.parse(content) as unknown;\n\tif (!isRecord(parsed)) throw new Error(`Expected an object in ${path}`);\n\treturn parsed;\n}\n\nfunction writePrivateJson(path: string, value: unknown) {\n\tmkdirSync(dirname(path), { recursive: true });\n\tconst temporaryPath = `${path}.${process.pid}.tmp`;\n\twriteFileSync(temporaryPath, `${JSON.stringify(value, null, \"\\t\")}\\n`, { encoding: \"utf8\", mode: 0o600 });\n\tif (process.platform !== \"win32\") chmodSync(temporaryPath, 0o600);\n\trenameSync(temporaryPath, path);\n\tif (process.platform !== \"win32\") chmodSync(path, 0o600);\n}\n\nexport function normalizeSpGatewayBaseUrl(input: string) {\n\tconst trimmed = input.trim();\n\tif (!trimmed) throw new Error(\"Gateway URL cannot be empty.\");\n\tconst withScheme = /^[a-z][a-z0-9+.-]*:\\/\\//iu.test(trimmed) ? trimmed : `https://${trimmed}`;\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(withScheme);\n\t} catch {\n\t\tthrow new Error(`Invalid gateway URL: ${input}`);\n\t}\n\tif (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n\t\tthrow new Error(\"Gateway URL must use HTTPS or HTTP.\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\");\n\tif (!url.pathname.endsWith(\"/v1\")) url.pathname = `${url.pathname}/v1`.replace(/\\/+/gu, \"/\");\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nfunction parseInput(value: unknown): (\"text\" | \"image\")[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst input = value.filter((entry): entry is \"text\" | \"image\" => entry === \"text\" || entry === \"image\");\n\treturn input.length > 0 ? [...new Set(input)] : undefined;\n}\n\nfunction parseCost(value: unknown): SpProviderModelConfig[\"cost\"] | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst input = nonNegativeNumber(value.input);\n\tconst output = nonNegativeNumber(value.output);\n\tconst cacheRead = nonNegativeNumber(value.cacheRead);\n\tconst cacheWrite = nonNegativeNumber(value.cacheWrite);\n\tif (input === undefined && output === undefined && cacheRead === undefined && cacheWrite === undefined)\n\t\treturn undefined;\n\treturn { input: input ?? 0, output: output ?? 0, cacheRead: cacheRead ?? 0, cacheWrite: cacheWrite ?? 0 };\n}\n\nfunction parseThinkingLevelMap(value: unknown): SpProviderModelConfig[\"thinkingLevelMap\"] {\n\tif (!isRecord(value)) return undefined;\n\tconst result: NonNullable<SpProviderModelConfig[\"thinkingLevelMap\"]> = {};\n\tfor (const key of [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const) {\n\t\tconst entry = value[key];\n\t\tif (typeof entry === \"string\" || entry === null) result[key] = entry;\n\t}\n\treturn Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction thinkingFormat(value: unknown): OpenAICompletionsCompat[\"thinkingFormat\"] {\n\tswitch (value) {\n\t\tcase \"openai\":\n\t\tcase \"openrouter\":\n\t\tcase \"deepseek\":\n\t\tcase \"together\":\n\t\tcase \"zai\":\n\t\tcase \"qwen\":\n\t\tcase \"chat-template\":\n\t\tcase \"qwen-chat-template\":\n\t\tcase \"string-thinking\":\n\t\tcase \"ant-ling\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction sessionAffinityFormat(value: unknown): OpenAICompletionsCompat[\"sessionAffinityFormat\"] {\n\treturn value === \"openai\" || value === \"openai-nosession\" || value === \"openrouter\" ? value : undefined;\n}\n\nfunction parseCompat(value: unknown): OpenAICompletionsCompat {\n\tconst record = isRecord(value) ? value : {};\n\tconst maxTokensField =\n\t\trecord.maxTokensField === \"max_completion_tokens\" || record.maxTokensField === \"max_tokens\"\n\t\t\t? record.maxTokensField\n\t\t\t: undefined;\n\tconst compat = {\n\t\tsupportsStore: booleanValue(record.supportsStore) ?? false,\n\t\tsupportsDeveloperRole: booleanValue(record.supportsDeveloperRole),\n\t\tsupportsReasoningEffort: booleanValue(record.supportsReasoningEffort),\n\t\tsupportsUsageInStreaming: booleanValue(record.supportsUsageInStreaming),\n\t\tmaxTokensField,\n\t\trequiresToolResultName: booleanValue(record.requiresToolResultName),\n\t\trequiresAssistantAfterToolResult: booleanValue(record.requiresAssistantAfterToolResult),\n\t\trequiresThinkingAsText: booleanValue(record.requiresThinkingAsText),\n\t\trequiresReasoningContentOnAssistantMessages: booleanValue(record.requiresReasoningContentOnAssistantMessages),\n\t\tthinkingFormat: thinkingFormat(record.thinkingFormat),\n\t\tsupportsStrictMode: booleanValue(record.supportsStrictMode),\n\t\tsendSessionAffinityHeaders: booleanValue(record.sendSessionAffinityHeaders),\n\t\tsessionAffinityFormat: sessionAffinityFormat(record.sessionAffinityFormat),\n\t\tsupportsLongCacheRetention: booleanValue(record.supportsLongCacheRetention),\n\t} satisfies OpenAICompletionsCompat;\n\treturn compat;\n}\n\nfunction parseGatewayModel(value: unknown): SpProviderModelConfig | undefined {\n\tconst record = typeof value === \"string\" ? { id: value } : isRecord(value) ? value : undefined;\n\tif (!record) return undefined;\n\tconst id = stringValue(record.id);\n\tif (!id || id.length > 256 || /[\\u0000-\\u001f\\u007f]/u.test(id)) return undefined;\n\tconst metadata = isRecord(record.metadata) ? record.metadata : {};\n\tconst field = (name: string) => metadata[name] ?? record[name];\n\tconst reasoning = field(\"reasoning\");\n\treturn {\n\t\tid,\n\t\tname: stringValue(field(\"name\")) ?? id,\n\t\treasoning: typeof reasoning === \"boolean\" ? reasoning : false,\n\t\tthinkingLevelMap: parseThinkingLevelMap(field(\"thinkingLevelMap\")),\n\t\tinput: parseInput(field(\"input\")) ?? [\"text\"],\n\t\tcost: parseCost(field(\"cost\")) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: positiveInteger(field(\"contextWindow\")) ?? 128_000,\n\t\tmaxTokens: positiveInteger(field(\"maxTokens\")) ?? 32_000,\n\t\tcompat: parseCompat(field(\"compat\")),\n\t};\n}\n\nfunction parseModelCatalog(values: readonly unknown[], source: string) {\n\tconst models = values.map(parseGatewayModel).filter((model): model is SpProviderModelConfig => model !== undefined);\n\tif (models.length === 0) throw new Error(`${source} contains no valid models.`);\n\tconst ids = new Set<string>();\n\tfor (const model of models) {\n\t\tif (ids.has(model.id)) throw new Error(`${source} contains duplicate model id ${model.id}.`);\n\t\tids.add(model.id);\n\t}\n\treturn models;\n}\n\nexport async function fetchSpGatewayModels(baseUrl: string, apiKey: string, signal?: AbortSignal) {\n\tconst response = await fetch(`${baseUrl.replace(/\\/$/u, \"\")}/models`, {\n\t\tsignal,\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\tAccept: \"application/json\",\n\t\t\t\"User-Agent\": SP_USER_AGENT,\n\t\t\t\"X-Senpiper-Client\": SP_CLIENT_NAME,\n\t\t},\n\t});\n\tif (!response.ok) {\n\t\tconst body = await response.text().catch(() => \"\");\n\t\tconst suffix = body.trim() ? `: ${body.trim().slice(0, 300)}` : \"\";\n\t\tthrow new Error(`Senpiper Gateway rejected /v1/models (${response.status} ${response.statusText})${suffix}`);\n\t}\n\tconst payload = (await response.json()) as unknown;\n\tif (!isRecord(payload) || !Array.isArray(payload.data)) {\n\t\tthrow new Error(\"Senpiper Gateway returned an invalid /v1/models envelope.\");\n\t}\n\treturn parseModelCatalog(payload.data, \"Senpiper Gateway /v1/models response\");\n}\n\nfunction readLegacySpGatewayState(agentDir: string): SpGatewayState | undefined {\n\tconst path = getLegacyModelsPath(agentDir);\n\tif (!existsSync(path)) return undefined;\n\tconst root = readJsonFile(path);\n\tconst providers = isRecord(root.providers) ? root.providers : undefined;\n\tconst providerValue = providers?.[SP_GATEWAY_PROVIDER_ID] ?? providers?.[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\tconst provider = isRecord(providerValue) ? providerValue : undefined;\n\tif (!provider || typeof provider.baseUrl !== \"string\" || !Array.isArray(provider.models)) return undefined;\n\treturn {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(provider.baseUrl),\n\t\tmodels: parseModelCatalog(provider.models, `legacy Senpiper Gateway cache ${path}`),\n\t};\n}\n\nexport function readSpGatewayState(agentDir = getSpAgentDir()): SpGatewayState | undefined {\n\tconst path = getSpGatewayStatePath(agentDir);\n\tif (!existsSync(path)) {\n\t\tconst legacy = readLegacySpGatewayState(agentDir);\n\t\tif (!legacy) return undefined;\n\t\twriteSpGatewayState(legacy.baseUrl, legacy.models, agentDir);\n\t\tgatewayWarning = {\n\t\t\tkind: \"legacy_cache_imported\",\n\t\t\tmessage: `Imported the legacy Senpiper Gateway model cache from ${getLegacyModelsPath(agentDir)}.`,\n\t\t\tat: new Date().toISOString(),\n\t\t};\n\t\treturn legacy;\n\t}\n\tconst value = readJsonFile(path);\n\tif (value.schemaVersion !== 1 || typeof value.baseUrl !== \"string\" || !Array.isArray(value.models)) {\n\t\tthrow new Error(`Invalid Senpiper Gateway configuration: ${path}`);\n\t}\n\treturn {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(value.baseUrl),\n\t\tmodels: parseModelCatalog(value.models, `Senpiper Gateway configuration ${path}`),\n\t};\n}\n\nexport function writeSpGatewayState(baseUrl: string, models: SpProviderModelConfig[], agentDir = getSpAgentDir()) {\n\tconst validatedModels = parseModelCatalog(models, \"Senpiper Gateway state\");\n\twritePrivateJson(getSpGatewayStatePath(agentDir), {\n\t\tschemaVersion: 1,\n\t\tbaseUrl: normalizeSpGatewayBaseUrl(baseUrl),\n\t\tmodels: validatedModels,\n\t} satisfies SpGatewayState);\n}\n\nexport function readSpGatewayApiKey(agentDir = getSpAgentDir()) {\n\tconst path = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(path);\n\tlet credential = auth[SP_GATEWAY_PROVIDER_ID];\n\tif (!credential && auth[LEGACY_SP_GATEWAY_PROVIDER_ID]) {\n\t\tcredential = auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\t\tauth[SP_GATEWAY_PROVIDER_ID] = credential;\n\t\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\t\twritePrivateJson(path, auth);\n\t}\n\treturn isRecord(credential) && credential.type === \"api_key\" && typeof credential.key === \"string\"\n\t\t? credential.key\n\t\t: undefined;\n}\n\nexport function writeSpGatewayLogin(apiKey: string, firstModelId: string, agentDir = getSpAgentDir()) {\n\tconst authPath = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(authPath);\n\tauth[SP_GATEWAY_PROVIDER_ID] = { type: \"api_key\", key: apiKey };\n\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\twritePrivateJson(authPath, auth);\n\n\tconst settingsPath = getSpSettingsPath(agentDir);\n\tconst settings = readJsonFile(settingsPath);\n\tsettings.defaultProvider = SP_GATEWAY_PROVIDER_ID;\n\tsettings.defaultModel = firstModelId;\n\twritePrivateJson(settingsPath, settings);\n}\n\nexport function removeSpGatewayLogin(agentDir = getSpAgentDir()) {\n\tconst path = getSpAuthPath(agentDir);\n\tconst auth = readJsonFile(path);\n\tdelete auth[SP_GATEWAY_PROVIDER_ID];\n\tdelete auth[LEGACY_SP_GATEWAY_PROVIDER_ID];\n\twritePrivateJson(path, auth);\n}\n\nfunction credentialKey(context: RefreshModelsContext) {\n\treturn context.credential?.type === \"api_key\" ? context.credential.key : undefined;\n}\n\nfunction storedModels(models: readonly SpProviderModelConfig[], baseUrl: string): Model<Api>[] {\n\treturn models.map((model) => ({\n\t\t...model,\n\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\tbaseUrl,\n\t\tapi: \"openai-completions\",\n\t}));\n}\n\nexport function getSpGatewayWarning() {\n\treturn gatewayWarning;\n}\n\nexport function clearSpGatewayWarning() {\n\tgatewayWarning = undefined;\n}\n\nexport function createSpGatewayProviderConfig(\n\tbaseUrl: string,\n\tmodels: SpProviderModelConfig[],\n\tagentDir = getSpAgentDir(),\n): ProviderConfig {\n\tlet currentModels = parseModelCatalog(models, \"Senpiper Gateway provider configuration\");\n\treturn {\n\t\tname: SP_GATEWAY_PROVIDER_NAME,\n\t\tbaseUrl,\n\t\tapi: \"openai-completions\",\n\t\tauthHeader: true,\n\t\theaders: {\n\t\t\t\"User-Agent\": SP_USER_AGENT,\n\t\t\t\"X-Senpiper-Client\": SP_CLIENT_NAME,\n\t\t},\n\t\tmodels: currentModels,\n\t\tasync refreshModels(context) {\n\t\t\tif (!context.allowNetwork) return currentModels;\n\t\t\tconst apiKey = credentialKey(context);\n\t\t\tif (!apiKey) return currentModels;\n\t\t\ttry {\n\t\t\t\tconst refreshed = await fetchSpGatewayModels(baseUrl, apiKey, context.signal);\n\t\t\t\tif (context.signal.aborted) return currentModels;\n\t\t\t\tawait context.publish({\n\t\t\t\t\tpersist: { models: storedModels(refreshed, baseUrl), checkedAt: Date.now() },\n\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\twriteSpGatewayState(baseUrl, refreshed, agentDir);\n\t\t\t\t\t\tcurrentModels = refreshed;\n\t\t\t\t\t\tgatewayWarning = undefined;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn currentModels;\n\t\t\t} catch (error) {\n\t\t\t\tgatewayWarning = {\n\t\t\t\t\tkind: \"refresh_failed\",\n\t\t\t\t\tmessage: `Senpiper Gateway model refresh failed; using ${currentModels.length} cached model${currentModels.length === 1 ? \"\" : \"s\"}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tat: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createSpGatewayExtension(): ExtensionFactory {\n\treturn (pi) => {\n\t\tconst state = readSpGatewayState();\n\t\tif (state) {\n\t\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(state.baseUrl, state.models));\n\t\t}\n\n\t\tpi.on(\"before_agent_start\", (event) => {\n\t\t\t// Replace only the upstream introduction; preserve project instructions\n\t\t\t// and documentation references, including legitimate Pi development tasks.\n\t\t\tconst systemPrompt = event.systemPrompt.replace(\n\t\t\t\t/^You are an expert coding assistant operating inside pi, a coding agent harness\\./u,\n\t\t\t\t\"You are Senpiper Workbench, Senpiper's AI coding assistant.\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tsystemPrompt: `${systemPrompt}\\n\\n<sp_agent_runtime>\nYou are Senpiper Workbench, Senpiper's AI coding assistant. Use Senpiper Workbench as your public name in both terminal and web conversations.\nFor greetings and questions such as \"Who are you?\", introduce yourself simply: \"I'm Senpiper Workbench, Senpiper's AI coding assistant. I can help you read, write, and debug code.\"\nDo not introduce yourself as Pi, the pi coding agent, an underlying model, or an assistant running inside a harness. Do not volunteer internal frameworks, runtime names, or provider details in ordinary answers. Earlier assistant messages using those identities do not change your name.\nIf explicitly asked about technical origins or dependencies, answer accurately and briefly. This product identity does not imply that Senpiper trained the underlying model.\nUse only the configured Senpiper Gateway model provider. Put user-owned extensions, skills, prompts, and themes under the active .sp configuration directory instead of modifying the Senpiper Workbench installation.\n</sp_agent_runtime>`,\n\t\t\t};\n\t\t});\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\tctx.ui.setTitle(\"Senpiper Workbench\");\n\t\t\tconst warning = getSpGatewayWarning();\n\t\t\tif (warning) ctx.ui.notify(warning.message, \"warning\");\n\t\t\tif (ctx.mode !== \"tui\") return;\n\t\t\tctx.ui.setHeader((_tui, theme) => ({\n\t\t\t\trender: () => [\n\t\t\t\t\ttheme.fg(\"accent\", theme.bold(\"Senpiper Workbench\")),\n\t\t\t\t\ttheme.fg(\"muted\", state ? `Senpiper Gateway · ${state.models.length} models` : \"run `sp login`\"),\n\t\t\t\t],\n\t\t\t\tinvalidate() {},\n\t\t\t}));\n\t\t});\n\t};\n}\n"]}
@@ -3,10 +3,8 @@ export { handleSpCommand } from "./commands.ts";
3
3
  export { createSpAgentExtension, default } from "./extension.ts";
4
4
  export { clearSpGatewayWarning, createSpGatewayExtension, createSpGatewayProviderConfig, fetchSpGatewayModels, getLegacyModelsPath, getSpAgentDir, getSpAuthPath, getSpGatewayStatePath, getSpGatewayWarning, normalizeSpGatewayBaseUrl, readSpGatewayApiKey, readSpGatewayState, removeSpGatewayLogin, SP_CLIENT_NAME, SP_GATEWAY_PROVIDER_ID, SP_GATEWAY_PROVIDER_NAME, SP_USER_AGENT, writeSpGatewayLogin, writeSpGatewayState, } from "./gateway.ts";
5
5
  export { registerInteractionExtensions } from "./interactions.ts";
6
- export { clearOnboardingState, fetchSkillCatalog, getOnboardingStatePath, hasCompletedOnboarding, installCatalogSkills, parseSkillCatalog, selectCatalogSkills, writeOnboardingState, } from "./onboarding.ts";
7
- export { installOnboardingSelection, type OnboardingInstallationResult } from "./onboarding-installation.ts";
8
6
  export type { PendingQuestion, QuestionResponse } from "./question-interaction.ts";
9
- export { ensureSpWebSidecar, getSpWebSidecarStatePath, resolveSpWebLaunch, type SpWebLauncherOptions, type SpWebLaunchResult, type SpWebSidecarState, } from "./sp-web-launcher.ts";
7
+ export { ensureSpWebSidecar, getSpWebSidecarStatePath, resolveSpWebLaunch, type SpWebLauncherOptions, type SpWebLaunchResult, type SpWebSidecarState, type SpWebStopResult, stopSpWebSidecar, } from "./sp-web-launcher.ts";
10
8
  export { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from "./startup-header.ts";
11
9
  export { DEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES, DEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS, DEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES, readTerminalBridgeDescriptor, registerTerminalWebBridge, TERMINAL_BRIDGE_PROTOCOL, TERMINAL_BRIDGE_VERSION, type TerminalBridgeDescriptor, TerminalWebBridge, type TerminalWebBridgeOptions, terminalBridgeDescriptorExists, } from "./terminal-web-bridge.ts";
12
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,4BAA4B,EAC5B,mCAAmC,EACnC,uBAAuB,EACvB,+BAA+B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EACN,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EACN,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,0BAA0B,EAAE,KAAK,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC7G,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EACN,0CAA0C,EAC1C,mCAAmC,EACnC,uCAAuC,EACvC,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n\tAskUserSchema,\n\tbuildAskUserQuestionResponse,\n\tcreateAskUserQuestionToolDefinition,\n\tregisterAskUserQuestion,\n\tvalidateAskUserQuestionEnvelope,\n} from \"./ask-user.ts\";\nexport { handleSpCommand } from \"./commands.ts\";\nexport { createSpAgentExtension, default } from \"./extension.ts\";\nexport {\n\tclearSpGatewayWarning,\n\tcreateSpGatewayExtension,\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetLegacyModelsPath,\n\tgetSpAgentDir,\n\tgetSpAuthPath,\n\tgetSpGatewayStatePath,\n\tgetSpGatewayWarning,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayApiKey,\n\treadSpGatewayState,\n\tremoveSpGatewayLogin,\n\tSP_CLIENT_NAME,\n\tSP_GATEWAY_PROVIDER_ID,\n\tSP_GATEWAY_PROVIDER_NAME,\n\tSP_USER_AGENT,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nexport { registerInteractionExtensions } from \"./interactions.ts\";\nexport {\n\tclearOnboardingState,\n\tfetchSkillCatalog,\n\tgetOnboardingStatePath,\n\thasCompletedOnboarding,\n\tinstallCatalogSkills,\n\tparseSkillCatalog,\n\tselectCatalogSkills,\n\twriteOnboardingState,\n} from \"./onboarding.ts\";\nexport { installOnboardingSelection, type OnboardingInstallationResult } from \"./onboarding-installation.ts\";\nexport type { PendingQuestion, QuestionResponse } from \"./question-interaction.ts\";\nexport {\n\tensureSpWebSidecar,\n\tgetSpWebSidecarStatePath,\n\tresolveSpWebLaunch,\n\ttype SpWebLauncherOptions,\n\ttype SpWebLaunchResult,\n\ttype SpWebSidecarState,\n} from \"./sp-web-launcher.ts\";\nexport { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from \"./startup-header.ts\";\nexport {\n\tDEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES,\n\treadTerminalBridgeDescriptor,\n\tregisterTerminalWebBridge,\n\tTERMINAL_BRIDGE_PROTOCOL,\n\tTERMINAL_BRIDGE_VERSION,\n\ttype TerminalBridgeDescriptor,\n\tTerminalWebBridge,\n\ttype TerminalWebBridgeOptions,\n\tterminalBridgeDescriptorExists,\n} from \"./terminal-web-bridge.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,4BAA4B,EAC5B,mCAAmC,EACnC,uBAAuB,EACvB,+BAA+B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EACN,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EACN,0CAA0C,EAC1C,mCAAmC,EACnC,uCAAuC,EACvC,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n\tAskUserSchema,\n\tbuildAskUserQuestionResponse,\n\tcreateAskUserQuestionToolDefinition,\n\tregisterAskUserQuestion,\n\tvalidateAskUserQuestionEnvelope,\n} from \"./ask-user.ts\";\nexport { handleSpCommand } from \"./commands.ts\";\nexport { createSpAgentExtension, default } from \"./extension.ts\";\nexport {\n\tclearSpGatewayWarning,\n\tcreateSpGatewayExtension,\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetLegacyModelsPath,\n\tgetSpAgentDir,\n\tgetSpAuthPath,\n\tgetSpGatewayStatePath,\n\tgetSpGatewayWarning,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayApiKey,\n\treadSpGatewayState,\n\tremoveSpGatewayLogin,\n\tSP_CLIENT_NAME,\n\tSP_GATEWAY_PROVIDER_ID,\n\tSP_GATEWAY_PROVIDER_NAME,\n\tSP_USER_AGENT,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nexport { registerInteractionExtensions } from \"./interactions.ts\";\nexport type { PendingQuestion, QuestionResponse } from \"./question-interaction.ts\";\nexport {\n\tensureSpWebSidecar,\n\tgetSpWebSidecarStatePath,\n\tresolveSpWebLaunch,\n\ttype SpWebLauncherOptions,\n\ttype SpWebLaunchResult,\n\ttype SpWebSidecarState,\n\ttype SpWebStopResult,\n\tstopSpWebSidecar,\n} from \"./sp-web-launcher.ts\";\nexport { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from \"./startup-header.ts\";\nexport {\n\tDEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES,\n\treadTerminalBridgeDescriptor,\n\tregisterTerminalWebBridge,\n\tTERMINAL_BRIDGE_PROTOCOL,\n\tTERMINAL_BRIDGE_VERSION,\n\ttype TerminalBridgeDescriptor,\n\tTerminalWebBridge,\n\ttype TerminalWebBridgeOptions,\n\tterminalBridgeDescriptorExists,\n} from \"./terminal-web-bridge.ts\";\n"]}
@@ -3,9 +3,7 @@ export { handleSpCommand } from "./commands.js";
3
3
  export { createSpAgentExtension, default } from "./extension.js";
4
4
  export { clearSpGatewayWarning, createSpGatewayExtension, createSpGatewayProviderConfig, fetchSpGatewayModels, getLegacyModelsPath, getSpAgentDir, getSpAuthPath, getSpGatewayStatePath, getSpGatewayWarning, normalizeSpGatewayBaseUrl, readSpGatewayApiKey, readSpGatewayState, removeSpGatewayLogin, SP_CLIENT_NAME, SP_GATEWAY_PROVIDER_ID, SP_GATEWAY_PROVIDER_NAME, SP_USER_AGENT, writeSpGatewayLogin, writeSpGatewayState, } from "./gateway.js";
5
5
  export { registerInteractionExtensions } from "./interactions.js";
6
- export { clearOnboardingState, fetchSkillCatalog, getOnboardingStatePath, hasCompletedOnboarding, installCatalogSkills, parseSkillCatalog, selectCatalogSkills, writeOnboardingState, } from "./onboarding.js";
7
- export { installOnboardingSelection } from "./onboarding-installation.js";
8
- export { ensureSpWebSidecar, getSpWebSidecarStatePath, resolveSpWebLaunch, } from "./sp-web-launcher.js";
6
+ export { ensureSpWebSidecar, getSpWebSidecarStatePath, resolveSpWebLaunch, stopSpWebSidecar, } from "./sp-web-launcher.js";
9
7
  export { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from "./startup-header.js";
10
8
  export { DEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES, DEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS, DEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES, readTerminalBridgeDescriptor, registerTerminalWebBridge, TERMINAL_BRIDGE_PROTOCOL, TERMINAL_BRIDGE_VERSION, TerminalWebBridge, terminalBridgeDescriptorExists, } from "./terminal-web-bridge.js";
11
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,4BAA4B,EAC5B,mCAAmC,EACnC,uBAAuB,EACvB,+BAA+B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EACN,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EACN,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,0BAA0B,EAAqC,MAAM,8BAA8B,CAAC;AAE7G,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,GAIlB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EACN,0CAA0C,EAC1C,mCAAmC,EACnC,uCAAuC,EACvC,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EAEvB,iBAAiB,EAEjB,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n\tAskUserSchema,\n\tbuildAskUserQuestionResponse,\n\tcreateAskUserQuestionToolDefinition,\n\tregisterAskUserQuestion,\n\tvalidateAskUserQuestionEnvelope,\n} from \"./ask-user.ts\";\nexport { handleSpCommand } from \"./commands.ts\";\nexport { createSpAgentExtension, default } from \"./extension.ts\";\nexport {\n\tclearSpGatewayWarning,\n\tcreateSpGatewayExtension,\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetLegacyModelsPath,\n\tgetSpAgentDir,\n\tgetSpAuthPath,\n\tgetSpGatewayStatePath,\n\tgetSpGatewayWarning,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayApiKey,\n\treadSpGatewayState,\n\tremoveSpGatewayLogin,\n\tSP_CLIENT_NAME,\n\tSP_GATEWAY_PROVIDER_ID,\n\tSP_GATEWAY_PROVIDER_NAME,\n\tSP_USER_AGENT,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nexport { registerInteractionExtensions } from \"./interactions.ts\";\nexport {\n\tclearOnboardingState,\n\tfetchSkillCatalog,\n\tgetOnboardingStatePath,\n\thasCompletedOnboarding,\n\tinstallCatalogSkills,\n\tparseSkillCatalog,\n\tselectCatalogSkills,\n\twriteOnboardingState,\n} from \"./onboarding.ts\";\nexport { installOnboardingSelection, type OnboardingInstallationResult } from \"./onboarding-installation.ts\";\nexport type { PendingQuestion, QuestionResponse } from \"./question-interaction.ts\";\nexport {\n\tensureSpWebSidecar,\n\tgetSpWebSidecarStatePath,\n\tresolveSpWebLaunch,\n\ttype SpWebLauncherOptions,\n\ttype SpWebLaunchResult,\n\ttype SpWebSidecarState,\n} from \"./sp-web-launcher.ts\";\nexport { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from \"./startup-header.ts\";\nexport {\n\tDEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES,\n\treadTerminalBridgeDescriptor,\n\tregisterTerminalWebBridge,\n\tTERMINAL_BRIDGE_PROTOCOL,\n\tTERMINAL_BRIDGE_VERSION,\n\ttype TerminalBridgeDescriptor,\n\tTerminalWebBridge,\n\ttype TerminalWebBridgeOptions,\n\tterminalBridgeDescriptorExists,\n} from \"./terminal-web-bridge.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,4BAA4B,EAC5B,mCAAmC,EACnC,uBAAuB,EACvB,+BAA+B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EACN,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAKlB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EACN,0CAA0C,EAC1C,mCAAmC,EACnC,uCAAuC,EACvC,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EAEvB,iBAAiB,EAEjB,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n\tAskUserSchema,\n\tbuildAskUserQuestionResponse,\n\tcreateAskUserQuestionToolDefinition,\n\tregisterAskUserQuestion,\n\tvalidateAskUserQuestionEnvelope,\n} from \"./ask-user.ts\";\nexport { handleSpCommand } from \"./commands.ts\";\nexport { createSpAgentExtension, default } from \"./extension.ts\";\nexport {\n\tclearSpGatewayWarning,\n\tcreateSpGatewayExtension,\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetLegacyModelsPath,\n\tgetSpAgentDir,\n\tgetSpAuthPath,\n\tgetSpGatewayStatePath,\n\tgetSpGatewayWarning,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayApiKey,\n\treadSpGatewayState,\n\tremoveSpGatewayLogin,\n\tSP_CLIENT_NAME,\n\tSP_GATEWAY_PROVIDER_ID,\n\tSP_GATEWAY_PROVIDER_NAME,\n\tSP_USER_AGENT,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nexport { registerInteractionExtensions } from \"./interactions.ts\";\nexport type { PendingQuestion, QuestionResponse } from \"./question-interaction.ts\";\nexport {\n\tensureSpWebSidecar,\n\tgetSpWebSidecarStatePath,\n\tresolveSpWebLaunch,\n\ttype SpWebLauncherOptions,\n\ttype SpWebLaunchResult,\n\ttype SpWebSidecarState,\n\ttype SpWebStopResult,\n\tstopSpWebSidecar,\n} from \"./sp-web-launcher.ts\";\nexport { filterSpStartupMessage, registerSpStartupHeader, renderSpStartupHeader } from \"./startup-header.ts\";\nexport {\n\tDEFAULT_TERMINAL_BRIDGE_MAX_BUFFERED_BYTES,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_CLIENTS,\n\tDEFAULT_TERMINAL_BRIDGE_MAX_FRAME_BYTES,\n\treadTerminalBridgeDescriptor,\n\tregisterTerminalWebBridge,\n\tTERMINAL_BRIDGE_PROTOCOL,\n\tTERMINAL_BRIDGE_VERSION,\n\ttype TerminalBridgeDescriptor,\n\tTerminalWebBridge,\n\ttype TerminalWebBridgeOptions,\n\tterminalBridgeDescriptorExists,\n} from \"./terminal-web-bridge.ts\";\n"]}
@@ -1,7 +1,5 @@
1
1
  import type { ExtensionAPI, ExtensionCommandContext } from "@senpiper/pi-coding-agent";
2
- import { runInteractiveOnboarding } from "./onboarding-command.ts";
3
2
  export type InteractionContext = ExtensionCommandContext;
4
3
  export type InteractionExtensionApi = ExtensionAPI;
5
- export { runInteractiveOnboarding };
6
4
  export declare function registerInteractionExtensions(pi: ExtensionAPI): void;
7
5
  //# sourceMappingURL=interactions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAA6B,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAE9F,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACzD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,CAAC;AAEpC,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,YAAY,QAG7D","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport { registerAskUserQuestion } from \"./ask-user.ts\";\nimport { registerOnboardingCommand, runInteractiveOnboarding } from \"./onboarding-command.ts\";\n\nexport type InteractionContext = ExtensionCommandContext;\nexport type InteractionExtensionApi = ExtensionAPI;\nexport { runInteractiveOnboarding };\n\nexport function registerInteractionExtensions(pi: ExtensionAPI) {\n\tregisterAskUserQuestion(pi);\n\tregisterOnboardingCommand(pi);\n}\n"]}
1
+ {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGvF,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACzD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC;AAEnD,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,YAAY,QAE7D","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport { registerAskUserQuestion } from \"./ask-user.ts\";\n\nexport type InteractionContext = ExtensionCommandContext;\nexport type InteractionExtensionApi = ExtensionAPI;\n\nexport function registerInteractionExtensions(pi: ExtensionAPI) {\n\tregisterAskUserQuestion(pi);\n}\n"]}
@@ -1,8 +1,5 @@
1
1
  import { registerAskUserQuestion } from "./ask-user.js";
2
- import { registerOnboardingCommand, runInteractiveOnboarding } from "./onboarding-command.js";
3
- export { runInteractiveOnboarding };
4
2
  export function registerInteractionExtensions(pi) {
5
3
  registerAskUserQuestion(pi);
6
- registerOnboardingCommand(pi);
7
4
  }
8
5
  //# sourceMappingURL=interactions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAI9F,OAAO,EAAE,wBAAwB,EAAE,CAAC;AAEpC,MAAM,UAAU,6BAA6B,CAAC,EAAgB,EAAE;IAC/D,uBAAuB,CAAC,EAAE,CAAC,CAAC;IAC5B,yBAAyB,CAAC,EAAE,CAAC,CAAC;AAAA,CAC9B","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport { registerAskUserQuestion } from \"./ask-user.ts\";\nimport { registerOnboardingCommand, runInteractiveOnboarding } from \"./onboarding-command.ts\";\n\nexport type InteractionContext = ExtensionCommandContext;\nexport type InteractionExtensionApi = ExtensionAPI;\nexport { runInteractiveOnboarding };\n\nexport function registerInteractionExtensions(pi: ExtensionAPI) {\n\tregisterAskUserQuestion(pi);\n\tregisterOnboardingCommand(pi);\n}\n"]}
1
+ {"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAKxD,MAAM,UAAU,6BAA6B,CAAC,EAAgB,EAAE;IAC/D,uBAAuB,CAAC,EAAE,CAAC,CAAC;AAAA,CAC5B","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport { registerAskUserQuestion } from \"./ask-user.ts\";\n\nexport type InteractionContext = ExtensionCommandContext;\nexport type InteractionExtensionApi = ExtensionAPI;\n\nexport function registerInteractionExtensions(pi: ExtensionAPI) {\n\tregisterAskUserQuestion(pi);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"login-command.d.ts","sourceRoot":"","sources":["../src/login-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAcvF,wBAAsB,aAAa,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,oBAyDnG;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,QAYpD","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport {\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetSpAgentDir,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayState,\n\tSP_GATEWAY_PROVIDER_ID,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nimport { hasCompletedOnboarding } from \"./onboarding.ts\";\nimport { runInteractiveOnboarding } from \"./onboarding-command.ts\";\n\nexport async function runSlashLogin(pi: ExtensionAPI, args: string, context: ExtensionCommandContext) {\n\tconst existingState = readSpGatewayState();\n\tconst argumentUrl = args.trim();\n\tconst enteredUrl = argumentUrl\n\t\t? argumentUrl\n\t\t: await context.ui.input(\"sp-gateway URL\", existingState?.baseUrl ?? \"https://gateway.example.com/v1\");\n\tif (enteredUrl === undefined) {\n\t\tcontext.ui.notify(\"sp-gateway login cancelled.\", \"warning\");\n\t\treturn false;\n\t}\n\tconst gatewayUrl = enteredUrl.trim() || existingState?.baseUrl;\n\tif (!gatewayUrl) {\n\t\tcontext.ui.notify(\"A sp-gateway URL is required.\", \"error\");\n\t\treturn false;\n\t}\n\tconst apiKey = await context.ui.input(\"sp-gateway API key\", \"Paste your API key\", { secret: true });\n\tif (!apiKey?.trim()) {\n\t\tcontext.ui.notify(apiKey === undefined ? \"sp-gateway login cancelled.\" : \"An API key is required.\", \"warning\");\n\t\treturn false;\n\t}\n\n\tcontext.ui.setProgress(\"Connecting to sp-gateway and synchronizing models…\");\n\ttry {\n\t\tconst baseUrl = normalizeSpGatewayBaseUrl(gatewayUrl);\n\t\tconst models = await fetchSpGatewayModels(baseUrl, apiKey.trim());\n\t\twriteSpGatewayState(baseUrl, models);\n\t\twriteSpGatewayLogin(apiKey.trim(), models[0]!.id);\n\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(baseUrl, models));\n\t\tawait context.modelRegistry.setRuntimeApiKey(SP_GATEWAY_PROVIDER_ID, apiKey.trim());\n\t\tconst firstModel = models[0]!;\n\t\tconst selected = await pi.setModel({\n\t\t\t...firstModel,\n\t\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\t\tbaseUrl,\n\t\t\tapi: \"openai-completions\",\n\t\t});\n\t\tcontext.ui.notify(\n\t\t\tselected\n\t\t\t\t? `Connected to sp-gateway · ${models.length} models · selected ${firstModel.id}.`\n\t\t\t\t: `Connected to sp-gateway · ${models.length} models available. Use /model to select one.`,\n\t\t\t\"info\",\n\t\t);\n\t} finally {\n\t\tcontext.ui.setProgress(undefined);\n\t}\n\n\tif (!hasCompletedOnboarding(getSpAgentDir())) {\n\t\ttry {\n\t\t\tawait runInteractiveOnboarding(context);\n\t\t} catch (error) {\n\t\t\tcontext.ui.notify(\n\t\t\t\t`Onboarding deferred: ${error instanceof Error ? error.message : String(error)}. Run /onboarding later.`,\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t}\n\t}\n\treturn true;\n}\n\nexport function registerLoginCommand(pi: ExtensionAPI) {\n\tpi.registerCommand(\"login\", {\n\t\tdescription: \"Log in to SP Gateway\",\n\t\thandler: async (args, context) => {\n\t\t\ttry {\n\t\t\t\tawait runSlashLogin(pi, args, context);\n\t\t\t} catch (error) {\n\t\t\t\tcontext.ui.setProgress(undefined);\n\t\t\t\tcontext.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"login-command.d.ts","sourceRoot":"","sources":["../src/login-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAWvF,wBAAsB,aAAa,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,oBAkDnG;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,QAYpD","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport {\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayState,\n\tSP_GATEWAY_PROVIDER_ID,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\n\nexport async function runSlashLogin(pi: ExtensionAPI, args: string, context: ExtensionCommandContext) {\n\tconst existingState = readSpGatewayState();\n\tconst argumentUrl = args.trim();\n\tconst enteredUrl = argumentUrl\n\t\t? argumentUrl\n\t\t: await context.ui.input(\"Senpiper Gateway URL\", existingState?.baseUrl ?? \"https://gateway.example.com/v1\");\n\tif (enteredUrl === undefined) {\n\t\tcontext.ui.notify(\"Senpiper Gateway login cancelled.\", \"warning\");\n\t\treturn false;\n\t}\n\tconst gatewayUrl = enteredUrl.trim() || existingState?.baseUrl;\n\tif (!gatewayUrl) {\n\t\tcontext.ui.notify(\"A Senpiper Gateway URL is required.\", \"error\");\n\t\treturn false;\n\t}\n\tconst apiKey = await context.ui.input(\"Senpiper Gateway API key\", \"Paste your API key\", { secret: true });\n\tif (!apiKey?.trim()) {\n\t\tcontext.ui.notify(\n\t\t\tapiKey === undefined ? \"Senpiper Gateway login cancelled.\" : \"An API key is required.\",\n\t\t\t\"warning\",\n\t\t);\n\t\treturn false;\n\t}\n\n\tcontext.ui.setProgress(\"Connecting to Senpiper Gateway and synchronizing models…\");\n\ttry {\n\t\tconst baseUrl = normalizeSpGatewayBaseUrl(gatewayUrl);\n\t\tconst models = await fetchSpGatewayModels(baseUrl, apiKey.trim());\n\t\twriteSpGatewayState(baseUrl, models);\n\t\twriteSpGatewayLogin(apiKey.trim(), models[0]!.id);\n\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(baseUrl, models));\n\t\tawait context.modelRegistry.setRuntimeApiKey(SP_GATEWAY_PROVIDER_ID, apiKey.trim());\n\t\tconst firstModel = models[0]!;\n\t\tconst selected = await pi.setModel({\n\t\t\t...firstModel,\n\t\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\t\tbaseUrl,\n\t\t\tapi: \"openai-completions\",\n\t\t});\n\t\tcontext.ui.notify(\n\t\t\tselected\n\t\t\t\t? `Connected to Senpiper Gateway · ${models.length} models · selected ${firstModel.id}.`\n\t\t\t\t: `Connected to Senpiper Gateway · ${models.length} models available. Use /model to select one.`,\n\t\t\t\"info\",\n\t\t);\n\t} finally {\n\t\tcontext.ui.setProgress(undefined);\n\t}\n\n\treturn true;\n}\n\nexport function registerLoginCommand(pi: ExtensionAPI) {\n\tpi.registerCommand(\"login\", {\n\t\tdescription: \"Log in to Senpiper Gateway\",\n\t\thandler: async (args, context) => {\n\t\t\ttry {\n\t\t\t\tawait runSlashLogin(pi, args, context);\n\t\t\t} catch (error) {\n\t\t\t\tcontext.ui.setProgress(undefined);\n\t\t\t\tcontext.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
@@ -1,27 +1,25 @@
1
- import { createSpGatewayProviderConfig, fetchSpGatewayModels, getSpAgentDir, normalizeSpGatewayBaseUrl, readSpGatewayState, SP_GATEWAY_PROVIDER_ID, writeSpGatewayLogin, writeSpGatewayState, } from "./gateway.js";
2
- import { hasCompletedOnboarding } from "./onboarding.js";
3
- import { runInteractiveOnboarding } from "./onboarding-command.js";
1
+ import { createSpGatewayProviderConfig, fetchSpGatewayModels, normalizeSpGatewayBaseUrl, readSpGatewayState, SP_GATEWAY_PROVIDER_ID, writeSpGatewayLogin, writeSpGatewayState, } from "./gateway.js";
4
2
  export async function runSlashLogin(pi, args, context) {
5
3
  const existingState = readSpGatewayState();
6
4
  const argumentUrl = args.trim();
7
5
  const enteredUrl = argumentUrl
8
6
  ? argumentUrl
9
- : await context.ui.input("sp-gateway URL", existingState?.baseUrl ?? "https://gateway.example.com/v1");
7
+ : await context.ui.input("Senpiper Gateway URL", existingState?.baseUrl ?? "https://gateway.example.com/v1");
10
8
  if (enteredUrl === undefined) {
11
- context.ui.notify("sp-gateway login cancelled.", "warning");
9
+ context.ui.notify("Senpiper Gateway login cancelled.", "warning");
12
10
  return false;
13
11
  }
14
12
  const gatewayUrl = enteredUrl.trim() || existingState?.baseUrl;
15
13
  if (!gatewayUrl) {
16
- context.ui.notify("A sp-gateway URL is required.", "error");
14
+ context.ui.notify("A Senpiper Gateway URL is required.", "error");
17
15
  return false;
18
16
  }
19
- const apiKey = await context.ui.input("sp-gateway API key", "Paste your API key", { secret: true });
17
+ const apiKey = await context.ui.input("Senpiper Gateway API key", "Paste your API key", { secret: true });
20
18
  if (!apiKey?.trim()) {
21
- context.ui.notify(apiKey === undefined ? "sp-gateway login cancelled." : "An API key is required.", "warning");
19
+ context.ui.notify(apiKey === undefined ? "Senpiper Gateway login cancelled." : "An API key is required.", "warning");
22
20
  return false;
23
21
  }
24
- context.ui.setProgress("Connecting to sp-gateway and synchronizing models…");
22
+ context.ui.setProgress("Connecting to Senpiper Gateway and synchronizing models…");
25
23
  try {
26
24
  const baseUrl = normalizeSpGatewayBaseUrl(gatewayUrl);
27
25
  const models = await fetchSpGatewayModels(baseUrl, apiKey.trim());
@@ -37,25 +35,17 @@ export async function runSlashLogin(pi, args, context) {
37
35
  api: "openai-completions",
38
36
  });
39
37
  context.ui.notify(selected
40
- ? `Connected to sp-gateway · ${models.length} models · selected ${firstModel.id}.`
41
- : `Connected to sp-gateway · ${models.length} models available. Use /model to select one.`, "info");
38
+ ? `Connected to Senpiper Gateway · ${models.length} models · selected ${firstModel.id}.`
39
+ : `Connected to Senpiper Gateway · ${models.length} models available. Use /model to select one.`, "info");
42
40
  }
43
41
  finally {
44
42
  context.ui.setProgress(undefined);
45
43
  }
46
- if (!hasCompletedOnboarding(getSpAgentDir())) {
47
- try {
48
- await runInteractiveOnboarding(context);
49
- }
50
- catch (error) {
51
- context.ui.notify(`Onboarding deferred: ${error instanceof Error ? error.message : String(error)}. Run /onboarding later.`, "warning");
52
- }
53
- }
54
44
  return true;
55
45
  }
56
46
  export function registerLoginCommand(pi) {
57
47
  pi.registerCommand("login", {
58
- description: "Log in to SP Gateway",
48
+ description: "Log in to Senpiper Gateway",
59
49
  handler: async (args, context) => {
60
50
  try {
61
51
  await runSlashLogin(pi, args, context);
@@ -1 +1 @@
1
- {"version":3,"file":"login-command.js","sourceRoot":"","sources":["../src/login-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport {\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tgetSpAgentDir,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayState,\n\tSP_GATEWAY_PROVIDER_ID,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\nimport { hasCompletedOnboarding } from \"./onboarding.ts\";\nimport { runInteractiveOnboarding } from \"./onboarding-command.ts\";\n\nexport async function runSlashLogin(pi: ExtensionAPI, args: string, context: ExtensionCommandContext) {\n\tconst existingState = readSpGatewayState();\n\tconst argumentUrl = args.trim();\n\tconst enteredUrl = argumentUrl\n\t\t? argumentUrl\n\t\t: await context.ui.input(\"sp-gateway URL\", existingState?.baseUrl ?? \"https://gateway.example.com/v1\");\n\tif (enteredUrl === undefined) {\n\t\tcontext.ui.notify(\"sp-gateway login cancelled.\", \"warning\");\n\t\treturn false;\n\t}\n\tconst gatewayUrl = enteredUrl.trim() || existingState?.baseUrl;\n\tif (!gatewayUrl) {\n\t\tcontext.ui.notify(\"A sp-gateway URL is required.\", \"error\");\n\t\treturn false;\n\t}\n\tconst apiKey = await context.ui.input(\"sp-gateway API key\", \"Paste your API key\", { secret: true });\n\tif (!apiKey?.trim()) {\n\t\tcontext.ui.notify(apiKey === undefined ? \"sp-gateway login cancelled.\" : \"An API key is required.\", \"warning\");\n\t\treturn false;\n\t}\n\n\tcontext.ui.setProgress(\"Connecting to sp-gateway and synchronizing models…\");\n\ttry {\n\t\tconst baseUrl = normalizeSpGatewayBaseUrl(gatewayUrl);\n\t\tconst models = await fetchSpGatewayModels(baseUrl, apiKey.trim());\n\t\twriteSpGatewayState(baseUrl, models);\n\t\twriteSpGatewayLogin(apiKey.trim(), models[0]!.id);\n\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(baseUrl, models));\n\t\tawait context.modelRegistry.setRuntimeApiKey(SP_GATEWAY_PROVIDER_ID, apiKey.trim());\n\t\tconst firstModel = models[0]!;\n\t\tconst selected = await pi.setModel({\n\t\t\t...firstModel,\n\t\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\t\tbaseUrl,\n\t\t\tapi: \"openai-completions\",\n\t\t});\n\t\tcontext.ui.notify(\n\t\t\tselected\n\t\t\t\t? `Connected to sp-gateway · ${models.length} models · selected ${firstModel.id}.`\n\t\t\t\t: `Connected to sp-gateway · ${models.length} models available. Use /model to select one.`,\n\t\t\t\"info\",\n\t\t);\n\t} finally {\n\t\tcontext.ui.setProgress(undefined);\n\t}\n\n\tif (!hasCompletedOnboarding(getSpAgentDir())) {\n\t\ttry {\n\t\t\tawait runInteractiveOnboarding(context);\n\t\t} catch (error) {\n\t\t\tcontext.ui.notify(\n\t\t\t\t`Onboarding deferred: ${error instanceof Error ? error.message : String(error)}. Run /onboarding later.`,\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t}\n\t}\n\treturn true;\n}\n\nexport function registerLoginCommand(pi: ExtensionAPI) {\n\tpi.registerCommand(\"login\", {\n\t\tdescription: \"Log in to SP Gateway\",\n\t\thandler: async (args, context) => {\n\t\t\ttry {\n\t\t\t\tawait runSlashLogin(pi, args, context);\n\t\t\t} catch (error) {\n\t\t\t\tcontext.ui.setProgress(undefined);\n\t\t\t\tcontext.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"login-command.js","sourceRoot":"","sources":["../src/login-command.ts"],"names":[],"mappings":"AACA,OAAO,EACN,6BAA6B,EAC7B,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAgB,EAAE,IAAY,EAAE,OAAgC,EAAE;IACrG,MAAM,aAAa,GAAG,kBAAkB,EAAE,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,WAAW;QAC7B,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,MAAM,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,EAAE,aAAa,EAAE,OAAO,IAAI,gCAAgC,CAAC,CAAC;IAC9G,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;QAClE,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE,OAAO,CAAC;IAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,qCAAqC,EAAE,OAAO,CAAC,CAAC;QAClE,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,EAAE,oBAAoB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1G,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,CAAC,MAAM,CAChB,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,yBAAyB,EACtF,SAAS,CACT,CAAC;QACF,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,4DAA0D,CAAC,CAAC;IACnF,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,yBAAyB,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACrC,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5F,MAAM,OAAO,CAAC,aAAa,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACpF,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;YAClC,GAAG,UAAU;YACb,QAAQ,EAAE,sBAAsB;YAChC,OAAO;YACP,GAAG,EAAE,oBAAoB;SACzB,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,MAAM,CAChB,QAAQ;YACP,CAAC,CAAC,oCAAmC,MAAM,CAAC,MAAM,uBAAsB,UAAU,CAAC,EAAE,GAAG;YACxF,CAAC,CAAC,oCAAmC,MAAM,CAAC,MAAM,8CAA8C,EACjG,MAAM,CACN,CAAC;IACH,CAAC;YAAS,CAAC;QACV,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,IAAI,CAAC;AAAA,CACZ;AAED,MAAM,UAAU,oBAAoB,CAAC,EAAgB,EAAE;IACtD,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE;QAC3B,WAAW,EAAE,4BAA4B;QACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;YACjC,IAAI,CAAC;gBACJ,MAAM,aAAa,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACxC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBAClC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;YACpF,CAAC;QAAA,CACD;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"@senpiper/pi-coding-agent\";\nimport {\n\tcreateSpGatewayProviderConfig,\n\tfetchSpGatewayModels,\n\tnormalizeSpGatewayBaseUrl,\n\treadSpGatewayState,\n\tSP_GATEWAY_PROVIDER_ID,\n\twriteSpGatewayLogin,\n\twriteSpGatewayState,\n} from \"./gateway.ts\";\n\nexport async function runSlashLogin(pi: ExtensionAPI, args: string, context: ExtensionCommandContext) {\n\tconst existingState = readSpGatewayState();\n\tconst argumentUrl = args.trim();\n\tconst enteredUrl = argumentUrl\n\t\t? argumentUrl\n\t\t: await context.ui.input(\"Senpiper Gateway URL\", existingState?.baseUrl ?? \"https://gateway.example.com/v1\");\n\tif (enteredUrl === undefined) {\n\t\tcontext.ui.notify(\"Senpiper Gateway login cancelled.\", \"warning\");\n\t\treturn false;\n\t}\n\tconst gatewayUrl = enteredUrl.trim() || existingState?.baseUrl;\n\tif (!gatewayUrl) {\n\t\tcontext.ui.notify(\"A Senpiper Gateway URL is required.\", \"error\");\n\t\treturn false;\n\t}\n\tconst apiKey = await context.ui.input(\"Senpiper Gateway API key\", \"Paste your API key\", { secret: true });\n\tif (!apiKey?.trim()) {\n\t\tcontext.ui.notify(\n\t\t\tapiKey === undefined ? \"Senpiper Gateway login cancelled.\" : \"An API key is required.\",\n\t\t\t\"warning\",\n\t\t);\n\t\treturn false;\n\t}\n\n\tcontext.ui.setProgress(\"Connecting to Senpiper Gateway and synchronizing models…\");\n\ttry {\n\t\tconst baseUrl = normalizeSpGatewayBaseUrl(gatewayUrl);\n\t\tconst models = await fetchSpGatewayModels(baseUrl, apiKey.trim());\n\t\twriteSpGatewayState(baseUrl, models);\n\t\twriteSpGatewayLogin(apiKey.trim(), models[0]!.id);\n\t\tpi.registerProvider(SP_GATEWAY_PROVIDER_ID, createSpGatewayProviderConfig(baseUrl, models));\n\t\tawait context.modelRegistry.setRuntimeApiKey(SP_GATEWAY_PROVIDER_ID, apiKey.trim());\n\t\tconst firstModel = models[0]!;\n\t\tconst selected = await pi.setModel({\n\t\t\t...firstModel,\n\t\t\tprovider: SP_GATEWAY_PROVIDER_ID,\n\t\t\tbaseUrl,\n\t\t\tapi: \"openai-completions\",\n\t\t});\n\t\tcontext.ui.notify(\n\t\t\tselected\n\t\t\t\t? `Connected to Senpiper Gateway · ${models.length} models · selected ${firstModel.id}.`\n\t\t\t\t: `Connected to Senpiper Gateway · ${models.length} models available. Use /model to select one.`,\n\t\t\t\"info\",\n\t\t);\n\t} finally {\n\t\tcontext.ui.setProgress(undefined);\n\t}\n\n\treturn true;\n}\n\nexport function registerLoginCommand(pi: ExtensionAPI) {\n\tpi.registerCommand(\"login\", {\n\t\tdescription: \"Log in to Senpiper Gateway\",\n\t\thandler: async (args, context) => {\n\t\t\ttry {\n\t\t\t\tawait runSlashLogin(pi, args, context);\n\t\t\t} catch (error) {\n\t\t\t\tcontext.ui.setProgress(undefined);\n\t\t\t\tcontext.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
@@ -5,16 +5,42 @@ export interface SpWebSidecarState {
5
5
  executable: string;
6
6
  args: string[];
7
7
  startedAt: string;
8
+ /** Random identity inherited only by this launched process tree. */
9
+ launchToken?: string;
8
10
  }
9
11
  export interface SpWebLaunchResult {
10
12
  status: "disabled" | "reused" | "launched" | "pending" | "failed";
11
13
  pid?: number;
12
14
  error?: string;
13
15
  }
16
+ export interface SpWebStopResult {
17
+ status: "stopped" | "not-running" | "pending" | "failed";
18
+ pid?: number;
19
+ error?: string;
20
+ }
21
+ export interface SpWebProcessIdentity {
22
+ launchToken?: string;
23
+ /** Full argv of the live process, when the platform exposes argument boundaries. */
24
+ argv?: string[];
25
+ /** Joined command line, used when argv boundaries are unavailable. */
26
+ command?: string;
27
+ /** Live process environment, when readable. */
28
+ env?: NodeJS.ProcessEnv;
29
+ /** Wall-clock start time of the live process, when readable. */
30
+ startedAtMs?: number;
31
+ }
14
32
  export interface SpWebLauncherOptions {
15
33
  env?: NodeJS.ProcessEnv;
16
34
  spawnProcess?: (executable: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
17
35
  isProcessRunning?: (pid: number) => boolean;
36
+ /** Verifies that a live PID is still the process recorded at launch. */
37
+ readProcessIdentity?: (pid: number) => SpWebProcessIdentity | undefined;
38
+ /** Sends the graceful stop signal. Defaults to process.kill. */
39
+ signalProcess?: (pid: number, signal: NodeJS.Signals) => void;
40
+ /** Waits for a signaled PID to exit. Defaults to polling isProcessRunning. */
41
+ waitForProcessExit?: (pid: number, timeoutMs: number) => Promise<boolean>;
42
+ /** Grace period for /web off before reporting a timeout. Defaults to 8000 ms. */
43
+ stopTimeoutMs?: number;
18
44
  }
19
45
  export declare function resolveSpWebLaunch(env: NodeJS.ProcessEnv, runtime?: {
20
46
  moduleUrl: string;
@@ -25,5 +51,6 @@ export declare function resolveSpWebLaunch(env: NodeJS.ProcessEnv, runtime?: {
25
51
  args: string[];
26
52
  };
27
53
  export declare function ensureSpWebSidecar(discoveryDir: string, options?: SpWebLauncherOptions): SpWebLaunchResult;
54
+ export declare function stopSpWebSidecar(discoveryDir: string, options?: SpWebLauncherOptions): Promise<SpWebStopResult>;
28
55
  export declare function getSpWebSidecarStatePath(discoveryDir: string): string;
29
56
  //# sourceMappingURL=sp-web-launcher.d.ts.map