





















@@ -66,7 +66,7 @@ vi.mock("./backup.js", () => ({
6666}));
67676868const {
69-MIGRATION_SKILL_SELECTION_SKIP,
69+MIGRATION_SKILL_SELECTION_ACCEPT,
7070MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
7171MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
7272} = await import("./migrate/selection.js");
@@ -444,11 +444,11 @@ describe("migrateApplyCommand", () => {
444444expect(selectionPrompt.initialValues).toStrictEqual(["skill:alpha", "skill:beta"]);
445445expect(selectionPrompt.required).toBe(false);
446446expect(selectionPrompt.options?.map(({ label, value }) => ({ label, value }))).toStrictEqual([
447-{ value: MIGRATION_SKILL_SELECTION_SKIP, label: "Skip for now" },
448-{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
449-{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
447+{ value: MIGRATION_SKILL_SELECTION_ACCEPT, label: "Accept recommended" },
450448{ value: "skill:alpha", label: "alpha" },
451449{ value: "skill:beta", label: "beta" },
450+{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
451+{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
452452]);
453453expect(mocks.promptYesNo).toHaveBeenCalledWith("Apply this migration now?", false);
454454const appliedPlan = firstAppliedPlan();
@@ -504,11 +504,11 @@ describe("migrateApplyCommand", () => {
504504expect(pluginPrompt.initialValues).toStrictEqual(["plugin:google-calendar", "plugin:gmail"]);
505505expect(pluginPrompt.required).toBe(false);
506506expect(pluginPrompt.options?.map(({ label, value }) => ({ label, value }))).toStrictEqual([
507-{ value: MIGRATION_SKILL_SELECTION_SKIP, label: "Skip for now" },
508-{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
509-{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
507+{ value: MIGRATION_SKILL_SELECTION_ACCEPT, label: "Accept recommended" },
510508{ value: "plugin:google-calendar", label: "google-calendar" },
511509{ value: "plugin:gmail", label: "gmail" },
510+{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
511+{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
512512]);
513513expect(mocks.promptYesNo).toHaveBeenCalledWith("Apply this migration now?", false);
514514const appliedPlan = firstAppliedPlan();
@@ -652,59 +652,6 @@ describe("migrateApplyCommand", () => {
652652expect(itemsById.get("plugin:gmail")?.status).toBe("planned");
653653});
654654655-it("skips interactive Codex plugin migration before confirmation when Skip for now is selected", async () => {
656-Object.defineProperty(process.stdin, "isTTY", {
657-configurable: true,
658-value: true,
659-});
660-const planned = codexPluginPlan();
661-mocks.provider.plan.mockResolvedValue(planned);
662-mocks.multiselect.mockResolvedValue([MIGRATION_SKILL_SELECTION_SKIP]);
663-664-const result = await migrateDefaultCommand(runtime, { provider: "codex" });
665-666-expect(result).toBe(planned);
667-expect(mocks.promptYesNo).not.toHaveBeenCalled();
668-expect(mocks.backupCreateCommand).not.toHaveBeenCalled();
669-expect(mocks.provider.apply).not.toHaveBeenCalled();
670-expect(runtime.log).toHaveBeenCalledWith("Codex plugin migration skipped for now.");
671-});
672-673-it("returns without confirmation when both Codex skill and plugin selectors are skipped", async () => {
674-Object.defineProperty(process.stdin, "isTTY", {
675-configurable: true,
676-value: true,
677-});
678-const skillPlan = codexSkillPlan();
679-const pluginPlan = codexPluginPlan();
680-const planned = codexSkillPlan({
681-summary: {
682-total: skillPlan.items.length + pluginPlan.items.length,
683-planned: skillPlan.items.length + pluginPlan.items.length,
684-migrated: 0,
685-skipped: 0,
686-conflicts: 0,
687-errors: 0,
688-sensitive: 0,
689-},
690-items: [...skillPlan.items, ...pluginPlan.items],
691-});
692-mocks.provider.plan.mockResolvedValue(planned);
693-mocks.multiselect
694-.mockResolvedValueOnce([MIGRATION_SKILL_SELECTION_SKIP])
695-.mockResolvedValueOnce([MIGRATION_SKILL_SELECTION_SKIP]);
696-697-const result = await migrateDefaultCommand(runtime, { provider: "codex" });
698-699-expect(result).toBe(planned);
700-expect(mocks.multiselect).toHaveBeenCalledTimes(2);
701-expect(mocks.promptYesNo).not.toHaveBeenCalled();
702-expect(mocks.backupCreateCommand).not.toHaveBeenCalled();
703-expect(mocks.provider.apply).not.toHaveBeenCalled();
704-expect(runtime.log).toHaveBeenCalledWith("Codex skill migration skipped for now.");
705-expect(runtime.log).toHaveBeenCalledWith("Codex plugin migration skipped for now.");
706-});
707-708655it("does not apply when interactive Codex plugin migration chooses no plugins", async () => {
709656Object.defineProperty(process.stdin, "isTTY", {
710657configurable: true,
@@ -821,105 +768,6 @@ describe("migrateApplyCommand", () => {
821768expect(mocks.provider.apply).not.toHaveBeenCalled();
822769});
823770824-it("continues to interactive Codex plugins when skill migration is skipped", async () => {
825-Object.defineProperty(process.stdin, "isTTY", {
826-configurable: true,
827-value: true,
828-});
829-const skillPlan = codexSkillPlan();
830-const pluginPlan = codexPluginPlan();
831-const planned = codexSkillPlan({
832-summary: {
833-total: skillPlan.items.length + pluginPlan.items.length,
834-planned: skillPlan.items.length + pluginPlan.items.length,
835-migrated: 0,
836-skipped: 0,
837-conflicts: 0,
838-errors: 0,
839-sensitive: 0,
840-},
841-items: [...skillPlan.items, ...pluginPlan.items],
842-});
843-mocks.provider.plan.mockResolvedValue(planned);
844-mocks.multiselect
845-.mockResolvedValueOnce([MIGRATION_SKILL_SELECTION_SKIP])
846-.mockResolvedValueOnce(["plugin:gmail"]);
847-mocks.promptYesNo.mockResolvedValue(true);
848-mocks.provider.apply.mockImplementation(async (_ctx, selectedPlan: MigrationPlan) => ({
849- ...selectedPlan,
850-summary: { ...selectedPlan.summary, planned: 0, migrated: selectedPlan.summary.planned },
851-items: selectedPlan.items.map((item) =>
852-item.status === "planned" ? { ...item, status: "migrated" as const } : item,
853-),
854-}));
855-856-await migrateDefaultCommand(runtime, { provider: "codex" });
857-858-expect(mocks.multiselect).toHaveBeenCalledTimes(2);
859-expect(runtime.log).toHaveBeenCalledWith("Codex skill migration skipped for now.");
860-expect(mocks.promptYesNo).toHaveBeenCalledWith("Apply this migration now?", false);
861-const appliedPlan = firstAppliedPlan();
862-expect(appliedPlan.summary.planned).toBe(3);
863-expect(appliedPlan.summary.skipped).toBe(3);
864-expect(appliedPlan.summary.conflicts).toBe(0);
865-const itemsById = new Map(appliedPlan.items.map((item) => [item.id, item]));
866-expect(itemsById.get("skill:alpha")?.status).toBe("skipped");
867-expect(itemsById.get("skill:alpha")?.reason).toBe("not selected for migration");
868-expect(itemsById.get("skill:beta")?.status).toBe("skipped");
869-expect(itemsById.get("skill:beta")?.reason).toBe("not selected for migration");
870-expect(itemsById.get("plugin:gmail")?.status).toBe("planned");
871-expect(itemsById.get("plugin:google-calendar")?.status).toBe("skipped");
872-expect(itemsById.get("plugin:google-calendar")?.reason).toBe("not selected for migration");
873-});
874-875-it("explains skipped plugin selection when Codex subscription auth is required", async () => {
876-Object.defineProperty(process.stdin, "isTTY", {
877-configurable: true,
878-value: true,
879-});
880-const skillPlan = codexSkillPlan();
881-const warning =
882-"Codex app-backed plugin migration requires the Codex app-server source account to be logged in with a ChatGPT subscription account.";
883-const planned = codexSkillPlan({
884-summary: {
885-total: skillPlan.items.length + 1,
886-planned: skillPlan.summary.planned,
887-migrated: 0,
888-skipped: 1,
889-conflicts: 0,
890-errors: 0,
891-sensitive: 0,
892-},
893-items: [
894- ...skillPlan.items,
895-{
896-id: "plugin:gmail:1",
897-kind: "manual",
898-action: "manual",
899-status: "skipped",
900-reason: "codex_subscription_required",
901-details: { pluginName: "gmail" },
902-},
903-],
904-warnings: [warning],
905-});
906-mocks.provider.plan.mockResolvedValue(planned);
907-mocks.multiselect.mockResolvedValueOnce([MIGRATION_SKILL_SELECTION_SKIP]);
908-909-const result = await migrateDefaultCommand(runtime, { provider: "codex" });
910-911-expect(result.summary.planned).toBe(1);
912-expect(result.summary.skipped).toBe(3);
913-expect(mocks.multiselect).toHaveBeenCalledTimes(1);
914-expect(mocks.promptYesNo).not.toHaveBeenCalled();
915-expect(mocks.provider.apply).not.toHaveBeenCalled();
916-expect(runtime.log).toHaveBeenCalledWith("Codex skill migration skipped for now.");
917-expect(runtime.log).toHaveBeenCalledWith(warning);
918-expect(runtime.log).toHaveBeenCalledWith(
919-"No Codex skills selected; native Codex plugins are not eligible for migration in this run.",
920-);
921-});
922-923771it("does not apply archive-only Codex migration work after Toggle all off", async () => {
924772Object.defineProperty(process.stdin, "isTTY", {
925773configurable: true,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。