@p4code/cli 0.1.12 → 0.1.13

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.
Files changed (87) hide show
  1. package/dist/bin.mjs +201 -32
  2. package/dist/client/assets/{DiffPanel-DLEF2Os4.js → DiffPanel-Bpvhj9Zk.js} +3 -3
  3. package/dist/client/assets/{FilePreviewPanel-8D_2Xs92.js → FilePreviewPanel-C2_gi2li.js} +5 -5
  4. package/dist/client/assets/PreviewPanel-CXrvKPAn.js +2 -0
  5. package/dist/client/assets/{angular-html-CMBWPyD3.js → angular-html-tWdnCR5u.js} +2 -2
  6. package/dist/client/assets/{angular-ts-BatZhjLf.js → angular-ts-DHHrhqEn.js} +2 -2
  7. package/dist/client/assets/{apl-Cx1sW3hC.js → apl-Dttzd1My.js} +2 -2
  8. package/dist/client/assets/arrow-right-DL8xTI3l.js +2 -0
  9. package/dist/client/assets/{astro-nMa7HQcv.js → astro-BhhLcbHg.js} +2 -2
  10. package/dist/client/assets/{blade-JxAt8tFv.js → blade-D1XdhGNZ.js} +2 -2
  11. package/dist/client/assets/{c-C-yEqtHp.js → c-DU3so7RH.js} +2 -2
  12. package/dist/client/assets/{cobol-CA3DrkO1.js → cobol-C5SwCVtJ.js} +2 -2
  13. package/dist/client/assets/{coffee-CNzul851.js → coffee-D8JHirJ4.js} +2 -2
  14. package/dist/client/assets/{cpp-DYasO6ny.js → cpp-BrxgqiPv.js} +2 -2
  15. package/dist/client/assets/{crystal-BkYnv3Y5.js → crystal-LnjbHrAj.js} +2 -2
  16. package/dist/client/assets/{css-GnxXZE-U.js → css-BhvHnfwC.js} +2 -2
  17. package/dist/client/assets/{edge-DHx6AdO-.js → edge-BIAZ2O1m.js} +2 -2
  18. package/dist/client/assets/{elixir-XiEvMT4-.js → elixir-C7fzptdf.js} +2 -2
  19. package/dist/client/assets/{elm-BY4GYI5F.js → elm-24neygAB.js} +2 -2
  20. package/dist/client/assets/{erb-DDG6lOki.js → erb-DpLDFI3P.js} +2 -2
  21. package/dist/client/assets/{fileCommentAnnotations-BTZDcAeh.js → fileCommentAnnotations-D9LoOqKz.js} +2 -2
  22. package/dist/client/assets/{git-rebase-BDUy60An.js → git-rebase-nk76LFrn.js} +2 -2
  23. package/dist/client/assets/{glimmer-js-Dpr_XG7j.js → glimmer-js-D4faXOGy.js} +2 -2
  24. package/dist/client/assets/{glimmer-ts-CtZ0ZipS.js → glimmer-ts-CUIVPmuw.js} +2 -2
  25. package/dist/client/assets/{glsl-DHtQlcKL.js → glsl-CHEysBk5.js} +2 -2
  26. package/dist/client/assets/{graphql-DtNuYKEb.js → graphql-DxDXWgtu.js} +2 -2
  27. package/dist/client/assets/{hack-BqNfldCe.js → hack-SE0rPM7F.js} +2 -2
  28. package/dist/client/assets/{haml-mPiLB45s.js → haml-CZNVJ1t_.js} +2 -2
  29. package/dist/client/assets/{handlebars-BLxX_l2A.js → handlebars-D3H0z0i1.js} +2 -2
  30. package/dist/client/assets/{html-DU5G3F4s.js → html-BXh14Kiu.js} +2 -2
  31. package/dist/client/assets/{html-derivative-BMJPXTuS.js → html-derivative-Dcx75xJi.js} +2 -2
  32. package/dist/client/assets/{http-6kGF1eof.js → http-CHN_K5kg.js} +2 -2
  33. package/dist/client/assets/{hurl-CvT1bXUG.js → hurl-DcyaHxXE.js} +2 -2
  34. package/dist/client/assets/{index-nkPMSYxq.css → index-D7hXE3Wh.css} +1 -1
  35. package/dist/client/assets/index-DesIBOH0.js +660 -0
  36. package/dist/client/assets/{java-bBnbDfw8.js → java-CibfJb97.js} +2 -2
  37. package/dist/client/assets/{javascript-CpOINVUc.js → javascript-CGKYJrgO.js} +2 -2
  38. package/dist/client/assets/{jinja-CItwptlU.js → jinja-hMi6h2V1.js} +2 -2
  39. package/dist/client/assets/{jison-BWvHru6a.js → jison-D5hwL1Vj.js} +2 -2
  40. package/dist/client/assets/{json-ClObSVU5.js → json-DBBzorBt.js} +2 -2
  41. package/dist/client/assets/{jsx-vHozUqKh.js → jsx-CfjpnlWf.js} +2 -2
  42. package/dist/client/assets/{julia-CITEF0SC.js → julia-DY-wGzwr.js} +2 -2
  43. package/dist/client/assets/{just-CAMHq4cU.js → just-Aiaxo0L3.js} +2 -2
  44. package/dist/client/assets/{latex-BHB-Vy2g.js → latex-Cl7y6v9p.js} +2 -2
  45. package/dist/client/assets/{liquid-rsijXGco.js → liquid-tjIYQaDR.js} +2 -2
  46. package/dist/client/assets/{lua-CPA1zmkS.js → lua-DeDHmNSA.js} +2 -2
  47. package/dist/client/assets/{marko-D9CJEgH2.js → marko-BLEE3RS_.js} +2 -2
  48. package/dist/client/assets/{mdc-DL5ptUuf.js → mdc-DBLy0ju2.js} +2 -2
  49. package/dist/client/assets/{nginx-DAAmFPDe.js → nginx-BpS56zJM.js} +2 -2
  50. package/dist/client/assets/{nim-DmaHLOWa.js → nim-BP_5ZWs4.js} +2 -2
  51. package/dist/client/assets/{perl-Bw03qQ4D.js → perl-BNoghH8w.js} +2 -2
  52. package/dist/client/assets/{php-DdSlZ5fF.js → php-fikhFdsH.js} +2 -2
  53. package/dist/client/assets/{pug-CgQdUdQK.js → pug-BmML_p4L.js} +2 -2
  54. package/dist/client/assets/{qml-6-Z__KDk.js → qml-WOQTdjfD.js} +2 -2
  55. package/dist/client/assets/{r-BwsNM1XU.js → r-BuLVFJ9C.js} +2 -2
  56. package/dist/client/assets/{razor-DRWY5qRs.js → razor-CsZ5mXvp.js} +2 -2
  57. package/dist/client/assets/{regexp-BGiLplmg.js → regexp-BbB_Z0k0.js} +2 -2
  58. package/dist/client/assets/{rst-CND1NmX_.js → rst-CGogIoWE.js} +2 -2
  59. package/dist/client/assets/{ruby-Dlxt-z_r.js → ruby-Drt9dpIY.js} +2 -2
  60. package/dist/client/assets/{sas-DFeunfku.js → sas-mvidrzzg.js} +2 -2
  61. package/dist/client/assets/{scss-D_BTo2XD.js → scss-DcqXsy4k.js} +2 -2
  62. package/dist/client/assets/{shellscript-cEuOjvsv.js → shellscript-C6nla6y6.js} +2 -2
  63. package/dist/client/assets/{shellsession-CeWrE-Lw.js → shellsession-Dhkmvk-h.js} +2 -2
  64. package/dist/client/assets/{soy-DdFNKMwD.js → soy-CA1GOdLw.js} +2 -2
  65. package/dist/client/assets/{sql-3jzdtF3L.js → sql-CaDtCgQd.js} +2 -2
  66. package/dist/client/assets/{stata-CfftDdbo.js → stata-r5dYDO1a.js} +2 -2
  67. package/dist/client/assets/{surrealql-BgLa39M_.js → surrealql-CreiDVJS.js} +2 -2
  68. package/dist/client/assets/{svelte-CJNznzEX.js → svelte-LQf52vP7.js} +2 -2
  69. package/dist/client/assets/{templ-DiQ0ONH_.js → templ-BAiCCrhW.js} +2 -2
  70. package/dist/client/assets/{tex-Dj5-ewTi.js → tex-Bi4veNnI.js} +2 -2
  71. package/dist/client/assets/textarea-8UeQ85tZ.js +46 -0
  72. package/dist/client/assets/{ts-tags-Rut2YPAl.js → ts-tags-CmONaW11.js} +2 -2
  73. package/dist/client/assets/{tsx-TxGWIfKc.js → tsx-DEGaq1SP.js} +2 -2
  74. package/dist/client/assets/{twig-CEDmL9ir.js → twig-DR3myS6w.js} +2 -2
  75. package/dist/client/assets/{typescript-B1NW_Svr.js → typescript-pTX3WTUF.js} +2 -2
  76. package/dist/client/assets/{vue-CEjpLlUp.js → vue-_Gh228sM.js} +2 -2
  77. package/dist/client/assets/{vue-html-BLRayXbW.js → vue-html-DqI2SuCG.js} +2 -2
  78. package/dist/client/assets/{vue-vine-BaZ_eWYq.js → vue-vine-DJ2u5TuR.js} +2 -2
  79. package/dist/client/assets/{xml-WjUY_YSL.js → xml-DtWHD1Mk.js} +2 -2
  80. package/dist/client/assets/{xsl-rMBkkP2N.js → xsl--uIbb82K.js} +2 -2
  81. package/dist/client/assets/{yaml-BVcdKGq_.js → yaml-BYZt09An.js} +2 -2
  82. package/dist/client/index.html +3 -3
  83. package/package.json +1 -1
  84. package/dist/client/assets/PreviewPanel-DiR-_u2D.js +0 -2
  85. package/dist/client/assets/arrow-right-D6CCHJEU.js +0 -2
  86. package/dist/client/assets/index-JvBwT8k1.js +0 -660
  87. package/dist/client/assets/textarea-CtwXMNmJ.js +0 -46
