@p4code/cli 0.1.14 → 0.1.15
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 +355 -46
- package/dist/client/assets/{DiffPanel-BdNsdwM5.js → DiffPanel-Btlwh6tZ.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-CWcDqLso.js → FilePreviewPanel-CJRGrUq9.js} +2 -2
- package/dist/client/assets/{PreviewPanel-2u47bK5v.js → PreviewPanel-CM8chpxZ.js} +2 -2
- package/dist/client/assets/{angular-html-BLv19dHn.js → angular-html-BjmAeE7T.js} +2 -2
- package/dist/client/assets/{angular-ts-D41w0Au3.js → angular-ts-BBpxlOlP.js} +2 -2
- package/dist/client/assets/{apl-BEl8UFu4.js → apl-BbgMrCuX.js} +2 -2
- package/dist/client/assets/arrow-right-DYd55OqT.js +2 -0
- package/dist/client/assets/{astro-U1Y_O85L.js → astro-mUvWYN-n.js} +2 -2
- package/dist/client/assets/{blade-CZ232EWr.js → blade-B5QWyKCP.js} +2 -2
- package/dist/client/assets/{c-DirgNKaz.js → c-BfHpmPOy.js} +2 -2
- package/dist/client/assets/{cobol-B7WyPi1F.js → cobol-DLZOS_vG.js} +2 -2
- package/dist/client/assets/{coffee-C_qHkMIP.js → coffee-9TkBNWbZ.js} +2 -2
- package/dist/client/assets/{cpp-SPUhkLTs.js → cpp-qjIc-2IN.js} +2 -2
- package/dist/client/assets/{crystal-vq6jdakY.js → crystal-DCOpXRVe.js} +2 -2
- package/dist/client/assets/{css-BAnKum7K.js → css-Xrxx3evf.js} +2 -2
- package/dist/client/assets/{edge-BuMKesaI.js → edge-BJXKMMao.js} +2 -2
- package/dist/client/assets/{elixir-BL-W6BH4.js → elixir-_uRFN4Aw.js} +2 -2
- package/dist/client/assets/{elm-DiUCNL3v.js → elm-fwfp6NdI.js} +2 -2
- package/dist/client/assets/{erb-skcSurJb.js → erb-DfSw8n3G.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-BRTew3I1.js → fileCommentAnnotations-BCnpdEVp.js} +2 -2
- package/dist/client/assets/{git-rebase-dO-xI28x.js → git-rebase-CwGd8ZXk.js} +2 -2
- package/dist/client/assets/{glimmer-js-CECukRm7.js → glimmer-js-DIl7yS9j.js} +2 -2
- package/dist/client/assets/{glimmer-ts-CIaRC8zm.js → glimmer-ts-ClbRblrS.js} +2 -2
- package/dist/client/assets/{glsl-CKSbugKg.js → glsl-DPbTpA_H.js} +2 -2
- package/dist/client/assets/{graphql-BiZ7twV7.js → graphql-Ugw-cmPb.js} +2 -2
- package/dist/client/assets/{hack-BdAxCPD7.js → hack-BNaGlFKY.js} +2 -2
- package/dist/client/assets/{haml-SZR9Ndrp.js → haml-CADPiQL8.js} +2 -2
- package/dist/client/assets/{handlebars-BExVQKqz.js → handlebars-lMMkQPVI.js} +2 -2
- package/dist/client/assets/{html-CkYFYJn1.js → html-dV4yJf1E.js} +2 -2
- package/dist/client/assets/{html-derivative-Cop3EQeZ.js → html-derivative-DC417Zuq.js} +2 -2
- package/dist/client/assets/{http-DQ8c4u3s.js → http-DHNl1S4G.js} +2 -2
- package/dist/client/assets/{hurl-BKyyIuNR.js → hurl-MeTzE8YN.js} +2 -2
- package/dist/client/assets/{index-ClVe76A5.js → index-BmkbvCRH.js} +200 -200
- package/dist/client/assets/index-DvMVFBig.css +1 -0
- package/dist/client/assets/{java-CedFcWif.js → java-_z6VtRIC.js} +2 -2
- package/dist/client/assets/{javascript-BdXDoWFM.js → javascript-mzH0UoeT.js} +2 -2
- package/dist/client/assets/{jinja-CK8YWL7a.js → jinja-CcSfwgQN.js} +2 -2
- package/dist/client/assets/{jison-C-mnFz-X.js → jison-Dnr6DQYK.js} +2 -2
- package/dist/client/assets/{json-Dxix4Qbo.js → json-xiKHc2eN.js} +2 -2
- package/dist/client/assets/{jsx-6M0gL61I.js → jsx-B0uBKQ5P.js} +2 -2
- package/dist/client/assets/{julia-SXfQGJ8P.js → julia-Du1DH_tJ.js} +2 -2
- package/dist/client/assets/{just-O0TR05uE.js → just-DlyxJRKQ.js} +2 -2
- package/dist/client/assets/{latex-w7R_uAyc.js → latex-FzyaW41z.js} +2 -2
- package/dist/client/assets/{liquid-hPzEzmzZ.js → liquid-n6xLDAue.js} +2 -2
- package/dist/client/assets/{lua-D24pQ94w.js → lua-DL20UMyO.js} +2 -2
- package/dist/client/assets/{marko-DsaGFeHY.js → marko-OhxSvhVO.js} +2 -2
- package/dist/client/assets/{mdc-C4vifn2U.js → mdc-JFr_O-f6.js} +2 -2
- package/dist/client/assets/{nginx-KnKOgHWr.js → nginx-DO3MRFFZ.js} +2 -2
- package/dist/client/assets/{nim-CXVNWegc.js → nim-gxiT3Pjh.js} +2 -2
- package/dist/client/assets/{perl-_PU7gLJn.js → perl-uO1ltvnm.js} +2 -2
- package/dist/client/assets/{php-B--0cDl3.js → php-DkSF6XhT.js} +2 -2
- package/dist/client/assets/{pug-DELbYjHv.js → pug-D6ks186t.js} +2 -2
- package/dist/client/assets/{qml-CyGKPCuH.js → qml-CsabseTB.js} +2 -2
- package/dist/client/assets/{r-CSjDVJJY.js → r-UjYqKhF6.js} +2 -2
- package/dist/client/assets/{razor-ppZnQuQy.js → razor-Dr34iB-_.js} +2 -2
- package/dist/client/assets/{regexp-DAYlObpi.js → regexp-BG9MLSbj.js} +2 -2
- package/dist/client/assets/{rst-DV8sAt14.js → rst-I9GYrav4.js} +2 -2
- package/dist/client/assets/{ruby-DXISWktP.js → ruby-DQZcmBTL.js} +2 -2
- package/dist/client/assets/{sas-CJl6Tu3p.js → sas-To8Ja79N.js} +2 -2
- package/dist/client/assets/{scss-DmbKMDuD.js → scss-KhIYRETT.js} +2 -2
- package/dist/client/assets/{shellscript-BFH8QS9G.js → shellscript-B3M9HD4S.js} +2 -2
- package/dist/client/assets/{shellsession-CIHFsdwm.js → shellsession-DCI3i_rX.js} +2 -2
- package/dist/client/assets/{soy--q_a3wNH.js → soy-11gkdBZx.js} +2 -2
- package/dist/client/assets/{sql-DE3xygzU.js → sql-Dc2GulG4.js} +2 -2
- package/dist/client/assets/{stata-BZORI8K-.js → stata-Br5SUE30.js} +2 -2
- package/dist/client/assets/{surrealql-DQwYGqPv.js → surrealql-Rg04dQNn.js} +2 -2
- package/dist/client/assets/{svelte-C8rcZCbS.js → svelte-CtlB9-BL.js} +2 -2
- package/dist/client/assets/{templ-YxwRimHC.js → templ-Du0y714B.js} +2 -2
- package/dist/client/assets/{tex-CreWrrVU.js → tex-DujbYFg6.js} +2 -2
- package/dist/client/assets/textarea-C3IX8FEW.js +46 -0
- package/dist/client/assets/{ts-tags-BGYLwTar.js → ts-tags-D1giNT28.js} +2 -2
- package/dist/client/assets/{tsx-dvRLM93g.js → tsx-6OJBHQve.js} +2 -2
- package/dist/client/assets/{twig-BwKK1q-j.js → twig-CsGDI-1m.js} +2 -2
- package/dist/client/assets/{typescript-CIA9s0mZ.js → typescript-BK1jdq6h.js} +2 -2
- package/dist/client/assets/{vue-RR_2K8-s.js → vue-CcdGezrU.js} +2 -2
- package/dist/client/assets/{vue-html-SobvEO2e.js → vue-html-Cki3bF1b.js} +2 -2
- package/dist/client/assets/{vue-vine-BQgxB5Yf.js → vue-vine-CqNi4Hn_.js} +2 -2
- package/dist/client/assets/{xml-qR9OaTYe.js → xml-By8mAu2E.js} +2 -2
- package/dist/client/assets/{xsl-CNAIK0Wp.js → xsl-DWgCtTr-.js} +2 -2
- package/dist/client/assets/{yaml-CnmdSZli.js → yaml-DZTshk4U.js} +2 -2
- package/dist/client/index.html +3 -3
- package/package.json +1 -1
- package/dist/client/assets/arrow-right-Tef5pBUM.js +0 -2
- package/dist/client/assets/index-DGu8ejUP.css +0 -1
- package/dist/client/assets/textarea-DogWRke3.js +0 -46
package/dist/bin.mjs
CHANGED
|
@@ -121,7 +121,7 @@ const closeServer = (server) => {
|
|
|
121
121
|
* NetService - Service tag for startup networking helpers.
|
|
122
122
|
*/
|
|
123
123
|
var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
|
|
124
|
-
const make$
|
|
124
|
+
const make$75 = () => {
|
|
125
125
|
/**
|
|
126
126
|
* Returns true when a TCP server can bind to {host, port}.
|
|
127
127
|
* `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
|
|
@@ -230,10 +230,10 @@ const make$74 = () => {
|
|
|
230
230
|
})
|
|
231
231
|
};
|
|
232
232
|
};
|
|
233
|
-
const layer$
|
|
233
|
+
const layer$71 = Layer.sync(NetService, make$75);
|
|
234
234
|
//#endregion
|
|
235
235
|
//#region package.json
|
|
236
|
-
var version = "0.1.
|
|
236
|
+
var version = "0.1.15";
|
|
237
237
|
//#endregion
|
|
238
238
|
//#region src/config.ts
|
|
239
239
|
/**
|
|
@@ -254,8 +254,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
|
|
|
254
254
|
/** @deprecated Import and use `layerTest` from this module. */
|
|
255
255
|
static layerTest = (cwd, baseDirOrPrefix) => layerTest$2(cwd, baseDirOrPrefix);
|
|
256
256
|
};
|
|
257
|
-
const make$
|
|
258
|
-
const layer$
|
|
257
|
+
const make$74 = (config) => ServerConfig$1.of(config);
|
|
258
|
+
const layer$70 = (config) => Layer.succeed(ServerConfig$1, make$74(config));
|
|
259
259
|
const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
|
|
260
260
|
const { join } = yield* Path.Path;
|
|
261
261
|
const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
|
|
@@ -8217,17 +8217,62 @@ const McpServerOAuthStatus = Schema$1.Struct({
|
|
|
8217
8217
|
* unusable *here*, and saying which slot is empty is the difference between a
|
|
8218
8218
|
* fixable state and a mystery.
|
|
8219
8219
|
*/
|
|
8220
|
+
/**
|
|
8221
|
+
* Where a listed server lives, which is also where an edit goes.
|
|
8222
|
+
*
|
|
8223
|
+
* `claude` is the CLI's user scope (`~/.claude.json`) — the primary home,
|
|
8224
|
+
* because every Claude Code session reads it, inside p4code and out.
|
|
8225
|
+
* `project` is one workspace project's `.mcp.json`, committed with the repo.
|
|
8226
|
+
* `registry` is p4code's own store, the only one that syncs through the hub
|
|
8227
|
+
* and carries secret slots.
|
|
8228
|
+
*/
|
|
8229
|
+
const McpServerSource = Schema$1.Literals([
|
|
8230
|
+
"registry",
|
|
8231
|
+
"claude",
|
|
8232
|
+
"project"
|
|
8233
|
+
]);
|
|
8220
8234
|
const McpServerStatus = Schema$1.Struct({
|
|
8221
8235
|
registration: McpServerRegistration,
|
|
8222
8236
|
missingSecrets: Schema$1.Array(McpSecretSlot),
|
|
8223
8237
|
/** True when this machine holds everything needed to start it. */
|
|
8224
8238
|
ready: Schema$1.Boolean,
|
|
8225
8239
|
/** Absent for servers that never challenged and hold no token here. */
|
|
8226
|
-
oauth: Schema$1.optional(McpServerOAuthStatus)
|
|
8240
|
+
oauth: Schema$1.optional(McpServerOAuthStatus),
|
|
8241
|
+
/** Absent means `registry`, which every row was before this field existed. */
|
|
8242
|
+
source: Schema$1.optional(McpServerSource),
|
|
8243
|
+
/** The workspace root whose `.mcp.json` holds this row. `project` rows only. */
|
|
8244
|
+
projectDir: Schema$1.optional(Schema$1.String)
|
|
8245
|
+
});
|
|
8246
|
+
/** A workspace project the panel can scope a server to. */
|
|
8247
|
+
const McpProjectRef = Schema$1.Struct({
|
|
8248
|
+
dir: Schema$1.String,
|
|
8249
|
+
title: Schema$1.String
|
|
8250
|
+
});
|
|
8251
|
+
const McpServerList = Schema$1.Struct({
|
|
8252
|
+
servers: Schema$1.Array(McpServerStatus),
|
|
8253
|
+
/**
|
|
8254
|
+
* The projects whose `.mcp.json` can be edited, for the add dialog's scope
|
|
8255
|
+
* picker. Carried with the list so the panel needs no second request.
|
|
8256
|
+
*/
|
|
8257
|
+
projects: Schema$1.optional(Schema$1.Array(McpProjectRef))
|
|
8258
|
+
});
|
|
8259
|
+
/**
|
|
8260
|
+
* `source` routes the write: `claude` edits the `mcpServers` key of the
|
|
8261
|
+
* CLI's user-scope file, `registry` (or absent) writes p4code's own store.
|
|
8262
|
+
* The user-scope file is the primary home — it is what every Claude Code
|
|
8263
|
+
* session reads, in and out of p4code — so the panel defaults to it.
|
|
8264
|
+
*/
|
|
8265
|
+
const McpServerSaveInput = Schema$1.Struct({
|
|
8266
|
+
registration: McpServerRegistration,
|
|
8267
|
+
source: Schema$1.optional(McpServerSource),
|
|
8268
|
+
/** Required when `source` is `project`: the workspace root to write into. */
|
|
8269
|
+
projectDir: Schema$1.optional(Schema$1.String)
|
|
8270
|
+
});
|
|
8271
|
+
const McpServerNameInput = Schema$1.Struct({
|
|
8272
|
+
name: McpServerName,
|
|
8273
|
+
source: Schema$1.optional(McpServerSource),
|
|
8274
|
+
projectDir: Schema$1.optional(Schema$1.String)
|
|
8227
8275
|
});
|
|
8228
|
-
const McpServerList = Schema$1.Struct({ servers: Schema$1.Array(McpServerStatus) });
|
|
8229
|
-
const McpServerSaveInput = Schema$1.Struct({ registration: McpServerRegistration });
|
|
8230
|
-
const McpServerNameInput = Schema$1.Struct({ name: McpServerName });
|
|
8231
8276
|
/**
|
|
8232
8277
|
* Setting one secret value, on this machine only.
|
|
8233
8278
|
*
|
|
@@ -9405,7 +9450,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
9405
9450
|
//#endregion
|
|
9406
9451
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
9407
9452
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
9408
|
-
const make$
|
|
9453
|
+
const make$73 = Effect.gen(function* () {
|
|
9409
9454
|
const config = yield* ServerConfig$1;
|
|
9410
9455
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
9411
9456
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -9423,7 +9468,7 @@ const make$72 = Effect.gen(function* () {
|
|
|
9423
9468
|
};
|
|
9424
9469
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
9425
9470
|
});
|
|
9426
|
-
const layer$
|
|
9471
|
+
const layer$69 = Layer.effect(EnvironmentAuthPolicy, make$73);
|
|
9427
9472
|
//#endregion
|
|
9428
9473
|
//#region src/persistence/Errors.ts
|
|
9429
9474
|
function summarizeSchemaIssue(issue) {
|
|
@@ -9604,7 +9649,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
9604
9649
|
cause
|
|
9605
9650
|
});
|
|
9606
9651
|
}
|
|
9607
|
-
const make$
|
|
9652
|
+
const make$72 = Effect.gen(function* () {
|
|
9608
9653
|
const sql = yield* SqlClient.SqlClient;
|
|
9609
9654
|
const createSessionRow = SqlSchema.void({
|
|
9610
9655
|
Request: CreateAuthSessionInput,
|
|
@@ -9738,7 +9783,7 @@ const make$71 = Effect.gen(function* () {
|
|
|
9738
9783
|
setLastConnectedAt
|
|
9739
9784
|
};
|
|
9740
9785
|
});
|
|
9741
|
-
const layer$
|
|
9786
|
+
const layer$68 = Layer.effect(AuthSessionRepository, make$72);
|
|
9742
9787
|
//#endregion
|
|
9743
9788
|
//#region src/auth/ServerSecretStore.ts
|
|
9744
9789
|
const secretStoreErrorContext = {
|
|
@@ -9805,7 +9850,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
|
|
|
9805
9850
|
const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
|
|
9806
9851
|
const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
|
|
9807
9852
|
var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
|
|
9808
|
-
const make$
|
|
9853
|
+
const make$71 = Effect.gen(function* () {
|
|
9809
9854
|
const crypto = yield* Crypto.Crypto;
|
|
9810
9855
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
9811
9856
|
const path = yield* Path.Path;
|
|
@@ -9875,7 +9920,7 @@ const make$70 = Effect.gen(function* () {
|
|
|
9875
9920
|
remove
|
|
9876
9921
|
});
|
|
9877
9922
|
});
|
|
9878
|
-
const layer$
|
|
9923
|
+
const layer$67 = Layer.effect(ServerSecretStore, make$71);
|
|
9879
9924
|
//#endregion
|
|
9880
9925
|
//#region src/auth/SessionStore.ts
|
|
9881
9926
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -10113,7 +10158,7 @@ function toAuthClientSession(input) {
|
|
|
10113
10158
|
current: false
|
|
10114
10159
|
};
|
|
10115
10160
|
}
|
|
10116
|
-
const make$
|
|
10161
|
+
const make$70 = Effect.gen(function* () {
|
|
10117
10162
|
const crypto = yield* Crypto.Crypto;
|
|
10118
10163
|
const serverConfig = yield* ServerConfig$1;
|
|
10119
10164
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -10427,7 +10472,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
10427
10472
|
markDisconnected
|
|
10428
10473
|
});
|
|
10429
10474
|
});
|
|
10430
|
-
const layer$
|
|
10475
|
+
const layer$66 = Layer.effect(SessionStore, make$70).pipe(Layer.provideMerge(layer$68));
|
|
10431
10476
|
//#endregion
|
|
10432
10477
|
//#region src/persistence/AuthPairingLinks.ts
|
|
10433
10478
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -10488,7 +10533,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
10488
10533
|
cause
|
|
10489
10534
|
});
|
|
10490
10535
|
}
|
|
10491
|
-
const make$
|
|
10536
|
+
const make$69 = Effect.gen(function* () {
|
|
10492
10537
|
const sql = yield* SqlClient.SqlClient;
|
|
10493
10538
|
const createPairingLinkRow = SqlSchema.void({
|
|
10494
10539
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -10623,7 +10668,7 @@ const make$68 = Effect.gen(function* () {
|
|
|
10623
10668
|
getByCredential
|
|
10624
10669
|
};
|
|
10625
10670
|
});
|
|
10626
|
-
const layer$
|
|
10671
|
+
const layer$65 = Layer.effect(AuthPairingLinkRepository, make$69);
|
|
10627
10672
|
//#endregion
|
|
10628
10673
|
//#region src/auth/PairingGrantStore.ts
|
|
10629
10674
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -10718,7 +10763,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
10718
10763
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
10719
10764
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
10720
10765
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
10721
|
-
const make$
|
|
10766
|
+
const make$68 = Effect.gen(function* () {
|
|
10722
10767
|
const crypto = yield* Crypto.Crypto;
|
|
10723
10768
|
const config = yield* ServerConfig$1;
|
|
10724
10769
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -10916,7 +10961,7 @@ const make$67 = Effect.gen(function* () {
|
|
|
10916
10961
|
consume
|
|
10917
10962
|
});
|
|
10918
10963
|
});
|
|
10919
|
-
const layer$
|
|
10964
|
+
const layer$64 = Layer.effect(PairingGrantStore, make$68).pipe(Layer.provideMerge(layer$65));
|
|
10920
10965
|
//#endregion
|
|
10921
10966
|
//#region src/persistence/Migrations/001_OrchestrationEvents.ts
|
|
10922
10967
|
var _001_OrchestrationEvents_default = Effect.gen(function* () {
|
|
@@ -12771,7 +12816,7 @@ function parseBearerToken(request) {
|
|
|
12771
12816
|
const token = header.slice(7).trim();
|
|
12772
12817
|
return token.length > 0 ? token : null;
|
|
12773
12818
|
}
|
|
12774
|
-
const make$
|
|
12819
|
+
const make$67 = Effect.gen(function* () {
|
|
12775
12820
|
const policy = yield* EnvironmentAuthPolicy;
|
|
12776
12821
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
12777
12822
|
const sessions = yield* SessionStore;
|
|
@@ -12966,9 +13011,9 @@ const make$66 = Effect.gen(function* () {
|
|
|
12966
13011
|
issueStartupPairingUrl
|
|
12967
13012
|
});
|
|
12968
13013
|
});
|
|
12969
|
-
const layer$
|
|
12970
|
-
const storageLayer = Layer.mergeAll(layer$
|
|
12971
|
-
const runtimeLayer = layer$
|
|
13014
|
+
const layer$63 = Layer.effect(EnvironmentAuth, make$67).pipe(Layer.provideMerge(layer$64), Layer.provideMerge(layer$66), Layer.provideMerge(layer$69));
|
|
13015
|
+
const storageLayer = Layer.mergeAll(layer$67, layerConfig);
|
|
13016
|
+
const runtimeLayer = layer$63.pipe(Layer.provideMerge(storageLayer));
|
|
12972
13017
|
//#endregion
|
|
12973
13018
|
//#region src/cliAuthFormat.ts
|
|
12974
13019
|
const newline = "\n";
|
|
@@ -13723,7 +13768,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
|
|
|
13723
13768
|
}
|
|
13724
13769
|
return yield* Effect.gen(function* () {
|
|
13725
13770
|
return yield* run(yield* EnvironmentAuth);
|
|
13726
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$
|
|
13771
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$70(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
13727
13772
|
});
|
|
13728
13773
|
const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
|
|
13729
13774
|
const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
|
|
@@ -13863,7 +13908,7 @@ const DEFAULT_LIMITS = {
|
|
|
13863
13908
|
windowMillis: FAILURE_WINDOW_MS,
|
|
13864
13909
|
blockMillis: BLOCK_DURATION_MS
|
|
13865
13910
|
};
|
|
13866
|
-
const make$
|
|
13911
|
+
const make$66 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
13867
13912
|
const state = yield* Ref.make(initialThrottleState);
|
|
13868
13913
|
return HubAuthThrottle.of({
|
|
13869
13914
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -13877,7 +13922,7 @@ const make$65 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
|
|
|
13877
13922
|
})
|
|
13878
13923
|
});
|
|
13879
13924
|
});
|
|
13880
|
-
const layer$
|
|
13925
|
+
const layer$62 = Layer.effect(HubAuthThrottle, make$66());
|
|
13881
13926
|
//#endregion
|
|
13882
13927
|
//#region src/hub/HubAuth.ts
|
|
13883
13928
|
/**
|
|
@@ -14676,7 +14721,7 @@ const deleteAssetRoute = HttpRouter.add("DELETE", "/assets/:kind/:name", respond
|
|
|
14676
14721
|
const outcome = yield* (yield* AgentAssetRepository).deleteByName(requested);
|
|
14677
14722
|
return outcome._tag === "conflict" ? assetConflict(Option.getOrNull(outcome.current)) : HttpServerResponse.empty({ status: 204 });
|
|
14678
14723
|
})));
|
|
14679
|
-
const layer$
|
|
14724
|
+
const layer$61 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute);
|
|
14680
14725
|
//#endregion
|
|
14681
14726
|
//#region src/hub/Migrations/001_Tasks.ts
|
|
14682
14727
|
/**
|
|
@@ -14955,7 +15000,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
|
|
|
14955
15000
|
});
|
|
14956
15001
|
if (isRemoteReachableHost(config.host)) yield* Effect.logWarning("Hub is reachable beyond loopback. The bearer token is the only control — repeated auth failures are not rate limited.", { host: config.host });
|
|
14957
15002
|
}));
|
|
14958
|
-
const makeHubLayer = HttpRouter.serve(layer$
|
|
15003
|
+
const makeHubLayer = HttpRouter.serve(layer$61).pipe(Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$62), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
|
|
14959
15004
|
const runHub = Layer.launch(makeHubLayer);
|
|
14960
15005
|
//#endregion
|
|
14961
15006
|
//#region src/atomicWrite.ts
|
|
@@ -15079,7 +15124,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
15079
15124
|
}
|
|
15080
15125
|
return Object.is(current, defaults) ? void 0 : current;
|
|
15081
15126
|
}
|
|
15082
|
-
const make$
|
|
15127
|
+
const make$65 = Effect.gen(function* () {
|
|
15083
15128
|
const { settingsPath } = yield* ServerConfig$1;
|
|
15084
15129
|
const fs = yield* FileSystem.FileSystem;
|
|
15085
15130
|
const pathService = yield* Path.Path;
|
|
@@ -15300,7 +15345,7 @@ const make$64 = Effect.gen(function* () {
|
|
|
15300
15345
|
}
|
|
15301
15346
|
};
|
|
15302
15347
|
});
|
|
15303
|
-
const layer$
|
|
15348
|
+
const layer$60 = Layer.effect(ServerSettingsService, make$65);
|
|
15304
15349
|
//#endregion
|
|
15305
15350
|
//#region src/pathExpansion.ts
|
|
15306
15351
|
/**
|
|
@@ -15510,6 +15555,192 @@ const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config
|
|
|
15510
15555
|
return [...skillsByName.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
15511
15556
|
});
|
|
15512
15557
|
//#endregion
|
|
15558
|
+
//#region src/mcp/ClaudeMcpFiles.ts
|
|
15559
|
+
/**
|
|
15560
|
+
* The MCP servers in Claude Code's own configuration files.
|
|
15561
|
+
*
|
|
15562
|
+
* Two homes, both the CLI's and both primary over p4code's registry:
|
|
15563
|
+
*
|
|
15564
|
+
* - **User scope**: the `mcpServers` key of `~/.claude.json`. Every Claude
|
|
15565
|
+
* Code session reads it, inside p4code and out.
|
|
15566
|
+
* - **Project scope**: `<project>/.mcp.json`, committed with the repository
|
|
15567
|
+
* and read by every session working in it.
|
|
15568
|
+
*
|
|
15569
|
+
* The settings panel manages both directly — list, add, edit, remove — so
|
|
15570
|
+
* this service writes them. **A user-scope write touches only the
|
|
15571
|
+
* `mcpServers` key**; `~/.claude.json` also holds `oauthAccount`, `machineID`
|
|
15572
|
+
* and a `projects` map, and everything outside the one key is carried
|
|
15573
|
+
* through a write as parsed. This is the same read-modify-write the
|
|
15574
|
+
* `claude mcp add` command performs, with the same last-writer-wins caveat
|
|
15575
|
+
* when a CLI session saves concurrently.
|
|
15576
|
+
*
|
|
15577
|
+
* A malformed entry, a name that would not survive as a registry filename, or
|
|
15578
|
+
* a missing file all cost only what they describe: that entry, or that one
|
|
15579
|
+
* file's list, never the panel.
|
|
15580
|
+
*
|
|
15581
|
+
* @module mcp/ClaudeMcpFiles
|
|
15582
|
+
*/
|
|
15583
|
+
const isServerName = Schema$1.is(McpServerName);
|
|
15584
|
+
/** The file a project's scope lives in, beside its lockfiles and dotfiles. */
|
|
15585
|
+
const PROJECT_MCP_FILENAME = ".mcp.json";
|
|
15586
|
+
/**
|
|
15587
|
+
* One entry as the CLI writes it. `type` is absent for the CLI's original
|
|
15588
|
+
* stdio-only shape, so it defaults rather than discriminates.
|
|
15589
|
+
*/
|
|
15590
|
+
const ClaudeMcpEntry = Schema$1.Struct({
|
|
15591
|
+
type: Schema$1.optional(Schema$1.Literals([
|
|
15592
|
+
"stdio",
|
|
15593
|
+
"http",
|
|
15594
|
+
"sse"
|
|
15595
|
+
])),
|
|
15596
|
+
command: Schema$1.optional(Schema$1.String),
|
|
15597
|
+
args: Schema$1.optional(Schema$1.Array(Schema$1.String)),
|
|
15598
|
+
env: Schema$1.optional(Schema$1.Record(Schema$1.String, Schema$1.String)),
|
|
15599
|
+
url: Schema$1.optional(Schema$1.String),
|
|
15600
|
+
headers: Schema$1.optional(Schema$1.Record(Schema$1.String, Schema$1.String))
|
|
15601
|
+
});
|
|
15602
|
+
/**
|
|
15603
|
+
* A config file as this service needs to see it: the one key it owns, with
|
|
15604
|
+
* every other key carried as parsed. Both `~/.claude.json` and `.mcp.json`
|
|
15605
|
+
* decode through this — the former has many other keys, the latter none.
|
|
15606
|
+
*/
|
|
15607
|
+
const McpConfigFile = Schema$1.StructWithRest(Schema$1.Struct({ mcpServers: Schema$1.optional(Schema$1.Record(Schema$1.String, Schema$1.Unknown)) }), [Schema$1.Record(Schema$1.String, Schema$1.Unknown)]);
|
|
15608
|
+
const McpConfigFileFromJson = Schema$1.fromJsonString(McpConfigFile);
|
|
15609
|
+
const decodeConfigFile = Schema$1.decodeUnknownExit(McpConfigFileFromJson);
|
|
15610
|
+
const encodeConfigFile = Schema$1.encodeSync(McpConfigFileFromJson);
|
|
15611
|
+
const decodeEntry = Schema$1.decodeUnknownExit(ClaudeMcpEntry);
|
|
15612
|
+
/** Where the CLI keeps user scope: `$CLAUDE_CONFIG_DIR/.claude.json` when set, else `~/.claude.json`. */
|
|
15613
|
+
const claudeUserConfigPath = Effect.fn("claudeUserConfigPath")(function* () {
|
|
15614
|
+
const path = yield* Path.Path;
|
|
15615
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"]?.trim() ?? "";
|
|
15616
|
+
return configDir.length > 0 ? path.join(path.resolve(configDir), ".claude.json") : path.join(NodeOS.homedir(), ".claude.json");
|
|
15617
|
+
});
|
|
15618
|
+
/**
|
|
15619
|
+
* Map one CLI entry to a registration, or nothing when it cannot be one.
|
|
15620
|
+
*
|
|
15621
|
+
* `enabled: true` because presence in the CLI's file is what enabled means
|
|
15622
|
+
* there. Exported for tests.
|
|
15623
|
+
*/
|
|
15624
|
+
function registrationFromClaudeEntry(name, entry) {
|
|
15625
|
+
if (!isServerName(name)) return void 0;
|
|
15626
|
+
const decoded = decodeEntry(entry);
|
|
15627
|
+
if (decoded._tag !== "Success") return void 0;
|
|
15628
|
+
const value = decoded.value;
|
|
15629
|
+
const type = value.type ?? "stdio";
|
|
15630
|
+
if (type === "stdio") {
|
|
15631
|
+
if (value.command === void 0 || value.command.trim().length === 0) return void 0;
|
|
15632
|
+
return {
|
|
15633
|
+
name,
|
|
15634
|
+
transport: "stdio",
|
|
15635
|
+
enabled: true,
|
|
15636
|
+
command: value.command,
|
|
15637
|
+
...value.args !== void 0 && value.args.length > 0 ? { args: value.args } : {},
|
|
15638
|
+
...value.env !== void 0 && Object.keys(value.env).length > 0 ? { env: value.env } : {}
|
|
15639
|
+
};
|
|
15640
|
+
}
|
|
15641
|
+
if (value.url === void 0 || value.url.trim().length === 0) return void 0;
|
|
15642
|
+
return {
|
|
15643
|
+
name,
|
|
15644
|
+
transport: type,
|
|
15645
|
+
enabled: true,
|
|
15646
|
+
url: value.url,
|
|
15647
|
+
...value.headers !== void 0 && Object.keys(value.headers).length > 0 ? { headers: value.headers } : {}
|
|
15648
|
+
};
|
|
15649
|
+
}
|
|
15650
|
+
/**
|
|
15651
|
+
* The inverse mapping, for writes. `enabled` is dropped: the CLI has no such
|
|
15652
|
+
* flag, and presence in the file is what enabled means there. Exported for
|
|
15653
|
+
* tests, so the two mappings can be checked as a round trip.
|
|
15654
|
+
*/
|
|
15655
|
+
function claudeEntryFromRegistration(registration) {
|
|
15656
|
+
if (registration.transport === "stdio") return {
|
|
15657
|
+
type: "stdio",
|
|
15658
|
+
command: registration.command,
|
|
15659
|
+
...registration.args !== void 0 && registration.args.length > 0 ? { args: registration.args } : {},
|
|
15660
|
+
...registration.env !== void 0 && Object.keys(registration.env).length > 0 ? { env: registration.env } : {}
|
|
15661
|
+
};
|
|
15662
|
+
return {
|
|
15663
|
+
type: registration.transport,
|
|
15664
|
+
url: registration.url,
|
|
15665
|
+
...registration.headers !== void 0 && Object.keys(registration.headers).length > 0 ? { headers: registration.headers } : {}
|
|
15666
|
+
};
|
|
15667
|
+
}
|
|
15668
|
+
var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
|
|
15669
|
+
const make$64 = Effect.gen(function* () {
|
|
15670
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
15671
|
+
const path = yield* Path.Path;
|
|
15672
|
+
const services = yield* Effect.context();
|
|
15673
|
+
const readEntries = Effect.fn("ClaudeMcpFiles.readEntries")(function* (filePath) {
|
|
15674
|
+
const raw = yield* fileSystem.readFileString(filePath).pipe(Effect.orElseSucceed(() => void 0));
|
|
15675
|
+
if (raw === void 0) return [];
|
|
15676
|
+
const decoded = decodeConfigFile(raw);
|
|
15677
|
+
if (decoded._tag !== "Success") return [];
|
|
15678
|
+
const found = [];
|
|
15679
|
+
for (const [name, entry] of Object.entries(decoded.value.mcpServers ?? {})) {
|
|
15680
|
+
const registration = registrationFromClaudeEntry(name, entry);
|
|
15681
|
+
if (registration !== void 0) found.push(registration);
|
|
15682
|
+
}
|
|
15683
|
+
return found;
|
|
15684
|
+
});
|
|
15685
|
+
const readAt = (filePath) => filePath.pipe(Effect.flatMap((resolved) => readEntries(resolved)), Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("claude mcp config read failed", { cause }).pipe(Effect.as([]))));
|
|
15686
|
+
/**
|
|
15687
|
+
* Read, change the one key, write back atomically.
|
|
15688
|
+
*
|
|
15689
|
+
* A file that exists but will not parse fails the write loudly instead of
|
|
15690
|
+
* being replaced with `{ mcpServers }`: whatever is in it — including a
|
|
15691
|
+
* `~/.claude.json` full of the CLI's own state — is worth more than the
|
|
15692
|
+
* edit. A missing file starts from empty, which is how `.mcp.json` is born.
|
|
15693
|
+
*/
|
|
15694
|
+
const changeFile = Effect.fn("ClaudeMcpFiles.changeFile")(function* (filePath, change) {
|
|
15695
|
+
const raw = yield* fileSystem.readFileString(filePath).pipe(Effect.orElseSucceed(() => void 0), Effect.provide(services));
|
|
15696
|
+
const decoded = raw === void 0 ? void 0 : decodeConfigFile(raw);
|
|
15697
|
+
if (decoded !== void 0 && decoded._tag !== "Success") return yield* new McpRegistryError({ detail: `${filePath} exists but could not be parsed, so it was left alone.` });
|
|
15698
|
+
const root = decoded === void 0 ? {} : decoded.value;
|
|
15699
|
+
const nextServers = change({ ...root.mcpServers });
|
|
15700
|
+
yield* fileSystem.makeDirectory(path.dirname(filePath), { recursive: true }).pipe(Effect.ignore, Effect.provide(services));
|
|
15701
|
+
yield* writeFileStringAtomically({
|
|
15702
|
+
filePath,
|
|
15703
|
+
contents: `${encodeConfigFile({
|
|
15704
|
+
...root,
|
|
15705
|
+
mcpServers: nextServers
|
|
15706
|
+
})}\n`
|
|
15707
|
+
}).pipe(Effect.provide(services), Effect.mapError(() => new McpRegistryError({ detail: `Could not write ${filePath}.` })));
|
|
15708
|
+
});
|
|
15709
|
+
const projectFile = (projectDir) => path.join(path.resolve(projectDir), PROJECT_MCP_FILENAME);
|
|
15710
|
+
const upsertAt = (filePath) => Effect.fn("ClaudeMcpFiles.upsertAt")(function* (registration) {
|
|
15711
|
+
const resolved = yield* filePath.pipe(Effect.provide(services));
|
|
15712
|
+
yield* changeFile(resolved, (entries) => ({
|
|
15713
|
+
...entries,
|
|
15714
|
+
[registration.name]: claudeEntryFromRegistration(registration)
|
|
15715
|
+
}));
|
|
15716
|
+
});
|
|
15717
|
+
const removeAt = (filePath) => Effect.fn("ClaudeMcpFiles.removeAt")(function* (name) {
|
|
15718
|
+
const resolved = yield* filePath.pipe(Effect.provide(services));
|
|
15719
|
+
yield* changeFile(resolved, (entries) => {
|
|
15720
|
+
const { [name]: _removed, ...rest } = entries;
|
|
15721
|
+
return rest;
|
|
15722
|
+
});
|
|
15723
|
+
});
|
|
15724
|
+
const userPath = claudeUserConfigPath();
|
|
15725
|
+
return {
|
|
15726
|
+
readUser: readAt(userPath),
|
|
15727
|
+
upsertUser: (registration) => upsertAt(userPath)(registration),
|
|
15728
|
+
removeUser: (name) => removeAt(userPath)(name),
|
|
15729
|
+
readProject: (projectDir) => readAt(Effect.succeed(projectFile(projectDir))),
|
|
15730
|
+
upsertProject: (projectDir, registration) => upsertAt(Effect.succeed(projectFile(projectDir)))(registration),
|
|
15731
|
+
removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
|
|
15732
|
+
};
|
|
15733
|
+
});
|
|
15734
|
+
const layer$59 = Layer.effect(ClaudeMcpFiles, make$64);
|
|
15735
|
+
Layer.succeed(ClaudeMcpFiles, {
|
|
15736
|
+
readUser: Effect.succeed([]),
|
|
15737
|
+
upsertUser: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
|
|
15738
|
+
removeUser: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
|
|
15739
|
+
readProject: () => Effect.succeed([]),
|
|
15740
|
+
upsertProject: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
|
|
15741
|
+
removeProject: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." }))
|
|
15742
|
+
});
|
|
15743
|
+
//#endregion
|
|
15513
15744
|
//#region src/mcp/McpOAuth.ts
|
|
15514
15745
|
/**
|
|
15515
15746
|
* OAuth sign-in for remote MCP servers, per the MCP authorization spec.
|
|
@@ -15978,6 +16209,7 @@ const make$62 = Effect.gen(function* () {
|
|
|
15978
16209
|
const config = yield* ServerConfig$1;
|
|
15979
16210
|
const secrets = yield* ServerSecretStore;
|
|
15980
16211
|
const oauth = yield* McpOAuth;
|
|
16212
|
+
const claudeFiles = yield* ClaudeMcpFiles;
|
|
15981
16213
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
15982
16214
|
const path = yield* Path.Path;
|
|
15983
16215
|
const services = yield* Effect.context();
|
|
@@ -16026,7 +16258,21 @@ const make$62 = Effect.gen(function* () {
|
|
|
16026
16258
|
registration,
|
|
16027
16259
|
missingSecrets,
|
|
16028
16260
|
ready: registration.enabled && missingSecrets.length === 0 && !needsSignIn,
|
|
16029
|
-
...Option.isSome(oauthStatus) ? { oauth: oauthStatus.value } : {}
|
|
16261
|
+
...Option.isSome(oauthStatus) ? { oauth: oauthStatus.value } : {},
|
|
16262
|
+
source: "registry"
|
|
16263
|
+
});
|
|
16264
|
+
}
|
|
16265
|
+
const registryNames = new Set(statuses.map((status) => status.registration.name));
|
|
16266
|
+
for (const userScope of yield* claudeFiles.readUser) {
|
|
16267
|
+
if (registryNames.has(userScope.name)) continue;
|
|
16268
|
+
const oauthStatus = userScope.transport === "stdio" ? Option.none() : yield* oauth.statusFor(userScope);
|
|
16269
|
+
const needsSignIn = Option.isSome(oauthStatus) && !oauthStatus.value.connected;
|
|
16270
|
+
statuses.push({
|
|
16271
|
+
registration: userScope,
|
|
16272
|
+
missingSecrets: [],
|
|
16273
|
+
ready: !needsSignIn,
|
|
16274
|
+
...Option.isSome(oauthStatus) ? { oauth: oauthStatus.value } : {},
|
|
16275
|
+
source: "claude"
|
|
16030
16276
|
});
|
|
16031
16277
|
}
|
|
16032
16278
|
return statuses;
|
|
@@ -16092,6 +16338,20 @@ const make$62 = Effect.gen(function* () {
|
|
|
16092
16338
|
headers
|
|
16093
16339
|
};
|
|
16094
16340
|
}
|
|
16341
|
+
for (const userScope of yield* claudeFiles.readUser) {
|
|
16342
|
+
if (userScope.transport === "stdio") continue;
|
|
16343
|
+
if (userScope.name in resolved) continue;
|
|
16344
|
+
const token = yield* oauth.accessTokenFor(userScope);
|
|
16345
|
+
if (Option.isNone(token)) continue;
|
|
16346
|
+
resolved[userScope.name] = {
|
|
16347
|
+
type: userScope.transport,
|
|
16348
|
+
url: userScope.url,
|
|
16349
|
+
headers: {
|
|
16350
|
+
...userScope.headers,
|
|
16351
|
+
Authorization: `Bearer ${token.value}`
|
|
16352
|
+
}
|
|
16353
|
+
};
|
|
16354
|
+
}
|
|
16095
16355
|
return resolved;
|
|
16096
16356
|
}).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
|
|
16097
16357
|
};
|
|
@@ -17813,7 +18073,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
17813
18073
|
const layer$54 = Layer.effect(AssetSync, make$59);
|
|
17814
18074
|
//#endregion
|
|
17815
18075
|
//#region src/cli/assets.ts
|
|
17816
|
-
const SyncServicesLive = layer$54.pipe(Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$
|
|
18076
|
+
const SyncServicesLive = layer$54.pipe(Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$60.pipe(Layer.provide(layer$67))), Layer.provideMerge(layer$67), Layer.provideMerge(FetchHttpClient.layer));
|
|
17817
18077
|
const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
17818
18078
|
const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
|
|
17819
18079
|
return yield* Effect.gen(function* () {
|
|
@@ -17821,7 +18081,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
|
17821
18081
|
sync: yield* AssetSync,
|
|
17822
18082
|
link: yield* HubLink
|
|
17823
18083
|
});
|
|
17824
|
-
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$
|
|
18084
|
+
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$70(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
|
|
17825
18085
|
});
|
|
17826
18086
|
const STATE_LABEL = {
|
|
17827
18087
|
synced: "synced",
|
|
@@ -28407,7 +28667,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
28407
28667
|
});
|
|
28408
28668
|
yield* Console.log(output);
|
|
28409
28669
|
}));
|
|
28410
|
-
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$
|
|
28670
|
+
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$70(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
|
|
28411
28671
|
return yield* Effect.gen(function* () {
|
|
28412
28672
|
const snapshot = yield* getOfflineSnapshot();
|
|
28413
28673
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
@@ -28418,7 +28678,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
28418
28678
|
});
|
|
28419
28679
|
yield* Console.log(output);
|
|
28420
28680
|
}).pipe(Effect.provide(offlineRuntimeLayer));
|
|
28421
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$43).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$
|
|
28681
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$43).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$70(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
28422
28682
|
});
|
|
28423
28683
|
const projectAddCommand = Command.make("add", {
|
|
28424
28684
|
...projectLocationFlags,
|
|
@@ -44046,6 +44306,22 @@ function toAuthAccessStreamEvent(change, revision, currentSessionId) {
|
|
|
44046
44306
|
};
|
|
44047
44307
|
}
|
|
44048
44308
|
}
|
|
44309
|
+
/**
|
|
44310
|
+
* Route one MCP write to the store its `source` names.
|
|
44311
|
+
*
|
|
44312
|
+
* `claude` and `project` write the CLI's own files; `registry` (or absent,
|
|
44313
|
+
* which every older client sends) writes p4code's store. A project write
|
|
44314
|
+
* without a directory is a caller bug worth a loud answer, not a fallback.
|
|
44315
|
+
*/
|
|
44316
|
+
const routeMcpWrite = (input, handlers) => {
|
|
44317
|
+
if (input.source === "claude") return handlers.claude();
|
|
44318
|
+
if (input.source === "project") {
|
|
44319
|
+
const dir = input.projectDir?.trim() ?? "";
|
|
44320
|
+
if (dir.length === 0) return Effect.fail(new McpRegistryError({ detail: "A project-scope write needs its project directory." }));
|
|
44321
|
+
return handlers.project(dir);
|
|
44322
|
+
}
|
|
44323
|
+
return handlers.registry();
|
|
44324
|
+
};
|
|
44049
44325
|
const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.toLayer(Effect.gen(function* () {
|
|
44050
44326
|
const currentSessionId = currentSession.sessionId;
|
|
44051
44327
|
const crypto = yield* Crypto.Crypto;
|
|
@@ -44074,7 +44350,26 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
44074
44350
|
const assetSync = yield* AssetSync;
|
|
44075
44351
|
const mcpRegistry = yield* McpRegistry;
|
|
44076
44352
|
const mcpOAuth = yield* McpOAuth;
|
|
44353
|
+
const claudeMcpFiles = yield* ClaudeMcpFiles;
|
|
44077
44354
|
const skillRegistry = yield* SkillRegistry;
|
|
44355
|
+
const listMcpServersEverywhere = Effect.gen(function* () {
|
|
44356
|
+
const servers = [...yield* mcpRegistry.list];
|
|
44357
|
+
const projectRows = yield* projectionProjects.listAll().pipe(Effect.map((rows) => rows.filter((row) => row.deletedAt === null)), Effect.orElseSucceed(() => []));
|
|
44358
|
+
for (const project of projectRows) for (const registration of yield* claudeMcpFiles.readProject(project.workspaceRoot)) servers.push({
|
|
44359
|
+
registration,
|
|
44360
|
+
missingSecrets: [],
|
|
44361
|
+
ready: true,
|
|
44362
|
+
source: "project",
|
|
44363
|
+
projectDir: project.workspaceRoot
|
|
44364
|
+
});
|
|
44365
|
+
return {
|
|
44366
|
+
servers,
|
|
44367
|
+
projects: projectRows.map((project) => ({
|
|
44368
|
+
dir: project.workspaceRoot,
|
|
44369
|
+
title: project.title
|
|
44370
|
+
}))
|
|
44371
|
+
};
|
|
44372
|
+
});
|
|
44078
44373
|
const startup = yield* ServerRuntimeStartup;
|
|
44079
44374
|
const workspaceEntries = yield* WorkspaceEntries;
|
|
44080
44375
|
const workspaceFileSystem = yield* WorkspaceFileSystem;
|
|
@@ -44667,21 +44962,35 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
44667
44962
|
}), { "rpc.aggregate": "skills" }),
|
|
44668
44963
|
[WS_METHODS.skillRegistrySearch]: ({ query }) => observeRpcEffect$1(WS_METHODS.skillRegistrySearch, skillRegistry.search(query), { "rpc.aggregate": "skills" }),
|
|
44669
44964
|
[WS_METHODS.skillRegistryFetch]: ({ id }) => observeRpcEffect$1(WS_METHODS.skillRegistryFetch, skillRegistry.fetch(id), { "rpc.aggregate": "skills" }),
|
|
44670
|
-
[WS_METHODS.mcpList]: (_input) => observeRpcEffect$1(WS_METHODS.mcpList,
|
|
44671
|
-
[WS_METHODS.mcpSave]: ({ registration }) => observeRpcEffect$1(WS_METHODS.mcpSave,
|
|
44672
|
-
|
|
44965
|
+
[WS_METHODS.mcpList]: (_input) => observeRpcEffect$1(WS_METHODS.mcpList, listMcpServersEverywhere, { "rpc.aggregate": "mcp" }),
|
|
44966
|
+
[WS_METHODS.mcpSave]: ({ registration, source, projectDir }) => observeRpcEffect$1(WS_METHODS.mcpSave, routeMcpWrite({
|
|
44967
|
+
source,
|
|
44968
|
+
projectDir
|
|
44969
|
+
}, {
|
|
44970
|
+
claude: () => claudeMcpFiles.upsertUser(registration),
|
|
44971
|
+
project: (dir) => claudeMcpFiles.upsertProject(dir, registration),
|
|
44972
|
+
registry: () => mcpRegistry.save(registration)
|
|
44973
|
+
}).pipe(Effect.andThen(listMcpServersEverywhere)), { "rpc.aggregate": "mcp" }),
|
|
44974
|
+
[WS_METHODS.mcpRemove]: ({ name, source, projectDir }) => observeRpcEffect$1(WS_METHODS.mcpRemove, routeMcpWrite({
|
|
44975
|
+
source,
|
|
44976
|
+
projectDir
|
|
44977
|
+
}, {
|
|
44978
|
+
claude: () => claudeMcpFiles.removeUser(name),
|
|
44979
|
+
project: (dir) => claudeMcpFiles.removeProject(dir, name),
|
|
44980
|
+
registry: () => mcpRegistry.remove(name)
|
|
44981
|
+
}).pipe(Effect.andThen(listMcpServersEverywhere)), { "rpc.aggregate": "mcp" }),
|
|
44673
44982
|
[WS_METHODS.mcpSetSecret]: ({ name, slot, value }) => observeRpcEffect$1(WS_METHODS.mcpSetSecret, mcpRegistry.setSecret({
|
|
44674
44983
|
name,
|
|
44675
44984
|
slot,
|
|
44676
44985
|
value
|
|
44677
|
-
}).pipe(Effect.andThen(
|
|
44986
|
+
}).pipe(Effect.andThen(listMcpServersEverywhere)), { "rpc.aggregate": "mcp" }),
|
|
44678
44987
|
[WS_METHODS.mcpOAuthBegin]: ({ name }) => observeRpcEffect$1(WS_METHODS.mcpOAuthBegin, Effect.gen(function* () {
|
|
44679
44988
|
const found = (yield* mcpRegistry.list).find((status) => status.registration.name === name);
|
|
44680
44989
|
if (found === void 0) return yield* new McpRegistryError({ detail: `No server is named ${name}.` });
|
|
44681
44990
|
if (found.registration.transport === "stdio") return yield* new McpRegistryError({ detail: "A stdio server is launched locally and has no sign-in." });
|
|
44682
44991
|
return yield* mcpOAuth.begin(found.registration);
|
|
44683
44992
|
}), { "rpc.aggregate": "mcp" }),
|
|
44684
|
-
[WS_METHODS.mcpOAuthDisconnect]: ({ name }) => observeRpcEffect$1(WS_METHODS.mcpOAuthDisconnect, mcpOAuth.disconnect(name).pipe(Effect.andThen(
|
|
44993
|
+
[WS_METHODS.mcpOAuthDisconnect]: ({ name }) => observeRpcEffect$1(WS_METHODS.mcpOAuthDisconnect, mcpOAuth.disconnect(name).pipe(Effect.andThen(listMcpServersEverywhere)), { "rpc.aggregate": "mcp" }),
|
|
44685
44994
|
[WS_METHODS.serverGetSettings]: (_input) => observeRpcEffect$1(WS_METHODS.serverGetSettings, serverSettings.getSettings.pipe(Effect.map(redactServerSettingsForClient)), { "rpc.aggregate": "server" }),
|
|
44686
44995
|
[WS_METHODS.serverUpdateSettings]: ({ patch }) => observeRpcEffect$1(WS_METHODS.serverUpdateSettings, serverSettings.updateSettings(patch).pipe(Effect.map(redactServerSettingsForClient)), { "rpc.aggregate": "server" }),
|
|
44687
44996
|
[WS_METHODS.serverDiscoverSourceControl]: (_input) => observeRpcEffect$1(WS_METHODS.serverDiscoverSourceControl, sourceControlDiscovery.discover, { "rpc.aggregate": "server" }),
|
|
@@ -47179,7 +47488,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
|
|
|
47179
47488
|
};
|
|
47180
47489
|
});
|
|
47181
47490
|
var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
|
|
47182
|
-
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$
|
|
47491
|
+
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$71));
|
|
47183
47492
|
//#endregion
|
|
47184
47493
|
//#region src/textGeneration/TextGenerationUtils.ts
|
|
47185
47494
|
const isTextGenerationError$2 = Schema$1.is(TextGenerationError);
|
|
@@ -86464,9 +86773,9 @@ const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$43));
|
|
|
86464
86773
|
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$43), Layer.provide(WorkspaceEntriesLayerLive));
|
|
86465
86774
|
const WorkspaceLayerLive = Layer.mergeAll(layer$43, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
|
|
86466
86775
|
const ProjectFaviconResolverLayerLive = layer$41.pipe(Layer.provide(layer$43), Layer.provide(layer$42));
|
|
86467
|
-
const AuthLayerLive = layer$
|
|
86776
|
+
const AuthLayerLive = layer$63.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$67));
|
|
86468
86777
|
const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
|
|
86469
|
-
const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), Layer.provideMerge(layer$51), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$
|
|
86778
|
+
const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), Layer.provideMerge(layer$51), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$60.pipe(Layer.provide(layer$67))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$52), Layer.provideMerge(layer$45), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(Layer.mergeAll(layer$57, layer$31).pipe(Layer.provideMerge(layer$58), Layer.provideMerge(layer$59))), Layer.provideMerge(layer$67)).pipe(Layer.provideMerge(layer$8), Layer.provideMerge(layer$7), Layer.provideMerge(layer$6), Layer.provideMerge(layer$48), Layer.provideMerge(layer$50), Layer.provideMerge(layer$49), Layer.provide(layer$71));
|
|
86470
86779
|
/**
|
|
86471
86780
|
* Hub asset sync.
|
|
86472
86781
|
*
|
|
@@ -86886,7 +87195,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
|
|
|
86886
87195
|
]));
|
|
86887
87196
|
//#endregion
|
|
86888
87197
|
//#region src/bin.ts
|
|
86889
|
-
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$
|
|
87198
|
+
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$71, FetchHttpClient.layer);
|
|
86890
87199
|
/**
|
|
86891
87200
|
* Prints an update reminder before dispatching, at most once a day.
|
|
86892
87201
|
*
|