@invitedlabs/cli 0.0.0-stage → 0.1.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 +55 -0
- package/README.md +68 -2
- package/dist/args.js +95 -0
- package/dist/browser.js +29 -0
- package/dist/commands.js +377 -0
- package/dist/connect.js +192 -0
- package/dist/credentials.js +150 -0
- package/dist/errors.js +9 -0
- package/dist/format.js +25 -0
- package/dist/http.js +39 -0
- package/dist/index.js +3 -0
- package/dist/loopback.js +140 -0
- package/dist/main.js +210 -0
- package/dist/mcp.js +144 -0
- package/dist/oauth.js +166 -0
- package/dist/toml.js +192 -0
- package/dist/version.js +4 -0
- package/package.json +24 -4
package/dist/toml.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/** A configuration file in a shape the CLI does not edit; it is left as it is. */
|
|
2
|
+
export class ShapeError extends Error {
|
|
3
|
+
}
|
|
4
|
+
/** A dotted key (bare, "basic" or 'literal' parts) from `start`; the index
|
|
5
|
+
* after it and its trailing spaces. */
|
|
6
|
+
function readKeys(source, start) {
|
|
7
|
+
const keys = [];
|
|
8
|
+
let i = start;
|
|
9
|
+
const skip = () => {
|
|
10
|
+
while (source[i] === ' ' || source[i] === '\t')
|
|
11
|
+
i++;
|
|
12
|
+
};
|
|
13
|
+
for (;;) {
|
|
14
|
+
skip();
|
|
15
|
+
if (source[i] === '"') {
|
|
16
|
+
let value = '';
|
|
17
|
+
i++;
|
|
18
|
+
while (i < source.length && source[i] !== '"') {
|
|
19
|
+
if (source[i] === '\\') {
|
|
20
|
+
const next = source[i + 1];
|
|
21
|
+
const width = next === 'u' ? 4 : next === 'U' ? 8 : 0;
|
|
22
|
+
value += width
|
|
23
|
+
? String.fromCodePoint(parseInt(source.slice(i + 2, i + 2 + width), 16))
|
|
24
|
+
: ({ n: '\n', t: '\t', r: '\r', b: '\b', f: '\f' }[next] ?? next);
|
|
25
|
+
i += 2 + width;
|
|
26
|
+
}
|
|
27
|
+
else
|
|
28
|
+
value += source[i++];
|
|
29
|
+
}
|
|
30
|
+
if (source[i] !== '"')
|
|
31
|
+
return null;
|
|
32
|
+
i++;
|
|
33
|
+
keys.push(value);
|
|
34
|
+
}
|
|
35
|
+
else if (source[i] === "'") {
|
|
36
|
+
const close = source.indexOf("'", i + 1);
|
|
37
|
+
if (close < 0)
|
|
38
|
+
return null;
|
|
39
|
+
keys.push(source.slice(i + 1, close));
|
|
40
|
+
i = close + 1;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const bare = /^[A-Za-z0-9_-]+/.exec(source.slice(i));
|
|
44
|
+
if (!bare)
|
|
45
|
+
return null;
|
|
46
|
+
keys.push(bare[0]);
|
|
47
|
+
i += bare[0].length;
|
|
48
|
+
}
|
|
49
|
+
skip();
|
|
50
|
+
if (source[i] !== '.')
|
|
51
|
+
return { keys, end: i };
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function readHeader(line) {
|
|
56
|
+
const open = /^\s*(\[\[?)/.exec(line);
|
|
57
|
+
if (!open)
|
|
58
|
+
return null;
|
|
59
|
+
const array = open[1] === '[[';
|
|
60
|
+
const keys = readKeys(line, open[0].length);
|
|
61
|
+
if (!keys)
|
|
62
|
+
return null;
|
|
63
|
+
const rest = line.slice(keys.end);
|
|
64
|
+
const close = array ? ']]' : ']';
|
|
65
|
+
return rest.startsWith(close) && /^\s*(#.*)?$/.test(rest.slice(close.length)) ? { keys: keys.keys, array } : null;
|
|
66
|
+
}
|
|
67
|
+
/** The last line of a value that starts at `column` of line `row`: arrays,
|
|
68
|
+
* inline tables and multi-line strings may span lines. */
|
|
69
|
+
function valueEnd(lines, row, column) {
|
|
70
|
+
let depth = 0;
|
|
71
|
+
let open = null;
|
|
72
|
+
for (let r = row; r < lines.length; r++) {
|
|
73
|
+
const line = lines[r];
|
|
74
|
+
for (let c = r === row ? column : 0; c < line.length; c++) {
|
|
75
|
+
const rest = line.slice(c);
|
|
76
|
+
if (open) {
|
|
77
|
+
if ((open === '"' || open === '"""') && line[c] === '\\')
|
|
78
|
+
c++;
|
|
79
|
+
else if (rest.startsWith(open)) {
|
|
80
|
+
c += open.length - 1;
|
|
81
|
+
open = null;
|
|
82
|
+
}
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (line[c] === '#')
|
|
86
|
+
break;
|
|
87
|
+
if (rest.startsWith('"""') || rest.startsWith("'''")) {
|
|
88
|
+
open = rest.slice(0, 3);
|
|
89
|
+
c += 2;
|
|
90
|
+
}
|
|
91
|
+
else if (line[c] === '"' || line[c] === "'")
|
|
92
|
+
open = line[c];
|
|
93
|
+
else if (line[c] === '[' || line[c] === '{')
|
|
94
|
+
depth++;
|
|
95
|
+
else if (line[c] === ']' || line[c] === '}')
|
|
96
|
+
depth--;
|
|
97
|
+
}
|
|
98
|
+
if (open === '"' || open === "'")
|
|
99
|
+
open = null;
|
|
100
|
+
if (!open && depth <= 0)
|
|
101
|
+
return r;
|
|
102
|
+
}
|
|
103
|
+
return lines.length - 1;
|
|
104
|
+
}
|
|
105
|
+
function scan(lines) {
|
|
106
|
+
const found = [];
|
|
107
|
+
for (let i = 0; i < lines.length; i++) {
|
|
108
|
+
const line = lines[i];
|
|
109
|
+
if (/^\s*(#.*)?$/.test(line))
|
|
110
|
+
continue;
|
|
111
|
+
const header = readHeader(line);
|
|
112
|
+
if (header) {
|
|
113
|
+
found.push({ kind: 'header', index: i, ...header });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const pair = readKeys(line, 0);
|
|
117
|
+
if (pair && line[pair.end] === '=') {
|
|
118
|
+
const end = valueEnd(lines, i, pair.end + 1);
|
|
119
|
+
found.push({ kind: 'pair', start: i, end, keys: pair.keys });
|
|
120
|
+
i = end;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return found;
|
|
124
|
+
}
|
|
125
|
+
const same = (a, b) => a.length === b.length && a.every((key, i) => key === b[i]);
|
|
126
|
+
/** A TOML basic string. */
|
|
127
|
+
export const tomlString = (value) => '"' +
|
|
128
|
+
value.replace(/[\\"\u0000-\u001f\u007f]/g, character => character === '\\' || character === '"'
|
|
129
|
+
? '\\' + character
|
|
130
|
+
: '\\u' + character.charCodeAt(0).toString(16).padStart(4, '0')) +
|
|
131
|
+
'"';
|
|
132
|
+
export const tomlArray = (values) => '[' + values.map(tomlString).join(', ') + ']';
|
|
133
|
+
/**
|
|
134
|
+
* Set `[mcp_servers.<name>]`'s `values` (keys with values already in TOML)
|
|
135
|
+
* and remove `drop` keys from it, adding the table at the end of the file
|
|
136
|
+
* when it is not there.
|
|
137
|
+
*/
|
|
138
|
+
export function setServerTable(source, name, values, drop) {
|
|
139
|
+
const text = source ?? '';
|
|
140
|
+
const eol = text.includes('\r\n') ? '\r\n' : '\n';
|
|
141
|
+
const lines = text.split(/\r?\n/);
|
|
142
|
+
const found = scan(lines);
|
|
143
|
+
let table = [];
|
|
144
|
+
let own = null;
|
|
145
|
+
let ownEnd = lines.length;
|
|
146
|
+
const others = new Set();
|
|
147
|
+
for (const line of found) {
|
|
148
|
+
if (line.kind === 'header') {
|
|
149
|
+
if (own && ownEnd === lines.length && line.index > own.index)
|
|
150
|
+
ownEnd = line.index;
|
|
151
|
+
table = line.keys;
|
|
152
|
+
if (line.keys[0] === 'mcp_servers' && line.keys.length > 1 && line.keys[1] !== name)
|
|
153
|
+
others.add(line.keys[1]);
|
|
154
|
+
if (!line.array && same(line.keys, ['mcp_servers', name]) && !own)
|
|
155
|
+
own = line;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const path = [...table, ...line.keys];
|
|
159
|
+
if (path[0] === 'mcp_servers' && path.length > 1) {
|
|
160
|
+
// The server defined from above its own table: `mcp_servers.<name> = { … }`
|
|
161
|
+
// at the top, or `<name> = { … }` under [mcp_servers].
|
|
162
|
+
const inside = table[0] === 'mcp_servers' && table[1] === name;
|
|
163
|
+
if (path[1] === name && !inside)
|
|
164
|
+
throw new ShapeError(`it defines ${name} with dotted keys or an inline table`);
|
|
165
|
+
if (path[1] !== name)
|
|
166
|
+
others.add(path[1]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const rendered = values.map(([key, value]) => `${key} = ${value}`);
|
|
170
|
+
if (!own) {
|
|
171
|
+
const block = [`[mcp_servers.${name}]`, ...rendered].join(eol) + eol;
|
|
172
|
+
if (!text.trim())
|
|
173
|
+
return { text: block, change: 'added', others: [...others] };
|
|
174
|
+
const ending = text.endsWith(eol + eol) ? '' : text.endsWith(eol) ? eol : eol + eol;
|
|
175
|
+
return { text: text + ending + block, change: 'added', others: [...others] };
|
|
176
|
+
}
|
|
177
|
+
// The table's own key lines; owned keys are removed and written again
|
|
178
|
+
// where the first of them stood.
|
|
179
|
+
const owned = new Set([...values.map(([key]) => key), ...drop]);
|
|
180
|
+
const removed = [];
|
|
181
|
+
for (const line of found)
|
|
182
|
+
if (line.kind === 'pair' && line.start > own.index && line.start < ownEnd && line.keys.length === 1)
|
|
183
|
+
if (owned.has(line.keys[0]))
|
|
184
|
+
removed.push([line.start, line.end]);
|
|
185
|
+
const at = removed.length ? removed[0][0] : own.index + 1;
|
|
186
|
+
const kept = lines.flatMap((line, index) => removed.some(([start, end]) => index >= start && index <= end) ? [] : [{ line, index }]);
|
|
187
|
+
const position = kept.findIndex(item => item.index >= at);
|
|
188
|
+
const next = kept.map(item => item.line);
|
|
189
|
+
next.splice(position < 0 ? next.length : position, 0, ...rendered);
|
|
190
|
+
const result = next.join(eol);
|
|
191
|
+
return { text: result, change: result === text ? 'unchanged' : 'updated', others: [...others] };
|
|
192
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
/** The package's own version, from cli/package.json (beside dist/ and src/). */
|
|
3
|
+
export const VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
4
|
+
export const USER_AGENT = `invited-cli/${VERSION} node/${process.versions.node}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@invitedlabs/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The invited command: connect terminal agents and AI assistants to your Invited Identity through Invited's MCP connector.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://invited.you",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"invited": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.13"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "22.19.19",
|
|
24
|
+
"typescript": "5.9.3"
|
|
25
|
+
}
|
|
26
|
+
}
|