t3code-cli 0.9.1 → 0.11.0

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 (126) hide show
  1. package/README.md +52 -14
  2. package/dist/application.js +2 -2
  3. package/dist/auth.js +1 -1
  4. package/dist/bin.js +1556 -341
  5. package/dist/cli.js +1 -1
  6. package/dist/config.js +1 -1
  7. package/dist/connection.js +1 -11
  8. package/dist/index.js +1 -1
  9. package/dist/layout.js +1 -1
  10. package/dist/node.js +2 -0
  11. package/dist/orchestration.js +2 -2
  12. package/dist/rpc.js +2 -2
  13. package/dist/runtime.js +1 -1
  14. package/dist/scope.js +1 -1
  15. package/dist/shared.js +1734 -756
  16. package/dist/src/application/index.d.ts +3 -2
  17. package/dist/src/application/layer.d.ts +82 -841
  18. package/dist/src/application/model-selection.d.ts +15 -0
  19. package/dist/src/application/models.d.ts +1 -87
  20. package/dist/src/application/project-commands.d.ts +9 -0
  21. package/dist/src/application/projects.d.ts +13 -135
  22. package/dist/src/application/service.d.ts +84 -5
  23. package/dist/src/application/shell-sequence.d.ts +2 -12
  24. package/dist/src/application/terminals.d.ts +66 -0
  25. package/dist/src/application/thread-commands.d.ts +47 -0
  26. package/dist/src/application/thread-update.d.ts +8 -0
  27. package/dist/src/application/thread-wait.d.ts +3 -14
  28. package/dist/src/application/threads.d.ts +21 -50
  29. package/dist/src/cli/flags.d.ts +3 -0
  30. package/dist/src/cli/output-format.d.ts +2 -0
  31. package/dist/src/domain/error.d.ts +14 -1
  32. package/dist/src/domain/helpers.d.ts +0 -9
  33. package/dist/src/domain/model-config.d.ts +29 -3
  34. package/dist/src/domain/thread-lifecycle.d.ts +2 -10
  35. package/dist/src/node/index.d.ts +2 -0
  36. package/dist/src/orchestration/index.d.ts +1 -0
  37. package/dist/src/orchestration/layer.d.ts +177 -1032
  38. package/dist/src/orchestration/service.d.ts +1 -0
  39. package/dist/src/rpc/error.d.ts +4 -2
  40. package/dist/src/rpc/index.d.ts +5 -0
  41. package/dist/src/rpc/layer.d.ts +1097 -499
  42. package/dist/src/rpc/operation.d.ts +5752 -0
  43. package/dist/src/rpc/ws-group.d.ts +327 -147
  44. package/dist/src/runtime/layer.d.ts +1 -1
  45. package/dist/t3tools.js +2 -2
  46. package/dist/upstream-t3code/packages/contracts/src/environmentHttp.d.ts +10 -33
  47. package/dist/upstream-t3code/packages/contracts/src/ipc.d.ts +0 -6
  48. package/dist/upstream-t3code/packages/contracts/src/orchestration.d.ts +1 -657
  49. package/dist/upstream-t3code/packages/contracts/src/provider.d.ts +0 -14
  50. package/dist/upstream-t3code/packages/contracts/src/providerRuntime.d.ts +1 -175
  51. package/dist/upstream-t3code/packages/contracts/src/rpc.d.ts +0 -492
  52. package/dist/upstream-t3code/packages/contracts/src/server.d.ts +0 -45
  53. package/dist/upstream-t3code/packages/contracts/src/settings.d.ts +0 -21
  54. package/dist/upstream-t3code/packages/contracts/src/terminal.d.ts +3 -6
  55. package/package.json +6 -2
  56. package/src/application/index.ts +28 -2
  57. package/src/application/layer.ts +34 -5
  58. package/src/application/model-selection.ts +68 -2
  59. package/src/application/models.ts +14 -14
  60. package/src/application/project-commands.ts +15 -0
  61. package/src/application/projects.ts +43 -13
  62. package/src/application/service.ts +196 -77
  63. package/src/application/shell-sequence.ts +5 -7
  64. package/src/application/terminals.ts +207 -0
  65. package/src/application/thread-commands.test.ts +43 -0
  66. package/src/application/thread-commands.ts +81 -0
  67. package/src/application/thread-update.ts +72 -0
  68. package/src/application/thread-wait.ts +46 -47
  69. package/src/application/threads.test.ts +166 -0
  70. package/src/application/threads.ts +123 -40
  71. package/src/bin.ts +2 -0
  72. package/src/cli/app.ts +14 -0
  73. package/src/cli/confirm.ts +31 -0
  74. package/src/cli/error.ts +26 -3
  75. package/src/cli/flags.ts +15 -0
  76. package/src/cli/input/layer.ts +20 -0
  77. package/src/cli/input/service.ts +1 -0
  78. package/src/cli/output-format.ts +6 -2
  79. package/src/cli/project-format.ts +7 -0
  80. package/src/cli/project.ts +2 -1
  81. package/src/cli/projects/delete.ts +50 -0
  82. package/src/cli/self-action.ts +34 -0
  83. package/src/cli/terminal/attach.ts +32 -0
  84. package/src/cli/terminal/commands.test.ts +101 -0
  85. package/src/cli/terminal/create.ts +54 -0
  86. package/src/cli/terminal/destroy.ts +60 -0
  87. package/src/cli/terminal/encoding.test.ts +63 -0
  88. package/src/cli/terminal/encoding.ts +23 -0
  89. package/src/cli/terminal/error.ts +14 -0
  90. package/src/cli/terminal/io-node-layer.ts +82 -0
  91. package/src/cli/terminal/io-service.ts +25 -0
  92. package/src/cli/terminal/list.ts +35 -0
  93. package/src/cli/terminal/read.ts +102 -0
  94. package/src/cli/terminal/scope.ts +30 -0
  95. package/src/cli/terminal/shared.ts +250 -0
  96. package/src/cli/terminal/stream.ts +64 -0
  97. package/src/cli/terminal/wait.test.ts +146 -0
  98. package/src/cli/terminal/wait.ts +222 -0
  99. package/src/cli/terminal/write.ts +132 -0
  100. package/src/cli/terminal-format.ts +167 -0
  101. package/src/cli/terminal.ts +26 -0
  102. package/src/cli/thread-format.test.ts +32 -0
  103. package/src/cli/thread-format.ts +8 -1
  104. package/src/cli/thread.ts +9 -13
  105. package/src/cli/threads/archive.ts +11 -18
  106. package/src/cli/threads/delete.ts +61 -0
  107. package/src/cli/threads/interrupt.ts +52 -0
  108. package/src/cli/threads/list.test.ts +69 -0
  109. package/src/cli/threads/list.ts +15 -3
  110. package/src/cli/threads/messages.ts +3 -3
  111. package/src/cli/threads/send.ts +22 -2
  112. package/src/cli/threads/unarchive.ts +44 -0
  113. package/src/cli/threads/update.ts +150 -0
  114. package/src/domain/error.ts +20 -1
  115. package/src/domain/model-config.ts +4 -0
  116. package/src/domain/thread-lifecycle.test.ts +35 -0
  117. package/src/domain/thread-lifecycle.ts +29 -6
  118. package/src/node/index.ts +2 -0
  119. package/src/orchestration/index.ts +1 -0
  120. package/src/orchestration/layer.ts +33 -85
  121. package/src/orchestration/service.ts +4 -0
  122. package/src/rpc/error.ts +10 -0
  123. package/src/rpc/index.ts +5 -0
  124. package/src/rpc/operation.ts +83 -0
  125. package/src/rpc/ws-group.ts +24 -0
  126. package/src/runtime/layer.ts +7 -2
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $d as string$2, $f as runFold, $p as timeoutOrElse, Af as tag, Am as getOrElse, Ap as fail, Bd as waitFormatFlag, Bf as Size, Bm as BaseProto, Bp as matchEffect, Cf as String$1, Cm as Service, Cp as as, Dd as ThreadSessionError, Df as decodeUnknownSync, Dm as flatMap$1, Dp as catchTags, Ed as ProjectLookupError, Ef as decodeUnknownEffect, Em as make$12, Ep as catchFilter, Fd as modelFlags, Ff as Path$1, Fm as match, Fp as forkScoped, Gd as T3Config, Gf as empty, Gm as isUndefined, Gp as result, Hd as canRenderLiveTerminal, Hf as make$9, Hm as isNotNull, Hp as provide$1, Id as projectFlag, If as TypeId$4, Im as none, Ip as gen, J as NodeEnvironmentLive, Jd as choice, Jf as merge, Jp as serviceOption, Kd as T3Auth, Kf as fromIterable, Km as dual, Kp as runFork, Ld as projectPathFlag, Lf as FileDescriptor, Lm as some, Lp as ignore, Md as resolveWorktreePath, Mf as make$8, Mm as isNone, Mp as fn, Nd as T3Application, Nf as fromReadable, Nm as isSome, Np as fnUntraced, Od as CliPath, Of as fromJsonString, Om as fromNullishOr, Op as catch_, Pd as formatFlag, Pf as fromWritable, Pm as map$3, Pp as forEach, Qd as optional$2, Qf as runDrain, Qp as tapError, Rd as threadFlag, Rf as FileSystem, Rm as Prototype, Rp as interrupt, Sf as Literal, Sm as Reference, Sp as andThen, Tf as TaggedErrorClass, Tm as getUnsafe, Tp as callback, Ud as resolveOutputFormat, Uf as callback$1, Um as isNotUndefined, Up as provideContext, Vd as worktreeFlag, Vf as WatchBackend, Vm as hasProperty, Vp as orDie, Wd as Environment, Wf as decodeText, Wm as isNullish, Wp as provideService, X as threadStatus, Xd as integer, Xf as run$1, Xp as suspend, Y as latestAssistantMessage, Yd as choiceWithValue, Yf as mkString, Yp as succeed, Zd as map$2, Zf as runCollect, Zp as sync, _f as ShowHelp, _m as ConsoleRef, _p as systemError, af as getParamMetadata, am as effect, ap as unwrap, bf as isCliError, bm as fail$2, bp as acquireRelease, cf as optional$1, cm as provideMerge, cp as drain, df as getTypeName, dm as MinimumLogLevel, dp as failCauseUnsafe, ef as withAlias, em as tryPromise, ep as runLast, ff as isBoolean, fm as _await, fp as make$11, gf as InvalidValue, gm as succeed$1, gp as badArgument, hf as DuplicateOption, hm as makeUnsafe, hp as BadArgument, if as extractSingleParams, im as fail$1, ip as transduce, jd as resolveThreadId, jf as Crypto, jm as getOrUndefined, jp as flatMap, kd as resolveCommandProjectRef, kf as optionalKey, km as fromUndefinedOr, kp as effectify, lf as string$1, lm as succeed$2, lp as isSink, mf as isTrueValue, mm as isDone, mp as offerUnsafe, nf as withDescription$1, nm as uninterruptible, np as succeed$4, of as isFlagParam, om as mergeAll, op as get, pf as isFalseValue, pm as doneUnsafe, pp as offer, qd as boolean, qf as isStream, qm as pipe, qp as scoped, rf as argumentKind, rm as void_, rp as tap, sf as isParam, sl as ProviderUserInputAnswers, sm as provide, sp as make$10, t as AppLayer, tf as withDefault, tm as try_, tp as splitLines, uf as getChoiceKeys, um as sync$2, up as endUnsafe, vf as UnknownSubcommand, vm as sync$1, vp as nominal, wf as Struct, wm as empty$1, wp as asVoid, xf as ErrorClass, xm as succeed$3, xp as addFinalizer, yf as UnrecognizedOption, ym as map$1, yp as makeRunMain, zd as threadFormatFlag, zf as FileTypeId, zm as withFiber, zp as map } from "./shared.js";
2
+ import { $d as isAgentEnvironment, $f as FileSystem, $m as getUnsafe, $p as flatMap, Ad as ProjectLookupError, Af as InvalidValue, Am as mergeAll, Ap as endUnsafe, Bf as Struct, Bm as makeUnsafe, Bp as nominal, Cf as run$2, Ch as pipeArguments, Cm as timeoutOrElse, Cp as tap, Df as isFalseValue, Dm as void_, Dp as make$9, Ef as isBoolean, Em as uninterruptible, Ep as get, Fd as resolveWorktreePath, Ff as Terminal, Fm as MinimumLogLevel, Fp as shutdown, Gd as projectPathFlag, Gf as optionalKey, Gm as map$1, Gp as as, Hd as formatFlag, Hf as decodeUnknownEffect, Hm as succeed$1, Hp as acquireRelease, Id as T3Application, If as isQuitError, Im as _await, Ip as unbounded, Jd as threadFormatFlag, Jf as fromReadable, Jm as isSuccess, Jp as catchFilter, Kd as selfActionForceFlag, Kf as Crypto, Km as fail$2, Kp as asVoid, Lf as make$11, Lm as doneUnsafe, Lp as BadArgument, Md as resolveCommandProjectRef, Mf as UnknownSubcommand, Mm as provideMerge, Mp as make$10, Nf as UnrecognizedOption, Nm as succeed$2, Np as offer, Of as isTrueValue, Om as fail$1, Op as drain, Pd as resolveThreadId, Pf as isCliError, Pm as sync$2, Pp as offerUnsafe, Qd as canRenderLiveTerminal, Qf as FileDescriptor, Qm as empty$1, Qp as fail, Rf as Literal, Rm as isDone, Rp as badArgument, Sf as confirm, Sh as pipe, Sm as tapError, Sp as succeed$5, Tf as getTypeName, Tm as try_, Tp as unwrap, Ud as modelFlags, Uf as decodeUnknownSync, Um as ConsoleRef, Up as addFinalizer, Vd as forceFlag, Vf as TaggedErrorClass, Vm as succeed$4, Vp as makeRunMain, Wd as projectFlag, Wf as fromJsonString, Wm as sync$1, Wp as andThen, Xd as worktreeFlag, Xf as Path$1, Xm as Reference, Xp as catch_, Yd as waitFormatFlag, Yf as fromWritable, Ym as succeed$3, Yp as catchTags, Zd as yesFlag, Zf as TypeId$4, Zm as Service, Zp as effectify, _f as getParamMetadata, _h as isNotUndefined, _m as scoped, _p as runFold, af as boolean, ah as getOrUndefined, am as ignore, ap as decodeText, bf as optional$1, bh as dual, bm as suspend, bp as runLast, cf as integer, ch as map$3, cm as mapError, cp as fromIterable, ct as NodeEnvironmentLive, df as string$2, dh as some, dm as orDie, dp as map$4, ef as isInteractiveHumanTerminal, eh as make$12, em as fn, ep as FileTypeId, ff as withAlias, fh as Prototype, fm as provide$1, fp as merge, gf as extractSingleParams, gh as isNotNull, gm as runFork, gp as runDrain, hf as argumentKind, hh as hasProperty, hm as result$1, hp as runCollect, i as AppLayer, if as T3Auth, ih as getOrElse, im as gen, ip as callback$1, jd as ThreadSessionError, jf as ShowHelp, jm as provide, jp as failCauseUnsafe, kd as CliPath, kf as DuplicateOption, km as effect, kp as isSink, lf as map$2, lh as match, lm as match$1, lp as fromQueue, lt as latestAssistantMessage, mf as withDescription$1, mh as BaseProto, ml as ProviderUserInputAnswers, mm as provideService, mp as run$1, nf as Environment, nh as fromNullishOr, nm as forEach, np as WatchBackend, of as choice, oh as isNone, om as interrupt, op as empty, pf as withDefault, ph as withFiber, pm as provideContext, pp as mkString, qd as threadFlag, qf as make$7, qm as isResult, qp as callback, rf as T3Config, rh as fromUndefinedOr, rm as forkScoped, rp as make$8, sf as choiceWithValue, sh as isSome, sm as map, sp as filter, tf as resolveOutputFormat, th as flatMap$1, tm as fnUntraced, tp as Size, uf as optional$2, uh as none, um as matchEffect, up as isStream, ut as threadStatus, vf as isFlagParam, vh as isNullish, vm as serviceOption, vp as runForEach, wf as getChoiceKeys, wm as tryPromise, wp as transduce, xf as string$1, xh as identity, xm as sync, xp as splitLines, yf as isParam, yh as isUndefined, ym as succeed, yp as runHead, zf as String$1, zm as make$13, zp as systemError } from "./shared.js";
3
3
  import * as NodeChildProcess from "node:child_process";
