t3code-cli 0.14.2 → 0.15.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 +36 -1
- package/dist/application.d.ts +2 -2
- package/dist/application.js +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +1 -1
- package/dist/bin.js +935 -336
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/client-runtime/authorization.d.ts +1 -1
- package/dist/client-runtime/authorization.js +1 -1
- package/dist/client-runtime/connection.d.ts +1 -1
- package/dist/client-runtime/connection.js +1 -1
- package/dist/client-runtime/environment.d.ts +3 -1
- package/dist/client-runtime/environment.js +1 -1
- package/dist/client-runtime/errors.js +1 -1
- package/dist/client-runtime/operations/projects.d.ts +1 -1
- package/dist/client-runtime/operations.d.ts +1 -1
- package/dist/client-runtime/platform.d.ts +1 -1
- package/dist/client-runtime/platform.js +1 -1
- package/dist/client-runtime/relay.d.ts +9 -2
- package/dist/client-runtime/relay.js +12 -2
- package/dist/client-runtime/rpc.d.ts +2 -2
- package/dist/client-runtime/rpc.js +2 -2
- package/dist/client-runtime/state/assets.d.ts +1 -1
- package/dist/client-runtime/state/assets.js +1 -1
- package/dist/client-runtime/state/auth.d.ts +1 -1
- package/dist/client-runtime/state/auth.js +1 -1
- package/dist/client-runtime/state/connections.js +1 -1
- package/dist/client-runtime/state/entities.d.ts +1 -1
- package/dist/client-runtime/state/filesystem.d.ts +1 -1
- package/dist/client-runtime/state/filesystem.js +1 -1
- package/dist/client-runtime/state/git.d.ts +2 -1
- package/dist/client-runtime/state/git.js +1 -1
- package/dist/client-runtime/state/models.d.ts +1 -1
- package/dist/client-runtime/state/models.js +1 -1
- package/dist/client-runtime/state/orchestration.d.ts +1 -1
- package/dist/client-runtime/state/orchestration.js +1 -1
- package/dist/client-runtime/state/presentation.d.ts +7 -1
- package/dist/client-runtime/state/presentation.js +1 -1
- package/dist/client-runtime/state/preview.d.ts +5 -2
- package/dist/client-runtime/state/preview.js +3 -2
- package/dist/client-runtime/state/project-grouping.d.ts +1 -1
- package/dist/client-runtime/state/project-grouping.js +1 -1
- package/dist/client-runtime/state/projects.d.ts +1 -1
- package/dist/client-runtime/state/pull-requests.d.ts +478 -0
- package/dist/client-runtime/state/pull-requests.js +172 -0
- package/dist/client-runtime/state/relay.d.ts +1 -1
- package/dist/client-runtime/state/relay.js +1 -1
- package/dist/client-runtime/state/review.d.ts +1 -1
- package/dist/client-runtime/state/review.js +1 -1
- package/dist/client-runtime/state/runtime.d.ts +2 -2
- package/dist/client-runtime/state/runtime.js +2 -2
- package/dist/client-runtime/state/server.d.ts +13 -1
- package/dist/client-runtime/state/server.js +1 -1
- package/dist/client-runtime/state/session.d.ts +13 -1
- package/dist/client-runtime/state/session.js +1 -1
- package/dist/client-runtime/state/shell.d.ts +7 -1
- package/dist/client-runtime/state/shell.js +1 -1
- package/dist/client-runtime/state/source-control.d.ts +1 -1
- package/dist/client-runtime/state/source-control.js +1 -1
- package/dist/client-runtime/state/subagentRuntime.d.ts +1 -1
- package/dist/client-runtime/state/terminal.d.ts +1 -1
- package/dist/client-runtime/state/terminal.js +1 -1
- package/dist/client-runtime/state/thread-search.d.ts +1 -1
- package/dist/client-runtime/state/thread-search.js +1 -1
- package/dist/client-runtime/state/thread-settled.d.ts +11 -8
- package/dist/client-runtime/state/thread-settled.js +2 -229
- package/dist/client-runtime/state/thread-sort.d.ts +1 -1
- package/dist/client-runtime/state/thread-sort.js +1 -1
- package/dist/client-runtime/state/threads.d.ts +1 -1
- package/dist/client-runtime/state/threads.js +1 -1
- package/dist/client-runtime/state/vcs.d.ts +1 -1
- package/dist/client-runtime/state/vcs.js +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connection.d.ts +1 -1
- package/dist/connection.js +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/orchestration.d.ts +12 -6
- package/dist/orchestration.js +2 -2
- package/dist/preview.d.ts +1 -1
- package/dist/rpc.d.ts +4 -9
- package/dist/rpc.js +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/shared/DrainableWorker.js +1 -1
- package/dist/shared/KeyedCoalescingWorker.js +1 -1
- package/dist/shared/Net.d.ts +6 -0
- package/dist/shared/Net.js +2 -1
- package/dist/shared/advertisedEndpoint.d.ts +1 -1
- package/dist/shared/advertisedEndpoint.js +1 -1
- package/dist/shared/agentAwareness.d.ts +1 -1
- package/dist/shared/backgroundActivitySettings.d.ts +1 -1
- package/dist/shared/connectAuth.d.ts +23 -4
- package/dist/shared/connectAuth.js +40 -7
- package/dist/shared/devHome.js +1 -1
- package/dist/shared/dpop.js +1 -1
- package/dist/shared/git.d.ts +1 -1
- package/dist/shared/httpObservability.js +1 -1
- package/dist/shared/httpReadiness.js +1 -1
- package/dist/shared/keybindings.d.ts +1 -1
- package/dist/shared/model.d.ts +1 -1
- package/dist/shared/oauthScope.js +1 -1
- package/dist/shared/observability.js +1 -1
- package/dist/shared/preview.js +1 -1
- package/dist/shared/previewViewport.d.ts +1 -1
- package/dist/shared/previewViewport.js +1 -1
- package/dist/shared/projectScripts.d.ts +1 -1
- package/dist/shared/relayAuth.js +1 -1
- package/dist/shared/relayClient.d.ts +1 -1
- package/dist/shared/relayClient.js +1 -1
- package/dist/shared/relayJwt.js +1 -1
- package/dist/shared/relayTracing.js +1 -1
- package/dist/shared/relayUrl.js +1 -1
- package/dist/shared/remote.js +1 -1
- package/dist/shared/schemaYaml.js +1 -1
- package/dist/shared/serverSettings.d.ts +1 -1
- package/dist/shared/serverSettings.js +1 -1
- package/dist/shared/shell.js +1 -1
- package/dist/shared/sourceControl.d.ts +1 -1
- package/dist/shared/t3ProjectFile.d.ts +1 -1
- package/dist/shared/t3ProjectFile.js +1 -1
- package/dist/shared/terminalLabels.d.ts +1 -1
- package/dist/shared/threadEnvMode.d.ts +1 -1
- package/dist/shared/toolActivity.d.ts +1 -1
- package/dist/shared/usageFormat.d.ts +16 -3
- package/dist/shared/usageFormat.js +92 -6
- package/dist/shared/usageMerge.d.ts +13 -2
- package/dist/shared/usageMerge.js +23 -0
- package/dist/shared.d.ts +3470 -378
- package/dist/shared.js +2434 -617
- package/dist/t3tools.d.ts +2 -2
- package/dist/t3tools.js +2 -2
- package/package.json +2 -2
- package/src/application/error.ts +2 -2
- package/src/application/index.ts +1 -0
- package/src/application/service.ts +38 -4
- package/src/application/thread-commands.ts +78 -0
- package/src/application/threads.ts +113 -16
- package/src/cli/app.ts +2 -0
- package/src/cli/ask-lifecycle.ts +331 -0
- package/src/cli/ask.ts +390 -0
- package/src/cli/error.ts +70 -0
- package/src/cli/format/thread.ts +26 -6
- package/src/cli/thread.ts +12 -0
- package/src/cli/threads/messages.ts +33 -3
- package/src/cli/threads/pin.ts +46 -0
- package/src/cli/threads/send.ts +5 -1
- package/src/cli/threads/settle.ts +46 -0
- package/src/cli/threads/snooze.ts +117 -0
- package/src/cli/threads/start.ts +6 -1
- package/src/cli/threads/unpin.ts +48 -0
- package/src/cli/threads/unsettle.ts +48 -0
- package/src/cli/threads/unsnooze.ts +48 -0
- package/src/connection/prepared.ts +12 -2
- package/src/orchestration/error.ts +10 -0
- package/src/orchestration/index.ts +1 -0
- package/src/orchestration/layer.ts +72 -0
- package/src/orchestration/service.ts +11 -3
- package/src/rpc/ws-group.ts +1 -0
- package/src/runtime/layer.ts +9 -4
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import { Command } from "effect/unstable/cli";
|
|
4
|
+
|
|
5
|
+
import { T3Application } from "../../application/service.ts";
|
|
6
|
+
import { loadT3CliEnv } from "../../config/env/env.ts";
|
|
7
|
+
import { MissingThreadError } from "../error.ts";
|
|
8
|
+
import { extraArgsConfig } from "../extra-args.ts";
|
|
9
|
+
import { formatFlag, threadFlag } from "../flags.ts";
|
|
10
|
+
import { resolveOutputFormat } from "../format/output.ts";
|
|
11
|
+
import { T3Output } from "../output/service.ts";
|
|
12
|
+
import { CliRuntime } from "../runtime/service.ts";
|
|
13
|
+
import { resolveThreadId } from "../scope/index.ts";
|
|
14
|
+
|
|
15
|
+
export const settleThreadCommand = Command.make(
|
|
16
|
+
"settle",
|
|
17
|
+
{
|
|
18
|
+
thread: threadFlag,
|
|
19
|
+
format: formatFlag,
|
|
20
|
+
...extraArgsConfig,
|
|
21
|
+
},
|
|
22
|
+
({ thread, format }) =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
const application = yield* T3Application;
|
|
25
|
+
const cliRuntime = yield* CliRuntime;
|
|
26
|
+
const t3CliEnv = yield* loadT3CliEnv;
|
|
27
|
+
const output = yield* T3Output;
|
|
28
|
+
const threadId = resolveThreadId({
|
|
29
|
+
value: Option.getOrUndefined(thread),
|
|
30
|
+
scope: t3CliEnv.scope,
|
|
31
|
+
});
|
|
32
|
+
if (threadId === undefined) {
|
|
33
|
+
return yield* Effect.fail(
|
|
34
|
+
new MissingThreadError({
|
|
35
|
+
message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
|
|
40
|
+
const dispatch = yield* application.settleThread(threadId);
|
|
41
|
+
if (resolvedFormat === "json") {
|
|
42
|
+
return yield* output.printJson(dispatch);
|
|
43
|
+
}
|
|
44
|
+
return yield* output.printInfo(`thread settled: ${threadId} (sequence ${dispatch.sequence})`);
|
|
45
|
+
}),
|
|
46
|
+
).pipe(Command.withDescription("settle thread"));
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as DateTime from "effect/DateTime";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Option from "effect/Option";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
import {
|
|
7
|
+
resolveSnoozePresets,
|
|
8
|
+
type SnoozePresetId,
|
|
9
|
+
} from "@t3tools/client-runtime/state/thread-settled";
|
|
10
|
+
|
|
11
|
+
import { T3Application } from "../../application/service.ts";
|
|
12
|
+
import { loadT3CliEnv } from "../../config/env/env.ts";
|
|
13
|
+
import {
|
|
14
|
+
InvalidFlagCombinationError,
|
|
15
|
+
InvalidSnoozeUntilError,
|
|
16
|
+
MissingThreadError,
|
|
17
|
+
UnavailableSnoozePresetError,
|
|
18
|
+
} from "../error.ts";
|
|
19
|
+
import { extraArgsConfig } from "../extra-args.ts";
|
|
20
|
+
import { formatFlag, threadFlag } from "../flags.ts";
|
|
21
|
+
import { resolveOutputFormat } from "../format/output.ts";
|
|
22
|
+
import { T3Output } from "../output/service.ts";
|
|
23
|
+
import { CliRuntime } from "../runtime/service.ts";
|
|
24
|
+
import { resolveThreadId } from "../scope/index.ts";
|
|
25
|
+
|
|
26
|
+
const snoozePresetChoices = [
|
|
27
|
+
"hour",
|
|
28
|
+
"evening",
|
|
29
|
+
"tomorrow",
|
|
30
|
+
"next-week",
|
|
31
|
+
] as const satisfies ReadonlyArray<SnoozePresetId>;
|
|
32
|
+
|
|
33
|
+
export const snoozeThreadCommand = Command.make(
|
|
34
|
+
"snooze",
|
|
35
|
+
{
|
|
36
|
+
thread: threadFlag,
|
|
37
|
+
until: Flag.string("until").pipe(Flag.optional),
|
|
38
|
+
preset: Flag.choice("preset", snoozePresetChoices).pipe(Flag.optional),
|
|
39
|
+
format: formatFlag,
|
|
40
|
+
...extraArgsConfig,
|
|
41
|
+
},
|
|
42
|
+
({ thread, until, preset, format }) =>
|
|
43
|
+
Effect.gen(function* () {
|
|
44
|
+
const application = yield* T3Application;
|
|
45
|
+
const cliRuntime = yield* CliRuntime;
|
|
46
|
+
const t3CliEnv = yield* loadT3CliEnv;
|
|
47
|
+
const output = yield* T3Output;
|
|
48
|
+
const threadId = resolveThreadId({
|
|
49
|
+
value: Option.getOrUndefined(thread),
|
|
50
|
+
scope: t3CliEnv.scope,
|
|
51
|
+
});
|
|
52
|
+
if (threadId === undefined) {
|
|
53
|
+
return yield* Effect.fail(
|
|
54
|
+
new MissingThreadError({
|
|
55
|
+
message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const untilValue = Option.getOrUndefined(until);
|
|
61
|
+
const presetValue = Option.getOrUndefined(preset);
|
|
62
|
+
if (untilValue !== undefined && presetValue !== undefined) {
|
|
63
|
+
return yield* Effect.fail(
|
|
64
|
+
new InvalidFlagCombinationError({
|
|
65
|
+
message: "exactly one of --until or --preset is required",
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let snoozedUntil: string;
|
|
71
|
+
if (untilValue !== undefined) {
|
|
72
|
+
snoozedUntil = yield* Schema.decodeUnknownEffect(Schema.DateTimeUtcFromString)(
|
|
73
|
+
untilValue,
|
|
74
|
+
).pipe(
|
|
75
|
+
Effect.map(DateTime.formatIso),
|
|
76
|
+
Effect.mapError(
|
|
77
|
+
() =>
|
|
78
|
+
new InvalidSnoozeUntilError({
|
|
79
|
+
message: `invalid ISO-8601 snooze time: ${untilValue}`,
|
|
80
|
+
value: untilValue,
|
|
81
|
+
}),
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
} else if (presetValue !== undefined) {
|
|
85
|
+
snoozedUntil = yield* resolveSnoozePreset(presetValue);
|
|
86
|
+
} else {
|
|
87
|
+
return yield* Effect.fail(
|
|
88
|
+
new InvalidFlagCombinationError({
|
|
89
|
+
message: "exactly one of --until or --preset is required",
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
|
|
95
|
+
const dispatch = yield* application.snoozeThread({ threadId, snoozedUntil });
|
|
96
|
+
if (resolvedFormat === "json") {
|
|
97
|
+
return yield* output.printJson(dispatch);
|
|
98
|
+
}
|
|
99
|
+
return yield* output.printInfo(
|
|
100
|
+
`thread snoozed: ${threadId} until ${snoozedUntil} (sequence ${dispatch.sequence})`,
|
|
101
|
+
);
|
|
102
|
+
}),
|
|
103
|
+
).pipe(Command.withDescription("snooze thread"));
|
|
104
|
+
|
|
105
|
+
const resolveSnoozePreset = Effect.fn("resolveSnoozePreset")(function* (presetId: SnoozePresetId) {
|
|
106
|
+
const now = yield* DateTime.nowAsDate;
|
|
107
|
+
const preset = resolveSnoozePresets(now).find((candidate) => candidate.id === presetId);
|
|
108
|
+
if (preset === undefined) {
|
|
109
|
+
return yield* Effect.fail(
|
|
110
|
+
new UnavailableSnoozePresetError({
|
|
111
|
+
message: `snooze preset is not available at this time: ${presetId}`,
|
|
112
|
+
preset: presetId,
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return preset.snoozedUntil;
|
|
117
|
+
});
|
package/src/cli/threads/start.ts
CHANGED
|
@@ -129,7 +129,12 @@ export const startThreadCommand = Command.make(
|
|
|
129
129
|
|
|
130
130
|
const result = yield* application.startThread(input, { until: "visible" });
|
|
131
131
|
if (resolvedFormat === "json") {
|
|
132
|
-
yield* output.printJson(
|
|
132
|
+
yield* output.printJson({
|
|
133
|
+
dispatch: result.dispatch,
|
|
134
|
+
project: result.project,
|
|
135
|
+
threadId: result.threadId,
|
|
136
|
+
thread: result.thread,
|
|
137
|
+
});
|
|
133
138
|
} else {
|
|
134
139
|
yield* output.printInfo(
|
|
135
140
|
formatThreadStartedHuman({
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import { Command } from "effect/unstable/cli";
|
|
4
|
+
|
|
5
|
+
import { T3Application } from "../../application/service.ts";
|
|
6
|
+
import { loadT3CliEnv } from "../../config/env/env.ts";
|
|
7
|
+
import { MissingThreadError } from "../error.ts";
|
|
8
|
+
import { extraArgsConfig } from "../extra-args.ts";
|
|
9
|
+
import { formatFlag, threadFlag } from "../flags.ts";
|
|
10
|
+
import { resolveOutputFormat } from "../format/output.ts";
|
|
11
|
+
import { T3Output } from "../output/service.ts";
|
|
12
|
+
import { CliRuntime } from "../runtime/service.ts";
|
|
13
|
+
import { resolveThreadId } from "../scope/index.ts";
|
|
14
|
+
|
|
15
|
+
export const unpinThreadCommand = Command.make(
|
|
16
|
+
"unpin",
|
|
17
|
+
{
|
|
18
|
+
thread: threadFlag,
|
|
19
|
+
format: formatFlag,
|
|
20
|
+
...extraArgsConfig,
|
|
21
|
+
},
|
|
22
|
+
({ thread, format }) =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
const application = yield* T3Application;
|
|
25
|
+
const cliRuntime = yield* CliRuntime;
|
|
26
|
+
const t3CliEnv = yield* loadT3CliEnv;
|
|
27
|
+
const output = yield* T3Output;
|
|
28
|
+
const threadId = resolveThreadId({
|
|
29
|
+
value: Option.getOrUndefined(thread),
|
|
30
|
+
scope: t3CliEnv.scope,
|
|
31
|
+
});
|
|
32
|
+
if (threadId === undefined) {
|
|
33
|
+
return yield* Effect.fail(
|
|
34
|
+
new MissingThreadError({
|
|
35
|
+
message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
|
|
40
|
+
const dispatch = yield* application.unpinThread(threadId);
|
|
41
|
+
if (resolvedFormat === "json") {
|
|
42
|
+
return yield* output.printJson(dispatch);
|
|
43
|
+
}
|
|
44
|
+
return yield* output.printInfo(
|
|
45
|
+
`thread unpinned: ${threadId} (sequence ${dispatch.sequence})`,
|
|
46
|
+
);
|
|
47
|
+
}),
|
|
48
|
+
).pipe(Command.withDescription("unpin thread"));
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import { Command } from "effect/unstable/cli";
|
|
4
|
+
|
|
5
|
+
import { T3Application } from "../../application/service.ts";
|
|
6
|
+
import { loadT3CliEnv } from "../../config/env/env.ts";
|
|
7
|
+
import { MissingThreadError } from "../error.ts";
|
|
8
|
+
import { extraArgsConfig } from "../extra-args.ts";
|
|
9
|
+
import { formatFlag, threadFlag } from "../flags.ts";
|
|
10
|
+
import { resolveOutputFormat } from "../format/output.ts";
|
|
11
|
+
import { T3Output } from "../output/service.ts";
|
|
12
|
+
import { CliRuntime } from "../runtime/service.ts";
|
|
13
|
+
import { resolveThreadId } from "../scope/index.ts";
|
|
14
|
+
|
|
15
|
+
export const unsettleThreadCommand = Command.make(
|
|
16
|
+
"unsettle",
|
|
17
|
+
{
|
|
18
|
+
thread: threadFlag,
|
|
19
|
+
format: formatFlag,
|
|
20
|
+
...extraArgsConfig,
|
|
21
|
+
},
|
|
22
|
+
({ thread, format }) =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
const application = yield* T3Application;
|
|
25
|
+
const cliRuntime = yield* CliRuntime;
|
|
26
|
+
const t3CliEnv = yield* loadT3CliEnv;
|
|
27
|
+
const output = yield* T3Output;
|
|
28
|
+
const threadId = resolveThreadId({
|
|
29
|
+
value: Option.getOrUndefined(thread),
|
|
30
|
+
scope: t3CliEnv.scope,
|
|
31
|
+
});
|
|
32
|
+
if (threadId === undefined) {
|
|
33
|
+
return yield* Effect.fail(
|
|
34
|
+
new MissingThreadError({
|
|
35
|
+
message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
|
|
40
|
+
const dispatch = yield* application.unsettleThread(threadId);
|
|
41
|
+
if (resolvedFormat === "json") {
|
|
42
|
+
return yield* output.printJson(dispatch);
|
|
43
|
+
}
|
|
44
|
+
return yield* output.printInfo(
|
|
45
|
+
`thread unsettled: ${threadId} (sequence ${dispatch.sequence})`,
|
|
46
|
+
);
|
|
47
|
+
}),
|
|
48
|
+
).pipe(Command.withDescription("unsettle thread"));
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import { Command } from "effect/unstable/cli";
|
|
4
|
+
|
|
5
|
+
import { T3Application } from "../../application/service.ts";
|
|
6
|
+
import { loadT3CliEnv } from "../../config/env/env.ts";
|
|
7
|
+
import { MissingThreadError } from "../error.ts";
|
|
8
|
+
import { extraArgsConfig } from "../extra-args.ts";
|
|
9
|
+
import { formatFlag, threadFlag } from "../flags.ts";
|
|
10
|
+
import { resolveOutputFormat } from "../format/output.ts";
|
|
11
|
+
import { T3Output } from "../output/service.ts";
|
|
12
|
+
import { CliRuntime } from "../runtime/service.ts";
|
|
13
|
+
import { resolveThreadId } from "../scope/index.ts";
|
|
14
|
+
|
|
15
|
+
export const unsnoozeThreadCommand = Command.make(
|
|
16
|
+
"unsnooze",
|
|
17
|
+
{
|
|
18
|
+
thread: threadFlag,
|
|
19
|
+
format: formatFlag,
|
|
20
|
+
...extraArgsConfig,
|
|
21
|
+
},
|
|
22
|
+
({ thread, format }) =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
const application = yield* T3Application;
|
|
25
|
+
const cliRuntime = yield* CliRuntime;
|
|
26
|
+
const t3CliEnv = yield* loadT3CliEnv;
|
|
27
|
+
const output = yield* T3Output;
|
|
28
|
+
const threadId = resolveThreadId({
|
|
29
|
+
value: Option.getOrUndefined(thread),
|
|
30
|
+
scope: t3CliEnv.scope,
|
|
31
|
+
});
|
|
32
|
+
if (threadId === undefined) {
|
|
33
|
+
return yield* Effect.fail(
|
|
34
|
+
new MissingThreadError({
|
|
35
|
+
message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
|
|
40
|
+
const dispatch = yield* application.unsnoozeThread(threadId);
|
|
41
|
+
if (resolvedFormat === "json") {
|
|
42
|
+
return yield* output.printJson(dispatch);
|
|
43
|
+
}
|
|
44
|
+
return yield* output.printInfo(
|
|
45
|
+
`thread unsnoozed: ${threadId} (sequence ${dispatch.sequence})`,
|
|
46
|
+
);
|
|
47
|
+
}),
|
|
48
|
+
).pipe(Command.withDescription("unsnooze thread"));
|
|
@@ -16,10 +16,20 @@ import { T3CodeConnectionError } from "./error.ts";
|
|
|
16
16
|
import { T3CodeConnectionProvider } from "./service.ts";
|
|
17
17
|
import type { T3CodeConnection } from "./type.ts";
|
|
18
18
|
|
|
19
|
+
export interface T3PreparedConnection extends PreparedConnection {
|
|
20
|
+
readonly httpAuthorization: {
|
|
21
|
+
readonly _tag: "Bearer";
|
|
22
|
+
readonly token: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
export class T3PreparedConnectionProvider extends Context.Service<
|
|
20
27
|
T3PreparedConnectionProvider,
|
|
21
28
|
{
|
|
22
|
-
readonly get: Effect.Effect<
|
|
29
|
+
readonly get: Effect.Effect<
|
|
30
|
+
T3PreparedConnection,
|
|
31
|
+
ConnectionAttemptError | T3CodeConnectionError
|
|
32
|
+
>;
|
|
23
33
|
}
|
|
24
34
|
>()("t3cli/T3PreparedConnectionProvider") {}
|
|
25
35
|
|
|
@@ -59,7 +69,7 @@ const makePreparedConnection = Effect.fn("makePreparedConnection")(function* (
|
|
|
59
69
|
label: descriptor.label,
|
|
60
70
|
connectionId: descriptor.environmentId,
|
|
61
71
|
}),
|
|
62
|
-
} satisfies
|
|
72
|
+
} satisfies T3PreparedConnection;
|
|
63
73
|
});
|
|
64
74
|
|
|
65
75
|
const makeT3PreparedConnectionProvider = Effect.fn("makeT3PreparedConnectionProvider")(
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
|
|
3
|
+
export class ThreadSnapshotRequestError extends Schema.TaggedErrorClass<ThreadSnapshotRequestError>()(
|
|
4
|
+
"ThreadSnapshotRequestError",
|
|
5
|
+
{
|
|
6
|
+
message: Schema.String,
|
|
7
|
+
threadId: Schema.String,
|
|
8
|
+
cause: Schema.Defect(),
|
|
9
|
+
},
|
|
10
|
+
) {}
|
|
@@ -3,6 +3,7 @@ import * as Layer from "effect/Layer";
|
|
|
3
3
|
import * as Option from "effect/Option";
|
|
4
4
|
import * as Sink from "effect/Sink";
|
|
5
5
|
import * as Stream from "effect/Stream";
|
|
6
|
+
import { HttpClient } from "effect/unstable/http";
|
|
6
7
|
import {
|
|
7
8
|
ORCHESTRATION_WS_METHODS,
|
|
8
9
|
ThreadId,
|
|
@@ -12,14 +13,25 @@ import {
|
|
|
12
13
|
type OrchestrationShellStreamItem,
|
|
13
14
|
type OrchestrationThreadStreamItem,
|
|
14
15
|
} from "@t3tools/contracts";
|
|
16
|
+
import { environmentEndpointUrl } from "@t3tools/client-runtime/environment";
|
|
17
|
+
import {
|
|
18
|
+
executeEnvironmentHttpRequest,
|
|
19
|
+
makeEnvironmentHttpApiClient,
|
|
20
|
+
} from "@t3tools/client-runtime/rpc";
|
|
15
21
|
import { applyShellStreamEvent } from "@t3tools/client-runtime/state/shell";
|
|
16
22
|
|
|
23
|
+
import { T3PreparedConnectionProvider } from "../connection/prepared.ts";
|
|
17
24
|
import { RpcError } from "../rpc/error.ts";
|
|
18
25
|
import { T3RpcOperations } from "../rpc/operation.ts";
|
|
26
|
+
import { ThreadSnapshotRequestError } from "./error.ts";
|
|
19
27
|
import { T3Orchestration, type OpenThread, type Orchestration } from "./service.ts";
|
|
20
28
|
|
|
29
|
+
const THREAD_SNAPSHOT_TIMEOUT_MS = 30_000;
|
|
30
|
+
|
|
21
31
|
export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* () {
|
|
22
32
|
const rpc = yield* T3RpcOperations;
|
|
33
|
+
const preparedConnectionProvider = yield* T3PreparedConnectionProvider;
|
|
34
|
+
const httpClient = yield* HttpClient.HttpClient;
|
|
23
35
|
|
|
24
36
|
const watchShellSnapshots: Orchestration["watchShellSnapshots"] = () =>
|
|
25
37
|
rpc
|
|
@@ -133,6 +145,65 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
133
145
|
}
|
|
134
146
|
return value.snapshot.thread;
|
|
135
147
|
});
|
|
148
|
+
const getThreadDetailSnapshot: Orchestration["getThreadDetailSnapshot"] = Effect.fn(
|
|
149
|
+
"T3OrchestrationLive.getThreadDetailSnapshot",
|
|
150
|
+
)(function* (input) {
|
|
151
|
+
const paginationSupported =
|
|
152
|
+
input.window === undefined
|
|
153
|
+
? true
|
|
154
|
+
: (yield* getServerConfig()).threadSnapshotPagination === true;
|
|
155
|
+
const window = paginationSupported ? input.window : undefined;
|
|
156
|
+
const prepared = yield* preparedConnectionProvider.get.pipe(
|
|
157
|
+
Effect.mapError(
|
|
158
|
+
(cause) =>
|
|
159
|
+
new ThreadSnapshotRequestError({
|
|
160
|
+
message: "failed to prepare the thread snapshot request",
|
|
161
|
+
threadId: input.threadId,
|
|
162
|
+
cause,
|
|
163
|
+
}),
|
|
164
|
+
),
|
|
165
|
+
);
|
|
166
|
+
const threadId = ThreadId.make(input.threadId);
|
|
167
|
+
const requestUrl = environmentEndpointUrl(
|
|
168
|
+
prepared.httpBaseUrl,
|
|
169
|
+
`/api/orchestration/threads/${threadId}`,
|
|
170
|
+
);
|
|
171
|
+
const client = yield* makeEnvironmentHttpApiClient(prepared.httpBaseUrl).pipe(
|
|
172
|
+
Effect.provideService(HttpClient.HttpClient, httpClient),
|
|
173
|
+
Effect.mapError(
|
|
174
|
+
(cause) =>
|
|
175
|
+
new ThreadSnapshotRequestError({
|
|
176
|
+
message: "failed to create the thread snapshot client",
|
|
177
|
+
threadId: input.threadId,
|
|
178
|
+
cause,
|
|
179
|
+
}),
|
|
180
|
+
),
|
|
181
|
+
);
|
|
182
|
+
return yield* executeEnvironmentHttpRequest(
|
|
183
|
+
requestUrl,
|
|
184
|
+
THREAD_SNAPSHOT_TIMEOUT_MS,
|
|
185
|
+
client.orchestration.threadSnapshot({
|
|
186
|
+
params: { threadId },
|
|
187
|
+
payload: {
|
|
188
|
+
...(window !== undefined ? { turnLimit: window.turnLimit } : {}),
|
|
189
|
+
...(window?.beforeCursor !== undefined ? { beforeCursor: window.beforeCursor } : {}),
|
|
190
|
+
},
|
|
191
|
+
headers: {
|
|
192
|
+
authorization: `Bearer ${prepared.httpAuthorization.token}`,
|
|
193
|
+
},
|
|
194
|
+
}),
|
|
195
|
+
).pipe(
|
|
196
|
+
Effect.provideService(HttpClient.HttpClient, httpClient),
|
|
197
|
+
Effect.mapError(
|
|
198
|
+
(cause) =>
|
|
199
|
+
new ThreadSnapshotRequestError({
|
|
200
|
+
message: "failed to load the thread snapshot",
|
|
201
|
+
threadId: input.threadId,
|
|
202
|
+
cause,
|
|
203
|
+
}),
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
});
|
|
136
207
|
const openThread = Effect.fn("T3OrchestrationLive.openThread")(function* (threadId: string) {
|
|
137
208
|
return yield* watchThreadItems(threadId).pipe(
|
|
138
209
|
Stream.peel(Sink.head<OrchestrationThreadStreamItem>()),
|
|
@@ -167,6 +238,7 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
167
238
|
getArchivedShellSnapshot,
|
|
168
239
|
searchThreads,
|
|
169
240
|
getThreadSnapshot,
|
|
241
|
+
getThreadDetailSnapshot,
|
|
170
242
|
watchShellSnapshots,
|
|
171
243
|
watchShellSequence,
|
|
172
244
|
watchThreadItems,
|
|
@@ -10,22 +10,26 @@ import type {
|
|
|
10
10
|
OrchestrationSearchThreadsInput,
|
|
11
11
|
OrchestrationSearchThreadsResult,
|
|
12
12
|
OrchestrationThread,
|
|
13
|
+
OrchestrationThreadDetailSnapshot,
|
|
14
|
+
OrchestrationThreadDetailWindow,
|
|
13
15
|
OrchestrationThreadStreamItem,
|
|
14
16
|
ServerProviders,
|
|
15
17
|
} from "@t3tools/contracts";
|
|
16
18
|
|
|
19
|
+
import type { ThreadSnapshotRequestError } from "./error.ts";
|
|
17
20
|
import type { RpcError } from "../rpc/error.ts";
|
|
18
21
|
|
|
19
|
-
export type OrchestrationError = RpcError;
|
|
22
|
+
export type OrchestrationError = RpcError | ThreadSnapshotRequestError;
|
|
20
23
|
|
|
21
24
|
export type OpenThread = {
|
|
22
25
|
readonly snapshot: OrchestrationThread;
|
|
23
26
|
readonly events: Stream.Stream<OrchestrationEvent, OrchestrationError>;
|
|
24
27
|
};
|
|
25
28
|
|
|
26
|
-
export
|
|
29
|
+
export interface ServerConfigForCli {
|
|
27
30
|
readonly providers: ServerProviders;
|
|
28
|
-
|
|
31
|
+
readonly threadSnapshotPagination?: boolean;
|
|
32
|
+
}
|
|
29
33
|
|
|
30
34
|
export type Orchestration = {
|
|
31
35
|
readonly dispatch: (
|
|
@@ -43,6 +47,10 @@ export type Orchestration = {
|
|
|
43
47
|
readonly getThreadSnapshot: (
|
|
44
48
|
threadId: string,
|
|
45
49
|
) => Effect.Effect<OrchestrationThread, OrchestrationError>;
|
|
50
|
+
readonly getThreadDetailSnapshot: (input: {
|
|
51
|
+
readonly threadId: string;
|
|
52
|
+
readonly window?: OrchestrationThreadDetailWindow;
|
|
53
|
+
}) => Effect.Effect<OrchestrationThreadDetailSnapshot, OrchestrationError>;
|
|
46
54
|
readonly watchShellSnapshots: () => Stream.Stream<
|
|
47
55
|
OrchestrationShellSnapshot,
|
|
48
56
|
OrchestrationError,
|
package/src/rpc/ws-group.ts
CHANGED
package/src/runtime/layer.ts
CHANGED
|
@@ -63,18 +63,23 @@ const T3ConfigConnectionProviderLayer = Layer.effect(
|
|
|
63
63
|
}),
|
|
64
64
|
).pipe(Layer.provide(T3ConfigLayer));
|
|
65
65
|
|
|
66
|
+
const T3PreparedConnectionLayer = T3PreparedConnectionProviderLive.pipe(
|
|
67
|
+
Layer.provide(Layer.mergeAll(T3ConfigConnectionProviderLayer, NodeHttpClient.layerUndici)),
|
|
68
|
+
);
|
|
66
69
|
const T3RpcLayer = T3RpcLive.pipe(
|
|
67
70
|
Layer.provide(
|
|
68
71
|
Layer.mergeAll(
|
|
69
|
-
|
|
70
|
-
Layer.provide(Layer.mergeAll(T3ConfigConnectionProviderLayer, NodeHttpClient.layerUndici)),
|
|
71
|
-
),
|
|
72
|
+
T3PreparedConnectionLayer,
|
|
72
73
|
T3RpcSessionFactoryLive.pipe(Layer.provide(NodeSocket.layerWebSocketConstructor)),
|
|
73
74
|
),
|
|
74
75
|
),
|
|
75
76
|
);
|
|
76
77
|
const T3RpcOperationsLayer = T3RpcOperationsLive.pipe(Layer.provide(T3RpcLayer));
|
|
77
|
-
export const T3OrchestrationLayer = T3OrchestrationLive.pipe(
|
|
78
|
+
export const T3OrchestrationLayer = T3OrchestrationLive.pipe(
|
|
79
|
+
Layer.provide(
|
|
80
|
+
Layer.mergeAll(T3RpcOperationsLayer, T3PreparedConnectionLayer, NodeHttpClient.layerUndici),
|
|
81
|
+
),
|
|
82
|
+
);
|
|
78
83
|
export const T3PreviewAutomationLayer = T3PreviewAutomationLive.pipe(
|
|
79
84
|
Layer.provide(T3RpcOperationsLayer),
|
|
80
85
|
);
|