poe-code 3.0.29 → 3.0.31
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/README.md +2 -2
- package/dist/bin/poe-claude.js +23 -0
- package/dist/bin/poe-codex.js +23 -0
- package/dist/bin/poe-kimi-cli.js +23 -0
- package/dist/bin/poe-opencode.js +23 -0
- package/dist/bin.cjs +9 -0
- package/dist/cli/binary-aliases.d.ts +7 -0
- package/dist/cli/binary-aliases.js +26 -0
- package/dist/cli/binary-aliases.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +4 -0
- package/dist/cli/bootstrap.js +78 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/command-not-found.d.ts +8 -0
- package/dist/cli/command-not-found.js +34 -0
- package/dist/cli/command-not-found.js.map +1 -0
- package/dist/cli/commands/configure-payload.d.ts +15 -0
- package/dist/cli/commands/configure-payload.js +31 -0
- package/dist/cli/commands/configure-payload.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +12 -0
- package/dist/cli/commands/configure.js +151 -0
- package/dist/cli/commands/configure.js.map +1 -0
- package/dist/cli/commands/ensure-isolated-config.d.ts +12 -0
- package/dist/cli/commands/ensure-isolated-config.js +53 -0
- package/dist/cli/commands/ensure-isolated-config.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.js +322 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/install.d.ts +4 -0
- package/dist/cli/commands/install.js +40 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/login.d.ts +6 -0
- package/dist/cli/commands/login.js +105 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.js +178 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/models.d.ts +3 -0
- package/dist/cli/commands/models.js +183 -0
- package/dist/cli/commands/models.js.map +1 -0
- package/dist/cli/commands/ralph-worktree.d.ts +3 -0
- package/dist/cli/commands/ralph-worktree.js +73 -0
- package/dist/cli/commands/ralph-worktree.js.map +1 -0
- package/dist/cli/commands/ralph.d.ts +3 -0
- package/dist/cli/commands/ralph.js +424 -0
- package/dist/cli/commands/ralph.js.map +1 -0
- package/dist/cli/commands/shared.d.ts +29 -0
- package/dist/cli/commands/shared.js +82 -0
- package/dist/cli/commands/shared.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +3 -0
- package/dist/cli/commands/skill.js +242 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/commands/spawn.d.ts +17 -0
- package/dist/cli/commands/spawn.js +226 -0
- package/dist/cli/commands/spawn.js.map +1 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +124 -0
- package/dist/cli/commands/test.js.map +1 -0
- package/dist/cli/commands/unconfigure.d.ts +7 -0
- package/dist/cli/commands/unconfigure.js +116 -0
- package/dist/cli/commands/unconfigure.js.map +1 -0
- package/dist/cli/commands/usage.d.ts +3 -0
- package/dist/cli/commands/usage.js +186 -0
- package/dist/cli/commands/usage.js.map +1 -0
- package/dist/cli/commands/version.d.ts +3 -0
- package/dist/cli/commands/version.js +31 -0
- package/dist/cli/commands/version.js.map +1 -0
- package/dist/cli/commands/wrap.d.ts +3 -0
- package/dist/cli/commands/wrap.js +61 -0
- package/dist/cli/commands/wrap.js.map +1 -0
- package/dist/cli/constants.d.ts +24 -0
- package/dist/cli/constants.js +44 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/container.d.ts +42 -0
- package/dist/cli/container.js +90 -0
- package/dist/cli/container.js.map +1 -0
- package/dist/cli/context.d.ts +33 -0
- package/dist/cli/context.js +91 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/environment.d.ts +21 -0
- package/dist/cli/environment.js +106 -0
- package/dist/cli/environment.js.map +1 -0
- package/dist/cli/error-logger.d.ts +62 -0
- package/dist/cli/error-logger.js +155 -0
- package/dist/cli/error-logger.js.map +1 -0
- package/dist/cli/errors.d.ts +95 -0
- package/dist/cli/errors.js +141 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/exit-signals.d.ts +4 -0
- package/dist/cli/exit-signals.js +8 -0
- package/dist/cli/exit-signals.js.map +1 -0
- package/dist/cli/http.d.ts +12 -0
- package/dist/cli/http.js +2 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/isolated-env-runner.d.ts +10 -0
- package/dist/cli/isolated-env-runner.js +50 -0
- package/dist/cli/isolated-env-runner.js.map +1 -0
- package/dist/cli/isolated-env.d.ts +24 -0
- package/dist/cli/isolated-env.js +210 -0
- package/dist/cli/isolated-env.js.map +1 -0
- package/dist/cli/logger.d.ts +36 -0
- package/dist/cli/logger.js +191 -0
- package/dist/cli/logger.js.map +1 -0
- package/dist/cli/mcp-output-format.d.ts +2 -0
- package/dist/cli/mcp-output-format.js +27 -0
- package/dist/cli/mcp-output-format.js.map +1 -0
- package/dist/cli/mcp-server.d.ts +21 -0
- package/dist/cli/mcp-server.js +321 -0
- package/dist/cli/mcp-server.js.map +1 -0
- package/dist/cli/options.d.ts +45 -0
- package/dist/cli/options.js +111 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/cli/poe-code-command-runner.d.ts +6 -0
- package/dist/cli/poe-code-command-runner.js +63 -0
- package/dist/cli/poe-code-command-runner.js.map +1 -0
- package/dist/cli/program.d.ts +4 -0
- package/dist/cli/program.js +249 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/prompt-runner.d.ts +10 -0
- package/dist/cli/prompt-runner.js +79 -0
- package/dist/cli/prompt-runner.js.map +1 -0
- package/dist/cli/prompts.d.ts +39 -0
- package/dist/cli/prompts.js +42 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/cli/service-registry.d.ts +108 -0
- package/dist/cli/service-registry.js +83 -0
- package/dist/cli/service-registry.js.map +1 -0
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/ui/service-menu.d.ts +7 -0
- package/dist/cli/ui/service-menu.js +43 -0
- package/dist/cli/ui/service-menu.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +36812 -0
- package/dist/index.js.map +7 -0
- package/dist/providers/claude-code.d.ts +13 -0
- package/dist/providers/claude-code.js +143 -0
- package/dist/providers/claude-code.js.map +1 -0
- package/dist/providers/codex.d.ts +17 -0
- package/dist/providers/codex.js +144 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/create-provider.d.ts +29 -0
- package/dist/providers/create-provider.js +78 -0
- package/dist/providers/create-provider.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/kimi.d.ts +4 -0
- package/dist/providers/kimi.js +123 -0
- package/dist/providers/kimi.js.map +1 -0
- package/dist/providers/opencode.d.ts +3 -0
- package/dist/providers/opencode.js +119 -0
- package/dist/providers/opencode.js.map +1 -0
- package/dist/providers/spawn-options.d.ts +13 -0
- package/dist/providers/spawn-options.js +2 -0
- package/dist/providers/spawn-options.js.map +1 -0
- package/dist/sdk/container.d.ts +18 -0
- package/dist/sdk/container.js +127 -0
- package/dist/sdk/container.js.map +1 -0
- package/dist/sdk/credentials.d.ts +9 -0
- package/dist/sdk/credentials.js +35 -0
- package/dist/sdk/credentials.js.map +1 -0
- package/dist/sdk/generate.d.ts +5 -0
- package/dist/sdk/generate.js +97 -0
- package/dist/sdk/generate.js.map +1 -0
- package/dist/sdk/spawn-core.d.ts +23 -0
- package/dist/sdk/spawn-core.js +105 -0
- package/dist/sdk/spawn-core.js.map +1 -0
- package/dist/sdk/spawn.d.ts +31 -0
- package/dist/sdk/spawn.js +109 -0
- package/dist/sdk/spawn.js.map +1 -0
- package/dist/sdk/types.d.ts +44 -0
- package/dist/sdk/types.js +2 -0
- package/dist/sdk/types.js.map +1 -0
- package/dist/services/client-instance.d.ts +12 -0
- package/dist/services/client-instance.js +36 -0
- package/dist/services/client-instance.js.map +1 -0
- package/dist/services/credentials.d.ts +24 -0
- package/dist/services/credentials.js +157 -0
- package/dist/services/credentials.js.map +1 -0
- package/dist/services/llm-client.d.ts +22 -0
- package/dist/services/llm-client.js +138 -0
- package/dist/services/llm-client.js.map +1 -0
- package/dist/services/media-download.d.ts +17 -0
- package/dist/services/media-download.js +42 -0
- package/dist/services/media-download.js.map +1 -0
- package/dist/services/model-strategy.d.ts +99 -0
- package/dist/services/model-strategy.js +187 -0
- package/dist/services/model-strategy.js.map +1 -0
- package/dist/services/mutation-events.d.ts +4 -0
- package/dist/services/mutation-events.js +53 -0
- package/dist/services/mutation-events.js.map +1 -0
- package/dist/services/service-install.d.ts +22 -0
- package/dist/services/service-install.js +70 -0
- package/dist/services/service-install.js.map +1 -0
- package/dist/services/version.d.ts +11 -0
- package/dist/services/version.js +28 -0
- package/dist/services/version.js.map +1 -0
- package/dist/tools/label-generator.d.ts +11 -0
- package/dist/tools/label-generator.js +78 -0
- package/dist/tools/label-generator.js.map +1 -0
- package/dist/utils/backup.d.ts +5 -0
- package/dist/utils/backup.js +56 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/cli-settings-merge.d.ts +22 -0
- package/dist/utils/cli-settings-merge.js +56 -0
- package/dist/utils/cli-settings-merge.js.map +1 -0
- package/dist/utils/command-checks.d.ts +36 -0
- package/dist/utils/command-checks.js +120 -0
- package/dist/utils/command-checks.js.map +1 -0
- package/dist/utils/command-line.d.ts +1 -0
- package/dist/utils/command-line.js +54 -0
- package/dist/utils/command-line.js.map +1 -0
- package/dist/utils/dry-run.d.ts +39 -0
- package/dist/utils/dry-run.js +315 -0
- package/dist/utils/dry-run.js.map +1 -0
- package/dist/utils/execution-context.d.ts +48 -0
- package/dist/utils/execution-context.js +151 -0
- package/dist/utils/execution-context.js.map +1 -0
- package/dist/utils/file-system.d.ts +21 -0
- package/dist/utils/file-system.js +2 -0
- package/dist/utils/file-system.js.map +1 -0
- package/dist/utils/json.d.ts +12 -0
- package/dist/utils/json.js +45 -0
- package/dist/utils/json.js.map +1 -0
- package/package.json +5 -2
- package/packages/tiny-mcp-test-server/dist/index.js +47 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/utils/backup.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAKxD,MAAM,iBAAiB,GAAsB,GAAG,EAAE,CAChD,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,EAAc,EACd,UAAkB,EAClB,YAA+B,iBAAiB;IAEhD,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,UAAU,WAAW,SAAS,EAAE,EAAE,CAAC;IACzD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACvC,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,EAAc,EACd,UAAkB;IAElB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEvC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,OAAO;SACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;SACpD,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IAEb,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,EAAc,EAAE,UAAkB;IACtD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,EAAc,EACd,IAAY,EACZ,EAAU;IAEV,IAAI,OAAO,EAAE,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CliSettings {
|
|
2
|
+
apiKeyHelper?: string;
|
|
3
|
+
env?: Record<string, string | number>;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface ExtractedSettings {
|
|
7
|
+
userSettings: CliSettings | null;
|
|
8
|
+
settingsFilePath?: string;
|
|
9
|
+
argsWithoutSettings: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Extracts --settings from args, returning parsed settings and remaining args
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractSettingsFromArgs(args: string[]): ExtractedSettings;
|
|
15
|
+
/**
|
|
16
|
+
* Deep merges settings, with required settings taking precedence
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeCliSettings(userSettings: CliSettings | null, requiredSettings: CliSettings): CliSettings;
|
|
19
|
+
/**
|
|
20
|
+
* Builds final args array with merged --settings
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildArgsWithMergedSettings(args: string[], requiredSettings: CliSettings): string[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts --settings from args, returning parsed settings and remaining args
|
|
3
|
+
*/
|
|
4
|
+
export function extractSettingsFromArgs(args) {
|
|
5
|
+
const settingsIdx = args.indexOf("--settings");
|
|
6
|
+
if (settingsIdx === -1 || settingsIdx >= args.length - 1) {
|
|
7
|
+
return { userSettings: null, argsWithoutSettings: args };
|
|
8
|
+
}
|
|
9
|
+
const settingsValue = args[settingsIdx + 1];
|
|
10
|
+
const argsWithoutSettings = [
|
|
11
|
+
...args.slice(0, settingsIdx),
|
|
12
|
+
...args.slice(settingsIdx + 2)
|
|
13
|
+
];
|
|
14
|
+
// JSON string
|
|
15
|
+
if (settingsValue.startsWith("{")) {
|
|
16
|
+
return {
|
|
17
|
+
userSettings: JSON.parse(settingsValue),
|
|
18
|
+
argsWithoutSettings
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// File path - return path for caller to handle
|
|
22
|
+
return {
|
|
23
|
+
userSettings: null,
|
|
24
|
+
settingsFilePath: settingsValue,
|
|
25
|
+
argsWithoutSettings
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Deep merges settings, with required settings taking precedence
|
|
30
|
+
*/
|
|
31
|
+
export function mergeCliSettings(userSettings, requiredSettings) {
|
|
32
|
+
if (!userSettings) {
|
|
33
|
+
return requiredSettings;
|
|
34
|
+
}
|
|
35
|
+
const merged = {
|
|
36
|
+
...userSettings,
|
|
37
|
+
...requiredSettings
|
|
38
|
+
};
|
|
39
|
+
// Deep merge env if both have it
|
|
40
|
+
if (userSettings.env || requiredSettings.env) {
|
|
41
|
+
merged.env = {
|
|
42
|
+
...(userSettings.env ?? {}),
|
|
43
|
+
...(requiredSettings.env ?? {})
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return merged;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Builds final args array with merged --settings
|
|
50
|
+
*/
|
|
51
|
+
export function buildArgsWithMergedSettings(args, requiredSettings) {
|
|
52
|
+
const { userSettings, argsWithoutSettings } = extractSettingsFromArgs(args);
|
|
53
|
+
const merged = mergeCliSettings(userSettings, requiredSettings);
|
|
54
|
+
return [...argsWithoutSettings, "--settings", JSON.stringify(merged)];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=cli-settings-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-settings-merge.js","sourceRoot":"","sources":["../../src/utils/cli-settings-merge.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAc;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/C,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAC3D,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,mBAAmB,GAAG;QAC1B,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;QAC7B,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;KAC/B,CAAC;IAEF,cAAc;IACd,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;YACvC,mBAAmB;SACpB,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,OAAO;QACL,YAAY,EAAE,IAAI;QAClB,gBAAgB,EAAE,aAAa;QAC/B,mBAAmB;KACpB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAAgC,EAChC,gBAA6B;IAE7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM,MAAM,GAAgB;QAC1B,GAAG,YAAY;QACf,GAAG,gBAAgB;KACpB,CAAC;IAEF,iCAAiC;IACjC,IAAI,YAAY,CAAC,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,GAAG;YACX,GAAG,CAAC,YAAY,CAAC,GAAG,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,gBAAgB,CAAC,GAAG,IAAI,EAAE,CAAC;SAChC,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,IAAc,EACd,gBAA6B;IAE7B,MAAM,EAAE,YAAY,EAAE,mBAAmB,EAAE,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAEhE,OAAO,CAAC,GAAG,mBAAmB,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { CommandRunner, CommandRunnerResult } from "@poe-code/agent-spawn";
|
|
2
|
+
export type { CommandRunner, CommandRunnerOptions, CommandRunnerResult } from "@poe-code/agent-spawn";
|
|
3
|
+
export declare function formatCommandRunnerResult(result: CommandRunnerResult): string;
|
|
4
|
+
export interface RunAndMatchOutputOptions {
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
expectedOutput: string;
|
|
8
|
+
skipOnDryRun?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function describeCommandExpectation(command: string, args: string[], expectedOutput: string): string;
|
|
11
|
+
export interface CommandExpectationCheckOptions extends RunAndMatchOutputOptions {
|
|
12
|
+
id: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function createCommandExpectationCheck(options: CommandExpectationCheckOptions): CommandCheck;
|
|
15
|
+
export declare function runAndMatchOutput(context: CommandCheckContext, options: RunAndMatchOutputOptions): Promise<void>;
|
|
16
|
+
export declare function stdoutMatchesExpected(stdout: string, expected: string): boolean;
|
|
17
|
+
export interface CommandCheckContext {
|
|
18
|
+
isDryRun: boolean;
|
|
19
|
+
runCommand: CommandRunner;
|
|
20
|
+
logDryRun?: (message: string) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface CommandCheck {
|
|
23
|
+
id: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
run(context: CommandCheckContext): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a check that detects if a binary exists using multiple fallback methods.
|
|
29
|
+
* This is useful in Docker/containerized environments where PATH may not be updated after npm install.
|
|
30
|
+
*
|
|
31
|
+
* @param binaryName - The name of the binary to check for (e.g., "claude", "codex")
|
|
32
|
+
* @param id - Unique identifier for the check
|
|
33
|
+
* @param description - Human-readable description of what's being checked
|
|
34
|
+
* @returns A CommandCheck that verifies the binary using multiple detection methods
|
|
35
|
+
*/
|
|
36
|
+
export declare function createBinaryExistsCheck(binaryName: string, id: string, description: string): CommandCheck;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export function formatCommandRunnerResult(result) {
|
|
2
|
+
const stdout = result.stdout.length > 0 ? result.stdout : "<empty>";
|
|
3
|
+
const stderr = result.stderr.length > 0 ? result.stderr : "<empty>";
|
|
4
|
+
return `stdout:\n${stdout}\nstderr:\n${stderr}`;
|
|
5
|
+
}
|
|
6
|
+
export function describeCommandExpectation(command, args, expectedOutput) {
|
|
7
|
+
return `${renderCommandLine(command, args)} (expecting "${expectedOutput}")`;
|
|
8
|
+
}
|
|
9
|
+
export function createCommandExpectationCheck(options) {
|
|
10
|
+
return {
|
|
11
|
+
id: options.id,
|
|
12
|
+
description: describeCommandExpectation(options.command, options.args, options.expectedOutput),
|
|
13
|
+
async run(context) {
|
|
14
|
+
await runAndMatchOutput(context, options);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export async function runAndMatchOutput(context, options) {
|
|
19
|
+
const rendered = renderCommandLine(options.command, options.args);
|
|
20
|
+
if (options.skipOnDryRun !== false && context.isDryRun) {
|
|
21
|
+
if (context.logDryRun) {
|
|
22
|
+
context.logDryRun(`Dry run: ${rendered} (expecting "${options.expectedOutput}")`);
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const result = await context.runCommand(options.command, options.args);
|
|
27
|
+
if (result.exitCode !== 0) {
|
|
28
|
+
const detail = formatCommandRunnerResult(result);
|
|
29
|
+
throw new Error([`Command ${rendered} failed with exit code ${result.exitCode}.`, detail].join("\n"));
|
|
30
|
+
}
|
|
31
|
+
if (!stdoutMatchesExpected(result.stdout, options.expectedOutput)) {
|
|
32
|
+
const detail = formatCommandRunnerResult(result);
|
|
33
|
+
const received = result.stdout.trim();
|
|
34
|
+
throw new Error([
|
|
35
|
+
`Command ${rendered} failed: expected "${options.expectedOutput}" but received "${received}".`,
|
|
36
|
+
detail
|
|
37
|
+
].join("\n"));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function stdoutMatchesExpected(stdout, expected) {
|
|
41
|
+
const trimmed = stdout.trim();
|
|
42
|
+
if (trimmed === expected) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return stdout
|
|
46
|
+
.split(/\r?\n/)
|
|
47
|
+
.map((line) => line.trim())
|
|
48
|
+
.filter((line) => line.length > 0)
|
|
49
|
+
.some((line) => line === expected);
|
|
50
|
+
}
|
|
51
|
+
function renderCommandLine(command, args) {
|
|
52
|
+
return [command, ...args].map(quoteIfNeeded).join(" ").trim();
|
|
53
|
+
}
|
|
54
|
+
function quoteIfNeeded(value) {
|
|
55
|
+
if (value.length === 0) {
|
|
56
|
+
return '""';
|
|
57
|
+
}
|
|
58
|
+
if (needsQuoting(value)) {
|
|
59
|
+
return `"${value.replaceAll('"', '\\"')}"`;
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function needsQuoting(value) {
|
|
64
|
+
return (value.includes(" ") ||
|
|
65
|
+
value.includes("\t") ||
|
|
66
|
+
value.includes("\n"));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Creates a check that detects if a binary exists using multiple fallback methods.
|
|
70
|
+
* This is useful in Docker/containerized environments where PATH may not be updated after npm install.
|
|
71
|
+
*
|
|
72
|
+
* @param binaryName - The name of the binary to check for (e.g., "claude", "codex")
|
|
73
|
+
* @param id - Unique identifier for the check
|
|
74
|
+
* @param description - Human-readable description of what's being checked
|
|
75
|
+
* @returns A CommandCheck that verifies the binary using multiple detection methods
|
|
76
|
+
*/
|
|
77
|
+
export function createBinaryExistsCheck(binaryName, id, description) {
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
description,
|
|
81
|
+
async run({ runCommand }) {
|
|
82
|
+
// Common installation paths for CLI tools
|
|
83
|
+
const commonPaths = [
|
|
84
|
+
`/usr/local/bin/${binaryName}`,
|
|
85
|
+
`/usr/bin/${binaryName}`,
|
|
86
|
+
`$HOME/.local/bin/${binaryName}`,
|
|
87
|
+
`$HOME/.claude/local/bin/${binaryName}`
|
|
88
|
+
];
|
|
89
|
+
const detectors = [
|
|
90
|
+
{
|
|
91
|
+
command: "which",
|
|
92
|
+
args: [binaryName],
|
|
93
|
+
validate: (result) => result.exitCode === 0
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
command: "where",
|
|
97
|
+
args: [binaryName],
|
|
98
|
+
validate: (result) => result.exitCode === 0 && result.stdout.trim().length > 0
|
|
99
|
+
},
|
|
100
|
+
// Check common installation paths using shell expansion for $HOME
|
|
101
|
+
{
|
|
102
|
+
command: "sh",
|
|
103
|
+
args: [
|
|
104
|
+
"-c",
|
|
105
|
+
commonPaths.map((p) => `test -f "${p}"`).join(" || ")
|
|
106
|
+
],
|
|
107
|
+
validate: (result) => result.exitCode === 0
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
for (const detector of detectors) {
|
|
111
|
+
const result = await runCommand(detector.command, detector.args);
|
|
112
|
+
if (detector.validate(result)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
throw new Error(`${binaryName} CLI binary not found on PATH.`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=command-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-checks.js","sourceRoot":"","sources":["../../src/utils/command-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function tokenizeCommandLine(input: string): string[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function tokenizeCommandLine(input) {
|
|
2
|
+
const trimmed = input.trim();
|
|
3
|
+
if (trimmed.length === 0) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
const tokens = [];
|
|
7
|
+
let current = "";
|
|
8
|
+
let quote = null;
|
|
9
|
+
let escapeNext = false;
|
|
10
|
+
for (const char of trimmed) {
|
|
11
|
+
if (escapeNext) {
|
|
12
|
+
current += char;
|
|
13
|
+
escapeNext = false;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (char === "\\" && quote !== "'") {
|
|
17
|
+
escapeNext = true;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (quote) {
|
|
21
|
+
if (char === quote) {
|
|
22
|
+
quote = null;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
current += char;
|
|
26
|
+
}
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (char === "'" || char === '"') {
|
|
30
|
+
quote = char;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (char === " " || char === "\t") {
|
|
34
|
+
if (current.length > 0) {
|
|
35
|
+
tokens.push(current);
|
|
36
|
+
current = "";
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
current += char;
|
|
41
|
+
}
|
|
42
|
+
if (escapeNext) {
|
|
43
|
+
current += "\\";
|
|
44
|
+
}
|
|
45
|
+
if (current.length > 0) {
|
|
46
|
+
tokens.push(current);
|
|
47
|
+
}
|
|
48
|
+
if (quote && tokens.length > 0) {
|
|
49
|
+
const last = tokens.pop() ?? "";
|
|
50
|
+
tokens.push(`${last}${quote}`);
|
|
51
|
+
}
|
|
52
|
+
return tokens;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=command-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-line.js","sourceRoot":"","sources":["../../src/utils/command-line.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,KAAK,GAAqB,IAAI,CAAC;IACnC,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,IAAI,IAAI,CAAC;YAChB,UAAU,GAAG,KAAK,CAAC;YACnB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACnC,UAAU,GAAG,IAAI,CAAC;YAClB,SAAS;QACX,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,IAAI,CAAC;YAClB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,KAAK,GAAG,IAAI,CAAC;YACb,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;YACD,SAAS;QACX,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { FileSystem } from "./file-system.js";
|
|
2
|
+
export type DryRunOperation = {
|
|
3
|
+
type: "writeFile";
|
|
4
|
+
path: string;
|
|
5
|
+
nextContent: string;
|
|
6
|
+
previousContent: string | null;
|
|
7
|
+
} | {
|
|
8
|
+
type: "mkdir";
|
|
9
|
+
path: string;
|
|
10
|
+
options?: {
|
|
11
|
+
recursive?: boolean;
|
|
12
|
+
};
|
|
13
|
+
} | {
|
|
14
|
+
type: "unlink";
|
|
15
|
+
path: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: "rm";
|
|
18
|
+
path: string;
|
|
19
|
+
options?: {
|
|
20
|
+
recursive?: boolean;
|
|
21
|
+
force?: boolean;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
type: "copyFile";
|
|
25
|
+
from: string;
|
|
26
|
+
to: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: "chmod";
|
|
29
|
+
path: string;
|
|
30
|
+
mode: number;
|
|
31
|
+
};
|
|
32
|
+
export declare class DryRunRecorder {
|
|
33
|
+
private operations;
|
|
34
|
+
record(operation: DryRunOperation): void;
|
|
35
|
+
drain(): DryRunOperation[];
|
|
36
|
+
}
|
|
37
|
+
export declare function createDryRunFileSystem(base: FileSystem, recorder: DryRunRecorder): FileSystem;
|
|
38
|
+
export declare function formatDryRunOperations(operations: DryRunOperation[]): string[];
|
|
39
|
+
export declare function renderUnifiedDiff(targetPath: string, previousContent: string | null, nextContent: string): string[];
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { basename, extname } from "node:path";
|
|
3
|
+
import { createTwoFilesPatch } from "diff";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { isNotFound } from "@poe-code/config-mutations";
|
|
6
|
+
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
7
|
+
const JSON_SENSITIVE_KEYS = ["apiKey", "api_key", "apiKeyHelper"];
|
|
8
|
+
const AUTH_SENSITIVE_KEYS = ["key"];
|
|
9
|
+
const TOML_SENSITIVE_KEYS = ["experimental_bearer_token"];
|
|
10
|
+
export class DryRunRecorder {
|
|
11
|
+
operations = [];
|
|
12
|
+
record(operation) {
|
|
13
|
+
this.operations.push(operation);
|
|
14
|
+
}
|
|
15
|
+
drain() {
|
|
16
|
+
const snapshot = this.operations;
|
|
17
|
+
this.operations = [];
|
|
18
|
+
return snapshot;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function createDryRunFileSystem(base, recorder) {
|
|
22
|
+
const proxy = {
|
|
23
|
+
async readFile(path, encoding) {
|
|
24
|
+
if (encoding) {
|
|
25
|
+
return base.readFile(path, encoding);
|
|
26
|
+
}
|
|
27
|
+
return base.readFile(path);
|
|
28
|
+
},
|
|
29
|
+
async writeFile(path, data, options) {
|
|
30
|
+
const previousContent = await tryReadText(base, path);
|
|
31
|
+
const nextContent = formatData(data, options?.encoding);
|
|
32
|
+
recorder.record({
|
|
33
|
+
type: "writeFile",
|
|
34
|
+
path,
|
|
35
|
+
nextContent,
|
|
36
|
+
previousContent
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
async mkdir(path, options) {
|
|
40
|
+
recorder.record({ type: "mkdir", path, options });
|
|
41
|
+
},
|
|
42
|
+
async stat(path) {
|
|
43
|
+
return base.stat(path);
|
|
44
|
+
},
|
|
45
|
+
async unlink(path) {
|
|
46
|
+
recorder.record({ type: "unlink", path });
|
|
47
|
+
},
|
|
48
|
+
async readdir(path) {
|
|
49
|
+
return base.readdir(path);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
if (typeof base.rm === "function") {
|
|
53
|
+
proxy.rm = async (path, options) => {
|
|
54
|
+
recorder.record({ type: "rm", path, options });
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (typeof base.copyFile === "function") {
|
|
58
|
+
proxy.copyFile = async (from, to) => {
|
|
59
|
+
recorder.record({ type: "copyFile", from, to });
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (typeof base.chmod === "function") {
|
|
63
|
+
proxy.chmod = async (target, mode) => {
|
|
64
|
+
recorder.record({ type: "chmod", path: target, mode });
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return proxy;
|
|
68
|
+
}
|
|
69
|
+
export function formatDryRunOperations(operations) {
|
|
70
|
+
if (operations.length === 0) {
|
|
71
|
+
return [chalk.dim("# no filesystem changes")];
|
|
72
|
+
}
|
|
73
|
+
const lines = [];
|
|
74
|
+
for (const operation of operations) {
|
|
75
|
+
const formatted = formatOperation(operation);
|
|
76
|
+
if (Array.isArray(formatted)) {
|
|
77
|
+
if (formatted.length === 0) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const [first, ...rest] = formatted;
|
|
81
|
+
const indented = rest.map((line) => ` ${line}`);
|
|
82
|
+
lines.push([first, ...indented].join("\n"));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
lines.push(formatted);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return lines;
|
|
89
|
+
}
|
|
90
|
+
function formatOperation(operation) {
|
|
91
|
+
switch (operation.type) {
|
|
92
|
+
case "mkdir": {
|
|
93
|
+
const recursiveFlag = operation.options?.recursive ? " -p" : "";
|
|
94
|
+
const command = `mkdir${recursiveFlag} ${operation.path}`;
|
|
95
|
+
return renderOperationCommand(command, chalk.cyan, "# ensure");
|
|
96
|
+
}
|
|
97
|
+
case "unlink":
|
|
98
|
+
return renderOperationCommand(`rm ${operation.path}`, chalk.red, "# delete");
|
|
99
|
+
case "rm": {
|
|
100
|
+
const flags = [];
|
|
101
|
+
if (operation.options?.recursive) {
|
|
102
|
+
flags.push("-r");
|
|
103
|
+
}
|
|
104
|
+
if (operation.options?.force) {
|
|
105
|
+
flags.push("-f");
|
|
106
|
+
}
|
|
107
|
+
const flagSuffix = flags.length > 0 ? ` ${flags.join(" ")}` : "";
|
|
108
|
+
return renderOperationCommand(`rm${flagSuffix} ${operation.path}`, chalk.red, "# delete");
|
|
109
|
+
}
|
|
110
|
+
case "copyFile":
|
|
111
|
+
return renderOperationCommand(`cp ${operation.from} ${operation.to}`, chalk.cyan, "# copy");
|
|
112
|
+
case "chmod": {
|
|
113
|
+
const mode = operation.mode.toString(8);
|
|
114
|
+
return renderOperationCommand(`chmod ${mode} ${operation.path}`, chalk.cyan, "# permissions");
|
|
115
|
+
}
|
|
116
|
+
case "writeFile": {
|
|
117
|
+
return renderWriteOperation(operation);
|
|
118
|
+
}
|
|
119
|
+
default: {
|
|
120
|
+
const neverOp = operation;
|
|
121
|
+
return chalk.dim(`# unknown ${neverOp.type}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function renderOperationCommand(command, colorize, detail) {
|
|
126
|
+
return `${colorize(command)} ${chalk.dim(detail)}`;
|
|
127
|
+
}
|
|
128
|
+
function describeWriteChange(previous, next) {
|
|
129
|
+
if (previous == null) {
|
|
130
|
+
return "create";
|
|
131
|
+
}
|
|
132
|
+
if (previous === next) {
|
|
133
|
+
return "noop";
|
|
134
|
+
}
|
|
135
|
+
return "update";
|
|
136
|
+
}
|
|
137
|
+
function renderWriteCommand(path, change) {
|
|
138
|
+
const command = `cat > ${path}`;
|
|
139
|
+
if (change === "create") {
|
|
140
|
+
return renderOperationCommand(command, chalk.green, "# create");
|
|
141
|
+
}
|
|
142
|
+
if (change === "update") {
|
|
143
|
+
return renderOperationCommand(command, chalk.yellow, "# update");
|
|
144
|
+
}
|
|
145
|
+
return renderOperationCommand(command, chalk.dim, "# no change");
|
|
146
|
+
}
|
|
147
|
+
function renderWriteOperation(operation) {
|
|
148
|
+
const change = describeWriteChange(operation.previousContent, operation.nextContent);
|
|
149
|
+
const lines = [renderWriteCommand(operation.path, change)];
|
|
150
|
+
if (change === "noop") {
|
|
151
|
+
return lines;
|
|
152
|
+
}
|
|
153
|
+
lines.push(...renderUnifiedDiff(operation.path, operation.previousContent, operation.nextContent));
|
|
154
|
+
return lines;
|
|
155
|
+
}
|
|
156
|
+
export function renderUnifiedDiff(targetPath, previousContent, nextContent) {
|
|
157
|
+
const sanitizedPrevious = previousContent == null
|
|
158
|
+
? null
|
|
159
|
+
: redactContentForDiff(targetPath, previousContent);
|
|
160
|
+
const sanitizedNext = redactContentForDiff(targetPath, nextContent);
|
|
161
|
+
const oldLabel = previousContent == null ? "/dev/null" : targetPath;
|
|
162
|
+
const patch = createTwoFilesPatch(oldLabel, targetPath, sanitizedPrevious ?? "", sanitizedNext, "", "", { context: 3 });
|
|
163
|
+
const diffLines = patch
|
|
164
|
+
.split("\n")
|
|
165
|
+
.filter((line) => line.length > 0);
|
|
166
|
+
const lines = [];
|
|
167
|
+
for (const line of diffLines) {
|
|
168
|
+
if (line.startsWith("Index:") || line.startsWith("====")) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (line.startsWith("---") || line.startsWith("+++")) {
|
|
172
|
+
lines.push(chalk.dim(line.trimEnd()));
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (line.startsWith("@@")) {
|
|
176
|
+
lines.push(chalk.cyan(line));
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (line.startsWith("+")) {
|
|
180
|
+
lines.push(chalk.green(line[0] ?? "+") + line.slice(1));
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (line.startsWith("-")) {
|
|
184
|
+
lines.push(chalk.red(line[0] ?? "-") + line.slice(1));
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (line.startsWith("\\ No newline")) {
|
|
188
|
+
lines.push(chalk.dim(line));
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
lines.push(chalk.dim(line));
|
|
192
|
+
}
|
|
193
|
+
return lines;
|
|
194
|
+
}
|
|
195
|
+
function redactContentForDiff(targetPath, content) {
|
|
196
|
+
const extension = extname(targetPath).toLowerCase();
|
|
197
|
+
if (extension === ".json") {
|
|
198
|
+
return redactJsonContent(content, basename(targetPath).toLowerCase());
|
|
199
|
+
}
|
|
200
|
+
if (extension === ".toml") {
|
|
201
|
+
return redactTomlContent(content);
|
|
202
|
+
}
|
|
203
|
+
return content;
|
|
204
|
+
}
|
|
205
|
+
function redactJsonContent(content, fileName) {
|
|
206
|
+
const keys = [...JSON_SENSITIVE_KEYS];
|
|
207
|
+
if (fileName === "auth.json") {
|
|
208
|
+
keys.push(...AUTH_SENSITIVE_KEYS);
|
|
209
|
+
}
|
|
210
|
+
return content
|
|
211
|
+
.split("\n")
|
|
212
|
+
.map((line) => redactJsonLine(line, keys))
|
|
213
|
+
.join("\n");
|
|
214
|
+
}
|
|
215
|
+
function redactJsonLine(line, keys) {
|
|
216
|
+
let result = line;
|
|
217
|
+
for (const key of keys) {
|
|
218
|
+
if (key === "apiKeyHelper") {
|
|
219
|
+
result = redactJsonStringValue(result, key, redactApiKeyHelperValue);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
result = redactJsonStringValue(result, key, () => REDACTED_PLACEHOLDER);
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
function redactApiKeyHelperValue(value) {
|
|
227
|
+
const echoIndex = value.indexOf("echo ");
|
|
228
|
+
if (echoIndex >= 0) {
|
|
229
|
+
const prefix = value.slice(0, echoIndex + "echo ".length);
|
|
230
|
+
return `${prefix}${REDACTED_PLACEHOLDER}`;
|
|
231
|
+
}
|
|
232
|
+
return REDACTED_PLACEHOLDER;
|
|
233
|
+
}
|
|
234
|
+
function redactJsonStringValue(line, key, redact) {
|
|
235
|
+
const token = `"${key}"`;
|
|
236
|
+
const keyIndex = line.indexOf(token);
|
|
237
|
+
if (keyIndex === -1) {
|
|
238
|
+
return line;
|
|
239
|
+
}
|
|
240
|
+
const colonIndex = line.indexOf(":", keyIndex + token.length);
|
|
241
|
+
if (colonIndex === -1) {
|
|
242
|
+
return line;
|
|
243
|
+
}
|
|
244
|
+
const valueStart = line.indexOf("\"", colonIndex + 1);
|
|
245
|
+
if (valueStart === -1) {
|
|
246
|
+
return line;
|
|
247
|
+
}
|
|
248
|
+
const valueEnd = line.indexOf("\"", valueStart + 1);
|
|
249
|
+
if (valueEnd === -1) {
|
|
250
|
+
return line;
|
|
251
|
+
}
|
|
252
|
+
const currentValue = line.slice(valueStart + 1, valueEnd);
|
|
253
|
+
const nextValue = redact(currentValue);
|
|
254
|
+
return `${line.slice(0, valueStart + 1)}${nextValue}${line.slice(valueEnd)}`;
|
|
255
|
+
}
|
|
256
|
+
function redactTomlContent(content) {
|
|
257
|
+
return content
|
|
258
|
+
.split("\n")
|
|
259
|
+
.map((line) => redactTomlLine(line))
|
|
260
|
+
.join("\n");
|
|
261
|
+
}
|
|
262
|
+
function redactTomlLine(line) {
|
|
263
|
+
const trimmed = line.trimStart();
|
|
264
|
+
for (const key of TOML_SENSITIVE_KEYS) {
|
|
265
|
+
if (!trimmed.startsWith(key)) {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const nextChar = trimmed.charAt(key.length);
|
|
269
|
+
if (nextChar && nextChar !== " " && nextChar !== "=") {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const keyIndex = line.indexOf(key);
|
|
273
|
+
const equalsIndex = line.indexOf("=", keyIndex + key.length);
|
|
274
|
+
if (equalsIndex === -1) {
|
|
275
|
+
return line;
|
|
276
|
+
}
|
|
277
|
+
const valueStart = line.indexOf("\"", equalsIndex + 1);
|
|
278
|
+
if (valueStart === -1) {
|
|
279
|
+
return line;
|
|
280
|
+
}
|
|
281
|
+
const valueEnd = line.indexOf("\"", valueStart + 1);
|
|
282
|
+
if (valueEnd === -1) {
|
|
283
|
+
return line;
|
|
284
|
+
}
|
|
285
|
+
return `${line.slice(0, valueStart + 1)}${REDACTED_PLACEHOLDER}${line.slice(valueEnd)}`;
|
|
286
|
+
}
|
|
287
|
+
return line;
|
|
288
|
+
}
|
|
289
|
+
async function tryReadText(base, path) {
|
|
290
|
+
try {
|
|
291
|
+
return await base.readFile(path, "utf8");
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
if (isNotFound(error)) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function formatData(data, encoding = "utf8") {
|
|
301
|
+
if (typeof data === "string") {
|
|
302
|
+
return data;
|
|
303
|
+
}
|
|
304
|
+
try {
|
|
305
|
+
const buffer = bufferFromView(data);
|
|
306
|
+
return buffer.toString(encoding);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return `<binary data (${data.byteLength} bytes)>`;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function bufferFromView(view) {
|
|
313
|
+
return Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=dry-run.js.map
|