@redaksjon/protokoll 1.0.21 → 1.0.22-dev.20260227214704.08e3d54
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/.dockerignore +42 -0
- package/.gcloudignore +43 -0
- package/deploy/cloud-run/Dockerfile +35 -0
- package/deploy/cloud-run/env.example.yaml +47 -0
- package/dist/configDiscovery.js +999 -40
- package/dist/configDiscovery.js.map +1 -1
- package/dist/mcp/server-hono.js +372 -121
- package/dist/mcp/server-hono.js.map +1 -1
- package/dist/mcp/server.js +4 -2
- package/dist/mcp/server.js.map +1 -1
- package/docs/gcs-authentication.md +70 -0
- package/docs/mcp-session-recovery.md +30 -0
- package/docs/storage-backends.md +79 -0
- package/guide/cloud-run.md +150 -0
- package/guide/index.md +1 -0
- package/package.json +4 -1
- package/scripts/ensure-executable-bins.mjs +29 -0
package/dist/mcp/server.js
CHANGED
|
@@ -8,17 +8,19 @@ import { resolve } from 'node:path';
|
|
|
8
8
|
import { realpath } from 'node:fs/promises';
|
|
9
9
|
import { i as initializeWorkingDirectoryFromArgsAndConfig, t as tools, h as handleToolCall, a as handleListResources, b as handleReadResource, g as getPrompts, c as getPrompt, d as initializeServerConfig, e as getCachedRoots, s as setRoots } from '../configDiscovery.js';
|
|
10
10
|
import { initializeWeightModel } from '../weightModel.js';
|
|
11
|
+
import 'node:os';
|
|
12
|
+
import '@fjell/logging';
|
|
11
13
|
import '@redaksjon/protokoll-engine';
|
|
14
|
+
import '@redaksjon/protokoll-format';
|
|
12
15
|
import 'js-yaml';
|
|
13
16
|
import 'node:fs';
|
|
14
17
|
import '@redaksjon/context';
|
|
15
|
-
import 'node:os';
|
|
16
18
|
import 'winston';
|
|
17
19
|
import 'glob';
|
|
18
20
|
import 'crypto';
|
|
19
21
|
import 'node:crypto';
|
|
20
|
-
import '@redaksjon/protokoll-format';
|
|
21
22
|
import '@utilarium/cardigantime';
|
|
23
|
+
import '@google-cloud/storage';
|
|
22
24
|
|
|
23
25
|
async function main() {
|
|
24
26
|
await initializeWorkingDirectoryFromArgsAndConfig();
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../../src/mcp/server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Protokoll MCP Server\n *\n * Exposes intelligent audio transcription as MCP tools for AI coding assistants.\n * Allows AI tools to process audio, manage context, and work with transcripts\n * without needing to understand command-line interfaces.\n *\n * Key capabilities:\n * - Process audio files with context-aware transcription\n * - Manage context entities (people, projects, terms, companies)\n * - Edit and combine existing transcripts\n * - Provide feedback to improve transcription quality\n */\n\nimport 'dotenv/config';\n// eslint-disable-next-line import/extensions\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\n// eslint-disable-next-line import/extensions\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n ListRootsRequestSchema,\n// eslint-disable-next-line import/extensions\n} from '@modelcontextprotocol/sdk/types.js';\nimport { fileURLToPath } from 'node:url';\nimport { resolve } from 'node:path';\nimport { realpath } from 'node:fs/promises';\nimport * as Resources from './resources';\nimport * as Prompts from './prompts';\nimport { tools, handleToolCall } from './tools';\nimport * as ServerConfig from './serverConfig';\nimport * as Roots from './roots';\nimport type { McpRoot } from './types';\nimport { initializeWorkingDirectoryFromArgsAndConfig } from './configDiscovery';\nimport { initializeWeightModel } from './services/weightModel';\n\n// ============================================================================\n// Server Setup\n// ============================================================================\n\nasync function main() {\n // Allow running `protokoll-mcp` directly from any subdirectory.\n // We discover `protokoll-config.yaml` (or explicit --config) and set WORKSPACE_ROOT accordingly.\n await initializeWorkingDirectoryFromArgsAndConfig();\n\n const server = new Server(\n {\n name: 'protokoll',\n version: '0.1.0',\n description:\n 'Intelligent audio transcription with context-aware enhancement. ' +\n 'Process audio files through a pipeline that transcribes with Whisper, ' +\n 'then enhances using LLMs with knowledge of your people, projects, and terminology. ' +\n 'Manage context entities (people, projects, terms) to improve recognition. ' +\n 'Edit and combine existing transcripts.',\n },\n {\n capabilities: {\n tools: {},\n resources: {\n subscribe: false,\n listChanged: true,\n },\n prompts: {\n listChanged: false,\n },\n },\n }\n );\n\n // Request roots from client and initialize configuration\n server.setRequestHandler(ListRootsRequestSchema, async () => {\n const roots = Roots.getCachedRoots() || [];\n return { roots };\n });\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools,\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n const result = await handleToolCall(name, args);\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n });\n\n // List available resources\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return Resources.handleListResources();\n });\n\n // Read a resource\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const { uri } = request.params;\n\n try {\n const contents = await Resources.handleReadResource(uri);\n return { contents: [contents] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read resource ${uri}: ${message}`);\n }\n });\n\n // List available prompts\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return { prompts: Prompts.getPrompts() };\n });\n\n // Get a prompt with arguments\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n const messages = await Prompts.getPrompt(name, args || {});\n return { messages };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to get prompt ${name}: ${message}`);\n }\n });\n\n // Start server\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Initialize configuration from workspace\n // Try to get roots from environment or use cwd as fallback\n const workspaceRoot = process.env.WORKSPACE_ROOT || process.cwd();\n const initialRoots: McpRoot[] = [{\n uri: `file://${workspaceRoot}`,\n name: 'Workspace',\n }];\n \n Roots.setRoots(initialRoots);\n await ServerConfig.initializeServerConfig(initialRoots);\n\n // Initialize weight model\n // eslint-disable-next-line no-console\n console.log('[MCP Server] Initializing weight model...');\n await initializeWeightModel(workspaceRoot);\n // eslint-disable-next-line no-console\n console.log('[MCP Server] Weight model initialization complete');\n\n // Keep the process alive - MCP servers should run indefinitely\n // The StdioServerTransport will handle stdin/stdout until the connection closes\n await new Promise(() => {\n // This promise never resolves, keeping the event loop alive\n // The process will only exit when killed or stdin closes\n });\n}\n\n// ES module equivalent of CommonJS `require.main === module`\n// Use realpath() to resolve symlinks before comparison\nasync function checkIsMainModule(): Promise<boolean> {\n if (!import.meta.url.startsWith('file:') || !process.argv[1]) {\n return false;\n }\n \n try {\n const argvPath = await realpath(resolve(process.argv[1]));\n const modulePath = await realpath(fileURLToPath(import.meta.url));\n return argvPath === modulePath;\n } catch {\n return false;\n }\n}\n\n// Start the server if this is the main module\ncheckIsMainModule().then((isMain) => {\n if (isMain) {\n main().catch((error) => {\n // eslint-disable-next-line no-console\n console.error(error);\n process.exit(1);\n });\n }\n});\n\n// ============================================================================\n// Exports for Testing\n// ============================================================================\n\nexport { main, checkIsMainModule };\n"],"names":["Roots.getCachedRoots","Resources.handleListResources","Resources.handleReadResource","Prompts.getPrompts","Prompts.getPrompt","Roots.setRoots","ServerConfig.initializeServerConfig"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8CA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,IAAA,CAAA,CAAA,CAAO,CAAA;AAGlB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,2CAAA,CAAA,CAA4C,CAAA;AAElD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,IAAS,CAAA,CAAA,CAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CACf,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACI,CAAA,CAAA,CAAA,CAAA,EAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACN,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACT,WAAA,CAAA,CACI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAKR,CAAA;AAAA,CAAA,CAAA,CAAA,CACA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACI,YAA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"}
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../../src/mcp/server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Protokoll MCP Server\n *\n * Exposes intelligent audio transcription as MCP tools for AI coding assistants.\n * Allows AI tools to process audio, manage context, and work with transcripts\n * without needing to understand command-line interfaces.\n *\n * Key capabilities:\n * - Process audio files with context-aware transcription\n * - Manage context entities (people, projects, terms, companies)\n * - Edit and combine existing transcripts\n * - Provide feedback to improve transcription quality\n */\n\nimport 'dotenv/config';\n// eslint-disable-next-line import/extensions\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\n// eslint-disable-next-line import/extensions\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n ListRootsRequestSchema,\n// eslint-disable-next-line import/extensions\n} from '@modelcontextprotocol/sdk/types.js';\nimport { fileURLToPath } from 'node:url';\nimport { resolve } from 'node:path';\nimport { realpath } from 'node:fs/promises';\nimport * as Resources from './resources';\nimport * as Prompts from './prompts';\nimport { tools, handleToolCall } from './tools';\nimport * as ServerConfig from './serverConfig';\nimport * as Roots from './roots';\nimport type { McpRoot } from './types';\nimport { initializeWorkingDirectoryFromArgsAndConfig } from './configDiscovery';\nimport { initializeWeightModel } from './services/weightModel';\n\n// ============================================================================\n// Server Setup\n// ============================================================================\n\nasync function main() {\n // Allow running `protokoll-mcp` directly from any subdirectory.\n // We discover `protokoll-config.yaml` (or explicit --config) and set WORKSPACE_ROOT accordingly.\n await initializeWorkingDirectoryFromArgsAndConfig();\n\n const server = new Server(\n {\n name: 'protokoll',\n version: '0.1.0',\n description:\n 'Intelligent audio transcription with context-aware enhancement. ' +\n 'Process audio files through a pipeline that transcribes with Whisper, ' +\n 'then enhances using LLMs with knowledge of your people, projects, and terminology. ' +\n 'Manage context entities (people, projects, terms) to improve recognition. ' +\n 'Edit and combine existing transcripts.',\n },\n {\n capabilities: {\n tools: {},\n resources: {\n subscribe: false,\n listChanged: true,\n },\n prompts: {\n listChanged: false,\n },\n },\n }\n );\n\n // Request roots from client and initialize configuration\n server.setRequestHandler(ListRootsRequestSchema, async () => {\n const roots = Roots.getCachedRoots() || [];\n return { roots };\n });\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools,\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n const result = await handleToolCall(name, args);\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n });\n\n // List available resources\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return Resources.handleListResources();\n });\n\n // Read a resource\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const { uri } = request.params;\n\n try {\n const contents = await Resources.handleReadResource(uri);\n return { contents: [contents] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read resource ${uri}: ${message}`);\n }\n });\n\n // List available prompts\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return { prompts: Prompts.getPrompts() };\n });\n\n // Get a prompt with arguments\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n const messages = await Prompts.getPrompt(name, args || {});\n return { messages };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to get prompt ${name}: ${message}`);\n }\n });\n\n // Start server\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Initialize configuration from workspace\n // Try to get roots from environment or use cwd as fallback\n const workspaceRoot = process.env.WORKSPACE_ROOT || process.cwd();\n const initialRoots: McpRoot[] = [{\n uri: `file://${workspaceRoot}`,\n name: 'Workspace',\n }];\n \n Roots.setRoots(initialRoots);\n await ServerConfig.initializeServerConfig(initialRoots);\n\n // Initialize weight model\n // eslint-disable-next-line no-console\n console.log('[MCP Server] Initializing weight model...');\n await initializeWeightModel(workspaceRoot);\n // eslint-disable-next-line no-console\n console.log('[MCP Server] Weight model initialization complete');\n\n // Keep the process alive - MCP servers should run indefinitely\n // The StdioServerTransport will handle stdin/stdout until the connection closes\n await new Promise(() => {\n // This promise never resolves, keeping the event loop alive\n // The process will only exit when killed or stdin closes\n });\n}\n\n// ES module equivalent of CommonJS `require.main === module`\n// Use realpath() to resolve symlinks before comparison\nasync function checkIsMainModule(): Promise<boolean> {\n if (!import.meta.url.startsWith('file:') || !process.argv[1]) {\n return false;\n }\n \n try {\n const argvPath = await realpath(resolve(process.argv[1]));\n const modulePath = await realpath(fileURLToPath(import.meta.url));\n return argvPath === modulePath;\n } catch {\n return false;\n }\n}\n\n// Start the server if this is the main module\ncheckIsMainModule().then((isMain) => {\n if (isMain) {\n main().catch((error) => {\n // eslint-disable-next-line no-console\n console.error(error);\n process.exit(1);\n });\n }\n});\n\n// ============================================================================\n// Exports for Testing\n// ============================================================================\n\nexport { main, checkIsMainModule };\n"],"names":["Roots.getCachedRoots","Resources.handleListResources","Resources.handleReadResource","Prompts.getPrompts","Prompts.getPrompt","Roots.setRoots","ServerConfig.initializeServerConfig"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8CA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,IAAA,CAAA,CAAA,CAAO,CAAA;AAGlB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,2CAAA,CAAA,CAA4C,CAAA;AAElD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,IAAS,CAAA,CAAA,CAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CACf,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACI,CAAA,CAAA,CAAA,CAAA,EAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACN,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACT,WAAA,CAAA,CACI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAKR,CAAA;AAAA,CAAA,CAAA,CAAA,CACA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACI,Y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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# GCS Authentication
|
|
2
|
+
|
|
3
|
+
This guide describes how to authenticate Protokoll when running with `storage.backend: gcs`.
|
|
4
|
+
|
|
5
|
+
## Cloud Run Recommendation (No Key File)
|
|
6
|
+
|
|
7
|
+
When running in Google Cloud Run, prefer the runtime service account identity:
|
|
8
|
+
|
|
9
|
+
- Do **not** set `storage.gcs.credentialsFile`
|
|
10
|
+
- Attach a service account to the Cloud Run service
|
|
11
|
+
- Grant that service account IAM access to the configured GCS buckets/prefixes
|
|
12
|
+
|
|
13
|
+
In this mode, Protokoll uses Google Application Default Credentials (ADC) from the Cloud Run environment.
|
|
14
|
+
|
|
15
|
+
## Recommended for This Phase
|
|
16
|
+
|
|
17
|
+
For local/dev and non-Cloud Run environments, use a service account key file and set:
|
|
18
|
+
|
|
19
|
+
- `storage.gcs.credentialsFile` in `protokoll-config.yaml`
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
storage:
|
|
25
|
+
backend: gcs
|
|
26
|
+
gcs:
|
|
27
|
+
inputUri: gs://my-input-bucket/protokoll/input/
|
|
28
|
+
outputUri: gs://my-output-bucket/protokoll/output/
|
|
29
|
+
contextUri: gs://shared-context-bucket/redaksjon/context/
|
|
30
|
+
credentialsFile: /absolute/path/to/service-account.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Create a Service Account Key
|
|
34
|
+
|
|
35
|
+
1. In Google Cloud Console, create/select a service account.
|
|
36
|
+
2. Grant bucket permissions required for your workload.
|
|
37
|
+
- Typical minimum: read/write object access on configured bucket paths.
|
|
38
|
+
3. Create and download a JSON key file.
|
|
39
|
+
4. Store the key file in a secure location outside source control.
|
|
40
|
+
5. Reference that absolute path as `storage.gcs.credentialsFile`.
|
|
41
|
+
|
|
42
|
+
## Optional: ADC Environment Variable
|
|
43
|
+
|
|
44
|
+
If `credentialsFile` is omitted, the underlying Google SDK can use default credentials resolution (for example `GOOGLE_APPLICATION_CREDENTIALS`).
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/service-account.json"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then omit `credentialsFile` from config.
|
|
53
|
+
|
|
54
|
+
## Permissions Checklist
|
|
55
|
+
|
|
56
|
+
For each configured URI bucket:
|
|
57
|
+
|
|
58
|
+
- `inputUri` bucket/prefix: list/read access for input object discovery and reads
|
|
59
|
+
- `outputUri` bucket/prefix: write/read/delete access for output objects
|
|
60
|
+
- `contextUri` bucket/prefix: read/write access for context entities
|
|
61
|
+
|
|
62
|
+
If any required permission is missing, Protokoll will fail fast in GCS mode.
|
|
63
|
+
|
|
64
|
+
## Security Notes
|
|
65
|
+
|
|
66
|
+
- Never commit service account JSON keys to git.
|
|
67
|
+
- Restrict key file permissions on disk.
|
|
68
|
+
- Prefer separate service accounts for environments (dev/stage/prod).
|
|
69
|
+
- Rotate keys periodically.
|
|
70
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# MCP Session Recovery Pattern
|
|
2
|
+
|
|
3
|
+
This document captures the session-recovery strategy used between `protokoll` (MCP server) and `protokoll-vscode` (HTTP client).
|
|
4
|
+
|
|
5
|
+
## Goals
|
|
6
|
+
|
|
7
|
+
- Keep MCP interactions resilient when session state drifts.
|
|
8
|
+
- Avoid hard failures on stale or missing session ids.
|
|
9
|
+
- Let clients recover transparently without user intervention.
|
|
10
|
+
|
|
11
|
+
## Three-step approach
|
|
12
|
+
|
|
13
|
+
1. **Always return effective session id**
|
|
14
|
+
- Server sets `Mcp-Session-Id` on successful `POST /mcp` responses.
|
|
15
|
+
- Client treats response header as authoritative and rotates local session id when it changes.
|
|
16
|
+
|
|
17
|
+
2. **Server auto-recovers stale/missing sessions**
|
|
18
|
+
- For non-`initialize` requests, if the incoming session id is unknown, server creates a replacement session instead of returning `Session not found`.
|
|
19
|
+
- If no session id is provided, server also creates a session and continues.
|
|
20
|
+
|
|
21
|
+
3. **Client retries once on session-loss errors**
|
|
22
|
+
- Client detects session-loss responses (`Session not found`, `Missing Mcp-Session-Id header`, `-32000`).
|
|
23
|
+
- Client re-initializes once, re-establishes SSE, re-subscribes known resources, then retries the original request once.
|
|
24
|
+
- Generic `HTTP 404` only triggers recovery if client already had a session id, to avoid retrying unrelated routes.
|
|
25
|
+
|
|
26
|
+
## Why this split
|
|
27
|
+
|
|
28
|
+
- Server-side tolerance handles the common stale-session edge quickly.
|
|
29
|
+
- Client-side recovery covers race conditions and transport-level failures.
|
|
30
|
+
- One retry prevents loops while still making failures far less disruptive.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Storage Backends
|
|
2
|
+
|
|
3
|
+
Protokoll supports two storage backends for `input`, `output`, and `context`:
|
|
4
|
+
|
|
5
|
+
- `filesystem` (default)
|
|
6
|
+
- `gcs` (optional, explicit opt-in)
|
|
7
|
+
|
|
8
|
+
If `storage.backend` is not set, Protokoll runs in filesystem mode exactly as before.
|
|
9
|
+
|
|
10
|
+
## Filesystem Mode (Default)
|
|
11
|
+
|
|
12
|
+
You do not need a `storage` section for filesystem mode.
|
|
13
|
+
|
|
14
|
+
Example `protokoll-config.yaml`:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
inputDirectory: ./recordings
|
|
18
|
+
outputDirectory: ./notes
|
|
19
|
+
processedDirectory: ./processed
|
|
20
|
+
contextDirectories:
|
|
21
|
+
- ./context
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Behavior:
|
|
25
|
+
|
|
26
|
+
- Protokoll reads audio from `inputDirectory`
|
|
27
|
+
- writes transcript/output artifacts under `outputDirectory`
|
|
28
|
+
- loads context entities from `contextDirectories`
|
|
29
|
+
|
|
30
|
+
## GCS Mode
|
|
31
|
+
|
|
32
|
+
To use GCS, explicitly set `storage.backend: gcs` and provide all three domain URIs.
|
|
33
|
+
|
|
34
|
+
Example `protokoll-config.yaml`:
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
inputDirectory: ./recordings
|
|
38
|
+
outputDirectory: ./notes
|
|
39
|
+
processedDirectory: ./processed
|
|
40
|
+
|
|
41
|
+
storage:
|
|
42
|
+
backend: gcs
|
|
43
|
+
gcs:
|
|
44
|
+
inputUri: gs://my-input-bucket/protokoll/input/
|
|
45
|
+
outputUri: gs://my-output-bucket/protokoll/output/
|
|
46
|
+
contextUri: gs://shared-context-bucket/redaksjon/context/
|
|
47
|
+
credentialsFile: /absolute/path/to/service-account.json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Notes:
|
|
51
|
+
|
|
52
|
+
- URIs must use canonical `gs://bucket/path` format.
|
|
53
|
+
- You can use different buckets per domain (`input`, `output`, `context`).
|
|
54
|
+
- A shared context bucket/prefix is supported.
|
|
55
|
+
- If `credentialsFile` is omitted, the Google SDK default credential chain is used.
|
|
56
|
+
|
|
57
|
+
## Fail-Fast Validation in GCS Mode
|
|
58
|
+
|
|
59
|
+
When `storage.backend: gcs` is enabled, startup validates:
|
|
60
|
+
|
|
61
|
+
- `storage.gcs.inputUri`
|
|
62
|
+
- `storage.gcs.outputUri`
|
|
63
|
+
- `storage.gcs.contextUri`
|
|
64
|
+
- `credentialsFile` readability (if provided)
|
|
65
|
+
- bucket access for configured input/output storage
|
|
66
|
+
|
|
67
|
+
Protokoll fails at startup when validation fails; it does not fall back to filesystem.
|
|
68
|
+
|
|
69
|
+
## Common Configuration Errors
|
|
70
|
+
|
|
71
|
+
- `storage.backend is set to gcs, but storage.gcs is missing`
|
|
72
|
+
- Add the `storage.gcs` section.
|
|
73
|
+
- `Invalid GCS URI "...": must start with "gs://"`
|
|
74
|
+
- Use `gs://bucket/path`.
|
|
75
|
+
- `GCS credentials file is not readable: ...`
|
|
76
|
+
- Fix path/permissions for the configured key file.
|
|
77
|
+
- Bucket access errors (metadata/read/write failures)
|
|
78
|
+
- Verify bucket names, IAM roles, and service account access.
|
|
79
|
+
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Cloud Run Deployment Template
|
|
2
|
+
|
|
3
|
+
This template deploys the Protokoll MCP HTTP server (`protokoll-mcp-http`) to Google Cloud Run using Cloud Build.
|
|
4
|
+
|
|
5
|
+
Use these files:
|
|
6
|
+
|
|
7
|
+
- `deploy/cloud-run/Dockerfile`
|
|
8
|
+
- `deploy/cloud-run/cloudbuild.yaml`
|
|
9
|
+
- `deploy/cloud-run/env.example.yaml`
|
|
10
|
+
|
|
11
|
+
## 1) Runtime Service Account
|
|
12
|
+
|
|
13
|
+
Create a dedicated runtime service account for Cloud Run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
gcloud iam service-accounts create protokoll-runtime \
|
|
17
|
+
--display-name="Protokoll Cloud Run Runtime"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Grant only the permissions your configured storage/backend needs.
|
|
21
|
+
|
|
22
|
+
For GCS storage (`storage.backend: gcs`), start with:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
|
|
26
|
+
--member="serviceAccount:protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com" \
|
|
27
|
+
--role="roles/storage.objectAdmin"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If using project-level ADC discovery, you may also need:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
|
|
34
|
+
--member="serviceAccount:protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com" \
|
|
35
|
+
--role="roles/storage.admin"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Allow deploy identities to use the runtime service account:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
PROJECT_NUMBER="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')"
|
|
42
|
+
|
|
43
|
+
gcloud iam service-accounts add-iam-policy-binding "protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com" \
|
|
44
|
+
--member="user:${USER_EMAIL}" \
|
|
45
|
+
--role="roles/iam.serviceAccountUser"
|
|
46
|
+
|
|
47
|
+
gcloud iam service-accounts add-iam-policy-binding "protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com" \
|
|
48
|
+
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
|
|
49
|
+
--role="roles/iam.serviceAccountUser"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 2) Required APIs + Deployer/Builder IAM
|
|
53
|
+
|
|
54
|
+
Enable required services:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
gcloud services enable \
|
|
58
|
+
cloudbuild.googleapis.com \
|
|
59
|
+
artifactregistry.googleapis.com \
|
|
60
|
+
run.googleapis.com \
|
|
61
|
+
storage.googleapis.com
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Minimum project roles for deploy user (`USER_EMAIL`):
|
|
65
|
+
|
|
66
|
+
- `roles/cloudbuild.builds.editor`
|
|
67
|
+
- `roles/run.admin`
|
|
68
|
+
- `roles/artifactregistry.writer`
|
|
69
|
+
- `roles/storage.admin` (for Cloud Build staging bucket setup)
|
|
70
|
+
|
|
71
|
+
Minimum project roles for Cloud Build service account (`${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com`):
|
|
72
|
+
|
|
73
|
+
- `roles/run.admin`
|
|
74
|
+
- `roles/artifactregistry.writer`
|
|
75
|
+
## 3) Artifact Registry (one-time)
|
|
76
|
+
|
|
77
|
+
Create an Artifact Registry Docker repo for images:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
gcloud artifacts repositories create protokoll \
|
|
81
|
+
--repository-format=docker \
|
|
82
|
+
--location=us-central1 \
|
|
83
|
+
--description="Protokoll images"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 4) Secrets (recommended)
|
|
87
|
+
|
|
88
|
+
Use Secret Manager for API keys instead of plaintext env files:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
PROJECT_ID="your-project-id"
|
|
92
|
+
|
|
93
|
+
# OPENAI_API_KEY must be present in your shell environment.
|
|
94
|
+
printf '%s' "$OPENAI_API_KEY" | gcloud secrets create protokoll-openai-api-key \
|
|
95
|
+
--project="$PROJECT_ID" \
|
|
96
|
+
--replication-policy=automatic \
|
|
97
|
+
--data-file=- || \
|
|
98
|
+
printf '%s' "$OPENAI_API_KEY" | gcloud secrets versions add protokoll-openai-api-key \
|
|
99
|
+
--project="$PROJECT_ID" \
|
|
100
|
+
--data-file=-
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Grant Cloud Run runtime service account access to read secrets:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
gcloud secrets add-iam-policy-binding protokoll-openai-api-key \
|
|
107
|
+
--project="$PROJECT_ID" \
|
|
108
|
+
--member="serviceAccount:protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com" \
|
|
109
|
+
--role="roles/secretmanager.secretAccessor"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 5) Environment Variables (non-secret)
|
|
113
|
+
|
|
114
|
+
Copy and edit env vars:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
cp deploy/cloud-run/env.example.yaml deploy/cloud-run/env.prod.yaml
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Update `deploy/cloud-run/env.prod.yaml` with non-secret values only.
|
|
121
|
+
|
|
122
|
+
## 6) Configure Cloud Build Substitutions
|
|
123
|
+
|
|
124
|
+
Use `deploy/cloud-run/cloudbuild.yaml` substitutions:
|
|
125
|
+
|
|
126
|
+
- `_REGION`
|
|
127
|
+
- `_SERVICE_NAME`
|
|
128
|
+
- `_AR_REPO`
|
|
129
|
+
- `_IMAGE_NAME`
|
|
130
|
+
- `_SERVICE_ACCOUNT`
|
|
131
|
+
- `_ENV_VARS_FILE`
|
|
132
|
+
- `_OPENAI_SECRET`
|
|
133
|
+
|
|
134
|
+
For production, set `_ENV_VARS_FILE=deploy/cloud-run/env.prod.yaml`.
|
|
135
|
+
|
|
136
|
+
## 7) Deploy
|
|
137
|
+
|
|
138
|
+
From the repo root:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
gcloud builds submit --config deploy/cloud-run/cloudbuild.yaml \
|
|
142
|
+
--substitutions=_REGION=us-central1,_SERVICE_NAME=protokoll-mcp,_AR_REPO=protokoll,_IMAGE_NAME=protokoll-mcp,_SERVICE_ACCOUNT=protokoll-runtime@${PROJECT_ID}.iam.gserviceaccount.com,_ENV_VARS_FILE=deploy/cloud-run/env.prod.yaml,_OPENAI_SECRET=protokoll-openai-api-key
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Notes
|
|
146
|
+
|
|
147
|
+
- The server listens on `PORT` (Cloud Run standard) and supports `MCP_PORT`/`PROTOKOLL_MCP_PORT`.
|
|
148
|
+
- The Docker image includes `ffmpeg`, required for audio format conversion/splitting.
|
|
149
|
+
- Cloud Run should use service account identity (ADC); do not bake key files into the image.
|
|
150
|
+
- Cloud Build uses `${BUILD_ID}` for image tags in this template so `gcloud builds submit` works reliably outside trigger contexts.
|
package/guide/index.md
CHANGED
|
@@ -30,6 +30,7 @@ Protokoll transforms audio recordings into intelligent, context-enhanced transcr
|
|
|
30
30
|
|
|
31
31
|
### AI Integration
|
|
32
32
|
- [**MCP Integration**](./mcp-integration.md): Use Protokoll through AI assistants
|
|
33
|
+
- [**Cloud Run Deployment**](./cloud-run.md): Deploy MCP HTTP server to Google Cloud Run
|
|
33
34
|
|
|
34
35
|
### Development
|
|
35
36
|
- [**Development**](./development.md): Building and testing
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redaksjon/protokoll",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22-dev.20260227214704.08e3d54",
|
|
4
4
|
"description": "Focused audio transcription with intelligent context integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"homepage": "https://github.com/redaksjon/protokoll",
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "npm run lint && tsc --noEmit && vite build && chmod +x dist/mcp/server.js dist/mcp/server-hono.js",
|
|
18
|
+
"postinstall": "node scripts/ensure-executable-bins.mjs",
|
|
18
19
|
"dev": "vite",
|
|
19
20
|
"watch": "vite build --watch",
|
|
20
21
|
"test": "vitest run --coverage",
|
|
@@ -54,6 +55,8 @@
|
|
|
54
55
|
},
|
|
55
56
|
"dependencies": {
|
|
56
57
|
"@anthropic-ai/sdk": "^0.71.2",
|
|
58
|
+
"@fjell/logging": "^4.4.69",
|
|
59
|
+
"@google-cloud/storage": "^7.19.0",
|
|
57
60
|
"@google/generative-ai": "^0.24.1",
|
|
58
61
|
"@hono/mcp": "^0.2.3",
|
|
59
62
|
"@hono/node-server": "^1.19.9",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { access, chmod } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const packageRoot = join(__dirname, '..');
|
|
9
|
+
|
|
10
|
+
const binTargets = [
|
|
11
|
+
join(packageRoot, 'dist/mcp/server.js'),
|
|
12
|
+
join(packageRoot, 'dist/mcp/server-hono.js'),
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
for (const target of binTargets) {
|
|
16
|
+
try {
|
|
17
|
+
await access(target);
|
|
18
|
+
await chmod(target, 0o755);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
const code = error && typeof error === 'object' && 'code' in error
|
|
21
|
+
? error.code
|
|
22
|
+
: undefined;
|
|
23
|
+
if (code === 'ENOENT') {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.warn(`[postinstall] Failed to chmod ${target}:`, error);
|
|
28
|
+
}
|
|
29
|
+
}
|