@p4code/cli 0.1.4 → 0.1.6
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 +1268 -169
- package/dist/client/assets/{DiffPanel-uBagt_9w.js → DiffPanel-CcuhH24b.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-Dgo3_--S.js → FilePreviewPanel-IupIzTGt.js} +2 -2
- package/dist/client/assets/{PreviewPanel-BzrobngD.js → PreviewPanel-CMRKi8Jr.js} +2 -2
- package/dist/client/assets/{angular-html-C9jMC3ZQ.js → angular-html-D4VEGoU_.js} +2 -2
- package/dist/client/assets/{angular-ts-CYoSZaKw.js → angular-ts-DDbN_Pcg.js} +2 -2
- package/dist/client/assets/{apl-CgWZs6Gn.js → apl-BH7XGSiX.js} +2 -2
- package/dist/client/assets/arrow-right-B-_6vDIF.js +2 -0
- package/dist/client/assets/{astro-CUIqu6Jz.js → astro-DKjLEfvq.js} +2 -2
- package/dist/client/assets/{blade-iplcV4Ix.js → blade-mO6atsi4.js} +2 -2
- package/dist/client/assets/{c-Dd6jN1w_.js → c-drphy09y.js} +2 -2
- package/dist/client/assets/{cobol-0ScsIx-z.js → cobol-Do365H-h.js} +2 -2
- package/dist/client/assets/{coffee-KS_79spe.js → coffee-CJ9y15YY.js} +2 -2
- package/dist/client/assets/{cpp-BllSLkvw.js → cpp-C1FVZ39w.js} +2 -2
- package/dist/client/assets/{crystal-DF2_oukQ.js → crystal-D1Y9mCOy.js} +2 -2
- package/dist/client/assets/{css-DBr167Oo.js → css-C1chQpfJ.js} +2 -2
- package/dist/client/assets/{edge-CRJ0aLAq.js → edge-Cir90YUi.js} +2 -2
- package/dist/client/assets/{elixir-DXl1oanW.js → elixir-D8U_xdUO.js} +2 -2
- package/dist/client/assets/{elm-CqKx609q.js → elm-DFyeiMH7.js} +2 -2
- package/dist/client/assets/{erb-MLJdAbE4.js → erb-C6TvSrSi.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-BjkCgE8J.js → fileCommentAnnotations-BotL9n2H.js} +2 -2
- package/dist/client/assets/{git-rebase-M0aVykt3.js → git-rebase-C7PDtezn.js} +2 -2
- package/dist/client/assets/{glimmer-js-CXPK1DP8.js → glimmer-js-CXugsloP.js} +2 -2
- package/dist/client/assets/{glimmer-ts-wptUL2fp.js → glimmer-ts-IiHVp7il.js} +2 -2
- package/dist/client/assets/{glsl-BRKhgqUF.js → glsl-eBdXjOgx.js} +2 -2
- package/dist/client/assets/{graphql-1BUUHzT4.js → graphql-CBwWowq8.js} +2 -2
- package/dist/client/assets/{hack-BR9NLXvX.js → hack-DoKoRNA-.js} +2 -2
- package/dist/client/assets/{haml-BgBKuGz0.js → haml-B2cA0ELm.js} +2 -2
- package/dist/client/assets/{handlebars-BUs0Hgpn.js → handlebars-OQNujFnM.js} +2 -2
- package/dist/client/assets/{html-BWwNwdti.js → html-B9l55IY7.js} +2 -2
- package/dist/client/assets/{html-derivative-B2dGSGlK.js → html-derivative-C24d_8BY.js} +2 -2
- package/dist/client/assets/{http-NIyxdCuV.js → http-Ca2KxOLT.js} +2 -2
- package/dist/client/assets/{hurl-CH8mm6dw.js → hurl-BuLZo6wH.js} +2 -2
- package/dist/client/assets/index-B-nUm8w7.js +664 -0
- package/dist/client/assets/index-DfKhU-QO.css +1 -0
- package/dist/client/assets/{java-CQPmtuJ5.js → java-BEVFbCvA.js} +2 -2
- package/dist/client/assets/{javascript-DzjJJM-s.js → javascript-AWDSrR1H.js} +2 -2
- package/dist/client/assets/{jinja-4Qs6tVyC.js → jinja-CFK-VDc5.js} +2 -2
- package/dist/client/assets/{jison-CPG2kEI3.js → jison-CSmyyQ0V.js} +2 -2
- package/dist/client/assets/{json-DlY_RU7e.js → json-D0qpEJUc.js} +2 -2
- package/dist/client/assets/{jsx-Cd_ApdjY.js → jsx-smdyqdvA.js} +2 -2
- package/dist/client/assets/{julia-SX8cqtZg.js → julia-DWo_5QH9.js} +2 -2
- package/dist/client/assets/{just-Ao5BO2B0.js → just-74GGYpCk.js} +2 -2
- package/dist/client/assets/{latex-C46nB2Dk.js → latex-d8vfKbSv.js} +2 -2
- package/dist/client/assets/{liquid-BMcKK3Z1.js → liquid-CsWNZJPs.js} +2 -2
- package/dist/client/assets/{lua-DjG6qAWa.js → lua-x3z7TbKl.js} +2 -2
- package/dist/client/assets/{marko-3JoFYw3q.js → marko-CJyhwQKw.js} +2 -2
- package/dist/client/assets/{mdc-BpGP1uha.js → mdc-CtbrrOYL.js} +2 -2
- package/dist/client/assets/{nginx-HOkzmdTd.js → nginx-CY-uw8dq.js} +2 -2
- package/dist/client/assets/{nim-CeKNmMcr.js → nim-DqT4w7rK.js} +2 -2
- package/dist/client/assets/{perl-BWQkxnsH.js → perl-CE3_DH1L.js} +2 -2
- package/dist/client/assets/{php-Df4cK7Vr.js → php-Zxsq1XMP.js} +2 -2
- package/dist/client/assets/{pug-CoCjyAiE.js → pug-DnCImvlN.js} +2 -2
- package/dist/client/assets/{qml-DYi25PQ3.js → qml-DLfoubjW.js} +2 -2
- package/dist/client/assets/{r-BzJkuBsW.js → r-BtfLsgk8.js} +2 -2
- package/dist/client/assets/{razor-BhG_PBuW.js → razor-CzAGh9fe.js} +2 -2
- package/dist/client/assets/{regexp-BAM54YZk.js → regexp-Bw17HBbP.js} +2 -2
- package/dist/client/assets/{rst-DHl4hyZ2.js → rst-DhRr0i5h.js} +2 -2
- package/dist/client/assets/{ruby-gNx0WumM.js → ruby-BnQcHU-H.js} +2 -2
- package/dist/client/assets/{sas-CW83v0Dn.js → sas-mMUu1htl.js} +2 -2
- package/dist/client/assets/{scss-WgrcQHVQ.js → scss-0_lOQ1qp.js} +2 -2
- package/dist/client/assets/{shellscript-CKEnN-lX.js → shellscript-BAdG8zJQ.js} +2 -2
- package/dist/client/assets/{shellsession-BbcmvnCz.js → shellsession-upfFHc_2.js} +2 -2
- package/dist/client/assets/{soy-D1MIxKdU.js → soy-Dzncl5z6.js} +2 -2
- package/dist/client/assets/{sql-Bhxl_Mi7.js → sql-Ca2FgbAh.js} +2 -2
- package/dist/client/assets/{stata-C-LT_UBU.js → stata-D8IymSlL.js} +2 -2
- package/dist/client/assets/{surrealql-Ch_ceRvJ.js → surrealql-CZsXvHAi.js} +2 -2
- package/dist/client/assets/{svelte-DlhsOd0r.js → svelte-nM61Il-m.js} +2 -2
- package/dist/client/assets/{templ-CIHR3tEf.js → templ-DzjlBYVo.js} +2 -2
- package/dist/client/assets/{tex-DRWioNbs.js → tex-BPwIdn9G.js} +2 -2
- package/dist/client/assets/textarea-DhTMBBxg.js +46 -0
- package/dist/client/assets/{ts-tags-BvRYwyAy.js → ts-tags-BL9D6Ojm.js} +2 -2
- package/dist/client/assets/{tsx-BRkrE5rM.js → tsx-AKDVGVPx.js} +2 -2
- package/dist/client/assets/{twig-BlZvFnQN.js → twig-B79f_Jz8.js} +2 -2
- package/dist/client/assets/{typescript-Djd2wnjW.js → typescript-BsyojNKj.js} +2 -2
- package/dist/client/assets/{vue-DActsgCM.js → vue-BTqtDJT-.js} +2 -2
- package/dist/client/assets/{vue-html-Cqt121Xa.js → vue-html-B_UfyILk.js} +2 -2
- package/dist/client/assets/{vue-vine-CzSkk7Q4.js → vue-vine-B8EK-Iln.js} +2 -2
- package/dist/client/assets/{xml-DPi6y6-m.js → xml-Do-3lCfL.js} +2 -2
- package/dist/client/assets/{xsl-BAvs_EI4.js → xsl-CwgwYGXC.js} +2 -2
- package/dist/client/assets/{yaml-DFFGim1C.js → yaml-C4XlY-p5.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/index-D28oUrhs.js +0 -664
- 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.6";
|
|
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");
|
|
@@ -5634,11 +5634,22 @@ const ClaudeSettings = makeProviderSettingsSchema({
|
|
|
5634
5634
|
placeholder: "e.g. --chrome",
|
|
5635
5635
|
clearWhenEmpty: "omit"
|
|
5636
5636
|
}
|
|
5637
|
+
})),
|
|
5638
|
+
/**
|
|
5639
|
+
* The SDK preset system prompt omits the interactive CLI's terminal-tone
|
|
5640
|
+
* sections, so the model tends to open a turn with a tool call instead of
|
|
5641
|
+
* saying what it is about to do. This appends that instruction back.
|
|
5642
|
+
*/
|
|
5643
|
+
narrateBeforeTools: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true)), Schema$1.annotateKey({
|
|
5644
|
+
title: "Explain before tool calls",
|
|
5645
|
+
description: "Ask Claude to write one short sentence before its first tool call in a turn.",
|
|
5646
|
+
providerSettingsForm: { control: "switch" }
|
|
5637
5647
|
}))
|
|
5638
5648
|
}, { order: [
|
|
5639
5649
|
"binaryPath",
|
|
5640
5650
|
"homePath",
|
|
5641
|
-
"launchArgs"
|
|
5651
|
+
"launchArgs",
|
|
5652
|
+
"narrateBeforeTools"
|
|
5642
5653
|
] });
|
|
5643
5654
|
const CursorSettings = makeProviderSettingsSchema({
|
|
5644
5655
|
enabled: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false)), Schema$1.annotateKey({ providerSettingsForm: { hidden: true } })),
|
|
@@ -5720,6 +5731,7 @@ const SourceControlWritingStyleSettings = Schema$1.Struct({
|
|
|
5720
5731
|
followChangeRequestTemplates: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true)))
|
|
5721
5732
|
});
|
|
5722
5733
|
const DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL = Duration.seconds(30);
|
|
5734
|
+
const TaskBoardSource = Schema$1.Literals(["local", "hub"]);
|
|
5723
5735
|
const ServerSettings = Schema$1.Struct({
|
|
5724
5736
|
enableAssistantStreaming: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
|
|
5725
5737
|
enableProviderUpdateChecks: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
@@ -5733,6 +5745,42 @@ const ServerSettings = Schema$1.Struct({
|
|
|
5733
5745
|
}))),
|
|
5734
5746
|
sourceControlWritingStyle: SourceControlWritingStyleSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
5735
5747
|
sourceControlWriterModelSelection: Schema$1.NullOr(ModelSelection).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
5748
|
+
/**
|
|
5749
|
+
* Where this server's task board lives.
|
|
5750
|
+
*
|
|
5751
|
+
* `local` is this machine's own SQLite database, which is where every board
|
|
5752
|
+
* has been until now. `hub` puts the board on the linked hub, so two servers
|
|
5753
|
+
* read and write one board instead of two that silently diverge.
|
|
5754
|
+
*
|
|
5755
|
+
* A setting rather than "hub if one is linked", because a hub can be linked
|
|
5756
|
+
* for skills alone, and flipping a board's home is not something to have
|
|
5757
|
+
* happen as a side effect of connecting. It is also the way back: the local
|
|
5758
|
+
* rows are still there, untouched, when it is set to `local` again.
|
|
5759
|
+
*
|
|
5760
|
+
* **On `hub`, an unreachable hub means no board.** There is no local
|
|
5761
|
+
* fallback by decision: answering from a stale local copy would recreate the
|
|
5762
|
+
* per-machine divergence the hub exists to remove, and it would do it
|
|
5763
|
+
* invisibly.
|
|
5764
|
+
*/
|
|
5765
|
+
taskBoardSource: TaskBoardSource.pipe(Schema$1.withDecodingDefault(Effect.succeed("local"))),
|
|
5766
|
+
/**
|
|
5767
|
+
* Skills the agents on this server must not see, by name.
|
|
5768
|
+
*
|
|
5769
|
+
* Server-scoped rather than per provider instance, because a skill is a
|
|
5770
|
+
* property of the machine's filesystem and every instance on it reads the
|
|
5771
|
+
* same directories.
|
|
5772
|
+
*
|
|
5773
|
+
* Deliberately **not** synced through the hub. A shared skill that is muted
|
|
5774
|
+
* on one machine is the useful combination — the laptop does not want the
|
|
5775
|
+
* skill that shells out to the Studio's build tooling — and syncing the mute
|
|
5776
|
+
* would make that inexpressible.
|
|
5777
|
+
*
|
|
5778
|
+
* What "disabled" means is bounded by what the provider can enforce: the
|
|
5779
|
+
* skill is hidden from the model's listing and from `/name`, and its files
|
|
5780
|
+
* stay on disk and remain readable by Read and Bash. It is a context filter,
|
|
5781
|
+
* not a sandbox, and nothing here should be described to a user as one.
|
|
5782
|
+
*/
|
|
5783
|
+
disabledSkills: Schema$1.Array(TrimmedNonEmptyString).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
|
|
5736
5784
|
providers: Schema$1.Struct({
|
|
5737
5785
|
codex: CodexSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
5738
5786
|
claudeAgent: ClaudeSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
@@ -5790,7 +5838,8 @@ const ClaudeSettingsPatch = Schema$1.Struct({
|
|
|
5790
5838
|
binaryPath: Schema$1.optionalKey(TrimmedString),
|
|
5791
5839
|
homePath: Schema$1.optionalKey(TrimmedString),
|
|
5792
5840
|
customModels: Schema$1.optionalKey(Schema$1.Array(Schema$1.String)),
|
|
5793
|
-
launchArgs: Schema$1.optionalKey(TrimmedString)
|
|
5841
|
+
launchArgs: Schema$1.optionalKey(TrimmedString),
|
|
5842
|
+
narrateBeforeTools: Schema$1.optionalKey(Schema$1.Boolean)
|
|
5794
5843
|
});
|
|
5795
5844
|
const CursorSettingsPatch = Schema$1.Struct({
|
|
5796
5845
|
enabled: Schema$1.optionalKey(Schema$1.Boolean),
|
|
@@ -5824,6 +5873,8 @@ const ServerSettingsPatch = Schema$1.Struct({
|
|
|
5824
5873
|
followChangeRequestTemplates: Schema$1.optionalKey(Schema$1.Boolean)
|
|
5825
5874
|
})),
|
|
5826
5875
|
sourceControlWriterModelSelection: Schema$1.optionalKey(Schema$1.NullOr(ModelSelection)),
|
|
5876
|
+
disabledSkills: Schema$1.optionalKey(Schema$1.Array(TrimmedNonEmptyString)),
|
|
5877
|
+
taskBoardSource: Schema$1.optionalKey(TaskBoardSource),
|
|
5827
5878
|
observability: Schema$1.optionalKey(Schema$1.Struct({
|
|
5828
5879
|
otlpTracesUrl: Schema$1.optionalKey(TrimmedString),
|
|
5829
5880
|
otlpMetricsUrl: Schema$1.optionalKey(TrimmedString)
|
|
@@ -7317,6 +7368,22 @@ const TaskStreamEvent = Schema$1.Union([
|
|
|
7317
7368
|
taskId: TaskId
|
|
7318
7369
|
})
|
|
7319
7370
|
]);
|
|
7371
|
+
Schema$1.Struct({
|
|
7372
|
+
patch: TaskUpdateInput,
|
|
7373
|
+
/** The status the caller believes the task is in. */
|
|
7374
|
+
expectedStatus: TaskStatus
|
|
7375
|
+
});
|
|
7376
|
+
Schema$1.Union([
|
|
7377
|
+
Schema$1.Struct({
|
|
7378
|
+
outcome: Schema$1.Literal("updated"),
|
|
7379
|
+
task: Task
|
|
7380
|
+
}),
|
|
7381
|
+
Schema$1.Struct({ outcome: Schema$1.Literal("missing") }),
|
|
7382
|
+
Schema$1.Struct({
|
|
7383
|
+
outcome: Schema$1.Literal("conflict"),
|
|
7384
|
+
current: Task
|
|
7385
|
+
})
|
|
7386
|
+
]);
|
|
7320
7387
|
/**
|
|
7321
7388
|
* Start an agent on a task.
|
|
7322
7389
|
*
|
|
@@ -7935,6 +8002,81 @@ var McpRegistryError = class extends Schema$1.TaggedErrorClass()("McpRegistryErr
|
|
|
7935
8002
|
}
|
|
7936
8003
|
};
|
|
7937
8004
|
//#endregion
|
|
8005
|
+
//#region ../../packages/contracts/src/skillRegistry.ts
|
|
8006
|
+
/**
|
|
8007
|
+
* Finding skills that are not on this machine yet.
|
|
8008
|
+
*
|
|
8009
|
+
* Managing the skills you already have is CRUD, and that is `agentAsset.ts`.
|
|
8010
|
+
* This is the other half: a catalogue to search and a repository to read a
|
|
8011
|
+
* skill out of, with the install itself going through the ordinary local-create
|
|
8012
|
+
* path so there is exactly one way a skill lands on disk.
|
|
8013
|
+
*
|
|
8014
|
+
* **Nothing here installs anything.** Search returns names; fetch returns the
|
|
8015
|
+
* files it *would* write, with the source they came from. The confirmation step
|
|
8016
|
+
* is a person looking at that list, which is the only reason it is two calls
|
|
8017
|
+
* rather than one — a `SKILL.md` is instructions handed to an agent that
|
|
8018
|
+
* already has a shell, so what it contains is worth seeing before it arrives.
|
|
8019
|
+
*
|
|
8020
|
+
* @module skillRegistry
|
|
8021
|
+
*/
|
|
8022
|
+
/**
|
|
8023
|
+
* One catalogue hit.
|
|
8024
|
+
*
|
|
8025
|
+
* `source` is the repository, and it is not decoration: it is what a person
|
|
8026
|
+
* judges the install on, so it travels with every result rather than being
|
|
8027
|
+
* fetched later.
|
|
8028
|
+
*/
|
|
8029
|
+
const RegistrySkill = Schema$1.Struct({
|
|
8030
|
+
/** `owner/repo/skill-name`, the catalogue's own identifier. */
|
|
8031
|
+
id: TrimmedNonEmptyString,
|
|
8032
|
+
name: TrimmedNonEmptyString,
|
|
8033
|
+
/** `owner/repo`. */
|
|
8034
|
+
source: TrimmedNonEmptyString,
|
|
8035
|
+
/** How many installs the catalogue has counted. Popularity, not endorsement. */
|
|
8036
|
+
installs: Schema$1.Int
|
|
8037
|
+
});
|
|
8038
|
+
const RegistrySkillSearchInput = Schema$1.Struct({ query: TrimmedNonEmptyString });
|
|
8039
|
+
/**
|
|
8040
|
+
* `unavailable` rather than a failure, matching the hub calls: a catalogue on
|
|
8041
|
+
* someone else's infrastructure being down is an ordinary condition, and a
|
|
8042
|
+
* panel has to say which of "nothing matched" and "could not ask" happened.
|
|
8043
|
+
*/
|
|
8044
|
+
const RegistrySkillSearchResult = Schema$1.Struct({
|
|
8045
|
+
results: Schema$1.Array(RegistrySkill),
|
|
8046
|
+
unavailable: Schema$1.NullOr(Schema$1.String)
|
|
8047
|
+
});
|
|
8048
|
+
const RegistrySkillFetchInput = Schema$1.Struct({
|
|
8049
|
+
/** `owner/repo/skill-name`, from a search result or typed by hand. */
|
|
8050
|
+
id: TrimmedNonEmptyString });
|
|
8051
|
+
/** Why a file in the skill's directory is not in the fetched set. */
|
|
8052
|
+
const RegistrySkillSkippedFile = Schema$1.Struct({
|
|
8053
|
+
path: Schema$1.String,
|
|
8054
|
+
reason: Schema$1.Literals([
|
|
8055
|
+
"too-large",
|
|
8056
|
+
"too-many-files",
|
|
8057
|
+
"over-total-size"
|
|
8058
|
+
])
|
|
8059
|
+
});
|
|
8060
|
+
/**
|
|
8061
|
+
* What installing this skill would write, and where it came from.
|
|
8062
|
+
*
|
|
8063
|
+
* `skipped` is part of the answer rather than a log line. A bound that silently
|
|
8064
|
+
* drops a script leaves a skill that is present, looks installed, and fails at
|
|
8065
|
+
* the moment it is used.
|
|
8066
|
+
*/
|
|
8067
|
+
const RegistrySkillFetchResult = Schema$1.Struct({
|
|
8068
|
+
found: Schema$1.Boolean,
|
|
8069
|
+
id: TrimmedNonEmptyString,
|
|
8070
|
+
/** The directory name the skill would take on disk. */
|
|
8071
|
+
name: Schema$1.String,
|
|
8072
|
+
source: Schema$1.String,
|
|
8073
|
+
/** Where these files can be read in full, before trusting them. */
|
|
8074
|
+
sourceUrl: Schema$1.String,
|
|
8075
|
+
files: Schema$1.Array(AgentAssetFile),
|
|
8076
|
+
skipped: Schema$1.Array(RegistrySkillSkippedFile),
|
|
8077
|
+
unavailable: Schema$1.NullOr(Schema$1.String)
|
|
8078
|
+
});
|
|
8079
|
+
//#endregion
|
|
7938
8080
|
//#region ../../packages/contracts/src/filesystem.ts
|
|
7939
8081
|
const FILESYSTEM_PATH_MAX_LENGTH = 512;
|
|
7940
8082
|
const FilesystemBrowseInput = Schema$1.Struct({
|
|
@@ -8197,6 +8339,8 @@ const WS_METHODS = {
|
|
|
8197
8339
|
assetsDelete: "assets.delete",
|
|
8198
8340
|
assetsCreateLocal: "assets.createLocal",
|
|
8199
8341
|
assetsRemoveLocal: "assets.removeLocal",
|
|
8342
|
+
skillRegistrySearch: "skillRegistry.search",
|
|
8343
|
+
skillRegistryFetch: "skillRegistry.fetch",
|
|
8200
8344
|
mcpList: "mcp.list",
|
|
8201
8345
|
mcpSave: "mcp.save",
|
|
8202
8346
|
mcpRemove: "mcp.remove",
|
|
@@ -8420,6 +8564,24 @@ const WsAssetsRemoveLocalRpc = Rpc.make(WS_METHODS.assetsRemoveLocal, {
|
|
|
8420
8564
|
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8421
8565
|
});
|
|
8422
8566
|
/**
|
|
8567
|
+
* Finding and reading skills that are not on this machine yet.
|
|
8568
|
+
*
|
|
8569
|
+
* Read-only, both of them. Installing is `assets.createLocal` with the files
|
|
8570
|
+
* `skillRegistry.fetch` returned, so a skill arriving from a catalogue goes
|
|
8571
|
+
* through exactly the same refusals as one typed into the New skill dialog, and
|
|
8572
|
+
* the step in between is a person looking at what would be written.
|
|
8573
|
+
*/
|
|
8574
|
+
const WsSkillRegistrySearchRpc = Rpc.make(WS_METHODS.skillRegistrySearch, {
|
|
8575
|
+
payload: RegistrySkillSearchInput,
|
|
8576
|
+
success: RegistrySkillSearchResult,
|
|
8577
|
+
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8578
|
+
});
|
|
8579
|
+
const WsSkillRegistryFetchRpc = Rpc.make(WS_METHODS.skillRegistryFetch, {
|
|
8580
|
+
payload: RegistrySkillFetchInput,
|
|
8581
|
+
success: RegistrySkillFetchResult,
|
|
8582
|
+
error: Schema$1.Union([EnvironmentAuthorizationError])
|
|
8583
|
+
});
|
|
8584
|
+
/**
|
|
8423
8585
|
* Registering the user's own MCP servers.
|
|
8424
8586
|
*
|
|
8425
8587
|
* Every one of these answers with the whole list, for the same reason the sync
|
|
@@ -8829,7 +8991,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
|
|
|
8829
8991
|
error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
|
|
8830
8992
|
stream: true
|
|
8831
8993
|
});
|
|
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);
|
|
8994
|
+
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
8995
|
//#endregion
|
|
8834
8996
|
//#region ../../packages/shared/src/oauthScope.ts
|
|
8835
8997
|
const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
|
|
@@ -8975,7 +9137,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
8975
9137
|
//#endregion
|
|
8976
9138
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
8977
9139
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
8978
|
-
const make$
|
|
9140
|
+
const make$71 = Effect.gen(function* () {
|
|
8979
9141
|
const config = yield* ServerConfig$1;
|
|
8980
9142
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
8981
9143
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -8993,7 +9155,7 @@ const make$70 = Effect.gen(function* () {
|
|
|
8993
9155
|
};
|
|
8994
9156
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
8995
9157
|
});
|
|
8996
|
-
const layer$
|
|
9158
|
+
const layer$67 = Layer.effect(EnvironmentAuthPolicy, make$71);
|
|
8997
9159
|
//#endregion
|
|
8998
9160
|
//#region src/persistence/Errors.ts
|
|
8999
9161
|
function summarizeSchemaIssue(issue) {
|
|
@@ -9174,7 +9336,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
9174
9336
|
cause
|
|
9175
9337
|
});
|
|
9176
9338
|
}
|
|
9177
|
-
const make$
|
|
9339
|
+
const make$70 = Effect.gen(function* () {
|
|
9178
9340
|
const sql = yield* SqlClient.SqlClient;
|
|
9179
9341
|
const createSessionRow = SqlSchema.void({
|
|
9180
9342
|
Request: CreateAuthSessionInput,
|
|
@@ -9308,7 +9470,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
9308
9470
|
setLastConnectedAt
|
|
9309
9471
|
};
|
|
9310
9472
|
});
|
|
9311
|
-
const layer$
|
|
9473
|
+
const layer$66 = Layer.effect(AuthSessionRepository, make$70);
|
|
9312
9474
|
//#endregion
|
|
9313
9475
|
//#region src/auth/ServerSecretStore.ts
|
|
9314
9476
|
const secretStoreErrorContext = {
|
|
@@ -9375,7 +9537,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
|
|
|
9375
9537
|
const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
|
|
9376
9538
|
const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
|
|
9377
9539
|
var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
|
|
9378
|
-
const make$
|
|
9540
|
+
const make$69 = Effect.gen(function* () {
|
|
9379
9541
|
const crypto = yield* Crypto.Crypto;
|
|
9380
9542
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
9381
9543
|
const path = yield* Path.Path;
|
|
@@ -9445,7 +9607,7 @@ const make$68 = Effect.gen(function* () {
|
|
|
9445
9607
|
remove
|
|
9446
9608
|
});
|
|
9447
9609
|
});
|
|
9448
|
-
const layer$
|
|
9610
|
+
const layer$65 = Layer.effect(ServerSecretStore, make$69);
|
|
9449
9611
|
//#endregion
|
|
9450
9612
|
//#region src/auth/SessionStore.ts
|
|
9451
9613
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -9683,7 +9845,7 @@ function toAuthClientSession(input) {
|
|
|
9683
9845
|
current: false
|
|
9684
9846
|
};
|
|
9685
9847
|
}
|
|
9686
|
-
const make$
|
|
9848
|
+
const make$68 = Effect.gen(function* () {
|
|
9687
9849
|
const crypto = yield* Crypto.Crypto;
|
|
9688
9850
|
const serverConfig = yield* ServerConfig$1;
|
|
9689
9851
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -9997,7 +10159,7 @@ const make$67 = Effect.gen(function* () {
|
|
|
9997
10159
|
markDisconnected
|
|
9998
10160
|
});
|
|
9999
10161
|
});
|
|
10000
|
-
const layer$
|
|
10162
|
+
const layer$64 = Layer.effect(SessionStore, make$68).pipe(Layer.provideMerge(layer$66));
|
|
10001
10163
|
//#endregion
|
|
10002
10164
|
//#region src/persistence/AuthPairingLinks.ts
|
|
10003
10165
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -10058,7 +10220,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
10058
10220
|
cause
|
|
10059
10221
|
});
|
|
10060
10222
|
}
|
|
10061
|
-
const make$
|
|
10223
|
+
const make$67 = Effect.gen(function* () {
|
|
10062
10224
|
const sql = yield* SqlClient.SqlClient;
|
|
10063
10225
|
const createPairingLinkRow = SqlSchema.void({
|
|
10064
10226
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -10193,7 +10355,7 @@ const make$66 = Effect.gen(function* () {
|
|
|
10193
10355
|
getByCredential
|
|
10194
10356
|
};
|
|
10195
10357
|
});
|
|
10196
|
-
const layer$
|
|
10358
|
+
const layer$63 = Layer.effect(AuthPairingLinkRepository, make$67);
|
|
10197
10359
|
//#endregion
|
|
10198
10360
|
//#region src/auth/PairingGrantStore.ts
|
|
10199
10361
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -10288,7 +10450,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
10288
10450
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
10289
10451
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
10290
10452
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
10291
|
-
const make$
|
|
10453
|
+
const make$66 = Effect.gen(function* () {
|
|
10292
10454
|
const crypto = yield* Crypto.Crypto;
|
|
10293
10455
|
const config = yield* ServerConfig$1;
|
|
10294
10456
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -10486,7 +10648,7 @@ const make$65 = Effect.gen(function* () {
|
|
|
10486
10648
|
consume
|
|
10487
10649
|
});
|
|
10488
10650
|
});
|
|
10489
|
-
const layer$
|
|
10651
|
+
const layer$62 = Layer.effect(PairingGrantStore, make$66).pipe(Layer.provideMerge(layer$63));
|
|
10490
10652
|
//#endregion
|
|
10491
10653
|
//#region src/persistence/Migrations/001_OrchestrationEvents.ts
|
|
10492
10654
|
var _001_OrchestrationEvents_default = Effect.gen(function* () {
|
|
@@ -12259,7 +12421,7 @@ function parseBearerToken(request) {
|
|
|
12259
12421
|
const token = header.slice(7).trim();
|
|
12260
12422
|
return token.length > 0 ? token : null;
|
|
12261
12423
|
}
|
|
12262
|
-
const make$
|
|
12424
|
+
const make$65 = Effect.gen(function* () {
|
|
12263
12425
|
const policy = yield* EnvironmentAuthPolicy;
|
|
12264
12426
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
12265
12427
|
const sessions = yield* SessionStore;
|
|
@@ -12454,9 +12616,9 @@ const make$64 = Effect.gen(function* () {
|
|
|
12454
12616
|
issueStartupPairingUrl
|
|
12455
12617
|
});
|
|
12456
12618
|
});
|
|
12457
|
-
const layer$
|
|
12458
|
-
const storageLayer = Layer.mergeAll(layer$
|
|
12459
|
-
const runtimeLayer = layer$
|
|
12619
|
+
const layer$61 = Layer.effect(EnvironmentAuth, make$65).pipe(Layer.provideMerge(layer$62), Layer.provideMerge(layer$64), Layer.provideMerge(layer$67));
|
|
12620
|
+
const storageLayer = Layer.mergeAll(layer$65, layerConfig);
|
|
12621
|
+
const runtimeLayer = layer$61.pipe(Layer.provideMerge(storageLayer));
|
|
12460
12622
|
//#endregion
|
|
12461
12623
|
//#region src/cliAuthFormat.ts
|
|
12462
12624
|
const newline = "\n";
|
|
@@ -13211,7 +13373,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
|
|
|
13211
13373
|
}
|
|
13212
13374
|
return yield* Effect.gen(function* () {
|
|
13213
13375
|
return yield* run(yield* EnvironmentAuth);
|
|
13214
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$
|
|
13376
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
13215
13377
|
});
|
|
13216
13378
|
const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
|
|
13217
13379
|
const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
|
|
@@ -13351,7 +13513,7 @@ const DEFAULT_LIMITS = {
|
|
|
13351
13513
|
windowMillis: FAILURE_WINDOW_MS,
|
|
13352
13514
|
blockMillis: BLOCK_DURATION_MS
|
|
13353
13515
|
};
|
|
13354
|
-
const make$
|
|
13516
|
+
const make$64 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
13355
13517
|
const state = yield* Ref.make(initialThrottleState);
|
|
13356
13518
|
return HubAuthThrottle.of({
|
|
13357
13519
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -13365,7 +13527,7 @@ const make$63 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
|
|
|
13365
13527
|
})
|
|
13366
13528
|
});
|
|
13367
13529
|
});
|
|
13368
|
-
const layer$
|
|
13530
|
+
const layer$60 = Layer.effect(HubAuthThrottle, make$64());
|
|
13369
13531
|
//#endregion
|
|
13370
13532
|
//#region src/hub/HubAuth.ts
|
|
13371
13533
|
/**
|
|
@@ -13817,6 +13979,43 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
13817
13979
|
task
|
|
13818
13980
|
})
|
|
13819
13981
|
})));
|
|
13982
|
+
/**
|
|
13983
|
+
* The claim, and the reason it is a separate method rather than an option on
|
|
13984
|
+
* `patch`: only this one has an outcome a caller must branch on.
|
|
13985
|
+
*
|
|
13986
|
+
* The comparison happens *inside* the transaction alongside the write, which
|
|
13987
|
+
* is the only arrangement that makes it a compare-and-set. Reading first and
|
|
13988
|
+
* writing after would leave exactly the window it exists to close.
|
|
13989
|
+
*/
|
|
13990
|
+
const patchIfStatus = (input, updatedAt) => sql.withTransaction(Effect.gen(function* () {
|
|
13991
|
+
const existing = yield* getTaskRow({ taskId: input.patch.taskId });
|
|
13992
|
+
if (Option.isNone(existing)) return { outcome: "missing" };
|
|
13993
|
+
if (existing.value.status !== input.expectedStatus) return {
|
|
13994
|
+
outcome: "conflict",
|
|
13995
|
+
current: existing.value
|
|
13996
|
+
};
|
|
13997
|
+
const updated = {
|
|
13998
|
+
...existing.value,
|
|
13999
|
+
...input.patch.projectId !== void 0 ? { projectId: input.patch.projectId } : {},
|
|
14000
|
+
...input.patch.repositoryKey !== void 0 ? { repositoryKey: input.patch.repositoryKey } : {},
|
|
14001
|
+
...input.patch.threadId !== void 0 ? { threadId: input.patch.threadId } : {},
|
|
14002
|
+
...input.patch.title !== void 0 ? { title: input.patch.title } : {},
|
|
14003
|
+
...input.patch.body !== void 0 ? { body: input.patch.body } : {},
|
|
14004
|
+
...input.patch.status !== void 0 ? { status: input.patch.status } : {},
|
|
14005
|
+
...input.patch.priority !== void 0 ? { priority: input.patch.priority } : {},
|
|
14006
|
+
...input.patch.assignee !== void 0 ? { assignee: input.patch.assignee } : {},
|
|
14007
|
+
...input.patch.labels !== void 0 ? { labels: input.patch.labels } : {},
|
|
14008
|
+
updatedAt
|
|
14009
|
+
};
|
|
14010
|
+
yield* upsertTaskRow(updated);
|
|
14011
|
+
return {
|
|
14012
|
+
outcome: "updated",
|
|
14013
|
+
task: updated
|
|
14014
|
+
};
|
|
14015
|
+
})).pipe(Effect.mapError(toPersistenceSqlError("TaskRepository.patchIfStatus:query")), Effect.tap((result) => result.outcome === "updated" ? publish({
|
|
14016
|
+
type: "upserted",
|
|
14017
|
+
task: result.task
|
|
14018
|
+
}) : Effect.void));
|
|
13820
14019
|
const deleteById = (input) => deleteTaskRow(input).pipe(Effect.mapError(toPersistenceSqlError("TaskRepository.deleteById:query")), Effect.tap(() => publish({
|
|
13821
14020
|
type: "deleted",
|
|
13822
14021
|
taskId: input.taskId
|
|
@@ -13824,6 +14023,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
13824
14023
|
return {
|
|
13825
14024
|
upsert,
|
|
13826
14025
|
patch,
|
|
14026
|
+
patchIfStatus,
|
|
13827
14027
|
getById,
|
|
13828
14028
|
list,
|
|
13829
14029
|
deleteById,
|
|
@@ -13944,13 +14144,25 @@ const updateTaskRoute = HttpRouter.add("PATCH", "/tasks/:taskId", respondToHubFa
|
|
|
13944
14144
|
yield* authenticateHubRequest();
|
|
13945
14145
|
const params = yield* HttpRouter.params;
|
|
13946
14146
|
const taskId = TaskId.make(params.taskId ?? "");
|
|
13947
|
-
const
|
|
14147
|
+
const { expectedStatus, ...patchBody } = (yield* readJsonBody()) ?? {};
|
|
13948
14148
|
const input = yield* decodeOrInvalid(TaskUpdateInput, "Request body does not match TaskUpdateInput.")({
|
|
13949
|
-
...
|
|
14149
|
+
...patchBody,
|
|
13950
14150
|
taskId
|
|
13951
14151
|
});
|
|
13952
14152
|
const tasks = yield* TaskRepository;
|
|
13953
14153
|
const timestamp = DateTime.formatIso(yield* DateTime.now);
|
|
14154
|
+
if (expectedStatus !== void 0) {
|
|
14155
|
+
const condition = yield* decodeOrInvalid(TaskStatus, "expectedStatus is not a task status.")(expectedStatus);
|
|
14156
|
+
const result = yield* tasks.patchIfStatus({
|
|
14157
|
+
patch: input,
|
|
14158
|
+
expectedStatus: condition
|
|
14159
|
+
}, timestamp);
|
|
14160
|
+
if (result.outcome === "missing") return notFound(taskId);
|
|
14161
|
+
return result.outcome === "conflict" ? HttpServerResponse.jsonUnsafe({
|
|
14162
|
+
error: "conflict",
|
|
14163
|
+
current: result.current
|
|
14164
|
+
}, { status: 409 }) : HttpServerResponse.jsonUnsafe(result.task);
|
|
14165
|
+
}
|
|
13954
14166
|
const patched = yield* tasks.patch(input, timestamp);
|
|
13955
14167
|
return Option.isNone(patched) ? notFound(taskId) : HttpServerResponse.jsonUnsafe(patched.value);
|
|
13956
14168
|
})));
|
|
@@ -14056,7 +14268,7 @@ const deleteAssetRoute = HttpRouter.add("DELETE", "/assets/:kind/:name", respond
|
|
|
14056
14268
|
const outcome = yield* (yield* AgentAssetRepository).deleteByName(requested);
|
|
14057
14269
|
return outcome._tag === "conflict" ? assetConflict(Option.getOrNull(outcome.current)) : HttpServerResponse.empty({ status: 204 });
|
|
14058
14270
|
})));
|
|
14059
|
-
const layer$
|
|
14271
|
+
const layer$59 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute);
|
|
14060
14272
|
//#endregion
|
|
14061
14273
|
//#region src/hub/Migrations/001_Tasks.ts
|
|
14062
14274
|
/**
|
|
@@ -14271,7 +14483,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
|
|
|
14271
14483
|
});
|
|
14272
14484
|
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
14485
|
}));
|
|
14274
|
-
const makeHubLayer = HttpRouter.serve(layer$
|
|
14486
|
+
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
14487
|
const runHub = Layer.launch(makeHubLayer);
|
|
14276
14488
|
//#endregion
|
|
14277
14489
|
//#region src/atomicWrite.ts
|
|
@@ -14395,7 +14607,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
14395
14607
|
}
|
|
14396
14608
|
return Object.is(current, defaults) ? void 0 : current;
|
|
14397
14609
|
}
|
|
14398
|
-
const make$
|
|
14610
|
+
const make$63 = Effect.gen(function* () {
|
|
14399
14611
|
const { settingsPath } = yield* ServerConfig$1;
|
|
14400
14612
|
const fs = yield* FileSystem.FileSystem;
|
|
14401
14613
|
const pathService = yield* Path.Path;
|
|
@@ -14616,7 +14828,7 @@ const make$62 = Effect.gen(function* () {
|
|
|
14616
14828
|
}
|
|
14617
14829
|
};
|
|
14618
14830
|
});
|
|
14619
|
-
const layer$
|
|
14831
|
+
const layer$58 = Layer.effect(ServerSettingsService, make$63);
|
|
14620
14832
|
//#endregion
|
|
14621
14833
|
//#region src/pathExpansion.ts
|
|
14622
14834
|
/**
|
|
@@ -14638,6 +14850,86 @@ function expandHomePath$3(value) {
|
|
|
14638
14850
|
return value;
|
|
14639
14851
|
}
|
|
14640
14852
|
//#endregion
|
|
14853
|
+
//#region src/provider/skillOverrides.ts
|
|
14854
|
+
/**
|
|
14855
|
+
* Turning "this skill is disabled" into something a provider enforces.
|
|
14856
|
+
*
|
|
14857
|
+
* **A skill has two names and either can reach it.** Discovery reports the
|
|
14858
|
+
* `SKILL.md` frontmatter `name` when there is one and the directory name
|
|
14859
|
+
* otherwise, while the sync panel lists directories — so the disabled set can
|
|
14860
|
+
* hold either form depending on which surface the toggle was pressed on, and
|
|
14861
|
+
* the CLI keys its own listing on the name it resolved. Matching on one form
|
|
14862
|
+
* only produces a toggle that works for most skills and silently does nothing
|
|
14863
|
+
* for the ones whose frontmatter disagrees with their directory, which is the
|
|
14864
|
+
* worst of the available failures: it looks like the feature works.
|
|
14865
|
+
*
|
|
14866
|
+
* So both forms are matched on the way in and both are emitted on the way out.
|
|
14867
|
+
*
|
|
14868
|
+
* **The lever is `Settings.skillOverrides`, not the SDK's `skills` option.**
|
|
14869
|
+
* `skills: string[]` is an allowlist: passing it enables *only* the listed
|
|
14870
|
+
* skills, so a single disabled skill would silently take every plugin-provided
|
|
14871
|
+
* skill with it, since those are not in our discovery at all. `skillOverrides`
|
|
14872
|
+
* is per skill and additive — an absent key means "on" — so nothing is affected
|
|
14873
|
+
* except what was named.
|
|
14874
|
+
*
|
|
14875
|
+
* @module provider/skillOverrides
|
|
14876
|
+
*/
|
|
14877
|
+
/**
|
|
14878
|
+
* Hidden from the model's listing *and* from `/name`.
|
|
14879
|
+
*
|
|
14880
|
+
* The other values the setting accepts are partial hides (`name-only`,
|
|
14881
|
+
* `user-invocable-only`); a p4code toggle labelled "disabled" has to be the
|
|
14882
|
+
* complete one, or the label is a lie.
|
|
14883
|
+
*/
|
|
14884
|
+
const SKILL_OVERRIDE_OFF = "off";
|
|
14885
|
+
/**
|
|
14886
|
+
* The directory a skill lives in, from its `SKILL.md` path.
|
|
14887
|
+
*
|
|
14888
|
+
* Path handling by hand rather than through `Path.Path`, because this stays a
|
|
14889
|
+
* pure function: it is called from discovery, from the adapter and from tests,
|
|
14890
|
+
* and the segment separator is the only platform fact it needs.
|
|
14891
|
+
*/
|
|
14892
|
+
function skillDirectoryName(skillPath) {
|
|
14893
|
+
const segments = skillPath.split(/[/\\]/).filter((segment) => segment.length > 0);
|
|
14894
|
+
return segments.length >= 2 ? segments[segments.length - 2] ?? "" : "";
|
|
14895
|
+
}
|
|
14896
|
+
/** Every name a skill answers to, ignoring empties. */
|
|
14897
|
+
function namesOf(skill) {
|
|
14898
|
+
const directoryName = skillDirectoryName(skill.path);
|
|
14899
|
+
return [skill.name, directoryName].filter((name) => name.length > 0);
|
|
14900
|
+
}
|
|
14901
|
+
/**
|
|
14902
|
+
* Whether a discovered skill is in the disabled set, under either of its names.
|
|
14903
|
+
*/
|
|
14904
|
+
function isSkillDisabled(skill, disabled) {
|
|
14905
|
+
const disabledSet = new Set(disabled);
|
|
14906
|
+
return namesOf(skill).some((name) => disabledSet.has(name));
|
|
14907
|
+
}
|
|
14908
|
+
/**
|
|
14909
|
+
* The `skillOverrides` map to hand a session, or `undefined` when nothing is
|
|
14910
|
+
* disabled.
|
|
14911
|
+
*
|
|
14912
|
+
* `undefined` rather than `{}` on purpose: an empty map is a setting the
|
|
14913
|
+
* session did not have before, and the point of this feature is that a server
|
|
14914
|
+
* with nothing disabled starts sessions byte-identical to the ones it started
|
|
14915
|
+
* yesterday.
|
|
14916
|
+
*
|
|
14917
|
+
* Names that match no discovered skill are still emitted. A skill can be
|
|
14918
|
+
* disabled and then removed from disk, or disabled in a project the current
|
|
14919
|
+
* session is not in, and dropping the entry would quietly re-enable it the
|
|
14920
|
+
* moment discovery misses it.
|
|
14921
|
+
*/
|
|
14922
|
+
function buildSkillOverrides(disabled, discovered) {
|
|
14923
|
+
if (disabled.length === 0) return;
|
|
14924
|
+
const overrides = {};
|
|
14925
|
+
for (const name of disabled) if (name.length > 0) overrides[name] = SKILL_OVERRIDE_OFF;
|
|
14926
|
+
for (const skill of discovered) {
|
|
14927
|
+
if (!isSkillDisabled(skill, disabled)) continue;
|
|
14928
|
+
for (const name of namesOf(skill)) overrides[name] = SKILL_OVERRIDE_OFF;
|
|
14929
|
+
}
|
|
14930
|
+
return Object.keys(overrides).length === 0 ? void 0 : overrides;
|
|
14931
|
+
}
|
|
14932
|
+
//#endregion
|
|
14641
14933
|
//#region src/provider/Drivers/ClaudeSkills.ts
|
|
14642
14934
|
/**
|
|
14643
14935
|
* ClaudeSkills — filesystem discovery of Claude Code skills for the `$` picker.
|
|
@@ -14709,7 +15001,7 @@ const resolveClaudeUserSkillsDir = Effect.fn("resolveClaudeUserSkillsDir")(funct
|
|
|
14709
15001
|
* collisions the project-scoped skill wins, matching Claude Code's
|
|
14710
15002
|
* most-specific-wins resolution.
|
|
14711
15003
|
*/
|
|
14712
|
-
const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config, cwd, environment) {
|
|
15004
|
+
const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config, cwd, environment, disabledSkills) {
|
|
14713
15005
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
14714
15006
|
const path = yield* Path.Path;
|
|
14715
15007
|
const configDirPath = yield* resolveClaudeConfigDirPath(config, environment ?? process.env, cwd);
|
|
@@ -14734,7 +15026,10 @@ const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config
|
|
|
14734
15026
|
skillsByName.set(name, {
|
|
14735
15027
|
name,
|
|
14736
15028
|
path: skillPath,
|
|
14737
|
-
enabled:
|
|
15029
|
+
enabled: !isSkillDisabled({
|
|
15030
|
+
name,
|
|
15031
|
+
path: skillPath
|
|
15032
|
+
}, disabledSkills ?? []),
|
|
14738
15033
|
scope: root.scope,
|
|
14739
15034
|
...frontmatter.kind === "parsed" && frontmatter.description ? { description: frontmatter.description } : {}
|
|
14740
15035
|
});
|
|
@@ -14749,7 +15044,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
|
|
|
14749
15044
|
const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
|
|
14750
15045
|
var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
|
|
14751
15046
|
const slotsOf = (registration) => registration.secrets ?? [];
|
|
14752
|
-
const make$
|
|
15047
|
+
const make$62 = Effect.gen(function* () {
|
|
14753
15048
|
const config = yield* ServerConfig$1;
|
|
14754
15049
|
const secrets = yield* ServerSecretStore;
|
|
14755
15050
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
@@ -14861,7 +15156,7 @@ const make$61 = Effect.gen(function* () {
|
|
|
14861
15156
|
}).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
|
|
14862
15157
|
};
|
|
14863
15158
|
});
|
|
14864
|
-
const layer$
|
|
15159
|
+
const layer$57 = Layer.effect(McpRegistry, make$62);
|
|
14865
15160
|
//#endregion
|
|
14866
15161
|
//#region src/sync/HubLink.ts
|
|
14867
15162
|
/**
|
|
@@ -14958,7 +15253,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
|
|
|
14958
15253
|
shareMode: input.shareMode
|
|
14959
15254
|
});
|
|
14960
15255
|
const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
|
|
14961
|
-
const make$
|
|
15256
|
+
const make$61 = Effect.fn("HubLink.make")(function* (environment) {
|
|
14962
15257
|
const secrets = yield* ServerSecretStore;
|
|
14963
15258
|
const env = environment ?? process.env;
|
|
14964
15259
|
const fromEnv = fromEnvironment(env);
|
|
@@ -15024,7 +15319,7 @@ const make$60 = Effect.fn("HubLink.make")(function* (environment) {
|
|
|
15024
15319
|
})
|
|
15025
15320
|
};
|
|
15026
15321
|
});
|
|
15027
|
-
const layer$
|
|
15322
|
+
const layer$56 = Layer.effect(HubLink, make$61());
|
|
15028
15323
|
//#endregion
|
|
15029
15324
|
//#region src/sync/HubAssetClient.ts
|
|
15030
15325
|
/**
|
|
@@ -15039,7 +15334,7 @@ const layer$55 = Layer.effect(HubLink, make$60());
|
|
|
15039
15334
|
*
|
|
15040
15335
|
* @module sync/HubAssetClient
|
|
15041
15336
|
*/
|
|
15042
|
-
const HUB_REQUEST_TIMEOUT_MS = 15e3;
|
|
15337
|
+
const HUB_REQUEST_TIMEOUT_MS$1 = 15e3;
|
|
15043
15338
|
/**
|
|
15044
15339
|
* The hub could not be reached, or answered something unusable.
|
|
15045
15340
|
*
|
|
@@ -15052,12 +15347,12 @@ var HubAssetConflict = class extends Data.TaggedError("HubAssetConflict") {};
|
|
|
15052
15347
|
/** No hub is configured on this server, so there is nothing to talk to. */
|
|
15053
15348
|
var HubNotConfigured = class extends Data.TaggedError("HubNotConfigured") {};
|
|
15054
15349
|
const AssetListPage = Schema$1.Struct({ assets: Schema$1.Array(AgentAsset) });
|
|
15055
|
-
const ConflictBody = Schema$1.Struct({ current: Schema$1.NullOr(AgentAsset) });
|
|
15350
|
+
const ConflictBody$1 = Schema$1.Struct({ current: Schema$1.NullOr(AgentAsset) });
|
|
15056
15351
|
const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
|
|
15057
|
-
const decodeConflictBody = Schema$1.decodeUnknownEffect(ConflictBody);
|
|
15352
|
+
const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
|
|
15058
15353
|
const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
|
|
15059
15354
|
var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
|
|
15060
|
-
const make$
|
|
15355
|
+
const make$60 = Effect.gen(function* () {
|
|
15061
15356
|
const http = yield* HttpClient.HttpClient;
|
|
15062
15357
|
const link = yield* HubLink;
|
|
15063
15358
|
const requireSettings = Effect.gen(function* () {
|
|
@@ -15066,7 +15361,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15066
15361
|
return state.settings.value;
|
|
15067
15362
|
});
|
|
15068
15363
|
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({
|
|
15364
|
+
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
15365
|
operation,
|
|
15071
15366
|
detail: `${cause._tag ?? "error"}`
|
|
15072
15367
|
})));
|
|
@@ -15086,7 +15381,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15086
15381
|
* which is what lets a caller show both sides instead of only saying no.
|
|
15087
15382
|
*/
|
|
15088
15383
|
const conflictFrom = Effect.fn("HubAssetClient.conflictFrom")(function* (name, response) {
|
|
15089
|
-
const body = yield* decodeBody("conflict", decodeConflictBody, response).pipe(Effect.orElseSucceed(() => ({ current: null })));
|
|
15384
|
+
const body = yield* decodeBody("conflict", decodeConflictBody$1, response).pipe(Effect.orElseSucceed(() => ({ current: null })));
|
|
15090
15385
|
return new HubAssetConflict({
|
|
15091
15386
|
name,
|
|
15092
15387
|
current: body.current === null ? Option.none() : Option.some(body.current)
|
|
@@ -15139,7 +15434,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
15139
15434
|
remove
|
|
15140
15435
|
};
|
|
15141
15436
|
});
|
|
15142
|
-
const layer$
|
|
15437
|
+
const layer$55 = Layer.effect(HubAssetClient, make$60);
|
|
15143
15438
|
//#endregion
|
|
15144
15439
|
//#region src/sync/mcpRegistrationFiles.ts
|
|
15145
15440
|
/**
|
|
@@ -15878,7 +16173,7 @@ const EMPTY_REPORT = {
|
|
|
15878
16173
|
unavailable: null
|
|
15879
16174
|
};
|
|
15880
16175
|
var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
|
|
15881
|
-
const make$
|
|
16176
|
+
const make$59 = Effect.gen(function* () {
|
|
15882
16177
|
const client = yield* HubAssetClient;
|
|
15883
16178
|
const link = yield* HubLink;
|
|
15884
16179
|
const settingsStore = yield* ServerSettingsService;
|
|
@@ -16575,10 +16870,10 @@ const make$58 = Effect.gen(function* () {
|
|
|
16575
16870
|
removeLocal
|
|
16576
16871
|
};
|
|
16577
16872
|
});
|
|
16578
|
-
const layer$
|
|
16873
|
+
const layer$54 = Layer.effect(AssetSync, make$59);
|
|
16579
16874
|
//#endregion
|
|
16580
16875
|
//#region src/cli/assets.ts
|
|
16581
|
-
const SyncServicesLive = layer$
|
|
16876
|
+
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
16877
|
const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
16583
16878
|
const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
|
|
16584
16879
|
return yield* Effect.gen(function* () {
|
|
@@ -16586,7 +16881,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
|
16586
16881
|
sync: yield* AssetSync,
|
|
16587
16882
|
link: yield* HubLink
|
|
16588
16883
|
});
|
|
16589
|
-
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$
|
|
16884
|
+
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
|
|
16590
16885
|
});
|
|
16591
16886
|
const STATE_LABEL = {
|
|
16592
16887
|
synced: "synced",
|
|
@@ -21801,12 +22096,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
|
|
|
21801
22096
|
stderrTruncated: stderr.truncated
|
|
21802
22097
|
};
|
|
21803
22098
|
});
|
|
21804
|
-
const make$
|
|
22099
|
+
const make$58 = Effect.fn("ProcessRunner.make")(function* () {
|
|
21805
22100
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
21806
22101
|
const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
|
|
21807
22102
|
return ProcessRunner.of({ run });
|
|
21808
22103
|
});
|
|
21809
|
-
const layer$
|
|
22104
|
+
const layer$53 = Layer.effect(ProcessRunner, make$58());
|
|
21810
22105
|
//#endregion
|
|
21811
22106
|
//#region src/project/RepositoryIdentityResolver.ts
|
|
21812
22107
|
const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
|
|
@@ -21897,7 +22192,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
|
|
|
21897
22192
|
rootPath: cacheKey
|
|
21898
22193
|
}) : null;
|
|
21899
22194
|
});
|
|
21900
|
-
const make$
|
|
22195
|
+
const make$57 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
|
|
21901
22196
|
const processRunner = yield* ProcessRunner;
|
|
21902
22197
|
const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
|
|
21903
22198
|
capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
|
|
@@ -21912,7 +22207,7 @@ const make$56 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
|
|
|
21912
22207
|
});
|
|
21913
22208
|
return RepositoryIdentityResolver.of({ resolve });
|
|
21914
22209
|
});
|
|
21915
|
-
const layer$
|
|
22210
|
+
const layer$52 = Layer.effect(RepositoryIdentityResolver, make$57()).pipe(Layer.provide(layer$53));
|
|
21916
22211
|
//#endregion
|
|
21917
22212
|
//#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
|
|
21918
22213
|
const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
|
|
@@ -23667,7 +23962,7 @@ function mergeWithDefaultKeybindings(custom) {
|
|
|
23667
23962
|
* Keybindings - Service tag for keybinding configuration operations.
|
|
23668
23963
|
*/
|
|
23669
23964
|
var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
|
|
23670
|
-
const make$
|
|
23965
|
+
const make$56 = Effect.gen(function* () {
|
|
23671
23966
|
const { keybindingsConfigPath } = yield* ServerConfig$1;
|
|
23672
23967
|
const fs = yield* FileSystem.FileSystem;
|
|
23673
23968
|
const path = yield* Path.Path;
|
|
@@ -23928,7 +24223,7 @@ const make$55 = Effect.gen(function* () {
|
|
|
23928
24223
|
}))
|
|
23929
24224
|
};
|
|
23930
24225
|
});
|
|
23931
|
-
const layer$
|
|
24226
|
+
const layer$51 = Layer.effect(Keybindings, make$56);
|
|
23932
24227
|
//#endregion
|
|
23933
24228
|
//#region src/process/externalLauncher.ts
|
|
23934
24229
|
/**
|
|
@@ -24155,7 +24450,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
|
|
|
24155
24450
|
cause
|
|
24156
24451
|
}));
|
|
24157
24452
|
});
|
|
24158
|
-
const make$
|
|
24453
|
+
const make$55 = Effect.gen(function* () {
|
|
24159
24454
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
24160
24455
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
24161
24456
|
const path = yield* Path.Path;
|
|
@@ -24166,7 +24461,7 @@ const make$54 = Effect.gen(function* () {
|
|
|
24166
24461
|
launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
|
|
24167
24462
|
});
|
|
24168
24463
|
});
|
|
24169
|
-
const layer$
|
|
24464
|
+
const layer$50 = Layer.effect(ExternalLauncher, make$55);
|
|
24170
24465
|
//#endregion
|
|
24171
24466
|
//#region src/orchestration/Services/OrchestrationReactor.ts
|
|
24172
24467
|
/**
|
|
@@ -24184,7 +24479,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
|
|
|
24184
24479
|
//#endregion
|
|
24185
24480
|
//#region src/serverLifecycleEvents.ts
|
|
24186
24481
|
var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
|
|
24187
|
-
const make$
|
|
24482
|
+
const make$54 = Effect.gen(function* () {
|
|
24188
24483
|
const pubsub = yield* PubSub.unbounded();
|
|
24189
24484
|
const state = yield* Ref.make({
|
|
24190
24485
|
sequence: 0,
|
|
@@ -24208,7 +24503,7 @@ const make$53 = Effect.gen(function* () {
|
|
|
24208
24503
|
}
|
|
24209
24504
|
};
|
|
24210
24505
|
});
|
|
24211
|
-
const layer$
|
|
24506
|
+
const layer$49 = Layer.effect(ServerLifecycleEvents, make$54);
|
|
24212
24507
|
//#endregion
|
|
24213
24508
|
//#region src/telemetry/Identify.ts
|
|
24214
24509
|
const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
|
|
@@ -24381,7 +24676,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
|
|
|
24381
24676
|
/** No-op layer for callers that intentionally disable telemetry. */
|
|
24382
24677
|
static layerTest = Layer.succeed(AnalyticsService, inert);
|
|
24383
24678
|
};
|
|
24384
|
-
const make$
|
|
24679
|
+
const make$53 = Effect.gen(function* () {
|
|
24385
24680
|
const telemetryConfig = yield* TelemetryEnvConfig;
|
|
24386
24681
|
const posthogKey = telemetryConfig.posthogKey.trim();
|
|
24387
24682
|
if (!telemetryConfig.enabled || posthogKey === "") return inert;
|
|
@@ -24451,7 +24746,7 @@ const make$52 = Effect.gen(function* () {
|
|
|
24451
24746
|
flush
|
|
24452
24747
|
});
|
|
24453
24748
|
});
|
|
24454
|
-
const layer$
|
|
24749
|
+
const layer$48 = Layer.effect(AnalyticsService, make$53);
|
|
24455
24750
|
AnalyticsService.layerTest;
|
|
24456
24751
|
//#endregion
|
|
24457
24752
|
//#region src/service/pinnedRuntime.ts
|
|
@@ -24798,7 +25093,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
|
|
|
24798
25093
|
}
|
|
24799
25094
|
};
|
|
24800
25095
|
var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
|
|
24801
|
-
const make$
|
|
25096
|
+
const make$52 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
24802
25097
|
const hostExecPath = yield* HostProcessExecutablePath;
|
|
24803
25098
|
const hostArguments = yield* HostProcessArguments;
|
|
24804
25099
|
const host = input.host ?? {
|
|
@@ -25017,7 +25312,7 @@ const make$51 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
|
25017
25312
|
logPath
|
|
25018
25313
|
});
|
|
25019
25314
|
});
|
|
25020
|
-
const layer$
|
|
25315
|
+
const layer$47 = (input) => Layer.effect(BootService, make$52(input));
|
|
25021
25316
|
//#endregion
|
|
25022
25317
|
//#region src/service/selfUpdate.ts
|
|
25023
25318
|
/**
|
|
@@ -25092,7 +25387,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
|
|
|
25092
25387
|
return null;
|
|
25093
25388
|
});
|
|
25094
25389
|
var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
|
|
25095
|
-
const make$
|
|
25390
|
+
const make$51 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
25096
25391
|
const serverConfig = yield* ServerConfig$1;
|
|
25097
25392
|
const fs = yield* FileSystem.FileSystem;
|
|
25098
25393
|
const path = yield* Path.Path;
|
|
@@ -25242,7 +25537,7 @@ const make$50 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
|
25242
25537
|
});
|
|
25243
25538
|
return ServerSelfUpdate.of({ update });
|
|
25244
25539
|
});
|
|
25245
|
-
const layer$
|
|
25540
|
+
const layer$46 = Layer.effect(ServerSelfUpdate, make$51()).pipe(Layer.provide(layer$53));
|
|
25246
25541
|
//#endregion
|
|
25247
25542
|
//#region src/environment/ServerEnvironmentLabel.ts
|
|
25248
25543
|
const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
|
|
@@ -25374,7 +25669,7 @@ function platformArch(architecture) {
|
|
|
25374
25669
|
default: return "other";
|
|
25375
25670
|
}
|
|
25376
25671
|
}
|
|
25377
|
-
const make$
|
|
25672
|
+
const make$50 = Effect.gen(function* () {
|
|
25378
25673
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
25379
25674
|
const path = yield* Path.Path;
|
|
25380
25675
|
const serverConfig = yield* ServerConfig$1;
|
|
@@ -25437,7 +25732,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
25437
25732
|
* state. It intentionally has no fallback Layer.succeed value: callers must
|
|
25438
25733
|
* provide the external platform services and a ServerConfig.
|
|
25439
25734
|
*/
|
|
25440
|
-
const layer$
|
|
25735
|
+
const layer$45 = Layer.effect(ServerEnvironment, make$50).pipe(Layer.provide(layer$53));
|
|
25441
25736
|
//#endregion
|
|
25442
25737
|
//#region src/provider/Services/ProviderSessionReaper.ts
|
|
25443
25738
|
var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
|
|
@@ -26513,7 +26808,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
|
|
|
26513
26808
|
yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
|
|
26514
26809
|
});
|
|
26515
26810
|
const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
|
|
26516
|
-
const make$
|
|
26811
|
+
const make$49 = Effect.gen(function* () {
|
|
26517
26812
|
const serverConfig = yield* ServerConfig$1;
|
|
26518
26813
|
const keybindings = yield* Keybindings;
|
|
26519
26814
|
const orchestrationReactor = yield* OrchestrationReactor;
|
|
@@ -26654,7 +26949,7 @@ const make$48 = Effect.gen(function* () {
|
|
|
26654
26949
|
enqueueCommand: commandGate.enqueueCommand
|
|
26655
26950
|
};
|
|
26656
26951
|
});
|
|
26657
|
-
const layer$
|
|
26952
|
+
const layer$44 = Layer.effect(ServerRuntimeStartup, make$49);
|
|
26658
26953
|
//#endregion
|
|
26659
26954
|
//#region src/serverRuntimeState.ts
|
|
26660
26955
|
const PersistedServerRuntimeState = Schema$1.Struct({
|
|
@@ -26802,7 +27097,7 @@ function expandHomePath$2(input, path) {
|
|
|
26802
27097
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
26803
27098
|
return input;
|
|
26804
27099
|
}
|
|
26805
|
-
const make$
|
|
27100
|
+
const make$48 = Effect.gen(function* () {
|
|
26806
27101
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
26807
27102
|
const path = yield* Path.Path;
|
|
26808
27103
|
const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
|
|
@@ -26859,7 +27154,7 @@ const make$47 = Effect.gen(function* () {
|
|
|
26859
27154
|
resolveRelativePathWithinRoot
|
|
26860
27155
|
});
|
|
26861
27156
|
});
|
|
26862
|
-
const layer$
|
|
27157
|
+
const layer$43 = Layer.effect(WorkspacePaths, make$48);
|
|
26863
27158
|
//#endregion
|
|
26864
27159
|
//#region src/cli/project.ts
|
|
26865
27160
|
const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
|
|
@@ -26965,7 +27260,7 @@ const projectCommandUuid = Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.
|
|
|
26965
27260
|
operation: "generateProjectCommandId",
|
|
26966
27261
|
cause
|
|
26967
27262
|
})));
|
|
26968
|
-
const ProjectCliRuntimeLive = Layer.mergeAll(layer$
|
|
27263
|
+
const ProjectCliRuntimeLive = Layer.mergeAll(layer$43, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$52), Layer.provideMerge(layerConfig)));
|
|
26969
27264
|
const PROJECT_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(1);
|
|
26970
27265
|
const withProjectCliSessionToken = (environmentAuth, run) => Effect.acquireUseRelease(environmentAuth.issueSession({
|
|
26971
27266
|
scopes: AuthAdministrativeScopes,
|
|
@@ -27056,7 +27351,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
27056
27351
|
});
|
|
27057
27352
|
yield* Console.log(output);
|
|
27058
27353
|
}));
|
|
27059
|
-
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$
|
|
27354
|
+
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$68(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
|
|
27060
27355
|
return yield* Effect.gen(function* () {
|
|
27061
27356
|
const snapshot = yield* getOfflineSnapshot();
|
|
27062
27357
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
@@ -27067,7 +27362,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
27067
27362
|
});
|
|
27068
27363
|
yield* Console.log(output);
|
|
27069
27364
|
}).pipe(Effect.provide(offlineRuntimeLayer));
|
|
27070
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$
|
|
27365
|
+
}).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
27366
|
});
|
|
27072
27367
|
const projectAddCommand = Command.make("add", {
|
|
27073
27368
|
...projectLocationFlags,
|
|
@@ -27674,7 +27969,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
|
|
|
27674
27969
|
filePath: error.filePath,
|
|
27675
27970
|
errorTag: error._tag
|
|
27676
27971
|
}));
|
|
27677
|
-
const make$
|
|
27972
|
+
const make$47 = Effect.gen(function* () {
|
|
27678
27973
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
27679
27974
|
const path = yield* Path.Path;
|
|
27680
27975
|
const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
|
|
@@ -27695,7 +27990,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
27695
27990
|
});
|
|
27696
27991
|
return P4ProjectFileLoader.of({ load });
|
|
27697
27992
|
});
|
|
27698
|
-
const layer$
|
|
27993
|
+
const layer$42 = Layer.effect(P4ProjectFileLoader, make$47);
|
|
27699
27994
|
//#endregion
|
|
27700
27995
|
//#region src/project/ProjectFaviconResolver.ts
|
|
27701
27996
|
/**
|
|
@@ -27766,7 +28061,7 @@ function extractIconHref(source) {
|
|
|
27766
28061
|
return null;
|
|
27767
28062
|
}
|
|
27768
28063
|
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$
|
|
28064
|
+
const make$46 = Effect.gen(function* () {
|
|
27770
28065
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
27771
28066
|
const path = yield* Path.Path;
|
|
27772
28067
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -27835,7 +28130,7 @@ const make$45 = Effect.gen(function* () {
|
|
|
27835
28130
|
});
|
|
27836
28131
|
return ProjectFaviconResolver.of({ resolvePath });
|
|
27837
28132
|
});
|
|
27838
|
-
const layer$
|
|
28133
|
+
const layer$41 = Layer.effect(ProjectFaviconResolver, make$46);
|
|
27839
28134
|
//#endregion
|
|
27840
28135
|
//#region src/assets/AssetAccess.ts
|
|
27841
28136
|
const ASSET_ROUTE_PREFIX = "/api/assets";
|
|
@@ -28088,10 +28383,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
28088
28383
|
//#endregion
|
|
28089
28384
|
//#region src/observability/BrowserTraceCollector.ts
|
|
28090
28385
|
var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
|
|
28091
|
-
const make$
|
|
28386
|
+
const make$45 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
|
|
28092
28387
|
for (const record of records) sink.push(record);
|
|
28093
28388
|
}) });
|
|
28094
|
-
const layer$
|
|
28389
|
+
const layer$40 = (sink) => Layer.succeed(BrowserTraceCollector, make$45(sink));
|
|
28095
28390
|
//#endregion
|
|
28096
28391
|
//#region src/auth/http.ts
|
|
28097
28392
|
const CREDENTIAL_RESPONSE_HEADERS = {
|
|
@@ -30305,7 +30600,7 @@ const classifyNonZeroExit = (command, stderr) => {
|
|
|
30305
30600
|
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
30601
|
return "command-failed";
|
|
30307
30602
|
};
|
|
30308
|
-
const make$
|
|
30603
|
+
const make$44 = Effect.gen(function* () {
|
|
30309
30604
|
const processRunner = yield* ProcessRunner;
|
|
30310
30605
|
const run = Effect.fn("VcsProcess.run")(function* (input) {
|
|
30311
30606
|
const baseError = {
|
|
@@ -30362,7 +30657,7 @@ const make$43 = Effect.gen(function* () {
|
|
|
30362
30657
|
});
|
|
30363
30658
|
return VcsProcess.of({ run });
|
|
30364
30659
|
});
|
|
30365
|
-
const layer$
|
|
30660
|
+
const layer$39 = Layer.effect(VcsProcess, make$44).pipe(Layer.provide(layer$53));
|
|
30366
30661
|
//#endregion
|
|
30367
30662
|
//#region src/vcs/VcsDriver.ts
|
|
30368
30663
|
var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
|
|
@@ -30813,12 +31108,12 @@ const makeVcsDriver = Effect.gen(function* () {
|
|
|
30813
31108
|
const driver = yield* makeVcsDriverShape();
|
|
30814
31109
|
return VcsDriver.of(driver);
|
|
30815
31110
|
});
|
|
30816
|
-
const make$
|
|
31111
|
+
const make$43 = Effect.gen(function* () {
|
|
30817
31112
|
const git = yield* makeGitVcsDriverCore();
|
|
30818
31113
|
return GitVcsDriver.of(git);
|
|
30819
31114
|
});
|
|
30820
31115
|
Layer.effect(VcsDriver, makeVcsDriver);
|
|
30821
|
-
const layer$
|
|
31116
|
+
const layer$38 = Layer.effect(GitVcsDriver, make$43);
|
|
30822
31117
|
//#endregion
|
|
30823
31118
|
//#region src/vcs/VcsProjectConfig.ts
|
|
30824
31119
|
const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
|
|
@@ -30850,7 +31145,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
|
|
|
30850
31145
|
configPath: error.configPath,
|
|
30851
31146
|
errorTag: error._tag
|
|
30852
31147
|
}));
|
|
30853
|
-
const make$
|
|
31148
|
+
const make$42 = Effect.gen(function* () {
|
|
30854
31149
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
30855
31150
|
const path = yield* Path.Path;
|
|
30856
31151
|
const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
|
|
@@ -30891,7 +31186,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
30891
31186
|
});
|
|
30892
31187
|
return VcsProjectConfig.of({ resolveKind });
|
|
30893
31188
|
});
|
|
30894
|
-
const layer$
|
|
31189
|
+
const layer$37 = Layer.effect(VcsProjectConfig, make$42);
|
|
30895
31190
|
//#endregion
|
|
30896
31191
|
//#region src/vcs/VcsDriverRegistry.ts
|
|
30897
31192
|
const DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -30911,7 +31206,7 @@ function parseDetectionCacheKey(key) {
|
|
|
30911
31206
|
cwd: key.slice(separatorIndex + 1)
|
|
30912
31207
|
};
|
|
30913
31208
|
}
|
|
30914
|
-
const make$
|
|
31209
|
+
const make$41 = Effect.gen(function* () {
|
|
30915
31210
|
const projectConfig = yield* VcsProjectConfig;
|
|
30916
31211
|
const git = yield* makeVcsDriver;
|
|
30917
31212
|
const drivers = { git };
|
|
@@ -30968,7 +31263,7 @@ const make$40 = Effect.gen(function* () {
|
|
|
30968
31263
|
resolve
|
|
30969
31264
|
});
|
|
30970
31265
|
});
|
|
30971
|
-
const layer$
|
|
31266
|
+
const layer$36 = Layer.effect(VcsDriverRegistry, make$41).pipe(Layer.provide(layer$37));
|
|
30972
31267
|
//#endregion
|
|
30973
31268
|
//#region src/checkpointing/CheckpointStore.ts
|
|
30974
31269
|
/**
|
|
@@ -30988,7 +31283,7 @@ const layer$35 = Layer.effect(VcsDriverRegistry, make$40).pipe(Layer.provide(lay
|
|
|
30988
31283
|
*/
|
|
30989
31284
|
/** Service tag for checkpoint persistence and restore operations. */
|
|
30990
31285
|
var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
|
|
30991
|
-
const make$
|
|
31286
|
+
const make$40 = Effect.gen(function* () {
|
|
30992
31287
|
const vcsRegistry = yield* VcsDriverRegistry;
|
|
30993
31288
|
const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
|
|
30994
31289
|
const handle = yield* vcsRegistry.resolve({ cwd });
|
|
@@ -31027,7 +31322,7 @@ const make$39 = Effect.gen(function* () {
|
|
|
31027
31322
|
deleteCheckpointRefs
|
|
31028
31323
|
});
|
|
31029
31324
|
});
|
|
31030
|
-
const layer$
|
|
31325
|
+
const layer$35 = Layer.effect(CheckpointStore, make$40);
|
|
31031
31326
|
//#endregion
|
|
31032
31327
|
//#region src/checkpointing/CheckpointDiffQuery.ts
|
|
31033
31328
|
/**
|
|
@@ -31049,7 +31344,7 @@ function buildTurnDiffResult(input, diff) {
|
|
|
31049
31344
|
diff
|
|
31050
31345
|
};
|
|
31051
31346
|
}
|
|
31052
|
-
const make$
|
|
31347
|
+
const make$39 = Effect.gen(function* () {
|
|
31053
31348
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
31054
31349
|
const checkpointStore = yield* CheckpointStore;
|
|
31055
31350
|
const getTurnDiff = Effect.fn("getTurnDiff")(function* (input) {
|
|
@@ -31185,7 +31480,7 @@ const make$38 = Effect.gen(function* () {
|
|
|
31185
31480
|
getFullThreadDiff
|
|
31186
31481
|
});
|
|
31187
31482
|
});
|
|
31188
|
-
const layer$
|
|
31483
|
+
const layer$34 = Layer.effect(CheckpointDiffQuery, make$39);
|
|
31189
31484
|
//#endregion
|
|
31190
31485
|
//#region src/orchestration/ActivityPayloadProjection.ts
|
|
31191
31486
|
function asRecord$1(value) {
|
|
@@ -32038,7 +32333,7 @@ function makeUpdateState(input) {
|
|
|
32038
32333
|
output: input.output ?? null
|
|
32039
32334
|
};
|
|
32040
32335
|
}
|
|
32041
|
-
const make$
|
|
32336
|
+
const make$38 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
32042
32337
|
const providerRegistry = yield* ProviderRegistry;
|
|
32043
32338
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
32044
32339
|
const httpClient = yield* HttpClient.HttpClient;
|
|
@@ -32153,7 +32448,7 @@ const make$37 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
|
32153
32448
|
});
|
|
32154
32449
|
return ProviderMaintenanceRunner.of({ updateProvider });
|
|
32155
32450
|
});
|
|
32156
|
-
const layer$
|
|
32451
|
+
const layer$33 = Layer.effect(ProviderMaintenanceRunner, make$38());
|
|
32157
32452
|
//#endregion
|
|
32158
32453
|
//#region src/provider/Services/ProviderInstanceRegistry.ts
|
|
32159
32454
|
var ProviderInstanceRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderInstanceRegistry") {};
|
|
@@ -32177,11 +32472,228 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
|
|
|
32177
32472
|
detail: "This provider does not report account usage."
|
|
32178
32473
|
}))))
|
|
32179
32474
|
});
|
|
32180
|
-
const make$
|
|
32475
|
+
const make$37 = Effect.gen(function* () {
|
|
32181
32476
|
const registry = yield* ProviderInstanceRegistry;
|
|
32182
32477
|
return makeTextGenerationFromRegistry(registry);
|
|
32183
32478
|
});
|
|
32184
|
-
const layer$
|
|
32479
|
+
const layer$32 = Layer.effect(TextGeneration, make$37);
|
|
32480
|
+
const SKILL_MANIFEST_FILENAME = "SKILL.md";
|
|
32481
|
+
/**
|
|
32482
|
+
* Split a catalogue id (`owner/repo/skill-name`) into its parts.
|
|
32483
|
+
*
|
|
32484
|
+
* The skill segment is everything after the repository, because a nested skill
|
|
32485
|
+
* id contains slashes and rejoining the tail is the only reading that survives
|
|
32486
|
+
* one.
|
|
32487
|
+
*/
|
|
32488
|
+
function parseRegistrySkillId(id) {
|
|
32489
|
+
const segments = id.split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
32490
|
+
if (segments.length < 3) return null;
|
|
32491
|
+
const [owner, repo, ...rest] = segments;
|
|
32492
|
+
if (!owner || !repo || rest.length === 0) return null;
|
|
32493
|
+
return {
|
|
32494
|
+
owner,
|
|
32495
|
+
repo,
|
|
32496
|
+
skillId: rest.join("/")
|
|
32497
|
+
};
|
|
32498
|
+
}
|
|
32499
|
+
/**
|
|
32500
|
+
* Where the skill lives in the repository, from the repository's file list.
|
|
32501
|
+
*
|
|
32502
|
+
* Matched on `<...>/<skillId>/SKILL.md` rather than on any fixed layout,
|
|
32503
|
+
* because repositories disagree: some keep skills at the root, some under
|
|
32504
|
+
* `skills/`, some several levels down inside a plugin. The shallowest match
|
|
32505
|
+
* wins, which is what picks the skill itself over a copy vendored inside an
|
|
32506
|
+
* example or a test fixture.
|
|
32507
|
+
*/
|
|
32508
|
+
function chooseSkillRoot(entries, skillId) {
|
|
32509
|
+
const leaf = skillId.split("/").pop() ?? skillId;
|
|
32510
|
+
const candidates = [];
|
|
32511
|
+
for (const entry of entries) {
|
|
32512
|
+
if (entry.type !== "blob" || !entry.path.endsWith(`/SKILL.md`)) {
|
|
32513
|
+
if (entry.type === "blob" && entry.path === "SKILL.md") candidates.push("");
|
|
32514
|
+
continue;
|
|
32515
|
+
}
|
|
32516
|
+
const root = entry.path.slice(0, -9);
|
|
32517
|
+
if ((root.split("/").pop() ?? root) === leaf || root === skillId || root.endsWith(`/${skillId}`)) candidates.push(root);
|
|
32518
|
+
}
|
|
32519
|
+
if (candidates.length === 0) return null;
|
|
32520
|
+
candidates.sort((left, right) => {
|
|
32521
|
+
const depth = left.split("/").length - right.split("/").length;
|
|
32522
|
+
return depth === 0 ? left.localeCompare(right) : depth;
|
|
32523
|
+
});
|
|
32524
|
+
return candidates[0] ?? null;
|
|
32525
|
+
}
|
|
32526
|
+
/**
|
|
32527
|
+
* The files under a skill root, bounded and with the manifest first.
|
|
32528
|
+
*
|
|
32529
|
+
* `SKILL.md` leads because it is the one file that must arrive: everything
|
|
32530
|
+
* downstream — the local create refusal, the panel preview, discovery — keys on
|
|
32531
|
+
* it, so if a bound is going to drop something it must not be that.
|
|
32532
|
+
*/
|
|
32533
|
+
function selectSkillFiles(entries, root) {
|
|
32534
|
+
const prefix = root === "" ? "" : `${root}/`;
|
|
32535
|
+
const manifestPath = `${prefix}${SKILL_MANIFEST_FILENAME}`;
|
|
32536
|
+
const inRoot = entries.filter((entry) => entry.type === "blob" && entry.path.startsWith(prefix) && entry.path !== `${prefix}`);
|
|
32537
|
+
const ordered = [...inRoot.filter((entry) => entry.path === manifestPath), ...inRoot.filter((entry) => entry.path !== manifestPath).sort((left, right) => left.path.localeCompare(right.path))];
|
|
32538
|
+
const paths = [];
|
|
32539
|
+
const skipped = [];
|
|
32540
|
+
let totalBytes = 0;
|
|
32541
|
+
for (const entry of ordered) {
|
|
32542
|
+
if (entry.size !== void 0 && entry.size > 262144) {
|
|
32543
|
+
skipped.push({
|
|
32544
|
+
path: entry.path,
|
|
32545
|
+
reason: "too-large"
|
|
32546
|
+
});
|
|
32547
|
+
continue;
|
|
32548
|
+
}
|
|
32549
|
+
if (paths.length >= 40) {
|
|
32550
|
+
skipped.push({
|
|
32551
|
+
path: entry.path,
|
|
32552
|
+
reason: "too-many-files"
|
|
32553
|
+
});
|
|
32554
|
+
continue;
|
|
32555
|
+
}
|
|
32556
|
+
const size = entry.size ?? 0;
|
|
32557
|
+
if (totalBytes + size > 1048576) {
|
|
32558
|
+
skipped.push({
|
|
32559
|
+
path: entry.path,
|
|
32560
|
+
reason: "over-total-size"
|
|
32561
|
+
});
|
|
32562
|
+
continue;
|
|
32563
|
+
}
|
|
32564
|
+
totalBytes += size;
|
|
32565
|
+
paths.push(entry.path);
|
|
32566
|
+
}
|
|
32567
|
+
return {
|
|
32568
|
+
paths,
|
|
32569
|
+
skipped
|
|
32570
|
+
};
|
|
32571
|
+
}
|
|
32572
|
+
/**
|
|
32573
|
+
* The asset-relative path of a repository file, for writing on disk.
|
|
32574
|
+
*
|
|
32575
|
+
* A skill asset's files are named relative to its own directory, so the
|
|
32576
|
+
* repository prefix comes off here rather than at the call site — the sync's
|
|
32577
|
+
* file shape and the registry's are the same shape, and only this line knows
|
|
32578
|
+
* why they differ.
|
|
32579
|
+
*/
|
|
32580
|
+
function toAssetFilePath(repositoryPath, root) {
|
|
32581
|
+
return root === "" ? repositoryPath : repositoryPath.slice(root.length + 1);
|
|
32582
|
+
}
|
|
32583
|
+
//#endregion
|
|
32584
|
+
//#region src/skills/SkillRegistry.ts
|
|
32585
|
+
const REGISTRY_SEARCH_URL = "https://www.skills.sh/api/search";
|
|
32586
|
+
const GITHUB_API_URL = "https://api.github.com";
|
|
32587
|
+
const GITHUB_RAW_URL = "https://raw.githubusercontent.com";
|
|
32588
|
+
const REQUEST_TIMEOUT_MS = 15e3;
|
|
32589
|
+
/** More than a person reads, few enough that the panel is a list and not a feed. */
|
|
32590
|
+
const MAX_SEARCH_RESULTS = 25;
|
|
32591
|
+
/**
|
|
32592
|
+
* The catalogue's search response, decoded loosely on purpose.
|
|
32593
|
+
*
|
|
32594
|
+
* Only the four fields we display are required. This is an undocumented public
|
|
32595
|
+
* endpoint on someone else's service; a field appearing or disappearing beside
|
|
32596
|
+
* these should not turn search into an error.
|
|
32597
|
+
*/
|
|
32598
|
+
const SearchResponse = Schema$1.Struct({ skills: Schema$1.Array(Schema$1.Struct({
|
|
32599
|
+
id: Schema$1.String,
|
|
32600
|
+
name: Schema$1.String,
|
|
32601
|
+
source: Schema$1.String,
|
|
32602
|
+
installs: Schema$1.optional(Schema$1.Number)
|
|
32603
|
+
})) });
|
|
32604
|
+
const decodeSearchResponse = Schema$1.decodeUnknownEffect(SearchResponse);
|
|
32605
|
+
const TreeResponse = Schema$1.Struct({
|
|
32606
|
+
tree: Schema$1.Array(Schema$1.Struct({
|
|
32607
|
+
path: Schema$1.String,
|
|
32608
|
+
type: Schema$1.String,
|
|
32609
|
+
size: Schema$1.optional(Schema$1.Number)
|
|
32610
|
+
})),
|
|
32611
|
+
truncated: Schema$1.optional(Schema$1.Boolean)
|
|
32612
|
+
});
|
|
32613
|
+
const decodeTreeResponse = Schema$1.decodeUnknownEffect(TreeResponse);
|
|
32614
|
+
var SkillRegistry = class extends Context.Service()("@p4code/cli/skills/SkillRegistry") {};
|
|
32615
|
+
const emptyFetch = (id, unavailable) => ({
|
|
32616
|
+
found: false,
|
|
32617
|
+
id,
|
|
32618
|
+
name: "",
|
|
32619
|
+
source: "",
|
|
32620
|
+
sourceUrl: "",
|
|
32621
|
+
files: [],
|
|
32622
|
+
skipped: [],
|
|
32623
|
+
unavailable
|
|
32624
|
+
});
|
|
32625
|
+
const make$36 = Effect.gen(function* () {
|
|
32626
|
+
const http = yield* HttpClient.HttpClient;
|
|
32627
|
+
const request = Effect.fn("SkillRegistry.request")(function* (url) {
|
|
32628
|
+
return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS));
|
|
32629
|
+
});
|
|
32630
|
+
const search = (query) => Effect.gen(function* () {
|
|
32631
|
+
const response = yield* request(`${REGISTRY_SEARCH_URL}?q=${encodeURIComponent(query)}`).pipe(Effect.orElseSucceed(() => null));
|
|
32632
|
+
if (response === null) return {
|
|
32633
|
+
results: [],
|
|
32634
|
+
unavailable: "The skill catalogue could not be reached."
|
|
32635
|
+
};
|
|
32636
|
+
if (response.status !== 200) return {
|
|
32637
|
+
results: [],
|
|
32638
|
+
unavailable: `The skill catalogue answered ${response.status}.`
|
|
32639
|
+
};
|
|
32640
|
+
const body = yield* response.json.pipe(Effect.flatMap(decodeSearchResponse), Effect.orElseSucceed(() => null));
|
|
32641
|
+
if (body === null) return {
|
|
32642
|
+
results: [],
|
|
32643
|
+
unavailable: "The skill catalogue answered something unreadable."
|
|
32644
|
+
};
|
|
32645
|
+
return {
|
|
32646
|
+
results: body.skills.slice(0, MAX_SEARCH_RESULTS).map((skill) => ({
|
|
32647
|
+
id: skill.id,
|
|
32648
|
+
name: skill.name,
|
|
32649
|
+
source: skill.source,
|
|
32650
|
+
installs: Math.trunc(skill.installs ?? 0)
|
|
32651
|
+
})),
|
|
32652
|
+
unavailable: null
|
|
32653
|
+
};
|
|
32654
|
+
});
|
|
32655
|
+
const fetch = (id) => Effect.gen(function* () {
|
|
32656
|
+
const ref = parseRegistrySkillId(id);
|
|
32657
|
+
if (ref === null) return emptyFetch(id, "Expected owner/repo/skill-name.");
|
|
32658
|
+
const repository = `${ref.owner}/${ref.repo}`;
|
|
32659
|
+
const treeResponse = yield* request(`${GITHUB_API_URL}/repos/${repository}/git/trees/HEAD?recursive=1`).pipe(Effect.orElseSucceed(() => null));
|
|
32660
|
+
if (treeResponse === null) return emptyFetch(id, `${repository} could not be reached.`);
|
|
32661
|
+
if (treeResponse.status === 403 || treeResponse.status === 429) return emptyFetch(id, "GitHub is rate limiting this machine. Try again later.");
|
|
32662
|
+
if (treeResponse.status !== 200) return emptyFetch(id, `GitHub answered ${treeResponse.status} for ${repository}.`);
|
|
32663
|
+
const tree = yield* treeResponse.json.pipe(Effect.flatMap(decodeTreeResponse), Effect.orElseSucceed(() => null));
|
|
32664
|
+
if (tree === null) return emptyFetch(id, `GitHub answered something unreadable for ${repository}.`);
|
|
32665
|
+
const entries = tree.tree;
|
|
32666
|
+
const root = chooseSkillRoot(entries, ref.skillId);
|
|
32667
|
+
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.`);
|
|
32668
|
+
const selection = selectSkillFiles(entries, root);
|
|
32669
|
+
const files = [];
|
|
32670
|
+
for (const path of selection.paths) {
|
|
32671
|
+
const fileResponse = yield* request(`${GITHUB_RAW_URL}/${repository}/HEAD/${path.split("/").map(encodeURIComponent).join("/")}`).pipe(Effect.orElseSucceed(() => null));
|
|
32672
|
+
if (fileResponse === null || fileResponse.status !== 200) return emptyFetch(id, `${path} could not be downloaded.`);
|
|
32673
|
+
const content = yield* fileResponse.text.pipe(Effect.orElseSucceed(() => null));
|
|
32674
|
+
if (content === null) return emptyFetch(id, `${path} is not text, so this skill cannot be installed here.`);
|
|
32675
|
+
files.push({
|
|
32676
|
+
path: toAssetFilePath(path, root),
|
|
32677
|
+
content
|
|
32678
|
+
});
|
|
32679
|
+
}
|
|
32680
|
+
return {
|
|
32681
|
+
found: true,
|
|
32682
|
+
id,
|
|
32683
|
+
name: root === "" ? ref.repo : root.split("/").pop() ?? ref.skillId,
|
|
32684
|
+
source: repository,
|
|
32685
|
+
sourceUrl: root === "" ? `https://github.com/${repository}` : `https://github.com/${repository}/tree/HEAD/${root}`,
|
|
32686
|
+
files,
|
|
32687
|
+
skipped: selection.skipped,
|
|
32688
|
+
unavailable: null
|
|
32689
|
+
};
|
|
32690
|
+
});
|
|
32691
|
+
return {
|
|
32692
|
+
search,
|
|
32693
|
+
fetch
|
|
32694
|
+
};
|
|
32695
|
+
});
|
|
32696
|
+
const layer$31 = Layer.effect(SkillRegistry, make$36);
|
|
32185
32697
|
//#endregion
|
|
32186
32698
|
//#region ../../packages/shared/src/KeyedCoalescingWorker.ts
|
|
32187
32699
|
const makeKeyedCoalescingWorker = (options) => Effect.gen(function* () {
|
|
@@ -32396,7 +32908,7 @@ const COMMON_DEV_PORTS = Object.freeze([
|
|
|
32396
32908
|
8888,
|
|
32397
32909
|
9e3
|
|
32398
32910
|
]);
|
|
32399
|
-
const POLL_INTERVAL = Duration.seconds(3);
|
|
32911
|
+
const POLL_INTERVAL$1 = Duration.seconds(3);
|
|
32400
32912
|
const LSOF_TIMEOUT_MS = 5e3;
|
|
32401
32913
|
const WINDOWS_LISTENER_TIMEOUT_MS = 5e3;
|
|
32402
32914
|
const terminalOwnerKey = (owner) => `${owner.threadId}\u0000${owner.terminalId}`;
|
|
@@ -32571,7 +33083,7 @@ const make$35 = Effect.gen(function* PortDiscoveryMake() {
|
|
|
32571
33083
|
lastSnapshot: next
|
|
32572
33084
|
}])) yield* broadcast(next);
|
|
32573
33085
|
}, Effect.catchCause((cause) => Effect.logWarning("preview port scan failed", Cause.pretty(cause))));
|
|
32574
|
-
yield* Effect.forkScoped(pollTick().pipe(Effect.repeat(Schedule.spaced(POLL_INTERVAL))));
|
|
33086
|
+
yield* Effect.forkScoped(pollTick().pipe(Effect.repeat(Schedule.spaced(POLL_INTERVAL$1))));
|
|
32575
33087
|
const acquireRetention = Effect.fn("PortDiscovery.retain")(function* () {
|
|
32576
33088
|
if (yield* Ref.modify(stateRef, (state) => [state.retainCount === 0, {
|
|
32577
33089
|
...state,
|
|
@@ -34271,7 +34783,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
|
|
|
34271
34783
|
subscribeMetadata
|
|
34272
34784
|
});
|
|
34273
34785
|
});
|
|
34274
|
-
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$
|
|
34786
|
+
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$53));
|
|
34275
34787
|
//#endregion
|
|
34276
34788
|
//#region src/mcp/McpInvocationContext.ts
|
|
34277
34789
|
var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
|
|
@@ -41454,6 +41966,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
41454
41966
|
const hubLink = yield* HubLink;
|
|
41455
41967
|
const assetSync = yield* AssetSync;
|
|
41456
41968
|
const mcpRegistry = yield* McpRegistry;
|
|
41969
|
+
const skillRegistry = yield* SkillRegistry;
|
|
41457
41970
|
const startup = yield* ServerRuntimeStartup;
|
|
41458
41971
|
const workspaceEntries = yield* WorkspaceEntries;
|
|
41459
41972
|
const workspaceFileSystem = yield* WorkspaceFileSystem;
|
|
@@ -42038,6 +42551,8 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
42038
42551
|
status: yield* assetSync.status
|
|
42039
42552
|
};
|
|
42040
42553
|
}), { "rpc.aggregate": "skills" }),
|
|
42554
|
+
[WS_METHODS.skillRegistrySearch]: ({ query }) => observeRpcEffect$1(WS_METHODS.skillRegistrySearch, skillRegistry.search(query), { "rpc.aggregate": "skills" }),
|
|
42555
|
+
[WS_METHODS.skillRegistryFetch]: ({ id }) => observeRpcEffect$1(WS_METHODS.skillRegistryFetch, skillRegistry.fetch(id), { "rpc.aggregate": "skills" }),
|
|
42041
42556
|
[WS_METHODS.mcpList]: (_input) => observeRpcEffect$1(WS_METHODS.mcpList, mcpRegistry.list.pipe(Effect.map((servers) => ({ servers }))), { "rpc.aggregate": "mcp" }),
|
|
42042
42557
|
[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
42558
|
[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 +42734,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
42219
42734
|
const serverAuth = yield* EnvironmentAuth;
|
|
42220
42735
|
const sessions = yield* SessionStore;
|
|
42221
42736
|
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$
|
|
42737
|
+
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
42738
|
return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
|
|
42224
42739
|
}).pipe(Effect.catchTags({
|
|
42225
42740
|
EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
|
|
@@ -42227,6 +42742,281 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
42227
42742
|
})));
|
|
42228
42743
|
}));
|
|
42229
42744
|
//#endregion
|
|
42745
|
+
//#region src/persistence/Layers/RemoteTasks.ts
|
|
42746
|
+
/**
|
|
42747
|
+
* The board, kept on the hub instead of in this machine's database.
|
|
42748
|
+
*
|
|
42749
|
+
* A drop-in `TaskRepository`: same interface, same events, so the MCP toolkit,
|
|
42750
|
+
* the websocket RPCs and the board itself are unchanged and do not know which
|
|
42751
|
+
* one they are talking to. That was the point of making it an interface.
|
|
42752
|
+
*
|
|
42753
|
+
* **An unreachable hub fails loudly, by decision.** There is no local fallback
|
|
42754
|
+
* and no write queue. A server that answered from a local copy while the hub
|
|
42755
|
+
* was down would recreate exactly the divergence the hub exists to remove —
|
|
42756
|
+
* two Macs with two boards, silently — and the failure would be invisible until
|
|
42757
|
+
* someone noticed a task missing on the other machine. So a hub that cannot be
|
|
42758
|
+
* reached means the board says so and nothing is written. The cost is real and
|
|
42759
|
+
* is the point: no board while the hub is down.
|
|
42760
|
+
*
|
|
42761
|
+
* **Changes are polled, because the hub has no push.** The interface promises
|
|
42762
|
+
* a change stream, and the honest implementation of that against a plain HTTP
|
|
42763
|
+
* API is a poll with a diff. A write made through *this* server publishes
|
|
42764
|
+
* immediately, so the local board is live; the poll is what carries the other
|
|
42765
|
+
* machine's writes, at up to `POLL_INTERVAL` of lag.
|
|
42766
|
+
*
|
|
42767
|
+
* @module persistence/Layers/RemoteTasks
|
|
42768
|
+
*/
|
|
42769
|
+
const HUB_REQUEST_TIMEOUT_MS = 15e3;
|
|
42770
|
+
/**
|
|
42771
|
+
* How stale another machine's write may look here.
|
|
42772
|
+
*
|
|
42773
|
+
* Short enough that a board left open follows along, long enough that two
|
|
42774
|
+
* servers idling all day are not a steady stream of requests at a hosted
|
|
42775
|
+
* service. Only changes made elsewhere wait for it.
|
|
42776
|
+
*/
|
|
42777
|
+
const POLL_INTERVAL = Duration.seconds(10);
|
|
42778
|
+
const TaskListPage = Schema$1.Struct({ tasks: Schema$1.Array(Task) });
|
|
42779
|
+
const ConflictBody = Schema$1.Struct({ current: Task });
|
|
42780
|
+
const decodeTaskListPage = Schema$1.decodeUnknownEffect(TaskListPage);
|
|
42781
|
+
const decodeTask = Schema$1.decodeUnknownEffect(Task);
|
|
42782
|
+
const decodeConflictBody = Schema$1.decodeUnknownEffect(ConflictBody);
|
|
42783
|
+
/**
|
|
42784
|
+
* Every failure here is reported as the interface's own error type.
|
|
42785
|
+
*
|
|
42786
|
+
* `PersistenceSqlError` names a store that would not answer, which is exactly
|
|
42787
|
+
* what this is from a caller's point of view — the detail says the store is the
|
|
42788
|
+
* hub. Inventing a second error type would mean touching every call site to
|
|
42789
|
+
* handle a case they already handle.
|
|
42790
|
+
*/
|
|
42791
|
+
const hubUnavailable = (operation, detail) => new PersistenceSqlError({
|
|
42792
|
+
operation: `RemoteTaskRepository.${operation}`,
|
|
42793
|
+
detail: `The hub board is unavailable: ${detail}`,
|
|
42794
|
+
cause: null
|
|
42795
|
+
});
|
|
42796
|
+
/**
|
|
42797
|
+
* @param isActive Whether this server is currently reading its board from the
|
|
42798
|
+
* hub. The poll asks before every pass rather than being started once: a
|
|
42799
|
+
* machine with the board set to `local` must not be sending a request to a
|
|
42800
|
+
* hosted service every ten seconds for a board nobody is reading, and the
|
|
42801
|
+
* setting can change while the server runs.
|
|
42802
|
+
*/
|
|
42803
|
+
const makeRemoteTaskRepository = Effect.fn("makeRemoteTaskRepository")(function* (isActive) {
|
|
42804
|
+
const http = yield* HttpClient.HttpClient;
|
|
42805
|
+
const link = yield* HubLink;
|
|
42806
|
+
const changes = yield* PubSub.unbounded();
|
|
42807
|
+
const publish = (event) => PubSub.publish(changes, event).pipe(Effect.asVoid);
|
|
42808
|
+
/** The board as of the last poll, for diffing the next one against. */
|
|
42809
|
+
const lastSeen = yield* Ref.make(null);
|
|
42810
|
+
const requireSettings = (operation) => Effect.gen(function* () {
|
|
42811
|
+
const state = yield* link.current;
|
|
42812
|
+
if (Option.isNone(state.settings)) return yield* hubUnavailable(operation, "no hub is configured on this server");
|
|
42813
|
+
return state.settings.value;
|
|
42814
|
+
});
|
|
42815
|
+
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"}`)));
|
|
42816
|
+
const list = (filter) => Effect.gen(function* () {
|
|
42817
|
+
const settings = yield* requireSettings("list");
|
|
42818
|
+
const query = new URLSearchParams();
|
|
42819
|
+
for (const key of [
|
|
42820
|
+
"projectId",
|
|
42821
|
+
"repositoryKey",
|
|
42822
|
+
"threadId",
|
|
42823
|
+
"status",
|
|
42824
|
+
"assignee"
|
|
42825
|
+
]) {
|
|
42826
|
+
const value = filter[key];
|
|
42827
|
+
if (value !== void 0) query.set(key, value);
|
|
42828
|
+
}
|
|
42829
|
+
const suffix = query.size === 0 ? "" : `?${query.toString()}`;
|
|
42830
|
+
const response = yield* send("list", settings, HttpClientRequest.get(`${settings.baseUrl}/tasks${suffix}`));
|
|
42831
|
+
if (response.status !== 200) return yield* hubUnavailable("list", `status ${response.status}`);
|
|
42832
|
+
return (yield* response.json.pipe(Effect.flatMap(decodeTaskListPage), Effect.mapError(() => hubUnavailable("list", "the response did not match the contract")))).tasks;
|
|
42833
|
+
});
|
|
42834
|
+
const getById = ({ taskId }) => Effect.gen(function* () {
|
|
42835
|
+
const settings = yield* requireSettings("getById");
|
|
42836
|
+
const response = yield* send("getById", settings, HttpClientRequest.get(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`));
|
|
42837
|
+
if (response.status === 404) return Option.none();
|
|
42838
|
+
if (response.status !== 200) return yield* hubUnavailable("getById", `status ${response.status}`);
|
|
42839
|
+
return Option.some(yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("getById", "the response did not match the contract"))));
|
|
42840
|
+
});
|
|
42841
|
+
/**
|
|
42842
|
+
* Upsert is a create here, and that is a real difference from the local
|
|
42843
|
+
* store.
|
|
42844
|
+
*
|
|
42845
|
+
* The hub mints its own ids and timestamps, so a row written through this
|
|
42846
|
+
* comes back with the hub's version of both. The caller's `taskId` is not
|
|
42847
|
+
* carried: honouring it would need a hub route that takes one, and inventing
|
|
42848
|
+
* that quietly would let two servers mint colliding ids.
|
|
42849
|
+
*/
|
|
42850
|
+
const upsert = (row) => Effect.gen(function* () {
|
|
42851
|
+
const settings = yield* requireSettings("upsert");
|
|
42852
|
+
const response = yield* send("upsert", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.post(`${settings.baseUrl}/tasks`), {
|
|
42853
|
+
...row.projectId === null ? {} : { projectId: row.projectId },
|
|
42854
|
+
...row.repositoryKey === null ? {} : { repositoryKey: row.repositoryKey },
|
|
42855
|
+
...row.threadId === null ? {} : { threadId: row.threadId },
|
|
42856
|
+
title: row.title,
|
|
42857
|
+
body: row.body,
|
|
42858
|
+
status: row.status,
|
|
42859
|
+
priority: row.priority,
|
|
42860
|
+
...row.assignee === null ? {} : { assignee: row.assignee },
|
|
42861
|
+
labels: row.labels
|
|
42862
|
+
}));
|
|
42863
|
+
if (response.status !== 201 && response.status !== 200) return yield* hubUnavailable("upsert", `status ${response.status}`);
|
|
42864
|
+
const created = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("upsert", "the response did not match the contract")));
|
|
42865
|
+
yield* publish({
|
|
42866
|
+
type: "upserted",
|
|
42867
|
+
task: created
|
|
42868
|
+
});
|
|
42869
|
+
});
|
|
42870
|
+
const patch = (input) => Effect.gen(function* () {
|
|
42871
|
+
const settings = yield* requireSettings("patch");
|
|
42872
|
+
const { taskId, ...fields } = input;
|
|
42873
|
+
const response = yield* send("patch", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.patch(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`), fields));
|
|
42874
|
+
if (response.status === 404) return Option.none();
|
|
42875
|
+
if (response.status !== 200) return yield* hubUnavailable("patch", `status ${response.status}`);
|
|
42876
|
+
const updated = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("patch", "the response did not match the contract")));
|
|
42877
|
+
yield* publish({
|
|
42878
|
+
type: "upserted",
|
|
42879
|
+
task: updated
|
|
42880
|
+
});
|
|
42881
|
+
return Option.some(updated);
|
|
42882
|
+
});
|
|
42883
|
+
const patchIfStatus = (input) => Effect.gen(function* () {
|
|
42884
|
+
const settings = yield* requireSettings("patchIfStatus");
|
|
42885
|
+
const { taskId, ...fields } = input.patch;
|
|
42886
|
+
const response = yield* send("patchIfStatus", settings, HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.patch(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`), {
|
|
42887
|
+
...fields,
|
|
42888
|
+
expectedStatus: input.expectedStatus
|
|
42889
|
+
}));
|
|
42890
|
+
if (response.status === 404) return { outcome: "missing" };
|
|
42891
|
+
if (response.status === 409) return {
|
|
42892
|
+
outcome: "conflict",
|
|
42893
|
+
current: (yield* response.json.pipe(Effect.flatMap(decodeConflictBody), Effect.mapError(() => hubUnavailable("patchIfStatus", "the conflict response did not match the contract")))).current
|
|
42894
|
+
};
|
|
42895
|
+
if (response.status !== 200) return yield* hubUnavailable("patchIfStatus", `status ${response.status}`);
|
|
42896
|
+
const updated = yield* response.json.pipe(Effect.flatMap(decodeTask), Effect.mapError(() => hubUnavailable("patchIfStatus", "the response did not match the contract")));
|
|
42897
|
+
yield* publish({
|
|
42898
|
+
type: "upserted",
|
|
42899
|
+
task: updated
|
|
42900
|
+
});
|
|
42901
|
+
return {
|
|
42902
|
+
outcome: "updated",
|
|
42903
|
+
task: updated
|
|
42904
|
+
};
|
|
42905
|
+
});
|
|
42906
|
+
const deleteById = ({ taskId }) => Effect.gen(function* () {
|
|
42907
|
+
const settings = yield* requireSettings("deleteById");
|
|
42908
|
+
const response = yield* send("deleteById", settings, HttpClientRequest.delete(`${settings.baseUrl}/tasks/${encodeURIComponent(taskId)}`));
|
|
42909
|
+
if (response.status !== 200 && response.status !== 204 && response.status !== 404) return yield* hubUnavailable("deleteById", `status ${response.status}`);
|
|
42910
|
+
yield* publish({
|
|
42911
|
+
type: "deleted",
|
|
42912
|
+
taskId
|
|
42913
|
+
});
|
|
42914
|
+
});
|
|
42915
|
+
/**
|
|
42916
|
+
* One poll: read the board, publish what differs from last time.
|
|
42917
|
+
*
|
|
42918
|
+
* Compared on `updatedAt` rather than deep equality, because that is the
|
|
42919
|
+
* field every hub write moves and it makes the diff O(n) with no schema
|
|
42920
|
+
* knowledge. A failed poll publishes nothing and leaves the last snapshot in
|
|
42921
|
+
* place — a hub blip should not empty every open board.
|
|
42922
|
+
*/
|
|
42923
|
+
const pollOnce = Effect.gen(function* () {
|
|
42924
|
+
if (!(yield* isActive)) return;
|
|
42925
|
+
const current = yield* list({});
|
|
42926
|
+
const previous = yield* Ref.getAndSet(lastSeen, current);
|
|
42927
|
+
if (previous === null) return;
|
|
42928
|
+
const previousById = new Map(previous.map((task) => [task.taskId, task]));
|
|
42929
|
+
for (const task of current) {
|
|
42930
|
+
const before = previousById.get(task.taskId);
|
|
42931
|
+
if (before === void 0 || before.updatedAt !== task.updatedAt) yield* publish({
|
|
42932
|
+
type: "upserted",
|
|
42933
|
+
task
|
|
42934
|
+
});
|
|
42935
|
+
previousById.delete(task.taskId);
|
|
42936
|
+
}
|
|
42937
|
+
for (const taskId of previousById.keys()) yield* publish({
|
|
42938
|
+
type: "deleted",
|
|
42939
|
+
taskId
|
|
42940
|
+
});
|
|
42941
|
+
}).pipe(Effect.ignoreCause({ log: true }));
|
|
42942
|
+
yield* Effect.forever(pollOnce.pipe(Effect.andThen(Effect.sleep(POLL_INTERVAL)))).pipe(Effect.forkScoped);
|
|
42943
|
+
return {
|
|
42944
|
+
upsert,
|
|
42945
|
+
patch,
|
|
42946
|
+
patchIfStatus,
|
|
42947
|
+
getById,
|
|
42948
|
+
list,
|
|
42949
|
+
deleteById,
|
|
42950
|
+
streamChanges: Stream.fromPubSub(changes),
|
|
42951
|
+
streamWithSnapshot: Stream.unwrap(Effect.gen(function* () {
|
|
42952
|
+
const subscription = yield* PubSub.subscribe(changes);
|
|
42953
|
+
const snapshot = yield* list({});
|
|
42954
|
+
yield* Ref.set(lastSeen, snapshot);
|
|
42955
|
+
return Stream.concat(Stream.succeed({
|
|
42956
|
+
type: "snapshot",
|
|
42957
|
+
tasks: snapshot
|
|
42958
|
+
}), Stream.fromSubscription(subscription));
|
|
42959
|
+
}))
|
|
42960
|
+
};
|
|
42961
|
+
});
|
|
42962
|
+
Layer.effect(TaskRepository, makeRemoteTaskRepository(Effect.succeed(true)));
|
|
42963
|
+
//#endregion
|
|
42964
|
+
//#region src/persistence/Layers/TaskBoardSource.ts
|
|
42965
|
+
/**
|
|
42966
|
+
* Which board a call goes to: this machine's database, or the hub's.
|
|
42967
|
+
*
|
|
42968
|
+
* Both repositories are built, and every call reads the setting and delegates.
|
|
42969
|
+
* That is deliberate rather than picking one at startup: `taskBoardSource` is
|
|
42970
|
+
* an ordinary setting a person changes in a panel, and a setting that only
|
|
42971
|
+
* takes effect after a restart is the same hazard the hub link already
|
|
42972
|
+
* documents — you change it, nothing happens, and there is nothing on screen
|
|
42973
|
+
* saying why.
|
|
42974
|
+
*
|
|
42975
|
+
* **Subscriptions pick their source when they subscribe.** A stream cannot
|
|
42976
|
+
* change its mind mid-flight without inventing a "your board moved" event that
|
|
42977
|
+
* nothing knows how to render, so an open board keeps reading the source it
|
|
42978
|
+
* opened against and picks up the change when it reconnects. Switching is rare;
|
|
42979
|
+
* a wrong row on screen is not worth a new event type.
|
|
42980
|
+
*
|
|
42981
|
+
* @module persistence/Layers/TaskBoardSource
|
|
42982
|
+
*/
|
|
42983
|
+
const makeRoutedTaskRepository = Effect.gen(function* () {
|
|
42984
|
+
const local = yield* makeTaskRepository;
|
|
42985
|
+
const usingHub = (yield* ServerSettingsService).getSettings.pipe(Effect.map((current) => current.taskBoardSource === "hub"), Effect.orElseSucceed(() => false));
|
|
42986
|
+
const remote = yield* makeRemoteTaskRepository(usingHub);
|
|
42987
|
+
/**
|
|
42988
|
+
* `local` on a settings read failure, and that direction is chosen.
|
|
42989
|
+
*
|
|
42990
|
+
* The alternative is refusing every board call because a settings file could
|
|
42991
|
+
* not be read, which turns one broken file into a dead board. Falling back to
|
|
42992
|
+
* the machine's own database is the answer that still works and cannot lose a
|
|
42993
|
+
* hub write, because a write that never reached the hub was never accepted.
|
|
42994
|
+
*/
|
|
42995
|
+
const pick = usingHub.pipe(Effect.map((hub) => hub ? remote : local));
|
|
42996
|
+
return {
|
|
42997
|
+
upsert: (row) => pick.pipe(Effect.flatMap((repository) => repository.upsert(row))),
|
|
42998
|
+
patch: (input, updatedAt) => pick.pipe(Effect.flatMap((repository) => repository.patch(input, updatedAt))),
|
|
42999
|
+
patchIfStatus: (input, updatedAt) => pick.pipe(Effect.flatMap((repository) => repository.patchIfStatus(input, updatedAt))),
|
|
43000
|
+
getById: (input) => pick.pipe(Effect.flatMap((repository) => repository.getById(input))),
|
|
43001
|
+
list: (filter) => pick.pipe(Effect.flatMap((repository) => repository.list(filter))),
|
|
43002
|
+
deleteById: (input) => pick.pipe(Effect.flatMap((repository) => repository.deleteById(input))),
|
|
43003
|
+
get streamChanges() {
|
|
43004
|
+
return Stream.unwrap(pick.pipe(Effect.map((repository) => repository.streamChanges)));
|
|
43005
|
+
},
|
|
43006
|
+
get streamWithSnapshot() {
|
|
43007
|
+
return Stream.unwrap(pick.pipe(Effect.map((repository) => repository.streamWithSnapshot)));
|
|
43008
|
+
}
|
|
43009
|
+
};
|
|
43010
|
+
});
|
|
43011
|
+
/**
|
|
43012
|
+
* The board, wherever it lives.
|
|
43013
|
+
*
|
|
43014
|
+
* Replaces `TaskRepositoryLive` at the one place the route tree provides it, so
|
|
43015
|
+
* the MCP toolkit and the websocket handlers keep sharing a single instance —
|
|
43016
|
+
* which is what makes a task an agent files appear on an open board.
|
|
43017
|
+
*/
|
|
43018
|
+
const RoutedTaskRepositoryLive = Layer.effect(TaskRepository, makeRoutedTaskRepository);
|
|
43019
|
+
//#endregion
|
|
42230
43020
|
//#region src/persistence/ProviderSessionRuntime.ts
|
|
42231
43021
|
/**
|
|
42232
43022
|
* ProviderSessionRuntimeRepository - Repository interface for provider runtime sessions.
|
|
@@ -44246,7 +45036,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
|
|
|
44246
45036
|
};
|
|
44247
45037
|
});
|
|
44248
45038
|
var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
|
|
44249
|
-
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$
|
|
45039
|
+
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$69));
|
|
44250
45040
|
//#endregion
|
|
44251
45041
|
//#region src/textGeneration/TextGenerationUtils.ts
|
|
44252
45042
|
const isTextGenerationError$2 = Schema$1.is(TextGenerationError);
|
|
@@ -45218,7 +46008,7 @@ const runClaudeCommand = Effect.fn("runClaudeCommand")(function* (claudeSettings
|
|
|
45218
46008
|
});
|
|
45219
46009
|
return yield* spawnAndCollect(claudeSettings.binaryPath, command);
|
|
45220
46010
|
});
|
|
45221
|
-
const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(function* (claudeSettings, resolveCapabilities, environment, cwd) {
|
|
46011
|
+
const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(function* (claudeSettings, resolveCapabilities, environment, cwd, disabledSkills) {
|
|
45222
46012
|
const resolvedEnvironment = environment ?? process.env;
|
|
45223
46013
|
const checkedAt = DateTime.formatIso(yield* DateTime.now);
|
|
45224
46014
|
const allModels = providerModelsFromSettings(BUILT_IN_MODELS, claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES);
|
|
@@ -45292,7 +46082,7 @@ const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(functio
|
|
|
45292
46082
|
const models = providerModelsFromSettings(getBuiltInClaudeModelsForVersion(parsedVersion), claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES);
|
|
45293
46083
|
const versionUpgradeMessage = supportsClaudeOpus5(parsedVersion) ? void 0 : supportsClaudeFable5(parsedVersion) ? formatClaudeOpus5UpgradeMessage(parsedVersion) : supportsClaudeOpus48(parsedVersion) ? formatClaudeFable5UpgradeMessage(parsedVersion) : supportsClaudeOpus47(parsedVersion) ? formatClaudeOpus48UpgradeMessage(parsedVersion) : formatClaudeOpus47UpgradeMessage(parsedVersion);
|
|
45294
46084
|
const capabilities = resolveCapabilities ? yield* resolveCapabilities(claudeSettings).pipe(Effect.orElseSucceed(() => void 0)) : void 0;
|
|
45295
|
-
const skills = yield* discoverClaudeSkills(claudeSettings, cwd, resolvedEnvironment);
|
|
46085
|
+
const skills = yield* discoverClaudeSkills(claudeSettings, cwd, resolvedEnvironment, disabledSkills);
|
|
45296
46086
|
const dedupedSlashCommands = dedupeSlashCommands(capabilities?.slashCommands ?? []);
|
|
45297
46087
|
if (!capabilities) return buildServerProvider({
|
|
45298
46088
|
presentation: CLAUDE_PRESENTATION,
|
|
@@ -45693,6 +46483,214 @@ function parseCliArgs(args, options) {
|
|
|
45693
46483
|
};
|
|
45694
46484
|
}
|
|
45695
46485
|
//#endregion
|
|
46486
|
+
//#region ../../packages/shared/src/toolCategory.ts
|
|
46487
|
+
const TOOL_CATEGORY_TITLES = {
|
|
46488
|
+
file_read: "File read",
|
|
46489
|
+
file_search: "File search",
|
|
46490
|
+
file_change: "File change",
|
|
46491
|
+
command: "Command run",
|
|
46492
|
+
mcp_tool: "MCP tool call",
|
|
46493
|
+
subagent: "Subagent task",
|
|
46494
|
+
web_search: "Web search",
|
|
46495
|
+
image_view: "Image view",
|
|
46496
|
+
tool: "Tool call"
|
|
46497
|
+
};
|
|
46498
|
+
/** Exact tool names, lowercased, matched before the substring heuristics below. */
|
|
46499
|
+
const FILE_READ_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
46500
|
+
"read",
|
|
46501
|
+
"readfile",
|
|
46502
|
+
"read_file",
|
|
46503
|
+
"view",
|
|
46504
|
+
"viewfile",
|
|
46505
|
+
"view_file",
|
|
46506
|
+
"notebookread",
|
|
46507
|
+
"notebook_read",
|
|
46508
|
+
"openfile",
|
|
46509
|
+
"open_file"
|
|
46510
|
+
]);
|
|
46511
|
+
const FILE_SEARCH_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
46512
|
+
"grep",
|
|
46513
|
+
"glob",
|
|
46514
|
+
"search",
|
|
46515
|
+
"filesearch",
|
|
46516
|
+
"file_search",
|
|
46517
|
+
"codebasesearch",
|
|
46518
|
+
"codebase_search",
|
|
46519
|
+
"listdir",
|
|
46520
|
+
"list_dir",
|
|
46521
|
+
"list_directory",
|
|
46522
|
+
"ls"
|
|
46523
|
+
]);
|
|
46524
|
+
const FILE_CHANGE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
46525
|
+
"edit",
|
|
46526
|
+
"write",
|
|
46527
|
+
"multiedit",
|
|
46528
|
+
"multi_edit",
|
|
46529
|
+
"notebookedit",
|
|
46530
|
+
"notebook_edit",
|
|
46531
|
+
"applypatch",
|
|
46532
|
+
"apply_patch",
|
|
46533
|
+
"patch",
|
|
46534
|
+
"createfile",
|
|
46535
|
+
"create_file",
|
|
46536
|
+
"strreplace",
|
|
46537
|
+
"str_replace",
|
|
46538
|
+
"deletefile",
|
|
46539
|
+
"delete_file"
|
|
46540
|
+
]);
|
|
46541
|
+
const COMMAND_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
46542
|
+
"bash",
|
|
46543
|
+
"shell",
|
|
46544
|
+
"terminal",
|
|
46545
|
+
"exec",
|
|
46546
|
+
"execute",
|
|
46547
|
+
"execcommand",
|
|
46548
|
+
"exec_command",
|
|
46549
|
+
"runcommand",
|
|
46550
|
+
"run_command",
|
|
46551
|
+
"local_shell"
|
|
46552
|
+
]);
|
|
46553
|
+
const SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
46554
|
+
"task",
|
|
46555
|
+
"agent",
|
|
46556
|
+
"subagent",
|
|
46557
|
+
"sub_agent"
|
|
46558
|
+
]);
|
|
46559
|
+
/** Shell builtins that say nothing about what the command as a whole does. */
|
|
46560
|
+
const NEUTRAL_SHELL_COMMANDS = /* @__PURE__ */ new Set([
|
|
46561
|
+
"cd",
|
|
46562
|
+
"echo",
|
|
46563
|
+
"printf",
|
|
46564
|
+
"pwd",
|
|
46565
|
+
"true",
|
|
46566
|
+
"false",
|
|
46567
|
+
"time"
|
|
46568
|
+
]);
|
|
46569
|
+
/** `sed`/`awk` are stream editors (`sed -i` rewrites files), so they stay commands. */
|
|
46570
|
+
const FILE_READ_SHELL_COMMANDS = /* @__PURE__ */ new Set([
|
|
46571
|
+
"cat",
|
|
46572
|
+
"head",
|
|
46573
|
+
"tail",
|
|
46574
|
+
"less",
|
|
46575
|
+
"more",
|
|
46576
|
+
"bat",
|
|
46577
|
+
"nl",
|
|
46578
|
+
"jq",
|
|
46579
|
+
"wc"
|
|
46580
|
+
]);
|
|
46581
|
+
const FILE_SEARCH_SHELL_COMMANDS = /* @__PURE__ */ new Set([
|
|
46582
|
+
"grep",
|
|
46583
|
+
"egrep",
|
|
46584
|
+
"fgrep",
|
|
46585
|
+
"rg",
|
|
46586
|
+
"ag",
|
|
46587
|
+
"ack",
|
|
46588
|
+
"find",
|
|
46589
|
+
"fd",
|
|
46590
|
+
"ls",
|
|
46591
|
+
"tree",
|
|
46592
|
+
"which"
|
|
46593
|
+
]);
|
|
46594
|
+
const SHELL_SEGMENT_SEPARATOR = /\|\||&&|;|\||\n/u;
|
|
46595
|
+
const LEADING_ENV_ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=\S*\s+/u;
|
|
46596
|
+
const REDIRECT_TARGET = /\d?>>?\s*(?<target>[^\s|;&]+)/gu;
|
|
46597
|
+
/** Redirect targets that discard output instead of writing a file. */
|
|
46598
|
+
const DISCARDED_REDIRECT_TARGETS = /* @__PURE__ */ new Set([
|
|
46599
|
+
"/dev/null",
|
|
46600
|
+
"&1",
|
|
46601
|
+
"&2"
|
|
46602
|
+
]);
|
|
46603
|
+
function toolCategoryTitle(category) {
|
|
46604
|
+
return TOOL_CATEGORY_TITLES[category];
|
|
46605
|
+
}
|
|
46606
|
+
function readCommandInput(toolInput) {
|
|
46607
|
+
const raw = toolInput?.command ?? toolInput?.cmd;
|
|
46608
|
+
if (typeof raw !== "string") return;
|
|
46609
|
+
const trimmed = raw.trim();
|
|
46610
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
46611
|
+
}
|
|
46612
|
+
/** `cat x > y` reads and writes; only the write matters for the row heading. */
|
|
46613
|
+
function redirectsToFile(segment) {
|
|
46614
|
+
for (const match of segment.matchAll(REDIRECT_TARGET)) {
|
|
46615
|
+
const target = match.groups?.target;
|
|
46616
|
+
if (target && !DISCARDED_REDIRECT_TARGETS.has(target)) return true;
|
|
46617
|
+
}
|
|
46618
|
+
return false;
|
|
46619
|
+
}
|
|
46620
|
+
function classifyShellSegment(segment) {
|
|
46621
|
+
if (redirectsToFile(segment)) return "command";
|
|
46622
|
+
const head = segment.trim().replace(LEADING_ENV_ASSIGNMENT, "").split(/\s+/u)[0]?.replace(/^.*\//u, "").toLowerCase();
|
|
46623
|
+
if (!head || NEUTRAL_SHELL_COMMANDS.has(head)) return;
|
|
46624
|
+
if (FILE_READ_SHELL_COMMANDS.has(head)) return "file_read";
|
|
46625
|
+
if (FILE_SEARCH_SHELL_COMMANDS.has(head)) return "file_search";
|
|
46626
|
+
return "command";
|
|
46627
|
+
}
|
|
46628
|
+
/**
|
|
46629
|
+
* A shell call only counts as a read or a search when every non-neutral segment
|
|
46630
|
+
* agrees; anything unrecognized (or write-ish) keeps the whole call a command.
|
|
46631
|
+
* Quoted separators split segments too, which can only downgrade to "command".
|
|
46632
|
+
*/
|
|
46633
|
+
function classifyShellCommand(command) {
|
|
46634
|
+
const categories = command.split(SHELL_SEGMENT_SEPARATOR).map(classifyShellSegment).filter((category) => category !== void 0);
|
|
46635
|
+
if (categories.length === 0 || categories.includes("command")) return "command";
|
|
46636
|
+
return categories.includes("file_search") ? "file_search" : "file_read";
|
|
46637
|
+
}
|
|
46638
|
+
function classifyToolCategory(input) {
|
|
46639
|
+
const normalized = input.toolName.trim().toLowerCase();
|
|
46640
|
+
if (normalized.startsWith("mcp__") || normalized.includes("mcp")) return "mcp_tool";
|
|
46641
|
+
if (SUBAGENT_TOOL_NAMES.has(normalized) || normalized.includes("agent")) return "subagent";
|
|
46642
|
+
if (FILE_READ_TOOL_NAMES.has(normalized)) return "file_read";
|
|
46643
|
+
if (FILE_SEARCH_TOOL_NAMES.has(normalized)) return "file_search";
|
|
46644
|
+
if (FILE_CHANGE_TOOL_NAMES.has(normalized)) return "file_change";
|
|
46645
|
+
if (COMMAND_TOOL_NAMES.has(normalized) || normalized.includes("bash") || normalized.includes("shell") || normalized.includes("terminal") || normalized.includes("command")) {
|
|
46646
|
+
const command = readCommandInput(input.toolInput);
|
|
46647
|
+
return command ? classifyShellCommand(command) : "command";
|
|
46648
|
+
}
|
|
46649
|
+
if (normalized.includes("websearch") || normalized.includes("web_search")) return "web_search";
|
|
46650
|
+
if (normalized.includes("edit") || normalized.includes("write") || normalized.includes("patch") || normalized.includes("replace") || normalized.includes("create") || normalized.includes("delete")) return "file_change";
|
|
46651
|
+
if (normalized.includes("read") || normalized.includes("view")) return "file_read";
|
|
46652
|
+
if (normalized.includes("grep") || normalized.includes("glob")) return "file_search";
|
|
46653
|
+
if (normalized.includes("image")) return "image_view";
|
|
46654
|
+
return "tool";
|
|
46655
|
+
}
|
|
46656
|
+
//#endregion
|
|
46657
|
+
//#region src/provider/askUserQuestionAnswers.ts
|
|
46658
|
+
/**
|
|
46659
|
+
* What separates the options of one multi-select answer.
|
|
46660
|
+
*
|
|
46661
|
+
* Comma-and-space rather than a bare comma: the SDK renders this string into a
|
|
46662
|
+
* tool result a model reads, and option labels are prose ("Fail loudly, no
|
|
46663
|
+
* fallback"), so the space is what keeps two joined labels from reading as one.
|
|
46664
|
+
*/
|
|
46665
|
+
const MULTI_SELECT_SEPARATOR = ", ";
|
|
46666
|
+
function formatAnswerValue(value) {
|
|
46667
|
+
if (typeof value === "string") {
|
|
46668
|
+
const trimmed = value.trim();
|
|
46669
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
46670
|
+
}
|
|
46671
|
+
if (Array.isArray(value)) {
|
|
46672
|
+
const parts = value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
46673
|
+
return parts.length > 0 ? parts.join(MULTI_SELECT_SEPARATOR) : null;
|
|
46674
|
+
}
|
|
46675
|
+
return null;
|
|
46676
|
+
}
|
|
46677
|
+
/**
|
|
46678
|
+
* The answers map to hand back to the SDK.
|
|
46679
|
+
*
|
|
46680
|
+
* Questions whose answer is empty, or is neither a string nor a list of them,
|
|
46681
|
+
* are dropped rather than stringified. `String(value)` on an object would put
|
|
46682
|
+
* `[object Object]` in front of the model as though it were the user's choice,
|
|
46683
|
+
* and an absent key is at least a fact the SDK can see.
|
|
46684
|
+
*/
|
|
46685
|
+
function formatAskUserQuestionAnswers(answers) {
|
|
46686
|
+
const formatted = {};
|
|
46687
|
+
for (const [question, value] of Object.entries(answers)) {
|
|
46688
|
+
const answer = formatAnswerValue(value);
|
|
46689
|
+
if (answer !== null) formatted[question] = answer;
|
|
46690
|
+
}
|
|
46691
|
+
return formatted;
|
|
46692
|
+
}
|
|
46693
|
+
//#endregion
|
|
45696
46694
|
//#region src/provider/Layers/ClaudeAdapter.ts
|
|
45697
46695
|
/**
|
|
45698
46696
|
* ClaudeAdapterLive - Scoped live implementation for the Claude Agent provider adapter.
|
|
@@ -46183,32 +47181,62 @@ function planStepsFromClaudeTasks(tasks) {
|
|
|
46183
47181
|
};
|
|
46184
47182
|
});
|
|
46185
47183
|
}
|
|
47184
|
+
const TOOL_SUMMARY_MAX_LENGTH = 400;
|
|
47185
|
+
const TOOL_PROMPT_SUMMARY_MAX_LENGTH = 200;
|
|
47186
|
+
const TOOL_PATH_INPUT_KEYS = [
|
|
47187
|
+
"file_path",
|
|
47188
|
+
"filePath",
|
|
47189
|
+
"notebook_path",
|
|
47190
|
+
"path"
|
|
47191
|
+
];
|
|
47192
|
+
function readTrimmedStringInput(input, keys) {
|
|
47193
|
+
for (const key of keys) {
|
|
47194
|
+
const value = input[key];
|
|
47195
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
47196
|
+
}
|
|
47197
|
+
}
|
|
47198
|
+
/**
|
|
47199
|
+
* Read/Grep/Glob carry no `command`, so without this they fall through to the
|
|
47200
|
+
* raw-JSON fallback and the work log shows `Read: {"file_path":...,"offset":80}`.
|
|
47201
|
+
*/
|
|
47202
|
+
function summarizeFileToolRequest(toolName, input) {
|
|
47203
|
+
const pattern = readTrimmedStringInput(input, ["pattern", "query"]);
|
|
47204
|
+
const path = readTrimmedStringInput(input, TOOL_PATH_INPUT_KEYS);
|
|
47205
|
+
if (pattern) return path ? `${toolName}: ${pattern} in ${path}` : `${toolName}: ${pattern}`;
|
|
47206
|
+
if (!path) return;
|
|
47207
|
+
const offset = input.offset;
|
|
47208
|
+
const limit = input.limit;
|
|
47209
|
+
if (typeof offset === "number" && Number.isFinite(offset)) return `${toolName}: ${path}:${offset}${typeof limit === "number" && Number.isFinite(limit) && limit > 0 ? `-${offset + limit - 1}` : ""}`;
|
|
47210
|
+
return `${toolName}: ${path}`;
|
|
47211
|
+
}
|
|
46186
47212
|
function summarizeToolRequest(toolName, input) {
|
|
46187
47213
|
const commandValue = input.command ?? input.cmd;
|
|
46188
47214
|
const command = typeof commandValue === "string" ? commandValue : void 0;
|
|
46189
|
-
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0,
|
|
47215
|
+
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0, TOOL_SUMMARY_MAX_LENGTH)}`;
|
|
46190
47216
|
if (classifyToolItemType(toolName) === "collab_agent_tool_call") {
|
|
46191
47217
|
const description = typeof input.description === "string" ? input.description.trim() : void 0;
|
|
46192
47218
|
const prompt = typeof input.prompt === "string" ? input.prompt.trim() : void 0;
|
|
46193
47219
|
const subagentType = typeof input.subagent_type === "string" ? input.subagent_type.trim() : void 0;
|
|
46194
|
-
const label = description || (prompt ? prompt.slice(0,
|
|
47220
|
+
const label = description || (prompt ? prompt.slice(0, TOOL_PROMPT_SUMMARY_MAX_LENGTH) : void 0);
|
|
46195
47221
|
if (label) return subagentType ? `${subagentType}: ${label}` : label;
|
|
46196
47222
|
}
|
|
47223
|
+
const fileSummary = summarizeFileToolRequest(toolName, input);
|
|
47224
|
+
if (fileSummary) return fileSummary.slice(0, TOOL_SUMMARY_MAX_LENGTH);
|
|
46197
47225
|
const serialized = encodeJsonStringForDiagnostics$2(input) ?? "[unserializable input]";
|
|
46198
|
-
if (serialized.length <=
|
|
46199
|
-
return `${toolName}: ${serialized.slice(0,
|
|
47226
|
+
if (serialized.length <= TOOL_SUMMARY_MAX_LENGTH) return `${toolName}: ${serialized}`;
|
|
47227
|
+
return `${toolName}: ${serialized.slice(0, TOOL_SUMMARY_MAX_LENGTH - 3)}...`;
|
|
46200
47228
|
}
|
|
46201
|
-
|
|
46202
|
-
|
|
46203
|
-
|
|
46204
|
-
|
|
46205
|
-
|
|
46206
|
-
|
|
46207
|
-
|
|
46208
|
-
|
|
46209
|
-
|
|
46210
|
-
|
|
46211
|
-
}
|
|
47229
|
+
/**
|
|
47230
|
+
* Heading for a tool row. Derived from the tool name plus its input so a `Read`
|
|
47231
|
+
* reads as "File read" instead of a bare "Tool call", and a `Bash` that only
|
|
47232
|
+
* inspects a file (`sed -n 1,20p src/x.ts`) reads as "File read" instead of
|
|
47233
|
+
* "Command run". Recomputed as streamed input arrives.
|
|
47234
|
+
*/
|
|
47235
|
+
function titleForTool(toolName, toolInput) {
|
|
47236
|
+
return toolCategoryTitle(classifyToolCategory({
|
|
47237
|
+
toolName,
|
|
47238
|
+
toolInput
|
|
47239
|
+
}));
|
|
46212
47240
|
}
|
|
46213
47241
|
const SUPPORTED_CLAUDE_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
46214
47242
|
"image/gif",
|
|
@@ -46216,6 +47244,12 @@ const SUPPORTED_CLAUDE_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
|
46216
47244
|
"image/png",
|
|
46217
47245
|
"image/webp"
|
|
46218
47246
|
]);
|
|
47247
|
+
/**
|
|
47248
|
+
* Appended to the preset system prompt when `narrateBeforeTools` is on. The SDK
|
|
47249
|
+
* preset drops the interactive CLI's terminal-tone sections, so without this the
|
|
47250
|
+
* model opens a turn with a tool call rather than a line saying what it is doing.
|
|
47251
|
+
*/
|
|
47252
|
+
const NARRATE_BEFORE_TOOLS_PROMPT = "Before your first tool call in a turn, write one short sentence saying what you are about to do. Keep it to a single line and skip it when you are answering without tools.";
|
|
46219
47253
|
const CLAUDE_SETTING_SOURCES = [
|
|
46220
47254
|
"user",
|
|
46221
47255
|
"project",
|
|
@@ -46237,6 +47271,23 @@ function buildUserMessage(input) {
|
|
|
46237
47271
|
}
|
|
46238
47272
|
};
|
|
46239
47273
|
}
|
|
47274
|
+
function userMessageContentBlocks(message) {
|
|
47275
|
+
const content = message.message.content;
|
|
47276
|
+
if (typeof content === "string") return content.length > 0 ? [{
|
|
47277
|
+
type: "text",
|
|
47278
|
+
text: content
|
|
47279
|
+
}] : [];
|
|
47280
|
+
return Array.isArray(content) ? content : [];
|
|
47281
|
+
}
|
|
47282
|
+
/**
|
|
47283
|
+
* Messages typed while a turn runs are delivered as one prompt, not one turn
|
|
47284
|
+
* each: a user who sends three corrections and then hits Stop means them to be
|
|
47285
|
+
* read together, and replaying them as separate turns made the agent act on the
|
|
47286
|
+
* first before seeing the rest.
|
|
47287
|
+
*/
|
|
47288
|
+
function mergeUserMessages(previous, next) {
|
|
47289
|
+
return buildUserMessage({ sdkContent: [...userMessageContentBlocks(previous), ...userMessageContentBlocks(next)] });
|
|
47290
|
+
}
|
|
46240
47291
|
function buildClaudeImageContentBlock(input) {
|
|
46241
47292
|
return {
|
|
46242
47293
|
type: "image",
|
|
@@ -46876,6 +47927,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46876
47927
|
title: tool.title,
|
|
46877
47928
|
...tool.detail ? { detail: tool.detail } : {},
|
|
46878
47929
|
data: {
|
|
47930
|
+
toolCallId: tool.itemId,
|
|
46879
47931
|
toolName: tool.toolName,
|
|
46880
47932
|
input: tool.input
|
|
46881
47933
|
}
|
|
@@ -46923,6 +47975,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46923
47975
|
});
|
|
46924
47976
|
const updatedAt = yield* nowIso;
|
|
46925
47977
|
context.turnState = void 0;
|
|
47978
|
+
context.steeredMessages.clear();
|
|
46926
47979
|
context.session = {
|
|
46927
47980
|
...context.session,
|
|
46928
47981
|
status: "ready",
|
|
@@ -46969,6 +48022,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46969
48022
|
const updatedAt = yield* nowIso;
|
|
46970
48023
|
context.turnState = turnState;
|
|
46971
48024
|
context.interruptRequested = false;
|
|
48025
|
+
context.steeredMessages.clear();
|
|
46972
48026
|
context.session = {
|
|
46973
48027
|
...context.session,
|
|
46974
48028
|
status: "running",
|
|
@@ -46988,25 +48042,51 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
46988
48042
|
});
|
|
46989
48043
|
});
|
|
46990
48044
|
/**
|
|
46991
|
-
* Start the
|
|
48045
|
+
* Start the queued sendTurn, if the session has gone idle.
|
|
46992
48046
|
*
|
|
46993
|
-
* Runs after every turn completion.
|
|
46994
|
-
*
|
|
46995
|
-
*
|
|
46996
|
-
*
|
|
46997
|
-
* the next one starts when this turn's result arrives.
|
|
48047
|
+
* Runs after every turn completion. What waits here are the steers Stop took
|
|
48048
|
+
* back from the CLI before they ran (see `reclaimSteeredMessages`); they are
|
|
48049
|
+
* already merged into one request, so they start as a single turn the moment
|
|
48050
|
+
* the interrupted loop ends.
|
|
46998
48051
|
*/
|
|
46999
48052
|
const drainPendingTurns = Effect.fn("drainPendingTurns")(function* (context) {
|
|
47000
48053
|
if (context.stopped || context.turnState !== void 0) return;
|
|
47001
|
-
const pending = context.
|
|
48054
|
+
const pending = context.pendingTurnRequest;
|
|
47002
48055
|
if (pending === void 0) return;
|
|
47003
|
-
|
|
47004
|
-
yield* beginTurn(context, pending.turnId,
|
|
48056
|
+
context.pendingTurnRequest = void 0;
|
|
48057
|
+
yield* beginTurn(context, pending.turnId, context.session.model);
|
|
47005
48058
|
yield* Queue.offer(context.promptQueue, {
|
|
47006
48059
|
type: "message",
|
|
47007
48060
|
message: pending.message
|
|
47008
48061
|
}).pipe(Effect.ignore);
|
|
47009
48062
|
});
|
|
48063
|
+
/**
|
|
48064
|
+
* Take back the steers the CLI has not started yet, so Stop still runs them.
|
|
48065
|
+
*
|
|
48066
|
+
* A steer sits in the CLI's async-message queue until the agent loop reaches
|
|
48067
|
+
* its next boundary. `cancelAsyncMessage` answers true only while it is still
|
|
48068
|
+
* waiting there: those never reached the model and become the next turn
|
|
48069
|
+
* together, while an already-dequeued one is part of the turn being stopped
|
|
48070
|
+
* and must not run a second time.
|
|
48071
|
+
*/
|
|
48072
|
+
const reclaimSteeredMessages = Effect.fn("reclaimSteeredMessages")(function* (context) {
|
|
48073
|
+
const steered = Array.from(context.steeredMessages);
|
|
48074
|
+
context.steeredMessages.clear();
|
|
48075
|
+
const cancelAsyncMessage = context.query.cancelAsyncMessage;
|
|
48076
|
+
if (steered.length === 0 || cancelAsyncMessage === void 0) return;
|
|
48077
|
+
const reclaimed = [];
|
|
48078
|
+
for (const [messageUuid, message] of steered) if (yield* Effect.tryPromise({
|
|
48079
|
+
try: () => cancelAsyncMessage(messageUuid),
|
|
48080
|
+
catch: (cause) => toRequestError$1(context.session.threadId, "turn/cancelAsyncMessage", cause)
|
|
48081
|
+
}).pipe(Effect.catchCause((cause) => Effect.logWarning("claude steer cancel failed", { cause }).pipe(Effect.as(false))))) reclaimed.push(message);
|
|
48082
|
+
if (reclaimed.length === 0) return;
|
|
48083
|
+
const merged = reclaimed.reduce((left, right) => mergeUserMessages(left, right));
|
|
48084
|
+
const pending = context.pendingTurnRequest;
|
|
48085
|
+
context.pendingTurnRequest = {
|
|
48086
|
+
turnId: pending?.turnId ?? TurnId.make(yield* randomUUIDv4),
|
|
48087
|
+
message: pending ? mergeUserMessages(pending.message, merged) : merged
|
|
48088
|
+
};
|
|
48089
|
+
});
|
|
47010
48090
|
const handleStreamEvent = Effect.fn("handleStreamEvent")(function* (context, message) {
|
|
47011
48091
|
if (message.type !== "stream_event") return;
|
|
47012
48092
|
const { event } = message;
|
|
@@ -47057,11 +48137,13 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47057
48137
|
const partialInputJson = tool.partialInputJson + event.delta.partial_json;
|
|
47058
48138
|
const parsedInput = tryParseJsonRecord(partialInputJson);
|
|
47059
48139
|
const detail = parsedInput ? summarizeToolRequest(tool.toolName, parsedInput) : tool.detail;
|
|
48140
|
+
const title = parsedInput ? titleForTool(tool.toolName, parsedInput) : tool.title;
|
|
47060
48141
|
let nextTool = {
|
|
47061
48142
|
...tool,
|
|
47062
48143
|
partialInputJson,
|
|
47063
48144
|
...parsedInput ? { input: parsedInput } : {},
|
|
47064
|
-
...detail ? { detail } : {}
|
|
48145
|
+
...detail ? { detail } : {},
|
|
48146
|
+
title
|
|
47065
48147
|
};
|
|
47066
48148
|
const nextFingerprint = parsedInput && Object.keys(parsedInput).length > 0 ? toolInputFingerprint(parsedInput) : void 0;
|
|
47067
48149
|
context.inFlightTools.set(event.index, nextTool);
|
|
@@ -47086,6 +48168,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47086
48168
|
title: nextTool.title,
|
|
47087
48169
|
...nextTool.detail ? { detail: nextTool.detail } : {},
|
|
47088
48170
|
data: {
|
|
48171
|
+
toolCallId: nextTool.itemId,
|
|
47089
48172
|
toolName: nextTool.toolName,
|
|
47090
48173
|
input: nextTool.input
|
|
47091
48174
|
}
|
|
@@ -47133,7 +48216,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47133
48216
|
itemId,
|
|
47134
48217
|
itemType,
|
|
47135
48218
|
toolName,
|
|
47136
|
-
title: titleForTool(
|
|
48219
|
+
title: titleForTool(toolName, toolInput),
|
|
47137
48220
|
detail,
|
|
47138
48221
|
input: toolInput,
|
|
47139
48222
|
partialInputJson: "",
|
|
@@ -47155,6 +48238,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47155
48238
|
title: tool.title,
|
|
47156
48239
|
...tool.detail ? { detail: tool.detail } : {},
|
|
47157
48240
|
data: {
|
|
48241
|
+
toolCallId: tool.itemId,
|
|
47158
48242
|
toolName: tool.toolName,
|
|
47159
48243
|
input: toolInput
|
|
47160
48244
|
}
|
|
@@ -47192,6 +48276,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47192
48276
|
const itemStatus = toolResult.isError ? "failed" : "completed";
|
|
47193
48277
|
const toolUseResult = readClaudeToolUseResult(message);
|
|
47194
48278
|
const toolData = {
|
|
48279
|
+
toolCallId: tool.itemId,
|
|
47195
48280
|
toolName: tool.toolName,
|
|
47196
48281
|
input: tool.input,
|
|
47197
48282
|
result: toolResult.block
|
|
@@ -47852,7 +48937,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47852
48937
|
behavior: "allow",
|
|
47853
48938
|
updatedInput: {
|
|
47854
48939
|
questions: toolInput.questions,
|
|
47855
|
-
answers
|
|
48940
|
+
answers: formatAskUserQuestionAnswers(answers)
|
|
47856
48941
|
}
|
|
47857
48942
|
};
|
|
47858
48943
|
});
|
|
@@ -47981,10 +49066,13 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47981
49066
|
auto: "auto",
|
|
47982
49067
|
"full-access": "bypassPermissions"
|
|
47983
49068
|
}[input.runtimeMode];
|
|
49069
|
+
const disabledSkills = options?.resolveDisabledSkills === void 0 ? [] : yield* options.resolveDisabledSkills;
|
|
49070
|
+
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
49071
|
const settings = {
|
|
47985
49072
|
...typeof thinking === "boolean" ? { alwaysThinkingEnabled: thinking } : {},
|
|
47986
49073
|
...fastMode ? { fastMode: true } : {},
|
|
47987
|
-
...ultracode ? { ultracode: true } : {}
|
|
49074
|
+
...ultracode ? { ultracode: true } : {},
|
|
49075
|
+
...skillOverrides ? { skillOverrides } : {}
|
|
47988
49076
|
};
|
|
47989
49077
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
47990
49078
|
const externalMcpServers = options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers;
|
|
@@ -47994,7 +49082,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
47994
49082
|
pathToClaudeCodeExecutable: claudeBinaryPath,
|
|
47995
49083
|
systemPrompt: {
|
|
47996
49084
|
type: "preset",
|
|
47997
|
-
preset: "claude_code"
|
|
49085
|
+
preset: "claude_code",
|
|
49086
|
+
...claudeSettings.narrateBeforeTools ? { append: NARRATE_BEFORE_TOOLS_PROMPT } : {}
|
|
47998
49087
|
},
|
|
47999
49088
|
settingSources: [...CLAUDE_SETTING_SOURCES],
|
|
48000
49089
|
...effectiveEffort ? { effort: effectiveEffort } : {},
|
|
@@ -48036,6 +49125,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48036
49125
|
"claude.query.include_partial_messages": true,
|
|
48037
49126
|
"claude.query.additional_directories": input.cwd ? [input.cwd] : [],
|
|
48038
49127
|
"claude.query.setting_sources": [...CLAUDE_SETTING_SOURCES],
|
|
49128
|
+
"claude.query.narrate_before_tools": claudeSettings.narrateBeforeTools,
|
|
48039
49129
|
"claude.query.settings_json": encodeJsonStringForDiagnostics$2(settings) ?? "",
|
|
48040
49130
|
"claude.query.extra_args_json": encodeJsonStringForDiagnostics$2(extraArgs) ?? "",
|
|
48041
49131
|
"claude.query.path_to_executable": claudeBinaryPath
|
|
@@ -48085,7 +49175,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48085
49175
|
inFlightTools,
|
|
48086
49176
|
claudeTasks,
|
|
48087
49177
|
turnState: void 0,
|
|
48088
|
-
|
|
49178
|
+
pendingTurnRequest: void 0,
|
|
49179
|
+
steeredMessages: /* @__PURE__ */ new Map(),
|
|
48089
49180
|
lastKnownContextWindow: initialContextWindow,
|
|
48090
49181
|
lastKnownTokenUsage: void 0,
|
|
48091
49182
|
lastKnownTotalProcessedTokens: void 0,
|
|
@@ -48154,16 +49245,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48154
49245
|
boundInstanceId
|
|
48155
49246
|
});
|
|
48156
49247
|
if (context.turnState) {
|
|
48157
|
-
const
|
|
48158
|
-
|
|
48159
|
-
|
|
48160
|
-
|
|
48161
|
-
|
|
48162
|
-
|
|
48163
|
-
|
|
49248
|
+
const steerUuid = yield* randomUUIDv4;
|
|
49249
|
+
const steered = {
|
|
49250
|
+
...message,
|
|
49251
|
+
uuid: steerUuid
|
|
49252
|
+
};
|
|
49253
|
+
context.steeredMessages.set(steerUuid, steered);
|
|
49254
|
+
yield* Queue.offer(context.promptQueue, {
|
|
49255
|
+
type: "message",
|
|
49256
|
+
message: steered
|
|
49257
|
+
}).pipe(Effect.mapError((cause) => toRequestError$1(input.threadId, "turn/start", cause)));
|
|
48164
49258
|
return {
|
|
48165
49259
|
threadId: context.session.threadId,
|
|
48166
|
-
turnId,
|
|
49260
|
+
turnId: context.turnState.turnId,
|
|
48167
49261
|
...context.session.resumeCursor !== void 0 ? { resumeCursor: context.session.resumeCursor } : {}
|
|
48168
49262
|
};
|
|
48169
49263
|
}
|
|
@@ -48183,6 +49277,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
48183
49277
|
const interruptTurn = Effect.fn("interruptTurn")(function* (threadId, _turnId) {
|
|
48184
49278
|
const context = yield* requireSession(threadId);
|
|
48185
49279
|
context.interruptRequested = true;
|
|
49280
|
+
yield* reclaimSteeredMessages(context);
|
|
48186
49281
|
yield* Effect.tryPromise({
|
|
48187
49282
|
try: () => context.query.interrupt(),
|
|
48188
49283
|
catch: (cause) => toRequestError$1(threadId, "turn/interrupt", cause)
|
|
@@ -48346,7 +49441,8 @@ function mergeProviderInstanceEnvironment(environment, baseEnv = process.env) {
|
|
|
48346
49441
|
function makeProviderSnapshotSettings(provider, settings) {
|
|
48347
49442
|
return {
|
|
48348
49443
|
provider,
|
|
48349
|
-
enableProviderUpdateChecks: settings.enableProviderUpdateChecks
|
|
49444
|
+
enableProviderUpdateChecks: settings.enableProviderUpdateChecks,
|
|
49445
|
+
disabledSkills: settings.disabledSkills
|
|
48350
49446
|
};
|
|
48351
49447
|
}
|
|
48352
49448
|
function haveProviderSnapshotSettingsChanged(previous, next) {
|
|
@@ -48438,10 +49534,13 @@ const ClaudeDriver = {
|
|
|
48438
49534
|
accentColor,
|
|
48439
49535
|
continuationGroupKey
|
|
48440
49536
|
});
|
|
49537
|
+
const mcpRegistry = yield* McpRegistry;
|
|
49538
|
+
const resolveDisabledSkills = serverSettings.getSettings.pipe(Effect.map((settings) => settings.disabledSkills), Effect.orElseSucceed(() => []));
|
|
48441
49539
|
const adapter = yield* makeClaudeAdapter(effectiveConfig, {
|
|
48442
49540
|
instanceId,
|
|
48443
49541
|
environment: processEnv,
|
|
48444
|
-
resolveMcpServers:
|
|
49542
|
+
resolveMcpServers: mcpRegistry.resolveForSession,
|
|
49543
|
+
resolveDisabledSkills,
|
|
48445
49544
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
|
|
48446
49545
|
});
|
|
48447
49546
|
const textGeneration = yield* makeClaudeTextGeneration(effectiveConfig, processEnv);
|
|
@@ -48451,7 +49550,7 @@ const ClaudeDriver = {
|
|
|
48451
49550
|
lookup: () => probeClaudeCapabilities(effectiveConfig, processEnv, cwd).pipe(Effect.provideService(Path.Path, path))
|
|
48452
49551
|
});
|
|
48453
49552
|
const capabilitiesCacheKey = yield* makeClaudeCapabilitiesCacheKey(effectiveConfig, cwd);
|
|
48454
|
-
const checkProvider = checkClaudeProviderStatus(effectiveConfig, () => Cache.get(capabilitiesProbeCache, capabilitiesCacheKey), processEnv, cwd)
|
|
49553
|
+
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
49554
|
const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
|
|
48456
49555
|
const snapshot = yield* makeManagedServerProvider({
|
|
48457
49556
|
maintenanceCapabilities,
|
|
@@ -83338,7 +84437,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
83338
84437
|
sink,
|
|
83339
84438
|
...delegate ? { delegate } : {}
|
|
83340
84439
|
});
|
|
83341
|
-
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$
|
|
84440
|
+
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$40(sink));
|
|
83342
84441
|
})).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
|
|
83343
84442
|
const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
|
|
83344
84443
|
url: config.otlpMetricsUrl,
|
|
@@ -83617,25 +84716,25 @@ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReacto
|
|
|
83617
84716
|
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$3));
|
|
83618
84717
|
const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
|
|
83619
84718
|
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$
|
|
84719
|
+
const VcsDriverRegistryLayerLive = layer$36.pipe(Layer.provide(layer$37));
|
|
84720
|
+
const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
84721
|
+
const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$38), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$32));
|
|
84722
|
+
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$38));
|
|
83624
84723
|
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$
|
|
84724
|
+
const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
|
|
84725
|
+
const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
84726
|
+
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))));
|
|
84727
|
+
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$34), Layer.provideMerge(layer$35.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
|
|
84728
|
+
const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$53));
|
|
83630
84729
|
const TerminalLayerLive = layer$29.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
|
|
83631
84730
|
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$
|
|
84731
|
+
const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$43));
|
|
84732
|
+
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$43), Layer.provide(WorkspaceEntriesLayerLive));
|
|
84733
|
+
const WorkspaceLayerLive = Layer.mergeAll(layer$43, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
|
|
84734
|
+
const ProjectFaviconResolverLayerLive = layer$41.pipe(Layer.provide(layer$43), Layer.provide(layer$42));
|
|
84735
|
+
const AuthLayerLive = layer$61.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$65));
|
|
83637
84736
|
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$
|
|
84737
|
+
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
84738
|
/**
|
|
83640
84739
|
* Hub asset sync.
|
|
83641
84740
|
*
|
|
@@ -83643,9 +84742,9 @@ const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(Checkpo
|
|
|
83643
84742
|
* not-configured shape, and every call reports that rather than failing — so
|
|
83644
84743
|
* this costs a server with no hub nothing but a layer.
|
|
83645
84744
|
*/
|
|
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(
|
|
84745
|
+
const AssetSyncLive = layer$54.pipe(Layer.provideMerge(layer$55), Layer.provideMerge(layer$56));
|
|
84746
|
+
const RuntimeServicesLive = layer$44.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
|
|
84747
|
+
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
84748
|
const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
83650
84749
|
const config = yield* ServerConfig$1;
|
|
83651
84750
|
yield* fixPath();
|
|
@@ -83688,7 +84787,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
83688
84787
|
cause,
|
|
83689
84788
|
servePort: configured.servePort
|
|
83690
84789
|
}))) : 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$
|
|
84790
|
+
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
84791
|
}));
|
|
83693
84792
|
const runServer = Layer.launch(makeServerLayer);
|
|
83694
84793
|
//#endregion
|
|
@@ -83850,11 +84949,11 @@ const reconcileWithNewBinary = Effect.fn("cli.selfUpdate.reconcileWithNewBinary"
|
|
|
83850
84949
|
//#endregion
|
|
83851
84950
|
//#region src/cli/service.ts
|
|
83852
84951
|
const isBootServiceCommandError = Schema$1.is(BootServiceCommandError);
|
|
83853
|
-
const bootServiceLayer = (config) => layer$
|
|
84952
|
+
const bootServiceLayer = (config) => layer$47({
|
|
83854
84953
|
baseDir: config.baseDir,
|
|
83855
84954
|
logsDir: config.logsDir,
|
|
83856
84955
|
cliVersion: version
|
|
83857
|
-
}).pipe(Layer.provide(layer$
|
|
84956
|
+
}).pipe(Layer.provide(layer$53));
|
|
83858
84957
|
/** Install, update, or repair the service using the CLI version running this command. */
|
|
83859
84958
|
const reconcileService = Effect.fn("cli.service.reconcile")(function* () {
|
|
83860
84959
|
const service = yield* BootService;
|
|
@@ -83901,7 +85000,7 @@ const runServiceCommand = Effect.fn("cli.service.run")(function* (flags, run, pr
|
|
|
83901
85000
|
const baseDirNotice = yield* describeNonDefaultBaseDir(config.baseDir);
|
|
83902
85001
|
if (baseDirNotice !== null) yield* Console.error(baseDirNotice);
|
|
83903
85002
|
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$
|
|
85003
|
+
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
85004
|
});
|
|
83906
85005
|
/**
|
|
83907
85006
|
* Options the installed unit carries, rather than ones this command consumes.
|
|
@@ -84055,7 +85154,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
|
|
|
84055
85154
|
]));
|
|
84056
85155
|
//#endregion
|
|
84057
85156
|
//#region src/bin.ts
|
|
84058
|
-
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$
|
|
85157
|
+
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$69, FetchHttpClient.layer);
|
|
84059
85158
|
/**
|
|
84060
85159
|
* Prints an update reminder before dispatching, at most once a day.
|
|
84061
85160
|
*
|