specrails-desktop 2.35.0 → 2.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/dist/assets/{ActivityFeedPage-LCBJ5WiD.js → ActivityFeedPage-tAQcWs1R.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-B-xQpyZr.js → AgentBrowserCapture-BX8BNae5.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-BI1Vcf3T.js → AgentModeAnalyticsPane-BVAqCL0K.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-BTRwCl9h.js → AgentModeCodePane-9XfqQc9c.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-VzeBJLqP.js → AgentModeJobsPane-BCjLsPhc.js} +1 -1
- package/client/dist/assets/{AgentsPage-CJj1K24O.js → AgentsPage-C8J_42sm.js} +1 -1
- package/client/dist/assets/{AnalyticsPage-CQpV5_fX.js → AnalyticsPage-BtQuyfJm.js} +1 -1
- package/client/dist/assets/{CodePage-9-tFh0jB.js → CodePage-BZ2MwdCu.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-BcZ0_O_C.js → DesktopAnalyticsPage-Bh_29V4g.js} +1 -1
- package/client/dist/assets/{DocsDialog-BPAzDICW.js → DocsDialog-C76VdBJC.js} +1 -1
- package/client/dist/assets/{DocsPage-Dqo4Hn6G.js → DocsPage-ziMlj6B6.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-D36fZWai.js → InteractiveJobComposer-BCZiSfzc.js} +1 -1
- package/client/dist/assets/{JobDetailModal-BxsktbkQ.js → JobDetailModal-NAJmuYIT.js} +1 -1
- package/client/dist/assets/{JobDetailPage-WWyCy6Sp.js → JobDetailPage-fE0ZycUX.js} +1 -1
- package/client/dist/assets/{JobsPage-CEbM7uxU.js → JobsPage-z5M_HVJG.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-CYsSN8io.js → LoopBuilderPage-j1FQS47c.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-BJhgX5wY.js → LoopPreviewModal-DhDJjdCe.js} +1 -1
- package/client/dist/assets/{LoopsPage-DB4OqMot.js → LoopsPage-Ll7zORZb.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-CcjBHMHd.js → MinimizedChatsContext-Bd3OqR_S.js} +1 -1
- package/client/dist/assets/{PluginsPage-CR8K4nM_.js → PluginsPage-DN4kGvJt.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-C45-qhF4.js → ProjectSettingsDialog-OgsgxjzF.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-Cz_QQeC3.js → ReviewPacketPage-DFog4sXn.js} +1 -1
- package/client/dist/assets/{TemplatePreviewModal-wFBd2vQP.js → TemplatePreviewModal-L2XxqiOD.js} +1 -1
- package/client/dist/assets/{TicketDetailModal-BvZoyDAL.js → TicketDetailModal-CsF-AWZX.js} +1 -1
- package/client/dist/assets/{Trans-DXZ-BLXb.js → Trans-Bsz9_gyq.js} +1 -1
- package/client/dist/assets/{formatDistanceToNow-C0ImhVKp.js → formatDistanceToNow-DQCvMgUc.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-owhDdTXs.js → getTimezoneOffsetInMilliseconds-C16cxSe1.js} +1 -1
- package/client/dist/assets/{i18n-DwgvwTnx.js → i18n-hnX2DPmo.js} +2 -2
- package/client/dist/assets/{index-DhjjFyU5.js → index-DIhMEAVw.js} +14 -14
- package/client/dist/assets/index-DwygcU7s.css +2 -0
- package/client/dist/assets/{jira-api-CcZMcEN5.js → jira-api-B1-MUehg.js} +1 -1
- package/client/dist/assets/{mcp-DsTwmjST.js → mcp-B8X8wBLu.js} +1 -1
- package/client/dist/assets/{mcp-SMkn8boG.js → mcp-C2AojZZN.js} +1 -1
- package/client/dist/assets/mcp-D8BT78_L.js +1 -0
- package/client/dist/assets/{mcp-D4ZjtIx3.js → mcp-Df5RWBNk.js} +1 -1
- package/client/dist/assets/{mcp-DIfBUv2D.js → mcp-Dj7BgMQW.js} +1 -1
- package/client/dist/assets/{mcp-D2pc5GGx.js → mcp-Q7iT7rcz.js} +1 -1
- package/client/dist/assets/{mcp-fSfiVYAc.js → mcp-YlvNvJbW.js} +1 -1
- package/client/dist/assets/{mcp-Czd_iyp0.js → mcp-mKFpTSRb.js} +1 -1
- package/client/dist/assets/{spending-BQX3P7Cq.js → spending-EC9xqio-.js} +1 -1
- package/client/dist/assets/{useDesktop-BzX769yH.js → useDesktop-BQVt8lFd.js} +1 -1
- package/client/dist/index.html +12 -12
- package/docs/mcp.md +16 -0
- package/package.json +1 -1
- package/server/dist/agent-chat-manager.js +2 -0
- package/server/dist/agent-mcp-config.js +94 -2
- package/server/dist/agent-operator-prompt.js +4 -0
- package/server/dist/desktop-router.js +22 -0
- package/server/dist/external-mcp.js +370 -0
- package/client/dist/assets/index-xBFsOEiJ.css +0 -2
- package/client/dist/assets/mcp-uDkXYu4L.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./createLucideIcon-Bjbbp_KS.js";import{a as t}from"./useDesktop-
|
|
1
|
+
import{t as e}from"./createLucideIcon-Bjbbp_KS.js";import{a as t}from"./useDesktop-BQVt8lFd.js";var n=e(`wrench`,[[`path`,{d:`M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z`,key:`1ngwbx`}]]);async function r(e){let t=await e.text(),n=t?JSON.parse(t):{};if(!e.ok)throw Error(n.error||`Request failed (${e.status})`);return n}function i(e){return e??t()}var a=e=>({method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}),o={getConnection(e){return fetch(`${i(e)}/jira/connection`).then(e=>r(e))},test(e,t){return fetch(`${i(t)}/jira/test`,a(e)).then(e=>r(e))},discoverProjects(e,t){return fetch(`${i(t)}/jira/discover-projects`,a(e)).then(e=>r(e))},discoverStatuses(e,t){return fetch(`${i(t)}/jira/discover-statuses`,a(e)).then(e=>r(e))},connect(e,t){return fetch(`${i(t)}/jira/connect`,a(e)).then(e=>r(e))},setEnabled(e,t){return fetch(`${i(t)}/jira/connection`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:e})}).then(e=>r(e))},patchConnection(e,t){return fetch(`${i(t)}/jira/connection`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>r(e))},listStatuses(e){return fetch(`${i(e)}/jira/statuses`).then(e=>r(e))},moveSpecToStatus(e,t,n){return fetch(`${i(n)}/jira/specs/${e}/move-to-status`,a({status:t})).then(e=>r(e))},discardSpec(e,t,n){return fetch(`${i(n)}/jira/specs/${e}/discard`,a({comment:t})).then(e=>r(e))},getSpecDetails(e,t){return fetch(`${i(t)}/jira/specs/${e}/details`).then(e=>r(e))},disconnect(e){return fetch(`${i(e)}/jira/connection`,{method:`DELETE`}).then(e=>r(e))},syncNow(e){return fetch(`${i(e)}/jira/sync`,{method:`POST`}).then(e=>r(e))},resume(e){return fetch(`${i(e)}/jira/resume`,{method:`POST`}).then(e=>r(e))},listOutbox(e,t){let n=e?`?state=${e}`:``;return fetch(`${i(t)}/jira/outbox${n}`).then(e=>r(e))},retryOutbox(e,t){return fetch(`${i(t)}/jira/outbox/${e}/retry`,{method:`POST`}).then(e=>r(e))}};export{n,o as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`MCP-Server`,t={what:`Ein MCP-Server (Model Context Protocol) ermöglicht es externen KI-Tools – wie Claude Desktop, Cursor oder jedem MCP-Client – direkt mit Specrails zu kommunizieren. Sie können Ihre Projekte durchsuchen, Spezifikationen lesen und – wenn Sie es erlauben – Arbeiten starten, alles über eine einzige sichere lokale Verbindung.`,how:`Aktivieren Sie ihn unten und kopieren Sie dann die Client-Konfiguration in Ihr KI-Tool. Specrails lauscht nur auf Ihrem eigenen Rechner – nichts wird ins Internet veröffentlicht.`,grants:`Standardmäßig erhalten Tools nur Lesezugriff. Verwenden Sie die Berechtigungsstufen, um mehr zu gewähren – eine Fähigkeit nach der anderen.`},n={on:`MCP-Server an`,off:`MCP-Server aus`,running_one:`Läuft · {{count}} Tool`,running_other:`Läuft · {{count}} Tools`,stopped:`Nicht aktiv`,activeSessions_one:`{{count}} aktive Sitzung`,activeSessions_other:`{{count}} aktive Sitzungen`,turnOn:`Einschalten`,turnOff:`Ausschalten`,enableFailed:`MCP-Server konnte nicht aktiviert werden: {{message}}`,disableFailed:`MCP-Server konnte nicht deaktiviert werden: {{message}}`},r={heading:`Berechtigungsstufen`,description:`Jede Stufe, die ein Client verwenden darf. Lesen ist immer aktiv; der Rest ist aus, bis Sie ihn gewähren.`,read:`Lesen`,readHelp:`Projekte, Spezifikationen und Analysen durchsuchen. Immer erlaubt.`,write:`Schreiben`,writeHelp:`Spezifikationen und Tickets erstellen und bearbeiten.`,aiSpawn:`KI starten`,aiSpawnHelp:`KI-Rails und Jobs starten, die die CLI ausführen.`,destructive:`Destruktiv`,destructiveHelp:`Spezifikationen, Tickets und andere Projektdaten löschen.`,updateFailed:`Berechtigungen konnten nicht aktualisiert werden: {{message}}`},i={heading:`Client-Konfiguration`,description:`Fügen Sie dies in Ihren MCP-Client ein. Sie enthält kein Geheimnis – das Token wird separat kopiert.`,copyConfig:`Konfiguration kopieren`,configCopied:`Konfiguration kopiert`,copyFailed:`Kopieren fehlgeschlagen`},a={heading:`Zugriffstoken`,description:`Ihr Client authentifiziert sich mit diesem Token. Behandeln Sie es wie ein Passwort.`,hint:`Token endet auf {{hint}}`,copyToken:`Token kopieren`,tokenCopied:`Token kopiert`,regenerate:`Neu generieren`,regenerateConfirm:`Zugriffstoken neu generieren? Jeder Client, der das alte Token verwendet, funktioniert nicht mehr, bis Sie seine Konfiguration aktualisieren.`,regenerated:`Zugriffstoken neu generiert`,regenerateFailed:`Token konnte nicht neu generiert werden: {{message}}`},o={open:`Öffnen`,exit:`Beenden`,statusOn:`MCP-Server: an`,statusOff:`MCP-Server: aus`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`MCP-Server`,t={what:`Ein MCP-Server (Model Context Protocol) ermöglicht es externen KI-Tools – wie Claude Desktop, Cursor oder jedem MCP-Client – direkt mit Specrails zu kommunizieren. Sie können Ihre Projekte durchsuchen, Spezifikationen lesen und – wenn Sie es erlauben – Arbeiten starten, alles über eine einzige sichere lokale Verbindung.`,how:`Aktivieren Sie ihn unten und kopieren Sie dann die Client-Konfiguration in Ihr KI-Tool. Specrails lauscht nur auf Ihrem eigenen Rechner – nichts wird ins Internet veröffentlicht.`,grants:`Standardmäßig erhalten Tools nur Lesezugriff. Verwenden Sie die Berechtigungsstufen, um mehr zu gewähren – eine Fähigkeit nach der anderen.`},n={on:`MCP-Server an`,off:`MCP-Server aus`,running_one:`Läuft · {{count}} Tool`,running_other:`Läuft · {{count}} Tools`,stopped:`Nicht aktiv`,activeSessions_one:`{{count}} aktive Sitzung`,activeSessions_other:`{{count}} aktive Sitzungen`,turnOn:`Einschalten`,turnOff:`Ausschalten`,enableFailed:`MCP-Server konnte nicht aktiviert werden: {{message}}`,disableFailed:`MCP-Server konnte nicht deaktiviert werden: {{message}}`},r={heading:`Berechtigungsstufen`,description:`Jede Stufe, die ein Client verwenden darf. Lesen ist immer aktiv; der Rest ist aus, bis Sie ihn gewähren.`,read:`Lesen`,readHelp:`Projekte, Spezifikationen und Analysen durchsuchen. Immer erlaubt.`,write:`Schreiben`,writeHelp:`Spezifikationen und Tickets erstellen und bearbeiten.`,aiSpawn:`KI starten`,aiSpawnHelp:`KI-Rails und Jobs starten, die die CLI ausführen.`,destructive:`Destruktiv`,destructiveHelp:`Spezifikationen, Tickets und andere Projektdaten löschen.`,updateFailed:`Berechtigungen konnten nicht aktualisiert werden: {{message}}`},i={heading:`Client-Konfiguration`,description:`Fügen Sie dies in Ihren MCP-Client ein. Sie enthält kein Geheimnis – das Token wird separat kopiert.`,copyConfig:`Konfiguration kopieren`,configCopied:`Konfiguration kopiert`,copyFailed:`Kopieren fehlgeschlagen`},a={heading:`Zugriffstoken`,description:`Ihr Client authentifiziert sich mit diesem Token. Behandeln Sie es wie ein Passwort.`,hint:`Token endet auf {{hint}}`,copyToken:`Token kopieren`,tokenCopied:`Token kopiert`,regenerate:`Neu generieren`,regenerateConfirm:`Zugriffstoken neu generieren? Jeder Client, der das alte Token verwendet, funktioniert nicht mehr, bis Sie seine Konfiguration aktualisieren.`,regenerated:`Zugriffstoken neu generiert`,regenerateFailed:`Token konnte nicht neu generiert werden: {{message}}`},o={open:`Öffnen`,exit:`Beenden`,statusOn:`MCP-Server: an`,statusOff:`MCP-Server: aus`},s={heading:`Externe MCP-Server`,description:`Stelle deine eigenen MCP-Server dem Missions-Agenten zur Verfügung. Entdeckte Einträge stammen aus den Konfigurationen deiner KI-Provider und werden live aufgelöst; hake einen Provider an, um einen Server für dessen Missionen zu aktivieren.`,warning:`Missions-Turns laufen ohne Tool-Freigabe-Abfragen, und externe Tools liegen außerhalb der Specrails-Berechtigungsstufen. Aktiviere nur Server, denen du vertraust.`,sourceDiscovered:`aus {{provider}}`,sourceCustom:`benutzerdefiniert`,orphan:`nicht in der Quellkonfiguration gefunden`,codexNative:`codex-nativ — immer aktiv`,empty:`Keine MCP-Server gefunden. Füge einen benutzerdefinierten Server hinzu oder registriere einen mit deinem KI-CLI.`,addCustom:`Benutzerdefiniert hinzufügen`,remove:`Server entfernen`,edit:`Server bearbeiten`,updateFailed:`Externe MCP-Einstellungen konnten nicht gespeichert werden`,form:{name:`Name (z. B. jira-tools)`,command:`Befehl (z. B. npx)`,args:`Argumente (durch Leerzeichen getrennt)`,env:`Umgebung (KEY=VALUE pro Zeile)`,cancel:`Abbrechen`,save:`Speichern`,nameLabel:`Name`,commandLabel:`Befehl`,argsLabel:`Argumente`,envLabel:`Umgebungsvariablen`,enableFor:`Aktivieren für`,addVar:`Variable hinzufügen`,envKey:`SCHLÜSSEL`,envValue:`Wert`,nameInvalid:`Nur Buchstaben, Ziffern, Punkte und Bindestriche — und 'specrails' ist reserviert`,nameTaken:`Ein benutzerdefinierter Server mit diesem Namen existiert bereits`},errors:{reserved_name:`Dieser Servername ist reserviert`,duplicate_server_name:`Zwei aktive Server teilen denselben Namen für einen Provider`,invalid_transport:`Ein benutzerdefinierter Server benötigt einen Befehl`,unknown_provider:`Unbekannter Provider in der Aktivierungsmatrix`,invalid_entry:`Fehlerhafter Servereintrag`,invalid_body:`Fehlerhafte Anfrage`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`Servidor MCP`,t={what:`Um servidor MCP (Model Context Protocol) permite que ferramentas de IA externas — como o Claude Desktop, o Cursor ou qualquer cliente MCP — comuniquem diretamente com o Specrails. Elas podem explorar os seus projetos, ler especificações e, se você permitir, iniciar trabalhos, tudo através de uma única ligação local segura.`,how:`Ative-o abaixo e copie a configuração do cliente para a sua ferramenta de IA. O Specrails só escuta na sua própria máquina: nada fica exposto à internet.`,grants:`Por predefinição, as ferramentas têm acesso só de leitura. Use os níveis de permissão para conceder mais, uma capacidade de cada vez.`},n={on:`Servidor MCP ativado`,off:`Servidor MCP desativado`,running_one:`Em execução · {{count}} ferramenta`,running_other:`Em execução · {{count}} ferramentas`,stopped:`Parado`,activeSessions_one:`{{count}} sessão ativa`,activeSessions_other:`{{count}} sessões ativas`,turnOn:`Ativar`,turnOff:`Desativar`,enableFailed:`Não foi possível ativar o servidor MCP: {{message}}`,disableFailed:`Não foi possível desativar o servidor MCP: {{message}}`},r={heading:`Níveis de permissão`,description:`Cada nível que um cliente pode usar. A leitura está sempre ativa; o resto está desativado até você conceder.`,read:`Leitura`,readHelp:`Explorar projetos, especificações e análises. Sempre permitido.`,write:`Escrita`,writeHelp:`Criar e editar especificações e tickets.`,aiSpawn:`Iniciar IA`,aiSpawnHelp:`Iniciar rails e trabalhos de IA que executam a CLI.`,destructive:`Destrutivo`,destructiveHelp:`Eliminar especificações, tickets e outros dados do projeto.`,updateFailed:`Não foi possível atualizar as permissões: {{message}}`},i={heading:`Configuração do cliente`,description:`Cole isto no seu cliente MCP. Não contém nenhum segredo: o token é copiado separadamente.`,copyConfig:`Copiar configuração`,configCopied:`Configuração copiada`,copyFailed:`Falha ao copiar`},a={heading:`Token de acesso`,description:`O seu cliente autentica-se com este token. Trate-o como uma palavra-passe.`,hint:`Token terminado em {{hint}}`,copyToken:`Copiar token`,tokenCopied:`Token copiado`,regenerate:`Regenerar`,regenerateConfirm:`Regenerar o token de acesso? Qualquer cliente que use o token antigo deixará de funcionar até você atualizar a sua configuração.`,regenerated:`Token de acesso regenerado`,regenerateFailed:`Não foi possível regenerar o token: {{message}}`},o={open:`Abrir`,exit:`Sair`,statusOn:`Servidor MCP: ativado`,statusOff:`Servidor MCP: desativado`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`Servidor MCP`,t={what:`Um servidor MCP (Model Context Protocol) permite que ferramentas de IA externas — como o Claude Desktop, o Cursor ou qualquer cliente MCP — comuniquem diretamente com o Specrails. Elas podem explorar os seus projetos, ler especificações e, se você permitir, iniciar trabalhos, tudo através de uma única ligação local segura.`,how:`Ative-o abaixo e copie a configuração do cliente para a sua ferramenta de IA. O Specrails só escuta na sua própria máquina: nada fica exposto à internet.`,grants:`Por predefinição, as ferramentas têm acesso só de leitura. Use os níveis de permissão para conceder mais, uma capacidade de cada vez.`},n={on:`Servidor MCP ativado`,off:`Servidor MCP desativado`,running_one:`Em execução · {{count}} ferramenta`,running_other:`Em execução · {{count}} ferramentas`,stopped:`Parado`,activeSessions_one:`{{count}} sessão ativa`,activeSessions_other:`{{count}} sessões ativas`,turnOn:`Ativar`,turnOff:`Desativar`,enableFailed:`Não foi possível ativar o servidor MCP: {{message}}`,disableFailed:`Não foi possível desativar o servidor MCP: {{message}}`},r={heading:`Níveis de permissão`,description:`Cada nível que um cliente pode usar. A leitura está sempre ativa; o resto está desativado até você conceder.`,read:`Leitura`,readHelp:`Explorar projetos, especificações e análises. Sempre permitido.`,write:`Escrita`,writeHelp:`Criar e editar especificações e tickets.`,aiSpawn:`Iniciar IA`,aiSpawnHelp:`Iniciar rails e trabalhos de IA que executam a CLI.`,destructive:`Destrutivo`,destructiveHelp:`Eliminar especificações, tickets e outros dados do projeto.`,updateFailed:`Não foi possível atualizar as permissões: {{message}}`},i={heading:`Configuração do cliente`,description:`Cole isto no seu cliente MCP. Não contém nenhum segredo: o token é copiado separadamente.`,copyConfig:`Copiar configuração`,configCopied:`Configuração copiada`,copyFailed:`Falha ao copiar`},a={heading:`Token de acesso`,description:`O seu cliente autentica-se com este token. Trate-o como uma palavra-passe.`,hint:`Token terminado em {{hint}}`,copyToken:`Copiar token`,tokenCopied:`Token copiado`,regenerate:`Regenerar`,regenerateConfirm:`Regenerar o token de acesso? Qualquer cliente que use o token antigo deixará de funcionar até você atualizar a sua configuração.`,regenerated:`Token de acesso regenerado`,regenerateFailed:`Não foi possível regenerar o token: {{message}}`},o={open:`Abrir`,exit:`Sair`,statusOn:`Servidor MCP: ativado`,statusOff:`Servidor MCP: desativado`},s={heading:`Servidores MCP externos`,description:`Disponibilize seus próprios servidores MCP para o agente de missões. As entradas descobertas vêm das configurações dos seus provedores de IA e são resolvidas ao vivo; marque um provedor para ativar um servidor nas suas missões.`,warning:`Os turnos de missão executam sem confirmação de ferramentas, e ferramentas externas ficam fora dos níveis de permissão do Specrails. Ative apenas servidores confiáveis.`,sourceDiscovered:`de {{provider}}`,sourceCustom:`personalizado`,orphan:`não encontrado na configuração de origem`,codexNative:`nativo do codex — sempre ativo`,empty:`Nenhum servidor MCP encontrado. Adicione um servidor personalizado ou registre um com seu CLI de IA.`,addCustom:`Adicionar personalizado`,remove:`Remover servidor`,edit:`Editar servidor`,updateFailed:`Não foi possível salvar as configurações de MCP externos`,form:{name:`Nome (p. ex. jira-tools)`,command:`Comando (p. ex. npx)`,args:`Argumentos (separados por espaços)`,env:`Ambiente (KEY=VALUE por linha)`,cancel:`Cancelar`,save:`Salvar`,nameLabel:`Nome`,commandLabel:`Comando`,argsLabel:`Argumentos`,envLabel:`Variáveis de ambiente`,enableFor:`Ativar para`,addVar:`Adicionar variável`,envKey:`CHAVE`,envValue:`valor`,nameInvalid:`Apenas letras, dígitos, pontos e hífens — e 'specrails' é reservado`,nameTaken:`Já existe um servidor personalizado com esse nome`},errors:{reserved_name:`Esse nome de servidor é reservado`,duplicate_server_name:`Dois servidores ativos compartilham o mesmo nome para um provedor`,invalid_transport:`Um servidor personalizado precisa de um comando`,unknown_provider:`Provedor desconhecido na matriz de ativação`,invalid_entry:`Entrada de servidor malformada`,invalid_body:`Requisição malformada`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-CNC7AqOf.js";var t=e({config:()=>o,default:()=>u,enable:()=>i,explainer:()=>r,external:()=>l,heading:()=>n,tiers:()=>a,token:()=>s,tray:()=>c}),n=`MCP server`,r={what:`An MCP (Model Context Protocol) server lets external AI tools — like Claude Desktop, Cursor, or any MCP client — talk to Specrails directly. They can browse your projects, read specs, and (if you allow it) launch work, all through one secure local connection.`,how:`Turn it on below, then copy the client config into your AI tool. Specrails only listens on your own machine — nothing is exposed to the internet.`,grants:`By default tools get read-only access. Use the permission tiers to grant more, one capability at a time.`},i={on:`MCP server on`,off:`MCP server off`,running_one:`Running · {{count}} tool`,running_other:`Running · {{count}} tools`,stopped:`Not running`,activeSessions_one:`{{count}} active session`,activeSessions_other:`{{count}} active sessions`,turnOn:`Turn on`,turnOff:`Turn off`,enableFailed:`Could not enable the MCP server: {{message}}`,disableFailed:`Could not disable the MCP server: {{message}}`},a={heading:`Permission tiers`,description:`Each tier a client may use. Read is always on; the rest are off until you grant them.`,read:`Read`,readHelp:`Browse projects, specs, and analytics. Always allowed.`,write:`Write`,writeHelp:`Create and edit specs and tickets.`,aiSpawn:`AI spawn`,aiSpawnHelp:`Launch AI rails and jobs that run the CLI.`,destructive:`Destructive`,destructiveHelp:`Delete specs, tickets, and other project data.`,updateFailed:`Could not update permissions: {{message}}`},o={heading:`Client config`,description:`Paste this into your MCP client. It contains no secret — the token is copied separately.`,copyConfig:`Copy config`,configCopied:`Config copied`,copyFailed:`Copy failed`},s={heading:`Access token`,description:`Your client authenticates with this token. Treat it like a password.`,hint:`Token ending in {{hint}}`,copyToken:`Copy token`,tokenCopied:`Token copied`,regenerate:`Regenerate`,regenerateConfirm:`Regenerate the access token? Any client using the old token will stop working until you update its config.`,regenerated:`Access token regenerated`,regenerateFailed:`Could not regenerate the token: {{message}}`},c={open:`Open`,exit:`Exit`,statusOn:`MCP server: on`,statusOff:`MCP server: off`},l={heading:`External MCP servers`,description:`Make your own MCP servers available to the mission agent. Discovered entries come from your AI provider configs and resolve live; tick a provider to enable a server for its missions.`,warning:`Mission turns run without tool-approval prompts, and external tools are outside the Specrails permission tiers. Enable only servers you trust.`,sourceDiscovered:`from {{provider}}`,sourceCustom:`custom`,orphan:`not found in source config`,codexNative:`codex native — always on`,empty:`No MCP servers found. Add a custom server or register one with your AI CLI.`,addCustom:`Add custom`,remove:`Remove server`,edit:`Edit server`,updateFailed:`Could not save external MCP settings`,form:{name:`Name (e.g. jira-tools)`,command:`Command (e.g. npx)`,args:`Arguments (space-separated)`,env:`Environment (KEY=VALUE per line)`,cancel:`Cancel`,save:`Save`,nameLabel:`Name`,commandLabel:`Command`,argsLabel:`Arguments`,envLabel:`Environment variables`,enableFor:`Enable for`,addVar:`Add variable`,envKey:`KEY`,envValue:`value`,nameInvalid:`Letters, digits, dots and dashes only — and 'specrails' is reserved`,nameTaken:`A custom server with this name already exists`},errors:{reserved_name:`That server name is reserved`,duplicate_server_name:`Two enabled servers share the same name for one provider`,invalid_transport:`A custom server needs a command`,unknown_provider:`Unknown provider in the activation matrix`,invalid_entry:`Malformed server entry`,invalid_body:`Malformed request`}},u={heading:n,explainer:r,enable:i,tiers:a,config:o,token:s,tray:c,external:l};export{t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`MCP サーバー`,t={what:`MCP(Model Context Protocol)サーバーを使うと、Claude Desktop や Cursor などの外部 AI ツール、あるいは任意の MCP クライアントが Specrails と直接やり取りできます。プロジェクトの閲覧、仕様の読み取り、そして許可すれば作業の起動まで、すべて安全なローカル接続を通じて行えます。`,how:`下で有効にしてから、クライアント設定を AI ツールにコピーしてください。Specrails はあなたのマシン上でのみ待ち受けます。インターネットには何も公開されません。`,grants:`デフォルトではツールは読み取り専用アクセスです。権限ティアを使って、1 つずつ機能を付与してください。`},n={on:`MCP サーバー オン`,off:`MCP サーバー オフ`,running_one:`実行中 · {{count}} 個のツール`,running_other:`実行中 · {{count}} 個のツール`,stopped:`停止中`,activeSessions_one:`{{count}} 件のアクティブセッション`,activeSessions_other:`{{count}} 件のアクティブセッション`,turnOn:`オンにする`,turnOff:`オフにする`,enableFailed:`MCP サーバーを有効にできませんでした: {{message}}`,disableFailed:`MCP サーバーを無効にできませんでした: {{message}}`},r={heading:`権限ティア`,description:`クライアントが使用できる各ティア。読み取りは常にオンで、それ以外は付与するまでオフです。`,read:`読み取り`,readHelp:`プロジェクト、仕様、分析を閲覧します。常に許可されます。`,write:`書き込み`,writeHelp:`仕様とチケットを作成・編集します。`,aiSpawn:`AI 起動`,aiSpawnHelp:`CLI を実行する AI レールとジョブを起動します。`,destructive:`破壊的操作`,destructiveHelp:`仕様、チケット、その他のプロジェクトデータを削除します。`,updateFailed:`権限を更新できませんでした: {{message}}`},i={heading:`クライアント設定`,description:`これを MCP クライアントに貼り付けてください。シークレットは含まれません。トークンは別途コピーします。`,copyConfig:`設定をコピー`,configCopied:`設定をコピーしました`,copyFailed:`コピーに失敗しました`},a={heading:`アクセストークン`,description:`クライアントはこのトークンで認証します。パスワードと同様に扱ってください。`,hint:`{{hint}} で終わるトークン`,copyToken:`トークンをコピー`,tokenCopied:`トークンをコピーしました`,regenerate:`再生成`,regenerateConfirm:`アクセストークンを再生成しますか?古いトークンを使用しているクライアントは、設定を更新するまで動作しなくなります。`,regenerated:`アクセストークンを再生成しました`,regenerateFailed:`トークンを再生成できませんでした: {{message}}`},o={open:`開く`,exit:`終了`,statusOn:`MCP サーバー: オン`,statusOff:`MCP サーバー: オフ`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`MCP サーバー`,t={what:`MCP(Model Context Protocol)サーバーを使うと、Claude Desktop や Cursor などの外部 AI ツール、あるいは任意の MCP クライアントが Specrails と直接やり取りできます。プロジェクトの閲覧、仕様の読み取り、そして許可すれば作業の起動まで、すべて安全なローカル接続を通じて行えます。`,how:`下で有効にしてから、クライアント設定を AI ツールにコピーしてください。Specrails はあなたのマシン上でのみ待ち受けます。インターネットには何も公開されません。`,grants:`デフォルトではツールは読み取り専用アクセスです。権限ティアを使って、1 つずつ機能を付与してください。`},n={on:`MCP サーバー オン`,off:`MCP サーバー オフ`,running_one:`実行中 · {{count}} 個のツール`,running_other:`実行中 · {{count}} 個のツール`,stopped:`停止中`,activeSessions_one:`{{count}} 件のアクティブセッション`,activeSessions_other:`{{count}} 件のアクティブセッション`,turnOn:`オンにする`,turnOff:`オフにする`,enableFailed:`MCP サーバーを有効にできませんでした: {{message}}`,disableFailed:`MCP サーバーを無効にできませんでした: {{message}}`},r={heading:`権限ティア`,description:`クライアントが使用できる各ティア。読み取りは常にオンで、それ以外は付与するまでオフです。`,read:`読み取り`,readHelp:`プロジェクト、仕様、分析を閲覧します。常に許可されます。`,write:`書き込み`,writeHelp:`仕様とチケットを作成・編集します。`,aiSpawn:`AI 起動`,aiSpawnHelp:`CLI を実行する AI レールとジョブを起動します。`,destructive:`破壊的操作`,destructiveHelp:`仕様、チケット、その他のプロジェクトデータを削除します。`,updateFailed:`権限を更新できませんでした: {{message}}`},i={heading:`クライアント設定`,description:`これを MCP クライアントに貼り付けてください。シークレットは含まれません。トークンは別途コピーします。`,copyConfig:`設定をコピー`,configCopied:`設定をコピーしました`,copyFailed:`コピーに失敗しました`},a={heading:`アクセストークン`,description:`クライアントはこのトークンで認証します。パスワードと同様に扱ってください。`,hint:`{{hint}} で終わるトークン`,copyToken:`トークンをコピー`,tokenCopied:`トークンをコピーしました`,regenerate:`再生成`,regenerateConfirm:`アクセストークンを再生成しますか?古いトークンを使用しているクライアントは、設定を更新するまで動作しなくなります。`,regenerated:`アクセストークンを再生成しました`,regenerateFailed:`トークンを再生成できませんでした: {{message}}`},o={open:`開く`,exit:`終了`,statusOn:`MCP サーバー: オン`,statusOff:`MCP サーバー: オフ`},s={heading:`外部 MCP サーバー`,description:`自分の MCP サーバーをミッションエージェントで使えるようにします。検出されたエントリは AI プロバイダーの設定から取得され、リアルタイムに解決されます。プロバイダーにチェックを入れると、そのミッションでサーバーが有効になります。`,warning:`ミッションのターンはツール承認プロンプトなしで実行され、外部ツールは Specrails の権限ティアの対象外です。信頼できるサーバーのみ有効にしてください。`,sourceDiscovered:`{{provider}} から`,sourceCustom:`カスタム`,orphan:`ソース設定に見つかりません`,codexNative:`codex ネイティブ — 常時有効`,empty:`MCP サーバーが見つかりません。カスタムサーバーを追加するか、AI CLI で登録してください。`,addCustom:`カスタムを追加`,remove:`サーバーを削除`,edit:`サーバーを編集`,updateFailed:`外部 MCP 設定を保存できませんでした`,form:{name:`名前(例: jira-tools)`,command:`コマンド(例: npx)`,args:`引数(スペース区切り)`,env:`環境変数(1 行につき KEY=VALUE)`,cancel:`キャンセル`,save:`保存`,nameLabel:`名前`,commandLabel:`コマンド`,argsLabel:`引数`,envLabel:`環境変数`,enableFor:`有効化対象`,addVar:`変数を追加`,envKey:`キー`,envValue:`値`,nameInvalid:`使用できるのは英数字・ドット・ハイフンのみ — 'specrails' は予約済みです`,nameTaken:`同じ名前のカスタムサーバーが既に存在します`},errors:{reserved_name:`そのサーバー名は予約されています`,duplicate_server_name:`同じプロバイダーで有効な 2 つのサーバーが同名です`,invalid_transport:`カスタムサーバーにはコマンドが必要です`,unknown_provider:`アクティベーションマトリクスに不明なプロバイダーがあります`,invalid_entry:`サーバーエントリの形式が不正です`,invalid_body:`リクエストの形式が不正です`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`MCP 服务器`,t={what:`MCP(模型上下文协议)服务器让外部 AI 工具——例如 Claude Desktop、Cursor 或任何 MCP 客户端——直接与 Specrails 通信。它们可以浏览你的项目、读取规格,并在你允许的情况下启动任务,全部通过一个安全的本地连接完成。`,how:`在下方开启它,然后将客户端配置复制到你的 AI 工具中。Specrails 仅在你自己的机器上监听——不会向互联网暴露任何内容。`,grants:`默认情况下工具只有只读访问权限。使用权限层级逐项授予更多能力。`},n={on:`MCP 服务器已开启`,off:`MCP 服务器已关闭`,running_one:`运行中 · {{count}} 个工具`,running_other:`运行中 · {{count}} 个工具`,stopped:`未运行`,activeSessions_one:`{{count}} 个活动会话`,activeSessions_other:`{{count}} 个活动会话`,turnOn:`开启`,turnOff:`关闭`,enableFailed:`无法开启 MCP 服务器:{{message}}`,disableFailed:`无法关闭 MCP 服务器:{{message}}`},r={heading:`权限层级`,description:`客户端可使用的每个层级。读取始终开启;其余在你授予前均为关闭。`,read:`读取`,readHelp:`浏览项目、规格和分析。始终允许。`,write:`写入`,writeHelp:`创建和编辑规格与工单。`,aiSpawn:`启动 AI`,aiSpawnHelp:`启动运行 CLI 的 AI rails 和任务。`,destructive:`破坏性操作`,destructiveHelp:`删除规格、工单和其他项目数据。`,updateFailed:`无法更新权限:{{message}}`},i={heading:`客户端配置`,description:`将此内容粘贴到你的 MCP 客户端。它不包含任何密钥——令牌需单独复制。`,copyConfig:`复制配置`,configCopied:`配置已复制`,copyFailed:`复制失败`},a={heading:`访问令牌`,description:`你的客户端使用此令牌进行身份验证。请将其视为密码。`,hint:`以 {{hint}} 结尾的令牌`,copyToken:`复制令牌`,tokenCopied:`令牌已复制`,regenerate:`重新生成`,regenerateConfirm:`重新生成访问令牌?任何使用旧令牌的客户端都将停止工作,直到你更新其配置。`,regenerated:`访问令牌已重新生成`,regenerateFailed:`无法重新生成令牌:{{message}}`},o={open:`打开`,exit:`退出`,statusOn:`MCP 服务器:开启`,statusOff:`MCP 服务器:关闭`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`MCP 服务器`,t={what:`MCP(模型上下文协议)服务器让外部 AI 工具——例如 Claude Desktop、Cursor 或任何 MCP 客户端——直接与 Specrails 通信。它们可以浏览你的项目、读取规格,并在你允许的情况下启动任务,全部通过一个安全的本地连接完成。`,how:`在下方开启它,然后将客户端配置复制到你的 AI 工具中。Specrails 仅在你自己的机器上监听——不会向互联网暴露任何内容。`,grants:`默认情况下工具只有只读访问权限。使用权限层级逐项授予更多能力。`},n={on:`MCP 服务器已开启`,off:`MCP 服务器已关闭`,running_one:`运行中 · {{count}} 个工具`,running_other:`运行中 · {{count}} 个工具`,stopped:`未运行`,activeSessions_one:`{{count}} 个活动会话`,activeSessions_other:`{{count}} 个活动会话`,turnOn:`开启`,turnOff:`关闭`,enableFailed:`无法开启 MCP 服务器:{{message}}`,disableFailed:`无法关闭 MCP 服务器:{{message}}`},r={heading:`权限层级`,description:`客户端可使用的每个层级。读取始终开启;其余在你授予前均为关闭。`,read:`读取`,readHelp:`浏览项目、规格和分析。始终允许。`,write:`写入`,writeHelp:`创建和编辑规格与工单。`,aiSpawn:`启动 AI`,aiSpawnHelp:`启动运行 CLI 的 AI rails 和任务。`,destructive:`破坏性操作`,destructiveHelp:`删除规格、工单和其他项目数据。`,updateFailed:`无法更新权限:{{message}}`},i={heading:`客户端配置`,description:`将此内容粘贴到你的 MCP 客户端。它不包含任何密钥——令牌需单独复制。`,copyConfig:`复制配置`,configCopied:`配置已复制`,copyFailed:`复制失败`},a={heading:`访问令牌`,description:`你的客户端使用此令牌进行身份验证。请将其视为密码。`,hint:`以 {{hint}} 结尾的令牌`,copyToken:`复制令牌`,tokenCopied:`令牌已复制`,regenerate:`重新生成`,regenerateConfirm:`重新生成访问令牌?任何使用旧令牌的客户端都将停止工作,直到你更新其配置。`,regenerated:`访问令牌已重新生成`,regenerateFailed:`无法重新生成令牌:{{message}}`},o={open:`打开`,exit:`退出`,statusOn:`MCP 服务器:开启`,statusOff:`MCP 服务器:关闭`},s={heading:`外部 MCP 服务器`,description:`让任务代理可以使用你自己的 MCP 服务器。发现的条目来自你的 AI 提供商配置并实时解析;勾选提供商即可在其任务中启用服务器。`,warning:`任务回合运行时不会弹出工具批准提示,外部工具也不受 Specrails 权限层级约束。请只启用你信任的服务器。`,sourceDiscovered:`来自 {{provider}}`,sourceCustom:`自定义`,orphan:`在源配置中未找到`,codexNative:`codex 原生 — 始终启用`,empty:`未找到 MCP 服务器。请添加自定义服务器,或使用你的 AI CLI 注册一个。`,addCustom:`添加自定义`,remove:`移除服务器`,edit:`编辑服务器`,updateFailed:`无法保存外部 MCP 设置`,form:{name:`名称(如 jira-tools)`,command:`命令(如 npx)`,args:`参数(空格分隔)`,env:`环境变量(每行 KEY=VALUE)`,cancel:`取消`,save:`保存`,nameLabel:`名称`,commandLabel:`命令`,argsLabel:`参数`,envLabel:`环境变量`,enableFor:`启用于`,addVar:`添加变量`,envKey:`键`,envValue:`值`,nameInvalid:`仅限字母、数字、点和连字符 — 且 'specrails' 为保留名称`,nameTaken:`已存在同名的自定义服务器`},errors:{reserved_name:`该服务器名称已被保留`,duplicate_server_name:`两个已启用的服务器在同一提供商下重名`,invalid_transport:`自定义服务器需要一个命令`,unknown_provider:`激活矩阵中存在未知提供商`,invalid_entry:`服务器条目格式错误`,invalid_body:`请求格式错误`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`Servidor MCP`,t={what:`Un servidor MCP (Model Context Protocol) permite que herramientas de IA externas —como Claude Desktop, Cursor o cualquier cliente MCP— se comuniquen directamente con Specrails. Pueden explorar tus proyectos, leer especificaciones y, si lo permites, lanzar trabajos, todo a través de una única conexión local segura.`,how:`Actívalo abajo y copia la configuración del cliente en tu herramienta de IA. Specrails solo escucha en tu propia máquina: nada queda expuesto a internet.`,grants:`Por defecto las herramientas tienen acceso de solo lectura. Usa los niveles de permiso para conceder más, una capacidad cada vez.`},n={on:`Servidor MCP activado`,off:`Servidor MCP desactivado`,running_one:`En ejecución · {{count}} herramienta`,running_other:`En ejecución · {{count}} herramientas`,stopped:`Detenido`,activeSessions_one:`{{count}} sesión activa`,activeSessions_other:`{{count}} sesiones activas`,turnOn:`Activar`,turnOff:`Desactivar`,enableFailed:`No se pudo activar el servidor MCP: {{message}}`,disableFailed:`No se pudo desactivar el servidor MCP: {{message}}`},r={heading:`Niveles de permiso`,description:`Cada nivel que un cliente puede usar. Lectura siempre está activa; el resto están desactivados hasta que los concedas.`,read:`Lectura`,readHelp:`Explorar proyectos, especificaciones y analíticas. Siempre permitido.`,write:`Escritura`,writeHelp:`Crear y editar especificaciones y tickets.`,aiSpawn:`Lanzar IA`,aiSpawnHelp:`Lanzar rails y trabajos de IA que ejecutan la CLI.`,destructive:`Destructivo`,destructiveHelp:`Eliminar especificaciones, tickets y otros datos del proyecto.`,updateFailed:`No se pudieron actualizar los permisos: {{message}}`},i={heading:`Configuración del cliente`,description:`Pega esto en tu cliente MCP. No contiene ningún secreto: el token se copia por separado.`,copyConfig:`Copiar configuración`,configCopied:`Configuración copiada`,copyFailed:`Error al copiar`},a={heading:`Token de acceso`,description:`Tu cliente se autentica con este token. Trátalo como una contraseña.`,hint:`Token que termina en {{hint}}`,copyToken:`Copiar token`,tokenCopied:`Token copiado`,regenerate:`Regenerar`,regenerateConfirm:`¿Regenerar el token de acceso? Cualquier cliente que use el token antiguo dejará de funcionar hasta que actualices su configuración.`,regenerated:`Token de acceso regenerado`,regenerateFailed:`No se pudo regenerar el token: {{message}}`},o={open:`Abrir`,exit:`Salir`,statusOn:`Servidor MCP: activado`,statusOff:`Servidor MCP: desactivado`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`Servidor MCP`,t={what:`Un servidor MCP (Model Context Protocol) permite que herramientas de IA externas —como Claude Desktop, Cursor o cualquier cliente MCP— se comuniquen directamente con Specrails. Pueden explorar tus proyectos, leer especificaciones y, si lo permites, lanzar trabajos, todo a través de una única conexión local segura.`,how:`Actívalo abajo y copia la configuración del cliente en tu herramienta de IA. Specrails solo escucha en tu propia máquina: nada queda expuesto a internet.`,grants:`Por defecto las herramientas tienen acceso de solo lectura. Usa los niveles de permiso para conceder más, una capacidad cada vez.`},n={on:`Servidor MCP activado`,off:`Servidor MCP desactivado`,running_one:`En ejecución · {{count}} herramienta`,running_other:`En ejecución · {{count}} herramientas`,stopped:`Detenido`,activeSessions_one:`{{count}} sesión activa`,activeSessions_other:`{{count}} sesiones activas`,turnOn:`Activar`,turnOff:`Desactivar`,enableFailed:`No se pudo activar el servidor MCP: {{message}}`,disableFailed:`No se pudo desactivar el servidor MCP: {{message}}`},r={heading:`Niveles de permiso`,description:`Cada nivel que un cliente puede usar. Lectura siempre está activa; el resto están desactivados hasta que los concedas.`,read:`Lectura`,readHelp:`Explorar proyectos, especificaciones y analíticas. Siempre permitido.`,write:`Escritura`,writeHelp:`Crear y editar especificaciones y tickets.`,aiSpawn:`Lanzar IA`,aiSpawnHelp:`Lanzar rails y trabajos de IA que ejecutan la CLI.`,destructive:`Destructivo`,destructiveHelp:`Eliminar especificaciones, tickets y otros datos del proyecto.`,updateFailed:`No se pudieron actualizar los permisos: {{message}}`},i={heading:`Configuración del cliente`,description:`Pega esto en tu cliente MCP. No contiene ningún secreto: el token se copia por separado.`,copyConfig:`Copiar configuración`,configCopied:`Configuración copiada`,copyFailed:`Error al copiar`},a={heading:`Token de acceso`,description:`Tu cliente se autentica con este token. Trátalo como una contraseña.`,hint:`Token que termina en {{hint}}`,copyToken:`Copiar token`,tokenCopied:`Token copiado`,regenerate:`Regenerar`,regenerateConfirm:`¿Regenerar el token de acceso? Cualquier cliente que use el token antiguo dejará de funcionar hasta que actualices su configuración.`,regenerated:`Token de acceso regenerado`,regenerateFailed:`No se pudo regenerar el token: {{message}}`},o={open:`Abrir`,exit:`Salir`,statusOn:`Servidor MCP: activado`,statusOff:`Servidor MCP: desactivado`},s={heading:`Servidores MCP externos`,description:`Pon tus propios servidores MCP a disposición del agente de misiones. Las entradas descubiertas provienen de las configuraciones de tus proveedores de IA y se resuelven en vivo; marca un proveedor para activar un servidor en sus misiones.`,warning:`Los turnos de misión se ejecutan sin confirmación de herramientas, y las herramientas externas quedan fuera de los niveles de permiso de Specrails. Activa solo servidores de confianza.`,sourceDiscovered:`de {{provider}}`,sourceCustom:`personalizado`,orphan:`no encontrado en la configuración de origen`,codexNative:`nativo de codex — siempre activo`,empty:`No se encontraron servidores MCP. Añade uno personalizado o regístralo con tu CLI de IA.`,addCustom:`Añadir personalizado`,remove:`Eliminar servidor`,edit:`Editar servidor`,updateFailed:`No se pudo guardar la configuración de MCP externos`,form:{name:`Nombre (p. ej. jira-tools)`,command:`Comando (p. ej. npx)`,args:`Argumentos (separados por espacios)`,env:`Entorno (KEY=VALUE por línea)`,cancel:`Cancelar`,save:`Guardar`,nameLabel:`Nombre`,commandLabel:`Comando`,argsLabel:`Argumentos`,envLabel:`Variables de entorno`,enableFor:`Activar para`,addVar:`Añadir variable`,envKey:`CLAVE`,envValue:`valor`,nameInvalid:`Solo letras, dígitos, puntos y guiones — y 'specrails' está reservado`,nameTaken:`Ya existe un servidor personalizado con ese nombre`},errors:{reserved_name:`Ese nombre de servidor está reservado`,duplicate_server_name:`Dos servidores activos comparten nombre para un mismo proveedor`,invalid_transport:`Un servidor personalizado necesita un comando`,unknown_provider:`Proveedor desconocido en la matriz de activación`,invalid_entry:`Entrada de servidor malformada`,invalid_body:`Petición malformada`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`Server MCP`,t={what:`Un server MCP (Model Context Protocol) consente a strumenti di IA esterni — come Claude Desktop, Cursor o qualsiasi client MCP — di comunicare direttamente con Specrails. Possono esplorare i tuoi progetti, leggere le specifiche e, se lo consenti, avviare lavori, il tutto tramite un'unica connessione locale sicura.`,how:`Attivalo qui sotto, poi copia la configurazione del client nel tuo strumento di IA. Specrails è in ascolto solo sulla tua macchina: nulla viene esposto a internet.`,grants:`Per impostazione predefinita gli strumenti hanno accesso in sola lettura. Usa i livelli di permesso per concederne di più, una capacità alla volta.`},n={on:`Server MCP attivo`,off:`Server MCP disattivato`,running_one:`In esecuzione · {{count}} strumento`,running_other:`In esecuzione · {{count}} strumenti`,stopped:`Non in esecuzione`,activeSessions_one:`{{count}} sessione attiva`,activeSessions_other:`{{count}} sessioni attive`,turnOn:`Attiva`,turnOff:`Disattiva`,enableFailed:`Impossibile attivare il server MCP: {{message}}`,disableFailed:`Impossibile disattivare il server MCP: {{message}}`},r={heading:`Livelli di permesso`,description:`Ogni livello che un client può usare. La lettura è sempre attiva; il resto è disattivato finché non lo concedi.`,read:`Lettura`,readHelp:`Esplorare progetti, specifiche e analisi. Sempre consentito.`,write:`Scrittura`,writeHelp:`Creare e modificare specifiche e ticket.`,aiSpawn:`Avvio IA`,aiSpawnHelp:`Avviare rail e lavori di IA che eseguono la CLI.`,destructive:`Distruttivo`,destructiveHelp:`Eliminare specifiche, ticket e altri dati del progetto.`,updateFailed:`Impossibile aggiornare i permessi: {{message}}`},i={heading:`Configurazione del client`,description:`Incolla questo nel tuo client MCP. Non contiene alcun segreto: il token si copia separatamente.`,copyConfig:`Copia configurazione`,configCopied:`Configurazione copiata`,copyFailed:`Copia non riuscita`},a={heading:`Token di accesso`,description:`Il tuo client si autentica con questo token. Trattalo come una password.`,hint:`Token che termina con {{hint}}`,copyToken:`Copia token`,tokenCopied:`Token copiato`,regenerate:`Rigenera`,regenerateConfirm:`Rigenerare il token di accesso? Qualsiasi client che usa il vecchio token smetterà di funzionare finché non ne aggiorni la configurazione.`,regenerated:`Token di accesso rigenerato`,regenerateFailed:`Impossibile rigenerare il token: {{message}}`},o={open:`Apri`,exit:`Esci`,statusOn:`Server MCP: attivo`,statusOff:`Server MCP: disattivato`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`Server MCP`,t={what:`Un server MCP (Model Context Protocol) consente a strumenti di IA esterni — come Claude Desktop, Cursor o qualsiasi client MCP — di comunicare direttamente con Specrails. Possono esplorare i tuoi progetti, leggere le specifiche e, se lo consenti, avviare lavori, il tutto tramite un'unica connessione locale sicura.`,how:`Attivalo qui sotto, poi copia la configurazione del client nel tuo strumento di IA. Specrails è in ascolto solo sulla tua macchina: nulla viene esposto a internet.`,grants:`Per impostazione predefinita gli strumenti hanno accesso in sola lettura. Usa i livelli di permesso per concederne di più, una capacità alla volta.`},n={on:`Server MCP attivo`,off:`Server MCP disattivato`,running_one:`In esecuzione · {{count}} strumento`,running_other:`In esecuzione · {{count}} strumenti`,stopped:`Non in esecuzione`,activeSessions_one:`{{count}} sessione attiva`,activeSessions_other:`{{count}} sessioni attive`,turnOn:`Attiva`,turnOff:`Disattiva`,enableFailed:`Impossibile attivare il server MCP: {{message}}`,disableFailed:`Impossibile disattivare il server MCP: {{message}}`},r={heading:`Livelli di permesso`,description:`Ogni livello che un client può usare. La lettura è sempre attiva; il resto è disattivato finché non lo concedi.`,read:`Lettura`,readHelp:`Esplorare progetti, specifiche e analisi. Sempre consentito.`,write:`Scrittura`,writeHelp:`Creare e modificare specifiche e ticket.`,aiSpawn:`Avvio IA`,aiSpawnHelp:`Avviare rail e lavori di IA che eseguono la CLI.`,destructive:`Distruttivo`,destructiveHelp:`Eliminare specifiche, ticket e altri dati del progetto.`,updateFailed:`Impossibile aggiornare i permessi: {{message}}`},i={heading:`Configurazione del client`,description:`Incolla questo nel tuo client MCP. Non contiene alcun segreto: il token si copia separatamente.`,copyConfig:`Copia configurazione`,configCopied:`Configurazione copiata`,copyFailed:`Copia non riuscita`},a={heading:`Token di accesso`,description:`Il tuo client si autentica con questo token. Trattalo come una password.`,hint:`Token che termina con {{hint}}`,copyToken:`Copia token`,tokenCopied:`Token copiato`,regenerate:`Rigenera`,regenerateConfirm:`Rigenerare il token di accesso? Qualsiasi client che usa il vecchio token smetterà di funzionare finché non ne aggiorni la configurazione.`,regenerated:`Token di accesso rigenerato`,regenerateFailed:`Impossibile rigenerare il token: {{message}}`},o={open:`Apri`,exit:`Esci`,statusOn:`Server MCP: attivo`,statusOff:`Server MCP: disattivato`},s={heading:`Server MCP esterni`,description:`Rendi i tuoi server MCP disponibili all'agente delle missioni. Le voci scoperte provengono dalle configurazioni dei tuoi provider IA e vengono risolte in tempo reale; spunta un provider per attivare un server nelle sue missioni.`,warning:`I turni di missione vengono eseguiti senza conferme degli strumenti, e gli strumenti esterni sono fuori dai livelli di permesso di Specrails. Attiva solo server di cui ti fidi.`,sourceDiscovered:`da {{provider}}`,sourceCustom:`personalizzato`,orphan:`non trovato nella configurazione di origine`,codexNative:`nativo codex — sempre attivo`,empty:`Nessun server MCP trovato. Aggiungi un server personalizzato o registrane uno con la tua CLI IA.`,addCustom:`Aggiungi personalizzato`,remove:`Rimuovi server`,edit:`Modifica server`,updateFailed:`Impossibile salvare le impostazioni MCP esterne`,form:{name:`Nome (es. jira-tools)`,command:`Comando (es. npx)`,args:`Argomenti (separati da spazi)`,env:`Ambiente (KEY=VALUE per riga)`,cancel:`Annulla`,save:`Salva`,nameLabel:`Nome`,commandLabel:`Comando`,argsLabel:`Argomenti`,envLabel:`Variabili d'ambiente`,enableFor:`Attiva per`,addVar:`Aggiungi variabile`,envKey:`CHIAVE`,envValue:`valore`,nameInvalid:`Solo lettere, cifre, punti e trattini — e 'specrails' è riservato`,nameTaken:`Esiste già un server personalizzato con questo nome`},errors:{reserved_name:`Quel nome di server è riservato`,duplicate_server_name:`Due server attivi condividono lo stesso nome per un provider`,invalid_transport:`Un server personalizzato richiede un comando`,unknown_provider:`Provider sconosciuto nella matrice di attivazione`,invalid_entry:`Voce di server malformata`,invalid_body:`Richiesta malformata`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`Serveur MCP`,t={what:`Un serveur MCP (Model Context Protocol) permet à des outils d'IA externes — comme Claude Desktop, Cursor ou tout client MCP — de communiquer directement avec Specrails. Ils peuvent parcourir vos projets, lire les spécifications et, si vous l'autorisez, lancer des tâches, le tout via une seule connexion locale sécurisée.`,how:`Activez-le ci-dessous, puis copiez la configuration du client dans votre outil d'IA. Specrails n'écoute que sur votre propre machine : rien n'est exposé à internet.`,grants:`Par défaut, les outils ont un accès en lecture seule. Utilisez les niveaux de permission pour en accorder davantage, une capacité à la fois.`},n={on:`Serveur MCP activé`,off:`Serveur MCP désactivé`,running_one:`En cours · {{count}} outil`,running_other:`En cours · {{count}} outils`,stopped:`Arrêté`,activeSessions_one:`{{count}} session active`,activeSessions_other:`{{count}} sessions actives`,turnOn:`Activer`,turnOff:`Désactiver`,enableFailed:`Impossible d'activer le serveur MCP : {{message}}`,disableFailed:`Impossible de désactiver le serveur MCP : {{message}}`},r={heading:`Niveaux de permission`,description:`Chaque niveau qu'un client peut utiliser. La lecture est toujours active ; le reste est désactivé jusqu'à ce que vous l'accordiez.`,read:`Lecture`,readHelp:`Parcourir les projets, les spécifications et les analyses. Toujours autorisé.`,write:`Écriture`,writeHelp:`Créer et modifier des spécifications et des tickets.`,aiSpawn:`Lancer l'IA`,aiSpawnHelp:`Lancer des rails et des tâches d'IA qui exécutent la CLI.`,destructive:`Destructif`,destructiveHelp:`Supprimer des spécifications, des tickets et d'autres données du projet.`,updateFailed:`Impossible de mettre à jour les permissions : {{message}}`},i={heading:`Configuration du client`,description:`Collez ceci dans votre client MCP. Elle ne contient aucun secret : le jeton se copie séparément.`,copyConfig:`Copier la configuration`,configCopied:`Configuration copiée`,copyFailed:`Échec de la copie`},a={heading:`Jeton d'accès`,description:`Votre client s'authentifie avec ce jeton. Traitez-le comme un mot de passe.`,hint:`Jeton se terminant par {{hint}}`,copyToken:`Copier le jeton`,tokenCopied:`Jeton copié`,regenerate:`Régénérer`,regenerateConfirm:`Régénérer le jeton d'accès ? Tout client utilisant l'ancien jeton cessera de fonctionner jusqu'à ce que vous mettiez à jour sa configuration.`,regenerated:`Jeton d'accès régénéré`,regenerateFailed:`Impossible de régénérer le jeton : {{message}}`},o={open:`Ouvrir`,exit:`Quitter`,statusOn:`Serveur MCP : activé`,statusOff:`Serveur MCP : désactivé`},s={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o};export{i as config,
|
|
1
|
+
var e=`Serveur MCP`,t={what:`Un serveur MCP (Model Context Protocol) permet à des outils d'IA externes — comme Claude Desktop, Cursor ou tout client MCP — de communiquer directement avec Specrails. Ils peuvent parcourir vos projets, lire les spécifications et, si vous l'autorisez, lancer des tâches, le tout via une seule connexion locale sécurisée.`,how:`Activez-le ci-dessous, puis copiez la configuration du client dans votre outil d'IA. Specrails n'écoute que sur votre propre machine : rien n'est exposé à internet.`,grants:`Par défaut, les outils ont un accès en lecture seule. Utilisez les niveaux de permission pour en accorder davantage, une capacité à la fois.`},n={on:`Serveur MCP activé`,off:`Serveur MCP désactivé`,running_one:`En cours · {{count}} outil`,running_other:`En cours · {{count}} outils`,stopped:`Arrêté`,activeSessions_one:`{{count}} session active`,activeSessions_other:`{{count}} sessions actives`,turnOn:`Activer`,turnOff:`Désactiver`,enableFailed:`Impossible d'activer le serveur MCP : {{message}}`,disableFailed:`Impossible de désactiver le serveur MCP : {{message}}`},r={heading:`Niveaux de permission`,description:`Chaque niveau qu'un client peut utiliser. La lecture est toujours active ; le reste est désactivé jusqu'à ce que vous l'accordiez.`,read:`Lecture`,readHelp:`Parcourir les projets, les spécifications et les analyses. Toujours autorisé.`,write:`Écriture`,writeHelp:`Créer et modifier des spécifications et des tickets.`,aiSpawn:`Lancer l'IA`,aiSpawnHelp:`Lancer des rails et des tâches d'IA qui exécutent la CLI.`,destructive:`Destructif`,destructiveHelp:`Supprimer des spécifications, des tickets et d'autres données du projet.`,updateFailed:`Impossible de mettre à jour les permissions : {{message}}`},i={heading:`Configuration du client`,description:`Collez ceci dans votre client MCP. Elle ne contient aucun secret : le jeton se copie séparément.`,copyConfig:`Copier la configuration`,configCopied:`Configuration copiée`,copyFailed:`Échec de la copie`},a={heading:`Jeton d'accès`,description:`Votre client s'authentifie avec ce jeton. Traitez-le comme un mot de passe.`,hint:`Jeton se terminant par {{hint}}`,copyToken:`Copier le jeton`,tokenCopied:`Jeton copié`,regenerate:`Régénérer`,regenerateConfirm:`Régénérer le jeton d'accès ? Tout client utilisant l'ancien jeton cessera de fonctionner jusqu'à ce que vous mettiez à jour sa configuration.`,regenerated:`Jeton d'accès régénéré`,regenerateFailed:`Impossible de régénérer le jeton : {{message}}`},o={open:`Ouvrir`,exit:`Quitter`,statusOn:`Serveur MCP : activé`,statusOff:`Serveur MCP : désactivé`},s={heading:`Serveurs MCP externes`,description:`Rendez vos propres serveurs MCP disponibles pour l'agent de missions. Les entrées découvertes proviennent des configurations de vos fournisseurs d'IA et sont résolues en direct ; cochez un fournisseur pour activer un serveur dans ses missions.`,warning:`Les tours de mission s'exécutent sans confirmation d'outils, et les outils externes sont hors des niveaux de permission Specrails. N'activez que des serveurs de confiance.`,sourceDiscovered:`depuis {{provider}}`,sourceCustom:`personnalisé`,orphan:`introuvable dans la configuration source`,codexNative:`natif codex — toujours actif`,empty:`Aucun serveur MCP trouvé. Ajoutez un serveur personnalisé ou enregistrez-en un avec votre CLI d'IA.`,addCustom:`Ajouter personnalisé`,remove:`Supprimer le serveur`,edit:`Modifier le serveur`,updateFailed:`Impossible d'enregistrer les paramètres MCP externes`,form:{name:`Nom (p. ex. jira-tools)`,command:`Commande (p. ex. npx)`,args:`Arguments (séparés par des espaces)`,env:`Environnement (KEY=VALUE par ligne)`,cancel:`Annuler`,save:`Enregistrer`,nameLabel:`Nom`,commandLabel:`Commande`,argsLabel:`Arguments`,envLabel:`Variables d'environnement`,enableFor:`Activer pour`,addVar:`Ajouter une variable`,envKey:`CLÉ`,envValue:`valeur`,nameInvalid:`Lettres, chiffres, points et tirets uniquement — et « specrails » est réservé`,nameTaken:`Un serveur personnalisé porte déjà ce nom`},errors:{reserved_name:`Ce nom de serveur est réservé`,duplicate_server_name:`Deux serveurs actifs partagent le même nom pour un fournisseur`,invalid_transport:`Un serveur personnalisé nécessite une commande`,unknown_provider:`Fournisseur inconnu dans la matrice d'activation`,invalid_entry:`Entrée de serveur malformée`,invalid_body:`Requête malformée`}},c={heading:e,explainer:t,enable:n,tiers:r,config:i,token:a,tray:o,external:s};export{i as config,c as default,n as enable,t as explainer,s as external,e as heading,r as tiers,a as token,o as tray};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./i18n-
|
|
1
|
+
import{o as e}from"./i18n-hnX2DPmo.js";var t={job:`analytics:surfaces.job`,"quick-spec":`analytics:surfaces.quickSpec`,"explore-spec":`analytics:surfaces.exploreSpec`,"ai-edit":`analytics:surfaces.aiEdit`,smash:`analytics:surfaces.smash`,"file-summary":`analytics:surfaces.fileSummary`,loop:`analytics:surfaces.loop`,"chat-sidebar":`analytics:surfaces.chatSidebar`,"spec-launcher":`analytics:surfaces.specLauncher`,proposal:`analytics:surfaces.proposal`,"agent-studio":`analytics:surfaces.agentStudio`,setup:`analytics:surfaces.setup`},n={bg:`bg-muted/40`,text:`text-muted-foreground`,ring:`ring-border/40`,dot:`bg-muted-foreground`},r={job:{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"quick-spec":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},"explore-spec":{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"ai-edit":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},smash:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"file-summary":{bg:`bg-accent-warning/15`,text:`text-accent-warning`,ring:`ring-accent-warning/40`,dot:`bg-accent-warning`},loop:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`},"chat-sidebar":{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"spec-launcher":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},proposal:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"agent-studio":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},setup:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`}};function i(e,t){return new Proxy(e,{get(e,n,r){return typeof n==`string`&&!(n in e)?t(n):Reflect.get(e,n,r)}})}var a=i(Object.defineProperties({},Object.fromEntries(Object.keys(t).map(n=>[n,{get:()=>e.t(t[n]),enumerable:!0}]))),e=>e),o=i(r,()=>n);export{a as n,o as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{o as r,w as i}from"./i18n-
|
|
1
|
+
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{o as r,w as i}from"./i18n-hnX2DPmo.js";import{n as a}from"./dist-bVqfYmby.js";import{a as o}from"./auth-D_5bQv5W.js";var s=e(t(),1),c=null;function l(e){c=e}function u(){if(!c)throw Error(`getApiBase called with no active project — call setActiveProjectId first`);return`${o}/api/projects/${c}`}var d=new Map;function f(e,t){return`${e}:${t}`}function p(e){return(e instanceof Error?e.message:e==null?``:String(e)).trim()||`Request failed`}function m(e){if(!e)return;let t=`${e}:`;for(let e of d.keys())e.startsWith(t)&&d.delete(e)}function h({namespace:e,projectId:t,initialValue:n,fetcher:r,pollInterval:i=0}){let a=t?f(t,e):null,[o,c]=(0,s.useState)(()=>a&&d.has(a)?d.get(a):n),[l,u]=(0,s.useState)(()=>!a||!d.has(a)),[m,h]=(0,s.useState)(l),[g,_]=(0,s.useState)(null),v=(0,s.useRef)(r);v.current=r;let y=(0,s.useRef)(n);y.current=n;let b=(0,s.useRef)(a);b.current=a;let x=(0,s.useRef)(0),S=(0,s.useRef)(null),C=(0,s.useCallback)(async(e,t,n)=>{let r=++x.current;S.current?.abort();let i=new AbortController;S.current=i,n&&b.current===e&&(h(!0),_(null));try{let n=await v.current({projectId:t,signal:i.signal});if(i.signal.aborted||r!==x.current)return;d.set(e,n),b.current===e&&(c(n),_(null))}catch(t){if(i.signal.aborted||r!==x.current)return;b.current===e&&_(p(t))}finally{r===x.current&&(S.current===i&&(S.current=null),b.current===e&&(h(!1),u(!1)))}},[]);return(0,s.useEffect)(()=>{if(x.current+=1,S.current?.abort(),S.current=null,_(null),!a||!t){c(y.current),u(!0),h(!1);return}let e=d.has(a);e?(c(d.get(a)),u(!1),h(!1)):(c(y.current),u(!0),h(!0)),C(a,t,!e);let n;return i>0&&(n=setInterval(()=>{C(a,t,!1)},i)),()=>{x.current+=1,S.current?.abort(),S.current=null,n&&clearInterval(n)}},[a,t,i,C]),{data:o,isLoading:m,isFirstLoad:l,error:g,refresh:(0,s.useCallback)(async()=>{!a||!t||await C(a,t,!0)},[a,t,C])}}var g=n();function _(e){return e.providers&&e.providers.length>0?e.providers:[e.provider]}var v=(0,s.createContext)(null),y=`specrails-desktop:activeProjectId`;function b(e){try{e?localStorage.setItem(y,e):localStorage.removeItem(y)}catch{}}function x(){try{return localStorage.getItem(y)}catch{return null}}function S({children:e}){let[t,n]=(0,s.useState)([]),[c,u]=(0,s.useState)(null),[d,f]=(0,s.useState)(!0),[p,h]=(0,s.useState)(!1),_=(0,s.useRef)(null),y=(0,s.useRef)(new Set),S=(0,s.useCallback)(e=>{b(e),l(e),u(t=>(t!==null&&t!==e&&(_.current&&clearTimeout(_.current),h(!0),_.current=setTimeout(()=>h(!1),400)),e))},[]),{registerHandler:C,unregisterHandler:w}=i();(0,s.useEffect)(()=>{async function e(){try{let e=await fetch(`${o}/api/projects`);if(!e.ok)return;let t=await e.json();n(t.projects)}catch{}finally{f(!1)}}e()},[]);let T=(0,s.useCallback)(e=>{let t=e;if(typeof t.type==`string`){if(t.type===`desktop.projects`){if(!Array.isArray(t.projects))return;let e=t.projects;n(e),u(t=>{let n;if(t&&e.find(e=>e.id===t))n=t;else{let t=x();n=t&&e.find(e=>e.id===t)?t:e.length>0?e[0].id:null}return b(n),l(n),n}),f(!1)}else if(t.type===`desktop.project_added`){let e=t.project;n(t=>t.find(t=>t.id===e.id)?t:[...t,e]),y.current.has(e.id)?y.current.delete(e.id):(a.success(r.t(`nav:projects.added`,{name:e.name})),S(e.id))}else if(t.type===`providers.detected_changed`)fetch(`${o}/api/projects`).then(e=>e.ok?e.json():null).then(e=>{e&&Array.isArray(e.projects)&&n(e.projects)}).catch(()=>{});else if(t.type===`desktop.project_removed`){let e=t.projectId;a.success(r.t(`nav:projects.removed`)),m(e),n(t=>t.filter(t=>t.id!==e)),u(t=>t===e?(b(null),l(null),null):t)}}},[]);(0,s.useLayoutEffect)(()=>(C(`desktop`,T),()=>w(`desktop`)),[T,C,w]);let E=(0,s.useRef)(0);(0,s.useEffect)(()=>{let e=()=>{let e=Date.now();e-E.current<6e4||(E.current=e,fetch(`${o}/api/providers/detected?refresh=1`).catch(()=>{}))};return window.addEventListener(`focus`,e),()=>window.removeEventListener(`focus`,e)},[]);let D=(0,s.useCallback)(async(e,t,r)=>{try{let i={path:e};r&&r.length>0&&(i.providers=r),t&&(i.name=t);let a=await fetch(`/api/projects`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)});if(!a.ok){let e=await a.json();throw Error(e.error??`HTTP ${a.status}`)}let o=await a.json();return y.current.add(o.project.id),n(e=>e.find(e=>e.id===o.project.id)?e:[...e,o.project]),S(o.project.id),o}catch(e){throw console.error(`[useDesktop] addProject error:`,e),e}},[S]),O=(0,s.useCallback)(async e=>{try{let t=await fetch(`${o}/api/projects/${e}`,{method:`DELETE`});if(!t.ok){let e=await t.json();throw Error(e.error??`HTTP ${t.status}`)}m(e),n(t=>t.filter(t=>t.id!==e)),u(t=>t===e?(b(null),l(null),null):t)}catch(e){throw console.error(`[useDesktop] removeProject error:`,e),e}},[]),k=(0,s.useMemo)(()=>({projects:t,activeProjectId:c,setActiveProjectId:S,addProject:D,removeProject:O,isLoading:d,isSwitchingProject:p}),[t,c,S,D,O,d,p]);return(0,g.jsx)(v.Provider,{value:k,children:e})}var C={projects:[],activeProjectId:null,setActiveProjectId:()=>{},addProject:async()=>null,removeProject:async()=>{},isLoading:!1,isSwitchingProject:!1};function w(){return(0,s.useContext)(v)??C}export{u as a,h as i,_ as n,w as r,S as t};
|
package/client/dist/index.html
CHANGED
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
.specrails-splash__mark .pill { opacity: 1; }
|
|
205
205
|
}
|
|
206
206
|
</style>
|
|
207
|
-
<script type="module" crossorigin src="/assets/index-
|
|
207
|
+
<script type="module" crossorigin src="/assets/index-DIhMEAVw.js"></script>
|
|
208
208
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CNC7AqOf.js">
|
|
209
209
|
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-zu2_FqZY.js">
|
|
210
210
|
<link rel="modulepreload" crossorigin href="/assets/react-dom-DiWzBDP9.js">
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
<link rel="modulepreload" crossorigin href="/assets/jira-CKJg3HZd.js">
|
|
233
233
|
<link rel="modulepreload" crossorigin href="/assets/jobs-B_TeSQxb.js">
|
|
234
234
|
<link rel="modulepreload" crossorigin href="/assets/loops-B7YpGizO.js">
|
|
235
|
-
<link rel="modulepreload" crossorigin href="/assets/mcp-
|
|
235
|
+
<link rel="modulepreload" crossorigin href="/assets/mcp-D8BT78_L.js">
|
|
236
236
|
<link rel="modulepreload" crossorigin href="/assets/narration-DRaDnhT5.js">
|
|
237
237
|
<link rel="modulepreload" crossorigin href="/assets/nav-DjkmQJjd.js">
|
|
238
238
|
<link rel="modulepreload" crossorigin href="/assets/packet-Bh5kkbiB.js">
|
|
@@ -241,14 +241,14 @@
|
|
|
241
241
|
<link rel="modulepreload" crossorigin href="/assets/specs-DII0C8gw.js">
|
|
242
242
|
<link rel="modulepreload" crossorigin href="/assets/terminal-BFRZnMPP.js">
|
|
243
243
|
<link rel="modulepreload" crossorigin href="/assets/tickets-W6pBmbrX.js">
|
|
244
|
-
<link rel="modulepreload" crossorigin href="/assets/i18n-
|
|
245
|
-
<link rel="modulepreload" crossorigin href="/assets/Trans-
|
|
244
|
+
<link rel="modulepreload" crossorigin href="/assets/i18n-hnX2DPmo.js">
|
|
245
|
+
<link rel="modulepreload" crossorigin href="/assets/Trans-Bsz9_gyq.js">
|
|
246
246
|
<link rel="modulepreload" crossorigin href="/assets/dist-bVqfYmby.js">
|
|
247
247
|
<link rel="modulepreload" crossorigin href="/assets/save-B6wGWwBR.js">
|
|
248
248
|
<link rel="modulepreload" crossorigin href="/assets/sparkles-DrY8hb0X.js">
|
|
249
249
|
<link rel="modulepreload" crossorigin href="/assets/x-CBMI9ejn.js">
|
|
250
|
-
<link rel="modulepreload" crossorigin href="/assets/useDesktop-
|
|
251
|
-
<link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-
|
|
250
|
+
<link rel="modulepreload" crossorigin href="/assets/useDesktop-BQVt8lFd.js">
|
|
251
|
+
<link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-Bd3OqR_S.js">
|
|
252
252
|
<link rel="modulepreload" crossorigin href="/assets/file-text-BcLCfcWZ.js">
|
|
253
253
|
<link rel="modulepreload" crossorigin href="/assets/circle-x-CMYsN4ZH.js">
|
|
254
254
|
<link rel="modulepreload" crossorigin href="/assets/download-CFHyyHcw.js">
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
<link rel="modulepreload" crossorigin href="/assets/search-Cq_gE3Ik.js">
|
|
261
261
|
<link rel="modulepreload" crossorigin href="/assets/trash-2-BOU3WdZZ.js">
|
|
262
262
|
<link rel="modulepreload" crossorigin href="/assets/triangle-alert-H9T4jAmh.js">
|
|
263
|
-
<link rel="modulepreload" crossorigin href="/assets/jira-api-
|
|
263
|
+
<link rel="modulepreload" crossorigin href="/assets/jira-api-B1-MUehg.js">
|
|
264
264
|
<link rel="modulepreload" crossorigin href="/assets/zap-CHo3aCD1.js">
|
|
265
265
|
<link rel="modulepreload" crossorigin href="/assets/clsx-CjueKrWZ.js">
|
|
266
266
|
<link rel="modulepreload" crossorigin href="/assets/utils-BC4DHlz2.js">
|
|
@@ -268,15 +268,15 @@
|
|
|
268
268
|
<link rel="modulepreload" crossorigin href="/assets/button-CJqFnUOL.js">
|
|
269
269
|
<link rel="modulepreload" crossorigin href="/assets/provider-capabilities-Doej9lfa.js">
|
|
270
270
|
<link rel="modulepreload" crossorigin href="/assets/lib-CGdyxIWg.js">
|
|
271
|
-
<link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-
|
|
272
|
-
<link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-
|
|
273
|
-
<link rel="modulepreload" crossorigin href="/assets/spending-
|
|
274
|
-
<link rel="modulepreload" crossorigin href="/assets/TicketDetailModal-
|
|
271
|
+
<link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-C16cxSe1.js">
|
|
272
|
+
<link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-DQCvMgUc.js">
|
|
273
|
+
<link rel="modulepreload" crossorigin href="/assets/spending-EC9xqio-.js">
|
|
274
|
+
<link rel="modulepreload" crossorigin href="/assets/TicketDetailModal-CsF-AWZX.js">
|
|
275
275
|
<link rel="modulepreload" crossorigin href="/assets/bot-DzuuuC5R.js">
|
|
276
276
|
<link rel="modulepreload" crossorigin href="/assets/git-refresh-wTW0rO0Z.js">
|
|
277
277
|
<link rel="modulepreload" crossorigin href="/assets/core-B3mKBIh5.js">
|
|
278
278
|
<link rel="modulepreload" crossorigin href="/assets/event-Bt7f3wXe.js">
|
|
279
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
279
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DwygcU7s.css">
|
|
280
280
|
</head>
|
|
281
281
|
<body>
|
|
282
282
|
<div id="specrails-splash" aria-hidden="false" role="status" aria-label="Loading Specrails">
|
package/docs/mcp.md
CHANGED
|
@@ -253,6 +253,22 @@ only with the scoped MCP token:
|
|
|
253
253
|
|
|
254
254
|
These boundaries are intentional and may be revisited in a later version.
|
|
255
255
|
|
|
256
|
+
## External MCP servers for the mission agent
|
|
257
|
+
|
|
258
|
+
The inverse direction — the mission agent (Desktop agent chat) consuming *your*
|
|
259
|
+
MCP servers — is configured in **Settings ▸ MCP ▸ External MCP servers**. The
|
|
260
|
+
app discovers servers registered in your provider CLIs (`~/.claude.json`,
|
|
261
|
+
`~/.gemini/settings.json`, `~/.kimi-code/mcp.json`; codex `config.toml` servers
|
|
262
|
+
already load natively in missions) and lets you enable each one per provider,
|
|
263
|
+
or add a custom stdio server manually. Nothing activates without your explicit
|
|
264
|
+
per-provider tick, and discovered transports resolve live from your CLI config
|
|
265
|
+
at every mission turn — edits there flow through automatically.
|
|
266
|
+
|
|
267
|
+
**Security note:** mission turns run without per-tool approval prompts, and
|
|
268
|
+
external tools are outside the Specrails permission tiers (those govern only
|
|
269
|
+
`specrails_*` tools). Enable only servers you trust. Kill switch:
|
|
270
|
+
`SPECRAILS_EXTERNAL_MCP=false`.
|
|
271
|
+
|
|
256
272
|
## Troubleshooting
|
|
257
273
|
|
|
258
274
|
**My client can't connect / "app is not running"** — start the Specrails
|
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ const desktop_db_1 = require("./desktop-db");
|
|
|
19
19
|
const agent_cwd_manager_1 = require("./agent-cwd-manager");
|
|
20
20
|
const agent_operator_prompt_1 = require("./agent-operator-prompt");
|
|
21
21
|
const agent_mcp_config_1 = require("./agent-mcp-config");
|
|
22
|
+
const external_mcp_1 = require("./external-mcp");
|
|
22
23
|
const agent_tier_1 = require("./agent-tier");
|
|
23
24
|
const agent_capability_1 = require("./mcp/agent-capability");
|
|
24
25
|
const attachment_manager_1 = require("./attachment-manager");
|
|
@@ -335,6 +336,7 @@ class AgentChatManager {
|
|
|
335
336
|
cwd,
|
|
336
337
|
port: this._port,
|
|
337
338
|
capability: agentCapability,
|
|
339
|
+
external: (0, external_mcp_1.resolveExternalEntries)(adapter.id, this._db),
|
|
338
340
|
});
|
|
339
341
|
mcpArgs = wiring.extraArgs;
|
|
340
342
|
mcpEnv = wiring.env;
|
|
@@ -10,6 +10,7 @@ exports.mergeSpecrailsIntoWorkspaceMcp = mergeSpecrailsIntoWorkspaceMcp;
|
|
|
10
10
|
exports.buildAgentMcpArgs = buildAgentMcpArgs;
|
|
11
11
|
exports.removeAgentCapabilityFile = removeAgentCapabilityFile;
|
|
12
12
|
exports.prepareAgentMcp = prepareAgentMcp;
|
|
13
|
+
exports.syncExternalServersIntoJsonFile = syncExternalServersIntoJsonFile;
|
|
13
14
|
const fs_1 = __importDefault(require("fs"));
|
|
14
15
|
const path_1 = __importDefault(require("path"));
|
|
15
16
|
const os_1 = __importDefault(require("os"));
|
|
@@ -18,6 +19,7 @@ const path_resolver_1 = require("./path-resolver");
|
|
|
18
19
|
const win_spawn_1 = require("./util/win-spawn");
|
|
19
20
|
const agent_tier_1 = require("./agent-tier");
|
|
20
21
|
const providers_1 = require("./providers");
|
|
22
|
+
const external_mcp_1 = require("./external-mcp");
|
|
21
23
|
const AGENT_CONVERSATION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
22
24
|
// ─── Agent MCP wiring (design D8 / D1) ────────────────────────────────────────
|
|
23
25
|
//
|
|
@@ -141,7 +143,13 @@ function buildAgentMcpArgs(opts) {
|
|
|
141
143
|
return [];
|
|
142
144
|
const dir = agentDir(opts.conversationId);
|
|
143
145
|
const file = path_1.default.join(dir, 'mcp.json');
|
|
144
|
-
|
|
146
|
+
const mcpServers = { specrails: entry };
|
|
147
|
+
for (const server of opts.external ?? []) {
|
|
148
|
+
if (server.name === 'specrails')
|
|
149
|
+
continue;
|
|
150
|
+
mcpServers[server.name] = server.config;
|
|
151
|
+
}
|
|
152
|
+
fs_1.default.writeFileSync(file, JSON.stringify({ mcpServers }, null, 2), { mode: 0o600 });
|
|
145
153
|
try {
|
|
146
154
|
fs_1.default.chmodSync(file, 0o600);
|
|
147
155
|
}
|
|
@@ -228,6 +236,27 @@ function codexMcpOverrides(entry) {
|
|
|
228
236
|
}
|
|
229
237
|
return args;
|
|
230
238
|
}
|
|
239
|
+
/** External-server variant of the codex `-c` overrides. Callers pre-filter with
|
|
240
|
+
* `isCodexInjectable` (TOML-safe name + string command). */
|
|
241
|
+
function codexExternalOverrides(server) {
|
|
242
|
+
const c = (kv) => ['-c', kv];
|
|
243
|
+
const command = String(server.config.command);
|
|
244
|
+
const argsList = Array.isArray(server.config.args)
|
|
245
|
+
? server.config.args.filter((a) => typeof a === 'string')
|
|
246
|
+
: [];
|
|
247
|
+
const args = [
|
|
248
|
+
...c(`mcp_servers.${server.name}.command=${JSON.stringify(command)}`),
|
|
249
|
+
...c(`mcp_servers.${server.name}.args=[${argsList.map((a) => JSON.stringify(a)).join(', ')}]`),
|
|
250
|
+
];
|
|
251
|
+
const env = server.config.env;
|
|
252
|
+
if (env && typeof env === 'object' && !Array.isArray(env)) {
|
|
253
|
+
for (const [k, v] of Object.entries(env)) {
|
|
254
|
+
if (typeof v === 'string')
|
|
255
|
+
args.push(...c(`mcp_servers.${server.name}.env.${k}=${JSON.stringify(v)}`));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return args;
|
|
259
|
+
}
|
|
231
260
|
/**
|
|
232
261
|
* Prepares the specrails MCP for the given provider and returns the spawn
|
|
233
262
|
* extraArgs + env to merge. Returns empty wiring when the bridge is unavailable
|
|
@@ -235,6 +264,7 @@ function codexMcpOverrides(entry) {
|
|
|
235
264
|
*/
|
|
236
265
|
function prepareAgentMcp(opts) {
|
|
237
266
|
const adapter = (0, providers_1.getAdapter)(opts.adapterId);
|
|
267
|
+
const external = (opts.external ?? []).filter((s) => s.name !== 'specrails');
|
|
238
268
|
if (adapter.id === 'claude') {
|
|
239
269
|
return { extraArgs: buildAgentMcpArgs(opts), env: {} };
|
|
240
270
|
}
|
|
@@ -243,12 +273,14 @@ function prepareAgentMcp(opts) {
|
|
|
243
273
|
return { extraArgs: [], env: {} };
|
|
244
274
|
if (adapter.mcpRegistration === 'cli-add') {
|
|
245
275
|
// Inline -c overrides contain only the capability FILE PATH, never its secret.
|
|
246
|
-
|
|
276
|
+
const externalArgs = external.filter(external_mcp_1.isCodexInjectable).flatMap(codexExternalOverrides);
|
|
277
|
+
return { extraArgs: [...codexMcpOverrides(entry), ...externalArgs], env: {} };
|
|
247
278
|
}
|
|
248
279
|
// Project-json providers write only their native project config in the
|
|
249
280
|
// conversation-isolated cwd.
|
|
250
281
|
const file = adapter.projectMcpPath?.(opts.cwd) ?? path_1.default.join(opts.cwd, '.mcp.json');
|
|
251
282
|
mergeServerIntoJsonFile(file, entry);
|
|
283
|
+
syncExternalServersIntoJsonFile(file, external);
|
|
252
284
|
if (adapter.id === 'gemini') {
|
|
253
285
|
// gemini-cli has NEVER read .mcp.json (a Claude convention) — its only MCP
|
|
254
286
|
// surface is `mcpServers` in settings.json (user or <cwd>/.gemini project
|
|
@@ -286,3 +318,63 @@ function mergeServerIntoJsonFile(file, entry) {
|
|
|
286
318
|
}
|
|
287
319
|
catch { /* best-effort */ }
|
|
288
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Sync the user's EXTERNAL servers into a persistent settings file (gemini
|
|
323
|
+
* `.gemini/settings.json`, kimi `.kimi-code/mcp.json`) with owned-key hygiene:
|
|
324
|
+
* a sidecar (`external-owned.json`, same dir) records every key the app wrote,
|
|
325
|
+
* and each spawn removes the previously-owned set before merging the currently
|
|
326
|
+
* enabled one — so disabling an entry removes it on the next spawn while keys
|
|
327
|
+
* the app never wrote (and `specrails`, managed separately) are untouched.
|
|
328
|
+
*/
|
|
329
|
+
function syncExternalServersIntoJsonFile(file, external) {
|
|
330
|
+
const dir = path_1.default.dirname(file);
|
|
331
|
+
const sidecar = path_1.default.join(dir, 'external-owned.json');
|
|
332
|
+
let owned = [];
|
|
333
|
+
try {
|
|
334
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(sidecar, 'utf-8'));
|
|
335
|
+
if (parsed && Array.isArray(parsed.owned)) {
|
|
336
|
+
owned = parsed.owned.filter((n) => typeof n === 'string');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
/* first spawn / no sidecar yet */
|
|
341
|
+
}
|
|
342
|
+
// Nothing owned before and nothing to inject now → leave the file alone.
|
|
343
|
+
if (owned.length === 0 && external.length === 0)
|
|
344
|
+
return;
|
|
345
|
+
let current = {};
|
|
346
|
+
try {
|
|
347
|
+
if (fs_1.default.existsSync(file)) {
|
|
348
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(file, 'utf-8'));
|
|
349
|
+
if (parsed && typeof parsed === 'object')
|
|
350
|
+
current = parsed;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
current = {};
|
|
355
|
+
}
|
|
356
|
+
const mcpServers = { ...(current.mcpServers ?? {}) };
|
|
357
|
+
for (const name of owned) {
|
|
358
|
+
if (name !== 'specrails')
|
|
359
|
+
delete mcpServers[name];
|
|
360
|
+
}
|
|
361
|
+
const nextOwned = [];
|
|
362
|
+
for (const server of external) {
|
|
363
|
+
if (server.name === 'specrails')
|
|
364
|
+
continue;
|
|
365
|
+
mcpServers[server.name] = server.config;
|
|
366
|
+
nextOwned.push(server.name);
|
|
367
|
+
}
|
|
368
|
+
const next = { ...current, mcpServers };
|
|
369
|
+
fs_1.default.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
370
|
+
fs_1.default.writeFileSync(file, JSON.stringify(next, null, 2), { mode: 0o600 });
|
|
371
|
+
try {
|
|
372
|
+
fs_1.default.chmodSync(file, 0o600);
|
|
373
|
+
}
|
|
374
|
+
catch { /* best-effort */ }
|
|
375
|
+
fs_1.default.writeFileSync(sidecar, JSON.stringify({ owned: nextOwned }, null, 2), { mode: 0o600 });
|
|
376
|
+
try {
|
|
377
|
+
fs_1.default.chmodSync(sidecar, 0o600);
|
|
378
|
+
}
|
|
379
|
+
catch { /* best-effort */ }
|
|
380
|
+
}
|
|
@@ -69,6 +69,10 @@ coding pipelines over them.
|
|
|
69
69
|
\`mcp_specrails_<canonical name>\` (e.g. \`mcp_specrails_specrails_specs\`).
|
|
70
70
|
Use whatever form your tool list shows; they are identical tools. They are
|
|
71
71
|
MCP tools, NOT shell commands or files — never hunt for them on disk.
|
|
72
|
+
- Additional USER-CONFIGURED tools (external MCP servers) may also appear in
|
|
73
|
+
your tool list. Use them for their own domains when helpful, but ALL
|
|
74
|
+
Specrails app operations (specs, rails, jobs, projects, …) MUST still go
|
|
75
|
+
through the \`specrails_*\` tools — never through a lookalike external tool.
|
|
72
76
|
- Target a project with \`specrails_select_project\` (or the \`projectId\`
|
|
73
77
|
argument). If none is pinned ("Home") and the request is project-specific, ASK
|
|
74
78
|
whether to create a project or search across all — do not guess.
|
|
@@ -18,6 +18,7 @@ const core_compat_1 = require("./core-compat");
|
|
|
18
18
|
const providers_1 = require("./providers");
|
|
19
19
|
const provider_detection_1 = require("./provider-detection");
|
|
20
20
|
const agent_defaults_1 = require("./agent-defaults");
|
|
21
|
+
const external_mcp_1 = require("./external-mcp");
|
|
21
22
|
const workspace_manager_1 = require("./workspace-manager");
|
|
22
23
|
const workspace_resolution_1 = require("./workspace-resolution");
|
|
23
24
|
const desktop_analytics_1 = require("./desktop-analytics");
|
|
@@ -1153,6 +1154,27 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
1153
1154
|
res.status(500).json({ error: 'agent_defaults_failed', message: err.message });
|
|
1154
1155
|
}
|
|
1155
1156
|
});
|
|
1157
|
+
// ─── External MCP servers (mission agent, app-global) ─────────────────────
|
|
1158
|
+
// Registry of the user's OWN MCP servers for mission spawns. Discovery reads
|
|
1159
|
+
// provider native configs per request (cheap file reads, read-only); entries
|
|
1160
|
+
// resolve at spawn time, so a PATCH applies to the next turn with no restart.
|
|
1161
|
+
router.get('/external-mcp', (_req, res) => {
|
|
1162
|
+
const settings = (0, external_mcp_1.readExternalMcpSettings)(registry.desktopDb);
|
|
1163
|
+
res.json({ discovered: (0, external_mcp_1.discoverExternalMcp)(settings), settings });
|
|
1164
|
+
});
|
|
1165
|
+
router.patch('/external-mcp', (req, res) => {
|
|
1166
|
+
try {
|
|
1167
|
+
const settings = (0, external_mcp_1.applyExternalMcpPatch)(registry.desktopDb, req.body);
|
|
1168
|
+
res.json({ discovered: (0, external_mcp_1.discoverExternalMcp)(settings), settings });
|
|
1169
|
+
}
|
|
1170
|
+
catch (err) {
|
|
1171
|
+
if (err instanceof external_mcp_1.ExternalMcpValidationError) {
|
|
1172
|
+
res.status(400).json({ error: err.code, message: err.message });
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
res.status(500).json({ error: 'external_mcp_failed', message: err.message });
|
|
1176
|
+
}
|
|
1177
|
+
});
|
|
1156
1178
|
// ─── specrails-core update channel (app-global) ─────────────────────────────
|
|
1157
1179
|
// Detect + apply a specrails-core framework update independently of the desktop
|
|
1158
1180
|
// app update. See server/core-update-manager.ts. A single manager instance
|