@juspay/neurolink 12.36.0 → 12.36.1
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/CHANGELOG.md +3 -3
- package/dist/agent/directTools.js +56 -22
- package/dist/browser/neurolink.min.js +374 -374
- package/dist/types/file.d.ts +12 -0
- package/dist/utils/csvProcessor.d.ts +3 -3
- package/dist/utils/csvProcessor.js +53 -5
- package/docs-site/static/search-index.json +5 -5
- package/package.json +1 -1
package/dist/types/file.d.ts
CHANGED
|
@@ -425,6 +425,18 @@ export type CSVColumnMetadata = {
|
|
|
425
425
|
};
|
|
426
426
|
/** A parsed CSV row: string-keyed with string (or missing) cell values (#384). */
|
|
427
427
|
export type CSVRow = Record<string, string | undefined>;
|
|
428
|
+
/**
|
|
429
|
+
* How `CSVProcessor.parseCSVFile` opens the file.
|
|
430
|
+
*
|
|
431
|
+
* `followSymlinks: false` opens with O_NOFOLLOW, so a symlink at the final
|
|
432
|
+
* path component is refused (ELOOP) rather than followed. The sandboxed
|
|
433
|
+
* analyzeCSV tool passes it after containment has resolved the real path,
|
|
434
|
+
* closing the window between that check and the open. Defaults to `true`; on
|
|
435
|
+
* Windows, where O_NOFOLLOW does not exist, the option has no effect.
|
|
436
|
+
*/
|
|
437
|
+
export type CSVFileOpenOptions = {
|
|
438
|
+
followSymlinks?: boolean;
|
|
439
|
+
};
|
|
428
440
|
/** Result of decoding a buffer with encoding detection (#362). */
|
|
429
441
|
export type DecodedBuffer = {
|
|
430
442
|
/** Decoded text with any BOM removed. */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Converts CSV files to LLM-friendly text formats
|
|
4
4
|
* Uses streaming for memory efficiency with large files
|
|
5
5
|
*/
|
|
6
|
-
import type { FileProcessingResult, CSVProcessorOptions, CSVRow } from "../types/index.js";
|
|
6
|
+
import type { FileProcessingResult, CSVFileOpenOptions, CSVProcessorOptions, CSVRow } from "../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Rewrite a raw header into a valid identifier. Trims, replaces non-identifier
|
|
9
9
|
* runs with `_`, prefixes a `col_` when it starts with a digit or is empty,
|
|
@@ -132,12 +132,12 @@ export declare class CSVProcessor {
|
|
|
132
132
|
* @param maxRows - Maximum rows to parse (default: 1000)
|
|
133
133
|
* @returns Array of row objects
|
|
134
134
|
*/
|
|
135
|
-
static parseCSVFile(filePath: string, maxRows?: number, timeoutMs?: number): Promise<CSVRow[]>;
|
|
135
|
+
static parseCSVFile(filePath: string, maxRows?: number, timeoutMs?: number, openOptions?: CSVFileOpenOptions): Promise<CSVRow[]>;
|
|
136
136
|
/**
|
|
137
137
|
* File-parse variant that also reports whether the parse timed out, used by
|
|
138
138
|
* `process()` to surface `metadata.parseTimedOut`.
|
|
139
139
|
*/
|
|
140
|
-
static parseCSVFileWithMeta(filePath: string, maxRows?: number, timeoutMs?: number, encoding?: string): Promise<{
|
|
140
|
+
static parseCSVFileWithMeta(filePath: string, maxRows?: number, timeoutMs?: number, encoding?: string, openOptions?: CSVFileOpenOptions): Promise<{
|
|
141
141
|
rows: CSVRow[];
|
|
142
142
|
timedOut: boolean;
|
|
143
143
|
}>;
|
|
@@ -1077,15 +1077,15 @@ export class CSVProcessor {
|
|
|
1077
1077
|
* @param maxRows - Maximum rows to parse (default: 1000)
|
|
1078
1078
|
* @returns Array of row objects
|
|
1079
1079
|
*/
|
|
1080
|
-
static async parseCSVFile(filePath, maxRows = 1000, timeoutMs = DEFAULT_CSV_FILE_PARSE_TIMEOUT_MS) {
|
|
1081
|
-
const { rows } = await this.parseCSVFileWithMeta(filePath, maxRows, timeoutMs);
|
|
1080
|
+
static async parseCSVFile(filePath, maxRows = 1000, timeoutMs = DEFAULT_CSV_FILE_PARSE_TIMEOUT_MS, openOptions) {
|
|
1081
|
+
const { rows } = await this.parseCSVFileWithMeta(filePath, maxRows, timeoutMs, undefined, openOptions);
|
|
1082
1082
|
return rows;
|
|
1083
1083
|
}
|
|
1084
1084
|
/**
|
|
1085
1085
|
* File-parse variant that also reports whether the parse timed out, used by
|
|
1086
1086
|
* `process()` to surface `metadata.parseTimedOut`.
|
|
1087
1087
|
*/
|
|
1088
|
-
static async parseCSVFileWithMeta(filePath, maxRows = 1000, timeoutMs = DEFAULT_CSV_FILE_PARSE_TIMEOUT_MS, encoding) {
|
|
1088
|
+
static async parseCSVFileWithMeta(filePath, maxRows = 1000, timeoutMs = DEFAULT_CSV_FILE_PARSE_TIMEOUT_MS, encoding, openOptions) {
|
|
1089
1089
|
if (typeof filePath !== "string" || filePath.trim().length === 0) {
|
|
1090
1090
|
throw ErrorFactory.csvInvalidInput("CSVProcessor.parseCSVFile: filePath must be a non-empty string");
|
|
1091
1091
|
}
|
|
@@ -1114,10 +1114,58 @@ export class CSVProcessor {
|
|
|
1114
1114
|
catch (error) {
|
|
1115
1115
|
throw ErrorFactory.csvFileAccessFailed(`[CSVProcessor] Failed to open CSV file (${filePath}): ${error instanceof Error ? error.message : String(error)}`, filePath, error instanceof Error ? error : undefined);
|
|
1116
1116
|
}
|
|
1117
|
-
//
|
|
1117
|
+
// The handle is opened through fs.promises because its `flags` accepts a
|
|
1118
|
+
// number; the stream then owns it (autoClose), so destroy() on the error
|
|
1119
|
+
// paths below still releases the descriptor. Three flags do the work:
|
|
1120
|
+
//
|
|
1121
|
+
// - `followSymlinks: false` adds O_NOFOLLOW (0 on Windows, so a no-op
|
|
1122
|
+
// there): the sandboxed caller has already checked the real path, and a
|
|
1123
|
+
// link that appears at the final component afterwards must fail with
|
|
1124
|
+
// ELOOP rather than redirect the read.
|
|
1125
|
+
// - O_NONBLOCK (0 where undefined) so a FIFO with no writer returns from
|
|
1126
|
+
// open() at once instead of parking the call in the threadpool for ever,
|
|
1127
|
+
// beyond the reach of any deadline. It is ignored for regular files.
|
|
1128
|
+
// - O_RDONLY, and then a stat on the opened handle: a CSV is a regular
|
|
1129
|
+
// file, so a FIFO, a device or a directory is refused before the read
|
|
1130
|
+
// phase, which is also what stops a device read from never ending.
|
|
1131
|
+
//
|
|
1132
|
+
// The open itself runs under the same wall-clock budget as the phases
|
|
1133
|
+
// after it (#1199). A handle that arrives after the deadline is closed
|
|
1134
|
+
// when it does, so the timed-out open cannot leak a descriptor.
|
|
1135
|
+
const noFollow = openOptions?.followSymlinks === false
|
|
1136
|
+
? (fs.constants.O_NOFOLLOW ?? 0)
|
|
1137
|
+
: 0;
|
|
1138
|
+
const openFlags = fs.constants.O_RDONLY | noFollow | (fs.constants.O_NONBLOCK ?? 0);
|
|
1139
|
+
const openRegularFile = async () => {
|
|
1140
|
+
const opened = await fs.promises.open(filePath, openFlags);
|
|
1141
|
+
try {
|
|
1142
|
+
if (!(await opened.stat()).isFile()) {
|
|
1143
|
+
throw new Error("not a regular file");
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
catch (error) {
|
|
1147
|
+
await opened.close();
|
|
1148
|
+
throw error;
|
|
1149
|
+
}
|
|
1150
|
+
return opened;
|
|
1151
|
+
};
|
|
1152
|
+
const opening = openRegularFile();
|
|
1153
|
+
let handle;
|
|
1154
|
+
try {
|
|
1155
|
+
handle = await withTimeout(opening, remaining(), "[CSVProcessor] Timed out opening CSV file");
|
|
1156
|
+
}
|
|
1157
|
+
catch (error) {
|
|
1158
|
+
if (error instanceof TimeoutError) {
|
|
1159
|
+
void opening.then((late) => late.close(), () => undefined);
|
|
1160
|
+
logger.warn(`[CSVProcessor] Opening ${filePath} exceeded the ${timeoutMs}ms parse budget; returning an empty partial result`);
|
|
1161
|
+
return { rows: [], timedOut: true };
|
|
1162
|
+
}
|
|
1163
|
+
throw ErrorFactory.csvFileAccessFailed(`[CSVProcessor] Failed to open CSV file (${filePath}): ${error instanceof Error ? error.message : String(error)}`, filePath, error instanceof Error ? error : undefined);
|
|
1164
|
+
}
|
|
1165
|
+
// #368: a SINGLE read stream. We peek its leading bytes to sniff the
|
|
1118
1166
|
// encoding (#362) and detect a metadata line + delimiter (#361), then
|
|
1119
1167
|
// replay those bytes back onto the same stream — no second disk read.
|
|
1120
|
-
const rawSource =
|
|
1168
|
+
const rawSource = handle.createReadStream();
|
|
1121
1169
|
let prepared;
|
|
1122
1170
|
try {
|
|
1123
1171
|
prepared = await withTimeout(this.prepareFileSource(rawSource, encoding, extname(filePath)), remaining(), "[CSVProcessor] Timed out preparing CSV file source");
|
|
@@ -3753,7 +3753,7 @@
|
|
|
3753
3753
|
{"objectID":"d72275c9e7abbf35d2de393371870aaa3be8bbdd91700d6b40b764f021b98ee7","title":"Testing","url":"/docs/features/mcp-enhancements#testing","content":"The MCP enhancements include a comprehensive continuous test suite covering all 14 modules.","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Testing","lvl3":""}},
|
|
3754
3754
|
{"objectID":"b7897e60e94294066b1f6cc7bf6826a9775fceed2d09959e6ddfaaea03c5e278","title":"Environment Variables","url":"/docs/features/mcp-enhancements#environment-variables","content":"| Variable | Description | Default |\n| --------------- | ---------------------------------------- | ---------------------- |\n| TEST_PROVIDER | AI provider to use for integration tests | vertex |\n| TEST_MODEL | Model name override | Provider default model |","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Environment Variables","lvl3":""}},
|
|
3755
3755
|
{"objectID":"41243c9cf6b59f63bf30d887f10b3be94d6ab2926fb59964b17b25292ef90e89","title":"Test Coverage","url":"/docs/features/mcp-enhancements#test-coverage","content":"The suite contains 44 test functions with 172+ assertions organized across 9 parts:\n\n| Part | Module | Tests | Focus |\n| ---- | --------------------------------- | ----- | ----------------------------------------------------- |\n| 1 | Tool Router | 5 | Strategies, registration, affinity, health, events |\n| 2 | Tool Cache | 5 | Set/get, TTL, eviction, invalidation, stats |\n| 3 | Request Batcher | 5 | Batching, flush, drain, server grouping, events |\n| 4 | Tool Annotations | 5 | Inference, safety levels, validation, merge, filter |\n| 5 | Tool Converter | 5 | Bidirectional conversion, batch, function, sanitize |\n| 6 | Tool Integration & Middleware | 5 | Middleware chain, elicitation, timeout, retry, custom |\n| 7 | Enhanced Discovery & Multi-Server | 5 | Search, safety filter, server groups, namespacing |\n| 8 | Server Base, Exposure, Registry | 5 | Custom server, agent/workflow exposure, registry |\n| 9 | Server Capabilities & Elicitation | 4 | Resources, prompts, subscriptions, elicitation types |","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Test Coverage","lvl3":""}},
|
|
3756
|
-
{"objectID":"1f250cb2aa3fc19be6b69bf1883a325f5979f48d35c830dd3b09590df31fdd27","title":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase","content":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server\n\nSince: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05\n\nOverview\n\nNeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.\n\nWhat is MCP?\n\nThe Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities\n\nWhy MCP Matters\n\n| Traditional Approach | MCP Approach | Benefit |\n| --------------------------------------- | --------------------------------- | ----------------------- |\n| Custom tool integrations per provider | One MCP tool works everywhere | 10x faster integration |\n| Manual tool discovery and configuration | Automatic tool registry | Zero-config tool usage |\n| Provider-specific tool formats | Universal JSON-RPC protocol | Provider portability |\n| Limited to SDK-defined tools | any community MCP server + custom | Unlimited extensibility |\n| Static tool set | Dynamic runtime addition | Adapt to changing needs |\n\nNeuroLink's Deep MCP Integration\n\nFactory-First Architecture: MCP tools work internally while users see simple factory methods:\n\nKey Features:\n99% Lighthouse Compatible: Existing MCP tools work with minimal changes\nDynamic Server Management: Add/remove MCP servers programmatically\nRich Context: 15+ fields including session, user, permissions, metadata\nPerformance Optimized: 0-11ms tool execution (target: \\<100ms)\nEnterprise Grade: Comprehensive error handling, audit logging, security\n\nQuick Start\n\nBuilt-in Core Tools (6)\n\nNeuroLink ships with 6 essential tools that require zero configuration:\ngetCurrentTime\n\nPurpose: Real-time clock with timezone support\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nTimestamp generation\nTimezone conversions\nScheduling and reminders\nTime-based calculations\n\nExample:\n\nTool Schema:\nreadFile\n\nPurpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:\nwriteFile\n\nPurpose: Write content to filesystem\n\nAuto-Available: Yes (with HITL approval recommended)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nTool Schema:\nlistDirectory\n\nPurpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:\n\nFile tool roots\n\nreadFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused
|
|
3756
|
+
{"objectID":"1f250cb2aa3fc19be6b69bf1883a325f5979f48d35c830dd3b09590df31fdd27","title":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase","content":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server\n\nSince: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05\n\nOverview\n\nNeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.\n\nWhat is MCP?\n\nThe Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities\n\nWhy MCP Matters\n\n| Traditional Approach | MCP Approach | Benefit |\n| --------------------------------------- | --------------------------------- | ----------------------- |\n| Custom tool integrations per provider | One MCP tool works everywhere | 10x faster integration |\n| Manual tool discovery and configuration | Automatic tool registry | Zero-config tool usage |\n| Provider-specific tool formats | Universal JSON-RPC protocol | Provider portability |\n| Limited to SDK-defined tools | any community MCP server + custom | Unlimited extensibility |\n| Static tool set | Dynamic runtime addition | Adapt to changing needs |\n\nNeuroLink's Deep MCP Integration\n\nFactory-First Architecture: MCP tools work internally while users see simple factory methods:\n\nKey Features:\n99% Lighthouse Compatible: Existing MCP tools work with minimal changes\nDynamic Server Management: Add/remove MCP servers programmatically\nRich Context: 15+ fields including session, user, permissions, metadata\nPerformance Optimized: 0-11ms tool execution (target: \\<100ms)\nEnterprise Grade: Comprehensive error handling, audit logging, security\n\nQuick Start\n\nBuilt-in Core Tools (6)\n\nNeuroLink ships with 6 essential tools that require zero configuration:\ngetCurrentTime\n\nPurpose: Real-time clock with timezone support\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nTimestamp generation\nTimezone conversions\nScheduling and reminders\nTime-based calculations\n\nExample:\n\nTool Schema:\nreadFile\n\nPurpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:\nwriteFile\n\nPurpose: Write content to filesystem\n\nAuto-Available: Yes (with HITL approval recommended)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nTool Schema:\nlistDirectory\n\nPurpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:\n\nFile tool roots\n\nreadFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused. On Linux and macOS, reads, writes and CSV parses open the checked path with O_NOFOLLOW (create mode with O_EXCL), so a link swapped in at the final path component after the check fails instead of redirecting the operation; Windows has no O_NOFOLLOW, so there only create mode carries that last-moment guarantee — the realpath check itself applies on every platform. analyzeCSV also refuses anything that is not a regular file (a FIFO, a device, a directory). listDirectory reports a symlink entry as type: \"symlink\" with the link's own metadata, never its target's. One race is not closed on any platform: a directory component swapped for a symlink between the check and the open is followed, because Node has no openat-style walk and O_NOFOLLOW covers only the final component. That needs an attacker writing into the workspace while the agent runs; i","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"","lvl3":""}},
|
|
3757
3757
|
{"objectID":"d77f56e2563e08643ae18e7fea4540e640fdcdc7720690210a1b9c5c9a651cc2","title":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase#mcp-tools-ecosystem-built-in-tools-any-mcp-server","content":"Since: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server","lvl3":""}},
|
|
3758
3758
|
{"objectID":"a2f242bd22bfb6fb857e7dc60825acc010064d863f53ef5ec236dbb81f1a6a88","title":"Overview","url":"/docs/features/mcp-tools-showcase#overview","content":"NeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"Overview","lvl3":""}},
|
|
3759
3759
|
{"objectID":"6baec5fd689dfd70d9280b9efedecb44456fddef2a81d409f734d582aa0e856b","title":"What is MCP?","url":"/docs/features/mcp-tools-showcase#what-is-mcp","content":"The Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"What is MCP?","lvl3":""}},
|
|
@@ -3764,7 +3764,7 @@
|
|
|
3764
3764
|
{"objectID":"0415eee591ea3bb5e8bb01bdcea857d051be08a17783ada2a3f2f3e8c9abfbac","title":"2. readFile","url":"/docs/features/mcp-tools-showcase#2-readfile","content":"Purpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"2. readFile","lvl3":""}},
|
|
3765
3765
|
{"objectID":"0cb0c9165418d9251e667c3cc9ffab1dc09a25dbb4360b6317d3e4fe85bae458","title":"3. writeFile","url":"/docs/features/mcp-tools-showcase#3-writefile","content":"Purpose: Write content to filesystem\n\nAuto-Available: Yes (with HITL approval recommended)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"3. writeFile","lvl3":""}},
|
|
3766
3766
|
{"objectID":"c27259323275ac78a5c96f275cba4c67336b351f10d6a5990acd9ecb33c015f4","title":"4. listDirectory","url":"/docs/features/mcp-tools-showcase#4-listdirectory","content":"Purpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"4. listDirectory","lvl3":""}},
|
|
3767
|
-
{"objectID":"ea372be739ffab9dc37c0fce82830b21566da728269b630501d0755b353a2491","title":"File tool roots","url":"/docs/features/mcp-tools-showcase#file-tool-roots","content":"readFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused
|
|
3767
|
+
{"objectID":"ea372be739ffab9dc37c0fce82830b21566da728269b630501d0755b353a2491","title":"File tool roots","url":"/docs/features/mcp-tools-showcase#file-tool-roots","content":"readFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused. On Linux and macOS, reads, writes and CSV parses open the checked path with O_NOFOLLOW (create mode with O_EXCL), so a link swapped in at the final path component after the check fails instead of redirecting the operation; Windows has no O_NOFOLLOW, so there only create mode carries that last-moment guarantee — the realpath check itself applies on every platform. analyzeCSV also refuses anything that is not a regular file (a FIFO, a device, a directory). listDirectory reports a symlink entry as type: \"symlink\" with the link's own metadata, never its target's. One race is not closed on any platform: a directory component swapped for a symlink between the check and the open is followed, because Node has no openat-style walk and O_NOFOLLOW covers only the final component. That needs an attacker writing into the workspace while the agent runs; if that is your threat model, isolate the process at the OS level rather than relying on this check alone. Relative paths resolve against the first root; a root of / contains every absolute path. Versions before 12.28.0 compared p","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"File tool roots","lvl3":""}},
|
|
3768
3768
|
{"objectID":"ad698242f08b12159d85a199152ed3aa7035bbde7fe3ba613977b8cf5371fbbd","title":"5. calculateMath","url":"/docs/features/mcp-tools-showcase#5-calculatemath","content":"Purpose: Complex mathematical calculations\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nFinancial calculations\nStatistical analysis\nUnit conversions\nScientific computations\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"5. calculateMath","lvl3":""}},
|
|
3769
3769
|
{"objectID":"143629fbd9246f9f135dab71bb41068eb3b7a1007a086298e48eadd77f4782c2","title":"6. websearchGrounding","url":"/docs/features/mcp-tools-showcase#6-websearchgrounding","content":"Purpose: Web search with result grounding\n\nAuto-Available: Only with Google Vertex AI provider\n\nUse Cases:\nReal-time information lookup\nFact verification\nCurrent events\nResearch augmentation\n\nExample:\n\nTool Schema:\n\nNote: This tool is provider-specific (Google Vertex AI only) and leverages Google's grounding capabilities.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"6. websearchGrounding","lvl3":""}},
|
|
3770
3770
|
{"objectID":"34487d043deb9df5927b3f66758bf17d6e28e070682a3d99a5f16c9628829088","title":"External MCP Servers","url":"/docs/features/mcp-tools-showcase#external-mcp-servers","content":"NeuroLink connects to the growing MCP ecosystem — any MCP-compliant server works; the server catalog lists 58+ across 6 major categories.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"External MCP Servers","lvl3":""}},
|
|
@@ -10772,14 +10772,14 @@
|
|
|
10772
10772
|
{"objectID":"25e1ac265c89596a09bce35c4ba7b8d82ccf92f016708d1f6f4826b290af00ae","title":"Delivery","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#delivery","content":"juspay/neurolink merges one commit per PR, so two PRs:\nRefactor, no behaviour change: extract the comparator into accountRanking.ts and count in-flight on the unlimited lease. Proven by the replay and the existing route tests.\nPolicies: headroom-first, prefer-primary, session affinity, spill, config, telemetry, /status, and the documentation correction below.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Delivery","lvl3":""}},
|
|
10773
10773
|
{"objectID":"06eb4e8ea79a4077f7cb445c1ec17985516046ab28d49d3c87b85ade0155f2c1","title":"Documentation","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#documentation","content":"docs/features/claude-proxy-config-reference.md gains the five keys. The primary-account text and source comments that still say the primary is \"tried first under fill-first\" are corrected: with quota routing the primary is the final tiebreaker unless prefer-primary is set.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Documentation","lvl3":""}},
|
|
10774
10774
|
{"objectID":"1cf022d6f43b961b6fd1c13d8a5677077f9109584a3a5e67d837c4d5f6e613da","title":"Out of scope","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#out-of-scope","content":"Per-model policies, weighted scoring, persisting affinity across restarts, an account reserve, and changes to cooldown classification, in-stream rate-limit handling or state persistence. Those last three are separate designs.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Out of scope","lvl3":""}},
|
|
10775
|
-
{"objectID":"f0109d9239beed7372578f5d0ad41b745b321c526407db0d3bbb32adced24e2e","title":"Codex Outbound Fallback — Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design","content":"Codex Outbound Fallback — Design\n\nStatus: design complete
|
|
10776
|
-
{"objectID":"6034ef59cb5b3d2520fa92f2f181aca534a58aa28338f3411aa9d28d998e487e","title":"Codex Outbound Fallback — Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codex-outbound-fallback-design","content":"Status: design complete
|
|
10775
|
+
{"objectID":"f0109d9239beed7372578f5d0ad41b745b321c526407db0d3bbb32adced24e2e","title":"Codex Outbound Fallback — Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design","content":"Codex Outbound Fallback — Design\n\nStatus: design complete; implementation under way in build order. PR 1 (the IR\ntypes) merged as #1826; PR 2 (the request codec) is #1836; PRs 3 to 8 have not\nstarted, and nothing is wired into a route yet. Produced by 22 parallel agents\n(6 grounding, 8 design, 8 adversarial review) plus 8 resolution passes; every design\nclaim below was checked against the code by a reviewer whose brief was to refute it.\n\nGoal\n\nA native Codex client request that its own account pool cannot serve currently fails to the\nclient. This design gives the Codex engine an outbound fallback chain to the Anthropic OAuth\npool and to Vertex, so the request is served instead — with prompt caching preserved across\nthe hop, tool calls translated faithfully in both directions, and no client-visible protocol\nanomaly.\n\nEvidence\nsrc/lib/server/routes/codexProxyRoutes.ts has no outbound fallback. Its only fallback\n references are a string-default helper (line 138) and code recognising when the Codex engine\n is itself invoked as an inner Anthropic fallback (lines 666, 817, CODEX_FALLBACK_METADATA_KEY\n at 109). On pool exhaustion it returns a terminal error: buildCodexErrorResponse\n (1458-1462), or buildCodexQuotaExhaustedResponse (909-914) when every account is already\n cooling.\nThree directions exist and work: Claude Code → Anthropic pool; Claude/Anthropic → Codex\n (executeClaudeCodexFallback, claudeProxyRoutes.ts:5499, called at 6131, in-process — no\n HTTP hop); Claude/Anthropic → Vertex (vertexAnthropicFallback.ts:611, gated on\n isVertexAnthropicModel, 576).\nThree do not exist: Vertex → Anthropic, native Codex → Anthropic, native Codex →\n Vertex. PR #1782 fixed translation defects in the existing Claude → Vertex direction; it\n did not add a reverse path.\nCodex prompt caching is live but partial. proxy_tokens_cache_read by model:\n gpt-5.6-sol 566,657,536; gpt-6-astra 3,285,888; gpt-5.6-terra 490,752;\n gpt-5.6-luna 5,888. proxy_tokens_cache_creation is 0 for every Codex series, which is\n correct — OpenAI caching is automatic and has no explicit write.\nThe caching asymmetry is the central design constraint. Anthropic caching is explicit:\n up to 4 cache_control breakpoints over a tools → system → messages prefix, write at\n 1.25x base input (5-minute TTL) or 2x (1-hour), read at 0.1x, and each account holds its\n own cache. A Codex request translated to Anthropic arrives with no breakpoints at all,\n so it would be cached not at all unless the translator inserts them deliberately.\nSince Claude-on-Vertex speaks the Anthropic Messages wire format, one Codex→Anthropic\n translator covers both targets. There is no smaller Vertex-only variant of this work.\n\nBuild order\n\nDependency-ordered; each step is one reviewable PR under the one-commit-per-PR policy. Default\noff at every step, so behaviour is byte-for-byte unchanged until the final enable.\n\n| # | PR | Depends on | Gate |\n| --- | ------------------------------------------------------------------- | ---------- | -------------------------------------------- |\n| 1 | IR types + codec contract (src/lib/types/proxyIR.ts) | — | typecheck; exhaustiveness is a compile error |\n| 2 | Request codec Codex → Anthropic (codexOutboundFallback.ts) | 1 | offline shape suite |\n| 3 | Response/stream codec Anthropic → Codex | 1 | offline event-order suite |\n| 4 | Tool fidelity + id correlation | 2, 3 | offline round-trip suite |\n| 5 | Cache breakpoints + prefix byte-stability (codexOutboundCache.ts) | 2 | byte-stability assertion across two turns |\n| 6 | Trigger policy, commitment rule, loop prevention, accounting | 2-4 | totality + commitment suites |\n| 7 | Config keys, kill switch, metrics | 6 | config validation suite |\n| 8 | Enable + live model matrix | all | live pass criteria |\n\nOpen questions gating the build\n\nEvery one needs the same thing: real captured native Codex traffic. The repo has 4 synthetic\nfixtures, one real single-turn capture (~/.neurolink/reference/codex-cli-wire-sample.json,\ncaptured 2026-09-21), a real usage-frame capture (test/fixtures/codex-response-usage.sse,\ncaptured 2026-08-21), and one real controlled bisection experiment against the actual\ncodex_exec/0.155.1 binary (scripts/codex-replay-listener.ts, test/fixtures/sse-bisection-findings.md,\nrun 2026-09-27). Two questions are now settled; the rest are listed here because they can still\ninvalidate a whole section, so they should be settled before the PRs that depend on them are\nwritten.\n\n| Question ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"","lvl3":""}},
|
|
10776
|
+
{"objectID":"6034ef59cb5b3d2520fa92f2f181aca534a58aa28338f3411aa9d28d998e487e","title":"Codex Outbound Fallback — Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codex-outbound-fallback-design","content":"Status: design complete; implementation under way in build order. PR 1 (the IR\ntypes) merged as #1826; PR 2 (the request codec) is #1836; PRs 3 to 8 have not\nstarted, and nothing is wired into a route yet. Produced by 22 parallel agents\n(6 grounding, 8 design, 8 adversarial review) plus 8 resolution passes; every design\nclaim below was checked against the code by a reviewer whose brief was to refute it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Codex Outbound Fallback — Design","lvl3":""}},
|
|
10777
10777
|
{"objectID":"580c5a06163d1e603bb34f5f3b51c78e4efa36e12426cf22b63706680af0ea56","title":"Goal","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#goal","content":"A native Codex client request that its own account pool cannot serve currently fails to the\nclient. This design gives the Codex engine an outbound fallback chain to the Anthropic OAuth\npool and to Vertex, so the request is served instead — with prompt caching preserved across\nthe hop, tool calls translated faithfully in both directions, and no client-visible protocol\nanomaly.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Goal","lvl3":""}},
|
|
10778
10778
|
{"objectID":"ed180fb4ca61ad0027c4359503ac6ea54b391281020d32b2a9b498cd6c83abeb","title":"Evidence","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#evidence","content":"src/lib/server/routes/codexProxyRoutes.ts has no outbound fallback. Its only fallback\n references are a string-default helper (line 138) and code recognising when the Codex engine\n is itself invoked as an inner Anthropic fallback (lines 666, 817, CODEX_FALLBACK_METADATA_KEY\n at 109). On pool exhaustion it returns a terminal error: buildCodexErrorResponse\n (1458-1462), or buildCodexQuotaExhaustedResponse (909-914) when every account is already\n cooling.\nThree directions exist and work: Claude Code → Anthropic pool; Claude/Anthropic → Codex\n (executeClaudeCodexFallback, claudeProxyRoutes.ts:5499, called at 6131, in-process — no\n HTTP hop); Claude/Anthropic → Vertex (vertexAnthropicFallback.ts:611, gated on\n isVertexAnthropicModel, 576).\nThree do not exist: Vertex → Anthropic, native Codex → Anthropic, native Codex →\n Vertex. PR #1782 fixed translation defects in the existing Claude → Vertex direction; it\n did not add a reverse path.\nCodex prompt caching is live but partial. proxy_tokens_cache_read by model:\n gpt-5.6-sol 566,657,536; gpt-6-astra 3,285,888; gpt-5.6-terra 490,752;\n gpt-5.6-luna 5,888. proxy_tokens_cache_creation is 0 for every Codex series, which is\n correct — OpenAI caching is automatic and has no explicit write.\nThe caching asymmetry is the central design constraint. Anthropic caching is explicit:\n up to 4 cache_control breakpoints over a tools → system → messages prefix, write at\n 1.25x base input (5-minute TTL) or 2x (1-hour), read at 0.1x, and each account holds its\n own cache. A Codex request translated to Anthropic arrives with no breakpoints at all,\n so it would be cached not at all unless the translator inserts them deliberately.\nSince Claude-on-Vertex speaks the Anthropic Messages wire format, one Codex→Anthropic\n translator covers both targets. There is no smaller Vertex-only variant of this work.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Evidence","lvl3":""}},
|
|
10779
10779
|
{"objectID":"a5aa19ce68fa1175c4bade50ae303cc0a954bf1128588e294af993c049e2f466","title":"Build order","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#build-order","content":"Dependency-ordered; each step is one reviewable PR under the one-commit-per-PR policy. Default\noff at every step, so behaviour is byte-for-byte unchanged until the final enable.\n\n| # | PR | Depends on | Gate |\n| --- | ------------------------------------------------------------------- | ---------- | -------------------------------------------- |\n| 1 | IR types + codec contract (src/lib/types/proxyIR.ts) | — | typecheck; exhaustiveness is a compile error |\n| 2 | Request codec Codex → Anthropic (codexOutboundFallback.ts) | 1 | offline shape suite |\n| 3 | Response/stream codec Anthropic → Codex | 1 | offline event-order suite |\n| 4 | Tool fidelity + id correlation | 2, 3 | offline round-trip suite |\n| 5 | Cache breakpoints + prefix byte-stability (codexOutboundCache.ts) | 2 | byte-stability assertion across two turns |\n| 6 | Trigger policy, commitment rule, loop prevention, accounting | 2-4 | totality + commitment suites |\n| 7 | Config keys, kill switch, metrics | 6 | config validation suite |\n| 8 | Enable + live model matrix | all | live pass criteria |","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Build order","lvl3":""}},
|
|
10780
10780
|
{"objectID":"db4fcb5c145b85c8e756be096fdda4d88c5f6fc576ec62653a8545735ff1a653","title":"Open questions gating the build","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#open-questions-gating-the-build","content":"Every one needs the same thing: real captured native Codex traffic. The repo has 4 synthetic\nfixtures, one real single-turn capture (~/.neurolink/reference/codex-cli-wire-sample.json,\ncaptured 2026-09-21), a real usage-frame capture (test/fixtures/codex-response-usage.sse,\ncaptured 2026-08-21), and one real controlled bisection experiment against the actual\ncodex_exec/0.155.1 binary (scripts/codex-replay-listener.ts, test/fixtures/sse-bisection-findings.md,\nrun 2026-09-27). Two questions are now settled; the rest are listed here because they can still\ninvalidate a whole section, so they should be settled before the PRs that depend on them are\nwritten.\n\n| Question | Blocks | Settled by |\n| ---------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Does the real Codex CLI accept a call_id it did not mint (a toolu_-shaped id)? | PR 4 | SETTLED (2026-09-27) — yes, verbatim. codex-replay-listener.ts --script tool-call against real codex_exec/0.155.1: the CLI's follow-up function_call_output carried call_id: \"toolu_replay0000000000000000\" unmodified (own id field is CLI-minted fco_-","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Open questions gating the build","lvl3":""}},
|
|
10781
10781
|
{"objectID":"a85c34c0265b0c27d696611075427124ef72062ef3e1248bf75ddc2f859229d0","title":"Contents","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#contents","content":"Translation layer: canonical IR and codec contract\nRequest translation: Codex Responses → Anthropic Messages\nResponse translation: Anthropic → Codex wire format\nTool-call fidelity in both directions\nPreserving prompt caching across the hop\nTrigger policy, commitment safety, loop prevention, accounting\nConfiguration surface and staged rollout\nValidation plan","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Contents","lvl3":""}},
|
|
10782
|
-
{"objectID":"62546125e30c54bebd2104e396943d1fb60478f7d22873e75792c81c408d2791","title":"Consolidated unresolved items","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#consolidated-unresolved-items","content":"ir-and-types — whether native Codex ever sends top-level reasoning/tools on a genuine inbound request — the
|
|
10782
|
+
{"objectID":"62546125e30c54bebd2104e396943d1fb60478f7d22873e75792c81c408d2791","title":"Consolidated unresolved items","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#consolidated-unresolved-items","content":"ir-and-types — whether native Codex ever sends top-level reasoning/tools on a genuine inbound request — settled for reasoning by the 2026-09-21 capture, which is exactly the check this item asked for (see the gating table above): it is sent with a non-default effort ({\"effort\":\"xhigh\",\"context\":\"all_turns\"}). That captured request has no top-level tools field, only the nested additional_tools item, but one first-turn capture cannot show that no request ever carries one. Still open from the same gating row: whether it ever sends stream:false.\nir-and-types — whether Anthropic's live API ever rejects consecutive same-role messages in some edge case — the one check that would settle it is a probe request against the real API with two consecutive user messages.\nir-and-types — the storage/lifetime contract for a resumed session's id map spanning multiple proxy requests — the one check that would settle it is reading how originSessionId/originThreadId are persisted by the session-affinity\nir-and-types — above.\nrequest-translation — in §10. It converts an unknown into a loud, caller-visible failure instead of a silent one, which is what the \"nothing may break silently\" requirement demands even without live traffic.\nrequest-translation — whether additional_tools/developer items can appear anywhere other than before the first user item in real traffic — the one check that would settle it: capture one real Codex CLI multi-turn session with a mid-conv\nrequest-translation — whether a resumed-session request's input is genuinely full-history or incremental — the one check that would settle it: capture one real resumed-session Codex Responses request (the referenced ~/.neurolink/reference/\n- **request-translation** — whether toolchoice or reasoning ever appear on genuine inbound requests at all (absent from all 4 fixtures) — **settled**: the 2026-09-21 capture carries both, toolchoice: \"auto\" and reasoning as quoted in the first item of this list.\n- **request-translation** — wheth","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Consolidated unresolved items","lvl3":""}},
|
|
10783
10783
|
{"objectID":"b890fc666ae87c04302cb9122b852c6e394f3a6eb3ad2c2a3b90aed60a49e057","title":"Decision (kept)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#decision-kept","content":"Single canonical IR, not ClaudeRequest-as-hub, not pairwise codecs. Verified: openaiFormat.ts/geminiFormat.ts already use ClaudeRequest as an implicit hub only because it is also the literal Anthropic wire type; codexFallback.ts already needs a role cast ((message.role as string) !== \"system\", line 154) to special-case Claude Code's inline-system convention inside a converter meant to be neutral. A new file, src/lib/types/proxyIR.ts, holds a real wire-neutral IR. ClaudeRequest/ClaudeResponse (proxy.ts:154, :187) stay untouched — the Anthropic hot path (claudeProxyRoutes.ts) never changes.\n\nVertex needs no separate codec. Confirmed: executeVertexAnthropicFallback (vertexAnthropicFallback.ts:605-665) forwards the upstream body/stream untouched with a code comment that it is \"already Anthropic-shaped\"; buildVertexAnthropicPayload (line 399) only strips UNSUPPORTED_FIELDS = [\"model\", \"context_management\"] (line 42). Vertex reuses anthropicMessagesIRCodec.buildRequest's output as-is.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Decision (kept)","lvl3":""}},
|
|
10784
10784
|
{"objectID":"a1d8a0c721ce132a2ececad931143e90dddbb50e47f04652ec692c3c3e12a040","title":"codexFallback.ts: left unrefactored this PR","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codexfallbackts-left-unrefactored-this-pr","content":"It already implements, in the new vocabulary, the codex-responses request builder (convertClaudeRequestToCodex, line 407) and response parser (parseCodexFallbackSSE line 592, createCodexFallbackStream line 719) — never a request parser or response renderer, since Codex there is a fallback target, not a served client. Deferred to a named follow-up PR (one-commit-per-PR; mixing a mechanical port with new functional work is out of scope). Coexistence cost: convertClaudeRequestToCodex and the new anthropicMessagesIRCodec/codexNativeRequestCodec independently implement the same tool_choice bijection (any↔required, tool↔function) and the same reasoning-effort concept in reverse; a fix to one will not propagate until the follow-up ports codexFallback.ts onto the same 4 capabilities, verified byte-for-byte against test/continuous-test-suite-codex.ts.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"codexFallback.ts: left unrefactored this PR","lvl3":""}},
|
|
10785
10785
|
{"objectID":"6a41248b50b7d11345c624537be172f4317d8a583d937c841b1f804ccfe4397f","title":"Grounding notes from the fixtures (all 4 read in full)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#grounding-notes-from-the-fixtures-all-4-read-in-full","content":"test/fixtures/codex-request-{exec-mode,interactive-mode,resumed-session,tool-result-turn}.json. Each fixture's body.input[0] is one {type:\"additional_tools\", role:\"developer\", tools:{functions:[...], collaboration:[...]}} item. Correction to the original design's blanket claim (\"no Anthropic tool shape maps to collaboration, genuinely unmappable\"): the collaboration bucket is not grammar-only. In all 4 fixtures it holds exactly two tools — exec (type:\"custom\", has a grammar string, no parameters) and request_review (no type tag, has a plain JSON-Schema parameters object, no grammar — structurally identical to a functions entry, just filed under the wrong bucket on the wire). Mappability is a per-tool fact keyed on presence of grammar, never inferable from which array a tool sits in.\n\nfunction_call.arguments is not guaranteed JSON: codex-request-tool-result-turn.json's function_call (call_id:\"call_synthetic_0001\", name:\"exec\") has arguments: \"ls -la\" — a bare string, since exec is grammar-typed. codexFallback.ts's parseFunctionArguments (line 466) throws today on exactly this input (JSON.parse(\"ls -la\") fails, hits catch, throws) — confirmed by reading the function. A tool-call IR part therefore needs argumentsRaw: string as the source of truth always, argumentsJson only when it happens to parse as an object.\n\nAll 4 fixtures: additional_tools is the single, first input item; 4 contiguous developer-role message items follow (indices 1-4); then 2 consecutive user-role message items (confirmed non-hypothetical — tool-result-turn's second user item carries an <environment_context> block, not a second real user turn); tool-result-turn additionally has one function_call/function_call_output pair. No fixture shows an assistant-role message item, even resumed-session. Top-level body keys across all 4: {model, stream, store, input} plus {session_id, thread_id} only on resumed-session — never top-level tools or reasoning.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Grounding notes from the fixtures (all 4 read in full)","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.36.
|
|
3
|
+
"version": "12.36.1",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|