@unigent/cli 0.1.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/LICENSE +21 -0
- package/README.md +470 -0
- package/dist/cli.js +132 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.js +44 -0
- package/dist/command.js.map +1 -0
- package/dist/environment.js +20 -0
- package/dist/environment.js.map +1 -0
- package/dist/error_message.js +59 -0
- package/dist/error_message.js.map +1 -0
- package/dist/format.js +38 -0
- package/dist/format.js.map +1 -0
- package/dist/node_version.js +9 -0
- package/dist/node_version.js.map +1 -0
- package/dist/protocol.js +72 -0
- package/dist/protocol.js.map +1 -0
- package/dist/register.js +78 -0
- package/dist/register.js.map +1 -0
- package/dist/script_runtime.js +29 -0
- package/dist/script_runtime.js.map +1 -0
- package/dist/tui/app.js +453 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/clipboard.js +31 -0
- package/dist/tui/clipboard.js.map +1 -0
- package/dist/tui/runner.js +116 -0
- package/dist/tui/runner.js.map +1 -0
- package/dist/tui/scroll.js +33 -0
- package/dist/tui/scroll.js.map +1 -0
- package/dist/tui/store.js +99 -0
- package/dist/tui/store.js.map +1 -0
- package/dist/tui/theme.js +35 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/tree.js +267 -0
- package/dist/tui/tree.js.map +1 -0
- package/dist/tui.js +63 -0
- package/dist/tui.js.map +1 -0
- package/node_modules/@unigent/core/dist/adapter_process.d.ts +25 -0
- package/node_modules/@unigent/core/dist/adapter_process.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/adapter_process.js +46 -0
- package/node_modules/@unigent/core/dist/adapter_process.js.map +1 -0
- package/node_modules/@unigent/core/dist/args.d.ts +17 -0
- package/node_modules/@unigent/core/dist/args.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/args.js +233 -0
- package/node_modules/@unigent/core/dist/args.js.map +1 -0
- package/node_modules/@unigent/core/dist/backend.d.ts +83 -0
- package/node_modules/@unigent/core/dist/backend.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/backend.js +2 -0
- package/node_modules/@unigent/core/dist/backend.js.map +1 -0
- package/node_modules/@unigent/core/dist/checkpoint.d.ts +26 -0
- package/node_modules/@unigent/core/dist/checkpoint.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/checkpoint.js +107 -0
- package/node_modules/@unigent/core/dist/checkpoint.js.map +1 -0
- package/node_modules/@unigent/core/dist/checkpoint_fingerprint.d.ts +4 -0
- package/node_modules/@unigent/core/dist/checkpoint_fingerprint.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/checkpoint_fingerprint.js +41 -0
- package/node_modules/@unigent/core/dist/checkpoint_fingerprint.js.map +1 -0
- package/node_modules/@unigent/core/dist/completion.d.ts +9 -0
- package/node_modules/@unigent/core/dist/completion.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/completion.js +4 -0
- package/node_modules/@unigent/core/dist/completion.js.map +1 -0
- package/node_modules/@unigent/core/dist/errors.d.ts +43 -0
- package/node_modules/@unigent/core/dist/errors.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/errors.js +48 -0
- package/node_modules/@unigent/core/dist/errors.js.map +1 -0
- package/node_modules/@unigent/core/dist/events.d.ts +101 -0
- package/node_modules/@unigent/core/dist/events.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/events.js +105 -0
- package/node_modules/@unigent/core/dist/events.js.map +1 -0
- package/node_modules/@unigent/core/dist/index.d.ts +19 -0
- package/node_modules/@unigent/core/dist/index.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/index.js +10 -0
- package/node_modules/@unigent/core/dist/index.js.map +1 -0
- package/node_modules/@unigent/core/dist/json_schema_validator.d.ts +8 -0
- package/node_modules/@unigent/core/dist/json_schema_validator.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/json_schema_validator.js +27 -0
- package/node_modules/@unigent/core/dist/json_schema_validator.js.map +1 -0
- package/node_modules/@unigent/core/dist/mcp.d.ts +12 -0
- package/node_modules/@unigent/core/dist/mcp.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/mcp.js +117 -0
- package/node_modules/@unigent/core/dist/mcp.js.map +1 -0
- package/node_modules/@unigent/core/dist/runtime.d.ts +109 -0
- package/node_modules/@unigent/core/dist/runtime.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/runtime.js +976 -0
- package/node_modules/@unigent/core/dist/runtime.js.map +1 -0
- package/node_modules/@unigent/core/dist/schema.d.ts +15 -0
- package/node_modules/@unigent/core/dist/schema.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/schema.js +71 -0
- package/node_modules/@unigent/core/dist/schema.js.map +1 -0
- package/node_modules/@unigent/core/dist/source_tools.d.ts +7 -0
- package/node_modules/@unigent/core/dist/source_tools.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/source_tools.js +450 -0
- package/node_modules/@unigent/core/dist/source_tools.js.map +1 -0
- package/node_modules/@unigent/core/dist/tool.d.ts +41 -0
- package/node_modules/@unigent/core/dist/tool.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/tool.js +43 -0
- package/node_modules/@unigent/core/dist/tool.js.map +1 -0
- package/node_modules/@unigent/core/dist/tools.d.ts +7 -0
- package/node_modules/@unigent/core/dist/tools.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/tools.js +3 -0
- package/node_modules/@unigent/core/dist/tools.js.map +1 -0
- package/node_modules/@unigent/core/dist/trace.d.ts +82 -0
- package/node_modules/@unigent/core/dist/trace.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/trace.js +235 -0
- package/node_modules/@unigent/core/dist/trace.js.map +1 -0
- package/node_modules/@unigent/core/dist/usage.d.ts +26 -0
- package/node_modules/@unigent/core/dist/usage.d.ts.map +1 -0
- package/node_modules/@unigent/core/dist/usage.js +47 -0
- package/node_modules/@unigent/core/dist/usage.js.map +1 -0
- package/node_modules/@unigent/core/package.json +68 -0
- package/package.json +68 -0
package/dist/command.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
function isHelpFlag(argument) {
|
|
3
|
+
return argument === undefined || argument === "--help" || argument === "-h";
|
|
4
|
+
}
|
|
5
|
+
function isVersionFlag(argument) {
|
|
6
|
+
return argument === "--version" || argument === "-V";
|
|
7
|
+
}
|
|
8
|
+
function parseCommand(arguments_, workingDirectory) {
|
|
9
|
+
if (isHelpFlag(arguments_[0])) {
|
|
10
|
+
return { kind: "help" };
|
|
11
|
+
}
|
|
12
|
+
if (isVersionFlag(arguments_[0])) {
|
|
13
|
+
return { kind: "version" };
|
|
14
|
+
}
|
|
15
|
+
if (arguments_[0] === "bake") {
|
|
16
|
+
const [, source] = arguments_;
|
|
17
|
+
if (source === undefined || source === "--") {
|
|
18
|
+
throw new Error("unigent bake: missing TypeScript entry file");
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
kind: "bake",
|
|
22
|
+
command: { sourceFile: isAbsolute(source) ? source : resolve(workingDirectory, source) },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const [requestedMode] = arguments_;
|
|
26
|
+
const mode = requestedMode === "tui" ? "tui" : "run";
|
|
27
|
+
const sourceIndex = requestedMode === "run" || requestedMode === "tui" ? 1 : 0;
|
|
28
|
+
const source = arguments_[sourceIndex];
|
|
29
|
+
if (source === undefined || source === "--") {
|
|
30
|
+
throw new Error(`unigent ${mode}: missing script file`);
|
|
31
|
+
}
|
|
32
|
+
const remaining = arguments_.slice(sourceIndex + 1);
|
|
33
|
+
const separator = remaining[0] === "--" ? 1 : 0;
|
|
34
|
+
return {
|
|
35
|
+
kind: "run",
|
|
36
|
+
command: {
|
|
37
|
+
mode,
|
|
38
|
+
sourceFile: isAbsolute(source) ? source : resolve(workingDirectory, source),
|
|
39
|
+
scriptArguments: remaining.slice(separator),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export { parseCommand };
|
|
44
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBhD,SAAS,UAAU,CAAC,QAA4B;IAC9C,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC;AAC9E,CAAC;AAED,SAAS,aAAa,CAAC,QAA4B;IACjD,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,IAAI,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,UAA6B,EAAE,gBAAwB;IAC3E,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC;QAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,EAAE;SACzF,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC;IACnC,MAAM,IAAI,GAAG,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACrD,MAAM,WAAW,GAAG,aAAa,KAAK,KAAK,IAAI,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,uBAAuB,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO;QACL,IAAI,EAAE,KAAK;QACX,OAAO,EAAE;YACP,IAAI;YACJ,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC;YAC3E,eAAe,EAAE,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;SAC5C;KACF,CAAC;AACJ,CAAC;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { isAbsolute, resolve } from \"node:path\";\n\ninterface RunCommand {\n readonly mode: \"run\" | \"tui\";\n readonly sourceFile: string;\n readonly scriptArguments: readonly string[];\n}\n\ninterface BakeCommand {\n readonly sourceFile: string;\n}\n\ntype ParsedCommand =\n | { readonly kind: \"help\" }\n | { readonly kind: \"version\" }\n | { readonly kind: \"bake\"; readonly command: BakeCommand }\n | { readonly kind: \"run\"; readonly command: RunCommand };\n\nfunction isHelpFlag(argument: string | undefined): boolean {\n return argument === undefined || argument === \"--help\" || argument === \"-h\";\n}\n\nfunction isVersionFlag(argument: string | undefined): boolean {\n return argument === \"--version\" || argument === \"-V\";\n}\n\nfunction parseCommand(arguments_: readonly string[], workingDirectory: string): ParsedCommand {\n if (isHelpFlag(arguments_[0])) {\n return { kind: \"help\" };\n }\n if (isVersionFlag(arguments_[0])) {\n return { kind: \"version\" };\n }\n if (arguments_[0] === \"bake\") {\n const [, source] = arguments_;\n if (source === undefined || source === \"--\") {\n throw new Error(\"unigent bake: missing TypeScript entry file\");\n }\n return {\n kind: \"bake\",\n command: { sourceFile: isAbsolute(source) ? source : resolve(workingDirectory, source) },\n };\n }\n const [requestedMode] = arguments_;\n const mode = requestedMode === \"tui\" ? \"tui\" : \"run\";\n const sourceIndex = requestedMode === \"run\" || requestedMode === \"tui\" ? 1 : 0;\n const source = arguments_[sourceIndex];\n if (source === undefined || source === \"--\") {\n throw new Error(`unigent ${mode}: missing script file`);\n }\n const remaining = arguments_.slice(sourceIndex + 1);\n const separator = remaining[0] === \"--\" ? 1 : 0;\n return {\n kind: \"run\",\n command: {\n mode,\n sourceFile: isAbsolute(source) ? source : resolve(workingDirectory, source),\n scriptArguments: remaining.slice(separator),\n },\n };\n}\n\nexport type { RunCommand };\nexport { parseCommand };\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
function environmentVariable(name) {
|
|
3
|
+
// biome-ignore lint/style/noProcessEnv: This module is the process-environment boundary.
|
|
4
|
+
return process.env[name];
|
|
5
|
+
}
|
|
6
|
+
function childProcessEnvironment(overrides) {
|
|
7
|
+
// biome-ignore lint/style/noProcessEnv: This module is the process-environment boundary.
|
|
8
|
+
const environment = { ...process.env };
|
|
9
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
10
|
+
if (value === undefined) {
|
|
11
|
+
delete environment[name];
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
environment[name] = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return environment;
|
|
18
|
+
}
|
|
19
|
+
export { childProcessEnvironment, environmentVariable };
|
|
20
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,SAAS,mBAAmB,CAAC,IAAY;IACvC,yFAAyF;IACzF,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,uBAAuB,CAC9B,SAAuD;IAEvD,yFAAyF;IACzF,MAAM,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,CAAC","sourcesContent":["import process from \"node:process\";\n\nfunction environmentVariable(name: string): string | undefined {\n // biome-ignore lint/style/noProcessEnv: This module is the process-environment boundary.\n return process.env[name];\n}\n\nfunction childProcessEnvironment(\n overrides: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n // biome-ignore lint/style/noProcessEnv: This module is the process-environment boundary.\n const environment = { ...process.env };\n for (const [name, value] of Object.entries(overrides)) {\n if (value === undefined) {\n delete environment[name];\n } else {\n environment[name] = value;\n }\n }\n return environment;\n}\n\nexport { childProcessEnvironment, environmentVariable };\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
|
|
2
|
+
const INVALID_INPUT_PREFIX_PATTERN = /^Invalid input:\s*/u;
|
|
3
|
+
const WHITESPACE_PATTERN = /\s+/gu;
|
|
4
|
+
function isUnknownArray(value) {
|
|
5
|
+
return Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function validationIssues(error) {
|
|
8
|
+
if (typeof error !== "object" || error === null || !("issues" in error)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const issues = error.issues;
|
|
12
|
+
if (!isUnknownArray(issues)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const parsed = issues.flatMap((issue) => {
|
|
16
|
+
if (typeof issue !== "object" || issue === null || !("message" in issue)) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const message = issue.message;
|
|
20
|
+
const rawPath = "path" in issue ? issue.path : undefined;
|
|
21
|
+
const path = isUnknownArray(rawPath) ? rawPath : [];
|
|
22
|
+
return [{ message: String(message), path }];
|
|
23
|
+
});
|
|
24
|
+
return parsed.length === 0 ? undefined : parsed;
|
|
25
|
+
}
|
|
26
|
+
function validationPath(path) {
|
|
27
|
+
let formatted = "input";
|
|
28
|
+
for (const segment of path) {
|
|
29
|
+
if (typeof segment === "number") {
|
|
30
|
+
formatted += `[${segment}]`;
|
|
31
|
+
}
|
|
32
|
+
else if (typeof segment === "string" && IDENTIFIER_PATTERN.test(segment)) {
|
|
33
|
+
formatted += `.${segment}`;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
formatted += `[${JSON.stringify(String(segment))}]`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return formatted;
|
|
40
|
+
}
|
|
41
|
+
function conciseIssueMessage(message) {
|
|
42
|
+
return message.replace(INVALID_INPUT_PREFIX_PATTERN, "").replace(WHITESPACE_PATTERN, " ").trim();
|
|
43
|
+
}
|
|
44
|
+
function validationMessage(issues) {
|
|
45
|
+
const [onlyIssue] = issues;
|
|
46
|
+
if (issues.length === 1 && onlyIssue !== undefined && onlyIssue.path.length === 0) {
|
|
47
|
+
return onlyIssue.message;
|
|
48
|
+
}
|
|
49
|
+
const details = issues.map((issue) => ` ${validationPath(issue.path)}: ${conciseIssueMessage(issue.message)}`);
|
|
50
|
+
return `validation failed:\n${details.join("\n")}`;
|
|
51
|
+
}
|
|
52
|
+
export function fatalErrorMessage(error) {
|
|
53
|
+
const issues = validationIssues(error);
|
|
54
|
+
if (issues !== undefined) {
|
|
55
|
+
return validationMessage(issues);
|
|
56
|
+
}
|
|
57
|
+
return error instanceof Error ? error.message : String(error);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=error_message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error_message.js","sourceRoot":"","sources":["../src/error_message.ts"],"names":[],"mappings":"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","sourcesContent":["interface ValidationIssue {\n readonly message: string;\n readonly path: readonly unknown[];\n}\n\nconst IDENTIFIER_PATTERN = /^[A-Za-z_$][\\w$]*$/u;\nconst INVALID_INPUT_PREFIX_PATTERN = /^Invalid input:\\s*/u;\nconst WHITESPACE_PATTERN = /\\s+/gu;\n\nfunction isUnknownArray(value: unknown): value is readonly unknown[] {\n return Array.isArray(value);\n}\n\nfunction validationIssues(error: unknown): readonly ValidationIssue[] | undefined {\n if (typeof error !== \"object\" || error === null || !(\"issues\" in error)) {\n return;\n }\n const issues: unknown = error.issues;\n if (!isUnknownArray(issues)) {\n return;\n }\n const parsed = issues.flatMap((issue): ValidationIssue[] => {\n if (typeof issue !== \"object\" || issue === null || !(\"message\" in issue)) {\n return [];\n }\n const message: unknown = issue.message;\n const rawPath: unknown = \"path\" in issue ? issue.path : undefined;\n const path = isUnknownArray(rawPath) ? rawPath : [];\n return [{ message: String(message), path }];\n });\n return parsed.length === 0 ? undefined : parsed;\n}\n\nfunction validationPath(path: readonly unknown[]): string {\n let formatted = \"input\";\n for (const segment of path) {\n if (typeof segment === \"number\") {\n formatted += `[${segment}]`;\n } else if (typeof segment === \"string\" && IDENTIFIER_PATTERN.test(segment)) {\n formatted += `.${segment}`;\n } else {\n formatted += `[${JSON.stringify(String(segment))}]`;\n }\n }\n return formatted;\n}\n\nfunction conciseIssueMessage(message: string): string {\n return message.replace(INVALID_INPUT_PREFIX_PATTERN, \"\").replace(WHITESPACE_PATTERN, \" \").trim();\n}\n\nfunction validationMessage(issues: readonly ValidationIssue[]): string {\n const [onlyIssue] = issues;\n if (issues.length === 1 && onlyIssue !== undefined && onlyIssue.path.length === 0) {\n return onlyIssue.message;\n }\n const details = issues.map(\n (issue) => ` ${validationPath(issue.path)}: ${conciseIssueMessage(issue.message)}`,\n );\n return `validation failed:\\n${details.join(\"\\n\")}`;\n}\n\nexport function fatalErrorMessage(error: unknown): string {\n const issues = validationIssues(error);\n if (issues !== undefined) {\n return validationMessage(issues);\n }\n return error instanceof Error ? error.message : String(error);\n}\n"]}
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const MILLISECONDS_PER_SECOND = 1000;
|
|
2
|
+
const SECONDS_PER_MINUTE = 60;
|
|
3
|
+
const TOKENS_PER_KILO = 1000;
|
|
4
|
+
const SUB_CENT_THRESHOLD_USD = 0.1;
|
|
5
|
+
const SUB_CENT_DECIMALS = 4;
|
|
6
|
+
const STANDARD_COST_DECIMALS = 2;
|
|
7
|
+
function formatDuration(milliseconds) {
|
|
8
|
+
if (milliseconds === undefined) {
|
|
9
|
+
return "—";
|
|
10
|
+
}
|
|
11
|
+
const seconds = Math.round(milliseconds / MILLISECONDS_PER_SECOND);
|
|
12
|
+
if (seconds < 1) {
|
|
13
|
+
return "<1s";
|
|
14
|
+
}
|
|
15
|
+
if (seconds < SECONDS_PER_MINUTE) {
|
|
16
|
+
return `${seconds}s`;
|
|
17
|
+
}
|
|
18
|
+
const minutes = Math.floor(seconds / SECONDS_PER_MINUTE);
|
|
19
|
+
return `${minutes}m ${String(seconds % SECONDS_PER_MINUTE).padStart(2, "0")}s`;
|
|
20
|
+
}
|
|
21
|
+
function formatTokens(tokens) {
|
|
22
|
+
return tokens < TOKENS_PER_KILO ? `${tokens}tok` : `${(tokens / TOKENS_PER_KILO).toFixed(1)}ktok`;
|
|
23
|
+
}
|
|
24
|
+
function formatCost(costUsd) {
|
|
25
|
+
return costUsd === undefined
|
|
26
|
+
? ""
|
|
27
|
+
: `$${costUsd.toFixed(costUsd < SUB_CENT_THRESHOLD_USD ? SUB_CENT_DECIMALS : STANDARD_COST_DECIMALS)}`;
|
|
28
|
+
}
|
|
29
|
+
function formatUsage(usage) {
|
|
30
|
+
const parts = [formatTokens(usage.totalTokens)];
|
|
31
|
+
const cost = formatCost(usage.costUsd);
|
|
32
|
+
if (cost.length > 0) {
|
|
33
|
+
parts.push(cost);
|
|
34
|
+
}
|
|
35
|
+
return parts.join(" ");
|
|
36
|
+
}
|
|
37
|
+
export { formatCost, formatDuration, formatTokens, formatUsage };
|
|
38
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAEA,MAAM,uBAAuB,GAAG,IAAI,CAAC;AACrC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,MAAM,sBAAsB,GAAG,GAAG,CAAC;AACnC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,SAAS,cAAc,CAAC,YAAgC;IACtD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,uBAAuB,CAAC,CAAC;IACnE,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACjC,OAAO,GAAG,OAAO,GAAG,CAAC;IACvB,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAC;IACzD,OAAO,GAAG,OAAO,KAAK,MAAM,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;AACjF,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACpG,CAAC;AAED,SAAS,UAAU,CAAC,OAA2B;IAC7C,OAAO,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,GAAG,sBAAsB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB;IACpC,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC","sourcesContent":["import type { AgentUsage } from \"@unigent/core\";\n\nconst MILLISECONDS_PER_SECOND = 1000;\nconst SECONDS_PER_MINUTE = 60;\nconst TOKENS_PER_KILO = 1000;\nconst SUB_CENT_THRESHOLD_USD = 0.1;\nconst SUB_CENT_DECIMALS = 4;\nconst STANDARD_COST_DECIMALS = 2;\n\nfunction formatDuration(milliseconds: number | undefined): string {\n if (milliseconds === undefined) {\n return \"—\";\n }\n const seconds = Math.round(milliseconds / MILLISECONDS_PER_SECOND);\n if (seconds < 1) {\n return \"<1s\";\n }\n if (seconds < SECONDS_PER_MINUTE) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / SECONDS_PER_MINUTE);\n return `${minutes}m ${String(seconds % SECONDS_PER_MINUTE).padStart(2, \"0\")}s`;\n}\n\nfunction formatTokens(tokens: number): string {\n return tokens < TOKENS_PER_KILO ? `${tokens}tok` : `${(tokens / TOKENS_PER_KILO).toFixed(1)}ktok`;\n}\n\nfunction formatCost(costUsd: number | undefined): string {\n return costUsd === undefined\n ? \"\"\n : `$${costUsd.toFixed(costUsd < SUB_CENT_THRESHOLD_USD ? SUB_CENT_DECIMALS : STANDARD_COST_DECIMALS)}`;\n}\n\nfunction formatUsage(usage: AgentUsage): string {\n const parts = [formatTokens(usage.totalTokens)];\n const cost = formatCost(usage.costUsd);\n if (cost.length > 0) {\n parts.push(cost);\n }\n return parts.join(\" \");\n}\n\nexport { formatCost, formatDuration, formatTokens, formatUsage };\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const MINIMUM_NODE_MAJOR_VERSION = 24;
|
|
2
|
+
function assertSupportedNodeVersion(version) {
|
|
3
|
+
const majorVersion = Number.parseInt(version.split(".", 1)[0] ?? "", 10);
|
|
4
|
+
if (!Number.isInteger(majorVersion) || majorVersion < MINIMUM_NODE_MAJOR_VERSION) {
|
|
5
|
+
throw new Error(`Node.js ${MINIMUM_NODE_MAJOR_VERSION} or newer is required; current version is ${version}.`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export { assertSupportedNodeVersion };
|
|
9
|
+
//# sourceMappingURL=node_version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node_version.js","sourceRoot":"","sources":["../src/node_version.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAEtC,SAAS,0BAA0B,CAAC,OAAe;IACjD,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,0BAA0B,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CACb,WAAW,0BAA0B,6CAA6C,OAAO,GAAG,CAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC","sourcesContent":["const MINIMUM_NODE_MAJOR_VERSION = 24;\n\nfunction assertSupportedNodeVersion(version: string): void {\n const majorVersion = Number.parseInt(version.split(\".\", 1)[0] ?? \"\", 10);\n if (!Number.isInteger(majorVersion) || majorVersion < MINIMUM_NODE_MAJOR_VERSION) {\n throw new Error(\n `Node.js ${MINIMUM_NODE_MAJOR_VERSION} or newer is required; current version is ${version}.`,\n );\n }\n}\n\nexport { assertSupportedNodeVersion };\n"]}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const PROTOCOL_VERSION = 1;
|
|
2
|
+
const MAX_STRING_LENGTH = 32_768;
|
|
3
|
+
const MAX_ARRAY_LENGTH = 100;
|
|
4
|
+
function isUnknownArray(value) {
|
|
5
|
+
return Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function normalizeTraceScalar(value) {
|
|
8
|
+
if (typeof value === "bigint") {
|
|
9
|
+
return `${value.toString()}n`;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "string" && value.length > MAX_STRING_LENGTH) {
|
|
12
|
+
return `${value.slice(0, MAX_STRING_LENGTH)}… [truncated ${value.length - MAX_STRING_LENGTH} chars]`;
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function traceReplacer() {
|
|
17
|
+
const ancestors = [];
|
|
18
|
+
const replacementSources = new WeakMap();
|
|
19
|
+
return function traceValue(_key, value) {
|
|
20
|
+
const normalizedValue = normalizeTraceScalar(value);
|
|
21
|
+
if (typeof normalizedValue !== "object" || normalizedValue === null) {
|
|
22
|
+
return normalizedValue;
|
|
23
|
+
}
|
|
24
|
+
const parent = replacementSources.get(this) ?? this;
|
|
25
|
+
while (ancestors.length > 0 && ancestors.at(-1) !== parent) {
|
|
26
|
+
ancestors.pop();
|
|
27
|
+
}
|
|
28
|
+
if (ancestors.includes(normalizedValue)) {
|
|
29
|
+
return "[Circular]";
|
|
30
|
+
}
|
|
31
|
+
ancestors.push(normalizedValue);
|
|
32
|
+
if (isUnknownArray(normalizedValue) && normalizedValue.length > MAX_ARRAY_LENGTH) {
|
|
33
|
+
const truncated = [
|
|
34
|
+
...normalizedValue.slice(0, MAX_ARRAY_LENGTH),
|
|
35
|
+
`[truncated ${normalizedValue.length - MAX_ARRAY_LENGTH} items]`,
|
|
36
|
+
];
|
|
37
|
+
replacementSources.set(truncated, normalizedValue);
|
|
38
|
+
return truncated;
|
|
39
|
+
}
|
|
40
|
+
return normalizedValue;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function serializeTraceEvent(event) {
|
|
44
|
+
return `${JSON.stringify({ version: PROTOCOL_VERSION, event }, traceReplacer())}\n`;
|
|
45
|
+
}
|
|
46
|
+
function isTraceRecord(value) {
|
|
47
|
+
if (typeof value !== "object" || value === null || !("version" in value) || value.version !== 1) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (!("event" in value) || typeof value.event !== "object" || value.event === null) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const { event } = value;
|
|
54
|
+
return ("type" in event &&
|
|
55
|
+
typeof event.type === "string" &&
|
|
56
|
+
"traceId" in event &&
|
|
57
|
+
typeof event.traceId === "string" &&
|
|
58
|
+
"spanId" in event &&
|
|
59
|
+
typeof event.spanId === "string");
|
|
60
|
+
}
|
|
61
|
+
function parseTraceRecord(line) {
|
|
62
|
+
try {
|
|
63
|
+
const value = JSON.parse(line);
|
|
64
|
+
return isTraceRecord(value) ? value : undefined;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const TRACE_TRANSPORT_ENVIRONMENT_VARIABLE = "UNIGENT_TRACE_FILE_DESCRIPTOR";
|
|
71
|
+
export { parseTraceRecord, serializeTraceEvent, TRACE_TRANSPORT_ENVIRONMENT_VARIABLE };
|
|
72
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEvent } from \"@unigent/core\";\n\nconst PROTOCOL_VERSION = 1;\nconst MAX_STRING_LENGTH = 32_768;\nconst MAX_ARRAY_LENGTH = 100;\n\nfunction isUnknownArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\ninterface TraceRecord {\n readonly version: typeof PROTOCOL_VERSION;\n readonly event: AgentEvent;\n}\n\nfunction normalizeTraceScalar(value: unknown): unknown {\n if (typeof value === \"bigint\") {\n return `${value.toString()}n`;\n }\n if (typeof value === \"string\" && value.length > MAX_STRING_LENGTH) {\n return `${value.slice(0, MAX_STRING_LENGTH)}… [truncated ${value.length - MAX_STRING_LENGTH} chars]`;\n }\n return value;\n}\n\nfunction traceReplacer(): (key: string, value: unknown) => unknown {\n const ancestors: object[] = [];\n const replacementSources = new WeakMap<object, object>();\n return function traceValue(this: object, _key: string, value: unknown): unknown {\n const normalizedValue = normalizeTraceScalar(value);\n if (typeof normalizedValue !== \"object\" || normalizedValue === null) {\n return normalizedValue;\n }\n const parent = replacementSources.get(this) ?? this;\n while (ancestors.length > 0 && ancestors.at(-1) !== parent) {\n ancestors.pop();\n }\n if (ancestors.includes(normalizedValue)) {\n return \"[Circular]\";\n }\n ancestors.push(normalizedValue);\n if (isUnknownArray(normalizedValue) && normalizedValue.length > MAX_ARRAY_LENGTH) {\n const truncated = [\n ...normalizedValue.slice(0, MAX_ARRAY_LENGTH),\n `[truncated ${normalizedValue.length - MAX_ARRAY_LENGTH} items]`,\n ];\n replacementSources.set(truncated, normalizedValue);\n return truncated;\n }\n return normalizedValue;\n };\n}\n\nfunction serializeTraceEvent(event: AgentEvent): string {\n return `${JSON.stringify({ version: PROTOCOL_VERSION, event }, traceReplacer())}\\n`;\n}\n\nfunction isTraceRecord(value: unknown): value is TraceRecord {\n if (typeof value !== \"object\" || value === null || !(\"version\" in value) || value.version !== 1) {\n return false;\n }\n if (!(\"event\" in value) || typeof value.event !== \"object\" || value.event === null) {\n return false;\n }\n const { event } = value;\n return (\n \"type\" in event &&\n typeof event.type === \"string\" &&\n \"traceId\" in event &&\n typeof event.traceId === \"string\" &&\n \"spanId\" in event &&\n typeof event.spanId === \"string\"\n );\n}\n\nfunction parseTraceRecord(line: string): TraceRecord | undefined {\n try {\n const value: unknown = JSON.parse(line);\n return isTraceRecord(value) ? value : undefined;\n } catch {\n return;\n }\n}\n\nconst TRACE_TRANSPORT_ENVIRONMENT_VARIABLE = \"UNIGENT_TRACE_FILE_DESCRIPTOR\";\n\nexport { parseTraceRecord, serializeTraceEvent, TRACE_TRANSPORT_ENVIRONMENT_VARIABLE };\n"]}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { subscribeRunControls, subscribeTrace } from "@unigent/core/trace";
|
|
4
|
+
import { environmentVariable } from "./environment.js";
|
|
5
|
+
import { fatalErrorMessage } from "./error_message.js";
|
|
6
|
+
import { serializeTraceEvent, TRACE_TRANSPORT_ENVIRONMENT_VARIABLE } from "./protocol.js";
|
|
7
|
+
const TRACE_FILE_DESCRIPTOR = 3;
|
|
8
|
+
const INTERRUPTED_EXIT_CODE = 130;
|
|
9
|
+
const INTERRUPT_GRACE_MILLISECONDS = 1000;
|
|
10
|
+
const traceStream = environmentVariable(TRACE_TRANSPORT_ENVIRONMENT_VARIABLE) === String(TRACE_FILE_DESCRIPTOR)
|
|
11
|
+
? createWriteStream("/dev/null", {
|
|
12
|
+
fd: TRACE_FILE_DESCRIPTOR,
|
|
13
|
+
autoClose: false,
|
|
14
|
+
})
|
|
15
|
+
: undefined;
|
|
16
|
+
traceStream?.on("error", () => {
|
|
17
|
+
// Telemetry is best-effort and must never fail the script it observes.
|
|
18
|
+
});
|
|
19
|
+
const stopObserving = traceStream === undefined
|
|
20
|
+
? undefined
|
|
21
|
+
: subscribeTrace((event) => {
|
|
22
|
+
try {
|
|
23
|
+
traceStream.write(serializeTraceEvent(event));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Hostile or unserializable tool payloads must not affect the observed run.
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const activeRuns = new Map();
|
|
30
|
+
let interrupted = false;
|
|
31
|
+
let fatalHandled = false;
|
|
32
|
+
const stopSupervising = subscribeRunControls((event) => {
|
|
33
|
+
if (event.type === "run_start") {
|
|
34
|
+
activeRuns.set(event.spanId, event.abort);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
activeRuns.delete(event.spanId);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
process.on("SIGINT", () => {
|
|
41
|
+
if (interrupted) {
|
|
42
|
+
process.exit(INTERRUPTED_EXIT_CODE);
|
|
43
|
+
}
|
|
44
|
+
interrupted = true;
|
|
45
|
+
for (const abort of activeRuns.values()) {
|
|
46
|
+
abort(new Error("run interrupted by Unigent CLI"));
|
|
47
|
+
}
|
|
48
|
+
if (activeRuns.size === 0) {
|
|
49
|
+
process.exit(INTERRUPTED_EXIT_CODE);
|
|
50
|
+
}
|
|
51
|
+
setTimeout(() => process.exit(INTERRUPTED_EXIT_CODE), INTERRUPT_GRACE_MILLISECONDS).unref();
|
|
52
|
+
});
|
|
53
|
+
function exitWithMessage(code, message) {
|
|
54
|
+
process.stderr.write(`${message}\n`, () => process.exit(code));
|
|
55
|
+
}
|
|
56
|
+
const handleFatalError = (error) => {
|
|
57
|
+
if (interrupted &&
|
|
58
|
+
error instanceof Error &&
|
|
59
|
+
(error.name === "AgentCancelledError" || error.name === "AbortError")) {
|
|
60
|
+
process.exit(INTERRUPTED_EXIT_CODE);
|
|
61
|
+
}
|
|
62
|
+
if (fatalHandled) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
fatalHandled = true;
|
|
66
|
+
const details = error instanceof Error ? (error.stack ?? error.message) : fatalErrorMessage(error);
|
|
67
|
+
exitWithMessage(1, `unigent: ${details}`);
|
|
68
|
+
};
|
|
69
|
+
process.on("uncaughtException", handleFatalError);
|
|
70
|
+
process.on("unhandledRejection", handleFatalError);
|
|
71
|
+
process.once("beforeExit", () => {
|
|
72
|
+
stopObserving?.();
|
|
73
|
+
stopSupervising();
|
|
74
|
+
process.removeListener("uncaughtException", handleFatalError);
|
|
75
|
+
process.removeListener("unhandledRejection", handleFatalError);
|
|
76
|
+
traceStream?.end();
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"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","sourcesContent":["import { createWriteStream } from \"node:fs\";\nimport process from \"node:process\";\nimport { subscribeRunControls, subscribeTrace } from \"@unigent/core/trace\";\nimport { environmentVariable } from \"./environment.js\";\nimport { fatalErrorMessage } from \"./error_message.js\";\nimport { serializeTraceEvent, TRACE_TRANSPORT_ENVIRONMENT_VARIABLE } from \"./protocol.js\";\n\nconst TRACE_FILE_DESCRIPTOR = 3;\nconst INTERRUPTED_EXIT_CODE = 130;\nconst INTERRUPT_GRACE_MILLISECONDS = 1000;\nconst traceStream =\n environmentVariable(TRACE_TRANSPORT_ENVIRONMENT_VARIABLE) === String(TRACE_FILE_DESCRIPTOR)\n ? createWriteStream(\"/dev/null\", {\n fd: TRACE_FILE_DESCRIPTOR,\n autoClose: false,\n })\n : undefined;\n\ntraceStream?.on(\"error\", () => {\n // Telemetry is best-effort and must never fail the script it observes.\n});\n\nconst stopObserving =\n traceStream === undefined\n ? undefined\n : subscribeTrace((event) => {\n try {\n traceStream.write(serializeTraceEvent(event));\n } catch {\n // Hostile or unserializable tool payloads must not affect the observed run.\n }\n });\nconst activeRuns = new Map<string, (reason?: unknown) => void>();\nlet interrupted = false;\nlet fatalHandled = false;\nconst stopSupervising = subscribeRunControls((event) => {\n if (event.type === \"run_start\") {\n activeRuns.set(event.spanId, event.abort);\n } else {\n activeRuns.delete(event.spanId);\n }\n});\n\nprocess.on(\"SIGINT\", () => {\n if (interrupted) {\n process.exit(INTERRUPTED_EXIT_CODE);\n }\n interrupted = true;\n for (const abort of activeRuns.values()) {\n abort(new Error(\"run interrupted by Unigent CLI\"));\n }\n if (activeRuns.size === 0) {\n process.exit(INTERRUPTED_EXIT_CODE);\n }\n setTimeout(() => process.exit(INTERRUPTED_EXIT_CODE), INTERRUPT_GRACE_MILLISECONDS).unref();\n});\n\nfunction exitWithMessage(code: number, message: string): void {\n process.stderr.write(`${message}\\n`, () => process.exit(code));\n}\n\nconst handleFatalError = (error: unknown): void => {\n if (\n interrupted &&\n error instanceof Error &&\n (error.name === \"AgentCancelledError\" || error.name === \"AbortError\")\n ) {\n process.exit(INTERRUPTED_EXIT_CODE);\n }\n if (fatalHandled) {\n return;\n }\n fatalHandled = true;\n const details =\n error instanceof Error ? (error.stack ?? error.message) : fatalErrorMessage(error);\n exitWithMessage(1, `unigent: ${details}`);\n};\nprocess.on(\"uncaughtException\", handleFatalError);\nprocess.on(\"unhandledRejection\", handleFatalError);\n\nprocess.once(\"beforeExit\", () => {\n stopObserving?.();\n stopSupervising();\n process.removeListener(\"uncaughtException\", handleFatalError);\n process.removeListener(\"unhandledRejection\", handleFatalError);\n traceStream?.end();\n});\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { open } from "node:fs/promises";
|
|
2
|
+
const SHEBANG_READ_BYTES = 256;
|
|
3
|
+
const BUN_SHEBANG = /^#!\s*(?:\/usr\/bin\/env(?:\s+-S)?\s+)?(?:\S*\/)?bun(?:\s|$)/u;
|
|
4
|
+
const LINE_BREAK = /\r?\n/u;
|
|
5
|
+
async function detectScriptRuntime(sourceFile) {
|
|
6
|
+
const file = await open(sourceFile, "r").catch((error) => {
|
|
7
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
8
|
+
throw new Error(`script file not found: ${sourceFile}`, { cause: error });
|
|
9
|
+
}
|
|
10
|
+
throw error;
|
|
11
|
+
});
|
|
12
|
+
try {
|
|
13
|
+
const buffer = Buffer.alloc(SHEBANG_READ_BYTES);
|
|
14
|
+
const { bytesRead } = await file.read(buffer, 0, buffer.length, 0);
|
|
15
|
+
const sourceStart = buffer.toString("utf8", 0, bytesRead);
|
|
16
|
+
const [firstLine = ""] = sourceStart.split(LINE_BREAK, 1);
|
|
17
|
+
return BUN_SHEBANG.test(firstLine) ? "bun" : "node";
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await file.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function runtimeInvocation(runtime, nodeExecutable) {
|
|
24
|
+
return runtime === "bun"
|
|
25
|
+
? { kind: runtime, executable: "bun", arguments: ["--install=fallback"] }
|
|
26
|
+
: { kind: runtime, executable: nodeExecutable, arguments: [] };
|
|
27
|
+
}
|
|
28
|
+
export { detectScriptRuntime, runtimeInvocation };
|
|
29
|
+
//# sourceMappingURL=script_runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script_runtime.js","sourceRoot":"","sources":["../src/script_runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,WAAW,GAAG,+DAA+D,CAAC;AACpF,MAAM,UAAU,GAAG,QAAQ,CAAC;AAU5B,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IACnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAChE,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAChD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IACtD,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAsB,EAAE,cAAsB;IACvE,OAAO,OAAO,KAAK,KAAK;QACtB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,oBAAoB,CAAC,EAAE;QACzE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AACnE,CAAC;AAGD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import { open } from \"node:fs/promises\";\n\nconst SHEBANG_READ_BYTES = 256;\nconst BUN_SHEBANG = /^#!\\s*(?:\\/usr\\/bin\\/env(?:\\s+-S)?\\s+)?(?:\\S*\\/)?bun(?:\\s|$)/u;\nconst LINE_BREAK = /\\r?\\n/u;\n\ntype ScriptRuntime = \"bun\" | \"node\";\n\ninterface RuntimeInvocation {\n readonly kind: ScriptRuntime;\n readonly executable: string;\n readonly arguments: readonly string[];\n}\n\nasync function detectScriptRuntime(sourceFile: string): Promise<ScriptRuntime> {\n const file = await open(sourceFile, \"r\").catch((error: unknown) => {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n throw new Error(`script file not found: ${sourceFile}`, { cause: error });\n }\n throw error;\n });\n try {\n const buffer = Buffer.alloc(SHEBANG_READ_BYTES);\n const { bytesRead } = await file.read(buffer, 0, buffer.length, 0);\n const sourceStart = buffer.toString(\"utf8\", 0, bytesRead);\n const [firstLine = \"\"] = sourceStart.split(LINE_BREAK, 1);\n return BUN_SHEBANG.test(firstLine) ? \"bun\" : \"node\";\n } finally {\n await file.close();\n }\n}\n\nfunction runtimeInvocation(runtime: ScriptRuntime, nodeExecutable: string): RuntimeInvocation {\n return runtime === \"bun\"\n ? { kind: runtime, executable: \"bun\", arguments: [\"--install=fallback\"] }\n : { kind: runtime, executable: nodeExecutable, arguments: [] };\n}\n\nexport type { RuntimeInvocation, ScriptRuntime };\nexport { detectScriptRuntime, runtimeInvocation };\n"]}
|