@arizeai/phoenix-cli 1.5.3 → 1.6.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/build/pxi/App.d.ts +22 -0
- package/build/pxi/App.d.ts.map +1 -0
- package/build/pxi/App.js +328 -0
- package/build/pxi/App.js.map +1 -0
- package/build/pxi/client.d.ts +77 -0
- package/build/pxi/client.d.ts.map +1 -0
- package/build/pxi/client.js +170 -0
- package/build/pxi/client.js.map +1 -0
- package/build/pxi/commands.d.ts +37 -0
- package/build/pxi/commands.d.ts.map +1 -0
- package/build/pxi/commands.js +61 -0
- package/build/pxi/commands.js.map +1 -0
- package/build/pxi/index.d.ts +14 -0
- package/build/pxi/index.d.ts.map +1 -0
- package/build/pxi/index.js +36 -0
- package/build/pxi/index.js.map +1 -0
- package/build/pxi/inkMarkdown.d.ts +17 -0
- package/build/pxi/inkMarkdown.d.ts.map +1 -0
- package/build/pxi/inkMarkdown.js +22 -0
- package/build/pxi/inkMarkdown.js.map +1 -0
- package/build/pxi/markdown.d.ts +24 -0
- package/build/pxi/markdown.d.ts.map +1 -0
- package/build/pxi/markdown.js +115 -0
- package/build/pxi/markdown.js.map +1 -0
- package/build/pxi/options.d.ts +64 -0
- package/build/pxi/options.d.ts.map +1 -0
- package/build/pxi/options.js +148 -0
- package/build/pxi/options.js.map +1 -0
- package/build/pxi/preflight.d.ts +88 -0
- package/build/pxi/preflight.d.ts.map +1 -0
- package/build/pxi/preflight.js +255 -0
- package/build/pxi/preflight.js.map +1 -0
- package/build/pxi/tokenUsage.d.ts +35 -0
- package/build/pxi/tokenUsage.d.ts.map +1 -0
- package/build/pxi/tokenUsage.js +62 -0
- package/build/pxi/tokenUsage.js.map +1 -0
- package/build/pxi/toolProgress.d.ts +37 -0
- package/build/pxi/toolProgress.d.ts.map +1 -0
- package/build/pxi/toolProgress.js +71 -0
- package/build/pxi/toolProgress.js.map +1 -0
- package/build/pxi/types.d.ts +123 -0
- package/build/pxi/types.d.ts.map +1 -0
- package/build/pxi/types.js +2 -0
- package/build/pxi/types.js.map +1 -0
- package/package.json +14 -5
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side slash commands for the PXI chat UI.
|
|
3
|
+
*
|
|
4
|
+
* Commands are intercepted before the input reaches the server, so they run
|
|
5
|
+
* instantly and never consume a network round-trip.
|
|
6
|
+
*/
|
|
7
|
+
export type CommandContext = {
|
|
8
|
+
clearMessages: () => void;
|
|
9
|
+
exit: () => void;
|
|
10
|
+
};
|
|
11
|
+
export type PxiCommand = {
|
|
12
|
+
/** The name after the leading slash, e.g. "clear" for `/clear`. */
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
handler: (args: string, ctx: CommandContext) => void;
|
|
16
|
+
};
|
|
17
|
+
export declare const SLASH_COMMANDS: PxiCommand[];
|
|
18
|
+
export type SlashCommandResult = {
|
|
19
|
+
type: "unknown";
|
|
20
|
+
name: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: "handled";
|
|
23
|
+
} | {
|
|
24
|
+
type: "help";
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Parse and dispatch a slash command string. Returns a result describing what
|
|
28
|
+
* happened so the caller can react (e.g. display an error for unknown commands).
|
|
29
|
+
*
|
|
30
|
+
* @param input - The full draft string, expected to start with `/`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runSlashCommand(input: string, ctx: CommandContext): SlashCommandResult;
|
|
33
|
+
/** Return the command name being typed, or null if the input isn't a slash command. */
|
|
34
|
+
export declare function getSlashCommandName(draft: string): string | null;
|
|
35
|
+
/** Return commands whose names start with the given prefix (case-insensitive). */
|
|
36
|
+
export declare function matchingCommands(prefix: string): PxiCommand[];
|
|
37
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/pxi/commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,UAAU,EAkBtC,CAAC;AAIF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,cAAc,GAClB,kBAAkB,CAoBpB;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhE;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAG7D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side slash commands for the PXI chat UI.
|
|
3
|
+
*
|
|
4
|
+
* Commands are intercepted before the input reaches the server, so they run
|
|
5
|
+
* instantly and never consume a network round-trip.
|
|
6
|
+
*/
|
|
7
|
+
export const SLASH_COMMANDS = [
|
|
8
|
+
{
|
|
9
|
+
name: "clear",
|
|
10
|
+
description: "Clear the conversation history",
|
|
11
|
+
handler: (_args, ctx) => ctx.clearMessages(),
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "exit",
|
|
15
|
+
description: "Exit PXI",
|
|
16
|
+
handler: (_args, ctx) => ctx.exit(),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "help",
|
|
20
|
+
description: "Show available slash commands",
|
|
21
|
+
handler: (_args, _ctx) => {
|
|
22
|
+
// handled specially in the UI to print the command list
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
const COMMAND_MAP = new Map(SLASH_COMMANDS.map((c) => [c.name, c]));
|
|
27
|
+
/**
|
|
28
|
+
* Parse and dispatch a slash command string. Returns a result describing what
|
|
29
|
+
* happened so the caller can react (e.g. display an error for unknown commands).
|
|
30
|
+
*
|
|
31
|
+
* @param input - The full draft string, expected to start with `/`.
|
|
32
|
+
*/
|
|
33
|
+
export function runSlashCommand(input, ctx) {
|
|
34
|
+
const withoutSlash = input.slice(1).trimStart();
|
|
35
|
+
const spaceIndex = withoutSlash.indexOf(" ");
|
|
36
|
+
const name = (spaceIndex === -1 ? withoutSlash : withoutSlash.slice(0, spaceIndex)).toLowerCase();
|
|
37
|
+
const args = spaceIndex === -1 ? "" : withoutSlash.slice(spaceIndex + 1).trim();
|
|
38
|
+
if (name === "help") {
|
|
39
|
+
return { type: "help" };
|
|
40
|
+
}
|
|
41
|
+
const command = COMMAND_MAP.get(name);
|
|
42
|
+
if (!command) {
|
|
43
|
+
return { type: "unknown", name };
|
|
44
|
+
}
|
|
45
|
+
command.handler(args, ctx);
|
|
46
|
+
return { type: "handled" };
|
|
47
|
+
}
|
|
48
|
+
/** Return the command name being typed, or null if the input isn't a slash command. */
|
|
49
|
+
export function getSlashCommandName(draft) {
|
|
50
|
+
if (!draft.startsWith("/"))
|
|
51
|
+
return null;
|
|
52
|
+
const rest = draft.slice(1);
|
|
53
|
+
const spaceIndex = rest.indexOf(" ");
|
|
54
|
+
return spaceIndex === -1 ? rest : rest.slice(0, spaceIndex);
|
|
55
|
+
}
|
|
56
|
+
/** Return commands whose names start with the given prefix (case-insensitive). */
|
|
57
|
+
export function matchingCommands(prefix) {
|
|
58
|
+
const lower = prefix.toLowerCase();
|
|
59
|
+
return SLASH_COMMANDS.filter((c) => c.name.startsWith(lower));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/pxi/commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,gCAAgC;QAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE;KAC7C;IACD;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,UAAU;QACvB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACpC;IACD;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,+BAA+B;QAC5C,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,wDAAwD;QAC1D,CAAC;KACF;CACF,CAAC;AAEF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAOpE;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,GAAmB;IAEnB,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,CACX,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CACrE,CAAC,WAAW,EAAE,CAAC;IAChB,MAAM,IAAI,GACR,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAErE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAC9D,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Entry point for the `pxi` command.
|
|
4
|
+
*
|
|
5
|
+
* Parses CLI flags into runtime options, runs the model preflight (verifying
|
|
6
|
+
* the chosen provider/model is available and credentialed on the Phoenix
|
|
7
|
+
* server) before anything is drawn, then mounts the Ink chat UI and blocks
|
|
8
|
+
* until the user exits. Preflight runs first so configuration problems surface
|
|
9
|
+
* as a clean error instead of a half-rendered terminal.
|
|
10
|
+
*/
|
|
11
|
+
export declare function main({ argv, }?: {
|
|
12
|
+
argv?: string[];
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pxi/index.tsx"],"names":[],"mappings":";AAWA;;;;;;;;GAQG;AACH,wBAAsB,IAAI,CAAC,EACzB,IAAmB,GACpB,GAAE;IACD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import { getExitCodeForError } from "../exitCodes.js";
|
|
5
|
+
import { writeError } from "../io.js";
|
|
6
|
+
import { PxiApp } from "./App.js";
|
|
7
|
+
import { parsePxiRuntimeOptions } from "./options.js";
|
|
8
|
+
import { runPxiModelPreflight } from "./preflight.js";
|
|
9
|
+
/**
|
|
10
|
+
* Entry point for the `pxi` command.
|
|
11
|
+
*
|
|
12
|
+
* Parses CLI flags into runtime options, runs the model preflight (verifying
|
|
13
|
+
* the chosen provider/model is available and credentialed on the Phoenix
|
|
14
|
+
* server) before anything is drawn, then mounts the Ink chat UI and blocks
|
|
15
|
+
* until the user exits. Preflight runs first so configuration problems surface
|
|
16
|
+
* as a clean error instead of a half-rendered terminal.
|
|
17
|
+
*/
|
|
18
|
+
export async function main({ argv = process.argv, } = {}) {
|
|
19
|
+
const options = await parsePxiRuntimeOptions({ argv });
|
|
20
|
+
await runPxiModelPreflight({ options });
|
|
21
|
+
const instance = render(_jsx(PxiApp, { options: options }), {
|
|
22
|
+
exitOnCtrlC: false,
|
|
23
|
+
kittyKeyboard: {
|
|
24
|
+
mode: "auto",
|
|
25
|
+
flags: ["disambiguateEscapeCodes"],
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
await instance.waitUntilExit();
|
|
29
|
+
}
|
|
30
|
+
void main().catch((error) => {
|
|
31
|
+
writeError({
|
|
32
|
+
message: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
33
|
+
});
|
|
34
|
+
process.exit(getExitCodeForError(error));
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pxi/index.tsx"],"names":[],"mappings":";;AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAG7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,EACzB,IAAI,GAAG,OAAO,CAAC,IAAI,MAGjB,EAAE;IACJ,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,oBAAoB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,MAAM,IAAC,OAAO,EAAE,OAAO,GAAI,EAAE;QACpD,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE;YACb,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,CAAC,yBAAyB,CAAC;SACnC;KACF,CAAC,CAAC;IACH,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;AACjC,CAAC;AAED,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,UAAU,CAAC;QACT,OAAO,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;KAC5E,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Renders markdown text as styled terminal output inside an Ink `<Text>`.
|
|
4
|
+
*
|
|
5
|
+
* Modeled on the `ink-markdown` component
|
|
6
|
+
* (https://github.com/cameronhunter/ink-markdown, MIT). That package is
|
|
7
|
+
* published as CommonJS and `require()`s Ink internally, which is incompatible
|
|
8
|
+
* with Ink 6 (pure ESM with top-level await — `require()` throws
|
|
9
|
+
* `ERR_REQUIRE_ASYNC_MODULE`). We keep its API — `<Markdown>{text}</Markdown>` —
|
|
10
|
+
* but render through {@link formatMarkdownForTerminal}, which uses the current
|
|
11
|
+
* `marked` + `marked-terminal` API and preserves our width-aware table layout.
|
|
12
|
+
*/
|
|
13
|
+
export declare function Markdown({ children, phoenixBaseUrl, }: {
|
|
14
|
+
children: string;
|
|
15
|
+
phoenixBaseUrl?: string;
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
//# sourceMappingURL=inkMarkdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inkMarkdown.d.ts","sourceRoot":"","sources":["../../src/pxi/inkMarkdown.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,qBAMA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from "ink";
|
|
3
|
+
import { formatMarkdownForTerminal } from "./markdown.js";
|
|
4
|
+
/**
|
|
5
|
+
* Renders markdown text as styled terminal output inside an Ink `<Text>`.
|
|
6
|
+
*
|
|
7
|
+
* Modeled on the `ink-markdown` component
|
|
8
|
+
* (https://github.com/cameronhunter/ink-markdown, MIT). That package is
|
|
9
|
+
* published as CommonJS and `require()`s Ink internally, which is incompatible
|
|
10
|
+
* with Ink 6 (pure ESM with top-level await — `require()` throws
|
|
11
|
+
* `ERR_REQUIRE_ASYNC_MODULE`). We keep its API — `<Markdown>{text}</Markdown>` —
|
|
12
|
+
* but render through {@link formatMarkdownForTerminal}, which uses the current
|
|
13
|
+
* `marked` + `marked-terminal` API and preserves our width-aware table layout.
|
|
14
|
+
*/
|
|
15
|
+
export function Markdown({ children, phoenixBaseUrl, }) {
|
|
16
|
+
const rendered = formatMarkdownForTerminal({
|
|
17
|
+
text: children,
|
|
18
|
+
phoenixBaseUrl,
|
|
19
|
+
});
|
|
20
|
+
return _jsx(Text, { children: rendered || " " });
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=inkMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inkMarkdown.js","sourceRoot":"","sources":["../../src/pxi/inkMarkdown.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAG3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,QAAQ,EACR,cAAc,GAIf;IACC,MAAM,QAAQ,GAAG,yBAAyB,CAAC;QACzC,IAAI,EAAE,QAAQ;QACd,cAAc;KACf,CAAC,CAAC;IACH,OAAO,KAAC,IAAI,cAAE,QAAQ,IAAI,GAAG,GAAQ,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a markdown link/image href against the Phoenix base URL.
|
|
3
|
+
*
|
|
4
|
+
* Absolute, fragment, and protocol-relative hrefs pass through unchanged, as
|
|
5
|
+
* does any href when no (valid) base URL is configured. Root-relative paths
|
|
6
|
+
* (`/foo`) are joined onto the base URL's path prefix so a Phoenix deployed
|
|
7
|
+
* under a sub-path still produces correct links; other relative paths resolve
|
|
8
|
+
* against the base path as usual.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolvePhoenixMarkdownHref({ href, phoenixBaseUrl, }: {
|
|
11
|
+
href: string;
|
|
12
|
+
phoenixBaseUrl?: string;
|
|
13
|
+
}): string;
|
|
14
|
+
/**
|
|
15
|
+
* Render markdown to terminal-styled text. The main entry point for callers:
|
|
16
|
+
* defaults `maxWidth` to the current terminal column count and absolutizes
|
|
17
|
+
* relative links against `phoenixBaseUrl` when provided.
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatMarkdownForTerminal({ text, maxWidth, phoenixBaseUrl, }: {
|
|
20
|
+
text: string;
|
|
21
|
+
maxWidth?: number;
|
|
22
|
+
phoenixBaseUrl?: string;
|
|
23
|
+
}): string;
|
|
24
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/pxi/markdown.ts"],"names":[],"mappings":"AAmDA;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,IAAI,EACJ,cAAc,GACf,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAkBT;AA2DD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,QAA6C,EAC7C,cAAc,GACf,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAET"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Marked } from "marked";
|
|
2
|
+
import { markedTerminal } from "marked-terminal";
|
|
3
|
+
/**
|
|
4
|
+
* Render assistant markdown for the terminal.
|
|
5
|
+
*
|
|
6
|
+
* Wraps `marked` + `marked-terminal` to turn markdown into ANSI-styled text
|
|
7
|
+
* that fits the current terminal width. It also rewrites relative links against
|
|
8
|
+
* the Phoenix base URL so links the agent emits (e.g. `/projects/123`) become
|
|
9
|
+
* clickable absolute URLs pointing at the right Phoenix instance.
|
|
10
|
+
*/
|
|
11
|
+
// There is only ever one terminal width in play at a time, so a single cached
|
|
12
|
+
// renderer is enough to avoid re-registering the marked-terminal extension on
|
|
13
|
+
// every render. Rebuild it only when the width actually changes (e.g. resize),
|
|
14
|
+
// which keeps this bounded instead of accumulating an entry per resize.
|
|
15
|
+
let cachedRenderer = null;
|
|
16
|
+
/**
|
|
17
|
+
* Whether an href should be left untouched: fragment (`#`), protocol-relative
|
|
18
|
+
* (`//`), or already carrying a scheme (`https:`, `mailto:`, …). Only truly
|
|
19
|
+
* relative paths get resolved against the Phoenix base URL.
|
|
20
|
+
*/
|
|
21
|
+
function isAbsoluteOrSpecialHref(href) {
|
|
22
|
+
return (href.startsWith("#") ||
|
|
23
|
+
href.startsWith("//") ||
|
|
24
|
+
/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(href));
|
|
25
|
+
}
|
|
26
|
+
function getPhoenixBaseUrl(phoenixBaseUrl) {
|
|
27
|
+
const trimmedBaseUrl = phoenixBaseUrl?.trim();
|
|
28
|
+
if (!trimmedBaseUrl) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return new URL(trimmedBaseUrl);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function getOrigin(url) {
|
|
39
|
+
return `${url.protocol}//${url.host}`;
|
|
40
|
+
}
|
|
41
|
+
function getNormalizedBasePath(url) {
|
|
42
|
+
return url.pathname === "/" ? "" : url.pathname.replace(/\/+$/, "");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a markdown link/image href against the Phoenix base URL.
|
|
46
|
+
*
|
|
47
|
+
* Absolute, fragment, and protocol-relative hrefs pass through unchanged, as
|
|
48
|
+
* does any href when no (valid) base URL is configured. Root-relative paths
|
|
49
|
+
* (`/foo`) are joined onto the base URL's path prefix so a Phoenix deployed
|
|
50
|
+
* under a sub-path still produces correct links; other relative paths resolve
|
|
51
|
+
* against the base path as usual.
|
|
52
|
+
*/
|
|
53
|
+
export function resolvePhoenixMarkdownHref({ href, phoenixBaseUrl, }) {
|
|
54
|
+
const trimmedHref = href.trim();
|
|
55
|
+
if (!trimmedHref || isAbsoluteOrSpecialHref(trimmedHref)) {
|
|
56
|
+
return href;
|
|
57
|
+
}
|
|
58
|
+
const baseUrl = getPhoenixBaseUrl(phoenixBaseUrl);
|
|
59
|
+
if (!baseUrl) {
|
|
60
|
+
return href;
|
|
61
|
+
}
|
|
62
|
+
const origin = getOrigin(baseUrl);
|
|
63
|
+
const basePath = getNormalizedBasePath(baseUrl);
|
|
64
|
+
if (trimmedHref.startsWith("/")) {
|
|
65
|
+
return new URL(`${basePath}${trimmedHref}`, origin).toString();
|
|
66
|
+
}
|
|
67
|
+
return new URL(trimmedHref, `${origin}${basePath}/`).toString();
|
|
68
|
+
}
|
|
69
|
+
function absolutizeMarkdownLinkToken({ token, phoenixBaseUrl, }) {
|
|
70
|
+
if (token.type !== "link" && token.type !== "image") {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
token.href = resolvePhoenixMarkdownHref({
|
|
74
|
+
href: token.href,
|
|
75
|
+
phoenixBaseUrl,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get a `marked` renderer configured for the given terminal width, reusing the
|
|
80
|
+
* cached one when the width is unchanged (see {@link cachedRenderer}). Text
|
|
81
|
+
* reflow is disabled so the agent's own line breaks are preserved.
|
|
82
|
+
*/
|
|
83
|
+
function getMarkedRenderer(width) {
|
|
84
|
+
if (cachedRenderer?.width === width) {
|
|
85
|
+
return cachedRenderer.renderer;
|
|
86
|
+
}
|
|
87
|
+
const renderer = new Marked();
|
|
88
|
+
renderer.use(markedTerminal(Number.isFinite(width) ? { width, reflowText: false } : {}));
|
|
89
|
+
cachedRenderer = { width, renderer };
|
|
90
|
+
return renderer;
|
|
91
|
+
}
|
|
92
|
+
function renderMarkdownBlock({ text, maxWidth, phoenixBaseUrl, }) {
|
|
93
|
+
if (text.trim() === "") {
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
const renderer = getMarkedRenderer(maxWidth);
|
|
97
|
+
// The marked-terminal extension renders synchronously, so `parse` returns a
|
|
98
|
+
// string (marked's types don't narrow this from the `async: false` option).
|
|
99
|
+
const rendered = renderer.parse(text, {
|
|
100
|
+
async: false,
|
|
101
|
+
walkTokens: (token) => {
|
|
102
|
+
absolutizeMarkdownLinkToken({ token, phoenixBaseUrl });
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return rendered.replace(/\n+$/, "");
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Render markdown to terminal-styled text. The main entry point for callers:
|
|
109
|
+
* defaults `maxWidth` to the current terminal column count and absolutizes
|
|
110
|
+
* relative links against `phoenixBaseUrl` when provided.
|
|
111
|
+
*/
|
|
112
|
+
export function formatMarkdownForTerminal({ text, maxWidth = process.stdout.columns ?? Infinity, phoenixBaseUrl, }) {
|
|
113
|
+
return renderMarkdownBlock({ text, maxWidth, phoenixBaseUrl });
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/pxi/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { BuiltInProvider, ModelSelection, PxiRuntimeOptions } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_PXI_PROVIDER: BuiltInProvider;
|
|
4
|
+
export declare const DEFAULT_PXI_MODEL = "claude-opus-4-8";
|
|
5
|
+
export declare const BUILT_IN_PROVIDERS: readonly ["ANTHROPIC", "AWS", "AZURE_OPENAI", "CEREBRAS", "DEEPSEEK", "FIREWORKS", "GOOGLE", "GROQ", "MOONSHOT", "OLLAMA", "OPENAI", "PERPLEXITY", "TOGETHER", "XAI"];
|
|
6
|
+
type RawPxiOptions = {
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
profile?: string;
|
|
10
|
+
provider?: string;
|
|
11
|
+
model?: string;
|
|
12
|
+
customProviderId?: string;
|
|
13
|
+
skipModelPreflight?: boolean;
|
|
14
|
+
enableWebAccess?: boolean;
|
|
15
|
+
enableSubagents?: boolean;
|
|
16
|
+
enableGraphqlMutations?: boolean;
|
|
17
|
+
bypassEdits?: boolean;
|
|
18
|
+
ingestTraces?: boolean;
|
|
19
|
+
exportRemoteTraces?: boolean;
|
|
20
|
+
attachUserId?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type ResolvePxiRuntimeOptionsInput = {
|
|
23
|
+
cliOptions: RawPxiOptions;
|
|
24
|
+
sessionId?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Turn the raw `--provider` / `--model` / `--custom-provider-id` flags into a
|
|
28
|
+
* normalized {@link ModelSelection}.
|
|
29
|
+
*
|
|
30
|
+
* Passing `--custom-provider-id` selects a custom provider and requires an
|
|
31
|
+
* explicit `--model`. Otherwise a built-in provider is used: its name is
|
|
32
|
+
* upper-cased and validated against {@link BUILT_IN_PROVIDERS}, and the model
|
|
33
|
+
* falls back to {@link DEFAULT_PXI_MODEL}. Throws {@link InvalidArgumentError}
|
|
34
|
+
* for an unknown provider or a custom provider missing its model.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveModelSelection({ provider, model, customProviderId, }: {
|
|
37
|
+
provider?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
customProviderId?: string;
|
|
40
|
+
}): ModelSelection;
|
|
41
|
+
/**
|
|
42
|
+
* Build the fully-resolved {@link PxiRuntimeOptions} for a session from parsed
|
|
43
|
+
* CLI flags. This layers the endpoint/api-key/profile through
|
|
44
|
+
* {@link resolveConfig}, resolves the model selection, and coerces the boolean
|
|
45
|
+
* feature flags into their final shape. A fresh `sessionId` is generated unless
|
|
46
|
+
* one is supplied (tests pass a fixed id for determinism).
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolvePxiRuntimeOptions({ cliOptions, sessionId, }: ResolvePxiRuntimeOptionsInput): PxiRuntimeOptions;
|
|
49
|
+
/**
|
|
50
|
+
* Define the `pxi` Commander program: its flags, defaults, and help text.
|
|
51
|
+
* Kept separate from parsing so tests can introspect the command definition
|
|
52
|
+
* without executing it.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createPxiProgram(): Command;
|
|
55
|
+
/**
|
|
56
|
+
* Parse `argv` with the `pxi` program and resolve it into runtime options. This
|
|
57
|
+
* is the one-call path used by the entry point; `createPxiProgram` and
|
|
58
|
+
* `resolvePxiRuntimeOptions` are exposed separately for finer-grained testing.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parsePxiRuntimeOptions({ argv, }?: {
|
|
61
|
+
argv?: string[];
|
|
62
|
+
}): Promise<PxiRuntimeOptions>;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/pxi/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAEd,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,oBAAoB,EAAE,eAA6B,CAAC;AACjE,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,eAAO,MAAM,kBAAkB,uKAegB,CAAC;AAEhD,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,UAAU,EAAE,aAAa,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAcF;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,gBAAgB,GACjB,EAAE;IACD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,cAAc,CAgCjB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,UAAU,EACV,SAA+B,GAChC,EAAE,6BAA6B,GAAG,iBAAiB,CA8BnD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CA+C1C;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,IAAmB,GACpB,GAAE;IACD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAMlC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { resolveConfig } from "../config.js";
|
|
3
|
+
import { InvalidArgumentError } from "../exitCodes.js";
|
|
4
|
+
export const DEFAULT_PXI_PROVIDER = "ANTHROPIC";
|
|
5
|
+
export const DEFAULT_PXI_MODEL = "claude-opus-4-8";
|
|
6
|
+
export const BUILT_IN_PROVIDERS = [
|
|
7
|
+
"ANTHROPIC",
|
|
8
|
+
"AWS",
|
|
9
|
+
"AZURE_OPENAI",
|
|
10
|
+
"CEREBRAS",
|
|
11
|
+
"DEEPSEEK",
|
|
12
|
+
"FIREWORKS",
|
|
13
|
+
"GOOGLE",
|
|
14
|
+
"GROQ",
|
|
15
|
+
"MOONSHOT",
|
|
16
|
+
"OLLAMA",
|
|
17
|
+
"OPENAI",
|
|
18
|
+
"PERPLEXITY",
|
|
19
|
+
"TOGETHER",
|
|
20
|
+
"XAI",
|
|
21
|
+
];
|
|
22
|
+
function getExpectedProviderMessage() {
|
|
23
|
+
return `Expected one of: ${BUILT_IN_PROVIDERS.join(", ")}.`;
|
|
24
|
+
}
|
|
25
|
+
function isBuiltInProvider(provider) {
|
|
26
|
+
return BUILT_IN_PROVIDERS.includes(provider);
|
|
27
|
+
}
|
|
28
|
+
function normalizeBuiltInProvider({ provider }) {
|
|
29
|
+
return provider.toUpperCase();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Turn the raw `--provider` / `--model` / `--custom-provider-id` flags into a
|
|
33
|
+
* normalized {@link ModelSelection}.
|
|
34
|
+
*
|
|
35
|
+
* Passing `--custom-provider-id` selects a custom provider and requires an
|
|
36
|
+
* explicit `--model`. Otherwise a built-in provider is used: its name is
|
|
37
|
+
* upper-cased and validated against {@link BUILT_IN_PROVIDERS}, and the model
|
|
38
|
+
* falls back to {@link DEFAULT_PXI_MODEL}. Throws {@link InvalidArgumentError}
|
|
39
|
+
* for an unknown provider or a custom provider missing its model.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveModelSelection({ provider, model, customProviderId, }) {
|
|
42
|
+
const trimmedModel = model?.trim();
|
|
43
|
+
const trimmedCustomProviderId = customProviderId?.trim();
|
|
44
|
+
if (trimmedCustomProviderId) {
|
|
45
|
+
if (!trimmedModel) {
|
|
46
|
+
throw new InvalidArgumentError("Missing required flag --model when --custom-provider-id is provided. Expected a non-empty model name.");
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
providerType: "custom",
|
|
50
|
+
providerId: trimmedCustomProviderId,
|
|
51
|
+
modelName: trimmedModel,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const rawSelectedProvider = (provider ?? DEFAULT_PXI_PROVIDER).trim();
|
|
55
|
+
const selectedProvider = normalizeBuiltInProvider({
|
|
56
|
+
provider: rawSelectedProvider,
|
|
57
|
+
});
|
|
58
|
+
if (!isBuiltInProvider(selectedProvider)) {
|
|
59
|
+
throw new InvalidArgumentError(`Invalid value for --provider: ${rawSelectedProvider}. ${getExpectedProviderMessage()}`);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
providerType: "builtin",
|
|
63
|
+
provider: selectedProvider,
|
|
64
|
+
modelName: trimmedModel || DEFAULT_PXI_MODEL,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build the fully-resolved {@link PxiRuntimeOptions} for a session from parsed
|
|
69
|
+
* CLI flags. This layers the endpoint/api-key/profile through
|
|
70
|
+
* {@link resolveConfig}, resolves the model selection, and coerces the boolean
|
|
71
|
+
* feature flags into their final shape. A fresh `sessionId` is generated unless
|
|
72
|
+
* one is supplied (tests pass a fixed id for determinism).
|
|
73
|
+
*/
|
|
74
|
+
export function resolvePxiRuntimeOptions({ cliOptions, sessionId = crypto.randomUUID(), }) {
|
|
75
|
+
const config = resolveConfig({
|
|
76
|
+
cliOptions: {
|
|
77
|
+
endpoint: cliOptions.endpoint,
|
|
78
|
+
apiKey: cliOptions.apiKey,
|
|
79
|
+
},
|
|
80
|
+
profileName: cliOptions.profile,
|
|
81
|
+
});
|
|
82
|
+
const modelSelection = resolveModelSelection({
|
|
83
|
+
provider: cliOptions.provider,
|
|
84
|
+
model: cliOptions.model,
|
|
85
|
+
customProviderId: cliOptions.customProviderId,
|
|
86
|
+
});
|
|
87
|
+
const editPermission = cliOptions.bypassEdits
|
|
88
|
+
? "bypass"
|
|
89
|
+
: "manual";
|
|
90
|
+
return {
|
|
91
|
+
sessionId,
|
|
92
|
+
config,
|
|
93
|
+
modelSelection,
|
|
94
|
+
skipModelPreflight: Boolean(cliOptions.skipModelPreflight),
|
|
95
|
+
enableWebAccess: Boolean(cliOptions.enableWebAccess),
|
|
96
|
+
enableSubagents: Boolean(cliOptions.enableSubagents),
|
|
97
|
+
enableGraphqlMutations: Boolean(cliOptions.enableGraphqlMutations),
|
|
98
|
+
editPermission,
|
|
99
|
+
ingestTraces: Boolean(cliOptions.ingestTraces),
|
|
100
|
+
exportRemoteTraces: Boolean(cliOptions.exportRemoteTraces),
|
|
101
|
+
attachUserId: Boolean(cliOptions.attachUserId),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Define the `pxi` Commander program: its flags, defaults, and help text.
|
|
106
|
+
* Kept separate from parsing so tests can introspect the command definition
|
|
107
|
+
* without executing it.
|
|
108
|
+
*/
|
|
109
|
+
export function createPxiProgram() {
|
|
110
|
+
const program = new Command();
|
|
111
|
+
program
|
|
112
|
+
.name("pxi")
|
|
113
|
+
.description("Open an interactive Phoenix PXI terminal chat.")
|
|
114
|
+
.option("--endpoint <url>", "Phoenix endpoint URL")
|
|
115
|
+
.option("--api-key <key>", "Phoenix API key")
|
|
116
|
+
.option("--profile <name>", "Phoenix CLI profile name")
|
|
117
|
+
.option("--provider <provider>", `Built-in model provider (${BUILT_IN_PROVIDERS.join("|")})`, DEFAULT_PXI_PROVIDER)
|
|
118
|
+
.option("--model <model>", `Model name (defaults to ${DEFAULT_PXI_MODEL} for built-in providers)`)
|
|
119
|
+
.option("--custom-provider-id <id>", "Custom provider ID")
|
|
120
|
+
.option("--skip-model-preflight", "Skip Phoenix model catalog and credential checks before launch")
|
|
121
|
+
.option("--enable-web-access", "Enable PXI web access context")
|
|
122
|
+
.option("--enable-subagents", "Enable PXI subagent context")
|
|
123
|
+
.option("--enable-graphql-mutations", "Allow server-agent GraphQL mutation tools")
|
|
124
|
+
.option("--bypass-edits", "Bypass manual edit approvals when supported")
|
|
125
|
+
.option("--ingest-traces", "Persist local PXI traces in Phoenix")
|
|
126
|
+
.option("--export-remote-traces", "Export PXI traces remotely")
|
|
127
|
+
.option("--attach-user-id", "Attach the authenticated Phoenix user to PXI traces")
|
|
128
|
+
.addHelpText("after", `
|
|
129
|
+
Examples:
|
|
130
|
+
pxi
|
|
131
|
+
pxi --endpoint http://localhost:6006 --provider OPENAI --model gpt-5.4
|
|
132
|
+
pxi --custom-provider-id provider-id --model custom-agent-model
|
|
133
|
+
`);
|
|
134
|
+
return program;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parse `argv` with the `pxi` program and resolve it into runtime options. This
|
|
138
|
+
* is the one-call path used by the entry point; `createPxiProgram` and
|
|
139
|
+
* `resolvePxiRuntimeOptions` are exposed separately for finer-grained testing.
|
|
140
|
+
*/
|
|
141
|
+
export async function parsePxiRuntimeOptions({ argv = process.argv, } = {}) {
|
|
142
|
+
const program = createPxiProgram();
|
|
143
|
+
await program.parseAsync(argv);
|
|
144
|
+
return resolvePxiRuntimeOptions({
|
|
145
|
+
cliOptions: program.opts(),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/pxi/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAQpD,MAAM,CAAC,MAAM,oBAAoB,GAAoB,WAAW,CAAC;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW;IACX,KAAK;IACL,cAAc;IACd,UAAU;IACV,UAAU;IACV,WAAW;IACX,QAAQ;IACR,MAAM;IACN,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,UAAU;IACV,KAAK;CACwC,CAAC;AAwBhD,SAAS,0BAA0B;IACjC,OAAO,oBAAoB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO,kBAAkB,CAAC,QAAQ,CAAC,QAA2B,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,wBAAwB,CAAC,EAAE,QAAQ,EAAwB;IAClE,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,gBAAgB,GAKjB;IACC,MAAM,YAAY,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IACnC,MAAM,uBAAuB,GAAG,gBAAgB,EAAE,IAAI,EAAE,CAAC;IAEzD,IAAI,uBAAuB,EAAE,CAAC;QAC5B,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,oBAAoB,CAC5B,uGAAuG,CACxG,CAAC;QACJ,CAAC;QACD,OAAO;YACL,YAAY,EAAE,QAAQ;YACtB,UAAU,EAAE,uBAAuB;YACnC,SAAS,EAAE,YAAY;SACxB,CAAC;IACJ,CAAC;IAED,MAAM,mBAAmB,GAAG,CAAC,QAAQ,IAAI,oBAAoB,CAAC,CAAC,IAAI,EAAE,CAAC;IACtE,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;QAChD,QAAQ,EAAE,mBAAmB;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,oBAAoB,CAC5B,iCAAiC,mBAAmB,KAAK,0BAA0B,EAAE,EAAE,CACxF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,YAAY,EAAE,SAAS;QACvB,QAAQ,EAAE,gBAAgB;QAC1B,SAAS,EAAE,YAAY,IAAI,iBAAiB;KAC7C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,EACvC,UAAU,EACV,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,GACD;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC;QAC3B,UAAU,EAAE;YACV,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B;QACD,WAAW,EAAE,UAAU,CAAC,OAAO;KAChC,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,qBAAqB,CAAC;QAC3C,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;KAC9C,CAAC,CAAC;IACH,MAAM,cAAc,GAAsB,UAAU,CAAC,WAAW;QAC9D,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC;IAEb,OAAO;QACL,SAAS;QACT,MAAM;QACN,cAAc;QACd,kBAAkB,EAAE,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC;QAC1D,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC;QACpD,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC;QACpD,sBAAsB,EAAE,OAAO,CAAC,UAAU,CAAC,sBAAsB,CAAC;QAClE,cAAc;QACd,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;QAC9C,kBAAkB,EAAE,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC;QAC1D,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,KAAK,CAAC;SACX,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;SAClD,MAAM,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;SAC5C,MAAM,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;SACtD,MAAM,CACL,uBAAuB,EACvB,4BAA4B,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAC3D,oBAAoB,CACrB;SACA,MAAM,CACL,iBAAiB,EACjB,2BAA2B,iBAAiB,0BAA0B,CACvE;SACA,MAAM,CAAC,2BAA2B,EAAE,oBAAoB,CAAC;SACzD,MAAM,CACL,wBAAwB,EACxB,gEAAgE,CACjE;SACA,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;SAC9D,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CACL,4BAA4B,EAC5B,2CAA2C,CAC5C;SACA,MAAM,CAAC,gBAAgB,EAAE,6CAA6C,CAAC;SACvE,MAAM,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;SAChE,MAAM,CAAC,wBAAwB,EAAE,4BAA4B,CAAC;SAC9D,MAAM,CACL,kBAAkB,EAClB,qDAAqD,CACtD;SACA,WAAW,CACV,OAAO,EACP;;;;;CAKL,CACI,CAAC;IAEJ,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,EAC3C,IAAI,GAAG,OAAO,CAAC,IAAI,MAGjB,EAAE;IACJ,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,wBAAwB,CAAC;QAC9B,UAAU,EAAE,OAAO,CAAC,IAAI,EAAiB;KAC1C,CAAC,CAAC;AACL,CAAC"}
|