@nram-ai/setup-agents 0.0.1-pre.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/LICENSE +19 -0
- package/README.md +109 -0
- package/dist/helpers/configure/amp.d.ts +9 -0
- package/dist/helpers/configure/amp.js +49 -0
- package/dist/helpers/configure/amp.js.map +1 -0
- package/dist/helpers/configure/antigravity.d.ts +12 -0
- package/dist/helpers/configure/antigravity.js +74 -0
- package/dist/helpers/configure/antigravity.js.map +1 -0
- package/dist/helpers/configure/claude_code.d.ts +9 -0
- package/dist/helpers/configure/claude_code.js +119 -0
- package/dist/helpers/configure/claude_code.js.map +1 -0
- package/dist/helpers/configure/codex.d.ts +19 -0
- package/dist/helpers/configure/codex.js +76 -0
- package/dist/helpers/configure/codex.js.map +1 -0
- package/dist/helpers/configure/copilot.d.ts +11 -0
- package/dist/helpers/configure/copilot.js +64 -0
- package/dist/helpers/configure/copilot.js.map +1 -0
- package/dist/helpers/configure/cursor.d.ts +26 -0
- package/dist/helpers/configure/cursor.js +90 -0
- package/dist/helpers/configure/cursor.js.map +1 -0
- package/dist/helpers/configure/droid.d.ts +18 -0
- package/dist/helpers/configure/droid.js +70 -0
- package/dist/helpers/configure/droid.js.map +1 -0
- package/dist/helpers/configure/grok.d.ts +25 -0
- package/dist/helpers/configure/grok.js +93 -0
- package/dist/helpers/configure/grok.js.map +1 -0
- package/dist/helpers/configure/hermes.d.ts +22 -0
- package/dist/helpers/configure/hermes.js +107 -0
- package/dist/helpers/configure/hermes.js.map +1 -0
- package/dist/helpers/configure/junie.d.ts +10 -0
- package/dist/helpers/configure/junie.js +52 -0
- package/dist/helpers/configure/junie.js.map +1 -0
- package/dist/helpers/configure/kilo.d.ts +19 -0
- package/dist/helpers/configure/kilo.js +110 -0
- package/dist/helpers/configure/kilo.js.map +1 -0
- package/dist/helpers/configure/kimi.d.ts +10 -0
- package/dist/helpers/configure/kimi.js +75 -0
- package/dist/helpers/configure/kimi.js.map +1 -0
- package/dist/helpers/configure/kiro.d.ts +25 -0
- package/dist/helpers/configure/kiro.js +77 -0
- package/dist/helpers/configure/kiro.js.map +1 -0
- package/dist/helpers/configure/openclaw.d.ts +10 -0
- package/dist/helpers/configure/openclaw.js +72 -0
- package/dist/helpers/configure/openclaw.js.map +1 -0
- package/dist/helpers/configure/opencode.d.ts +18 -0
- package/dist/helpers/configure/opencode.js +72 -0
- package/dist/helpers/configure/opencode.js.map +1 -0
- package/dist/helpers/configure/pi.d.ts +10 -0
- package/dist/helpers/configure/pi.js +60 -0
- package/dist/helpers/configure/pi.js.map +1 -0
- package/dist/helpers/configure/trae.d.ts +11 -0
- package/dist/helpers/configure/trae.js +63 -0
- package/dist/helpers/configure/trae.js.map +1 -0
- package/dist/helpers/configure/vibe.d.ts +24 -0
- package/dist/helpers/configure/vibe.js +106 -0
- package/dist/helpers/configure/vibe.js.map +1 -0
- package/dist/helpers/configure/vscode.d.ts +18 -0
- package/dist/helpers/configure/vscode.js +81 -0
- package/dist/helpers/configure/vscode.js.map +1 -0
- package/dist/helpers/harnesses.d.ts +8 -0
- package/dist/helpers/harnesses.js +161 -0
- package/dist/helpers/harnesses.js.map +1 -0
- package/dist/helpers/instructions.d.ts +63 -0
- package/dist/helpers/instructions.js +175 -0
- package/dist/helpers/instructions.js.map +1 -0
- package/dist/helpers/paths.d.ts +130 -0
- package/dist/helpers/paths.js +211 -0
- package/dist/helpers/paths.js.map +1 -0
- package/dist/helpers/upsert.d.ts +197 -0
- package/dist/helpers/upsert.js +428 -0
- package/dist/helpers/upsert.js.map +1 -0
- package/dist/helpers/url.d.ts +15 -0
- package/dist/helpers/url.js +51 -0
- package/dist/helpers/url.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/setup.d.ts +17 -0
- package/dist/setup.js +296 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ActionResult } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Identifies our SessionStart hook entry among the user's hooks, across every
|
|
4
|
+
* historical command format
|
|
5
|
+
*/
|
|
6
|
+
export declare const SESSION_START_MARKER = "@nram-ai/setup-agents";
|
|
7
|
+
/**
|
|
8
|
+
* The shell command injected as a SessionStart hook; its stdout (the agent
|
|
9
|
+
* instructions, fetched from the configured nram server) is added to the
|
|
10
|
+
* model's context by the harness
|
|
11
|
+
*
|
|
12
|
+
* @param base_url the normalized nram base URL the hook fetches from
|
|
13
|
+
*/
|
|
14
|
+
export declare const session_start_command: (base_url: string) => string;
|
|
15
|
+
export type MarkerStyle = 'hash' | 'html';
|
|
16
|
+
/**
|
|
17
|
+
* Returns whether the text already carries our marker-fenced block
|
|
18
|
+
*
|
|
19
|
+
* @param text the file content
|
|
20
|
+
* @param style the marker comment style
|
|
21
|
+
*/
|
|
22
|
+
export declare const has_marker_block: (text: string, style: MarkerStyle) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Reads a text file, returning an empty string when the file does not exist
|
|
25
|
+
*
|
|
26
|
+
* @param path the file to read
|
|
27
|
+
*/
|
|
28
|
+
export declare const read_text: (path: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Writes a text file, creating parent directories as needed
|
|
31
|
+
*
|
|
32
|
+
* @param path the file to write
|
|
33
|
+
* @param text the file content
|
|
34
|
+
*/
|
|
35
|
+
export declare const write_text: (path: string, text: string) => void;
|
|
36
|
+
export type JsonReadResult = {
|
|
37
|
+
ok: true;
|
|
38
|
+
value: any;
|
|
39
|
+
existed: boolean;
|
|
40
|
+
} | {
|
|
41
|
+
ok: false;
|
|
42
|
+
error: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Reads and parses a JSON file. A missing file is NOT an error (it yields
|
|
46
|
+
* `value: undefined`); an existing file that cannot be parsed is, and the
|
|
47
|
+
* caller MUST leave that file untouched and fall back to a manual snippet
|
|
48
|
+
*
|
|
49
|
+
* @param path the file to read
|
|
50
|
+
*/
|
|
51
|
+
export declare const read_json: (path: string) => JsonReadResult;
|
|
52
|
+
/**
|
|
53
|
+
* Serializes a value as 2-space-indented JSON (with a trailing newline)
|
|
54
|
+
* and writes it, creating parent directories as needed
|
|
55
|
+
*
|
|
56
|
+
* @param path the file to write
|
|
57
|
+
* @param value the value to serialize
|
|
58
|
+
*/
|
|
59
|
+
export declare const write_json: (path: string, value: unknown) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Inserts a marker-fenced block into a body of text, or replaces the existing
|
|
62
|
+
* fenced block in place. Content outside the markers is never modified, and
|
|
63
|
+
* re-applying the same block is byte-stable
|
|
64
|
+
*
|
|
65
|
+
* @param text the current file content (may be empty)
|
|
66
|
+
* @param block the block content to place between the markers
|
|
67
|
+
* @param style the marker comment style for the target file type
|
|
68
|
+
* @param position where to place a NEW block; ignored when replacing
|
|
69
|
+
* @returns the updated text and whether anything changed
|
|
70
|
+
*/
|
|
71
|
+
export declare const upsert_marker_block: (text: string, block: string, style: MarkerStyle, position?: "prepend" | "append") => {
|
|
72
|
+
text: string;
|
|
73
|
+
changed: boolean;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Upserts our SessionStart hook entry into a hooks-style configuration object
|
|
77
|
+
* (the SessionStart shape is identical between Claude Code's settings.json
|
|
78
|
+
* and Codex's hooks.json). An existing entry referencing `@nram-ai/setup-agents` is
|
|
79
|
+
* replaced in place when its command differs (a different server URL, or the
|
|
80
|
+
* URL-less command written by older package versions), left alone when it
|
|
81
|
+
* already matches, and appended when absent. Unrelated hooks are never touched
|
|
82
|
+
*
|
|
83
|
+
* @param config the parsed configuration object (mutated in place)
|
|
84
|
+
* @param base_url the normalized nram base URL embedded in the hook command
|
|
85
|
+
* @returns the configuration and whether it changed
|
|
86
|
+
*/
|
|
87
|
+
export declare const upsert_session_start_hook: (config: any, base_url: string) => {
|
|
88
|
+
config: any;
|
|
89
|
+
changed: boolean;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Upserts our SessionStart hook into a hooks-style JSON file (Claude Code's
|
|
93
|
+
* settings.json and Codex's hooks.json share the shape) and reports the
|
|
94
|
+
* outcome; an unparseable file is left untouched
|
|
95
|
+
*
|
|
96
|
+
* @param path the hooks file to update
|
|
97
|
+
* @param base_url the normalized nram base URL embedded in the hook command
|
|
98
|
+
*/
|
|
99
|
+
export declare const upsert_hooks_json: (path: string, base_url: string) => ActionResult;
|
|
100
|
+
export type JsonUpsertResult = {
|
|
101
|
+
kind: 'skipped' | 'written' | 'updated';
|
|
102
|
+
} | {
|
|
103
|
+
kind: 'manual';
|
|
104
|
+
error: string;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Merges a value into a JSON file at the given key path (creating intermediate
|
|
108
|
+
* objects as needed), writing only when the value differs. An unparseable
|
|
109
|
+
* existing file is left untouched and reported for manual handling
|
|
110
|
+
*
|
|
111
|
+
* @param path the JSON file to update
|
|
112
|
+
* @param key_path the nested key path, e.g. ['mcpServers', 'nram']
|
|
113
|
+
* @param entry the value to place at the key path
|
|
114
|
+
* @param fallback the configuration to start from when the file is missing
|
|
115
|
+
*/
|
|
116
|
+
export declare const upsert_json_path: (path: string, key_path: string[], entry: unknown, fallback?: any) => JsonUpsertResult;
|
|
117
|
+
/**
|
|
118
|
+
* The manual follow-up shown whenever a configuration references the
|
|
119
|
+
* NRAM_API_KEY environment variable instead of embedding the key
|
|
120
|
+
*/
|
|
121
|
+
export declare const api_key_manual_result: () => ActionResult;
|
|
122
|
+
/**
|
|
123
|
+
* The manual follow-up shown when a tool's configuration has no verified
|
|
124
|
+
* environment-variable substitution, so the Authorization header must be
|
|
125
|
+
* added by hand rather than risking a literal key on disk
|
|
126
|
+
*
|
|
127
|
+
* @param path the configuration file the header belongs in
|
|
128
|
+
*/
|
|
129
|
+
export declare const api_key_header_manual_result: (path: string) => ActionResult;
|
|
130
|
+
export interface McpJsonOptions {
|
|
131
|
+
/** Starting configuration when the file is missing */
|
|
132
|
+
fallback?: any;
|
|
133
|
+
/** Replaces the parse-error reason in the manual detail (e.g. a JSONC caveat) */
|
|
134
|
+
parse_hint?: string;
|
|
135
|
+
/** Appended to the written/updated detail */
|
|
136
|
+
note?: string;
|
|
137
|
+
/** The key path addresses an array merged by entry name instead of a keyed object */
|
|
138
|
+
array?: boolean;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Merges an MCP server entry into a JSON configuration and maps the outcome
|
|
142
|
+
* onto the standard `MCP registration` ActionResult, including the manual
|
|
143
|
+
* snippet for unparseable files; this is the shared report flow every
|
|
144
|
+
* JSON-configured harness uses
|
|
145
|
+
*
|
|
146
|
+
* @param path the JSON file to update
|
|
147
|
+
* @param key_path the nested key path (the leaf is the entry key, or the array itself with `array`)
|
|
148
|
+
* @param entry the entry value
|
|
149
|
+
* @param options report and merge options
|
|
150
|
+
*/
|
|
151
|
+
export declare const mcp_json_result: (path: string, key_path: string[], entry: any, options?: McpJsonOptions) => ActionResult;
|
|
152
|
+
/**
|
|
153
|
+
* Upserts a marker-fenced configuration block into a structured text file
|
|
154
|
+
* (TOML, YAML): parse the existing content (manual on failure), let the
|
|
155
|
+
* caller veto via a conflict check, apply the marker upsert, validate that
|
|
156
|
+
* the result re-parses with the expected entry, and only then write. The
|
|
157
|
+
* file is never re-serialized as a whole, so user comments survive
|
|
158
|
+
*
|
|
159
|
+
* @param path the configuration file
|
|
160
|
+
* @param block the marker-fenced block content
|
|
161
|
+
* @param parse the format parser (throws on invalid input)
|
|
162
|
+
* @param format the format name for messaging
|
|
163
|
+
* @param conflict returns a result to report instead of editing (e.g. the key exists outside our markers)
|
|
164
|
+
* @param valid post-edit check that the entry is present in the re-parsed file
|
|
165
|
+
*/
|
|
166
|
+
export declare const upsert_block_with_validation: (path: string, block: string, parse: (text: string) => any, format: string, conflict: (parsed: any, text: string) => ActionResult | undefined, valid: (parsed: any) => boolean) => ActionResult;
|
|
167
|
+
/**
|
|
168
|
+
* Merges an entry into an array-shaped JSON configuration (e.g. Factory's
|
|
169
|
+
* `servers: []`), keyed by a name field: replace in place when an element
|
|
170
|
+
* with the same name exists and differs, append when absent, skip when
|
|
171
|
+
* identical. An unparseable existing file is left untouched
|
|
172
|
+
*
|
|
173
|
+
* @param path the JSON file to update
|
|
174
|
+
* @param array_key_path the nested key path holding the array
|
|
175
|
+
* @param entry the element to place (must carry the name key)
|
|
176
|
+
* @param name_key the field that identifies elements (default `name`)
|
|
177
|
+
*/
|
|
178
|
+
export declare const upsert_json_array_entry: (path: string, array_key_path: string[], entry: any, name_key?: string) => JsonUpsertResult;
|
|
179
|
+
/**
|
|
180
|
+
* Writes a file the tool owns outright (rule files, steering docs,
|
|
181
|
+
* instruction files): compare, write when different, and report
|
|
182
|
+
*
|
|
183
|
+
* @param path the file to write
|
|
184
|
+
* @param content the full file content
|
|
185
|
+
* @param action the action name for the result
|
|
186
|
+
*/
|
|
187
|
+
export declare const upsert_own_file: (path: string, content: string, action: string) => ActionResult;
|
|
188
|
+
/**
|
|
189
|
+
* Upserts the marker-fenced agent-instructions block at the top of an
|
|
190
|
+
* AGENTS.md-style file and reports the outcome; tools sharing the same file
|
|
191
|
+
* (the project-root AGENTS.md) dedupe automatically because the second
|
|
192
|
+
* upsert finds the block unchanged
|
|
193
|
+
*
|
|
194
|
+
* @param path the markdown file to update
|
|
195
|
+
* @param instructions the agent instructions text to place in the block
|
|
196
|
+
*/
|
|
197
|
+
export declare const agents_md_result: (path: string, instructions: string) => ActionResult;
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2026, Brandon Lehmann <brandonlehmann@gmail.com>
|
|
3
|
+
//
|
|
4
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
// in the Software without restriction, including without limitation the rights
|
|
7
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
// furnished to do so, subject to the following conditions:
|
|
10
|
+
//
|
|
11
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
// copies or substantial portions of the Software.
|
|
13
|
+
//
|
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
// SOFTWARE.
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.agents_md_result = exports.upsert_own_file = exports.upsert_json_array_entry = exports.upsert_block_with_validation = exports.mcp_json_result = exports.api_key_header_manual_result = exports.api_key_manual_result = exports.upsert_json_path = exports.upsert_hooks_json = exports.upsert_session_start_hook = exports.upsert_marker_block = exports.write_json = exports.read_json = exports.write_text = exports.read_text = exports.has_marker_block = exports.session_start_command = exports.SESSION_START_MARKER = void 0;
|
|
23
|
+
const fs_1 = require("fs");
|
|
24
|
+
const path_1 = require("path");
|
|
25
|
+
/**
|
|
26
|
+
* Identifies our SessionStart hook entry among the user's hooks, across every
|
|
27
|
+
* historical command format
|
|
28
|
+
*/
|
|
29
|
+
exports.SESSION_START_MARKER = '@nram-ai/setup-agents';
|
|
30
|
+
/**
|
|
31
|
+
* The shell command injected as a SessionStart hook; its stdout (the agent
|
|
32
|
+
* instructions, fetched from the configured nram server) is added to the
|
|
33
|
+
* model's context by the harness
|
|
34
|
+
*
|
|
35
|
+
* @param base_url the normalized nram base URL the hook fetches from
|
|
36
|
+
*/
|
|
37
|
+
const session_start_command = (base_url) => `npx -y @nram-ai/setup-agents --session-start --url ${base_url}`;
|
|
38
|
+
exports.session_start_command = session_start_command;
|
|
39
|
+
const MARKERS = {
|
|
40
|
+
hash: ['# >>> nram setup >>>', '# <<< nram setup <<<'],
|
|
41
|
+
html: ['<!-- nram:start -->', '<!-- nram:end -->']
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Returns whether the text already carries our marker-fenced block
|
|
45
|
+
*
|
|
46
|
+
* @param text the file content
|
|
47
|
+
* @param style the marker comment style
|
|
48
|
+
*/
|
|
49
|
+
const has_marker_block = (text, style) => text.includes(MARKERS[style][0]);
|
|
50
|
+
exports.has_marker_block = has_marker_block;
|
|
51
|
+
/**
|
|
52
|
+
* Reads a text file, returning an empty string when the file does not exist
|
|
53
|
+
*
|
|
54
|
+
* @param path the file to read
|
|
55
|
+
*/
|
|
56
|
+
const read_text = (path) => (0, fs_1.existsSync)(path) ? (0, fs_1.readFileSync)(path, 'utf8') : '';
|
|
57
|
+
exports.read_text = read_text;
|
|
58
|
+
/**
|
|
59
|
+
* Writes a text file, creating parent directories as needed
|
|
60
|
+
*
|
|
61
|
+
* @param path the file to write
|
|
62
|
+
* @param text the file content
|
|
63
|
+
*/
|
|
64
|
+
const write_text = (path, text) => {
|
|
65
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(path), { recursive: true });
|
|
66
|
+
(0, fs_1.writeFileSync)(path, text);
|
|
67
|
+
};
|
|
68
|
+
exports.write_text = write_text;
|
|
69
|
+
/**
|
|
70
|
+
* Reads and parses a JSON file. A missing file is NOT an error (it yields
|
|
71
|
+
* `value: undefined`); an existing file that cannot be parsed is, and the
|
|
72
|
+
* caller MUST leave that file untouched and fall back to a manual snippet
|
|
73
|
+
*
|
|
74
|
+
* @param path the file to read
|
|
75
|
+
*/
|
|
76
|
+
const read_json = (path) => {
|
|
77
|
+
if (!(0, fs_1.existsSync)(path)) {
|
|
78
|
+
return { ok: true, value: undefined, existed: false };
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
return { ok: true, value: JSON.parse((0, fs_1.readFileSync)(path, 'utf8')), existed: true };
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return { ok: false, error: error.toString() };
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
exports.read_json = read_json;
|
|
88
|
+
/**
|
|
89
|
+
* Serializes a value as 2-space-indented JSON (with a trailing newline)
|
|
90
|
+
* and writes it, creating parent directories as needed
|
|
91
|
+
*
|
|
92
|
+
* @param path the file to write
|
|
93
|
+
* @param value the value to serialize
|
|
94
|
+
*/
|
|
95
|
+
const write_json = (path, value) => (0, exports.write_text)(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
96
|
+
exports.write_json = write_json;
|
|
97
|
+
/**
|
|
98
|
+
* Inserts a marker-fenced block into a body of text, or replaces the existing
|
|
99
|
+
* fenced block in place. Content outside the markers is never modified, and
|
|
100
|
+
* re-applying the same block is byte-stable
|
|
101
|
+
*
|
|
102
|
+
* @param text the current file content (may be empty)
|
|
103
|
+
* @param block the block content to place between the markers
|
|
104
|
+
* @param style the marker comment style for the target file type
|
|
105
|
+
* @param position where to place a NEW block; ignored when replacing
|
|
106
|
+
* @returns the updated text and whether anything changed
|
|
107
|
+
*/
|
|
108
|
+
const upsert_marker_block = (text, block, style, position = 'append') => {
|
|
109
|
+
const [begin, end] = MARKERS[style];
|
|
110
|
+
const fenced = `${begin}\n${block.trimEnd()}\n${end}\n`;
|
|
111
|
+
const begin_idx = text.indexOf(begin);
|
|
112
|
+
if (begin_idx !== -1) {
|
|
113
|
+
const end_idx = text.indexOf(end, begin_idx);
|
|
114
|
+
if (end_idx !== -1) {
|
|
115
|
+
const after = text.slice(end_idx + end.length).replace(/^\r?\n/, '');
|
|
116
|
+
const updated = `${text.slice(0, begin_idx)}${fenced}${after}`;
|
|
117
|
+
return { text: updated, changed: updated !== text };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (text.trim().length === 0) {
|
|
121
|
+
return { text: fenced, changed: true };
|
|
122
|
+
}
|
|
123
|
+
if (position === 'prepend') {
|
|
124
|
+
return { text: `${fenced}\n${text.replace(/^\s*\n/, '')}`, changed: true };
|
|
125
|
+
}
|
|
126
|
+
return { text: `${text.trimEnd()}\n\n${fenced}`, changed: true };
|
|
127
|
+
};
|
|
128
|
+
exports.upsert_marker_block = upsert_marker_block;
|
|
129
|
+
/**
|
|
130
|
+
* Upserts our SessionStart hook entry into a hooks-style configuration object
|
|
131
|
+
* (the SessionStart shape is identical between Claude Code's settings.json
|
|
132
|
+
* and Codex's hooks.json). An existing entry referencing `@nram-ai/setup-agents` is
|
|
133
|
+
* replaced in place when its command differs (a different server URL, or the
|
|
134
|
+
* URL-less command written by older package versions), left alone when it
|
|
135
|
+
* already matches, and appended when absent. Unrelated hooks are never touched
|
|
136
|
+
*
|
|
137
|
+
* @param config the parsed configuration object (mutated in place)
|
|
138
|
+
* @param base_url the normalized nram base URL embedded in the hook command
|
|
139
|
+
* @returns the configuration and whether it changed
|
|
140
|
+
*/
|
|
141
|
+
const upsert_session_start_hook = (config, base_url) => {
|
|
142
|
+
config ??= {};
|
|
143
|
+
config.hooks ??= {};
|
|
144
|
+
config.hooks.SessionStart ??= [];
|
|
145
|
+
const command = (0, exports.session_start_command)(base_url);
|
|
146
|
+
for (const group of config.hooks.SessionStart) {
|
|
147
|
+
for (const hook of group?.hooks ?? []) {
|
|
148
|
+
if (typeof hook?.command === 'string' && hook.command.includes(exports.SESSION_START_MARKER)) {
|
|
149
|
+
if (hook.command === command) {
|
|
150
|
+
return { config, changed: false };
|
|
151
|
+
}
|
|
152
|
+
hook.command = command;
|
|
153
|
+
return { config, changed: true };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
config.hooks.SessionStart.push({
|
|
158
|
+
matcher: '',
|
|
159
|
+
hooks: [{
|
|
160
|
+
type: 'command',
|
|
161
|
+
command
|
|
162
|
+
}]
|
|
163
|
+
});
|
|
164
|
+
return { config, changed: true };
|
|
165
|
+
};
|
|
166
|
+
exports.upsert_session_start_hook = upsert_session_start_hook;
|
|
167
|
+
/**
|
|
168
|
+
* Upserts our SessionStart hook into a hooks-style JSON file (Claude Code's
|
|
169
|
+
* settings.json and Codex's hooks.json share the shape) and reports the
|
|
170
|
+
* outcome; an unparseable file is left untouched
|
|
171
|
+
*
|
|
172
|
+
* @param path the hooks file to update
|
|
173
|
+
* @param base_url the normalized nram base URL embedded in the hook command
|
|
174
|
+
*/
|
|
175
|
+
const upsert_hooks_json = (path, base_url) => {
|
|
176
|
+
const file = (0, exports.read_json)(path);
|
|
177
|
+
if (!file.ok) {
|
|
178
|
+
return {
|
|
179
|
+
action: 'SessionStart hook',
|
|
180
|
+
kind: 'manual',
|
|
181
|
+
detail: `${path} exists but could not be parsed (${file.error}); ` +
|
|
182
|
+
'add this to hooks.SessionStart yourself: ' +
|
|
183
|
+
`{ "matcher": "", "hooks": [{ "type": "command", "command": "${(0, exports.session_start_command)(base_url)}" }] }`
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const { config, changed } = (0, exports.upsert_session_start_hook)(file.value ?? {}, base_url);
|
|
187
|
+
if (!changed) {
|
|
188
|
+
return { action: 'SessionStart hook', kind: 'skipped', detail: `already present in ${path}` };
|
|
189
|
+
}
|
|
190
|
+
(0, exports.write_json)(path, config);
|
|
191
|
+
return { action: 'SessionStart hook', kind: file.existed ? 'updated' : 'written', detail: path };
|
|
192
|
+
};
|
|
193
|
+
exports.upsert_hooks_json = upsert_hooks_json;
|
|
194
|
+
/**
|
|
195
|
+
* Merges a value into a JSON file at the given key path (creating intermediate
|
|
196
|
+
* objects as needed), writing only when the value differs. An unparseable
|
|
197
|
+
* existing file is left untouched and reported for manual handling
|
|
198
|
+
*
|
|
199
|
+
* @param path the JSON file to update
|
|
200
|
+
* @param key_path the nested key path, e.g. ['mcpServers', 'nram']
|
|
201
|
+
* @param entry the value to place at the key path
|
|
202
|
+
* @param fallback the configuration to start from when the file is missing
|
|
203
|
+
*/
|
|
204
|
+
const upsert_json_path = (path, key_path, entry, fallback = {}) => {
|
|
205
|
+
const file = (0, exports.read_json)(path);
|
|
206
|
+
if (!file.ok) {
|
|
207
|
+
return { kind: 'manual', error: file.error };
|
|
208
|
+
}
|
|
209
|
+
const config = file.value ?? fallback;
|
|
210
|
+
let node = config;
|
|
211
|
+
for (const key of key_path.slice(0, -1)) {
|
|
212
|
+
node[key] ??= {};
|
|
213
|
+
node = node[key];
|
|
214
|
+
}
|
|
215
|
+
const leaf = key_path[key_path.length - 1];
|
|
216
|
+
if (JSON.stringify(node[leaf]) === JSON.stringify(entry)) {
|
|
217
|
+
return { kind: 'skipped' };
|
|
218
|
+
}
|
|
219
|
+
node[leaf] = entry;
|
|
220
|
+
(0, exports.write_json)(path, config);
|
|
221
|
+
return { kind: file.existed ? 'updated' : 'written' };
|
|
222
|
+
};
|
|
223
|
+
exports.upsert_json_path = upsert_json_path;
|
|
224
|
+
/**
|
|
225
|
+
* The manual follow-up shown whenever a configuration references the
|
|
226
|
+
* NRAM_API_KEY environment variable instead of embedding the key
|
|
227
|
+
*/
|
|
228
|
+
const api_key_manual_result = () => ({
|
|
229
|
+
action: 'API key',
|
|
230
|
+
kind: 'manual',
|
|
231
|
+
detail: 'set the NRAM_API_KEY environment variable to your nram API key; ' +
|
|
232
|
+
'the key is never written to disk'
|
|
233
|
+
});
|
|
234
|
+
exports.api_key_manual_result = api_key_manual_result;
|
|
235
|
+
/**
|
|
236
|
+
* The manual follow-up shown when a tool's configuration has no verified
|
|
237
|
+
* environment-variable substitution, so the Authorization header must be
|
|
238
|
+
* added by hand rather than risking a literal key on disk
|
|
239
|
+
*
|
|
240
|
+
* @param path the configuration file the header belongs in
|
|
241
|
+
*/
|
|
242
|
+
const api_key_header_manual_result = (path) => ({
|
|
243
|
+
action: 'API key',
|
|
244
|
+
kind: 'manual',
|
|
245
|
+
detail: `this tool has no verified env-var substitution, so add the header yourself in ${path}: ` +
|
|
246
|
+
'"headers": { "Authorization": "Bearer <your nram_k_ key>" }'
|
|
247
|
+
});
|
|
248
|
+
exports.api_key_header_manual_result = api_key_header_manual_result;
|
|
249
|
+
/**
|
|
250
|
+
* Merges an MCP server entry into a JSON configuration and maps the outcome
|
|
251
|
+
* onto the standard `MCP registration` ActionResult, including the manual
|
|
252
|
+
* snippet for unparseable files; this is the shared report flow every
|
|
253
|
+
* JSON-configured harness uses
|
|
254
|
+
*
|
|
255
|
+
* @param path the JSON file to update
|
|
256
|
+
* @param key_path the nested key path (the leaf is the entry key, or the array itself with `array`)
|
|
257
|
+
* @param entry the entry value
|
|
258
|
+
* @param options report and merge options
|
|
259
|
+
*/
|
|
260
|
+
const mcp_json_result = (path, key_path, entry, options = {}) => {
|
|
261
|
+
const merged = options.array
|
|
262
|
+
? (0, exports.upsert_json_array_entry)(path, key_path, entry)
|
|
263
|
+
: (0, exports.upsert_json_path)(path, key_path, entry, options.fallback ?? {});
|
|
264
|
+
if (merged.kind === 'manual') {
|
|
265
|
+
const reason = options.parse_hint ?? merged.error;
|
|
266
|
+
const target = options.array
|
|
267
|
+
? `add this to the "${key_path.join('.')}" array yourself`
|
|
268
|
+
: `add this under "${key_path.slice(0, -1).join('.')}" yourself: "${key_path[key_path.length - 1]}"`;
|
|
269
|
+
return {
|
|
270
|
+
action: 'MCP registration',
|
|
271
|
+
kind: 'manual',
|
|
272
|
+
detail: `${path} exists but could not be parsed (${reason}); ${target}: ${JSON.stringify(entry)}`
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
if (merged.kind === 'skipped') {
|
|
276
|
+
return { action: 'MCP registration', kind: 'skipped', detail: `already present in ${path}` };
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
action: 'MCP registration',
|
|
280
|
+
kind: merged.kind,
|
|
281
|
+
detail: options.note === undefined ? path : `${path} (${options.note})`
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
exports.mcp_json_result = mcp_json_result;
|
|
285
|
+
/**
|
|
286
|
+
* Upserts a marker-fenced configuration block into a structured text file
|
|
287
|
+
* (TOML, YAML): parse the existing content (manual on failure), let the
|
|
288
|
+
* caller veto via a conflict check, apply the marker upsert, validate that
|
|
289
|
+
* the result re-parses with the expected entry, and only then write. The
|
|
290
|
+
* file is never re-serialized as a whole, so user comments survive
|
|
291
|
+
*
|
|
292
|
+
* @param path the configuration file
|
|
293
|
+
* @param block the marker-fenced block content
|
|
294
|
+
* @param parse the format parser (throws on invalid input)
|
|
295
|
+
* @param format the format name for messaging
|
|
296
|
+
* @param conflict returns a result to report instead of editing (e.g. the key exists outside our markers)
|
|
297
|
+
* @param valid post-edit check that the entry is present in the re-parsed file
|
|
298
|
+
*/
|
|
299
|
+
const upsert_block_with_validation = (path, block, parse, format, conflict, valid) => {
|
|
300
|
+
const text = (0, exports.read_text)(path);
|
|
301
|
+
if (text.trim().length !== 0) {
|
|
302
|
+
let parsed;
|
|
303
|
+
try {
|
|
304
|
+
parsed = parse(text);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return {
|
|
308
|
+
action: 'MCP registration',
|
|
309
|
+
kind: 'manual',
|
|
310
|
+
detail: `${path} exists but could not be parsed as ${format}; add this yourself:\n${block}`
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const vetoed = conflict(parsed, text);
|
|
314
|
+
if (vetoed !== undefined) {
|
|
315
|
+
return vetoed;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const { text: updated, changed } = (0, exports.upsert_marker_block)(text, block, 'hash', 'append');
|
|
319
|
+
if (!changed) {
|
|
320
|
+
return { action: 'MCP registration', kind: 'skipped', detail: `already present in ${path}` };
|
|
321
|
+
}
|
|
322
|
+
let ok;
|
|
323
|
+
try {
|
|
324
|
+
ok = valid(parse(updated));
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
ok = false;
|
|
328
|
+
}
|
|
329
|
+
if (!ok) {
|
|
330
|
+
return {
|
|
331
|
+
action: 'MCP registration',
|
|
332
|
+
kind: 'failed',
|
|
333
|
+
detail: `refusing to write ${path}: the updated file did not re-parse cleanly; ` +
|
|
334
|
+
`add this yourself:\n${block}`
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
(0, exports.write_text)(path, updated);
|
|
338
|
+
return {
|
|
339
|
+
action: 'MCP registration',
|
|
340
|
+
kind: text.length === 0 ? 'written' : 'updated',
|
|
341
|
+
detail: path
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
exports.upsert_block_with_validation = upsert_block_with_validation;
|
|
345
|
+
/**
|
|
346
|
+
* Merges an entry into an array-shaped JSON configuration (e.g. Factory's
|
|
347
|
+
* `servers: []`), keyed by a name field: replace in place when an element
|
|
348
|
+
* with the same name exists and differs, append when absent, skip when
|
|
349
|
+
* identical. An unparseable existing file is left untouched
|
|
350
|
+
*
|
|
351
|
+
* @param path the JSON file to update
|
|
352
|
+
* @param array_key_path the nested key path holding the array
|
|
353
|
+
* @param entry the element to place (must carry the name key)
|
|
354
|
+
* @param name_key the field that identifies elements (default `name`)
|
|
355
|
+
*/
|
|
356
|
+
const upsert_json_array_entry = (path, array_key_path, entry, name_key = 'name') => {
|
|
357
|
+
const file = (0, exports.read_json)(path);
|
|
358
|
+
if (!file.ok) {
|
|
359
|
+
return { kind: 'manual', error: file.error };
|
|
360
|
+
}
|
|
361
|
+
const config = file.value ?? {};
|
|
362
|
+
let node = config;
|
|
363
|
+
for (const key of array_key_path.slice(0, -1)) {
|
|
364
|
+
node[key] ??= {};
|
|
365
|
+
node = node[key];
|
|
366
|
+
}
|
|
367
|
+
const leaf = array_key_path[array_key_path.length - 1];
|
|
368
|
+
node[leaf] ??= [];
|
|
369
|
+
const list = node[leaf];
|
|
370
|
+
const index = list.findIndex(element => element?.[name_key] === entry[name_key]);
|
|
371
|
+
if (index !== -1 && JSON.stringify(list[index]) === JSON.stringify(entry)) {
|
|
372
|
+
return { kind: 'skipped' };
|
|
373
|
+
}
|
|
374
|
+
if (index !== -1) {
|
|
375
|
+
list[index] = entry;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
list.push(entry);
|
|
379
|
+
}
|
|
380
|
+
(0, exports.write_json)(path, config);
|
|
381
|
+
return { kind: file.existed ? 'updated' : 'written' };
|
|
382
|
+
};
|
|
383
|
+
exports.upsert_json_array_entry = upsert_json_array_entry;
|
|
384
|
+
/**
|
|
385
|
+
* Writes a file the tool owns outright (rule files, steering docs,
|
|
386
|
+
* instruction files): compare, write when different, and report
|
|
387
|
+
*
|
|
388
|
+
* @param path the file to write
|
|
389
|
+
* @param content the full file content
|
|
390
|
+
* @param action the action name for the result
|
|
391
|
+
*/
|
|
392
|
+
const upsert_own_file = (path, content, action) => {
|
|
393
|
+
const existing = (0, exports.read_text)(path);
|
|
394
|
+
if (existing === content) {
|
|
395
|
+
return { action, kind: 'skipped', detail: `already present at ${path}` };
|
|
396
|
+
}
|
|
397
|
+
(0, exports.write_text)(path, content);
|
|
398
|
+
return {
|
|
399
|
+
action,
|
|
400
|
+
kind: existing.length === 0 ? 'written' : 'updated',
|
|
401
|
+
detail: path
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
exports.upsert_own_file = upsert_own_file;
|
|
405
|
+
/**
|
|
406
|
+
* Upserts the marker-fenced agent-instructions block at the top of an
|
|
407
|
+
* AGENTS.md-style file and reports the outcome; tools sharing the same file
|
|
408
|
+
* (the project-root AGENTS.md) dedupe automatically because the second
|
|
409
|
+
* upsert finds the block unchanged
|
|
410
|
+
*
|
|
411
|
+
* @param path the markdown file to update
|
|
412
|
+
* @param instructions the agent instructions text to place in the block
|
|
413
|
+
*/
|
|
414
|
+
const agents_md_result = (path, instructions) => {
|
|
415
|
+
const text = (0, exports.read_text)(path);
|
|
416
|
+
const { text: updated, changed } = (0, exports.upsert_marker_block)(text, instructions, 'html', 'prepend');
|
|
417
|
+
if (!changed) {
|
|
418
|
+
return { action: 'Agent instructions', kind: 'skipped', detail: `already present in ${path}` };
|
|
419
|
+
}
|
|
420
|
+
(0, exports.write_text)(path, updated);
|
|
421
|
+
return {
|
|
422
|
+
action: 'Agent instructions',
|
|
423
|
+
kind: text.length === 0 ? 'written' : 'updated',
|
|
424
|
+
detail: path
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
exports.agents_md_result = agents_md_result;
|
|
428
|
+
//# sourceMappingURL=upsert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert.js","sourceRoot":"","sources":["../../src/helpers/upsert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes an nram base URL: trims whitespace, requires http/https,
|
|
3
|
+
* and strips any trailing slash so that paths can be appended safely
|
|
4
|
+
*
|
|
5
|
+
* @param input the user-supplied base URL
|
|
6
|
+
* @returns the normalized base URL
|
|
7
|
+
* @throws Error when the input is not a valid http(s) URL
|
|
8
|
+
*/
|
|
9
|
+
export declare const normalize_base_url: (input: string) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Derives the MCP endpoint URL from a normalized base URL
|
|
12
|
+
*
|
|
13
|
+
* @param base_url the normalized nram base URL
|
|
14
|
+
*/
|
|
15
|
+
export declare const mcp_url: (base_url: string) => string;
|