package/dist/bin.mjs CHANGED
@@ -233,7 +233,7 @@ const make$73 = () => {
233
233
  const layer$69 = Layer.sync(NetService, make$73);
234
234
  //#endregion
235
235
  //#region package.json
236
- var version = "0.1.12";
236
+ var version = "0.1.13";
237
237
  //#endregion
238
238
  //#region src/config.ts
239
239
  /**
@@ -1657,6 +1657,7 @@ const CompressMode = Schema$1.Literals([
1657
1657
  "full",
1658
1658
  "ultra"
1659
1659
  ]);
1660
+ const DEFAULT_COMPRESS_MODE = "full";
1660
1661
  const ProviderRequestKind = Schema$1.Literals([
1661
1662
  "command",
1662
1663
  "file-read",
@@ -1833,7 +1834,7 @@ const OrchestrationThread = Schema$1.Struct({
1833
1834
  modelSelection: ModelSelection,
1834
1835
  runtimeMode: RuntimeMode,
1835
1836
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
1836
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
1837
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
1837
1838
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
1838
1839
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
1839
1840
  latestTurn: Schema$1.NullOr(OrchestrationLatestTurn),
@@ -1874,7 +1875,7 @@ const OrchestrationThreadShell = Schema$1.Struct({
1874
1875
  modelSelection: ModelSelection,
1875
1876
  runtimeMode: RuntimeMode,
1876
1877
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
1877
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
1878
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
1878
1879
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
1879
1880
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
1880
1881
  latestTurn: Schema$1.NullOr(OrchestrationLatestTurn),
@@ -1997,7 +1998,7 @@ const ThreadCreateCommand = Schema$1.Struct({
1997
1998
  modelSelection: ModelSelection,
1998
1999
  runtimeMode: RuntimeMode,
1999
2000
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
2000
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2001
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2001
2002
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
2002
2003
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
2003
2004
  createdAt: IsoDateTime
@@ -2077,7 +2078,7 @@ const ThreadTurnStartBootstrapCreateThread = Schema$1.Struct({
2077
2078
  modelSelection: ModelSelection,
2078
2079
  runtimeMode: RuntimeMode,
2079
2080
  interactionMode: ProviderInteractionMode,
2080
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2081
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2081
2082
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
2082
2083
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
2083
2084
  createdAt: IsoDateTime
@@ -2107,7 +2108,7 @@ const ThreadTurnStartCommand = Schema$1.Struct({
2107
2108
  titleSeed: Schema$1.optional(TrimmedNonEmptyString),
2108
2109
  runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
2109
2110
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
2110
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2111
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2111
2112
  bootstrap: Schema$1.optional(ThreadTurnStartBootstrap),
2112
2113
  sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
2113
2114
  createdAt: IsoDateTime
@@ -2126,7 +2127,7 @@ const ClientThreadTurnStartCommand = Schema$1.Struct({
2126
2127
  titleSeed: Schema$1.optional(TrimmedNonEmptyString),
2127
2128
  runtimeMode: RuntimeMode,
2128
2129
  interactionMode: ProviderInteractionMode,
2129
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2130
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2130
2131
  bootstrap: Schema$1.optional(ThreadTurnStartBootstrap),
2131
2132
  sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
2132
2133
  createdAt: IsoDateTime
@@ -2346,7 +2347,7 @@ const ThreadCreatedPayload$1 = Schema$1.Struct({
2346
2347
  modelSelection: ModelSelection,
2347
2348
  runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
2348
2349
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
2349
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2350
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2350
2351
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
2351
2352
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
2352
2353
  createdAt: IsoDateTime,
@@ -2406,7 +2407,7 @@ const ThreadInteractionModeSetPayload$1 = Schema$1.Struct({
2406
2407
  });
2407
2408
  const ThreadCompressModeSetPayload$1 = Schema$1.Struct({
2408
2409
  threadId: ThreadId,
2409
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2410
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2410
2411
  updatedAt: IsoDateTime
2411
2412
  });
2412
2413
  const ThreadMessageSentPayload = Schema$1.Struct({
@@ -2427,7 +2428,7 @@ const ThreadTurnStartRequestedPayload = Schema$1.Struct({
2427
2428
  titleSeed: Schema$1.optional(TrimmedNonEmptyString),
2428
2429
  runtimeMode: RuntimeMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE$2))),
2429
2430
  interactionMode: ProviderInteractionMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE))),
2430
- compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed("off"))),
2431
+ compressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
2431
2432
  sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference),
2432
2433
  createdAt: IsoDateTime
2433
2434
  });
@@ -7651,6 +7652,57 @@ const ThreadControlToolError = Schema$1.Union([
7651
7652
  ThreadRenameRejectedError,
7652
7653
  MemoryAppendFailedError
7653
7654
  ]);
7655
+ const ThreadWatchEventsInput = Schema$1.Struct({
7656
+ threadId: ThreadId.annotate({ description: "The watched thread to read events from. Must be explicitly granted." }),
7657
+ afterSequence: Schema$1.optional(NonNegativeInt.annotate({ description: "Exclusive sequence cursor. Events with a higher sequence are returned. Omit to read from the beginning." })),
7658
+ limit: Schema$1.optional(NonNegativeInt.check(Schema$1.isLessThanOrEqualTo(200)).annotate({ description: `Maximum events to return (default 50, max 200).` }))
7659
+ });
7660
+ const ThreadWatchEventsResult = Schema$1.Struct({
7661
+ threadId: ThreadId,
7662
+ /** Ordered by sequence ascending; resume with the last event's sequence. */
7663
+ events: Schema$1.Array(OrchestrationEvent),
7664
+ /**
7665
+ * The engine's latest persisted sequence at read time. Equal to the last
7666
+ * returned event's sequence when the watcher is caught up.
7667
+ */
7668
+ headSequence: NonNegativeInt,
7669
+ /** True when more events for this thread exist past the returned page. */
7670
+ hasMore: Schema$1.Boolean
7671
+ });
7672
+ var WatchToolUnavailableError = class extends Schema$1.TaggedErrorClass()("WatchToolUnavailableError", {
7673
+ capability: Schema$1.Literal("watch"),
7674
+ environmentId: EnvironmentId,
7675
+ threadId: ThreadId,
7676
+ providerSessionId: TrimmedNonEmptyString,
7677
+ providerInstanceId: ProviderInstanceId
7678
+ }) {
7679
+ get message() {
7680
+ return `MCP credential does not grant the ${this.capability} capability.`;
7681
+ }
7682
+ };
7683
+ /**
7684
+ * The capability is present but the requested thread is not in the granted
7685
+ * set. Separate from {@link WatchToolUnavailableError} so a watcher can tell
7686
+ * "you cannot watch at all" apart from "not this thread".
7687
+ */
7688
+ var ThreadWatchNotPermittedError = class extends Schema$1.TaggedErrorClass()("ThreadWatchNotPermittedError", { threadId: ThreadId }) {
7689
+ get message() {
7690
+ return `This session was not granted watch access to thread ${this.threadId}.`;
7691
+ }
7692
+ };
7693
+ var ThreadWatchFailedError = class extends Schema$1.TaggedErrorClass()("ThreadWatchFailedError", {
7694
+ threadId: ThreadId,
7695
+ detail: Schema$1.String
7696
+ }) {
7697
+ get message() {
7698
+ return `Reading events for thread ${this.threadId} failed: ${this.detail}`;
7699
+ }
7700
+ };
7701
+ const ThreadWatchToolError = Schema$1.Union([
7702
+ WatchToolUnavailableError,
7703
+ ThreadWatchNotPermittedError,
7704
+ ThreadWatchFailedError
7705
+ ]);
7654
7706
  //#endregion
