t3code-cli 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +41 -16
  2. package/dist/Context-DueQ9iMH.js +4916 -0
  3. package/dist/Path-D8WPdPwR.js +11406 -0
  4. package/dist/Schema-DsQxYh6_.js +13581 -0
  5. package/dist/UrlParams-BA6gBvaY.js +205 -0
  6. package/dist/application.js +2 -0
  7. package/dist/auth.js +3 -0
  8. package/dist/base-dir-R12OMDso.js +20 -0
  9. package/dist/bin.js +236 -13526
  10. package/dist/chunk-B5meny8j.js +36 -0
  11. package/dist/cli.js +2 -0
  12. package/dist/config.js +4 -0
  13. package/dist/connection.js +15 -0
  14. package/dist/contracts.js +1 -0
  15. package/dist/error-B2t1bAP9.js +169 -0
  16. package/dist/error-BHRnjLux.js +15 -0
  17. package/dist/error-jwMt3VoW.js +54 -0
  18. package/dist/flags-CM7_iGdA.js +13371 -0
  19. package/dist/index.js +5 -12
  20. package/dist/layer-CfC5qZol.js +1508 -0
  21. package/dist/layer-DHhKS5jd.js +13 -0
  22. package/dist/layer-DIg0RxSO.js +1217 -0
  23. package/dist/layer-DUv99vsS.js +72 -0
  24. package/dist/layer-DvHnKBYj.js +29466 -0
  25. package/dist/layout.js +2 -0
  26. package/dist/orchestration.js +2 -0
  27. package/dist/rpc.js +2 -0
  28. package/dist/runtime.js +3 -0
  29. package/dist/scope-GycYiJ54.js +29 -0
  30. package/dist/scope.js +2 -0
  31. package/dist/service-CLmRO2Dp.js +8 -0
  32. package/dist/service-ybOWV9pL.js +5 -0
  33. package/dist/src/application/index.d.ts +3 -0
  34. package/dist/src/application/layer.d.ts +4 -4
  35. package/dist/src/application/projects.d.ts +1 -1
  36. package/dist/src/application/service.d.ts +1 -1
  37. package/dist/src/application/threads.d.ts +4 -4
  38. package/dist/src/auth/index.d.ts +10 -0
  39. package/dist/src/auth/local-base-dir.d.ts +5 -7
  40. package/dist/src/auth/local-token.d.ts +2 -2
  41. package/dist/src/auth/type.d.ts +1 -0
  42. package/dist/src/cli/flags.d.ts +15 -0
  43. package/dist/src/cli/index.d.ts +1 -0
  44. package/dist/src/cli/output-format.d.ts +9 -0
  45. package/dist/src/config/index.d.ts +5 -0
  46. package/dist/src/config/layer.d.ts +2 -0
  47. package/dist/src/config/service.d.ts +2 -0
  48. package/dist/src/connection/index.d.ts +5 -0
  49. package/dist/src/contracts/index.d.ts +1 -0
  50. package/dist/src/domain/helpers.d.ts +164 -32
  51. package/dist/src/index.d.ts +4 -28
  52. package/dist/src/layout/base-dir.d.ts +12 -0
  53. package/dist/src/layout/index.d.ts +1 -0
  54. package/dist/src/orchestration/index.d.ts +2 -0
  55. package/dist/src/rpc/index.d.ts +1 -0
  56. package/dist/src/runtime/index.d.ts +2 -0
  57. package/dist/src/runtime/layer.d.ts +11 -0
  58. package/dist/src/scope/index.d.ts +1 -0
  59. package/dist/src/scope/resolve.d.ts +19 -0
  60. package/dist/src/t3tools/index.d.ts +1 -0
  61. package/dist/src-KdbHqrex.js +8874 -0
  62. package/dist/t3tools.js +2 -0
  63. package/dist/transport-D3zBdZ1h.js +539 -0
  64. package/dist/url-SlsaG8nY.js +165 -0
  65. package/package.json +50 -1
  66. package/src/application/index.ts +3 -0
  67. package/src/application/service.ts +1 -1
  68. package/src/application/threads.ts +40 -11
  69. package/src/auth/index.ts +28 -0
  70. package/src/auth/layer.ts +13 -6
  71. package/src/auth/local-base-dir.ts +15 -19
  72. package/src/auth/local-origin.ts +4 -1
  73. package/src/auth/local-token.ts +4 -1
  74. package/src/auth/type.ts +1 -0
  75. package/src/bin.ts +1 -1
  76. package/src/cli/app.ts +6 -6
  77. package/src/cli/auth-format.ts +2 -0
  78. package/src/cli/auth.ts +19 -9
  79. package/src/cli/error.ts +7 -0
  80. package/src/cli/flags.ts +51 -0
  81. package/src/cli/index.ts +10 -0
  82. package/src/cli/{models.ts → model.ts} +5 -4
  83. package/src/cli/{projects.ts → project.ts} +8 -7
  84. package/src/cli/require.ts +31 -0
  85. package/src/cli/{threads.ts → thread.ts} +2 -2
  86. package/src/cli/threads/archive.ts +24 -8
  87. package/src/cli/threads/list.ts +12 -5
  88. package/src/cli/threads/messages.ts +20 -5
  89. package/src/cli/threads/send.ts +27 -23
  90. package/src/cli/threads/start.ts +22 -21
  91. package/src/cli/threads/wait.ts +22 -12
  92. package/src/config/index.ts +5 -0
  93. package/src/config/layer.ts +2 -0
  94. package/src/config/service.ts +2 -0
  95. package/src/connection/index.ts +9 -0
  96. package/src/contracts/index.ts +8 -0
  97. package/src/domain/helpers.ts +136 -16
  98. package/src/index.ts +4 -87
  99. package/src/layout/base-dir.ts +35 -0
  100. package/src/layout/index.ts +1 -0
  101. package/src/orchestration/index.ts +7 -0
  102. package/src/rpc/index.ts +1 -0
  103. package/src/runtime/index.ts +12 -0
  104. package/src/{runtime.ts → runtime/layer.ts} +15 -15
  105. package/src/scope/index.ts +6 -0
  106. package/src/scope/resolve.ts +62 -0
  107. package/src/t3tools/index.ts +1 -0
  108. package/dist/runtime-KQVRmRk-.js +0 -71499
  109. package/dist/src/connection.d.ts +0 -5
  110. package/dist/src/runtime.d.ts +0 -10
  111. package/src/connection.ts +0 -9
