@webinson/peer-core 0.1.977 → 0.1.978
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bin.mjs +1 -1
- package/dist/{binCli-BD8xnLcs.mjs → binCli-B32nSvwp.mjs} +113 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,4 +16,4 @@ peer core serve --detach # or let the editor start it on demand
|
|
|
16
16
|
`peer core status` says who runs Peer here; `peer core stop` stops Peer Core. The Peer desktop app,
|
|
17
17
|
when it starts, takes coordination over. Any other `peer <command>` goes to the running Peer.
|
|
18
18
|
|
|
19
|
-
Version 0.1.
|
|
19
|
+
Version 0.1.978 of Peer Local (https://github.com/SemanS/peer-app, branch `peer`), based on T3 Code.
|
package/dist/bin.mjs
CHANGED
|
@@ -77,7 +77,7 @@ if (isEntrypoint({
|
|
|
77
77
|
} else {
|
|
78
78
|
const { attachConsoleStdin } = await import("./consoleStdin-DO-vIhyg.mjs");
|
|
79
79
|
attachConsoleStdin();
|
|
80
|
-
const { runCli } = await import("./binCli-
|
|
80
|
+
const { runCli } = await import("./binCli-B32nSvwp.mjs");
|
|
81
81
|
runCli(npmPeerBin ? "peer" : "t3");
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -27680,6 +27680,22 @@ const connectEditor = (id, stateDir, io) => gen$1(function* () {
|
|
|
27680
27680
|
stateDir
|
|
27681
27681
|
}, io);
|
|
27682
27682
|
});
|
|
27683
|
+
/** The way out of `connectEditor`: Peer's hooks out of Claude Code or Codex, the MCP entry out of the rest. */
|
|
27684
|
+
const disconnectEditor = (id, io) => gen$1(function* () {
|
|
27685
|
+
if (id === "claude" || id === "codex") {
|
|
27686
|
+
const status = yield* (yield* PeerAdapters).setCoordination(id === "claude" ? { claudeHooks: false } : { codexHooks: false });
|
|
27687
|
+
return yield* sayHooks(status, {
|
|
27688
|
+
claude: id === "claude",
|
|
27689
|
+
codex: id === "codex",
|
|
27690
|
+
install: false
|
|
27691
|
+
}, io);
|
|
27692
|
+
}
|
|
27693
|
+
const answer = yield* (yield* McpClients).disconnect({
|
|
27694
|
+
client: id,
|
|
27695
|
+
scope: "user"
|
|
27696
|
+
});
|
|
27697
|
+
yield* io.say(answer.outcome === "manual" ? `${answer.path} is not plain JSON, so Peer left it alone. Remove this entry by hand:\n${answer.entry}` : answer.outcome === "unchanged" ? `${editorTitle(id)} had no Peer entry in ${answer.path}.` : `Disconnected ${editorTitle(id)}: removed Peer's entry from ${answer.path}.`);
|
|
27698
|
+
});
|
|
27683
27699
|
//#endregion
|
|
27684
27700
|
//#region src/cli/joinLink.ts
|
|
27685
27701
|
/**
|
|
@@ -27999,11 +28015,13 @@ async function findRepositories(home, limit = 25) {
|
|
|
27999
28015
|
const RECOMMENDED = "Recommended";
|
|
28000
28016
|
/** `~/…` for a path under the home directory: the name matters, the full path is context. */
|
|
28001
28017
|
const shortPath = (path, home) => path === home || path.startsWith(`${home}${NodePath.sep}`) ? `~${path.slice(home.length)}` : path;
|
|
28002
|
-
/** The lines above the menu: who, which workspace, and the
|
|
28003
|
-
const menuContext = (status, here,
|
|
28018
|
+
/** The lines above the menu: who, which workspace, the project here, and the editors connected. */
|
|
28019
|
+
const menuContext = (status, here, editors) => {
|
|
28004
28020
|
const names = status.workspaces.map((w) => w.slug);
|
|
28005
28021
|
const lines = [`Signed in as ${status.email ?? "nobody"}`, names.length === 0 ? "Workspace: none yet" : names.length === 1 ? `Workspace: ${names[0]}` : `Workspaces: ${names.join(", ")}`];
|
|
28006
|
-
if (here !== null) lines.push(`
|
|
28022
|
+
if (here !== null) lines.push(`Project: ${NodePath.basename(here.root)} · ${here.state === "connected" ? `Connected${here.project === NodePath.basename(here.root) ? "" : ` as ${here.workspace}/${here.project}`}` : here.state === "clone" ? `Clone of ${here.project}, not connected` : "Not connected"}`);
|
|
28023
|
+
const connected = editors.filter((e) => e.connected);
|
|
28024
|
+
lines.push(connected.length === 0 ? "Editors: none connected yet" : ["Editors:", ...connected.map((e) => ` ✓ ${e.title}`)].join("\n"));
|
|
28007
28025
|
return lines;
|
|
28008
28026
|
};
|
|
28009
28027
|
/**
|
|
@@ -28012,7 +28030,7 @@ const menuContext = (status, here, home) => {
|
|
|
28012
28030
|
* the project here, else inviting a teammate to it. Inviting is offered where they own or
|
|
28013
28031
|
* administer a workspace; joining or creating one stays reachable, Exit last.
|
|
28014
28032
|
*/
|
|
28015
|
-
const menuItems = (status, here) => {
|
|
28033
|
+
const menuItems = (status, here, editors = []) => {
|
|
28016
28034
|
const offers = [...(status.foundings ?? []).filter((f) => f.expired !== true).map((f) => ({
|
|
28017
28035
|
title: `Accept ${f.name}, founded for you`,
|
|
28018
28036
|
value: {
|
|
@@ -28054,9 +28072,19 @@ const menuItems = (status, here) => {
|
|
|
28054
28072
|
description: "The app: tasks, agents and who works on what.",
|
|
28055
28073
|
value: { kind: "open" }
|
|
28056
28074
|
}];
|
|
28075
|
+
const launch = here?.state === "connected" ? editors.filter((e) => e.connected && e.launchable).map((e) => ({
|
|
28076
|
+
title: `Open ${e.title}`,
|
|
28077
|
+
description: `In ${NodePath.basename(here.root)}, with Peer coordinating its agents.`,
|
|
28078
|
+
value: {
|
|
28079
|
+
kind: "launch",
|
|
28080
|
+
editor: e.id,
|
|
28081
|
+
folder: here.root
|
|
28082
|
+
}
|
|
28083
|
+
})) : [];
|
|
28057
28084
|
const items = inWorkspace ? [
|
|
28058
28085
|
...offers,
|
|
28059
28086
|
...here?.state === "connected" ? [
|
|
28087
|
+
...launch,
|
|
28060
28088
|
...invite,
|
|
28061
28089
|
...work,
|
|
28062
28090
|
...connectHere
|
|
@@ -28087,7 +28115,11 @@ const menuItems = (status, here) => {
|
|
|
28087
28115
|
value: { kind: "join" }
|
|
28088
28116
|
}
|
|
28089
28117
|
];
|
|
28090
|
-
items.push({
|
|
28118
|
+
items.push(editors.some((e) => e.connected) ? {
|
|
28119
|
+
title: "Manage integrations",
|
|
28120
|
+
description: "Connect or disconnect editors and agents.",
|
|
28121
|
+
value: { kind: "editor" }
|
|
28122
|
+
} : {
|
|
28091
28123
|
title: "Connect an editor",
|
|
28092
28124
|
description: "So your agents (Claude Code, Codex, Cursor, …) coordinate through Peer.",
|
|
28093
28125
|
value: { kind: "editor" }
|
|
@@ -28122,21 +28154,30 @@ const menu = (ask, steps, io) => gen$1(function* () {
|
|
|
28122
28154
|
for (;;) {
|
|
28123
28155
|
const status = yield* steps.status;
|
|
28124
28156
|
const here = yield* steps.here;
|
|
28125
|
-
const
|
|
28157
|
+
const editors = yield* steps.editors;
|
|
28158
|
+
const editorsConnected = editors.some((e) => e.connected);
|
|
28159
|
+
const context = menuContext(status, here, editors).join("\n");
|
|
28126
28160
|
if (context !== shown) {
|
|
28127
28161
|
yield* io.say(context);
|
|
28128
28162
|
shown = context;
|
|
28129
28163
|
}
|
|
28130
|
-
const item = yield* ask.choose("What would you like to do?", menuItems(status, here));
|
|
28131
|
-
if (item === null || item.kind === "exit") return;
|
|
28164
|
+
const item = yield* ask.choose("What would you like to do?", menuItems(status, here, editors));
|
|
28165
|
+
if (item === null || item.kind === "exit") return { editorsConnected };
|
|
28166
|
+
if (item.kind === "launch") return {
|
|
28167
|
+
editorsConnected,
|
|
28168
|
+
launch: {
|
|
28169
|
+
editor: item.editor,
|
|
28170
|
+
folder: item.folder
|
|
28171
|
+
}
|
|
28172
|
+
};
|
|
28132
28173
|
if (item.kind === "open") {
|
|
28133
|
-
if (yield* steps.openPeer.pipe(as(true), catch_((error) => io.say(String(error.message).replace(/^peer core: /, "")).pipe(as(false))))) return;
|
|
28174
|
+
if (yield* steps.openPeer.pipe(as(true), catch_((error) => io.say(String(error.message).replace(/^peer core: /, "")).pipe(as(false))))) return { editorsConnected: false };
|
|
28134
28175
|
continue;
|
|
28135
28176
|
}
|
|
28136
28177
|
const connect = (folder) => gen$1(function* () {
|
|
28137
28178
|
const joined = yield* steps.share(folder);
|
|
28138
28179
|
if (joined === null) return;
|
|
28139
|
-
const ready = yield* steps.
|
|
28180
|
+
const ready = (yield* steps.editors).some((e) => e.connected);
|
|
28140
28181
|
yield* io.say([
|
|
28141
28182
|
"",
|
|
28142
28183
|
`✓ Signed in as ${status.email ?? ""}`,
|
|
@@ -28174,10 +28215,19 @@ const menu = (ask, steps, io) => gen$1(function* () {
|
|
|
28174
28215
|
if (folder !== null && folder.trim() !== "") yield* connect(folder.trim());
|
|
28175
28216
|
return;
|
|
28176
28217
|
}
|
|
28177
|
-
case "editor":
|
|
28178
|
-
yield*
|
|
28218
|
+
case "editor": {
|
|
28219
|
+
const id = yield* ask.choose("Which editor or agent?", editors.map((e) => ({
|
|
28220
|
+
title: `${e.connected ? "✓ " : " "}${e.title}`,
|
|
28221
|
+
description: e.connected ? "Connected: choose it to disconnect" : "Connect it",
|
|
28222
|
+
value: e.id
|
|
28223
|
+
})));
|
|
28224
|
+
const chosen = editors.find((e) => e.id === id);
|
|
28225
|
+
if (chosen === void 0) return;
|
|
28226
|
+
if (!chosen.connected) yield* steps.connectEditor(chosen.id);
|
|
28227
|
+
else if (yield* ask.confirm(`Disconnect ${chosen.title} from Peer?`, false)) yield* steps.disconnectEditor(chosen.id);
|
|
28179
28228
|
shown = "";
|
|
28180
28229
|
return;
|
|
28230
|
+
}
|
|
28181
28231
|
case "workspace": {
|
|
28182
28232
|
const next = yield* ask.choose("Join or create", [{
|
|
28183
28233
|
title: "Join a workspace",
|
|
@@ -28732,7 +28782,7 @@ const runMenu = (stateDir) => gen$1(function* () {
|
|
|
28732
28782
|
const workspaces = yield* PeerWorkspaces;
|
|
28733
28783
|
const state = yield* PeerState;
|
|
28734
28784
|
const status = workspaces.sync.pipe(hubFailure);
|
|
28735
|
-
yield* menu(menuAsk, {
|
|
28785
|
+
return yield* menu(menuAsk, {
|
|
28736
28786
|
status,
|
|
28737
28787
|
home: NodeOS.homedir(),
|
|
28738
28788
|
here: gen$1(function* () {
|
|
@@ -28757,11 +28807,17 @@ const runMenu = (stateDir) => gen$1(function* () {
|
|
|
28757
28807
|
project: `${match.workspace}/${match.project}`
|
|
28758
28808
|
};
|
|
28759
28809
|
}),
|
|
28760
|
-
|
|
28810
|
+
editors: gen$1(function* () {
|
|
28761
28811
|
const coordination = (yield* status).coordination;
|
|
28762
28812
|
const mcp = yield* (yield* McpClients).connected;
|
|
28763
|
-
|
|
28764
|
-
|
|
28813
|
+
const env = yield* Environment;
|
|
28814
|
+
return EDITORS.map((id) => ({
|
|
28815
|
+
id,
|
|
28816
|
+
title: editorTitle(id),
|
|
28817
|
+
connected: id === "claude" ? coordination.claudeHooks : id === "codex" ? (coordination.codexHookHomes ?? []).some((home) => home.installed) : mcp.includes(id),
|
|
28818
|
+
launchable: (id === "claude" || id === "codex") && onPath(id, env.PATH)
|
|
28819
|
+
}));
|
|
28820
|
+
}).pipe(orElseSucceed(() => [])),
|
|
28765
28821
|
join: (slug) => join({ target: slug }, terminalIo).pipe(flatMap$1((joined) => sayNextStep(joined, terminalIo)), hubFailure),
|
|
28766
28822
|
founding: (slug) => workspaces.acceptFounding({ slug }).pipe(andThen(log(`Accepted: ${slug}. You are its owner.`)), hubFailure),
|
|
28767
28823
|
create: (name) => create({ name }, terminalIo).pipe(asVoid, hubFailure),
|
|
@@ -28814,10 +28870,8 @@ const runMenu = (stateDir) => gen$1(function* () {
|
|
|
28814
28870
|
if (opener !== void 0) yield* launch(PEER_DOWNLOAD);
|
|
28815
28871
|
return yield* fail(`peer core: the Peer app is not installed here${opener === void 0 ? "" : "; its download page is open"}: ${PEER_DOWNLOAD}`);
|
|
28816
28872
|
}),
|
|
28817
|
-
|
|
28818
|
-
|
|
28819
|
-
if (editor !== null) yield* connectEditor(editor, stateDir, terminalIo);
|
|
28820
|
-
}).pipe(hubFailure)
|
|
28873
|
+
connectEditor: (id) => connectEditor(id, stateDir, terminalIo).pipe(hubFailure),
|
|
28874
|
+
disconnectEditor: (id) => disconnectEditor(id, terminalIo).pipe(hubFailure)
|
|
28821
28875
|
}, terminalIo);
|
|
28822
28876
|
});
|
|
28823
28877
|
const registerIn = (stateDir) => (path, name) => tryPromise({
|
|
@@ -28832,12 +28886,15 @@ const loginCommand = make$62("login", {
|
|
|
28832
28886
|
}).pipe(withDescription("Sign this computer's Peer in to its Peer Hub; on a terminal, then a menu: create or join a workspace, share, invite."), withHandler((flags) => gen$1(function* () {
|
|
28833
28887
|
const config = yield* resolveConfig(flags);
|
|
28834
28888
|
yield* refuseWhileRunning(config.stateDir);
|
|
28835
|
-
yield* gen$1(function* () {
|
|
28889
|
+
const end = yield* gen$1(function* () {
|
|
28836
28890
|
const signedIn = (yield* (yield* PeerState).read).persisted.email;
|
|
28837
28891
|
const email = getOrUndefined(flags.email)?.trim();
|
|
28838
28892
|
if (email === void 0 || signedIn !== null && signedIn === email) {
|
|
28839
28893
|
if (signedIn === null) return yield* fail("peer core: nobody is signed in; run peer core login <email>.");
|
|
28840
|
-
if (!isTerminal())
|
|
28894
|
+
if (!isTerminal()) {
|
|
28895
|
+
yield* log(`Signed in: ${signedIn}`);
|
|
28896
|
+
return;
|
|
28897
|
+
}
|
|
28841
28898
|
return yield* runMenu(config.stateDir);
|
|
28842
28899
|
}
|
|
28843
28900
|
yield* login({
|
|
@@ -28845,9 +28902,41 @@ const loginCommand = make$62("login", {
|
|
|
28845
28902
|
...isSome(flags.code) ? { code: flags.code.value } : {},
|
|
28846
28903
|
...isSome(flags.hub) ? { hub: flags.hub.value } : {}
|
|
28847
28904
|
}, terminalIo);
|
|
28848
|
-
|
|
28905
|
+
return isTerminal() ? yield* runMenu(config.stateDir) : void 0;
|
|
28849
28906
|
}).pipe(hubFailure, provide(layer$107.pipe(provideMerge(oneShotLayer(config)))));
|
|
28907
|
+
if (end !== void 0) yield* afterMenu(end, config, flags);
|
|
28850
28908
|
})));
|
|
28909
|
+
/** Whether `command` is an executable in one of `path`'s folders. */
|
|
28910
|
+
const onPath = (command, path) => (path ?? "").split(NodePath.delimiter).some((dir) => {
|
|
28911
|
+
try {
|
|
28912
|
+
NodeFS.accessSync(NodePath.join(dir, command), NodeFS.constants.X_OK);
|
|
28913
|
+
return true;
|
|
28914
|
+
} catch {
|
|
28915
|
+
return false;
|
|
28916
|
+
}
|
|
28917
|
+
});
|
|
28918
|
+
/**
|
|
28919
|
+
* After the menu, with its state written and closed: Peer Core keeps coordinating when an editor
|
|
28920
|
+
* is connected and no Peer runs (the hooks only talk to a running Peer), and the editor the
|
|
28921
|
+
* person chose starts in the project, in this terminal.
|
|
28922
|
+
*/
|
|
28923
|
+
const afterMenu = (end, config, flags) => gen$1(function* () {
|
|
28924
|
+
if ((end.editorsConnected || end.launch !== void 0) && (yield* ownerOf(config.stateDir)) === null) {
|
|
28925
|
+
yield* serveDetached(config, flags);
|
|
28926
|
+
yield* log("Peer Core coordinates your agents in the background; peer core stop ends it.");
|
|
28927
|
+
}
|
|
28928
|
+
const launch = end.launch;
|
|
28929
|
+
if (launch === void 0) return;
|
|
28930
|
+
yield* log(`Starting ${editorTitle(launch.editor)} in ${launch.folder}…`);
|
|
28931
|
+
if ((yield* callback((resume) => {
|
|
28932
|
+
const child = NodeChildProcess.spawn(launch.editor, [], {
|
|
28933
|
+
cwd: launch.folder,
|
|
28934
|
+
stdio: "inherit"
|
|
28935
|
+
});
|
|
28936
|
+
child.once("error", () => resume(succeed$1(127)));
|
|
28937
|
+
child.once("exit", (exit) => resume(succeed$1(exit ?? 0)));
|
|
28938
|
+
})) === 127) return yield* fail(`peer core: could not start ${launch.editor}; is it installed?`);
|
|
28939
|
+
});
|
|
28851
28940
|
const createCommand = make$62("create", {
|
|
28852
28941
|
...authLocationFlags,
|
|
28853
28942
|
name: String$2("name").pipe(withDescription$2("The workspace's name.")),
|
|
@@ -55448,4 +55537,4 @@ function runCli(root = "t3") {
|
|
|
55448
55537
|
//#endregion
|
|
55449
55538
|
export { runCli };
|
|
55450
55539
|
|
|
55451
|
-
//# sourceMappingURL=binCli-
|
|
55540
|
+
//# sourceMappingURL=binCli-B32nSvwp.mjs.map
|