4
4
  import * as NodeCrypto from "node:crypto";
5
5
  import * as NFS from "node:fs";
@@ -142,7 +142,7 @@ const makeHandle = (params) => Object.assign(Object.create(HandleProto), params)
142
142
  * @category models
143
143
  * @since 4.0.0
144
144
  */
145
- const make$7 = (spawn) => {
145
+ const make$6 = (spawn) => {
146
146
  const streamString = (command, options) => spawn(command).pipe(map((handle) => decodeText(options?.includeStderr === true ? handle.all : handle.stdout)), unwrap);
147
147
  const streamLines = (command, options) => splitLines(streamString(command, options));
148
148
  return ChildProcessSpawner.of({
@@ -253,7 +253,7 @@ const makeStandardCommand = (command, args, options) => Object.assign(Object.cre
253
253
  * @category constructors
254
254
  * @since 4.0.0
255
255
  */
256
- const make$6 = function make(...args) {
256
+ const make$5 = function make(...args) {
257
257
  if (isTemplateString(args[0])) {
258
258
  const [templates, ...expressions] = args;
259
259
  const tokens = parseTemplates(templates, expressions);
@@ -734,7 +734,7 @@ const layer$11 = /*#__PURE__*/ effect(ChildProcessSpawner, /* @__PURE__ */ gen(f
734
734
  const stdinConfig = resolveStdinOption(command.options);
735
735
  const sourceStream = unwrap(succeed(getSourceStream(handles[handles.length - 1], options.from)));
736
736
  const toOption = options.to ?? "stdin";
737
- if (toOption === "stdin") handles.push(yield* spawnCommand(make$6(command.command, command.args, {
737
+ if (toOption === "stdin") handles.push(yield* spawnCommand(make$5(command.command, command.args, {
738
738
  ...command.options,
739
739
  stdin: {
740
740
  ...stdinConfig,
@@ -746,7 +746,7 @@ const layer$11 = /*#__PURE__*/ effect(ChildProcessSpawner, /* @__PURE__ */ gen(f
746
746
  if (isNotUndefined(fd)) {
747
747
  const fdName$1 = fdName(fd);
748
748
  const existingFds = command.options.additionalFds ?? {};
749
- handles.push(yield* spawnCommand(make$6(command.command, command.args, {
749
+ handles.push(yield* spawnCommand(make$5(command.command, command.args, {
750
750
  ...command.options,
751
751
  additionalFds: {
752
752
  ...existingFds,
@@ -756,7 +756,7 @@ const layer$11 = /*#__PURE__*/ effect(ChildProcessSpawner, /* @__PURE__ */ gen(f
756
756
  }
757
757
  }
758
758
  })));
759
- } else handles.push(yield* spawnCommand(make$6(command.command, command.args, {
759
+ } else handles.push(yield* spawnCommand(make$5(command.command, command.args, {
760
760
  ...command.options,
761
761
  stdin: {
762
762
  ...stdinConfig,
@@ -787,7 +787,7 @@ const layer$11 = /*#__PURE__*/ effect(ChildProcessSpawner, /* @__PURE__ */ gen(f
787
787
  }
788
788
  }
789
789
  });
790
- return make$7(spawnCommand);
790
+ return make$6(spawnCommand);
791
791
  }));
792
792
  /**
793
793
  * Flattens a `Command` into an array of `StandardCommand`s along with pipe
@@ -885,7 +885,7 @@ const digest = (algorithm, data) => try_({
885
885
  * @category layers
886
886
  * @since 1.0.0
887
887
  */
888
- const layer$9 = /* @__PURE__ */ succeed$2(Crypto, /* @__PURE__ */ make$8({
888
+ const layer$9 = /* @__PURE__ */ succeed$2(Crypto, /* @__PURE__ */ make$7({
889
889
  randomBytes: NodeCrypto.randomBytes,
890
890
  digest
891
891
  }));
@@ -1169,7 +1169,7 @@ const symlink = /*#__PURE__*/ (() => {
1169
1169
  const nodeSymlink = /*#__PURE__*/ effectify(NFS.symlink, /*#__PURE__*/ handleErrnoException("FileSystem", "symlink"), /*#__PURE__*/ handleBadArgument("symlink"));
1170
1170
  return (target, path) => nodeSymlink(target, path);
1171
1171
  })();
1172
- const truncate = /*#__PURE__*/ (() => {
1172
+ const truncate$1 = /*#__PURE__*/ (() => {
1173
1173
  const nodeTruncate = /*#__PURE__*/ effectify(NFS.truncate, /*#__PURE__*/ handleErrnoException("FileSystem", "truncate"), /*#__PURE__*/ handleBadArgument("truncate"));
1174
1174
  return (path, length) => nodeTruncate(path, length !== void 0 ? Number(length) : void 0);
1175
1175
  })();
@@ -1230,7 +1230,7 @@ const writeFile = (path, data, options) => callback((resume, signal) => {
1230
1230
  resume(fail(handleBadArgument("writeFile")(err)));
1231
1231
  }
1232
1232
  });
1233
- const makeFileSystem = /*#__PURE__*/ map(/*#__PURE__*/ serviceOption(WatchBackend), (backend) => make$9({
1233
+ const makeFileSystem = /*#__PURE__*/ map(/*#__PURE__*/ serviceOption(WatchBackend), (backend) => make$8({
1234
1234
  access,
1235
1235
  chmod,
1236
1236
  chown,
@@ -1251,7 +1251,7 @@ const makeFileSystem = /*#__PURE__*/ map(/*#__PURE__*/ serviceOption(WatchBacken
1251
1251
  rename,
1252
1252
  stat,
1253
1253
  symlink,
1254
- truncate,
1254
+ truncate: truncate$1,
1255
1255
  utimes,
1256
1256
  watch(path) {
1257
1257
  return watch(backend, path);
@@ -1466,7 +1466,7 @@ const Stdio = /*#__PURE__*/ Service(TypeId$2);
1466
1466
  * @category constructors
1467
1467
  * @since 4.0.0
1468
1468
  */
1469
- const make$3 = (options) => ({
1469
+ const make$2 = (options) => ({
1470
1470
  [TypeId$2]: TypeId$2,
1471
1471
  ...options
1472
1472
  });
@@ -1506,7 +1506,7 @@ const make$3 = (options) => ({
1506
1506
  * @category layers
1507
1507
  * @since 4.0.0
1508
1508
  */
1509
- const layer$3 = /* @__PURE__ */ succeed$2(Stdio, /*#__PURE__*/ make$3({
1509
+ const layer$3 = /* @__PURE__ */ succeed$2(Stdio, /*#__PURE__*/ make$2({
1510
1510
  args: /*#__PURE__*/ sync(() => process.argv.slice(2)),
1511
1511
  stdout: (options) => fromWritable({
1512
1512
  evaluate: () => process.stdout,
@@ -1539,64 +1539,6 @@ const layer$3 = /* @__PURE__ */ succeed$2(Stdio, /*#__PURE__*/ make$3({
1539
1539
  closeOnDone: false
1540
1540
  })
1541
1541
  }));
1542
- //#endregion
1543
- //#region node_modules/.pnpm/effect@4.0.0-beta.78/node_modules/effect/dist/Terminal.js
1544
- const TypeId$1 = "~effect/platform/Terminal";
1545
- const QuitErrorTypeId = "effect/platform/Terminal/QuitError";
1546
- ErrorClass("QuitError")({ _tag: /*#__PURE__*/ tag("QuitError") });
1547
- /**
1548
- * Returns `true` if the provided value is a `Terminal.QuitError`.
1549
- *
1550
- * **When to use**
1551
- *
1552
- * Use to narrow unknown failures to `QuitError` when handling terminal input
1553
- * cancellation.
1554
- *
1555
- * **Details**
1556
- *
1557
- * Returns `true` when the value carries the `QuitError` runtime marker and
1558
- * narrows it to `QuitError`.
1559
- *
1560
- * @see {@link QuitError} for the error value produced when terminal input is quit
1561
- *
1562
- * @category guards
1563
- * @since 4.0.0
1564
- */
1565
- const isQuitError = (u) => hasProperty(u, QuitErrorTypeId);
1566
- /**
1567
- * Service tag for command-line input and output services.
1568
- *
1569
- * **When to use**
1570
- *
1571
- * Use to access or provide platform terminal capabilities such as reading
1572
- * input, writing output, and inspecting terminal dimensions.
1573
- *
1574
- * @category services
1575
- * @since 4.0.0
1576
- */
1577
- const Terminal = /*#__PURE__*/ Service("effect/platform/Terminal");
1578
- /**
1579
- * Creates a `Terminal` service implementation.
1580
- *
1581
- * **When to use**
1582
- *
1583
- * Use to construct a custom `Terminal` service implementation from concrete
1584
- * terminal capabilities when writing a platform adapter, test implementation,
1585
- * or custom runtime service.
1586
- *
1587
- * **Details**
1588
- *
1589
- * The implementation object supplies `columns`, `rows`, `readInput`,
1590
- * `readLine`, and `display`; `make` attaches the `Terminal` service marker so
1591
- * the result can be provided through the `Terminal` context service.
1592
- *
1593
- * @category constructors
1594
- * @since 4.0.0
1595
- */
1596
- const make$2 = (impl) => Terminal.of({
1597
- ...impl,
1598
- [TypeId$1]: TypeId$1
1599
- });
1600
1542
  /**
1601
1543
  * Provides the default process-backed `Terminal` service, ending key input on
1602
1544
  * Ctrl+C or Ctrl+D.
@@ -1607,7 +1549,7 @@ const make$2 = (impl) => Terminal.of({
1607
1549
  const layer$2 = /*#__PURE__*/ effect(Terminal, /*#__PURE__*/ (/* @__PURE__ */ fnUntraced(function* (shouldQuit = defaultShouldQuit) {
1608
1550
  const stdin = process.stdin;
1609
1551
  const stdout = process.stdout;
1610
- const rlRef = yield* make$10({ acquire: acquireRelease(sync(() => {
1552
+ const rlRef = yield* make$9({ acquire: acquireRelease(sync(() => {
1611
1553
  const rl = readline.createInterface({
1612
1554
  input: stdin,
1613
1555
  escapeCodeTimeout: 50
@@ -1623,7 +1565,7 @@ const layer$2 = /*#__PURE__*/ effect(Terminal, /*#__PURE__*/ (/* @__PURE__ */ fn
1623
1565
  const rows = sync(() => stdout.rows ?? 0);
1624
1566
  const readInput = gen(function* () {
1625
1567
  yield* get(rlRef);
1626
- const queue = yield* make$11();
1568
+ const queue = yield* make$10();
1627
1569
  const handleKeypress = (s, k) => {
1628
1570
  const userInput = {
1629
1571
  input: fromUndefinedOr(s),
@@ -1654,7 +1596,7 @@ const layer$2 = /*#__PURE__*/ effect(Terminal, /*#__PURE__*/ (/* @__PURE__ */ fn
1654
1596
  cause: err
1655
1597
  }))));
1656
1598
  }));
1657
- return make$2({
1599
+ return make$11({
1658
1600
  columns,
1659
1601
  rows,
1660
1602
  readInput,
@@ -1866,7 +1808,7 @@ const visualLength = (text) => stripAnsi(text).length;
1866
1808
  * Helper function to pad strings to a specified width.
1867
1809
  * @internal
1868
1810
  */
1869
- const pad = (s, width) => {
1811
+ const pad$1 = (s, width) => {
1870
1812
  const actualLength = visualLength(s);
1871
1813
  const padding = Math.max(0, width - actualLength);
1872
1814
  return s + " ".repeat(padding);
@@ -1878,7 +1820,7 @@ const pad = (s, width) => {
1878
1820
  const renderTable = (rows, widthCap) => {
1879
1821
  const maxColumn = Math.max(...rows.map((r) => visualLength(r.left))) + 4;
1880
1822
  const col = widthCap === void 0 ? maxColumn : Math.min(maxColumn, widthCap);
1881
- return rows.map(({ left, right }) => ` ${pad(left, col)}${right}`).join("\n");
1823
+ return rows.map(({ left, right }) => ` ${pad$1(left, col)}${right}`).join("\n");
1882
1824
  };
1883
1825
  const formatSubcommandName = (name, alias) => alias ? `${name}, ${alias}` : name;
1884
1826
  /**
@@ -2639,7 +2581,7 @@ const reconstructTree = (tree, results) => {
2639
2581
  * Internal implementation details for CLI commands.
2640
2582
  * Public API is in ../Command.ts
2641
2583
  */
2642
- const TypeId = "~effect/cli/Command";
2584
+ const TypeId$1 = "~effect/cli/Command";
2643
2585
  /**
2644
2586
  * Casts a Command to its internal implementation.
2645
2587
  * For use by internal modules that need access to config, parse, handle, etc.
@@ -2721,7 +2663,7 @@ const makeCommand = (options) => {
2721
2663
  };
2722
2664
  };
2723
2665
  return Object.assign(Object.create(Proto), {
2724
- [TypeId]: TypeId,
2666
+ [TypeId$1]: TypeId$1,
2725
2667
  name: options.name,
2726
2668
  examples: options.examples ?? [],
2727
2669
  annotations,
@@ -3796,7 +3738,7 @@ const scanCommandLevel = (tokens, context) => {
3796
3738
  * @category guards
3797
3739
  * @since 4.0.0
3798
3740
  */
3799
- const isCommand = (u) => hasProperty(u, TypeId);
3741
+ const isCommand = (u) => hasProperty(u, TypeId$1);
3800
3742
  /**
3801
3743
  * Creates a `Command` from a name, an optional configuration, and an optional
3802
3744
  * handler.
@@ -4163,7 +4105,7 @@ const runWith = (command, config) => {
4163
4105
  commandPath,
4164
4106
  errors: parsedArgs.errors
4165
4107
  });
4166
- const parseResult = yield* result(commandImpl.parse(parsedArgs));
4108
+ const parseResult = yield* result$1(commandImpl.parse(parsedArgs));
4167
4109
  if (parseResult._tag === "Failure") return yield* new ShowHelp({
4168
4110
  commandPath,
4169
4111
  errors: [parseResult.failure]
@@ -4291,78 +4233,6 @@ const statusCommand = make("status", { format: formatFlag }, ({ format }) => gen
4291
4233
  }));
4292
4234
  })).pipe(withDescription("show auth status"));
4293
4235
  //#endregion
4294
- //#region src/cli/model-format.ts
4295
- function formatModelsHuman(providers) {
4296
- if (providers.length === 0) return "no models found\n";
4297
- return providers.map((provider) => {
4298
- const models = provider.models;
4299
- const header = `${provider.displayName ?? provider.instanceId} (${provider.instanceId}) - ${provider.status}`;
4300
- if (models.length === 0) return `${header}\n no models`;
4301
- return [header, ...models.map((model) => ` ${model.slug} - ${model.name}`)].join("\n");
4302
- }).join("\n\n");
4303
- }
4304
- //#endregion
4305
- //#region src/cli/model.ts
4306
- function createModelCommand() {
4307
- return make("model").pipe(withDescription("model commands"), withSubcommands([listCommand$1]));
4308
- }
4309
- const listCommand$1 = make("list", {
4310
- all: boolean("all"),
4311
- provider: string$2("provider").pipe(optional$2),
4312
- format: formatFlag
4313
- }, ({ all, provider, format }) => gen(function* () {
4314
- const application = yield* T3Application;
4315
- const environment = yield* Environment;
4316
- const output = yield* T3Output;
4317
- const providerValue = getOrUndefined(provider);
4318
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
4319
- const providers = yield* application.listModels({
4320
- all,
4321
- ...providerValue !== void 0 && providerValue.length > 0 ? { provider: providerValue } : {}
4322
- });
4323
- if (resolvedFormat === "json") yield* output.printJson(providers);
4324
- else yield* output.writeStdout(formatModelsHuman(providers));
4325
- })).pipe(withDescription("list provider models"));
4326
- //#endregion
4327
- //#region src/cli/project-format.ts
4328
- function formatProjectsHuman(projects) {
4329
- return projects.map((project) => `- ${project.title}\n id: ${project.id}\n path: ${project.workspaceRoot}\n`).join("");
4330
- }
4331
- function formatProjectAddedHuman(project) {
4332
- return `project added: ${project.title}\nid: ${project.id}\npath: ${project.workspaceRoot}`;
4333
- }
4334
- //#endregion
4335
- //#region src/cli/project.ts
4336
- function createProjectCommand() {
4337
- return make("project").pipe(withDescription("project commands"), withSubcommands([listCommand, addCommand]));
4338
- }
4339
- const listCommand = make("list", { format: formatFlag }, ({ format }) => gen(function* () {
4340
- const application = yield* T3Application;
4341
- const environment = yield* Environment;
4342
- const output = yield* T3Output;
4343
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
4344
- const snapshot = yield* application.loadShell();
4345
- if (resolvedFormat === "json") yield* output.printJson(snapshot.projects);
4346
- else yield* output.writeStdout(formatProjectsHuman(snapshot.projects));
4347
- })).pipe(withDescription("list projects"));
4348
- const addCommand = make("add", {
4349
- path: projectPathFlag,
4350
- title: string$2("title").pipe(optional$2),
4351
- format: formatFlag
4352
- }, ({ path, title, format }) => gen(function* () {
4353
- const application = yield* T3Application;
4354
- const environment = yield* Environment;
4355
- const output = yield* T3Output;
4356
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
4357
- const titleValue = getOrUndefined(title);
4358
- const result = yield* application.addProject({
4359
- path,
4360
- ...titleValue !== void 0 && titleValue.length > 0 ? { title: titleValue } : {}
4361
- });
4362
- if (resolvedFormat === "json") yield* output.printJson(result);
4363
- else yield* output.printInfo(formatProjectAddedHuman(result.project));
4364
- })).pipe(withDescription("add project"));
4365
- //#endregion
4366
4236
  //#region src/cli/error.ts
4367
4237
  var MessageInputError = class extends TaggedErrorClass()("MessageInputError", { message: String$1 }) {};
4368
4238
  var InvalidLimitError = class extends TaggedErrorClass()("InvalidLimitError", {
@@ -4370,149 +4240,1262 @@ var InvalidLimitError = class extends TaggedErrorClass()("InvalidLimitError", {
4370
4240
  value: String$1
4371
4241
  }) {};
4372
4242
  var MissingThreadError = class extends TaggedErrorClass()("MissingThreadError", { message: String$1 }) {};
4373
- var SelfArchiveError = class extends TaggedErrorClass()("SelfArchiveError", {
4243
+ var SelfActionError = class extends TaggedErrorClass()("SelfActionError", {
4374
4244
  message: String$1,
4375
4245
  threadId: String$1
4376
4246
  }) {};
4247
+ var DestructiveConfirmationRequiredError = class extends TaggedErrorClass()("DestructiveConfirmationRequiredError", { message: String$1 }) {};
4248
+ var InvalidFlagCombinationError = class extends TaggedErrorClass()("InvalidFlagCombinationError", { message: String$1 }) {};
4377
4249
  var MissingRequestError = class extends TaggedErrorClass()("MissingRequestError", { message: String$1 }) {};
4250
+ var MissingUpdateFieldsError = class extends TaggedErrorClass()("MissingUpdateFieldsError", { message: String$1 }) {};
4251
+ var ConflictingUpdateFlagsError = class extends TaggedErrorClass()("ConflictingUpdateFlagsError", { message: String$1 }) {};
4378
4252
  //#endregion
4379
- //#region src/cli/threads/approve.ts
4380
- const approvalDecisionFlag = choice("decision", [
4381
- "accept",
4382
- "decline",
4383
- "cancel"
4384
- ]).pipe(withDescription$1("Approval decision"));
4385
- const approveThreadCommand = make("approve", {
4386
- thread: threadFlag,
4387
- request: string$2("request").pipe(withDescription$1("Pending approval request id"), optional$2),
4388
- decision: approvalDecisionFlag,
4389
- format: formatFlag
4390
- }, ({ thread, request, decision, format }) => gen(function* () {
4391
- const application = yield* T3Application;
4392
- const environment = yield* Environment;
4393
- const output = yield* T3Output;
4394
- const threadId = resolveThreadId({
4395
- value: getOrUndefined(thread),
4396
- env: environment.env
4397
- });
4398
- if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
4399
- const requestId = getOrUndefined(request);
4400
- if (requestId === void 0 || requestId.length === 0) return yield* fail(new MissingRequestError({ message: "request id is required: pass --request" }));
4401
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
4402
- const result = yield* application.approveThread({
4403
- threadId,
4404
- requestId,
4405
- decision
4406
- });
4407
- if (resolvedFormat === "json") return yield* output.printJson(result);
4408
- return yield* output.printInfo(`approval submitted: ${result.requestId}\nsequence: ${result.dispatch.sequence}`);
4409
- })).pipe(withDescription("respond to a pending approval request"));
4410
- //#endregion
4411
- //#region src/cli/threads/archive.ts
4412
- const archiveThreadCommand = make("archive", {
4413
- thread: threadFlag,
4414
- force: boolean("force").pipe(withAlias("f")),
4415
- format: formatFlag
4416
- }, ({ thread, force, format }) => gen(function* () {
4417
- const application = yield* T3Application;
4418
- const environment = yield* Environment;
4419
- const output = yield* T3Output;
4420
- const threadId = resolveThreadId({
4421
- value: getOrUndefined(thread),
4422
- env: environment.env
4253
+ //#region src/cli/terminal/scope.ts
4254
+ function resolveCommandThreadId(input) {
4255
+ return resolveThreadId({
4256
+ value: getOrUndefined(input.thread),
4257
+ env: input.env
4423
4258
  });
4259
+ }
4260
+ const requireCommandThreadId = fn("requireCommandThreadId")(function* (input) {
4261
+ const threadId = resolveCommandThreadId(input);
4424
4262
  if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
4425
- const envThreadId = environment.env.T3CODE_THREAD_ID;
4426
- if (envThreadId !== void 0 && envThreadId.length > 0 && threadId === envThreadId && !force) return yield* fail(new SelfArchiveError({
4427
- threadId,
4428
- message: `cannot archive thread ${threadId}: matches T3CODE_THREAD_ID (are you trying to archive yourself?). Use --force to override.`
4429
- }));
4430
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
4431
- const dispatch = yield* application.archiveThread(threadId);
4432
- if (resolvedFormat === "json") return yield* output.printJson(dispatch);
4433
- return yield* output.printInfo(`thread archived: ${threadId}\nsequence: ${dispatch.sequence}`);
4434
- })).pipe(withDescription("archive thread"));
4435
- //#endregion
4436
- //#region src/cli/threads/callback.ts
4437
- const callbackThreadCommand = make("callback", {
4438
- from: string$2("from").pipe(withDescription$1("Thread ID to watch for completion")),
4439
- thread: threadFlag,
4440
- prompt: string$2("prompt").pipe(withDescription$1("Message to send to target thread")),
4441
- background: boolean("background").pipe(withDescription$1("Fork and detach as background process"), optional$2)
4442
- }, ({ from, thread, prompt, background }) => gen(function* () {
4443
- const application = yield* T3Application;
4444
- const environment = yield* Environment;
4445
- const output = yield* T3Output;
4446
- const cliPath = yield* CliPath;
4447
- const spawner = yield* ChildProcessSpawner;
4448
- const fromThreadId = from;
4449
- const targetThreadId = resolveThreadId({
4450
- value: getOrUndefined(thread),
4451
- env: environment.env
4452
- });
4453
- if (targetThreadId === void 0) return yield* fail(new MissingThreadError({ message: "target thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
4454
- if (getOrElse(background, () => false)) {
4455
- const args = [
4456
- cliPath.path,
4457
- "thread",
4458
- "callback",
4459
- "--from",
4460
- fromThreadId,
4461
- "--thread",
4462
- targetThreadId,
4463
- "--prompt",
4464
- prompt
4465
- ];
4466
- const proc = make$6(process.execPath, args, {
4467
- detached: true,
4468
- stdin: "ignore",
4469
- stdout: "ignore",
4470
- stderr: "ignore"
4471
- });
4472
- const handle = yield* spawner.spawn(proc);
4473
- yield* handle.unref.pipe(ignore);
4474
- yield* output.printInfo(`background callback scheduled: ${fromThreadId} -> ${targetThreadId} (pid: ${handle.pid})`);
4475
- return;
4263
+ return threadId;
4264
+ });
4265
+ const ValueMatcherProto = {
4266
+ ["~effect/match/Match/Matcher"]: {
4267
+ _input: identity,
4268
+ _filters: identity,
4269
+ _result: identity,
4270
+ _return: identity
4271
+ },
4272
+ _tag: "ValueMatcher",
4273
+ add(_case) {
4274
+ if (isSuccess(this.value)) return this;
4275
+ if (_case._tag === "When" && _case.guard(this.provided) === true) return makeValueMatcher(this.provided, succeed$3(_case.evaluate(this.provided)));
4276
+ else if (_case._tag === "Not" && _case.guard(this.provided) === false) return makeValueMatcher(this.provided, succeed$3(_case.evaluate(this.provided)));
4277
+ return this;
4278
+ },
4279
+ pipe() {
4280
+ return pipeArguments(this, arguments);
4476
4281
  }
4477
- yield* output.printInfo(`watching thread ${fromThreadId} for completion...`);
4478
- const result = yield* application.callbackThread({
4479
- fromThreadId,
4480
- targetThreadId,
4481
- prompt
4482
- });
4483
- yield* output.printInfo(`callback sent to ${result.targetThreadId} (dispatch: ${result.dispatch.sequence})`);
4484
- })).pipe(withDescription("watch a thread and send a message when it completes"));
4485
- //#endregion
4486
- //#region src/cli/require.ts
4487
- const requireCommandProjectRef = fn("requireCommandProjectRef")(function* (input) {
4488
- const resolved = yield* (yield* T3Config).resolve();
4489
- const ref = resolveCommandProjectRef({
4490
- value: getOrUndefined(input.project),
4491
- env: input.env,
4492
- cwd: input.cwd,
4493
- isLocal: resolved.local
4494
- });
4495
- if (ref === void 0) return yield* fail(new ProjectLookupError({
4496
- message: "project is required: pass --project, set T3CODE_PROJECT_ROOT / T3CODE_PROJECT_ID, or use local auth",
4497
- ref: input.cwd
4498
- }));
4499
- return ref;
4282
+ };
4283
+ function makeValueMatcher(provided, value) {
4284
+ const matcher = Object.create(ValueMatcherProto);
4285
+ matcher.provided = provided;
4286
+ matcher.value = value;
4287
+ return matcher;
4288
+ }
4289
+ const makeWhen = (guard, evaluate) => ({
4290
+ _tag: "When",
4291
+ guard,
4292
+ evaluate
4500
4293
  });
4294
+ const makePredicate = (pattern) => {
4295
+ if (typeof pattern === "function") return pattern;
4296
+ else if (Array.isArray(pattern)) {
4297
+ const predicates = pattern.map(makePredicate);
4298
+ const len = predicates.length;
4299
+ return (u) => {
4300
+ if (!Array.isArray(u)) return false;
4301
+ for (let i = 0; i < len; i++) if (predicates[i](u[i]) === false) return false;
4302
+ return true;
4303
+ };
4304
+ } else if (pattern !== null && typeof pattern === "object") {
4305
+ const keysAndPredicates = Object.entries(pattern).map(([k, p]) => [k, makePredicate(p)]);
4306
+ const len = keysAndPredicates.length;
4307
+ return (u) => {
4308
+ if (typeof u !== "object" || u === null) return false;
4309
+ for (let i = 0; i < len; i++) {
4310
+ const [key, predicate] = keysAndPredicates[i];
4311
+ if (!(key in u) || predicate(u[key]) === false) return false;
4312
+ }
4313
+ return true;
4314
+ };
4315
+ }
4316
+ return (u) => u === pattern;
4317
+ };
4318
+ /** @internal */
4319
+ const value$1 = (i) => makeValueMatcher(i, fail$2(i));
4320
+ /** @internal */
4321
+ const when$1 = (pattern, f) => (self) => self.add(makeWhen(makePredicate(pattern), f));
4322
+ /** @internal */
4323
+ const discriminator = (field) => (...pattern) => {
4324
+ const f = pattern[pattern.length - 1];
4325
+ const values = pattern.slice(0, -1);
4326
+ const pred = values.length === 1 ? (_) => _ != null && _[field] === values[0] : (_) => _ != null && values.includes(_[field]);
4327
+ return (self) => self.add(makeWhen(pred, f));
4328
+ };
4329
+ /** @internal */
4330
+ const tag$1 = /*#__PURE__*/ discriminator("_tag");
4331
+ /** @internal */
4332
+ const orElse$1 = (f) => (self) => {
4333
+ const toResult = result(self);
4334
+ if (isResult(toResult)) return toResult._tag === "Success" ? toResult.success : f(toResult.failure);
4335
+ return (input) => {
4336
+ const a = toResult(input);
4337
+ return isSuccess(a) ? a.success : f(a.failure);
4338
+ };
4339
+ };
4340
+ /** @internal */
4341
+ const result = (self) => {
4342
+ if (self._tag === "ValueMatcher") return self.value;
4343
+ const len = self.cases.length;
4344
+ if (len === 1) {
4345
+ const _case = self.cases[0];
4346
+ return (input) => {
4347
+ if (_case._tag === "When" && _case.guard(input) === true) return succeed$3(_case.evaluate(input));
4348
+ else if (_case._tag === "Not" && _case.guard(input) === false) return succeed$3(_case.evaluate(input));
4349
+ return fail$2(input);
4350
+ };
4351
+ }
4352
+ return (input) => {
4353
+ for (let i = 0; i < len; i++) {
4354
+ const _case = self.cases[i];
4355
+ if (_case._tag === "When" && _case.guard(input) === true) return succeed$3(_case.evaluate(input));
4356
+ else if (_case._tag === "Not" && _case.guard(input) === false) return succeed$3(_case.evaluate(input));
4357
+ }
4358
+ return fail$2(input);
4359
+ };
4360
+ };
4501
4361
  //#endregion
4502
- //#region src/cli/thread-format.ts
4503
- function formatThreadShowJson(thread) {
4504
- return {
4505
- id: thread.id,
4506
- projectId: thread.projectId,
4507
- title: thread.title,
4508
- status: thread.status,
4509
- session: thread.session,
4510
- latestTurn: thread.latestTurn,
4511
- modelSelection: thread.modelSelection,
4512
- runtimeMode: thread.runtimeMode,
4513
- interactionMode: thread.interactionMode,
4514
- branch: thread.branch,
4515
- worktreePath: thread.worktreePath,
4362
+ //#region node_modules/.pnpm/effect@4.0.0-beta.78/node_modules/effect/dist/Match.js
4363
+ /**
4364
+ * Pattern matching for TypeScript values, predicates, and tagged unions.
4365
+ *
4366
+ * `Match` turns branching logic into a matcher that is built from ordered
4367
+ * cases and finished with an explicit finalizer. Use `Match.type` to define a
4368
+ * reusable matcher for a type, or `Match.value` to classify one value
4369
+ * immediately. Cases can match literal values, predicates, object patterns,
4370
+ * discriminators, tags, or negated patterns.
4371
+ *
4372
+ * **Mental model**
4373
+ *
4374
+ * A matcher checks cases in the order they are added and evaluates the handler
4375
+ * for the first match. Type matchers produce a function that can be reused with
4376
+ * different inputs, while value matchers already contain the input value. As
4377
+ * cases are added, the type system tracks which inputs remain unmatched, so
4378
+ * `Match.exhaustive` is only available when every remaining case has been
4379
+ * handled.
4380
+ *
4381
+ * **Common tasks**
4382
+ *
4383
+ * - Use `Match.type<Union>()` when a branch table should be reusable and
4384
+ * exhaustiveness-checked.
4385
+ * - Use `Match.value(value)` when a single value should be matched immediately.
4386
+ * - Use `Match.tag`, `Match.tags`, or `Match.discriminator` for discriminated
4387
+ * unions and domain objects with tag fields.
4388
+ * - Use `Match.orElse`, `Match.option`, or `Match.result` when unmatched input
4389
+ * should be handled explicitly instead of requiring full exhaustiveness.
4390
+ *
4391
+ * **Example** (Matching a tagged union)
4392
+ *
4393
+ * ```ts
4394
+ * import { Match } from "effect"
4395
+ *
4396
+ * type Event =
4397
+ * | { readonly _tag: "UserCreated"; readonly id: string }
4398
+ * | { readonly _tag: "UserDeleted"; readonly id: string }
4399
+ *
4400
+ * const describe = Match.type<Event>().pipe(
4401
+ * Match.tag("UserCreated", (event) => `created ${event.id}`),
4402
+ * Match.tag("UserDeleted", (event) => `deleted ${event.id}`),
4403
+ * Match.exhaustive
4404
+ * )
4405
+ * ```
4406
+ *
4407
+ * @since 4.0.0
4408
+ */
4409
+ /**
4410
+ * Creates a matcher from a specific value.
4411
+ *
4412
+ * **When to use**
4413
+ *
4414
+ * Use to match one concrete input immediately.
4415
+ *
4416
+ * **Details**
4417
+ *
4418
+ * This function allows you to define a `Matcher` directly from a given value,
4419
+ * rather than from a type. This is useful when working with known values,
4420
+ * enabling structured pattern matching on objects, primitives, or any data
4421
+ * structure.
4422
+ *
4423
+ * Once the matcher is created, you can use pattern-matching functions like
4424
+ * {@link when} to define how different cases should be handled.
4425
+ *
4426
+ * **Example** (Matching an Object by Property)
4427
+ *
4428
+ * ```ts
4429
+ * import { Match } from "effect"
4430
+ *
4431
+ * const input = { name: "John", age: 30 }
4432
+ *
4433
+ * // Create a matcher for the specific object
4434
+ * const result = Match.value(input).pipe(
4435
+ * // Match when the 'name' property is "John"
4436
+ * Match.when(
4437
+ * { name: "John" },
4438
+ * (user) => `${user.name} is ${user.age} years old`
4439
+ * ),
4440
+ * // Provide a fallback if no match is found
4441
+ * Match.orElse(() => "Oh, not John")
4442
+ * )
4443
+ *
4444
+ * console.log(result)
4445
+ * // Output: "John is 30 years old"
4446
+ * ```
4447
+ *
4448
+ * @see {@link type} for creating a matcher from a specific type.
4449
+ *
4450
+ * @category constructors
4451
+ * @since 4.0.0
4452
+ */
4453
+ const value = value$1;
4454
+ /**
4455
+ * Defines a condition for matching values.
4456
+ *
4457
+ * **When to use**
4458
+ *
4459
+ * Use to add one positive pattern case to a `Match.type` or `Match.value`
4460
+ * pipeline when a direct value, predicate, or structured object pattern should
4461
+ * run a handler for matching input.
4462
+ *
4463
+ * **Details**
4464
+ *
4465
+ * Supports both direct value comparisons and predicate functions. If the
4466
+ * pattern matches, the associated function is executed and the matched input is
4467
+ * removed from the remaining cases tracked by the matcher.
4468
+ *
4469
+ * **Example** (Matching with Values and Predicates)
4470
+ *
4471
+ * ```ts
4472
+ * import { Match } from "effect"
4473
+ *
4474
+ * // Create a matcher for objects with an "age" property
4475
+ * const match = Match.type<{ age: number }>().pipe(
4476
+ * // Match when age is greater than 18
4477
+ * Match.when(
4478
+ * { age: (age: number) => age > 18 },
4479
+ * (user: { age: number }) => `Age: ${user.age}`
4480
+ * ),
4481
+ * // Match when age is exactly 18
4482
+ * Match.when({ age: 18 }, () => "You can vote"),
4483
+ * // Fallback case for all other ages
4484
+ * Match.orElse((user: { age: number }) => `${user.age} is too young`)
4485
+ * )
4486
+ *
4487
+ * console.log(match({ age: 20 }))
4488
+ * // Output: "Age: 20"
4489
+ *
4490
+ * console.log(match({ age: 18 }))
4491
+ * // Output: "You can vote"
4492
+ *
4493
+ * console.log(match({ age: 4 }))
4494
+ * // Output: "4 is too young"
4495
+ * ```
4496
+ *
4497
+ * @see {@link whenOr} for handling any one of several patterns with the same handler
4498
+ * @see {@link whenAnd} for requiring all provided patterns to match before running a handler
4499
+ * @see {@link not} for handling inputs that do not match a pattern
4500
+ * @see {@link orElse} for providing a fallback when no pattern case matches
4501
+ *
4502
+ * @category Defining patterns
4503
+ * @since 4.0.0
4504
+ */
4505
+ const when = when$1;
4506
+ /**
4507
+ * Matches discriminated union members by their `_tag` field.
4508
+ *
4509
+ * **When to use**
4510
+ *
4511
+ * Use to handle one or more `_tag` cases with the same matcher branch.
4512
+ *
4513
+ * **Details**
4514
+ *
4515
+ * This helper follows the Effect convention that discriminated unions use
4516
+ * `"_tag"` as their discriminator field. Use {@link discriminator} for a
4517
+ * different discriminator field.
4518
+ *
4519
+ * **Example** (Matching a Discriminated Union by Tag)
4520
+ *
4521
+ * ```ts
4522
+ * import { Match } from "effect"
4523
+ *
4524
+ * type Event =
4525
+ * | { readonly _tag: "fetch" }
4526
+ * | { readonly _tag: "success"; readonly data: string }
4527
+ * | { readonly _tag: "error"; readonly error: Error }
4528
+ * | { readonly _tag: "cancel" }
4529
+ *
4530
+ * const match = Match.type<Event>().pipe(
4531
+ * // Match either "fetch" or "success"
4532
+ * Match.tag("fetch", "success", () => `Ok!`),
4533
+ * // Match "error" and extract the error message
4534
+ * Match.tag("error", (event) => `Error: ${event.error.message}`),
4535
+ * // Match "cancel"
4536
+ * Match.tag("cancel", () => "Cancelled"),
4537
+ * Match.exhaustive
4538
+ * )
4539
+ *
4540
+ * console.log(match({ _tag: "success", data: "Hello" }))
4541
+ * // Output: "Ok!"
4542
+ *
4543
+ * console.log(match({ _tag: "error", error: new Error("Oops!") }))
4544
+ * // Output: "Error: Oops!"
4545
+ * ```
4546
+ *
4547
+ * @category Defining patterns
4548
+ * @since 4.0.0
4549
+ */
4550
+ const tag = tag$1;
4551
+ /**
4552
+ * Provides a fallback value when no patterns match.
4553
+ *
4554
+ * **When to use**
4555
+ *
4556
+ * Use to finalize a matcher with a fallback for unmatched input.
4557
+ *
4558
+ * **Details**
4559
+ *
4560
+ * This function ensures that a matcher always returns a valid result, even if
4561
+ * no defined patterns match. It acts as a default case, similar to the
4562
+ * `default` clause in a `switch` statement or the final `else` in an `if-else`
4563
+ * chain.
4564
+ *
4565
+ * **Example** (Providing a Default Value When No Patterns Match)
4566
+ *
4567
+ * ```ts
4568
+ * import { Match } from "effect"
4569
+ *
4570
+ * // Create a matcher for string or number values
4571
+ * const match = Match.type<string | number>().pipe(
4572
+ * // Match when the value is "a"
4573
+ * Match.when("a", () => "ok"),
4574
+ * // Fallback when no patterns match
4575
+ * Match.orElse(() => "fallback")
4576
+ * )
4577
+ *
4578
+ * console.log(match("a"))
4579
+ * // Output: "ok"
4580
+ *
4581
+ * console.log(match("b"))
4582
+ * // Output: "fallback"
4583
+ * ```
4584
+ *
4585
+ * @see {@link option} for finalizing unmatched input as `Option.none`
4586
+ * @see {@link result} for returning unmatched input as a `Result` failure
4587
+ * @see {@link orElseAbsurd} for finalizing when unmatched input should be impossible
4588
+ *
4589
+ * @category completion
4590
+ * @since 4.0.0
4591
+ */
4592
+ const orElse = orElse$1;
4593
+ //#endregion
4594
+ //#region src/cli/terminal/encoding.ts
4595
+ function bytesToLatin1String(bytes) {
4596
+ return Buffer.from(bytes).toString("latin1");
4597
+ }
4598
+ function decodeHexPayload(value) {
4599
+ const normalized = value.trim();
4600
+ if (normalized.length === 0 || normalized.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(normalized)) return;
4601
+ return Buffer.from(normalized, "hex").toString("latin1");
4602
+ }
4603
+ function decodeBase64Payload(value) {
4604
+ const normalized = value.trim();
4605
+ if (normalized.length === 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) return;
4606
+ return Buffer.from(normalized, "base64").toString("latin1");
4607
+ }
4608
+ //#endregion
4609
+ //#region src/cli/terminal/error.ts
4610
+ var TerminalCliError = class extends TaggedErrorClass()("TerminalCliError", {
4611
+ message: String$1,
4612
+ threadId: optionalKey(String$1),
4613
+ terminalId: optionalKey(String$1)
4614
+ }) {};
4615
+ var TerminalIoError = class extends TaggedErrorClass()("TerminalIoError", { message: String$1 }) {};
4616
+ //#endregion
4617
+ //#region src/cli/terminal/io-service.ts
4618
+ var TerminalIo = class extends Service()("t3cli/T3TerminalIo") {};
4619
+ //#endregion
4620
+ //#region src/cli/terminal/shared.ts
4621
+ const DETACH_BYTE = 29;
4622
+ const ANSI_CLEAR_SCREEN = "\x1Bc";
4623
+ function runAttachedTerminalSession(input) {
4624
+ return scoped(gen(function* () {
4625
+ const application = yield* T3Application;
4626
+ const io = yield* TerminalIo;
4627
+ const { cols, rows } = yield* io.getWindowSize.pipe(mapError((error) => mapTerminalIoError(error, input.terminal)));
4628
+ const session = yield* io.openRawSession.pipe(mapError((error) => mapTerminalIoError(error, input.terminal)));
4629
+ const completion = yield* make$13();
4630
+ yield* runForEach(application.attachTerminal({
4631
+ terminal: input.terminal,
4632
+ cols,
4633
+ rows
4634
+ }), applyAttachEvent).pipe(match$1({
4635
+ onFailure: (error) => completeAttachSession(completion, {
4636
+ _tag: "Failure",
4637
+ error
4638
+ }),
4639
+ onSuccess: () => completeAttachSession(completion, { _tag: "Success" })
4640
+ }), forkScoped);
4641
+ yield* runForEach(session.resize, ({ cols: nextCols, rows: nextRows }) => application.resizeTerminal({
4642
+ terminal: input.terminal,
4643
+ cols: nextCols,
4644
+ rows: nextRows
4645
+ })).pipe(match$1({
4646
+ onFailure: (error) => completeAttachSession(completion, {
4647
+ _tag: "Failure",
4648
+ error
4649
+ }),
4650
+ onSuccess: () => completeAttachSession(completion, { _tag: "Success" })
4651
+ }), forkScoped);
4652
+ yield* runForEach(session.input, (chunk) => handleSessionInput({
4653
+ completion,
4654
+ terminal: input.terminal,
4655
+ chunk
4656
+ })).pipe(match$1({
4657
+ onFailure: (error) => completeAttachSession(completion, {
4658
+ _tag: "Failure",
4659
+ error
4660
+ }),
4661
+ onSuccess: () => completeAttachSession(completion, { _tag: "Success" })
4662
+ }), forkScoped);
4663
+ const result = yield* _await(completion);
4664
+ if (result.message !== void 0) yield* writeSystemMessage(result.message);
4665
+ return yield* value(result).pipe(tag("Failure", ({ error }) => fail(error)), orElse(() => void_));
4666
+ }));
4667
+ }
4668
+ function completeAttachSession(completion, result) {
4669
+ return succeed$4(completion, result).pipe(ignore);
4670
+ }
4671
+ function handleSessionInput(input) {
4672
+ const detachOffset = input.chunk.indexOf(DETACH_BYTE);
4673
+ const payload = detachOffset === -1 ? input.chunk : input.chunk.slice(0, detachOffset);
4674
+ if (payload.length === 0 && detachOffset === -1) return void_;
4675
+ return gen(function* () {
4676
+ const application = yield* T3Application;
4677
+ if (payload.length > 0) yield* application.writeTerminal({
4678
+ terminal: input.terminal,
4679
+ data: bytesToLatin1String(payload)
4680
+ });
4681
+ if (detachOffset !== -1) yield* completeAttachSession(input.completion, {
4682
+ _tag: "Success",
4683
+ message: "detached"
4684
+ });
4685
+ });
4686
+ }
4687
+ function mapTerminalIoError(error, terminal) {
4688
+ return new TerminalCliError({
4689
+ message: error.message,
4690
+ threadId: terminal.threadId,
4691
+ terminalId: terminal.terminalId
4692
+ });
4693
+ }
4694
+ function applyAttachEvent(event) {
4695
+ return gen(function* () {
4696
+ const io = yield* TerminalIo;
4697
+ yield* value(event).pipe(when({ type: "activity" }, () => void_), when({ type: "snapshot" }, ({ snapshot }) => writeSnapshot(snapshot.history)), when({ type: "restarted" }, ({ snapshot }) => writeSnapshot(snapshot.history)), when({ type: "output" }, ({ data }) => io.writeOutput(data)), when({ type: "cleared" }, () => io.writeOutput(ANSI_CLEAR_SCREEN)), when({ type: "error" }, ({ message }) => writeSystemMessage(message)), when({ type: "closed" }, () => writeSystemMessage("Terminal closed")), orElse((next) => {
4698
+ const details = [typeof next.exitCode === "number" ? `code ${next.exitCode}` : null, typeof next.exitSignal === "number" ? `signal ${next.exitSignal}` : null].filter((value) => value !== null).join(", ");
4699
+ return writeSystemMessage(details.length > 0 ? `Process exited (${details})` : "Process exited");
4700
+ }));
4701
+ });
4702
+ }
4703
+ function writeSnapshot(history) {
4704
+ return gen(function* () {
4705
+ const io = yield* TerminalIo;
4706
+ yield* io.writeOutput(ANSI_CLEAR_SCREEN);
4707
+ if (history.length > 0) yield* io.writeOutput(history);
4708
+ });
4709
+ }
4710
+ function writeSystemMessage(message) {
4711
+ return gen(function* () {
4712
+ yield* (yield* TerminalIo).writeOutput(`\r\n[terminal] ${message}\r\n`);
4713
+ });
4714
+ }
4715
+ function toTerminalAttachTarget(terminal) {
4716
+ return {
4717
+ threadId: terminal.threadId,
4718
+ terminalId: terminal.terminalId,
4719
+ cwd: terminal.cwd,
4720
+ worktreePath: terminal.worktreePath
4721
+ };
4722
+ }
4723
+ function snapshotToTerminalAttachTarget(snapshot) {
4724
+ return {
4725
+ threadId: snapshot.threadId,
4726
+ terminalId: snapshot.terminalId,
4727
+ cwd: snapshot.cwd,
4728
+ worktreePath: snapshot.worktreePath
4729
+ };
4730
+ }
4731
+ function filterAttachStreamEvent(event, options) {
4732
+ if (event.type === "snapshot" || event.type === "restarted") {
4733
+ if (options.fromSequence !== void 0 && event.type === "restarted" && typeof event.snapshot.sequence === "number" && event.snapshot.sequence < options.fromSequence) return null;
4734
+ return {
4735
+ ...event,
4736
+ snapshot: {
4737
+ ...event.snapshot,
4738
+ history: options.includeHistory ? event.snapshot.history : ""
4739
+ }
4740
+ };
4741
+ }
4742
+ if (options.fromSequence !== void 0 && typeof event.sequence === "number" && event.sequence < options.fromSequence) return null;
4743
+ return event;
4744
+ }
4745
+ //#endregion
4746
+ //#region src/cli/terminal/attach.ts
4747
+ const attachTerminalCommand = make("attach", {
4748
+ thread: threadFlag,
4749
+ terminalId: string("terminal-id")
4750
+ }, ({ thread, terminalId }) => gen(function* () {
4751
+ const application = yield* T3Application;
4752
+ const threadId = yield* requireCommandThreadId({
4753
+ thread,
4754
+ env: (yield* Environment).env
4755
+ });
4756
+ yield* runAttachedTerminalSession({ terminal: toTerminalAttachTarget(yield* application.getTerminal({
4757
+ threadId,
4758
+ terminalId
4759
+ })) });
4760
+ })).pipe(withDescription("attach to a terminal"));
4761
+ //#endregion
4762
+ //#region src/cli/terminal-format.ts
4763
+ function formatTerminalListHuman(terminals) {
4764
+ if (terminals.length === 0) return "no terminals\n";
4765
+ return `${formatTerminalTable(terminals.map(toSummaryRow))}\n`;
4766
+ }
4767
+ function formatTerminalCreatedHuman(snapshot) {
4768
+ return `terminal created\n${formatTerminalTable([toSnapshotRow(snapshot)])}`;
4769
+ }
4770
+ function formatTerminalWrittenHuman(input) {
4771
+ return `wrote ${input.bytes} bytes to ${input.terminalId} (${input.threadId})`;
4772
+ }
4773
+ function formatTerminalDestroyedHuman(input) {
4774
+ return `destroyed ${input.terminalId} (${input.threadId})`;
4775
+ }
4776
+ function formatTerminalTable(rows) {
4777
+ const headers = {
4778
+ id: "id",
4779
+ status: "status",
4780
+ label: "label",
4781
+ cwd: "cwd",
4782
+ updated: "updated",
4783
+ process: "process"
4784
+ };
4785
+ const widths = {
4786
+ id: columnWidth(headers.id, rows.map((row) => row.id), 44),
4787
+ status: columnWidth(headers.status, rows.map((row) => row.status), 8),
4788
+ label: columnWidth(headers.label, rows.map((row) => row.label), 24),
4789
+ cwd: columnWidth(headers.cwd, rows.map((row) => row.cwd), 40),
4790
+ updated: columnWidth(headers.updated, rows.map((row) => row.updated), 24),
4791
+ process: columnWidth(headers.process, rows.map((row) => row.process), 20)
4792
+ };
4793
+ return `${[
4794
+ pad(headers.id, widths.id),
4795
+ pad(headers.status, widths.status),
4796
+ pad(headers.label, widths.label),
4797
+ pad(headers.cwd, widths.cwd),
4798
+ pad(headers.updated, widths.updated),
4799
+ pad(headers.process, widths.process)
4800
+ ].join(" ")}\n${[
4801
+ "-".repeat(widths.id),
4802
+ "-".repeat(widths.status),
4803
+ "-".repeat(widths.label),
4804
+ "-".repeat(widths.cwd),
4805
+ "-".repeat(widths.updated),
4806
+ "-".repeat(widths.process)
4807
+ ].join(" ")}\n${rows.map((row) => [
4808
+ pad(row.id, widths.id),
4809
+ pad(row.status, widths.status),
4810
+ pad(row.label, widths.label),
4811
+ pad(row.cwd, widths.cwd),
4812
+ pad(row.updated, widths.updated),
4813
+ pad(row.process, widths.process)
4814
+ ].join(" ")).join("\n")}`;
4815
+ }
4816
+ function toSummaryRow(terminal) {
4817
+ return {
4818
+ id: terminal.terminalId,
4819
+ status: terminal.status,
4820
+ label: terminal.label,
4821
+ cwd: terminal.cwd,
4822
+ updated: terminal.updatedAt,
4823
+ process: formatProcessInfo(terminal)
4824
+ };
4825
+ }
4826
+ function toSnapshotRow(snapshot) {
4827
+ return {
4828
+ id: snapshot.terminalId,
4829
+ status: snapshot.status,
4830
+ label: snapshot.label,
4831
+ cwd: snapshot.cwd,
4832
+ updated: snapshot.updatedAt,
4833
+ process: formatProcessInfo(snapshot)
4834
+ };
4835
+ }
4836
+ function formatProcessInfo(input) {
4837
+ const parts = [
4838
+ typeof input.pid === "number" ? `pid ${input.pid}` : null,
4839
+ typeof input.exitCode === "number" ? `exit ${input.exitCode}` : null,
4840
+ typeof input.exitSignal === "number" ? `sig ${input.exitSignal}` : null
4841
+ ].filter((part) => part !== null);
4842
+ return parts.length > 0 ? parts.join(", ") : "-";
4843
+ }
4844
+ function columnWidth(header, values, maxWidth) {
4845
+ const widest = values.reduce((width, value) => Math.max(width, value.length), header.length);
4846
+ return Math.min(widest, maxWidth);
4847
+ }
4848
+ function pad(value, width) {
4849
+ return truncate(value, width).padEnd(width, " ");
4850
+ }
4851
+ function truncate(value, width) {
4852
+ if (value.length <= width) return value;
4853
+ if (width <= 3) return value.slice(0, width);
4854
+ return `${value.slice(0, width - 3)}...`;
4855
+ }
4856
+ //#endregion
4857
+ //#region src/cli/terminal/create.ts
4858
+ const createTerminalCommand = make("create", {
4859
+ thread: threadFlag,
4860
+ command: string("command").pipe(optional),
4861
+ id: string$2("id").pipe(optional$2),
4862
+ attach: boolean("attach"),
4863
+ format: formatFlag
4864
+ }, ({ thread, command, id, attach, format }) => gen(function* () {
4865
+ const application = yield* T3Application;
4866
+ const environment = yield* Environment;
4867
+ const output = yield* T3Output;
4868
+ const threadId = yield* requireCommandThreadId({
4869
+ thread,
4870
+ env: environment.env
4871
+ });
4872
+ const terminalId = getOrUndefined(id);
4873
+ const commandValue = getOrUndefined(command);
4874
+ const snapshot = yield* application.createTerminal({
4875
+ threadId,
4876
+ ...terminalId !== void 0 ? { terminalId } : {},
4877
+ ...commandValue !== void 0 ? { command: commandValue } : {}
4878
+ });
4879
+ if (attach) {
4880
+ yield* runAttachedTerminalSession({ terminal: snapshotToTerminalAttachTarget(snapshot) });
4881
+ return;
4882
+ }
4883
+ if (resolveOutputFormat(format, environment, "json") === "json") yield* output.printJson(snapshot);
4884
+ else yield* output.printInfo(formatTerminalCreatedHuman(snapshot));
4885
+ })).pipe(withDescription("create a terminal for a thread"));
4886
+ //#endregion
4887
+ //#region src/cli/confirm.ts
4888
+ const requireDestructiveConfirmation = fn("requireDestructiveConfirmation")(function* (input) {
4889
+ if (input.yes) return;
4890
+ if (!isInteractiveHumanTerminal(input.environment)) {
4891
+ yield* fail(new DestructiveConfirmationRequiredError({ message: "destructive action requires --yes in non-interactive mode" }));
4892
+ return;
4893
+ }
4894
+ if (yield* run$2(confirm({
4895
+ message: input.message,
4896
+ initial: false
4897
+ }))) return;
4898
+ yield* fail(new DestructiveConfirmationRequiredError({ message: "aborted" }));
4899
+ });
4900
+ //#endregion
4901
+ //#region src/cli/terminal/destroy.ts
4902
+ const destroyTerminalCommand = make("destroy", {
4903
+ thread: threadFlag,
4904
+ terminalId: string("terminal-id"),
4905
+ quiet: boolean("quiet"),
4906
+ yes: yesFlag,
4907
+ format: formatFlag
4908
+ }, ({ thread, terminalId, quiet, yes, format }) => gen(function* () {
4909
+ const application = yield* T3Application;
4910
+ const environment = yield* Environment;
4911
+ const output = yield* T3Output;
4912
+ const threadId = yield* requireCommandThreadId({
4913
+ thread,
4914
+ env: environment.env
4915
+ });
4916
+ yield* requireDestructiveConfirmation({
4917
+ message: `Destroy terminal ${terminalId} in thread ${threadId} and delete its history?`,
4918
+ yes,
4919
+ environment
4920
+ });
4921
+ const terminal = {
4922
+ threadId,
4923
+ terminalId
4924
+ };
4925
+ yield* application.destroyTerminal(terminal);
4926
+ if (quiet) return;
4927
+ if (resolveOutputFormat(format, environment, "json") === "json") {
4928
+ yield* output.printJson({
4929
+ threadId: terminal.threadId,
4930
+ terminalId: terminal.terminalId,
4931
+ destroyed: true
4932
+ });
4933
+ return;
4934
+ }
4935
+ yield* output.printInfo(formatTerminalDestroyedHuman({
4936
+ terminalId,
4937
+ threadId
4938
+ }));
4939
+ })).pipe(withDescription("destroy a terminal and its history"));
4940
+ //#endregion
4941
+ //#region src/cli/terminal/list.ts
4942
+ const listTerminalCommand = make("list", {
4943
+ thread: threadFlag,
4944
+ format: formatFlag
4945
+ }, ({ thread, format }) => gen(function* () {
4946
+ const application = yield* T3Application;
4947
+ const environment = yield* Environment;
4948
+ const output = yield* T3Output;
4949
+ const threadId = yield* requireCommandThreadId({
4950
+ thread,
4951
+ env: environment.env
4952
+ });
4953
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
4954
+ const terminals = yield* application.listTerminals(threadId);
4955
+ if (resolvedFormat === "json") yield* output.printJson(terminals);
4956
+ else yield* output.writeStdout(formatTerminalListHuman(terminals));
4957
+ })).pipe(withDescription("list terminals for a thread"));
4958
+ const readTerminalCommand = make("read", {
4959
+ thread: threadFlag,
4960
+ terminalId: string("terminal-id"),
4961
+ history: boolean("history"),
4962
+ follow: boolean("follow"),
4963
+ fromSequence: integer("from-sequence").pipe(optional$2),
4964
+ format: choice("format", ["json", "ndjson"]).pipe(withDefault("json"))
4965
+ }, ({ thread, terminalId, history, follow, fromSequence, format }) => gen(function* () {
4966
+ const output = yield* T3Output;
4967
+ const application = yield* T3Application;
4968
+ const threadId = yield* requireCommandThreadId({
4969
+ thread,
4970
+ env: (yield* Environment).env
4971
+ });
4972
+ const fromSequenceValue = getOrUndefined(fromSequence);
4973
+ if (fromSequenceValue !== void 0 && fromSequenceValue < 0) yield* fail(new InvalidLimitError({
4974
+ message: "from-sequence must be a non-negative integer",
4975
+ value: String(fromSequenceValue)
4976
+ }));
4977
+ if (fromSequenceValue !== void 0 && !follow) yield* fail(new InvalidFlagCombinationError({ message: "--from-sequence requires --follow" }));
4978
+ if (follow && format !== "ndjson") yield* fail(new InvalidFlagCombinationError({ message: "--follow requires --format ndjson" }));
4979
+ const terminal = yield* application.getTerminal({
4980
+ threadId,
4981
+ terminalId
4982
+ });
4983
+ const stream = application.attachTerminal({ terminal: toTerminalAttachTarget(terminal) }).pipe(map$4((event) => filterAttachStreamEvent(event, {
4984
+ includeHistory: history,
4985
+ ...fromSequenceValue !== void 0 ? { fromSequence: fromSequenceValue } : {}
4986
+ })), filter((event) => event !== null));
4987
+ if (follow) {
4988
+ yield* runForEach(stream, (event) => output.printNdjson(event));
4989
+ return;
4990
+ }
4991
+ const event = getOrUndefined(yield* runHead(stream));
4992
+ if (event === void 0 || event.type !== "snapshot") yield* fail(new TerminalCliError({
4993
+ message: "server did not return terminal snapshot",
4994
+ threadId,
4995
+ terminalId
4996
+ }));
4997
+ else if (format === "ndjson") yield* output.printNdjson(event);
4998
+ else yield* output.printJson(event.snapshot);
4999
+ })).pipe(withDescription("read terminal state and optional history"));
5000
+ const streamTerminalCommand = make("stream", {
5001
+ thread: threadFlag,
5002
+ terminalId: string("terminal-id"),
5003
+ fromSequence: integer("from-sequence").pipe(optional$2),
5004
+ format: choice("format", ["ndjson"]).pipe(withDefault("ndjson"))
5005
+ }, ({ thread, terminalId, fromSequence }) => gen(function* () {
5006
+ const output = yield* T3Output;
5007
+ const application = yield* T3Application;
5008
+ const threadId = yield* requireCommandThreadId({
5009
+ thread,
5010
+ env: (yield* Environment).env
5011
+ });
5012
+ const fromSequenceValue = getOrUndefined(fromSequence);
5013
+ if (fromSequenceValue !== void 0 && fromSequenceValue < 0) yield* fail(new InvalidLimitError({
5014
+ message: "from-sequence must be a non-negative integer",
5015
+ value: String(fromSequenceValue)
5016
+ }));
5017
+ const terminal = yield* application.getTerminal({
5018
+ threadId,
5019
+ terminalId
5020
+ });
5021
+ yield* runForEach(application.attachTerminal({ terminal: toTerminalAttachTarget(terminal) }).pipe(map$4((event) => filterAttachStreamEvent(event, {
5022
+ includeHistory: true,
5023
+ ...fromSequenceValue !== void 0 ? { fromSequence: fromSequenceValue } : {}
5024
+ })), filter((event) => event !== null)), (event) => output.printNdjson(event));
5025
+ })).pipe(withDescription("stream terminal attach events as ndjson"));
5026
+ const waitTerminalCommand = make("wait", {
5027
+ thread: threadFlag,
5028
+ terminalId: string("terminal-id"),
5029
+ target: choice("for", [
5030
+ "exited",
5031
+ "closed",
5032
+ "ended"
5033
+ ]).pipe(withDefault("exited")),
5034
+ format: formatFlag
5035
+ }, ({ thread, terminalId, target, format }) => gen(function* () {
5036
+ const application = yield* T3Application;
5037
+ const environment = yield* Environment;
5038
+ const output = yield* T3Output;
5039
+ const threadId = yield* requireCommandThreadId({
5040
+ thread,
5041
+ env: environment.env
5042
+ });
5043
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5044
+ const resolution = yield* application.watchTerminalMetadata().pipe(map$4((event) => resolveMetadataWait(event, target, threadId, terminalId)), filter((value) => value !== null), runHead);
5045
+ if (isNone(resolution)) yield* fail(new TerminalCliError({
5046
+ message: "terminal wait stream ended unexpectedly",
5047
+ threadId,
5048
+ terminalId
5049
+ }));
5050
+ else if (resolution.value.kind === "fail") yield* fail(resolution.value.error);
5051
+ else {
5052
+ const result = resolution.value.value;
5053
+ if (resolvedFormat === "json") yield* output.printJson(result);
5054
+ else yield* output.printInfo(formatWaitHuman(result));
5055
+ }
5056
+ })).pipe(withDescription("wait for terminal lifecycle events"));
5057
+ function terminalClosedBeforeExitError(threadId, terminalId) {
5058
+ return new TerminalCliError({
5059
+ message: `terminal closed before an exited event was observed: ${terminalId}`,
5060
+ threadId,
5061
+ terminalId
5062
+ });
5063
+ }
5064
+ function resolveMetadataWait(event, target, threadId, terminalId) {
5065
+ if (event.type === "snapshot") {
5066
+ const terminal = event.terminals.find((candidate) => candidate.threadId === threadId && candidate.terminalId === terminalId);
5067
+ if (terminal !== void 0) {
5068
+ if (targetSatisfiedBySummary(target, terminal)) return {
5069
+ kind: "result",
5070
+ value: {
5071
+ threadId: terminal.threadId,
5072
+ terminalId: terminal.terminalId,
5073
+ target,
5074
+ status: terminal.status,
5075
+ exitCode: terminal.exitCode,
5076
+ exitSignal: terminal.exitSignal,
5077
+ updatedAt: terminal.updatedAt,
5078
+ alreadySatisfied: true
5079
+ }
5080
+ };
5081
+ return null;
5082
+ }
5083
+ if (target === "closed" || target === "ended") return {
5084
+ kind: "result",
5085
+ value: {
5086
+ threadId,
5087
+ terminalId,
5088
+ target,
5089
+ status: "closed",
5090
+ alreadySatisfied: true,
5091
+ missingTreatedAsClosed: true
5092
+ }
5093
+ };
5094
+ return {
5095
+ kind: "fail",
5096
+ error: terminalClosedBeforeExitError(threadId, terminalId)
5097
+ };
5098
+ }
5099
+ if (event.type === "upsert") {
5100
+ if (event.terminal.threadId !== threadId || event.terminal.terminalId !== terminalId) return null;
5101
+ if ((target === "exited" || target === "ended") && event.terminal.status === "exited") return {
5102
+ kind: "result",
5103
+ value: {
5104
+ threadId,
5105
+ terminalId,
5106
+ target,
5107
+ status: "exited",
5108
+ exitCode: event.terminal.exitCode,
5109
+ exitSignal: event.terminal.exitSignal,
5110
+ alreadySatisfied: false
5111
+ }
5112
+ };
5113
+ return null;
5114
+ }
5115
+ if (event.threadId !== threadId || event.terminalId !== terminalId) return null;
5116
+ if (target === "exited") return {
5117
+ kind: "fail",
5118
+ error: terminalClosedBeforeExitError(threadId, terminalId)
5119
+ };
5120
+ if (target === "closed" || target === "ended") return {
5121
+ kind: "result",
5122
+ value: {
5123
+ threadId,
5124
+ terminalId,
5125
+ target,
5126
+ status: "closed",
5127
+ alreadySatisfied: false
5128
+ }
5129
+ };
5130
+ return null;
5131
+ }
5132
+ function targetSatisfiedBySummary(target, terminal) {
5133
+ if (target === "exited") return terminal.status === "exited";
5134
+ if (target === "closed") return false;
5135
+ return terminal.status === "exited";
5136
+ }
5137
+ function formatWaitHuman(input) {
5138
+ const details = [typeof input.exitCode === "number" ? `code ${input.exitCode}` : null, typeof input.exitSignal === "number" ? `signal ${input.exitSignal}` : null].filter((value) => value !== null).join(", ");
5139
+ return details.length > 0 ? `terminal ${input.status}: ${input.terminalId} (${input.threadId}) ${details}` : `terminal ${input.status}: ${input.terminalId} (${input.threadId})`;
5140
+ }
5141
+ //#endregion
5142
+ //#region src/cli/input/service.ts
5143
+ var T3Input = class extends Service()("t3cli/T3Input") {};
5144
+ //#endregion
5145
+ //#region src/cli/terminal/write.ts
5146
+ const writeTerminalCommand = make("write", {
5147
+ thread: threadFlag,
5148
+ terminalId: string("terminal-id"),
5149
+ data: string("data").pipe(optional),
5150
+ stdin: boolean("stdin"),
5151
+ hex: string$2("hex").pipe(optional$2),
5152
+ base64: string$2("base64").pipe(optional$2),
5153
+ quiet: boolean("quiet"),
5154
+ format: formatFlag
5155
+ }, ({ thread, terminalId, data, stdin, hex, base64, quiet, format }) => gen(function* () {
5156
+ const output = yield* T3Output;
5157
+ const inputService = yield* T3Input;
5158
+ const application = yield* T3Application;
5159
+ const environment = yield* Environment;
5160
+ const threadId = yield* requireCommandThreadId({
5161
+ thread,
5162
+ env: environment.env
5163
+ });
5164
+ const argumentData = getOrUndefined(data);
5165
+ const hexData = getOrUndefined(hex);
5166
+ const base64Data = getOrUndefined(base64);
5167
+ if ([
5168
+ stdin,
5169
+ argumentData !== void 0,
5170
+ hexData !== void 0,
5171
+ base64Data !== void 0
5172
+ ].filter(Boolean).length !== 1) yield* fail(new InvalidFlagCombinationError({ message: "provide exactly one of <data>, --stdin, --hex <data>, or --base64 <data>" }));
5173
+ const payload = hexData !== void 0 ? yield* decodeHexPayloadOrFail(hexData, threadId, terminalId) : base64Data !== void 0 ? yield* decodeBase64PayloadOrFail(base64Data, threadId, terminalId) : stdin ? yield* inputService.readStdinBinary() : argumentData;
5174
+ if (payload.length === 0) yield* fail(new TerminalCliError({
5175
+ message: "terminal write payload is empty",
5176
+ threadId,
5177
+ terminalId
5178
+ }));
5179
+ yield* application.writeTerminal({
5180
+ terminal: {
5181
+ threadId,
5182
+ terminalId
5183
+ },
5184
+ data: payload
5185
+ });
5186
+ if (quiet) return;
5187
+ const bytes = Buffer.byteLength(payload, "latin1");
5188
+ if (resolveOutputFormat(format, environment, "json") === "json") {
5189
+ yield* output.printJson({
5190
+ threadId,
5191
+ terminalId,
5192
+ bytes,
5193
+ encoding: hexData !== void 0 ? "hex" : base64Data !== void 0 ? "base64" : "latin1"
5194
+ });
5195
+ return;
5196
+ }
5197
+ yield* output.printInfo(formatTerminalWrittenHuman({
5198
+ terminalId,
5199
+ threadId,
5200
+ bytes
5201
+ }));
5202
+ })).pipe(withDescription("write raw data to a terminal"));
5203
+ function decodeHexPayloadOrFail(value, threadId, terminalId) {
5204
+ const decoded = decodeHexPayload(value);
5205
+ if (decoded === void 0) return fail(new TerminalCliError({
5206
+ message: "invalid hex payload",
5207
+ threadId,
5208
+ terminalId
5209
+ }));
5210
+ return succeed(decoded);
5211
+ }
5212
+ function decodeBase64PayloadOrFail(value, threadId, terminalId) {
5213
+ const decoded = decodeBase64Payload(value);
5214
+ if (decoded === void 0) return fail(new TerminalCliError({
5215
+ message: "invalid base64 payload",
5216
+ threadId,
5217
+ terminalId
5218
+ }));
5219
+ return succeed(decoded);
5220
+ }
5221
+ //#endregion
5222
+ //#region src/cli/terminal.ts
5223
+ function createTerminalCommandGroup() {
5224
+ return make("terminal").pipe(withDescription("terminal commands"), withSubcommands([
5225
+ listTerminalCommand,
5226
+ createTerminalCommand,
5227
+ attachTerminalCommand,
5228
+ readTerminalCommand,
5229
+ streamTerminalCommand,
5230
+ waitTerminalCommand,
5231
+ writeTerminalCommand,
5232
+ destroyTerminalCommand
5233
+ ]));
5234
+ }
5235
+ //#endregion
5236
+ //#region src/cli/model-format.ts
5237
+ function formatModelsHuman(providers) {
5238
+ if (providers.length === 0) return "no models found\n";
5239
+ return providers.map((provider) => {
5240
+ const models = provider.models;
5241
+ const header = `${provider.displayName ?? provider.instanceId} (${provider.instanceId}) - ${provider.status}`;
5242
+ if (models.length === 0) return `${header}\n no models`;
5243
+ return [header, ...models.map((model) => ` ${model.slug} - ${model.name}`)].join("\n");
5244
+ }).join("\n\n");
5245
+ }
5246
+ //#endregion
5247
+ //#region src/cli/model.ts
5248
+ function createModelCommand() {
5249
+ return make("model").pipe(withDescription("model commands"), withSubcommands([listCommand$1]));
5250
+ }
5251
+ const listCommand$1 = make("list", {
5252
+ all: boolean("all"),
5253
+ provider: string$2("provider").pipe(optional$2),
5254
+ format: formatFlag
5255
+ }, ({ all, provider, format }) => gen(function* () {
5256
+ const application = yield* T3Application;
5257
+ const environment = yield* Environment;
5258
+ const output = yield* T3Output;
5259
+ const providerValue = getOrUndefined(provider);
5260
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5261
+ const providers = yield* application.listModels({
5262
+ all,
5263
+ ...providerValue !== void 0 && providerValue.length > 0 ? { provider: providerValue } : {}
5264
+ });
5265
+ if (resolvedFormat === "json") yield* output.printJson(providers);
5266
+ else yield* output.writeStdout(formatModelsHuman(providers));
5267
+ })).pipe(withDescription("list provider models"));
5268
+ //#endregion
5269
+ //#region src/cli/project-format.ts
5270
+ function formatProjectsHuman(projects) {
5271
+ return projects.map((project) => `- ${project.title}\n id: ${project.id}\n path: ${project.workspaceRoot}\n`).join("");
5272
+ }
5273
+ function formatProjectAddedHuman(project) {
5274
+ return `project added: ${project.title}\nid: ${project.id}\npath: ${project.workspaceRoot}`;
5275
+ }
5276
+ function formatProjectDeletedHuman(input) {
5277
+ return `project deleted: ${input.projectId}\nsequence: ${input.dispatch.sequence}`;
5278
+ }
5279
+ //#endregion
5280
+ //#region src/cli/require.ts
5281
+ const requireCommandProjectRef = fn("requireCommandProjectRef")(function* (input) {
5282
+ const resolved = yield* (yield* T3Config).resolve();
5283
+ const ref = resolveCommandProjectRef({
5284
+ value: getOrUndefined(input.project),
5285
+ env: input.env,
5286
+ cwd: input.cwd,
5287
+ isLocal: resolved.local
5288
+ });
5289
+ if (ref === void 0) return yield* fail(new ProjectLookupError({
5290
+ message: "project is required: pass --project, set T3CODE_PROJECT_ROOT / T3CODE_PROJECT_ID, or use local auth",
5291
+ ref: input.cwd
5292
+ }));
5293
+ return ref;
5294
+ });
5295
+ //#endregion
5296
+ //#region src/cli/projects/delete.ts
5297
+ const deleteProjectCommand = make("delete", {
5298
+ project: projectFlag,
5299
+ force: forceFlag,
5300
+ yes: yesFlag,
5301
+ format: formatFlag
5302
+ }, ({ project, force, yes, format }) => gen(function* () {
5303
+ const application = yield* T3Application;
5304
+ const environment = yield* Environment;
5305
+ const output = yield* T3Output;
5306
+ const projectRef = yield* requireCommandProjectRef({
5307
+ project,
5308
+ env: environment.env,
5309
+ cwd: environment.cwd
5310
+ });
5311
+ const resolvedProject = yield* application.resolveProject(projectRef);
5312
+ yield* requireDestructiveConfirmation({
5313
+ message: `Delete project ${resolvedProject.title} (${resolvedProject.id})?`,
5314
+ yes,
5315
+ environment
5316
+ });
5317
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5318
+ const result = yield* application.deleteProject({
5319
+ projectId: resolvedProject.id,
5320
+ ...force ? { force: true } : {}
5321
+ });
5322
+ if (resolvedFormat === "json") return yield* output.printJson({
5323
+ projectId: result.projectId,
5324
+ dispatch: result.dispatch
5325
+ });
5326
+ return yield* output.printInfo(formatProjectDeletedHuman(result));
5327
+ })).pipe(withDescription("delete project"));
5328
+ //#endregion
5329
+ //#region src/cli/project.ts
5330
+ function createProjectCommand() {
5331
+ return make("project").pipe(withDescription("project commands"), withSubcommands([
5332
+ listCommand,
5333
+ addCommand,
5334
+ deleteProjectCommand
5335
+ ]));
5336
+ }
5337
+ const listCommand = make("list", { format: formatFlag }, ({ format }) => gen(function* () {
5338
+ const application = yield* T3Application;
5339
+ const environment = yield* Environment;
5340
+ const output = yield* T3Output;
5341
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5342
+ const snapshot = yield* application.loadShell();
5343
+ if (resolvedFormat === "json") yield* output.printJson(snapshot.projects);
5344
+ else yield* output.writeStdout(formatProjectsHuman(snapshot.projects));
5345
+ })).pipe(withDescription("list projects"));
5346
+ const addCommand = make("add", {
5347
+ path: projectPathFlag,
5348
+ title: string$2("title").pipe(optional$2),
5349
+ format: formatFlag
5350
+ }, ({ path, title, format }) => gen(function* () {
5351
+ const application = yield* T3Application;
5352
+ const environment = yield* Environment;
5353
+ const output = yield* T3Output;
5354
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5355
+ const titleValue = getOrUndefined(title);
5356
+ const result = yield* application.addProject({
5357
+ path,
5358
+ ...titleValue !== void 0 && titleValue.length > 0 ? { title: titleValue } : {}
5359
+ });
5360
+ if (resolvedFormat === "json") yield* output.printJson(result);
5361
+ else yield* output.printInfo(formatProjectAddedHuman(result.project));
5362
+ })).pipe(withDescription("add project"));
5363
+ //#endregion
5364
+ //#region src/cli/threads/approve.ts
5365
+ const approvalDecisionFlag = choice("decision", [
5366
+ "accept",
5367
+ "decline",
5368
+ "cancel"
5369
+ ]).pipe(withDescription$1("Approval decision"));
5370
+ const approveThreadCommand = make("approve", {
5371
+ thread: threadFlag,
5372
+ request: string$2("request").pipe(withDescription$1("Pending approval request id"), optional$2),
5373
+ decision: approvalDecisionFlag,
5374
+ format: formatFlag
5375
+ }, ({ thread, request, decision, format }) => gen(function* () {
5376
+ const application = yield* T3Application;
5377
+ const environment = yield* Environment;
5378
+ const output = yield* T3Output;
5379
+ const threadId = resolveThreadId({
5380
+ value: getOrUndefined(thread),
5381
+ env: environment.env
5382
+ });
5383
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5384
+ const requestId = getOrUndefined(request);
5385
+ if (requestId === void 0 || requestId.length === 0) return yield* fail(new MissingRequestError({ message: "request id is required: pass --request" }));
5386
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5387
+ const result = yield* application.approveThread({
5388
+ threadId,
5389
+ requestId,
5390
+ decision
5391
+ });
5392
+ if (resolvedFormat === "json") return yield* output.printJson(result);
5393
+ return yield* output.printInfo(`approval submitted: ${result.requestId}\nsequence: ${result.dispatch.sequence}`);
5394
+ })).pipe(withDescription("respond to a pending approval request"));
5395
+ //#endregion
5396
+ //#region src/cli/self-action.ts
5397
+ const requireSelfActionConfirmation = fn("requireSelfActionConfirmation")(function* (input) {
5398
+ if (input.force) return;
5399
+ if (!isAgentEnvironment(input.environment)) return;
5400
+ const callerThreadId = input.environment.env.T3CODE_THREAD_ID;
5401
+ if (callerThreadId === void 0 || callerThreadId.length === 0) return;
5402
+ if (input.threadId !== callerThreadId) return;
5403
+ yield* fail(new SelfActionError({
5404
+ threadId: input.threadId,
5405
+ message: `cannot ${input.action} thread ${input.threadId}: command targets the calling thread. Pass --force to confirm.`
5406
+ }));
5407
+ });
5408
+ //#endregion
5409
+ //#region src/cli/threads/archive.ts
5410
+ const archiveThreadCommand = make("archive", {
5411
+ thread: threadFlag,
5412
+ force: selfActionForceFlag,
5413
+ format: formatFlag
5414
+ }, ({ thread, force, format }) => gen(function* () {
5415
+ const application = yield* T3Application;
5416
+ const environment = yield* Environment;
5417
+ const output = yield* T3Output;
5418
+ const threadId = resolveThreadId({
5419
+ value: getOrUndefined(thread),
5420
+ env: environment.env
5421
+ });
5422
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5423
+ yield* requireSelfActionConfirmation({
5424
+ threadId,
5425
+ force,
5426
+ environment,
5427
+ action: "archive"
5428
+ });
5429
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5430
+ const dispatch = yield* application.archiveThread(threadId);
5431
+ if (resolvedFormat === "json") return yield* output.printJson(dispatch);
5432
+ return yield* output.printInfo(`thread archived: ${threadId}\nsequence: ${dispatch.sequence}`);
5433
+ })).pipe(withDescription("archive thread"));
5434
+ //#endregion
5435
+ //#region src/cli/threads/callback.ts
5436
+ const callbackThreadCommand = make("callback", {
5437
+ from: string$2("from").pipe(withDescription$1("Thread ID to watch for completion")),
5438
+ thread: threadFlag,
5439
+ prompt: string$2("prompt").pipe(withDescription$1("Message to send to target thread")),
5440
+ background: boolean("background").pipe(withDescription$1("Fork and detach as background process"), optional$2)
5441
+ }, ({ from, thread, prompt, background }) => gen(function* () {
5442
+ const application = yield* T3Application;
5443
+ const environment = yield* Environment;
5444
+ const output = yield* T3Output;
5445
+ const cliPath = yield* CliPath;
5446
+ const spawner = yield* ChildProcessSpawner;
5447
+ const fromThreadId = from;
5448
+ const targetThreadId = resolveThreadId({
5449
+ value: getOrUndefined(thread),
5450
+ env: environment.env
5451
+ });
5452
+ if (targetThreadId === void 0) return yield* fail(new MissingThreadError({ message: "target thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5453
+ if (getOrElse(background, () => false)) {
5454
+ const args = [
5455
+ cliPath.path,
5456
+ "thread",
5457
+ "callback",
5458
+ "--from",
5459
+ fromThreadId,
5460
+ "--thread",
5461
+ targetThreadId,
5462
+ "--prompt",
5463
+ prompt
5464
+ ];
5465
+ const proc = make$5(process.execPath, args, {
5466
+ detached: true,
5467
+ stdin: "ignore",
5468
+ stdout: "ignore",
5469
+ stderr: "ignore"
5470
+ });
5471
+ const handle = yield* spawner.spawn(proc);
5472
+ yield* handle.unref.pipe(ignore);
5473
+ yield* output.printInfo(`background callback scheduled: ${fromThreadId} -> ${targetThreadId} (pid: ${handle.pid})`);
5474
+ return;
5475
+ }
5476
+ yield* output.printInfo(`watching thread ${fromThreadId} for completion...`);
5477
+ const result = yield* application.callbackThread({
5478
+ fromThreadId,
5479
+ targetThreadId,
5480
+ prompt
5481
+ });
5482
+ yield* output.printInfo(`callback sent to ${result.targetThreadId} (dispatch: ${result.dispatch.sequence})`);
5483
+ })).pipe(withDescription("watch a thread and send a message when it completes"));
5484
+ //#endregion
5485
+ //#region src/cli/thread-format.ts
5486
+ function formatThreadShowJson(thread) {
5487
+ return {
5488
+ id: thread.id,
5489
+ projectId: thread.projectId,
5490
+ title: thread.title,
5491
+ status: thread.status,
5492
+ session: thread.session,
5493
+ latestTurn: thread.latestTurn,
5494
+ modelSelection: thread.modelSelection,
5495
+ runtimeMode: thread.runtimeMode,
5496
+ interactionMode: thread.interactionMode,
5497
+ branch: thread.branch,
5498
+ worktreePath: thread.worktreePath,
4516
5499
  archivedAt: thread.archivedAt,
4517
5500
  createdAt: thread.createdAt,
4518
5501
  updatedAt: thread.updatedAt,
@@ -4545,7 +5528,10 @@ function formatThreadShowHuman(thread) {
4545
5528
  return `${lines.join("\n")}\n`;
4546
5529
  }
4547
5530
  function formatThreadsHuman(threads) {
4548
- return threads.map((thread) => `- ${thread.title}\n id: ${thread.id}\n status: ${threadStatus(thread)}\n updated: ${thread.updatedAt}\n`).join("");
5531
+ return threads.map((thread) => `- ${thread.title}${thread.archivedAt !== null ? " (archived)" : ""}\n id: ${thread.id}\n status: ${threadStatus(thread)}\n updated: ${thread.updatedAt}\n`).join("");
5532
+ }
5533
+ function formatThreadDeletedHuman(input) {
5534
+ return `thread deleted: ${input.threadId}\nsequence: ${input.dispatch.sequence}`;
4549
5535
  }
4550
5536
  function formatThreadStartedHuman(input) {
4551
5537
  return `thread started: ${input.thread.title}\nid: ${input.thread.id}\nstatus: ${threadStatus(input.thread)}\nsequence: ${input.sequence}`;
@@ -4585,36 +5571,47 @@ function stripThreadHeavy(thread) {
4585
5571
  return rest;
4586
5572
  }
4587
5573
  //#endregion
4588
- //#region src/cli/threads/list.ts
4589
- const listThreadsCommand = make("list", {
4590
- project: projectFlag,
5574
+ //#region src/cli/threads/delete.ts
5575
+ const deleteThreadCommand = make("delete", {
5576
+ thread: threadFlag,
5577
+ force: selfActionForceFlag,
5578
+ yes: yesFlag,
4591
5579
  format: formatFlag
4592
- }, ({ project, format }) => gen(function* () {
5580
+ }, ({ thread, force, yes, format }) => gen(function* () {
4593
5581
  const application = yield* T3Application;
4594
5582
  const environment = yield* Environment;
4595
5583
  const output = yield* T3Output;
5584
+ const threadId = resolveThreadId({
5585
+ value: getOrUndefined(thread),
5586
+ env: environment.env
5587
+ });
5588
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5589
+ yield* requireSelfActionConfirmation({
5590
+ threadId,
5591
+ force,
5592
+ environment,
5593
+ action: "delete"
5594
+ });
5595
+ yield* requireDestructiveConfirmation({
5596
+ message: `Delete thread ${threadId}?`,
5597
+ yes,
5598
+ environment
5599
+ });
4596
5600
  const resolvedFormat = resolveOutputFormat(format, environment, "json");
4597
- const projectRef = yield* requireCommandProjectRef({
4598
- project,
4599
- env: environment.env,
4600
- cwd: environment.cwd
5601
+ const result = yield* application.deleteThread(threadId);
5602
+ if (resolvedFormat === "json") return yield* output.printJson({
5603
+ threadId: result.threadId,
5604
+ dispatch: result.dispatch
4601
5605
  });
4602
- const result = yield* application.listThreads(projectRef);
4603
- if (resolvedFormat === "json") yield* output.printJson(result.threads);
4604
- else yield* output.writeStdout(formatThreadsHuman(result.threads));
4605
- })).pipe(withDescription("list project threads"));
5606
+ return yield* output.printInfo(formatThreadDeletedHuman(result));
5607
+ })).pipe(withDescription("delete thread"));
4606
5608
  //#endregion
4607
- //#region src/cli/threads/messages.ts
4608
- const getThreadMessagesCommand = make("messages", {
5609
+ //#region src/cli/threads/interrupt.ts
5610
+ const interruptThreadCommand = make("interrupt", {
4609
5611
  thread: threadFlag,
4610
- limit: integer("limit").pipe(withDefault(20)),
4611
- full: boolean("full"),
5612
+ force: selfActionForceFlag,
4612
5613
  format: formatFlag
4613
- }, ({ thread, limit, full, format }) => gen(function* () {
4614
- if (limit < 0) return yield* fail(new InvalidLimitError({
4615
- message: `invalid limit: ${limit}`,
4616
- value: String(limit)
4617
- }));
5614
+ }, ({ thread, force, format }) => gen(function* () {
4618
5615
  const application = yield* T3Application;
4619
5616
  const environment = yield* Environment;
4620
5617
  const output = yield* T3Output;
@@ -4623,11 +5620,20 @@ const getThreadMessagesCommand = make("messages", {
4623
5620
  env: environment.env
4624
5621
  });
4625
5622
  if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5623
+ yield* requireSelfActionConfirmation({
5624
+ threadId,
5625
+ force,
5626
+ environment,
5627
+ action: "interrupt"
5628
+ });
4626
5629
  const resolvedFormat = resolveOutputFormat(format, environment, "json");
4627
- const detail = yield* application.getThreadMessages(threadId);
4628
- if (resolvedFormat === "json") return yield* output.printJson(formatThreadMessagesJson(detail, full));
4629
- return yield* output.writeStdout(formatThreadMessagesHuman(detail, limit));
4630
- })).pipe(withDescription("get latest thread messages"));
5630
+ const dispatch = yield* application.interruptThread(threadId);
5631
+ if (resolvedFormat === "json") return yield* output.printJson({
5632
+ threadId,
5633
+ dispatch
5634
+ });
5635
+ return yield* output.printInfo(`thread interrupted: ${threadId}\nsequence: ${dispatch.sequence}`);
5636
+ })).pipe(withDescription("interrupt running thread turn"));
4631
5637
  //#endregion
4632
5638
  //#region src/cli/message-input.ts
4633
5639
  function readInitialMessage(input) {
@@ -4650,9 +5656,6 @@ function parseJsonAnswers(text) {
4650
5656
  return fail(new MessageInputError({ message: "invalid JSON in answers" }));
4651
5657
  }
4652
5658
  }
4653
- //#endregion
4654
- //#region src/cli/input/service.ts
4655
- var T3Input = class extends Service()("t3cli/T3Input") {};
4656
5659
  const respondThreadCommand = make("respond", {
4657
5660
  thread: threadFlag,
4658
5661
  request: string$2("request").pipe(withDescription$1("Pending user-input request id"), optional$2),
@@ -4686,6 +5689,25 @@ const respondThreadCommand = make("respond", {
4686
5689
  return yield* output.printInfo(`user input submitted: ${result.requestId}\nsequence: ${result.dispatch.sequence}`);
4687
5690
  })).pipe(withDescription("respond to a pending user-input request"));
4688
5691
  //#endregion
5692
+ //#region src/cli/threads/unarchive.ts
5693
+ const unarchiveThreadCommand = make("unarchive", {
5694
+ thread: threadFlag,
5695
+ format: formatFlag
5696
+ }, ({ thread, format }) => gen(function* () {
5697
+ const application = yield* T3Application;
5698
+ const environment = yield* Environment;
5699
+ const output = yield* T3Output;
5700
+ const threadId = resolveThreadId({
5701
+ value: getOrUndefined(thread),
5702
+ env: environment.env
5703
+ });
5704
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5705
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5706
+ const dispatch = yield* application.unarchiveThread(threadId);
5707
+ if (resolvedFormat === "json") return yield* output.printJson(dispatch);
5708
+ return yield* output.printInfo(`thread unarchived: ${threadId}\nsequence: ${dispatch.sequence}`);
5709
+ })).pipe(withDescription("unarchive thread"));
5710
+ //#endregion
4689
5711
  //#region src/cli/model-options.ts
4690
5712
  function buildModelOptions(input) {
4691
5713
  const options = /* @__PURE__ */ new Map();
@@ -4719,6 +5741,106 @@ function setBooleanOption(options, id, value) {
4719
5741
  });
4720
5742
  }
4721
5743
  //#endregion
5744
+ //#region src/cli/threads/update.ts
5745
+ const updateThreadCommand = make("update", {
5746
+ thread: threadFlag,
5747
+ force: selfActionForceFlag,
5748
+ title: string$2("title").pipe(optional$2),
5749
+ provider: string$2("provider").pipe(optional$2),
5750
+ model: string$2("model").pipe(optional$2),
5751
+ ...modelFlags,
5752
+ branch: string$2("branch").pipe(optional$2),
5753
+ clearBranch: boolean("clear-branch").pipe(optional$2),
5754
+ worktree: string$2("worktree").pipe(optional$2),
5755
+ clearWorktree: boolean("clear-worktree").pipe(optional$2),
5756
+ format: formatFlag
5757
+ }, ({ thread, force, title, provider, model, option, reasoningEffort, effort, fastMode, thinking, branch, clearBranch, worktree, clearWorktree, format }) => gen(function* () {
5758
+ const application = yield* T3Application;
5759
+ const environment = yield* Environment;
5760
+ const output = yield* T3Output;
5761
+ const threadId = resolveThreadId({
5762
+ value: getOrUndefined(thread),
5763
+ env: environment.env
5764
+ });
5765
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5766
+ yield* requireSelfActionConfirmation({
5767
+ threadId,
5768
+ force,
5769
+ environment,
5770
+ action: "update"
5771
+ });
5772
+ const titleValue = getOrUndefined(title);
5773
+ const providerValue = getOrUndefined(provider);
5774
+ const modelValue = getOrUndefined(model);
5775
+ const branchValue = getOrUndefined(branch);
5776
+ const worktreeValue = getOrUndefined(worktree);
5777
+ const clearBranchValue = getOrUndefined(clearBranch);
5778
+ const clearWorktreeValue = getOrUndefined(clearWorktree);
5779
+ const options = buildModelOptions({
5780
+ option,
5781
+ reasoningEffort,
5782
+ effort,
5783
+ fastMode,
5784
+ thinking
5785
+ });
5786
+ if (clearBranchValue === true && branchValue !== void 0) return yield* fail(new ConflictingUpdateFlagsError({ message: "--branch and --clear-branch are mutually exclusive" }));
5787
+ if (clearWorktreeValue === true && worktreeValue !== void 0) return yield* fail(new ConflictingUpdateFlagsError({ message: "--worktree and --clear-worktree are mutually exclusive" }));
5788
+ const hasTitle = titleValue !== void 0 && titleValue.length > 0;
5789
+ const hasProvider = providerValue !== void 0 && providerValue.length > 0;
5790
+ const hasModel = modelValue !== void 0 && modelValue.length > 0;
5791
+ const hasBranch = branchValue !== void 0 && branchValue.length > 0;
5792
+ const hasWorktree = worktreeValue !== void 0 && worktreeValue.length > 0;
5793
+ if (!hasTitle && !hasProvider && !hasModel && options.length === 0 && !hasBranch && clearBranchValue !== true && !hasWorktree && clearWorktreeValue !== true) return yield* fail(new MissingUpdateFieldsError({ message: "at least one update field is required: --title, model flags, --branch, --clear-branch, --worktree, or --clear-worktree" }));
5794
+ const dispatch = yield* application.updateThread({
5795
+ threadId,
5796
+ ...hasTitle ? { title: titleValue } : {},
5797
+ ...hasProvider ? { provider: providerValue } : {},
5798
+ ...hasModel ? { model: modelValue } : {},
5799
+ ...options.length > 0 ? { options } : {},
5800
+ ...clearBranchValue === true ? { branch: null } : hasBranch ? { branch: branchValue } : {},
5801
+ ...clearWorktreeValue === true ? { worktreePath: null } : hasWorktree ? { worktreePath: worktreeValue } : {}
5802
+ });
5803
+ if (resolveOutputFormat(format, environment, "json") === "json") return yield* output.printJson(dispatch);
5804
+ return yield* output.printInfo(`thread updated: ${threadId}\nsequence: ${dispatch.sequence}`);
5805
+ })).pipe(withDescription("update thread metadata"));
5806
+ //#endregion
5807
+ //#region src/cli/thread.ts
5808
+ function createThreadCommand() {
5809
+ return make("thread").pipe(withDescription("advanced thread commands"), withSubcommands([
5810
+ approveThreadCommand,
5811
+ respondThreadCommand,
5812
+ archiveThreadCommand,
5813
+ interruptThreadCommand,
5814
+ unarchiveThreadCommand,
5815
+ updateThreadCommand,
5816
+ deleteThreadCommand,
5817
+ callbackThreadCommand
5818
+ ]));
5819
+ }
5820
+ //#endregion
5821
+ //#region src/cli/threads/list.ts
5822
+ const listThreadsCommand = make("list", {
5823
+ project: projectFlag,
5824
+ archived: boolean("archived").pipe(withDescription$1("List archived threads only")),
5825
+ all: boolean("all").pipe(withDescription$1("List active and archived threads")),
5826
+ format: formatFlag
5827
+ }, ({ project, archived, all, format }) => gen(function* () {
5828
+ const application = yield* T3Application;
5829
+ const environment = yield* Environment;
5830
+ const output = yield* T3Output;
5831
+ if (archived && all) yield* fail(new InvalidFlagCombinationError({ message: "--archived and --all are mutually exclusive" }));
5832
+ const include = archived ? "archived" : all ? "all" : "active";
5833
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
5834
+ const projectRef = yield* requireCommandProjectRef({
5835
+ project,
5836
+ env: environment.env,
5837
+ cwd: environment.cwd
5838
+ });
5839
+ const result = yield* application.listThreads(projectRef, { include });
5840
+ if (resolvedFormat === "json") yield* output.printJson(result.threads);
5841
+ else yield* output.writeStdout(formatThreadsHuman(result.threads));
5842
+ })).pipe(withDescription("list project threads"));
5843
+ //#endregion
4722
5844
  //#region src/cli/wait-events.ts
4723
5845
  function printWaitEventsNdjson(output, events) {
4724
5846
  return events.pipe(tap((event) => output.printNdjson(formatWaitEventNdjson(event))), runDrain);
@@ -4777,12 +5899,13 @@ function fitLine(text, columns) {
4777
5899
  //#region src/cli/threads/send.ts
4778
5900
  const sendThreadCommand = make("send", {
4779
5901
  thread: threadFlag,
5902
+ force: selfActionForceFlag,
4780
5903
  message: string("message").pipe(optional),
4781
5904
  stdin: boolean("stdin"),
4782
5905
  ...modelFlags,
4783
5906
  wait: boolean("wait"),
4784
5907
  format: threadFormatFlag
4785
- }, ({ thread, message, stdin, option, reasoningEffort, effort, fastMode, thinking, wait, format }) => gen(function* () {
5908
+ }, ({ thread, force, message, stdin, option, reasoningEffort, effort, fastMode, thinking, wait, format }) => gen(function* () {
4786
5909
  const inputService = yield* T3Input;
4787
5910
  const text = yield* readInitialMessage({
4788
5911
  message: getOrUndefined(message),
@@ -4804,6 +5927,12 @@ const sendThreadCommand = make("send", {
4804
5927
  env: environment.env
4805
5928
  });
4806
5929
  if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
5930
+ yield* requireSelfActionConfirmation({
5931
+ threadId,
5932
+ force,
5933
+ environment,
5934
+ action: "send a message to"
5935
+ });
4807
5936
  const input = {
4808
5937
  message: text,
4809
5938
  threadId,
@@ -4948,6 +6077,31 @@ const startThreadCommand = make("start", {
4948
6077
  }));
4949
6078
  })).pipe(withDescription("start thread with initial message"));
4950
6079
  //#endregion
6080
+ //#region src/cli/threads/messages.ts
6081
+ const getThreadTranscriptCommand = make("transcript", {
6082
+ thread: threadFlag,
6083
+ limit: integer("limit").pipe(withDefault(20)),
6084
+ full: boolean("full"),
6085
+ format: formatFlag
6086
+ }, ({ thread, limit, full, format }) => gen(function* () {
6087
+ if (limit < 0) return yield* fail(new InvalidLimitError({
6088
+ message: `invalid limit: ${limit}`,
6089
+ value: String(limit)
6090
+ }));
6091
+ const application = yield* T3Application;
6092
+ const environment = yield* Environment;
6093
+ const output = yield* T3Output;
6094
+ const threadId = resolveThreadId({
6095
+ value: getOrUndefined(thread),
6096
+ env: environment.env
6097
+ });
6098
+ if (threadId === void 0) return yield* fail(new MissingThreadError({ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID" }));
6099
+ const resolvedFormat = resolveOutputFormat(format, environment, "json");
6100
+ const detail = yield* application.getThreadMessages(threadId);
6101
+ if (resolvedFormat === "json") return yield* output.printJson(formatThreadMessagesJson(detail, full));
6102
+ return yield* output.writeStdout(formatThreadMessagesHuman(detail, limit));
6103
+ })).pipe(withDescription("get latest thread transcript"));
6104
+ //#endregion
4951
6105
  //#region src/cli/threads/wait.ts
4952
6106
  const waitForThreadCommand = make("wait", {
4953
6107
  thread: threadFlag,
@@ -4968,28 +6122,19 @@ const waitForThreadCommand = make("wait", {
4968
6122
  });
4969
6123
  })).pipe(withDescription("wait for thread to pause"));
4970
6124
  //#endregion
4971
- //#region src/cli/thread.ts
4972
- function createThreadCommand() {
4973
- return make("thread").pipe(withDescription("thread commands"), withSubcommands([
4974
- listThreadsCommand,
4975
- startThreadCommand,
4976
- sendThreadCommand,
4977
- showThreadCommand,
4978
- approveThreadCommand,
4979
- respondThreadCommand,
4980
- archiveThreadCommand,
4981
- getThreadMessagesCommand,
4982
- waitForThreadCommand,
4983
- callbackThreadCommand
4984
- ]));
4985
- }
4986
- //#endregion
4987
6125
  //#region src/cli/app.ts
4988
6126
  function createCliCommand() {
4989
6127
  return make("t3cli").pipe(withDescription("non-interactive cli for running t3code server"), withSubcommands([
4990
6128
  createAuthCommand(),
6129
+ listThreadsCommand,
4991
6130
  createModelCommand(),
4992
6131
  createProjectCommand(),
6132
+ createTerminalCommandGroup(),
6133
+ startThreadCommand,
6134
+ sendThreadCommand,
6135
+ showThreadCommand,
6136
+ getThreadTranscriptCommand,
6137
+ waitForThreadCommand,
4993
6138
  createThreadCommand()
4994
6139
  ]));
4995
6140
  }
@@ -5005,12 +6150,25 @@ var InputError = class extends TaggedErrorClass()("InputError", {
5005
6150
  }) {};
5006
6151
  const T3InputLive = effect(T3Input, fn("makeT3Input")(function* () {
5007
6152
  const stdio = yield* Stdio;
5008
- return { readStdin: fn("T3InputLive.readStdin")(function* () {
5009
- return yield* stdio.stdin.pipe(decodeText(), runFold(() => "", (acc, chunk) => acc + chunk), catchTags({ PlatformError: (error) => fail(new InputError({
5010
- message: "failed to read stdin",
5011
- cause: error
5012
- })) }));
5013
- }) };
6153
+ return {
6154
+ readStdin: fn("T3InputLive.readStdin")(function* () {
6155
+ return yield* stdio.stdin.pipe(decodeText(), runFold(() => "", (acc, chunk) => acc + chunk), catchTags({ PlatformError: (error) => fail(new InputError({
6156
+ message: "failed to read stdin",
6157
+ cause: error
6158
+ })) }));
6159
+ }),
6160
+ readStdinBinary: fn("T3InputLive.readStdinBinary")(function* () {
6161
+ return yield* stdio.stdin.pipe(runFold(() => new Uint8Array(0), (acc, chunk) => {
6162
+ const merged = new Uint8Array(acc.length + chunk.length);
6163
+ merged.set(acc);
6164
+ merged.set(chunk, acc.length);
6165
+ return merged;
6166
+ }), map((bytes) => Buffer.from(bytes).toString("latin1")), catchTags({ PlatformError: (error) => fail(new InputError({
6167
+ message: "failed to read stdin",
6168
+ cause: error
6169
+ })) }));
6170
+ })
6171
+ };
5014
6172
  })());
5015
6173
  //#endregion
5016
6174
  //#region src/cli/output/error.ts
@@ -5025,7 +6183,7 @@ var OutputError = class extends TaggedErrorClass()("OutputError", {
5025
6183
  const T3OutputLive = effect(T3Output, fn("makeT3Output")(function* () {
5026
6184
  const stdio = yield* Stdio;
5027
6185
  const writeStdout = fn("T3OutputLive.writeStdout")(function* (text) {
5028
- yield* succeed$4(text).pipe(run$1(stdio.stdout()), catchTags({ PlatformError: (error) => fail(new OutputError({
6186
+ yield* succeed$5(text).pipe(run$1(stdio.stdout()), catchTags({ PlatformError: (error) => fail(new OutputError({
5029
6187
  message: "failed to write output",
5030
6188
  cause: error
5031
6189
  })) }));
@@ -5033,7 +6191,7 @@ const T3OutputLive = effect(T3Output, fn("makeT3Output")(function* () {
5033
6191
  return {
5034
6192
  writeStdout,
5035
6193
  writeStderr: fn("T3OutputLive.writeStderr")(function* (text) {
5036
- yield* succeed$4(text).pipe(run$1(stdio.stderr()), catchTags({ PlatformError: (error) => fail(new OutputError({
6194
+ yield* succeed$5(text).pipe(run$1(stdio.stderr()), catchTags({ PlatformError: (error) => fail(new OutputError({
5037
6195
  message: "failed to write output",
5038
6196
  cause: error
5039
6197
  })) }));
@@ -5050,12 +6208,69 @@ const T3OutputLive = effect(T3Output, fn("makeT3Output")(function* () {
5050
6208
  };
5051
6209
  })());
5052
6210
  //#endregion
6211
+ //#region src/cli/terminal/io-node-layer.ts
6212
+ const DEFAULT_COLS = 80;
6213
+ const DEFAULT_ROWS = 24;
6214
+ const INTERACTIVE_TTY_MESSAGE = "terminal attach requires an interactive TTY on stdin and stdout";
6215
+ const requireInteractiveTty = gen(function* () {
6216
+ if (!process.stdin.isTTY || !process.stdout.isTTY || process.stdin.setRawMode === void 0) return yield* fail(new TerminalIoError({ message: INTERACTIVE_TTY_MESSAGE }));
6217
+ return {
6218
+ stdin: process.stdin,
6219
+ stdout: process.stdout
6220
+ };
6221
+ });
6222
+ const NodeTerminalIoLive = succeed$2(TerminalIo, {
6223
+ getWindowSize: requireInteractiveTty.pipe(map(readWindowSize)),
6224
+ writeOutput: (text) => sync(() => {
6225
+ process.stdout.write(text);
6226
+ }),
6227
+ openRawSession: acquireRelease(gen(function* () {
6228
+ const tty = yield* requireInteractiveTty;
6229
+ const input = yield* unbounded();
6230
+ const resize = yield* unbounded();
6231
+ const onResize = () => {
6232
+ runFork(offer(resize, readWindowSize(tty)).pipe(ignore));
6233
+ };
6234
+ const onData = (chunk) => {
6235
+ runFork(offer(input, typeof chunk === "string" ? Buffer.from(chunk) : chunk).pipe(ignore));
6236
+ };
6237
+ tty.stdin.resume();
6238
+ tty.stdin.setRawMode(true);
6239
+ process.on("SIGWINCH", onResize);
6240
+ tty.stdin.on("data", onData);
6241
+ return {
6242
+ tty,
6243
+ input,
6244
+ resize,
6245
+ onData,
6246
+ onResize,
6247
+ session: {
6248
+ input: fromQueue(input),
6249
+ resize: fromQueue(resize)
6250
+ }
6251
+ };
6252
+ }), ({ tty, input, resize, onData, onResize }) => gen(function* () {
6253
+ tty.stdin.off("data", onData);
6254
+ process.off("SIGWINCH", onResize);
6255
+ tty.stdin.setRawMode(false);
6256
+ tty.stdin.pause();
6257
+ yield* shutdown(input);
6258
+ yield* shutdown(resize);
6259
+ })).pipe(map(({ session }) => session))
6260
+ });
6261
+ function readWindowSize(tty) {
6262
+ return {
6263
+ cols: tty.stdout.columns ?? DEFAULT_COLS,
6264
+ rows: tty.stdout.rows ?? DEFAULT_ROWS
6265
+ };
6266
+ }
6267
+ //#endregion
5053
6268
  //#region src/version/service.ts
5054
6269
  var T3Version = class extends Service()("t3cli/T3Version") {};
5055
6270
  //#endregion
5056
6271
  //#region src/version/layer.ts
5057
6272
  const PackageJsonSchema = fromJsonString(Struct({ version: String$1 }));
5058
- const T3VersionBundledLive = sync$2(T3Version, () => ({ version: "0.9.1" }));
6273
+ const T3VersionBundledLive = sync$2(T3Version, () => ({ version: "0.11.0" }));
5059
6274
  effect(T3Version, gen(function* () {
5060
6275
  const packageJson = yield* (yield* FileSystem).readFileString(fileURLToPath(new URL("../../package.json", import.meta.url)));
5061
6276
  return { version: (yield* decodeUnknownEffect(PackageJsonSchema)(packageJson)).version };
@@ -5064,7 +6279,7 @@ effect(T3Version, gen(function* () {
5064
6279
  //#region src/bin.ts
5065
6280
  const VersionLive = T3VersionBundledLive;
5066
6281
  const PlatformLayer = mergeAll(layer, NodeEnvironmentLive);
5067
- const CliLayer = mergeAll(AppLayer.pipe(provide(PlatformLayer)), layer, NodeEnvironmentLive, T3InputLive.pipe(provide(layer)), T3OutputLive.pipe(provide(layer)), VersionLive.pipe(provide(layer)));
6282
+ const CliLayer = mergeAll(AppLayer.pipe(provide(PlatformLayer)), layer, NodeEnvironmentLive, T3InputLive.pipe(provide(layer)), T3OutputLive.pipe(provide(layer)), NodeTerminalIoLive, VersionLive.pipe(provide(layer)));
5068
6283
  runMain(gen(function* () {
5069
6284
  const version = yield* T3Version;
5070
6285
  return yield* run(createCliCommand(), { version: version.version });