@@ -0,0 +1,10 @@
1
+ export {
2
+ formatFlag,
3
+ modelFlags,
4
+ projectFlag,
5
+ projectPathFlag,
6
+ threadFlag,
7
+ threadFormatFlag,
8
+ waitFormatFlag,
9
+ worktreeFlag,
10
+ } from "./flags.ts";
@@ -2,14 +2,15 @@ import * as Effect from "effect/Effect";
2
2
  import * as Option from "effect/Option";
3
3
  import { Command, Flag } from "effect/unstable/cli";
4
4
 
5
+ import { formatFlag } from "./flags.ts";
5
6
  import { T3Application } from "../application/service.ts";
6
7
  import { Environment } from "../environment/service.ts";
7
8
  import { formatModelsHuman } from "./model-format.ts";
8
- import { humanJsonFormatChoices, resolveOutputFormat } from "./output-format.ts";
9
+ import { resolveOutputFormat } from "./output-format.ts";
9
10
  import { T3Output } from "./output/service.ts";
10
11
 
11
- export function createModelsCommand() {
12
- return Command.make("models").pipe(
12
+ export function createModelCommand() {
13
+ return Command.make("model").pipe(
13
14
  Command.withDescription("model commands"),
14
15
  Command.withSubcommands([listCommand]),
15
16
  );
@@ -20,7 +21,7 @@ const listCommand = Command.make(
20
21
  {
21
22
  all: Flag.boolean("all"),
22
23
  provider: Flag.string("provider").pipe(Flag.optional),
23
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
24
+ format: formatFlag,
24
25
  },
25
26
  ({ all, provider, format }) =>
26
27
  Effect.gen(function* () {
@@ -1,15 +1,16 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import * as Option from "effect/Option";
3
- import { Argument, Command, Flag } from "effect/unstable/cli";
3
+ import { Command, Flag } from "effect/unstable/cli";
4
4
 
5
+ import { formatFlag, projectPathFlag } from "./flags.ts";
5
6
  import { formatProjectAddedHuman, formatProjectsHuman } from "./project-format.ts";
6
7
  import { T3Application } from "../application/service.ts";
7
8
  import { Environment } from "../environment/service.ts";
8
- import { humanJsonFormatChoices, resolveOutputFormat } from "./output-format.ts";
9
+ import { resolveOutputFormat } from "./output-format.ts";
9
10
  import { T3Output } from "./output/service.ts";
10
11
 
11
- export function createProjectsCommand() {
12
- return Command.make("projects").pipe(
12
+ export function createProjectCommand() {
13
+ return Command.make("project").pipe(
13
14
  Command.withDescription("project commands"),
14
15
  Command.withSubcommands([listCommand, addCommand]),
15
16
  );
@@ -18,7 +19,7 @@ export function createProjectsCommand() {
18
19
  const listCommand = Command.make(
19
20
  "list",
20
21
  {
21
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
22
+ format: formatFlag,
22
23
  },
23
24
  ({ format }) =>
24
25
  Effect.gen(function* () {
@@ -38,9 +39,9 @@ const listCommand = Command.make(
38
39
  const addCommand = Command.make(
39
40
  "add",
40
41
  {
41
- path: Argument.string("path"),
42
+ path: projectPathFlag,
42
43
  title: Flag.string("title").pipe(Flag.optional),
43
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
44
+ format: formatFlag,
44
45
  },
45
46
  ({ path, title, format }) =>
46
47
  Effect.gen(function* () {
@@ -0,0 +1,31 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Option from "effect/Option";
3
+
4
+ import { T3Config } from "../config/service.ts";
5
+ import { ProjectLookupError } from "../domain/error.ts";
6
+ import { resolveCommandProjectRef } from "../scope/index.ts";
7
+
8
+ export const requireCommandProjectRef = Effect.fn("requireCommandProjectRef")(function* (input: {
9
+ readonly project: Option.Option<string>;
10
+ readonly env: Readonly<Record<string, string | undefined>>;
11
+ readonly cwd: string;
12
+ }) {
13
+ const config = yield* T3Config;
14
+ const resolved = yield* config.resolve();
15
+ const ref = resolveCommandProjectRef({
16
+ value: Option.getOrUndefined(input.project),
17
+ env: input.env,
18
+ cwd: input.cwd,
19
+ isLocal: resolved.local,
20
+ });
21
+ if (ref === undefined) {
22
+ return yield* Effect.fail(
23
+ new ProjectLookupError({
24
+ message:
25
+ "project is required: pass --project, set T3CODE_PROJECT_ROOT / T3CODE_PROJECT_ID, or use local auth",
26
+ ref: input.cwd,
27
+ }),
28
+ );
29
+ }
30
+ return ref;
31
+ });
@@ -7,8 +7,8 @@ import { sendThreadCommand } from "./threads/send.ts";
7
7
  import { startThreadCommand } from "./threads/start.ts";
8
8
  import { waitForThreadCommand } from "./threads/wait.ts";
9
9
 
10
- export function createThreadsCommand() {
11
- return Command.make("threads").pipe(
10
+ export function createThreadCommand() {
11
+ return Command.make("thread").pipe(
12
12
  Command.withDescription("thread commands"),
13
13
  Command.withSubcommands([
14
14
  listThreadsCommand,
@@ -1,28 +1,44 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { Argument, Command, Flag } from "effect/unstable/cli";
2
+ import * as Option from "effect/Option";
3
+ import { Command } from "effect/unstable/cli";
3
4
 
5
+ import { formatFlag, threadFlag } from "../flags.ts";
6
+ import { MissingThreadError } from "../error.ts";
7
+ import { resolveThreadId } from "../../scope/index.ts";
4
8
  import { T3Application } from "../../application/service.ts";
5
9
  import { Environment } from "../../environment/service.ts";
6
- import { humanJsonFormatChoices, resolveOutputFormat } from "../output-format.ts";
10
+ import { resolveOutputFormat } from "../output-format.ts";
7
11
  import { T3Output } from "../output/service.ts";
8
12
 
9
13
  export const archiveThreadCommand = Command.make(
10
14
  "archive",
11
15
  {
12
- thread: Argument.string("thread"),
13
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
16
+ thread: threadFlag,
17
+ format: formatFlag,
14
18
  },
15
19
  ({ thread, format }) =>
16
20
  Effect.gen(function* () {
17
21
  const application = yield* T3Application;
18
22
  const environment = yield* Environment;
19
23
  const output = yield* T3Output;
24
+ const threadId = resolveThreadId({
25
+ value: Option.getOrUndefined(thread),
26
+ env: environment.env,
27
+ });
28
+ if (threadId === undefined) {
29
+ return yield* Effect.fail(
30
+ new MissingThreadError({
31
+ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
32
+ }),
33
+ );
34
+ }
20
35
  const resolvedFormat = resolveOutputFormat(format, environment, "json");
21
- const dispatch = yield* application.archiveThread(thread);
36
+ const dispatch = yield* application.archiveThread(threadId);
22
37
  if (resolvedFormat === "json") {
23
- yield* output.printJson(dispatch);
24
- } else {
25
- yield* output.printInfo(`thread archived: ${thread}\nsequence: ${dispatch.sequence}`);
38
+ return yield* output.printJson(dispatch);
26
39
  }
40
+ return yield* output.printInfo(
41
+ `thread archived: ${threadId}\nsequence: ${dispatch.sequence}`,
42
+ );
27
43
  }),
28
44
  ).pipe(Command.withDescription("archive thread"));
@@ -1,17 +1,19 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { Argument, Command, Flag } from "effect/unstable/cli";
2
+ import { Command } from "effect/unstable/cli";
3
3
 
4
+ import { formatFlag, projectFlag } from "../flags.ts";
5
+ import { requireCommandProjectRef } from "../require.ts";
4
6
  import { formatThreadsHuman } from "../thread-format.ts";
5
7
  import { T3Application } from "../../application/service.ts";
6
8
  import { Environment } from "../../environment/service.ts";
7
- import { humanJsonFormatChoices, resolveOutputFormat } from "../output-format.ts";
9
+ import { resolveOutputFormat } from "../output-format.ts";
8
10
  import { T3Output } from "../output/service.ts";
9
11
 
10
12
  export const listThreadsCommand = Command.make(
11
13
  "list",
12
14
  {
13
- project: Argument.string("project"),
14
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
15
+ project: projectFlag,
16
+ format: formatFlag,
15
17
  },
16
18
  ({ project, format }) =>
17
19
  Effect.gen(function* () {
@@ -19,7 +21,12 @@ export const listThreadsCommand = Command.make(
19
21
  const environment = yield* Environment;
20
22
  const output = yield* T3Output;
21
23
  const resolvedFormat = resolveOutputFormat(format, environment, "json");
22
- const result = yield* application.listThreads(project);
24
+ const projectRef = yield* requireCommandProjectRef({
25
+ project,
26
+ env: environment.env,
27
+ cwd: environment.cwd,
28
+ });
29
+ const result = yield* application.listThreads(projectRef);
23
30
  if (resolvedFormat === "json") {
24
31
  yield* output.printJson(result.threads);
25
32
  } else {
@@ -1,20 +1,24 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { Argument, Command, Flag } from "effect/unstable/cli";
2
+ import * as Option from "effect/Option";
3
+ import { Command, Flag } from "effect/unstable/cli";
3
4
 
5
+ import { formatFlag, threadFlag } from "../flags.ts";
4
6
  import { InvalidLimitError } from "../error.ts";
7
+ import { MissingThreadError } from "../error.ts";
8
+ import { resolveThreadId } from "../../scope/index.ts";
5
9
  import { formatThreadMessagesHuman, formatThreadMessagesJson } from "../thread-format.ts";
6
10
  import { T3Application } from "../../application/service.ts";
7
11
  import { Environment } from "../../environment/service.ts";
8
- import { humanJsonFormatChoices, resolveOutputFormat } from "../output-format.ts";
12
+ import { resolveOutputFormat } from "../output-format.ts";
9
13
  import { T3Output } from "../output/service.ts";
10
14
 
11
15
  export const getThreadMessagesCommand = Command.make(
12
16
  "messages",
13
17
  {
14
- thread: Argument.string("thread"),
18
+ thread: threadFlag,
15
19
  limit: Flag.integer("limit").pipe(Flag.withDefault(20)),
16
20
  full: Flag.boolean("full"),
17
- format: Flag.choice("format", humanJsonFormatChoices).pipe(Flag.withDefault("auto")),
21
+ format: formatFlag,
18
22
  },
19
23
  ({ thread, limit, full, format }) =>
20
24
  Effect.gen(function* () {
@@ -26,8 +30,19 @@ export const getThreadMessagesCommand = Command.make(
26
30
  const application = yield* T3Application;
27
31
  const environment = yield* Environment;
28
32
  const output = yield* T3Output;
33
+ const threadId = resolveThreadId({
34
+ value: Option.getOrUndefined(thread),
35
+ env: environment.env,
36
+ });
37
+ if (threadId === undefined) {
38
+ return yield* Effect.fail(
39
+ new MissingThreadError({
40
+ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
41
+ }),
42
+ );
43
+ }
29
44
  const resolvedFormat = resolveOutputFormat(format, environment, "json");
30
- const detail = yield* application.getThreadMessages(thread);
45
+ const detail = yield* application.getThreadMessages(threadId);
31
46
  if (resolvedFormat === "json") {
32
47
  return yield* output.printJson(formatThreadMessagesJson(detail, full));
33
48
  }
@@ -2,32 +2,27 @@ import * as Effect from "effect/Effect";
2
2
  import * as Option from "effect/Option";
3
3
  import { Argument, Command, Flag } from "effect/unstable/cli";
4
4
 
5
+ import { modelFlags, threadFlag, threadFormatFlag } from "../flags.ts";
5
6
  import { readInitialMessage } from "../message-input.ts";
6
7
  import { buildModelOptions } from "../model-options.ts";
8
+ import { MissingThreadError } from "../error.ts";
9
+ import { resolveThreadId } from "../../scope/index.ts";
7
10
  import { T3Application } from "../../application/service.ts";
8
11
  import { Environment } from "../../environment/service.ts";
9
12
  import { T3Input } from "../input/service.ts";
10
- import {
11
- canRenderLiveTerminal,
12
- humanJsonNdjsonFormatChoices,
13
- resolveOutputFormat,
14
- } from "../output-format.ts";
13
+ import { canRenderLiveTerminal, resolveOutputFormat } from "../output-format.ts";
15
14
  import { T3Output } from "../output/service.ts";
16
15
  import { printWaitEventsHuman, printWaitEventsNdjson } from "../wait-events.ts";
17
16
 
18
17
  export const sendThreadCommand = Command.make(
19
18
  "send",
20
19
  {
21
- thread: Argument.string("thread"),
20
+ thread: threadFlag,
22
21
  message: Argument.string("message").pipe(Argument.optional),
23
22
  stdin: Flag.boolean("stdin"),
24
- option: Flag.keyValuePair("option").pipe(Flag.optional),
25
- reasoningEffort: Flag.string("reasoning-effort").pipe(Flag.optional),
26
- effort: Flag.string("effort").pipe(Flag.optional),
27
- fastMode: Flag.boolean("fast-mode").pipe(Flag.optional),
28
- thinking: Flag.boolean("thinking").pipe(Flag.optional),
23
+ ...modelFlags,
29
24
  wait: Flag.boolean("wait"),
30
- format: Flag.choice("format", humanJsonNdjsonFormatChoices).pipe(Flag.withDefault("auto")),
25
+ format: threadFormatFlag,
31
26
  },
32
27
  ({ thread, message, stdin, option, reasoningEffort, effort, fastMode, thinking, wait, format }) =>
33
28
  Effect.gen(function* () {
@@ -44,14 +39,25 @@ export const sendThreadCommand = Command.make(
44
39
  fastMode,
45
40
  thinking,
46
41
  });
42
+ const application = yield* T3Application;
43
+ const environment = yield* Environment;
44
+ const output = yield* T3Output;
45
+ const threadId = resolveThreadId({
46
+ value: Option.getOrUndefined(thread),
47
+ env: environment.env,
48
+ });
49
+ if (threadId === undefined) {
50
+ return yield* Effect.fail(
51
+ new MissingThreadError({
52
+ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
53
+ }),
54
+ );
55
+ }
47
56
  const input = {
48
57
  message: text,
49
- threadId: thread,
58
+ threadId,
50
59
  ...(options.length > 0 ? { options } : {}),
51
60
  };
52
- const application = yield* T3Application;
53
- const environment = yield* Environment;
54
- const output = yield* T3Output;
55
61
  const resolvedFormat = resolveOutputFormat(format, environment, wait ? "ndjson" : "json");
56
62
 
57
63
  if (resolvedFormat === "ndjson") {
@@ -60,32 +66,30 @@ export const sendThreadCommand = Command.make(
60
66
  if (wait) {
61
67
  yield* printWaitEventsNdjson(output, application.watchThread(sent.threadId));
62
68
  }
63
- return;
69
+ return yield* Effect.void;
64
70
  }
65
71
 
66
72
  if (wait) {
67
73
  const sent = yield* application.sendThread(input, { until: "dispatch" });
68
74
  if (resolvedFormat === "json") {
69
75
  const finalThread = yield* application.waitForThread(sent.threadId);
70
- yield* output.printJson({
76
+ return yield* output.printJson({
71
77
  dispatch: sent.dispatch,
72
78
  threadId: sent.threadId,
73
79
  thread: finalThread,
74
80
  });
75
- return;
76
81
  }
77
82
  yield* printWaitEventsHuman(output, application.watchThread(sent.threadId), {
78
83
  threadId: sent.threadId,
79
84
  live: canRenderLiveTerminal(environment),
80
85
  });
81
- return;
86
+ return yield* Effect.void;
82
87
  }
83
88
 
84
89
  const result = yield* application.sendThread(input, { until: "visible" });
85
90
  if (resolvedFormat === "json") {
86
- yield* output.printJson(result);
87
- } else {
88
- yield* output.printInfo(`message sent: ${result.threadId}`);
91
+ return yield* output.printJson(result);
89
92
  }
93
+ return yield* output.printInfo(`message sent: ${result.threadId}`);
90
94
  }),
91
95
  ).pipe(Command.withDescription("send message to existing thread"));
@@ -3,37 +3,32 @@ import * as Option from "effect/Option";
3
3
  import * as Stream from "effect/Stream";
4
4
  import { Argument, Command, Flag } from "effect/unstable/cli";
5
5
 
6
+ import { modelFlags, projectFlag, threadFormatFlag, worktreeFlag } from "../flags.ts";
6
7
  import { readInitialMessage } from "../message-input.ts";
7
8
  import { buildModelOptions } from "../model-options.ts";
9
+ import { requireCommandProjectRef } from "../require.ts";
10
+ import { resolveWorktreePath } from "../../scope/index.ts";
8
11
  import { formatThreadStartedHuman } from "../thread-format.ts";
9
12
  import { T3Application } from "../../application/service.ts";
10
13
  import { Environment } from "../../environment/service.ts";
11
14
  import { T3Input } from "../input/service.ts";
12
- import {
13
- canRenderLiveTerminal,
14
- humanJsonNdjsonFormatChoices,
15
- resolveOutputFormat,
16
- } from "../output-format.ts";
15
+ import { canRenderLiveTerminal, resolveOutputFormat } from "../output-format.ts";
17
16
  import { T3Output } from "../output/service.ts";
18
17
  import { printWaitEventsHuman, printWaitEventsNdjson } from "../wait-events.ts";
19
18
 
20
19
  export const startThreadCommand = Command.make(
21
20
  "start",
22
21
  {
23
- project: Argument.string("project"),
22
+ project: projectFlag,
24
23
  message: Argument.string("message").pipe(Argument.optional),
25
24
  stdin: Flag.boolean("stdin"),
26
25
  title: Flag.string("title").pipe(Flag.optional),
27
- worktree: Flag.string("worktree").pipe(Flag.optional),
26
+ worktree: worktreeFlag,
28
27
  provider: Flag.string("provider").pipe(Flag.optional),
29
28
  model: Flag.string("model").pipe(Flag.optional),
30
- option: Flag.keyValuePair("option").pipe(Flag.optional),
31
- reasoningEffort: Flag.string("reasoning-effort").pipe(Flag.optional),
32
- effort: Flag.string("effort").pipe(Flag.optional),
33
- fastMode: Flag.boolean("fast-mode").pipe(Flag.optional),
34
- thinking: Flag.boolean("thinking").pipe(Flag.optional),
29
+ ...modelFlags,
35
30
  wait: Flag.boolean("wait"),
36
- format: Flag.choice("format", humanJsonNdjsonFormatChoices).pipe(Flag.withDefault("auto")),
31
+ format: threadFormatFlag,
37
32
  },
38
33
  ({
39
34
  project,
@@ -59,7 +54,6 @@ export const startThreadCommand = Command.make(
59
54
  readStdin: inputService.readStdin,
60
55
  });
61
56
  const titleValue = Option.getOrUndefined(title);
62
- const worktreeValue = Option.getOrUndefined(worktree);
63
57
  const providerValue = Option.getOrUndefined(provider);
64
58
  const modelValue = Option.getOrUndefined(model);
65
59
  const options = buildModelOptions({
@@ -69,22 +63,29 @@ export const startThreadCommand = Command.make(
69
63
  fastMode,
70
64
  thinking,
71
65
  });
66
+ const application = yield* T3Application;
67
+ const environment = yield* Environment;
68
+ const output = yield* T3Output;
69
+ const projectRef = yield* requireCommandProjectRef({
70
+ project,
71
+ env: environment.env,
72
+ cwd: environment.cwd,
73
+ });
74
+ const worktreePath = resolveWorktreePath({
75
+ value: Option.getOrUndefined(worktree),
76
+ env: environment.env,
77
+ });
72
78
  const input = {
73
- projectRef: project,
74
79
  message: text,
80
+ projectRef,
75
81
  ...(titleValue !== undefined && titleValue.length > 0 ? { title: titleValue } : {}),
76
- ...(worktreeValue !== undefined && worktreeValue.length > 0
77
- ? { worktreePath: worktreeValue }
78
- : {}),
82
+ ...(worktreePath !== undefined ? { worktreePath } : {}),
79
83
  ...(providerValue !== undefined && providerValue.length > 0
80
84
  ? { provider: providerValue }
81
85
  : {}),
82
86
  ...(modelValue !== undefined && modelValue.length > 0 ? { model: modelValue } : {}),
83
87
  ...(options.length > 0 ? { options } : {}),
84
88
  };
85
- const application = yield* T3Application;
86
- const environment = yield* Environment;
87
- const output = yield* T3Output;
88
89
  const resolvedFormat = resolveOutputFormat(format, environment, wait ? "ndjson" : "json");
89
90
 
90
91
  if (resolvedFormat === "ndjson") {
@@ -1,34 +1,44 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { Argument, Command, Flag } from "effect/unstable/cli";
2
+ import * as Option from "effect/Option";
3
+ import { Command } from "effect/unstable/cli";
3
4
 
5
+ import { threadFlag, waitFormatFlag } from "../flags.ts";
6
+ import { MissingThreadError } from "../error.ts";
7
+ import { resolveThreadId } from "../../scope/index.ts";
4
8
  import { Environment } from "../../environment/service.ts";
5
9
  import { T3Application } from "../../application/service.ts";
6
- import {
7
- canRenderLiveTerminal,
8
- humanNdjsonFormatChoices,
9
- resolveOutputFormat,
10
- } from "../output-format.ts";
10
+ import { canRenderLiveTerminal, resolveOutputFormat } from "../output-format.ts";
11
11
  import { T3Output } from "../output/service.ts";
12
12
  import { printWaitEventsHuman, printWaitEventsNdjson } from "../wait-events.ts";
13
13
 
14
14
  export const waitForThreadCommand = Command.make(
15
15
  "wait",
16
16
  {
17
- thread: Argument.string("thread"),
18
- format: Flag.choice("format", humanNdjsonFormatChoices).pipe(Flag.withDefault("auto")),
17
+ thread: threadFlag,
18
+ format: waitFormatFlag,
19
19
  },
20
20
  ({ thread, format }) =>
21
21
  Effect.gen(function* () {
22
22
  const application = yield* T3Application;
23
23
  const environment = yield* Environment;
24
24
  const output = yield* T3Output;
25
+ const threadId = resolveThreadId({
26
+ value: Option.getOrUndefined(thread),
27
+ env: environment.env,
28
+ });
29
+ if (threadId === undefined) {
30
+ return yield* Effect.fail(
31
+ new MissingThreadError({
32
+ message: "thread id is required: pass --thread or set T3CODE_THREAD_ID",
33
+ }),
34
+ );
35
+ }
25
36
  const resolvedFormat = resolveOutputFormat(format, environment, "ndjson");
26
37
  if (resolvedFormat === "ndjson") {
27
- yield* printWaitEventsNdjson(output, application.watchThread(thread));
28
- return;
38
+ return yield* printWaitEventsNdjson(output, application.watchThread(threadId));
29
39
  }
30
- yield* printWaitEventsHuman(output, application.watchThread(thread), {
31
- threadId: thread,
40
+ return yield* printWaitEventsHuman(output, application.watchThread(threadId), {
41
+ threadId,
32
42
  live: canRenderLiveTerminal(environment),
33
43
  });
34
44
  }),
@@ -0,0 +1,5 @@
1
+ export { T3Config } from "./service.ts";
2
+ export type { ResolvedConfig, StoredConfig } from "./service.ts";
3
+ export { T3ConfigLive, makeT3Config } from "./layer.ts";
4
+ export { ConfigError, UrlError } from "./error.ts";
5
+ export type { ConfigServiceError } from "./error.ts";
@@ -69,6 +69,7 @@ export const makeT3Config = Effect.fn("makeT3Config")(function* () {
69
69
  url: normalizedUrl,
70
70
  token,
71
71
  source,
72
+ local: stored.local ?? false,
72
73
  };
73
74
  });
74
75
 
@@ -84,6 +85,7 @@ export const T3ConfigLive = Layer.effect(T3Config, makeT3Config());
84
85
  const StoredConfigSchema = Schema.Struct({
85
86
  url: Schema.optionalKey(Schema.String),
86
87
  token: Schema.optionalKey(Schema.String),
88
+ local: Schema.optionalKey(Schema.Boolean),
87
89
  });
88
90
 
89
91
  function parseStoredConfig(raw: string) {
@@ -6,12 +6,14 @@ import type { ConfigError, ConfigServiceError } from "./error.ts";
6
6
  export type StoredConfig = {
7
7
  readonly url?: string;
8
8
  readonly token?: string;
9
+ readonly local?: boolean;
9
10
  };
10
11
 
11
12
  export type ResolvedConfig = {
12
13
  readonly url: string;
13
14
  readonly token: string;
14
15
  readonly source: "env" | "config";
16
+ readonly local: boolean;
15
17
  };
16
18
 
17
19
  export class T3Config extends Context.Service<
@@ -0,0 +1,9 @@
1
+ export { T3CodeConnectionError } from "./error.ts";
2
+ export { T3CodeRpcLayer, makeT3CodeRpcLayer } from "./layer.ts";
3
+ export { T3CodeNodeRpcLayer } from "./node.ts";
4
+ export {
5
+ T3CodeConnectionProvider,
6
+ T3CodeConnectionProviderLive,
7
+ makeT3CodeConnectionProvider,
8
+ } from "./service.ts";
9
+ export type { T3CodeAuth, T3CodeConnection, T3CodeOrigin } from "./type.ts";
@@ -0,0 +1,8 @@
1
+ export type {
2
+ OrchestrationMessage,
3
+ OrchestrationProjectShell,
4
+ OrchestrationShellSnapshot,
5
+ OrchestrationThread,
6
+ OrchestrationThreadShell,
7
+ ServerProvider,
8
+ } from "#t3tools/contracts";