@p4code/cli 0.1.3 → 0.1.5
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 +1022 -147
- package/dist/client/assets/{DiffPanel-DyAcFDt3.js → DiffPanel-ML_kqHo4.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-BYBlt2Jx.js → FilePreviewPanel-DqEQ4wir.js} +2 -2
- package/dist/client/assets/{PreviewPanel-2wO230Hl.js → PreviewPanel-BwHQqsFC.js} +2 -2
- package/dist/client/assets/{angular-html-C9jMC3ZQ.js → angular-html-B70hXg9o.js} +2 -2
- package/dist/client/assets/{angular-ts-CYoSZaKw.js → angular-ts-B2MRnnc1.js} +2 -2
- package/dist/client/assets/{apl-CgWZs6Gn.js → apl-DY9W2lgD.js} +2 -2
- package/dist/client/assets/arrow-right-Bdq-W9Bm.js +2 -0
- package/dist/client/assets/{astro-CUIqu6Jz.js → astro-CKmYmuzu.js} +2 -2
- package/dist/client/assets/{blade-iplcV4Ix.js → blade-mlm-ZlOd.js} +2 -2
- package/dist/client/assets/{c-Dd6jN1w_.js → c-9y7zDOj9.js} +2 -2
- package/dist/client/assets/{cobol-0ScsIx-z.js → cobol-CD87wiGp.js} +2 -2
- package/dist/client/assets/{coffee-KS_79spe.js → coffee-kgGv4P2i.js} +2 -2
- package/dist/client/assets/{cpp-BllSLkvw.js → cpp-DpZlUxYu.js} +2 -2
- package/dist/client/assets/{crystal-DF2_oukQ.js → crystal-B0OLLlY8.js} +2 -2
- package/dist/client/assets/{css-DBr167Oo.js → css--MUQJ4o7.js} +2 -2
- package/dist/client/assets/{edge-CRJ0aLAq.js → edge-B9eY7KZn.js} +2 -2
- package/dist/client/assets/{elixir-DXl1oanW.js → elixir-BZ2mTmkv.js} +2 -2
- package/dist/client/assets/{elm-CqKx609q.js → elm-Bu95APK0.js} +2 -2
- package/dist/client/assets/{erb-MLJdAbE4.js → erb-CpKKo-fS.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-BaJ5XhsU.js → fileCommentAnnotations-DeY-XSzV.js} +2 -2
- package/dist/client/assets/{git-rebase-M0aVykt3.js → git-rebase-BN70gFDl.js} +2 -2
- package/dist/client/assets/{glimmer-js-CXPK1DP8.js → glimmer-js-DM-4mIJW.js} +2 -2
- package/dist/client/assets/{glimmer-ts-wptUL2fp.js → glimmer-ts-DFHG1P9q.js} +2 -2
- package/dist/client/assets/{glsl-BRKhgqUF.js → glsl-B4TfqZ4_.js} +2 -2
- package/dist/client/assets/{graphql-1BUUHzT4.js → graphql-DLTs8DHV.js} +2 -2
- package/dist/client/assets/{hack-BR9NLXvX.js → hack-DRRemOcq.js} +2 -2
- package/dist/client/assets/{haml-BgBKuGz0.js → haml-4MHJURGQ.js} +2 -2
- package/dist/client/assets/{handlebars-BUs0Hgpn.js → handlebars-D7k0HQlo.js} +2 -2
- package/dist/client/assets/{html-BWwNwdti.js → html-DovLLqdO.js} +2 -2
- package/dist/client/assets/{html-derivative-B2dGSGlK.js → html-derivative-Dz9-s5om.js} +2 -2
- package/dist/client/assets/{http-NIyxdCuV.js → http-cxnvN4kV.js} +2 -2
- package/dist/client/assets/{hurl-CH8mm6dw.js → hurl-CSBBQOts.js} +2 -2
- package/dist/client/assets/{index-HEbzvM18.js → index-BXFHdiV7.js} +202 -202
- package/dist/client/assets/index-oFUAtVw2.css +1 -0
- package/dist/client/assets/{java-CQPmtuJ5.js → java-DIz7GrNg.js} +2 -2
- package/dist/client/assets/{javascript-DzjJJM-s.js → javascript-MSaRoKWU.js} +2 -2
- package/dist/client/assets/{jinja-4Qs6tVyC.js → jinja-DI8yd0V9.js} +2 -2
- package/dist/client/assets/{jison-CPG2kEI3.js → jison-sGqXSFug.js} +2 -2
- package/dist/client/assets/{json-DlY_RU7e.js → json-C_w_LNS4.js} +2 -2
- package/dist/client/assets/{jsx-Cd_ApdjY.js → jsx-V5NNKrjP.js} +2 -2
- package/dist/client/assets/{julia-SX8cqtZg.js → julia-BGVYDOsa.js} +2 -2
- package/dist/client/assets/{just-Ao5BO2B0.js → just-D-04ksOT.js} +2 -2
- package/dist/client/assets/{latex-C46nB2Dk.js → latex-BEsliWgq.js} +2 -2
- package/dist/client/assets/{liquid-BMcKK3Z1.js → liquid-DNUeMt2o.js} +2 -2
- package/dist/client/assets/{lua-DjG6qAWa.js → lua--TgilFGl.js} +2 -2
- package/dist/client/assets/{marko-3JoFYw3q.js → marko-DxDDGF4_.js} +2 -2
- package/dist/client/assets/{mdc-BpGP1uha.js → mdc-DzjvIH05.js} +2 -2
- package/dist/client/assets/{nginx-HOkzmdTd.js → nginx-BqVTMZgm.js} +2 -2
- package/dist/client/assets/{nim-CeKNmMcr.js → nim-Co2BGNef.js} +2 -2
- package/dist/client/assets/{perl-BWQkxnsH.js → perl-Ba8Q7XkF.js} +2 -2
- package/dist/client/assets/{php-Df4cK7Vr.js → php-Bfbmd1-m.js} +2 -2
- package/dist/client/assets/{pug-CoCjyAiE.js → pug-be-1Xvfl.js} +2 -2
- package/dist/client/assets/{qml-DYi25PQ3.js → qml-D7icULiU.js} +2 -2
- package/dist/client/assets/{r-BzJkuBsW.js → r-Cph7TJQ-.js} +2 -2
- package/dist/client/assets/{razor-BhG_PBuW.js → razor-CjLyUAnD.js} +2 -2
- package/dist/client/assets/{regexp-BAM54YZk.js → regexp-BdlWyepz.js} +2 -2
- package/dist/client/assets/{rst-DHl4hyZ2.js → rst-DEpJb2t7.js} +2 -2
- package/dist/client/assets/{ruby-gNx0WumM.js → ruby-C_x4mzoE.js} +2 -2
- package/dist/client/assets/{sas-CW83v0Dn.js → sas-Bz4iLdau.js} +2 -2
- package/dist/client/assets/{scss-WgrcQHVQ.js → scss-CwgGUhGr.js} +2 -2
- package/dist/client/assets/{shellscript-CKEnN-lX.js → shellscript-CHr9xiaE.js} +2 -2
- package/dist/client/assets/{shellsession-BbcmvnCz.js → shellsession-11TeKCPG.js} +2 -2
- package/dist/client/assets/{soy-D1MIxKdU.js → soy-BLILGuwU.js} +2 -2
- package/dist/client/assets/{sql-Bhxl_Mi7.js → sql-KbVEV8JC.js} +2 -2
- package/dist/client/assets/{stata-C-LT_UBU.js → stata-XDGn9IyV.js} +2 -2
- package/dist/client/assets/{surrealql-Ch_ceRvJ.js → surrealql-BkijSB1h.js} +2 -2
- package/dist/client/assets/{svelte-DlhsOd0r.js → svelte-S0qXpcmK.js} +2 -2
- package/dist/client/assets/{templ-CIHR3tEf.js → templ-Bpai32u4.js} +2 -2
- package/dist/client/assets/{tex-DRWioNbs.js → tex-BqM5PBWs.js} +2 -2
- package/dist/client/assets/textarea-CUI7U2B2.js +46 -0
- package/dist/client/assets/{ts-tags-BvRYwyAy.js → ts-tags-ChsaUtvn.js} +2 -2
- package/dist/client/assets/{tsx-BRkrE5rM.js → tsx-Bw54IsTH.js} +2 -2
- package/dist/client/assets/{twig-BlZvFnQN.js → twig-BOAKWhe6.js} +2 -2
- package/dist/client/assets/{typescript-Djd2wnjW.js → typescript-vJRDqHfC.js} +2 -2
- package/dist/client/assets/{vue-DActsgCM.js → vue-CtHSR0DM.js} +2 -2
- package/dist/client/assets/{vue-html-Cqt121Xa.js → vue-html-KPDmQoqc.js} +2 -2
- package/dist/client/assets/{vue-vine-CzSkk7Q4.js → vue-vine-BSN6OPd2.js} +2 -2
- package/dist/client/assets/{xml-DPi6y6-m.js → xml-8bohM9Or.js} +2 -2
- package/dist/client/assets/{xsl-BAvs_EI4.js → xsl-D-jqs0Dv.js} +2 -2
- package/dist/client/assets/{yaml-DFFGim1C.js → yaml-CzI494Jo.js} +2 -2
- package/dist/client/index.html +3 -3
- package/package.json +1 -1
- package/dist/client/assets/arrow-right-BpqEKABW.js +0 -2
- package/dist/client/assets/index-C7UXI10J.css +0 -1
- package/dist/client/assets/textarea-CHMvJ0-S.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$73 = () => {
|
|
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$72 = () => {
|
|
|
230
230
|
})
|
|
231
231
|
};
|
|
232
232
|
};
|
|
233
|
-
const layer$
|
|
233
|
+
const layer$69 = Layer.sync(NetService, make$73);
|
|
234
234
|
//#endregion
|
|
235
235
|
//#region package.json
|
|
236
|
-
var version = "0.1.
|
|
236
|
+
var version = "0.1.5";
|
|
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$72 = (config) => ServerConfig$1.of(config);
|
|
258
|
+
const layer$68 = (config) => Layer.succeed(ServerConfig$1, make$72(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");
|
|
@@ -5720,6 +5720,7 @@ const SourceControlWritingStyleSettings = Schema$1.Struct({
|
|
|
5720
5720
|
followChangeRequestTemplates: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true)))
|
|
5721
5721
|
});
|
|
5722
5722
|
const DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL = Duration.seconds(30);
|
|
5723
|
+
const TaskBoardSource = Schema$1.Literals(["local", "hub"]);
|
|
5723
5724
|
const ServerSettings = Schema$1.Struct({
|
|
5724
5725
|
enableAssistantStreaming: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
|
|
5725
5726
|
enableProviderUpdateChecks: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
@@ -5733,6 +5734,42 @@ const ServerSettings = Schema$1.Struct({
|
|
|
5733
5734
|
}))),
|
|
5734
5735
|
sourceControlWritingStyle: SourceControlWritingStyleSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
5735
5736
|
sourceControlWriterModelSelection: Schema$1.NullOr(ModelSelection).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
5737
|
+
/**
|
|
5738
|
+
* Where this server's task board lives.
|
|
5739
|
+
*
|
|
5740
|
+
* `local` is this machine's own SQLite database, which is where every board
|
|
5741
|
+
* has been until now. `hub` puts the board on the linked hub, so two servers
|
|
5742
|
+
* read and write one board instead of two that silently diverge.
|
|
5743
|
+
*
|
|
5744
|
+
* A setting rather than "hub if one is linked", because a hub can be linked
|
|
5745
|
+
* for skills alone, and flipping a board's home is not something to have
|
|
5746
|
+
* happen as a side effect of connecting. It is also the way back: the local
|
|
5747
|
+
* rows are still there, untouched, when it is set to `local` again.
|
|
5748
|
+
*
|
|
5749
|
+
* **On `hub`, an unreachable hub means no board.** There is no local
|
|
5750
|
+
* fallback by decision: answering from a stale local copy would recreate the
|
|
5751
|
+
* per-machine divergence the hub exists to remove, and it would do it
|
|
5752
|
+
* invisibly.
|
|
5753
|
+
*/
|
|
5754
|
+
taskBoardSource: TaskBoardSource.pipe(Schema$1.withDecodingDefault(Effect.succeed("local"))),
|
|
5755
|
+
/**
|
|
5756
|
+
* Skills the agents on this server must not see, by name.
|
|
5757
|
+
*
|
|
5758
|
+
* Server-scoped rather than per provider instance, because a skill is a
|
|
5759
|
+
* property of the machine's filesystem and every instance on it reads the
|
|
5760
|
+
* same directories.
|
|
5761
|
+
*
|
|
5762
|
+
* Deliberately **not** synced through the hub. A shared skill that is muted
|
|
5763
|
+
* on one machine is the useful combination — the laptop does not want the
|
|
5764
|
+
* skill that shells out to the Studio's build tooling — and syncing the mute
|
|
5765
|
+
* would make that inexpressible.
|
|
5766
|
+
*
|
|
5767
|
+
* What "disabled" means is bounded by what the provider can enforce: the
|
|
5768
|
+
* skill is hidden from the model's listing and from `/name`, and its files
|
|
5769
|
+
* stay on disk and remain readable by Read and Bash. It is a context filter,
|
|
5770
|
+
* not a sandbox, and nothing here should be described to a user as one.
|
|
5771
|
+
*/
|
|
5772
|
+
disabledSkills: Schema$1.Array(TrimmedNonEmptyString).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
|
|
5736
5773
|
providers: Schema$1.Struct({
|
|
5737
5774
|
codex: CodexSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
5738
5775
|
claudeAgent: ClaudeSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
@@ -5824,6 +5861,8 @@ const ServerSettingsPatch = Schema$1.Struct({
|
|
|
5824
5861
|
followChangeRequestTemplates: Schema$1.optionalKey(Schema$1.Boolean)
|
|
5825
5862
|
})),
|
|
5826
5863
|
sourceControlWriterModelSelection: Schema$1.optionalKey(Schema$1.NullOr(ModelSelection)),
|
|
5864
|
+
disabledSkills: Schema$1.optionalKey(Schema$1.Array(TrimmedNonEmptyString)),
|
|
5865
|
+
taskBoardSource: Schema$1.optionalKey(TaskBoardSource),
|
|
5827
5866
|
observability: Schema$1.optionalKey(Schema$1.Struct({
|
|
5828
5867
|
otlpTracesUrl: Schema$1.optionalKey(TrimmedString),
|
|
5829
5868
|
otlpMetricsUrl: Schema$1.optionalKey(TrimmedString)
|
|
@@ -7317,6 +7356,22 @@ const TaskStreamEvent = Schema$1.Union([
|
|
|
7317
7356
|
taskId: TaskId
|
|
7318
7357
|
})
|
|
7319
7358
|
]);
|
|
7359
|
+
Schema$1.Struct({
|
|
7360
|
+
patch: TaskUpdateInput,
|
|
7361
|
+
/** The status the caller believes the task is in. */
|
|
7362
|
+
expectedStatus: TaskStatus
|
|
7363
|
+
});
|
|
7364
|
+
Schema$1.Union([
|
|
7365
|
+
Schema$1.Struct({
|
|
7366
|
+
outcome: Schema$1.Literal("updated"),
|
|
7367
|
+
task: Task
|
|
7368
|
+
}),
|
|
7369
|
+
Schema$1.Struct({ outcome: Schema$1.Literal("missing") }),
|
|
7370
|
+
Schema$1.Struct({
|
|
7371
|
+
outcome: Schema$1.Literal("conflict"),
|
|
7372
|
+
current: Task
|
|
7373
|
+
})
|
|
7374
|
+
]);
|
|
7320
7375
|
/**
|
|
7321
7376
|
* Start an agent on a task.
|
|
7322
7377
|
*
|
|
@@ -7935,6 +7990,81 @@ var McpRegistryError = class extends Schema$1.TaggedErrorClass()("McpRegistryErr
|
|
|
7935
7990
|
}
|
|
7936
7991
|
};
|
|
7937
7992
|
//#endregion
|
|
7993
|
+
//#region ../../packages/contracts/src/skillRegistry.ts
|
|
7994
|
+
/**
|
|
7995
|
+
* Finding skills that are not on this machine yet.
|
|
7996
|
+
*
|
|
7997
|
+
* Managing the skills you already have is CRUD, and that is `agentAsset.ts`.
|
|
7998
|
+
* This is the other half: a catalogue to search and a repository to read a
|
|
7999
|
+
* skill out of, with the install itself going through the ordinary local-create
|
|
8000
|
+
* path so there is exactly one way a skill lands on disk.
|
|
8001
|
+
*
|
|
8002
|
+
* **Nothing here installs anything.** Search returns names; fetch returns the
|
|
8003
|
+
* files it *would* write, with the source they came from. The confirmation step
|
|
8004
|
+
* is a person looking at that list, which is the only reason it is two calls
|
|
8005
|
+
* rather than one — a `SKILL.md` is instructions handed to an agent that
|
|
8006
|
+
* already has a shell, so what it contains is worth seeing before it arrives.
|
|
8007
|
+
*
|
|
8008
|
+
* @module skillRegistry
|
|
8009
|
+
*/
|
|
8010
|
+
/**
|
|
8011
|
+
* One catalogue hit.
|
|
8012
|
+
*
|
|
8013
|
+
* `source` is the repository, and it is not decoration: it is what a person
|
|
8014
|
+
* judges the install on, so it travels with every result rather than being
|
|
8015
|
+
* fetched later.
|
|
8016
|
+
*/
|
|
8017
|
+
const RegistrySkill = Schema$1.Struct({
|
|
8018
|
+
/** `owner/repo/skill-name`, the catalogue's own identifier. */
|
|
8019
|
+
id: TrimmedNonEmptyString,
|
|
8020
|
+
name: TrimmedNonEmptyString,
|
|
8021
|
+
/** `owner/repo`. */
|
|
8022
|
+
source: TrimmedNonEmptyString,
|
|
8023
|
+
/** How many installs the catalogue has counted. Popularity, not endorsement. */
|
|
8024
|
+
installs: Schema$1.Int
|
|
8025
|
+
});
|
|
8026
|
+
const RegistrySkillSearchInput = Schema$1.Struct({ query: TrimmedNonEmptyString });
|
|
8027
|
+
/**
|
|
8028
|
+
* `unavailable` rather than a failure, matching the hub calls: a catalogue on
|
|
8029
|
+
* someone else's infrastructure being down is an ordinary condition, and a
|
|
8030
|
+
* panel has to say which of "nothing matched" and "could not ask" happened.
|
|
8031
|
+
*/
|
|
8032
|
+
const RegistrySkillSearchResult = Schema$1.Struct({
|
|
8033
|
+
results: Schema$1.Array(RegistrySkill),
|
|
8034
|
+
unavailable: Schema$1.NullOr(Schema$1.String)
|
|
8035
|
+
});
|
|
8036
|
+
const RegistrySkillFetchInput = Schema$1.Struct({
|
|
8037
|
+
/** `owner/repo/skill-name`, from a search result or typed by hand. */
|
|
8038
|
+
id: TrimmedNonEmptyString });
|
|
8039
|
+
/** Why a file in the skill's directory is not in the fetched set. */
|
|
8040
|
+
const RegistrySkillSkippedFile = Schema$1.Struct({
|
|
8041
|
+
path: Schema$1.String,
|
|
8042
|
+
reason: Schema$1.Literals([
|
|
8043
|
+
"too-large",
|
|
8044
|
+
"too-many-files",
|
|
8045
|
+
"over-total-size"
|
|
8046
|
+
])
|
|
8047
|
+
});
|
|
8048
|
+
/**
|
|
8049
|
+
* What installing this skill would write, and where it came from.
|
|
8050
|
+
*
|
|
8051
|
+
* `skipped` is part of the answer rather than a log line. A bound that silently
|
|
8052
|
+
* drops a script leaves a skill that is present, looks installed, and fails at
|
|
8053
|
+
* the moment it is used.
|
|
8054
|
+
*/
|
|
8055
|
+
const RegistrySkillFetchResult = Schema$1.Struct({
|
|
8056
|
+
found: Schema$1.Boolean,
|
|
8057
|
+
id: TrimmedNonEmptyString,
|
|
8058
|
+
/** The directory name the skill would take on disk. */
|
|
8059
|
+
name: Schema$1.String,
|
|
8060
|
+
source: Schema$1.String,
|
|
8061
|
+
/** Where these files can be read in full, before trusting them. */
|
|
8062
|
+
sourceUrl: Schema$1.String,
|
|
8063
|
+
files: Schema$1.Array(AgentAssetFile),
|
|
8064
|
+
skipped: Schema$1.Array(RegistrySkillSkippedFile),
|
|
8065
|
+
unavailable: Schema$1.NullOr(Schema$1.String)
|
|
8066
|
+
});
|
|
8067
|
+
//#endregion
|
|
7938
8068
|
//#region ../../packages/contracts/src/filesystem.ts
|
|
7939
8069
|
const FILESYSTEM_PATH_MAX_LENGTH = 512;
|
|
7940
8070
|
const FilesystemBrowseInput = Schema$1.Struct({
|
|
@@ -8197,6 +8327,8 @@ const WS_METHODS = {
|
|
|
8197
8327
|
assetsDelete: "assets.delete",
|
|
8198
8328
|
assetsCreateLocal: "assets.createLocal",
|
|
8199
8329
|
assetsRemoveLocal: "assets.removeLocal",
|
|
8330
|
+
skillRegistrySearch: "skillRegistry.search",
|
|
8331
|
+
skillRegistryFetch: "skillRegistry.fetch",
|
|
8200
8332
|
mcpList: "mcp.list",
|
|
8201
8333
|
mcpSave: "mcp.save",
|
|
8202
8334
|
mcpRemove: "mcp.remove",
|
|
@@ -8420,6 +8552,24 @@ const WsAssetsRemoveLocalRpc = Rpc.make(WS_METHODS.assetsRemoveLocal, {
|
|
|
8420
8552
|
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8421
8553
|
});
|
|
8422
8554
|
/**
|
|
8555
|
+
* Finding and reading skills that are not on this machine yet.
|
|
8556
|
+
*
|
|
8557
|
+
* Read-only, both of them. Installing is `assets.createLocal` with the files
|
|
8558
|
+
* `skillRegistry.fetch` returned, so a skill arriving from a catalogue goes
|
|
8559
|
+
* through exactly the same refusals as one typed into the New skill dialog, and
|
|
8560
|
+
* the step in between is a person looking at what would be written.
|
|
8561
|
+
*/
|
|
8562
|
+
const WsSkillRegistrySearchRpc = Rpc.make(WS_METHODS.skillRegistrySearch, {
|
|
8563
|
+
payload: RegistrySkillSearchInput,
|
|
8564
|
+
success: RegistrySkillSearchResult,
|
|
8565
|
+
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8566
|
+
});
|
|
8567
|
+
const WsSkillRegistryFetchRpc = Rpc.make(WS_METHODS.skillRegistryFetch, {
|
|
8568
|
+
payload: RegistrySkillFetchInput,
|
|
8569
|
+
success: RegistrySkillFetchResult,
|
|
8570
|
+
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8571
|
+
});
|
|
8572
|
+
/**
|
|
8423
8573
|
* Registering the user's own MCP servers.
|
|
8424
8574
|
*
|
|
8425
8575
|
* Every one of these answers with the whole list, for the same reason the sync
|
|
@@ -8829,7 +8979,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
|
|
|
8829
8979
|
error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
|
|
8830
8980
|
stream: true
|
|
8831
8981
|
});
|
|
8832
|
-
const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
8982
|
+
const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsSkillRegistrySearchRpc, WsSkillRegistryFetchRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
8833
8983
|
//#endregion
|
|
8834
8984
|
//#region ../../packages/shared/src/oauthScope.ts
|
|
8835
8985
|
const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
|
|
@@ -8975,7 +9125,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
8975
9125
|
//#endregion
|
|
8976
9126
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
8977
9127
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
8978
|
-
const make$
|
|
9128
|
+
const make$71 = Effect.gen(function* () {
|
|
8979
9129
|
const config = yield* ServerConfig$1;
|
|
8980
9130
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
8981
9131
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -8993,7 +9143,7 @@ const make$70 = Effect.gen(function* () {
|
|
|
8993
9143
|
};
|
|
8994
9144
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
8995
9145
|
});
|
|
8996
|
-
const layer$
|
|
9146
|
+
const layer$67 = Layer.effect(EnvironmentAuthPolicy, make$71);
|
|
8997
9147
|
//#endregion
|
|
8998
9148
|
//#region src/persistence/Errors.ts
|
|
8999
9149
|
function summarizeSchemaIssue(issue) {
|
|
@@ -9174,7 +9324,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
9174
9324
|
cause
|
|
9175
9325
|
});
|
|
9176
9326
|
}
|
|
9177
|
-
const make$
|
|
9327
|
+
const make$70 = Effect.gen(function* () {
|
|
9178
9328
|
const sql = yield* SqlClient.SqlClient;
|
|
9179
9329
|
const createSessionRow = SqlSchema.void({
|
|
9180
9330
|
Request: CreateAuthSessionInput,
|
|
@@ -9308,7 +9458,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
9308
9458
|
setLastConnectedAt
|
|
9309
9459
|
};
|
|
9310
9460
|
});
|
|
9311
|
-
const layer$
|
|
9461
|
+
const layer$66 = Layer.effect(AuthSessionRepository, make$70);
|
|
9312
9462
|
//#endregion
|
|
9313
9463
|
//#region src/auth/ServerSecretStore.ts
|
|
9314
9464
|
const secretStoreErrorContext = {
|
|
@@ -9375,7 +9525,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
|
|
|
9375
9525
|
const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
|
|
9376
9526
|
const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
|
|
9377
9527
|
var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
|
|
9378
|
-
const make$
|
|
9528
|
+
const make$69 = Effect.gen(function* () {
|
|
9379
9529
|
const crypto = yield* Crypto.Crypto;
|
|
9380
9530
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
9381
9531
|
const path = yield* Path.Path;
|
|
@@ -9445,7 +9595,7 @@ const make$68 = Effect.gen(function* () {
|
|
|
9445
9595
|
remove
|
|
9446
9596
|
});
|
|
9447
9597
|
});
|
|
9448
|
-
const layer$
|
|
9598
|
+
const layer$65 = Layer.effect(ServerSecretStore, make$69);
|
|
9449
9599
|
//#endregion
|
|
9450
9600
|
//#region src/auth/SessionStore.ts
|
|
9451
9601
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -9683,7 +9833,7 @@ function toAuthClientSession(input) {
|
|
|
9683
9833
|
current: false
|
|
9684
9834
|
};
|
|
9685
9835
|
}
|
|
9686
|
-
const make$
|
|
9836
|
+
const make$68 = Effect.gen(function* () {
|
|
9687
9837
|
const crypto = yield* Crypto.Crypto;
|
|
9688
9838
|
const serverConfig = yield* ServerConfig$1;
|
|
9689
9839
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -9997,7 +10147,7 @@ const make$67 = Effect.gen(function* () {
|
|
|
9997
10147
|
markDisconnected
|
|
9998
10148
|
});
|
|
9999
10149
|
});
|
|
10000
|
-
const layer$
|
|
10150
|
+
const layer$64 = Layer.effect(SessionStore, make$68).pipe(Layer.provideMerge(layer$66));
|
|
10001
10151
|
//#endregion
|
|
10002
10152
|
//#region src/persistence/AuthPairingLinks.ts
|
|
10003
10153
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -10058,7 +10208,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
10058
10208
|
cause
|
|
10059
10209
|
});
|
|
10060
10210
|
}
|
|
10061
|
-
const make$
|
|
10211
|
+
const make$67 = Effect.gen(function* () {
|
|
10062
10212
|
const sql = yield* SqlClient.SqlClient;
|
|
10063
10213
|
const createPairingLinkRow = SqlSchema.void({
|
|
10064
10214
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -10193,7 +10343,7 @@ const make$66 = Effect.gen(function* () {
|
|
|
10193
10343
|
getByCredential
|
|
10194
10344
|
};
|
|
10195
10345
|
});
|
|
10196
|
-
const layer$
|
|
10346
|
+
const layer$63 = Layer.effect(AuthPairingLinkRepository, make$67);
|
|
10197
10347
|
//#endregion
|
|
10198
10348
|
//#region src/auth/PairingGrantStore.ts
|
|
10199
10349
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -10288,7 +10438,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
10288
10438
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
10289
10439
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
10290
10440
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
10291
|
-
const make$
|
|
10441
|
+
const make$66 = Effect.gen(function* () {
|
|
10292
10442
|
const crypto = yield* Crypto.Crypto;
|
|
10293
10443
|
const config = yield* ServerConfig$1;
|
|
10294
10444
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -10486,7 +10636,7 @@ const make$65 = Effect.gen(function* () {
|
|
|
10486
10636
|
consume
|
|
10487
10637
|
});
|
|
10488
10638
|
});
|
|
10489
|
-
const layer$
|
|
10639
|
+
const layer$62 = Layer.effect(PairingGrantStore, make$66).pipe(Layer.provideMerge(layer$63));
|
|
10490
10640
|
//#endregion
|
|
10491
10641
|
//#region src/persistence/Migrations/001_OrchestrationEvents.ts
|
|
10492
10642
|
var _001_OrchestrationEvents_default = Effect.gen(function* () {
|
|
@@ -12259,7 +12409,7 @@ function parseBearerToken(request) {
|
|
|
12259
12409
|
const token = header.slice(7).trim();
|
|
12260
12410
|
return token.length > 0 ? token : null;
|
|
12261
12411
|
}
|
|
12262
|
-
const make$
|
|
12412
|
+
const make$65 = Effect.gen(function* () {
|
|
12263
12413
|
const policy = yield* EnvironmentAuthPolicy;
|
|
12264
12414
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
12265
12415
|
const sessions = yield* SessionStore;
|
|
@@ -12454,9 +12604,9 @@ const make$64 = Effect.gen(function* () {
|
|
|
12454
12604
|
issueStartupPairingUrl
|
|
12455
12605
|
});
|
|
12456
12606
|
});
|
|
12457
|
-
const layer$
|
|
12458
|
-
const storageLayer = Layer.mergeAll(layer$
|
|
12459
|
-
const runtimeLayer = layer$
|
|
12607
|
+
const layer$61 = Layer.effect(EnvironmentAuth, make$65).pipe(Layer.provideMerge(layer$62), Layer.provideMerge(layer$64), Layer.provideMerge(layer$67));
|
|
12608
|
+
const storageLayer = Layer.mergeAll(layer$65, layerConfig);
|
|
12609
|
+
const runtimeLayer = layer$61.pipe(Layer.provideMerge(storageLayer));
|
|
12460
12610
|
//#endregion
|
|
12461
12611
|
//#region src/cliAuthFormat.ts
|
|
12462
12612
|
const newline = "\n";
|
|
@@ -13211,7 +13361,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
|
|
|
13211
13361
|
}
|
|
13212
13362
|
return yield* Effect.gen(function* () {
|
|
13213
13363
|
return yield* run(yield* EnvironmentAuth);
|
|
13214
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$
|
|
13364
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
13215
13365
|
});
|
|
13216
13366
|
const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
|
|
13217
13367
|
const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
|
|
@@ -13351,7 +13501,7 @@ const DEFAULT_LIMITS = {
|
|
|
13351
13501
|
windowMillis: FAILURE_WINDOW_MS,
|
|
13352
13502
|
blockMillis: BLOCK_DURATION_MS
|
|
13353
13503
|
};
|
|
13354
|
-
const make$
|
|
13504
|
+
const make$64 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
13355
13505
|
const state = yield* Ref.make(initialThrottleState);
|
|
13356
13506
|
return HubAuthThrottle.of({
|
|
13357
13507
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -13365,7 +13515,7 @@ const make$63 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
|
|
|
13365
13515
|
})
|
|
13366
13516
|
});
|
|
13367
13517
|
});
|
|
13368
|
-
const layer$
|
|
13518
|
+
const layer$60 = Layer.effect(HubAuthThrottle, make$64());
|
|
13369
13519
|
//#endregion
|
|
13370
13520
|
//#region src/hub/HubAuth.ts
|
|
13371
13521
|
/**
|
|
@@ -13817,6 +13967,43 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
13817
13967
|
task
|
|
13818
13968
|
})
|
|
13819
13969
|
})));
|
|
13970
|
+
/**
|
|
13971
|
+
* The claim, and the reason it is a separate method rather than an option on
|
|
13972
|
+
* `patch`: only this one has an outcome a caller must branch on.
|
|
13973
|
+
*
|
|
13974
|
+
* The comparison happens *inside* the transaction alongside the write, which
|
|
13975
|
+
* is the only arrangement that makes it a compare-and-set. Reading first and
|
|
13976
|
+
* writing after would leave exactly the window it exists to close.
|
|
13977
|
+
*/
|
|
13978
|
+
const patchIfStatus = (input, updatedAt) => sql.withTransaction(Effect.gen(function* () {
|
|
13979
|
+
const existing = yield* getTaskRow({ taskId: input.patch.taskId });
|
|
13980
|
+
if (Option.isNone(existing)) return { outcome: "missing" };
|
|
13981
|
+
if (existing.value.status !== input.expectedStatus) return {
|
|
13982
|
+
outcome: "conflict",
|
|
13983
|
+
current: existing.value
|
|
13984
|
+
};
|
|
13985
|
+
const updated = {
|
|
13986
|
+
...existing.value,
|
|
13987
|
+
...input.patch.projectId !== void 0 ? { projectId: input.patch.projectId } : {},
|
|
13988
|
+
...input.patch.repositoryKey !== void 0 ? { repositoryKey: input.patch.repositoryKey } : {},
|
|
13989
|
+
...input.patch.threadId !== void 0 ? { threadId: input.patch.threadId } : {},
|
|
13990
|
+
...input.patch.title !== void 0 ? { title: input.patch.title } : {},
|
|
13991
|
+
...input.patch.body !== void 0 ? { body: input.patch.body } : {},
|
|
13992
|
+
...input.patch.status !== void 0 ? { status: input.patch.status } : {},
|
|
13993
|
+
...input.patch.priority !== void 0 ? { priority: input.patch.priority } : {},
|
|
13994
|
+
...input.patch.assignee !== void 0 ? { assignee: input.patch.assignee } : {},
|
|
13995
|
+
...input.patch.labels !== void 0 ? { labels: input.patch.labels } : {},
|
|
13996
|
+
updatedAt
|
|
13997
|
+
};
|
|
13998
|
+
yield* upsertTaskRow(updated);
|
|
13999
|
+
return {
|
|
14000
|
+
outcome: "updated",
|
|
14001
|
+
task: updated
|
|
14002
|
+
};
|
|
14003
|
+
})).pipe(Effect.mapError(toPersistenceSqlError("TaskRepository.patchIfStatus:query")), Effect.tap((result) => result.outcome === "updated" ? publish({
|
|
14004
|
+
type: "upserted",
|
|
14005
|
+
task: result.task
|
|
14006
|
+
}) : Effect.void));
|
|
13820
14007
|
const deleteById = (input) => deleteTaskRow(input).pipe(Effect.mapError(toPersistenceSqlError("TaskRepository.deleteById:query")), Effect.tap(() => publish({
|
|
13821
14008
|
type: "deleted",
|
|
13822
14009
|
taskId: input.taskId
|
|
@@ -13824,6 +14011,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
13824
14011
|
return {
|
|
13825
14012
|
upsert,
|
|
13826
14013
|
patch,
|
|
14014
|
+
patchIfStatus,
|
|
13827
14015
|
getById,
|
|
13828
14016
|
list,
|
|
13829
14017
|
deleteById,
|
|
@@ -13944,13 +14132,25 @@ const updateTaskRoute = HttpRouter.add("PATCH", "/tasks/:taskId", respondToHubFa
|
|
|
13944
14132
|
yield* authenticateHubRequest();
|
|
13945
14133
|
const params = yield* HttpRouter.params;
|
|
13946
14134
|
const taskId = TaskId.make(params.taskId ?? "");
|
|
13947
|
-
const
|
|
14135
|
+
const { expectedStatus, ...patchBody } = (yield* readJsonBody()) ?? {};
|
|
13948
14136
|
const input = yield* decodeOrInvalid(TaskUpdateInput, "Request body does not match TaskUpdateInput.")({
|
|
13949
|
-
...
|
|
14137
|
+
...patchBody,
|
|
13950
14138
|
taskId
|
|
13951
14139
|
});
|
|
13952
14140
|
const tasks = yield* TaskRepository;
|
|
13953
14141
|
const timestamp = DateTime.formatIso(yield* DateTime.now);
|
|
14142
|
+
if (expectedStatus !== void 0) {
|
|
14143
|
+
const condition = yield* decodeOrInvalid(TaskStatus, "expectedStatus is not a task status.")(expectedStatus);
|
|
14144
|
+
const result = yield* tasks.patchIfStatus({
|
|
14145
|
+
patch: input,
|
|
14146
|
+
expectedStatus: condition
|
|
14147
|
+
}, timestamp);
|
|
14148
|
+
if (result.outcome === "missing") return notFound(taskId);
|
|
14149
|
+
return result.outcome === "conflict" ? HttpServerResponse.jsonUnsafe({
|
|
14150
|
+
error: "conflict",
|
|
14151
|
+
current: result.current
|
|
14152
|
+
}, { status: 409 }) : HttpServerResponse.jsonUnsafe(result.task);
|
|
14153
|
+
}
|
|
13954
14154
|
const patched = yield* tasks.patch(input, timestamp);
|
|
13955
14155
|
return Option.isNone(patched) ? notFound(taskId) : HttpServerResponse.jsonUnsafe(patched.value);
|
|
13956
14156
|
})));
|
|
@@ -14056,7 +14256,7 @@ const deleteAssetRoute = HttpRouter.add("DELETE", "/assets/:kind/:name", respond
|
|
|
14056
14256
|
const outcome = yield* (yield* AgentAssetRepository).deleteByName(requested);
|
|
14057
14257
|
return outcome._tag === "conflict" ? assetConflict(Option.getOrNull(outcome.current)) : HttpServerResponse.empty({ status: 204 });
|
|
14058
14258
|
})));
|
|
14059
|
-
const layer$
|
|
14259
|
+
const layer$59 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute);
|
|
14060
14260
|
//#endregion
|
|
14061
14261
|
//#region src/hub/Migrations/001_Tasks.ts
|
|
14062
14262
|
/**
|
|
@@ -14271,7 +14471,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
|
|
|
14271
14471
|
});
|
|
14272
14472
|
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 });
|
|
14273
14473
|
}));
|
|
14274
|
-
const makeHubLayer = HttpRouter.serve(layer$
|
|
14474
|
+
const makeHubLayer = HttpRouter.serve(layer$59).pipe(Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$60), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
|
|
14275
14475
|
const runHub = Layer.launch(makeHubLayer);
|
|
14276
14476
|
//#endregion
|
|
14277
14477
|
//#region src/atomicWrite.ts
|
|
@@ -14395,7 +14595,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
14395
14595
|
}
|
|
14396
14596
|
return Object.is(current, defaults) ? void 0 : current;
|
|
14397
14597
|
}
|
|
14398
|
-
const make$
|
|
14598
|
+
const make$63 = Effect.gen(function* () {
|
|
14399
14599
|
const { settingsPath } = yield* ServerConfig$1;
|
|
14400
14600
|
const fs = yield* FileSystem.FileSystem;
|
|
14401
14601
|
const pathService = yield* Path.Path;
|
|
@@ -14616,7 +14816,7 @@ const make$62 = Effect.gen(function* () {
|
|
|
14616
14816
|
}
|
|
14617
14817
|
};
|
|
14618
14818
|
});
|
|
14619
|
-
const layer$
|
|
14819
|
+
const layer$58 = Layer.effect(ServerSettingsService, make$63);
|
|
14620
14820
|
//#endregion
|
|
14621
14821
|
//#region src/pathExpansion.ts
|
|
14622
14822
|
/**
|
|
@@ -14638,6 +14838,86 @@ function expandHomePath$3(value) {
|
|
|
14638
14838
|
return value;
|
|
14639
14839
|
}
|
|
14640
14840
|
//#endregion
|
|
14841
|
+
//#region src/provider/skillOverrides.ts
|
|
14842
|
+
/**
|
|
14843
|
+
* Turning "this skill is disabled" into something a provider enforces.
|
|
14844
|
+
*
|
|
14845
|
+
* **A skill has two names and either can reach it.** Discovery reports the
|
|
14846
|
+
* `SKILL.md` frontmatter `name` when there is one and the directory name
|
|
14847
|
+
* otherwise, while the sync panel lists directories — so the disabled set can
|
|
14848
|
+
* hold either form depending on which surface the toggle was pressed on, and
|
|
14849
|
+
* the CLI keys its own listing on the name it resolved. Matching on one form
|
|
14850
|
+
* only produces a toggle that works for most skills and silently does nothing
|
|
14851
|
+
* for the ones whose frontmatter disagrees with their directory, which is the
|
|
14852
|
+
* worst of the available failures: it looks like the feature works.
|
|
14853
|
+
*
|
|
14854
|
+
* So both forms are matched on the way in and both are emitted on the way out.
|
|
14855
|
+
*
|
|
14856
|
+
* **The lever is `Settings.skillOverrides`, not the SDK's `skills` option.**
|
|
14857
|
+
* `skills: string[]` is an allowlist: passing it enables *only* the listed
|
|
14858
|
+
* skills, so a single disabled skill would silently take every plugin-provided
|
|
14859
|
+
* skill with it, since those are not in our discovery at all. `skillOverrides`
|
|
14860
|
+
* is per skill and additive — an absent key means "on" — so nothing is affected
|
|
14861
|
+
* except what was named.
|
|
14862
|
+
*
|
|
14863
|
+
* @module provider/skillOverrides
|
|
14864
|
+
*/
|
|
14865
|
+
/**
|
|
14866
|
+
* Hidden from the model's listing *and* from `/name`.
|
|
14867
|
+
*
|
|
14868
|
+
* The other values the setting accepts are partial hides (`name-only`,
|
|
14869
|
+
* `user-invocable-only`); a p4code toggle labelled "disabled" has to be the
|
|
14870
|
+
* complete one, or the label is a lie.
|
|
14871
|
+
*/
|
|
14872
|
+
const SKILL_OVERRIDE_OFF = "off";
|
|
14873
|
+
/**
|
|
14874
|
+
* The directory a skill lives in, from its `SKILL.md` path.
|
|
14875
|
+
*
|
|
14876
|
+
* Path handling by hand rather than through `Path.Path`, because this stays a
|
|
14877
|
+
* pure function: it is called from discovery, from the adapter and from tests,
|
|
14878
|
+
* and the segment separator is the only platform fact it needs.
|
|
14879
|
+
*/
|
|
14880
|
+
function skillDirectoryName(skillPath) {
|
|
14881
|
+
const segments = skillPath.split(/[/\\]/).filter((segment) => segment.length > 0);
|
|
14882
|
+
return segments.length >= 2 ? segments[segments.length - 2] ?? "" : "";
|
|
14883
|
+
}
|
|
14884
|
+
/** Every name a skill answers to, ignoring empties. */
|
|
14885
|
+
function namesOf(skill) {
|
|
14886
|
+
const directoryName = skillDirectoryName(skill.path);
|
|
14887
|
+
return [skill.name, directoryName].filter((name) => name.length > 0);
|
|
14888
|
+
}
|
|
14889
|
+
/**
|
|
14890
|
+
* Whether a discovered skill is in the disabled set, under either of its names.
|
|
14891
|
+
*/
|
|
14892
|
+
function isSkillDisabled(skill, disabled) {
|
|
14893
|
+
const disabledSet = new Set(disabled);
|
|
14894
|
+
return namesOf(skill).some((name) => disabledSet.has(name));
|
|
14895
|
+
}
|
|
14896
|
+
/**
|
|
14897
|
+
* The `skillOverrides` map to hand a session, or `undefined` when nothing is
|
|
14898
|
+
* disabled.
|
|
14899
|
+
*
|
|
14900
|
+
* `undefined` rather than `{}` on purpose: an empty map is a setting the
|
|
14901
|
+
* session did not have before, and the point of this feature is that a server
|
|
14902
|
+
* with nothing disabled starts sessions byte-identical to the ones it started
|
|
14903
|
+
* yesterday.
|
|
14904
|
+
*
|
|
14905
|
+
* Names that match no discovered skill are still emitted. A skill can be
|
|
14906
|
+
* disabled and then removed from disk, or disabled in a project the current
|
|
14907
|
+
* session is not in, and dropping the entry would quietly re-enable it the
|
|
14908
|
+
* moment discovery misses it.
|
|
14909
|
+
*/
|
|
14910
|
+
function buildSkillOverrides(disabled, discovered) {
|
|
14911
|
+
if (disabled.length === 0) return;
|
|
14912
|
+
const overrides = {};
|
|
14913
|
+
for (const name of disabled) if (name.length > 0) overrides[name] = SKILL_OVERRIDE_OFF;
|
|
14914
|
+
for (const skill of discovered) {
|
|
14915
|
+
if (!isSkillDisabled(skill, disabled)) continue;
|
|
14916
|
+
for (const name of namesOf(skill)) overrides[name] = SKILL_OVERRIDE_OFF;
|
|
14917
|
+
}
|
|
14918
|
+
return Object.keys(overrides).length === 0 ? void 0 : overrides;
|
|
14919
|
+
}
|
|
14920
|
+
//#endregion
|
|
14641
14921
|
//#region src/provider/Drivers/ClaudeSkills.ts
|
|
14642
14922
|
/**
|
|
14643
14923
|
* ClaudeSkills — filesystem discovery of Claude Code skills for the `$` picker.
|
|
@@ -14709,7 +14989,7 @@ const resolveClaudeUserSkillsDir = Effect.fn("resolveClaudeUserSkillsDir")(funct
|
|
|
14709
14989
|
* collisions the project-scoped skill wins, matching Claude Code's
|
|
14710
14990
|
* most-specific-wins resolution.
|
|
14711
14991
|
*/
|
|
14712
|
-
const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config, cwd, environment) {
|
|
14992
|
+
const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config, cwd, environment, disabledSkills) {
|
|
14713
14993
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
14714
14994
|
const path = yield* Path.Path;
|
|
14715
14995
|
const configDirPath = yield* resolveClaudeConfigDirPath(config, environment ?? process.env, cwd);
|
|
@@ -14734,7 +15014,10 @@ const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config
|
|
|
14734
15014
|
skillsByName.set(name, {
|
|
14735
15015
|
name,
|
|
14736
15016
|
path: skillPath,
|
|
14737
|
-
enabled:
|
|
15017
|
+
enabled: !isSkillDisabled({
|
|
15018
|
+
name,
|
|
15019
|
+
path: skillPath
|
|
15020
|
+
}, disabledSkills ?? []),
|
|
14738
15021
|
scope: root.scope,
|
|
14739
15022
|
...frontmatter.kind === "parsed" && frontmatter.description ? { description: frontmatter.description } : {}
|
|
14740
15023
|
});
|
|
@@ -14749,7 +15032,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
|
|
|
14749
15032
|
const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
|
|
14750
15033
|
var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
|
|
14751
15034
|
const slotsOf = (registration) => registration.secrets ?? [];
|
|
14752
|
-
const make$
|
|
15035
|
+
const make$62 = Effect.gen(function* () {
|
|
14753
15036
|
const config = yield* ServerConfig$1;
|
|
14754
15037
|
const secrets = yield* ServerSecretStore;
|
|
14755
15038
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
@@ -14861,7 +15144,7 @@ const make$61 = Effect.gen(function* () {
|
|
|
14861
15144
|
}).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
|
|
14862
15145
|
};
|
|
14863
15146
|
});
|
|
14864
|
-
const layer$
|
|
15147
|
+
const layer$57 = Layer.effect(McpRegistry, make$62);
|
|
14865
15148
|
//#endregion
|
|
14866
15149
|
//#region src/sync/HubLink.ts
|
|
14867
15150
|
/**
|
|
@@ -14958,7 +15241,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
|
|
|
14958
15241
|
shareMode: input.shareMode
|
|
14959
15242
|
});
|
|
14960
15243
|
const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
|
|
14961
|
-
const make$
|
|
15244
|
+
const make$61 = Effect.fn("HubLink.make")(function* (environment) {
|
|
14962
15245
|
const secrets = yield* ServerSecretStore;
|
|
14963
15246
|
const env = environment ?? process.env;
|
|
14964
15247
|
const fromEnv = fromEnvironment(env);
|
|
@@ -15024,7 +15307,7 @@ const make$60 = Effect.fn("HubLink.make")(function* (environment) {
|
|
|
15024
15307
|
})
|
|
15025
15308
|
};
|
|
15026
15309
|
});
|
|
15027
|
-
const layer$
|
|
15310
|
+
const layer$56 = Layer.effect(HubLink, make$61());
|
|
15028
15311
|
//#endregion
|
|
15029
15312
|
//#region src/sync/HubAssetClient.ts
|
|
15030
15313
|
/**
|
|
@@ -15039,7 +15322,7 @@ const layer$55 = Layer.effect(HubLink, make$60());
|
|
|
15039
15322
|
*
|
|
15040
15323
|
* @module sync/HubAssetClient
|
|
15041
15324
|
*/
|
|
15042
|
-
const HUB_REQUEST_TIMEOUT_MS = 15e3;
|
|
15325
|
+
const HUB_REQUEST_TIMEOUT_MS$1 = 15e3;
|
|
15043
15326
|
/**
|
|
15044
15327
|
* The hub could not be reached, or answered something unusable.
|
|
15045
15328
|
*
|
|
@@ -15052,12 +15335,12 @@ var HubAssetConflict = class extends Data.TaggedError("HubAssetConflict") {};
|
|
|
15052
15335
|
/** No hub is configured on this server, so there is nothing to talk to. */
|
|
15053
15336
|
var HubNotConfigured = class extends Data.TaggedError("HubNotConfigured") {};
|
|
15054
15337
|
const AssetListPage = Schema$1.Struct({ assets: Schema$1.Array(AgentAsset) });
|
|
15055
|
-
const ConflictBody = Schema$1.Struct({ current: Schema$1.NullOr(AgentAsset) });
|
|
15338
|
+
const ConflictBody$1 = Schema$1.Struct({ current: Schema$1.NullOr(AgentAsset) });
|
|
15056
15339
|
const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
|
|
15057
|
-
const decodeConflictBody = Schema$1.decodeUnknownEffect(ConflictBody);
|
|
15340
|
+
const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
|
|
15058
15341
|
const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
|
|
15059
15342
|
var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
|
|
15060
|
-
const make$
|
|
15343
|
+
const make$60 = Effect.gen(function* () {
|
|
15061
15344
|
const http = yield* HttpClient.HttpClient;
|
|
15062
15345
|
const link = yield* HubLink;
|
|
15063
15346
|
const requireSettings = Effect.gen(function* () {
|
|
@@ -15066,7 +15349,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15066
15349
|
return state.settings.value;
|
|
15067
15350
|
});
|
|
15068
15351
|
const send = Effect.fn("HubAssetClient.send")(function* (operation, settings, request) {
|
|
15069
|
-
return yield* http.execute(request.pipe(HttpClientRequest.setHeader("authorization", `Bearer ${settings.token}`), HttpClientRequest.setHeader("accept", "application/json"))).pipe(Effect.timeout(HUB_REQUEST_TIMEOUT_MS), Effect.mapError((cause) => new HubUnavailable({
|
|
15352
|
+
return yield* http.execute(request.pipe(HttpClientRequest.setHeader("authorization", `Bearer ${settings.token}`), HttpClientRequest.setHeader("accept", "application/json"))).pipe(Effect.timeout(HUB_REQUEST_TIMEOUT_MS$1), Effect.mapError((cause) => new HubUnavailable({
|
|
15070
15353
|
operation,
|
|
15071
15354
|
detail: `${cause._tag ?? "error"}`
|
|
15072
15355
|
})));
|
|
@@ -15086,7 +15369,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15086
15369
|
* which is what lets a caller show both sides instead of only saying no.
|
|
15087
15370
|
*/
|
|
15088
15371
|
const conflictFrom = Effect.fn("HubAssetClient.conflictFrom")(function* (name, response) {
|
|
15089
|
-
const body = yield* decodeBody("conflict", decodeConflictBody, response).pipe(Effect.orElseSucceed(() => ({ current: null })));
|
|
15372
|
+
const body = yield* decodeBody("conflict", decodeConflictBody$1, response).pipe(Effect.orElseSucceed(() => ({ current: null })));
|
|
15090
15373
|
return new HubAssetConflict({
|
|
15091
15374
|
name,
|
|
15092
15375
|
current: body.current === null ? Option.none() : Option.some(body.current)
|
|
@@ -15139,7 +15422,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15139
15422
|
remove
|
|
15140
15423
|
};
|
|
15141
15424
|
});
|
|
15142
|
-
const layer$
|
|
15425
|
+
const layer$55 = Layer.effect(HubAssetClient, make$60);
|
|
15143
15426
|
//#endregion
|
|
15144
15427
|
//#region src/sync/mcpRegistrationFiles.ts
|
|
15145
15428
|
/**
|
|
@@ -15878,7 +16161,7 @@ const EMPTY_REPORT = {
|
|
|
15878
16161
|
unavailable: null
|
|
15879
16162
|
};
|
|
15880
16163
|
var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
|
|
15881
|
-
const make$
|
|
16164
|
+
const make$59 = Effect.gen(function* () {
|
|
15882
16165
|
const client = yield* HubAssetClient;
|
|
15883
16166
|
const link = yield* HubLink;
|
|
15884
16167
|
const settingsStore = yield* ServerSettingsService;
|
|
@@ -16575,10 +16858,10 @@ const make$58 = Effect.gen(function* () {
|
|
|
16575
16858
|
removeLocal
|
|
16576
16859
|
};
|
|
16577
16860
|
});
|
|
16578
|
-
const layer$
|
|
16861
|
+
const layer$54 = Layer.effect(AssetSync, make$59);
|
|
16579
16862
|
//#endregion
|
|
16580
16863
|
//#region src/cli/assets.ts
|
|
16581
|
-
const SyncServicesLive = layer$
|
|
16864
|
+
const SyncServicesLive = layer$54.pipe(Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$58.pipe(Layer.provide(layer$65))), Layer.provideMerge(layer$65), Layer.provideMerge(FetchHttpClient.layer));
|
|
16582
16865
|
const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
16583
16866
|
const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
|
|
16584
16867
|
return yield* Effect.gen(function* () {
|
|
@@ -16586,7 +16869,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
|
16586
16869
|
sync: yield* AssetSync,
|
|
16587
16870
|
link: yield* HubLink
|
|
16588
16871
|
});
|
|
16589
|
-
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$
|
|
16872
|
+
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
|
|
16590
16873
|
});
|
|
16591
16874
|
const STATE_LABEL = {
|
|
16592
16875
|
synced: "synced",
|
|
@@ -21801,12 +22084,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
|
|
|
21801
22084
|
stderrTruncated: stderr.truncated
|
|
21802
22085
|
};
|
|
21803
22086
|
});
|
|
21804
|
-
const make$
|
|
22087
|
+
const make$58 = Effect.fn("ProcessRunner.make")(function* () {
|
|
21805
22088
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
21806
22089
|
const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
|
|
21807
22090
|
return ProcessRunner.of({ run });
|
|
21808
22091
|
});
|
|
21809
|
-
const layer$
|
|
22092
|
+
const layer$53 = Layer.effect(ProcessRunner, make$58());
|
|
21810
22093
|
//#endregion
|
|
21811
22094
|
//#region src/project/RepositoryIdentityResolver.ts
|
|
21812
22095
|
const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
|
|
@@ -21897,7 +22180,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
|
|
|
21897
22180
|
rootPath: cacheKey
|
|
21898
22181
|
}) : null;
|
|
21899
22182
|
});
|
|
21900
|
-
const make$
|
|
22183
|
+
const make$57 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
|
|
21901
22184
|
const processRunner = yield* ProcessRunner;
|
|
21902
22185
|
const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
|
|
21903
22186
|
capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
|
|
@@ -21912,7 +22195,7 @@ const make$56 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
|
|
|
21912
22195
|
});
|
|
21913
22196
|
return RepositoryIdentityResolver.of({ resolve });
|
|
21914
22197
|
});
|
|
21915
|
-
const layer$
|
|
22198
|
+
const layer$52 = Layer.effect(RepositoryIdentityResolver, make$57()).pipe(Layer.provide(layer$53));
|
|
21916
22199
|
//#endregion
|
|
21917
22200
|
//#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
|
|
21918
22201
|
const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
|
|
@@ -23667,7 +23950,7 @@ function mergeWithDefaultKeybindings(custom) {
|
|
|
23667
23950
|
* Keybindings - Service tag for keybinding configuration operations.
|
|
23668
23951
|
*/
|
|
23669
23952
|
var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
|
|
23670
|
-
const make$
|
|
23953
|
+
const make$56 = Effect.gen(function* () {
|
|
23671
23954
|
const { keybindingsConfigPath } = yield* ServerConfig$1;
|
|
23672
23955
|
const fs = yield* FileSystem.FileSystem;
|
|
23673
23956
|
const path = yield* Path.Path;
|
|
@@ -23928,7 +24211,7 @@ const make$55 = Effect.gen(function* () {
|
|
|
23928
24211
|
}))
|
|
23929
24212
|
};
|
|
23930
24213
|
});
|
|
23931
|
-
const layer$
|
|
24214
|
+
const layer$51 = Layer.effect(Keybindings, make$56);
|
|
23932
24215
|
//#endregion
|
|
23933
24216
|
//#region src/process/externalLauncher.ts
|
|
23934
24217
|
/**
|
|
@@ -24155,7 +24438,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
|
|
|
24155
24438
|
cause
|
|
24156
24439
|
}));
|
|
24157
24440
|
});
|
|
24158
|
-
const make$
|
|
24441
|
+
const make$55 = Effect.gen(function* () {
|
|
24159
24442
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
24160
24443
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
24161
24444
|
const path = yield* Path.Path;
|
|
@@ -24166,7 +24449,7 @@ const make$54 = Effect.gen(function* () {
|
|
|
24166
24449
|
launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
|
|
24167
24450
|
});
|
|
24168
24451
|
});
|
|
24169
|
-
const layer$
|
|
24452
|
+
const layer$50 = Layer.effect(ExternalLauncher, make$55);
|
|
24170
24453
|
//#endregion
|
|
24171
24454
|
//#region src/orchestration/Services/OrchestrationReactor.ts
|
|
24172
24455
|
/**
|
|
@@ -24184,7 +24467,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
|
|
|
24184
24467
|
//#endregion
|
|
24185
24468
|
//#region src/serverLifecycleEvents.ts
|
|
24186
24469
|
var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
|
|
24187
|
-
const make$
|
|
24470
|
+
const make$54 = Effect.gen(function* () {
|
|
24188
24471
|
const pubsub = yield* PubSub.unbounded();
|
|
24189
24472
|
const state = yield* Ref.make({
|
|
24190
24473
|
sequence: 0,
|
|
@@ -24208,7 +24491,7 @@ const make$53 = Effect.gen(function* () {
|
|
|
24208
24491
|
}
|
|
24209
24492
|
};
|
|
24210
24493
|
});
|
|
24211
|
-
const layer$
|
|
24494
|
+
const layer$49 = Layer.effect(ServerLifecycleEvents, make$54);
|
|
24212
24495
|
//#endregion
|
|
24213
24496
|
//#region src/telemetry/Identify.ts
|
|
24214
24497
|
const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
|
|
@@ -24381,7 +24664,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
|
|
|
24381
24664
|
/** No-op layer for callers that intentionally disable telemetry. */
|
|
24382
24665
|
static layerTest = Layer.succeed(AnalyticsService, inert);
|
|
24383
24666
|
};
|
|
24384
|
-
const make$
|
|
24667
|
+
const make$53 = Effect.gen(function* () {
|
|
24385
24668
|
const telemetryConfig = yield* TelemetryEnvConfig;
|
|
24386
24669
|
const posthogKey = telemetryConfig.posthogKey.trim();
|
|
24387
24670
|
if (!telemetryConfig.enabled || posthogKey === "") return inert;
|
|
@@ -24451,7 +24734,7 @@ const make$52 = Effect.gen(function* () {
|
|
|
24451
24734
|
flush
|
|
24452
24735
|
});
|
|
24453
24736
|
});
|
|
24454
|
-
const layer$
|
|
24737
|
+
const layer$48 = Layer.effect(AnalyticsService, make$53);
|
|
24455
24738
|
AnalyticsService.layerTest;
|
|
24456
24739
|
//#endregion
|
|
24457
24740
|
//#region src/service/pinnedRuntime.ts
|
|
@@ -24798,7 +25081,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
|
|
|
24798
25081
|
}
|
|
24799
25082
|
};
|
|
24800
25083
|
var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
|
|
24801
|
-
const make$
|
|
25084
|
+
const make$52 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
24802
25085
|
const hostExecPath = yield* HostProcessExecutablePath;
|
|
24803
25086
|
const hostArguments = yield* HostProcessArguments;
|
|
24804
25087
|
const host = input.host ?? {
|
|
@@ -25017,7 +25300,7 @@ const make$51 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
|
25017
25300
|
logPath
|
|
25018
25301
|
});
|
|
25019
25302
|
});
|
|
25020
|
-
const layer$
|
|
25303
|
+
const layer$47 = (input) => Layer.effect(BootService, make$52(input));
|
|
25021
25304
|
//#endregion
|
|
25022
25305
|
//#region src/service/selfUpdate.ts
|
|
25023
25306
|
/**
|
|
@@ -25092,7 +25375,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
|
|
|
25092
25375
|
return null;
|
|
25093
25376
|
});
|
|
25094
25377
|
var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
|
|
25095
|
-
const make$
|
|
25378
|
+
const make$51 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
25096
25379
|
const serverConfig = yield* ServerConfig$1;
|
|
25097
25380
|
const fs = yield* FileSystem.FileSystem;
|
|
25098
25381
|
const path = yield* Path.Path;
|
|
@@ -25242,7 +25525,7 @@ const make$50 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
|
25242
25525
|
});
|
|
25243
25526
|
return ServerSelfUpdate.of({ update });
|
|
25244
25527
|
});
|
|
25245
|
-
const layer$
|
|
25528
|
+
const layer$46 = Layer.effect(ServerSelfUpdate, make$51()).pipe(Layer.provide(layer$53));
|
|
25246
25529
|
//#endregion
|
|
25247
25530
|
//#region src/environment/ServerEnvironmentLabel.ts
|
|
25248
25531
|
const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
|
|
@@ -25374,7 +25657,7 @@ function platformArch(architecture) {
|
|
|
25374
25657
|
default: return "other";
|
|
25375
25658
|
}
|
|
25376
25659
|
}
|
|
25377
|
-
const make$
|
|
25660
|
+
const make$50 = Effect.gen(function* () {
|
|
25378
25661
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
25379
25662
|
const path = yield* Path.Path;
|
|
25380
25663
|
const serverConfig = yield* ServerConfig$1;
|
|
@@ -25437,7 +25720,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
25437
25720
|
* state. It intentionally has no fallback Layer.succeed value: callers must
|
|
25438
25721
|
* provide the external platform services and a ServerConfig.
|
|
25439
25722
|
*/
|
|
25440
|
-
const layer$
|
|
25723
|
+
const layer$45 = Layer.effect(ServerEnvironment, make$50).pipe(Layer.provide(layer$53));
|
|
25441
25724
|
//#endregion
|
|
25442
25725
|
//#region src/provider/Services/ProviderSessionReaper.ts
|
|
25443
25726
|
var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
|
|
@@ -26513,7 +26796,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
|
|
|
26513
26796
|
yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
|
|
26514
26797
|
});
|
|
26515
26798
|
const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
|
|
26516
|
-
const make$
|
|
26799
|
+
const make$49 = Effect.gen(function* () {
|
|
26517
26800
|
const serverConfig = yield* ServerConfig$1;
|
|
26518
26801
|
const keybindings = yield* Keybindings;
|
|
26519
26802
|
const orchestrationReactor = yield* OrchestrationReactor;
|
|
@@ -26654,7 +26937,7 @@ const make$48 = Effect.gen(function* () {
|
|
|
26654
26937
|
enqueueCommand: commandGate.enqueueCommand
|
|
26655
26938
|
};
|
|
26656
26939
|
});
|
|
26657
|
-
const layer$
|
|
26940
|
+
const layer$44 = Layer.effect(ServerRuntimeStartup, make$49);
|
|
26658
26941
|
//#endregion
|
|
26659
26942
|
//#region src/serverRuntimeState.ts
|
|
26660
26943
|
const PersistedServerRuntimeState = Schema$1.Struct({
|
|
@@ -26802,7 +27085,7 @@ function expandHomePath$2(input, path) {
|
|
|
26802
27085
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
26803
27086
|
return input;
|
|
26804
27087
|
}
|
|
26805
|
-
const make$
|
|
27088
|
+
const make$48 = Effect.gen(function* () {
|
|
26806
27089
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
26807
27090
|
const path = yield* Path.Path;
|
|
26808
27091
|
const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
|
|
@@ -26859,7 +27142,7 @@ const make$47 = Effect.gen(function* () {
|
|
|
26859
27142
|
resolveRelativePathWithinRoot
|
|
26860
27143
|
});
|
|
26861
27144
|
});
|
|
26862
|
-
const layer$
|
|
27145
|
+
const layer$43 = Layer.effect(WorkspacePaths, make$48);
|
|
26863
27146
|
//#endregion
|
|
26864
27147
|
//#region src/cli/project.ts
|
|
26865
27148
|
const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
|
|
@@ -26965,7 +27248,7 @@ const projectCommandUuid = Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.
|
|
|
26965
27248
|
operation: "generateProjectCommandId",
|
|
26966
27249
|
cause
|
|
26967
27250
|
})));
|
|
26968
|
-
const ProjectCliRuntimeLive = Layer.mergeAll(layer$
|
|
27251
|
+
const ProjectCliRuntimeLive = Layer.mergeAll(layer$43, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$52), Layer.provideMerge(layerConfig)));
|
|
26969
27252
|
const PROJECT_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(1);
|
|
26970
27253
|
const withProjectCliSessionToken = (environmentAuth, run) => Effect.acquireUseRelease(environmentAuth.issueSession({
|
|
26971
27254
|
scopes: AuthAdministrativeScopes,
|
|
@@ -27056,7 +27339,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
27056
27339
|
});
|
|
27057
27340
|
yield* Console.log(output);
|
|
27058
27341
|
}));
|
|
27059
|
-
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$
|
|
27342
|
+
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
|
|
27060
27343
|
return yield* Effect.gen(function* () {
|
|
27061
27344
|
const snapshot = yield* getOfflineSnapshot();
|
|
27062
27345
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
@@ -27067,7 +27350,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
27067
27350
|
});
|
|
27068
27351
|
yield* Console.log(output);
|
|
27069
27352
|
}).pipe(Effect.provide(offlineRuntimeLayer));
|
|
27070
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$
|
|
27353
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$43).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
27071
27354
|
});
|
|
27072
27355
|
const projectAddCommand = Command.make("add", {
|
|
27073
27356
|
...projectLocationFlags,
|
|
@@ -27674,7 +27957,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
|
|
|
27674
27957
|
filePath: error.filePath,
|
|
27675
27958
|
errorTag: error._tag
|
|
27676
27959
|
}));
|
|
27677
|
-
const make$
|
|
27960
|
+
const make$47 = Effect.gen(function* () {
|
|
27678
27961
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
27679
27962
|
const path = yield* Path.Path;
|
|
27680
27963
|
const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
|
|
@@ -27695,7 +27978,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
27695
27978
|
});
|
|
27696
27979
|
return P4ProjectFileLoader.of({ load });
|
|
27697
27980
|
});
|
|
27698
|
-
const layer$
|
|
27981
|
+
const layer$42 = Layer.effect(P4ProjectFileLoader, make$47);
|
|
27699
27982
|
//#endregion
|
|
27700
27983
|
//#region src/project/ProjectFaviconResolver.ts
|
|
27701
27984
|
/**
|
|
@@ -27766,7 +28049,7 @@ function extractIconHref(source) {
|
|
|
27766
28049
|
return null;
|
|
27767
28050
|
}
|
|
27768
28051
|
const optionOnNotFound$1 = (effect) => effect.pipe(Effect.map(Option.some), Effect.catchTags({ PlatformError: (error) => error.reason._tag === "NotFound" ? Effect.succeed(Option.none()) : Effect.fail(error) }));
|
|
27769
|
-
const make$
|
|
28052
|
+
const make$46 = Effect.gen(function* () {
|
|
27770
28053
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
27771
28054
|
const path = yield* Path.Path;
|
|
27772
28055
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -27835,7 +28118,7 @@ const make$45 = Effect.gen(function* () {
|
|
|
27835
28118
|
});
|
|
27836
28119
|
return ProjectFaviconResolver.of({ resolvePath });
|
|
27837
28120
|
});
|
|
27838
|
-
const layer$
|
|
28121
|
+
const layer$41 = Layer.effect(ProjectFaviconResolver, make$46);
|
|
27839
28122
|
//#endregion
|
|
27840
28123
|
//#region src/assets/AssetAccess.ts
|
|
27841
28124
|
const ASSET_ROUTE_PREFIX = "/api/assets";
|
|
@@ -28088,10 +28371,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
28088
28371
|
//#endregion
|
|
28089
28372
|
//#region src/observability/BrowserTraceCollector.ts
|
|
28090
28373
|
var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
|
|
28091
|
-
const make$
|
|
28374
|
+
const make$45 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
|
|
28092
28375
|
for (const record of records) sink.push(record);
|
|
28093
28376
|
}) });
|
|
28094
|
-
const layer$
|
|
28377
|
+
const layer$40 = (sink) => Layer.succeed(BrowserTraceCollector, make$45(sink));
|
|
28095
28378
|
//#endregion
|
|
28096
28379
|
//#region src/auth/http.ts
|
|
28097
28380
|
const CREDENTIAL_RESPONSE_HEADERS = {
|
|
@@ -30305,7 +30588,7 @@ const classifyNonZeroExit = (command, stderr) => {
|
|
|
30305
30588
|
if (command === "gh" && (normalized.includes("could not resolve to a pullrequest") || normalized.includes("repository.pullrequest") || normalized.includes("no pull requests found for branch") || normalized.includes("pull request not found")) || command === "glab" && (normalized.includes("merge request not found") || normalized.includes("not found") || normalized.includes("404")) || command === "az" && normalized.includes("pull request") && (normalized.includes("not found") || normalized.includes("does not exist"))) return "not-found";
|
|
30306
30589
|
return "command-failed";
|
|
30307
30590
|
};
|
|
30308
|
-
const make$
|
|
30591
|
+
const make$44 = Effect.gen(function* () {
|
|
30309
30592
|
const processRunner = yield* ProcessRunner;
|
|
30310
30593
|
const run = Effect.fn("VcsProcess.run")(function* (input) {
|
|
30311
30594
|
const baseError = {
|
|
@@ -30362,7 +30645,7 @@ const make$43 = Effect.gen(function* () {
|
|
|
30362
30645
|
});
|
|
30363
30646
|
return VcsProcess.of({ run });
|
|
30364
30647
|
});
|
|
30365
|
-
const layer$
|
|
30648
|
+
const layer$39 = Layer.effect(VcsProcess, make$44).pipe(Layer.provide(layer$53));
|
|
30366
30649
|
//#endregion
|
|
30367
30650
|
//#region src/vcs/VcsDriver.ts
|
|
30368
30651
|
var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
|
|
@@ -30813,12 +31096,12 @@ const makeVcsDriver = Effect.gen(function* () {
|
|
|
30813
31096
|
const driver = yield* makeVcsDriverShape();
|
|
30814
31097
|
return VcsDriver.of(driver);
|
|
30815
31098
|
});
|
|
30816
|
-
const make$
|
|
31099
|
+
const make$43 = Effect.gen(function* () {
|
|
30817
31100
|
const git = yield* makeGitVcsDriverCore();
|
|
30818
31101
|
return GitVcsDriver.of(git);
|
|
30819
31102
|
});
|
|
30820
31103
|
Layer.effect(VcsDriver, makeVcsDriver);
|
|
30821
|
-
const layer$
|
|
31104
|
+
const layer$38 = Layer.effect(GitVcsDriver, make$43);
|
|
30822
31105
|
//#endregion
|
|
30823
31106
|
//#region src/vcs/VcsProjectConfig.ts
|
|
30824
31107
|
const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
|
|
@@ -30850,7 +31133,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
|
|
|
30850
31133
|
configPath: error.configPath,
|
|
30851
31134
|
errorTag: error._tag
|
|
30852
31135
|
}));
|
|
30853
|
-
const make$
|
|
31136
|
+
const make$42 = Effect.gen(function* () {
|
|
30854
31137
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
30855
31138
|
const path = yield* Path.Path;
|
|
30856
31139
|
const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
|
|
@@ -30891,7 +31174,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
30891
31174
|
});
|
|
30892
31175
|
return VcsProjectConfig.of({ resolveKind });
|
|
30893
31176
|
});
|
|
30894
|
-
const layer$
|
|
31177
|
+
const layer$37 = Layer.effect(VcsProjectConfig, make$42);
|
|
30895
31178
|
//#endregion
|
|
30896
31179
|
//#region src/vcs/VcsDriverRegistry.ts
|
|
30897
31180
|
const DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -30911,7 +31194,7 @@ function parseDetectionCacheKey(key) {
|
|
|
30911
31194
|
cwd: key.slice(separatorIndex + 1)
|
|
30912
31195
|
};
|
|
30913
31196
|
}
|
|
30914
|
-
const make$
|
|
31197
|
+
const make$41 = Effect.gen(function* () {
|
|
30915
31198
|
const projectConfig = yield* VcsProjectConfig;
|
|
30916
31199
|
const git = yield* makeVcsDriver;
|
|
30917
31200
|
const drivers = { git };
|
|
@@ -30968,7 +31251,7 @@ const make$40 = Effect.gen(function* () {
|
|
|
30968
31251
|
resolve
|
|
30969
31252
|
});
|
|
30970
31253
|
});
|
|
30971
|
-
const layer$
|
|
31254
|
+
const layer$36 = Layer.effect(VcsDriverRegistry, make$41).pipe(Layer.provide(layer$37));
|
|
30972
31255
|
//#endregion
|
|
30973
31256
|
//#region src/checkpointing/CheckpointStore.ts
|
|
30974
31257
|
/**
|
|
@@ -30988,7 +31271,7 @@ const layer$35 = Layer.effect(VcsDriverRegistry, make$40).pipe(Layer.provide(lay
|
|
|
30988
31271
|
*/
|
|
30989
31272
|
/** Service tag for checkpoint persistence and restore operations. */
|
|
30990
31273
|
var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
|
|
30991
|
-
const make$
|
|
31274
|
+
const make$40 = Effect.gen(function* () {
|
|
30992
31275
|
const vcsRegistry = yield* VcsDriverRegistry;
|
|
30993
31276
|
const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
|
|
30994
31277
|
const handle = yield* vcsRegistry.resolve({ cwd });
|
|
@@ -31027,7 +31310,7 @@ const make$39 = Effect.gen(function* () {
|
|
|
31027
31310
|
deleteCheckpointRefs
|
|
31028
31311
|
});
|
|
31029
31312
|
});
|
|
31030
|
-
const layer$
|
|
31313
|
+
const layer$35 = Layer.effect(CheckpointStore, make$40);
|
|
31031
31314
|
//#endregion
|
|
31032
31315
|
//#region src/checkpointing/CheckpointDiffQuery.ts
|
|
31033
31316
|
/**
|
|
@@ -31049,7 +31332,7 @@ function buildTurnDiffResult(input, diff) {
|
|
|
31049
31332
|
diff
|
|
31050
31333
|
};
|
|
31051
31334
|
}
|
|
31052
|
-
const make$
|
|
31335
|
+
const make$39 = Effect.gen(function* () {
|
|
31053
31336
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
31054
31337
|
const checkpointStore = yield* CheckpointStore;
|
|
31055
31338
|
const getTurnDiff = Effect.fn("getTurnDiff")(function* (input) {
|
|
@@ -31185,7 +31468,7 @@ const make$38 = Effect.gen(function* () {
|
|
|
31185
31468
|
getFullThreadDiff
|
|
31186
31469
|
});
|
|
31187
31470
|
});
|
|
31188
|
-
const layer$
|
|
31471
|
+
const layer$34 = Layer.effect(CheckpointDiffQuery, make$39);
|
|
31189
31472
|
//#endregion
|
|
31190
31473
|
//#region src/orchestration/ActivityPayloadProjection.ts
|
|
31191
31474
|
function asRecord$1(value) {
|
|
@@ -32038,7 +32321,7 @@ function makeUpdateState(input) {
|
|
|
32038
32321
|
output: input.output ?? null
|
|
32039
32322
|
};
|
|
32040
32323
|
}
|
|
32041
|
-
const make$
|
|
32324
|
+
const make$38 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
32042
32325
|
const providerRegistry = yield* ProviderRegistry;
|
|
32043
32326
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
32044
32327
|
const httpClient = yield* HttpClient.HttpClient;
|
|
@@ -32153,7 +32436,7 @@ const make$37 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
|
32153
32436
|
});
|
|
32154
32437
|
return ProviderMaintenanceRunner.of({ updateProvider });
|
|
32155
32438
|
});
|
|
32156
|
-
const layer$
|
|
32439
|
+
const layer$33 = Layer.effect(ProviderMaintenanceRunner, make$38());
|
|
32157
32440
|
//#endregion
|
|
32158
32441
|
//#region src/provider/Services/ProviderInstanceRegistry.ts
|
|
32159
32442
|
var ProviderInstanceRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderInstanceRegistry") {};
|
|
@@ -32177,11 +32460,228 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
|
|
|
32177
32460
|
detail: "This provider does not report account usage."
|
|
32178
32461
|
}))))
|
|
32179
32462
|
});
|
|
32180
|
-
const make$
|
|
32463
|
+
const make$37 = Effect.gen(function* () {
|
|
32181
32464
|
const registry = yield* ProviderInstanceRegistry;
|
|
32182
32465
|
return makeTextGenerationFromRegistry(registry);
|
|
32183
32466
|
});
|
|
32184
|
-
const layer$
|
|
32467
|
+
const layer$32 = Layer.effect(TextGeneration, make$37);
|
|
32468
|
+
const SKILL_MANIFEST_FILENAME = "SKILL.md";
|
|
32469
|
+
/**
|
|
32470
|
+
* Split a catalogue id (`owner/repo/skill-name`) into its parts.
|
|
32471
|
+
*
|
|
32472
|
+
* The skill segment is everything after the repository, because a nested skill
|
|
32473
|
+
* id contains slashes and rejoining the tail is the only reading that survives
|
|
32474
|
+
* one.
|
|
32475
|
+
*/
|
|
32476
|
+
function parseRegistrySkillId(id) {
|
|
32477
|
+
const segments = id.split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
32478
|
+
if (segments.length < 3) return null;
|
|
32479
|
+
const [owner, repo, ...rest] = segments;
|
|
32480
|
+
if (!owner || !repo || rest.length === 0) return null;
|
|
32481
|
+
return {
|
|
32482
|
+
owner,
|
|
32483
|
+
repo,
|
|
32484
|
+
skillId: rest.join("/")
|
|
32485
|
+
};
|
|
32486
|
+
}
|
|
32487
|
+
/**
|
|
32488
|
+
* Where the skill lives in the repository, from the repository's file list.
|
|
32489
|
+
*
|
|
32490
|
+
* Matched on `<...>/<skillId>/SKILL.md` rather than on any fixed layout,
|
|
32491
|
+
* because repositories disagree: some keep skills at the root, some under
|
|
32492
|
+
* `skills/`, some several levels down inside a plugin. The shallowest match
|
|
32493
|
+
* wins, which is what picks the skill itself over a copy vendored inside an
|
|
32494
|
+
* example or a test fixture.
|
|
32495
|
+
*/
|
|
32496
|
+
function chooseSkillRoot(entries, skillId) {
|
|
32497
|
+
const leaf = skillId.split("/").pop() ?? skillId;
|
|
32498
|
+
const candidates = [];
|
|
32499
|
+
for (const entry of entries) {
|
|
32500
|
+
if (entry.type !== "blob" || !entry.path.endsWith(`/SKILL.md`)) {
|
|
32501
|
+
if (entry.type === "blob" && entry.path === "SKILL.md") candidates.push("");
|
|
32502
|
+
continue;
|
|
32503
|
+
}
|
|
32504
|
+
const root = entry.path.slice(0, -9);
|
|
32505
|
+
if ((root.split("/").pop() ?? root) === leaf || root === skillId || root.endsWith(`/${skillId}`)) candidates.push(root);
|
|
32506
|
+
}
|
|
32507
|
+
if (candidates.length === 0) return null;
|
|
32508
|
+
candidates.sort((left, right) => {
|
|
32509
|
+
const depth = left.split("/").length - right.split("/").length;
|
|
32510
|
+
return depth === 0 ? left.localeCompare(right) : depth;
|
|
32511
|
+
});
|
|
32512
|
+
return candidates[0] ?? null;
|
|
32513
|
+
}
|
|
32514
|
+
/**
|
|
32515
|
+
* The files under a skill root, bounded and with the manifest first.
|
|
32516
|
+
*
|
|
32517
|
+
* `SKILL.md` leads because it is the one file that must arrive: everything
|
|
32518
|
+
* downstream — the local create refusal, the panel preview, discovery — keys on
|
|
32519
|
+
* it, so if a bound is going to drop something it must not be that.
|
|
32520
|
+
*/
|
|
32521
|
+
function selectSkillFiles(entries, root) {
|
|
32522
|
+
const prefix = root === "" ? "" : `${root}/`;
|
|
32523
|
+
const manifestPath = `${prefix}${SKILL_MANIFEST_FILENAME}`;
|
|
32524
|
+
const inRoot = entries.filter((entry) => entry.type === "blob" && entry.path.startsWith(prefix) && entry.path !== `${prefix}`);
|
|
32525
|
+
const ordered = [...inRoot.filter((entry) => entry.path === manifestPath), ...inRoot.filter((entry) => entry.path !== manifestPath).sort((left, right) => left.path.localeCompare(right.path))];
|
|
32526
|
+
const paths = [];
|
|
32527
|
+
const skipped = [];
|
|
32528
|
+
let totalBytes = 0;
|
|
32529
|
+
for (const entry of ordered) {
|
|
32530
|
+
if (entry.size !== void 0 && entry.size > 262144) {
|
|
32531
|
+
skipped.push({
|
|
32532
|
+
path: entry.path,
|
|
32533
|
+
reason: "too-large"
|
|
32534
|
+
});
|
|
32535
|
+
continue;
|
|
32536
|
+
}
|
|
32537
|
+
if (paths.length >= 40) {
|
|
32538
|
+
skipped.push({
|
|
32539
|
+
path: entry.path,
|
|
32540
|
+
reason: "too-many-files"
|
|
32541
|
+
});
|
|
32542
|
+
continue;
|
|
32543
|
+
}
|
|
32544
|
+
const size = entry.size ?? 0;
|
|
32545
|
+
if (totalBytes + size > 1048576) {
|
|
32546
|
+
skipped.push({
|
|
32547
|
+
path: entry.path,
|
|
32548
|
+
reason: "over-total-size"
|
|
32549
|
+
});
|
|
32550
|
+
continue;
|
|
32551
|
+
}
|
|
32552
|
+
totalBytes += size;
|
|
32553
|
+
paths.push(entry.path);
|
|
32554
|
+
}
|
|
32555
|
+
return {
|
|
32556
|
+
paths,
|
|
32557
|
+
skipped
|
|
32558
|
+
};
|
|
32559
|
+
}
|
|
32560
|
+
/**
|
|
32561
|
+
* The asset-relative path of a repository file, for writing on disk.
|
|
32562
|
+
*
|
|
32563
|
+
* A skill asset's files are named relative to its own directory, so the
|
|
32564
|
+
* repository prefix comes off here rather than at the call site — the sync's
|
|
32565
|
+
* file shape and the registry's are the same shape, and only this line knows
|
|
32566
|
+
* why they differ.
|
|
32567
|
+
*/
|
|
32568
|
+
function toAssetFilePath(repositoryPath, root) {
|
|
32569
|
+
return root === "" ? repositoryPath : repositoryPath.slice(root.length + 1);
|
|
32570
|
+
}
|
|
32571
|
+
//#endregion
|
|
32572
|
+
//#region src/skills/SkillRegistry.ts
|
|
32573
|
+
const REGISTRY_SEARCH_URL = "https://www.skills.sh/api/search";
|
|
32574
|
+
const GITHUB_API_URL = "https://api.github.com";
|
|
32575
|
+
const GITHUB_RAW_URL = "https://raw.githubusercontent.com";
|
|
32576
|
+
const REQUEST_TIMEOUT_MS = 15e3;
|
|
32577
|
+
/** More than a person reads, few enough that the panel is a list and not a feed. */
|
|
32578
|
+
const MAX_SEARCH_RESULTS = 25;
|
|
32579
|
+
/**
|
|
32580
|
+
* The catalogue's search response, decoded loosely on purpose.
|
|
32581
|
+
*
|
|
32582
|
+
* Only the four fields we display are required. This is an undocumented public
|
|
32583
|
+
* endpoint on someone else's service; a field appearing or disappearing beside
|
|
32584
|
+
* these should not turn search into an error.
|
|
32585
|
+
*/
|
|
32586
|
+
const SearchResponse = Schema$1.Struct({ skills: Schema$1.Array(Schema$1.Struct({
|
|
32587
|
+
id: Schema$1.String,
|
|
32588
|
+
name: Schema$1.String,
|
|
32589
|
+
source: Schema$1.String,
|
|
32590
|
+
installs: Schema$1.optional(Schema$1.Number)
|
|
32591
|
+
})) });
|
|
32592
|
+
const decodeSearchResponse = Schema$1.decodeUnknownEffect(SearchResponse);
|
|
32593
|
+
const TreeResponse = Schema$1.Struct({
|
|
32594
|
+
tree: Schema$1.Array(Schema$1.Struct({
|
|
32595
|
+
path: Schema$1.String,
|
|
32596
|
+
type: Schema$1.String,
|
|
32597
|
+
size: Schema$1.optional(Schema$1.Number)
|
|
32598
|
+
})),
|
|
32599
|
+
truncated: Schema$1.optional(Schema$1.Boolean)
|
|
32600
|
+
});
|
|
32601
|
+
const decodeTreeResponse = Schema$1.decodeUnknownEffect(TreeResponse);
|
|
32602
|
+
var SkillRegistry = class extends Context.Service()("@p4code/cli/skills/SkillRegistry") {};
|
|
32603
|
+
const emptyFetch = (id, unavailable) => ({
|
|
32604
|
+
found: false,
|
|
32605
|
+
id,
|
|
32606
|
+
name: "",
|
|
32607
|
+
source: "",
|
|
32608
|
+
sourceUrl: "",
|
|
32609
|
+
files: [],
|
|
32610
|
+
skipped: [],
|
|
32611
|
+
unavailable
|
|
32612
|
+
});
|
|
32613
|
+
const make$36 = Effect.gen(function* () {
|
|
32614
|
+
const http = yield* HttpClient.HttpClient;
|
|
32615
|
+
const request = Effect.fn("SkillRegistry.request")(function* (url) {
|
|
32616
|
+
return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS));
|
|
32617
|
+
});
|
|
32618
|
+
const search = (query) => Effect.gen(function* () {
|
|
32619
|
+
const response = yield* request(`${REGISTRY_SEARCH_URL}?q=${encodeURIComponent(query)}`).pipe(Effect.orElseSucceed(() => null));
|
|
32620
|
+
if (response === null) return {
|
|
32621
|
+
results: [],
|
|
32622
|
+
unavailable: "The skill catalogue could not be reached."
|
|
32623
|
+
};
|
|
32624
|
+
if (response.status !== 200) return {
|
|
32625
|
+
results: [],
|
|
32626
|
+
unavailable: `The skill catalogue answered ${response.status}.`
|
|
32627
|
+
};
|
|
32628
|
+
const body = yield* response.json.pipe(Effect.flatMap(decodeSearchResponse), Effect.orElseSucceed(() => null));
|
|
32629
|
+
if (body === null) return {
|
|
32630
|
+
results: [],
|
|
32631
|
+
unavailable: "The skill catalogue answered something unreadable."
|
|
32632
|
+
};
|
|
32633
|
+
return {
|
|
32634
|
+
results: body.skills.slice(0, MAX_SEARCH_RESULTS).map((skill) => ({
|
|
32635
|
+
id: skill.id,
|
|
32636
|
+
name: skill.name,
|
|
32637
|
+
source: skill.source,
|
|
32638
|
+
installs: Math.trunc(skill.installs ?? 0)
|
|
32639
|
+
})),
|
|
32640
|
+
unavailable: null
|
|
32641
|
+
};
|
|
32642
|
+
});
|
|
32643
|
+
const fetch = (id) => Effect.gen(function* () {
|
|
32644
|
+
const ref = parseRegistrySkillId(id);
|
|
32645
|
+
if (ref === null) return emptyFetch(id, "Expected owner/repo/skill-name.");
|
|
32646
|
+
const repository = `${ref.owner}/${ref.repo}`;
|
|
32647
|
+
const treeResponse = yield* request(`${GITHUB_API_URL}/repos/${repository}/git/trees/HEAD?recursive=1`).pipe(Effect.orElseSucceed(() => null));
|
|
32648
|
+
if (treeResponse === null) return emptyFetch(id, `${repository} could not be reached.`);
|
|
32649
|
+
if (treeResponse.status === 403 || treeResponse.status === 429) return emptyFetch(id, "GitHub is rate limiting this machine. Try again later.");
|
|
32650
|
+
if (treeResponse.status !== 200) return emptyFetch(id, `GitHub answered ${treeResponse.status} for ${repository}.`);
|
|
32651
|
+
const tree = yield* treeResponse.json.pipe(Effect.flatMap(decodeTreeResponse), Effect.orElseSucceed(() => null));
|
|
32652
|
+
if (tree === null) return emptyFetch(id, `GitHub answered something unreadable for ${repository}.`);
|
|
32653
|
+
const entries = tree.tree;
|
|
32654
|
+
const root = chooseSkillRoot(entries, ref.skillId);
|
|
32655
|
+
if (root === null) return emptyFetch(id, tree.truncated === true ? `${repository} is too large for GitHub to list in one response, and ${ref.skillId} was not in the part it returned.` : `${repository} has no ${ref.skillId}/SKILL.md.`);
|
|
32656
|
+
const selection = selectSkillFiles(entries, root);
|
|
32657
|
+
const files = [];
|
|
32658
|
+
for (const path of selection.paths) {
|
|
32659
|
+
const fileResponse = yield* request(`${GITHUB_RAW_URL}/${repository}/HEAD/${path.split("/").map(encodeURIComponent).join("/")}`).pipe(Effect.orElseSucceed(() => null));
|
|
32660
|
+
if (fileResponse === null || fileResponse.status !== 200) return emptyFetch(id, `${path} could not be downloaded.`);
|
|
32661
|
+
const content = yield* fileResponse.text.pipe(Effect.orElseSucceed(() => null));
|
|
32662
|
+
if (content === null) return emptyFetch(id, `${path} is not text, so this skill cannot be installed here.`);
|
|
32663
|
+
files.push({
|
|
32664
|
+
path: toAssetFilePath(path, root),
|
|
32665
|
+
content
|
|
32666
|
+
});
|
|
32667
|
+
}
|
|
32668
|
+
return {
|
|
32669
|
+
found: true,
|
|
32670
|
+
id,
|
|
32671
|
+
name: root === "" ? ref.repo : root.split("/").pop() ?? ref.skillId,
|
|
32672
|
+
source: repository,
|
|
32673
|
+
sourceUrl: root === "" ? `https://github.com/${repository}` : `https://github.com/${repository}/tree/HEAD/${root}`,
|
|
32674
|
+
files,
|
|
32675
|
+
skipped: selection.skipped,
|
|
32676
|
+
unavailable: null
|
|
32677
|
+
};
|
|
32678
|
+
});
|
|
32679
|
+
return {
|
|
32680
|
+
search,
|
|
32681
|
+
fetch
|
|
32682
|
+
};
|
|
32683
|
+
});
|
|
32684
|
+
const layer$31 = Layer.effect(SkillRegistry, make$36);
|
|
32185
32685
|
//#endregion
|
|
32186
32686
|
//#region ../../packages/shared/src/KeyedCoalescingWorker.ts
|
|
32187
32687
|
const makeKeyedCoalescingWorker = (options) => Effect.gen(function* () {
|
|
@@ -32396,7 +32896,7 @@ const COMMON_DEV_PORTS = Object.freeze([
|
|
|
32396
32896
|
8888,
|
|
32397
32897
|
9e3
|
|
32398
32898
|
]);
|
|
32399
|
-
const POLL_INTERVAL = Duration.seconds(3);
|
|
32899
|
+
const POLL_INTERVAL$1 = Duration.seconds(3);
|
|
32400
32900
|
const LSOF_TIMEOUT_MS = 5e3;
|
|
32401
32901
|
const WINDOWS_LISTENER_TIMEOUT_MS = 5e3;
|
|
32402
32902
|
const terminalOwnerKey = (owner) => `${owner.threadId}\u0000${owner.terminalId}`;
|
|
@@ -32571,7 +33071,7 @@ const make$35 = Effect.gen(function* PortDiscoveryMake() {
|
|
|
32571
33071
|
lastSnapshot: next
|
|
32572
33072
|
}])) yield* broadcast(next);
|
|
32573
33073
|
}, Effect.catchCause((cause) => Effect.logWarning("preview port scan failed", Cause.pretty(cause))));
|
|
32574
|
-
yield* Effect.forkScoped(pollTick().pipe(Effect.repeat(Schedule.spaced(POLL_INTERVAL))));
|
|
33074
|
+
yield* Effect.forkScoped(pollTick().pipe(Effect.repeat(Schedule.spaced(POLL_INTERVAL$1))));
|
|
32575
33075
|
const acquireRetention = Effect.fn("PortDiscovery.retain")(function* () {
|
|
32576
33076
|
if (yield* Ref.modify(stateRef, (state) => [state.retainCount === 0, {
|
|
32577
33077
|
...state,
|
|
@@ -34271,7 +34771,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
|
|
|
34271
34771
|
subscribeMetadata
|
|
34272
34772
|
});
|
|
34273
34773
|
});
|
|
34274
|
-
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$
|
|
34774
|
+
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$53));
|
|
34275
34775
|
//#endregion
|
|
34276
34776
|
//#region src/mcp/McpInvocationContext.ts
|
|
34277
34777
|
var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
|
|
@@ -41454,6 +41954,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
41454
41954
|
const hubLink = yield* HubLink;
|
|
41455
41955
|
const assetSync = yield* AssetSync;
|
|
41456
41956
|
const mcpRegistry = yield* McpRegistry;
|
|
41957
|
+
const skillRegistry = yield* SkillRegistry;
|
|
41457
41958
|
const startup = yield* ServerRuntimeStartup;
|
|
41458
41959
|
const workspaceEntries = yield* WorkspaceEntries;
|
|
41459
41960
|
const workspaceFileSystem = yield* WorkspaceFileSystem;
|
|
@@ -42038,6 +42539,8 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
42038
42539
|
status: yield* assetSync.status
|
|
42039
42540
|
};
|
|
42040
42541
|
}), { "rpc.aggregate": "skills" }),
|
|
42542
|
+
[WS_METHODS.skillRegistrySearch]: ({ query }) => observeRpcEffect$1(WS_METHODS.skillRegistrySearch, skillRegistry.search(query), { "rpc.aggregate": "skills" }),
|
|
42543
|
+
[WS_METHODS.skillRegistryFetch]: ({ id }) => observeRpcEffect$1(WS_METHODS.skillRegistryFetch, skillRegistry.fetch(id), { "rpc.aggregate": "skills" }),
|
|
42041
42544
|
[WS_METHODS.mcpList]: (_input) => observeRpcEffect$1(WS_METHODS.mcpList, mcpRegistry.list.pipe(Effect.map((servers) => ({ servers }))), { "rpc.aggregate": "mcp" }),
|
|
42042
42545
|
[WS_METHODS.mcpSave]: ({ registration }) => observeRpcEffect$1(WS_METHODS.mcpSave, mcpRegistry.save(registration).pipe(Effect.andThen(mcpRegistry.list.pipe(Effect.map((servers) => ({ servers }))))), { "rpc.aggregate": "mcp" }),
|
|
42043
42546
|
[WS_METHODS.mcpRemove]: ({ name }) => observeRpcEffect$1(WS_METHODS.mcpRemove, mcpRegistry.remove(name).pipe(Effect.andThen(mcpRegistry.list.pipe(Effect.map((servers) => ({ servers }))))), { "rpc.aggregate": "mcp" }),
|
|
@@ -42219,7 +42722,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
42219
42722
|
const serverAuth = yield* EnvironmentAuth;
|
|
42220
42723
|
const sessions = yield* SessionStore;
|
|
42221
42724
|
const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
|
|
42222
|
-
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$
|
|
42725
|
+
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$33), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(TaskRepository, taskRepository)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(layer$5.pipe(Layer.provide(layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$38), Layer.provide(layer$36.pipe(Layer.provide(layer$37))))), Layer.provide(layer$39))))));
|
|
42223
42726
|
return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
|
|
42224
42727
|
}).pipe(Effect.catchTags({
|
|
42225
42728
|
EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
|
|
@@ -42227,6 +42730,281 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
42227
42730
|
})));
|
|
42228
42731
|
}));
|
|
42229
42732
|
//#endregion
|
|
42733
|
+
//#region src/persistence/Layers/RemoteTasks.ts
|
|
42734
|
+
/**
|
|
42735
|
+
* The board, kept on the hub instead of in this machine's database.
|
|
42736
|
+
*
|
|
42737
|
+
* A drop-in `TaskRepository`: same interface, same events, so the MCP toolkit,
|
|
42738
|
+
* the websocket RPCs and the board itself are unchanged and do not know which
|
|
42739
|
+
* one they are talking to. That was the point of making it an interface.
|
|
42740
|
+
*
|
|
42741
|
+
* **An unreachable hub fails loudly, by decision.** There is no local fallback
|
|
42742
|
+
* and no write queue. A server that answered from a local copy while the hub
|
|
42743
|
+
* was down would recreate exactly the divergence the hub exists to remove —
|
|
42744
|
+
* two Macs with two boards, silently — and the failure would be invisible until
|
|
42745
|
+
* someone noticed a task missing on the other machine. So a hub that cannot be
|
|
42746
|
+
* reached means the board says so and nothing is written. The cost is real and
|
|
42747
|
+
* is the point: no board while the hub is down.
|
|
42748
|
+
*
|
|
42749
|
+
* **Changes are polled, because the hub has no push.** The interface promises
|
|
42750
|
+
* a change stream, and the honest implementation of that against a plain HTTP
|
|
42751
|
+
* API is a poll with a diff. A write made through *this* server publishes
|
|
42752
|
+
* immediately, so the local board is live; the poll is what carries the other
|
|
42753
|
+
* machine's writes, at up to `POLL_INTERVAL` of lag.
|
|
42754
|
+
*
|
|
42755
|
+
* @module persistence/Layers/RemoteTasks
|
|
42756
|
+
*/
|
|
42757
|
+
const HUB_REQUEST_TIMEOUT_MS = 15e3;
|
|
42758
|
+
/**
|
|
42759
|
+
* How stale another machine's write may look here.
|
|
42760
|
+
*
|
|
42761
|
+
* Short enough that a board left open follows along, long enough that two
|
|
42762
|
+
* servers idling all day are not a steady stream of requests at a hosted
|
|
42763
|
+
* service. Only changes made elsewhere wait for it.
|
|
42764
|
+
*/
|
|
42765
|
+
const POLL_INTERVAL = Duration.seconds(10);
|
|
42766
|
+
const TaskListPage = Schema$1.Struct({ tasks: Schema$1.Array(Task) });
|
|
42767
|
+
const ConflictBody = Schema$1.Struct({ current: Task });
|
|
42768
|
+
const decodeTaskListPage = Schema$1.decodeUnknownEffect(TaskListPage);
|
|
42769
|
+
const decodeTask = Schema$1.decodeUnknownEffect(Task);
|
|
42770
|
+
const decodeConflictBody = Schema$1.decodeUnknownEffect(ConflictBody);
|
|
42771
|
+
/**
|
|
42772
|
+
* Every failure here is reported as the interface's own error type.
|
|
42773
|
+
*
|
|
42774
|
+
* `PersistenceSqlError` names a store that would not answer, which is exactly
|
|
42775
|
+
* what this is from a caller's point of view — the detail says the store is the
|
|
42776
|
+
* hub. Inventing a second error type would mean touching every call site to
|
|
42777
|
+
* handle a case they already handle.
|
|
42778
|
+
*/
|
|
42779
|
+
const hubUnavailable = (operation, detail) => new PersistenceSqlError({
|
|
42780
|
+
operation: `RemoteTaskRepository.${operation}`,
|
|
42781
|
+
detail: `The hub board is unavailable: ${detail}`,
|
|
42782
|
+
cause: null
|
|
42783
|
+
});
|
|
42784
|
+
/**
|
|
42785
|
+
* @param isActive Whether this server is currently reading its board from the
|
|
42786
|
+
* hub. The poll asks before every pass rather than being started once: a
|
|
42787
|
+
* machine with the board set to `local` must not be sending a request to a
|
|
42788
|
+
* hosted service every ten seconds for a board nobody is reading, and the
|
|
42789
|
+
* setting can change while the server runs.
|
|
42790
|
+
*/
|
|
42791
|
+
const makeRemoteTaskRepository = Effect.fn("makeRemoteTaskRepository")(function* (isActive) {
|
|
42792
|
+
const http = yield* HttpClient.HttpClient;
|
|
42793
|
+
const link = yield* HubLink;
|
|
42794
|
+
const changes = yield* PubSub.unbounded();
|
|
42795
|
+
const publish = (event) => PubSub.publish(changes, event).pipe(Effect.asVoid);
|
|
42796
|
+
/** The board as of the last poll, for diffing the next one against. */
|
|
42797
|
+
const lastSeen = yield* Ref.make(null);
|
|
42798
|
+
const requireSettings = (operation) => Effect.gen(function* () {
|
|
42799
|
+
const state = yield* link.current;
|
|
42800
|
+
if (Option.isNone(state.settings)) return yield* hubUnavailable(operation, "no hub is configured on this server");
|
|
42801
|
+
return state.settings.value;
|
|
42802
|
+
});
|
|
42803
|
+
const send = (operation, settings, request) => http.execute(request.pipe(HttpClientRequest.setHeader("authorization", `Bearer ${settings.token}`), HttpClientRequest.setHeader("accept", "application/json"))).pipe(Effect.timeout(HUB_REQUEST_TIMEOUT_MS), Effect.mapError((cause) => hubUnavailable(operation, `${cause._tag ?? "request failed"}`)));
|
|
42804
|
+
const list = (filter) => Effect.gen(function* () {
|
|
42805
|
+
const settings = yield* requireSettings("list");
|
|
42806
|
+
const query = new URLSearchParams();
|
|
42807
|
+
for (const key of [
|
|
42808
|
+
"projectId",
|
|
42809
|
+
"repositoryKey",
|
|
42810
|
+
"threadId",
|
|
42811
|
+
"status",
|
|
42812
|
+
"assignee"
|
|
42813
|
+
]) {
|
|
42814
|
+
const value = filter[key];
|
|
42815
|
+
if (value !== void 0) query.set(key, value);
|
|
42816
|
+
}
|
|
42817
|
+
const suffix = query.size === 0 ? "" : `?${query.toString()}`;
|
|
42818
|
+
const response = yield* send("list", settings, HttpClientRequest.get(`${settings.baseUrl}/tasks${suffix}`));
|
|
42819
|
+
if (response.status !== 200) return yield* hubUnavailable("list", `status ${response.status}`);
|
|
42820
|
+
return (yield* response.json.pipe(Effect.flatMap(decodeTaskListPage), Effect.mapError(() => hubUnavailable("list", "the response did not match the contract")))).tasks;
|
|
42821
|
+
});
|
|
42822
|
+
const getById = ({ taskId }) => Effect.gen(function* () {
|
|
42823
|
+
const settings = yield* requireSettings("getById");
|
|
42824
|
+
const response = yield* send("getById", settings, HttpClientRequest.get(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`));
|
|
42825
|
+
if (response.status === 404) return Option.none();
|
|
42826
|
+
if (response.status !== 200) return yield* hubUnavailable("getById", `status ${response.status}`);
|
|
42827
|
+
return Option.some(yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("getById", "the response did not match the contract"))));
|
|
42828
|
+
});
|
|
42829
|
+
/**
|
|
42830
|
+
* Upsert is a create here, and that is a real difference from the local
|
|
42831
|
+
* store.
|
|
42832
|
+
*
|
|
42833
|
+
* The hub mints its own ids and timestamps, so a row written through this
|
|
42834
|
+
* comes back with the hub's version of both. The caller's `taskId` is not
|
|
42835
|
+
* carried: honouring it would need a hub route that takes one, and inventing
|
|
42836
|
+
* that quietly would let two servers mint colliding ids.
|
|
42837
|
+
*/
|
|
42838
|
+
const upsert = (row) => Effect.gen(function* () {
|
|
42839
|
+
const settings = yield* requireSettings("upsert");
|
|
42840
|
+
const response = yield* send("upsert", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.post(`${settings.baseUrl}/tasks`), {
|
|
42841
|
+
...row.projectId === null ? {} : { projectId: row.projectId },
|
|
42842
|
+
...row.repositoryKey === null ? {} : { repositoryKey: row.repositoryKey },
|
|
42843
|
+
...row.threadId === null ? {} : { threadId: row.threadId },
|
|
42844
|
+
title: row.title,
|
|
42845
|
+
body: row.body,
|
|
42846
|
+
status: row.status,
|
|
42847
|
+
priority: row.priority,
|
|
42848
|
+
...row.assignee === null ? {} : { assignee: row.assignee },
|
|
42849
|
+
labels: row.labels
|
|
42850
|
+
}));
|
|
42851
|
+
if (response.status !== 201 && response.status !== 200) return yield* hubUnavailable("upsert", `status ${response.status}`);
|
|
42852
|
+
const created = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("upsert", "the response did not match the contract")));
|
|
42853
|
+
yield* publish({
|
|
42854
|
+
type: "upserted",
|
|
42855
|
+
task: created
|
|
42856
|
+
});
|
|
42857
|
+
});
|
|
42858
|
+
const patch = (input) => Effect.gen(function* () {
|
|
42859
|
+
const settings = yield* requireSettings("patch");
|
|
42860
|
+
const { taskId, ...fields } = input;
|
|
42861
|
+
const response = yield* send("patch", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.patch(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`), fields));
|
|
42862
|
+
if (response.status === 404) return Option.none();
|
|
42863
|
+
if (response.status !== 200) return yield* hubUnavailable("patch", `status ${response.status}`);
|
|
42864
|
+
const updated = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("patch", "the response did not match the contract")));
|
|
42865
|
+
yield* publish({
|
|
42866
|
+
type: "upserted",
|
|
42867
|
+
task: updated
|
|
42868
|
+
});
|
|
42869
|
+
return Option.some(updated);
|
|
42870
|
+
});
|
|
42871
|
+
const patchIfStatus = (input) => Effect.gen(function* () {
|
|
42872
|
+
const settings = yield* requireSettings("patchIfStatus");
|
|
42873
|
+
const { taskId, ...fields } = input.patch;
|
|
42874
|
+
const response = yield* send("patchIfStatus", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.patch(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`), {
|
|
42875
|
+
...fields,
|
|
42876
|
+
expectedStatus: input.expectedStatus
|
|
42877
|
+
}));
|
|
42878
|
+
if (response.status === 404) return { outcome: "missing" };
|
|
42879
|
+
if (response.status === 409) return {
|
|
42880
|
+
outcome: "conflict",
|
|
42881
|
+
current: (yield* response.json.pipe(Effect.flatMap(decodeConflictBody), Effect.mapError(() => hubUnavailable("patchIfStatus", "the conflict response did not match the contract")))).current
|
|
42882
|
+
};
|
|
42883
|
+
if (response.status !== 200) return yield* hubUnavailable("patchIfStatus", `status ${response.status}`);
|
|
42884
|
+
const updated = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("patchIfStatus", "the response did not match the contract")));
|
|
42885
|
+
yield* publish({
|
|
42886
|
+
type: "upserted",
|
|
42887
|
+
task: updated
|
|
42888
|
+
});
|
|
42889
|
+
return {
|
|
42890
|
+
outcome: "updated",
|
|
42891
|
+
task: updated
|
|
42892
|
+
};
|
|
42893
|
+
});
|
|
42894
|
+
const deleteById = ({ taskId }) => Effect.gen(function* () {
|
|
42895
|
+
const settings = yield* requireSettings("deleteById");
|
|
42896
|
+
const response = yield* send("deleteById", settings, HttpClientRequest.delete(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`));
|
|
42897
|
+
if (response.status !== 200 && response.status !== 204 && response.status !== 404) return yield* hubUnavailable("deleteById", `status ${response.status}`);
|
|
42898
|
+
yield* publish({
|
|
42899
|
+
type: "deleted",
|
|
42900
|
+
taskId
|
|
42901
|
+
});
|
|
42902
|
+
});
|
|
42903
|
+
/**
|
|
42904
|
+
* One poll: read the board, publish what differs from last time.
|
|
42905
|
+
*
|
|
42906
|
+
* Compared on `updatedAt` rather than deep equality, because that is the
|
|
42907
|
+
* field every hub write moves and it makes the diff O(n) with no schema
|
|
42908
|
+
* knowledge. A failed poll publishes nothing and leaves the last snapshot in
|
|
42909
|
+
* place — a hub blip should not empty every open board.
|
|
42910
|
+
*/
|
|
42911
|
+
const pollOnce = Effect.gen(function* () {
|
|
42912
|
+
if (!(yield* isActive)) return;
|
|
42913
|
+
const current = yield* list({});
|
|
42914
|
+
const previous = yield* Ref.getAndSet(lastSeen, current);
|
|
42915
|
+
if (previous === null) return;
|
|
42916
|
+
const previousById = new Map(previous.map((task) => [task.taskId, task]));
|
|
42917
|
+
for (const task of current) {
|
|
42918
|
+
const before = previousById.get(task.taskId);
|
|
42919
|
+
if (before === void 0 || before.updatedAt !== task.updatedAt) yield* publish({
|
|
42920
|
+
type: "upserted",
|
|
42921
|
+
task
|
|
42922
|
+
});
|
|
42923
|
+
previousById.delete(task.taskId);
|
|
42924
|
+
}
|
|
42925
|
+
for (const taskId of previousById.keys()) yield* publish({
|
|
42926
|
+
type: "deleted",
|
|
42927
|
+
taskId
|
|
42928
|
+
});
|
|
42929
|
+
}).pipe(Effect.ignoreCause({ log: true }));
|
|
42930
|
+
yield* Effect.forever(pollOnce.pipe(Effect.andThen(Effect.sleep(POLL_INTERVAL)))).pipe(Effect.forkScoped);
|
|
42931
|
+
return {
|
|
42932
|
+
upsert,
|
|
42933
|
+
patch,
|
|
42934
|
+
patchIfStatus,
|
|
42935
|
+
getById,
|
|
42936
|
+
list,
|
|
42937
|
+
deleteById,
|
|
42938
|
+
streamChanges: Stream.fromPubSub(changes),
|
|
42939
|
+
streamWithSnapshot: Stream.unwrap(Effect.gen(function* () {
|
|
42940
|
+
const subscription = yield* PubSub.subscribe(changes);
|
|
42941
|
+
const snapshot = yield* list({});
|
|
42942
|
+
yield* Ref.set(lastSeen, snapshot);
|
|
42943
|
+
return Stream.concat(Stream.succeed({
|
|
42944
|
+
type: "snapshot",
|
|
42945
|
+
tasks: snapshot
|
|
42946
|
+
}), Stream.fromSubscription(subscription));
|
|
42947
|
+
}))
|
|
42948
|
+
};
|
|
42949
|
+
});
|
|
42950
|
+
Layer.effect(TaskRepository, makeRemoteTaskRepository(Effect.succeed(true)));
|
|
42951
|
+
//#endregion
|
|
42952
|
+
//#region src/persistence/Layers/TaskBoardSource.ts
|
|
42953
|
+
/**
|
|
42954
|
+
* Which board a call goes to: this machine's database, or the hub's.
|
|
42955
|
+
*
|
|
42956
|
+
* Both repositories are built, and every call reads the setting and delegates.
|
|
42957
|
+
* That is deliberate rather than picking one at startup: `taskBoardSource` is
|
|
42958
|
+
* an ordinary setting a person changes in a panel, and a setting that only
|
|
42959
|
+
* takes effect after a restart is the same hazard the hub link already
|
|
42960
|
+
* documents — you change it, nothing happens, and there is nothing on screen
|
|
42961
|
+
* saying why.
|
|
42962
|
+
*
|
|
42963
|
+
* **Subscriptions pick their source when they subscribe.** A stream cannot
|
|
42964
|
+
* change its mind mid-flight without inventing a "your board moved" event that
|
|
42965
|
+
* nothing knows how to render, so an open board keeps reading the source it
|
|
42966
|
+
* opened against and picks up the change when it reconnects. Switching is rare;
|
|
42967
|
+
* a wrong row on screen is not worth a new event type.
|
|
42968
|
+
*
|
|
42969
|
+
* @module persistence/Layers/TaskBoardSource
|
|
42970
|
+
*/
|
|
42971
|
+
const makeRoutedTaskRepository = Effect.gen(function* () {
|
|
42972
|
+
const local = yield* makeTaskRepository;
|
|
42973
|
+
const usingHub = (yield* ServerSettingsService).getSettings.pipe(Effect.map((current) => current.taskBoardSource === "hub"), Effect.orElseSucceed(() => false));
|
|
42974
|
+
const remote = yield* makeRemoteTaskRepository(usingHub);
|
|
42975
|
+
/**
|
|
42976
|
+
* `local` on a settings read failure, and that direction is chosen.
|
|
42977
|
+
*
|
|
42978
|
+
* The alternative is refusing every board call because a settings file could
|
|
42979
|
+
* not be read, which turns one broken file into a dead board. Falling back to
|
|
42980
|
+
* the machine's own database is the answer that still works and cannot lose a
|
|
42981
|
+
* hub write, because a write that never reached the hub was never accepted.
|
|
42982
|
+
*/
|
|
42983
|
+
const pick = usingHub.pipe(Effect.map((hub) => hub ? remote : local));
|
|
42984
|
+
return {
|
|
42985
|
+
upsert: (row) => pick.pipe(Effect.flatMap((repository) => repository.upsert(row))),
|
|
42986
|
+
patch: (input, updatedAt) => pick.pipe(Effect.flatMap((repository) => repository.patch(input, updatedAt))),
|
|
42987
|
+
patchIfStatus: (input, updatedAt) => pick.pipe(Effect.flatMap((repository) => repository.patchIfStatus(input, updatedAt))),
|
|
42988
|
+
getById: (input) => pick.pipe(Effect.flatMap((repository) => repository.getById(input))),
|
|
42989
|
+
list: (filter) => pick.pipe(Effect.flatMap((repository) => repository.list(filter))),
|
|
42990
|
+
deleteById: (input) => pick.pipe(Effect.flatMap((repository) => repository.deleteById(input))),
|
|
42991
|
+
get streamChanges() {
|
|
42992
|
+
return Stream.unwrap(pick.pipe(Effect.map((repository) => repository.streamChanges)));
|
|
42993
|
+
},
|
|
42994
|
+
get streamWithSnapshot() {
|
|
42995
|
+
return Stream.unwrap(pick.pipe(Effect.map((repository) => repository.streamWithSnapshot)));
|
|
42996
|
+
}
|
|
42997
|
+
};
|
|
42998
|
+
});
|
|
42999
|
+
/**
|
|
43000
|
+
* The board, wherever it lives.
|
|
43001
|
+
*
|
|
43002
|
+
* Replaces `TaskRepositoryLive` at the one place the route tree provides it, so
|
|
43003
|
+
* the MCP toolkit and the websocket handlers keep sharing a single instance —
|
|
43004
|
+
* which is what makes a task an agent files appear on an open board.
|
|
43005
|
+
*/
|
|
43006
|
+
const RoutedTaskRepositoryLive = Layer.effect(TaskRepository, makeRoutedTaskRepository);
|
|
43007
|
+
//#endregion
|
|
42230
43008
|
//#region src/persistence/ProviderSessionRuntime.ts
|
|
42231
43009
|
/**
|
|
42232
43010
|
* ProviderSessionRuntimeRepository - Repository interface for provider runtime sessions.
|
|
@@ -44246,7 +45024,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
|
|
|
44246
45024
|
};
|
|
44247
45025
|
});
|
|
44248
45026
|
var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
|
|
44249
|
-
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$
|
|
45027
|
+
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$69));
|
|
44250
45028
|
//#endregion
|
|
44251
45029
|
//#region src/textGeneration/TextGenerationUtils.ts
|
|
44252
45030
|
const isTextGenerationError$2 = Schema$1.is(TextGenerationError);
|
|
@@ -45218,7 +45996,7 @@ const runClaudeCommand = Effect.fn("runClaudeCommand")(function* (claudeSettings
|
|
|
45218
45996
|
});
|
|
45219
45997
|
return yield* spawnAndCollect(claudeSettings.binaryPath, command);
|
|
45220
45998
|
});
|
|
45221
|
-
const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(function* (claudeSettings, resolveCapabilities, environment, cwd) {
|
|
45999
|
+
const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(function* (claudeSettings, resolveCapabilities, environment, cwd, disabledSkills) {
|
|
45222
46000
|
const resolvedEnvironment = environment ?? process.env;
|
|
45223
46001
|
const checkedAt = DateTime.formatIso(yield* DateTime.now);
|
|
45224
46002
|
const allModels = providerModelsFromSettings(BUILT_IN_MODELS, claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES);
|
|
@@ -45292,7 +46070,7 @@ const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(functio
|
|
|
45292
46070
|
const models = providerModelsFromSettings(getBuiltInClaudeModelsForVersion(parsedVersion), claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES);
|
|
45293
46071
|
const versionUpgradeMessage = supportsClaudeOpus5(parsedVersion) ? void 0 : supportsClaudeFable5(parsedVersion) ? formatClaudeOpus5UpgradeMessage(parsedVersion) : supportsClaudeOpus48(parsedVersion) ? formatClaudeFable5UpgradeMessage(parsedVersion) : supportsClaudeOpus47(parsedVersion) ? formatClaudeOpus48UpgradeMessage(parsedVersion) : formatClaudeOpus47UpgradeMessage(parsedVersion);
|
|
45294
46072
|
const capabilities = resolveCapabilities ? yield* resolveCapabilities(claudeSettings).pipe(Effect.orElseSucceed(() => void 0)) : void 0;
|
|
45295
|
-
const skills = yield* discoverClaudeSkills(claudeSettings, cwd, resolvedEnvironment);
|
|
46073
|
+
const skills = yield* discoverClaudeSkills(claudeSettings, cwd, resolvedEnvironment, disabledSkills);
|
|
45296
46074
|
const dedupedSlashCommands = dedupeSlashCommands(capabilities?.slashCommands ?? []);
|
|
45297
46075
|
if (!capabilities) return buildServerProvider({
|
|
45298
46076
|
presentation: CLAUDE_PRESENTATION,
|
|
@@ -45693,6 +46471,43 @@ function parseCliArgs(args, options) {
|
|
|
45693
46471
|
};
|
|
45694
46472
|
}
|
|
45695
46473
|
//#endregion
|
|
46474
|
+
//#region src/provider/askUserQuestionAnswers.ts
|
|
46475
|
+
/**
|
|
46476
|
+
* What separates the options of one multi-select answer.
|
|
46477
|
+
*
|
|
46478
|
+
* Comma-and-space rather than a bare comma: the SDK renders this string into a
|
|
46479
|
+
* tool result a model reads, and option labels are prose ("Fail loudly, no
|
|
46480
|
+
* fallback"), so the space is what keeps two joined labels from reading as one.
|
|
46481
|
+
*/
|
|
46482
|
+
const MULTI_SELECT_SEPARATOR = ", ";
|
|
46483
|
+
function formatAnswerValue(value) {
|
|
46484
|
+
if (typeof value === "string") {
|
|
46485
|
+
const trimmed = value.trim();
|
|
46486
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
46487
|
+
}
|
|
46488
|
+
if (Array.isArray(value)) {
|
|
46489
|
+
const parts = value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
46490
|
+
return parts.length > 0 ? parts.join(MULTI_SELECT_SEPARATOR) : null;
|
|
46491
|
+
}
|
|
46492
|
+
return null;
|
|
46493
|
+
}
|
|
46494
|
+
/**
|
|
46495
|
+
* The answers map to hand back to the SDK.
|
|
46496
|
+
*
|
|
46497
|
+
* Questions whose answer is empty, or is neither a string nor a list of them,
|
|
46498
|
+
* are dropped rather than stringified. `String(value)` on an object would put
|
|
46499
|
+
* `[object Object]` in front of the model as though it were the user's choice,
|
|
46500
|
+
* and an absent key is at least a fact the SDK can see.
|
|
46501
|
+
*/
|
|
46502
|
+
function formatAskUserQuestionAnswers(answers) {
|
|
46503
|
+
const formatted = {};
|
|
46504
|
+
for (const [question, value] of Object.entries(answers)) {
|
|
46505
|
+
const answer = formatAnswerValue(value);
|
|
46506
|
+
if (answer !== null) formatted[question] = answer;
|
|
46507
|
+
}
|
|
46508
|
+
return formatted;
|
|
46509
|
+
}
|
|
46510
|
+
//#endregion
|
|
45696
46511
|
//#region src/provider/Layers/ClaudeAdapter.ts
|
|
45697
46512
|
/**
|
|
45698
46513
|
* ClaudeAdapterLive - Scoped live implementation for the Claude Agent provider adapter.
|
|
@@ -46183,20 +46998,50 @@ function planStepsFromClaudeTasks(tasks) {
|
|
|
46183
46998
|
};
|
|
46184
46999
|
});
|
|
46185
47000
|
}
|
|
47001
|
+
const TOOL_SUMMARY_MAX_LENGTH = 400;
|
|
47002
|
+
const TOOL_PROMPT_SUMMARY_MAX_LENGTH = 200;
|
|
47003
|
+
const TOOL_PATH_INPUT_KEYS = [
|
|
47004
|
+
"file_path",
|
|
47005
|
+
"filePath",
|
|
47006
|
+
"notebook_path",
|
|
47007
|
+
"path"
|
|
47008
|
+
];
|
|
47009
|
+
function readTrimmedStringInput(input, keys) {
|
|
47010
|
+
for (const key of keys) {
|
|
47011
|
+
const value = input[key];
|
|
47012
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
47013
|
+
}
|
|
47014
|
+
}
|
|
47015
|
+
/**
|
|
47016
|
+
* Read/Grep/Glob carry no `command`, so without this they fall through to the
|
|
47017
|
+
* raw-JSON fallback and the work log shows `Read: {"file_path":...,"offset":80}`.
|
|
47018
|
+
*/
|
|
47019
|
+
function summarizeFileToolRequest(toolName, input) {
|
|
47020
|
+
const pattern = readTrimmedStringInput(input, ["pattern", "query"]);
|
|
47021
|
+
const path = readTrimmedStringInput(input, TOOL_PATH_INPUT_KEYS);
|
|
47022
|
+
if (pattern) return path ? `${toolName}: ${pattern} in ${path}` : `${toolName}: ${pattern}`;
|
|
47023
|
+
if (!path) return;
|
|
47024
|
+
const offset = input.offset;
|
|
47025
|
+
const limit = input.limit;
|
|
47026
|
+
if (typeof offset === "number" && Number.isFinite(offset)) return `${toolName}: ${path}:${offset}${typeof limit === "number" && Number.isFinite(limit) && limit > 0 ? `-${offset + limit - 1}` : ""}`;
|
|
47027
|
+
return `${toolName}: ${path}`;
|
|
47028
|
+
}
|
|
46186
47029
|
function summarizeToolRequest(toolName, input) {
|
|
46187
47030
|
const commandValue = input.command ?? input.cmd;
|
|
46188
47031
|
const command = typeof commandValue === "string" ? commandValue : void 0;
|
|
46189
|
-
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0,
|
|
47032
|
+
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0, TOOL_SUMMARY_MAX_LENGTH)}`;
|
|
46190
47033
|
if (classifyToolItemType(toolName) === "collab_agent_tool_call") {
|
|
46191
47034
|
const description = typeof input.description === "string" ? input.description.trim() : void 0;
|
|
46192
47035
|
const prompt = typeof input.prompt === "string" ? input.prompt.trim() : void 0;
|
|
46193
47036
|
const subagentType = typeof input.subagent_type === "string" ? input.subagent_type.trim() : void 0;
|
|
46194
|
-
const label = description || (prompt ? prompt.slice(0,
|
|
47037
|
+
const label = description || (prompt ? prompt.slice(0, TOOL_PROMPT_SUMMARY_MAX_LENGTH) : void 0);
|
|
46195
47038
|
if (label) return subagentType ? `${subagentType}: ${label}` : label;
|
|
46196
47039
|
}
|
|
47040
|
+
const fileSummary = summarizeFileToolRequest(toolName, input);
|
|
47041
|
+
if (fileSummary) return fileSummary.slice(0, TOOL_SUMMARY_MAX_LENGTH);
|
|
46197
47042
|
const serialized = encodeJsonStringForDiagnostics$2(input) ?? "[unserializable input]";
|
|
46198
|
-
if (serialized.length <=
|
|
46199
|
-
return `${toolName}: ${serialized.slice(0,
|
|
47043
|
+
if (serialized.length <= TOOL_SUMMARY_MAX_LENGTH) return `${toolName}: ${serialized}`;
|
|
47044
|
+
return `${toolName}: ${serialized.slice(0, TOOL_SUMMARY_MAX_LENGTH - 3)}...`;
|
|
46200
47045
|
}
|
|
46201
47046
|
function titleForTool(itemType) {
|
|
46202
47047
|
switch (itemType) {
|
|
@@ -46237,6 +47082,23 @@ function buildUserMessage(input) {
|
|
|
46237
47082
|
}
|
|
46238
47083
|
};
|
|
46239
47084
|
}
|
|
47085
|
+
function userMessageContentBlocks(message) {
|
|
47086
|
+
const content = message.message.content;
|
|
47087
|
+
if (typeof content === "string") return content.length > 0 ? [{
|
|
47088
|
+
type: "text",
|
|
47089
|
+
text: content
|
|
47090
|
+
}] : [];
|
|
47091
|
+
return Array.isArray(content) ? content : [];
|
|
47092
|
+
}
|
|
47093
|
+
/**
|
|
47094
|
+
* Messages typed while a turn runs are delivered as one prompt, not one turn
|
|
47095
|
+
* each: a user who sends three corrections and then hits Stop means them to be
|
|
47096
|
+
* read together, and replaying them as separate turns made the agent act on the
|
|
47097
|
+
* first before seeing the rest.
|
|
47098
|
+
*/
|
|
47099
|
+
function mergeUserMessages(previous, next) {
|
|
47100
|
+
return buildUserMessage({ sdkContent: [...userMessageContentBlocks(previous), ...userMessageContentBlocks(next)] });
|
|
47101
|
+
}
|
|
46240
47102
|
function buildClaudeImageContentBlock(input) {
|
|
46241
47103
|
return {
|
|
46242
47104
|
type: "image",
|
|
@@ -46876,6 +47738,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46876
47738
|
title: tool.title,
|
|
46877
47739
|
...tool.detail ? { detail: tool.detail } : {},
|
|
46878
47740
|
data: {
|
|
47741
|
+
toolCallId: tool.itemId,
|
|
46879
47742
|
toolName: tool.toolName,
|
|
46880
47743
|
input: tool.input
|
|
46881
47744
|
}
|
|
@@ -46988,18 +47851,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46988
47851
|
});
|
|
46989
47852
|
});
|
|
46990
47853
|
/**
|
|
46991
|
-
* Start the
|
|
47854
|
+
* Start the queued sendTurn, if the session has gone idle.
|
|
46992
47855
|
*
|
|
46993
|
-
* Runs after every turn completion.
|
|
46994
|
-
*
|
|
46995
|
-
*
|
|
46996
|
-
*
|
|
46997
|
-
*
|
|
47856
|
+
* Runs after every turn completion. Messages sent during a running turn wait
|
|
47857
|
+
* here for the agent loop to end; pressing Stop ends the loop early, and the
|
|
47858
|
+
* same drain is what makes Stop mean "and run my messages now". Everything
|
|
47859
|
+
* queued during that turn is already merged into one request by `sendTurn`,
|
|
47860
|
+
* so it starts as a single turn.
|
|
46998
47861
|
*/
|
|
46999
47862
|
const drainPendingTurns = Effect.fn("drainPendingTurns")(function* (context) {
|
|
47000
47863
|
if (context.stopped || context.turnState !== void 0) return;
|
|
47001
|
-
const pending = context.
|
|
47864
|
+
const pending = context.pendingTurnRequest;
|
|
47002
47865
|
if (pending === void 0) return;
|
|
47866
|
+
context.pendingTurnRequest = void 0;
|
|
47003
47867
|
yield* applyTurnSessionOptions(context, pending.modelSelection, pending.interactionMode).pipe(Effect.catchCause((cause) => Effect.logWarning("claude pending turn session options failed", { cause })));
|
|
47004
47868
|
yield* beginTurn(context, pending.turnId, pending.modelSelection?.model);
|
|
47005
47869
|
yield* Queue.offer(context.promptQueue, {
|
|
@@ -47086,6 +47950,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47086
47950
|
title: nextTool.title,
|
|
47087
47951
|
...nextTool.detail ? { detail: nextTool.detail } : {},
|
|
47088
47952
|
data: {
|
|
47953
|
+
toolCallId: nextTool.itemId,
|
|
47089
47954
|
toolName: nextTool.toolName,
|
|
47090
47955
|
input: nextTool.input
|
|
47091
47956
|
}
|
|
@@ -47155,6 +48020,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47155
48020
|
title: tool.title,
|
|
47156
48021
|
...tool.detail ? { detail: tool.detail } : {},
|
|
47157
48022
|
data: {
|
|
48023
|
+
toolCallId: tool.itemId,
|
|
47158
48024
|
toolName: tool.toolName,
|
|
47159
48025
|
input: toolInput
|
|
47160
48026
|
}
|
|
@@ -47192,6 +48058,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47192
48058
|
const itemStatus = toolResult.isError ? "failed" : "completed";
|
|
47193
48059
|
const toolUseResult = readClaudeToolUseResult(message);
|
|
47194
48060
|
const toolData = {
|
|
48061
|
+
toolCallId: tool.itemId,
|
|
47195
48062
|
toolName: tool.toolName,
|
|
47196
48063
|
input: tool.input,
|
|
47197
48064
|
result: toolResult.block
|
|
@@ -47852,7 +48719,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47852
48719
|
behavior: "allow",
|
|
47853
48720
|
updatedInput: {
|
|
47854
48721
|
questions: toolInput.questions,
|
|
47855
|
-
answers
|
|
48722
|
+
answers: formatAskUserQuestionAnswers(answers)
|
|
47856
48723
|
}
|
|
47857
48724
|
};
|
|
47858
48725
|
});
|
|
@@ -47981,10 +48848,13 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47981
48848
|
auto: "auto",
|
|
47982
48849
|
"full-access": "bypassPermissions"
|
|
47983
48850
|
}[input.runtimeMode];
|
|
48851
|
+
const disabledSkills = options?.resolveDisabledSkills === void 0 ? [] : yield* options.resolveDisabledSkills;
|
|
48852
|
+
const skillOverrides = disabledSkills.length === 0 ? void 0 : buildSkillOverrides(disabledSkills, yield* discoverClaudeSkills(claudeSettings, input.cwd, claudeEnvironment).pipe(Effect.provideService(FileSystem.FileSystem, fileSystem), Effect.provideService(Path.Path, path)));
|
|
47984
48853
|
const settings = {
|
|
47985
48854
|
...typeof thinking === "boolean" ? { alwaysThinkingEnabled: thinking } : {},
|
|
47986
48855
|
...fastMode ? { fastMode: true } : {},
|
|
47987
|
-
...ultracode ? { ultracode: true } : {}
|
|
48856
|
+
...ultracode ? { ultracode: true } : {},
|
|
48857
|
+
...skillOverrides ? { skillOverrides } : {}
|
|
47988
48858
|
};
|
|
47989
48859
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
47990
48860
|
const externalMcpServers = options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers;
|
|
@@ -48085,7 +48955,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48085
48955
|
inFlightTools,
|
|
48086
48956
|
claudeTasks,
|
|
48087
48957
|
turnState: void 0,
|
|
48088
|
-
|
|
48958
|
+
pendingTurnRequest: void 0,
|
|
48089
48959
|
lastKnownContextWindow: initialContextWindow,
|
|
48090
48960
|
lastKnownTokenUsage: void 0,
|
|
48091
48961
|
lastKnownTotalProcessedTokens: void 0,
|
|
@@ -48154,13 +49024,14 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48154
49024
|
boundInstanceId
|
|
48155
49025
|
});
|
|
48156
49026
|
if (context.turnState) {
|
|
48157
|
-
const
|
|
48158
|
-
|
|
49027
|
+
const pending = context.pendingTurnRequest;
|
|
49028
|
+
const turnId = pending?.turnId ?? TurnId.make(yield* randomUUIDv4);
|
|
49029
|
+
context.pendingTurnRequest = {
|
|
48159
49030
|
turnId,
|
|
48160
|
-
message,
|
|
49031
|
+
message: pending ? mergeUserMessages(pending.message, message) : message,
|
|
48161
49032
|
modelSelection,
|
|
48162
49033
|
interactionMode: input.interactionMode
|
|
48163
|
-
}
|
|
49034
|
+
};
|
|
48164
49035
|
return {
|
|
48165
49036
|
threadId: context.session.threadId,
|
|
48166
49037
|
turnId,
|
|
@@ -48346,7 +49217,8 @@ function mergeProviderInstanceEnvironment(environment, baseEnv = process.env) {
|
|
|
48346
49217
|
function makeProviderSnapshotSettings(provider, settings) {
|
|
48347
49218
|
return {
|
|
48348
49219
|
provider,
|
|
48349
|
-
enableProviderUpdateChecks: settings.enableProviderUpdateChecks
|
|
49220
|
+
enableProviderUpdateChecks: settings.enableProviderUpdateChecks,
|
|
49221
|
+
disabledSkills: settings.disabledSkills
|
|
48350
49222
|
};
|
|
48351
49223
|
}
|
|
48352
49224
|
function haveProviderSnapshotSettingsChanged(previous, next) {
|
|
@@ -48438,10 +49310,13 @@ const ClaudeDriver = {
|
|
|
48438
49310
|
accentColor,
|
|
48439
49311
|
continuationGroupKey
|
|
48440
49312
|
});
|
|
49313
|
+
const mcpRegistry = yield* McpRegistry;
|
|
49314
|
+
const resolveDisabledSkills = serverSettings.getSettings.pipe(Effect.map((settings) => settings.disabledSkills), Effect.orElseSucceed(() => []));
|
|
48441
49315
|
const adapter = yield* makeClaudeAdapter(effectiveConfig, {
|
|
48442
49316
|
instanceId,
|
|
48443
49317
|
environment: processEnv,
|
|
48444
|
-
resolveMcpServers:
|
|
49318
|
+
resolveMcpServers: mcpRegistry.resolveForSession,
|
|
49319
|
+
resolveDisabledSkills,
|
|
48445
49320
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
|
|
48446
49321
|
});
|
|
48447
49322
|
const textGeneration = yield* makeClaudeTextGeneration(effectiveConfig, processEnv);
|
|
@@ -48451,7 +49326,7 @@ const ClaudeDriver = {
|
|
|
48451
49326
|
lookup: () => probeClaudeCapabilities(effectiveConfig, processEnv, cwd).pipe(Effect.provideService(Path.Path, path))
|
|
48452
49327
|
});
|
|
48453
49328
|
const capabilitiesCacheKey = yield* makeClaudeCapabilitiesCacheKey(effectiveConfig, cwd);
|
|
48454
|
-
const checkProvider = checkClaudeProviderStatus(effectiveConfig, () => Cache.get(capabilitiesProbeCache, capabilitiesCacheKey), processEnv, cwd)
|
|
49329
|
+
const checkProvider = resolveDisabledSkills.pipe(Effect.flatMap((disabledSkills) => checkClaudeProviderStatus(effectiveConfig, () => Cache.get(capabilitiesProbeCache, capabilitiesCacheKey), processEnv, cwd, disabledSkills)), Effect.map(stampIdentity), Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), Effect.provideService(FileSystem.FileSystem, fileSystem), Effect.provideService(Path.Path, path));
|
|
48455
49330
|
const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
|
|
48456
49331
|
const snapshot = yield* makeManagedServerProvider({
|
|
48457
49332
|
maintenanceCapabilities,
|
|
@@ -83338,7 +84213,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
83338
84213
|
sink,
|
|
83339
84214
|
...delegate ? { delegate } : {}
|
|
83340
84215
|
});
|
|
83341
|
-
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$
|
|
84216
|
+
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$40(sink));
|
|
83342
84217
|
})).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
|
|
83343
84218
|
const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
|
|
83344
84219
|
url: config.otlpMetricsUrl,
|
|
@@ -83617,25 +84492,25 @@ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReacto
|
|
|
83617
84492
|
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$3));
|
|
83618
84493
|
const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
|
|
83619
84494
|
const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
|
|
83620
|
-
const VcsDriverRegistryLayerLive = layer$
|
|
83621
|
-
const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$
|
|
83622
|
-
const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$
|
|
83623
|
-
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$
|
|
84495
|
+
const VcsDriverRegistryLayerLive = layer$36.pipe(Layer.provide(layer$37));
|
|
84496
|
+
const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
84497
|
+
const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$38), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$32));
|
|
84498
|
+
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$38));
|
|
83624
84499
|
const GitWorkflowLayerLive = layer$12.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
|
|
83625
|
-
const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$
|
|
83626
|
-
const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$
|
|
83627
|
-
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
83628
|
-
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
83629
|
-
const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$
|
|
84500
|
+
const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
|
|
84501
|
+
const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
84502
|
+
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$37), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$10.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$11.pipe(Layer.provide(GitWorkflowLayerLive))));
|
|
84503
|
+
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$34), Layer.provideMerge(layer$35.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
|
|
84504
|
+
const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$53));
|
|
83630
84505
|
const TerminalLayerLive = layer$29.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
|
|
83631
84506
|
const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$27), Layer.provideMerge(PortScannerLayerLive));
|
|
83632
|
-
const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$
|
|
83633
|
-
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$
|
|
83634
|
-
const WorkspaceLayerLive = Layer.mergeAll(layer$
|
|
83635
|
-
const ProjectFaviconResolverLayerLive = layer$
|
|
83636
|
-
const AuthLayerLive = layer$
|
|
84507
|
+
const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$43));
|
|
84508
|
+
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$43), Layer.provide(WorkspaceEntriesLayerLive));
|
|
84509
|
+
const WorkspaceLayerLive = Layer.mergeAll(layer$43, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
|
|
84510
|
+
const ProjectFaviconResolverLayerLive = layer$41.pipe(Layer.provide(layer$43), Layer.provide(layer$42));
|
|
84511
|
+
const AuthLayerLive = layer$61.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$65));
|
|
83637
84512
|
const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
|
|
83638
|
-
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$
|
|
84513
|
+
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$58.pipe(Layer.provide(layer$65))), 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)), Layer.provideMerge(layer$65)).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$69));
|
|
83639
84514
|
/**
|
|
83640
84515
|
* Hub asset sync.
|
|
83641
84516
|
*
|
|
@@ -83643,9 +84518,9 @@ const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(Checkpo
|
|
|
83643
84518
|
* not-configured shape, and every call reports that rather than failing — so
|
|
83644
84519
|
* this costs a server with no hub nothing but a layer.
|
|
83645
84520
|
*/
|
|
83646
|
-
const AssetSyncLive = layer$
|
|
83647
|
-
const RuntimeServicesLive = layer$
|
|
83648
|
-
const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$2))).pipe(Layer.provide(
|
|
84521
|
+
const AssetSyncLive = layer$54.pipe(Layer.provideMerge(layer$55), Layer.provideMerge(layer$56));
|
|
84522
|
+
const RuntimeServicesLive = layer$44.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
|
|
84523
|
+
const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$2))).pipe(Layer.provide(RoutedTaskRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$28), Layer.provide(layer$46), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
|
|
83649
84524
|
const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
83650
84525
|
const config = yield* ServerConfig$1;
|
|
83651
84526
|
yield* fixPath();
|
|
@@ -83688,7 +84563,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
83688
84563
|
cause,
|
|
83689
84564
|
servePort: configured.servePort
|
|
83690
84565
|
}))) : Effect.void)) : Layer.empty;
|
|
83691
|
-
return Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$
|
|
84566
|
+
return Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$39), Layer.provideMerge(PlatformServicesLive));
|
|
83692
84567
|
}));
|
|
83693
84568
|
const runServer = Layer.launch(makeServerLayer);
|
|
83694
84569
|
//#endregion
|
|
@@ -83850,11 +84725,11 @@ const reconcileWithNewBinary = Effect.fn("cli.selfUpdate.reconcileWithNewBinary"
|
|
|
83850
84725
|
//#endregion
|
|
83851
84726
|
//#region src/cli/service.ts
|
|
83852
84727
|
const isBootServiceCommandError = Schema$1.is(BootServiceCommandError);
|
|
83853
|
-
const bootServiceLayer = (config) => layer$
|
|
84728
|
+
const bootServiceLayer = (config) => layer$47({
|
|
83854
84729
|
baseDir: config.baseDir,
|
|
83855
84730
|
logsDir: config.logsDir,
|
|
83856
84731
|
cliVersion: version
|
|
83857
|
-
}).pipe(Layer.provide(layer$
|
|
84732
|
+
}).pipe(Layer.provide(layer$53));
|
|
83858
84733
|
/** Install, update, or repair the service using the CLI version running this command. */
|
|
83859
84734
|
const reconcileService = Effect.fn("cli.service.reconcile")(function* () {
|
|
83860
84735
|
const service = yield* BootService;
|
|
@@ -83901,7 +84776,7 @@ const runServiceCommand = Effect.fn("cli.service.run")(function* (flags, run, pr
|
|
|
83901
84776
|
const baseDirNotice = yield* describeNonDefaultBaseDir(config.baseDir);
|
|
83902
84777
|
if (baseDirNotice !== null) yield* Console.error(baseDirNotice);
|
|
83903
84778
|
if (prepare !== void 0) yield* prepare(config);
|
|
83904
|
-
return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$
|
|
84779
|
+
return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$53)));
|
|
83905
84780
|
});
|
|
83906
84781
|
/**
|
|
83907
84782
|
* Options the installed unit carries, rather than ones this command consumes.
|
|
@@ -84055,7 +84930,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
|
|
|
84055
84930
|
]));
|
|
84056
84931
|
//#endregion
|
|
84057
84932
|
//#region src/bin.ts
|
|
84058
|
-
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$
|
|
84933
|
+
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$69, FetchHttpClient.layer);
|
|
84059
84934
|
/**
|
|
84060
84935
|
* Prints an update reminder before dispatching, at most once a day.
|
|
84061
84936
|
*
|