@p4code/cli 0.1.18 → 0.1.20
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 +1330 -160
- package/dist/client/assets/{DiffPanel-CP_cM9m0.js → DiffPanel-Di8WylWU.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-CLho0PPu.js → FilePreviewPanel-CSqqsbYX.js} +2 -2
- package/dist/client/assets/{PreviewPanel-DvnUpMQv.js → PreviewPanel-BcRUQSMy.js} +2 -2
- package/dist/client/assets/{angular-html-CEMakyzJ.js → angular-html-CPSNyy71.js} +2 -2
- package/dist/client/assets/{angular-ts-YXZHq2uz.js → angular-ts-BgndqOdx.js} +2 -2
- package/dist/client/assets/{apl-BTa85Bsd.js → apl-CFWK0bta.js} +2 -2
- package/dist/client/assets/arrow-right-wbRntSmq.js +2 -0
- package/dist/client/assets/{astro-DIbti84c.js → astro-D2uzatlp.js} +2 -2
- package/dist/client/assets/{blade-CKAdvdwG.js → blade-DfrK_8z3.js} +2 -2
- package/dist/client/assets/{c-DW17xzCK.js → c-DyORVYNJ.js} +2 -2
- package/dist/client/assets/{cobol-DXiicIcZ.js → cobol-BUWePdBc.js} +2 -2
- package/dist/client/assets/{coffee-9Pdmmdn2.js → coffee-Ba8BYHli.js} +2 -2
- package/dist/client/assets/{cpp-bm3vFVmW.js → cpp-BX0iAGNA.js} +2 -2
- package/dist/client/assets/{crystal-DbxZDZf9.js → crystal-BDSdceoQ.js} +2 -2
- package/dist/client/assets/{css-BEBnbxDe.js → css-TKd0Sp86.js} +2 -2
- package/dist/client/assets/{edge-K97wVEy_.js → edge-Bus7Aab8.js} +2 -2
- package/dist/client/assets/{elixir-Rc2JDLLD.js → elixir-BlT2g4EX.js} +2 -2
- package/dist/client/assets/{elm-QsA8aREL.js → elm-DTGJZ36e.js} +2 -2
- package/dist/client/assets/{erb-CliRJz4v.js → erb-BF4yZGxQ.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-DtIPA0Fm.js → fileCommentAnnotations-C5BlQ5s_.js} +2 -2
- package/dist/client/assets/{git-rebase-Da_Wuhd_.js → git-rebase-GAe0_ZI9.js} +2 -2
- package/dist/client/assets/{glimmer-js-XPbTw3tC.js → glimmer-js-GWmPSTNt.js} +2 -2
- package/dist/client/assets/{glimmer-ts-BtK3NOkH.js → glimmer-ts-CDLqKTZ9.js} +2 -2
- package/dist/client/assets/{glsl-DqEtJptk.js → glsl-Bv3E3r0O.js} +2 -2
- package/dist/client/assets/{graphql-BSRTeXs0.js → graphql-B5-LupiK.js} +2 -2
- package/dist/client/assets/{hack-Dw9HaNHZ.js → hack-KTQ3DPKm.js} +2 -2
- package/dist/client/assets/{haml-BBNabTlb.js → haml-BvC-52XY.js} +2 -2
- package/dist/client/assets/{handlebars-BgXzhWSj.js → handlebars-CK9WCq20.js} +2 -2
- package/dist/client/assets/{html-wBdSHoow.js → html-BGjxg0hO.js} +2 -2
- package/dist/client/assets/{html-derivative-CANLUZ-z.js → html-derivative-C0EaHUuc.js} +2 -2
- package/dist/client/assets/{http-BY44QKMy.js → http-hvxfwUee.js} +2 -2
- package/dist/client/assets/{hurl-EMZQkkjM.js → hurl-D5cuiBPB.js} +2 -2
- package/dist/client/assets/index-QC2FhlVn.js +836 -0
- package/dist/client/assets/{java-ByjPbT42.js → java-DOkofowB.js} +2 -2
- package/dist/client/assets/{javascript-C9vbUEcm.js → javascript-dCesbfJ7.js} +2 -2
- package/dist/client/assets/{jinja-DH-AbsBN.js → jinja-BDrVqT_2.js} +2 -2
- package/dist/client/assets/{jison-Bef1Ntr_.js → jison-Dvzh0XRq.js} +2 -2
- package/dist/client/assets/{json-Gk_oM0bP.js → json-CpV_dVb2.js} +2 -2
- package/dist/client/assets/{jsx-Ds7YHLou.js → jsx-CbaKC498.js} +2 -2
- package/dist/client/assets/{julia-Dm-6xpIK.js → julia-BKYdI_5W.js} +2 -2
- package/dist/client/assets/{just-BXY93QN4.js → just-FrVMEGvg.js} +2 -2
- package/dist/client/assets/{latex-B3-eYkFA.js → latex-BSmwt_7j.js} +2 -2
- package/dist/client/assets/{liquid-C10OBLnm.js → liquid-Bb2nFp-U.js} +2 -2
- package/dist/client/assets/{lua-BUR8bsxC.js → lua-CEANnQ2c.js} +2 -2
- package/dist/client/assets/{marko-COPLM_fz.js → marko-CjJZ1eHg.js} +2 -2
- package/dist/client/assets/{mdc-CTAUTBsz.js → mdc-B3VSAYVT.js} +2 -2
- package/dist/client/assets/{nginx-D1BLqLRM.js → nginx-BkYJUm4E.js} +2 -2
- package/dist/client/assets/{nim-Xs8VbhdY.js → nim-D8xT6_xt.js} +2 -2
- package/dist/client/assets/{perl-D7-zmFa1.js → perl-cazo7YHC.js} +2 -2
- package/dist/client/assets/{php-BiTVgoaL.js → php-C0LwuOo3.js} +2 -2
- package/dist/client/assets/{pug-DphfHoFa.js → pug-OP6SwNFw.js} +2 -2
- package/dist/client/assets/{qml-CYcNnFOd.js → qml-C1-WQIQ-.js} +2 -2
- package/dist/client/assets/{r-BrJ-p0TS.js → r-PkhwsIgx.js} +2 -2
- package/dist/client/assets/{razor-1gio6m_g.js → razor-WONkd3aR.js} +2 -2
- package/dist/client/assets/{regexp-CNiuKup7.js → regexp-SDnpa4md.js} +2 -2
- package/dist/client/assets/{rst-BPOsO8_U.js → rst-DulobrTh.js} +2 -2
- package/dist/client/assets/{ruby-CpfKHKDc.js → ruby-RYHm8H3x.js} +2 -2
- package/dist/client/assets/{sas-CngX1we2.js → sas-BBwb67VZ.js} +2 -2
- package/dist/client/assets/{scss-B2remLQX.js → scss-y2IZtjKJ.js} +2 -2
- package/dist/client/assets/{shellscript-CQmxALRY.js → shellscript-B3vxtpJZ.js} +2 -2
- package/dist/client/assets/{shellsession-BB-5CB_r.js → shellsession-CvHfy0TS.js} +2 -2
- package/dist/client/assets/{soy-kYUnX51I.js → soy-DWpn3a9x.js} +2 -2
- package/dist/client/assets/{sql-Cq9fRkwr.js → sql-CCfTsIvj.js} +2 -2
- package/dist/client/assets/{stata-17nboilR.js → stata-Dr5CN-Tp.js} +2 -2
- package/dist/client/assets/{surrealql-D1hrcsSn.js → surrealql-DgzXJo35.js} +2 -2
- package/dist/client/assets/{svelte-GmGi3eK8.js → svelte-JQb5PCjP.js} +2 -2
- package/dist/client/assets/{templ-DySdTLEs.js → templ-DQt5AsQ7.js} +2 -2
- package/dist/client/assets/{tex-CblcFqPi.js → tex-B8Qokwwv.js} +2 -2
- package/dist/client/assets/textarea-BlxAoGJe.js +46 -0
- package/dist/client/assets/{ts-tags-BQC5pzJI.js → ts-tags-B-RrSBzw.js} +2 -2
- package/dist/client/assets/{tsx-1bNjXgiV.js → tsx-C7Q0nn_B.js} +2 -2
- package/dist/client/assets/{twig-CNwthYXl.js → twig-CzVGXsz7.js} +2 -2
- package/dist/client/assets/{typescript-BTKoaKmx.js → typescript-irwEvPgw.js} +2 -2
- package/dist/client/assets/{vue-B4XpWxge.js → vue-BE-nMa-3.js} +2 -2
- package/dist/client/assets/{vue-html-CcUSqexV.js → vue-html-SXHQOmAo.js} +2 -2
- package/dist/client/assets/{vue-vine-JDMd26pY.js → vue-vine-D62pnm9I.js} +2 -2
- package/dist/client/assets/{xml-DRuNSJP8.js → xml-BnssPo1i.js} +2 -2
- package/dist/client/assets/{xsl-BIJJg1B0.js → xsl-Dg7cN1LO.js} +2 -2
- package/dist/client/assets/{yaml-BNEnOsJI.js → yaml-BAeQKrXU.js} +2 -2
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/dist/client/assets/arrow-right-Bi8kADrV.js +0 -2
- package/dist/client/assets/index-kwzTYbVb.js +0 -775
- package/dist/client/assets/textarea-Cf56oU_6.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$76 = () => {
|
|
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$75 = () => {
|
|
|
230
230
|
})
|
|
231
231
|
};
|
|
232
232
|
};
|
|
233
|
-
const layer$
|
|
233
|
+
const layer$72 = Layer.sync(NetService, make$76);
|
|
234
234
|
//#endregion
|
|
235
235
|
//#region package.json
|
|
236
|
-
var version = "0.1.
|
|
236
|
+
var version = "0.1.20";
|
|
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$75 = (config) => ServerConfig$1.of(config);
|
|
258
|
+
const layer$71 = (config) => Layer.succeed(ServerConfig$1, make$75(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");
|
|
@@ -1838,6 +1838,7 @@ const OrchestrationThread = Schema$1.Struct({
|
|
|
1838
1838
|
runtimeMode: RuntimeMode,
|
|
1839
1839
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
1840
1840
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
1841
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
1841
1842
|
branch: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
1842
1843
|
worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
1843
1844
|
latestTurn: Schema$1.NullOr(OrchestrationLatestTurn),
|
|
@@ -1879,6 +1880,7 @@ const OrchestrationThreadShell = Schema$1.Struct({
|
|
|
1879
1880
|
runtimeMode: RuntimeMode,
|
|
1880
1881
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
1881
1882
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
1883
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
1882
1884
|
branch: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
1883
1885
|
worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
1884
1886
|
latestTurn: Schema$1.NullOr(OrchestrationLatestTurn),
|
|
@@ -2002,6 +2004,7 @@ const ThreadCreateCommand = Schema$1.Struct({
|
|
|
2002
2004
|
runtimeMode: RuntimeMode,
|
|
2003
2005
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
2004
2006
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2007
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2005
2008
|
branch: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2006
2009
|
worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2007
2010
|
createdAt: IsoDateTime
|
|
@@ -2075,6 +2078,18 @@ const ThreadCompressModeSetCommand = Schema$1.Struct({
|
|
|
2075
2078
|
compressMode: CompressMode,
|
|
2076
2079
|
createdAt: IsoDateTime
|
|
2077
2080
|
});
|
|
2081
|
+
/**
|
|
2082
|
+
* No decoding default on the value, matching the compress command beside it: a
|
|
2083
|
+
* command is an instruction someone issued, and defaulting the very field it
|
|
2084
|
+
* exists to carry would turn a malformed dispatch into a silent write.
|
|
2085
|
+
*/
|
|
2086
|
+
const ThreadUnpromptedSubagentsSetCommand = Schema$1.Struct({
|
|
2087
|
+
type: Schema$1.Literal("thread.unprompted-subagents.set"),
|
|
2088
|
+
commandId: CommandId,
|
|
2089
|
+
threadId: ThreadId,
|
|
2090
|
+
unpromptedSubagents: Schema$1.Boolean,
|
|
2091
|
+
createdAt: IsoDateTime
|
|
2092
|
+
});
|
|
2078
2093
|
const ThreadTurnStartBootstrapCreateThread = Schema$1.Struct({
|
|
2079
2094
|
projectId: ProjectId,
|
|
2080
2095
|
title: TrimmedNonEmptyString,
|
|
@@ -2082,6 +2097,7 @@ const ThreadTurnStartBootstrapCreateThread = Schema$1.Struct({
|
|
|
2082
2097
|
runtimeMode: RuntimeMode,
|
|
2083
2098
|
interactionMode: ProviderInteractionMode,
|
|
2084
2099
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2100
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2085
2101
|
branch: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2086
2102
|
worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2087
2103
|
createdAt: IsoDateTime
|
|
@@ -2112,6 +2128,7 @@ const ThreadTurnStartCommand = Schema$1.Struct({
|
|
|
2112
2128
|
runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
|
|
2113
2129
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
2114
2130
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2131
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2115
2132
|
bootstrap: Schema$1.optional(ThreadTurnStartBootstrap),
|
|
2116
2133
|
sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
|
|
2117
2134
|
createdAt: IsoDateTime
|
|
@@ -2131,6 +2148,7 @@ const ClientThreadTurnStartCommand = Schema$1.Struct({
|
|
|
2131
2148
|
runtimeMode: RuntimeMode,
|
|
2132
2149
|
interactionMode: ProviderInteractionMode,
|
|
2133
2150
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2151
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2134
2152
|
bootstrap: Schema$1.optional(ThreadTurnStartBootstrap),
|
|
2135
2153
|
sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
|
|
2136
2154
|
createdAt: IsoDateTime
|
|
@@ -2187,6 +2205,7 @@ const DispatchableClientOrchestrationCommand = Schema$1.Union([
|
|
|
2187
2205
|
ThreadRuntimeModeSetCommand,
|
|
2188
2206
|
ThreadInteractionModeSetCommand,
|
|
2189
2207
|
ThreadCompressModeSetCommand,
|
|
2208
|
+
ThreadUnpromptedSubagentsSetCommand,
|
|
2190
2209
|
ThreadTurnStartCommand,
|
|
2191
2210
|
ThreadTurnInterruptCommand,
|
|
2192
2211
|
ThreadApprovalRespondCommand,
|
|
@@ -2210,6 +2229,7 @@ const ClientOrchestrationCommand = Schema$1.Union([
|
|
|
2210
2229
|
ThreadRuntimeModeSetCommand,
|
|
2211
2230
|
ThreadInteractionModeSetCommand,
|
|
2212
2231
|
ThreadCompressModeSetCommand,
|
|
2232
|
+
ThreadUnpromptedSubagentsSetCommand,
|
|
2213
2233
|
ClientThreadTurnStartCommand,
|
|
2214
2234
|
ThreadTurnInterruptCommand,
|
|
2215
2235
|
ThreadApprovalRespondCommand,
|
|
@@ -2301,6 +2321,7 @@ const OrchestrationEventType = Schema$1.Literals([
|
|
|
2301
2321
|
"thread.runtime-mode-set",
|
|
2302
2322
|
"thread.interaction-mode-set",
|
|
2303
2323
|
"thread.compress-mode-set",
|
|
2324
|
+
"thread.unprompted-subagents-set",
|
|
2304
2325
|
"thread.message-sent",
|
|
2305
2326
|
"thread.turn-start-requested",
|
|
2306
2327
|
"thread.turn-interrupt-requested",
|
|
@@ -2351,6 +2372,7 @@ const ThreadCreatedPayload$1 = Schema$1.Struct({
|
|
|
2351
2372
|
runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
|
|
2352
2373
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
2353
2374
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2375
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2354
2376
|
branch: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2355
2377
|
worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2356
2378
|
createdAt: IsoDateTime,
|
|
@@ -2413,6 +2435,16 @@ const ThreadCompressModeSetPayload$1 = Schema$1.Struct({
|
|
|
2413
2435
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2414
2436
|
updatedAt: IsoDateTime
|
|
2415
2437
|
});
|
|
2438
|
+
/**
|
|
2439
|
+
* One thread's subagent policy changed. Its own event rather than a field on
|
|
2440
|
+
* the compress one, for the reason every event here is narrow: replaying a
|
|
2441
|
+
* combined event would rewrite whichever half the user did not touch.
|
|
2442
|
+
*/
|
|
2443
|
+
const ThreadUnpromptedSubagentsSetPayload$1 = Schema$1.Struct({
|
|
2444
|
+
threadId: ThreadId,
|
|
2445
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2446
|
+
updatedAt: IsoDateTime
|
|
2447
|
+
});
|
|
2416
2448
|
const ThreadMessageSentPayload = Schema$1.Struct({
|
|
2417
2449
|
threadId: ThreadId,
|
|
2418
2450
|
messageId: MessageId,
|
|
@@ -2432,6 +2464,7 @@ const ThreadTurnStartRequestedPayload = Schema$1.Struct({
|
|
|
2432
2464
|
runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
|
|
2433
2465
|
interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
|
|
2434
2466
|
compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
2467
|
+
unpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
2435
2468
|
sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
|
|
2436
2469
|
createdAt: IsoDateTime
|
|
2437
2470
|
});
|
|
@@ -2581,6 +2614,11 @@ const OrchestrationEvent = Schema$1.Union([
|
|
|
2581
2614
|
type: Schema$1.Literal("thread.compress-mode-set"),
|
|
2582
2615
|
payload: ThreadCompressModeSetPayload$1
|
|
2583
2616
|
}),
|
|
2617
|
+
Schema$1.Struct({
|
|
2618
|
+
...EventBaseFields,
|
|
2619
|
+
type: Schema$1.Literal("thread.unprompted-subagents-set"),
|
|
2620
|
+
payload: ThreadUnpromptedSubagentsSetPayload$1
|
|
2621
|
+
}),
|
|
2584
2622
|
Schema$1.Struct({
|
|
2585
2623
|
...EventBaseFields,
|
|
2586
2624
|
type: Schema$1.Literal("thread.message-sent"),
|
|
@@ -3430,6 +3468,36 @@ const PreviewAutomationNetworkEntry = Schema.Struct({
|
|
|
3430
3468
|
errorText: Schema.optional(Schema.String),
|
|
3431
3469
|
timestamp: Schema.String
|
|
3432
3470
|
});
|
|
3471
|
+
/** Value of an accessibility state such as `expanded`, `checked` or `level`. */
|
|
3472
|
+
const PreviewAccessibilityState = Schema.Union([
|
|
3473
|
+
Schema.String,
|
|
3474
|
+
Schema.Number,
|
|
3475
|
+
Schema.Boolean
|
|
3476
|
+
]);
|
|
3477
|
+
/**
|
|
3478
|
+
* A node of the compacted accessibility tree. `parentId` points at the nearest
|
|
3479
|
+
* emitted ancestor, so the hierarchy is reconstructible without child lists.
|
|
3480
|
+
*/
|
|
3481
|
+
const PreviewAccessibilityNode = Schema.Struct({
|
|
3482
|
+
id: Schema.String,
|
|
3483
|
+
parentId: Schema.optional(Schema.String),
|
|
3484
|
+
role: Schema.String,
|
|
3485
|
+
name: Schema.optional(Schema.String),
|
|
3486
|
+
description: Schema.optional(Schema.String),
|
|
3487
|
+
value: Schema.optional(Schema.String),
|
|
3488
|
+
states: Schema.optional(Schema.Record(Schema.String, PreviewAccessibilityState))
|
|
3489
|
+
});
|
|
3490
|
+
/**
|
|
3491
|
+
* Semantic nodes only: ignored nodes, raw text nodes and unnamed layout
|
|
3492
|
+
* wrappers are dropped, and the node list is capped. `totalNodes` counts the
|
|
3493
|
+
* nodes that survived filtering, so `truncated` distinguishes a clipped tree
|
|
3494
|
+
* from a small page.
|
|
3495
|
+
*/
|
|
3496
|
+
const PreviewAccessibilitySnapshot = Schema.Struct({
|
|
3497
|
+
nodes: Schema.Array(PreviewAccessibilityNode),
|
|
3498
|
+
totalNodes: Schema.Int,
|
|
3499
|
+
truncated: Schema.Boolean
|
|
3500
|
+
});
|
|
3433
3501
|
const PreviewAutomationActionEvent = Schema.Struct({
|
|
3434
3502
|
id: Schema.String,
|
|
3435
3503
|
action: Schema.String,
|
|
@@ -3449,7 +3517,7 @@ const PreviewAutomationSnapshot = Schema.Struct({
|
|
|
3449
3517
|
loading: Schema.Boolean,
|
|
3450
3518
|
visibleText: Schema.String,
|
|
3451
3519
|
interactiveElements: Schema.Array(PreviewAutomationElement),
|
|
3452
|
-
accessibilityTree:
|
|
3520
|
+
accessibilityTree: PreviewAccessibilitySnapshot,
|
|
3453
3521
|
consoleEntries: Schema.Array(PreviewAutomationConsoleEntry),
|
|
3454
3522
|
networkEntries: Schema.Array(PreviewAutomationNetworkEntry),
|
|
3455
3523
|
actionTimeline: Schema.Array(PreviewAutomationActionEvent),
|
|
@@ -4557,7 +4625,8 @@ const ProviderSessionStartInput = Schema$1.Struct({
|
|
|
4557
4625
|
approvalPolicy: Schema$1.optional(ProviderApprovalPolicy),
|
|
4558
4626
|
sandboxMode: Schema$1.optional(ProviderSandboxMode),
|
|
4559
4627
|
runtimeMode: RuntimeMode,
|
|
4560
|
-
compressMode: Schema$1.optional(CompressMode)
|
|
4628
|
+
compressMode: Schema$1.optional(CompressMode),
|
|
4629
|
+
unpromptedSubagents: Schema$1.optional(Schema$1.Boolean)
|
|
4561
4630
|
});
|
|
4562
4631
|
const ProviderSendTurnInput = Schema$1.Struct({
|
|
4563
4632
|
threadId: ThreadId,
|
|
@@ -4565,7 +4634,8 @@ const ProviderSendTurnInput = Schema$1.Struct({
|
|
|
4565
4634
|
attachments: Schema$1.optional(Schema$1.Array(ChatAttachment).check(Schema$1.isMaxLength(8))),
|
|
4566
4635
|
modelSelection: Schema$1.optional(ModelSelection),
|
|
4567
4636
|
interactionMode: Schema$1.optional(ProviderInteractionMode),
|
|
4568
|
-
compressMode: Schema$1.optional(CompressMode)
|
|
4637
|
+
compressMode: Schema$1.optional(CompressMode),
|
|
4638
|
+
unpromptedSubagents: Schema$1.optional(Schema$1.Boolean)
|
|
4569
4639
|
});
|
|
4570
4640
|
Schema$1.Struct({
|
|
4571
4641
|
threadId: ThreadId,
|
|
@@ -5823,6 +5893,45 @@ const ServerSettings = Schema$1.Struct({
|
|
|
5823
5893
|
* instruction can override an earlier general one.
|
|
5824
5894
|
*/
|
|
5825
5895
|
enableUnpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
5896
|
+
/**
|
|
5897
|
+
* Whether the board offers the scoping agent: the Scope action on a task and
|
|
5898
|
+
* the panel that drafts a new one by interview.
|
|
5899
|
+
*
|
|
5900
|
+
* A switch rather than a permanent fixture because the discipline it imposes
|
|
5901
|
+
* — one question at a time, no file edits, a task body with verifiable
|
|
5902
|
+
* criteria — is a way of working, not a fact about the product. Someone who
|
|
5903
|
+
* writes their own tasks wants the button gone, not ignored.
|
|
5904
|
+
*
|
|
5905
|
+
* Off hides the entry points. It does not delete the skill file already
|
|
5906
|
+
* written into a repository, and it does not stop anyone invoking the same
|
|
5907
|
+
* discipline by name from an ordinary chat: that is what {@link disabledSkills}
|
|
5908
|
+
* is for.
|
|
5909
|
+
*/
|
|
5910
|
+
enableScopingAgent: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
5911
|
+
/**
|
|
5912
|
+
* Whether the board offers the plan phase: splitting one scoped task into
|
|
5913
|
+
* ordered subtasks. Separate from {@link enableScopingAgent} because the two
|
|
5914
|
+
* are useful apart — scoping a task by interview says nothing about wanting
|
|
5915
|
+
* it decomposed, and a board that plans everything into five rows is a board
|
|
5916
|
+
* nobody reads.
|
|
5917
|
+
*/
|
|
5918
|
+
enablePlanPhase: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
5919
|
+
/**
|
|
5920
|
+
* Whether the scoping and planning flows write their generated `SKILL.md`
|
|
5921
|
+
* into the repository they run in.
|
|
5922
|
+
*
|
|
5923
|
+
* Its own switch because it is the only one of the three with a side effect
|
|
5924
|
+
* outside p4code: the file lands in the working tree and shows up in
|
|
5925
|
+
* `git status`, which is unwelcome in a repo whose `.claude/` is checked in
|
|
5926
|
+
* and shared. Off does not cost the discipline — the thread seed carries the
|
|
5927
|
+
* rules inline instead, exactly as the create flow already does for providers
|
|
5928
|
+
* with no notion of a skill — it costs only invoking it by name later from an
|
|
5929
|
+
* ordinary chat.
|
|
5930
|
+
*
|
|
5931
|
+
* Files already written are left alone. Nothing here deletes anything from a
|
|
5932
|
+
* user's repository.
|
|
5933
|
+
*/
|
|
5934
|
+
writeGeneratedSkillsToRepo: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
5826
5935
|
automaticGitFetchInterval: Schema$1.DurationFromMillis.pipe(Schema$1.withDecodingDefault(Effect.succeed(Duration.toMillis(DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL)))),
|
|
5827
5936
|
defaultThreadEnvMode: ThreadEnvMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("local"))),
|
|
5828
5937
|
newWorktreesStartFromOrigin: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
@@ -5958,6 +6067,9 @@ const ServerSettingsPatch = Schema$1.Struct({
|
|
|
5958
6067
|
enableProviderUpdateChecks: Schema$1.optionalKey(Schema$1.Boolean),
|
|
5959
6068
|
enableToolCallNarration: Schema$1.optionalKey(Schema$1.Boolean),
|
|
5960
6069
|
enableUnpromptedSubagents: Schema$1.optionalKey(Schema$1.Boolean),
|
|
6070
|
+
enableScopingAgent: Schema$1.optionalKey(Schema$1.Boolean),
|
|
6071
|
+
enablePlanPhase: Schema$1.optionalKey(Schema$1.Boolean),
|
|
6072
|
+
writeGeneratedSkillsToRepo: Schema$1.optionalKey(Schema$1.Boolean),
|
|
5961
6073
|
automaticGitFetchInterval: Schema$1.optionalKey(Schema$1.DurationFromMillis),
|
|
5962
6074
|
defaultThreadEnvMode: Schema$1.optionalKey(ThreadEnvMode),
|
|
5963
6075
|
newWorktreesStartFromOrigin: Schema$1.optionalKey(Schema$1.Boolean),
|
|
@@ -7218,6 +7330,36 @@ const RepositoryKeyField = TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({
|
|
|
7218
7330
|
* placed by hand and falls back to the priority/recency order.
|
|
7219
7331
|
*/
|
|
7220
7332
|
const OrderKeyField = TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({ description: "Manual board position key. Lexicographic: smaller sorts higher in the column. Null means no manual position." }));
|
|
7333
|
+
/**
|
|
7334
|
+
* Where a task came from when it did not originate on this board.
|
|
7335
|
+
*
|
|
7336
|
+
* The identifier is the tracker's own, not ours: `MOBILE-12262` reads the same
|
|
7337
|
+
* in p4code as it does in Linear, in a commit message, and in conversation,
|
|
7338
|
+
* which is the whole point of carrying it. `url` is what the tracker itself
|
|
7339
|
+
* reported, never a guess assembled from the identifier - a Linear URL embeds
|
|
7340
|
+
* the workspace slug, so a constructed one would 404.
|
|
7341
|
+
*/
|
|
7342
|
+
const TaskExternalRef = Schema$1.Struct({
|
|
7343
|
+
source: Schema$1.Literals(["linear"]),
|
|
7344
|
+
identifier: TrimmedNonEmptyString,
|
|
7345
|
+
url: TrimmedNonEmptyString
|
|
7346
|
+
});
|
|
7347
|
+
const ExternalRefField = TaskExternalRef.pipe(Schema$1.annotateEncoded({ description: "The tracker issue this task mirrors, e.g. a Linear ticket. Null for a task that originated on this board." }));
|
|
7348
|
+
/**
|
|
7349
|
+
* The task this one was split out of.
|
|
7350
|
+
*
|
|
7351
|
+
* Carried as a field rather than as a sentence in the body because the plan
|
|
7352
|
+
* phase writes it and the board reads it: a parent chip, a subtask list and
|
|
7353
|
+
* "does this still have unfinished children" are all questions about the graph,
|
|
7354
|
+
* and prose cannot be asked them. Stored as the parent's UUID, but accepted as
|
|
7355
|
+
* either a UUID or a readable id on the way in - a planning agent works in
|
|
7356
|
+
* `P4-12`, and making it look up a UUID first is a round trip for nothing.
|
|
7357
|
+
*
|
|
7358
|
+
* One level is all this promises. Nothing forbids a subtask of a subtask, and
|
|
7359
|
+
* nothing walks the chain either; the board renders the direct children of a
|
|
7360
|
+
* task and stops.
|
|
7361
|
+
*/
|
|
7362
|
+
const ParentTaskIdField = TaskId.pipe(Schema$1.annotateEncoded({ description: "The task this one is a subtask of - the parent's UUID or readable id (e.g. P4-12). Null for a task that is not part of a larger one." }));
|
|
7221
7363
|
const LabelsField = Schema$1.Array(TaskLabel).check(Schema$1.isMaxLength(TASK_LABELS_MAX_COUNT)).pipe(Schema$1.annotateEncoded({ description: "Free-form tags used to group and filter tasks." }));
|
|
7222
7364
|
const TaskIdField = TaskId.pipe(Schema$1.annotateEncoded({ description: "Id of the task to act on - the UUID or the readable id (e.g. P4-12)." }));
|
|
7223
7365
|
const Task = Schema$1.Struct({
|
|
@@ -7259,6 +7401,20 @@ const Task = Schema$1.Struct({
|
|
|
7259
7401
|
* to a history.
|
|
7260
7402
|
*/
|
|
7261
7403
|
threadId: Schema$1.NullOr(ThreadId),
|
|
7404
|
+
/**
|
|
7405
|
+
* The tracker issue this task mirrors, or `null` for a task that was filed
|
|
7406
|
+
* here. Nullable-with-default for the same version-skew reason as
|
|
7407
|
+
* `readableId` above: a row from a store without the migration decodes to
|
|
7408
|
+
* `null` rather than failing the whole board.
|
|
7409
|
+
*/
|
|
7410
|
+
externalRef: Schema$1.NullOr(TaskExternalRef).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
7411
|
+
/**
|
|
7412
|
+
* The task this one was split out of, always as a UUID once stored - a
|
|
7413
|
+
* readable id given on the way in is resolved before the row is written, so
|
|
7414
|
+
* the link survives a board where readable ids were allocated elsewhere.
|
|
7415
|
+
* Nullable-with-default for the same version-skew reason as `readableId`.
|
|
7416
|
+
*/
|
|
7417
|
+
parentTaskId: Schema$1.NullOr(TaskId).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
7262
7418
|
title: TrimmedNonEmptyString.check(Schema$1.isMaxLength(TASK_TITLE_MAX_LENGTH)),
|
|
7263
7419
|
body: Schema$1.String,
|
|
7264
7420
|
status: StoredStatusField,
|
|
@@ -7272,6 +7428,8 @@ const TaskCreateInput = Schema$1.Struct({
|
|
|
7272
7428
|
projectId: Schema$1.optional(ProjectIdField),
|
|
7273
7429
|
repositoryKey: Schema$1.optional(RepositoryKeyField),
|
|
7274
7430
|
threadId: Schema$1.optional(ThreadIdField),
|
|
7431
|
+
externalRef: Schema$1.optional(ExternalRefField),
|
|
7432
|
+
parentTaskId: Schema$1.optional(ParentTaskIdField),
|
|
7275
7433
|
title: TitleField,
|
|
7276
7434
|
body: Schema$1.optional(BodyField),
|
|
7277
7435
|
status: Schema$1.optional(StatusField),
|
|
@@ -7310,6 +7468,8 @@ const TaskUpdateInput = Schema$1.Struct({
|
|
|
7310
7468
|
projectId: Schema$1.optional(Schema$1.NullOr(ProjectIdField)),
|
|
7311
7469
|
repositoryKey: Schema$1.optional(Schema$1.NullOr(RepositoryKeyField)),
|
|
7312
7470
|
threadId: Schema$1.optional(Schema$1.NullOr(ThreadIdField)),
|
|
7471
|
+
externalRef: Schema$1.optional(Schema$1.NullOr(ExternalRefField)),
|
|
7472
|
+
parentTaskId: Schema$1.optional(Schema$1.NullOr(ParentTaskIdField)),
|
|
7313
7473
|
title: Schema$1.optional(TitleField),
|
|
7314
7474
|
body: Schema$1.optional(BodyField),
|
|
7315
7475
|
status: Schema$1.optional(StatusField),
|
|
@@ -7675,6 +7835,58 @@ var ProjectWriteFileError = class extends Schema$1.TaggedErrorClass()("ProjectWr
|
|
|
7675
7835
|
}
|
|
7676
7836
|
};
|
|
7677
7837
|
//#endregion
|
|
7838
|
+
//#region ../../packages/contracts/src/ticket.ts
|
|
7839
|
+
/**
|
|
7840
|
+
* Reading an issue out of an external tracker.
|
|
7841
|
+
*
|
|
7842
|
+
* One call, deliberately: p4code does not sync trackers, it recognizes a ticket
|
|
7843
|
+
* somebody pasted and asks the tracker what it is called. Everything durable
|
|
7844
|
+
* that comes back is stored on a task as its {@link TaskExternalRef}.
|
|
7845
|
+
*
|
|
7846
|
+
* The tracker is reached through the MCP server the user already registered for
|
|
7847
|
+
* it, so there is no second place to configure credentials and no p4code-owned
|
|
7848
|
+
* API key. That also bounds what this can ever answer: a tracker with no MCP
|
|
7849
|
+
* server registered, or one never signed in to on this machine, is reported as
|
|
7850
|
+
* unconfigured rather than silently returning nothing.
|
|
7851
|
+
*
|
|
7852
|
+
* @module contracts/ticket
|
|
7853
|
+
*/
|
|
7854
|
+
/**
|
|
7855
|
+
* A tracker reference as it was typed, before anything has confirmed it exists.
|
|
7856
|
+
*
|
|
7857
|
+
* Deliberately not the parsed `{ source, identifier }` pair: what a user pastes
|
|
7858
|
+
* is a URL as often as an id, and which tracker a bare `MOBILE-12262` belongs
|
|
7859
|
+
* to is a question only the resolver can answer.
|
|
7860
|
+
*/
|
|
7861
|
+
const TicketResolveInput = Schema$1.Struct({ reference: TrimmedNonEmptyString });
|
|
7862
|
+
const TicketResolveResult = Schema$1.Struct({
|
|
7863
|
+
externalRef: TaskExternalRef,
|
|
7864
|
+
/** The issue title as the tracker reports it, for the task that mirrors it. */
|
|
7865
|
+
title: TrimmedNonEmptyString
|
|
7866
|
+
});
|
|
7867
|
+
/**
|
|
7868
|
+
* Why a reference could not be turned into a ticket.
|
|
7869
|
+
*
|
|
7870
|
+
* The reason is separate from the detail because the client acts on it: an
|
|
7871
|
+
* unconfigured tracker is a thing the user can fix in Settings and is worth
|
|
7872
|
+
* saying so about, while `unavailable` is a retry and `not_found` usually means
|
|
7873
|
+
* a typo. `detail` is the sentence to show; the reason decides the shape.
|
|
7874
|
+
*/
|
|
7875
|
+
const TicketResolveFailureReason = Schema$1.Literals([
|
|
7876
|
+
"not_configured",
|
|
7877
|
+
"not_authorized",
|
|
7878
|
+
"not_found",
|
|
7879
|
+
"unavailable"
|
|
7880
|
+
]);
|
|
7881
|
+
var TicketResolveError = class extends Schema$1.TaggedErrorClass()("TicketResolveError", {
|
|
7882
|
+
reason: TicketResolveFailureReason,
|
|
7883
|
+
detail: Schema$1.String
|
|
7884
|
+
}) {
|
|
7885
|
+
get message() {
|
|
7886
|
+
return this.detail;
|
|
7887
|
+
}
|
|
7888
|
+
};
|
|
7889
|
+
//#endregion
|
|
7678
7890
|
//#region ../../packages/contracts/src/threadControl.ts
|
|
7679
7891
|
/**
|
|
7680
7892
|
* Thread control over MCP - the self-scoped toolkit an agent uses to act on
|
|
@@ -7693,6 +7905,11 @@ var ProjectWriteFileError = class extends Schema$1.TaggedErrorClass()("ProjectWr
|
|
|
7693
7905
|
* Quick-append to memory lives here too: it is the other thing an agent wants
|
|
7694
7906
|
* to do *from* a thread, and it shares the toolkit's capability and scope.
|
|
7695
7907
|
*
|
|
7908
|
+
* Compressing an asset joins them for a different reason. It is a write the
|
|
7909
|
+
* agent could perform with its ordinary file tools, and the point of routing it
|
|
7910
|
+
* through a tool instead is that the server gets to check the rewrite before it
|
|
7911
|
+
* lands - and to keep the original somewhere the rewrite cannot reach.
|
|
7912
|
+
*
|
|
7696
7913
|
* @module contracts/threadControl
|
|
7697
7914
|
*/
|
|
7698
7915
|
const ThreadRenameInput = Schema$1.Struct({ title: TrimmedNonEmptyString.annotate({ description: "The new thread title. Replaces the current one." }) });
|
|
@@ -7719,6 +7936,23 @@ const MemoryAppendResult = Schema$1.Struct({
|
|
|
7719
7936
|
/** Absolute path the append landed in, so the agent can cite or inspect it. */
|
|
7720
7937
|
path: Schema$1.String
|
|
7721
7938
|
});
|
|
7939
|
+
const AssetCompressInput = Schema$1.Struct({
|
|
7940
|
+
path: TrimmedNonEmptyString.annotate({ description: "Absolute path of the asset file to overwrite. Must sit inside one of this machine's agent asset directories: user skills, the provider config directory that holds the memory files, or the subagent definitions directory." }),
|
|
7941
|
+
content: Schema$1.String.check(Schema$1.isNonEmpty()).annotate({ description: "The compressed file, whole. Headings, fenced code blocks, inline code, URLs, paths and any YAML frontmatter must come back unchanged; only the prose around them may be rewritten." })
|
|
7942
|
+
});
|
|
7943
|
+
const AssetCompressResult = Schema$1.Struct({
|
|
7944
|
+
/** Absolute path that was rewritten. */
|
|
7945
|
+
path: Schema$1.String,
|
|
7946
|
+
/** Where the pre-compression original was kept, outside every synced directory. */
|
|
7947
|
+
backupPath: Schema$1.String,
|
|
7948
|
+
charsBefore: Schema$1.Number,
|
|
7949
|
+
charsAfter: Schema$1.Number,
|
|
7950
|
+
/** Estimated at four characters per token, not measured by a provider tokenizer. */
|
|
7951
|
+
estimatedTokensBefore: Schema$1.Number,
|
|
7952
|
+
estimatedTokensAfter: Schema$1.Number,
|
|
7953
|
+
/** Differences worth reporting that were not worth refusing the write over. */
|
|
7954
|
+
warnings: Schema$1.Array(Schema$1.String)
|
|
7955
|
+
});
|
|
7722
7956
|
var ThreadToolUnavailableError = class extends Schema$1.TaggedErrorClass()("ThreadToolUnavailableError", {
|
|
7723
7957
|
capability: Schema$1.Literal("threads"),
|
|
7724
7958
|
environmentId: EnvironmentId,
|
|
@@ -7747,10 +7981,43 @@ var MemoryAppendFailedError = class extends Schema$1.TaggedErrorClass()("MemoryA
|
|
|
7747
7981
|
return `Appending to ${this.file} failed: ${this.detail}`;
|
|
7748
7982
|
}
|
|
7749
7983
|
};
|
|
7984
|
+
/**
|
|
7985
|
+
* The compression will not be attempted, or the file could not be read.
|
|
7986
|
+
*
|
|
7987
|
+
* Separate from the validation failure below because they want opposite
|
|
7988
|
+
* responses. A refusal is final - the path is not an asset, the name looks like
|
|
7989
|
+
* a credential, the file is not there - and retrying it produces the same
|
|
7990
|
+
* answer. A validation failure is a rewrite that can be corrected.
|
|
7991
|
+
*/
|
|
7992
|
+
var AssetCompressRefusedError = class extends Schema$1.TaggedErrorClass()("AssetCompressRefusedError", {
|
|
7993
|
+
path: Schema$1.String,
|
|
7994
|
+
detail: Schema$1.String
|
|
7995
|
+
}) {
|
|
7996
|
+
get message() {
|
|
7997
|
+
return `Compressing ${this.path} was refused: ${this.detail}`;
|
|
7998
|
+
}
|
|
7999
|
+
};
|
|
8000
|
+
/**
|
|
8001
|
+
* The rewrite lost something, and nothing was written.
|
|
8002
|
+
*
|
|
8003
|
+
* Carries the checks that failed rather than a summary, because the agent's
|
|
8004
|
+
* next move is to restore exactly those things from the original and call
|
|
8005
|
+
* again. The file on disk is untouched, so a second failure costs nothing more.
|
|
8006
|
+
*/
|
|
8007
|
+
var AssetCompressValidationFailedError = class extends Schema$1.TaggedErrorClass()("AssetCompressValidationFailedError", {
|
|
8008
|
+
path: Schema$1.String,
|
|
8009
|
+
errors: Schema$1.Array(Schema$1.String)
|
|
8010
|
+
}) {
|
|
8011
|
+
get message() {
|
|
8012
|
+
return `The compressed ${this.path} did not validate, so nothing was written: ${this.errors.join(" ")}`;
|
|
8013
|
+
}
|
|
8014
|
+
};
|
|
7750
8015
|
const ThreadControlToolError = Schema$1.Union([
|
|
7751
8016
|
ThreadToolUnavailableError,
|
|
7752
8017
|
ThreadRenameRejectedError,
|
|
7753
|
-
MemoryAppendFailedError
|
|
8018
|
+
MemoryAppendFailedError,
|
|
8019
|
+
AssetCompressRefusedError,
|
|
8020
|
+
AssetCompressValidationFailedError
|
|
7754
8021
|
]);
|
|
7755
8022
|
const ThreadWatchEventsInput = Schema$1.Struct({
|
|
7756
8023
|
threadId: ThreadId.annotate({ description: "The watched thread to read events from. Must be explicitly granted." }),
|
|
@@ -8726,6 +8993,7 @@ const WS_METHODS = {
|
|
|
8726
8993
|
tasksUpdate: "tasks.update",
|
|
8727
8994
|
tasksDelete: "tasks.delete",
|
|
8728
8995
|
tasksStartThread: "tasks.startThread",
|
|
8996
|
+
ticketsResolve: "tickets.resolve",
|
|
8729
8997
|
hubGetSyncStatus: "hub.getSyncStatus",
|
|
8730
8998
|
hubConnect: "hub.connect",
|
|
8731
8999
|
hubDisconnect: "hub.disconnect",
|
|
@@ -9033,6 +9301,17 @@ const WsMcpOAuthDisconnectRpc = Rpc.make(WS_METHODS.mcpOAuthDisconnect, {
|
|
|
9033
9301
|
error: Schema$1.Union([McpRegistryError, EnvironmentAuthorizationError])
|
|
9034
9302
|
});
|
|
9035
9303
|
/**
|
|
9304
|
+
* Asks the tracker what a pasted reference is, without writing anything.
|
|
9305
|
+
*
|
|
9306
|
+
* Read-only on purpose: the caller decides whether the answer becomes a task.
|
|
9307
|
+
* A resolve that filed a row would make an accidental paste a board entry.
|
|
9308
|
+
*/
|
|
9309
|
+
const WsTicketsResolveRpc = Rpc.make(WS_METHODS.ticketsResolve, {
|
|
9310
|
+
payload: TicketResolveInput,
|
|
9311
|
+
success: TicketResolveResult,
|
|
9312
|
+
error: Schema$1.Union([TicketResolveError, EnvironmentAuthorizationError])
|
|
9313
|
+
});
|
|
9314
|
+
/**
|
|
9036
9315
|
* The board, then every change to it, for as long as the client stays
|
|
9037
9316
|
* subscribed. The leading snapshot is what makes this sufficient on its own —
|
|
9038
9317
|
* a client does not list first, so there is no window between the two in which
|
|
@@ -9410,7 +9689,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
|
|
|
9410
9689
|
error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
|
|
9411
9690
|
stream: true
|
|
9412
9691
|
});
|
|
9413
|
-
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, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
9692
|
+
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, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsTicketsResolveRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
9414
9693
|
//#endregion
|
|
9415
9694
|
//#region ../../packages/shared/src/oauthScope.ts
|
|
9416
9695
|
const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
|
|
@@ -9556,7 +9835,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
9556
9835
|
//#endregion
|
|
9557
9836
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
9558
9837
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
9559
|
-
const make$
|
|
9838
|
+
const make$74 = Effect.gen(function* () {
|
|
9560
9839
|
const config = yield* ServerConfig$1;
|
|
9561
9840
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
9562
9841
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -9574,7 +9853,7 @@ const make$73 = Effect.gen(function* () {
|
|
|
9574
9853
|
};
|
|
9575
9854
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
9576
9855
|
});
|
|
9577
|
-
const layer$
|
|
9856
|
+
const layer$70 = Layer.effect(EnvironmentAuthPolicy, make$74);
|
|
9578
9857
|
//#endregion
|
|
9579
9858
|
//#region src/persistence/Errors.ts
|
|
9580
9859
|
function summarizeSchemaIssue(issue) {
|
|
@@ -9755,7 +10034,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
9755
10034
|
cause
|
|
9756
10035
|
});
|
|
9757
10036
|
}
|
|
9758
|
-
const make$
|
|
10037
|
+
const make$73 = Effect.gen(function* () {
|
|
9759
10038
|
const sql = yield* SqlClient.SqlClient;
|
|
9760
10039
|
const createSessionRow = SqlSchema.void({
|
|
9761
10040
|
Request: CreateAuthSessionInput,
|
|
@@ -9889,7 +10168,7 @@ const make$72 = Effect.gen(function* () {
|
|
|
9889
10168
|
setLastConnectedAt
|
|
9890
10169
|
};
|
|
9891
10170
|
});
|
|
9892
|
-
const layer$
|
|
10171
|
+
const layer$69 = Layer.effect(AuthSessionRepository, make$73);
|
|
9893
10172
|
//#endregion
|
|
9894
10173
|
//#region src/auth/ServerSecretStore.ts
|
|
9895
10174
|
const secretStoreErrorContext = {
|
|
@@ -9956,7 +10235,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
|
|
|
9956
10235
|
const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
|
|
9957
10236
|
const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
|
|
9958
10237
|
var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
|
|
9959
|
-
const make$
|
|
10238
|
+
const make$72 = Effect.gen(function* () {
|
|
9960
10239
|
const crypto = yield* Crypto.Crypto;
|
|
9961
10240
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
9962
10241
|
const path = yield* Path.Path;
|
|
@@ -10026,7 +10305,7 @@ const make$71 = Effect.gen(function* () {
|
|
|
10026
10305
|
remove
|
|
10027
10306
|
});
|
|
10028
10307
|
});
|
|
10029
|
-
const layer$
|
|
10308
|
+
const layer$68 = Layer.effect(ServerSecretStore, make$72);
|
|
10030
10309
|
//#endregion
|
|
10031
10310
|
//#region src/auth/SessionStore.ts
|
|
10032
10311
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -10264,7 +10543,7 @@ function toAuthClientSession(input) {
|
|
|
10264
10543
|
current: false
|
|
10265
10544
|
};
|
|
10266
10545
|
}
|
|
10267
|
-
const make$
|
|
10546
|
+
const make$71 = Effect.gen(function* () {
|
|
10268
10547
|
const crypto = yield* Crypto.Crypto;
|
|
10269
10548
|
const serverConfig = yield* ServerConfig$1;
|
|
10270
10549
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -10578,7 +10857,7 @@ const make$70 = Effect.gen(function* () {
|
|
|
10578
10857
|
markDisconnected
|
|
10579
10858
|
});
|
|
10580
10859
|
});
|
|
10581
|
-
const layer$
|
|
10860
|
+
const layer$67 = Layer.effect(SessionStore, make$71).pipe(Layer.provideMerge(layer$69));
|
|
10582
10861
|
//#endregion
|
|
10583
10862
|
//#region src/persistence/AuthPairingLinks.ts
|
|
10584
10863
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -10639,7 +10918,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
10639
10918
|
cause
|
|
10640
10919
|
});
|
|
10641
10920
|
}
|
|
10642
|
-
const make$
|
|
10921
|
+
const make$70 = Effect.gen(function* () {
|
|
10643
10922
|
const sql = yield* SqlClient.SqlClient;
|
|
10644
10923
|
const createPairingLinkRow = SqlSchema.void({
|
|
10645
10924
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -10774,7 +11053,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
10774
11053
|
getByCredential
|
|
10775
11054
|
};
|
|
10776
11055
|
});
|
|
10777
|
-
const layer$
|
|
11056
|
+
const layer$66 = Layer.effect(AuthPairingLinkRepository, make$70);
|
|
10778
11057
|
//#endregion
|
|
10779
11058
|
//#region src/auth/PairingGrantStore.ts
|
|
10780
11059
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -10869,7 +11148,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
10869
11148
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
10870
11149
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
10871
11150
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
10872
|
-
const make$
|
|
11151
|
+
const make$69 = Effect.gen(function* () {
|
|
10873
11152
|
const crypto = yield* Crypto.Crypto;
|
|
10874
11153
|
const config = yield* ServerConfig$1;
|
|
10875
11154
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -11067,7 +11346,7 @@ const make$68 = Effect.gen(function* () {
|
|
|
11067
11346
|
consume
|
|
11068
11347
|
});
|
|
11069
11348
|
});
|
|
11070
|
-
const layer$
|
|
11349
|
+
const layer$65 = Layer.effect(PairingGrantStore, make$69).pipe(Layer.provideMerge(layer$66));
|
|
11071
11350
|
//#endregion
|
|
11072
11351
|
//#region src/persistence/Migrations/001_OrchestrationEvents.ts
|
|
11073
11352
|
var _001_OrchestrationEvents_default = Effect.gen(function* () {
|
|
@@ -12520,6 +12799,75 @@ var _039_ProjectionThreadsCompressMode_default = Effect.gen(function* () {
|
|
|
12520
12799
|
`;
|
|
12521
12800
|
});
|
|
12522
12801
|
//#endregion
|
|
12802
|
+
//#region src/persistence/Migrations/040_TaskExternalRef.ts
|
|
12803
|
+
/**
|
|
12804
|
+
* The tracker issue a task mirrors, for tasks that did not start on this board.
|
|
12805
|
+
*
|
|
12806
|
+
* Stored as one JSON blob rather than three columns because nothing queries
|
|
12807
|
+
* inside it except the uniqueness check below, and a tracker's shape is not
|
|
12808
|
+
* ours to normalize - a second source will bring fields Linear does not have.
|
|
12809
|
+
*
|
|
12810
|
+
* The unique index is over the identifier alone, extracted from the JSON: it is
|
|
12811
|
+
* what stops a second paste of the same ticket from filing a duplicate task.
|
|
12812
|
+
* Partial, so the many rows with no external ref do not collide on NULL.
|
|
12813
|
+
*/
|
|
12814
|
+
var _040_TaskExternalRef_default = Effect.gen(function* () {
|
|
12815
|
+
const sql = yield* SqlClient.SqlClient;
|
|
12816
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN external_ref_json TEXT`;
|
|
12817
|
+
yield* sql`
|
|
12818
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_external_ref_identifier
|
|
12819
|
+
ON tasks(json_extract(external_ref_json, '$.identifier'))
|
|
12820
|
+
WHERE external_ref_json IS NOT NULL
|
|
12821
|
+
`;
|
|
12822
|
+
});
|
|
12823
|
+
//#endregion
|
|
12824
|
+
//#region src/persistence/Migrations/041_TaskParentTaskId.ts
|
|
12825
|
+
/**
|
|
12826
|
+
* The task a task was split out of, for the plan phase's subtasks.
|
|
12827
|
+
*
|
|
12828
|
+
* A plain column rather than a join table: a task has at most one parent, and
|
|
12829
|
+
* the question asked of it is always "children of this row", which one indexed
|
|
12830
|
+
* column answers.
|
|
12831
|
+
*
|
|
12832
|
+
* No foreign key. Tasks are synced between machines and a child can arrive
|
|
12833
|
+
* before its parent does, or outlive it - a constraint would reject the write
|
|
12834
|
+
* rather than leave a link that resolves later. The board treats a parent it
|
|
12835
|
+
* cannot find as no parent at all.
|
|
12836
|
+
*
|
|
12837
|
+
* The index is non-unique and partial: many children per parent, and the many
|
|
12838
|
+
* rows that are nobody's child stay out of it.
|
|
12839
|
+
*/
|
|
12840
|
+
var _041_TaskParentTaskId_default = Effect.gen(function* () {
|
|
12841
|
+
const sql = yield* SqlClient.SqlClient;
|
|
12842
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`;
|
|
12843
|
+
yield* sql`
|
|
12844
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_parent_task_id
|
|
12845
|
+
ON tasks(parent_task_id)
|
|
12846
|
+
WHERE parent_task_id IS NOT NULL
|
|
12847
|
+
`;
|
|
12848
|
+
});
|
|
12849
|
+
//#endregion
|
|
12850
|
+
//#region src/persistence/Migrations/042_ProjectionThreadsUnpromptedSubagents.ts
|
|
12851
|
+
/**
|
|
12852
|
+
* Whether a thread lets the model spawn subagents without being asked, moved
|
|
12853
|
+
* from a machine-wide setting onto the thread itself.
|
|
12854
|
+
*
|
|
12855
|
+
* Stored as an integer beside `has_actionable_proposed_plan` rather than as a
|
|
12856
|
+
* SQLite boolean, which does not exist; the projection reads it back as
|
|
12857
|
+
* `> 0`.
|
|
12858
|
+
*
|
|
12859
|
+
* The default is `1` — subagents allowed — because that is what every existing
|
|
12860
|
+
* thread has been doing under the old server setting. Anything else would
|
|
12861
|
+
* change the behaviour of live threads on upgrade, which is not a migration's
|
|
12862
|
+
* business.
|
|
12863
|
+
*/
|
|
12864
|
+
var _042_ProjectionThreadsUnpromptedSubagents_default = Effect.gen(function* () {
|
|
12865
|
+
yield* (yield* SqlClient.SqlClient)`
|
|
12866
|
+
ALTER TABLE projection_threads
|
|
12867
|
+
ADD COLUMN unprompted_subagents INTEGER NOT NULL DEFAULT 1
|
|
12868
|
+
`;
|
|
12869
|
+
});
|
|
12870
|
+
//#endregion
|
|
12523
12871
|
//#region src/persistence/Migrations.ts
|
|
12524
12872
|
/**
|
|
12525
12873
|
* MigrationsLive - Migration runner with inline loader
|
|
@@ -12735,6 +13083,21 @@ const migrationEntries = [
|
|
|
12735
13083
|
39,
|
|
12736
13084
|
"ProjectionThreadsCompressMode",
|
|
12737
13085
|
_039_ProjectionThreadsCompressMode_default
|
|
13086
|
+
],
|
|
13087
|
+
[
|
|
13088
|
+
40,
|
|
13089
|
+
"TaskExternalRef",
|
|
13090
|
+
_040_TaskExternalRef_default
|
|
13091
|
+
],
|
|
13092
|
+
[
|
|
13093
|
+
41,
|
|
13094
|
+
"TaskParentTaskId",
|
|
13095
|
+
_041_TaskParentTaskId_default
|
|
13096
|
+
],
|
|
13097
|
+
[
|
|
13098
|
+
42,
|
|
13099
|
+
"ProjectionThreadsUnpromptedSubagents",
|
|
13100
|
+
_042_ProjectionThreadsUnpromptedSubagents_default
|
|
12738
13101
|
]
|
|
12739
13102
|
];
|
|
12740
13103
|
const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -12922,7 +13285,7 @@ function parseBearerToken(request) {
|
|
|
12922
13285
|
const token = header.slice(7).trim();
|
|
12923
13286
|
return token.length > 0 ? token : null;
|
|
12924
13287
|
}
|
|
12925
|
-
const make$
|
|
13288
|
+
const make$68 = Effect.gen(function* () {
|
|
12926
13289
|
const policy = yield* EnvironmentAuthPolicy;
|
|
12927
13290
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
12928
13291
|
const sessions = yield* SessionStore;
|
|
@@ -13117,9 +13480,9 @@ const make$67 = Effect.gen(function* () {
|
|
|
13117
13480
|
issueStartupPairingUrl
|
|
13118
13481
|
});
|
|
13119
13482
|
});
|
|
13120
|
-
const layer$
|
|
13121
|
-
const storageLayer = Layer.mergeAll(layer$
|
|
13122
|
-
const runtimeLayer = layer$
|
|
13483
|
+
const layer$64 = Layer.effect(EnvironmentAuth, make$68).pipe(Layer.provideMerge(layer$65), Layer.provideMerge(layer$67), Layer.provideMerge(layer$70));
|
|
13484
|
+
const storageLayer = Layer.mergeAll(layer$68, layerConfig);
|
|
13485
|
+
const runtimeLayer = layer$64.pipe(Layer.provideMerge(storageLayer));
|
|
13123
13486
|
//#endregion
|
|
13124
13487
|
//#region src/cliAuthFormat.ts
|
|
13125
13488
|
const newline = "\n";
|
|
@@ -13874,7 +14237,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
|
|
|
13874
14237
|
}
|
|
13875
14238
|
return yield* Effect.gen(function* () {
|
|
13876
14239
|
return yield* run(yield* EnvironmentAuth);
|
|
13877
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$
|
|
14240
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$71(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
13878
14241
|
});
|
|
13879
14242
|
const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
|
|
13880
14243
|
const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
|
|
@@ -14014,7 +14377,7 @@ const DEFAULT_LIMITS = {
|
|
|
14014
14377
|
windowMillis: FAILURE_WINDOW_MS,
|
|
14015
14378
|
blockMillis: BLOCK_DURATION_MS
|
|
14016
14379
|
};
|
|
14017
|
-
const make$
|
|
14380
|
+
const make$67 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
14018
14381
|
const state = yield* Ref.make(initialThrottleState);
|
|
14019
14382
|
return HubAuthThrottle.of({
|
|
14020
14383
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -14028,7 +14391,7 @@ const make$66 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
|
|
|
14028
14391
|
})
|
|
14029
14392
|
});
|
|
14030
14393
|
});
|
|
14031
|
-
const layer$
|
|
14394
|
+
const layer$63 = Layer.effect(HubAuthThrottle, make$67());
|
|
14032
14395
|
//#endregion
|
|
14033
14396
|
//#region src/hub/HubAuth.ts
|
|
14034
14397
|
/**
|
|
@@ -14342,7 +14705,10 @@ const DeleteTaskInput = Schema$1.Struct({ taskId: TaskId });
|
|
|
14342
14705
|
var TaskRepository = class extends Context.Service()("@p4code/cli/persistence/Services/Tasks/TaskRepository") {};
|
|
14343
14706
|
//#endregion
|
|
14344
14707
|
//#region src/persistence/Layers/Tasks.ts
|
|
14345
|
-
const TaskDbRow = Task.mapFields(Struct.assign({
|
|
14708
|
+
const TaskDbRow = Task.mapFields(Struct.assign({
|
|
14709
|
+
labels: Schema$1.fromJsonString(Schema$1.Array(TaskLabel)),
|
|
14710
|
+
externalRef: Schema$1.NullOr(Schema$1.fromJsonString(TaskExternalRef))
|
|
14711
|
+
}));
|
|
14346
14712
|
/**
|
|
14347
14713
|
* The `list` filter with every field normalized to a bound `null` rather than
|
|
14348
14714
|
* an absent key. Each predicate is then `(:param IS NULL OR column = :param)`,
|
|
@@ -14362,6 +14728,8 @@ const TASK_COLUMNS = `
|
|
|
14362
14728
|
project_id AS "projectId",
|
|
14363
14729
|
repository_key AS "repositoryKey",
|
|
14364
14730
|
thread_id AS "threadId",
|
|
14731
|
+
external_ref_json AS "externalRef",
|
|
14732
|
+
parent_task_id AS "parentTaskId",
|
|
14365
14733
|
title,
|
|
14366
14734
|
body,
|
|
14367
14735
|
status,
|
|
@@ -14385,6 +14753,8 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
14385
14753
|
project_id,
|
|
14386
14754
|
repository_key,
|
|
14387
14755
|
thread_id,
|
|
14756
|
+
external_ref_json,
|
|
14757
|
+
parent_task_id,
|
|
14388
14758
|
title,
|
|
14389
14759
|
body,
|
|
14390
14760
|
status,
|
|
@@ -14401,6 +14771,8 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
14401
14771
|
${row.projectId},
|
|
14402
14772
|
${row.repositoryKey},
|
|
14403
14773
|
${row.threadId},
|
|
14774
|
+
${row.externalRef === null ? null : JSON.stringify(row.externalRef)},
|
|
14775
|
+
${row.parentTaskId},
|
|
14404
14776
|
${row.title},
|
|
14405
14777
|
${row.body},
|
|
14406
14778
|
${row.status},
|
|
@@ -14417,6 +14789,8 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
14417
14789
|
project_id = excluded.project_id,
|
|
14418
14790
|
repository_key = excluded.repository_key,
|
|
14419
14791
|
thread_id = excluded.thread_id,
|
|
14792
|
+
external_ref_json = excluded.external_ref_json,
|
|
14793
|
+
parent_task_id = excluded.parent_task_id,
|
|
14420
14794
|
title = excluded.title,
|
|
14421
14795
|
body = excluded.body,
|
|
14422
14796
|
status = excluded.status,
|
|
@@ -14515,6 +14889,8 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
14515
14889
|
...input.projectId !== void 0 ? { projectId: input.projectId } : {},
|
|
14516
14890
|
...input.repositoryKey !== void 0 ? { repositoryKey: input.repositoryKey } : {},
|
|
14517
14891
|
...input.threadId !== void 0 ? { threadId: input.threadId } : {},
|
|
14892
|
+
...input.externalRef !== void 0 ? { externalRef: input.externalRef } : {},
|
|
14893
|
+
...input.parentTaskId !== void 0 ? { parentTaskId: input.parentTaskId } : {},
|
|
14518
14894
|
...input.title !== void 0 ? { title: input.title } : {},
|
|
14519
14895
|
...input.body !== void 0 ? { body: input.body } : {},
|
|
14520
14896
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -14553,6 +14929,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
14553
14929
|
...input.patch.projectId !== void 0 ? { projectId: input.patch.projectId } : {},
|
|
14554
14930
|
...input.patch.repositoryKey !== void 0 ? { repositoryKey: input.patch.repositoryKey } : {},
|
|
14555
14931
|
...input.patch.threadId !== void 0 ? { threadId: input.patch.threadId } : {},
|
|
14932
|
+
...input.patch.parentTaskId !== void 0 ? { parentTaskId: input.patch.parentTaskId } : {},
|
|
14556
14933
|
...input.patch.title !== void 0 ? { title: input.patch.title } : {},
|
|
14557
14934
|
...input.patch.body !== void 0 ? { body: input.patch.body } : {},
|
|
14558
14935
|
...input.patch.status !== void 0 ? { status: input.patch.status } : {},
|
|
@@ -14686,6 +15063,8 @@ const createTaskRoute = HttpRouter.add("POST", "/tasks", respondToHubFailures(Ef
|
|
|
14686
15063
|
projectId: input.projectId ?? null,
|
|
14687
15064
|
repositoryKey: input.repositoryKey ?? null,
|
|
14688
15065
|
threadId: input.threadId ?? null,
|
|
15066
|
+
externalRef: input.externalRef ?? null,
|
|
15067
|
+
parentTaskId: input.parentTaskId ?? null,
|
|
14689
15068
|
title: input.title,
|
|
14690
15069
|
body: input.body ?? "",
|
|
14691
15070
|
status: input.status ?? "backlog",
|
|
@@ -14827,7 +15206,7 @@ const deleteAssetRoute = HttpRouter.add("DELETE", "/assets/:kind/:name", respond
|
|
|
14827
15206
|
const outcome = yield* (yield* AgentAssetRepository).deleteByName(requested);
|
|
14828
15207
|
return outcome._tag === "conflict" ? assetConflict(Option.getOrNull(outcome.current)) : HttpServerResponse.empty({ status: 204 });
|
|
14829
15208
|
})));
|
|
14830
|
-
const layer$
|
|
15209
|
+
const layer$62 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute);
|
|
14831
15210
|
//#endregion
|
|
14832
15211
|
//#region src/hub/Migrations/001_Tasks.ts
|
|
14833
15212
|
/**
|
|
@@ -14989,6 +15368,38 @@ var _005_TaskOrderKeys_default = Effect.gen(function* () {
|
|
|
14989
15368
|
yield* (yield* SqlClient.SqlClient)`ALTER TABLE tasks ADD COLUMN order_key TEXT`;
|
|
14990
15369
|
});
|
|
14991
15370
|
//#endregion
|
|
15371
|
+
//#region src/hub/Migrations/006_TaskExternalRef.ts
|
|
15372
|
+
/**
|
|
15373
|
+
* The tracker issue a task mirrors, mirroring the environment server's
|
|
15374
|
+
* migration 040. The hub carries the column so a task filed against a Linear
|
|
15375
|
+
* ticket on one machine still reads as that ticket on another.
|
|
15376
|
+
*/
|
|
15377
|
+
var _006_TaskExternalRef_default = Effect.gen(function* () {
|
|
15378
|
+
const sql = yield* SqlClient.SqlClient;
|
|
15379
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN external_ref_json TEXT`;
|
|
15380
|
+
yield* sql`
|
|
15381
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_external_ref_identifier
|
|
15382
|
+
ON tasks(json_extract(external_ref_json, '$.identifier'))
|
|
15383
|
+
WHERE external_ref_json IS NOT NULL
|
|
15384
|
+
`;
|
|
15385
|
+
});
|
|
15386
|
+
//#endregion
|
|
15387
|
+
//#region src/hub/Migrations/007_TaskParentTaskId.ts
|
|
15388
|
+
/**
|
|
15389
|
+
* The task a task was split out of, mirroring the environment server's
|
|
15390
|
+
* migration 041. The hub carries the column so a plan filed on one machine
|
|
15391
|
+
* still reads as a plan on another, rather than as a handful of loose tasks.
|
|
15392
|
+
*/
|
|
15393
|
+
var _007_TaskParentTaskId_default = Effect.gen(function* () {
|
|
15394
|
+
const sql = yield* SqlClient.SqlClient;
|
|
15395
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`;
|
|
15396
|
+
yield* sql`
|
|
15397
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_parent_task_id
|
|
15398
|
+
ON tasks(parent_task_id)
|
|
15399
|
+
WHERE parent_task_id IS NOT NULL
|
|
15400
|
+
`;
|
|
15401
|
+
});
|
|
15402
|
+
//#endregion
|
|
14992
15403
|
//#region src/hub/Migrations.ts
|
|
14993
15404
|
/**
|
|
14994
15405
|
* Hub migrations.
|
|
@@ -15024,6 +15435,16 @@ const hubMigrationEntries = [
|
|
|
15024
15435
|
5,
|
|
15025
15436
|
"TaskOrderKeys",
|
|
15026
15437
|
_005_TaskOrderKeys_default
|
|
15438
|
+
],
|
|
15439
|
+
[
|
|
15440
|
+
6,
|
|
15441
|
+
"TaskExternalRef",
|
|
15442
|
+
_006_TaskExternalRef_default
|
|
15443
|
+
],
|
|
15444
|
+
[
|
|
15445
|
+
7,
|
|
15446
|
+
"TaskParentTaskId",
|
|
15447
|
+
_007_TaskParentTaskId_default
|
|
15027
15448
|
]
|
|
15028
15449
|
];
|
|
15029
15450
|
const hubMigrationLoader = Migrator.fromRecord(Object.fromEntries(hubMigrationEntries.map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -15106,7 +15527,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
|
|
|
15106
15527
|
});
|
|
15107
15528
|
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 });
|
|
15108
15529
|
}));
|
|
15109
|
-
const makeHubLayer = HttpRouter.serve(layer$
|
|
15530
|
+
const makeHubLayer = HttpRouter.serve(layer$62).pipe(Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$63), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
|
|
15110
15531
|
const runHub = Layer.launch(makeHubLayer);
|
|
15111
15532
|
//#endregion
|
|
15112
15533
|
//#region src/atomicWrite.ts
|
|
@@ -15230,7 +15651,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
15230
15651
|
}
|
|
15231
15652
|
return Object.is(current, defaults) ? void 0 : current;
|
|
15232
15653
|
}
|
|
15233
|
-
const make$
|
|
15654
|
+
const make$66 = Effect.gen(function* () {
|
|
15234
15655
|
const { settingsPath } = yield* ServerConfig$1;
|
|
15235
15656
|
const fs = yield* FileSystem.FileSystem;
|
|
15236
15657
|
const pathService = yield* Path.Path;
|
|
@@ -15451,7 +15872,7 @@ const make$65 = Effect.gen(function* () {
|
|
|
15451
15872
|
}
|
|
15452
15873
|
};
|
|
15453
15874
|
});
|
|
15454
|
-
const layer$
|
|
15875
|
+
const layer$61 = Layer.effect(ServerSettingsService, make$66);
|
|
15455
15876
|
//#endregion
|
|
15456
15877
|
//#region src/pathExpansion.ts
|
|
15457
15878
|
/**
|
|
@@ -15793,7 +16214,7 @@ function claudeEntryFromRegistration(registration) {
|
|
|
15793
16214
|
};
|
|
15794
16215
|
}
|
|
15795
16216
|
var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
|
|
15796
|
-
const make$
|
|
16217
|
+
const make$65 = Effect.gen(function* () {
|
|
15797
16218
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
15798
16219
|
const path = yield* Path.Path;
|
|
15799
16220
|
const services = yield* Effect.context();
|
|
@@ -15858,7 +16279,7 @@ const make$64 = Effect.gen(function* () {
|
|
|
15858
16279
|
removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
|
|
15859
16280
|
};
|
|
15860
16281
|
});
|
|
15861
|
-
const layer$
|
|
16282
|
+
const layer$60 = Layer.effect(ClaudeMcpFiles, make$65);
|
|
15862
16283
|
Layer.succeed(ClaudeMcpFiles, {
|
|
15863
16284
|
readUser: Effect.succeed([]),
|
|
15864
16285
|
upsertUser: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
|
|
@@ -15994,7 +16415,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
|
|
|
15994
16415
|
const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
|
|
15995
16416
|
var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
|
|
15996
16417
|
const registryError = (detail) => new McpRegistryError({ detail });
|
|
15997
|
-
const make$
|
|
16418
|
+
const make$64 = Effect.gen(function* () {
|
|
15998
16419
|
const config = yield* ServerConfig$1;
|
|
15999
16420
|
const secrets = yield* ServerSecretStore;
|
|
16000
16421
|
const http = yield* HttpClient.HttpClient;
|
|
@@ -16314,7 +16735,7 @@ const make$63 = Effect.gen(function* () {
|
|
|
16314
16735
|
accessTokenFor
|
|
16315
16736
|
};
|
|
16316
16737
|
});
|
|
16317
|
-
const layer$
|
|
16738
|
+
const layer$59 = Layer.effect(McpOAuth, make$64);
|
|
16318
16739
|
Layer.succeed(McpOAuth, {
|
|
16319
16740
|
statusFor: () => Effect.succeed(Option.none()),
|
|
16320
16741
|
begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
|
|
@@ -16332,7 +16753,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
|
|
|
16332
16753
|
const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
|
|
16333
16754
|
var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
|
|
16334
16755
|
const slotsOf = (registration) => registration.secrets ?? [];
|
|
16335
|
-
const make$
|
|
16756
|
+
const make$63 = Effect.gen(function* () {
|
|
16336
16757
|
const config = yield* ServerConfig$1;
|
|
16337
16758
|
const secrets = yield* ServerSecretStore;
|
|
16338
16759
|
const oauth = yield* McpOAuth;
|
|
@@ -16483,7 +16904,7 @@ const make$62 = Effect.gen(function* () {
|
|
|
16483
16904
|
}).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
|
|
16484
16905
|
};
|
|
16485
16906
|
});
|
|
16486
|
-
const layer$
|
|
16907
|
+
const layer$58 = Layer.effect(McpRegistry, make$63);
|
|
16487
16908
|
//#endregion
|
|
16488
16909
|
//#region src/sync/skillDirectory.ts
|
|
16489
16910
|
/**
|
|
@@ -16539,7 +16960,7 @@ const isIgnoredEntry = (entry) => IGNORED_ENTRIES.has(entry) || entry.startsWith
|
|
|
16539
16960
|
* Exported so the single-file kinds ask it the same way this one does, rather
|
|
16540
16961
|
* than each keeping a copy that could drift into a different answer.
|
|
16541
16962
|
*/
|
|
16542
|
-
const looksBinary$
|
|
16963
|
+
const looksBinary$2 = (content) => content.includes("\0");
|
|
16543
16964
|
/**
|
|
16544
16965
|
* Read one directory as an asset's files, or say why it cannot be one.
|
|
16545
16966
|
*
|
|
@@ -16571,7 +16992,7 @@ const readSkillFiles = Effect.fn("skillDirectory.readSkillFiles")(function* (roo
|
|
|
16571
16992
|
if (files.length >= 512) return "too-many-files";
|
|
16572
16993
|
const content = yield* fileSystem.readFileString(absolute).pipe(Effect.orElseSucceed(() => void 0));
|
|
16573
16994
|
if (content === void 0) return "unreadable";
|
|
16574
|
-
if (looksBinary$
|
|
16995
|
+
if (looksBinary$2(content)) return "binary-file";
|
|
16575
16996
|
if (content.length > 524288) return "file-too-large";
|
|
16576
16997
|
files.push({
|
|
16577
16998
|
path: relative,
|
|
@@ -16695,7 +17116,7 @@ const readAgentDefinitions = Effect.fn("agentDefinitionFiles.read")(function* (a
|
|
|
16695
17116
|
});
|
|
16696
17117
|
continue;
|
|
16697
17118
|
}
|
|
16698
|
-
if (looksBinary$
|
|
17119
|
+
if (looksBinary$2(content)) {
|
|
16699
17120
|
refused.push({
|
|
16700
17121
|
name: entry,
|
|
16701
17122
|
reason: "binary-file"
|
|
@@ -16862,7 +17283,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
|
|
|
16862
17283
|
shareMode: input.shareMode
|
|
16863
17284
|
});
|
|
16864
17285
|
const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
|
|
16865
|
-
const make$
|
|
17286
|
+
const make$62 = Effect.fn("HubLink.make")(function* (environment) {
|
|
16866
17287
|
const secrets = yield* ServerSecretStore;
|
|
16867
17288
|
const env = environment ?? process.env;
|
|
16868
17289
|
const fromEnv = fromEnvironment(env);
|
|
@@ -16928,7 +17349,7 @@ const make$61 = Effect.fn("HubLink.make")(function* (environment) {
|
|
|
16928
17349
|
})
|
|
16929
17350
|
};
|
|
16930
17351
|
});
|
|
16931
|
-
const layer$
|
|
17352
|
+
const layer$57 = Layer.effect(HubLink, make$62());
|
|
16932
17353
|
//#endregion
|
|
16933
17354
|
//#region src/sync/HubAssetClient.ts
|
|
16934
17355
|
/**
|
|
@@ -16961,7 +17382,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
|
|
|
16961
17382
|
const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
|
|
16962
17383
|
const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
|
|
16963
17384
|
var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
|
|
16964
|
-
const make$
|
|
17385
|
+
const make$61 = Effect.gen(function* () {
|
|
16965
17386
|
const http = yield* HttpClient.HttpClient;
|
|
16966
17387
|
const link = yield* HubLink;
|
|
16967
17388
|
const requireSettings = Effect.gen(function* () {
|
|
@@ -17043,7 +17464,7 @@ const make$60 = Effect.gen(function* () {
|
|
|
17043
17464
|
remove
|
|
17044
17465
|
};
|
|
17045
17466
|
});
|
|
17046
|
-
const layer$
|
|
17467
|
+
const layer$56 = Layer.effect(HubAssetClient, make$61);
|
|
17047
17468
|
//#endregion
|
|
17048
17469
|
//#region src/sync/mcpRegistrationFiles.ts
|
|
17049
17470
|
/**
|
|
@@ -17217,7 +17638,7 @@ const isMemoryDirectoryName = (name) => MEMORY_DIRECTORY_NAMES.includes(name);
|
|
|
17217
17638
|
*/
|
|
17218
17639
|
const isMemoryAssetName = (name) => isMemoryFileName(name) || isMemoryDirectoryName(name);
|
|
17219
17640
|
/** The same test the skill reader uses: a NUL is what breaks a JSON text column. */
|
|
17220
|
-
const looksBinary = (content) => content.includes("\0");
|
|
17641
|
+
const looksBinary$1 = (content) => content.includes("\0");
|
|
17221
17642
|
/**
|
|
17222
17643
|
* Read whichever memory files exist in this machine's config directory.
|
|
17223
17644
|
*
|
|
@@ -17241,7 +17662,7 @@ const readMemoryFiles = Effect.fn("memoryFile.readMemoryFiles")(function* (memor
|
|
|
17241
17662
|
});
|
|
17242
17663
|
continue;
|
|
17243
17664
|
}
|
|
17244
|
-
if (looksBinary(content)) {
|
|
17665
|
+
if (looksBinary$1(content)) {
|
|
17245
17666
|
refused.push({
|
|
17246
17667
|
name,
|
|
17247
17668
|
reason: "binary-file"
|
|
@@ -17618,7 +18039,7 @@ const EMPTY_REPORT = {
|
|
|
17618
18039
|
unavailable: null
|
|
17619
18040
|
};
|
|
17620
18041
|
var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
|
|
17621
|
-
const make$
|
|
18042
|
+
const make$60 = Effect.gen(function* () {
|
|
17622
18043
|
const client = yield* HubAssetClient;
|
|
17623
18044
|
const link = yield* HubLink;
|
|
17624
18045
|
const settingsStore = yield* ServerSettingsService;
|
|
@@ -18331,7 +18752,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
18331
18752
|
removeLocal
|
|
18332
18753
|
};
|
|
18333
18754
|
});
|
|
18334
|
-
const layer$
|
|
18755
|
+
const layer$55 = Layer.effect(AssetSync, make$60);
|
|
18335
18756
|
//#endregion
|
|
18336
18757
|
//#region src/provider/CompressPrompts.ts
|
|
18337
18758
|
/**
|
|
@@ -18354,6 +18775,8 @@ Never drop not/never/no/only/except: flipping the meaning costs more than any to
|
|
|
18354
18775
|
|
|
18355
18776
|
Tool calls: fire direct. No plan, no progress note between calls, never announce the next call. If the harness asks for a short lead-in before tool calls, write that one line and nothing more. Otherwise text before a call only to clarify, warn about a security or irreversible action, or resolve ambiguity.
|
|
18356
18777
|
|
|
18778
|
+
Subagent and tool output is raw material, not the answer. Never relay a subagent report, a file listing, or command output verbatim - state the conclusion it supports and cite the file and line that back it. Its length is its own and is never a licence to answer at that length. Quote from it only where the exact wording is the point.
|
|
18779
|
+
|
|
18357
18780
|
Preserve the user's dominant language: reply in the language the user writes, whatever language the examples or the surrounding context use. Compress the style, not the language. Every emitted line in that language, lead-in lines included, not just the final reply. Always keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim unless the user explicitly asks for translation.
|
|
18358
18781
|
|
|
18359
18782
|
Dropping articles applies to article languages only. Where small markers carry case or role (particles, postpositions), keep them: grammar, not filler. Compress politeness and filler instead.
|
|
@@ -18590,7 +19013,7 @@ const findAgentPreset = (requested) => {
|
|
|
18590
19013
|
};
|
|
18591
19014
|
//#endregion
|
|
18592
19015
|
//#region src/cli/assets.ts
|
|
18593
|
-
const SyncServicesLive = layer$
|
|
19016
|
+
const SyncServicesLive = layer$55.pipe(Layer.provideMerge(layer$56), Layer.provideMerge(layer$57), Layer.provideMerge(layer$61.pipe(Layer.provide(layer$68))), Layer.provideMerge(layer$68), Layer.provideMerge(FetchHttpClient.layer));
|
|
18594
19017
|
const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
18595
19018
|
const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
|
|
18596
19019
|
return yield* Effect.gen(function* () {
|
|
@@ -18598,7 +19021,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
|
18598
19021
|
sync: yield* AssetSync,
|
|
18599
19022
|
link: yield* HubLink
|
|
18600
19023
|
});
|
|
18601
|
-
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$
|
|
19024
|
+
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$71(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
|
|
18602
19025
|
});
|
|
18603
19026
|
const STATE_LABEL = {
|
|
18604
19027
|
synced: "synced",
|
|
@@ -19613,6 +20036,7 @@ const ThreadMetaUpdatedPayload = ThreadMetaUpdatedPayload$1;
|
|
|
19613
20036
|
const ThreadRuntimeModeSetPayload = ThreadRuntimeModeSetPayload$1;
|
|
19614
20037
|
const ThreadInteractionModeSetPayload = ThreadInteractionModeSetPayload$1;
|
|
19615
20038
|
const ThreadCompressModeSetPayload = ThreadCompressModeSetPayload$1;
|
|
20039
|
+
const ThreadUnpromptedSubagentsSetPayload = ThreadUnpromptedSubagentsSetPayload$1;
|
|
19616
20040
|
const ThreadDeletedPayload = ThreadDeletedPayload$1;
|
|
19617
20041
|
const ThreadUnarchivedPayload = ThreadUnarchivedPayload$1;
|
|
19618
20042
|
const ThreadUnsettledPayload = ThreadUnsettledPayload$1;
|
|
@@ -19753,6 +20177,7 @@ function projectEvent(model, event) {
|
|
|
19753
20177
|
runtimeMode: payload.runtimeMode,
|
|
19754
20178
|
interactionMode: payload.interactionMode,
|
|
19755
20179
|
compressMode: payload.compressMode,
|
|
20180
|
+
unpromptedSubagents: payload.unpromptedSubagents,
|
|
19756
20181
|
branch: payload.branch,
|
|
19757
20182
|
worktreePath: payload.worktreePath,
|
|
19758
20183
|
latestTurn: null,
|
|
@@ -19859,6 +20284,13 @@ function projectEvent(model, event) {
|
|
|
19859
20284
|
updatedAt: payload.updatedAt
|
|
19860
20285
|
})
|
|
19861
20286
|
})));
|
|
20287
|
+
case "thread.unprompted-subagents-set": return decodeForEvent(ThreadUnpromptedSubagentsSetPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => ({
|
|
20288
|
+
...nextBase,
|
|
20289
|
+
threads: updateThread(nextBase.threads, payload.threadId, {
|
|
20290
|
+
unpromptedSubagents: payload.unpromptedSubagents,
|
|
20291
|
+
updatedAt: payload.updatedAt
|
|
20292
|
+
})
|
|
20293
|
+
})));
|
|
19862
20294
|
case "thread.message-sent": return Effect.gen(function* () {
|
|
19863
20295
|
const payload = yield* decodeForEvent(MessageSentPayloadSchema, event.payload, event.type, "payload");
|
|
19864
20296
|
const thread = nextBase.threads.find((entry) => entry.id === payload.threadId);
|
|
@@ -20225,6 +20657,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
20225
20657
|
runtimeMode: command.runtimeMode,
|
|
20226
20658
|
interactionMode: command.interactionMode,
|
|
20227
20659
|
compressMode: command.compressMode,
|
|
20660
|
+
unpromptedSubagents: command.unpromptedSubagents,
|
|
20228
20661
|
branch: command.branch,
|
|
20229
20662
|
worktreePath: command.worktreePath,
|
|
20230
20663
|
createdAt: command.createdAt,
|
|
@@ -20504,6 +20937,28 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
20504
20937
|
}
|
|
20505
20938
|
};
|
|
20506
20939
|
}
|
|
20940
|
+
case "thread.unprompted-subagents.set": {
|
|
20941
|
+
yield* requireThread({
|
|
20942
|
+
readModel,
|
|
20943
|
+
command,
|
|
20944
|
+
threadId: command.threadId
|
|
20945
|
+
});
|
|
20946
|
+
const occurredAt = yield* nowIso$8;
|
|
20947
|
+
return {
|
|
20948
|
+
...yield* withEventBase({
|
|
20949
|
+
aggregateKind: "thread",
|
|
20950
|
+
aggregateId: command.threadId,
|
|
20951
|
+
occurredAt,
|
|
20952
|
+
commandId: command.commandId
|
|
20953
|
+
}),
|
|
20954
|
+
type: "thread.unprompted-subagents-set",
|
|
20955
|
+
payload: {
|
|
20956
|
+
threadId: command.threadId,
|
|
20957
|
+
unpromptedSubagents: command.unpromptedSubagents,
|
|
20958
|
+
updatedAt: occurredAt
|
|
20959
|
+
}
|
|
20960
|
+
};
|
|
20961
|
+
}
|
|
20507
20962
|
case "thread.turn.start": {
|
|
20508
20963
|
const targetThread = yield* requireThread({
|
|
20509
20964
|
readModel,
|
|
@@ -20562,6 +21017,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
20562
21017
|
runtimeMode: targetThread.runtimeMode,
|
|
20563
21018
|
interactionMode: targetThread.interactionMode,
|
|
20564
21019
|
compressMode: targetThread.compressMode,
|
|
21020
|
+
unpromptedSubagents: targetThread.unpromptedSubagents,
|
|
20565
21021
|
...sourceProposedPlan !== void 0 ? { sourceProposedPlan } : {},
|
|
20566
21022
|
createdAt: command.createdAt
|
|
20567
21023
|
}
|
|
@@ -21328,6 +21784,8 @@ const ProjectionThread = Schema$1.Struct({
|
|
|
21328
21784
|
runtimeMode: RuntimeMode,
|
|
21329
21785
|
interactionMode: ProviderInteractionMode,
|
|
21330
21786
|
compressMode: CompressMode,
|
|
21787
|
+
/** 0 or 1: SQLite has no boolean, matching `hasActionableProposedPlan`. */
|
|
21788
|
+
unpromptedSubagents: NonNegativeInt,
|
|
21331
21789
|
branch: Schema$1.NullOr(Schema$1.String),
|
|
21332
21790
|
worktreePath: Schema$1.NullOr(Schema$1.String),
|
|
21333
21791
|
latestTurnId: Schema$1.NullOr(TurnId),
|
|
@@ -22216,6 +22674,7 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
22216
22674
|
runtime_mode,
|
|
22217
22675
|
interaction_mode,
|
|
22218
22676
|
compress_mode,
|
|
22677
|
+
unprompted_subagents,
|
|
22219
22678
|
branch,
|
|
22220
22679
|
worktree_path,
|
|
22221
22680
|
latest_turn_id,
|
|
@@ -22240,6 +22699,7 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
22240
22699
|
${row.runtimeMode},
|
|
22241
22700
|
${row.interactionMode},
|
|
22242
22701
|
${row.compressMode},
|
|
22702
|
+
${row.unpromptedSubagents},
|
|
22243
22703
|
${row.branch},
|
|
22244
22704
|
${row.worktreePath},
|
|
22245
22705
|
${row.latestTurnId},
|
|
@@ -22264,6 +22724,7 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
22264
22724
|
runtime_mode = excluded.runtime_mode,
|
|
22265
22725
|
interaction_mode = excluded.interaction_mode,
|
|
22266
22726
|
compress_mode = excluded.compress_mode,
|
|
22727
|
+
unprompted_subagents = excluded.unprompted_subagents,
|
|
22267
22728
|
branch = excluded.branch,
|
|
22268
22729
|
worktree_path = excluded.worktree_path,
|
|
22269
22730
|
latest_turn_id = excluded.latest_turn_id,
|
|
@@ -22293,6 +22754,7 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
22293
22754
|
runtime_mode AS "runtimeMode",
|
|
22294
22755
|
interaction_mode AS "interactionMode",
|
|
22295
22756
|
compress_mode AS "compressMode",
|
|
22757
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
22296
22758
|
branch,
|
|
22297
22759
|
worktree_path AS "worktreePath",
|
|
22298
22760
|
latest_turn_id AS "latestTurnId",
|
|
@@ -22324,6 +22786,7 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
22324
22786
|
runtime_mode AS "runtimeMode",
|
|
22325
22787
|
interaction_mode AS "interactionMode",
|
|
22326
22788
|
compress_mode AS "compressMode",
|
|
22789
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
22327
22790
|
branch,
|
|
22328
22791
|
worktree_path AS "worktreePath",
|
|
22329
22792
|
latest_turn_id AS "latestTurnId",
|
|
@@ -22791,6 +23254,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
22791
23254
|
runtimeMode: event.payload.runtimeMode,
|
|
22792
23255
|
interactionMode: event.payload.interactionMode,
|
|
22793
23256
|
compressMode: event.payload.compressMode,
|
|
23257
|
+
unpromptedSubagents: event.payload.unpromptedSubagents ? 1 : 0,
|
|
22794
23258
|
branch: event.payload.branch,
|
|
22795
23259
|
worktreePath: event.payload.worktreePath,
|
|
22796
23260
|
latestTurnId: null,
|
|
@@ -22915,6 +23379,16 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
22915
23379
|
});
|
|
22916
23380
|
return;
|
|
22917
23381
|
}
|
|
23382
|
+
case "thread.unprompted-subagents-set": {
|
|
23383
|
+
const existingRow = yield* projectionThreadRepository.getById({ threadId: event.payload.threadId });
|
|
23384
|
+
if (Option.isNone(existingRow)) return;
|
|
23385
|
+
yield* projectionThreadRepository.upsert({
|
|
23386
|
+
...existingRow.value,
|
|
23387
|
+
unpromptedSubagents: event.payload.unpromptedSubagents ? 1 : 0,
|
|
23388
|
+
updatedAt: event.payload.updatedAt
|
|
23389
|
+
});
|
|
23390
|
+
return;
|
|
23391
|
+
}
|
|
22918
23392
|
case "thread.deleted": {
|
|
22919
23393
|
attachmentSideEffects.deletedThreadIds.add(event.payload.threadId);
|
|
22920
23394
|
const existingRow = yield* projectionThreadRepository.getById({ threadId: event.payload.threadId });
|
|
@@ -23950,12 +24424,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
|
|
|
23950
24424
|
stderrTruncated: stderr.truncated
|
|
23951
24425
|
};
|
|
23952
24426
|
});
|
|
23953
|
-
const make$
|
|
24427
|
+
const make$59 = Effect.fn("ProcessRunner.make")(function* () {
|
|
23954
24428
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
23955
24429
|
const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
|
|
23956
24430
|
return ProcessRunner.of({ run });
|
|
23957
24431
|
});
|
|
23958
|
-
const layer$
|
|
24432
|
+
const layer$54 = Layer.effect(ProcessRunner, make$59());
|
|
23959
24433
|
//#endregion
|
|
23960
24434
|
//#region src/project/RepositoryIdentityResolver.ts
|
|
23961
24435
|
const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
|
|
@@ -24046,7 +24520,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
|
|
|
24046
24520
|
rootPath: cacheKey
|
|
24047
24521
|
}) : null;
|
|
24048
24522
|
});
|
|
24049
|
-
const make$
|
|
24523
|
+
const make$58 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
|
|
24050
24524
|
const processRunner = yield* ProcessRunner;
|
|
24051
24525
|
const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
|
|
24052
24526
|
capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
|
|
@@ -24061,7 +24535,7 @@ const make$57 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
|
|
|
24061
24535
|
});
|
|
24062
24536
|
return RepositoryIdentityResolver.of({ resolve });
|
|
24063
24537
|
});
|
|
24064
|
-
const layer$
|
|
24538
|
+
const layer$53 = Layer.effect(RepositoryIdentityResolver, make$58()).pipe(Layer.provide(layer$54));
|
|
24065
24539
|
//#endregion
|
|
24066
24540
|
//#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
|
|
24067
24541
|
const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
|
|
@@ -24237,6 +24711,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
24237
24711
|
runtime_mode AS "runtimeMode",
|
|
24238
24712
|
interaction_mode AS "interactionMode",
|
|
24239
24713
|
compress_mode AS "compressMode",
|
|
24714
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
24240
24715
|
branch,
|
|
24241
24716
|
worktree_path AS "worktreePath",
|
|
24242
24717
|
latest_turn_id AS "latestTurnId",
|
|
@@ -24268,6 +24743,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
24268
24743
|
runtime_mode AS "runtimeMode",
|
|
24269
24744
|
interaction_mode AS "interactionMode",
|
|
24270
24745
|
compress_mode AS "compressMode",
|
|
24746
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
24271
24747
|
branch,
|
|
24272
24748
|
worktree_path AS "worktreePath",
|
|
24273
24749
|
latest_turn_id AS "latestTurnId",
|
|
@@ -24301,6 +24777,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
24301
24777
|
runtime_mode AS "runtimeMode",
|
|
24302
24778
|
interaction_mode AS "interactionMode",
|
|
24303
24779
|
compress_mode AS "compressMode",
|
|
24780
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
24304
24781
|
branch,
|
|
24305
24782
|
worktree_path AS "worktreePath",
|
|
24306
24783
|
latest_turn_id AS "latestTurnId",
|
|
@@ -24634,6 +25111,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
24634
25111
|
runtime_mode AS "runtimeMode",
|
|
24635
25112
|
interaction_mode AS "interactionMode",
|
|
24636
25113
|
compress_mode AS "compressMode",
|
|
25114
|
+
unprompted_subagents AS "unpromptedSubagents",
|
|
24637
25115
|
branch,
|
|
24638
25116
|
worktree_path AS "worktreePath",
|
|
24639
25117
|
latest_turn_id AS "latestTurnId",
|
|
@@ -24936,6 +25414,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
24936
25414
|
runtimeMode: row.runtimeMode,
|
|
24937
25415
|
interactionMode: row.interactionMode,
|
|
24938
25416
|
compressMode: row.compressMode,
|
|
25417
|
+
unpromptedSubagents: row.unpromptedSubagents > 0,
|
|
24939
25418
|
branch: row.branch,
|
|
24940
25419
|
worktreePath: row.worktreePath,
|
|
24941
25420
|
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
|
|
@@ -25048,6 +25527,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
25048
25527
|
runtimeMode: row.runtimeMode,
|
|
25049
25528
|
interactionMode: row.interactionMode,
|
|
25050
25529
|
compressMode: row.compressMode,
|
|
25530
|
+
unpromptedSubagents: row.unpromptedSubagents > 0,
|
|
25051
25531
|
branch: row.branch,
|
|
25052
25532
|
worktreePath: row.worktreePath,
|
|
25053
25533
|
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
|
|
@@ -25107,6 +25587,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
25107
25587
|
runtimeMode: row.runtimeMode,
|
|
25108
25588
|
interactionMode: row.interactionMode,
|
|
25109
25589
|
compressMode: row.compressMode,
|
|
25590
|
+
unpromptedSubagents: row.unpromptedSubagents > 0,
|
|
25110
25591
|
branch: row.branch,
|
|
25111
25592
|
worktreePath: row.worktreePath,
|
|
25112
25593
|
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
|
|
@@ -25162,6 +25643,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
25162
25643
|
runtimeMode: row.runtimeMode,
|
|
25163
25644
|
interactionMode: row.interactionMode,
|
|
25164
25645
|
compressMode: row.compressMode,
|
|
25646
|
+
unpromptedSubagents: row.unpromptedSubagents > 0,
|
|
25165
25647
|
branch: row.branch,
|
|
25166
25648
|
worktreePath: row.worktreePath,
|
|
25167
25649
|
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
|
|
@@ -25253,6 +25735,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
25253
25735
|
runtimeMode: threadRow.value.runtimeMode,
|
|
25254
25736
|
interactionMode: threadRow.value.interactionMode,
|
|
25255
25737
|
compressMode: threadRow.value.compressMode,
|
|
25738
|
+
unpromptedSubagents: threadRow.value.unpromptedSubagents > 0,
|
|
25256
25739
|
branch: threadRow.value.branch,
|
|
25257
25740
|
worktreePath: threadRow.value.worktreePath,
|
|
25258
25741
|
latestTurn: Option.isSome(latestTurnRow) ? mapLatestTurn(latestTurnRow.value) : null,
|
|
@@ -25289,6 +25772,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
25289
25772
|
runtimeMode: threadRow.value.runtimeMode,
|
|
25290
25773
|
interactionMode: threadRow.value.interactionMode,
|
|
25291
25774
|
compressMode: threadRow.value.compressMode,
|
|
25775
|
+
unpromptedSubagents: threadRow.value.unpromptedSubagents > 0,
|
|
25292
25776
|
branch: threadRow.value.branch,
|
|
25293
25777
|
worktreePath: threadRow.value.worktreePath,
|
|
25294
25778
|
latestTurn: Option.isSome(latestTurnRow) ? mapLatestTurn(latestTurnRow.value) : null,
|
|
@@ -25881,7 +26365,7 @@ function mergeWithDefaultKeybindings(custom) {
|
|
|
25881
26365
|
* Keybindings - Service tag for keybinding configuration operations.
|
|
25882
26366
|
*/
|
|
25883
26367
|
var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
|
|
25884
|
-
const make$
|
|
26368
|
+
const make$57 = Effect.gen(function* () {
|
|
25885
26369
|
const { keybindingsConfigPath } = yield* ServerConfig$1;
|
|
25886
26370
|
const fs = yield* FileSystem.FileSystem;
|
|
25887
26371
|
const path = yield* Path.Path;
|
|
@@ -26142,7 +26626,7 @@ const make$56 = Effect.gen(function* () {
|
|
|
26142
26626
|
}))
|
|
26143
26627
|
};
|
|
26144
26628
|
});
|
|
26145
|
-
const layer$
|
|
26629
|
+
const layer$52 = Layer.effect(Keybindings, make$57);
|
|
26146
26630
|
//#endregion
|
|
26147
26631
|
//#region src/process/externalLauncher.ts
|
|
26148
26632
|
/**
|
|
@@ -26369,7 +26853,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
|
|
|
26369
26853
|
cause
|
|
26370
26854
|
}));
|
|
26371
26855
|
});
|
|
26372
|
-
const make$
|
|
26856
|
+
const make$56 = Effect.gen(function* () {
|
|
26373
26857
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
26374
26858
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
26375
26859
|
const path = yield* Path.Path;
|
|
@@ -26380,7 +26864,7 @@ const make$55 = Effect.gen(function* () {
|
|
|
26380
26864
|
launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
|
|
26381
26865
|
});
|
|
26382
26866
|
});
|
|
26383
|
-
const layer$
|
|
26867
|
+
const layer$51 = Layer.effect(ExternalLauncher, make$56);
|
|
26384
26868
|
//#endregion
|
|
26385
26869
|
//#region src/orchestration/Services/OrchestrationReactor.ts
|
|
26386
26870
|
/**
|
|
@@ -26398,7 +26882,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
|
|
|
26398
26882
|
//#endregion
|
|
26399
26883
|
//#region src/serverLifecycleEvents.ts
|
|
26400
26884
|
var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
|
|
26401
|
-
const make$
|
|
26885
|
+
const make$55 = Effect.gen(function* () {
|
|
26402
26886
|
const pubsub = yield* PubSub.unbounded();
|
|
26403
26887
|
const state = yield* Ref.make({
|
|
26404
26888
|
sequence: 0,
|
|
@@ -26422,7 +26906,7 @@ const make$54 = Effect.gen(function* () {
|
|
|
26422
26906
|
}
|
|
26423
26907
|
};
|
|
26424
26908
|
});
|
|
26425
|
-
const layer$
|
|
26909
|
+
const layer$50 = Layer.effect(ServerLifecycleEvents, make$55);
|
|
26426
26910
|
//#endregion
|
|
26427
26911
|
//#region src/telemetry/Identify.ts
|
|
26428
26912
|
const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
|
|
@@ -26595,7 +27079,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
|
|
|
26595
27079
|
/** No-op layer for callers that intentionally disable telemetry. */
|
|
26596
27080
|
static layerTest = Layer.succeed(AnalyticsService, inert);
|
|
26597
27081
|
};
|
|
26598
|
-
const make$
|
|
27082
|
+
const make$54 = Effect.gen(function* () {
|
|
26599
27083
|
const telemetryConfig = yield* TelemetryEnvConfig;
|
|
26600
27084
|
const posthogKey = telemetryConfig.posthogKey.trim();
|
|
26601
27085
|
if (!telemetryConfig.enabled || posthogKey === "") return inert;
|
|
@@ -26665,7 +27149,7 @@ const make$53 = Effect.gen(function* () {
|
|
|
26665
27149
|
flush
|
|
26666
27150
|
});
|
|
26667
27151
|
});
|
|
26668
|
-
const layer$
|
|
27152
|
+
const layer$49 = Layer.effect(AnalyticsService, make$54);
|
|
26669
27153
|
AnalyticsService.layerTest;
|
|
26670
27154
|
//#endregion
|
|
26671
27155
|
//#region src/service/pinnedRuntime.ts
|
|
@@ -27012,7 +27496,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
|
|
|
27012
27496
|
}
|
|
27013
27497
|
};
|
|
27014
27498
|
var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
|
|
27015
|
-
const make$
|
|
27499
|
+
const make$53 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
27016
27500
|
const hostExecPath = yield* HostProcessExecutablePath;
|
|
27017
27501
|
const hostArguments = yield* HostProcessArguments;
|
|
27018
27502
|
const host = input.host ?? {
|
|
@@ -27231,7 +27715,7 @@ const make$52 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
|
27231
27715
|
logPath
|
|
27232
27716
|
});
|
|
27233
27717
|
});
|
|
27234
|
-
const layer$
|
|
27718
|
+
const layer$48 = (input) => Layer.effect(BootService, make$53(input));
|
|
27235
27719
|
//#endregion
|
|
27236
27720
|
//#region src/service/selfUpdate.ts
|
|
27237
27721
|
/**
|
|
@@ -27306,7 +27790,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
|
|
|
27306
27790
|
return null;
|
|
27307
27791
|
});
|
|
27308
27792
|
var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
|
|
27309
|
-
const make$
|
|
27793
|
+
const make$52 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
27310
27794
|
const serverConfig = yield* ServerConfig$1;
|
|
27311
27795
|
const fs = yield* FileSystem.FileSystem;
|
|
27312
27796
|
const path = yield* Path.Path;
|
|
@@ -27456,7 +27940,7 @@ const make$51 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
|
27456
27940
|
});
|
|
27457
27941
|
return ServerSelfUpdate.of({ update });
|
|
27458
27942
|
});
|
|
27459
|
-
const layer$
|
|
27943
|
+
const layer$47 = Layer.effect(ServerSelfUpdate, make$52()).pipe(Layer.provide(layer$54));
|
|
27460
27944
|
//#endregion
|
|
27461
27945
|
//#region src/environment/ServerEnvironmentLabel.ts
|
|
27462
27946
|
const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
|
|
@@ -27588,7 +28072,7 @@ function platformArch(architecture) {
|
|
|
27588
28072
|
default: return "other";
|
|
27589
28073
|
}
|
|
27590
28074
|
}
|
|
27591
|
-
const make$
|
|
28075
|
+
const make$51 = Effect.gen(function* () {
|
|
27592
28076
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
27593
28077
|
const path = yield* Path.Path;
|
|
27594
28078
|
const serverConfig = yield* ServerConfig$1;
|
|
@@ -27651,7 +28135,7 @@ const make$50 = Effect.gen(function* () {
|
|
|
27651
28135
|
* state. It intentionally has no fallback Layer.succeed value: callers must
|
|
27652
28136
|
* provide the external platform services and a ServerConfig.
|
|
27653
28137
|
*/
|
|
27654
|
-
const layer$
|
|
28138
|
+
const layer$46 = Layer.effect(ServerEnvironment, make$51).pipe(Layer.provide(layer$54));
|
|
27655
28139
|
//#endregion
|
|
27656
28140
|
//#region src/provider/Services/ProviderSessionReaper.ts
|
|
27657
28141
|
var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
|
|
@@ -28698,6 +29182,7 @@ const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
|
|
|
28698
29182
|
modelSelection: nextProjectDefaultModelSelection,
|
|
28699
29183
|
interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
|
|
28700
29184
|
compressMode: DEFAULT_COMPRESS_MODE,
|
|
29185
|
+
unpromptedSubagents: true,
|
|
28701
29186
|
runtimeMode: "full-access",
|
|
28702
29187
|
branch: null,
|
|
28703
29188
|
worktreePath: null,
|
|
@@ -28728,7 +29213,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
|
|
|
28728
29213
|
yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
|
|
28729
29214
|
});
|
|
28730
29215
|
const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
|
|
28731
|
-
const make$
|
|
29216
|
+
const make$50 = Effect.gen(function* () {
|
|
28732
29217
|
const serverConfig = yield* ServerConfig$1;
|
|
28733
29218
|
const keybindings = yield* Keybindings;
|
|
28734
29219
|
const orchestrationReactor = yield* OrchestrationReactor;
|
|
@@ -28869,7 +29354,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
28869
29354
|
enqueueCommand: commandGate.enqueueCommand
|
|
28870
29355
|
};
|
|
28871
29356
|
});
|
|
28872
|
-
const layer$
|
|
29357
|
+
const layer$45 = Layer.effect(ServerRuntimeStartup, make$50);
|
|
28873
29358
|
//#endregion
|
|
28874
29359
|
//#region src/serverRuntimeState.ts
|
|
28875
29360
|
const PersistedServerRuntimeState = Schema$1.Struct({
|
|
@@ -29017,7 +29502,7 @@ function expandHomePath$2(input, path) {
|
|
|
29017
29502
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
29018
29503
|
return input;
|
|
29019
29504
|
}
|
|
29020
|
-
const make$
|
|
29505
|
+
const make$49 = Effect.gen(function* () {
|
|
29021
29506
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
29022
29507
|
const path = yield* Path.Path;
|
|
29023
29508
|
const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
|
|
@@ -29074,7 +29559,7 @@ const make$48 = Effect.gen(function* () {
|
|
|
29074
29559
|
resolveRelativePathWithinRoot
|
|
29075
29560
|
});
|
|
29076
29561
|
});
|
|
29077
|
-
const layer$
|
|
29562
|
+
const layer$44 = Layer.effect(WorkspacePaths, make$49);
|
|
29078
29563
|
//#endregion
|
|
29079
29564
|
//#region src/cli/project.ts
|
|
29080
29565
|
const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
|
|
@@ -29180,7 +29665,7 @@ const projectCommandUuid = Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.
|
|
|
29180
29665
|
operation: "generateProjectCommandId",
|
|
29181
29666
|
cause
|
|
29182
29667
|
})));
|
|
29183
|
-
const ProjectCliRuntimeLive = Layer.mergeAll(layer$
|
|
29668
|
+
const ProjectCliRuntimeLive = Layer.mergeAll(layer$44, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$53), Layer.provideMerge(layerConfig)));
|
|
29184
29669
|
const PROJECT_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(1);
|
|
29185
29670
|
const withProjectCliSessionToken = (environmentAuth, run) => Effect.acquireUseRelease(environmentAuth.issueSession({
|
|
29186
29671
|
scopes: AuthAdministrativeScopes,
|
|
@@ -29271,7 +29756,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
29271
29756
|
});
|
|
29272
29757
|
yield* Console.log(output);
|
|
29273
29758
|
}));
|
|
29274
|
-
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$
|
|
29759
|
+
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$71(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
|
|
29275
29760
|
return yield* Effect.gen(function* () {
|
|
29276
29761
|
const snapshot = yield* getOfflineSnapshot();
|
|
29277
29762
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
@@ -29282,7 +29767,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
29282
29767
|
});
|
|
29283
29768
|
yield* Console.log(output);
|
|
29284
29769
|
}).pipe(Effect.provide(offlineRuntimeLayer));
|
|
29285
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$
|
|
29770
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$44).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$71(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
29286
29771
|
});
|
|
29287
29772
|
const projectAddCommand = Command.make("add", {
|
|
29288
29773
|
...projectLocationFlags,
|
|
@@ -29889,7 +30374,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
|
|
|
29889
30374
|
filePath: error.filePath,
|
|
29890
30375
|
errorTag: error._tag
|
|
29891
30376
|
}));
|
|
29892
|
-
const make$
|
|
30377
|
+
const make$48 = Effect.gen(function* () {
|
|
29893
30378
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
29894
30379
|
const path = yield* Path.Path;
|
|
29895
30380
|
const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
|
|
@@ -29910,7 +30395,7 @@ const make$47 = Effect.gen(function* () {
|
|
|
29910
30395
|
});
|
|
29911
30396
|
return P4ProjectFileLoader.of({ load });
|
|
29912
30397
|
});
|
|
29913
|
-
const layer$
|
|
30398
|
+
const layer$43 = Layer.effect(P4ProjectFileLoader, make$48);
|
|
29914
30399
|
//#endregion
|
|
29915
30400
|
//#region src/project/ProjectFaviconResolver.ts
|
|
29916
30401
|
/**
|
|
@@ -29981,7 +30466,7 @@ function extractIconHref(source) {
|
|
|
29981
30466
|
return null;
|
|
29982
30467
|
}
|
|
29983
30468
|
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) }));
|
|
29984
|
-
const make$
|
|
30469
|
+
const make$47 = Effect.gen(function* () {
|
|
29985
30470
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
29986
30471
|
const path = yield* Path.Path;
|
|
29987
30472
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -30050,7 +30535,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
30050
30535
|
});
|
|
30051
30536
|
return ProjectFaviconResolver.of({ resolvePath });
|
|
30052
30537
|
});
|
|
30053
|
-
const layer$
|
|
30538
|
+
const layer$42 = Layer.effect(ProjectFaviconResolver, make$47);
|
|
30054
30539
|
//#endregion
|
|
30055
30540
|
//#region src/assets/AssetAccess.ts
|
|
30056
30541
|
const ASSET_ROUTE_PREFIX = "/api/assets";
|
|
@@ -30303,10 +30788,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
30303
30788
|
//#endregion
|
|
30304
30789
|
//#region src/observability/BrowserTraceCollector.ts
|
|
30305
30790
|
var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
|
|
30306
|
-
const make$
|
|
30791
|
+
const make$46 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
|
|
30307
30792
|
for (const record of records) sink.push(record);
|
|
30308
30793
|
}) });
|
|
30309
|
-
const layer$
|
|
30794
|
+
const layer$41 = (sink) => Layer.succeed(BrowserTraceCollector, make$46(sink));
|
|
30310
30795
|
//#endregion
|
|
30311
30796
|
//#region src/auth/http.ts
|
|
30312
30797
|
const CREDENTIAL_RESPONSE_HEADERS = {
|
|
@@ -31269,7 +31754,7 @@ const NESTED_PAYLOAD_KEYS = [
|
|
|
31269
31754
|
"operations"
|
|
31270
31755
|
];
|
|
31271
31756
|
const MAX_COLLECT_DEPTH = 4;
|
|
31272
|
-
function asRecord$
|
|
31757
|
+
function asRecord$4(value) {
|
|
31273
31758
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
31274
31759
|
}
|
|
31275
31760
|
function pushChangedFilePath(target, value) {
|
|
@@ -31284,7 +31769,7 @@ function collectChangedFilePaths(value, target, depth) {
|
|
|
31284
31769
|
for (const entry of value) collectChangedFilePaths(entry, target, depth + 1);
|
|
31285
31770
|
return;
|
|
31286
31771
|
}
|
|
31287
|
-
const record = asRecord$
|
|
31772
|
+
const record = asRecord$4(value);
|
|
31288
31773
|
if (!record) return;
|
|
31289
31774
|
for (const field of CHANGED_FILE_FIELDS) pushChangedFilePath(target, record[field]);
|
|
31290
31775
|
for (const nestedKey of NESTED_PAYLOAD_KEYS) if (nestedKey in record) collectChangedFilePaths(record[nestedKey], target, depth + 1);
|
|
@@ -31295,7 +31780,7 @@ function collectChangedFilePaths(value, target, depth) {
|
|
|
31295
31780
|
*/
|
|
31296
31781
|
function collectActivityChangedFilePaths(payload) {
|
|
31297
31782
|
const target = /* @__PURE__ */ new Set();
|
|
31298
|
-
collectChangedFilePaths(asRecord$
|
|
31783
|
+
collectChangedFilePaths(asRecord$4(asRecord$4(payload)?.data), target, 0);
|
|
31299
31784
|
return target;
|
|
31300
31785
|
}
|
|
31301
31786
|
/**
|
|
@@ -33200,7 +33685,7 @@ const classifyNonZeroExit = (command, stderr) => {
|
|
|
33200
33685
|
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";
|
|
33201
33686
|
return "command-failed";
|
|
33202
33687
|
};
|
|
33203
|
-
const make$
|
|
33688
|
+
const make$45 = Effect.gen(function* () {
|
|
33204
33689
|
const processRunner = yield* ProcessRunner;
|
|
33205
33690
|
const run = Effect.fn("VcsProcess.run")(function* (input) {
|
|
33206
33691
|
const baseError = {
|
|
@@ -33257,7 +33742,7 @@ const make$44 = Effect.gen(function* () {
|
|
|
33257
33742
|
});
|
|
33258
33743
|
return VcsProcess.of({ run });
|
|
33259
33744
|
});
|
|
33260
|
-
const layer$
|
|
33745
|
+
const layer$40 = Layer.effect(VcsProcess, make$45).pipe(Layer.provide(layer$54));
|
|
33261
33746
|
//#endregion
|
|
33262
33747
|
//#region src/vcs/VcsDriver.ts
|
|
33263
33748
|
var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
|
|
@@ -33708,12 +34193,12 @@ const makeVcsDriver = Effect.gen(function* () {
|
|
|
33708
34193
|
const driver = yield* makeVcsDriverShape();
|
|
33709
34194
|
return VcsDriver.of(driver);
|
|
33710
34195
|
});
|
|
33711
|
-
const make$
|
|
34196
|
+
const make$44 = Effect.gen(function* () {
|
|
33712
34197
|
const git = yield* makeGitVcsDriverCore();
|
|
33713
34198
|
return GitVcsDriver.of(git);
|
|
33714
34199
|
});
|
|
33715
34200
|
Layer.effect(VcsDriver, makeVcsDriver);
|
|
33716
|
-
const layer$
|
|
34201
|
+
const layer$39 = Layer.effect(GitVcsDriver, make$44);
|
|
33717
34202
|
//#endregion
|
|
33718
34203
|
//#region src/vcs/VcsProjectConfig.ts
|
|
33719
34204
|
const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
|
|
@@ -33745,7 +34230,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
|
|
|
33745
34230
|
configPath: error.configPath,
|
|
33746
34231
|
errorTag: error._tag
|
|
33747
34232
|
}));
|
|
33748
|
-
const make$
|
|
34233
|
+
const make$43 = Effect.gen(function* () {
|
|
33749
34234
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
33750
34235
|
const path = yield* Path.Path;
|
|
33751
34236
|
const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
|
|
@@ -33786,7 +34271,7 @@ const make$42 = Effect.gen(function* () {
|
|
|
33786
34271
|
});
|
|
33787
34272
|
return VcsProjectConfig.of({ resolveKind });
|
|
33788
34273
|
});
|
|
33789
|
-
const layer$
|
|
34274
|
+
const layer$38 = Layer.effect(VcsProjectConfig, make$43);
|
|
33790
34275
|
//#endregion
|
|
33791
34276
|
//#region src/vcs/VcsDriverRegistry.ts
|
|
33792
34277
|
const DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -33806,7 +34291,7 @@ function parseDetectionCacheKey(key) {
|
|
|
33806
34291
|
cwd: key.slice(separatorIndex + 1)
|
|
33807
34292
|
};
|
|
33808
34293
|
}
|
|
33809
|
-
const make$
|
|
34294
|
+
const make$42 = Effect.gen(function* () {
|
|
33810
34295
|
const projectConfig = yield* VcsProjectConfig;
|
|
33811
34296
|
const git = yield* makeVcsDriver;
|
|
33812
34297
|
const drivers = { git };
|
|
@@ -33863,7 +34348,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
33863
34348
|
resolve
|
|
33864
34349
|
});
|
|
33865
34350
|
});
|
|
33866
|
-
const layer$
|
|
34351
|
+
const layer$37 = Layer.effect(VcsDriverRegistry, make$42).pipe(Layer.provide(layer$38));
|
|
33867
34352
|
//#endregion
|
|
33868
34353
|
//#region src/checkpointing/CheckpointStore.ts
|
|
33869
34354
|
/**
|
|
@@ -33883,7 +34368,7 @@ const layer$36 = Layer.effect(VcsDriverRegistry, make$41).pipe(Layer.provide(lay
|
|
|
33883
34368
|
*/
|
|
33884
34369
|
/** Service tag for checkpoint persistence and restore operations. */
|
|
33885
34370
|
var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
|
|
33886
|
-
const make$
|
|
34371
|
+
const make$41 = Effect.gen(function* () {
|
|
33887
34372
|
const vcsRegistry = yield* VcsDriverRegistry;
|
|
33888
34373
|
const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
|
|
33889
34374
|
const handle = yield* vcsRegistry.resolve({ cwd });
|
|
@@ -33922,7 +34407,7 @@ const make$40 = Effect.gen(function* () {
|
|
|
33922
34407
|
deleteCheckpointRefs
|
|
33923
34408
|
});
|
|
33924
34409
|
});
|
|
33925
|
-
const layer$
|
|
34410
|
+
const layer$36 = Layer.effect(CheckpointStore, make$41);
|
|
33926
34411
|
//#endregion
|
|
33927
34412
|
//#region src/checkpointing/CheckpointDiffQuery.ts
|
|
33928
34413
|
/**
|
|
@@ -33944,7 +34429,7 @@ function buildTurnDiffResult(input, diff) {
|
|
|
33944
34429
|
diff
|
|
33945
34430
|
};
|
|
33946
34431
|
}
|
|
33947
|
-
const make$
|
|
34432
|
+
const make$40 = Effect.gen(function* () {
|
|
33948
34433
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
33949
34434
|
const checkpointStore = yield* CheckpointStore;
|
|
33950
34435
|
const threadActivities = yield* ProjectionThreadActivityRepository;
|
|
@@ -34110,7 +34595,7 @@ const make$39 = Effect.gen(function* () {
|
|
|
34110
34595
|
getFullThreadDiff
|
|
34111
34596
|
});
|
|
34112
34597
|
});
|
|
34113
|
-
const layer$
|
|
34598
|
+
const layer$35 = Layer.effect(CheckpointDiffQuery, make$40);
|
|
34114
34599
|
//#endregion
|
|
34115
34600
|
//#region ../../packages/shared/src/toolCategory.ts
|
|
34116
34601
|
const TOOL_CATEGORY_TITLES = {
|
|
@@ -34379,22 +34864,22 @@ function classifyToolCategory(input) {
|
|
|
34379
34864
|
if (normalized.includes("image")) return "image_view";
|
|
34380
34865
|
return "tool";
|
|
34381
34866
|
}
|
|
34382
|
-
function asRecord$
|
|
34867
|
+
function asRecord$3(value) {
|
|
34383
34868
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
34384
34869
|
}
|
|
34385
34870
|
/** Classify from a runtime item payload's `data` (`{ toolName, input }`). */
|
|
34386
34871
|
function classifyToolCategoryFromToolData(data) {
|
|
34387
|
-
const record = asRecord$
|
|
34872
|
+
const record = asRecord$3(data);
|
|
34388
34873
|
const toolName = record?.toolName;
|
|
34389
34874
|
if (typeof toolName !== "string" || toolName.trim().length === 0) return;
|
|
34390
34875
|
return classifyToolCategory({
|
|
34391
34876
|
toolName,
|
|
34392
|
-
toolInput: asRecord$
|
|
34877
|
+
toolInput: asRecord$3(record?.input)
|
|
34393
34878
|
});
|
|
34394
34879
|
}
|
|
34395
34880
|
//#endregion
|
|
34396
34881
|
//#region src/orchestration/ActivityPayloadProjection.ts
|
|
34397
|
-
function asRecord$
|
|
34882
|
+
function asRecord$2(value) {
|
|
34398
34883
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
34399
34884
|
}
|
|
34400
34885
|
function asTrimmedString$1(value) {
|
|
@@ -34417,7 +34902,7 @@ function collectChangedFiles(value, target, seen, depth) {
|
|
|
34417
34902
|
}
|
|
34418
34903
|
return;
|
|
34419
34904
|
}
|
|
34420
|
-
const record = asRecord$
|
|
34905
|
+
const record = asRecord$2(value);
|
|
34421
34906
|
if (!record) return;
|
|
34422
34907
|
pushChangedFile(target, seen, record.path);
|
|
34423
34908
|
pushChangedFile(target, seen, record.filePath);
|
|
@@ -34443,13 +34928,13 @@ function collectChangedFiles(value, target, seen, depth) {
|
|
|
34443
34928
|
}
|
|
34444
34929
|
}
|
|
34445
34930
|
function projectCommandData(data) {
|
|
34446
|
-
const item = asRecord$
|
|
34931
|
+
const item = asRecord$2(data.item);
|
|
34447
34932
|
if (!item) return;
|
|
34448
34933
|
const projectedItem = {};
|
|
34449
34934
|
if ("command" in item) projectedItem.command = item.command;
|
|
34450
|
-
const input = asRecord$
|
|
34935
|
+
const input = asRecord$2(item.input);
|
|
34451
34936
|
if (input && "command" in input) projectedItem.input = { command: input.command };
|
|
34452
|
-
const result = asRecord$
|
|
34937
|
+
const result = asRecord$2(item.result);
|
|
34453
34938
|
if (result && "command" in result) projectedItem.result = { command: result.command };
|
|
34454
34939
|
return Object.keys(projectedItem).length > 0 ? projectedItem : void 0;
|
|
34455
34940
|
}
|
|
@@ -34465,7 +34950,7 @@ function summarizeToolTextOutput(value) {
|
|
|
34465
34950
|
return null;
|
|
34466
34951
|
}
|
|
34467
34952
|
function projectRawOutput(value) {
|
|
34468
|
-
const rawOutput = asRecord$
|
|
34953
|
+
const rawOutput = asRecord$2(value);
|
|
34469
34954
|
if (!rawOutput) return;
|
|
34470
34955
|
if (typeof rawOutput.totalFiles === "number" && Number.isFinite(rawOutput.totalFiles)) return {
|
|
34471
34956
|
totalFiles: rawOutput.totalFiles,
|
|
@@ -34487,14 +34972,14 @@ function projectRawOutput(value) {
|
|
|
34487
34972
|
* the full payload in persistence and the event store.
|
|
34488
34973
|
*/
|
|
34489
34974
|
function projectActivityPayload(activity) {
|
|
34490
|
-
const payload = asRecord$
|
|
34491
|
-
const data = asRecord$
|
|
34975
|
+
const payload = asRecord$2(activity.payload);
|
|
34976
|
+
const data = asRecord$2(payload?.data);
|
|
34492
34977
|
if (!payload || !data || payload.itemType === "mcp_tool_call") return activity;
|
|
34493
34978
|
const projectedData = {};
|
|
34494
34979
|
const item = projectCommandData(data);
|
|
34495
34980
|
if (item) projectedData.item = item;
|
|
34496
34981
|
if ("command" in data) projectedData.command = data.command;
|
|
34497
|
-
const input = asRecord$
|
|
34982
|
+
const input = asRecord$2(data.input);
|
|
34498
34983
|
if (input && "command" in input) projectedData.input = { command: input.command };
|
|
34499
34984
|
const changedFiles = [];
|
|
34500
34985
|
collectChangedFiles(data, changedFiles, /* @__PURE__ */ new Set(), 0);
|
|
@@ -34521,7 +35006,7 @@ function projectActivityPayload(activity) {
|
|
|
34521
35006
|
*/
|
|
34522
35007
|
function isResolvableContextWindowActivity(activity) {
|
|
34523
35008
|
if (activity.kind !== "context-window.updated") return false;
|
|
34524
|
-
const usedTokens = asRecord$
|
|
35009
|
+
const usedTokens = asRecord$2(activity.payload)?.usedTokens;
|
|
34525
35010
|
return typeof usedTokens === "number" && Number.isFinite(usedTokens) && usedTokens >= 0;
|
|
34526
35011
|
}
|
|
34527
35012
|
/**
|
|
@@ -34537,7 +35022,7 @@ function isResolvableContextWindowActivity(activity) {
|
|
|
34537
35022
|
* client.
|
|
34538
35023
|
*/
|
|
34539
35024
|
function withoutContextWindowBreakdown$1(activity) {
|
|
34540
|
-
const payload = asRecord$
|
|
35025
|
+
const payload = asRecord$2(activity.payload);
|
|
34541
35026
|
if (!payload || payload.breakdown === void 0) return activity;
|
|
34542
35027
|
const { breakdown: _breakdown, ...rest } = payload;
|
|
34543
35028
|
return {
|
|
@@ -34552,7 +35037,7 @@ function dropStaleContextWindowActivities(activities) {
|
|
|
34552
35037
|
const retainedIndexes = new Set(latestIndexByTurn.values());
|
|
34553
35038
|
let breakdownIndex = null;
|
|
34554
35039
|
for (const index of retainedIndexes) {
|
|
34555
|
-
if (asRecord$
|
|
35040
|
+
if (asRecord$2(activities[index].payload)?.breakdown === void 0) continue;
|
|
34556
35041
|
if (breakdownIndex === null || index > breakdownIndex) breakdownIndex = index;
|
|
34557
35042
|
}
|
|
34558
35043
|
return activities.flatMap((activity, index) => {
|
|
@@ -34680,6 +35165,8 @@ const buildTaskRow = (input, taskId, timestamp, repositoryKey = null) => ({
|
|
|
34680
35165
|
projectId: input.projectId ?? null,
|
|
34681
35166
|
repositoryKey: repositoryKey ?? input.repositoryKey ?? null,
|
|
34682
35167
|
threadId: input.threadId ?? null,
|
|
35168
|
+
externalRef: input.externalRef ?? null,
|
|
35169
|
+
parentTaskId: input.parentTaskId ?? null,
|
|
34683
35170
|
title: input.title,
|
|
34684
35171
|
body: input.body ?? "",
|
|
34685
35172
|
status: input.status ?? "backlog",
|
|
@@ -35272,7 +35759,7 @@ function makeUpdateState(input) {
|
|
|
35272
35759
|
output: input.output ?? null
|
|
35273
35760
|
};
|
|
35274
35761
|
}
|
|
35275
|
-
const make$
|
|
35762
|
+
const make$39 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
35276
35763
|
const providerRegistry = yield* ProviderRegistry;
|
|
35277
35764
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
35278
35765
|
const httpClient = yield* HttpClient.HttpClient;
|
|
@@ -35387,7 +35874,7 @@ const make$38 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
|
35387
35874
|
});
|
|
35388
35875
|
return ProviderMaintenanceRunner.of({ updateProvider });
|
|
35389
35876
|
});
|
|
35390
|
-
const layer$
|
|
35877
|
+
const layer$34 = Layer.effect(ProviderMaintenanceRunner, make$39());
|
|
35391
35878
|
//#endregion
|
|
35392
35879
|
//#region src/provider/Services/ProviderInstanceRegistry.ts
|
|
35393
35880
|
var ProviderInstanceRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderInstanceRegistry") {};
|
|
@@ -35411,11 +35898,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
|
|
|
35411
35898
|
detail: "This provider does not report account usage."
|
|
35412
35899
|
}))))
|
|
35413
35900
|
});
|
|
35414
|
-
const make$
|
|
35901
|
+
const make$38 = Effect.gen(function* () {
|
|
35415
35902
|
const registry = yield* ProviderInstanceRegistry;
|
|
35416
35903
|
return makeTextGenerationFromRegistry(registry);
|
|
35417
35904
|
});
|
|
35418
|
-
const layer$
|
|
35905
|
+
const layer$33 = Layer.effect(TextGeneration, make$38);
|
|
35419
35906
|
const SKILL_MANIFEST_FILENAME = "SKILL.md";
|
|
35420
35907
|
/**
|
|
35421
35908
|
* Split a catalogue id (`owner/repo/skill-name`) into its parts.
|
|
@@ -35524,7 +36011,7 @@ function toAssetFilePath(repositoryPath, root) {
|
|
|
35524
36011
|
const REGISTRY_SEARCH_URL = "https://www.skills.sh/api/search";
|
|
35525
36012
|
const GITHUB_API_URL = "https://api.github.com";
|
|
35526
36013
|
const GITHUB_RAW_URL = "https://raw.githubusercontent.com";
|
|
35527
|
-
const REQUEST_TIMEOUT_MS = 15e3;
|
|
36014
|
+
const REQUEST_TIMEOUT_MS$1 = 15e3;
|
|
35528
36015
|
/** More than a person reads, few enough that the panel is a list and not a feed. */
|
|
35529
36016
|
const MAX_SEARCH_RESULTS = 25;
|
|
35530
36017
|
/**
|
|
@@ -35561,10 +36048,10 @@ const emptyFetch = (id, unavailable) => ({
|
|
|
35561
36048
|
skipped: [],
|
|
35562
36049
|
unavailable
|
|
35563
36050
|
});
|
|
35564
|
-
const make$
|
|
36051
|
+
const make$37 = Effect.gen(function* () {
|
|
35565
36052
|
const http = yield* HttpClient.HttpClient;
|
|
35566
36053
|
const request = Effect.fn("SkillRegistry.request")(function* (url) {
|
|
35567
|
-
return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS));
|
|
36054
|
+
return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS$1));
|
|
35568
36055
|
});
|
|
35569
36056
|
const search = (query) => Effect.gen(function* () {
|
|
35570
36057
|
const response = yield* request(`${REGISTRY_SEARCH_URL}?q=${encodeURIComponent(query)}`).pipe(Effect.orElseSucceed(() => null));
|
|
@@ -35632,7 +36119,309 @@ const make$36 = Effect.gen(function* () {
|
|
|
35632
36119
|
fetch
|
|
35633
36120
|
};
|
|
35634
36121
|
});
|
|
35635
|
-
const layer$
|
|
36122
|
+
const layer$32 = Layer.effect(SkillRegistry, make$37);
|
|
36123
|
+
//#endregion
|
|
36124
|
+
//#region ../../packages/shared/src/ticketReference.ts
|
|
36125
|
+
/**
|
|
36126
|
+
* Recognizing a tracker reference in text somebody pasted.
|
|
36127
|
+
*
|
|
36128
|
+
* Shared because both ends need the same answer: the composer decides whether a
|
|
36129
|
+
* paste is worth a round trip, and the server decides what to ask the tracker.
|
|
36130
|
+
* Two copies of this rule would differ, and the difference would read as "it
|
|
36131
|
+
* works on my machine but the paste does nothing".
|
|
36132
|
+
*
|
|
36133
|
+
* @module ticketReference
|
|
36134
|
+
*/
|
|
36135
|
+
/**
|
|
36136
|
+
* A Linear issue URL, e.g.
|
|
36137
|
+
* `https://linear.app/omnicasa/issue/MOBILE-12262/haptic-feedback`.
|
|
36138
|
+
*
|
|
36139
|
+
* The workspace slug is what makes the URL unguessable from the identifier
|
|
36140
|
+
* alone, which is why a resolved ticket keeps the tracker's own URL rather than
|
|
36141
|
+
* rebuilding one.
|
|
36142
|
+
*/
|
|
36143
|
+
const LINEAR_ISSUE_URL_PATTERN = /https?:\/\/(?:www\.)?linear\.app\/[^/\s]+\/issue\/([A-Za-z][A-Za-z0-9]*-\d+)/;
|
|
36144
|
+
/**
|
|
36145
|
+
* A bare identifier, e.g. `MOBILE-12262`.
|
|
36146
|
+
*
|
|
36147
|
+
* Anchored: only a paste that is *nothing but* an identifier counts. Scanning
|
|
36148
|
+
* prose for this shape would claim things that are not tickets - a date range,
|
|
36149
|
+
* a version, a p4code readable id like `P4-40` - and each false positive costs
|
|
36150
|
+
* a request and, worse, a wrong link.
|
|
36151
|
+
*/
|
|
36152
|
+
const BARE_IDENTIFIER_PATTERN = /^([A-Za-z][A-Za-z0-9]*-\d+)$/;
|
|
36153
|
+
/**
|
|
36154
|
+
* The issue identifier a paste refers to, or `null` when it refers to none.
|
|
36155
|
+
*
|
|
36156
|
+
* Case is normalized up, the way every tracker prints it, so the same ticket
|
|
36157
|
+
* pasted two ways compares equal.
|
|
36158
|
+
*/
|
|
36159
|
+
function parseTicketReference(text) {
|
|
36160
|
+
const trimmed = text.trim();
|
|
36161
|
+
if (trimmed.length === 0) return null;
|
|
36162
|
+
const url = LINEAR_ISSUE_URL_PATTERN.exec(trimmed);
|
|
36163
|
+
if (url?.[1] !== void 0) return url[1].toUpperCase();
|
|
36164
|
+
const bare = BARE_IDENTIFIER_PATTERN.exec(trimmed);
|
|
36165
|
+
if (bare?.[1] !== void 0) return bare[1].toUpperCase();
|
|
36166
|
+
return null;
|
|
36167
|
+
}
|
|
36168
|
+
//#endregion
|
|
36169
|
+
//#region src/mcp/McpToolClient.ts
|
|
36170
|
+
/**
|
|
36171
|
+
* Calling a tool on somebody else's MCP server.
|
|
36172
|
+
*
|
|
36173
|
+
* The rest of `apps/server/src/mcp` points the other way: it *exposes* p4code's
|
|
36174
|
+
* toolkit to an agent. This is the only place p4code is the client, and it
|
|
36175
|
+
* exists because one feature - recognizing a pasted ticket - needs an answer
|
|
36176
|
+
* before any agent turn runs, from a server the user has already registered.
|
|
36177
|
+
*
|
|
36178
|
+
* Deliberately not a general MCP client. There is no session reuse, no tool
|
|
36179
|
+
* listing, no notifications, no SSE stream held open: one request/response pair
|
|
36180
|
+
* per call, which is all streamable HTTP requires for a plain `tools/call`. A
|
|
36181
|
+
* real client belongs here only once something needs one.
|
|
36182
|
+
*
|
|
36183
|
+
* @module mcp/McpToolClient
|
|
36184
|
+
*/
|
|
36185
|
+
/**
|
|
36186
|
+
* The version p4code speaks. Sent on `initialize` and echoed back as a header
|
|
36187
|
+
* on the follow-up calls, which is what the spec asks of a client that has
|
|
36188
|
+
* already negotiated.
|
|
36189
|
+
*/
|
|
36190
|
+
const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
36191
|
+
const REQUEST_TIMEOUT_MS = 15e3;
|
|
36192
|
+
var McpToolCallError = class extends Schema$1.TaggedErrorClass()("McpToolCallError", {
|
|
36193
|
+
detail: Schema$1.String,
|
|
36194
|
+
status: Schema$1.NullOr(Schema$1.Number)
|
|
36195
|
+
}) {
|
|
36196
|
+
get message() {
|
|
36197
|
+
return this.detail;
|
|
36198
|
+
}
|
|
36199
|
+
};
|
|
36200
|
+
const unauthorized$1 = (status) => status === 401 || status === 403;
|
|
36201
|
+
/**
|
|
36202
|
+
* Read a JSON-RPC envelope out of a response that may be either JSON or SSE.
|
|
36203
|
+
*
|
|
36204
|
+
* A streamable-http server picks the encoding, and both are legal answers to a
|
|
36205
|
+
* single call. The SSE branch keeps the last `data:` payload that parses: a
|
|
36206
|
+
* server is free to emit progress notifications ahead of the result, and the
|
|
36207
|
+
* result is what a caller of this asked for.
|
|
36208
|
+
*/
|
|
36209
|
+
const readEnvelope = (body) => {
|
|
36210
|
+
const direct = parseJsonObject(body);
|
|
36211
|
+
if (direct !== void 0) return direct;
|
|
36212
|
+
let latest;
|
|
36213
|
+
for (const line of body.split("\n")) {
|
|
36214
|
+
const trimmed = line.trim();
|
|
36215
|
+
if (!trimmed.startsWith("data:")) continue;
|
|
36216
|
+
const parsed = parseJsonObject(trimmed.slice(5).trim());
|
|
36217
|
+
if (parsed !== void 0) latest = parsed;
|
|
36218
|
+
}
|
|
36219
|
+
return latest;
|
|
36220
|
+
};
|
|
36221
|
+
const parseJsonObject = (text) => {
|
|
36222
|
+
if (text.length === 0) return void 0;
|
|
36223
|
+
try {
|
|
36224
|
+
const parsed = JSON.parse(text);
|
|
36225
|
+
return typeof parsed === "object" && parsed !== null ? parsed : void 0;
|
|
36226
|
+
} catch {
|
|
36227
|
+
return;
|
|
36228
|
+
}
|
|
36229
|
+
};
|
|
36230
|
+
const textOf = (content) => {
|
|
36231
|
+
if (!Array.isArray(content)) return "";
|
|
36232
|
+
const parts = [];
|
|
36233
|
+
for (const block of content) {
|
|
36234
|
+
if (typeof block !== "object" || block === null) continue;
|
|
36235
|
+
const record = block;
|
|
36236
|
+
if (record["type"] === "text" && typeof record["text"] === "string") parts.push(record["text"]);
|
|
36237
|
+
}
|
|
36238
|
+
return parts.join("\n");
|
|
36239
|
+
};
|
|
36240
|
+
/**
|
|
36241
|
+
* One `tools/call`, preceded by the `initialize` handshake the transport
|
|
36242
|
+
* requires.
|
|
36243
|
+
*
|
|
36244
|
+
* The handshake is not optional and not cacheable here: a server may hand out a
|
|
36245
|
+
* session id, and this holds no session state between calls. Two round trips
|
|
36246
|
+
* for one answer is the price of not keeping a connection open for a feature
|
|
36247
|
+
* that fires when somebody pastes something.
|
|
36248
|
+
*/
|
|
36249
|
+
const callMcpTool = Effect.fn("McpToolClient.callMcpTool")(function* (input) {
|
|
36250
|
+
const http = yield* HttpClient$1.HttpClient;
|
|
36251
|
+
const post = (body, extraHeaders) => http.execute(HttpClientRequest$1.bodyJsonUnsafe(HttpClientRequest$1.setHeaders(HttpClientRequest$1.post(input.url), {
|
|
36252
|
+
...input.headers,
|
|
36253
|
+
...extraHeaders,
|
|
36254
|
+
accept: "application/json, text/event-stream"
|
|
36255
|
+
}), body)).pipe(Effect.timeout(REQUEST_TIMEOUT_MS), Effect.catchCause((cause) => Effect.fail(new McpToolCallError({
|
|
36256
|
+
detail: `Could not reach ${input.url}: ${String(cause)}`,
|
|
36257
|
+
status: null
|
|
36258
|
+
}))));
|
|
36259
|
+
const initialize = yield* post({
|
|
36260
|
+
jsonrpc: "2.0",
|
|
36261
|
+
id: 1,
|
|
36262
|
+
method: "initialize",
|
|
36263
|
+
params: {
|
|
36264
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
36265
|
+
capabilities: {},
|
|
36266
|
+
clientInfo: {
|
|
36267
|
+
name: "p4code",
|
|
36268
|
+
version: "0.0.0"
|
|
36269
|
+
}
|
|
36270
|
+
}
|
|
36271
|
+
}, {});
|
|
36272
|
+
if (initialize.status >= 400) return yield* new McpToolCallError({
|
|
36273
|
+
detail: unauthorized$1(initialize.status) ? "The server rejected p4code's credentials." : `The server answered ${initialize.status} to initialize.`,
|
|
36274
|
+
status: initialize.status
|
|
36275
|
+
});
|
|
36276
|
+
const sessionId = initialize.headers["mcp-session-id"];
|
|
36277
|
+
const sessionHeaders = {
|
|
36278
|
+
"mcp-protocol-version": MCP_PROTOCOL_VERSION,
|
|
36279
|
+
...sessionId === void 0 ? {} : { "mcp-session-id": sessionId }
|
|
36280
|
+
};
|
|
36281
|
+
yield* post({
|
|
36282
|
+
jsonrpc: "2.0",
|
|
36283
|
+
method: "notifications/initialized"
|
|
36284
|
+
}, sessionHeaders).pipe(Effect.ignore);
|
|
36285
|
+
const response = yield* post({
|
|
36286
|
+
jsonrpc: "2.0",
|
|
36287
|
+
id: 2,
|
|
36288
|
+
method: "tools/call",
|
|
36289
|
+
params: {
|
|
36290
|
+
name: input.toolName,
|
|
36291
|
+
arguments: input.arguments
|
|
36292
|
+
}
|
|
36293
|
+
}, sessionHeaders);
|
|
36294
|
+
const body = yield* response.text.pipe(Effect.catchCause(() => Effect.succeed("")));
|
|
36295
|
+
if (response.status >= 400) return yield* new McpToolCallError({
|
|
36296
|
+
detail: unauthorized$1(response.status) ? "The server rejected p4code's credentials." : `The server answered ${response.status} to ${input.toolName}.`,
|
|
36297
|
+
status: response.status
|
|
36298
|
+
});
|
|
36299
|
+
const envelope = readEnvelope(body);
|
|
36300
|
+
if (envelope === void 0) return yield* new McpToolCallError({
|
|
36301
|
+
detail: `The server's answer to ${input.toolName} was not JSON-RPC.`,
|
|
36302
|
+
status: response.status
|
|
36303
|
+
});
|
|
36304
|
+
const error = envelope["error"];
|
|
36305
|
+
if (typeof error === "object" && error !== null) {
|
|
36306
|
+
const detail = error["message"];
|
|
36307
|
+
return yield* new McpToolCallError({
|
|
36308
|
+
detail: typeof detail === "string" ? detail : `${input.toolName} failed.`,
|
|
36309
|
+
status: response.status
|
|
36310
|
+
});
|
|
36311
|
+
}
|
|
36312
|
+
const result = envelope["result"];
|
|
36313
|
+
if (typeof result !== "object" || result === null) return yield* new McpToolCallError({
|
|
36314
|
+
detail: `${input.toolName} returned no result.`,
|
|
36315
|
+
status: response.status
|
|
36316
|
+
});
|
|
36317
|
+
const resultRecord = result;
|
|
36318
|
+
const text = textOf(resultRecord["content"]);
|
|
36319
|
+
if (resultRecord["isError"] === true) return yield* new McpToolCallError({
|
|
36320
|
+
detail: text.length > 0 ? text : `${input.toolName} reported an error.`,
|
|
36321
|
+
status: response.status
|
|
36322
|
+
});
|
|
36323
|
+
return {
|
|
36324
|
+
structuredContent: resultRecord["structuredContent"],
|
|
36325
|
+
text
|
|
36326
|
+
};
|
|
36327
|
+
});
|
|
36328
|
+
//#endregion
|
|
36329
|
+
//#region src/mcp/TicketResolver.ts
|
|
36330
|
+
/**
|
|
36331
|
+
* The registered server name a Linear ticket is resolved through.
|
|
36332
|
+
*
|
|
36333
|
+
* Matched by name rather than by URL: the name is what the user typed in
|
|
36334
|
+
* Settings and what every other surface calls it, and a workspace may reach
|
|
36335
|
+
* Linear through a proxy URL that no pattern here would recognize.
|
|
36336
|
+
*/
|
|
36337
|
+
const LINEAR_SERVER_NAME = "linear";
|
|
36338
|
+
/** Linear's own tool for reading one issue. */
|
|
36339
|
+
const LINEAR_GET_ISSUE_TOOL = "get_issue";
|
|
36340
|
+
var TicketResolver = class extends Context.Service()("@p4code/cli/mcp/TicketResolver") {};
|
|
36341
|
+
const stringField$1 = (record, key) => {
|
|
36342
|
+
const value = record[key];
|
|
36343
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
36344
|
+
};
|
|
36345
|
+
const asRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
36346
|
+
/**
|
|
36347
|
+
* Find the issue inside whatever the tool returned.
|
|
36348
|
+
*
|
|
36349
|
+
* MCP leaves the shape of a tool result to the tool, so this accepts the three
|
|
36350
|
+
* arrangements in the wild - the structured payload itself, that payload with
|
|
36351
|
+
* the issue nested one level down, or a text block that happens to be JSON -
|
|
36352
|
+
* rather than assuming the one Linear happens to send today.
|
|
36353
|
+
*/
|
|
36354
|
+
const readIssue = (result) => {
|
|
36355
|
+
const structured = asRecord$1(result.structuredContent);
|
|
36356
|
+
if (structured !== void 0) {
|
|
36357
|
+
const nested = asRecord$1(structured["issue"]);
|
|
36358
|
+
if (nested !== void 0) return nested;
|
|
36359
|
+
if (stringField$1(structured, "url") !== void 0) return structured;
|
|
36360
|
+
}
|
|
36361
|
+
try {
|
|
36362
|
+
const parsed = JSON.parse(result.text);
|
|
36363
|
+
const record = asRecord$1(parsed);
|
|
36364
|
+
if (record === void 0) return structured;
|
|
36365
|
+
return asRecord$1(record["issue"]) ?? record;
|
|
36366
|
+
} catch {
|
|
36367
|
+
return structured;
|
|
36368
|
+
}
|
|
36369
|
+
};
|
|
36370
|
+
const make$36 = Effect.gen(function* () {
|
|
36371
|
+
const registry = yield* McpRegistry;
|
|
36372
|
+
const oauth = yield* McpOAuth;
|
|
36373
|
+
const http = yield* HttpClient$1.HttpClient;
|
|
36374
|
+
return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
|
|
36375
|
+
const identifier = parseTicketReference(reference);
|
|
36376
|
+
if (identifier === null) return yield* new TicketResolveError({
|
|
36377
|
+
reason: "not_found",
|
|
36378
|
+
detail: `"${reference}" does not look like a ticket reference.`
|
|
36379
|
+
});
|
|
36380
|
+
const server = (yield* registry.list).find((candidate) => candidate.registration.name.toLowerCase() === LINEAR_SERVER_NAME && candidate.registration.enabled);
|
|
36381
|
+
if (server === void 0 || server.registration.transport === "stdio") return yield* new TicketResolveError({
|
|
36382
|
+
reason: "not_configured",
|
|
36383
|
+
detail: "No Linear MCP server is registered on this machine. Add it in Settings to link tickets."
|
|
36384
|
+
});
|
|
36385
|
+
const registration = server.registration;
|
|
36386
|
+
const token = yield* oauth.accessTokenFor(registration);
|
|
36387
|
+
const headers = {
|
|
36388
|
+
...registration.headers,
|
|
36389
|
+
...Option.isSome(token) ? { authorization: `Bearer ${token.value}` } : {}
|
|
36390
|
+
};
|
|
36391
|
+
if (Option.isNone(token) && Object.keys(registration.headers ?? {}).length === 0) return yield* new TicketResolveError({
|
|
36392
|
+
reason: "not_authorized",
|
|
36393
|
+
detail: "Linear is registered but not signed in on this machine. Sign in from Settings."
|
|
36394
|
+
});
|
|
36395
|
+
const result = yield* callMcpTool({
|
|
36396
|
+
url: registration.url,
|
|
36397
|
+
headers,
|
|
36398
|
+
toolName: LINEAR_GET_ISSUE_TOOL,
|
|
36399
|
+
arguments: { id: identifier }
|
|
36400
|
+
}).pipe(Effect.provideService(HttpClient$1.HttpClient, http), Effect.mapError((error) => error.status === 401 || error.status === 403 ? new TicketResolveError({
|
|
36401
|
+
reason: "not_authorized",
|
|
36402
|
+
detail: "Linear rejected p4code's sign-in. Sign in again from Settings."
|
|
36403
|
+
}) : new TicketResolveError({
|
|
36404
|
+
reason: "unavailable",
|
|
36405
|
+
detail: error.detail
|
|
36406
|
+
})));
|
|
36407
|
+
const issue = readIssue(result);
|
|
36408
|
+
const url = issue === void 0 ? void 0 : stringField$1(issue, "url");
|
|
36409
|
+
const title = issue === void 0 ? void 0 : stringField$1(issue, "title");
|
|
36410
|
+
if (issue === void 0 || url === void 0 || title === void 0) return yield* new TicketResolveError({
|
|
36411
|
+
reason: "not_found",
|
|
36412
|
+
detail: `Linear returned nothing usable for ${identifier}.`
|
|
36413
|
+
});
|
|
36414
|
+
return {
|
|
36415
|
+
externalRef: {
|
|
36416
|
+
source: "linear",
|
|
36417
|
+
identifier: stringField$1(issue, "identifier") ?? identifier,
|
|
36418
|
+
url
|
|
36419
|
+
},
|
|
36420
|
+
title
|
|
36421
|
+
};
|
|
36422
|
+
}) };
|
|
36423
|
+
});
|
|
36424
|
+
const layer$31 = Layer.effect(TicketResolver, make$36);
|
|
35636
36425
|
//#endregion
|
|
35637
36426
|
//#region ../../packages/shared/src/KeyedCoalescingWorker.ts
|
|
35638
36427
|
const makeKeyedCoalescingWorker = (options) => Effect.gen(function* () {
|
|
@@ -37722,7 +38511,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
|
|
|
37722
38511
|
subscribeMetadata
|
|
37723
38512
|
});
|
|
37724
38513
|
});
|
|
37725
|
-
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$
|
|
38514
|
+
const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$54));
|
|
37726
38515
|
//#endregion
|
|
37727
38516
|
//#region src/mcp/McpInvocationContext.ts
|
|
37728
38517
|
var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
|
|
@@ -44802,6 +45591,7 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
|
|
|
44802
45591
|
[WS_METHODS.tasksUpdate, AuthOrchestrationOperateScope],
|
|
44803
45592
|
[WS_METHODS.tasksDelete, AuthOrchestrationOperateScope],
|
|
44804
45593
|
[WS_METHODS.tasksStartThread, AuthOrchestrationOperateScope],
|
|
45594
|
+
[WS_METHODS.ticketsResolve, AuthOrchestrationReadScope],
|
|
44805
45595
|
[WS_METHODS.subscribeTasks, AuthOrchestrationReadScope],
|
|
44806
45596
|
[WS_METHODS.hubGetSyncStatus, AuthOrchestrationReadScope],
|
|
44807
45597
|
[WS_METHODS.hubConnect, AuthOrchestrationOperateScope],
|
|
@@ -44956,6 +45746,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
44956
45746
|
const mcpOAuth = yield* McpOAuth;
|
|
44957
45747
|
const claudeMcpFiles = yield* ClaudeMcpFiles;
|
|
44958
45748
|
const skillRegistry = yield* SkillRegistry;
|
|
45749
|
+
const ticketResolver = yield* TicketResolver;
|
|
44959
45750
|
const listMcpServersEverywhere = Effect.gen(function* () {
|
|
44960
45751
|
const servers = [...yield* mcpRegistry.list];
|
|
44961
45752
|
const projectRows = yield* projectionProjects.listAll().pipe(Effect.map((rows) => rows.filter((row) => row.deletedAt === null)), Effect.orElseSucceed(() => []));
|
|
@@ -45213,6 +46004,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
45213
46004
|
runtimeMode: bootstrap.createThread.runtimeMode,
|
|
45214
46005
|
interactionMode: bootstrap.createThread.interactionMode,
|
|
45215
46006
|
compressMode: bootstrap.createThread.compressMode,
|
|
46007
|
+
unpromptedSubagents: bootstrap.createThread.unpromptedSubagents,
|
|
45216
46008
|
branch: bootstrap.createThread.branch,
|
|
45217
46009
|
worktreePath: bootstrap.createThread.worktreePath,
|
|
45218
46010
|
createdAt: bootstrap.createThread.createdAt
|
|
@@ -45477,6 +46269,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
45477
46269
|
runtimeMode: DEFAULT_RUNTIME_MODE$2,
|
|
45478
46270
|
interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
|
|
45479
46271
|
compressMode: DEFAULT_COMPRESS_MODE,
|
|
46272
|
+
unpromptedSubagents: true,
|
|
45480
46273
|
bootstrap: { createThread: {
|
|
45481
46274
|
projectId: plan.projectId,
|
|
45482
46275
|
title: threadTitle,
|
|
@@ -45484,6 +46277,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
45484
46277
|
runtimeMode: DEFAULT_RUNTIME_MODE$2,
|
|
45485
46278
|
interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
|
|
45486
46279
|
compressMode: DEFAULT_COMPRESS_MODE,
|
|
46280
|
+
unpromptedSubagents: true,
|
|
45487
46281
|
branch: null,
|
|
45488
46282
|
worktreePath: null,
|
|
45489
46283
|
createdAt
|
|
@@ -45502,6 +46296,13 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
45502
46296
|
threadId
|
|
45503
46297
|
};
|
|
45504
46298
|
}), { "rpc.aggregate": "tasks" }),
|
|
46299
|
+
/**
|
|
46300
|
+
* What a pasted reference is, straight from the tracker.
|
|
46301
|
+
*
|
|
46302
|
+
* Nothing is written here: the client decides whether the answer
|
|
46303
|
+
* becomes a task, so an accidental paste costs one request and no row.
|
|
46304
|
+
*/
|
|
46305
|
+
[WS_METHODS.ticketsResolve]: ({ reference }) => observeRpcEffect$1(WS_METHODS.ticketsResolve, ticketResolver.resolve(reference), { "rpc.aggregate": "tickets" }),
|
|
45505
46306
|
[WS_METHODS.subscribeTasks]: (_input) => observeRpcStreamEffect$1(WS_METHODS.subscribeTasks, Effect.succeed(taskRepository.streamWithSnapshot.pipe(Stream.catch((cause) => Stream.fromEffect(toTaskStoreError("tasks.subscribe")(cause))))), { "rpc.aggregate": "tasks" }),
|
|
45506
46307
|
[WS_METHODS.hubGetSyncStatus]: (_input) => observeRpcEffect$1(WS_METHODS.hubGetSyncStatus, assetSync.status, { "rpc.aggregate": "hub" }),
|
|
45507
46308
|
[WS_METHODS.hubConnect]: (input) => observeRpcEffect$1(WS_METHODS.hubConnect, hubLink.connect(input).pipe(Effect.mapError((cause) => new HubLinkError({ detail: cause.message })), Effect.andThen(assetSync.status)), { "rpc.aggregate": "hub" }),
|
|
@@ -45769,7 +46570,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
45769
46570
|
const serverAuth = yield* EnvironmentAuth;
|
|
45770
46571
|
const sessions = yield* SessionStore;
|
|
45771
46572
|
const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
|
|
45772
|
-
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$
|
|
46573
|
+
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$34), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(TaskRepository, taskRepository)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), 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$39), Layer.provide(layer$37.pipe(Layer.provide(layer$38))))), Layer.provide(layer$40))))));
|
|
45773
46574
|
return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
|
|
45774
46575
|
}).pipe(Effect.catchTags({
|
|
45775
46576
|
EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
|
|
@@ -45887,6 +46688,7 @@ const makeRemoteTaskRepository = Effect.fn("makeRemoteTaskRepository")(function*
|
|
|
45887
46688
|
...row.projectId === null ? {} : { projectId: row.projectId },
|
|
45888
46689
|
...row.repositoryKey === null ? {} : { repositoryKey: row.repositoryKey },
|
|
45889
46690
|
...row.threadId === null ? {} : { threadId: row.threadId },
|
|
46691
|
+
...row.parentTaskId === null ? {} : { parentTaskId: row.parentTaskId },
|
|
45890
46692
|
title: row.title,
|
|
45891
46693
|
body: row.body,
|
|
45892
46694
|
status: row.status,
|
|
@@ -48093,7 +48895,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
|
|
|
48093
48895
|
};
|
|
48094
48896
|
});
|
|
48095
48897
|
var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
|
|
48096
|
-
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$
|
|
48898
|
+
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$72));
|
|
48097
48899
|
//#endregion
|
|
48098
48900
|
//#region src/textGeneration/TextGenerationUtils.ts
|
|
48099
48901
|
const isTextGenerationError$3 = Schema$1.is(TextGenerationError);
|
|
@@ -52015,7 +52817,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
52015
52817
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
52016
52818
|
const externalMcpServers = options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers;
|
|
52017
52819
|
const narrateBeforeTools = options?.resolveToolCallNarration === void 0 ? DEFAULT_SERVER_SETTINGS.enableToolCallNarration : yield* options.resolveToolCallNarration;
|
|
52018
|
-
const unpromptedSubagents = options?.resolveUnpromptedSubagents === void 0 ? DEFAULT_SERVER_SETTINGS.enableUnpromptedSubagents : yield* options.resolveUnpromptedSubagents;
|
|
52820
|
+
const unpromptedSubagents = input.unpromptedSubagents !== void 0 ? input.unpromptedSubagents : options?.resolveUnpromptedSubagents === void 0 ? DEFAULT_SERVER_SETTINGS.enableUnpromptedSubagents : yield* options.resolveUnpromptedSubagents;
|
|
52019
52821
|
const compressRuleset = compressRulesetFor(input.compressMode ?? "off");
|
|
52020
52822
|
const systemPromptAppend = [
|
|
52021
52823
|
...narrateBeforeTools ? [NARRATE_BEFORE_TOOLS_PROMPT] : [],
|
|
@@ -52114,6 +52916,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
52114
52916
|
startedAt,
|
|
52115
52917
|
basePermissionMode: permissionMode,
|
|
52116
52918
|
currentApiModelId: apiModelId,
|
|
52919
|
+
currentUnpromptedSubagents: unpromptedSubagents,
|
|
52117
52920
|
resumeSessionId: sessionId,
|
|
52118
52921
|
pendingApprovals,
|
|
52119
52922
|
pendingUserInputs,
|
|
@@ -52185,7 +52988,13 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
52185
52988
|
const context = yield* requireSession(input.threadId);
|
|
52186
52989
|
const modelSelection = input.modelSelection !== void 0 && input.modelSelection.instanceId === boundInstanceId ? input.modelSelection : void 0;
|
|
52187
52990
|
if (context.turnState?.synthetic === true) yield* completeTurn(context, "completed");
|
|
52188
|
-
const
|
|
52991
|
+
const turnSubagentsPrompt = input.unpromptedSubagents !== void 0 && input.unpromptedSubagents !== context.currentUnpromptedSubagents ? input.unpromptedSubagents ? SUBAGENTS_ALLOWED_PROMPT : SUBAGENTS_ON_REQUEST_PROMPT : void 0;
|
|
52992
|
+
if (input.unpromptedSubagents !== void 0) context.currentUnpromptedSubagents = input.unpromptedSubagents;
|
|
52993
|
+
const turnInput = turnSubagentsPrompt === void 0 ? input : {
|
|
52994
|
+
...input,
|
|
52995
|
+
input: input.input === void 0 ? turnSubagentsPrompt : `${turnSubagentsPrompt}\n\n${input.input}`
|
|
52996
|
+
};
|
|
52997
|
+
const message = yield* buildUserMessageEffect(turnInput, {
|
|
52189
52998
|
fileSystem,
|
|
52190
52999
|
attachmentsDir: serverConfig.attachmentsDir,
|
|
52191
53000
|
boundInstanceId
|
|
@@ -85458,6 +86267,28 @@ const findTask = (taskId) => Effect.gen(function* () {
|
|
|
85458
86267
|
const tasks = yield* TaskRepository;
|
|
85459
86268
|
return isReadableTaskId(taskId) ? yield* tasks.getByReadableId(taskId) : yield* tasks.getById({ taskId });
|
|
85460
86269
|
});
|
|
86270
|
+
/**
|
|
86271
|
+
* Resolve a parent reference to the UUID the column stores.
|
|
86272
|
+
*
|
|
86273
|
+
* A planning agent works in readable ids - it has just read `P4-12` off the
|
|
86274
|
+
* board - but the link is stored as the row key, because readable ids are
|
|
86275
|
+
* allocated per store and the one it quotes may have been minted on another
|
|
86276
|
+
* machine. Absent stays absent and an explicit null stays null: those mean
|
|
86277
|
+
* "leave it" and "clear it", neither of which is a reference to resolve.
|
|
86278
|
+
*
|
|
86279
|
+
* A readable id that names no task fails rather than being stored raw. The
|
|
86280
|
+
* opposite would file a subtask whose parent link can never resolve, which
|
|
86281
|
+
* reads on the board as a task that is part of nothing. A UUID is taken on
|
|
86282
|
+
* trust, matching the column's lack of a foreign key: a parent may legitimately
|
|
86283
|
+
* arrive after its child on a board synced from elsewhere.
|
|
86284
|
+
*/
|
|
86285
|
+
const resolveParentTaskId = (parentTaskId, operation) => Effect.gen(function* () {
|
|
86286
|
+
if (parentTaskId === void 0 || parentTaskId === null) return parentTaskId;
|
|
86287
|
+
if (!isReadableTaskId(parentTaskId)) return parentTaskId;
|
|
86288
|
+
const parent = yield* findTask(parentTaskId).pipe(Effect.catch(toTaskStoreError(operation)));
|
|
86289
|
+
if (Option.isNone(parent)) return yield* new TaskNotFoundError({ taskId: parentTaskId });
|
|
86290
|
+
return parent.value.taskId;
|
|
86291
|
+
});
|
|
85461
86292
|
const TaskToolkitHandlersLive = TaskToolkit.toLayer({
|
|
85462
86293
|
task_list: (input) => Effect.gen(function* () {
|
|
85463
86294
|
yield* requireTaskCapability();
|
|
@@ -85485,7 +86316,11 @@ const TaskToolkitHandlersLive = TaskToolkit.toLayer({
|
|
|
85485
86316
|
const timestamp = yield* nowIso$1;
|
|
85486
86317
|
const repositoryKey = yield* resolveTaskRepositoryKey(input.projectId);
|
|
85487
86318
|
const readableIdPrefix = yield* resolveTaskReadableIdPrefix(input.projectId);
|
|
85488
|
-
const
|
|
86319
|
+
const parentTaskId = yield* resolveParentTaskId(input.parentTaskId, "task_create");
|
|
86320
|
+
const row = buildTaskRow(parentTaskId === void 0 || parentTaskId === null ? input : {
|
|
86321
|
+
...input,
|
|
86322
|
+
parentTaskId
|
|
86323
|
+
}, taskId, timestamp, repositoryKey);
|
|
85489
86324
|
return yield* tasks.create(row, readableIdPrefix).pipe(Effect.catch(toTaskStoreError("task_create")));
|
|
85490
86325
|
}),
|
|
85491
86326
|
task_update: (input) => Effect.gen(function* () {
|
|
@@ -85494,13 +86329,12 @@ const TaskToolkitHandlersLive = TaskToolkit.toLayer({
|
|
|
85494
86329
|
const timestamp = yield* nowIso$1;
|
|
85495
86330
|
const taskId = isReadableTaskId(input.taskId) ? Option.getOrNull(yield* findTask(input.taskId).pipe(Effect.catch(toTaskStoreError("task_update"))))?.taskId : input.taskId;
|
|
85496
86331
|
if (taskId === void 0) return yield* new TaskNotFoundError({ taskId: input.taskId });
|
|
85497
|
-
const
|
|
85498
|
-
|
|
85499
|
-
taskId
|
|
85500
|
-
} : {
|
|
86332
|
+
const parentTaskId = yield* resolveParentTaskId(input.parentTaskId, "task_update");
|
|
86333
|
+
const patch = {
|
|
85501
86334
|
...input,
|
|
85502
86335
|
taskId,
|
|
85503
|
-
|
|
86336
|
+
...parentTaskId === void 0 ? {} : { parentTaskId },
|
|
86337
|
+
...input.projectId === void 0 ? {} : { repositoryKey: yield* resolveTaskRepositoryKey(input.projectId) }
|
|
85504
86338
|
};
|
|
85505
86339
|
const patched = yield* tasks.patch(patch, timestamp).pipe(Effect.catch(toTaskStoreError("task_update")));
|
|
85506
86340
|
if (Option.isNone(patched)) return yield* new TaskNotFoundError({ taskId: input.taskId });
|
|
@@ -85512,6 +86346,242 @@ const TaskToolkitHandlersLive = TaskToolkit.toLayer({
|
|
|
85512
86346
|
})
|
|
85513
86347
|
});
|
|
85514
86348
|
//#endregion
|
|
86349
|
+
//#region src/sync/assetCompression.ts
|
|
86350
|
+
/**
|
|
86351
|
+
* Checking that a compressed asset still says what the original said.
|
|
86352
|
+
*
|
|
86353
|
+
* Compression here is a rewrite of prose an agent reads before it does anything
|
|
86354
|
+
* else: a skill, a memory file, a subagent definition. Rewriting that prose is
|
|
86355
|
+
* cheap to get almost right and expensive to get slightly wrong, because the
|
|
86356
|
+
* damage is silent. A dropped URL, a mangled command, a heading that no longer
|
|
86357
|
+
* matches the sentence pointing at it - none of that fails loudly. It just makes
|
|
86358
|
+
* the agent behave a little differently on every machine that syncs the file.
|
|
86359
|
+
*
|
|
86360
|
+
* So the write is gated on a comparison rather than on the model's word for it.
|
|
86361
|
+
* The rules are ported from caveman's `validate.py`, with the ones this task
|
|
86362
|
+
* calls out - headings, code blocks, URLs, paths, bullet counts - promoted to
|
|
86363
|
+
* refusals rather than warnings. A refusal costs one retry; a bad write costs
|
|
86364
|
+
* whatever the agent does next, on every machine, until someone notices.
|
|
86365
|
+
*
|
|
86366
|
+
* Pure on purpose. Everything here is a string comparison, so every rule can be
|
|
86367
|
+
* tested without a filesystem, a provider or a thread, and the tool that calls
|
|
86368
|
+
* it is left with only the parts that genuinely touch disk.
|
|
86369
|
+
*
|
|
86370
|
+
* @module sync/assetCompression
|
|
86371
|
+
*/
|
|
86372
|
+
/**
|
|
86373
|
+
* How far the bullet count may move before the rewrite stops being compression.
|
|
86374
|
+
*
|
|
86375
|
+
* Not zero. Compression legitimately folds a two-line bullet into one, and a
|
|
86376
|
+
* rule that forbade that would forbid the feature. Caveman's own threshold,
|
|
86377
|
+
* kept because it is the one their receipts were measured against.
|
|
86378
|
+
*/
|
|
86379
|
+
const BULLET_COUNT_TOLERANCE = .15;
|
|
86380
|
+
/**
|
|
86381
|
+
* Characters per token, for the before/after figures.
|
|
86382
|
+
*
|
|
86383
|
+
* An estimate, and labelled as one everywhere it surfaces. The exact count
|
|
86384
|
+
* belongs to whichever provider tokenizer will read the file, and asking one
|
|
86385
|
+
* would mean a network call inside a validation path that is otherwise pure.
|
|
86386
|
+
* Four is the usual English-prose approximation and is good enough to answer
|
|
86387
|
+
* the only question anyone asks here: did this get meaningfully smaller.
|
|
86388
|
+
*/
|
|
86389
|
+
const CHARS_PER_TOKEN_ESTIMATE = 4;
|
|
86390
|
+
const URL_REGEX = /https?:\/\/[^\s)]+/gu;
|
|
86391
|
+
/**
|
|
86392
|
+
* Sentence punctuation swept up by the URL match.
|
|
86393
|
+
*
|
|
86394
|
+
* `See https://svgl.app for the catalogue.` and `Catalogue: https://svgl.app.`
|
|
86395
|
+
* name the same URL, and a comparison that disagreed would refuse every rewrite
|
|
86396
|
+
* that moved a link to the end of a sentence - which is most of them.
|
|
86397
|
+
*/
|
|
86398
|
+
const URL_TRAILING_PUNCTUATION_REGEX = /[.,;:!?'"\])]+$/u;
|
|
86399
|
+
const FENCE_LINE_REGEX = /^(\s{0,3})(`{3,}|~{3,})(.*)$/u;
|
|
86400
|
+
const HEADING_REGEX = /^(#{1,6})\s+(.*)$/gmu;
|
|
86401
|
+
const BULLET_REGEX = /^\s*[-*+]\s+/gmu;
|
|
86402
|
+
const INLINE_CODE_REGEX = /`([^`]+)`/gu;
|
|
86403
|
+
/**
|
|
86404
|
+
* Crude, and deliberately so.
|
|
86405
|
+
*
|
|
86406
|
+
* Either a path prefix (`./`, `../`, `/`, a drive letter) or a separator inside
|
|
86407
|
+
* the match. It over-matches - `and/or` is a "path" by this rule - and the
|
|
86408
|
+
* over-match is the safe direction: a false positive refuses a rewrite that
|
|
86409
|
+
* dropped the phrase, and a false negative lets a real path go missing.
|
|
86410
|
+
*/
|
|
86411
|
+
const PATH_REGEX = /(?:\.\/|\.\.\/|\/|[A-Za-z]:\\)[\w\-/\\.]+|[\w\-.]+[/\\][\w\-/\\.]+/gu;
|
|
86412
|
+
/** YAML frontmatter: `---` on the first line, `---` on a line of its own after. */
|
|
86413
|
+
const FRONTMATTER_REGEX = /^---\r?\n[\s\S]*?\r?\n---\r?\n/u;
|
|
86414
|
+
/**
|
|
86415
|
+
* Filenames that almost certainly hold secrets, and the directories that do.
|
|
86416
|
+
*
|
|
86417
|
+
* Compressing a file means handing its bytes to a model, so this is checked
|
|
86418
|
+
* before the read rather than after it. The asset roots should never contain
|
|
86419
|
+
* any of these, which is exactly why the check is cheap to keep: it costs
|
|
86420
|
+
* nothing in the ordinary case and is the only thing standing between a
|
|
86421
|
+
* misplaced `credentials.md` and a provider's API.
|
|
86422
|
+
*/
|
|
86423
|
+
const SENSITIVE_BASENAME_REGEX = /^(\.env(\..+)?|\.netrc|credentials(\..+)?|secrets?(\..+)?|passwords?(\..+)?|id_(rsa|dsa|ecdsa|ed25519)(\.pub)?|authorized_keys|known_hosts|.*\.(pem|key|p12|pfx|crt|cer|jks|keystore|asc|gpg))$/iu;
|
|
86424
|
+
const SENSITIVE_PATH_SEGMENTS = /* @__PURE__ */ new Set([
|
|
86425
|
+
".ssh",
|
|
86426
|
+
".aws",
|
|
86427
|
+
".gnupg",
|
|
86428
|
+
".kube",
|
|
86429
|
+
".docker"
|
|
86430
|
+
]);
|
|
86431
|
+
const SENSITIVE_NAME_TOKENS = [
|
|
86432
|
+
"secret",
|
|
86433
|
+
"credential",
|
|
86434
|
+
"password",
|
|
86435
|
+
"passwd",
|
|
86436
|
+
"apikey",
|
|
86437
|
+
"accesskey",
|
|
86438
|
+
"token",
|
|
86439
|
+
"privatekey"
|
|
86440
|
+
];
|
|
86441
|
+
const segmentsOf = (filePath) => filePath.split(/[/\\]/u).filter((segment) => segment.length > 0);
|
|
86442
|
+
/**
|
|
86443
|
+
* Whether this path looks like something that must not be sent to a model.
|
|
86444
|
+
*
|
|
86445
|
+
* Name-based, because that is all that is knowable before the read. Separators
|
|
86446
|
+
* inside the name are normalized away first so `api-key.md` and `api_key.md`
|
|
86447
|
+
* are the same answer.
|
|
86448
|
+
*/
|
|
86449
|
+
const isSensitiveAssetPath = (filePath) => {
|
|
86450
|
+
const segments = segmentsOf(filePath);
|
|
86451
|
+
const name = segments.at(-1) ?? "";
|
|
86452
|
+
if (SENSITIVE_BASENAME_REGEX.test(name)) return true;
|
|
86453
|
+
if (segments.some((segment) => SENSITIVE_PATH_SEGMENTS.has(segment.toLowerCase()))) return true;
|
|
86454
|
+
const flattened = name.toLowerCase().replace(/[_\-\s.]/gu, "");
|
|
86455
|
+
return SENSITIVE_NAME_TOKENS.some((token) => flattened.includes(token));
|
|
86456
|
+
};
|
|
86457
|
+
/** The frontmatter block including its delimiters, or the empty string. */
|
|
86458
|
+
const frontmatterOf = (text) => FRONTMATTER_REGEX.exec(text)?.[0] ?? "";
|
|
86459
|
+
const headingsOf = (text) => [...text.matchAll(HEADING_REGEX)].map((match) => `${match[1] ?? ""} ${(match[2] ?? "").trim()}`);
|
|
86460
|
+
/**
|
|
86461
|
+
* Fenced code blocks, as whole strings, fences included.
|
|
86462
|
+
*
|
|
86463
|
+
* Line-based rather than one regex, so a closing fence is only a closing fence
|
|
86464
|
+
* when CommonMark says it is: same character, at least as long as the opener,
|
|
86465
|
+
* nothing after it. That is what lets a four-backtick block wrap three-backtick
|
|
86466
|
+
* content without the extractor stopping in the middle of it.
|
|
86467
|
+
*
|
|
86468
|
+
* An unclosed fence is skipped rather than reported. It means the markdown was
|
|
86469
|
+
* already malformed, and including it would fail every compression of a file
|
|
86470
|
+
* that was broken before anyone touched it.
|
|
86471
|
+
*/
|
|
86472
|
+
const codeBlocksOf = (text) => {
|
|
86473
|
+
const lines = text.split("\n");
|
|
86474
|
+
const blocks = [];
|
|
86475
|
+
let index = 0;
|
|
86476
|
+
while (index < lines.length) {
|
|
86477
|
+
const opening = FENCE_LINE_REGEX.exec(lines[index] ?? "");
|
|
86478
|
+
if (opening === null) {
|
|
86479
|
+
index += 1;
|
|
86480
|
+
continue;
|
|
86481
|
+
}
|
|
86482
|
+
const fence = opening[2] ?? "";
|
|
86483
|
+
const collected = [lines[index] ?? ""];
|
|
86484
|
+
index += 1;
|
|
86485
|
+
let closed = false;
|
|
86486
|
+
while (index < lines.length) {
|
|
86487
|
+
const line = lines[index] ?? "";
|
|
86488
|
+
const closing = FENCE_LINE_REGEX.exec(line);
|
|
86489
|
+
const closingFence = closing?.[2] ?? "";
|
|
86490
|
+
if (closing !== null && closingFence[0] === fence[0] && closingFence.length >= fence.length && (closing[3] ?? "").trim().length === 0) {
|
|
86491
|
+
collected.push(line);
|
|
86492
|
+
closed = true;
|
|
86493
|
+
index += 1;
|
|
86494
|
+
break;
|
|
86495
|
+
}
|
|
86496
|
+
collected.push(line);
|
|
86497
|
+
index += 1;
|
|
86498
|
+
}
|
|
86499
|
+
if (closed) blocks.push(collected.join("\n"));
|
|
86500
|
+
}
|
|
86501
|
+
return blocks;
|
|
86502
|
+
};
|
|
86503
|
+
const withoutCodeBlocks = (text) => codeBlocksOf(text).reduce((rest, block) => rest.replace(block, ""), text);
|
|
86504
|
+
const inlineCodeCounts = (text) => {
|
|
86505
|
+
const counts = /* @__PURE__ */ new Map();
|
|
86506
|
+
for (const match of withoutCodeBlocks(text).matchAll(INLINE_CODE_REGEX)) {
|
|
86507
|
+
const span = match[1] ?? "";
|
|
86508
|
+
counts.set(span, (counts.get(span) ?? 0) + 1);
|
|
86509
|
+
}
|
|
86510
|
+
return counts;
|
|
86511
|
+
};
|
|
86512
|
+
const urlsOf = (text) => new Set([...text.matchAll(URL_REGEX)].map((match) => match[0].replace(URL_TRAILING_PUNCTUATION_REGEX, "")));
|
|
86513
|
+
/**
|
|
86514
|
+
* Paths, with URLs taken out of the text first.
|
|
86515
|
+
*
|
|
86516
|
+
* `//svgl.app` inside `https://svgl.app` is a path by the pattern's reckoning,
|
|
86517
|
+
* so leaving the URLs in would have every link contribute a phantom path whose
|
|
86518
|
+
* spelling changes with the punctuation after it.
|
|
86519
|
+
*/
|
|
86520
|
+
const pathsOf = (text) => new Set([...text.replace(URL_REGEX, " ").matchAll(PATH_REGEX)].map((match) => match[0]));
|
|
86521
|
+
const countOf = (text, pattern) => [...text.matchAll(pattern)].length;
|
|
86522
|
+
const missingFrom = (original, compressed) => [...original].filter((value) => !compressed.has(value));
|
|
86523
|
+
const addedTo = (original, compressed) => [...compressed].filter((value) => !original.has(value));
|
|
86524
|
+
const quoteList = (values) => values.map((value) => `'${value}'`).join(", ");
|
|
86525
|
+
/**
|
|
86526
|
+
* Compare a compressed rewrite against the original it came from.
|
|
86527
|
+
*
|
|
86528
|
+
* Errors are the things whose loss changes what the file instructs: a code
|
|
86529
|
+
* block, a URL, a path, an inline span, a heading, the frontmatter. Additions
|
|
86530
|
+
* are warnings rather than errors throughout, because a rewrite that names one
|
|
86531
|
+
* more path than the original is doing something odd but is not losing
|
|
86532
|
+
* anything, and a refusal there would be a refusal nobody can act on.
|
|
86533
|
+
*/
|
|
86534
|
+
const validateCompression = (original, compressed) => {
|
|
86535
|
+
const errors = [];
|
|
86536
|
+
const warnings = [];
|
|
86537
|
+
if (frontmatterOf(original) !== frontmatterOf(compressed)) errors.push("The YAML frontmatter changed. It is metadata the provider parses, not prose; return it byte-identical.");
|
|
86538
|
+
const originalHeadings = headingsOf(original);
|
|
86539
|
+
const compressedHeadings = headingsOf(compressed);
|
|
86540
|
+
if (originalHeadings.length !== compressedHeadings.length || originalHeadings.some((heading, at) => heading !== compressedHeadings[at])) errors.push(`Headings changed: ${originalHeadings.length} in the original, ${compressedHeadings.length} in the rewrite. Keep every heading, in order, with its exact text.`);
|
|
86541
|
+
const originalBlocks = codeBlocksOf(original);
|
|
86542
|
+
const compressedBlocks = codeBlocksOf(compressed);
|
|
86543
|
+
if (originalBlocks.length !== compressedBlocks.length || originalBlocks.some((block, at) => block !== compressedBlocks[at])) errors.push(`Code blocks are not byte-identical: ${originalBlocks.length} in the original, ${compressedBlocks.length} in the rewrite. Copy them through unchanged.`);
|
|
86544
|
+
const originalUrls = urlsOf(original);
|
|
86545
|
+
const compressedUrls = urlsOf(compressed);
|
|
86546
|
+
const lostUrls = missingFrom(originalUrls, compressedUrls);
|
|
86547
|
+
if (lostUrls.length > 0) errors.push(`URLs missing from the rewrite: ${quoteList(lostUrls)}.`);
|
|
86548
|
+
const addedUrls = addedTo(originalUrls, compressedUrls);
|
|
86549
|
+
if (addedUrls.length > 0) warnings.push(`URLs the original did not have: ${quoteList(addedUrls)}.`);
|
|
86550
|
+
const originalPaths = pathsOf(original);
|
|
86551
|
+
const compressedPaths = pathsOf(compressed);
|
|
86552
|
+
const lostPaths = missingFrom(originalPaths, compressedPaths);
|
|
86553
|
+
if (lostPaths.length > 0) errors.push(`Paths missing from the rewrite: ${quoteList(lostPaths)}.`);
|
|
86554
|
+
const addedPaths = addedTo(originalPaths, compressedPaths);
|
|
86555
|
+
if (addedPaths.length > 0) warnings.push(`Paths the original did not have: ${quoteList(addedPaths)}.`);
|
|
86556
|
+
const originalInline = inlineCodeCounts(original);
|
|
86557
|
+
const compressedInline = inlineCodeCounts(compressed);
|
|
86558
|
+
const lostInline = [...originalInline].filter(([span, count]) => (compressedInline.get(span) ?? 0) < count);
|
|
86559
|
+
if (lostInline.length > 0) errors.push(`Inline code spans missing from the rewrite: ${quoteList(lostInline.map(([span]) => span))}.`);
|
|
86560
|
+
const originalBullets = countOf(original, BULLET_REGEX);
|
|
86561
|
+
const compressedBullets = countOf(compressed, BULLET_REGEX);
|
|
86562
|
+
if (originalBullets > 0) {
|
|
86563
|
+
if (Math.abs(originalBullets - compressedBullets) / originalBullets > BULLET_COUNT_TOLERANCE) errors.push(`Bullet count moved from ${originalBullets} to ${compressedBullets}, past the ${Math.round(BULLET_COUNT_TOLERANCE * 100)}% tolerance. Compress the wording of each bullet rather than merging or dropping bullets.`);
|
|
86564
|
+
}
|
|
86565
|
+
return {
|
|
86566
|
+
errors,
|
|
86567
|
+
warnings
|
|
86568
|
+
};
|
|
86569
|
+
};
|
|
86570
|
+
/** Roughly how many tokens this text costs to read. Estimated, never measured. */
|
|
86571
|
+
const estimateTokens = (text) => Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE);
|
|
86572
|
+
/**
|
|
86573
|
+
* The name a backup of this file is kept under.
|
|
86574
|
+
*
|
|
86575
|
+
* Timestamped rather than fixed. Caveman refuses to compress when a backup
|
|
86576
|
+
* already exists, which protects the first original at the cost of blocking
|
|
86577
|
+
* every later compression; keeping one backup per write protects every version
|
|
86578
|
+
* instead, including the edits someone made between two compressions.
|
|
86579
|
+
*
|
|
86580
|
+
* The parent directory's name is carried in the path rather than the file name
|
|
86581
|
+
* so that `global-memory/feedback_svgl.md` and `svgl/SKILL.md` cannot collide.
|
|
86582
|
+
*/
|
|
86583
|
+
const backupFileName = (input) => `${input.fileName}.${input.atIso.replace(/[:.]/gu, "-")}.original`;
|
|
86584
|
+
//#endregion
|
|
85515
86585
|
//#region src/mcp/toolkits/threads/tools.ts
|
|
85516
86586
|
/**
|
|
85517
86587
|
* Self-scoped on purpose: neither tool takes a thread id. The thread acted on
|
|
@@ -85543,10 +86613,46 @@ const MemoryAppendTool = Tool.make("memory_append", {
|
|
|
85543
86613
|
Path.Path
|
|
85544
86614
|
]
|
|
85545
86615
|
}).annotate(Tool.Title, "Append to memory").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
|
|
85546
|
-
|
|
86616
|
+
/**
|
|
86617
|
+
* Overwrite an asset with a compressed version of itself, if it survives the
|
|
86618
|
+
* comparison.
|
|
86619
|
+
*
|
|
86620
|
+
* A tool rather than an instruction to use `Edit` because the guarantee is the
|
|
86621
|
+
* point: the original is copied out of every synced directory first, the
|
|
86622
|
+
* rewrite is compared against it, and a rewrite that lost a URL or a code block
|
|
86623
|
+
* is refused with the list of what it lost. An agent editing the file directly
|
|
86624
|
+
* can be asked to preserve those things but cannot be prevented from not.
|
|
86625
|
+
*/
|
|
86626
|
+
const AssetCompressTool = Tool.make("asset_compress", {
|
|
86627
|
+
description: "Overwrite one agent asset file - a skill, a memory file, a subagent definition - with a compressed rewrite of it, after checking the rewrite kept everything that carries meaning. Headings, fenced code blocks, inline code, URLs, paths and YAML frontmatter must come back unchanged; only the prose may be rewritten. The original is backed up outside every synced directory first. If the check fails nothing is written and the failed checks are returned, so a corrected rewrite can be sent as a second call.",
|
|
86628
|
+
parameters: AssetCompressInput,
|
|
86629
|
+
success: AssetCompressResult,
|
|
86630
|
+
failure: ThreadControlToolError,
|
|
86631
|
+
dependencies: [
|
|
86632
|
+
McpInvocationContext,
|
|
86633
|
+
ServerConfig$1,
|
|
86634
|
+
ServerSettingsService,
|
|
86635
|
+
FileSystem.FileSystem,
|
|
86636
|
+
Path.Path
|
|
86637
|
+
]
|
|
86638
|
+
}).annotate(Tool.Title, "Compress an asset").annotate(Tool.Readonly, false).annotate(Tool.Destructive, true).annotate(Tool.Idempotent, false);
|
|
86639
|
+
const ThreadToolkit = Toolkit.make(ThreadRenameTool, MemoryAppendTool, AssetCompressTool);
|
|
85547
86640
|
//#endregion
|
|
85548
86641
|
//#region src/mcp/toolkits/threads/handlers.ts
|
|
85549
86642
|
const DEFAULT_MEMORY_APPEND_TARGET = "CLAUDE.md";
|
|
86643
|
+
/**
|
|
86644
|
+
* Where originals are kept.
|
|
86645
|
+
*
|
|
86646
|
+
* Under the server's state directory, which is the one place on this machine
|
|
86647
|
+
* that is neither an asset root nor inside one. A backup next to the file would
|
|
86648
|
+
* be published by the next sync and re-read by the next agent turn, which is
|
|
86649
|
+
* the opposite of what compressing the file was for.
|
|
86650
|
+
*/
|
|
86651
|
+
const COMPRESS_BACKUP_DIRNAME = "asset-compress-backups";
|
|
86652
|
+
/** Prose only. A skill may ship scripts, and a rewritten script is a broken one. */
|
|
86653
|
+
const COMPRESSIBLE_EXTENSION = ".md";
|
|
86654
|
+
/** The same test the asset readers use: a NUL is what breaks a JSON text column. */
|
|
86655
|
+
const looksBinary = (content) => content.includes("\0");
|
|
85550
86656
|
const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
85551
86657
|
thread_rename: (input) => Effect.gen(function* () {
|
|
85552
86658
|
const invocation = yield* requireThreadCapability();
|
|
@@ -85596,6 +86702,68 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
85596
86702
|
file,
|
|
85597
86703
|
path: filePath
|
|
85598
86704
|
};
|
|
86705
|
+
}),
|
|
86706
|
+
asset_compress: (input) => Effect.gen(function* () {
|
|
86707
|
+
yield* requireThreadCapability();
|
|
86708
|
+
const path = yield* Path.Path;
|
|
86709
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
86710
|
+
const config = yield* ServerConfig$1;
|
|
86711
|
+
const claudeHome = { homePath: (yield* (yield* ServerSettingsService).getSettings.pipe(Effect.orElseSucceed(() => void 0)))?.providers.claudeAgent.homePath ?? "" };
|
|
86712
|
+
const refuse = (target, detail) => new AssetCompressRefusedError({
|
|
86713
|
+
path: target,
|
|
86714
|
+
detail
|
|
86715
|
+
});
|
|
86716
|
+
if (!path.isAbsolute(input.path)) return yield* refuse(input.path, "The path must be absolute.");
|
|
86717
|
+
const filePath = path.resolve(input.path);
|
|
86718
|
+
const fileName = path.basename(filePath);
|
|
86719
|
+
if (path.extname(fileName).toLowerCase() !== COMPRESSIBLE_EXTENSION) return yield* refuse(filePath, `Only ${COMPRESSIBLE_EXTENSION} files are compressed. Scripts and data files an asset ships alongside its prose are left alone.`);
|
|
86720
|
+
if (isSensitiveAssetPath(filePath)) return yield* refuse(filePath, "The name looks like credentials, keys or secrets, and compressing sends the file's contents to a model.");
|
|
86721
|
+
const configDir = yield* resolveClaudeConfigDirPath(claudeHome, process.env);
|
|
86722
|
+
const skillsDir = yield* resolveClaudeUserSkillsDir(claudeHome);
|
|
86723
|
+
const agentsDir = yield* resolveClaudeUserAgentsDir(claudeHome);
|
|
86724
|
+
const within = (root) => {
|
|
86725
|
+
const relative = path.relative(root, filePath);
|
|
86726
|
+
return relative.length > 0 && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
86727
|
+
};
|
|
86728
|
+
const memoryDirectoryName = path.relative(configDir, filePath).split(path.sep)[0] ?? "";
|
|
86729
|
+
if (!(within(skillsDir) || within(agentsDir) || path.dirname(filePath) === configDir && isMemoryFileName(fileName) || within(configDir) && isMemoryDirectoryName(memoryDirectoryName))) return yield* refuse(filePath, `Not an agent asset. Compressible files live under '${skillsDir}', under '${agentsDir}', or in '${configDir}' as a memory file or inside ${MEMORY_DIRECTORY_NAMES.join(" or ")}.`);
|
|
86730
|
+
const original = yield* fileSystem.readFileString(filePath).pipe(Effect.orElseSucceed(() => void 0));
|
|
86731
|
+
if (original === void 0) return yield* refuse(filePath, "The file could not be read.");
|
|
86732
|
+
if (looksBinary(original)) return yield* refuse(filePath, "The file is not text.");
|
|
86733
|
+
if (original.trim().length === 0) return yield* refuse(filePath, "The file is empty.");
|
|
86734
|
+
const compressed = input.content;
|
|
86735
|
+
if (compressed.trim().length === 0) return yield* refuse(filePath, "The rewrite is blank.");
|
|
86736
|
+
if (compressed.trim() === original.trim()) return yield* refuse(filePath, "The rewrite is the file that is already there. Nothing was written.");
|
|
86737
|
+
if (compressed.length >= original.length) return yield* refuse(filePath, `The rewrite is not smaller: ${original.length} characters became ${compressed.length}. Send the file's contents alone, with no commentary or wrapping fence.`);
|
|
86738
|
+
const validation = validateCompression(original, compressed);
|
|
86739
|
+
if (validation.errors.length > 0) return yield* new AssetCompressValidationFailedError({
|
|
86740
|
+
path: filePath,
|
|
86741
|
+
errors: validation.errors
|
|
86742
|
+
});
|
|
86743
|
+
const backupPath = path.join(config.stateDir, COMPRESS_BACKUP_DIRNAME, path.basename(path.dirname(filePath)), backupFileName({
|
|
86744
|
+
fileName,
|
|
86745
|
+
atIso: DateTime.formatIso(yield* DateTime.now)
|
|
86746
|
+
}));
|
|
86747
|
+
if (((yield* writeFileStringAtomically({
|
|
86748
|
+
filePath: backupPath,
|
|
86749
|
+
contents: original
|
|
86750
|
+
}).pipe(Effect.as(true), Effect.orElseSucceed(() => false))) ? yield* fileSystem.readFileString(backupPath).pipe(Effect.orElseSucceed(() => void 0)) : void 0) !== original) {
|
|
86751
|
+
yield* fileSystem.remove(backupPath, { force: true }).pipe(Effect.ignore);
|
|
86752
|
+
return yield* refuse(filePath, `The original could not be backed up to '${backupPath}', so it was left as it is.`);
|
|
86753
|
+
}
|
|
86754
|
+
yield* writeFileStringAtomically({
|
|
86755
|
+
filePath,
|
|
86756
|
+
contents: compressed
|
|
86757
|
+
}).pipe(Effect.mapError((cause) => refuse(filePath, `The write failed: ${cause.message}. The original is at '${backupPath}'.`)));
|
|
86758
|
+
return {
|
|
86759
|
+
path: filePath,
|
|
86760
|
+
backupPath,
|
|
86761
|
+
charsBefore: original.length,
|
|
86762
|
+
charsAfter: compressed.length,
|
|
86763
|
+
estimatedTokensBefore: estimateTokens(original),
|
|
86764
|
+
estimatedTokensAfter: estimateTokens(compressed),
|
|
86765
|
+
warnings: validation.warnings
|
|
86766
|
+
};
|
|
85599
86767
|
})
|
|
85600
86768
|
});
|
|
85601
86769
|
//#endregion
|
|
@@ -87179,7 +88347,8 @@ const make$2 = Effect.gen(function* () {
|
|
|
87179
88347
|
modelSelection: desiredModelSelection,
|
|
87180
88348
|
...input?.resumeCursor !== void 0 ? { resumeCursor: input.resumeCursor } : {},
|
|
87181
88349
|
runtimeMode: desiredRuntimeMode,
|
|
87182
|
-
compressMode: thread.compressMode
|
|
88350
|
+
compressMode: thread.compressMode,
|
|
88351
|
+
unpromptedSubagents: thread.unpromptedSubagents
|
|
87183
88352
|
});
|
|
87184
88353
|
const bindSessionToThread = (session) => Effect.gen(function* () {
|
|
87185
88354
|
if (session.providerInstanceId === void 0) return yield* new ProviderAdapterRequestError({
|
|
@@ -87281,7 +88450,8 @@ const make$2 = Effect.gen(function* () {
|
|
|
87281
88450
|
...normalizedAttachments.length > 0 ? { attachments: normalizedAttachments } : {},
|
|
87282
88451
|
...modelForTurn !== void 0 ? { modelSelection: modelForTurn } : {},
|
|
87283
88452
|
...input.interactionMode !== void 0 ? { interactionMode: input.interactionMode } : {},
|
|
87284
|
-
compressMode
|
|
88453
|
+
compressMode,
|
|
88454
|
+
unpromptedSubagents: thread.unpromptedSubagents
|
|
87285
88455
|
};
|
|
87286
88456
|
});
|
|
87287
88457
|
const maybeGenerateAndRenameWorktreeBranchForFirstTurn = Effect.fn("maybeGenerateAndRenameWorktreeBranchForFirstTurn")(function* (input) {
|
|
@@ -88537,7 +89707,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
88537
89707
|
sink,
|
|
88538
89708
|
...delegate ? { delegate } : {}
|
|
88539
89709
|
});
|
|
88540
|
-
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$
|
|
89710
|
+
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$41(sink));
|
|
88541
89711
|
})).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
|
|
88542
89712
|
const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
|
|
88543
89713
|
url: config.otlpMetricsUrl,
|
|
@@ -88816,25 +89986,25 @@ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReacto
|
|
|
88816
89986
|
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$3));
|
|
88817
89987
|
const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
|
|
88818
89988
|
const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
|
|
88819
|
-
const VcsDriverRegistryLayerLive = layer$
|
|
88820
|
-
const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$
|
|
88821
|
-
const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$
|
|
88822
|
-
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$
|
|
89989
|
+
const VcsDriverRegistryLayerLive = layer$37.pipe(Layer.provide(layer$38));
|
|
89990
|
+
const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
89991
|
+
const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$33));
|
|
89992
|
+
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$39));
|
|
88823
89993
|
const GitWorkflowLayerLive = layer$12.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
|
|
88824
|
-
const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$
|
|
88825
|
-
const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$
|
|
88826
|
-
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
88827
|
-
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
88828
|
-
const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$
|
|
89994
|
+
const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
|
|
89995
|
+
const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
89996
|
+
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$38), 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))));
|
|
89997
|
+
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$35), Layer.provideMerge(layer$36.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
|
|
89998
|
+
const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$54));
|
|
88829
89999
|
const TerminalLayerLive = layer$29.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
|
|
88830
90000
|
const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$27), Layer.provideMerge(PortScannerLayerLive));
|
|
88831
|
-
const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$
|
|
88832
|
-
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$
|
|
88833
|
-
const WorkspaceLayerLive = Layer.mergeAll(layer$
|
|
88834
|
-
const ProjectFaviconResolverLayerLive = layer$
|
|
88835
|
-
const AuthLayerLive = layer$
|
|
90001
|
+
const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$44));
|
|
90002
|
+
const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$44), Layer.provide(WorkspaceEntriesLayerLive));
|
|
90003
|
+
const WorkspaceLayerLive = Layer.mergeAll(layer$44, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
|
|
90004
|
+
const ProjectFaviconResolverLayerLive = layer$42.pipe(Layer.provide(layer$44), Layer.provide(layer$43));
|
|
90005
|
+
const AuthLayerLive = layer$64.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$68));
|
|
88836
90006
|
const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
|
|
88837
|
-
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$
|
|
90007
|
+
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$52), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$61.pipe(Layer.provide(layer$68))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$53), Layer.provideMerge(layer$46), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$31.pipe(Layer.provideMerge(Layer.mergeAll(layer$58, layer$32).pipe(Layer.provideMerge(layer$59), Layer.provideMerge(layer$60))))), Layer.provideMerge(layer$68)).pipe(Layer.provideMerge(layer$8), Layer.provideMerge(layer$7), Layer.provideMerge(layer$6), Layer.provideMerge(layer$49), Layer.provideMerge(layer$51), Layer.provideMerge(layer$50), Layer.provide(layer$72));
|
|
88838
90008
|
/**
|
|
88839
90009
|
* Hub asset sync.
|
|
88840
90010
|
*
|
|
@@ -88842,9 +90012,9 @@ const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(Checkpo
|
|
|
88842
90012
|
* not-configured shape, and every call reports that rather than failing — so
|
|
88843
90013
|
* this costs a server with no hub nothing but a layer.
|
|
88844
90014
|
*/
|
|
88845
|
-
const AssetSyncLive = layer$
|
|
88846
|
-
const RuntimeServicesLive = layer$
|
|
88847
|
-
const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, 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$
|
|
90015
|
+
const AssetSyncLive = layer$55.pipe(Layer.provideMerge(layer$56), Layer.provideMerge(layer$57));
|
|
90016
|
+
const RuntimeServicesLive = layer$45.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
|
|
90017
|
+
const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, 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$43), Layer.provide(layer$28), Layer.provide(layer$47), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
|
|
88848
90018
|
const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
88849
90019
|
const config = yield* ServerConfig$1;
|
|
88850
90020
|
yield* fixPath();
|
|
@@ -88887,7 +90057,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
88887
90057
|
cause,
|
|
88888
90058
|
servePort: configured.servePort
|
|
88889
90059
|
}))) : Effect.void)) : Layer.empty;
|
|
88890
|
-
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$
|
|
90060
|
+
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$40), Layer.provideMerge(PlatformServicesLive));
|
|
88891
90061
|
}));
|
|
88892
90062
|
const runServer = Layer.launch(makeServerLayer);
|
|
88893
90063
|
//#endregion
|
|
@@ -89049,11 +90219,11 @@ const reconcileWithNewBinary = Effect.fn("cli.selfUpdate.reconcileWithNewBinary"
|
|
|
89049
90219
|
//#endregion
|
|
89050
90220
|
//#region src/cli/service.ts
|
|
89051
90221
|
const isBootServiceCommandError = Schema$1.is(BootServiceCommandError);
|
|
89052
|
-
const bootServiceLayer = (config) => layer$
|
|
90222
|
+
const bootServiceLayer = (config) => layer$48({
|
|
89053
90223
|
baseDir: config.baseDir,
|
|
89054
90224
|
logsDir: config.logsDir,
|
|
89055
90225
|
cliVersion: version
|
|
89056
|
-
}).pipe(Layer.provide(layer$
|
|
90226
|
+
}).pipe(Layer.provide(layer$54));
|
|
89057
90227
|
/** Install, update, or repair the service using the CLI version running this command. */
|
|
89058
90228
|
const reconcileService = Effect.fn("cli.service.reconcile")(function* () {
|
|
89059
90229
|
const service = yield* BootService;
|
|
@@ -89100,7 +90270,7 @@ const runServiceCommand = Effect.fn("cli.service.run")(function* (flags, run, pr
|
|
|
89100
90270
|
const baseDirNotice = yield* describeNonDefaultBaseDir(config.baseDir);
|
|
89101
90271
|
if (baseDirNotice !== null) yield* Console.error(baseDirNotice);
|
|
89102
90272
|
if (prepare !== void 0) yield* prepare(config);
|
|
89103
|
-
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$
|
|
90273
|
+
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$54)));
|
|
89104
90274
|
});
|
|
89105
90275
|
/**
|
|
89106
90276
|
* Options the installed unit carries, rather than ones this command consumes.
|
|
@@ -89254,7 +90424,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
|
|
|
89254
90424
|
]));
|
|
89255
90425
|
//#endregion
|
|
89256
90426
|
//#region src/bin.ts
|
|
89257
|
-
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$
|
|
90427
|
+
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$72, FetchHttpClient.layer);
|
|
89258
90428
|
/**
|
|
89259
90429
|
* Prints an update reminder before dispatching, at most once a day.
|
|
89260
90430
|
*
|