7655
7707
  //#region ../../packages/contracts/src/agentAsset.ts
7656
7708
  /**
@@ -23936,11 +23988,66 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
23936
23988
  });
23937
23989
  const OrchestrationProjectionSnapshotQueryLive = Layer.effect(ProjectionSnapshotQuery, makeProjectionSnapshotQuery);
23938
23990
  //#endregion
23991
+ //#region src/orchestration/Services/ThreadEventStream.ts
23992
+ var ThreadEventStreamService = class extends Context.Service()("@p4code/cli/orchestration/Services/ThreadEventStream/ThreadEventStreamService") {};
23993
+ //#endregion
23994
+ //#region src/orchestration/Layers/ThreadEventStream.ts
23995
+ const makeThreadEventStream = Effect.gen(function* () {
23996
+ const engine = yield* OrchestrationEngineService;
23997
+ const isThreadEvent = (threadId) => (event) => event.aggregateKind === "thread" && event.aggregateId === threadId;
23998
+ const watch = (input) => Stream.unwrap(Effect.gen(function* () {
23999
+ const matchesThread = isThreadEvent(input.threadId);
24000
+ const liveBuffer = yield* Queue.unbounded();
24001
+ yield* Effect.forkScoped(engine.streamDomainEvents.pipe(Stream.filter(matchesThread), Stream.runForEach((event) => Queue.offer(liveBuffer, event))), { startImmediately: true });
24002
+ const afterSequence = input.afterSequence ?? 0;
24003
+ const headSequence = yield* engine.latestSequence;
24004
+ const replayGap = headSequence - afterSequence;
24005
+ const catchUp = replayGap > 0 ? engine.readEvents(afterSequence, replayGap).pipe(Stream.filter(matchesThread)) : Stream.empty;
24006
+ const caughtUp = Stream.make({
24007
+ kind: "caught-up",
24008
+ headSequence
24009
+ });
24010
+ const live = Stream.fromQueue(liveBuffer).pipe(Stream.filter((event) => event.sequence > headSequence));
24011
+ return Stream.concat(catchUp.pipe(Stream.map((event) => ({
24012
+ kind: "event",
24013
+ event
24014
+ }))), Stream.concat(caughtUp, live.pipe(Stream.map((event) => ({
24015
+ kind: "event",
24016
+ event
24017
+ })))));
24018
+ }));
24019
+ const read = (input) => Effect.gen(function* () {
24020
+ const matchesThread = isThreadEvent(input.threadId);
24021
+ const afterSequence = input.afterSequence ?? 0;
24022
+ const headSequence = yield* engine.latestSequence;
24023
+ const replayGap = headSequence - afterSequence;
24024
+ if (replayGap <= 0) return {
24025
+ events: [],
24026
+ headSequence,
24027
+ hasMore: false
24028
+ };
24029
+ const collected = yield* engine.readEvents(afterSequence, replayGap).pipe(Stream.filter(matchesThread), Stream.take(input.limit + 1), Stream.runCollect);
24030
+ const events = Array.from(collected);
24031
+ const hasMore = events.length > input.limit;
24032
+ return {
24033
+ events: hasMore ? events.slice(0, input.limit) : events,
24034
+ headSequence,
24035
+ hasMore
24036
+ };
24037
+ });
24038
+ return ThreadEventStreamService.of({
24039
+ watch,
24040
+ read
24041
+ });
24042
+ });
24043
+ const ThreadEventStreamLive = Layer.effect(ThreadEventStreamService, makeThreadEventStream);
24044
+ //#endregion
23939
24045
  //#region src/orchestration/runtimeLayer.ts
23940
24046
  const OrchestrationEventInfrastructureLayerLive = Layer.mergeAll(OrchestrationEventStoreLive, OrchestrationCommandReceiptRepositoryLive);
23941
24047
  const OrchestrationProjectionPipelineLayerLive = OrchestrationProjectionPipelineLive.pipe(Layer.provide(OrchestrationEventStoreLive));
23942
24048
  const OrchestrationInfrastructureLayerLive = Layer.mergeAll(OrchestrationProjectionSnapshotQueryLive, OrchestrationEventInfrastructureLayerLive, OrchestrationProjectionPipelineLayerLive);
23943
- const OrchestrationLayerLive = Layer.mergeAll(OrchestrationInfrastructureLayerLive, OrchestrationEngineLive.pipe(Layer.provide(OrchestrationInfrastructureLayerLive)));
24049
+ const OrchestrationEngineLayerLive = OrchestrationEngineLive.pipe(Layer.provide(OrchestrationInfrastructureLayerLive));
24050
+ const OrchestrationLayerLive = Layer.mergeAll(OrchestrationInfrastructureLayerLive, OrchestrationEngineLayerLive, ThreadEventStreamLive.pipe(Layer.provide(OrchestrationEngineLayerLive)));
23944
24051
  //#endregion
23945
24052
  //#region ../../packages/shared/src/keybindings.ts
23946
24053
  const DEFAULT_KEYBINDINGS = [
@@ -27210,7 +27317,7 @@ const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
27210
27317
  title: "New thread",
27211
27318
  modelSelection: nextProjectDefaultModelSelection,
27212
27319
  interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
27213
- compressMode: "off",
27320
+ compressMode: DEFAULT_COMPRESS_MODE,
27214
27321
  runtimeMode: "full-access",
27215
27322
  branch: null,
27216
27323
  worktreePath: null,
@@ -33254,6 +33361,12 @@ const toTaskStoreError = (operation) => (cause) => Effect.logWarning("task store
33254
33361
  /**
33255
33362
  * The `auto` rendering: here is the task, do it.
33256
33363
  *
33364
+ * The prompt carries a reference to the task, not a copy of it. Inlining the
33365
+ * body flattened the row into plain text: labels, project and priority were
33366
+ * lost, and an edit made after the thread started was invisible to an agent
33367
+ * still reading its stale snapshot. The row stays the single source of truth
33368
+ * and the agent reads it live over MCP.
33369
+ *
33257
33370
  * Two instructions carry their weight. The agent is told its thread is already
33258
33371
  * linked to the task, because otherwise its first useful move is to guess which
33259
33372
  * board row it is on. And it is told to leave `status` alone: the server moved
@@ -33262,18 +33375,16 @@ const toTaskStoreError = (operation) => (cause) => Effect.logWarning("task store
33262
33375
  * the reason the board's columns still mean something.
33263
33376
  */
