@jitera/connect 1.3.0 → 1.5.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +96 -25
- package/content/session-start-unconfigured.md +11 -0
- package/content/session-start.md +5 -4
- package/dist/adapters/codex.d.ts.map +1 -1
- package/dist/adapters/codex.js +3 -0
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/cursor.d.ts.map +1 -1
- package/dist/adapters/cursor.js +4 -3
- package/dist/adapters/cursor.js.map +1 -1
- package/dist/adapters/types.d.ts +1 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/bin/cli.js +6 -12
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/connect.js +6 -0
- package/dist/bin/connect.js.map +1 -1
- package/dist/bin/init.d.ts +3 -0
- package/dist/bin/init.d.ts.map +1 -0
- package/dist/bin/init.js +174 -0
- package/dist/bin/init.js.map +1 -0
- package/dist/bin/login.js +87 -17
- package/dist/bin/login.js.map +1 -1
- package/dist/bin/proxy.js +21 -2
- package/dist/bin/proxy.js.map +1 -1
- package/dist/bin/statusline.d.ts +3 -0
- package/dist/bin/statusline.d.ts.map +1 -0
- package/dist/bin/statusline.js +17 -0
- package/dist/bin/statusline.js.map +1 -0
- package/dist/cli-session.d.ts +12 -0
- package/dist/cli-session.d.ts.map +1 -0
- package/dist/cli-session.js +39 -0
- package/dist/cli-session.js.map +1 -0
- package/dist/device-flow.d.ts +10 -1
- package/dist/device-flow.d.ts.map +1 -1
- package/dist/device-flow.js +25 -1
- package/dist/device-flow.js.map +1 -1
- package/dist/graphql.d.ts +5 -0
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +15 -11
- package/dist/graphql.js.map +1 -1
- package/dist/hooks/session-start.js +32 -2
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/user-prompt-submit.js +10 -0
- package/dist/hooks/user-prompt-submit.js.map +1 -1
- package/dist/install/claude-code.d.ts +2 -0
- package/dist/install/claude-code.d.ts.map +1 -1
- package/dist/install/claude-code.js +28 -3
- package/dist/install/claude-code.js.map +1 -1
- package/dist/install/project-root.d.ts +2 -0
- package/dist/install/project-root.d.ts.map +1 -0
- package/dist/install/project-root.js +9 -0
- package/dist/install/project-root.js.map +1 -0
- package/dist/install/statusline.d.ts +12 -0
- package/dist/install/statusline.d.ts.map +1 -0
- package/dist/install/statusline.js +30 -0
- package/dist/install/statusline.js.map +1 -0
- package/dist/mcp-client.d.ts +2 -1
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +2 -1
- package/dist/mcp-client.js.map +1 -1
- package/dist/project-marker.d.ts +15 -0
- package/dist/project-marker.d.ts.map +1 -0
- package/dist/project-marker.js +59 -0
- package/dist/project-marker.js.map +1 -0
- package/dist/proxy.d.ts +8 -2
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +23 -4
- package/dist/proxy.js.map +1 -1
- package/dist/select.d.ts +36 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +111 -0
- package/dist/select.js.map +1 -0
- package/dist/session-status.d.ts +11 -0
- package/dist/session-status.d.ts.map +1 -0
- package/dist/session-status.js +46 -0
- package/dist/session-status.js.map +1 -0
- package/dist/statusline.d.ts +7 -0
- package/dist/statusline.d.ts.map +1 -0
- package/dist/statusline.js +31 -0
- package/dist/statusline.js.map +1 -0
- package/package.json +3 -3
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import { callTool, McpCallError } from "../mcp-client.js";
|
|
3
3
|
import { discoverDeployment } from "../discovery.js";
|
|
4
4
|
import { emitContext, readHookInput } from "../hook-io.js";
|
|
5
|
+
import { readProjectMarker } from "../project-marker.js";
|
|
5
6
|
import { claimOnce } from "../session-marker.js";
|
|
7
|
+
import { writeSessionStatus } from "../session-status.js";
|
|
6
8
|
const MAX_CONTEXT_CHARS = 6000;
|
|
7
9
|
const RECALL_TIMEOUT_MS = 8000;
|
|
8
10
|
const input = readHookInput();
|
|
@@ -30,10 +32,12 @@ else {
|
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
let memory;
|
|
35
|
+
const startedAt = Date.now();
|
|
33
36
|
try {
|
|
34
37
|
memory = await callTool({
|
|
35
38
|
url,
|
|
36
39
|
apiKey,
|
|
40
|
+
projectUuid: readProjectMarker(input.cwd ?? process.cwd())?.project,
|
|
37
41
|
name: "recall_jitera_memory",
|
|
38
42
|
args: {},
|
|
39
43
|
timeoutMs: RECALL_TIMEOUT_MS,
|
|
@@ -41,9 +45,15 @@ try {
|
|
|
41
45
|
}
|
|
42
46
|
catch (error) {
|
|
43
47
|
const message = error instanceof McpCallError ? error.message : String(error);
|
|
48
|
+
writeSessionStatus(input.session_id, { recallError: message });
|
|
44
49
|
process.stderr.write(`jitera-connect: could not load project memory: ${message}\n`);
|
|
45
50
|
process.exit(0);
|
|
46
51
|
}
|
|
52
|
+
writeSessionStatus(input.session_id, {
|
|
53
|
+
recallMs: Date.now() - startedAt,
|
|
54
|
+
recallChars: memory.length,
|
|
55
|
+
recallError: undefined,
|
|
56
|
+
});
|
|
47
57
|
if (!memory)
|
|
48
58
|
process.exit(0);
|
|
49
59
|
const body = memory.length > MAX_CONTEXT_CHARS
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-prompt-submit.js","sourceRoot":"","sources":["../../src/hooks/user-prompt-submit.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"user-prompt-submit.js","sourceRoot":"","sources":["../../src/hooks/user-prompt-submit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export declare const MARKETPLACE = "jitera-product/connect";
|
|
2
|
+
export declare const MARKETPLACE_NAME = "jitera";
|
|
2
3
|
export declare const PLUGIN_NAME = "jitera-connect";
|
|
3
4
|
export interface CommandRunner {
|
|
4
5
|
(command: string, args: readonly string[]): {
|
|
5
6
|
status: number;
|
|
7
|
+
stdout: string;
|
|
6
8
|
stderr: string;
|
|
7
9
|
};
|
|
8
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChG;AAWD,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,aAA6B,GAAG,OAAO,CAEjF;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,WAAW,EACX,GAAmB,GACpB,EAAE,oBAAoB,GAAG,mBAAmB,CAgD5C"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
export const MARKETPLACE = "jitera-product/connect";
|
|
3
|
+
export const MARKETPLACE_NAME = "jitera";
|
|
3
4
|
export const PLUGIN_NAME = "jitera-connect";
|
|
4
5
|
const defaultRunner = (command, args) => {
|
|
5
6
|
const result = spawnSync(command, [...args], { encoding: "utf8" });
|
|
6
|
-
return {
|
|
7
|
+
return {
|
|
8
|
+
status: result.status ?? 1,
|
|
9
|
+
stdout: result.stdout ?? "",
|
|
10
|
+
stderr: result.stderr ?? "",
|
|
11
|
+
};
|
|
7
12
|
};
|
|
8
13
|
export function isClaudeCodeAvailable(run = defaultRunner) {
|
|
9
14
|
return run("claude", ["--version"]).status === 0;
|
|
@@ -16,17 +21,37 @@ export function installClaudeCodePlugin({ apiKey, environment, run = defaultRunn
|
|
|
16
21
|
if (marketplace.status !== 0 && !/already/i.test(marketplace.stderr)) {
|
|
17
22
|
return { installed: false, reason: marketplace.stderr.trim() || "could not add the marketplace" };
|
|
18
23
|
}
|
|
24
|
+
// A stale clone serves an old manifest whose userConfig schema no longer
|
|
25
|
+
// matches this cli, so the install below would reject --config. Best-effort:
|
|
26
|
+
// the "not applied" check still catches a refresh that failed.
|
|
27
|
+
run("claude", ["plugin", "marketplace", "update", MARKETPLACE_NAME]);
|
|
28
|
+
// `plugin install` no-ops on an existing install without re-resolving the
|
|
29
|
+
// version or re-applying --config. Removing first makes install idempotent.
|
|
30
|
+
run("claude", ["plugin", "uninstall", `${PLUGIN_NAME}@${MARKETPLACE_NAME}`]);
|
|
19
31
|
const install = run("claude", [
|
|
20
32
|
"plugin",
|
|
21
33
|
"install",
|
|
22
|
-
PLUGIN_NAME
|
|
34
|
+
`${PLUGIN_NAME}@${MARKETPLACE_NAME}`,
|
|
23
35
|
"--config",
|
|
24
36
|
`environment=${environment}`,
|
|
25
37
|
"--config",
|
|
26
38
|
`jitera_api_key=${apiKey}`,
|
|
27
39
|
]);
|
|
28
40
|
if (install.status !== 0) {
|
|
29
|
-
return {
|
|
41
|
+
return {
|
|
42
|
+
installed: false,
|
|
43
|
+
reason: install.stderr.trim() || install.stdout.trim() || "the plugin install failed",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// The cli exits 0 while rejecting --config with only a warning, which would
|
|
47
|
+
// leave the mcp server unconfigurable and silently absent from sessions.
|
|
48
|
+
const output = `${install.stdout}\n${install.stderr}`;
|
|
49
|
+
if (/not applied/i.test(output)) {
|
|
50
|
+
const warning = output
|
|
51
|
+
.split("\n")
|
|
52
|
+
.find((line) => /not applied/i.test(line))
|
|
53
|
+
?.trim();
|
|
54
|
+
return { installed: false, reason: warning ?? "the plugin config was not applied" };
|
|
30
55
|
}
|
|
31
56
|
return { installed: true };
|
|
32
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,WAAW,GAAG,wBAAwB,CAAC;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAM5C,MAAM,aAAa,GAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACrD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,OAAO,
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../src/install/project-root.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK9D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export function resolveGitRoot(cwd) {
|
|
3
|
+
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8" });
|
|
4
|
+
if (result.status !== 0)
|
|
5
|
+
return undefined;
|
|
6
|
+
const root = result.stdout.trim();
|
|
7
|
+
return root || undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=project-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.js","sourceRoot":"","sources":["../../src/install/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,IAAI,IAAI,SAAS,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const STATUS_COMMAND: string;
|
|
2
|
+
export interface StatusLineInstallOptions {
|
|
3
|
+
readonly home: string;
|
|
4
|
+
readonly dryRun?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface StatusLineInstallResult {
|
|
7
|
+
readonly installed: boolean;
|
|
8
|
+
readonly reason?: string;
|
|
9
|
+
readonly path: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function installStatusLine({ home, dryRun, }: StatusLineInstallOptions): StatusLineInstallResult;
|
|
12
|
+
//# sourceMappingURL=statusline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../../src/install/statusline.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,QAEgB,CAAC;AAE5C,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,MAAc,GACf,EAAE,wBAAwB,GAAG,uBAAuB,CAwBpD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { MalformedConfigError, readConfig, writeConfig } from "../mcp-config.js";
|
|
3
|
+
// Resolves the newest installed plugin version at run time, so plugin updates
|
|
4
|
+
// never orphan the status line, and exits quietly if the plugin is gone.
|
|
5
|
+
export const STATUS_COMMAND = '_j="$(ls -dt "$HOME/.claude/plugins/cache/jitera/jitera-connect/"*"/dist/bin/statusline.js" 2>/dev/null | head -1)"; ' +
|
|
6
|
+
'[ -n "$_j" ] && exec node "$_j" || true';
|
|
7
|
+
export function installStatusLine({ home, dryRun = false, }) {
|
|
8
|
+
const path = join(home, ".claude", "settings.json");
|
|
9
|
+
let config;
|
|
10
|
+
try {
|
|
11
|
+
config = readConfig(path);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (error instanceof MalformedConfigError) {
|
|
15
|
+
return { installed: false, reason: error.message, path };
|
|
16
|
+
}
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
// The status line is a single global slot. Someone else's configuration is
|
|
20
|
+
// theirs; report why we stepped back instead of silently clobbering it.
|
|
21
|
+
const existing = config["statusLine"];
|
|
22
|
+
if (existing && existing.command !== STATUS_COMMAND) {
|
|
23
|
+
return { installed: false, reason: "a status line is already configured", path };
|
|
24
|
+
}
|
|
25
|
+
if (!existing && !dryRun) {
|
|
26
|
+
writeConfig(path, { ...config, statusLine: { type: "command", command: STATUS_COMMAND } });
|
|
27
|
+
}
|
|
28
|
+
return { installed: true, path };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=statusline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusline.js","sourceRoot":"","sources":["../../src/install/statusline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEjF,8EAA8E;AAC9E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GACzB,uHAAuH;IACvH,yCAAyC,CAAC;AAa5C,MAAM,UAAU,iBAAiB,CAAC,EAChC,IAAI,EACJ,MAAM,GAAG,KAAK,GACW;IACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAEpD,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;YAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAqC,CAAC;IAC1E,IAAI,QAAQ,IAAI,QAAQ,CAAC,OAAO,KAAK,cAAc,EAAE,CAAC;QACpD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,qCAAqC,EAAE,IAAI,EAAE,CAAC;IACnF,CAAC;IAED,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,WAAW,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC"}
|
package/dist/mcp-client.d.ts
CHANGED
|
@@ -33,8 +33,9 @@ export interface TransportOptions {
|
|
|
33
33
|
readonly url: string;
|
|
34
34
|
readonly apiKey: string;
|
|
35
35
|
readonly timeoutMs?: number;
|
|
36
|
+
readonly projectUuid?: string | undefined;
|
|
36
37
|
}
|
|
37
|
-
export declare function postRpc(request: JsonRpcRequest, { url, apiKey, timeoutMs }: TransportOptions): Promise<JsonRpcResponse | undefined>;
|
|
38
|
+
export declare function postRpc(request: JsonRpcRequest, { url, apiKey, timeoutMs, projectUuid }: TransportOptions): Promise<JsonRpcResponse | undefined>;
|
|
38
39
|
export interface CallToolOptions extends TransportOptions {
|
|
39
40
|
readonly name: string;
|
|
40
41
|
readonly args?: Record<string, unknown>;
|
package/dist/mcp-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,kBAAkB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAG5C;CACF;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAWvF;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAQlE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,kBAAkB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAG5C;CACF;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAWvF;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAQlE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAG5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,EAAE,GAAG,EAAE,MAAM,EAAE,SAAgB,EAAE,WAAW,EAAE,EAAE,gBAAgB,GAC/D,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CA2CtC;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,wBAAsB,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAS,EAAE,GAAG,SAAS,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBlG"}
|
package/dist/mcp-client.js
CHANGED
|
@@ -28,7 +28,7 @@ export function extractText(result) {
|
|
|
28
28
|
.join("\n")
|
|
29
29
|
.trim();
|
|
30
30
|
}
|
|
31
|
-
export async function postRpc(request, { url, apiKey, timeoutMs = 5000 }) {
|
|
31
|
+
export async function postRpc(request, { url, apiKey, timeoutMs = 5000, projectUuid }) {
|
|
32
32
|
if (!url)
|
|
33
33
|
throw new McpCallError("no mcp endpoint configured");
|
|
34
34
|
if (!apiKey)
|
|
@@ -46,6 +46,7 @@ export async function postRpc(request, { url, apiKey, timeoutMs = 5000 }) {
|
|
|
46
46
|
"content-type": "application/json",
|
|
47
47
|
accept: "application/json, text/event-stream",
|
|
48
48
|
authorization: `Bearer ${apiKey}`,
|
|
49
|
+
...(projectUuid ? { "x-jitera-project": projectUuid } : {}),
|
|
49
50
|
},
|
|
50
51
|
body: JSON.stringify(request),
|
|
51
52
|
});
|
package/dist/mcp-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAyBA,MAAM,OAAO,YAAa,SAAQ,KAAK;IACnB,IAAI,GAAG,cAAc,CAAC;IAC/B,MAAM,CAAU;IAEzB,YAAY,OAAe,EAAE,MAAgB;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,GAAW;IACxD,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,SAAS;YACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,IAAI,OAAO;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,YAAY,CAAC,oCAAoC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAA8B;IACxD,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC;SAC3B,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE,CACvD,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CACtD;SACA,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAC;AACZ,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const MARKER_FILENAME = ".jitera.json";
|
|
2
|
+
export interface ProjectMarker {
|
|
3
|
+
readonly environment?: string | undefined;
|
|
4
|
+
readonly project?: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface FoundProjectMarker extends ProjectMarker {
|
|
7
|
+
readonly path: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function readProjectMarker(startDir: string): FoundProjectMarker | undefined;
|
|
10
|
+
export interface MarkerWriteResult {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly changed: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function writeProjectMarker(root: string, marker: ProjectMarker, dryRun?: boolean): MarkerWriteResult;
|
|
15
|
+
//# sourceMappingURL=project-marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-marker.d.ts","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAM9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAyBlF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,UAAQ,GACb,iBAAiB,CAuBnB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
export const MARKER_FILENAME = ".jitera.json";
|
|
4
|
+
// Environments are studio, studio-stage, studio-NN. Anything else in the file
|
|
5
|
+
// is not echoed back into session context.
|
|
6
|
+
const SAFE_ENVIRONMENT = /^[A-Za-z0-9-]{1,64}$/;
|
|
7
|
+
export function readProjectMarker(startDir) {
|
|
8
|
+
let dir = startDir;
|
|
9
|
+
for (;;) {
|
|
10
|
+
const path = join(dir, MARKER_FILENAME);
|
|
11
|
+
if (existsSync(path)) {
|
|
12
|
+
let parsed;
|
|
13
|
+
try {
|
|
14
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const environment = parsed["environment"];
|
|
20
|
+
const project = parsed["project"];
|
|
21
|
+
return {
|
|
22
|
+
path,
|
|
23
|
+
...(typeof environment === "string" && SAFE_ENVIRONMENT.test(environment)
|
|
24
|
+
? { environment }
|
|
25
|
+
: {}),
|
|
26
|
+
...(typeof project === "string" ? { project } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const parent = dirname(dir);
|
|
30
|
+
if (parent === dir)
|
|
31
|
+
return undefined;
|
|
32
|
+
dir = parent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function writeProjectMarker(root, marker, dryRun = false) {
|
|
36
|
+
const path = join(root, MARKER_FILENAME);
|
|
37
|
+
let existing = {};
|
|
38
|
+
let before;
|
|
39
|
+
if (existsSync(path)) {
|
|
40
|
+
before = readFileSync(path, "utf8");
|
|
41
|
+
try {
|
|
42
|
+
existing = JSON.parse(before);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
existing = {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const next = {
|
|
49
|
+
...existing,
|
|
50
|
+
...(marker.environment ? { environment: marker.environment } : {}),
|
|
51
|
+
...(marker.project ? { project: marker.project } : {}),
|
|
52
|
+
};
|
|
53
|
+
const serialized = `${JSON.stringify(next, undefined, 2)}\n`;
|
|
54
|
+
const changed = before !== serialized;
|
|
55
|
+
if (changed && !dryRun)
|
|
56
|
+
writeFileSync(path, serialized, "utf8");
|
|
57
|
+
return { path, changed };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=project-marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-marker.js","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC;AAE9C,8EAA8E;AAC9E,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAWhD,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACxC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,MAA+B,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;YAC7E,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;YAClC,OAAO;gBACL,IAAI;gBACJ,GAAG,CAAC,OAAO,WAAW,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC;oBACvE,CAAC,CAAC,EAAE,WAAW,EAAE;oBACjB,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpD,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,MAAqB,EACrB,MAAM,GAAG,KAAK;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAEzC,IAAI,QAAQ,GAA4B,EAAE,CAAC;IAC3C,IAAI,MAA0B,CAAC;IAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAA4B,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,QAAQ;QACX,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC;IACF,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC;IAC7D,MAAM,OAAO,GAAG,MAAM,KAAK,UAAU,CAAC;IACtC,IAAI,OAAO,IAAI,CAAC,MAAM;QAAE,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC"}
|
package/dist/proxy.d.ts
CHANGED
|
@@ -6,7 +6,13 @@ export interface ProxyStreams {
|
|
|
6
6
|
export interface ProxyConfig {
|
|
7
7
|
readonly url: string;
|
|
8
8
|
readonly apiKey: string;
|
|
9
|
+
readonly instructions?: string | undefined;
|
|
10
|
+
readonly projectUuid?: string | undefined;
|
|
9
11
|
}
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
+
export declare function resolveProjectUuid(env: NodeJS.ProcessEnv, cwd?: string): string | undefined;
|
|
13
|
+
export declare function runProxy({ url, apiKey, instructions, projectUuid }: ProxyConfig, { input, output, log }: ProxyStreams): Promise<void>;
|
|
14
|
+
export interface ProxyEnvironment extends ProxyConfig {
|
|
15
|
+
readonly brand: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function configFromEnvironment(env: NodeJS.ProcessEnv): Promise<ProxyEnvironment>;
|
|
12
18
|
//# sourceMappingURL=proxy.d.ts.map
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,CAAC;CACrC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAID,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,GAAE,MAAsB,GAC1B,MAAM,GAAG,SAAS,CAIpB;AAiBD,wBAAsB,QAAQ,CAC5B,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,WAAW,EACvD,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,YAAY,GACnC,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAW7F"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { createInterface } from "node:readline";
|
|
2
2
|
import { discoverDeployment } from "./discovery.js";
|
|
3
|
+
import { DEFAULT_BRAND } from "./install/render.js";
|
|
3
4
|
import { McpCallError, postRpc } from "./mcp-client.js";
|
|
5
|
+
import { readProjectMarker } from "./project-marker.js";
|
|
4
6
|
const REQUEST_TIMEOUT_MS = 30_000;
|
|
7
|
+
// The repository's committed .jitera.json binds the workspace to a project;
|
|
8
|
+
// an explicit JITERA_PROJECT env always wins.
|
|
9
|
+
export function resolveProjectUuid(env, cwd = process.cwd()) {
|
|
10
|
+
const override = (env["JITERA_PROJECT"] ?? "").trim();
|
|
11
|
+
if (override)
|
|
12
|
+
return override;
|
|
13
|
+
return readProjectMarker(cwd)?.project;
|
|
14
|
+
}
|
|
5
15
|
function isNotification(request) {
|
|
6
16
|
return request.id === undefined || request.id === null;
|
|
7
17
|
}
|
|
8
18
|
function errorResponse(id, code, message) {
|
|
9
19
|
return JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
|
|
10
20
|
}
|
|
11
|
-
|
|
21
|
+
function injectInstructions(response, instructions) {
|
|
22
|
+
const result = response?.result;
|
|
23
|
+
if (result && typeof result === "object" && !result["instructions"]) {
|
|
24
|
+
result["instructions"] = instructions;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function runProxy({ url, apiKey, instructions, projectUuid }, { input, output, log }) {
|
|
12
28
|
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
13
29
|
for await (const line of lines) {
|
|
14
30
|
const trimmed = line.trim();
|
|
@@ -24,7 +40,7 @@ export async function runProxy({ url, apiKey }, { input, output, log }) {
|
|
|
24
40
|
}
|
|
25
41
|
let response;
|
|
26
42
|
try {
|
|
27
|
-
response = await postRpc(request, { url, apiKey, timeoutMs: REQUEST_TIMEOUT_MS });
|
|
43
|
+
response = await postRpc(request, { url, apiKey, projectUuid, timeoutMs: REQUEST_TIMEOUT_MS });
|
|
28
44
|
}
|
|
29
45
|
catch (error) {
|
|
30
46
|
const message = error instanceof McpCallError ? error.message : String(error);
|
|
@@ -34,6 +50,9 @@ export async function runProxy({ url, apiKey }, { input, output, log }) {
|
|
|
34
50
|
}
|
|
35
51
|
continue;
|
|
36
52
|
}
|
|
53
|
+
if (request.method === "initialize" && instructions) {
|
|
54
|
+
injectInstructions(response, instructions);
|
|
55
|
+
}
|
|
37
56
|
if (!isNotification(request) && response) {
|
|
38
57
|
output.write(`${JSON.stringify(response)}\n`);
|
|
39
58
|
}
|
|
@@ -43,12 +62,12 @@ export async function configFromEnvironment(env) {
|
|
|
43
62
|
const apiKey = env["JITERA_API_KEY"] ?? "";
|
|
44
63
|
const override = env["JITERA_MCP_URL"] ?? "";
|
|
45
64
|
if (override)
|
|
46
|
-
return { url: override, apiKey };
|
|
65
|
+
return { url: override, apiKey, brand: DEFAULT_BRAND };
|
|
47
66
|
const environment = env["JITERA_ENVIRONMENT"] ?? "";
|
|
48
67
|
const deployment = await discoverDeployment({
|
|
49
68
|
environment,
|
|
50
69
|
studioUrl: env["JITERA_STUDIO_URL"],
|
|
51
70
|
});
|
|
52
|
-
return { url: deployment.mcpUrl, apiKey };
|
|
71
|
+
return { url: deployment.mcpUrl, apiKey, brand: deployment.brand };
|
|
53
72
|
}
|
|
54
73
|
//# sourceMappingURL=proxy.js.map
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAuB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/select.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Theme } from "./theme.ts";
|
|
2
|
+
export declare class SelectCancelledError extends Error {
|
|
3
|
+
readonly name = "SelectCancelledError";
|
|
4
|
+
constructor();
|
|
5
|
+
}
|
|
6
|
+
export declare class InvalidChoiceError extends Error {
|
|
7
|
+
readonly name = "InvalidChoiceError";
|
|
8
|
+
readonly answer: string;
|
|
9
|
+
constructor(answer: string);
|
|
10
|
+
}
|
|
11
|
+
export declare function chooseFrom<T>({ items, prompt, label, theme, }: {
|
|
12
|
+
readonly items: readonly T[];
|
|
13
|
+
readonly prompt: string;
|
|
14
|
+
readonly label: (item: T) => string;
|
|
15
|
+
readonly theme: Theme;
|
|
16
|
+
}): Promise<T>;
|
|
17
|
+
export interface SelectInput {
|
|
18
|
+
setRawMode?(mode: boolean): unknown;
|
|
19
|
+
resume?(): unknown;
|
|
20
|
+
pause?(): unknown;
|
|
21
|
+
on(event: "data", listener: (chunk: Buffer | string) => void): unknown;
|
|
22
|
+
off(event: "data", listener: (chunk: Buffer | string) => void): unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface SelectOutput {
|
|
25
|
+
write(chunk: string): unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface SelectOptions<T> {
|
|
28
|
+
readonly items: readonly T[];
|
|
29
|
+
readonly prompt: string;
|
|
30
|
+
readonly label: (item: T) => string;
|
|
31
|
+
readonly theme: Theme;
|
|
32
|
+
readonly input: SelectInput;
|
|
33
|
+
readonly output: SelectOutput;
|
|
34
|
+
}
|
|
35
|
+
export declare function interactiveSelect<T>({ items, prompt, label, theme, input, output }: SelectOptions<T>): Promise<T>;
|
|
36
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../src/select.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,0BAA0B;IAEhD,cAEC;CACF;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAkB,IAAI,wBAAwB;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAGzB;CACF;AAGD,wBAAsB,UAAU,CAAC,CAAC,EAAE,EAClC,KAAK,EACL,MAAM,EACN,KAAK,EACL,KAAK,GACN,EAAE;IACD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBb;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACpC,MAAM,CAAC,IAAI,OAAO,CAAC;IACnB,KAAK,CAAC,IAAI,OAAO,CAAC;IAClB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;IACvE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;CACzE;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAqBD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA2DjH"}
|
package/dist/select.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
export class SelectCancelledError extends Error {
|
|
3
|
+
name = "SelectCancelledError";
|
|
4
|
+
constructor() {
|
|
5
|
+
super("selection cancelled");
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class InvalidChoiceError extends Error {
|
|
9
|
+
name = "InvalidChoiceError";
|
|
10
|
+
answer;
|
|
11
|
+
constructor(answer) {
|
|
12
|
+
super(`"${answer}" is not one of the listed options.`);
|
|
13
|
+
this.answer = answer;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// Arrow-key selection on a terminal, a numbered prompt everywhere else.
|
|
17
|
+
export async function chooseFrom({ items, prompt, label, theme, }) {
|
|
18
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
19
|
+
return interactiveSelect({
|
|
20
|
+
items,
|
|
21
|
+
prompt,
|
|
22
|
+
label,
|
|
23
|
+
theme,
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
process.stdout.write(`\n ${theme.bold(prompt)}\n\n`);
|
|
29
|
+
items.forEach((item, index) => {
|
|
30
|
+
process.stdout.write(` ${theme.accent(String(index + 1).padStart(2))} ${label(item)}\n`);
|
|
31
|
+
});
|
|
32
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
33
|
+
const answer = (await rl.question(`\n ${theme.dim(`Number [1-${items.length}]`)} `)).trim();
|
|
34
|
+
rl.close();
|
|
35
|
+
const picked = items[Number(answer) - 1];
|
|
36
|
+
if (!picked)
|
|
37
|
+
throw new InvalidChoiceError(answer);
|
|
38
|
+
return picked;
|
|
39
|
+
}
|
|
40
|
+
function parseKey(sequence, count) {
|
|
41
|
+
if (sequence === "" || sequence === "")
|
|
42
|
+
return { kind: "cancel" };
|
|
43
|
+
if (sequence === "\r" || sequence === "\n" || sequence === "\r\n")
|
|
44
|
+
return { kind: "confirm" };
|
|
45
|
+
if (sequence === "[A" || sequence === "OA" || sequence === "k")
|
|
46
|
+
return { kind: "move", delta: -1 };
|
|
47
|
+
if (sequence === "[B" || sequence === "OB" || sequence === "j")
|
|
48
|
+
return { kind: "move", delta: 1 };
|
|
49
|
+
if (/^[1-9]$/.test(sequence)) {
|
|
50
|
+
const index = Number(sequence) - 1;
|
|
51
|
+
if (index < count)
|
|
52
|
+
return { kind: "jump", index };
|
|
53
|
+
}
|
|
54
|
+
return { kind: "none" };
|
|
55
|
+
}
|
|
56
|
+
export function interactiveSelect({ items, prompt, label, theme, input, output }) {
|
|
57
|
+
if (items.length === 0) {
|
|
58
|
+
return Promise.reject(new Error("there is nothing to select from"));
|
|
59
|
+
}
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
let highlighted = 0;
|
|
62
|
+
const row = (index) => {
|
|
63
|
+
const text = label(items[index]);
|
|
64
|
+
return index === highlighted ? ` ${theme.accent("❯")} ${theme.bold(text)}` : ` ${text}`;
|
|
65
|
+
};
|
|
66
|
+
const paintItems = () => {
|
|
67
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
68
|
+
output.write(`\r[2K${row(index)}\n`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const repaint = () => {
|
|
72
|
+
output.write(`[${items.length}A`);
|
|
73
|
+
paintItems();
|
|
74
|
+
};
|
|
75
|
+
// Everything drawn (blank line, prompt, blank line, one line per item) is
|
|
76
|
+
// erased again on the way out, so the caller decides what remains on screen.
|
|
77
|
+
const finish = () => {
|
|
78
|
+
input.off("data", onData);
|
|
79
|
+
input.setRawMode?.(false);
|
|
80
|
+
input.pause?.();
|
|
81
|
+
output.write(`[${items.length + 3}A\r[J`);
|
|
82
|
+
output.write("[?25h");
|
|
83
|
+
};
|
|
84
|
+
const onData = (chunk) => {
|
|
85
|
+
const action = parseKey(chunk.toString(), items.length);
|
|
86
|
+
if (action.kind === "move") {
|
|
87
|
+
highlighted = (highlighted + action.delta + items.length) % items.length;
|
|
88
|
+
repaint();
|
|
89
|
+
}
|
|
90
|
+
else if (action.kind === "jump") {
|
|
91
|
+
highlighted = action.index;
|
|
92
|
+
repaint();
|
|
93
|
+
}
|
|
94
|
+
else if (action.kind === "confirm") {
|
|
95
|
+
finish();
|
|
96
|
+
resolve(items[highlighted]);
|
|
97
|
+
}
|
|
98
|
+
else if (action.kind === "cancel") {
|
|
99
|
+
finish();
|
|
100
|
+
reject(new SelectCancelledError());
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
output.write("[?25l");
|
|
104
|
+
output.write(`\n ${theme.bold(prompt)} ${theme.dim("↑/↓ then enter")}\n\n`);
|
|
105
|
+
paintItems();
|
|
106
|
+
input.setRawMode?.(true);
|
|
107
|
+
input.resume?.();
|
|
108
|
+
input.on("data", onData);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=select.js.map
|