@p4code/cli 0.4.11 → 0.4.13
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/dist/bin.mjs +415 -111
- package/dist/client/assets/{DiffPanel-j6MuEGOs.js → DiffPanel-DWdPV3K3.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-CcQBW0Vz.js → FilePreviewPanel-Djvz8ttF.js} +2 -2
- package/dist/client/assets/{PreviewPanel-C313NMXG.js → PreviewPanel-DbeIwgC3.js} +2 -2
- package/dist/client/assets/{PullRequestCodeTab-BdwnQcgi.js → PullRequestCodeTab-cFyorjex.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-CxfDb72Y.js → fileCommentAnnotations-Ddmzci4v.js} +2 -2
- package/dist/client/assets/{index-BWxnfRz6.js → index-CBqRo4NV.js} +16 -6
- package/dist/client/assets/{renderFileChildren-cnLyJS2T.js → renderFileChildren--IZ7ujV7.js} +2 -2
- package/dist/client/assets/{toggle-group-BCVKadvc.js → toggle-group-U3M0YUkk.js} +2 -2
- package/dist/client/index.html +1 -1
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -240,7 +240,7 @@ const make$93 = () => {
|
|
|
240
240
|
const layer$82 = Layer.sync(NetService, make$93);
|
|
241
241
|
//#endregion
|
|
242
242
|
//#region package.json
|
|
243
|
-
var version = "0.4.
|
|
243
|
+
var version = "0.4.13";
|
|
244
244
|
//#endregion
|
|
245
245
|
//#region src/config.ts
|
|
246
246
|
/**
|
|
@@ -23553,8 +23553,8 @@ const removeMemoryFile = Effect.fn("memoryFile.removeMemoryFile")(function* (inp
|
|
|
23553
23553
|
* config directory — the one holding `.credentials.json` — instead of a managed
|
|
23554
23554
|
* home the user would have to log in to again. See `docs/architecture/hub.md`.
|
|
23555
23555
|
*
|
|
23556
|
-
* Keyed by skills directory so
|
|
23557
|
-
*
|
|
23556
|
+
* Keyed by skills directory so ownership can move safely when the configured
|
|
23557
|
+
* provider path migrates to the provider-neutral shared root.
|
|
23558
23558
|
*
|
|
23559
23559
|
* @module sync/skillManifest
|
|
23560
23560
|
*/
|
|
@@ -23596,6 +23596,20 @@ const withEntriesFor = (manifest, skillsRoot, entries) => ({
|
|
|
23596
23596
|
[skillsRoot]: [...entries].sort((left, right) => left.name.localeCompare(right.name))
|
|
23597
23597
|
}
|
|
23598
23598
|
});
|
|
23599
|
+
const moveEntriesFor = (manifest, sourceRoot, targetRoot) => {
|
|
23600
|
+
if (sourceRoot === targetRoot || manifest.directories[sourceRoot] === void 0) return manifest;
|
|
23601
|
+
const { [sourceRoot]: sourceEntries, ...directories } = manifest.directories;
|
|
23602
|
+
const targetEntries = directories[targetRoot] ?? [];
|
|
23603
|
+
const merged = new Map(targetEntries.map((entry) => [entry.name, entry]));
|
|
23604
|
+
for (const entry of sourceEntries ?? []) merged.set(entry.name, entry);
|
|
23605
|
+
return {
|
|
23606
|
+
version: 1,
|
|
23607
|
+
directories: {
|
|
23608
|
+
...directories,
|
|
23609
|
+
[targetRoot]: [...merged.values()].sort((left, right) => left.name.localeCompare(right.name))
|
|
23610
|
+
}
|
|
23611
|
+
};
|
|
23612
|
+
};
|
|
23599
23613
|
const writeSkillManifest = Effect.fn("skillManifest.write")(function* (manifestPath, manifest) {
|
|
23600
23614
|
yield* writeFileStringAtomically({
|
|
23601
23615
|
filePath: manifestPath,
|
|
@@ -23804,6 +23818,170 @@ function planSkillSync(input) {
|
|
|
23804
23818
|
};
|
|
23805
23819
|
}
|
|
23806
23820
|
//#endregion
|
|
23821
|
+
//#region src/sync/sharedSkillRoot.ts
|
|
23822
|
+
const SHARED_SKILL_ROOT_REFUSAL = "shared-root-migration-blocked";
|
|
23823
|
+
const inspectLayout = Effect.fn("sharedSkillRoot.inspectLayout")(function* (input) {
|
|
23824
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
23825
|
+
const path = yield* Path.Path;
|
|
23826
|
+
const targetRoot = path.resolve(input.sharedSkillsRoot ?? path.join(NodeOS.homedir(), ".agents", "skills"));
|
|
23827
|
+
const claudeRoot = path.resolve(input.claudeSkillsRoot);
|
|
23828
|
+
const manifest = yield* readSkillManifest(input.manifestPath);
|
|
23829
|
+
if (claudeRoot === targetRoot) return {
|
|
23830
|
+
claudeRoot,
|
|
23831
|
+
targetRoot,
|
|
23832
|
+
manifest,
|
|
23833
|
+
entries: [],
|
|
23834
|
+
candidateSkillNames: [],
|
|
23835
|
+
ignoredEntries: [],
|
|
23836
|
+
refused: [],
|
|
23837
|
+
linked: true,
|
|
23838
|
+
exists: yield* fileSystem.exists(targetRoot)
|
|
23839
|
+
};
|
|
23840
|
+
const linkedTarget = yield* fileSystem.readLink(claudeRoot).pipe(Effect.map((target) => path.resolve(path.dirname(claudeRoot), target)), Effect.option);
|
|
23841
|
+
if (linkedTarget._tag === "Some") return {
|
|
23842
|
+
claudeRoot,
|
|
23843
|
+
targetRoot,
|
|
23844
|
+
manifest,
|
|
23845
|
+
entries: [],
|
|
23846
|
+
candidateSkillNames: [],
|
|
23847
|
+
ignoredEntries: [],
|
|
23848
|
+
refused: linkedTarget.value === targetRoot ? [] : [{
|
|
23849
|
+
name: claudeRoot,
|
|
23850
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
23851
|
+
}],
|
|
23852
|
+
linked: linkedTarget.value === targetRoot,
|
|
23853
|
+
exists: true
|
|
23854
|
+
};
|
|
23855
|
+
const exists = yield* fileSystem.exists(claudeRoot);
|
|
23856
|
+
if (exists) {
|
|
23857
|
+
const sourceDevice = (yield* fileSystem.stat(claudeRoot)).dev;
|
|
23858
|
+
let targetProbe = targetRoot;
|
|
23859
|
+
while (!(yield* fileSystem.exists(targetProbe))) {
|
|
23860
|
+
const parent = path.dirname(targetProbe);
|
|
23861
|
+
if (parent === targetProbe) break;
|
|
23862
|
+
targetProbe = parent;
|
|
23863
|
+
}
|
|
23864
|
+
if (sourceDevice !== (yield* fileSystem.stat(targetProbe)).dev) return {
|
|
23865
|
+
claudeRoot,
|
|
23866
|
+
targetRoot,
|
|
23867
|
+
manifest,
|
|
23868
|
+
entries: [],
|
|
23869
|
+
candidateSkillNames: [],
|
|
23870
|
+
ignoredEntries: [],
|
|
23871
|
+
refused: [{
|
|
23872
|
+
name: claudeRoot,
|
|
23873
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
23874
|
+
}],
|
|
23875
|
+
linked: false,
|
|
23876
|
+
exists
|
|
23877
|
+
};
|
|
23878
|
+
}
|
|
23879
|
+
const entries = exists ? yield* fileSystem.readDirectory(claudeRoot) : [];
|
|
23880
|
+
const managedNames = new Set(entriesFor(manifest, claudeRoot).map((entry) => entry.name));
|
|
23881
|
+
const candidateSkillNames = [];
|
|
23882
|
+
const ignoredEntries = [];
|
|
23883
|
+
const strayEntries = [];
|
|
23884
|
+
for (const entry of entries) {
|
|
23885
|
+
if (isIgnoredEntry(entry)) {
|
|
23886
|
+
ignoredEntries.push(entry);
|
|
23887
|
+
continue;
|
|
23888
|
+
}
|
|
23889
|
+
const entryPath = path.join(claudeRoot, entry);
|
|
23890
|
+
if ((yield* fileSystem.stat(entryPath)).type === "Directory" && (yield* fileSystem.exists(path.join(entryPath, "SKILL.md")))) candidateSkillNames.push(entry);
|
|
23891
|
+
else strayEntries.push(entry);
|
|
23892
|
+
}
|
|
23893
|
+
return {
|
|
23894
|
+
claudeRoot,
|
|
23895
|
+
targetRoot,
|
|
23896
|
+
manifest,
|
|
23897
|
+
entries,
|
|
23898
|
+
candidateSkillNames,
|
|
23899
|
+
ignoredEntries,
|
|
23900
|
+
refused: [...candidateSkillNames.filter((entry) => !managedNames.has(entry)), ...strayEntries].map((name) => ({
|
|
23901
|
+
name,
|
|
23902
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
23903
|
+
})),
|
|
23904
|
+
linked: false,
|
|
23905
|
+
exists
|
|
23906
|
+
};
|
|
23907
|
+
});
|
|
23908
|
+
/** Read-only root resolution used by status and previews. */
|
|
23909
|
+
const inspectSharedSkillRoot = Effect.fn("sharedSkillRoot.inspect")(function* (input) {
|
|
23910
|
+
const layout = yield* inspectLayout(input);
|
|
23911
|
+
if (layout.refused.length > 0) return {
|
|
23912
|
+
root: null,
|
|
23913
|
+
refused: layout.refused
|
|
23914
|
+
};
|
|
23915
|
+
return {
|
|
23916
|
+
root: layout.linked || !layout.exists ? layout.targetRoot : layout.claudeRoot,
|
|
23917
|
+
refused: []
|
|
23918
|
+
};
|
|
23919
|
+
});
|
|
23920
|
+
/**
|
|
23921
|
+
* Make Claude's configured skill path an alias of the provider-neutral user
|
|
23922
|
+
* skill root. Existing unmanaged content is never moved or replaced.
|
|
23923
|
+
*/
|
|
23924
|
+
const prepareSharedSkillRoot = Effect.fn("sharedSkillRoot.prepare")(function* (input) {
|
|
23925
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
23926
|
+
const path = yield* Path.Path;
|
|
23927
|
+
const layout = yield* inspectLayout(input);
|
|
23928
|
+
const { candidateSkillNames, claudeRoot, ignoredEntries, manifest, targetRoot } = layout;
|
|
23929
|
+
if (layout.refused.length > 0) return {
|
|
23930
|
+
root: null,
|
|
23931
|
+
refused: layout.refused
|
|
23932
|
+
};
|
|
23933
|
+
if (layout.linked) {
|
|
23934
|
+
yield* fileSystem.makeDirectory(targetRoot, { recursive: true });
|
|
23935
|
+
const migrated = moveEntriesFor(manifest, claudeRoot, targetRoot);
|
|
23936
|
+
if (migrated !== manifest) yield* writeSkillManifest(input.manifestPath, migrated);
|
|
23937
|
+
return {
|
|
23938
|
+
root: targetRoot,
|
|
23939
|
+
refused: []
|
|
23940
|
+
};
|
|
23941
|
+
}
|
|
23942
|
+
if (layout.exists) if (!(yield* fileSystem.exists(targetRoot))) {
|
|
23943
|
+
yield* fileSystem.makeDirectory(path.dirname(targetRoot), { recursive: true });
|
|
23944
|
+
yield* fileSystem.rename(claudeRoot, targetRoot);
|
|
23945
|
+
} else {
|
|
23946
|
+
const backupRoot = `${claudeRoot}.p4code-migrated`;
|
|
23947
|
+
if (ignoredEntries.length > 0 && (yield* fileSystem.exists(backupRoot))) return {
|
|
23948
|
+
root: null,
|
|
23949
|
+
refused: [{
|
|
23950
|
+
name: backupRoot,
|
|
23951
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
23952
|
+
}]
|
|
23953
|
+
};
|
|
23954
|
+
const targetEntries = new Set(yield* fileSystem.readDirectory(targetRoot));
|
|
23955
|
+
const collisions = candidateSkillNames.filter((entry) => targetEntries.has(entry));
|
|
23956
|
+
if (collisions.length > 0) return {
|
|
23957
|
+
root: null,
|
|
23958
|
+
refused: collisions.map((name) => ({
|
|
23959
|
+
name,
|
|
23960
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
23961
|
+
}))
|
|
23962
|
+
};
|
|
23963
|
+
for (const entry of candidateSkillNames) yield* fileSystem.rename(path.join(claudeRoot, entry), path.join(targetRoot, entry));
|
|
23964
|
+
}
|
|
23965
|
+
else {
|
|
23966
|
+
yield* fileSystem.makeDirectory(targetRoot, { recursive: true });
|
|
23967
|
+
yield* fileSystem.makeDirectory(path.dirname(claudeRoot), { recursive: true });
|
|
23968
|
+
}
|
|
23969
|
+
const stagedLink = `${claudeRoot}.p4code-link`;
|
|
23970
|
+
yield* fileSystem.remove(stagedLink, { force: true });
|
|
23971
|
+
yield* fileSystem.symlink(targetRoot, stagedLink);
|
|
23972
|
+
if (layout.exists && (yield* fileSystem.exists(claudeRoot))) if (ignoredEntries.length > 0) {
|
|
23973
|
+
const backupRoot = `${claudeRoot}.p4code-migrated`;
|
|
23974
|
+
yield* fileSystem.rename(claudeRoot, backupRoot);
|
|
23975
|
+
} else yield* fileSystem.remove(claudeRoot, { recursive: true });
|
|
23976
|
+
yield* fileSystem.rename(stagedLink, claudeRoot);
|
|
23977
|
+
const migrated = moveEntriesFor(manifest, claudeRoot, targetRoot);
|
|
23978
|
+
if (migrated !== manifest) yield* writeSkillManifest(input.manifestPath, migrated);
|
|
23979
|
+
return {
|
|
23980
|
+
root: targetRoot,
|
|
23981
|
+
refused: []
|
|
23982
|
+
};
|
|
23983
|
+
});
|
|
23984
|
+
//#endregion
|
|
23807
23985
|
//#region src/sync/AssetSync.ts
|
|
23808
23986
|
/**
|
|
23809
23987
|
* Syncing user-scope agent assets between this machine and the hub.
|
|
@@ -23864,10 +24042,30 @@ const make$77 = Effect.gen(function* () {
|
|
|
23864
24042
|
const claudeHome = Effect.fn("AssetSync.claudeHome")(function* () {
|
|
23865
24043
|
return { homePath: (yield* settingsStore.getSettings.pipe(Effect.orElseSucceed(() => void 0)))?.providers.claudeAgent.homePath ?? "" };
|
|
23866
24044
|
});
|
|
24045
|
+
const inspectSkillRoot = Effect.fn("AssetSync.inspectSkillRoot")(function* () {
|
|
24046
|
+
const claudeSkillsRoot = yield* claudeHome().pipe(Effect.flatMap(resolveClaudeUserSkillsDir));
|
|
24047
|
+
return yield* inspectSharedSkillRoot({
|
|
24048
|
+
claudeSkillsRoot,
|
|
24049
|
+
manifestPath
|
|
24050
|
+
}).pipe(Effect.catchCause((cause) => Effect.logWarning("shared skill root inspection failed", { cause }).pipe(Effect.as({
|
|
24051
|
+
root: null,
|
|
24052
|
+
refused: [{
|
|
24053
|
+
name: claudeSkillsRoot,
|
|
24054
|
+
reason: SHARED_SKILL_ROOT_REFUSAL
|
|
24055
|
+
}]
|
|
24056
|
+
}))));
|
|
24057
|
+
});
|
|
23867
24058
|
const drivers = [
|
|
23868
24059
|
{
|
|
23869
24060
|
kind: "skill",
|
|
23870
|
-
|
|
24061
|
+
prepareRoot: Effect.gen(function* () {
|
|
24062
|
+
yield* prepareSharedSkillRoot({
|
|
24063
|
+
claudeSkillsRoot: yield* claudeHome().pipe(Effect.flatMap(resolveClaudeUserSkillsDir)),
|
|
24064
|
+
manifestPath
|
|
24065
|
+
});
|
|
24066
|
+
}).pipe(Effect.catchCause((cause) => Effect.logWarning("shared skill root migration failed", { cause }))),
|
|
24067
|
+
resolveState: inspectSkillRoot(),
|
|
24068
|
+
resolveRoot: inspectSkillRoot().pipe(Effect.map((result) => result.root)),
|
|
23871
24069
|
read: (root) => readSkillDirectory(root),
|
|
23872
24070
|
write: ({ root, name, files }) => writeSkillDirectory({
|
|
23873
24071
|
skillsRoot: root,
|
|
@@ -23925,6 +24123,19 @@ const make$77 = Effect.gen(function* () {
|
|
|
23925
24123
|
}
|
|
23926
24124
|
];
|
|
23927
24125
|
const driverFor = (kind) => drivers.find((driver) => driver.kind === kind);
|
|
24126
|
+
const resolveDriverState = Effect.fn("AssetSync.resolveDriverState")(function* (driver) {
|
|
24127
|
+
if (driver.resolveState) return yield* driver.resolveState;
|
|
24128
|
+
return {
|
|
24129
|
+
root: yield* driver.resolveRoot,
|
|
24130
|
+
refused: []
|
|
24131
|
+
};
|
|
24132
|
+
});
|
|
24133
|
+
const resolveAllDriverStates = Effect.fn("AssetSync.resolveAllDriverStates")(function* () {
|
|
24134
|
+
return yield* Effect.forEach(drivers, (driver) => resolveDriverState(driver).pipe(Effect.map((state) => ({
|
|
24135
|
+
driver,
|
|
24136
|
+
...state
|
|
24137
|
+
}))), { concurrency: "unbounded" });
|
|
24138
|
+
});
|
|
23928
24139
|
const isConfigured = link.current.pipe(Effect.map((state) => Option.isSome(state.settings)));
|
|
23929
24140
|
/**
|
|
23930
24141
|
* The three views for one kind, gathered once.
|
|
@@ -23932,14 +24143,15 @@ const make$77 = Effect.gen(function* () {
|
|
|
23932
24143
|
* `status` and `run` both need exactly this and disagreeing about it is how a
|
|
23933
24144
|
* panel comes to show something the next sync does not do.
|
|
23934
24145
|
*/
|
|
23935
|
-
const viewsFor = Effect.fn("AssetSync.viewsFor")(function* (driver, hubAssets) {
|
|
23936
|
-
const
|
|
24146
|
+
const viewsFor = Effect.fn("AssetSync.viewsFor")(function* (driver, hubAssets, resolved) {
|
|
24147
|
+
const state = resolved ?? (yield* resolveDriverState(driver));
|
|
24148
|
+
const root = state.root;
|
|
23937
24149
|
const hub = hubAssets.filter((asset) => asset.kind === driver.kind);
|
|
23938
24150
|
if (root === null) return {
|
|
23939
24151
|
root,
|
|
23940
24152
|
hub,
|
|
23941
24153
|
local: [],
|
|
23942
|
-
refused:
|
|
24154
|
+
refused: state.refused,
|
|
23943
24155
|
managed: []
|
|
23944
24156
|
};
|
|
23945
24157
|
const local = yield* driver.read(root);
|
|
@@ -23952,7 +24164,11 @@ const make$77 = Effect.gen(function* () {
|
|
|
23952
24164
|
managed: entriesFor(manifest, root)
|
|
23953
24165
|
};
|
|
23954
24166
|
});
|
|
23955
|
-
const rootsOf = Effect.fn("AssetSync.rootsOf")(function* () {
|
|
24167
|
+
const rootsOf = Effect.fn("AssetSync.rootsOf")(function* (states) {
|
|
24168
|
+
if (states) return states.map(({ driver, root }) => ({
|
|
24169
|
+
kind: driver.kind,
|
|
24170
|
+
path: root
|
|
24171
|
+
}));
|
|
23956
24172
|
const roots = [];
|
|
23957
24173
|
for (const driver of drivers) roots.push({
|
|
23958
24174
|
kind: driver.kind,
|
|
@@ -23962,7 +24178,9 @@ const make$77 = Effect.gen(function* () {
|
|
|
23962
24178
|
});
|
|
23963
24179
|
const run = Effect.gen(function* () {
|
|
23964
24180
|
if (!(yield* isConfigured)) return EMPTY_REPORT;
|
|
23965
|
-
const
|
|
24181
|
+
for (const driver of drivers) if (driver.prepareRoot) yield* driver.prepareRoot;
|
|
24182
|
+
const resolvedDrivers = yield* resolveAllDriverStates();
|
|
24183
|
+
const roots = yield* rootsOf(resolvedDrivers);
|
|
23966
24184
|
const hubAssets = yield* client.list().pipe(Effect.option);
|
|
23967
24185
|
if (Option.isNone(hubAssets)) return {
|
|
23968
24186
|
...EMPTY_REPORT,
|
|
@@ -23977,8 +24195,9 @@ const make$77 = Effect.gen(function* () {
|
|
|
23977
24195
|
const conflicts = [];
|
|
23978
24196
|
const refused = [];
|
|
23979
24197
|
const shareMode = (yield* link.current).shareMode;
|
|
23980
|
-
for (const
|
|
23981
|
-
const
|
|
24198
|
+
for (const resolved of resolvedDrivers) {
|
|
24199
|
+
const driver = resolved.driver;
|
|
24200
|
+
const views = yield* viewsFor(driver, hubAssets.value, resolved);
|
|
23982
24201
|
const kind = driver.kind;
|
|
23983
24202
|
for (const entry of views.refused) refused.push({
|
|
23984
24203
|
kind,
|
|
@@ -24128,7 +24347,8 @@ const make$77 = Effect.gen(function* () {
|
|
|
24128
24347
|
*/
|
|
24129
24348
|
const assetStatus = Effect.gen(function* () {
|
|
24130
24349
|
const state = yield* link.current;
|
|
24131
|
-
const
|
|
24350
|
+
const resolvedDrivers = yield* resolveAllDriverStates();
|
|
24351
|
+
const roots = yield* rootsOf(resolvedDrivers);
|
|
24132
24352
|
const base = {
|
|
24133
24353
|
syncMode: state.syncMode,
|
|
24134
24354
|
shareMode: state.shareMode,
|
|
@@ -24138,9 +24358,10 @@ const make$77 = Effect.gen(function* () {
|
|
|
24138
24358
|
const hubAssets = Option.isNone(state.settings) ? Option.none() : yield* client.list().pipe(Effect.option);
|
|
24139
24359
|
const entries = [];
|
|
24140
24360
|
const refused = [];
|
|
24141
|
-
for (const
|
|
24361
|
+
for (const resolved of resolvedDrivers) {
|
|
24362
|
+
const driver = resolved.driver;
|
|
24142
24363
|
const kind = driver.kind;
|
|
24143
|
-
const views = yield* viewsFor(driver, Option.getOrElse(hubAssets, () => []));
|
|
24364
|
+
const views = yield* viewsFor(driver, Option.getOrElse(hubAssets, () => []), resolved);
|
|
24144
24365
|
for (const entry of views.refused) refused.push({
|
|
24145
24366
|
kind,
|
|
24146
24367
|
name: entry.name,
|
|
@@ -24468,6 +24689,7 @@ const make$77 = Effect.gen(function* () {
|
|
|
24468
24689
|
path: null,
|
|
24469
24690
|
detail: `Unknown asset kind '${input.kind}'.`
|
|
24470
24691
|
};
|
|
24692
|
+
if (driver.prepareRoot) yield* driver.prepareRoot;
|
|
24471
24693
|
const root = yield* driver.resolveRoot;
|
|
24472
24694
|
if (root === null) return {
|
|
24473
24695
|
outcome: "no-root",
|
|
@@ -28644,7 +28866,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
28644
28866
|
updatedAt: engagement.occurredAt
|
|
28645
28867
|
}
|
|
28646
28868
|
});
|
|
28647
|
-
|
|
28869
|
+
const enrichedEvents = events.map((event) => {
|
|
28648
28870
|
if (event.type === "thread.created") return {
|
|
28649
28871
|
...event,
|
|
28650
28872
|
payload: {
|
|
@@ -28687,6 +28909,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
28687
28909
|
default: return event;
|
|
28688
28910
|
}
|
|
28689
28911
|
});
|
|
28912
|
+
return enrichedEvents.length === 1 ? enrichedEvents[0] : enrichedEvents;
|
|
28690
28913
|
});
|
|
28691
28914
|
//#endregion
|
|
28692
28915
|
//#region src/orchestration/Services/ProjectionPipeline.ts
|
|
@@ -32546,8 +32769,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32546
32769
|
settled_at AS "settledAt",
|
|
32547
32770
|
lifecycle AS "lifecycle",
|
|
32548
32771
|
lifecycle_reason AS "lifecycleReason",
|
|
32549
|
-
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32550
|
-
last_engaged_at
|
|
32772
|
+
COALESCE(lifecycle_changed_at, archived_at, settled_at, created_at) AS "lifecycleChangedAt",
|
|
32773
|
+
COALESCE(last_engaged_at, MAX(created_at, COALESCE(latest_user_message_at, created_at),
|
|
32774
|
+
COALESCE((SELECT MAX(message.updated_at) FROM projection_thread_messages message
|
|
32775
|
+
WHERE message.thread_id = projection_threads.thread_id
|
|
32776
|
+
AND message.role IN ('user', 'assistant')), created_at))) AS "lastEngagedAt",
|
|
32551
32777
|
snoozed_until AS "snoozedUntil",
|
|
32552
32778
|
snoozed_at AS "snoozedAt",
|
|
32553
32779
|
pinned_at AS "pinnedAt",
|
|
@@ -32587,8 +32813,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32587
32813
|
settled_at AS "settledAt",
|
|
32588
32814
|
lifecycle AS "lifecycle",
|
|
32589
32815
|
lifecycle_reason AS "lifecycleReason",
|
|
32590
|
-
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32591
|
-
last_engaged_at
|
|
32816
|
+
COALESCE(lifecycle_changed_at, archived_at, settled_at, created_at) AS "lifecycleChangedAt",
|
|
32817
|
+
COALESCE(last_engaged_at, MAX(created_at, COALESCE(latest_user_message_at, created_at),
|
|
32818
|
+
COALESCE((SELECT MAX(message.updated_at) FROM projection_thread_messages message
|
|
32819
|
+
WHERE message.thread_id = projection_threads.thread_id
|
|
32820
|
+
AND message.role IN ('user', 'assistant')), created_at))) AS "lastEngagedAt",
|
|
32592
32821
|
snoozed_until AS "snoozedUntil",
|
|
32593
32822
|
snoozed_at AS "snoozedAt",
|
|
32594
32823
|
pinned_at AS "pinnedAt",
|
|
@@ -32630,8 +32859,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32630
32859
|
settled_at AS "settledAt",
|
|
32631
32860
|
lifecycle AS "lifecycle",
|
|
32632
32861
|
lifecycle_reason AS "lifecycleReason",
|
|
32633
|
-
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32634
|
-
last_engaged_at
|
|
32862
|
+
COALESCE(lifecycle_changed_at, archived_at, settled_at, created_at) AS "lifecycleChangedAt",
|
|
32863
|
+
COALESCE(last_engaged_at, MAX(created_at, COALESCE(latest_user_message_at, created_at),
|
|
32864
|
+
COALESCE((SELECT MAX(message.updated_at) FROM projection_thread_messages message
|
|
32865
|
+
WHERE message.thread_id = projection_threads.thread_id
|
|
32866
|
+
AND message.role IN ('user', 'assistant')), created_at))) AS "lastEngagedAt",
|
|
32635
32867
|
snoozed_until AS "snoozedUntil",
|
|
32636
32868
|
snoozed_at AS "snoozedAt",
|
|
32637
32869
|
pinned_at AS "pinnedAt",
|
|
@@ -33098,8 +33330,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33098
33330
|
settled_at AS "settledAt",
|
|
33099
33331
|
lifecycle AS "lifecycle",
|
|
33100
33332
|
lifecycle_reason AS "lifecycleReason",
|
|
33101
|
-
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
33102
|
-
last_engaged_at
|
|
33333
|
+
COALESCE(lifecycle_changed_at, archived_at, settled_at, created_at) AS "lifecycleChangedAt",
|
|
33334
|
+
COALESCE(last_engaged_at, MAX(created_at, COALESCE(latest_user_message_at, created_at),
|
|
33335
|
+
COALESCE((SELECT MAX(message.updated_at) FROM projection_thread_messages message
|
|
33336
|
+
WHERE message.thread_id = projection_threads.thread_id
|
|
33337
|
+
AND message.role IN ('user', 'assistant')), created_at))) AS "lastEngagedAt",
|
|
33103
33338
|
snoozed_until AS "snoozedUntil",
|
|
33104
33339
|
snoozed_at AS "snoozedAt",
|
|
33105
33340
|
pinned_at AS "pinnedAt",
|
|
@@ -99965,7 +100200,7 @@ const CURSOR_PRESENTATION = {
|
|
|
99965
100200
|
badgeLabel: "Early Access",
|
|
99966
100201
|
showInteractionModeToggle: true
|
|
99967
100202
|
};
|
|
99968
|
-
const EMPTY_CAPABILITIES$
|
|
100203
|
+
const EMPTY_CAPABILITIES$1 = createModelCapabilities({ optionDescriptors: [] });
|
|
99969
100204
|
const CURSOR_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15e3;
|
|
99970
100205
|
const CURSOR_PARAMETERIZED_MODEL_PICKER_MIN_VERSION_DATE = 20260408;
|
|
99971
100206
|
const CURSOR_CLI_INSTALLATION_DOCS_URL = "https://cursor.com/docs/cli/installation";
|
|
@@ -100073,7 +100308,7 @@ function getBooleanCurrentValue(option) {
|
|
|
100073
100308
|
if (normalized === "false") return false;
|
|
100074
100309
|
}
|
|
100075
100310
|
function buildCursorCapabilitiesFromConfigOptions(configOptions) {
|
|
100076
|
-
if (!configOptions || configOptions.length === 0) return EMPTY_CAPABILITIES$
|
|
100311
|
+
if (!configOptions || configOptions.length === 0) return EMPTY_CAPABILITIES$1;
|
|
100077
100312
|
const reasoningConfig = findCursorEffortConfigOption(configOptions);
|
|
100078
100313
|
const reasoningEffortLevels = reasoningConfig?.type === "select" ? flattenSessionConfigSelectOptions(reasoningConfig).flatMap((entry) => {
|
|
100079
100314
|
const normalizedValue = normalizeCursorReasoningValue(entry.value);
|
|
@@ -100242,7 +100477,7 @@ const discoverCursorModelsViaListAvailableModels = (cursorSettings, environment)
|
|
|
100242
100477
|
}), environment);
|
|
100243
100478
|
const discoverCursorModelsViaAcp = (cursorSettings, environment) => discoverCursorModelsViaListAvailableModels(cursorSettings, environment);
|
|
100244
100479
|
function getCursorFallbackModels(cursorSettings) {
|
|
100245
|
-
return providerModelsFromSettings([], cursorSettings.customModels, EMPTY_CAPABILITIES$
|
|
100480
|
+
return providerModelsFromSettings([], cursorSettings.customModels, EMPTY_CAPABILITIES$1);
|
|
100246
100481
|
}
|
|
100247
100482
|
/** Timeout for `agent about` — it's slower than a simple `--version` probe. */
|
|
100248
100483
|
const ABOUT_TIMEOUT_MS = 8e3;
|
|
@@ -100278,7 +100513,7 @@ function buildCursorProviderSnapshot(input) {
|
|
|
100278
100513
|
presentation: CURSOR_PRESENTATION,
|
|
100279
100514
|
enabled: input.cursorSettings.enabled,
|
|
100280
100515
|
checkedAt: input.checkedAt,
|
|
100281
|
-
models: providerModelsFromSettings(input.discoveredModels ?? [], input.cursorSettings.customModels, EMPTY_CAPABILITIES$
|
|
100516
|
+
models: providerModelsFromSettings(input.discoveredModels ?? [], input.cursorSettings.customModels, EMPTY_CAPABILITIES$1),
|
|
100282
100517
|
probe: {
|
|
100283
100518
|
installed: true,
|
|
100284
100519
|
version: input.parsed.version,
|
|
@@ -103111,14 +103346,14 @@ const GROK_PRESENTATION = {
|
|
|
103111
103346
|
showInteractionModeToggle: false,
|
|
103112
103347
|
requiresNewThreadForModelChange: true
|
|
103113
103348
|
};
|
|
103114
|
-
const EMPTY_CAPABILITIES
|
|
103349
|
+
const EMPTY_CAPABILITIES = createModelCapabilities({ optionDescriptors: [] });
|
|
103115
103350
|
const VERSION_PROBE_TIMEOUT_MS$1 = 4e3;
|
|
103116
103351
|
const GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15e3;
|
|
103117
103352
|
const GROK_BUILT_IN_MODELS = [{
|
|
103118
103353
|
slug: "grok-build",
|
|
103119
103354
|
name: "Grok Build",
|
|
103120
103355
|
isCustom: false,
|
|
103121
|
-
capabilities: EMPTY_CAPABILITIES
|
|
103356
|
+
capabilities: EMPTY_CAPABILITIES
|
|
103122
103357
|
}];
|
|
103123
103358
|
function buildInitialGrokProviderSnapshot(grokSettings) {
|
|
103124
103359
|
return Effect.gen(function* () {
|
|
@@ -103153,7 +103388,7 @@ function buildInitialGrokProviderSnapshot(grokSettings) {
|
|
|
103153
103388
|
});
|
|
103154
103389
|
}
|
|
103155
103390
|
function grokModelsFromSettings(customModels, builtInModels = GROK_BUILT_IN_MODELS) {
|
|
103156
|
-
return providerModelsFromSettings(builtInModels, customModels ?? [], EMPTY_CAPABILITIES
|
|
103391
|
+
return providerModelsFromSettings(builtInModels, customModels ?? [], EMPTY_CAPABILITIES);
|
|
103157
103392
|
}
|
|
103158
103393
|
function buildGrokDiscoveredModelsFromSessionModelState(modelState) {
|
|
103159
103394
|
if (!modelState || modelState.availableModels.length === 0) return [];
|
|
@@ -103166,7 +103401,7 @@ function buildGrokDiscoveredModelsFromSessionModelState(modelState) {
|
|
|
103166
103401
|
slug,
|
|
103167
103402
|
name: model.name.trim() || slug,
|
|
103168
103403
|
isCustom: false,
|
|
103169
|
-
capabilities: EMPTY_CAPABILITIES
|
|
103404
|
+
capabilities: EMPTY_CAPABILITIES
|
|
103170
103405
|
};
|
|
103171
103406
|
}).filter((model) => model !== void 0);
|
|
103172
103407
|
}
|
|
@@ -103406,20 +103641,52 @@ const GrokDriver = {
|
|
|
103406
103641
|
})
|
|
103407
103642
|
};
|
|
103408
103643
|
/**
|
|
103644
|
+
* Reasoning levels `muse exec --reasoning-effort` accepts, in the CLI's own
|
|
103645
|
+
* order (`muse exec --help`, Muse Code 1.1.1). `high` is the CLI default, so
|
|
103646
|
+
* it is the default here too.
|
|
103647
|
+
*/
|
|
103648
|
+
const MUSE_REASONING_EFFORTS = [
|
|
103649
|
+
"none",
|
|
103650
|
+
"minimal",
|
|
103651
|
+
"low",
|
|
103652
|
+
"medium",
|
|
103653
|
+
"high",
|
|
103654
|
+
"xhigh",
|
|
103655
|
+
"max",
|
|
103656
|
+
"ultra"
|
|
103657
|
+
];
|
|
103658
|
+
const MUSE_DEFAULT_REASONING_EFFORT = "high";
|
|
103659
|
+
/**
|
|
103660
|
+
* Keep a selection Muse cannot parse out of the argv. `reasoningEffort` is a
|
|
103661
|
+
* shared option id — Codex publishes one too — so a selection left over from
|
|
103662
|
+
* another provider can reach this driver, and an unknown level makes
|
|
103663
|
+
* `muse exec` reject the whole invocation.
|
|
103664
|
+
*/
|
|
103665
|
+
function museReasoningEffort(value) {
|
|
103666
|
+
return value !== void 0 && MUSE_REASONING_EFFORTS.includes(value) ? value : void 0;
|
|
103667
|
+
}
|
|
103668
|
+
/**
|
|
103409
103669
|
* Build the argument vector for one turn.
|
|
103410
103670
|
*
|
|
103411
|
-
* Approval policy is the load-bearing decision here.
|
|
103412
|
-
*
|
|
103413
|
-
* `--
|
|
103414
|
-
*
|
|
103415
|
-
*
|
|
103671
|
+
* Approval policy is the load-bearing decision here. Muse Code 1.1.1 does
|
|
103672
|
+
* express approval as a policy — `--approval-mode untrusted|on-request|never`,
|
|
103673
|
+
* plus named `--permission-profile` documents — but a headless `exec` run
|
|
103674
|
+
* still has no channel to answer a prompt: approvals are served over MSP
|
|
103675
|
+
* (`muse serve`), not on the `exec` stream. So the only two postures `exec`
|
|
103676
|
+
* can honour end to end are `--disable-approval` (keep the OS sandbox) and
|
|
103677
|
+
* `--yolo` (drop approval and the sandbox, and trust the workspace). P4Code
|
|
103678
|
+
* owns the user-facing runtime mode, so it maps onto those two:
|
|
103416
103679
|
*
|
|
103417
103680
|
* - `full-access` → `--yolo`
|
|
103418
103681
|
* - everything else → `--disable-approval --trust-workspace`, leaving the
|
|
103419
103682
|
* sandbox to contain what runs.
|
|
103420
103683
|
*
|
|
103421
|
-
* `approval-required` cannot be honoured
|
|
103422
|
-
* `config.warning` for it rather than silently pretending otherwise.
|
|
103684
|
+
* `approval-required` cannot be honoured over `exec`; the adapter emits a
|
|
103685
|
+
* `config.warning` for it rather than silently pretending otherwise. Serving
|
|
103686
|
+
* a real approval prompt means moving the driver onto MSP.
|
|
103687
|
+
*
|
|
103688
|
+
* Flags here were verified against Muse Code 1.1.1-R2514.1 (`muse exec
|
|
103689
|
+
* --help`).
|
|
103423
103690
|
*/
|
|
103424
103691
|
function buildMuseExecArgs(input) {
|
|
103425
103692
|
const args = [
|
|
@@ -103463,10 +103730,15 @@ function museApprovalsUnsupported(runtimeMode) {
|
|
|
103463
103730
|
* MuseExecEvents — pure translation of `muse exec --json` JSONL records into
|
|
103464
103731
|
* canonical `ProviderRuntimeEvent`s.
|
|
103465
103732
|
*
|
|
103466
|
-
* Muse
|
|
103467
|
-
*
|
|
103468
|
-
*
|
|
103469
|
-
*
|
|
103733
|
+
* P4Code drives Muse through `muse exec --json`, which runs one prompt to
|
|
103734
|
+
* completion and prints one JSON object per line; multi-turn threads are
|
|
103735
|
+
* rebuilt by re-invoking with `--session-id`. Muse Code 1.1.1 also serves a
|
|
103736
|
+
* session host over stdio (`muse serve`, the MSP wire protocol, exported by
|
|
103737
|
+
* `muse schema`) with approval, user-input and steering methods that `exec`
|
|
103738
|
+
* has no channel for. Moving onto MSP is the way to lift those limits; the
|
|
103739
|
+
* mapping below stays on the `exec` stream until then.
|
|
103740
|
+
*
|
|
103741
|
+
* Record shapes here were re-verified against CLI 1.1.1-R2514.1.
|
|
103470
103742
|
*
|
|
103471
103743
|
* Everything here is a pure function over a caller-owned state record so the
|
|
103472
103744
|
* mapping can be tested against captured CLI output without spawning a
|
|
@@ -103760,21 +104032,19 @@ function toolCallIdFromIdempotencyKey(key) {
|
|
|
103760
104032
|
const callId = key.slice(5).trim();
|
|
103761
104033
|
return callId.length > 0 ? callId : void 0;
|
|
103762
104034
|
}
|
|
104035
|
+
/**
|
|
104036
|
+
* Muse's tool names, as the CLI itself reports them (Muse Code 1.1.1). Names
|
|
104037
|
+
* it does not have are not listed: an unknown tool still maps to
|
|
104038
|
+
* `dynamic_tool_call`, which is the right answer for the memory, goal, cron,
|
|
104039
|
+
* skill and todo tools that have no canonical item type here.
|
|
104040
|
+
*/
|
|
103763
104041
|
function itemTypeForToolName(toolName) {
|
|
103764
104042
|
switch (toolName) {
|
|
103765
104043
|
case "bash":
|
|
103766
|
-
case "
|
|
103767
|
-
case "run_command":
|
|
103768
|
-
case "unified_exec": return "command_execution";
|
|
104044
|
+
case "bash_input": return "command_execution";
|
|
103769
104045
|
case "write_file":
|
|
103770
|
-
case "edit_file":
|
|
103771
|
-
case "
|
|
103772
|
-
case "apply_patch":
|
|
103773
|
-
case "delete_file":
|
|
103774
|
-
case "move_file": return "file_change";
|
|
103775
|
-
case "web_search":
|
|
103776
|
-
case "web_fetch": return "web_search";
|
|
103777
|
-
case "view_image": return "image_view";
|
|
104046
|
+
case "edit_file": return "file_change";
|
|
104047
|
+
case "web_search": return "web_search";
|
|
103778
104048
|
default:
|
|
103779
104049
|
if (toolName?.startsWith("subagent_")) return "collab_agent_tool_call";
|
|
103780
104050
|
if (toolName?.startsWith("mcp__")) return "mcp_tool_call";
|
|
@@ -103990,11 +104260,12 @@ const makeMuseTextGeneration = (museSettings, environment = process.env) => Effe
|
|
|
103990
104260
|
/**
|
|
103991
104261
|
* MuseExecRuntime — one `muse exec --json` child process per turn.
|
|
103992
104262
|
*
|
|
103993
|
-
*
|
|
103994
|
-
*
|
|
103995
|
-
*
|
|
103996
|
-
*
|
|
103997
|
-
*
|
|
104263
|
+
* On the `exec` path a turn is a process, and the thread is rebuilt from the
|
|
104264
|
+
* CLI's own event-sourced session log when the next turn passes
|
|
104265
|
+
* `--session-id`. (Muse Code 1.1.1 does have a long-lived surface —
|
|
104266
|
+
* `muse serve`, the MSP session host — which this driver does not use yet.)
|
|
104267
|
+
* This module owns spawning, line framing, interruption, and exit
|
|
104268
|
+
* classification; it knows nothing about canonical runtime events.
|
|
103998
104269
|
*
|
|
103999
104270
|
* @module provider/muse/MuseExecRuntime
|
|
104000
104271
|
*/
|
|
@@ -104238,11 +104509,12 @@ function nonNegativeInt(value) {
|
|
|
104238
104509
|
*
|
|
104239
104510
|
* Consequences that are visible to users, and deliberate:
|
|
104240
104511
|
*
|
|
104241
|
-
* - **No interactive approvals.**
|
|
104242
|
-
* approval prompt
|
|
104243
|
-
*
|
|
104244
|
-
*
|
|
104245
|
-
* a
|
|
104512
|
+
* - **No interactive approvals.** `muse exec` has no channel to answer an
|
|
104513
|
+
* approval prompt — Muse Code 1.1.1 serves approvals over MSP
|
|
104514
|
+
* (`muse serve`), which this adapter does not speak — so the adapter runs
|
|
104515
|
+
* with approval disabled and lets Muse's OS sandbox do the containing.
|
|
104516
|
+
* `respondToRequest` fails rather than pretending to route a decision, and
|
|
104517
|
+
* `approval-required` threads get a `config.warning`.
|
|
104246
104518
|
* - **No provider-side rollback.** Muse can fork a session interactively but
|
|
104247
104519
|
* exposes nothing headless.
|
|
104248
104520
|
* - **Tool arguments are not streamed.** They exist only in the on-disk
|
|
@@ -104382,10 +104654,12 @@ function makeMuseAdapter(museSettings, options) {
|
|
|
104382
104654
|
}
|
|
104383
104655
|
const turnId = TurnId.make(yield* randomUUIDv4);
|
|
104384
104656
|
const model = input.modelSelection?.model ?? ctx.session.model;
|
|
104657
|
+
const reasoningEffort = input.modelSelection?.instanceId === boundInstanceId ? museReasoningEffort(getModelSelectionStringOptionValue(input.modelSelection, "reasoningEffort")) : void 0;
|
|
104385
104658
|
const args = buildMuseExecArgs({
|
|
104386
104659
|
sessionId: ctx.museSessionId,
|
|
104387
104660
|
prompt,
|
|
104388
104661
|
model,
|
|
104662
|
+
reasoningEffort,
|
|
104389
104663
|
baseUrl: museSettings.baseUrl || void 0,
|
|
104390
104664
|
runtimeMode: ctx.session.runtimeMode,
|
|
104391
104665
|
imagePaths
|
|
@@ -104420,54 +104694,74 @@ function makeMuseAdapter(museSettings, options) {
|
|
|
104420
104694
|
...model ? { model } : {}
|
|
104421
104695
|
};
|
|
104422
104696
|
const turnScope = yield* Scope.make();
|
|
104423
|
-
|
|
104697
|
+
let runStarted = false;
|
|
104698
|
+
let settled = false;
|
|
104699
|
+
let outcome;
|
|
104700
|
+
/**
|
|
104701
|
+
* Release everything the turn holds, exactly once, whatever ended it:
|
|
104702
|
+
* a clean exit, a typed failure, a defect, or an interrupt from a
|
|
104703
|
+
* stopped thread. Leaving `activeTurn` or a `running` session behind
|
|
104704
|
+
* would wedge the thread — every later `sendTurn` would refuse with
|
|
104705
|
+
* "a Muse turn is already running" until the server restarted — so
|
|
104706
|
+
* this runs from an `ensuring` finalizer rather than the happy path.
|
|
104707
|
+
*/
|
|
104708
|
+
const finishTurn = Effect.suspend(() => {
|
|
104709
|
+
if (settled) return Effect.void;
|
|
104710
|
+
settled = true;
|
|
104711
|
+
return Effect.gen(function* () {
|
|
104712
|
+
ctx.activeTurn = void 0;
|
|
104713
|
+
yield* Scope.close(turnScope, Exit.void);
|
|
104714
|
+
if (runStarted && state.terminal === void 0) if (outcome === void 0 || outcome.kind === "interrupted") yield* publish({
|
|
104715
|
+
type: "turn.aborted",
|
|
104716
|
+
...yield* makeEventStamp(),
|
|
104717
|
+
provider: PROVIDER$1,
|
|
104718
|
+
providerInstanceId: boundInstanceId,
|
|
104719
|
+
threadId: input.threadId,
|
|
104720
|
+
turnId,
|
|
104721
|
+
payload: { reason: "interrupted" }
|
|
104722
|
+
});
|
|
104723
|
+
else {
|
|
104724
|
+
const detail = outcome.kind === "failed" ? outcome.stderr || `\`muse exec\` exited with code ${outcome.exitCode}.` : "`muse exec` ended without a terminal event.";
|
|
104725
|
+
yield* publish({
|
|
104726
|
+
type: "turn.completed",
|
|
104727
|
+
...yield* makeEventStamp(),
|
|
104728
|
+
provider: PROVIDER$1,
|
|
104729
|
+
providerInstanceId: boundInstanceId,
|
|
104730
|
+
threadId: input.threadId,
|
|
104731
|
+
turnId,
|
|
104732
|
+
payload: {
|
|
104733
|
+
state: "failed",
|
|
104734
|
+
errorMessage: detail
|
|
104735
|
+
}
|
|
104736
|
+
});
|
|
104737
|
+
}
|
|
104738
|
+
if (runStarted) yield* publishTokenUsage(ctx, turnId);
|
|
104739
|
+
const updatedAt = yield* nowIso;
|
|
104740
|
+
const { activeTurnId: _activeTurnId, ...readySession } = ctx.session;
|
|
104741
|
+
ctx.session = {
|
|
104742
|
+
...readySession,
|
|
104743
|
+
status: "ready",
|
|
104744
|
+
updatedAt
|
|
104745
|
+
};
|
|
104746
|
+
});
|
|
104747
|
+
}).pipe(Effect.ignore);
|
|
104748
|
+
yield* Effect.acquireUseRelease(runMuseExec({
|
|
104424
104749
|
threadId: input.threadId,
|
|
104425
104750
|
binaryPath: museSettings.binaryPath || "muse",
|
|
104426
104751
|
args,
|
|
104427
104752
|
cwd: ctx.cwd,
|
|
104428
104753
|
environment,
|
|
104429
104754
|
onLine: handleLine
|
|
104430
|
-
}).pipe(Effect.provideService(Scope.Scope, turnScope), Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), Effect.tapError(() =>
|
|
104431
|
-
|
|
104432
|
-
|
|
104433
|
-
run,
|
|
104434
|
-
state
|
|
104435
|
-
};
|
|
104436
|
-
const outcome = yield* run.awaitOutcome;
|
|
104437
|
-
yield* Scope.close(turnScope, Exit.void);
|
|
104438
|
-
ctx.activeTurn = void 0;
|
|
104439
|
-
if (state.terminal === void 0) if (outcome.kind === "interrupted") yield* publish({
|
|
104440
|
-
type: "turn.aborted",
|
|
104441
|
-
...yield* makeEventStamp(),
|
|
104442
|
-
provider: PROVIDER$1,
|
|
104443
|
-
providerInstanceId: boundInstanceId,
|
|
104444
|
-
threadId: input.threadId,
|
|
104445
|
-
turnId,
|
|
104446
|
-
payload: { reason: "interrupted" }
|
|
104447
|
-
});
|
|
104448
|
-
else {
|
|
104449
|
-
const detail = outcome.kind === "failed" ? outcome.stderr || `\`muse exec\` exited with code ${outcome.exitCode}.` : "`muse exec` ended without a terminal event.";
|
|
104450
|
-
yield* publish({
|
|
104451
|
-
type: "turn.completed",
|
|
104452
|
-
...yield* makeEventStamp(),
|
|
104453
|
-
provider: PROVIDER$1,
|
|
104454
|
-
providerInstanceId: boundInstanceId,
|
|
104455
|
-
threadId: input.threadId,
|
|
104755
|
+
}).pipe(Effect.provideService(Scope.Scope, turnScope), Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), Effect.tapError(() => finishTurn), Effect.tap((run) => Effect.sync(() => {
|
|
104756
|
+
runStarted = true;
|
|
104757
|
+
ctx.activeTurn = {
|
|
104456
104758
|
turnId,
|
|
104457
|
-
|
|
104458
|
-
|
|
104459
|
-
|
|
104460
|
-
|
|
104461
|
-
|
|
104462
|
-
}
|
|
104463
|
-
yield* publishTokenUsage(ctx, turnId);
|
|
104464
|
-
const updatedAt = yield* nowIso;
|
|
104465
|
-
const { activeTurnId: _activeTurnId, ...readySession } = ctx.session;
|
|
104466
|
-
ctx.session = {
|
|
104467
|
-
...readySession,
|
|
104468
|
-
status: "ready",
|
|
104469
|
-
updatedAt
|
|
104470
|
-
};
|
|
104759
|
+
run,
|
|
104760
|
+
state
|
|
104761
|
+
};
|
|
104762
|
+
}))), (run) => Effect.gen(function* () {
|
|
104763
|
+
outcome = yield* run.awaitOutcome;
|
|
104764
|
+
}), () => finishTurn);
|
|
104471
104765
|
return {
|
|
104472
104766
|
threadId: input.threadId,
|
|
104473
104767
|
turnId,
|
|
@@ -104596,7 +104890,17 @@ const MUSE_PRESENTATION = {
|
|
|
104596
104890
|
requiresNewThreadForModelChange: false,
|
|
104597
104891
|
supportedRuntimeModes: ["auto", "full-access"]
|
|
104598
104892
|
};
|
|
104599
|
-
const
|
|
104893
|
+
const MUSE_CAPABILITIES = createModelCapabilities({ optionDescriptors: [{
|
|
104894
|
+
id: "reasoningEffort",
|
|
104895
|
+
label: "Reasoning",
|
|
104896
|
+
type: "select",
|
|
104897
|
+
options: MUSE_REASONING_EFFORTS.map((effort) => ({
|
|
104898
|
+
id: effort,
|
|
104899
|
+
label: effort.charAt(0).toUpperCase() + effort.slice(1),
|
|
104900
|
+
...effort === "high" ? { isDefault: true } : {}
|
|
104901
|
+
})),
|
|
104902
|
+
currentValue: MUSE_DEFAULT_REASONING_EFFORT
|
|
104903
|
+
}] });
|
|
104600
104904
|
const VERSION_PROBE_TIMEOUT_MS = 4e3;
|
|
104601
104905
|
/** Models Meta documents for Muse Code; used until the CLI caches a catalog. */
|
|
104602
104906
|
const MUSE_BUILT_IN_MODELS = [
|
|
@@ -104604,30 +104908,30 @@ const MUSE_BUILT_IN_MODELS = [
|
|
|
104604
104908
|
slug: "muse-spark-1.3",
|
|
104605
104909
|
name: "Muse Spark 1.3",
|
|
104606
104910
|
isCustom: false,
|
|
104607
|
-
capabilities:
|
|
104911
|
+
capabilities: MUSE_CAPABILITIES
|
|
104608
104912
|
},
|
|
104609
104913
|
{
|
|
104610
104914
|
slug: "muse-spark-1.3-contributor",
|
|
104611
104915
|
name: "Muse Spark 1.3 (contributor)",
|
|
104612
104916
|
isCustom: false,
|
|
104613
104917
|
isDefault: true,
|
|
104614
|
-
capabilities:
|
|
104918
|
+
capabilities: MUSE_CAPABILITIES
|
|
104615
104919
|
},
|
|
104616
104920
|
{
|
|
104617
104921
|
slug: "muse-spark-1.2",
|
|
104618
104922
|
name: "Muse Spark 1.2",
|
|
104619
104923
|
isCustom: false,
|
|
104620
|
-
capabilities:
|
|
104924
|
+
capabilities: MUSE_CAPABILITIES
|
|
104621
104925
|
},
|
|
104622
104926
|
{
|
|
104623
104927
|
slug: "muse-spark-1.2-contributor",
|
|
104624
104928
|
name: "Muse Spark 1.2 (contributor)",
|
|
104625
104929
|
isCustom: false,
|
|
104626
|
-
capabilities:
|
|
104930
|
+
capabilities: MUSE_CAPABILITIES
|
|
104627
104931
|
}
|
|
104628
104932
|
];
|
|
104629
104933
|
function museModelsFromSettings(customModels, builtInModels = MUSE_BUILT_IN_MODELS) {
|
|
104630
|
-
return providerModelsFromSettings(builtInModels, customModels ?? [],
|
|
104934
|
+
return providerModelsFromSettings(builtInModels, customModels ?? [], MUSE_CAPABILITIES);
|
|
104631
104935
|
}
|
|
104632
104936
|
const discoverMuseModels = Effect.fn("discoverMuseModels")(function* (environment) {
|
|
104633
104937
|
return (yield* readMuseModelCatalog(environment)).map((model) => ({
|
|
@@ -104635,7 +104939,7 @@ const discoverMuseModels = Effect.fn("discoverMuseModels")(function* (environmen
|
|
|
104635
104939
|
name: model.name,
|
|
104636
104940
|
isCustom: false,
|
|
104637
104941
|
...model.isDefault ? { isDefault: true } : {},
|
|
104638
|
-
capabilities:
|
|
104942
|
+
capabilities: MUSE_CAPABILITIES
|
|
104639
104943
|
}));
|
|
104640
104944
|
});
|
|
104641
104945
|
/**
|