harness-wingman 0.8.0 → 0.8.2
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/apps/cli/dist/main.js +1228 -738
- package/apps/panel/dist/assets/index-CbsKc9BM.css +1 -0
- package/apps/panel/dist/assets/index-eHF_WfBX.js +236 -0
- package/apps/panel/dist/index.html +2 -2
- package/package.json +2 -2
- package/apps/panel/dist/assets/index-BquIYTp8.js +0 -231
- package/apps/panel/dist/assets/index-WYPdL-aq.css +0 -1
package/apps/cli/dist/main.js
CHANGED
|
@@ -7757,11 +7757,11 @@ function isPatchState(value) {
|
|
|
7757
7757
|
const patch = value;
|
|
7758
7758
|
return typeof patch.patchFile === "string" && typeof patch.original === "object" && patch.original !== null && typeof patch.original.existed === "boolean" && (patch.original.bytesBase64 === void 0 || typeof patch.original.bytesBase64 === "string");
|
|
7759
7759
|
}
|
|
7760
|
-
async function readState(
|
|
7761
|
-
const buffer = await readIfExists(
|
|
7760
|
+
async function readState(paths3) {
|
|
7761
|
+
const buffer = await readIfExists(paths3.stateFile);
|
|
7762
7762
|
if (buffer === void 0)
|
|
7763
7763
|
return void 0;
|
|
7764
|
-
const state = JSON.parse(decodeUtf8Strict(buffer,
|
|
7764
|
+
const state = JSON.parse(decodeUtf8Strict(buffer, paths3.stateFile));
|
|
7765
7765
|
if (typeof state !== "object" || state === null || state.version !== 1 && state.version !== 2) {
|
|
7766
7766
|
throw new Error("\u672A\u77E5\u7684\u63A5\u7EBF\u72B6\u6001\u7248\u672C,\u4E0D\u731C");
|
|
7767
7767
|
}
|
|
@@ -7770,18 +7770,18 @@ async function readState(paths) {
|
|
|
7770
7770
|
}
|
|
7771
7771
|
return state;
|
|
7772
7772
|
}
|
|
7773
|
-
async function writeState(
|
|
7774
|
-
await mkdir(dirname(
|
|
7775
|
-
await writeFile(
|
|
7773
|
+
async function writeState(paths3, state) {
|
|
7774
|
+
await mkdir(dirname(paths3.stateFile), { recursive: true });
|
|
7775
|
+
await writeFile(paths3.stateFile, `${JSON.stringify(state, void 0, 2)}
|
|
7776
7776
|
`, "utf8");
|
|
7777
7777
|
}
|
|
7778
|
-
function backupDirectory(
|
|
7779
|
-
return join(
|
|
7778
|
+
function backupDirectory(paths3) {
|
|
7779
|
+
return join(paths3.backupsRoot, (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
|
|
7780
7780
|
}
|
|
7781
|
-
async function backupPatchFile(
|
|
7782
|
-
const fromProfiles = relative(
|
|
7781
|
+
async function backupPatchFile(paths3, backupDir, file, bytes) {
|
|
7782
|
+
const fromProfiles = relative(paths3.profilesDir, file);
|
|
7783
7783
|
let safeRelative;
|
|
7784
|
-
if (file ===
|
|
7784
|
+
if (file === paths3.patchFile) {
|
|
7785
7785
|
safeRelative = join("home", "cordis.patch.yml");
|
|
7786
7786
|
} else if (!fromProfiles.startsWith("..") && !isAbsolute(fromProfiles)) {
|
|
7787
7787
|
safeRelative = join("profiles", fromProfiles);
|
|
@@ -7793,15 +7793,15 @@ async function backupPatchFile(paths, backupDir, file, bytes) {
|
|
|
7793
7793
|
await mkdir(dirname(target), { recursive: true });
|
|
7794
7794
|
await writeFile(target, bytes);
|
|
7795
7795
|
}
|
|
7796
|
-
async function writeOwnedFiles(
|
|
7797
|
-
await mkdir(dirname(
|
|
7798
|
-
await writeFile(
|
|
7799
|
-
await writeFile(
|
|
7796
|
+
async function writeOwnedFiles(paths3, url) {
|
|
7797
|
+
await mkdir(dirname(paths3.hooksConfigFile), { recursive: true });
|
|
7798
|
+
await writeFile(paths3.forwarderFile, FORWARDER_SOURCE, "utf8");
|
|
7799
|
+
await writeFile(paths3.hooksConfigFile, buildHooksConfig(paths3.forwarderFile, url), "utf8");
|
|
7800
7800
|
}
|
|
7801
|
-
async function listProfiles(
|
|
7801
|
+
async function listProfiles(paths3, environment) {
|
|
7802
7802
|
let entries;
|
|
7803
7803
|
try {
|
|
7804
|
-
entries = await readdir(
|
|
7804
|
+
entries = await readdir(paths3.profilesDir, { withFileTypes: true });
|
|
7805
7805
|
} catch (error) {
|
|
7806
7806
|
if (error.code === "ENOENT")
|
|
7807
7807
|
entries = [];
|
|
@@ -7813,12 +7813,12 @@ async function listProfiles(paths, environment) {
|
|
|
7813
7813
|
if (entry.name === "node_modules")
|
|
7814
7814
|
continue;
|
|
7815
7815
|
try {
|
|
7816
|
-
if (!(await stat(join(
|
|
7816
|
+
if (!(await stat(join(paths3.profilesDir, entry.name))).isDirectory())
|
|
7817
7817
|
continue;
|
|
7818
7818
|
} catch {
|
|
7819
7819
|
continue;
|
|
7820
7820
|
}
|
|
7821
|
-
const manifest = join(
|
|
7821
|
+
const manifest = join(paths3.profilesDir, entry.name, "package.json");
|
|
7822
7822
|
if (await readIfExists(manifest) !== void 0)
|
|
7823
7823
|
names.push(entry.name);
|
|
7824
7824
|
}
|
|
@@ -7830,12 +7830,12 @@ async function listProfiles(paths, environment) {
|
|
|
7830
7830
|
const selectedNames = selected === void 0 || selected === "" ? names : [selected];
|
|
7831
7831
|
const inspected = [];
|
|
7832
7832
|
for (const name of selectedNames) {
|
|
7833
|
-
const dir = join(
|
|
7833
|
+
const dir = join(paths3.profilesDir, name);
|
|
7834
7834
|
const missingPackages = [];
|
|
7835
7835
|
for (const packageName of REQUIRED_PACKAGES) {
|
|
7836
7836
|
const parts = packageName.split("/");
|
|
7837
7837
|
const localManifest = join(dir, "node_modules", ...parts, "package.json");
|
|
7838
|
-
const parentManifest = join(
|
|
7838
|
+
const parentManifest = join(paths3.profilesDir, "node_modules", ...parts, "package.json");
|
|
7839
7839
|
if (await readIfExists(localManifest) === void 0 && await readIfExists(parentManifest) === void 0) {
|
|
7840
7840
|
missingPackages.push(packageName);
|
|
7841
7841
|
}
|
|
@@ -7852,7 +7852,7 @@ async function listProfiles(paths, environment) {
|
|
|
7852
7852
|
function installCommand(profile) {
|
|
7853
7853
|
return `dsh plugin --profile ${profile} add ${DSH_HOOKS_PACKAGE}@${DSH_PINNED_VERSION} ${DSH_HOOK_PROTOCOL_PACKAGE}@${DSH_PINNED_VERSION}`;
|
|
7854
7854
|
}
|
|
7855
|
-
async function profileIsWired(profile,
|
|
7855
|
+
async function profileIsWired(profile, paths3) {
|
|
7856
7856
|
if (profile.missingPackages.length > 0)
|
|
7857
7857
|
return false;
|
|
7858
7858
|
const buffer = await readIfExists(profile.patchFile);
|
|
@@ -7869,18 +7869,18 @@ async function profileIsWired(profile, paths) {
|
|
|
7869
7869
|
const entries = tryParsePatchEntries(text, profile.patchFile);
|
|
7870
7870
|
if (entries === void 0 || !hasWingmanRow(entries))
|
|
7871
7871
|
return false;
|
|
7872
|
-
return await readIfExists(
|
|
7872
|
+
return await readIfExists(paths3.hooksConfigFile) !== void 0;
|
|
7873
7873
|
}
|
|
7874
7874
|
async function dshHookInstallReport(options, environment = process.env) {
|
|
7875
|
-
const
|
|
7876
|
-
const profiles = await listProfiles(
|
|
7875
|
+
const paths3 = resolveDshHookPaths(options);
|
|
7876
|
+
const profiles = await listProfiles(paths3, environment);
|
|
7877
7877
|
const reports = [];
|
|
7878
7878
|
for (const profile of profiles) {
|
|
7879
7879
|
const missingPackages = [...profile.missingPackages];
|
|
7880
7880
|
const blockPresent = hasLiveHooksBlock(await readIfExists(profile.patchFile));
|
|
7881
7881
|
const report = {
|
|
7882
7882
|
profile: profile.name,
|
|
7883
|
-
wired: await profileIsWired(profile,
|
|
7883
|
+
wired: await profileIsWired(profile, paths3),
|
|
7884
7884
|
blockPresent,
|
|
7885
7885
|
missingPackages
|
|
7886
7886
|
};
|
|
@@ -7890,16 +7890,16 @@ async function dshHookInstallReport(options, environment = process.env) {
|
|
|
7890
7890
|
}
|
|
7891
7891
|
return { profiles: reports };
|
|
7892
7892
|
}
|
|
7893
|
-
function prepareInstalledProfile(profile,
|
|
7893
|
+
function prepareInstalledProfile(profile, paths3, before, previous) {
|
|
7894
7894
|
const currentText = before === void 0 ? void 0 : decodeUtf8Strict(before, profile.patchFile);
|
|
7895
7895
|
const surgicalText = currentText === void 0 ? void 0 : stripLiveHooksBlocks(currentText, profile.patchFile);
|
|
7896
7896
|
const entriesBefore = surgicalText === void 0 ? [] : parsePatchEntries(surgicalText, profile.patchFile);
|
|
7897
7897
|
if (hasWingmanRow(entriesBefore)) {
|
|
7898
7898
|
throw new Error(`\u62D2\u5199:${profile.patchFile} \u5DF2\u6709\u672A\u5E26 wingman \u6807\u8BB0\u7684 ${DSH_HOOK_ROW_ID} \u6761\u76EE(\u7591\u624B\u5DE5\u6284\u5165),\u8BF7\u5148\u624B\u5DE5\u79FB\u9664`);
|
|
7899
7899
|
}
|
|
7900
|
-
const composed = composeInstalledText(surgicalText, entriesBefore.length, buildPatchBlock(
|
|
7900
|
+
const composed = composeInstalledText(surgicalText, entriesBefore.length, buildPatchBlock(paths3.hooksConfigFile));
|
|
7901
7901
|
const composedEntries = parsePatchEntries(composed, profile.patchFile);
|
|
7902
|
-
const expected = [...entriesBefore, expectedEntry(
|
|
7902
|
+
const expected = [...entriesBefore, expectedEntry(paths3.hooksConfigFile)];
|
|
7903
7903
|
if (JSON.stringify(composedEntries) !== JSON.stringify(expected)) {
|
|
7904
7904
|
throw new Error(`\u62D2\u5199:${profile.patchFile} \u8FFD\u52A0\u540E\u5F62\u72B6\u6821\u9A8C\u5931\u8D25(\u539F\u6587\u4EF6\u5F62\u6001\u65E0\u6CD5\u5B89\u5168\u8FFD\u52A0),\u4E0D\u731C`);
|
|
7905
7905
|
}
|
|
@@ -7951,13 +7951,13 @@ function restoredFromSnapshot(after, state) {
|
|
|
7951
7951
|
return false;
|
|
7952
7952
|
return after.equals(Buffer2.from(state.original.bytesBase64, "base64"));
|
|
7953
7953
|
}
|
|
7954
|
-
async function applyMutations(
|
|
7954
|
+
async function applyMutations(paths3, mutations) {
|
|
7955
7955
|
if (mutations.length === 0)
|
|
7956
7956
|
return;
|
|
7957
|
-
const backupDir = backupDirectory(
|
|
7957
|
+
const backupDir = backupDirectory(paths3);
|
|
7958
7958
|
for (const mutation of mutations) {
|
|
7959
7959
|
if (mutation.before !== void 0) {
|
|
7960
|
-
await backupPatchFile(
|
|
7960
|
+
await backupPatchFile(paths3, backupDir, mutation.file, mutation.before);
|
|
7961
7961
|
}
|
|
7962
7962
|
}
|
|
7963
7963
|
for (const mutation of mutations) {
|
|
@@ -7970,22 +7970,22 @@ async function applyMutations(paths, mutations) {
|
|
|
7970
7970
|
}
|
|
7971
7971
|
}
|
|
7972
7972
|
async function retireLegacyDshHomeHooks(options) {
|
|
7973
|
-
const
|
|
7973
|
+
const paths3 = resolveDshHookPaths(options);
|
|
7974
7974
|
try {
|
|
7975
|
-
const before = await readIfExists(
|
|
7975
|
+
const before = await readIfExists(paths3.patchFile);
|
|
7976
7976
|
if (!hasLiveHooksBlock(before))
|
|
7977
7977
|
return { removed: false, restored: "none" };
|
|
7978
|
-
const state = await readState(
|
|
7978
|
+
const state = await readState(paths3);
|
|
7979
7979
|
const candidate = state?.version === 1 ? { patchFile: state.patchFile, original: state.original } : state?.legacyHome;
|
|
7980
|
-
const legacyState = candidate?.patchFile ===
|
|
7981
|
-
const mutation = prepareRemoval(
|
|
7980
|
+
const legacyState = candidate?.patchFile === paths3.patchFile ? candidate : void 0;
|
|
7981
|
+
const mutation = prepareRemoval(paths3.patchFile, before, legacyState);
|
|
7982
7982
|
if (mutation === void 0)
|
|
7983
7983
|
return { removed: false, restored: "none" };
|
|
7984
|
-
await applyMutations(
|
|
7984
|
+
await applyMutations(paths3, [mutation]);
|
|
7985
7985
|
return {
|
|
7986
7986
|
removed: true,
|
|
7987
7987
|
restored: restoredFromSnapshot(mutation.after, legacyState) ? "byte-identical" : "surgical",
|
|
7988
|
-
path:
|
|
7988
|
+
path: paths3.patchFile
|
|
7989
7989
|
};
|
|
7990
7990
|
} catch {
|
|
7991
7991
|
return {
|
|
@@ -7997,9 +7997,9 @@ async function installDshHooks(port, options, environment = process.env) {
|
|
|
7997
7997
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
7998
7998
|
throw new Error(`\u975E\u6CD5\u7AEF\u53E3:${String(port)}`);
|
|
7999
7999
|
}
|
|
8000
|
-
const
|
|
8001
|
-
const profiles = await listProfiles(
|
|
8002
|
-
const previousState = await readState(
|
|
8000
|
+
const paths3 = resolveDshHookPaths(options);
|
|
8001
|
+
const profiles = await listProfiles(paths3, environment);
|
|
8002
|
+
const previousState = await readState(paths3);
|
|
8003
8003
|
const previousProfiles = previousState?.version === 2 ? previousState.profiles : {};
|
|
8004
8004
|
const nextProfiles = { ...previousProfiles };
|
|
8005
8005
|
const mutations = [];
|
|
@@ -8007,7 +8007,7 @@ async function installDshHooks(port, options, environment = process.env) {
|
|
|
8007
8007
|
for (const profile of profiles) {
|
|
8008
8008
|
const before = await readIfExists(profile.patchFile);
|
|
8009
8009
|
if (profile.missingPackages.length === 0) {
|
|
8010
|
-
const prepared = prepareInstalledProfile(profile,
|
|
8010
|
+
const prepared = prepareInstalledProfile(profile, paths3, before, previousProfiles[profile.name]);
|
|
8011
8011
|
nextProfiles[profile.name] = prepared.state;
|
|
8012
8012
|
if (prepared.mutation !== void 0)
|
|
8013
8013
|
mutations.push(prepared.mutation);
|
|
@@ -8021,19 +8021,19 @@ async function installDshHooks(port, options, environment = process.env) {
|
|
|
8021
8021
|
}
|
|
8022
8022
|
}
|
|
8023
8023
|
let legacyHome = previousState?.version === 2 ? previousState.legacyHome : previousState?.version === 1 ? { patchFile: previousState.patchFile, original: previousState.original } : void 0;
|
|
8024
|
-
const legacyBefore = await readIfExists(
|
|
8024
|
+
const legacyBefore = await readIfExists(paths3.patchFile);
|
|
8025
8025
|
let migratedThisRun = false;
|
|
8026
8026
|
if (hasLiveHooksBlock(legacyBefore)) {
|
|
8027
|
-
const legacyText = decodeUtf8Strict(legacyBefore,
|
|
8028
|
-
parsePatchEntries(legacyText,
|
|
8029
|
-
const surgical = stripLiveHooksBlocks(legacyText,
|
|
8030
|
-
const surgicalEntries = parsePatchEntries(surgical,
|
|
8027
|
+
const legacyText = decodeUtf8Strict(legacyBefore, paths3.patchFile);
|
|
8028
|
+
parsePatchEntries(legacyText, paths3.patchFile);
|
|
8029
|
+
const surgical = stripLiveHooksBlocks(legacyText, paths3.patchFile);
|
|
8030
|
+
const surgicalEntries = parsePatchEntries(surgical, paths3.patchFile);
|
|
8031
8031
|
legacyHome ??= {
|
|
8032
|
-
patchFile:
|
|
8032
|
+
patchFile: paths3.patchFile,
|
|
8033
8033
|
original: { existed: true }
|
|
8034
8034
|
};
|
|
8035
|
-
const after = resolveRestoredBytes(surgical, surgicalEntries, legacyHome,
|
|
8036
|
-
mutations.push({ file:
|
|
8035
|
+
const after = resolveRestoredBytes(surgical, surgicalEntries, legacyHome, paths3.patchFile);
|
|
8036
|
+
mutations.push({ file: paths3.patchFile, before: legacyBefore, after });
|
|
8037
8037
|
migratedThisRun = true;
|
|
8038
8038
|
}
|
|
8039
8039
|
const nextState = {
|
|
@@ -8046,38 +8046,38 @@ async function installDshHooks(port, options, environment = process.env) {
|
|
|
8046
8046
|
const hasState = hasManagedProfiles || legacyHome !== void 0;
|
|
8047
8047
|
const url = `http://127.0.0.1:${port}/hook?harness=dsh`;
|
|
8048
8048
|
if (hasManagedProfiles) {
|
|
8049
|
-
await writeOwnedFiles(
|
|
8049
|
+
await writeOwnedFiles(paths3, url);
|
|
8050
8050
|
if (hasState)
|
|
8051
|
-
await writeState(
|
|
8051
|
+
await writeState(paths3, nextState);
|
|
8052
8052
|
else
|
|
8053
|
-
await rm(
|
|
8054
|
-
await applyMutations(
|
|
8053
|
+
await rm(paths3.stateFile, { force: true });
|
|
8054
|
+
await applyMutations(paths3, mutations);
|
|
8055
8055
|
} else {
|
|
8056
|
-
await applyMutations(
|
|
8057
|
-
await rm(
|
|
8058
|
-
await rm(
|
|
8056
|
+
await applyMutations(paths3, mutations);
|
|
8057
|
+
await rm(paths3.hooksConfigFile, { force: true });
|
|
8058
|
+
await rm(paths3.forwarderFile, { force: true });
|
|
8059
8059
|
if (hasState)
|
|
8060
|
-
await writeState(
|
|
8060
|
+
await writeState(paths3, nextState);
|
|
8061
8061
|
else
|
|
8062
|
-
await rm(
|
|
8062
|
+
await rm(paths3.stateFile, { force: true });
|
|
8063
8063
|
}
|
|
8064
8064
|
return { migratedThisRun, removedProfiles };
|
|
8065
8065
|
}
|
|
8066
8066
|
async function uninstallDshHooks(options, environment = process.env) {
|
|
8067
|
-
const
|
|
8068
|
-
const state = await readState(
|
|
8067
|
+
const paths3 = resolveDshHookPaths(options);
|
|
8068
|
+
const state = await readState(paths3);
|
|
8069
8069
|
const stateProfiles = state?.version === 2 ? state.profiles : {};
|
|
8070
8070
|
const selected = environment.WINGMAN_DSH_PROFILE;
|
|
8071
8071
|
const inspectionEnvironment = { ...environment };
|
|
8072
8072
|
delete inspectionEnvironment.WINGMAN_DSH_PROFILE;
|
|
8073
|
-
const inspected = await listProfiles(
|
|
8073
|
+
const inspected = await listProfiles(paths3, inspectionEnvironment);
|
|
8074
8074
|
if (selected !== void 0 && selected !== "" && !inspected.some((profile) => profile.name === selected) && stateProfiles[selected] === void 0) {
|
|
8075
8075
|
throw new Error(`dsh profile \u4E0D\u5B58\u5728\u6216\u7F3A package.json:${selected}`);
|
|
8076
8076
|
}
|
|
8077
8077
|
const targetNames = selected === void 0 || selected === "" ? [.../* @__PURE__ */ new Set([...inspected.map((profile) => profile.name), ...Object.keys(stateProfiles)])] : [selected];
|
|
8078
8078
|
const remainingProfiles = { ...stateProfiles };
|
|
8079
8079
|
for (const profile of inspected) {
|
|
8080
|
-
if (!targetNames.includes(profile.name) && await profileIsWired(profile,
|
|
8080
|
+
if (!targetNames.includes(profile.name) && await profileIsWired(profile, paths3)) {
|
|
8081
8081
|
remainingProfiles[profile.name] ??= {
|
|
8082
8082
|
patchFile: profile.patchFile,
|
|
8083
8083
|
original: { existed: true }
|
|
@@ -8088,10 +8088,10 @@ async function uninstallDshHooks(options, environment = process.env) {
|
|
|
8088
8088
|
const results = [];
|
|
8089
8089
|
for (const name of targetNames) {
|
|
8090
8090
|
const profileState = stateProfiles[name];
|
|
8091
|
-
const file = profileState?.patchFile ?? join(
|
|
8091
|
+
const file = profileState?.patchFile ?? join(paths3.profilesDir, name, "cordis.patch.yml");
|
|
8092
8092
|
const before = await readIfExists(file);
|
|
8093
8093
|
const inspectedProfile = inspected.find((profile) => profile.name === name);
|
|
8094
|
-
const wired = inspectedProfile === void 0 ? false : await profileIsWired(inspectedProfile,
|
|
8094
|
+
const wired = inspectedProfile === void 0 ? false : await profileIsWired(inspectedProfile, paths3);
|
|
8095
8095
|
const removal = prepareRemoval(file, before, profileState);
|
|
8096
8096
|
if (removal !== void 0) {
|
|
8097
8097
|
mutations.push(removal);
|
|
@@ -8105,31 +8105,31 @@ async function uninstallDshHooks(options, environment = process.env) {
|
|
|
8105
8105
|
delete remainingProfiles[name];
|
|
8106
8106
|
}
|
|
8107
8107
|
const legacyState = state?.version === 1 ? { patchFile: state.patchFile, original: state.original } : state?.legacyHome;
|
|
8108
|
-
const legacyFile = legacyState?.patchFile ??
|
|
8108
|
+
const legacyFile = legacyState?.patchFile ?? paths3.patchFile;
|
|
8109
8109
|
const legacyRemoval = prepareRemoval(legacyFile, await readIfExists(legacyFile), legacyState);
|
|
8110
8110
|
if (legacyRemoval !== void 0)
|
|
8111
8111
|
mutations.push(legacyRemoval);
|
|
8112
|
-
await applyMutations(
|
|
8112
|
+
await applyMutations(paths3, mutations);
|
|
8113
8113
|
if (Object.keys(remainingProfiles).length > 0) {
|
|
8114
|
-
await writeState(
|
|
8114
|
+
await writeState(paths3, {
|
|
8115
8115
|
version: 2,
|
|
8116
8116
|
port: state?.port ?? 7333,
|
|
8117
8117
|
profiles: remainingProfiles
|
|
8118
8118
|
});
|
|
8119
8119
|
} else {
|
|
8120
|
-
await rm(
|
|
8121
|
-
await rm(
|
|
8122
|
-
await rm(
|
|
8120
|
+
await rm(paths3.hooksConfigFile, { force: true });
|
|
8121
|
+
await rm(paths3.forwarderFile, { force: true });
|
|
8122
|
+
await rm(paths3.stateFile, { force: true });
|
|
8123
8123
|
}
|
|
8124
8124
|
return { profiles: results };
|
|
8125
8125
|
}
|
|
8126
8126
|
async function detectDshLiveWiring(options, environment = process.env) {
|
|
8127
|
-
const
|
|
8127
|
+
const paths3 = resolveDshHookPaths(options);
|
|
8128
8128
|
const inspectionEnvironment = { ...environment };
|
|
8129
8129
|
delete inspectionEnvironment.WINGMAN_DSH_PROFILE;
|
|
8130
|
-
const profiles = await listProfiles(
|
|
8130
|
+
const profiles = await listProfiles(paths3, inspectionEnvironment);
|
|
8131
8131
|
for (const profile of profiles) {
|
|
8132
|
-
if (await profileIsWired(profile,
|
|
8132
|
+
if (await profileIsWired(profile, paths3))
|
|
8133
8133
|
return true;
|
|
8134
8134
|
}
|
|
8135
8135
|
return false;
|
|
@@ -8193,17 +8193,19 @@ var init_feedback_url = __esm({
|
|
|
8193
8193
|
|
|
8194
8194
|
// packages/core/dist/plan-protocol.js
|
|
8195
8195
|
import { createHash as createHash2 } from "node:crypto";
|
|
8196
|
-
function planProtocolBlockStart(version = PLAN_PROTOCOL_VERSION) {
|
|
8197
|
-
return `<!-- >>> wingman plan protocol v${version} >>> -->`;
|
|
8196
|
+
function planProtocolBlockStart(version = PLAN_PROTOCOL_VERSION, scope = "project") {
|
|
8197
|
+
return `<!-- >>> wingman plan protocol ${scope === "user" ? "user " : ""}v${version} >>> -->`;
|
|
8198
8198
|
}
|
|
8199
|
-
function buildPlanProtocolBlock(version = PLAN_PROTOCOL_VERSION, text) {
|
|
8200
|
-
|
|
8199
|
+
function buildPlanProtocolBlock(version = PLAN_PROTOCOL_VERSION, text, scope = "project") {
|
|
8200
|
+
const known = scope === "user" ? KNOWN_USER_PROTOCOL_TEXT : KNOWN_PROTOCOL_TEXT;
|
|
8201
|
+
let body = normalizeMarkdownLineEndings(text ?? known.get(version) ?? "");
|
|
8201
8202
|
if (body === "")
|
|
8202
8203
|
throw new Error(`\u672A\u77E5 Plan Protocol \u7248\u672C v${version}\uFF0C\u4E14\u672A\u63D0\u4F9B\u6B63\u6587`);
|
|
8203
8204
|
if (!body.endsWith("\n"))
|
|
8204
8205
|
body += "\n";
|
|
8205
|
-
|
|
8206
|
-
|
|
8206
|
+
const end = scope === "user" ? PLAN_PROTOCOL_USER_BLOCK_END : PLAN_PROTOCOL_BLOCK_END;
|
|
8207
|
+
return `${planProtocolBlockStart(version, scope)}
|
|
8208
|
+
${body}${end}
|
|
8207
8209
|
`;
|
|
8208
8210
|
}
|
|
8209
8211
|
function decodeUtf8Strict2(bytes, sourcePath = "<memory>") {
|
|
@@ -8224,9 +8226,17 @@ function preferredMarkdownLineEnding(text) {
|
|
|
8224
8226
|
const hasBareLf = text.replaceAll("\r\n", "").includes("\n");
|
|
8225
8227
|
return hasCrlf && !hasBareLf ? "\r\n" : "\n";
|
|
8226
8228
|
}
|
|
8227
|
-
function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
|
|
8228
|
-
const
|
|
8229
|
-
const
|
|
8229
|
+
function splitPlanProtocolBlock(text, sourcePath = "<memory>", scope = "project") {
|
|
8230
|
+
const startPattern = scope === "user" ? USER_BLOCK_START : BLOCK_START;
|
|
8231
|
+
const endMarker = scope === "user" ? PLAN_PROTOCOL_USER_BLOCK_END : PLAN_PROTOCOL_BLOCK_END;
|
|
8232
|
+
const starts = [...text.matchAll(startPattern)];
|
|
8233
|
+
const ends = allIndexesOf(text, endMarker);
|
|
8234
|
+
if (scope === "user") {
|
|
8235
|
+
const unrecognized = text.replace(startPattern, "").replaceAll(endMarker, "");
|
|
8236
|
+
if (/<!--\s*(?:>>>|<<<)\s*wingman plan protocol user\b/u.test(unrecognized)) {
|
|
8237
|
+
throw new Error(`wingman plan protocol user \u672A\u77E5\u6807\u8BB0\u683C\u5F0F(${sourcePath})`);
|
|
8238
|
+
}
|
|
8239
|
+
}
|
|
8230
8240
|
if (starts.length === 0 && ends.length === 0) {
|
|
8231
8241
|
return { before: text, after: "", remainder: text };
|
|
8232
8242
|
}
|
|
@@ -8238,7 +8248,7 @@ function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
|
|
|
8238
8248
|
if (start === void 0 || endMark === void 0 || endMark < start.index) {
|
|
8239
8249
|
throw new Error(`wingman plan protocol \u6807\u8BB0\u5757\u6B8B\u7F3A(${sourcePath})`);
|
|
8240
8250
|
}
|
|
8241
|
-
let end = endMark +
|
|
8251
|
+
let end = endMark + endMarker.length;
|
|
8242
8252
|
if (text.startsWith("\r\n", end))
|
|
8243
8253
|
end += 2;
|
|
8244
8254
|
else if (text[end] === "\n")
|
|
@@ -8253,15 +8263,17 @@ function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
|
|
|
8253
8263
|
version: Number(start[1])
|
|
8254
8264
|
};
|
|
8255
8265
|
}
|
|
8256
|
-
function inspectPlanProtocolBlock(block) {
|
|
8266
|
+
function inspectPlanProtocolBlock(block, scope = "project") {
|
|
8257
8267
|
const normalized = normalizeMarkdownLineEndings(block);
|
|
8258
|
-
const split = splitPlanProtocolBlock(normalized);
|
|
8268
|
+
const split = splitPlanProtocolBlock(normalized, "<memory>", scope);
|
|
8259
8269
|
const version = split.version;
|
|
8260
|
-
const
|
|
8261
|
-
const
|
|
8270
|
+
const currentVersion = scope === "user" ? PLAN_PROTOCOL_USER_VERSION : PLAN_PROTOCOL_VERSION;
|
|
8271
|
+
const knownTexts = scope === "user" ? KNOWN_USER_PROTOCOL_TEXT : KNOWN_PROTOCOL_TEXT;
|
|
8272
|
+
const knownText = version === void 0 ? void 0 : knownTexts.get(version);
|
|
8273
|
+
const knownBlock = version === void 0 || knownText === void 0 ? void 0 : buildPlanProtocolBlock(version, knownText, scope);
|
|
8262
8274
|
const known = split.before === "" && split.after === "" && normalized === knownBlock;
|
|
8263
8275
|
return {
|
|
8264
|
-
kind: known && version ===
|
|
8276
|
+
kind: known && version === currentVersion ? "current" : known ? "outdated" : "modified",
|
|
8265
8277
|
...version !== void 0 ? { version } : {},
|
|
8266
8278
|
sha256: sha256Hex(normalized)
|
|
8267
8279
|
};
|
|
@@ -8272,7 +8284,7 @@ function inspectPlanProtocolFile(bytes, sourcePath = "<memory>") {
|
|
|
8272
8284
|
for (const [version, text] of KNOWN_PROTOCOL_TEXT) {
|
|
8273
8285
|
if (sha256 === sha256Hex(text)) {
|
|
8274
8286
|
return {
|
|
8275
|
-
kind: version === PLAN_PROTOCOL_VERSION ? "current" : "
|
|
8287
|
+
kind: version === PLAN_PROTOCOL_VERSION ? "current" : "outdated",
|
|
8276
8288
|
version,
|
|
8277
8289
|
sha256
|
|
8278
8290
|
};
|
|
@@ -8287,12 +8299,37 @@ function allIndexesOf(text, needle) {
|
|
|
8287
8299
|
}
|
|
8288
8300
|
return indexes;
|
|
8289
8301
|
}
|
|
8290
|
-
|
|
8302
|
+
function mergePlanProtocolBlock(text, block, sourcePath = "<memory>", scope = "project") {
|
|
8303
|
+
const split = splitPlanProtocolBlock(text, sourcePath, scope);
|
|
8304
|
+
const lineEnding = preferredMarkdownLineEnding(text);
|
|
8305
|
+
const normalizedBlock = normalizeMarkdownLineEndings(block).replaceAll("\n", lineEnding);
|
|
8306
|
+
if (split.block !== void 0)
|
|
8307
|
+
return split.before + normalizedBlock + split.after;
|
|
8308
|
+
if (text === "")
|
|
8309
|
+
return normalizedBlock;
|
|
8310
|
+
let before = text;
|
|
8311
|
+
if (!before.endsWith("\n"))
|
|
8312
|
+
before += lineEnding;
|
|
8313
|
+
if (!before.endsWith(`${lineEnding}${lineEnding}`))
|
|
8314
|
+
before += lineEnding;
|
|
8315
|
+
return before + normalizedBlock;
|
|
8316
|
+
}
|
|
8317
|
+
var PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT, PLAN_PROTOCOL_TEXT_USER, PLAN_PROTOCOL_TEXT_V1, PLAN_PROTOCOL_TEXT_USER_V1, PLAN_PROTOCOL_USER_BLOCK_END, PLAN_PROTOCOL_BLOCK_END, LEGACY_PLAN_PROTOCOL_TEXT, KNOWN_PROTOCOL_TEXT, KNOWN_USER_PROTOCOL_TEXT, BLOCK_START, USER_BLOCK_START;
|
|
8291
8318
|
var init_plan_protocol = __esm({
|
|
8292
8319
|
"packages/core/dist/plan-protocol.js"() {
|
|
8293
8320
|
"use strict";
|
|
8294
|
-
PLAN_PROTOCOL_VERSION =
|
|
8295
|
-
|
|
8321
|
+
PLAN_PROTOCOL_VERSION = 2;
|
|
8322
|
+
PLAN_PROTOCOL_USER_VERSION = 2;
|
|
8323
|
+
PLAN_PROTOCOL_TEXT = `Wingman plan protocol v2 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
|
|
8324
|
+
- The project root is the directory that contains this instruction file (for Claude Code: the parent of \`.claude/\`).
|
|
8325
|
+
- Before starting work, read \`<project root>/.wingman/plan.md\`. If it does not exist, create it: a \`# Title\` line, immediately followed by \`\u76EE\u6807: <one sentence, what done looks like>\` (or \`Goal:\`), then a nested checkbox tree of steps; add an indented \`Verify:\` line to the steps whose completion a person would want to check; not every step needs one.
|
|
8326
|
+
- As soon as the scope is clear (after any clarifying questions), create the plan file before doing the first step. Mark a step \`[/]\` right before you start it and \`[x]\` right after it is done; do not write the whole plan as finished afterwards. Add sub-steps under your current step as you learn more. Mark abandoned steps \`[-]\` and steps that need the user's decision \`[?]\`.
|
|
8327
|
+
- Re-read the file before every write; change only your own lines; never reorder or rewrite other entries. Use your file-editing tool, not shell redirection.
|
|
8328
|
+
- Keep your in-session todo list as sub-steps of the \`[/]\` step; do not copy the whole file into it.
|
|
8329
|
+
- Never put secrets, credentials, or personal data in the plan.
|
|
8330
|
+
`;
|
|
8331
|
+
PLAN_PROTOCOL_TEXT_USER = PLAN_PROTOCOL_TEXT.replace(/^- The project root .*$/mu, "- The project root is the nearest git root containing the current working directory, or the current working directory when there is no git root. If the current working directory is the user\u2019s home directory, you MUST NOT create a plan file. Only multi-step tasks use the plan workflow below; single-turn questions do not create or update a plan file.");
|
|
8332
|
+
PLAN_PROTOCOL_TEXT_V1 = `Wingman plan protocol v1 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
|
|
8296
8333
|
- The project root is the directory that contains this instruction file (for Claude Code: the parent of \`.claude/\`).
|
|
8297
8334
|
- Before starting work, read \`<project root>/.wingman/plan.md\`. If it does not exist, create it: a \`# Title\` line, then a nested checkbox tree of steps, each step with an indented \`Verify:\` line describing how it will be checked.
|
|
8298
8335
|
- Mark the step you are working on \`[/]\` and add sub-steps under it as you learn more. Mark finished steps \`[x]\`, abandoned steps \`[-]\`, and steps that need the user's decision \`[?]\`.
|
|
@@ -8300,13 +8337,169 @@ var init_plan_protocol = __esm({
|
|
|
8300
8337
|
- Keep your in-session todo list as sub-steps of the \`[/]\` step; do not copy the whole file into it.
|
|
8301
8338
|
- Never put secrets, credentials, or personal data in the plan.
|
|
8302
8339
|
`;
|
|
8340
|
+
PLAN_PROTOCOL_TEXT_USER_V1 = PLAN_PROTOCOL_TEXT_V1.replace(/^- The project root .*$/mu, "- The project root is the nearest git root containing the current working directory, or the current working directory when there is no git root. If the current working directory is the user\u2019s home directory, you MUST NOT create a plan file. Only multi-step tasks use the plan workflow below; single-turn questions do not create or update a plan file.");
|
|
8341
|
+
PLAN_PROTOCOL_USER_BLOCK_END = "<!-- <<< wingman plan protocol user <<< -->";
|
|
8303
8342
|
PLAN_PROTOCOL_BLOCK_END = "<!-- <<< wingman plan protocol <<< -->";
|
|
8304
8343
|
LEGACY_PLAN_PROTOCOL_TEXT = "Wingman plan protocol v0 \u2014 legacy fixture text.\n";
|
|
8305
8344
|
KNOWN_PROTOCOL_TEXT = /* @__PURE__ */ new Map([
|
|
8306
8345
|
[0, LEGACY_PLAN_PROTOCOL_TEXT],
|
|
8346
|
+
[1, PLAN_PROTOCOL_TEXT_V1],
|
|
8307
8347
|
[PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_TEXT]
|
|
8308
8348
|
]);
|
|
8349
|
+
KNOWN_USER_PROTOCOL_TEXT = /* @__PURE__ */ new Map([
|
|
8350
|
+
[1, PLAN_PROTOCOL_TEXT_USER_V1],
|
|
8351
|
+
[PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT_USER]
|
|
8352
|
+
]);
|
|
8309
8353
|
BLOCK_START = /<!-- >>> wingman plan protocol v(\d+) >>> -->/gu;
|
|
8354
|
+
USER_BLOCK_START = /<!-- >>> wingman plan protocol user v(\d+) >>> -->/gu;
|
|
8355
|
+
}
|
|
8356
|
+
});
|
|
8357
|
+
|
|
8358
|
+
// packages/core/dist/plan-protocol-user.js
|
|
8359
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8360
|
+
import { basename as basename2, dirname as dirname2, join as join2 } from "node:path";
|
|
8361
|
+
function readTarget(targetPath2) {
|
|
8362
|
+
if (!existsSync(targetPath2))
|
|
8363
|
+
return void 0;
|
|
8364
|
+
const bytes = readFileSync(targetPath2);
|
|
8365
|
+
decodeUtf8Strict2(bytes, targetPath2);
|
|
8366
|
+
const text = bytes.toString("utf8");
|
|
8367
|
+
const split = splitPlanProtocolBlock(text, targetPath2, "user");
|
|
8368
|
+
const identity = split.block === void 0 ? void 0 : inspectPlanProtocolBlock(split.block, "user");
|
|
8369
|
+
return { bytes, text, split, identity };
|
|
8370
|
+
}
|
|
8371
|
+
function statusPlanProtocolUser(targetPath2) {
|
|
8372
|
+
try {
|
|
8373
|
+
const identity = readTarget(targetPath2)?.identity;
|
|
8374
|
+
return {
|
|
8375
|
+
targetPath: targetPath2,
|
|
8376
|
+
state: identity === void 0 ? "missing" : identity.kind === "current" ? "installed" : identity.kind,
|
|
8377
|
+
...identity?.version !== void 0 ? { version: identity.version } : {},
|
|
8378
|
+
...identity?.kind === "modified" ? { reason: "\u7528\u6237\u7EA7\u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539" } : {}
|
|
8379
|
+
};
|
|
8380
|
+
} catch (error) {
|
|
8381
|
+
return { targetPath: targetPath2, state: "modified", reason: error.message };
|
|
8382
|
+
}
|
|
8383
|
+
}
|
|
8384
|
+
function installPlanProtocolUser(paths3) {
|
|
8385
|
+
const existing = readTarget(paths3.targetPath);
|
|
8386
|
+
assertKnown(existing, paths3.targetPath);
|
|
8387
|
+
const before = existing?.text ?? "";
|
|
8388
|
+
if (existing?.identity?.kind === "current") {
|
|
8389
|
+
return result(paths3.targetPath, "install", "installed", before, before, true, false);
|
|
8390
|
+
}
|
|
8391
|
+
const statePath2 = snapshotPath(paths3);
|
|
8392
|
+
const prior = readSnapshot(statePath2, paths3.targetPath);
|
|
8393
|
+
const outdated = existing?.identity?.kind === "outdated";
|
|
8394
|
+
const block = buildPlanProtocolBlock(PLAN_PROTOCOL_USER_VERSION, void 0, "user");
|
|
8395
|
+
const after = mergePlanProtocolBlock(before, block, paths3.targetPath, "user");
|
|
8396
|
+
const backupDir = nextBackupDir(paths3.homeDir);
|
|
8397
|
+
if (!paths3.dryRun) {
|
|
8398
|
+
backupTarget(backupDir, paths3.targetPath, existing?.bytes);
|
|
8399
|
+
const snapshot = {
|
|
8400
|
+
version: 1,
|
|
8401
|
+
targetPath: paths3.targetPath,
|
|
8402
|
+
installedRemainderSha256: sha256Hex(splitPlanProtocolBlock(after, paths3.targetPath, "user").remainder),
|
|
8403
|
+
original: existing === void 0 || outdated && existing.split.remainder === "" ? { existed: false } : {
|
|
8404
|
+
existed: true,
|
|
8405
|
+
base64: (outdated ? Buffer.from(existing.split.remainder) : existing.bytes).toString("base64")
|
|
8406
|
+
}
|
|
8407
|
+
};
|
|
8408
|
+
if (!outdated || prior === void 0) {
|
|
8409
|
+
mkdirSync(dirname2(statePath2), { recursive: true });
|
|
8410
|
+
writeFileSync(statePath2, `${JSON.stringify(snapshot, null, 2)}
|
|
8411
|
+
`);
|
|
8412
|
+
}
|
|
8413
|
+
mkdirSync(dirname2(paths3.targetPath), { recursive: true });
|
|
8414
|
+
writeFileSync(paths3.targetPath, after);
|
|
8415
|
+
}
|
|
8416
|
+
return {
|
|
8417
|
+
...result(paths3.targetPath, "install", outdated ? "outdated" : "missing", before, after, true, true),
|
|
8418
|
+
state: "installed",
|
|
8419
|
+
version: PLAN_PROTOCOL_USER_VERSION,
|
|
8420
|
+
backupDir
|
|
8421
|
+
};
|
|
8422
|
+
}
|
|
8423
|
+
function uninstallPlanProtocolUser(paths3) {
|
|
8424
|
+
const existing = readTarget(paths3.targetPath);
|
|
8425
|
+
assertKnown(existing, paths3.targetPath);
|
|
8426
|
+
const before = existing?.text ?? "";
|
|
8427
|
+
if (existing?.identity === void 0) {
|
|
8428
|
+
return result(paths3.targetPath, "uninstall", "missing", before, before, existing !== void 0, false);
|
|
8429
|
+
}
|
|
8430
|
+
const statePath2 = snapshotPath(paths3);
|
|
8431
|
+
const snapshot = readSnapshot(statePath2, paths3.targetPath);
|
|
8432
|
+
const canRestore = snapshot !== void 0 && sha256Hex(existing.split.remainder) === snapshot.installedRemainderSha256;
|
|
8433
|
+
const restored = canRestore && snapshot.original.existed ? Buffer.from(snapshot.original.base64 ?? "", "base64") : void 0;
|
|
8434
|
+
const afterExists = canRestore ? snapshot.original.existed : existing.split.remainder !== "";
|
|
8435
|
+
const after = afterExists ? restored?.toString("utf8") ?? existing.split.remainder : "";
|
|
8436
|
+
const backupDir = nextBackupDir(paths3.homeDir);
|
|
8437
|
+
if (!paths3.dryRun) {
|
|
8438
|
+
backupTarget(backupDir, paths3.targetPath, existing.bytes);
|
|
8439
|
+
if (afterExists)
|
|
8440
|
+
writeFileSync(paths3.targetPath, restored ?? after);
|
|
8441
|
+
else
|
|
8442
|
+
rmSync(paths3.targetPath);
|
|
8443
|
+
rmSync(statePath2, { force: true });
|
|
8444
|
+
}
|
|
8445
|
+
return {
|
|
8446
|
+
...result(paths3.targetPath, "uninstall", existing.identity.kind === "outdated" ? "outdated" : "installed", before, after, afterExists, true),
|
|
8447
|
+
state: "missing",
|
|
8448
|
+
backupDir,
|
|
8449
|
+
restoredOriginal: canRestore
|
|
8450
|
+
};
|
|
8451
|
+
}
|
|
8452
|
+
function assertKnown(existing, targetPath2) {
|
|
8453
|
+
if (existing?.identity?.kind === "modified") {
|
|
8454
|
+
throw new Error(`${targetPath2}: \u7528\u6237\u7EA7\u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\u6216\u7248\u672C\u672A\u77E5\uFF0C\u62D2\u5199\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
|
|
8455
|
+
}
|
|
8456
|
+
}
|
|
8457
|
+
function result(targetPath2, operation, previousState, before, after, afterExists, changed) {
|
|
8458
|
+
return {
|
|
8459
|
+
targetPath: targetPath2,
|
|
8460
|
+
operation,
|
|
8461
|
+
previousState,
|
|
8462
|
+
state: previousState,
|
|
8463
|
+
before,
|
|
8464
|
+
after,
|
|
8465
|
+
afterExists,
|
|
8466
|
+
changed,
|
|
8467
|
+
effectiveAt: "next_session",
|
|
8468
|
+
totalBytes: Buffer.byteLength(after)
|
|
8469
|
+
};
|
|
8470
|
+
}
|
|
8471
|
+
function snapshotPath(paths3) {
|
|
8472
|
+
return join2(paths3.homeDir, ".wingman", "state", `plan-protocol-user-${sha256Hex(paths3.targetPath)}.json`);
|
|
8473
|
+
}
|
|
8474
|
+
function readSnapshot(statePath2, targetPath2) {
|
|
8475
|
+
if (!existsSync(statePath2))
|
|
8476
|
+
return void 0;
|
|
8477
|
+
try {
|
|
8478
|
+
const value = JSON.parse(readFileSync(statePath2, "utf8"));
|
|
8479
|
+
if (value.version === 1 && value.targetPath === targetPath2 && typeof value.installedRemainderSha256 === "string" && /^[a-f0-9]{64}$/u.test(value.installedRemainderSha256) && typeof value.original?.existed === "boolean" && (value.original.existed ? typeof value.original.base64 === "string" && Buffer.from(value.original.base64, "base64").toString("base64") === value.original.base64 : value.original.base64 === void 0)) {
|
|
8480
|
+
return value;
|
|
8481
|
+
}
|
|
8482
|
+
} catch {
|
|
8483
|
+
}
|
|
8484
|
+
throw new Error(`\u7528\u6237\u7EA7\u534F\u8BAE\u5FEB\u7167\u683C\u5F0F\u672A\u77E5(${statePath2})\uFF0C\u62D2\u5199\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
|
|
8485
|
+
}
|
|
8486
|
+
function nextBackupDir(homeDir) {
|
|
8487
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
8488
|
+
const root = join2(homeDir, ".wingman", "backups");
|
|
8489
|
+
let dir = join2(root, stamp);
|
|
8490
|
+
for (let n = 2; existsSync(dir); n += 1)
|
|
8491
|
+
dir = join2(root, `${stamp}-${n}`);
|
|
8492
|
+
return dir;
|
|
8493
|
+
}
|
|
8494
|
+
function backupTarget(backupDir, targetPath2, bytes) {
|
|
8495
|
+
mkdirSync(backupDir, { recursive: true });
|
|
8496
|
+
if (bytes !== void 0)
|
|
8497
|
+
writeFileSync(join2(backupDir, basename2(targetPath2)), bytes);
|
|
8498
|
+
}
|
|
8499
|
+
var init_plan_protocol_user = __esm({
|
|
8500
|
+
"packages/core/dist/plan-protocol-user.js"() {
|
|
8501
|
+
"use strict";
|
|
8502
|
+
init_plan_protocol();
|
|
8310
8503
|
}
|
|
8311
8504
|
});
|
|
8312
8505
|
|
|
@@ -8492,6 +8685,7 @@ var init_dist = __esm({
|
|
|
8492
8685
|
"use strict";
|
|
8493
8686
|
init_feedback_url();
|
|
8494
8687
|
init_plan_protocol();
|
|
8688
|
+
init_plan_protocol_user();
|
|
8495
8689
|
init_refscan();
|
|
8496
8690
|
SLOT_IDS = ["base", "rules", "skills", "tools", "gates", "history"];
|
|
8497
8691
|
HARNESS_IDS = ["cc", "codex", "dsh"];
|
|
@@ -8521,7 +8715,7 @@ var init_dist = __esm({
|
|
|
8521
8715
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
8522
8716
|
import { randomBytes } from "node:crypto";
|
|
8523
8717
|
import { mkdir as mkdir2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
8524
|
-
import { dirname as
|
|
8718
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, relative as relative2 } from "node:path";
|
|
8525
8719
|
function buildToggleBlock(instanceId, flags) {
|
|
8526
8720
|
const lines2 = [`${TOGGLE_BEGIN_PREFIX}${instanceId}${TOGGLE_BEGIN_SUFFIX}`];
|
|
8527
8721
|
if (flags.fileCreated)
|
|
@@ -8782,15 +8976,15 @@ async function planDshToggle(action, dump, options) {
|
|
|
8782
8976
|
if (row.id === DSH_HOOK_ROW_ID && row.name === DSH_HOOKS_PACKAGE) {
|
|
8783
8977
|
throw new Error(`\u300C${row.name}\u300D(${row.id})\u7531 Wingman \u5B9E\u51B5\u63A5\u7EBF(live hooks \u5757)\u5F15\u5165,\u8BF7\u7528 \`wingman hook uninstall dsh\` \u7BA1\u7406,\u4E0D\u8D70\u5F00\u5173`);
|
|
8784
8978
|
}
|
|
8785
|
-
const
|
|
8786
|
-
const buffer = await readIfExists(
|
|
8787
|
-
const text = buffer === void 0 ? void 0 : decodeUtf8Strict(buffer,
|
|
8788
|
-
const blocks = text === void 0 ? [] : findToggleBlocks(text,
|
|
8979
|
+
const paths3 = resolveDshHookPaths(options);
|
|
8980
|
+
const buffer = await readIfExists(paths3.patchFile);
|
|
8981
|
+
const text = buffer === void 0 ? void 0 : decodeUtf8Strict(buffer, paths3.patchFile);
|
|
8982
|
+
const blocks = text === void 0 ? [] : findToggleBlocks(text, paths3.patchFile);
|
|
8789
8983
|
const myBlock = blocks.find((b) => b.instanceId === row.id);
|
|
8790
|
-
const entriesAll = text === void 0 ? [] : parsePatchEntries(text,
|
|
8984
|
+
const entriesAll = text === void 0 ? [] : parsePatchEntries(text, paths3.patchFile);
|
|
8791
8985
|
const outsideToggle = text === void 0 ? "" : stripAllToggleBlocks(text, blocks);
|
|
8792
|
-
const entriesOutsideToggle = text === void 0 ? [] : parsePatchEntries(outsideToggle,
|
|
8793
|
-
const entriesUser = text === void 0 ? [] : parsePatchEntries(stripHooksBlocks(outsideToggle),
|
|
8986
|
+
const entriesOutsideToggle = text === void 0 ? [] : parsePatchEntries(outsideToggle, paths3.patchFile);
|
|
8987
|
+
const entriesUser = text === void 0 ? [] : parsePatchEntries(stripHooksBlocks(outsideToggle), paths3.patchFile);
|
|
8794
8988
|
const refInUser = referencesInstanceId(entriesUser, row.id);
|
|
8795
8989
|
const refInHooks = !refInUser && referencesInstanceId(entriesOutsideToggle, row.id);
|
|
8796
8990
|
if (refInHooks) {
|
|
@@ -8802,36 +8996,36 @@ async function planDshToggle(action, dump, options) {
|
|
|
8802
8996
|
throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u7531 Wingman \u5173\u95ED(dsh \u4E0B\u6B21\u542F\u52A8\u751F\u6548);\u5982\u9700\u6062\u590D\u8BF7 toggle on`);
|
|
8803
8997
|
}
|
|
8804
8998
|
if (refInUser) {
|
|
8805
|
-
throw new Error(`${
|
|
8999
|
+
throw new Error(`${paths3.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
|
|
8806
9000
|
}
|
|
8807
9001
|
if (row.disabled === true) {
|
|
8808
9002
|
throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u5728 ${item.source} \u5C42\u88AB\u7981\u7528(\u539F\u751F\u7981\u7528\u975E Wingman \u6240\u8F96),\u65E0\u9700\u518D\u5173`);
|
|
8809
9003
|
}
|
|
8810
9004
|
const composed = composeToggleOff(text, row.id, entriesAll.length);
|
|
8811
9005
|
const expected = JSON.stringify([...entriesAll, { id: row.id, disabled: true }]);
|
|
8812
|
-
if (JSON.stringify(parsePatchEntries(composed.after,
|
|
8813
|
-
throw new Error(`\u62D2\u5199:${
|
|
9006
|
+
if (JSON.stringify(parsePatchEntries(composed.after, paths3.patchFile)) !== expected) {
|
|
9007
|
+
throw new Error(`\u62D2\u5199:${paths3.patchFile} \u8FFD\u52A0\u540E\u5F62\u72B6\u6821\u9A8C\u5931\u8D25(\u539F\u6587\u4EF6\u5F62\u6001\u65E0\u6CD5\u5B89\u5168\u8FFD\u52A0),\u4E0D\u731C`);
|
|
8814
9008
|
}
|
|
8815
|
-
change = composed.kind === "create" || text === void 0 ? { file:
|
|
9009
|
+
change = composed.kind === "create" || text === void 0 ? { file: paths3.patchFile, kind: "create", after: composed.after } : { file: paths3.patchFile, kind: "modify", before: text, after: composed.after };
|
|
8816
9010
|
} else {
|
|
8817
9011
|
if (myBlock === void 0 || text === void 0) {
|
|
8818
9012
|
if (refInUser) {
|
|
8819
|
-
throw new Error(`${
|
|
9013
|
+
throw new Error(`${paths3.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
|
|
8820
9014
|
}
|
|
8821
9015
|
if (row.disabled === true) {
|
|
8822
9016
|
throw new Error(`\u300C${row.name}\u300D(${row.id})\u5728 ${item.source} \u5C42\u88AB\u539F\u751F\u7981\u7528,\u975E Wingman \u6240\u8F96:\u8BF7\u5230\u8BE5\u5C42(bundle/profile \u914D\u7F6E)\u4FEE\u6539`);
|
|
8823
9017
|
}
|
|
8824
9018
|
throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u662F\u542F\u7528\u72B6\u6001,\u65E0\u9700 toggle on`);
|
|
8825
9019
|
}
|
|
8826
|
-
const composed = composeToggleOn(text, myBlock,
|
|
8827
|
-
change = composed.kind === "delete" || composed.after === void 0 ? { file:
|
|
9020
|
+
const composed = composeToggleOn(text, myBlock, paths3.patchFile);
|
|
9021
|
+
change = composed.kind === "delete" || composed.after === void 0 ? { file: paths3.patchFile, kind: "delete", before: text } : { file: paths3.patchFile, kind: "modify", before: text, after: composed.after };
|
|
8828
9022
|
}
|
|
8829
9023
|
return {
|
|
8830
9024
|
harness: "dsh",
|
|
8831
9025
|
action: toggle,
|
|
8832
9026
|
writes: [change],
|
|
8833
|
-
backupDir:
|
|
8834
|
-
references: scanDshReferences(
|
|
9027
|
+
backupDir: join3(paths3.backupsRoot, backupDirName()),
|
|
9028
|
+
references: scanDshReferences(paths3.patchFile, text, dump, row),
|
|
8835
9029
|
// 生效时机:patch 层在 boot 时组装(composeProfile),保证下次启动生效;钉定版本
|
|
8836
9030
|
// 还会 watchUserPatches 热重载家目录层,但该监听失败被静默吞掉(suppressShutdownError)
|
|
8837
9031
|
// 且热拔插行为无兼容承诺 → 按宪法取保守值 next_session,如实不夸大。
|
|
@@ -8864,39 +9058,39 @@ function validatePlanShape(plan, patchFile, backupsRoot) {
|
|
|
8864
9058
|
}
|
|
8865
9059
|
async function applyDshToggle(plan, options) {
|
|
8866
9060
|
try {
|
|
8867
|
-
const
|
|
8868
|
-
const { change } = validatePlanShape(plan,
|
|
8869
|
-
const buffer = await readIfExists(
|
|
9061
|
+
const paths3 = resolveDshHookPaths(options);
|
|
9062
|
+
const { change } = validatePlanShape(plan, paths3.patchFile, paths3.backupsRoot);
|
|
9063
|
+
const buffer = await readIfExists(paths3.patchFile);
|
|
8870
9064
|
if (change.kind === "create") {
|
|
8871
9065
|
if (buffer !== void 0) {
|
|
8872
9066
|
return {
|
|
8873
9067
|
ok: false,
|
|
8874
|
-
error: `${
|
|
9068
|
+
error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u521B\u5EFA,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
|
|
8875
9069
|
};
|
|
8876
9070
|
}
|
|
8877
9071
|
} else {
|
|
8878
9072
|
if (buffer === void 0) {
|
|
8879
9073
|
return {
|
|
8880
9074
|
ok: false,
|
|
8881
|
-
error: `${
|
|
9075
|
+
error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u5220\u9664,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
|
|
8882
9076
|
};
|
|
8883
9077
|
}
|
|
8884
9078
|
if (!buffer.equals(Buffer3.from(change.before ?? "", "utf8"))) {
|
|
8885
9079
|
return {
|
|
8886
9080
|
ok: false,
|
|
8887
|
-
error: `${
|
|
9081
|
+
error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u6539\u52A8,\u4E0E plan \u5FEB\u7167\u4E0D\u4E00\u81F4:\u8BF7\u91CD\u65B0 plan`
|
|
8888
9082
|
};
|
|
8889
9083
|
}
|
|
8890
9084
|
}
|
|
8891
9085
|
await mkdir2(plan.backupDir, { recursive: true });
|
|
8892
9086
|
if (buffer !== void 0) {
|
|
8893
|
-
await writeFile2(
|
|
9087
|
+
await writeFile2(join3(plan.backupDir, "cordis.patch.yml"), buffer);
|
|
8894
9088
|
}
|
|
8895
9089
|
if (change.kind === "delete") {
|
|
8896
|
-
await rm2(
|
|
9090
|
+
await rm2(paths3.patchFile);
|
|
8897
9091
|
} else {
|
|
8898
|
-
await mkdir2(
|
|
8899
|
-
await writeFile2(
|
|
9092
|
+
await mkdir2(dirname3(paths3.patchFile), { recursive: true });
|
|
9093
|
+
await writeFile2(paths3.patchFile, change.after ?? "", "utf8");
|
|
8900
9094
|
}
|
|
8901
9095
|
return { ok: true, backupDir: plan.backupDir };
|
|
8902
9096
|
} catch (error) {
|
|
@@ -8925,55 +9119,55 @@ var init_toggle = __esm({
|
|
|
8925
9119
|
|
|
8926
9120
|
// packages/adapter-dsh/dist/protocol.js
|
|
8927
9121
|
import { execFileSync } from "node:child_process";
|
|
8928
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
9122
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
8929
9123
|
import { homedir as homedir2 } from "node:os";
|
|
8930
|
-
import { basename as
|
|
9124
|
+
import { basename as basename3, dirname as dirname4, join as join4, resolve } from "node:path";
|
|
8931
9125
|
function protocolStatusDsh(options) {
|
|
8932
|
-
const
|
|
8933
|
-
if (!
|
|
8934
|
-
return status(
|
|
9126
|
+
const paths3 = resolveOptions(options);
|
|
9127
|
+
if (!existsSync2(paths3.targetPath))
|
|
9128
|
+
return status(paths3.targetPath, "not_installed", options);
|
|
8935
9129
|
try {
|
|
8936
|
-
const file = readAgents(
|
|
9130
|
+
const file = readAgents(paths3.targetPath);
|
|
8937
9131
|
if (file.identity === void 0)
|
|
8938
|
-
return status(
|
|
9132
|
+
return status(paths3.targetPath, "not_installed", options);
|
|
8939
9133
|
const state = stateForIdentity(file.identity);
|
|
8940
|
-
return status(
|
|
9134
|
+
return status(paths3.targetPath, state, options, file.identity);
|
|
8941
9135
|
} catch (error) {
|
|
8942
|
-
return status(
|
|
9136
|
+
return status(paths3.targetPath, "invalid", options, void 0, error.message);
|
|
8943
9137
|
}
|
|
8944
9138
|
}
|
|
8945
9139
|
function installProtocolDsh(options) {
|
|
8946
|
-
const
|
|
8947
|
-
const existing =
|
|
9140
|
+
const paths3 = resolveOptions(options);
|
|
9141
|
+
const existing = existsSync2(paths3.targetPath) ? readAgents(paths3.targetPath) : void 0;
|
|
8948
9142
|
const previousState = stateForIdentity(existing?.identity);
|
|
8949
9143
|
if (previousState === "installed") {
|
|
8950
|
-
return overlayLoadState(
|
|
9144
|
+
return overlayLoadState(result2(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true), options);
|
|
8951
9145
|
}
|
|
8952
9146
|
if (previousState === "modified")
|
|
8953
|
-
throw modifiedError(
|
|
9147
|
+
throw modifiedError(paths3.targetPath, "\u5B89\u88C5");
|
|
8954
9148
|
const before = existing?.text ?? "";
|
|
8955
9149
|
const lineEnding = preferredMarkdownLineEnding(before);
|
|
8956
9150
|
const block = buildPlanProtocolBlock().replaceAll("\n", lineEnding);
|
|
8957
9151
|
const after = existing?.split.block ? existing.split.before + block + existing.split.after : appendBlock(before, block, lineEnding);
|
|
8958
|
-
const installedRemainder = splitPlanProtocolBlock(after,
|
|
8959
|
-
const backupDir =
|
|
8960
|
-
if (!
|
|
8961
|
-
const prior = readState2(
|
|
8962
|
-
|
|
8963
|
-
writeState2(
|
|
9152
|
+
const installedRemainder = splitPlanProtocolBlock(after, paths3.targetPath).remainder;
|
|
9153
|
+
const backupDir = nextBackupDir2(paths3.homeDir);
|
|
9154
|
+
if (!paths3.dryRun) {
|
|
9155
|
+
const prior = readState2(paths3.statePath, paths3.targetPath);
|
|
9156
|
+
backupTarget2(backupDir, paths3.targetPath, existing?.bytes);
|
|
9157
|
+
writeState2(paths3.statePath, {
|
|
8964
9158
|
version: 1,
|
|
8965
|
-
projectDir:
|
|
8966
|
-
targetPath:
|
|
9159
|
+
projectDir: paths3.projectDir,
|
|
9160
|
+
targetPath: paths3.targetPath,
|
|
8967
9161
|
protocolVersion: PLAN_PROTOCOL_VERSION,
|
|
8968
9162
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8969
9163
|
backupDir,
|
|
8970
|
-
installedRemainderSha256: sha256Hex(installedRemainder),
|
|
9164
|
+
installedRemainderSha256: previousState === "outdated" && prior !== void 0 ? prior.installedRemainderSha256 : sha256Hex(installedRemainder),
|
|
8971
9165
|
original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
|
|
8972
9166
|
});
|
|
8973
|
-
|
|
9167
|
+
writeFileSync2(paths3.targetPath, after);
|
|
8974
9168
|
}
|
|
8975
9169
|
return overlayLoadState({
|
|
8976
|
-
...
|
|
9170
|
+
...result2(paths3.targetPath, "install", true, previousState, before, true),
|
|
8977
9171
|
state: "installed",
|
|
8978
9172
|
version: PLAN_PROTOCOL_VERSION,
|
|
8979
9173
|
after,
|
|
@@ -8982,33 +9176,33 @@ function installProtocolDsh(options) {
|
|
|
8982
9176
|
}, options);
|
|
8983
9177
|
}
|
|
8984
9178
|
function uninstallProtocolDsh(options) {
|
|
8985
|
-
const
|
|
8986
|
-
if (!
|
|
8987
|
-
return
|
|
9179
|
+
const paths3 = resolveOptions(options);
|
|
9180
|
+
if (!existsSync2(paths3.targetPath)) {
|
|
9181
|
+
return result2(paths3.targetPath, "uninstall", false, "not_installed", "", false);
|
|
8988
9182
|
}
|
|
8989
|
-
const existing = readAgents(
|
|
9183
|
+
const existing = readAgents(paths3.targetPath);
|
|
8990
9184
|
if (existing.identity === void 0) {
|
|
8991
|
-
return
|
|
9185
|
+
return result2(paths3.targetPath, "uninstall", false, "not_installed", existing.text, true);
|
|
8992
9186
|
}
|
|
8993
9187
|
const previousState = stateForIdentity(existing.identity);
|
|
8994
9188
|
if (previousState === "modified")
|
|
8995
|
-
throw modifiedError(
|
|
8996
|
-
const state = readState2(
|
|
9189
|
+
throw modifiedError(paths3.targetPath, "\u5378\u8F7D");
|
|
9190
|
+
const state = readState2(paths3.statePath, paths3.targetPath);
|
|
8997
9191
|
const canRestore = state !== void 0 && sha256Hex(existing.split.remainder) === state.installedRemainderSha256;
|
|
8998
9192
|
const restored = canRestore ? originalBytes(state) : void 0;
|
|
8999
9193
|
const deleteTarget = canRestore ? state?.original.existed === false : existing.split.remainder.trim() === "";
|
|
9000
9194
|
const after = deleteTarget ? "" : restored?.toString("utf8") ?? existing.split.remainder;
|
|
9001
|
-
const backupDir =
|
|
9002
|
-
if (!
|
|
9003
|
-
|
|
9195
|
+
const backupDir = nextBackupDir2(paths3.homeDir);
|
|
9196
|
+
if (!paths3.dryRun) {
|
|
9197
|
+
backupTarget2(backupDir, paths3.targetPath, existing.bytes);
|
|
9004
9198
|
if (deleteTarget)
|
|
9005
|
-
|
|
9199
|
+
rmSync2(paths3.targetPath, { force: true });
|
|
9006
9200
|
else
|
|
9007
|
-
|
|
9008
|
-
|
|
9201
|
+
writeFileSync2(paths3.targetPath, restored ?? existing.split.remainder);
|
|
9202
|
+
rmSync2(paths3.statePath, { force: true });
|
|
9009
9203
|
}
|
|
9010
9204
|
return {
|
|
9011
|
-
...
|
|
9205
|
+
...result2(paths3.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
|
|
9012
9206
|
state: "not_installed",
|
|
9013
9207
|
message: canRestore ? `${SHARED_MESSAGE}\uFF1B\u5378\u8F7D\u540C\u65F6\u5F71\u54CD Codex \u4E0E dsh` : `${SHARED_MESSAGE}\uFF1B\u5378\u8F7D\u540C\u65F6\u5F71\u54CD Codex \u4E0E dsh\uFF1B\u5DF2\u4FDD\u7559\u7528\u6237\u6539\u52A8`,
|
|
9014
9208
|
after,
|
|
@@ -9020,18 +9214,19 @@ function uninstallProtocolDsh(options) {
|
|
|
9020
9214
|
function resolveOptions(options) {
|
|
9021
9215
|
const homeDir = resolve(options?.homeDir ?? homedir2());
|
|
9022
9216
|
const projectDir = resolve(options?.projectDir ?? process.cwd());
|
|
9023
|
-
const targetPath2 =
|
|
9217
|
+
const targetPath2 = join4(projectDir, "AGENTS.md");
|
|
9024
9218
|
return {
|
|
9025
9219
|
homeDir,
|
|
9026
9220
|
projectDir,
|
|
9027
9221
|
targetPath: targetPath2,
|
|
9028
|
-
statePath:
|
|
9222
|
+
statePath: join4(homeDir, ".wingman", "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`),
|
|
9029
9223
|
dryRun: options?.dryRun ?? false
|
|
9030
9224
|
};
|
|
9031
9225
|
}
|
|
9032
9226
|
function readAgents(targetPath2) {
|
|
9033
|
-
const bytes =
|
|
9034
|
-
|
|
9227
|
+
const bytes = readFileSync2(targetPath2);
|
|
9228
|
+
decodeUtf8Strict2(bytes, targetPath2);
|
|
9229
|
+
const text = bytes.toString("utf8");
|
|
9035
9230
|
let split;
|
|
9036
9231
|
try {
|
|
9037
9232
|
split = splitPlanProtocolBlock(text, targetPath2);
|
|
@@ -9060,7 +9255,7 @@ function stateForIdentity(identity) {
|
|
|
9060
9255
|
return "not_installed";
|
|
9061
9256
|
if (identity.kind === "current")
|
|
9062
9257
|
return "installed";
|
|
9063
|
-
if (identity.kind === "
|
|
9258
|
+
if (identity.kind === "outdated")
|
|
9064
9259
|
return "outdated";
|
|
9065
9260
|
return "modified";
|
|
9066
9261
|
}
|
|
@@ -9078,7 +9273,7 @@ function status(targetPath2, state, options, identity, reason) {
|
|
|
9078
9273
|
...reason !== void 0 ? { reason } : {}
|
|
9079
9274
|
};
|
|
9080
9275
|
}
|
|
9081
|
-
function
|
|
9276
|
+
function result2(targetPath2, operation, changed, previousState, before, afterExists) {
|
|
9082
9277
|
return {
|
|
9083
9278
|
harness: "dsh",
|
|
9084
9279
|
state: previousState,
|
|
@@ -9112,7 +9307,7 @@ function agentInstructionsDisabled(options) {
|
|
|
9112
9307
|
if (options?.dumpConfigText !== void 0)
|
|
9113
9308
|
text = options.dumpConfigText;
|
|
9114
9309
|
else if (options?.dumpConfigPath !== void 0)
|
|
9115
|
-
text =
|
|
9310
|
+
text = readFileSync2(options.dumpConfigPath, "utf8");
|
|
9116
9311
|
else {
|
|
9117
9312
|
text = execFileSync("dsh", ["--profile", options?.profile ?? "web", "--dump-config"], {
|
|
9118
9313
|
encoding: "utf8",
|
|
@@ -9129,38 +9324,41 @@ function agentInstructionsDisabled(options) {
|
|
|
9129
9324
|
function modifiedError(targetPath2, operation) {
|
|
9130
9325
|
return new Error(`${targetPath2}: \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
|
|
9131
9326
|
}
|
|
9132
|
-
function
|
|
9327
|
+
function nextBackupDir2(homeDir) {
|
|
9133
9328
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
9134
|
-
const root =
|
|
9135
|
-
let dir =
|
|
9136
|
-
for (let n = 2;
|
|
9137
|
-
dir =
|
|
9329
|
+
const root = join4(homeDir, ".wingman", "backups");
|
|
9330
|
+
let dir = join4(root, stamp);
|
|
9331
|
+
for (let n = 2; existsSync2(dir); n += 1)
|
|
9332
|
+
dir = join4(root, `${stamp}-${n}`);
|
|
9138
9333
|
return dir;
|
|
9139
9334
|
}
|
|
9140
|
-
function
|
|
9141
|
-
|
|
9335
|
+
function backupTarget2(backupDir, targetPath2, bytes) {
|
|
9336
|
+
mkdirSync2(backupDir, { recursive: true });
|
|
9142
9337
|
if (bytes !== void 0)
|
|
9143
|
-
|
|
9338
|
+
writeFileSync2(join4(backupDir, basename3(targetPath2)), bytes);
|
|
9144
9339
|
}
|
|
9145
9340
|
function readState2(statePath2, targetPath2) {
|
|
9146
|
-
if (!
|
|
9341
|
+
if (!existsSync2(statePath2))
|
|
9147
9342
|
return void 0;
|
|
9148
9343
|
try {
|
|
9149
|
-
const value = JSON.parse(
|
|
9344
|
+
const value = JSON.parse(readFileSync2(statePath2, "utf8"));
|
|
9150
9345
|
return value.version === 1 && value.targetPath === targetPath2 ? value : void 0;
|
|
9151
9346
|
} catch {
|
|
9152
9347
|
return void 0;
|
|
9153
9348
|
}
|
|
9154
9349
|
}
|
|
9155
9350
|
function writeState2(statePath2, state) {
|
|
9156
|
-
|
|
9157
|
-
|
|
9351
|
+
mkdirSync2(dirname4(statePath2), { recursive: true });
|
|
9352
|
+
writeFileSync2(statePath2, `${JSON.stringify(state, null, 2)}
|
|
9158
9353
|
`);
|
|
9159
9354
|
}
|
|
9160
9355
|
function originalBytes(state) {
|
|
9161
9356
|
return state.original.existed ? Buffer.from(state.original.base64 ?? "", "base64") : void 0;
|
|
9162
9357
|
}
|
|
9163
|
-
|
|
9358
|
+
function protocolStatusDshUser(_options) {
|
|
9359
|
+
return { unsupported: "dsh \u6CA1\u6709\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6,\u8BF7\u6309\u9879\u76EE\u5B89\u88C5" };
|
|
9360
|
+
}
|
|
9361
|
+
var SHARED_MESSAGE, DISABLED_MESSAGE, installProtocolDshUser, uninstallProtocolDshUser;
|
|
9164
9362
|
var init_protocol = __esm({
|
|
9165
9363
|
"packages/adapter-dsh/dist/protocol.js"() {
|
|
9166
9364
|
"use strict";
|
|
@@ -9168,6 +9366,8 @@ var init_protocol = __esm({
|
|
|
9168
9366
|
init_dump_config();
|
|
9169
9367
|
SHARED_MESSAGE = "\u6B64 AGENTS.md \u534F\u8BAE\u5757\u7531 Codex \u4E0E dsh \u5171\u7528";
|
|
9170
9368
|
DISABLED_MESSAGE = "dsh \u6307\u4EE4\u52A0\u8F7D\u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u89C1\u63A7\u5236\u9875\u5F00\u5173";
|
|
9369
|
+
installProtocolDshUser = protocolStatusDshUser;
|
|
9370
|
+
uninstallProtocolDshUser = protocolStatusDshUser;
|
|
9171
9371
|
}
|
|
9172
9372
|
});
|
|
9173
9373
|
|
|
@@ -9183,18 +9383,21 @@ __export(dist_exports, {
|
|
|
9183
9383
|
hasManagedHooks: () => hasManagedHooks,
|
|
9184
9384
|
installDshHooks: () => installDshHooks,
|
|
9185
9385
|
installProtocolDsh: () => installProtocolDsh,
|
|
9386
|
+
installProtocolDshUser: () => installProtocolDshUser,
|
|
9186
9387
|
parseDumpConfig: () => parseDumpConfig,
|
|
9187
9388
|
protocolStatusDsh: () => protocolStatusDsh,
|
|
9389
|
+
protocolStatusDshUser: () => protocolStatusDshUser,
|
|
9188
9390
|
resolveDshHome: () => resolveDshHome,
|
|
9189
9391
|
resolveDshHookPaths: () => resolveDshHookPaths,
|
|
9190
9392
|
retireLegacyDshHomeHooks: () => retireLegacyDshHomeHooks,
|
|
9191
9393
|
uninstallDshHooks: () => uninstallDshHooks,
|
|
9192
|
-
uninstallProtocolDsh: () => uninstallProtocolDsh
|
|
9394
|
+
uninstallProtocolDsh: () => uninstallProtocolDsh,
|
|
9395
|
+
uninstallProtocolDshUser: () => uninstallProtocolDshUser
|
|
9193
9396
|
});
|
|
9194
9397
|
import { execFile } from "node:child_process";
|
|
9195
|
-
import { existsSync as
|
|
9398
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
9196
9399
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
9197
|
-
import { join as
|
|
9400
|
+
import { join as join5 } from "node:path";
|
|
9198
9401
|
import { promisify } from "node:util";
|
|
9199
9402
|
async function execVersionViaPath() {
|
|
9200
9403
|
const { stdout } = await execFileAsync("dsh", ["-V"], {
|
|
@@ -9267,7 +9470,7 @@ function createAdapter(options = {}) {
|
|
|
9267
9470
|
// 检测与 CC/Codex 同构:探用户 dsh 家目录(homeDir/.dsh → $DSH_HOME → ~/.dsh)是否存在。
|
|
9268
9471
|
// 版本尽力:PATH 上 `dsh -V`,3 秒超时;失败不影响 installed 判定。
|
|
9269
9472
|
async detect(options2) {
|
|
9270
|
-
if (!
|
|
9473
|
+
if (!existsSync3(resolveDshHome(options2)))
|
|
9271
9474
|
return { installed: false };
|
|
9272
9475
|
const version = await loadVersion();
|
|
9273
9476
|
return version !== void 0 ? { installed: true, version } : { installed: true };
|
|
@@ -9300,7 +9503,7 @@ function createAdapter(options = {}) {
|
|
|
9300
9503
|
},
|
|
9301
9504
|
async planAction(action, options2) {
|
|
9302
9505
|
const text = await loadDumpText();
|
|
9303
|
-
const file = dumpConfigPath ??
|
|
9506
|
+
const file = dumpConfigPath ?? join5(resolveDshHookPaths(options2).dshHome, `dump-config(${profile})`);
|
|
9304
9507
|
return await planDshToggle(action, { text, file }, options2);
|
|
9305
9508
|
},
|
|
9306
9509
|
async applyAction(plan, options2) {
|
|
@@ -9331,7 +9534,7 @@ var init_dist2 = __esm({
|
|
|
9331
9534
|
|
|
9332
9535
|
// packages/adapter-cc/dist/walk.js
|
|
9333
9536
|
import { readdirSync } from "node:fs";
|
|
9334
|
-
import { join as
|
|
9537
|
+
import { join as join9, parse as parse2, resolve as resolve2 } from "node:path";
|
|
9335
9538
|
function newWalkStats(entryBudget = MAX_WALK_ENTRIES) {
|
|
9336
9539
|
return { unknownErrors: 0, truncated: false, entriesLeft: entryBudget };
|
|
9337
9540
|
}
|
|
@@ -9358,7 +9561,7 @@ function walkFiles(dir, fileName, stats = newWalkStats()) {
|
|
|
9358
9561
|
return;
|
|
9359
9562
|
}
|
|
9360
9563
|
stats.entriesLeft -= 1;
|
|
9361
|
-
const p =
|
|
9564
|
+
const p = join9(d, entry.name);
|
|
9362
9565
|
if (entry.isDirectory()) {
|
|
9363
9566
|
if (entry.name.startsWith(".") || SKIP_DIR_NAMES.has(entry.name))
|
|
9364
9567
|
continue;
|
|
@@ -9375,7 +9578,7 @@ function walkFiles(dir, fileName, stats = newWalkStats()) {
|
|
|
9375
9578
|
return found;
|
|
9376
9579
|
}
|
|
9377
9580
|
function listMdFiles(dir, stats) {
|
|
9378
|
-
return safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".md")).sort().map((n) =>
|
|
9581
|
+
return safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".md")).sort().map((n) => join9(dir, n));
|
|
9379
9582
|
}
|
|
9380
9583
|
function isBareProjectDir(projectDir, homeDir) {
|
|
9381
9584
|
const r = resolve2(projectDir);
|
|
@@ -9393,21 +9596,21 @@ var init_walk = __esm({
|
|
|
9393
9596
|
});
|
|
9394
9597
|
|
|
9395
9598
|
// packages/adapter-cc/dist/detect.js
|
|
9396
|
-
import { existsSync as
|
|
9599
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
9397
9600
|
import { homedir as homedir5 } from "node:os";
|
|
9398
|
-
import { join as
|
|
9601
|
+
import { join as join10 } from "node:path";
|
|
9399
9602
|
function probeVersion(homeDir, stats = newWalkStats()) {
|
|
9400
|
-
const root =
|
|
9603
|
+
const root = join10(homeDir, ".claude", "projects");
|
|
9401
9604
|
let latest;
|
|
9402
9605
|
for (const entry of safeReaddir(root, stats)) {
|
|
9403
9606
|
if (!entry.isDirectory())
|
|
9404
9607
|
continue;
|
|
9405
|
-
const dir =
|
|
9608
|
+
const dir = join10(root, entry.name);
|
|
9406
9609
|
for (const sub of safeReaddir(dir, stats)) {
|
|
9407
9610
|
const name = sub.name;
|
|
9408
9611
|
if (!name.endsWith(".jsonl"))
|
|
9409
9612
|
continue;
|
|
9410
|
-
const file =
|
|
9613
|
+
const file = join10(dir, name);
|
|
9411
9614
|
let mtimeMs;
|
|
9412
9615
|
try {
|
|
9413
9616
|
mtimeMs = statSync(file).mtimeMs;
|
|
@@ -9423,7 +9626,7 @@ function probeVersion(homeDir, stats = newWalkStats()) {
|
|
|
9423
9626
|
return void 0;
|
|
9424
9627
|
let lines2;
|
|
9425
9628
|
try {
|
|
9426
|
-
lines2 =
|
|
9629
|
+
lines2 = readFileSync5(latest.file, "utf8").split("\n");
|
|
9427
9630
|
} catch (error) {
|
|
9428
9631
|
recordWalkError(error, stats);
|
|
9429
9632
|
return void 0;
|
|
@@ -9443,7 +9646,7 @@ function probeVersion(homeDir, stats = newWalkStats()) {
|
|
|
9443
9646
|
}
|
|
9444
9647
|
async function detectCc(options) {
|
|
9445
9648
|
const homeDir = options?.homeDir ?? homedir5();
|
|
9446
|
-
const installed =
|
|
9649
|
+
const installed = existsSync5(join10(homeDir, ".claude")) || existsSync5(join10(homeDir, ".claude.json"));
|
|
9447
9650
|
if (!installed)
|
|
9448
9651
|
return { installed: false };
|
|
9449
9652
|
const version = probeVersion(homeDir);
|
|
@@ -9458,11 +9661,11 @@ var init_detect = __esm({
|
|
|
9458
9661
|
|
|
9459
9662
|
// packages/adapter-cc/dist/scan.js
|
|
9460
9663
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
9461
|
-
import { existsSync as
|
|
9664
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
|
|
9462
9665
|
import { homedir as homedir6 } from "node:os";
|
|
9463
|
-
import { basename as
|
|
9666
|
+
import { basename as basename4, dirname as dirname7, join as join11, resolve as resolve3, sep } from "node:path";
|
|
9464
9667
|
function readJsonFile(file) {
|
|
9465
|
-
const text =
|
|
9668
|
+
const text = readFileSync6(file, "utf8");
|
|
9466
9669
|
try {
|
|
9467
9670
|
return JSON.parse(text);
|
|
9468
9671
|
} catch (e) {
|
|
@@ -9478,13 +9681,13 @@ function recordField(v, key) {
|
|
|
9478
9681
|
}
|
|
9479
9682
|
function readSettingsChain(homeDir, projectDir) {
|
|
9480
9683
|
const chain = [
|
|
9481
|
-
{ file:
|
|
9482
|
-
{ file:
|
|
9483
|
-
{ file:
|
|
9684
|
+
{ file: join11(homeDir, ".claude", "settings.json"), source: "user" },
|
|
9685
|
+
{ file: join11(projectDir, ".claude", "settings.json"), source: "project" },
|
|
9686
|
+
{ file: join11(projectDir, ".claude", "settings.local.json"), source: "local" }
|
|
9484
9687
|
];
|
|
9485
9688
|
const out = [];
|
|
9486
9689
|
for (const { file, source } of chain) {
|
|
9487
|
-
if (!
|
|
9690
|
+
if (!existsSync6(file))
|
|
9488
9691
|
continue;
|
|
9489
9692
|
const data = asRecord(readJsonFile(file));
|
|
9490
9693
|
if (!data)
|
|
@@ -9527,7 +9730,7 @@ function ruleItem(file, source, stats) {
|
|
|
9527
9730
|
return {
|
|
9528
9731
|
id: "",
|
|
9529
9732
|
slot: "rules",
|
|
9530
|
-
nativeName:
|
|
9733
|
+
nativeName: basename4(file),
|
|
9531
9734
|
nativePath: file,
|
|
9532
9735
|
tokens: estimateTokens(statSync2(file).size),
|
|
9533
9736
|
residency: "resident",
|
|
@@ -9547,20 +9750,20 @@ function buildRules(homeDir, projectDir, stats) {
|
|
|
9547
9750
|
if (item !== void 0)
|
|
9548
9751
|
items.push(item);
|
|
9549
9752
|
};
|
|
9550
|
-
const userClaudeMd =
|
|
9551
|
-
if (
|
|
9753
|
+
const userClaudeMd = join11(homeDir, ".claude", "CLAUDE.md");
|
|
9754
|
+
if (existsSync6(userClaudeMd))
|
|
9552
9755
|
append(userClaudeMd, "user");
|
|
9553
|
-
for (const f of listMdFiles(
|
|
9756
|
+
for (const f of listMdFiles(join11(homeDir, ".claude", "rules"), stats))
|
|
9554
9757
|
append(f, "user");
|
|
9555
9758
|
if (isBareProjectDir(projectDir, homeDir)) {
|
|
9556
|
-
const direct =
|
|
9557
|
-
if (
|
|
9759
|
+
const direct = join11(projectDir, "CLAUDE.md");
|
|
9760
|
+
if (existsSync6(direct))
|
|
9558
9761
|
append(direct, "project");
|
|
9559
9762
|
} else {
|
|
9560
9763
|
for (const f of walkFiles(projectDir, "CLAUDE.md", stats))
|
|
9561
9764
|
append(f, "project");
|
|
9562
9765
|
}
|
|
9563
|
-
for (const f of listMdFiles(
|
|
9766
|
+
for (const f of listMdFiles(join11(projectDir, ".claude", "rules"), stats)) {
|
|
9564
9767
|
append(f, "project");
|
|
9565
9768
|
}
|
|
9566
9769
|
return items;
|
|
@@ -9583,14 +9786,14 @@ function parseSkillFrontmatter(content) {
|
|
|
9583
9786
|
return out;
|
|
9584
9787
|
}
|
|
9585
9788
|
function buildSkills(homeDir, projectDir, overrides, stats) {
|
|
9586
|
-
const userRoot =
|
|
9587
|
-
const syncedRoot =
|
|
9789
|
+
const userRoot = join11(homeDir, ".claude", "skills");
|
|
9790
|
+
const syncedRoot = join11(userRoot, "synced");
|
|
9588
9791
|
const roots = [
|
|
9589
9792
|
{ root: userRoot, source: "user", exclude: syncedRoot },
|
|
9590
9793
|
// projectDir 为家目录时,项目 skills 根与 user 根是同一目录,再走一遍会把每个
|
|
9591
9794
|
// skill 重复列为 project 层;bare root 无项目上下文 → 不设项目 skills 根
|
|
9592
|
-
...isBareProjectDir(projectDir, homeDir) ? [] : [{ root:
|
|
9593
|
-
{ root:
|
|
9795
|
+
...isBareProjectDir(projectDir, homeDir) ? [] : [{ root: join11(projectDir, ".claude", "skills"), source: "project" }],
|
|
9796
|
+
{ root: join11(homeDir, ".claude", "plugins"), source: "plugin" },
|
|
9594
9797
|
{ root: syncedRoot, source: "synced" }
|
|
9595
9798
|
];
|
|
9596
9799
|
const items = [];
|
|
@@ -9599,8 +9802,8 @@ function buildSkills(homeDir, projectDir, overrides, stats) {
|
|
|
9599
9802
|
if (exclude && (skillFile === exclude || skillFile.startsWith(exclude + sep)))
|
|
9600
9803
|
continue;
|
|
9601
9804
|
try {
|
|
9602
|
-
const fm = parseSkillFrontmatter(
|
|
9603
|
-
const name = fm.name ??
|
|
9805
|
+
const fm = parseSkillFrontmatter(readFileSync6(skillFile, "utf8"));
|
|
9806
|
+
const name = fm.name ?? basename4(dirname7(skillFile));
|
|
9604
9807
|
const size = statSync2(skillFile).size;
|
|
9605
9808
|
items.push({
|
|
9606
9809
|
id: "",
|
|
@@ -9624,9 +9827,9 @@ function buildSkills(homeDir, projectDir, overrides, stats) {
|
|
|
9624
9827
|
}
|
|
9625
9828
|
function buildTools(homeDir, projectDir) {
|
|
9626
9829
|
const items = [];
|
|
9627
|
-
const claudeJsonPath =
|
|
9830
|
+
const claudeJsonPath = join11(homeDir, ".claude.json");
|
|
9628
9831
|
let claudeJson;
|
|
9629
|
-
if (
|
|
9832
|
+
if (existsSync6(claudeJsonPath))
|
|
9630
9833
|
claudeJson = asRecord(readJsonFile(claudeJsonPath));
|
|
9631
9834
|
const projectEntry = recordField(claudeJson?.projects, resolve3(projectDir));
|
|
9632
9835
|
const disabledRaw = projectEntry?.disabledMcpServers;
|
|
@@ -9650,8 +9853,8 @@ function buildTools(homeDir, projectDir) {
|
|
|
9650
9853
|
for (const name of Object.keys(localServers).sort()) {
|
|
9651
9854
|
items.push(mcpItem(name, "local", claudeJsonPath));
|
|
9652
9855
|
}
|
|
9653
|
-
const mcpJsonPath =
|
|
9654
|
-
if (
|
|
9856
|
+
const mcpJsonPath = join11(projectDir, ".mcp.json");
|
|
9857
|
+
if (existsSync6(mcpJsonPath)) {
|
|
9655
9858
|
const projectServers = recordField(readJsonFile(mcpJsonPath), "mcpServers") ?? {};
|
|
9656
9859
|
for (const name of Object.keys(projectServers).sort()) {
|
|
9657
9860
|
items.push(mcpItem(name, "project", mcpJsonPath));
|
|
@@ -9697,7 +9900,7 @@ function lastContextTotal(file, stats) {
|
|
|
9697
9900
|
let total;
|
|
9698
9901
|
let text;
|
|
9699
9902
|
try {
|
|
9700
|
-
text =
|
|
9903
|
+
text = readFileSync6(file, "utf8");
|
|
9701
9904
|
} catch (error) {
|
|
9702
9905
|
recordWalkError(error, stats);
|
|
9703
9906
|
return void 0;
|
|
@@ -9725,10 +9928,10 @@ function lastContextTotal(file, stats) {
|
|
|
9725
9928
|
return total;
|
|
9726
9929
|
}
|
|
9727
9930
|
function buildHistory(homeDir, projectDir, stats) {
|
|
9728
|
-
const dir =
|
|
9931
|
+
const dir = join11(homeDir, ".claude", "projects", projectSlug(projectDir));
|
|
9729
9932
|
const items = [];
|
|
9730
9933
|
for (const name of safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".jsonl")).sort()) {
|
|
9731
|
-
const file =
|
|
9934
|
+
const file = join11(dir, name);
|
|
9732
9935
|
const total = lastContextTotal(file, stats);
|
|
9733
9936
|
if (total === void 0)
|
|
9734
9937
|
continue;
|
|
@@ -9839,9 +10042,9 @@ var init_scan = __esm({
|
|
|
9839
10042
|
});
|
|
9840
10043
|
|
|
9841
10044
|
// packages/adapter-cc/dist/actions.js
|
|
9842
|
-
import { existsSync as
|
|
10045
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
9843
10046
|
import { homedir as homedir7 } from "node:os";
|
|
9844
|
-
import { basename as
|
|
10047
|
+
import { basename as basename5, dirname as dirname8, join as join12, resolve as resolve4 } from "node:path";
|
|
9845
10048
|
function asRecord2(v) {
|
|
9846
10049
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
|
|
9847
10050
|
}
|
|
@@ -9865,10 +10068,10 @@ function deepEqual(a, b) {
|
|
|
9865
10068
|
}
|
|
9866
10069
|
function backupDirPath(homeDir) {
|
|
9867
10070
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
9868
|
-
const root =
|
|
9869
|
-
let dir =
|
|
9870
|
-
for (let n = 2;
|
|
9871
|
-
dir =
|
|
10071
|
+
const root = join12(homeDir, ".wingman", "backups");
|
|
10072
|
+
let dir = join12(root, ts);
|
|
10073
|
+
for (let n = 2; existsSync7(dir); n++)
|
|
10074
|
+
dir = join12(root, `${ts}-${n}`);
|
|
9872
10075
|
return dir;
|
|
9873
10076
|
}
|
|
9874
10077
|
function decodeUtf8Strict3(buffer, file) {
|
|
@@ -9880,15 +10083,15 @@ function decodeUtf8Strict3(buffer, file) {
|
|
|
9880
10083
|
}
|
|
9881
10084
|
function readSettingsSnapshots(homeDir, projectDir) {
|
|
9882
10085
|
const files = [
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
10086
|
+
join12(homeDir, ".claude", "settings.json"),
|
|
10087
|
+
join12(projectDir, ".claude", "settings.json"),
|
|
10088
|
+
join12(projectDir, ".claude", "settings.local.json")
|
|
9886
10089
|
];
|
|
9887
10090
|
const out = [];
|
|
9888
10091
|
for (const file of files) {
|
|
9889
|
-
if (!
|
|
10092
|
+
if (!existsSync7(file))
|
|
9890
10093
|
continue;
|
|
9891
|
-
const raw = decodeUtf8Strict3(
|
|
10094
|
+
const raw = decodeUtf8Strict3(readFileSync7(file), file);
|
|
9892
10095
|
let parsed;
|
|
9893
10096
|
try {
|
|
9894
10097
|
parsed = JSON.parse(raw);
|
|
@@ -9911,7 +10114,7 @@ function overridesRecord(s) {
|
|
|
9911
10114
|
return rec;
|
|
9912
10115
|
}
|
|
9913
10116
|
function skillTargetFile(item, homeDir, projectDir) {
|
|
9914
|
-
return item.source === "project" ?
|
|
10117
|
+
return item.source === "project" ? join12(projectDir, ".claude", "settings.json") : join12(homeDir, ".claude", "settings.json");
|
|
9915
10118
|
}
|
|
9916
10119
|
function planSkillToggle(item, enable, homeDir, projectDir) {
|
|
9917
10120
|
const name = item.nativeName;
|
|
@@ -9964,11 +10167,11 @@ function planSkillToggle(item, enable, homeDir, projectDir) {
|
|
|
9964
10167
|
});
|
|
9965
10168
|
}
|
|
9966
10169
|
function planMcpToggle(name, enable, homeDir, projectDir) {
|
|
9967
|
-
const file =
|
|
9968
|
-
if (!
|
|
10170
|
+
const file = join12(homeDir, ".claude.json");
|
|
10171
|
+
if (!existsSync7(file)) {
|
|
9969
10172
|
throw new Error(`\u62D2\u7EDD:\u627E\u4E0D\u5230 ${file}(MCP \u8FDE\u63A5\u5F00\u5173\u6309\u9879\u76EE\u5B58\u653E\u4E8E\u8BE5\u6587\u4EF6)`);
|
|
9970
10173
|
}
|
|
9971
|
-
const raw =
|
|
10174
|
+
const raw = readFileSync7(file, "utf8");
|
|
9972
10175
|
let parsed;
|
|
9973
10176
|
try {
|
|
9974
10177
|
parsed = JSON.parse(raw);
|
|
@@ -10042,24 +10245,24 @@ function collectRefSources(homeDir, projectDir, exclude) {
|
|
|
10042
10245
|
sources.push({ file, text });
|
|
10043
10246
|
};
|
|
10044
10247
|
const pushFile = (file) => {
|
|
10045
|
-
if (!seen.has(file) &&
|
|
10046
|
-
push(file,
|
|
10248
|
+
if (!seen.has(file) && existsSync7(file))
|
|
10249
|
+
push(file, readFileSync7(file, "utf8"));
|
|
10047
10250
|
};
|
|
10048
10251
|
const bareRoot = isBareProjectDir(projectDir, homeDir);
|
|
10049
|
-
pushFile(
|
|
10050
|
-
for (const f of listMdFiles(
|
|
10252
|
+
pushFile(join12(homeDir, ".claude", "CLAUDE.md"));
|
|
10253
|
+
for (const f of listMdFiles(join12(homeDir, ".claude", "rules")))
|
|
10051
10254
|
pushFile(f);
|
|
10052
10255
|
if (bareRoot)
|
|
10053
|
-
pushFile(
|
|
10256
|
+
pushFile(join12(projectDir, "CLAUDE.md"));
|
|
10054
10257
|
else
|
|
10055
10258
|
for (const f of walkFiles(projectDir, "CLAUDE.md"))
|
|
10056
10259
|
pushFile(f);
|
|
10057
|
-
for (const f of listMdFiles(
|
|
10260
|
+
for (const f of listMdFiles(join12(projectDir, ".claude", "rules")))
|
|
10058
10261
|
pushFile(f);
|
|
10059
10262
|
const skillRoots = [
|
|
10060
|
-
|
|
10061
|
-
...bareRoot ? [] : [
|
|
10062
|
-
|
|
10263
|
+
join12(homeDir, ".claude", "skills"),
|
|
10264
|
+
...bareRoot ? [] : [join12(projectDir, ".claude", "skills")],
|
|
10265
|
+
join12(homeDir, ".claude", "plugins")
|
|
10063
10266
|
];
|
|
10064
10267
|
for (const root of skillRoots) {
|
|
10065
10268
|
for (const f of walkFiles(root, "SKILL.md")) {
|
|
@@ -10068,20 +10271,20 @@ function collectRefSources(homeDir, projectDir, exclude) {
|
|
|
10068
10271
|
}
|
|
10069
10272
|
}
|
|
10070
10273
|
for (const dir of [
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10274
|
+
join12(homeDir, ".claude", "agents"),
|
|
10275
|
+
join12(projectDir, ".claude", "agents"),
|
|
10276
|
+
join12(homeDir, ".claude", "commands"),
|
|
10277
|
+
join12(projectDir, ".claude", "commands")
|
|
10075
10278
|
]) {
|
|
10076
10279
|
for (const f of listMdFiles(dir))
|
|
10077
10280
|
pushFile(f);
|
|
10078
10281
|
}
|
|
10079
10282
|
for (const s of readSettingsSnapshots(homeDir, projectDir))
|
|
10080
10283
|
push(s.file, s.raw);
|
|
10081
|
-
for (const file of [
|
|
10082
|
-
if (seen.has(file) || !
|
|
10284
|
+
for (const file of [join12(projectDir, ".mcp.json"), join12(homeDir, ".claude.json")]) {
|
|
10285
|
+
if (seen.has(file) || !existsSync7(file))
|
|
10083
10286
|
continue;
|
|
10084
|
-
const raw =
|
|
10287
|
+
const raw = readFileSync7(file, "utf8");
|
|
10085
10288
|
let parsed;
|
|
10086
10289
|
try {
|
|
10087
10290
|
parsed = JSON.parse(raw);
|
|
@@ -10188,14 +10391,14 @@ async function applyActionCc(plan, _options) {
|
|
|
10188
10391
|
const currentByFile = /* @__PURE__ */ new Map();
|
|
10189
10392
|
for (const w of plan.writes) {
|
|
10190
10393
|
if (w.kind === "create") {
|
|
10191
|
-
if (
|
|
10394
|
+
if (existsSync7(w.file)) {
|
|
10192
10395
|
return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5728 plan \u540E\u88AB\u521B\u5EFA,\u8BF7\u91CD\u65B0 plan` };
|
|
10193
10396
|
}
|
|
10194
10397
|
} else {
|
|
10195
|
-
if (!
|
|
10398
|
+
if (!existsSync7(w.file)) {
|
|
10196
10399
|
return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5DF2\u4E0D\u5B58\u5728(plan \u540E\u88AB\u6539\u52A8),\u8BF7\u91CD\u65B0 plan` };
|
|
10197
10400
|
}
|
|
10198
|
-
const currentRaw =
|
|
10401
|
+
const currentRaw = readFileSync7(w.file);
|
|
10199
10402
|
if (!currentRaw.equals(Buffer.from(w.before, "utf8"))) {
|
|
10200
10403
|
return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5728 plan \u540E\u88AB\u6539\u8FC7,\u8BF7\u91CD\u65B0 plan` };
|
|
10201
10404
|
}
|
|
@@ -10203,15 +10406,15 @@ async function applyActionCc(plan, _options) {
|
|
|
10203
10406
|
}
|
|
10204
10407
|
}
|
|
10205
10408
|
const toBackup = plan.writes.filter((w) => w.kind !== "create");
|
|
10206
|
-
|
|
10409
|
+
mkdirSync4(plan.backupDir, { recursive: true });
|
|
10207
10410
|
const manifestFiles = toBackup.map((w, i) => ({
|
|
10208
|
-
backup: `${i}-${
|
|
10411
|
+
backup: `${i}-${basename5(w.file)}`,
|
|
10209
10412
|
target: w.file
|
|
10210
10413
|
}));
|
|
10211
10414
|
toBackup.forEach((w, i) => {
|
|
10212
|
-
|
|
10415
|
+
writeFileSync5(join12(plan.backupDir, `${i}-${basename5(w.file)}`), currentByFile.get(w.file));
|
|
10213
10416
|
});
|
|
10214
|
-
|
|
10417
|
+
writeFileSync5(join12(plan.backupDir, "manifest.json"), serialize({
|
|
10215
10418
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10216
10419
|
harness: "cc",
|
|
10217
10420
|
action: plan.action,
|
|
@@ -10221,10 +10424,10 @@ async function applyActionCc(plan, _options) {
|
|
|
10221
10424
|
try {
|
|
10222
10425
|
for (const w of plan.writes) {
|
|
10223
10426
|
if (w.kind === "delete") {
|
|
10224
|
-
|
|
10427
|
+
rmSync3(w.file);
|
|
10225
10428
|
} else {
|
|
10226
|
-
|
|
10227
|
-
|
|
10429
|
+
mkdirSync4(dirname8(w.file), { recursive: true });
|
|
10430
|
+
writeFileSync5(w.file, w.after ?? "");
|
|
10228
10431
|
}
|
|
10229
10432
|
written.push(w);
|
|
10230
10433
|
}
|
|
@@ -10233,9 +10436,9 @@ async function applyActionCc(plan, _options) {
|
|
|
10233
10436
|
for (const w of written) {
|
|
10234
10437
|
try {
|
|
10235
10438
|
if (w.kind === "create")
|
|
10236
|
-
|
|
10439
|
+
rmSync3(w.file, { force: true });
|
|
10237
10440
|
else
|
|
10238
|
-
|
|
10441
|
+
writeFileSync5(w.file, w.before ?? "");
|
|
10239
10442
|
} catch {
|
|
10240
10443
|
failures.push(w.file);
|
|
10241
10444
|
}
|
|
@@ -10244,12 +10447,12 @@ async function applyActionCc(plan, _options) {
|
|
|
10244
10447
|
return { ok: false, error: `\u5199\u5165\u5931\u8D25:${e.message};${rollbackNote}` };
|
|
10245
10448
|
}
|
|
10246
10449
|
for (const w of plan.writes) {
|
|
10247
|
-
if (
|
|
10450
|
+
if (basename5(w.file) !== ".claude.json" || w.kind !== "modify" || w.after === void 0) {
|
|
10248
10451
|
continue;
|
|
10249
10452
|
}
|
|
10250
10453
|
let verified = false;
|
|
10251
10454
|
try {
|
|
10252
|
-
verified = deepEqual(JSON.parse(
|
|
10455
|
+
verified = deepEqual(JSON.parse(readFileSync7(w.file, "utf8")), JSON.parse(w.after));
|
|
10253
10456
|
} catch {
|
|
10254
10457
|
verified = false;
|
|
10255
10458
|
}
|
|
@@ -10275,9 +10478,9 @@ var init_actions = __esm({
|
|
|
10275
10478
|
});
|
|
10276
10479
|
|
|
10277
10480
|
// packages/adapter-cc/dist/hooks.js
|
|
10278
|
-
import { existsSync as
|
|
10481
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync8, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
10279
10482
|
import { homedir as homedir8 } from "node:os";
|
|
10280
|
-
import { dirname as
|
|
10483
|
+
import { dirname as dirname9, join as join13 } from "node:path";
|
|
10281
10484
|
function wingmanUrl(port) {
|
|
10282
10485
|
return `http://127.0.0.1:${port}${SIGNATURE}`;
|
|
10283
10486
|
}
|
|
@@ -10289,18 +10492,18 @@ function isWingmanHandler(h) {
|
|
|
10289
10492
|
return rec?.type === "http" && typeof rec.url === "string" && rec.url.includes(SIGNATURE);
|
|
10290
10493
|
}
|
|
10291
10494
|
function wingmanRoot(homeDir) {
|
|
10292
|
-
return
|
|
10495
|
+
return join13(homeDir, ".wingman");
|
|
10293
10496
|
}
|
|
10294
10497
|
function statePath(homeDir) {
|
|
10295
|
-
return
|
|
10498
|
+
return join13(wingmanRoot(homeDir), "state", "cc-hooks.json");
|
|
10296
10499
|
}
|
|
10297
10500
|
function readState3(homeDir) {
|
|
10298
10501
|
const file = statePath(homeDir);
|
|
10299
|
-
if (!
|
|
10502
|
+
if (!existsSync8(file))
|
|
10300
10503
|
return void 0;
|
|
10301
10504
|
let parsed;
|
|
10302
10505
|
try {
|
|
10303
|
-
parsed = JSON.parse(
|
|
10506
|
+
parsed = JSON.parse(readFileSync8(file, "utf8"));
|
|
10304
10507
|
} catch {
|
|
10305
10508
|
return void 0;
|
|
10306
10509
|
}
|
|
@@ -10321,23 +10524,23 @@ function readState3(homeDir) {
|
|
|
10321
10524
|
}
|
|
10322
10525
|
function writeState3(homeDir, state) {
|
|
10323
10526
|
const file = statePath(homeDir);
|
|
10324
|
-
|
|
10325
|
-
|
|
10527
|
+
mkdirSync5(dirname9(file), { recursive: true });
|
|
10528
|
+
writeFileSync6(file, `${JSON.stringify(state, null, 2)}
|
|
10326
10529
|
`);
|
|
10327
10530
|
}
|
|
10328
10531
|
function makeBackupDir(homeDir) {
|
|
10329
10532
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
10330
|
-
const root =
|
|
10331
|
-
let dir =
|
|
10332
|
-
for (let n = 2;
|
|
10333
|
-
dir =
|
|
10334
|
-
|
|
10533
|
+
const root = join13(wingmanRoot(homeDir), "backups");
|
|
10534
|
+
let dir = join13(root, ts);
|
|
10535
|
+
for (let n = 2; existsSync8(dir); n++)
|
|
10536
|
+
dir = join13(root, `${ts}-${n}`);
|
|
10537
|
+
mkdirSync5(dir, { recursive: true });
|
|
10335
10538
|
return dir;
|
|
10336
10539
|
}
|
|
10337
|
-
function
|
|
10338
|
-
if (!
|
|
10540
|
+
function readTarget2(target) {
|
|
10541
|
+
if (!existsSync8(target))
|
|
10339
10542
|
return { bytes: null, settings: {} };
|
|
10340
|
-
const bytes =
|
|
10543
|
+
const bytes = readFileSync8(target, "utf8");
|
|
10341
10544
|
let parsed;
|
|
10342
10545
|
try {
|
|
10343
10546
|
parsed = JSON.parse(bytes);
|
|
@@ -10440,13 +10643,13 @@ function deepEqual2(a, b) {
|
|
|
10440
10643
|
return false;
|
|
10441
10644
|
}
|
|
10442
10645
|
function targetPath(homeDir) {
|
|
10443
|
-
return
|
|
10646
|
+
return join13(homeDir, ".claude", "settings.json");
|
|
10444
10647
|
}
|
|
10445
10648
|
async function installHooksCc(port, options) {
|
|
10446
10649
|
const homeDir = options?.homeDir ?? homedir8();
|
|
10447
10650
|
const target = targetPath(homeDir);
|
|
10448
10651
|
const url = wingmanUrl(port);
|
|
10449
|
-
const { bytes, settings } =
|
|
10652
|
+
const { bytes, settings } = readTarget2(target);
|
|
10450
10653
|
if (isFullyWired(settings, url))
|
|
10451
10654
|
return;
|
|
10452
10655
|
if (settings.hooks !== void 0 && !asRecord3(settings.hooks)) {
|
|
@@ -10462,7 +10665,7 @@ async function installHooksCc(port, options) {
|
|
|
10462
10665
|
}
|
|
10463
10666
|
const backupDir = makeBackupDir(homeDir);
|
|
10464
10667
|
if (bytes !== null)
|
|
10465
|
-
|
|
10668
|
+
writeFileSync6(join13(backupDir, "settings.json"), bytes);
|
|
10466
10669
|
const prev = readState3(homeDir);
|
|
10467
10670
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10468
10671
|
writeState3(homeDir, prev ? { ...prev, port, installedAt: now } : { target, original: bytes, backupDir, port, installedAt: now });
|
|
@@ -10474,44 +10677,44 @@ async function installHooksCc(port, options) {
|
|
|
10474
10677
|
groups.push({ hooks: [{ type: "http", url }] });
|
|
10475
10678
|
hooks[event] = groups;
|
|
10476
10679
|
}
|
|
10477
|
-
|
|
10478
|
-
|
|
10680
|
+
mkdirSync5(dirname9(target), { recursive: true });
|
|
10681
|
+
writeFileSync6(target, `${JSON.stringify(settings, null, 2)}
|
|
10479
10682
|
`);
|
|
10480
10683
|
}
|
|
10481
10684
|
async function uninstallHooksCc(options) {
|
|
10482
10685
|
const homeDir = options?.homeDir ?? homedir8();
|
|
10483
10686
|
const target = targetPath(homeDir);
|
|
10484
10687
|
const state = readState3(homeDir);
|
|
10485
|
-
if (!
|
|
10486
|
-
|
|
10688
|
+
if (!existsSync8(target)) {
|
|
10689
|
+
rmSync4(statePath(homeDir), { force: true });
|
|
10487
10690
|
return;
|
|
10488
10691
|
}
|
|
10489
|
-
const { bytes, settings } =
|
|
10692
|
+
const { bytes, settings } = readTarget2(target);
|
|
10490
10693
|
const changed = removeWingmanEntries(settings);
|
|
10491
10694
|
if (!changed) {
|
|
10492
|
-
|
|
10695
|
+
rmSync4(statePath(homeDir), { force: true });
|
|
10493
10696
|
return;
|
|
10494
10697
|
}
|
|
10495
10698
|
const backupDir = makeBackupDir(homeDir);
|
|
10496
10699
|
if (bytes !== null)
|
|
10497
|
-
|
|
10700
|
+
writeFileSync6(join13(backupDir, "settings.json"), bytes);
|
|
10498
10701
|
if (state && state.original !== null) {
|
|
10499
10702
|
const originalParsed = asRecord3(JSON.parse(state.original));
|
|
10500
10703
|
if (originalParsed && deepEqual2(normalizeForCompare(settings), normalizeForCompare(originalParsed))) {
|
|
10501
|
-
|
|
10502
|
-
|
|
10704
|
+
writeFileSync6(target, state.original);
|
|
10705
|
+
rmSync4(statePath(homeDir), { force: true });
|
|
10503
10706
|
return;
|
|
10504
10707
|
}
|
|
10505
10708
|
} else if (state && state.original === null) {
|
|
10506
10709
|
if (deepEqual2(normalizeForCompare(settings), {})) {
|
|
10507
|
-
|
|
10508
|
-
|
|
10710
|
+
rmSync4(target, { force: true });
|
|
10711
|
+
rmSync4(statePath(homeDir), { force: true });
|
|
10509
10712
|
return;
|
|
10510
10713
|
}
|
|
10511
10714
|
}
|
|
10512
|
-
|
|
10715
|
+
writeFileSync6(target, `${JSON.stringify(settings, null, 2)}
|
|
10513
10716
|
`);
|
|
10514
|
-
|
|
10717
|
+
rmSync4(statePath(homeDir), { force: true });
|
|
10515
10718
|
}
|
|
10516
10719
|
var WIRED_EVENTS, SIGNATURE;
|
|
10517
10720
|
var init_hooks2 = __esm({
|
|
@@ -10532,60 +10735,60 @@ var init_hooks2 = __esm({
|
|
|
10532
10735
|
});
|
|
10533
10736
|
|
|
10534
10737
|
// packages/adapter-cc/dist/protocol.js
|
|
10535
|
-
import { existsSync as
|
|
10738
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as readFileSync9, rmdirSync, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
10536
10739
|
import { homedir as homedir9 } from "node:os";
|
|
10537
|
-
import { basename as
|
|
10740
|
+
import { basename as basename6, dirname as dirname10, join as join14, resolve as resolve5 } from "node:path";
|
|
10538
10741
|
function protocolStatusCc(options) {
|
|
10539
|
-
const
|
|
10540
|
-
if (!
|
|
10541
|
-
return { harness: "cc", state: "not_installed", targetPath:
|
|
10742
|
+
const paths3 = resolveOptions2(options);
|
|
10743
|
+
if (!existsSync9(paths3.targetPath)) {
|
|
10744
|
+
return { harness: "cc", state: "not_installed", targetPath: paths3.targetPath };
|
|
10542
10745
|
}
|
|
10543
10746
|
try {
|
|
10544
|
-
return statusFromIdentity(
|
|
10747
|
+
return statusFromIdentity(paths3.targetPath, inspectPlanProtocolFile(readFileSync9(paths3.targetPath), paths3.targetPath));
|
|
10545
10748
|
} catch (error) {
|
|
10546
10749
|
return {
|
|
10547
10750
|
harness: "cc",
|
|
10548
10751
|
state: "invalid",
|
|
10549
|
-
targetPath:
|
|
10752
|
+
targetPath: paths3.targetPath,
|
|
10550
10753
|
reason: error.message
|
|
10551
10754
|
};
|
|
10552
10755
|
}
|
|
10553
10756
|
}
|
|
10554
10757
|
function installProtocolCc(options) {
|
|
10555
|
-
const
|
|
10556
|
-
const existing = readExisting(
|
|
10758
|
+
const paths3 = resolveOptions2(options);
|
|
10759
|
+
const existing = readExisting(paths3.targetPath);
|
|
10557
10760
|
const previousState = stateForIdentity2(existing?.identity);
|
|
10558
10761
|
if (previousState === "installed") {
|
|
10559
|
-
return
|
|
10762
|
+
return result3(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true);
|
|
10560
10763
|
}
|
|
10561
10764
|
if (previousState === "modified")
|
|
10562
|
-
throw modifiedError2(
|
|
10765
|
+
throw modifiedError2(paths3.targetPath, "\u5B89\u88C5");
|
|
10563
10766
|
const before = existing?.text ?? "";
|
|
10564
|
-
const backupDir =
|
|
10767
|
+
const backupDir = nextBackupDir3(paths3.homeDir);
|
|
10565
10768
|
const installedSha256 = sha256Hex(PLAN_PROTOCOL_TEXT);
|
|
10566
|
-
if (!
|
|
10567
|
-
const claudeDir =
|
|
10568
|
-
const rulesDir =
|
|
10569
|
-
const prior = readState4(
|
|
10570
|
-
|
|
10571
|
-
writeState4(
|
|
10769
|
+
if (!paths3.dryRun) {
|
|
10770
|
+
const claudeDir = join14(paths3.projectDir, ".claude");
|
|
10771
|
+
const rulesDir = dirname10(paths3.targetPath);
|
|
10772
|
+
const prior = readState4(paths3.statePath);
|
|
10773
|
+
backupTarget3(backupDir, paths3.targetPath, existing?.bytes);
|
|
10774
|
+
writeState4(paths3.statePath, {
|
|
10572
10775
|
version: 1,
|
|
10573
10776
|
harness: "cc",
|
|
10574
|
-
projectDir:
|
|
10575
|
-
targetPath:
|
|
10777
|
+
projectDir: paths3.projectDir,
|
|
10778
|
+
targetPath: paths3.targetPath,
|
|
10576
10779
|
protocolVersion: PLAN_PROTOCOL_VERSION,
|
|
10577
10780
|
installedSha256,
|
|
10578
10781
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10579
10782
|
backupDir,
|
|
10580
10783
|
original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") }),
|
|
10581
|
-
createdClaudeDir: prior?.createdClaudeDir ?? !
|
|
10582
|
-
createdRulesDir: prior?.createdRulesDir ?? !
|
|
10784
|
+
createdClaudeDir: prior?.createdClaudeDir ?? !existsSync9(claudeDir),
|
|
10785
|
+
createdRulesDir: prior?.createdRulesDir ?? !existsSync9(rulesDir)
|
|
10583
10786
|
});
|
|
10584
|
-
|
|
10585
|
-
|
|
10787
|
+
mkdirSync6(rulesDir, { recursive: true });
|
|
10788
|
+
writeFileSync7(paths3.targetPath, PLAN_PROTOCOL_TEXT);
|
|
10586
10789
|
}
|
|
10587
10790
|
return {
|
|
10588
|
-
...
|
|
10791
|
+
...result3(paths3.targetPath, "install", true, previousState, before, true),
|
|
10589
10792
|
state: "installed",
|
|
10590
10793
|
version: PLAN_PROTOCOL_VERSION,
|
|
10591
10794
|
sha256: installedSha256,
|
|
@@ -10595,31 +10798,31 @@ function installProtocolCc(options) {
|
|
|
10595
10798
|
};
|
|
10596
10799
|
}
|
|
10597
10800
|
function uninstallProtocolCc(options) {
|
|
10598
|
-
const
|
|
10599
|
-
const existing = readExisting(
|
|
10801
|
+
const paths3 = resolveOptions2(options);
|
|
10802
|
+
const existing = readExisting(paths3.targetPath);
|
|
10600
10803
|
if (existing === void 0) {
|
|
10601
|
-
return
|
|
10804
|
+
return result3(paths3.targetPath, "uninstall", false, "not_installed", "", false);
|
|
10602
10805
|
}
|
|
10603
10806
|
const previousState = stateForIdentity2(existing.identity);
|
|
10604
10807
|
if (previousState === "modified")
|
|
10605
|
-
throw modifiedError2(
|
|
10606
|
-
const state = readState4(
|
|
10808
|
+
throw modifiedError2(paths3.targetPath, "\u5378\u8F7D");
|
|
10809
|
+
const state = readState4(paths3.statePath);
|
|
10607
10810
|
const restored = restoredOriginal(state);
|
|
10608
10811
|
const after = restored?.toString("utf8") ?? "";
|
|
10609
10812
|
const afterExists = restored !== void 0;
|
|
10610
|
-
const backupDir =
|
|
10611
|
-
if (!
|
|
10612
|
-
|
|
10813
|
+
const backupDir = nextBackupDir3(paths3.homeDir);
|
|
10814
|
+
if (!paths3.dryRun) {
|
|
10815
|
+
backupTarget3(backupDir, paths3.targetPath, existing.bytes);
|
|
10613
10816
|
if (restored === void 0)
|
|
10614
|
-
|
|
10817
|
+
rmSync5(paths3.targetPath, { force: true });
|
|
10615
10818
|
else
|
|
10616
|
-
|
|
10819
|
+
writeFileSync7(paths3.targetPath, restored);
|
|
10617
10820
|
if (restored === void 0)
|
|
10618
|
-
removeCreatedEmptyDirs(
|
|
10619
|
-
|
|
10821
|
+
removeCreatedEmptyDirs(paths3, state);
|
|
10822
|
+
rmSync5(paths3.statePath, { force: true });
|
|
10620
10823
|
}
|
|
10621
10824
|
return {
|
|
10622
|
-
...
|
|
10825
|
+
...result3(paths3.targetPath, "uninstall", true, previousState, existing.text, afterExists),
|
|
10623
10826
|
state: "not_installed",
|
|
10624
10827
|
after,
|
|
10625
10828
|
backupDir,
|
|
@@ -10629,20 +10832,20 @@ function uninstallProtocolCc(options) {
|
|
|
10629
10832
|
function resolveOptions2(options) {
|
|
10630
10833
|
const homeDir = resolve5(options?.homeDir ?? homedir9());
|
|
10631
10834
|
const projectDir = resolve5(options?.projectDir ?? process.cwd());
|
|
10632
|
-
const targetPath2 =
|
|
10835
|
+
const targetPath2 = join14(projectDir, ".claude", "rules", "wingman-plan-protocol.md");
|
|
10633
10836
|
const projectHash = sha256Hex(projectDir);
|
|
10634
10837
|
return {
|
|
10635
10838
|
homeDir,
|
|
10636
10839
|
projectDir,
|
|
10637
10840
|
dryRun: options?.dryRun ?? false,
|
|
10638
10841
|
targetPath: targetPath2,
|
|
10639
|
-
statePath:
|
|
10842
|
+
statePath: join14(homeDir, ".wingman", "state", `plan-protocol-cc-${projectHash}.json`)
|
|
10640
10843
|
};
|
|
10641
10844
|
}
|
|
10642
10845
|
function readExisting(targetPath2) {
|
|
10643
|
-
if (!
|
|
10846
|
+
if (!existsSync9(targetPath2))
|
|
10644
10847
|
return void 0;
|
|
10645
|
-
const bytes =
|
|
10848
|
+
const bytes = readFileSync9(targetPath2);
|
|
10646
10849
|
const identity = inspectPlanProtocolFile(bytes, targetPath2);
|
|
10647
10850
|
return { bytes, text: bytes.toString("utf8"), identity };
|
|
10648
10851
|
}
|
|
@@ -10651,7 +10854,7 @@ function stateForIdentity2(identity) {
|
|
|
10651
10854
|
return "not_installed";
|
|
10652
10855
|
if (identity.kind === "current")
|
|
10653
10856
|
return "installed";
|
|
10654
|
-
if (identity.kind === "
|
|
10857
|
+
if (identity.kind === "outdated")
|
|
10655
10858
|
return "outdated";
|
|
10656
10859
|
return "modified";
|
|
10657
10860
|
}
|
|
@@ -10665,7 +10868,7 @@ function statusFromIdentity(targetPath2, identity) {
|
|
|
10665
10868
|
...identity.kind === "modified" ? { reason: "\u53D7\u7BA1\u534F\u8BAE\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539" } : {}
|
|
10666
10869
|
};
|
|
10667
10870
|
}
|
|
10668
|
-
function
|
|
10871
|
+
function result3(targetPath2, operation, changed, previousState, before, afterExists) {
|
|
10669
10872
|
return {
|
|
10670
10873
|
harness: "cc",
|
|
10671
10874
|
operation,
|
|
@@ -10683,32 +10886,32 @@ function result2(targetPath2, operation, changed, previousState, before, afterEx
|
|
|
10683
10886
|
function modifiedError2(targetPath2, operation) {
|
|
10684
10887
|
return new Error(`\u53D7\u7BA1\u534F\u8BAE\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539(${targetPath2})\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
|
|
10685
10888
|
}
|
|
10686
|
-
function
|
|
10889
|
+
function nextBackupDir3(homeDir) {
|
|
10687
10890
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
10688
|
-
const root =
|
|
10689
|
-
let dir =
|
|
10690
|
-
for (let n = 2;
|
|
10691
|
-
dir =
|
|
10891
|
+
const root = join14(homeDir, ".wingman", "backups");
|
|
10892
|
+
let dir = join14(root, stamp);
|
|
10893
|
+
for (let n = 2; existsSync9(dir); n += 1)
|
|
10894
|
+
dir = join14(root, `${stamp}-${n}`);
|
|
10692
10895
|
return dir;
|
|
10693
10896
|
}
|
|
10694
|
-
function
|
|
10695
|
-
|
|
10897
|
+
function backupTarget3(backupDir, targetPath2, bytes) {
|
|
10898
|
+
mkdirSync6(backupDir, { recursive: true });
|
|
10696
10899
|
if (bytes !== void 0)
|
|
10697
|
-
|
|
10900
|
+
writeFileSync7(join14(backupDir, basename6(targetPath2)), bytes);
|
|
10698
10901
|
}
|
|
10699
10902
|
function readState4(statePath2) {
|
|
10700
|
-
if (!
|
|
10903
|
+
if (!existsSync9(statePath2))
|
|
10701
10904
|
return void 0;
|
|
10702
10905
|
try {
|
|
10703
|
-
const state = JSON.parse(
|
|
10906
|
+
const state = JSON.parse(readFileSync9(statePath2, "utf8"));
|
|
10704
10907
|
return state.version === 1 && state.harness === "cc" && typeof state.targetPath === "string" ? state : void 0;
|
|
10705
10908
|
} catch {
|
|
10706
10909
|
return void 0;
|
|
10707
10910
|
}
|
|
10708
10911
|
}
|
|
10709
10912
|
function writeState4(statePath2, state) {
|
|
10710
|
-
|
|
10711
|
-
|
|
10913
|
+
mkdirSync6(dirname10(statePath2), { recursive: true });
|
|
10914
|
+
writeFileSync7(statePath2, `${JSON.stringify(state, null, 2)}
|
|
10712
10915
|
`);
|
|
10713
10916
|
}
|
|
10714
10917
|
function restoredOriginal(state) {
|
|
@@ -10716,13 +10919,13 @@ function restoredOriginal(state) {
|
|
|
10716
10919
|
return void 0;
|
|
10717
10920
|
return Buffer.from(state.original.base64 ?? "", "base64");
|
|
10718
10921
|
}
|
|
10719
|
-
function removeCreatedEmptyDirs(
|
|
10720
|
-
const rulesDir =
|
|
10721
|
-
const claudeDir =
|
|
10722
|
-
if (state?.createdRulesDir &&
|
|
10922
|
+
function removeCreatedEmptyDirs(paths3, state) {
|
|
10923
|
+
const rulesDir = dirname10(paths3.targetPath);
|
|
10924
|
+
const claudeDir = dirname10(rulesDir);
|
|
10925
|
+
if (state?.createdRulesDir && existsSync9(rulesDir) && readdirSync2(rulesDir).length === 0) {
|
|
10723
10926
|
rmdirSync(rulesDir);
|
|
10724
10927
|
}
|
|
10725
|
-
if (state?.createdClaudeDir &&
|
|
10928
|
+
if (state?.createdClaudeDir && existsSync9(claudeDir) && readdirSync2(claudeDir).length === 0) {
|
|
10726
10929
|
rmdirSync(claudeDir);
|
|
10727
10930
|
}
|
|
10728
10931
|
}
|
|
@@ -10733,6 +10936,33 @@ var init_protocol2 = __esm({
|
|
|
10733
10936
|
}
|
|
10734
10937
|
});
|
|
10735
10938
|
|
|
10939
|
+
// packages/adapter-cc/dist/protocol-user.js
|
|
10940
|
+
import { homedir as homedir10 } from "node:os";
|
|
10941
|
+
import { join as join15, resolve as resolve6 } from "node:path";
|
|
10942
|
+
function paths(options) {
|
|
10943
|
+
const homeDir = resolve6(options?.homeDir ?? homedir10());
|
|
10944
|
+
return {
|
|
10945
|
+
homeDir,
|
|
10946
|
+
targetPath: join15(homeDir, ".claude", "CLAUDE.md"),
|
|
10947
|
+
dryRun: options?.dryRun ?? false
|
|
10948
|
+
};
|
|
10949
|
+
}
|
|
10950
|
+
function protocolStatusCcUser(options) {
|
|
10951
|
+
return { harness: "cc", ...statusPlanProtocolUser(paths(options).targetPath) };
|
|
10952
|
+
}
|
|
10953
|
+
function installProtocolCcUser(options) {
|
|
10954
|
+
return { harness: "cc", ...installPlanProtocolUser(paths(options)) };
|
|
10955
|
+
}
|
|
10956
|
+
function uninstallProtocolCcUser(options) {
|
|
10957
|
+
return { harness: "cc", ...uninstallPlanProtocolUser(paths(options)) };
|
|
10958
|
+
}
|
|
10959
|
+
var init_protocol_user = __esm({
|
|
10960
|
+
"packages/adapter-cc/dist/protocol-user.js"() {
|
|
10961
|
+
"use strict";
|
|
10962
|
+
init_dist();
|
|
10963
|
+
}
|
|
10964
|
+
});
|
|
10965
|
+
|
|
10736
10966
|
// packages/adapter-cc/dist/index.js
|
|
10737
10967
|
var dist_exports2 = {};
|
|
10738
10968
|
__export(dist_exports2, {
|
|
@@ -10740,8 +10970,11 @@ __export(dist_exports2, {
|
|
|
10740
10970
|
createAdapter: () => createAdapter2,
|
|
10741
10971
|
feedbackSignals: () => feedbackSignalsCc,
|
|
10742
10972
|
installProtocolCc: () => installProtocolCc,
|
|
10973
|
+
installProtocolCcUser: () => installProtocolCcUser,
|
|
10743
10974
|
protocolStatusCc: () => protocolStatusCc,
|
|
10744
|
-
|
|
10975
|
+
protocolStatusCcUser: () => protocolStatusCcUser,
|
|
10976
|
+
uninstallProtocolCc: () => uninstallProtocolCc,
|
|
10977
|
+
uninstallProtocolCcUser: () => uninstallProtocolCcUser
|
|
10745
10978
|
});
|
|
10746
10979
|
function createAdapter2(_options) {
|
|
10747
10980
|
return {
|
|
@@ -10764,6 +10997,7 @@ var init_dist3 = __esm({
|
|
|
10764
10997
|
init_hooks2();
|
|
10765
10998
|
init_protocol2();
|
|
10766
10999
|
init_scan();
|
|
11000
|
+
init_protocol_user();
|
|
10767
11001
|
}
|
|
10768
11002
|
});
|
|
10769
11003
|
|
|
@@ -11476,15 +11710,15 @@ var init_dist4 = __esm({
|
|
|
11476
11710
|
});
|
|
11477
11711
|
|
|
11478
11712
|
// packages/adapter-codex/dist/shared.js
|
|
11479
|
-
import { homedir as
|
|
11480
|
-
import { join as
|
|
11713
|
+
import { homedir as homedir11 } from "node:os";
|
|
11714
|
+
import { join as join16 } from "node:path";
|
|
11481
11715
|
function resolvePaths(options) {
|
|
11482
|
-
const homeDir = options?.homeDir ??
|
|
11716
|
+
const homeDir = options?.homeDir ?? homedir11();
|
|
11483
11717
|
const projectDir = options?.projectDir ?? process.cwd();
|
|
11484
|
-
return { homeDir, projectDir, codexHome:
|
|
11718
|
+
return { homeDir, projectDir, codexHome: join16(homeDir, ".codex") };
|
|
11485
11719
|
}
|
|
11486
|
-
function wingmanStateRoot(
|
|
11487
|
-
return
|
|
11720
|
+
function wingmanStateRoot(paths3) {
|
|
11721
|
+
return join16(paths3.homeDir, ".wingman");
|
|
11488
11722
|
}
|
|
11489
11723
|
function isTable(value) {
|
|
11490
11724
|
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
|
|
@@ -11793,26 +12027,26 @@ var init_toml_edit = __esm({
|
|
|
11793
12027
|
});
|
|
11794
12028
|
|
|
11795
12029
|
// packages/adapter-codex/dist/actions.js
|
|
11796
|
-
import { existsSync as
|
|
11797
|
-
import { basename as
|
|
12030
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
12031
|
+
import { basename as basename7, dirname as dirname11, join as join17 } from "node:path";
|
|
11798
12032
|
async function planAction(action, options) {
|
|
11799
|
-
const
|
|
11800
|
-
const resolved = resolveToggle(action,
|
|
12033
|
+
const paths3 = resolvePaths(options);
|
|
12034
|
+
const resolved = resolveToggle(action, paths3);
|
|
11801
12035
|
return {
|
|
11802
12036
|
harness: "codex",
|
|
11803
12037
|
action,
|
|
11804
12038
|
writes: [
|
|
11805
12039
|
{ file: resolved.file, kind: "modify", before: resolved.before, after: resolved.after }
|
|
11806
12040
|
],
|
|
11807
|
-
backupDir:
|
|
11808
|
-
references: scanReferences(collectCorpus(
|
|
12041
|
+
backupDir: nextBackupDir4(paths3),
|
|
12042
|
+
references: scanReferences(collectCorpus(paths3), resolved.bareName),
|
|
11809
12043
|
// §4b 地面真值:config.toml 启动时读,外改对运行中会话不生效 → 如实报 next_session
|
|
11810
12044
|
effectiveAt: "next_session"
|
|
11811
12045
|
};
|
|
11812
12046
|
}
|
|
11813
12047
|
async function applyAction(plan, options) {
|
|
11814
12048
|
try {
|
|
11815
|
-
const
|
|
12049
|
+
const paths3 = resolvePaths(options);
|
|
11816
12050
|
if (plan.harness !== "codex") {
|
|
11817
12051
|
return { ok: false, error: `plan.harness=${String(plan.harness)} \u4E0D\u662F codex,\u62D2\u7EDD\u6267\u884C` };
|
|
11818
12052
|
}
|
|
@@ -11823,38 +12057,38 @@ async function applyAction(plan, options) {
|
|
|
11823
12057
|
error: "plan.writes \u4E0D\u662F\u672C adapter \u4EA7\u51FA\u7684\u5F62\u72B6(\u5E94\u6070\u4E3A\u4E00\u5904 modify),\u62D2\u7EDD\u6267\u884C"
|
|
11824
12058
|
};
|
|
11825
12059
|
}
|
|
11826
|
-
const backupsRoot =
|
|
11827
|
-
if (
|
|
12060
|
+
const backupsRoot = join17(wingmanStateRoot(paths3), "backups");
|
|
12061
|
+
if (dirname11(plan.backupDir) !== backupsRoot) {
|
|
11828
12062
|
return { ok: false, error: `backupDir \u4E0D\u5728 wingman \u5907\u4EFD\u6839(${backupsRoot})\u4E0B,\u62D2\u7EDD\u6267\u884C` };
|
|
11829
12063
|
}
|
|
11830
|
-
const currentRaw =
|
|
12064
|
+
const currentRaw = readFileSync10(write.file);
|
|
11831
12065
|
if (!currentRaw.equals(Buffer.from(write.before, "utf8"))) {
|
|
11832
12066
|
return { ok: false, error: `\u6587\u4EF6\u5728 plan \u4E4B\u540E\u88AB\u4FEE\u6539(${write.file}),\u62D2\u7EDD\u6267\u884C;\u8BF7\u91CD\u65B0 plan` };
|
|
11833
12067
|
}
|
|
11834
|
-
const resolved = resolveToggle(plan.action,
|
|
12068
|
+
const resolved = resolveToggle(plan.action, paths3);
|
|
11835
12069
|
if (resolved.file !== write.file) {
|
|
11836
12070
|
return { ok: false, error: "plan.writes \u7684\u76EE\u6807\u6587\u4EF6\u4E0E itemId \u5BF9\u4E0D\u4E0A,\u62D2\u7EDD\u6267\u884C" };
|
|
11837
12071
|
}
|
|
11838
12072
|
if (resolved.after !== write.after) {
|
|
11839
12073
|
return { ok: false, error: "plan \u4E0E\u672C adapter \u7684\u63A8\u6F14\u4E0D\u4E00\u81F4,\u62D2\u7EDD\u6267\u884C;\u8BF7\u91CD\u65B0 plan" };
|
|
11840
12074
|
}
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
12075
|
+
mkdirSync7(plan.backupDir, { recursive: true });
|
|
12076
|
+
writeFileSync8(join17(plan.backupDir, basename7(write.file)), currentRaw);
|
|
12077
|
+
writeFileSync8(write.file, write.after);
|
|
11844
12078
|
return { ok: true, backupDir: plan.backupDir };
|
|
11845
12079
|
} catch (error) {
|
|
11846
12080
|
return { ok: false, error: error.message };
|
|
11847
12081
|
}
|
|
11848
12082
|
}
|
|
11849
|
-
function
|
|
12083
|
+
function nextBackupDir4(paths3) {
|
|
11850
12084
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
11851
|
-
const base =
|
|
11852
|
-
let dir =
|
|
11853
|
-
for (let n = 1;
|
|
11854
|
-
dir =
|
|
12085
|
+
const base = join17(wingmanStateRoot(paths3), "backups");
|
|
12086
|
+
let dir = join17(base, stamp);
|
|
12087
|
+
for (let n = 1; existsSync10(dir); n += 1)
|
|
12088
|
+
dir = join17(base, `${stamp}-${n}`);
|
|
11855
12089
|
return dir;
|
|
11856
12090
|
}
|
|
11857
|
-
function resolveToggle(action,
|
|
12091
|
+
function resolveToggle(action, paths3) {
|
|
11858
12092
|
if (action.kind !== "toggle") {
|
|
11859
12093
|
throw new Error(`\u672A\u77E5\u52A8\u4F5C\u79CD\u7C7B:${String(action.kind)}(v1 \u4EC5 toggle \u8D70 plan\u2192apply)`);
|
|
11860
12094
|
}
|
|
@@ -11865,10 +12099,10 @@ function resolveToggle(action, paths) {
|
|
|
11865
12099
|
const slot = m[1];
|
|
11866
12100
|
const source = m[2];
|
|
11867
12101
|
const nativeName = m[3];
|
|
11868
|
-
const file = source === "user" ?
|
|
11869
|
-
if (!
|
|
12102
|
+
const file = source === "user" ? join17(paths3.codexHome, "config.toml") : join17(paths3.projectDir, ".codex", "config.toml");
|
|
12103
|
+
if (!existsSync10(file))
|
|
11870
12104
|
throw new Error(`itemId \u627E\u4E0D\u5230:\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728(${file})`);
|
|
11871
|
-
const before =
|
|
12105
|
+
const before = readFileSync10(file, "utf8");
|
|
11872
12106
|
let table;
|
|
11873
12107
|
try {
|
|
11874
12108
|
table = parse3(before);
|
|
@@ -12089,15 +12323,15 @@ function verifyEdit(table, edit, file) {
|
|
|
12089
12323
|
throw new Error(`\u7F16\u8F91\u7ED3\u679C\u4E0E\u671F\u671B\u7684\u6700\u5C0F\u53D8\u66F4\u4E0D\u4E00\u81F4,\u62D2\u7EDD\u5199\u5165(${file})`);
|
|
12090
12324
|
}
|
|
12091
12325
|
}
|
|
12092
|
-
function collectCorpus(
|
|
12326
|
+
function collectCorpus(paths3) {
|
|
12093
12327
|
const candidates = [
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
...listFilesRecursive(
|
|
12328
|
+
join17(paths3.codexHome, "AGENTS.md"),
|
|
12329
|
+
join17(paths3.projectDir, "AGENTS.md"),
|
|
12330
|
+
join17(paths3.codexHome, "config.toml"),
|
|
12331
|
+
join17(paths3.projectDir, ".codex", "config.toml"),
|
|
12332
|
+
join17(paths3.codexHome, "hooks.json"),
|
|
12333
|
+
join17(paths3.projectDir, ".codex", "hooks.json"),
|
|
12334
|
+
...listFilesRecursive(join17(paths3.codexHome, "prompts"))
|
|
12101
12335
|
];
|
|
12102
12336
|
const sources = [];
|
|
12103
12337
|
for (const file of candidates) {
|
|
@@ -12107,7 +12341,7 @@ function collectCorpus(paths) {
|
|
|
12107
12341
|
} catch {
|
|
12108
12342
|
continue;
|
|
12109
12343
|
}
|
|
12110
|
-
sources.push({ file, text:
|
|
12344
|
+
sources.push({ file, text: readFileSync10(file, "utf8") });
|
|
12111
12345
|
}
|
|
12112
12346
|
return sources;
|
|
12113
12347
|
}
|
|
@@ -12120,7 +12354,7 @@ function listFilesRecursive(dir) {
|
|
|
12120
12354
|
}
|
|
12121
12355
|
const files = [];
|
|
12122
12356
|
for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
12123
|
-
const path =
|
|
12357
|
+
const path = join17(dir, entry.name);
|
|
12124
12358
|
if (entry.isDirectory())
|
|
12125
12359
|
files.push(...listFilesRecursive(path));
|
|
12126
12360
|
else if (entry.isFile())
|
|
@@ -12187,17 +12421,17 @@ var init_actions2 = __esm({
|
|
|
12187
12421
|
|
|
12188
12422
|
// packages/adapter-codex/dist/hooks.js
|
|
12189
12423
|
import { spawnSync } from "node:child_process";
|
|
12190
|
-
import { existsSync as
|
|
12191
|
-
import { basename as
|
|
12424
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync11, realpathSync, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
12425
|
+
import { basename as basename8, dirname as dirname12, join as join18 } from "node:path";
|
|
12192
12426
|
async function installHooks(port, options) {
|
|
12193
12427
|
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
12194
12428
|
throw new Error(`\u975E\u6CD5\u7AEF\u53E3:${port}`);
|
|
12195
12429
|
}
|
|
12196
|
-
const
|
|
12197
|
-
const root = wingmanStateRoot(
|
|
12198
|
-
const scriptPath =
|
|
12199
|
-
const configPath =
|
|
12200
|
-
const raw =
|
|
12430
|
+
const paths3 = resolvePaths(options);
|
|
12431
|
+
const root = wingmanStateRoot(paths3);
|
|
12432
|
+
const scriptPath = join18(root, FORWARD_SCRIPT_NAME);
|
|
12433
|
+
const configPath = join18(paths3.codexHome, "config.toml");
|
|
12434
|
+
const raw = existsSync11(configPath) ? readFileSync11(configPath) : void 0;
|
|
12201
12435
|
const text = raw?.toString("utf8") ?? "";
|
|
12202
12436
|
const { before, after, remainder, block } = splitManagedBlock(text, configPath);
|
|
12203
12437
|
const lineEnding = preferredLineEnding(text);
|
|
@@ -12206,8 +12440,8 @@ async function installHooks(port, options) {
|
|
|
12206
12440
|
if (block !== void 0 && knownBlock === void 0) {
|
|
12207
12441
|
throw new Error(`Wingman Codex hook \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\u6216\u6B8B\u7F3A(${configPath}),\u62D2\u7EDD\u8C0E\u62A5\u63A5\u7EBF\u6210\u529F;\u8BF7\u5148\u4ECE <wingman\u6839>/backups/ \u6062\u590D\u5B8C\u6574\u5757,\u6216\u4EBA\u5DE5\u6838\u5BF9\u540E\u79FB\u9664\u8BE5\u53D7\u7BA1\u5757\u518D\u91CD\u65B0\u5B89\u88C5\u5E76\u4FE1\u4EFB`);
|
|
12208
12442
|
}
|
|
12209
|
-
|
|
12210
|
-
|
|
12443
|
+
mkdirSync8(root, { recursive: true });
|
|
12444
|
+
writeFileSync9(scriptPath, FORWARD_SCRIPT);
|
|
12211
12445
|
const statePath2 = hooksStatePath(root);
|
|
12212
12446
|
const prior = readState5(statePath2);
|
|
12213
12447
|
if (knownBlock !== void 0 && knownBlock.state === void 0) {
|
|
@@ -12236,7 +12470,7 @@ async function installHooks(port, options) {
|
|
|
12236
12470
|
...backupDir !== void 0 ? { backupDir } : {}
|
|
12237
12471
|
});
|
|
12238
12472
|
const state = hasStateOutsideBlock ? "" : knownBlock.state;
|
|
12239
|
-
|
|
12473
|
+
writeFileSync9(configPath, before + knownBlock.managedBlock + state + after);
|
|
12240
12474
|
return;
|
|
12241
12475
|
}
|
|
12242
12476
|
const original = prior?.original ?? (raw === void 0 ? { existed: false } : { existed: true, base64: raw.toString("base64") });
|
|
@@ -12252,17 +12486,17 @@ async function installHooks(port, options) {
|
|
|
12252
12486
|
let base = remainder;
|
|
12253
12487
|
if (base !== "" && !base.endsWith("\n"))
|
|
12254
12488
|
base += lineEnding;
|
|
12255
|
-
|
|
12256
|
-
|
|
12489
|
+
mkdirSync8(paths3.codexHome, { recursive: true });
|
|
12490
|
+
writeFileSync9(configPath, base + newBlock);
|
|
12257
12491
|
}
|
|
12258
12492
|
async function uninstallHooks(options) {
|
|
12259
|
-
const
|
|
12260
|
-
const root = wingmanStateRoot(
|
|
12261
|
-
const scriptPath =
|
|
12493
|
+
const paths3 = resolvePaths(options);
|
|
12494
|
+
const root = wingmanStateRoot(paths3);
|
|
12495
|
+
const scriptPath = join18(root, FORWARD_SCRIPT_NAME);
|
|
12262
12496
|
const statePath2 = hooksStatePath(root);
|
|
12263
|
-
const configPath =
|
|
12497
|
+
const configPath = join18(paths3.codexHome, "config.toml");
|
|
12264
12498
|
const state = readState5(statePath2);
|
|
12265
|
-
const raw =
|
|
12499
|
+
const raw = existsSync11(configPath) ? readFileSync11(configPath) : void 0;
|
|
12266
12500
|
if (raw !== void 0) {
|
|
12267
12501
|
const text = raw.toString("utf8");
|
|
12268
12502
|
const { before, after, remainder, block } = splitManagedBlock(text, configPath);
|
|
@@ -12275,34 +12509,34 @@ async function uninstallHooks(options) {
|
|
|
12275
12509
|
const preservedState = hasHooksState(remainder) ? "" : knownBlock.state ?? "";
|
|
12276
12510
|
const restored = restoreTarget(before + preservedState + after, state);
|
|
12277
12511
|
if (restored === null)
|
|
12278
|
-
|
|
12512
|
+
rmSync6(configPath);
|
|
12279
12513
|
else
|
|
12280
|
-
|
|
12514
|
+
writeFileSync9(configPath, restored);
|
|
12281
12515
|
}
|
|
12282
12516
|
}
|
|
12283
|
-
|
|
12284
|
-
|
|
12517
|
+
rmSync6(scriptPath, { force: true });
|
|
12518
|
+
rmSync6(statePath2, { force: true });
|
|
12285
12519
|
}
|
|
12286
|
-
function hasManagedHooks2(
|
|
12287
|
-
const configPath =
|
|
12288
|
-
if (!
|
|
12520
|
+
function hasManagedHooks2(paths3) {
|
|
12521
|
+
const configPath = join18(paths3.codexHome, "config.toml");
|
|
12522
|
+
if (!existsSync11(configPath))
|
|
12289
12523
|
return false;
|
|
12290
12524
|
try {
|
|
12291
|
-
const { block } = splitManagedBlock(
|
|
12292
|
-
return block !== void 0 && inspectManagedBlock(block,
|
|
12525
|
+
const { block } = splitManagedBlock(readFileSync11(configPath, "utf8"), configPath);
|
|
12526
|
+
return block !== void 0 && inspectManagedBlock(block, join18(wingmanStateRoot(paths3), FORWARD_SCRIPT_NAME)) !== void 0;
|
|
12293
12527
|
} catch {
|
|
12294
12528
|
return false;
|
|
12295
12529
|
}
|
|
12296
12530
|
}
|
|
12297
12531
|
function feedbackSignalsCodex(options) {
|
|
12298
|
-
const
|
|
12299
|
-
const configPath =
|
|
12532
|
+
const paths3 = resolvePaths(options);
|
|
12533
|
+
const configPath = join18(paths3.codexHome, "config.toml");
|
|
12300
12534
|
const wiredEvents = [];
|
|
12301
|
-
if (
|
|
12535
|
+
if (existsSync11(configPath)) {
|
|
12302
12536
|
try {
|
|
12303
|
-
const { block } = splitManagedBlock(
|
|
12537
|
+
const { block } = splitManagedBlock(readFileSync11(configPath, "utf8"), configPath);
|
|
12304
12538
|
if (block !== void 0) {
|
|
12305
|
-
const knownBlock = inspectManagedBlock(block,
|
|
12539
|
+
const knownBlock = inspectManagedBlock(block, join18(wingmanStateRoot(paths3), FORWARD_SCRIPT_NAME));
|
|
12306
12540
|
const hooks = knownBlock === void 0 ? void 0 : parse3(normalizeLineEndings(knownBlock.managedBlock)).hooks;
|
|
12307
12541
|
if (isTable(hooks)) {
|
|
12308
12542
|
for (const [event, groups] of Object.entries(hooks)) {
|
|
@@ -12343,7 +12577,7 @@ function restoreTarget(remainder, state) {
|
|
|
12343
12577
|
}
|
|
12344
12578
|
function resolveNodeExecutable(probe = {}) {
|
|
12345
12579
|
const execPath = probe.execPath ?? process.execPath;
|
|
12346
|
-
const exists = probe.exists ??
|
|
12580
|
+
const exists = probe.exists ?? existsSync11;
|
|
12347
12581
|
let executable = isNodeExecutable(execPath) ? execPath : void 0;
|
|
12348
12582
|
if (executable === void 0) {
|
|
12349
12583
|
const loginShellWhich = probe.loginShellWhich ?? defaultLoginShellWhich;
|
|
@@ -12390,13 +12624,13 @@ function defaultRealpath(path) {
|
|
|
12390
12624
|
}
|
|
12391
12625
|
}
|
|
12392
12626
|
function defaultLoginShellWhich(shell) {
|
|
12393
|
-
const
|
|
12627
|
+
const result5 = spawnSync(shell, ["-lc", "command -v node"], {
|
|
12394
12628
|
encoding: "utf8",
|
|
12395
12629
|
timeout: 3e3
|
|
12396
12630
|
});
|
|
12397
|
-
if (
|
|
12631
|
+
if (result5.error !== void 0)
|
|
12398
12632
|
return void 0;
|
|
12399
|
-
return
|
|
12633
|
+
return result5.stdout.trim() || void 0;
|
|
12400
12634
|
}
|
|
12401
12635
|
function buildManagedBlock(scriptPath, nodeExecutable = "node") {
|
|
12402
12636
|
return buildManagedBlockForCommand(`${nodeExecutable} "${scriptPath}"`);
|
|
@@ -12548,28 +12782,28 @@ function hasHooksState(text) {
|
|
|
12548
12782
|
}
|
|
12549
12783
|
function backupFile(root, filePath, contents) {
|
|
12550
12784
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
12551
|
-
let dir =
|
|
12552
|
-
for (let n = 1;
|
|
12553
|
-
dir =
|
|
12554
|
-
|
|
12555
|
-
|
|
12785
|
+
let dir = join18(root, "backups", stamp);
|
|
12786
|
+
for (let n = 1; existsSync11(dir); n += 1)
|
|
12787
|
+
dir = join18(root, "backups", `${stamp}-${n}`);
|
|
12788
|
+
mkdirSync8(dir, { recursive: true });
|
|
12789
|
+
writeFileSync9(join18(dir, basename8(filePath)), contents);
|
|
12556
12790
|
return dir;
|
|
12557
12791
|
}
|
|
12558
12792
|
function hooksStatePath(root) {
|
|
12559
|
-
return
|
|
12793
|
+
return join18(root, "state", "codex-hooks.json");
|
|
12560
12794
|
}
|
|
12561
12795
|
function readState5(statePath2) {
|
|
12562
|
-
if (!
|
|
12796
|
+
if (!existsSync11(statePath2))
|
|
12563
12797
|
return void 0;
|
|
12564
12798
|
try {
|
|
12565
|
-
return JSON.parse(
|
|
12799
|
+
return JSON.parse(readFileSync11(statePath2, "utf8"));
|
|
12566
12800
|
} catch {
|
|
12567
12801
|
return void 0;
|
|
12568
12802
|
}
|
|
12569
12803
|
}
|
|
12570
12804
|
function writeState5(statePath2, state) {
|
|
12571
|
-
|
|
12572
|
-
|
|
12805
|
+
mkdirSync8(dirname12(statePath2), { recursive: true });
|
|
12806
|
+
writeFileSync9(statePath2, `${JSON.stringify(state, null, 2)}
|
|
12573
12807
|
`);
|
|
12574
12808
|
}
|
|
12575
12809
|
function deepEqual3(a, b) {
|
|
@@ -12725,15 +12959,15 @@ process.stdin.on('end', async () => {
|
|
|
12725
12959
|
});
|
|
12726
12960
|
|
|
12727
12961
|
// packages/adapter-codex/dist/scan.js
|
|
12728
|
-
import { existsSync as
|
|
12729
|
-
import { dirname as
|
|
12962
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync4 } from "node:fs";
|
|
12963
|
+
import { dirname as dirname13, isAbsolute as isAbsolute3, join as join19, resolve as resolve7 } from "node:path";
|
|
12730
12964
|
async function detect(options) {
|
|
12731
12965
|
const { codexHome } = resolvePaths(options);
|
|
12732
|
-
return { installed:
|
|
12966
|
+
return { installed: existsSync12(codexHome) };
|
|
12733
12967
|
}
|
|
12734
12968
|
async function scan(options) {
|
|
12735
|
-
const
|
|
12736
|
-
const layers = loadConfigLayers(
|
|
12969
|
+
const paths3 = resolvePaths(options);
|
|
12970
|
+
const layers = loadConfigLayers(paths3);
|
|
12737
12971
|
const slots = {
|
|
12738
12972
|
base: [],
|
|
12739
12973
|
rules: [],
|
|
@@ -12742,14 +12976,14 @@ async function scan(options) {
|
|
|
12742
12976
|
gates: [],
|
|
12743
12977
|
history: []
|
|
12744
12978
|
};
|
|
12745
|
-
collectRules(slots.rules,
|
|
12979
|
+
collectRules(slots.rules, paths3, layers);
|
|
12746
12980
|
for (const layer of layers) {
|
|
12747
12981
|
collectBase(slots.base, layer);
|
|
12748
12982
|
collectSkills(slots.skills, layer);
|
|
12749
12983
|
collectTools(slots.tools, layer);
|
|
12750
12984
|
collectGates(slots.gates, layer);
|
|
12751
12985
|
}
|
|
12752
|
-
collectHistory(slots.history,
|
|
12986
|
+
collectHistory(slots.history, paths3, layers);
|
|
12753
12987
|
assertUniqueIds(slots);
|
|
12754
12988
|
return {
|
|
12755
12989
|
harness: "codex",
|
|
@@ -12759,21 +12993,21 @@ async function scan(options) {
|
|
|
12759
12993
|
// actions:M3 起 toggle(plan→apply)/scan_references(命中随 plan)已落地;
|
|
12760
12994
|
// open_editor 是面板用 nativePath 跳转的即时动作,无需 adapter 方法
|
|
12761
12995
|
capabilities: {
|
|
12762
|
-
live: hasManagedHooks2(
|
|
12996
|
+
live: hasManagedHooks2(paths3) ? "push" : "none",
|
|
12763
12997
|
actions: ["toggle", "open_editor", "scan_references"]
|
|
12764
12998
|
}
|
|
12765
12999
|
};
|
|
12766
13000
|
}
|
|
12767
|
-
function loadConfigLayers(
|
|
13001
|
+
function loadConfigLayers(paths3) {
|
|
12768
13002
|
const candidates = [
|
|
12769
|
-
["user",
|
|
12770
|
-
["project",
|
|
13003
|
+
["user", join19(paths3.codexHome, "config.toml")],
|
|
13004
|
+
["project", join19(paths3.projectDir, ".codex", "config.toml")]
|
|
12771
13005
|
];
|
|
12772
13006
|
const layers = [];
|
|
12773
13007
|
for (const [source, path] of candidates) {
|
|
12774
13008
|
if (fileSize(path) === void 0)
|
|
12775
13009
|
continue;
|
|
12776
|
-
const text =
|
|
13010
|
+
const text = readFileSync12(path, "utf8");
|
|
12777
13011
|
try {
|
|
12778
13012
|
layers.push({ source, path, table: parse3(text) });
|
|
12779
13013
|
} catch (error) {
|
|
@@ -12782,10 +13016,10 @@ function loadConfigLayers(paths) {
|
|
|
12782
13016
|
}
|
|
12783
13017
|
return layers;
|
|
12784
13018
|
}
|
|
12785
|
-
function collectRules(out,
|
|
13019
|
+
function collectRules(out, paths3, layers) {
|
|
12786
13020
|
const agentsChain = [
|
|
12787
|
-
["user",
|
|
12788
|
-
["project",
|
|
13021
|
+
["user", join19(paths3.codexHome, "AGENTS.md")],
|
|
13022
|
+
["project", join19(paths3.projectDir, "AGENTS.md")]
|
|
12789
13023
|
];
|
|
12790
13024
|
for (const [source, file] of agentsChain) {
|
|
12791
13025
|
const size = fileSize(file);
|
|
@@ -12820,7 +13054,7 @@ function collectRules(out, paths, layers) {
|
|
|
12820
13054
|
}
|
|
12821
13055
|
const instructionsFile = layer.table.model_instructions_file;
|
|
12822
13056
|
if (typeof instructionsFile === "string") {
|
|
12823
|
-
const filePath = isAbsolute3(instructionsFile) ? instructionsFile :
|
|
13057
|
+
const filePath = isAbsolute3(instructionsFile) ? instructionsFile : resolve7(dirname13(layer.path), instructionsFile);
|
|
12824
13058
|
const item = {
|
|
12825
13059
|
id: `codex:rules:${layer.source}:model_instructions_file`,
|
|
12826
13060
|
slot: "rules",
|
|
@@ -12919,8 +13153,8 @@ function collectGates(out, layer) {
|
|
|
12919
13153
|
});
|
|
12920
13154
|
}
|
|
12921
13155
|
}
|
|
12922
|
-
function collectHistory(out,
|
|
12923
|
-
const historyFile =
|
|
13156
|
+
function collectHistory(out, paths3, layers) {
|
|
13157
|
+
const historyFile = join19(paths3.codexHome, "history.jsonl");
|
|
12924
13158
|
const historyBytes = fileSize(historyFile);
|
|
12925
13159
|
if (historyBytes !== void 0) {
|
|
12926
13160
|
out.push({
|
|
@@ -12935,7 +13169,7 @@ function collectHistory(out, paths, layers) {
|
|
|
12935
13169
|
});
|
|
12936
13170
|
}
|
|
12937
13171
|
const configured = layers.find((layer) => layer.source === "user")?.table.log_dir;
|
|
12938
|
-
const logDir = typeof configured === "string" ? expandPath(configured,
|
|
13172
|
+
const logDir = typeof configured === "string" ? expandPath(configured, paths3) : join19(paths3.codexHome, "log");
|
|
12939
13173
|
if (isDirectory(logDir)) {
|
|
12940
13174
|
out.push({
|
|
12941
13175
|
id: "codex:history:user:log_dir",
|
|
@@ -12949,10 +13183,10 @@ function collectHistory(out, paths, layers) {
|
|
|
12949
13183
|
});
|
|
12950
13184
|
}
|
|
12951
13185
|
}
|
|
12952
|
-
function expandPath(value,
|
|
13186
|
+
function expandPath(value, paths3) {
|
|
12953
13187
|
if (value === "~" || value.startsWith("~/"))
|
|
12954
|
-
return
|
|
12955
|
-
return isAbsolute3(value) ? value :
|
|
13188
|
+
return join19(paths3.homeDir, value.slice(2));
|
|
13189
|
+
return isAbsolute3(value) ? value : resolve7(paths3.codexHome, value);
|
|
12956
13190
|
}
|
|
12957
13191
|
function assertUniqueIds(slots) {
|
|
12958
13192
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -12983,7 +13217,7 @@ function isDirectory(path) {
|
|
|
12983
13217
|
function directoryBytes(dir) {
|
|
12984
13218
|
let total = 0;
|
|
12985
13219
|
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
12986
|
-
const entryPath =
|
|
13220
|
+
const entryPath = join19(dir, entry.name);
|
|
12987
13221
|
if (entry.isDirectory())
|
|
12988
13222
|
total += directoryBytes(entryPath);
|
|
12989
13223
|
else if (entry.isFile())
|
|
@@ -13005,54 +13239,54 @@ var init_scan2 = __esm({
|
|
|
13005
13239
|
});
|
|
13006
13240
|
|
|
13007
13241
|
// packages/adapter-codex/dist/protocol.js
|
|
13008
|
-
import { existsSync as
|
|
13009
|
-
import { basename as
|
|
13242
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync13, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
|
|
13243
|
+
import { basename as basename9, dirname as dirname14, join as join20, resolve as resolve8 } from "node:path";
|
|
13010
13244
|
function protocolStatusCodex(options) {
|
|
13011
|
-
const
|
|
13012
|
-
if (!
|
|
13013
|
-
return status2(
|
|
13245
|
+
const paths3 = resolveOptions3(options);
|
|
13246
|
+
if (!existsSync13(paths3.targetPath))
|
|
13247
|
+
return status2(paths3.targetPath, "not_installed");
|
|
13014
13248
|
try {
|
|
13015
|
-
const file = readAgents2(
|
|
13249
|
+
const file = readAgents2(paths3.targetPath);
|
|
13016
13250
|
if (file.identity === void 0)
|
|
13017
|
-
return status2(
|
|
13251
|
+
return status2(paths3.targetPath, "not_installed");
|
|
13018
13252
|
const state = stateForIdentity3(file.identity);
|
|
13019
|
-
return status2(
|
|
13253
|
+
return status2(paths3.targetPath, state, file.identity);
|
|
13020
13254
|
} catch (error) {
|
|
13021
|
-
return status2(
|
|
13255
|
+
return status2(paths3.targetPath, "invalid", void 0, error.message);
|
|
13022
13256
|
}
|
|
13023
13257
|
}
|
|
13024
13258
|
function installProtocolCodex(options) {
|
|
13025
|
-
const
|
|
13026
|
-
const existing =
|
|
13259
|
+
const paths3 = resolveOptions3(options);
|
|
13260
|
+
const existing = existsSync13(paths3.targetPath) ? readAgents2(paths3.targetPath) : void 0;
|
|
13027
13261
|
const previousState = stateForIdentity3(existing?.identity);
|
|
13028
13262
|
if (previousState === "installed") {
|
|
13029
|
-
return
|
|
13263
|
+
return result4(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true);
|
|
13030
13264
|
}
|
|
13031
13265
|
if (previousState === "modified")
|
|
13032
|
-
throw modifiedError3(
|
|
13266
|
+
throw modifiedError3(paths3.targetPath, "\u5B89\u88C5");
|
|
13033
13267
|
const before = existing?.text ?? "";
|
|
13034
13268
|
const lineEnding = preferredMarkdownLineEnding(before);
|
|
13035
13269
|
const block = buildPlanProtocolBlock().replaceAll("\n", lineEnding);
|
|
13036
13270
|
const after = existing?.split.block ? existing.split.before + block + existing.split.after : appendBlock2(before, block, lineEnding);
|
|
13037
|
-
const installedRemainder = splitPlanProtocolBlock(after,
|
|
13038
|
-
const backupDir =
|
|
13039
|
-
if (!
|
|
13040
|
-
const prior = readState6(
|
|
13041
|
-
|
|
13042
|
-
writeState6(
|
|
13271
|
+
const installedRemainder = splitPlanProtocolBlock(after, paths3.targetPath).remainder;
|
|
13272
|
+
const backupDir = nextBackupDir5(paths3.homeDir);
|
|
13273
|
+
if (!paths3.dryRun) {
|
|
13274
|
+
const prior = readState6(paths3.statePath, paths3.targetPath);
|
|
13275
|
+
backupTarget4(backupDir, paths3.targetPath, existing?.bytes);
|
|
13276
|
+
writeState6(paths3.statePath, {
|
|
13043
13277
|
version: 1,
|
|
13044
|
-
projectDir:
|
|
13045
|
-
targetPath:
|
|
13278
|
+
projectDir: paths3.projectDir,
|
|
13279
|
+
targetPath: paths3.targetPath,
|
|
13046
13280
|
protocolVersion: PLAN_PROTOCOL_VERSION,
|
|
13047
13281
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13048
13282
|
backupDir,
|
|
13049
|
-
installedRemainderSha256: sha256Hex(installedRemainder),
|
|
13283
|
+
installedRemainderSha256: previousState === "outdated" && prior !== void 0 ? prior.installedRemainderSha256 : sha256Hex(installedRemainder),
|
|
13050
13284
|
original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
|
|
13051
13285
|
});
|
|
13052
|
-
|
|
13286
|
+
writeFileSync10(paths3.targetPath, after);
|
|
13053
13287
|
}
|
|
13054
13288
|
return {
|
|
13055
|
-
...
|
|
13289
|
+
...result4(paths3.targetPath, "install", true, previousState, before, true),
|
|
13056
13290
|
state: "installed",
|
|
13057
13291
|
version: PLAN_PROTOCOL_VERSION,
|
|
13058
13292
|
after,
|
|
@@ -13061,33 +13295,33 @@ function installProtocolCodex(options) {
|
|
|
13061
13295
|
};
|
|
13062
13296
|
}
|
|
13063
13297
|
function uninstallProtocolCodex(options) {
|
|
13064
|
-
const
|
|
13065
|
-
if (!
|
|
13066
|
-
return
|
|
13298
|
+
const paths3 = resolveOptions3(options);
|
|
13299
|
+
if (!existsSync13(paths3.targetPath)) {
|
|
13300
|
+
return result4(paths3.targetPath, "uninstall", false, "not_installed", "", false);
|
|
13067
13301
|
}
|
|
13068
|
-
const existing = readAgents2(
|
|
13302
|
+
const existing = readAgents2(paths3.targetPath);
|
|
13069
13303
|
if (existing.identity === void 0) {
|
|
13070
|
-
return
|
|
13304
|
+
return result4(paths3.targetPath, "uninstall", false, "not_installed", existing.text, true);
|
|
13071
13305
|
}
|
|
13072
13306
|
const previousState = stateForIdentity3(existing.identity);
|
|
13073
13307
|
if (previousState === "modified")
|
|
13074
|
-
throw modifiedError3(
|
|
13075
|
-
const state = readState6(
|
|
13308
|
+
throw modifiedError3(paths3.targetPath, "\u5378\u8F7D");
|
|
13309
|
+
const state = readState6(paths3.statePath, paths3.targetPath);
|
|
13076
13310
|
const canRestore = state !== void 0 && sha256Hex(existing.split.remainder) === state.installedRemainderSha256;
|
|
13077
13311
|
const restored = canRestore ? originalBytes2(state) : void 0;
|
|
13078
13312
|
const deleteTarget = canRestore ? state?.original.existed === false : existing.split.remainder.trim() === "";
|
|
13079
13313
|
const after = deleteTarget ? "" : restored?.toString("utf8") ?? existing.split.remainder;
|
|
13080
|
-
const backupDir =
|
|
13081
|
-
if (!
|
|
13082
|
-
|
|
13314
|
+
const backupDir = nextBackupDir5(paths3.homeDir);
|
|
13315
|
+
if (!paths3.dryRun) {
|
|
13316
|
+
backupTarget4(backupDir, paths3.targetPath, existing.bytes);
|
|
13083
13317
|
if (deleteTarget)
|
|
13084
|
-
|
|
13318
|
+
rmSync7(paths3.targetPath, { force: true });
|
|
13085
13319
|
else
|
|
13086
|
-
|
|
13087
|
-
|
|
13320
|
+
writeFileSync10(paths3.targetPath, restored ?? existing.split.remainder);
|
|
13321
|
+
rmSync7(paths3.statePath, { force: true });
|
|
13088
13322
|
}
|
|
13089
13323
|
return {
|
|
13090
|
-
...
|
|
13324
|
+
...result4(paths3.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
|
|
13091
13325
|
state: "not_installed",
|
|
13092
13326
|
message: canRestore ? SHARED_MESSAGE2 : `${SHARED_MESSAGE2}\uFF1B\u5DF2\u79FB\u9664\u5757\u5E76\u4FDD\u7559\u7528\u6237\u6539\u52A8`,
|
|
13093
13327
|
after,
|
|
@@ -13098,15 +13332,16 @@ function uninstallProtocolCodex(options) {
|
|
|
13098
13332
|
}
|
|
13099
13333
|
function resolveOptions3(options) {
|
|
13100
13334
|
const base = resolvePaths(options);
|
|
13101
|
-
const homeDir =
|
|
13102
|
-
const projectDir =
|
|
13103
|
-
const targetPath2 =
|
|
13104
|
-
const statePath2 =
|
|
13335
|
+
const homeDir = resolve8(base.homeDir);
|
|
13336
|
+
const projectDir = resolve8(base.projectDir);
|
|
13337
|
+
const targetPath2 = join20(projectDir, "AGENTS.md");
|
|
13338
|
+
const statePath2 = join20(wingmanStateRoot({ ...base, homeDir, projectDir }), "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`);
|
|
13105
13339
|
return { homeDir, projectDir, targetPath: targetPath2, statePath: statePath2, dryRun: options?.dryRun ?? false };
|
|
13106
13340
|
}
|
|
13107
13341
|
function readAgents2(targetPath2) {
|
|
13108
|
-
const bytes =
|
|
13109
|
-
|
|
13342
|
+
const bytes = readFileSync13(targetPath2);
|
|
13343
|
+
decodeUtf8Strict2(bytes, targetPath2);
|
|
13344
|
+
const text = bytes.toString("utf8");
|
|
13110
13345
|
let split;
|
|
13111
13346
|
try {
|
|
13112
13347
|
split = splitPlanProtocolBlock(text, targetPath2);
|
|
@@ -13135,7 +13370,7 @@ function stateForIdentity3(identity) {
|
|
|
13135
13370
|
return "not_installed";
|
|
13136
13371
|
if (identity.kind === "current")
|
|
13137
13372
|
return "installed";
|
|
13138
|
-
if (identity.kind === "
|
|
13373
|
+
if (identity.kind === "outdated")
|
|
13139
13374
|
return "outdated";
|
|
13140
13375
|
return "modified";
|
|
13141
13376
|
}
|
|
@@ -13150,7 +13385,7 @@ function status2(targetPath2, state, identity, reason) {
|
|
|
13150
13385
|
...reason !== void 0 ? { reason } : {}
|
|
13151
13386
|
};
|
|
13152
13387
|
}
|
|
13153
|
-
function
|
|
13388
|
+
function result4(targetPath2, operation, changed, previousState, before, afterExists) {
|
|
13154
13389
|
return {
|
|
13155
13390
|
...status2(targetPath2, previousState),
|
|
13156
13391
|
operation,
|
|
@@ -13166,32 +13401,32 @@ function result3(targetPath2, operation, changed, previousState, before, afterEx
|
|
|
13166
13401
|
function modifiedError3(targetPath2, operation) {
|
|
13167
13402
|
return new Error(`${targetPath2}: \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
|
|
13168
13403
|
}
|
|
13169
|
-
function
|
|
13404
|
+
function nextBackupDir5(homeDir) {
|
|
13170
13405
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
13171
|
-
const root =
|
|
13172
|
-
let dir =
|
|
13173
|
-
for (let n = 2;
|
|
13174
|
-
dir =
|
|
13406
|
+
const root = join20(homeDir, ".wingman", "backups");
|
|
13407
|
+
let dir = join20(root, stamp);
|
|
13408
|
+
for (let n = 2; existsSync13(dir); n += 1)
|
|
13409
|
+
dir = join20(root, `${stamp}-${n}`);
|
|
13175
13410
|
return dir;
|
|
13176
13411
|
}
|
|
13177
|
-
function
|
|
13178
|
-
|
|
13412
|
+
function backupTarget4(backupDir, targetPath2, bytes) {
|
|
13413
|
+
mkdirSync9(backupDir, { recursive: true });
|
|
13179
13414
|
if (bytes !== void 0)
|
|
13180
|
-
|
|
13415
|
+
writeFileSync10(join20(backupDir, basename9(targetPath2)), bytes);
|
|
13181
13416
|
}
|
|
13182
13417
|
function readState6(statePath2, targetPath2) {
|
|
13183
|
-
if (!
|
|
13418
|
+
if (!existsSync13(statePath2))
|
|
13184
13419
|
return void 0;
|
|
13185
13420
|
try {
|
|
13186
|
-
const value = JSON.parse(
|
|
13421
|
+
const value = JSON.parse(readFileSync13(statePath2, "utf8"));
|
|
13187
13422
|
return value.version === 1 && value.targetPath === targetPath2 ? value : void 0;
|
|
13188
13423
|
} catch {
|
|
13189
13424
|
return void 0;
|
|
13190
13425
|
}
|
|
13191
13426
|
}
|
|
13192
13427
|
function writeState6(statePath2, state) {
|
|
13193
|
-
|
|
13194
|
-
|
|
13428
|
+
mkdirSync9(dirname14(statePath2), { recursive: true });
|
|
13429
|
+
writeFileSync10(statePath2, `${JSON.stringify(state, null, 2)}
|
|
13195
13430
|
`);
|
|
13196
13431
|
}
|
|
13197
13432
|
function originalBytes2(state) {
|
|
@@ -13207,6 +13442,33 @@ var init_protocol3 = __esm({
|
|
|
13207
13442
|
}
|
|
13208
13443
|
});
|
|
13209
13444
|
|
|
13445
|
+
// packages/adapter-codex/dist/protocol-user.js
|
|
13446
|
+
import { homedir as homedir12 } from "node:os";
|
|
13447
|
+
import { join as join21, resolve as resolve9 } from "node:path";
|
|
13448
|
+
function paths2(options) {
|
|
13449
|
+
const homeDir = resolve9(options?.homeDir ?? homedir12());
|
|
13450
|
+
return {
|
|
13451
|
+
homeDir,
|
|
13452
|
+
targetPath: join21(homeDir, ".codex", "AGENTS.md"),
|
|
13453
|
+
dryRun: options?.dryRun ?? false
|
|
13454
|
+
};
|
|
13455
|
+
}
|
|
13456
|
+
function protocolStatusCodexUser(options) {
|
|
13457
|
+
return { harness: "codex", ...statusPlanProtocolUser(paths2(options).targetPath) };
|
|
13458
|
+
}
|
|
13459
|
+
function installProtocolCodexUser(options) {
|
|
13460
|
+
return { harness: "codex", ...installPlanProtocolUser(paths2(options)) };
|
|
13461
|
+
}
|
|
13462
|
+
function uninstallProtocolCodexUser(options) {
|
|
13463
|
+
return { harness: "codex", ...uninstallPlanProtocolUser(paths2(options)) };
|
|
13464
|
+
}
|
|
13465
|
+
var init_protocol_user2 = __esm({
|
|
13466
|
+
"packages/adapter-codex/dist/protocol-user.js"() {
|
|
13467
|
+
"use strict";
|
|
13468
|
+
init_dist();
|
|
13469
|
+
}
|
|
13470
|
+
});
|
|
13471
|
+
|
|
13210
13472
|
// packages/adapter-codex/dist/index.js
|
|
13211
13473
|
var dist_exports3 = {};
|
|
13212
13474
|
__export(dist_exports3, {
|
|
@@ -13214,9 +13476,12 @@ __export(dist_exports3, {
|
|
|
13214
13476
|
createAdapter: () => createAdapter3,
|
|
13215
13477
|
feedbackSignals: () => feedbackSignalsCodex,
|
|
13216
13478
|
installProtocolCodex: () => installProtocolCodex,
|
|
13479
|
+
installProtocolCodexUser: () => installProtocolCodexUser,
|
|
13217
13480
|
protocolStatusCodex: () => protocolStatusCodex,
|
|
13481
|
+
protocolStatusCodexUser: () => protocolStatusCodexUser,
|
|
13218
13482
|
resolveNodeExecutable: () => resolveNodeExecutable,
|
|
13219
|
-
uninstallProtocolCodex: () => uninstallProtocolCodex
|
|
13483
|
+
uninstallProtocolCodex: () => uninstallProtocolCodex,
|
|
13484
|
+
uninstallProtocolCodexUser: () => uninstallProtocolCodexUser
|
|
13220
13485
|
});
|
|
13221
13486
|
function createAdapter3(_options) {
|
|
13222
13487
|
return {
|
|
@@ -13237,23 +13502,24 @@ var init_dist5 = __esm({
|
|
|
13237
13502
|
init_scan2();
|
|
13238
13503
|
init_hooks3();
|
|
13239
13504
|
init_protocol3();
|
|
13505
|
+
init_protocol_user2();
|
|
13240
13506
|
}
|
|
13241
13507
|
});
|
|
13242
13508
|
|
|
13243
13509
|
// apps/cli/dist/main.js
|
|
13244
13510
|
init_dist2();
|
|
13245
13511
|
init_dist();
|
|
13246
|
-
import { readFileSync as
|
|
13247
|
-
import { homedir as
|
|
13248
|
-
import { dirname as
|
|
13512
|
+
import { readFileSync as readFileSync19 } from "node:fs";
|
|
13513
|
+
import { homedir as homedir16 } from "node:os";
|
|
13514
|
+
import { dirname as dirname20, resolve as resolve14 } from "node:path";
|
|
13249
13515
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13250
13516
|
|
|
13251
13517
|
// packages/fixtures/dist/index.js
|
|
13252
|
-
import { dirname as
|
|
13518
|
+
import { dirname as dirname5, join as join6 } from "node:path";
|
|
13253
13519
|
import { fileURLToPath } from "node:url";
|
|
13254
|
-
var fixturesRoot =
|
|
13520
|
+
var fixturesRoot = join6(dirname5(dirname5(fileURLToPath(import.meta.url))), "data");
|
|
13255
13521
|
function fixturePath(...segments) {
|
|
13256
|
-
return
|
|
13522
|
+
return join6(fixturesRoot, ...segments);
|
|
13257
13523
|
}
|
|
13258
13524
|
|
|
13259
13525
|
// packages/live/dist/receiver.js
|
|
@@ -13373,7 +13639,7 @@ function isHookPayload(value) {
|
|
|
13373
13639
|
}
|
|
13374
13640
|
var HOOK_BODY_LIMIT = 1024 * 1024;
|
|
13375
13641
|
function readBody(req) {
|
|
13376
|
-
return new Promise((
|
|
13642
|
+
return new Promise((resolve15, reject) => {
|
|
13377
13643
|
const chunks = [];
|
|
13378
13644
|
let size = 0;
|
|
13379
13645
|
req.on("data", (chunk) => {
|
|
@@ -13385,7 +13651,7 @@ function readBody(req) {
|
|
|
13385
13651
|
}
|
|
13386
13652
|
chunks.push(chunk);
|
|
13387
13653
|
});
|
|
13388
|
-
req.on("end", () =>
|
|
13654
|
+
req.on("end", () => resolve15(Buffer.concat(chunks).toString("utf8")));
|
|
13389
13655
|
req.on("error", reject);
|
|
13390
13656
|
});
|
|
13391
13657
|
}
|
|
@@ -13400,9 +13666,9 @@ function sendText(res, status3, body) {
|
|
|
13400
13666
|
|
|
13401
13667
|
// apps/cli/dist/license.js
|
|
13402
13668
|
import { verify } from "node:crypto";
|
|
13403
|
-
import { existsSync as
|
|
13669
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
13404
13670
|
import { homedir as homedir3 } from "node:os";
|
|
13405
|
-
import { join as
|
|
13671
|
+
import { join as join7 } from "node:path";
|
|
13406
13672
|
var OFFLINE_GRACE_DAYS = 14;
|
|
13407
13673
|
var PROD_PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyU4yO0SJcflt/CV77wqVxIwCkM52CYGC6qrPGP8dMME=\n-----END PUBLIC KEY-----\n";
|
|
13408
13674
|
function checkLicense(options = {}) {
|
|
@@ -13416,7 +13682,7 @@ function licenseStatus(options = {}) {
|
|
|
13416
13682
|
const home = options.homeDir ?? homedir3();
|
|
13417
13683
|
let raw;
|
|
13418
13684
|
try {
|
|
13419
|
-
raw =
|
|
13685
|
+
raw = readFileSync3(join7(home, ".wingman", "license.json"), "utf8");
|
|
13420
13686
|
} catch {
|
|
13421
13687
|
return { state: "none", detail: "\u672A\u5B89\u88C5 license(anatomy \u4E0E\u5B9E\u51B5\u514D\u8D39\u53EF\u7528;\u5199\u52A8\u4F5C\u9700\u8BA2\u9605)" };
|
|
13422
13688
|
}
|
|
@@ -13483,7 +13749,7 @@ function verifyEntitlement(raw, now, publicKeyPem) {
|
|
|
13483
13749
|
function nextLicenseBackupPath(licensePath, now) {
|
|
13484
13750
|
const base = `${licensePath}.bak-${now.toISOString().replaceAll(":", "-")}`;
|
|
13485
13751
|
let candidate = base;
|
|
13486
|
-
for (let index = 2;
|
|
13752
|
+
for (let index = 2; existsSync4(candidate); index++)
|
|
13487
13753
|
candidate = `${base}-${index}`;
|
|
13488
13754
|
return candidate;
|
|
13489
13755
|
}
|
|
@@ -13504,13 +13770,13 @@ function installLicense(raw, options = {}) {
|
|
|
13504
13770
|
return { ok: false, error: status3.detail };
|
|
13505
13771
|
}
|
|
13506
13772
|
}
|
|
13507
|
-
const dir =
|
|
13508
|
-
const licensePath =
|
|
13509
|
-
const tmpPath =
|
|
13773
|
+
const dir = join7(options.homeDir ?? homedir3(), ".wingman");
|
|
13774
|
+
const licensePath = join7(dir, "license.json");
|
|
13775
|
+
const tmpPath = join7(dir, `.license.json.tmp-${process.pid}`);
|
|
13510
13776
|
try {
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
if (
|
|
13777
|
+
mkdirSync3(dir, { recursive: true });
|
|
13778
|
+
writeFileSync3(tmpPath, raw);
|
|
13779
|
+
if (existsSync4(licensePath)) {
|
|
13514
13780
|
renameSync(licensePath, nextLicenseBackupPath(licensePath, options.now ?? /* @__PURE__ */ new Date()));
|
|
13515
13781
|
}
|
|
13516
13782
|
renameSync(tmpPath, licensePath);
|
|
@@ -13522,17 +13788,17 @@ function installLicense(raw, options = {}) {
|
|
|
13522
13788
|
}
|
|
13523
13789
|
|
|
13524
13790
|
// apps/cli/dist/license-refresh.js
|
|
13525
|
-
import { copyFileSync, readFileSync as
|
|
13791
|
+
import { copyFileSync, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
13526
13792
|
import { homedir as homedir4 } from "node:os";
|
|
13527
|
-
import { dirname as
|
|
13793
|
+
import { dirname as dirname6, join as join8 } from "node:path";
|
|
13528
13794
|
var DEFAULT_LICENSE_SERVER = "https://api.getwingman.dev";
|
|
13529
13795
|
async function refreshLicense(options = {}) {
|
|
13530
13796
|
const home = options.homeDir ?? homedir4();
|
|
13531
13797
|
const baseUrl = options.baseUrl ?? process.env.WINGMAN_LICENSE_SERVER ?? DEFAULT_LICENSE_SERVER;
|
|
13532
|
-
const licensePath =
|
|
13798
|
+
const licensePath = join8(home, ".wingman", "license.json");
|
|
13533
13799
|
let raw;
|
|
13534
13800
|
try {
|
|
13535
|
-
raw =
|
|
13801
|
+
raw = readFileSync4(licensePath, "utf8");
|
|
13536
13802
|
} catch {
|
|
13537
13803
|
return {
|
|
13538
13804
|
ok: false,
|
|
@@ -13602,7 +13868,7 @@ async function refreshLicense(options = {}) {
|
|
|
13602
13868
|
}
|
|
13603
13869
|
}
|
|
13604
13870
|
try {
|
|
13605
|
-
if (
|
|
13871
|
+
if (readFileSync4(licensePath, "utf8") !== raw) {
|
|
13606
13872
|
return {
|
|
13607
13873
|
ok: false,
|
|
13608
13874
|
message: "\u5237\u65B0\u671F\u95F4\u672C\u673A\u6388\u6743\u5DF2\u88AB\u66F4\u6362;\u5DF2\u4FDD\u7559\u8F83\u65B0\u7684\u6587\u4EF6,\u8BF7\u518D\u70B9\u4E00\u6B21\u5237\u65B0",
|
|
@@ -13616,9 +13882,9 @@ async function refreshLicense(options = {}) {
|
|
|
13616
13882
|
reason: "changed"
|
|
13617
13883
|
};
|
|
13618
13884
|
}
|
|
13619
|
-
const tmpPath =
|
|
13885
|
+
const tmpPath = join8(dirname6(licensePath), `.license.json.tmp-${process.pid}`);
|
|
13620
13886
|
try {
|
|
13621
|
-
|
|
13887
|
+
writeFileSync4(tmpPath, next);
|
|
13622
13888
|
copyFileSync(licensePath, nextLicenseBackupPath(licensePath, options.now ?? /* @__PURE__ */ new Date()));
|
|
13623
13889
|
renameSync2(tmpPath, licensePath);
|
|
13624
13890
|
} catch (error) {
|
|
@@ -13646,7 +13912,7 @@ init_dist5();
|
|
|
13646
13912
|
init_dist2();
|
|
13647
13913
|
init_dist();
|
|
13648
13914
|
import { readdir as readdir2 } from "node:fs/promises";
|
|
13649
|
-
import { isAbsolute as isAbsolute6, join as
|
|
13915
|
+
import { isAbsolute as isAbsolute6, join as join25, resolve as resolve11 } from "node:path";
|
|
13650
13916
|
|
|
13651
13917
|
// packages/narrative/dist/attribute.js
|
|
13652
13918
|
function extractSteps(lines2) {
|
|
@@ -13671,13 +13937,13 @@ function extractSteps(lines2) {
|
|
|
13671
13937
|
byToolUseId.set(block.id, step);
|
|
13672
13938
|
}
|
|
13673
13939
|
} else if (line.kind === "user") {
|
|
13674
|
-
for (const
|
|
13675
|
-
const step = byToolUseId.get(
|
|
13940
|
+
for (const result5 of line.toolResults) {
|
|
13941
|
+
const step = byToolUseId.get(result5.toolUseId);
|
|
13676
13942
|
if (step === void 0)
|
|
13677
13943
|
continue;
|
|
13678
13944
|
if (line.timestamp !== void 0)
|
|
13679
13945
|
step.endTs = line.timestamp;
|
|
13680
|
-
if (
|
|
13946
|
+
if (result5.isError)
|
|
13681
13947
|
step.isError = true;
|
|
13682
13948
|
}
|
|
13683
13949
|
}
|
|
@@ -13849,17 +14115,17 @@ function parseResponseItem(payload, timestamp) {
|
|
|
13849
14115
|
return call;
|
|
13850
14116
|
}
|
|
13851
14117
|
if (payload !== void 0 && (payloadType === "function_call_output" || payloadType === "custom_tool_call_output")) {
|
|
13852
|
-
const
|
|
13853
|
-
assignString(
|
|
13854
|
-
assignString(
|
|
13855
|
-
assignString(
|
|
13856
|
-
assignString(
|
|
14118
|
+
const result5 = { kind: "tool_result", resultType: payloadType };
|
|
14119
|
+
assignString(result5, "timestamp", timestamp);
|
|
14120
|
+
assignString(result5, "callId", optionalString(payload.call_id));
|
|
14121
|
+
assignString(result5, "itemId", optionalString(payload.id));
|
|
14122
|
+
assignString(result5, "turnId", extractTurnId(payload));
|
|
13857
14123
|
if (payload.output !== void 0) {
|
|
13858
|
-
|
|
14124
|
+
result5.output = payload.output;
|
|
13859
14125
|
if (codexToolResultIsError(payload.output))
|
|
13860
|
-
|
|
14126
|
+
result5.isError = true;
|
|
13861
14127
|
}
|
|
13862
|
-
return
|
|
14128
|
+
return result5;
|
|
13863
14129
|
}
|
|
13864
14130
|
return otherLine("response_item", payload, timestamp);
|
|
13865
14131
|
}
|
|
@@ -14041,13 +14307,13 @@ function parseUser(raw, common) {
|
|
|
14041
14307
|
if (!isRecord3(block))
|
|
14042
14308
|
continue;
|
|
14043
14309
|
if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
14044
|
-
const
|
|
14310
|
+
const result5 = {
|
|
14045
14311
|
toolUseId: block.tool_use_id,
|
|
14046
14312
|
// 实测:成功结果常无 is_error 字段;仅显式 true 视为失败
|
|
14047
14313
|
isError: block.is_error === true,
|
|
14048
14314
|
content: block.content
|
|
14049
14315
|
};
|
|
14050
|
-
line.toolResults.push(
|
|
14316
|
+
line.toolResults.push(result5);
|
|
14051
14317
|
} else if (block.type === "text" && typeof block.text === "string") {
|
|
14052
14318
|
texts.push(block.text);
|
|
14053
14319
|
}
|
|
@@ -14570,11 +14836,11 @@ function buildTaskCreateResultIndex(lines2) {
|
|
|
14570
14836
|
for (const line of lines2) {
|
|
14571
14837
|
if (line.kind !== "user")
|
|
14572
14838
|
continue;
|
|
14573
|
-
const
|
|
14574
|
-
if (!isRecord3(
|
|
14839
|
+
const result5 = line.toolUseResult;
|
|
14840
|
+
if (!isRecord3(result5) || !isRecord3(result5.task) || typeof result5.task.id !== "string")
|
|
14575
14841
|
continue;
|
|
14576
14842
|
for (const toolResult of line.toolResults)
|
|
14577
|
-
index.set(toolResult.toolUseId,
|
|
14843
|
+
index.set(toolResult.toolUseId, result5.task.id);
|
|
14578
14844
|
}
|
|
14579
14845
|
return index;
|
|
14580
14846
|
}
|
|
@@ -14708,7 +14974,7 @@ function turnUsage(line) {
|
|
|
14708
14974
|
if (inputTokens === void 0 || cacheCreationInputTokens === void 0 || cacheReadInputTokens === void 0 || outputTokens === void 0) {
|
|
14709
14975
|
return void 0;
|
|
14710
14976
|
}
|
|
14711
|
-
const
|
|
14977
|
+
const result5 = {
|
|
14712
14978
|
inputTokens,
|
|
14713
14979
|
cacheCreationInputTokens,
|
|
14714
14980
|
cacheReadInputTokens,
|
|
@@ -14723,11 +14989,11 @@ function turnUsage(line) {
|
|
|
14723
14989
|
const fiveMinute = finiteNumber(breakdown.ephemeral_5m_input_tokens);
|
|
14724
14990
|
const oneHour = finiteNumber(breakdown.ephemeral_1h_input_tokens);
|
|
14725
14991
|
if (fiveMinute !== void 0)
|
|
14726
|
-
|
|
14992
|
+
result5.cacheCreation5mTokens = fiveMinute;
|
|
14727
14993
|
if (oneHour !== void 0)
|
|
14728
|
-
|
|
14994
|
+
result5.cacheCreation1hTokens = oneHour;
|
|
14729
14995
|
}
|
|
14730
|
-
return
|
|
14996
|
+
return result5;
|
|
14731
14997
|
}
|
|
14732
14998
|
function finiteNumber(value) {
|
|
14733
14999
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
@@ -15101,9 +15367,9 @@ function fromTool(harness, name, input, source, at) {
|
|
|
15101
15367
|
return [];
|
|
15102
15368
|
if (harness === "codex" && name === "exec") {
|
|
15103
15369
|
const inputText = toolText(input, ["input"]);
|
|
15104
|
-
const
|
|
15105
|
-
if (
|
|
15106
|
-
return
|
|
15370
|
+
const paths3 = codexExecPatchPaths(inputText);
|
|
15371
|
+
if (paths3.length > 0) {
|
|
15372
|
+
return paths3.map((path) => fileObservation(path, "codex apply_patch via exec", source, false, at));
|
|
15107
15373
|
}
|
|
15108
15374
|
}
|
|
15109
15375
|
if (name === "Bash" || name === "exec") {
|
|
@@ -15145,13 +15411,13 @@ function fileObservation(path, method, source, wholeFile, at) {
|
|
|
15145
15411
|
function patchPaths(patch) {
|
|
15146
15412
|
if (patch === void 0)
|
|
15147
15413
|
return [];
|
|
15148
|
-
const
|
|
15414
|
+
const paths3 = [];
|
|
15149
15415
|
for (const line of patch.split("\n")) {
|
|
15150
15416
|
const match = /^\*\*\* (?:Update|Add) File: (.+?)\s*$/u.exec(line);
|
|
15151
15417
|
if (match?.[1] !== void 0 && isPlanPath(match[1]))
|
|
15152
|
-
|
|
15418
|
+
paths3.push(match[1]);
|
|
15153
15419
|
}
|
|
15154
|
-
return
|
|
15420
|
+
return paths3;
|
|
15155
15421
|
}
|
|
15156
15422
|
function codexExecPatchPaths(input) {
|
|
15157
15423
|
if (input === void 0 || !input.includes("*** Begin Patch"))
|
|
@@ -15212,22 +15478,29 @@ function isRecord5(value) {
|
|
|
15212
15478
|
|
|
15213
15479
|
// apps/cli/dist/project-index.js
|
|
15214
15480
|
import { lstat, readFile as readFile3, realpath, stat as stat3 } from "node:fs/promises";
|
|
15215
|
-
import { dirname as
|
|
15481
|
+
import { dirname as dirname15, isAbsolute as isAbsolute4, join as join22, relative as relative3, resolve as resolve10 } from "node:path";
|
|
15216
15482
|
var PROJECT_ROOT_MAX_DIRECTORIES = 8;
|
|
15217
15483
|
var PROJECT_PLAN_POLL_MS = 2e3;
|
|
15218
15484
|
async function resolveProjectRoot(cwd, options) {
|
|
15219
|
-
const root =
|
|
15220
|
-
const homeDir =
|
|
15221
|
-
const boundaryDir = options.boundaryDir === void 0 ? void 0 :
|
|
15485
|
+
const root = resolve10(cwd);
|
|
15486
|
+
const homeDir = resolve10(options.homeDir);
|
|
15487
|
+
const boundaryDir = options.boundaryDir === void 0 ? void 0 : resolve10(options.boundaryDir);
|
|
15222
15488
|
const [rootIdentity, homeIdentity, boundaryIdentity] = await Promise.all([
|
|
15223
15489
|
pathIdentity(root),
|
|
15224
15490
|
pathIdentity(homeDir),
|
|
15225
15491
|
boundaryDir === void 0 ? void 0 : pathIdentity(boundaryDir)
|
|
15226
15492
|
]);
|
|
15227
|
-
const wingmanHomeIdentity = await pathIdentity(
|
|
15228
|
-
const planPathIdentity = await pathIdentity(
|
|
15493
|
+
const wingmanHomeIdentity = await pathIdentity(join22(homeIdentity, ".wingman"));
|
|
15494
|
+
const planPathIdentity = await pathIdentity(join22(rootIdentity, ".wingman", "plan.md"));
|
|
15229
15495
|
if (rootIdentity === homeIdentity || rootIdentity === wingmanHomeIdentity || boundaryIdentity !== void 0 && !isWithin(boundaryIdentity, rootIdentity)) {
|
|
15230
|
-
return {
|
|
15496
|
+
return {
|
|
15497
|
+
root,
|
|
15498
|
+
rootIdentity,
|
|
15499
|
+
planPathIdentity,
|
|
15500
|
+
lookedUp: [],
|
|
15501
|
+
higherPlanPaths: [],
|
|
15502
|
+
...rootIdentity === homeIdentity ? { isHome: true } : {}
|
|
15503
|
+
};
|
|
15231
15504
|
}
|
|
15232
15505
|
const lookedUp = [];
|
|
15233
15506
|
const found = [];
|
|
@@ -15239,7 +15512,7 @@ async function resolveProjectRoot(cwd, options) {
|
|
|
15239
15512
|
break;
|
|
15240
15513
|
if (boundaryIdentity !== void 0 && !isWithin(boundaryIdentity, currentIdentity))
|
|
15241
15514
|
break;
|
|
15242
|
-
const planPath =
|
|
15515
|
+
const planPath = join22(current, ".wingman", "plan.md");
|
|
15243
15516
|
lookedUp.push(planPath);
|
|
15244
15517
|
try {
|
|
15245
15518
|
await lstat(planPath);
|
|
@@ -15251,7 +15524,7 @@ async function resolveProjectRoot(cwd, options) {
|
|
|
15251
15524
|
});
|
|
15252
15525
|
} catch {
|
|
15253
15526
|
}
|
|
15254
|
-
const parent =
|
|
15527
|
+
const parent = dirname15(current);
|
|
15255
15528
|
if (parent === current)
|
|
15256
15529
|
break;
|
|
15257
15530
|
current = parent;
|
|
@@ -15329,7 +15602,7 @@ function watchProjectPlan(planPath, options) {
|
|
|
15329
15602
|
};
|
|
15330
15603
|
}
|
|
15331
15604
|
async function pathIdentity(path) {
|
|
15332
|
-
const resolved =
|
|
15605
|
+
const resolved = resolve10(path);
|
|
15333
15606
|
try {
|
|
15334
15607
|
return normalizedPath(await realpath(resolved));
|
|
15335
15608
|
} catch {
|
|
@@ -15344,7 +15617,7 @@ async function pathsReferToSameLocation(left, right) {
|
|
|
15344
15617
|
return relative3(leftIdentity, rightIdentity) === "";
|
|
15345
15618
|
}
|
|
15346
15619
|
function normalizedPath(path) {
|
|
15347
|
-
const resolved =
|
|
15620
|
+
const resolved = resolve10(path);
|
|
15348
15621
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
15349
15622
|
}
|
|
15350
15623
|
function isWithin(parent, child) {
|
|
@@ -15354,17 +15627,17 @@ function isWithin(parent, child) {
|
|
|
15354
15627
|
|
|
15355
15628
|
// apps/cli/dist/project-roots.js
|
|
15356
15629
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
15357
|
-
import { closeSync, mkdirSync as
|
|
15358
|
-
import { dirname as
|
|
15630
|
+
import { closeSync, mkdirSync as mkdirSync10, openSync, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync8, statSync as statSync5, writeFileSync as writeFileSync11 } from "node:fs";
|
|
15631
|
+
import { dirname as dirname16, isAbsolute as isAbsolute5, join as join23 } from "node:path";
|
|
15359
15632
|
var PROJECT_ROOTS_MAX_ENTRIES = 200;
|
|
15360
15633
|
function projectRootsPath(homeDir) {
|
|
15361
|
-
return
|
|
15634
|
+
return join23(homeDir, ".wingman", "state", "projects.json");
|
|
15362
15635
|
}
|
|
15363
15636
|
function readProjectRoots(homeDir) {
|
|
15364
15637
|
const path = projectRootsPath(homeDir);
|
|
15365
15638
|
let raw;
|
|
15366
15639
|
try {
|
|
15367
|
-
raw =
|
|
15640
|
+
raw = readFileSync14(path, "utf8");
|
|
15368
15641
|
} catch (error) {
|
|
15369
15642
|
if (isErrno(error, "ENOENT"))
|
|
15370
15643
|
return { version: 1, roots: {} };
|
|
@@ -15404,7 +15677,7 @@ function pruneProjectRoots(homeDir) {
|
|
|
15404
15677
|
return current;
|
|
15405
15678
|
const roots = Object.fromEntries(Object.entries(current.roots).filter(([, entry]) => {
|
|
15406
15679
|
try {
|
|
15407
|
-
statSync5(
|
|
15680
|
+
statSync5(join23(entry.root, ".wingman", "plan.md"));
|
|
15408
15681
|
return true;
|
|
15409
15682
|
} catch (error) {
|
|
15410
15683
|
return !isErrno(error, "ENOENT") && !isErrno(error, "ENOTDIR");
|
|
@@ -15428,12 +15701,12 @@ function limitRoots(roots) {
|
|
|
15428
15701
|
}
|
|
15429
15702
|
function writeProjectRoots(homeDir, state) {
|
|
15430
15703
|
const path = projectRootsPath(homeDir);
|
|
15431
|
-
const tempPath =
|
|
15704
|
+
const tempPath = join23(dirname16(path), `.projects-${randomBytes2(8).toString("hex")}.tmp`);
|
|
15432
15705
|
let fd;
|
|
15433
15706
|
try {
|
|
15434
|
-
|
|
15707
|
+
mkdirSync10(dirname16(path), { recursive: true, mode: 448 });
|
|
15435
15708
|
fd = openSync(tempPath, "wx", 384);
|
|
15436
|
-
|
|
15709
|
+
writeFileSync11(fd, `${JSON.stringify(state)}
|
|
15437
15710
|
`, "utf8");
|
|
15438
15711
|
closeSync(fd);
|
|
15439
15712
|
fd = void 0;
|
|
@@ -15446,7 +15719,7 @@ function writeProjectRoots(homeDir, state) {
|
|
|
15446
15719
|
}
|
|
15447
15720
|
}
|
|
15448
15721
|
try {
|
|
15449
|
-
|
|
15722
|
+
rmSync8(tempPath, { force: true });
|
|
15450
15723
|
} catch {
|
|
15451
15724
|
}
|
|
15452
15725
|
throw error;
|
|
@@ -15475,16 +15748,16 @@ function isErrno(error, code) {
|
|
|
15475
15748
|
|
|
15476
15749
|
// apps/cli/dist/task-overlay.js
|
|
15477
15750
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
15478
|
-
import { closeSync as closeSync2, mkdirSync as
|
|
15479
|
-
import { dirname as
|
|
15751
|
+
import { closeSync as closeSync2, mkdirSync as mkdirSync11, openSync as openSync2, readFileSync as readFileSync15, renameSync as renameSync4, rmSync as rmSync9, writeFileSync as writeFileSync12 } from "node:fs";
|
|
15752
|
+
import { dirname as dirname17, join as join24 } from "node:path";
|
|
15480
15753
|
function taskOverlayPath(homeDir) {
|
|
15481
|
-
return
|
|
15754
|
+
return join24(homeDir, ".wingman", "state", "task-overlay.json");
|
|
15482
15755
|
}
|
|
15483
15756
|
function readTaskOverlay(homeDir) {
|
|
15484
15757
|
const path = taskOverlayPath(homeDir);
|
|
15485
15758
|
let raw;
|
|
15486
15759
|
try {
|
|
15487
|
-
raw =
|
|
15760
|
+
raw = readFileSync15(path, "utf8");
|
|
15488
15761
|
} catch (error) {
|
|
15489
15762
|
if (isErrno2(error, "ENOENT"))
|
|
15490
15763
|
return { version: 1, entries: {} };
|
|
@@ -15536,12 +15809,12 @@ function patchTaskOverlay(homeDir, key, patch, now) {
|
|
|
15536
15809
|
}
|
|
15537
15810
|
function writeTaskOverlay(homeDir, overlay) {
|
|
15538
15811
|
const path = taskOverlayPath(homeDir);
|
|
15539
|
-
const tempPath =
|
|
15812
|
+
const tempPath = join24(dirname17(path), `.task-overlay-${randomBytes3(8).toString("hex")}.tmp`);
|
|
15540
15813
|
let fd;
|
|
15541
15814
|
try {
|
|
15542
|
-
|
|
15815
|
+
mkdirSync11(dirname17(path), { recursive: true, mode: 448 });
|
|
15543
15816
|
fd = openSync2(tempPath, "wx", 384);
|
|
15544
|
-
|
|
15817
|
+
writeFileSync12(fd, `${JSON.stringify(overlay)}
|
|
15545
15818
|
`, "utf8");
|
|
15546
15819
|
closeSync2(fd);
|
|
15547
15820
|
fd = void 0;
|
|
@@ -15554,7 +15827,7 @@ function writeTaskOverlay(homeDir, overlay) {
|
|
|
15554
15827
|
}
|
|
15555
15828
|
}
|
|
15556
15829
|
try {
|
|
15557
|
-
|
|
15830
|
+
rmSync9(tempPath, { force: true });
|
|
15558
15831
|
} catch {
|
|
15559
15832
|
}
|
|
15560
15833
|
throw error;
|
|
@@ -15587,7 +15860,7 @@ function errorMessage(error) {
|
|
|
15587
15860
|
}
|
|
15588
15861
|
|
|
15589
15862
|
// apps/cli/dist/version.js
|
|
15590
|
-
import { readFileSync as
|
|
15863
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
15591
15864
|
function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPackage }) {
|
|
15592
15865
|
if (typeof defined === "string" && defined.trim() !== "")
|
|
15593
15866
|
return defined;
|
|
@@ -15606,10 +15879,10 @@ function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPacka
|
|
|
15606
15879
|
return void 0;
|
|
15607
15880
|
}
|
|
15608
15881
|
function wingmanVersion() {
|
|
15609
|
-
const defined = false ? void 0 : "0.8.
|
|
15882
|
+
const defined = false ? void 0 : "0.8.2";
|
|
15610
15883
|
return resolveWingmanVersion({
|
|
15611
15884
|
defined,
|
|
15612
|
-
readPackage: (url) => JSON.parse(
|
|
15885
|
+
readPackage: (url) => JSON.parse(readFileSync16(url, "utf8"))
|
|
15613
15886
|
});
|
|
15614
15887
|
}
|
|
15615
15888
|
|
|
@@ -15692,6 +15965,9 @@ function createNarrativeService(options = {}) {
|
|
|
15692
15965
|
generation: 0,
|
|
15693
15966
|
lines: [],
|
|
15694
15967
|
codexLines: [],
|
|
15968
|
+
instructionSeq: 0,
|
|
15969
|
+
sessionPlanSeq: 0,
|
|
15970
|
+
hookInstructions: [],
|
|
15695
15971
|
pendingPlanWrites: [],
|
|
15696
15972
|
confirmedPlanWrites: [],
|
|
15697
15973
|
nonPlanToolSteps: 0,
|
|
@@ -15725,6 +16001,8 @@ function createNarrativeService(options = {}) {
|
|
|
15725
16001
|
if (closed || session.cwd !== cwd)
|
|
15726
16002
|
return;
|
|
15727
16003
|
session.projectResolution = resolution;
|
|
16004
|
+
if (resolution.isHome)
|
|
16005
|
+
session.label = "\u65E0\u9879\u76EE\u76EE\u5F55(\u5BB6\u76EE\u5F55)";
|
|
15728
16006
|
seenProjectRoots.add(resolution.rootIdentity);
|
|
15729
16007
|
rememberResolution(resolution);
|
|
15730
16008
|
watchResolution(resolution);
|
|
@@ -15778,7 +16056,7 @@ function createNarrativeService(options = {}) {
|
|
|
15778
16056
|
function watchResolution(resolution) {
|
|
15779
16057
|
if (resolution.lookedUp.length === 0)
|
|
15780
16058
|
return;
|
|
15781
|
-
const planPath = resolution.planPath ??
|
|
16059
|
+
const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
|
|
15782
16060
|
const planPathIdentity = resolution.planPathIdentity;
|
|
15783
16061
|
if (projectWatchers.has(planPathIdentity))
|
|
15784
16062
|
return;
|
|
@@ -15867,7 +16145,7 @@ function createNarrativeService(options = {}) {
|
|
|
15867
16145
|
for (const session of sessions.values()) {
|
|
15868
16146
|
const resolution = session.projectResolution;
|
|
15869
16147
|
if (resolution?.planPathIdentity === planPathIdentity) {
|
|
15870
|
-
const planPath = resolution.planPath ??
|
|
16148
|
+
const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
|
|
15871
16149
|
void applyPendingPlanWrites(session, planPath, planPathIdentity).then(() => {
|
|
15872
16150
|
session.dirty = true;
|
|
15873
16151
|
notify(harness);
|
|
@@ -15912,7 +16190,7 @@ function createNarrativeService(options = {}) {
|
|
|
15912
16190
|
}
|
|
15913
16191
|
const resolution = session.projectResolution;
|
|
15914
16192
|
if (resolution !== void 0) {
|
|
15915
|
-
const planPath = resolution.planPath ??
|
|
16193
|
+
const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
|
|
15916
16194
|
void applyPendingPlanWrites(session, planPath, resolution.planPathIdentity).then(() => {
|
|
15917
16195
|
session.dirty = true;
|
|
15918
16196
|
notify(harness);
|
|
@@ -15942,12 +16220,12 @@ function createNarrativeService(options = {}) {
|
|
|
15942
16220
|
at: observation.at ?? versions.current.info.mtime,
|
|
15943
16221
|
nonPlanStepsBefore: pending.nonPlanStepsBefore
|
|
15944
16222
|
});
|
|
15945
|
-
const
|
|
15946
|
-
if ("attachedTo" in
|
|
15947
|
-
session.planAttachment =
|
|
16223
|
+
const result5 = attributePlanWrite(before, after, observation);
|
|
16224
|
+
if ("attachedTo" in result5) {
|
|
16225
|
+
session.planAttachment = result5;
|
|
15948
16226
|
session.planUnattachedReason = void 0;
|
|
15949
16227
|
} else {
|
|
15950
|
-
session.planUnattachedReason =
|
|
16228
|
+
session.planUnattachedReason = result5.reason;
|
|
15951
16229
|
}
|
|
15952
16230
|
}
|
|
15953
16231
|
session.pendingPlanWrites = remaining;
|
|
@@ -16002,8 +16280,13 @@ function createNarrativeService(options = {}) {
|
|
|
16002
16280
|
session.lines = [];
|
|
16003
16281
|
session.codexLines = [];
|
|
16004
16282
|
session.hookIntervals = [];
|
|
16005
|
-
session.
|
|
16006
|
-
|
|
16283
|
+
if (session.transcriptPath !== void 0) {
|
|
16284
|
+
session.hookPrompt = void 0;
|
|
16285
|
+
session.hookPromptAt = void 0;
|
|
16286
|
+
session.hookInstructions = [];
|
|
16287
|
+
}
|
|
16288
|
+
session.instructionSeq = 0;
|
|
16289
|
+
session.sessionPlanSeq = 0;
|
|
16007
16290
|
session.mockNote = void 0;
|
|
16008
16291
|
session.transcriptPath = path;
|
|
16009
16292
|
session.dirty = true;
|
|
@@ -16040,7 +16323,7 @@ function createNarrativeService(options = {}) {
|
|
|
16040
16323
|
const sessionDir = transcriptPath.replace(/\.jsonl$/, "");
|
|
16041
16324
|
if (sessionDir === transcriptPath)
|
|
16042
16325
|
return;
|
|
16043
|
-
const subagentsDir =
|
|
16326
|
+
const subagentsDir = join25(sessionDir, "subagents");
|
|
16044
16327
|
const generation = session.generation;
|
|
16045
16328
|
const poll = async () => {
|
|
16046
16329
|
try {
|
|
@@ -16050,7 +16333,7 @@ function createNarrativeService(options = {}) {
|
|
|
16050
16333
|
}
|
|
16051
16334
|
for (const entry of entries) {
|
|
16052
16335
|
if (/^agent-.*\.jsonl$/.test(entry)) {
|
|
16053
|
-
startFollowing(harness, session,
|
|
16336
|
+
startFollowing(harness, session, join25(subagentsDir, entry), generation);
|
|
16054
16337
|
}
|
|
16055
16338
|
}
|
|
16056
16339
|
} catch {
|
|
@@ -16073,7 +16356,7 @@ function createNarrativeService(options = {}) {
|
|
|
16073
16356
|
if (cwd !== void 0) {
|
|
16074
16357
|
anchorCwd(event.harness, session, cwd);
|
|
16075
16358
|
const base = pathBasename(cwd);
|
|
16076
|
-
if (base !== "")
|
|
16359
|
+
if (base !== "" && !session.projectResolution?.isHome)
|
|
16077
16360
|
session.label = base;
|
|
16078
16361
|
}
|
|
16079
16362
|
recordToolObservations(event.harness, session, extractToolObservations(event.harness, [{ ...payload, received_at: event.received_at }]));
|
|
@@ -16086,11 +16369,17 @@ function createNarrativeService(options = {}) {
|
|
|
16086
16369
|
}
|
|
16087
16370
|
}
|
|
16088
16371
|
}
|
|
16089
|
-
if (name === "UserPromptSubmit"
|
|
16090
|
-
const prompt = payload.prompt.trim();
|
|
16091
|
-
if (prompt !== "" && !isHarnessSystemNotice(prompt)) {
|
|
16092
|
-
session.
|
|
16093
|
-
|
|
16372
|
+
if (name === "UserPromptSubmit") {
|
|
16373
|
+
const prompt = typeof payload.prompt === "string" ? payload.prompt.trim() : void 0;
|
|
16374
|
+
if (prompt === void 0 || prompt !== "" && !isHarnessSystemNotice(prompt)) {
|
|
16375
|
+
session.hookInstructions.push({
|
|
16376
|
+
at: event.received_at,
|
|
16377
|
+
...prompt === void 0 ? {} : { text: prompt }
|
|
16378
|
+
});
|
|
16379
|
+
if (prompt !== void 0) {
|
|
16380
|
+
session.hookPrompt = truncate(prompt, DETAIL_LIMIT);
|
|
16381
|
+
session.hookPromptAt = event.received_at;
|
|
16382
|
+
}
|
|
16094
16383
|
}
|
|
16095
16384
|
}
|
|
16096
16385
|
if (name === "SubagentStart") {
|
|
@@ -16176,7 +16465,7 @@ function createNarrativeService(options = {}) {
|
|
|
16176
16465
|
if (cwd !== void 0) {
|
|
16177
16466
|
anchorCwd(harness, session2, cwd);
|
|
16178
16467
|
const base = pathBasename(cwd);
|
|
16179
|
-
if (base !== "")
|
|
16468
|
+
if (base !== "" && !session2.projectResolution?.isHome)
|
|
16180
16469
|
session2.label = base;
|
|
16181
16470
|
}
|
|
16182
16471
|
session2.dirty = true;
|
|
@@ -16203,7 +16492,7 @@ function createNarrativeService(options = {}) {
|
|
|
16203
16492
|
if (typeof cwd === "string") {
|
|
16204
16493
|
anchorCwd(harness, session, cwd);
|
|
16205
16494
|
const base = pathBasename(cwd);
|
|
16206
|
-
if (base !== "")
|
|
16495
|
+
if (base !== "" && !session.projectResolution?.isHome)
|
|
16207
16496
|
session.label = base;
|
|
16208
16497
|
break;
|
|
16209
16498
|
}
|
|
@@ -16291,7 +16580,7 @@ function createNarrativeService(options = {}) {
|
|
|
16291
16580
|
let state;
|
|
16292
16581
|
if (observed.state === "installed_not_loaded")
|
|
16293
16582
|
state = "installed_not_loaded";
|
|
16294
|
-
else if (observed.state === "installed") {
|
|
16583
|
+
else if (observed.state === "installed" || observed.state === "outdated") {
|
|
16295
16584
|
state = planMtime === void 0 ? "installed" : "plan_present";
|
|
16296
16585
|
} else
|
|
16297
16586
|
state = "not_installed";
|
|
@@ -16345,7 +16634,7 @@ function createNarrativeService(options = {}) {
|
|
|
16345
16634
|
for (const session of sessions.values()) {
|
|
16346
16635
|
if (session.cwd === void 0)
|
|
16347
16636
|
continue;
|
|
16348
|
-
const rootIdentity = session.projectResolution?.rootIdentity ??
|
|
16637
|
+
const rootIdentity = session.projectResolution?.rootIdentity ?? resolve11(session.cwd);
|
|
16349
16638
|
const group = grouped.get(rootIdentity);
|
|
16350
16639
|
if (group === void 0) {
|
|
16351
16640
|
grouped.set(rootIdentity, {
|
|
@@ -16365,8 +16654,8 @@ function createNarrativeService(options = {}) {
|
|
|
16365
16654
|
for (const [rootIdentity, group] of grouped) {
|
|
16366
16655
|
const { members } = group;
|
|
16367
16656
|
const resolution = members.find((member) => member.session.projectResolution !== void 0)?.session.projectResolution ?? group.resolution;
|
|
16368
|
-
const root = resolution?.root ??
|
|
16369
|
-
const planPath = resolution?.planPath ??
|
|
16657
|
+
const root = resolution?.root ?? resolve11(members[0]?.session.cwd ?? "");
|
|
16658
|
+
const planPath = resolution?.planPath ?? join25(root, ".wingman", "plan.md");
|
|
16370
16659
|
const runtime = projectFiles.get(resolution?.planPathIdentity ?? planPath);
|
|
16371
16660
|
const parsed = runtime?.missing === true ? void 0 : runtime?.parsed;
|
|
16372
16661
|
const planMtime = parsed?.availability === "available" ? runtime?.current?.info.mtime : void 0;
|
|
@@ -16384,12 +16673,13 @@ function createNarrativeService(options = {}) {
|
|
|
16384
16673
|
const verification = state?.taskWorkflow?.verification;
|
|
16385
16674
|
const attachedTitle = session.planAttachment?.attachedTo.split(" > ").at(-1);
|
|
16386
16675
|
const instructionTitle = state?.taskWorkflow?.latestInstruction?.text;
|
|
16676
|
+
const planInstruction = state?.taskWorkflow?.plan.availability === "available" ? session.sessionPlanInstruction : void 0;
|
|
16387
16677
|
return {
|
|
16388
16678
|
harness,
|
|
16389
16679
|
id: session.id,
|
|
16390
16680
|
label,
|
|
16391
16681
|
ended: info?.ended ?? false,
|
|
16392
|
-
title: attachedTitle !== void 0 ? { text: attachedTitle, source: "plan.md \u6B65\u9AA4" } : instructionTitle !== void 0 ? { text: truncate(instructionTitle, DETAIL_LIMIT), source: "\u6700\u65B0\u6307\u4EE4" } : { text: label, source: "\u5DE5\u4F5C\u76EE\u5F55" },
|
|
16682
|
+
title: attachedTitle !== void 0 ? { text: attachedTitle, source: "plan.md \u6B65\u9AA4" } : planInstruction !== void 0 ? { text: truncate(planInstruction, DETAIL_LIMIT), source: "\u8BA1\u5212\u6240\u5C5E\u6307\u4EE4" } : instructionTitle !== void 0 ? { text: truncate(instructionTitle, DETAIL_LIMIT), source: "\u6700\u65B0\u6307\u4EE4" } : { text: label, source: "\u5DE5\u4F5C\u76EE\u5F55" },
|
|
16393
16683
|
user: {
|
|
16394
16684
|
...userEntry?.title === void 0 ? {} : { title: userEntry.title },
|
|
16395
16685
|
pinned: userEntry?.pinned ?? false,
|
|
@@ -16434,14 +16724,14 @@ function createNarrativeService(options = {}) {
|
|
|
16434
16724
|
id: `${session.harness}:${session.id}`,
|
|
16435
16725
|
...session.attachedTo === void 0 ? {} : { attachedTo: session.attachedTo },
|
|
16436
16726
|
ended: session.ended,
|
|
16437
|
-
...session.sessionPlan?.availability === "available" && session.sessionPlan.steps.length > 0 ? {
|
|
16727
|
+
...session.sessionPlan?.availability === "available" && session.sessionPlan.forInstruction === "current" && session.sessionPlan.steps.length > 0 ? {
|
|
16438
16728
|
sessionPlanAllCompleted: session.sessionPlan.steps.every((step) => step.status === "completed")
|
|
16439
16729
|
} : {},
|
|
16440
16730
|
...session.attachedBy?.at === void 0 ? {} : { wrotePlanAt: session.attachedBy.at }
|
|
16441
16731
|
})), now().toISOString());
|
|
16442
16732
|
const lastWriter = [...sessionViews].filter((session) => typeof session.attachedBy?.at === "string").sort((left, right) => right.attachedBy.at.localeCompare(left.attachedBy.at))[0];
|
|
16443
|
-
const titleText = parsed?.availability === "available" && parsed.title !== void 0 ? parsed.title : pathBasename(root) || root;
|
|
16444
|
-
const titleSource = parsed?.availability === "available" && parsed.title !== void 0 ? ".wingman/plan.md H1" : "\u5DE5\u4F5C\u76EE\u5F55";
|
|
16733
|
+
const titleText = resolution?.isHome ? "\u65E0\u9879\u76EE\u76EE\u5F55(\u5BB6\u76EE\u5F55)" : parsed?.availability === "available" && parsed.title !== void 0 ? parsed.title : pathBasename(root) || root;
|
|
16734
|
+
const titleSource = resolution?.isHome ? "\u5DE5\u4F5C\u76EE\u5F55 = \u5BB6\u76EE\u5F55" : parsed?.availability === "available" && parsed.title !== void 0 ? ".wingman/plan.md H1" : "\u5DE5\u4F5C\u76EE\u5F55";
|
|
16445
16735
|
let plan;
|
|
16446
16736
|
if (parsed?.availability === "available") {
|
|
16447
16737
|
plan = {
|
|
@@ -16680,8 +16970,8 @@ function extractRawToolObservations(harness, rawLine) {
|
|
|
16680
16970
|
}
|
|
16681
16971
|
function resolveObservedPath(path, cwd) {
|
|
16682
16972
|
if (isAbsolute6(path))
|
|
16683
|
-
return
|
|
16684
|
-
return cwd === void 0 ? void 0 :
|
|
16973
|
+
return resolve11(path);
|
|
16974
|
+
return cwd === void 0 ? void 0 : resolve11(cwd, path);
|
|
16685
16975
|
}
|
|
16686
16976
|
function agentIdOf(payload) {
|
|
16687
16977
|
const id = payload.agent_id ?? payload.agentId;
|
|
@@ -16745,9 +17035,9 @@ function derive(harness, session, nowIso) {
|
|
|
16745
17035
|
const attributed = attributeSteps(steps, timeline, intervals);
|
|
16746
17036
|
const results = collectResults(lines2);
|
|
16747
17037
|
const resultBriefs = /* @__PURE__ */ new Map();
|
|
16748
|
-
for (const [toolUseId,
|
|
16749
|
-
if (
|
|
16750
|
-
resultBriefs.set(toolUseId,
|
|
17038
|
+
for (const [toolUseId, result5] of results) {
|
|
17039
|
+
if (result5.brief !== void 0)
|
|
17040
|
+
resultBriefs.set(toolUseId, result5.brief);
|
|
16751
17041
|
}
|
|
16752
17042
|
const checks = deriveCheckStats(allSteps, resultBriefs);
|
|
16753
17043
|
const todoChecks = deriveTodoCheckStats(attributed);
|
|
@@ -16856,11 +17146,16 @@ function derive(harness, session, nowIso) {
|
|
|
16856
17146
|
const activeTodos = todos.filter((todo) => todo.status === "in_progress");
|
|
16857
17147
|
const activeTodo = activeTodos.length === 1 ? activeTodos[0] : void 0;
|
|
16858
17148
|
const activeChecks = activeTodo === void 0 ? void 0 : todoChecks.get(activeTodo.id);
|
|
16859
|
-
|
|
17149
|
+
scopeSessionPlan(harness, session, lines2);
|
|
17150
|
+
const plan = workflowBase.plan.availability === "available" ? {
|
|
17151
|
+
...workflowBase.plan,
|
|
17152
|
+
forInstruction: session.sessionPlanSeq === session.instructionSeq ? "current" : "previous"
|
|
17153
|
+
} : workflowBase.plan;
|
|
16860
17154
|
const taskWorkflow = {
|
|
16861
17155
|
...workflowBase,
|
|
17156
|
+
plan,
|
|
16862
17157
|
verification: {
|
|
16863
|
-
agentMarkedComplete: plan.availability === "available" && plan.steps.length > 0 && plan.steps.every((step) => step.status === "completed"),
|
|
17158
|
+
agentMarkedComplete: plan.availability === "available" && plan.forInstruction === "current" && plan.steps.length > 0 && plan.steps.every((step) => step.status === "completed"),
|
|
16864
17159
|
checks: { ...checks, source: CHECK_STATS_SOURCE },
|
|
16865
17160
|
...activeTodo === void 0 ? {} : {
|
|
16866
17161
|
currentStep: {
|
|
@@ -16880,7 +17175,7 @@ function derive(harness, session, nowIso) {
|
|
|
16880
17175
|
...session.cwd === void 0 ? {} : { cwd: session.cwd },
|
|
16881
17176
|
...session.cwd === void 0 ? {} : {
|
|
16882
17177
|
project: {
|
|
16883
|
-
root: session.projectResolution?.root ??
|
|
17178
|
+
root: session.projectResolution?.root ?? resolve11(session.cwd),
|
|
16884
17179
|
...session.planAttachment === void 0 ? {} : { attachedTo: session.planAttachment.attachedTo }
|
|
16885
17180
|
}
|
|
16886
17181
|
},
|
|
@@ -16898,6 +17193,92 @@ function derive(harness, session, nowIso) {
|
|
|
16898
17193
|
updatedAt: nowIso
|
|
16899
17194
|
};
|
|
16900
17195
|
}
|
|
17196
|
+
function scopeSessionPlan(harness, session, lines2) {
|
|
17197
|
+
const observations = [];
|
|
17198
|
+
const seenUsers = /* @__PURE__ */ new Set();
|
|
17199
|
+
const taskIds = /* @__PURE__ */ new Set();
|
|
17200
|
+
const resultLines = /* @__PURE__ */ new Map();
|
|
17201
|
+
for (const line of lines2) {
|
|
17202
|
+
if (line.kind === "user") {
|
|
17203
|
+
for (const result5 of line.toolResults)
|
|
17204
|
+
resultLines.set(result5.toolUseId, line);
|
|
17205
|
+
}
|
|
17206
|
+
}
|
|
17207
|
+
let at;
|
|
17208
|
+
for (const line of lines2) {
|
|
17209
|
+
if (line.kind === "unknown" || line.agentId !== void 0 || line.isSidechain === true) {
|
|
17210
|
+
continue;
|
|
17211
|
+
}
|
|
17212
|
+
at = line.timestamp ?? at;
|
|
17213
|
+
const timestamp = at === void 0 ? {} : { at };
|
|
17214
|
+
if (line.kind === "user" && line.toolResults.length === 0) {
|
|
17215
|
+
const text = line.text?.trim();
|
|
17216
|
+
if (text === void 0 || text === "" || isHarnessSystemNotice(text))
|
|
17217
|
+
continue;
|
|
17218
|
+
if (line.uuid !== void 0) {
|
|
17219
|
+
if (seenUsers.has(line.uuid))
|
|
17220
|
+
continue;
|
|
17221
|
+
seenUsers.add(line.uuid);
|
|
17222
|
+
}
|
|
17223
|
+
observations.push({ kind: "instruction", source: "transcript", text, ...timestamp });
|
|
17224
|
+
} else if (line.kind === "assistant") {
|
|
17225
|
+
for (const block of line.blocks) {
|
|
17226
|
+
if (block.kind !== "tool_use")
|
|
17227
|
+
continue;
|
|
17228
|
+
if (harness === "codex" && block.name === "update_plan") {
|
|
17229
|
+
observations.push({ kind: "plan", ...timestamp });
|
|
17230
|
+
} else if (harness === "cc") {
|
|
17231
|
+
if (block.name === "TaskCreate" || block.name === "TodoWrite") {
|
|
17232
|
+
const result5 = resultLines.get(block.id);
|
|
17233
|
+
const snapshot = extractTodoSnapshots([
|
|
17234
|
+
{ ...line, blocks: [block] },
|
|
17235
|
+
...result5 === void 0 ? [] : [result5]
|
|
17236
|
+
]).at(-1);
|
|
17237
|
+
if (snapshot === void 0)
|
|
17238
|
+
continue;
|
|
17239
|
+
if (block.name === "TodoWrite")
|
|
17240
|
+
taskIds.clear();
|
|
17241
|
+
for (const todo of snapshot.todos)
|
|
17242
|
+
taskIds.add(todo.id);
|
|
17243
|
+
} else if (block.name === "TaskUpdate") {
|
|
17244
|
+
const taskId = block.input.taskId;
|
|
17245
|
+
if (typeof taskId !== "string" || !taskIds.has(taskId))
|
|
17246
|
+
continue;
|
|
17247
|
+
if (block.input.status === "deleted")
|
|
17248
|
+
taskIds.delete(taskId);
|
|
17249
|
+
} else {
|
|
17250
|
+
continue;
|
|
17251
|
+
}
|
|
17252
|
+
observations.push({ kind: "plan", ...timestamp });
|
|
17253
|
+
}
|
|
17254
|
+
}
|
|
17255
|
+
}
|
|
17256
|
+
}
|
|
17257
|
+
for (const hook of session.hookInstructions) {
|
|
17258
|
+
observations.push({ kind: "instruction", source: "hook", ...hook });
|
|
17259
|
+
}
|
|
17260
|
+
observations.sort((a, b) => (a.at ?? "").localeCompare(b.at ?? ""));
|
|
17261
|
+
session.instructionSeq = 0;
|
|
17262
|
+
session.sessionPlanSeq = 0;
|
|
17263
|
+
const instructions = /* @__PURE__ */ new Map();
|
|
17264
|
+
let unpaired;
|
|
17265
|
+
for (const observation of observations) {
|
|
17266
|
+
if (observation.kind === "plan") {
|
|
17267
|
+
session.sessionPlanSeq = session.instructionSeq;
|
|
17268
|
+
unpaired = void 0;
|
|
17269
|
+
} else if (unpaired !== void 0 && unpaired.source !== observation.source && (unpaired.text === void 0 || observation.text === void 0 || unpaired.text === observation.text)) {
|
|
17270
|
+
if (observation.text !== void 0)
|
|
17271
|
+
instructions.set(session.instructionSeq, observation.text);
|
|
17272
|
+
unpaired = void 0;
|
|
17273
|
+
} else {
|
|
17274
|
+
session.instructionSeq += 1;
|
|
17275
|
+
if (observation.text !== void 0)
|
|
17276
|
+
instructions.set(session.instructionSeq, observation.text);
|
|
17277
|
+
unpaired = observation;
|
|
17278
|
+
}
|
|
17279
|
+
}
|
|
17280
|
+
session.sessionPlanInstruction = instructions.get(session.sessionPlanSeq);
|
|
17281
|
+
}
|
|
16901
17282
|
function todoInProgressAt(timeline, ts) {
|
|
16902
17283
|
const active = timeline.filter((entry) => entry.spans.some((span) => span.status === "in_progress" && span.from !== void 0 && span.from <= ts && (span.to === void 0 || ts < span.to)));
|
|
16903
17284
|
const only = active[0];
|
|
@@ -17053,18 +17434,18 @@ function collectResults(lines2) {
|
|
|
17053
17434
|
for (const line of lines2) {
|
|
17054
17435
|
if (line.kind !== "user")
|
|
17055
17436
|
continue;
|
|
17056
|
-
for (const
|
|
17057
|
-
if (
|
|
17437
|
+
for (const result5 of line.toolResults) {
|
|
17438
|
+
if (result5.content === void 0)
|
|
17058
17439
|
continue;
|
|
17059
17440
|
const info = {};
|
|
17060
17441
|
try {
|
|
17061
|
-
info.bytes = Buffer.byteLength(JSON.stringify(
|
|
17442
|
+
info.bytes = Buffer.byteLength(JSON.stringify(result5.content), "utf8");
|
|
17062
17443
|
} catch {
|
|
17063
17444
|
}
|
|
17064
|
-
const brief = errorBrief(
|
|
17445
|
+
const brief = errorBrief(result5.content);
|
|
17065
17446
|
if (brief !== void 0)
|
|
17066
17447
|
info.brief = brief;
|
|
17067
|
-
results.set(
|
|
17448
|
+
results.set(result5.toolUseId, info);
|
|
17068
17449
|
}
|
|
17069
17450
|
}
|
|
17070
17451
|
return results;
|
|
@@ -17370,16 +17751,22 @@ function errorBrief(content) {
|
|
|
17370
17751
|
init_dist3();
|
|
17371
17752
|
init_dist5();
|
|
17372
17753
|
init_dist2();
|
|
17754
|
+
import { homedir as homedir13 } from "node:os";
|
|
17373
17755
|
import { createInterface } from "node:readline/promises";
|
|
17374
17756
|
var ProtocolUsageError = class extends Error {
|
|
17375
17757
|
};
|
|
17376
|
-
async function runProtocolCli(args) {
|
|
17758
|
+
async function runProtocolCli(args, options = { homeDir: homedir13() }) {
|
|
17377
17759
|
const parsed = parseProtocolArgs(args);
|
|
17760
|
+
if (parsed.user && parsed.harness === "dsh") {
|
|
17761
|
+
throw new ProtocolUsageError(protocolStatusDshUser(options).unsupported);
|
|
17762
|
+
}
|
|
17378
17763
|
if (parsed.action === "status") {
|
|
17379
|
-
|
|
17764
|
+
const user = getUserStatus(parsed.harness, options.homeDir);
|
|
17765
|
+
printStatus(user, "\u7528\u6237\u7EA7");
|
|
17766
|
+
printStatus(getStatus(parsed.harness, parsed.projectDir, options.homeDir), "\u9879\u76EE\u7EA7");
|
|
17380
17767
|
return 0;
|
|
17381
17768
|
}
|
|
17382
|
-
const preview = mutate(parsed
|
|
17769
|
+
const preview = mutate(parsed, options.homeDir, true);
|
|
17383
17770
|
printPreview(preview);
|
|
17384
17771
|
if (!preview.changed)
|
|
17385
17772
|
return 0;
|
|
@@ -17389,7 +17776,7 @@ async function runProtocolCli(args) {
|
|
|
17389
17776
|
process.stdout.write("wingman:\u5DF2\u53D6\u6D88\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002\n");
|
|
17390
17777
|
return 0;
|
|
17391
17778
|
}
|
|
17392
|
-
const applied = mutate(parsed
|
|
17779
|
+
const applied = mutate(parsed, options.homeDir, false);
|
|
17393
17780
|
process.stdout.write(`wingman:${parsed.harness} protocol ${parsed.action} \u5B8C\u6210
|
|
17394
17781
|
state: ${applied.state}
|
|
17395
17782
|
backupDir: ${applied.backupDir ?? "(no backup)"}
|
|
@@ -17401,12 +17788,15 @@ ${applied.message ?? ""}${applied.message === void 0 ? "" : "\n"}`);
|
|
|
17401
17788
|
function parseProtocolArgs(args) {
|
|
17402
17789
|
const [actionText, harnessText, ...tail] = args;
|
|
17403
17790
|
if (actionText !== "install" && actionText !== "uninstall" && actionText !== "status") {
|
|
17404
|
-
throw new ProtocolUsageError("protocol \u7528\u6CD5:wingman protocol install|uninstall|status <cc|codex|dsh> [--project <dir>] [--dry-run] [--yes]");
|
|
17791
|
+
throw new ProtocolUsageError("protocol \u7528\u6CD5:wingman protocol install|uninstall|status <cc|codex|dsh> [--project <dir> | --user] [--dry-run] [--yes]");
|
|
17405
17792
|
}
|
|
17406
17793
|
if (harnessText !== "cc" && harnessText !== "codex" && harnessText !== "dsh") {
|
|
17407
17794
|
throw new ProtocolUsageError(`protocol \u9700\u8981 harness \u2208 cc|codex|dsh,\u5F97\u5230 ${harnessText ?? "(\u7F3A\u53C2)"}`);
|
|
17408
17795
|
}
|
|
17409
17796
|
let projectDir = process.cwd();
|
|
17797
|
+
let user = false;
|
|
17798
|
+
let project = false;
|
|
17799
|
+
let fixtures = false;
|
|
17410
17800
|
let dryRun = false;
|
|
17411
17801
|
let yes = false;
|
|
17412
17802
|
const rest = [...tail];
|
|
@@ -17414,9 +17804,14 @@ function parseProtocolArgs(args) {
|
|
|
17414
17804
|
const arg = rest.shift();
|
|
17415
17805
|
if (arg === "--project") {
|
|
17416
17806
|
const value = rest.shift();
|
|
17417
|
-
if (value === void 0)
|
|
17807
|
+
if (value === void 0 || value.startsWith("--"))
|
|
17418
17808
|
throw new ProtocolUsageError("--project \u9700\u8981\u76EE\u5F55\u8DEF\u5F84,\u5F97\u5230(\u7F3A\u53C2)");
|
|
17809
|
+
project = true;
|
|
17419
17810
|
projectDir = value;
|
|
17811
|
+
} else if (arg === "--user") {
|
|
17812
|
+
user = true;
|
|
17813
|
+
} else if (arg === "--fixtures") {
|
|
17814
|
+
fixtures = true;
|
|
17420
17815
|
} else if (arg === "--dry-run") {
|
|
17421
17816
|
dryRun = true;
|
|
17422
17817
|
} else if (arg === "--yes") {
|
|
@@ -17425,36 +17820,57 @@ function parseProtocolArgs(args) {
|
|
|
17425
17820
|
throw new ProtocolUsageError(`protocol \u4E0D\u8BA4\u8BC6\u53C2\u6570:${arg}`);
|
|
17426
17821
|
}
|
|
17427
17822
|
}
|
|
17428
|
-
|
|
17823
|
+
if (user && project)
|
|
17824
|
+
throw new ProtocolUsageError("--user \u4E0E --project \u4E92\u65A5");
|
|
17825
|
+
if (fixtures && user)
|
|
17826
|
+
throw new ProtocolUsageError("fixtures \u6A21\u5F0F\u62D2\u7EDD --user\uFF0C\u4E0D\u80FD\u8BBF\u95EE\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6");
|
|
17827
|
+
if (fixtures)
|
|
17828
|
+
throw new ProtocolUsageError("protocol \u4E0D\u652F\u6301 --fixtures");
|
|
17829
|
+
return { action: actionText, harness: harnessText, projectDir, user, dryRun, yes };
|
|
17429
17830
|
}
|
|
17430
|
-
function getStatus(harness, projectDir) {
|
|
17831
|
+
function getStatus(harness, projectDir, homeDir) {
|
|
17431
17832
|
switch (harness) {
|
|
17432
17833
|
case "cc":
|
|
17433
|
-
return protocolStatusCc({ projectDir });
|
|
17834
|
+
return protocolStatusCc({ projectDir, homeDir });
|
|
17434
17835
|
case "codex":
|
|
17435
|
-
return protocolStatusCodex({ projectDir });
|
|
17836
|
+
return protocolStatusCodex({ projectDir, homeDir });
|
|
17436
17837
|
case "dsh":
|
|
17437
|
-
return protocolStatusDsh({ projectDir });
|
|
17838
|
+
return protocolStatusDsh({ projectDir, homeDir });
|
|
17438
17839
|
}
|
|
17439
17840
|
}
|
|
17440
|
-
function
|
|
17841
|
+
function getUserStatus(harness, homeDir) {
|
|
17441
17842
|
switch (harness) {
|
|
17442
17843
|
case "cc":
|
|
17443
|
-
return
|
|
17844
|
+
return protocolStatusCcUser({ homeDir });
|
|
17444
17845
|
case "codex":
|
|
17445
|
-
return
|
|
17846
|
+
return protocolStatusCodexUser({ homeDir });
|
|
17446
17847
|
case "dsh":
|
|
17447
|
-
return
|
|
17848
|
+
return protocolStatusDshUser({ homeDir });
|
|
17448
17849
|
}
|
|
17449
17850
|
}
|
|
17450
|
-
function
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17851
|
+
function mutate(parsed, homeDir, dryRun) {
|
|
17852
|
+
const { action, harness, projectDir, user } = parsed;
|
|
17853
|
+
switch (harness) {
|
|
17854
|
+
case "cc":
|
|
17855
|
+
return action === "install" ? (user ? installProtocolCcUser : installProtocolCc)({ projectDir, homeDir, dryRun }) : (user ? uninstallProtocolCcUser : uninstallProtocolCc)({ projectDir, homeDir, dryRun });
|
|
17856
|
+
case "codex":
|
|
17857
|
+
return action === "install" ? (user ? installProtocolCodexUser : installProtocolCodex)({ projectDir, homeDir, dryRun }) : (user ? uninstallProtocolCodexUser : uninstallProtocolCodex)({
|
|
17858
|
+
projectDir,
|
|
17859
|
+
homeDir,
|
|
17860
|
+
dryRun
|
|
17861
|
+
});
|
|
17862
|
+
case "dsh":
|
|
17863
|
+
return action === "install" ? installProtocolDsh({ projectDir, homeDir, dryRun }) : uninstallProtocolDsh({ projectDir, homeDir, dryRun });
|
|
17864
|
+
}
|
|
17865
|
+
}
|
|
17866
|
+
function printStatus(value, scope) {
|
|
17867
|
+
if ("unsupported" in value) {
|
|
17868
|
+
process.stdout.write(`${scope}: unsupported \u2014 ${value.unsupported}
|
|
17869
|
+
`);
|
|
17870
|
+
return;
|
|
17871
|
+
}
|
|
17872
|
+
process.stdout.write(`${scope}: ${value.state} | target: ${value.targetPath} | state: ${value.state}${value.version === void 0 ? "" : ` | version: ${value.version}`}${value.message === void 0 ? "" : ` | ${value.message}`}${value.reason === void 0 ? "" : ` | reason: ${value.reason}`}
|
|
17873
|
+
`);
|
|
17458
17874
|
}
|
|
17459
17875
|
function printPreview(value) {
|
|
17460
17876
|
process.stdout.write(`${unifiedDiff(value.targetPath, value.before, value.after)}
|
|
@@ -17504,8 +17920,8 @@ async function confirmWrite() {
|
|
|
17504
17920
|
}
|
|
17505
17921
|
|
|
17506
17922
|
// apps/cli/dist/registry.js
|
|
17507
|
-
import { existsSync as
|
|
17508
|
-
import { homedir as
|
|
17923
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
17924
|
+
import { homedir as homedir14 } from "node:os";
|
|
17509
17925
|
async function importHarnessModule(harness) {
|
|
17510
17926
|
const mod = await importAdapterModule(harness);
|
|
17511
17927
|
if (typeof mod.createAdapter !== "function") {
|
|
@@ -17527,7 +17943,7 @@ function importAdapterModule(harness) {
|
|
|
17527
17943
|
}
|
|
17528
17944
|
}
|
|
17529
17945
|
function fixtureScanOptions(harness) {
|
|
17530
|
-
if (!
|
|
17946
|
+
if (!existsSync14(fixturePath())) {
|
|
17531
17947
|
throw new Error("--fixtures \u9700\u8981\u4ED3\u5E93\u5185\u7684 packages/fixtures \u6570\u636E;\u53D1\u5E03\u5B89\u88C5\u5305/npx \u4EA7\u7269\u4E0D\u5305\u542B\u6837\u4F8B");
|
|
17532
17948
|
}
|
|
17533
17949
|
switch (harness) {
|
|
@@ -17548,16 +17964,16 @@ async function loadHarness(harness, mode) {
|
|
|
17548
17964
|
return {
|
|
17549
17965
|
harness,
|
|
17550
17966
|
adapter,
|
|
17551
|
-
scanOptions: mode.fixtures ? fixtureScanOptions(harness) : { homeDir:
|
|
17967
|
+
scanOptions: mode.fixtures ? fixtureScanOptions(harness) : { homeDir: homedir14() },
|
|
17552
17968
|
feedbackSignals
|
|
17553
17969
|
};
|
|
17554
17970
|
}
|
|
17555
17971
|
|
|
17556
17972
|
// apps/cli/dist/runtime-state.js
|
|
17557
17973
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
17558
|
-
import { closeSync as closeSync3, mkdirSync as
|
|
17559
|
-
import { homedir as
|
|
17560
|
-
import { dirname as
|
|
17974
|
+
import { closeSync as closeSync3, mkdirSync as mkdirSync12, openSync as openSync3, readFileSync as readFileSync17, renameSync as renameSync5, rmSync as rmSync10, writeFileSync as writeFileSync13 } from "node:fs";
|
|
17975
|
+
import { homedir as homedir15 } from "node:os";
|
|
17976
|
+
import { dirname as dirname18, join as join26 } from "node:path";
|
|
17561
17977
|
function createHookToken() {
|
|
17562
17978
|
return randomBytes4(32).toString("base64url");
|
|
17563
17979
|
}
|
|
@@ -17568,15 +17984,15 @@ function writeServeRuntimeState(port, token, options = {}) {
|
|
|
17568
17984
|
const pid = options.pid ?? process.pid;
|
|
17569
17985
|
const suffix = randomBytes4(8).toString("base64url");
|
|
17570
17986
|
const owner = `serve-${startedAtMs}-${pid}-${suffix}`;
|
|
17571
|
-
const path =
|
|
17572
|
-
const tempPath =
|
|
17987
|
+
const path = join26(options.homeDir ?? homedir15(), ".wingman", "state", "serve", `${owner}.json`);
|
|
17988
|
+
const tempPath = join26(dirname18(path), `.${owner}.tmp`);
|
|
17573
17989
|
const contents = Buffer.from(`${JSON.stringify({ version: 2, owner, pid, port, startedAtMs, token })}
|
|
17574
17990
|
`, "utf8");
|
|
17575
17991
|
let fd;
|
|
17576
17992
|
try {
|
|
17577
|
-
|
|
17993
|
+
mkdirSync12(dirname18(path), { recursive: true, mode: 448 });
|
|
17578
17994
|
fd = openSync3(tempPath, "wx", 384);
|
|
17579
|
-
|
|
17995
|
+
writeFileSync13(fd, contents);
|
|
17580
17996
|
closeSync3(fd);
|
|
17581
17997
|
fd = void 0;
|
|
17582
17998
|
renameSync5(tempPath, path);
|
|
@@ -17589,7 +18005,7 @@ function writeServeRuntimeState(port, token, options = {}) {
|
|
|
17589
18005
|
}
|
|
17590
18006
|
}
|
|
17591
18007
|
try {
|
|
17592
|
-
|
|
18008
|
+
rmSync10(tempPath, { force: true });
|
|
17593
18009
|
} catch {
|
|
17594
18010
|
}
|
|
17595
18011
|
warn(`Codex hook \u8FD0\u884C\u6001\u5199\u5165\u5931\u8D25,\u9762\u677F\u7EE7\u7EED\u8FD0\u884C:${errorMessage2(error)}`);
|
|
@@ -17600,9 +18016,9 @@ function removeServeRuntimeState(registration) {
|
|
|
17600
18016
|
if (registration === void 0)
|
|
17601
18017
|
return;
|
|
17602
18018
|
try {
|
|
17603
|
-
const current =
|
|
18019
|
+
const current = readFileSync17(registration.path);
|
|
17604
18020
|
if (current.equals(registration.contents))
|
|
17605
|
-
|
|
18021
|
+
rmSync10(registration.path, { force: true });
|
|
17606
18022
|
} catch {
|
|
17607
18023
|
}
|
|
17608
18024
|
}
|
|
@@ -17623,17 +18039,20 @@ async function scanValidated(adapter, options) {
|
|
|
17623
18039
|
}
|
|
17624
18040
|
|
|
17625
18041
|
// apps/cli/dist/server.js
|
|
18042
|
+
init_dist3();
|
|
18043
|
+
init_dist5();
|
|
17626
18044
|
init_dist();
|
|
17627
18045
|
import { execFile as execFile2 } from "node:child_process";
|
|
17628
18046
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
17629
18047
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
17630
18048
|
import { createServer } from "node:http";
|
|
17631
|
-
import {
|
|
18049
|
+
import { hostname } from "node:os";
|
|
18050
|
+
import { extname, relative as relative4, resolve as resolve13, sep as sep2 } from "node:path";
|
|
17632
18051
|
|
|
17633
18052
|
// apps/cli/dist/return-target.js
|
|
17634
18053
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
17635
|
-
import { closeSync as closeSync4, copyFileSync as copyFileSync2, mkdirSync as
|
|
17636
|
-
import { dirname as
|
|
18054
|
+
import { closeSync as closeSync4, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13, openSync as openSync4, readFileSync as readFileSync18, renameSync as renameSync6, rmSync as rmSync11, statSync as statSync6, writeFileSync as writeFileSync14 } from "node:fs";
|
|
18055
|
+
import { dirname as dirname19, join as join27, resolve as resolve12 } from "node:path";
|
|
17637
18056
|
var BUNDLES = [
|
|
17638
18057
|
["Terminal", "Terminal.app"],
|
|
17639
18058
|
["iTerm", "iTerm.app"],
|
|
@@ -17644,11 +18063,11 @@ var BUNDLES = [
|
|
|
17644
18063
|
["kitty", "kitty.app"],
|
|
17645
18064
|
["VS Code", "Visual Studio Code.app"]
|
|
17646
18065
|
];
|
|
17647
|
-
function detectReturnTargets(homeDir, roots = ["/Applications",
|
|
18066
|
+
function detectReturnTargets(homeDir, roots = ["/Applications", join27(homeDir, "Applications")]) {
|
|
17648
18067
|
const available = [];
|
|
17649
18068
|
for (const [name, bundle] of BUNDLES) {
|
|
17650
|
-
for (const root of new Set(roots.map((root2) =>
|
|
17651
|
-
const bundlePath =
|
|
18069
|
+
for (const root of new Set(roots.map((root2) => resolve12(root2)))) {
|
|
18070
|
+
const bundlePath = join27(root, bundle);
|
|
17652
18071
|
try {
|
|
17653
18072
|
if (statSync6(bundlePath).isDirectory())
|
|
17654
18073
|
available.push({ name, bundlePath });
|
|
@@ -17659,12 +18078,12 @@ function detectReturnTargets(homeDir, roots = ["/Applications", join24(homeDir,
|
|
|
17659
18078
|
return available;
|
|
17660
18079
|
}
|
|
17661
18080
|
function settingsPath(homeDir) {
|
|
17662
|
-
return
|
|
18081
|
+
return join27(homeDir, ".wingman", "state", "settings.json");
|
|
17663
18082
|
}
|
|
17664
18083
|
function readReturnTargetSettings(homeDir) {
|
|
17665
18084
|
let raw;
|
|
17666
18085
|
try {
|
|
17667
|
-
raw =
|
|
18086
|
+
raw = readFileSync18(settingsPath(homeDir), "utf8");
|
|
17668
18087
|
} catch (error) {
|
|
17669
18088
|
if (isRecord8(error) && error.code === "ENOENT")
|
|
17670
18089
|
return { version: 1 };
|
|
@@ -17685,10 +18104,10 @@ function saveReturnTarget(homeDir, bundlePath) {
|
|
|
17685
18104
|
return current;
|
|
17686
18105
|
const settings = { version: 1, returnTarget: { bundlePath } };
|
|
17687
18106
|
const path = settingsPath(homeDir);
|
|
17688
|
-
const tempPath =
|
|
18107
|
+
const tempPath = join27(dirname19(path), `.settings-${randomBytes5(8).toString("hex")}.tmp`);
|
|
17689
18108
|
let fd;
|
|
17690
18109
|
try {
|
|
17691
|
-
|
|
18110
|
+
mkdirSync13(dirname19(path), { recursive: true, mode: 448 });
|
|
17692
18111
|
try {
|
|
17693
18112
|
copyFileSync2(path, `${path}.bak`);
|
|
17694
18113
|
} catch (error) {
|
|
@@ -17696,7 +18115,7 @@ function saveReturnTarget(homeDir, bundlePath) {
|
|
|
17696
18115
|
throw error;
|
|
17697
18116
|
}
|
|
17698
18117
|
fd = openSync4(tempPath, "wx", 384);
|
|
17699
|
-
|
|
18118
|
+
writeFileSync14(fd, `${JSON.stringify(settings)}
|
|
17700
18119
|
`, "utf8");
|
|
17701
18120
|
closeSync4(fd);
|
|
17702
18121
|
fd = void 0;
|
|
@@ -17712,7 +18131,7 @@ function saveReturnTarget(homeDir, bundlePath) {
|
|
|
17712
18131
|
}
|
|
17713
18132
|
}
|
|
17714
18133
|
try {
|
|
17715
|
-
|
|
18134
|
+
rmSync11(tempPath, { force: true });
|
|
17716
18135
|
} catch {
|
|
17717
18136
|
}
|
|
17718
18137
|
}
|
|
@@ -18037,8 +18456,18 @@ async function handle(req, res, options, warn, runtime) {
|
|
|
18037
18456
|
}
|
|
18038
18457
|
if (url.pathname === "/api/anatomy") {
|
|
18039
18458
|
const configs = await scanAll(options.harnesses, warn);
|
|
18459
|
+
const anatomy = configs.map((config) => {
|
|
18460
|
+
const scanOptions = options.harnesses.find((entry) => entry.harness === config.harness)?.scanOptions;
|
|
18461
|
+
const homeDir = scanOptions?.homeDir ?? options.homeDir;
|
|
18462
|
+
if (homeDir === void 0)
|
|
18463
|
+
throw new Error("anatomy \u9700\u8981\u663E\u5F0F homeDir");
|
|
18464
|
+
const user = config.harness === "cc" ? protocolStatusCcUser({ homeDir }).state : config.harness === "codex" ? protocolStatusCodexUser({ homeDir }).state : "unsupported";
|
|
18465
|
+
const projectDir = scanOptions?.projectDir;
|
|
18466
|
+
const project = projectDir === void 0 ? "not_installed" : config.harness === "cc" ? protocolStatusCc({ homeDir, projectDir }).state : protocolStatusCodex({ homeDir, projectDir }).state;
|
|
18467
|
+
return { ...config, planProtocol: { user, project } };
|
|
18468
|
+
});
|
|
18040
18469
|
res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
18041
|
-
res.end(JSON.stringify(
|
|
18470
|
+
res.end(JSON.stringify(anatomy));
|
|
18042
18471
|
return;
|
|
18043
18472
|
}
|
|
18044
18473
|
if (url.pathname === "/api/version") {
|
|
@@ -18157,6 +18586,10 @@ async function handleActionPlan(req, res, options) {
|
|
|
18157
18586
|
sendJson2(res, 400, { error: "\u8BF7\u6C42\u4F53\u5FC5\u987B\u662F\u5408\u6CD5 JSON" });
|
|
18158
18587
|
return;
|
|
18159
18588
|
}
|
|
18589
|
+
if (isProtocolUserRequest(body)) {
|
|
18590
|
+
handleProtocolUserAction(body, res, options);
|
|
18591
|
+
return;
|
|
18592
|
+
}
|
|
18160
18593
|
const { harness, action } = body;
|
|
18161
18594
|
const loaded = pickHarness(options, harness);
|
|
18162
18595
|
if (!loaded) {
|
|
@@ -18188,6 +18621,10 @@ async function handleActionApply(req, res, options, runtime) {
|
|
|
18188
18621
|
sendJson2(res, 400, { error: "\u8BF7\u6C42\u4F53\u5FC5\u987B\u662F\u5408\u6CD5 JSON" });
|
|
18189
18622
|
return;
|
|
18190
18623
|
}
|
|
18624
|
+
if (isProtocolUserRequest(body)) {
|
|
18625
|
+
handleProtocolUserAction(body, res, options, runtime);
|
|
18626
|
+
return;
|
|
18627
|
+
}
|
|
18191
18628
|
const { harness, plan } = body;
|
|
18192
18629
|
const loaded = pickHarness(options, harness);
|
|
18193
18630
|
if (!loaded) {
|
|
@@ -18199,15 +18636,68 @@ async function handleActionApply(req, res, options, runtime) {
|
|
|
18199
18636
|
return;
|
|
18200
18637
|
}
|
|
18201
18638
|
try {
|
|
18202
|
-
const
|
|
18203
|
-
if (
|
|
18639
|
+
const result5 = await loaded.adapter.applyAction(plan, loaded.scanOptions);
|
|
18640
|
+
if (result5.ok) {
|
|
18204
18641
|
runtime.anatomy = null;
|
|
18205
18642
|
}
|
|
18206
|
-
sendJson2(res, 200,
|
|
18643
|
+
sendJson2(res, 200, result5);
|
|
18207
18644
|
} catch (error) {
|
|
18208
18645
|
sendJson2(res, 400, { error: errorMessage3(error) });
|
|
18209
18646
|
}
|
|
18210
18647
|
}
|
|
18648
|
+
function isProtocolUserRequest(body) {
|
|
18649
|
+
return isRecord9(body) && (body.kind === "protocol_user_install" || body.kind === "protocol_user_uninstall");
|
|
18650
|
+
}
|
|
18651
|
+
function handleProtocolUserAction(body, res, options, runtime) {
|
|
18652
|
+
if (options.readonlyActions) {
|
|
18653
|
+
sendJson2(res, 403, { error: "fixtures \u6A21\u5F0F\u53EA\u8BFB:\u4E0D\u9884\u89C8\u6216\u5199\u5165\u7528\u6237\u7EA7\u534F\u8BAE" });
|
|
18654
|
+
return;
|
|
18655
|
+
}
|
|
18656
|
+
if (body.harness === "dsh") {
|
|
18657
|
+
sendJson2(res, 400, { error: "unsupported: dsh \u65E0\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6\uFF0C\u8BF7\u6309\u9879\u76EE\u5B89\u88C5\u8BA1\u5212\u534F\u8BAE" });
|
|
18658
|
+
return;
|
|
18659
|
+
}
|
|
18660
|
+
const loaded = pickHarness(options, body.harness);
|
|
18661
|
+
if (!loaded || body.harness !== "cc" && body.harness !== "codex") {
|
|
18662
|
+
sendJson2(res, 400, { error: "\u7528\u6237\u7EA7\u8BA1\u5212\u534F\u8BAE harness \u9700\u8981 cc|codex" });
|
|
18663
|
+
return;
|
|
18664
|
+
}
|
|
18665
|
+
const homeDir = loaded.scanOptions.homeDir ?? options.homeDir;
|
|
18666
|
+
if (homeDir === void 0) {
|
|
18667
|
+
sendJson2(res, 500, { error: "\u7528\u6237\u7EA7\u8BA1\u5212\u534F\u8BAE\u9700\u8981\u663E\u5F0F homeDir" });
|
|
18668
|
+
return;
|
|
18669
|
+
}
|
|
18670
|
+
const install = body.kind === "protocol_user_install";
|
|
18671
|
+
const operation = body.harness === "cc" ? install ? installProtocolCcUser : uninstallProtocolCcUser : install ? installProtocolCodexUser : uninstallProtocolCodexUser;
|
|
18672
|
+
try {
|
|
18673
|
+
const result5 = operation({ homeDir, dryRun: runtime === void 0 });
|
|
18674
|
+
if (runtime === void 0) {
|
|
18675
|
+
const before = splitPlanProtocolBlock(result5.before, result5.targetPath, "user");
|
|
18676
|
+
const after = splitPlanProtocolBlock(result5.after, result5.targetPath, "user");
|
|
18677
|
+
const block = install ? after.block : before.block;
|
|
18678
|
+
sendJson2(res, 200, {
|
|
18679
|
+
kind: body.kind,
|
|
18680
|
+
harness: body.harness,
|
|
18681
|
+
targetPath: body.harness === "cc" ? "~/.claude/CLAUDE.md" : "~/.codex/AGENTS.md",
|
|
18682
|
+
hasBlock: before.block !== void 0,
|
|
18683
|
+
...install && before.version !== void 0 && after.version !== void 0 && before.version < after.version ? { fromVersion: before.version, toVersion: after.version } : {},
|
|
18684
|
+
blockBytes: Buffer.byteLength(block ?? ""),
|
|
18685
|
+
backupDir: "~/.wingman/backups/<ISO \u65F6\u95F4\u6233>\uFF08\u91CD\u540D\u8FFD\u52A0 -N\uFF09",
|
|
18686
|
+
hostname: hostname()
|
|
18687
|
+
});
|
|
18688
|
+
} else {
|
|
18689
|
+
runtime.anatomy = null;
|
|
18690
|
+
const user = body.harness === "cc" ? protocolStatusCcUser({ homeDir }).state : protocolStatusCodexUser({ homeDir }).state;
|
|
18691
|
+
sendJson2(res, 200, {
|
|
18692
|
+
ok: true,
|
|
18693
|
+
planProtocol: { user },
|
|
18694
|
+
...result5.backupDir === void 0 ? {} : { backupDir: `~/${relative4(homeDir, result5.backupDir).split(sep2).join("/")}` }
|
|
18695
|
+
});
|
|
18696
|
+
}
|
|
18697
|
+
} catch (error) {
|
|
18698
|
+
sendJson2(res, 400, { error: errorSummary(error) });
|
|
18699
|
+
}
|
|
18700
|
+
}
|
|
18211
18701
|
async function handleReturn(req, res, options, activate) {
|
|
18212
18702
|
if (req.method !== "POST" && (activate || req.method !== "GET")) {
|
|
18213
18703
|
sendText2(res, 405, "method not allowed");
|
|
@@ -18283,12 +18773,12 @@ async function handleTaskOverlay(req, res, options) {
|
|
|
18283
18773
|
return;
|
|
18284
18774
|
}
|
|
18285
18775
|
const key = `${body.harness}:${body.sessionId}`;
|
|
18286
|
-
const
|
|
18287
|
-
if ("unavailable" in
|
|
18288
|
-
sendJson2(res, 409, { error:
|
|
18776
|
+
const result5 = patchTaskOverlay(options.homeDir, key, body.patch, /* @__PURE__ */ new Date());
|
|
18777
|
+
if ("unavailable" in result5) {
|
|
18778
|
+
sendJson2(res, 409, { error: result5.unavailable });
|
|
18289
18779
|
return;
|
|
18290
18780
|
}
|
|
18291
|
-
sendJson2(res, 200, { key, entry:
|
|
18781
|
+
sendJson2(res, 200, { key, entry: result5.entry });
|
|
18292
18782
|
}
|
|
18293
18783
|
var LICENSE_BODY_LIMIT = 64 * 1024;
|
|
18294
18784
|
async function handleLicenseInstall(req, res, options) {
|
|
@@ -18297,12 +18787,12 @@ async function handleLicenseInstall(req, res, options) {
|
|
|
18297
18787
|
sendJson2(res, 400, { error: "license \u6587\u4EF6\u8D85\u8FC7 64KB \u4E0A\u9650\u6216\u8BFB\u53D6\u5931\u8D25" });
|
|
18298
18788
|
return;
|
|
18299
18789
|
}
|
|
18300
|
-
const
|
|
18301
|
-
if (!
|
|
18302
|
-
sendJson2(res, 400, { error:
|
|
18790
|
+
const result5 = installLicense(raw, options.licenseOptions);
|
|
18791
|
+
if (!result5.ok) {
|
|
18792
|
+
sendJson2(res, 400, { error: result5.error });
|
|
18303
18793
|
return;
|
|
18304
18794
|
}
|
|
18305
|
-
sendJson2(res, 200, publicLicenseStatus(
|
|
18795
|
+
sendJson2(res, 200, publicLicenseStatus(result5.status));
|
|
18306
18796
|
}
|
|
18307
18797
|
async function handleLicenseRefresh(res, options) {
|
|
18308
18798
|
const homeDir = options.licenseRefreshOptions?.homeDir ?? options.licenseOptions?.homeDir;
|
|
@@ -18314,11 +18804,11 @@ async function handleLicenseRefresh(res, options) {
|
|
|
18314
18804
|
...publicKeyPem === void 0 ? {} : { publicKeyPem },
|
|
18315
18805
|
...now === void 0 ? {} : { now }
|
|
18316
18806
|
};
|
|
18317
|
-
const
|
|
18318
|
-
if (!
|
|
18807
|
+
const result5 = await refreshLicense(refreshOptions);
|
|
18808
|
+
if (!result5.ok) {
|
|
18319
18809
|
sendJson2(res, 400, {
|
|
18320
|
-
error:
|
|
18321
|
-
canSubscribe:
|
|
18810
|
+
error: result5.message,
|
|
18811
|
+
canSubscribe: result5.reason === "inactive"
|
|
18322
18812
|
});
|
|
18323
18813
|
return;
|
|
18324
18814
|
}
|
|
@@ -18330,7 +18820,7 @@ async function handleLicenseRefresh(res, options) {
|
|
|
18330
18820
|
};
|
|
18331
18821
|
sendJson2(res, 200, {
|
|
18332
18822
|
...publicLicenseStatus(licenseStatus(statusOptions)),
|
|
18333
|
-
message:
|
|
18823
|
+
message: result5.message
|
|
18334
18824
|
});
|
|
18335
18825
|
}
|
|
18336
18826
|
function publicLicenseStatus(status3) {
|
|
@@ -18425,8 +18915,8 @@ async function serveStatic(pathname, res, panelDistDir) {
|
|
|
18425
18915
|
return;
|
|
18426
18916
|
}
|
|
18427
18917
|
const rel = decoded === "/" ? "/index.html" : decoded;
|
|
18428
|
-
const distDir =
|
|
18429
|
-
const filePath =
|
|
18918
|
+
const distDir = resolve13(panelDistDir);
|
|
18919
|
+
const filePath = resolve13(distDir, `.${rel}`);
|
|
18430
18920
|
if (filePath !== distDir && !filePath.startsWith(distDir + sep2)) {
|
|
18431
18921
|
sendText2(res, 403, "forbidden");
|
|
18432
18922
|
return;
|
|
@@ -18463,8 +18953,8 @@ var HELP = `wingman \u2014 Not your copilot. Your wingman.
|
|
|
18463
18953
|
wingman hook install <harness> [--port 7333] \u5B9E\u51B5\u63A5\u7EBF(\u5199\u524D\u5907\u4EFD,\u5E42\u7B49)
|
|
18464
18954
|
[--profile <p>] dsh:\u53EA\u5904\u7406\u6307\u5B9A profile
|
|
18465
18955
|
wingman hook uninstall <harness> [--profile <p>] \u89E3\u7EBF(\u914D\u7F6E\u6062\u590D,\u5E42\u7B49)
|
|
18466
|
-
wingman protocol install|uninstall|status <harness> \
|
|
18467
|
-
[--project <dir>] [--dry-run] [--yes]
|
|
18956
|
+
wingman protocol install|uninstall|status <harness> \u7BA1\u7406\u7528\u6237\u7EA7 / \u9879\u76EE\u7EA7 Plan Protocol
|
|
18957
|
+
[--project <dir> | --user] [--dry-run] [--yes]
|
|
18468
18958
|
wingman license status \u67E5\u770B\u8BA2\u9605\u72B6\u6001(\u5199\u52A8\u4F5C\u7684\u95F8)
|
|
18469
18959
|
wingman license refresh \u8054\u7F51\u5411\u7B7E\u53D1\u7AEF\u6362\u65B0 license(\u7EED\u671F)
|
|
18470
18960
|
wingman --version | -v | version \u663E\u793A\u7248\u672C
|
|
@@ -18493,7 +18983,7 @@ async function main(argv) {
|
|
|
18493
18983
|
case "hook":
|
|
18494
18984
|
return runHook(rest);
|
|
18495
18985
|
case "protocol":
|
|
18496
|
-
return runProtocolCli(rest);
|
|
18986
|
+
return runProtocolCli(rest, { homeDir: homedir16() });
|
|
18497
18987
|
case "license": {
|
|
18498
18988
|
if (rest[0] === "status") {
|
|
18499
18989
|
const status3 = licenseStatus();
|
|
@@ -18502,10 +18992,10 @@ async function main(argv) {
|
|
|
18502
18992
|
return 0;
|
|
18503
18993
|
}
|
|
18504
18994
|
if (rest[0] === "refresh") {
|
|
18505
|
-
const
|
|
18506
|
-
process.stdout.write(`${
|
|
18995
|
+
const result5 = await refreshLicense();
|
|
18996
|
+
process.stdout.write(`${result5.message}
|
|
18507
18997
|
`);
|
|
18508
|
-
if (!
|
|
18998
|
+
if (!result5.ok)
|
|
18509
18999
|
return 1;
|
|
18510
19000
|
const status3 = licenseStatus();
|
|
18511
19001
|
process.stdout.write(`${status3.state}:${status3.detail}
|
|
@@ -18544,7 +19034,7 @@ ${counts}
|
|
|
18544
19034
|
}
|
|
18545
19035
|
async function runServe(args) {
|
|
18546
19036
|
const { port, fixtures, panelDist } = parseServeArgs(args);
|
|
18547
|
-
const homeDir = fixtures ? fixturesRoot :
|
|
19037
|
+
const homeDir = fixtures ? fixturesRoot : homedir16();
|
|
18548
19038
|
const hookToken = createHookToken();
|
|
18549
19039
|
let dshRetirementNotice;
|
|
18550
19040
|
if (!fixtures) {
|
|
@@ -18579,7 +19069,7 @@ async function runServe(args) {
|
|
|
18579
19069
|
`);
|
|
18580
19070
|
}
|
|
18581
19071
|
}
|
|
18582
|
-
const panelDistDir = panelDist === void 0 ?
|
|
19072
|
+
const panelDistDir = panelDist === void 0 ? resolve14(dirname20(fileURLToPath2(import.meta.url)), "../../panel/dist") : resolve14(panelDist);
|
|
18583
19073
|
const narrative = createNarrativeService({
|
|
18584
19074
|
followTranscripts: !fixtures,
|
|
18585
19075
|
homeDir,
|
|
@@ -18592,7 +19082,7 @@ async function runServe(args) {
|
|
|
18592
19082
|
});
|
|
18593
19083
|
if (fixtures) {
|
|
18594
19084
|
try {
|
|
18595
|
-
const raw =
|
|
19085
|
+
const raw = readFileSync19(fixturePath("cc", "sessions", "session-todos.jsonl"), "utf8");
|
|
18596
19086
|
narrative.seedFixture("cc", raw.split("\n"), "MOCK \u2014 fixtures \u6F14\u793A:\u53D9\u4E8B\u6570\u636E\u6765\u81EA packages/fixtures \u7684 session-todos.jsonl \u6837\u4F8B\u4F1A\u8BDD,\u975E\u672C\u673A\u771F\u5B9E transcript\u3002");
|
|
18597
19087
|
} catch (error) {
|
|
18598
19088
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -18666,8 +19156,8 @@ async function runHook(args) {
|
|
|
18666
19156
|
const { adapter, scanOptions } = await loadHarness(harness, { fixtures: false });
|
|
18667
19157
|
if (action === "install") {
|
|
18668
19158
|
if (harness === "dsh") {
|
|
18669
|
-
const
|
|
18670
|
-
writeDshInstallReport(await dshHookInstallReport(scanOptions),
|
|
19159
|
+
const result5 = await installDshHooks(port, scanOptions);
|
|
19160
|
+
writeDshInstallReport(await dshHookInstallReport(scanOptions), result5);
|
|
18671
19161
|
process.stdout.write(`wingman:dsh profile \u63A5\u7EBF\u5904\u7406\u5B8C\u6210(POST http://127.0.0.1:${port}/hook?harness=dsh)\u3002
|
|
18672
19162
|
\u5199\u524D\u5DF2\u5907\u4EFD;\u91CD\u590D\u6267\u884C\u5E42\u7B49;\u89E3\u7EBF:wingman hook uninstall dsh
|
|
18673
19163
|
`);
|
|
@@ -18681,14 +19171,14 @@ async function runHook(args) {
|
|
|
18681
19171
|
`);
|
|
18682
19172
|
}
|
|
18683
19173
|
} else if (harness === "dsh") {
|
|
18684
|
-
const
|
|
19174
|
+
const result5 = await uninstallDshHooks(scanOptions);
|
|
18685
19175
|
const messages = {
|
|
18686
19176
|
unwired: "\u5DF2\u89E3\u7EBF",
|
|
18687
19177
|
state: "\u5DF2\u6062\u590D",
|
|
18688
19178
|
removed: "\u5DF2\u79FB\u9664\u6B8B\u7559\u5757",
|
|
18689
19179
|
cleared: "\u5DF2\u6E05\u7406\u8BB0\u5F55"
|
|
18690
19180
|
};
|
|
18691
|
-
for (const profile2 of
|
|
19181
|
+
for (const profile2 of result5.profiles) {
|
|
18692
19182
|
process.stdout.write(`${profile2.profile}:${messages[profile2.restored]}
|
|
18693
19183
|
`);
|
|
18694
19184
|
}
|
|
@@ -18709,16 +19199,16 @@ function writeDshInstallReport(report, installResult) {
|
|
|
18709
19199
|
process.stdout.write("\u672A\u53D1\u73B0\u542B package.json \u7684 dsh profile\u3002\n");
|
|
18710
19200
|
return;
|
|
18711
19201
|
}
|
|
18712
|
-
for (const
|
|
18713
|
-
if (
|
|
18714
|
-
process.stdout.write(`${
|
|
19202
|
+
for (const result5 of report.profiles) {
|
|
19203
|
+
if (result5.wired) {
|
|
19204
|
+
process.stdout.write(`${result5.profile}:\u5DF2\u63A5\u7EBF
|
|
18715
19205
|
`);
|
|
18716
|
-
} else if (
|
|
18717
|
-
const removed = installResult.removedProfiles.includes(
|
|
18718
|
-
process.stdout.write(`${
|
|
19206
|
+
} else if (result5.missingPackages.length > 0) {
|
|
19207
|
+
const removed = installResult.removedProfiles.includes(result5.profile) ? "\u5DF2\u79FB\u9664\u65E7\u63A5\u7EBF\u5757," : "";
|
|
19208
|
+
process.stdout.write(`${result5.profile}:\u672A\u63A5\u7EBF,${removed}\u7F3A ${result5.missingPackages.join("\u3001")} \u2192 ${result5.installCommand ?? ""}
|
|
18719
19209
|
`);
|
|
18720
19210
|
} else {
|
|
18721
|
-
process.stdout.write(`${
|
|
19211
|
+
process.stdout.write(`${result5.profile}:\u672A\u63A5\u7EBF
|
|
18722
19212
|
`);
|
|
18723
19213
|
}
|
|
18724
19214
|
}
|
|
@@ -18798,7 +19288,7 @@ main(process.argv.slice(2)).then((code) => {
|
|
|
18798
19288
|
process.stderr.write(`
|
|
18799
19289
|
${HELP}`);
|
|
18800
19290
|
}
|
|
18801
|
-
process.exitCode = 1;
|
|
19291
|
+
process.exitCode = error instanceof ProtocolUsageError ? 2 : 1;
|
|
18802
19292
|
});
|
|
18803
19293
|
/*! Bundled license information:
|
|
18804
19294
|
|