33264
33377
  const buildAutoPrompt = (task) => {
33265
- const body = task.body.trim();
33266
- return `You are picking up a task from the board. Do the work.
33378
+ const reference = task.readableId ?? task.taskId;
33379
+ return `You are picking up task \`${reference}\` from the board: ${task.title}
33267
33380
 
33268
- ## ${task.title}
33381
+ Start by reading the task itself with \`task_current\` (or \`task_get\` with \`${reference}\`). The body, labels, project and priority live on the row, not in this message, and the row may have been edited since this thread started — what it says now is the source of truth. Re-read it the same way whenever you need the fields again.
33269
33382
 
33270
- ${body.length === 0 ? "_The task has no description. Read enough of the repository to work out what it means, and ask if it is genuinely ambiguous._" : body}
33271
-
33272
- This thread is linked to task \`${task.taskId}\`, which is now In progress. \`task_current\` re-reads it if you need the fields again.
33383
+ This thread is already linked to the task, which is now In progress. Do the work.
33273
33384
 
33274
33385
  Record what you find with \`task_update\` as you go — a decision you made, a constraint you hit, something the task turned out to be wrong about. That is what makes the row worth reading afterwards. Leave \`status\` alone: moving work across the board is the user's call.
33275
33386
 
33276
- Start by reading the code the task concerns. If it turns out to be specified too poorly to act on, say so and stop rather than guessing at what was meant.`;
33387
+ After reading the task, read the code it concerns. If it turns out to be specified too poorly to act on, say so and stop rather than guessing at what was meant.`;
33277
33388
  };
33278
33389
  /**
33279
33390
  * Render a task into the prompt that seeds its thread.
@@ -36228,6 +36339,24 @@ const requireTaskCapability = Effect.fn("mcp.requireTaskCapability")(function* (
36228
36339
  });
36229
36340
  return invocation;
36230
36341
  });
36342
+ /**
36343
+ * The watch capability's guard is two checks, not one: the capability must be
36344
+ * present AND the requested thread must be in the explicit grant set. The two
36345
+ * failures are distinct errors so a watcher can tell "this session cannot
36346
+ * watch at all" apart from "not this thread".
36347
+ */
36348
+ const requireWatchCapability = Effect.fn("mcp.requireWatchCapability")(function* (watchedThreadId) {
36349
+ const invocation = yield* McpInvocationContext;
36350
+ if (!invocation.capabilities.has("watch")) return yield* new WatchToolUnavailableError({
36351
+ capability: "watch",
36352
+ environmentId: invocation.environmentId,
36353
+ threadId: invocation.threadId,
36354
+ providerSessionId: invocation.providerSessionId,
36355
+ providerInstanceId: invocation.providerInstanceId
36356
+ });
36357
+ if (!invocation.watchThreadIds?.has(watchedThreadId)) return yield* new ThreadWatchNotPermittedError({ threadId: watchedThreadId });
36358
+ return invocation;
36359
+ });
36231
36360
  /** Third of the trio, for the same reason the second exists. */
36232
36361
  const requireThreadCapability = Effect.fn("mcp.requireThreadCapability")(function* () {
36233
36362
  const invocation = yield* McpInvocationContext;
@@ -43885,8 +44014,8 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
43885
44014
  mode: "auto",
43886
44015
  task: {
43887
44016
  taskId,
43888
- title: task.title,
43889
- body: task.body
44017
+ readableId: task.readableId,
44018
+ title: task.title
43890
44019
  }
43891
44020
  }),
43892
44021
  attachments: []
@@ -43895,14 +44024,14 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
43895
44024
  titleSeed: threadTitle,
43896
44025
  runtimeMode: DEFAULT_RUNTIME_MODE$2,
43897
44026
  interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
43898
- compressMode: "off",
44027
+ compressMode: DEFAULT_COMPRESS_MODE,
43899
44028
  bootstrap: { createThread: {
43900
44029
  projectId: plan.projectId,
43901
44030
  title: threadTitle,
43902
44031
  modelSelection,
43903
44032
  runtimeMode: DEFAULT_RUNTIME_MODE$2,
43904
44033
  interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
43905
- compressMode: "off",
44034
+ compressMode: DEFAULT_COMPRESS_MODE,
43906
44035
  branch: null,
43907
44036
  worktreePath: null,
43908
44037
  createdAt
@@ -45186,16 +45315,20 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
45186
45315
  const providerSessionId = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
45187
45316
  const rawToken = yield* crypto.randomBytes(32).pipe(Effect.map(tokenFromBytes), Effect.orDie);
45188
45317
  const tokenHash = yield* hashToken(rawToken);
45318
+ const watchThreadIds = new Set((request.watchThreadIds ?? []).map((threadId) => ThreadId.make(threadId)));
45319
+ const capabilities = /* @__PURE__ */ new Set([
45320
+ "preview",
45321
+ "tasks",
45322
+ "threads"
45323
+ ]);
45324
+ if (watchThreadIds.size > 0) capabilities.add("watch");
45189
45325
  const scope = {
45190
45326
  environmentId,
45191
45327
  threadId: ThreadId.make(request.threadId),
45192
45328
  providerSessionId,
45193
45329
  providerInstanceId: ProviderInstanceId.make(request.providerInstanceId),
45194
- capabilities: /* @__PURE__ */ new Set([
45195
- "preview",
45196
- "tasks",
45197
- "threads"
45198
- ]),
45330
+ capabilities,
45331
+ ...watchThreadIds.size > 0 ? { watchThreadIds } : {},
45199
45332
  issuedAt
45200
45333
  };
45201
45334
  yield* SynchronizedRef.update(state, ({ records }) => {
@@ -82309,7 +82442,7 @@ const invokeTargeted = (operation, input, timeoutMs) => {
82309
82442
  const { tabId, ...operationInput } = input;
82310
82443
  return invoke(operation, operationInput, timeoutMs, tabId);
82311
82444
  };
82312
- const handlers$2 = {
82445
+ const handlers$3 = {
82313
82446
  preview_status: (input) => invokeTargeted("status", input ?? {}),
82314
82447
  preview_open: (input) => invokeTargeted("open", normalizePreviewOpenInput(input)),
82315
82448
  preview_navigate: (input) => invokeTargeted("navigate", input, input.timeoutMs),
@@ -82325,10 +82458,10 @@ const handlers$2 = {
82325
82458
  preview_recording_start: (input) => invokeTargeted("recordingStart", input ?? {}),
82326
82459
  preview_recording_stop: (input) => invokeTargeted("recordingStop", input ?? {})
82327
82460
  };
82328
- const { preview_snapshot, ...standardHandlers } = handlers$2;
82461
+ const { preview_snapshot, ...standardHandlers } = handlers$3;
82329
82462
  const PreviewStandardToolkitHandlersLive = PreviewStandardToolkit.toLayer(standardHandlers);
82330
82463
  const PreviewSnapshotToolkitHandlersLive = PreviewSnapshotToolkit.toLayer({ preview_snapshot });
82331
- PreviewToolkit.toLayer(handlers$2);
82464
+ PreviewToolkit.toLayer(handlers$3);
82332
82465
  //#endregion
82333
82466
  //#region src/mcp/toolkits/tasks/tools.ts
82334
82467
  const dependencies = [McpInvocationContext, TaskRepository];
@@ -82561,6 +82694,41 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
82561
82694
  })
82562
82695
  });
82563
82696
  //#endregion
82697
+ //#region src/mcp/toolkits/watch/tools.ts
82698
+ /**
82699
+ * Cross-thread by design, which is exactly why it is the most guarded tool in
82700
+ * the registry: the handler admits only threads in the session's explicit
82701
+ * `watchThreadIds` grant, never the token's whole reach. The read is a cursor
82702
+ * poll because MCP tools are request/response; a watcher advances
82703
+ * `afterSequence` with each page and knows it is caught up when `hasMore` is
82704
+ * false and the last sequence equals `headSequence`.
82705
+ */
82706
+ const ThreadWatchEventsTool = Tool.make("thread_watch_events", {
82707
+ description: "Read a watched thread's orchestration events after a sequence cursor. Returns an ordered page plus the head sequence; pass the last event's sequence back as afterSequence to poll forward. Only threads this session was explicitly granted are readable.",
82708
+ parameters: ThreadWatchEventsInput,
82709
+ success: ThreadWatchEventsResult,
82710
+ failure: ThreadWatchToolError,
82711
+ dependencies: [McpInvocationContext, ThreadEventStreamService]
82712
+ }).annotate(Tool.Title, "Read watched thread events").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
82713
+ const WatchToolkit = Toolkit.make(ThreadWatchEventsTool);
82714
+ const WatchToolkitHandlersLive = WatchToolkit.toLayer({ thread_watch_events: (input) => Effect.gen(function* () {
82715
+ yield* requireWatchCapability(input.threadId);
82716
+ const page = yield* (yield* ThreadEventStreamService).read({
82717
+ threadId: input.threadId,
82718
+ ...input.afterSequence !== void 0 ? { afterSequence: input.afterSequence } : {},
82719
+ limit: input.limit ?? 50
82720
+ }).pipe(Effect.mapError((cause) => new ThreadWatchFailedError({
82721
+ threadId: input.threadId,
82722
+ detail: cause.message
82723
+ })));
82724
+ return {
82725
+ threadId: input.threadId,
82726
+ events: page.events,
82727
+ headSequence: page.headSequence,
82728
+ hasMore: page.hasMore
82729
+ };
82730
+ }) });
82731
+ //#endregion
82564
82732
  //#region src/mcp/McpHttpServer.ts
82565
82733
  const unauthorized = HttpServerResponse.jsonUnsafe({
82566
82734
  error: "invalid_mcp_credential",
@@ -82665,12 +82833,13 @@ const PreviewSnapshotRegistrationLive = Layer.effectDiscard(registerPreviewSnaps
82665
82833
  const PreviewToolkitRegistrationLive = Layer.mergeAll(PreviewStandardToolkitRegistrationLive, PreviewSnapshotRegistrationLive);
82666
82834
  const TaskToolkitRegistrationLive = McpServer.toolkit(TaskToolkit).pipe(Layer.provide(TaskToolkitHandlersLive));
82667
82835
  const ThreadToolkitRegistrationLive = McpServer.toolkit(ThreadToolkit).pipe(Layer.provide(ThreadToolkitHandlersLive));
82836
+ const WatchToolkitRegistrationLive = McpServer.toolkit(WatchToolkit).pipe(Layer.provide(WatchToolkitHandlersLive));
82668
82837
  const McpTransportLive = McpServer.layerHttp({
82669
82838
  name: "P4Code",
82670
82839
  version,
82671
82840
  path: "/mcp"
82672
82841
  }).pipe(Layer.provide(McpAuthMiddlewareLive));
82673
- const layer = Layer.mergeAll(PreviewToolkitRegistrationLive, TaskToolkitRegistrationLive, ThreadToolkitRegistrationLive).pipe(Layer.provideMerge(McpTransportLive));
82842
+ const layer = Layer.mergeAll(PreviewToolkitRegistrationLive, TaskToolkitRegistrationLive, ThreadToolkitRegistrationLive, WatchToolkitRegistrationLive).pipe(Layer.provideMerge(McpTransportLive));
82674
82843
  //#endregion
82675
82844
  //#region src/orchestration/Services/CheckpointReactor.ts
82676
82845
  /**