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.
- package/README.md +52 -14
- package/dist/application.js +2 -2
- package/dist/auth.js +1 -1
- package/dist/bin.js +1556 -341
- package/dist/cli.js +1 -1
- package/dist/config.js +1 -1
- package/dist/connection.js +1 -11
- package/dist/index.js +1 -1
- package/dist/layout.js +1 -1
- package/dist/node.js +2 -0
- package/dist/orchestration.js +2 -2
- package/dist/rpc.js +2 -2
- package/dist/runtime.js +1 -1
- package/dist/scope.js +1 -1
- package/dist/shared.js +1734 -756
- package/dist/src/application/index.d.ts +3 -2
- package/dist/src/application/layer.d.ts +82 -841
- package/dist/src/application/model-selection.d.ts +15 -0
- package/dist/src/application/models.d.ts +1 -87
- package/dist/src/application/project-commands.d.ts +9 -0
- package/dist/src/application/projects.d.ts +13 -135
- package/dist/src/application/service.d.ts +84 -5
- package/dist/src/application/shell-sequence.d.ts +2 -12
- package/dist/src/application/terminals.d.ts +66 -0
- package/dist/src/application/thread-commands.d.ts +47 -0
- package/dist/src/application/thread-update.d.ts +8 -0
- package/dist/src/application/thread-wait.d.ts +3 -14
- package/dist/src/application/threads.d.ts +21 -50
- package/dist/src/cli/flags.d.ts +3 -0
- package/dist/src/cli/output-format.d.ts +2 -0
- package/dist/src/domain/error.d.ts +14 -1
- package/dist/src/domain/helpers.d.ts +0 -9
- package/dist/src/domain/model-config.d.ts +29 -3
- package/dist/src/domain/thread-lifecycle.d.ts +2 -10
- package/dist/src/node/index.d.ts +2 -0
- package/dist/src/orchestration/index.d.ts +1 -0
- package/dist/src/orchestration/layer.d.ts +177 -1032
- package/dist/src/orchestration/service.d.ts +1 -0
- package/dist/src/rpc/error.d.ts +4 -2
- package/dist/src/rpc/index.d.ts +5 -0
- package/dist/src/rpc/layer.d.ts +1097 -499
- package/dist/src/rpc/operation.d.ts +5752 -0
- package/dist/src/rpc/ws-group.d.ts +327 -147
- package/dist/src/runtime/layer.d.ts +1 -1
- package/dist/t3tools.js +2 -2
- package/dist/upstream-t3code/packages/contracts/src/environmentHttp.d.ts +10 -33
- package/dist/upstream-t3code/packages/contracts/src/ipc.d.ts +0 -6
- package/dist/upstream-t3code/packages/contracts/src/orchestration.d.ts +1 -657
- package/dist/upstream-t3code/packages/contracts/src/provider.d.ts +0 -14
- package/dist/upstream-t3code/packages/contracts/src/providerRuntime.d.ts +1 -175
- package/dist/upstream-t3code/packages/contracts/src/rpc.d.ts +0 -492
- package/dist/upstream-t3code/packages/contracts/src/server.d.ts +0 -45
- package/dist/upstream-t3code/packages/contracts/src/settings.d.ts +0 -21
- package/dist/upstream-t3code/packages/contracts/src/terminal.d.ts +3 -6
- package/package.json +6 -2
- package/src/application/index.ts +28 -2
- package/src/application/layer.ts +34 -5
- package/src/application/model-selection.ts +68 -2
- package/src/application/models.ts +14 -14
- package/src/application/project-commands.ts +15 -0
- package/src/application/projects.ts +43 -13
- package/src/application/service.ts +196 -77
- package/src/application/shell-sequence.ts +5 -7
- package/src/application/terminals.ts +207 -0
- package/src/application/thread-commands.test.ts +43 -0
- package/src/application/thread-commands.ts +81 -0
- package/src/application/thread-update.ts +72 -0
- package/src/application/thread-wait.ts +46 -47
- package/src/application/threads.test.ts +166 -0
- package/src/application/threads.ts +123 -40
- package/src/bin.ts +2 -0
- package/src/cli/app.ts +14 -0
- package/src/cli/confirm.ts +31 -0
- package/src/cli/error.ts +26 -3
- package/src/cli/flags.ts +15 -0
- package/src/cli/input/layer.ts +20 -0
- package/src/cli/input/service.ts +1 -0
- package/src/cli/output-format.ts +6 -2
- package/src/cli/project-format.ts +7 -0
- package/src/cli/project.ts +2 -1
- package/src/cli/projects/delete.ts +50 -0
- package/src/cli/self-action.ts +34 -0
- package/src/cli/terminal/attach.ts +32 -0
- package/src/cli/terminal/commands.test.ts +101 -0
- package/src/cli/terminal/create.ts +54 -0
- package/src/cli/terminal/destroy.ts +60 -0
- package/src/cli/terminal/encoding.test.ts +63 -0
- package/src/cli/terminal/encoding.ts +23 -0
- package/src/cli/terminal/error.ts +14 -0
- package/src/cli/terminal/io-node-layer.ts +82 -0
- package/src/cli/terminal/io-service.ts +25 -0
- package/src/cli/terminal/list.ts +35 -0
- package/src/cli/terminal/read.ts +102 -0
- package/src/cli/terminal/scope.ts +30 -0
- package/src/cli/terminal/shared.ts +250 -0
- package/src/cli/terminal/stream.ts +64 -0
- package/src/cli/terminal/wait.test.ts +146 -0
- package/src/cli/terminal/wait.ts +222 -0
- package/src/cli/terminal/write.ts +132 -0
- package/src/cli/terminal-format.ts +167 -0
- package/src/cli/terminal.ts +26 -0
- package/src/cli/thread-format.test.ts +32 -0
- package/src/cli/thread-format.ts +8 -1
- package/src/cli/thread.ts +9 -13
- package/src/cli/threads/archive.ts +11 -18
- package/src/cli/threads/delete.ts +61 -0
- package/src/cli/threads/interrupt.ts +52 -0
- package/src/cli/threads/list.test.ts +69 -0
- package/src/cli/threads/list.ts +15 -3
- package/src/cli/threads/messages.ts +3 -3
- package/src/cli/threads/send.ts +22 -2
- package/src/cli/threads/unarchive.ts +44 -0
- package/src/cli/threads/update.ts +150 -0
- package/src/domain/error.ts +20 -1
- package/src/domain/model-config.ts +4 -0
- package/src/domain/thread-lifecycle.test.ts +35 -0
- package/src/domain/thread-lifecycle.ts +29 -6
- package/src/node/index.ts +2 -0
- package/src/orchestration/index.ts +1 -0
- package/src/orchestration/layer.ts +33 -85
- package/src/orchestration/service.ts +4 -0
- package/src/rpc/error.ts +10 -0
- package/src/rpc/index.ts +5 -0
- package/src/rpc/operation.ts +83 -0
- package/src/rpc/ws-group.ts +24 -0
- 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
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
|
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/
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
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
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
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
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
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
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
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/
|
|
4589
|
-
const
|
|
4590
|
-
|
|
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
|
-
}, ({
|
|
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
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
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
|
-
|
|
4603
|
-
|
|
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/
|
|
4608
|
-
const
|
|
5609
|
+
//#region src/cli/threads/interrupt.ts
|
|
5610
|
+
const interruptThreadCommand = make("interrupt", {
|
|
4609
5611
|
thread: threadFlag,
|
|
4610
|
-
|
|
4611
|
-
full: boolean("full"),
|
|
5612
|
+
force: selfActionForceFlag,
|
|
4612
5613
|
format: formatFlag
|
|
4613
|
-
}, ({ thread,
|
|
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
|
|
4628
|
-
if (resolvedFormat === "json") return yield* output.printJson(
|
|
4629
|
-
|
|
4630
|
-
|
|
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 {
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
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$
|
|
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$
|
|
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.
|
|
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 });
|