@aicalas/loopy 0.2.0 → 0.2.1

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 (75) hide show
  1. package/README.md +213 -38
  2. package/dist/adapters.d.ts +2 -0
  3. package/dist/adapters.d.ts.map +1 -1
  4. package/dist/adapters.js.map +1 -1
  5. package/dist/authoring/effect-config.d.ts +2 -2
  6. package/dist/authoring/effect-config.d.ts.map +1 -1
  7. package/dist/authoring/effect-config.js +2 -2
  8. package/dist/authoring/effect-config.js.map +1 -1
  9. package/dist/authoring/types.d.ts +5 -0
  10. package/dist/authoring/types.d.ts.map +1 -1
  11. package/dist/cli-help.d.ts +1 -11
  12. package/dist/cli-help.d.ts.map +1 -1
  13. package/dist/cli-help.js +184 -134
  14. package/dist/cli-help.js.map +1 -1
  15. package/dist/cli.d.ts +2 -3
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +10 -46
  18. package/dist/cli.js.map +1 -1
  19. package/dist/core/calls.d.ts +3 -1
  20. package/dist/core/calls.d.ts.map +1 -1
  21. package/dist/core/calls.js +7 -2
  22. package/dist/core/calls.js.map +1 -1
  23. package/dist/core/prompts.d.ts +8 -0
  24. package/dist/core/prompts.d.ts.map +1 -0
  25. package/dist/core/prompts.js +59 -0
  26. package/dist/core/prompts.js.map +1 -0
  27. package/dist/core/wire.d.ts +13 -4
  28. package/dist/core/wire.d.ts.map +1 -1
  29. package/dist/core/wire.js +29 -8
  30. package/dist/core/wire.js.map +1 -1
  31. package/dist/harnesses/claude.d.ts.map +1 -1
  32. package/dist/harnesses/claude.js +10 -1
  33. package/dist/harnesses/claude.js.map +1 -1
  34. package/dist/harnesses/codex-app-server.d.ts +29 -0
  35. package/dist/harnesses/codex-app-server.d.ts.map +1 -0
  36. package/dist/harnesses/codex-app-server.js +166 -0
  37. package/dist/harnesses/codex-app-server.js.map +1 -0
  38. package/dist/harnesses/codex.d.ts.map +1 -1
  39. package/dist/harnesses/codex.js +34 -7
  40. package/dist/harnesses/codex.js.map +1 -1
  41. package/dist/harnesses/opencode.d.ts.map +1 -1
  42. package/dist/harnesses/opencode.js +1 -0
  43. package/dist/harnesses/opencode.js.map +1 -1
  44. package/dist/harnesses/probe.d.ts +5 -0
  45. package/dist/harnesses/probe.d.ts.map +1 -0
  46. package/dist/harnesses/probe.js +53 -0
  47. package/dist/harnesses/probe.js.map +1 -0
  48. package/dist/temporal/activities.d.ts.map +1 -1
  49. package/dist/temporal/activities.js +50 -10
  50. package/dist/temporal/activities.js.map +1 -1
  51. package/dist/temporal/contracts.d.ts +1 -1
  52. package/dist/temporal/contracts.d.ts.map +1 -1
  53. package/dist/temporal/contracts.js +1 -1
  54. package/dist/temporal/contracts.js.map +1 -1
  55. package/dist/temporal/handle.d.ts.map +1 -1
  56. package/dist/temporal/handle.js +23 -4
  57. package/dist/temporal/handle.js.map +1 -1
  58. package/dist/temporal/metadata.d.ts +7 -0
  59. package/dist/temporal/metadata.d.ts.map +1 -0
  60. package/dist/temporal/metadata.js +44 -0
  61. package/dist/temporal/metadata.js.map +1 -0
  62. package/dist/temporal/observe.d.ts +15 -2
  63. package/dist/temporal/observe.d.ts.map +1 -1
  64. package/dist/temporal/observe.js +7 -2
  65. package/dist/temporal/observe.js.map +1 -1
  66. package/dist/temporal/supervisor.d.ts +3 -1
  67. package/dist/temporal/supervisor.d.ts.map +1 -1
  68. package/dist/temporal/supervisor.js +31 -7
  69. package/dist/temporal/supervisor.js.map +1 -1
  70. package/dist/temporal/worker.d.ts.map +1 -1
  71. package/dist/temporal/worker.js +1 -0
  72. package/dist/temporal/worker.js.map +1 -1
  73. package/dist/version.d.ts +1 -1
  74. package/dist/version.js +1 -1
  75. package/package.json +1 -1
package/dist/cli-help.js CHANGED
@@ -1,168 +1,222 @@
1
- /**
2
- * Operator-facing guidance printed by the CLI. It must stand alone: loopy runs on a machine whose
3
- * agent operator is not expected to open repo docs or reach the network, so everything an operator
4
- * needs is emitted here. Two standing rules shape the copy - loopy never explains how Temporal
5
- * itself works (it names the temporal-developer skill and stops), and it never teaches authoring a
6
- * new adapter (there is no plugin API yet; the built-ins are configured, not defined).
7
- */
8
- /** Named so an operator can find generic Temporal help; loopy-specific guidance never depends on it. */
9
- export const TEMPORAL_SKILL_POINTER = "Temporal itself (server, CLI, non-determinism, Event History) is out of loopy's scope.\n" +
10
- "For that, use the temporal-developer skill: https://github.com/temporalio/skill-temporal-developer";
1
+ /** Operator-facing guidance bundled with the CLI so it works without configuration, a Temporal connection, or network access. */
2
+ export const TEMPORAL_SKILL_POINTER = "Use Temporal UI or CLI for execution inspection, Event History, cancellation, termination, and Schedule administration.\n" +
3
+ "For Temporal operations, use the temporal-developer skill: https://github.com/temporalio/skill-temporal-developer";
11
4
  const SETUP = {
12
5
  name: "setup",
13
- summary: "config.toml and pointing loopy at a Temporal Service (local, self-hosted, or Cloud)",
6
+ summary: "install loopy, configure the local runtime, and preserve its state",
14
7
  body: [
15
8
  "loopy guide setup",
16
9
  "",
17
- "Configure loopy with a TOML file, then point it at a Temporal Service.",
18
- "",
19
- "Config file",
20
- " Default path: ~/.config/loopy/config.toml ($XDG_CONFIG_HOME/loopy/config.toml).",
21
- " Override with -c/--config <path>.",
22
- "",
23
- " Minimal example:",
24
- "",
25
- ' repository = "owner/name" # required; the workspace repo agents clone',
26
- ' default_branch = "main"',
27
- " poll_interval_seconds = 300",
28
- ' workflows = "workflows" # directory of workflow modules',
29
- "",
30
- " [temporal]",
31
- ' address = "localhost:7233"',
32
- ' namespace = "default"',
33
- ' control_task_queue = "loopy-control" # required',
34
- ' agent_task_queue = "loopy-agent" # required',
35
- " tls = false",
36
- "",
37
- " Other keys: project_directory, working_directory, drain_timeout_seconds,",
38
- " shutdown_grace_seconds, agent_worker.max_concurrent_activities, log_level.",
39
- "",
40
- "Temporal connection - three setups, differing only in [temporal]:",
41
- " Local dev address=localhost:7233, tls=false. Start one with your Temporal",
42
- " dev server (temporal server start-dev).",
43
- " Self-hosted point address/namespace at it; set tls as deployed.",
44
- " Cloud address=<ns>.<acct>.tmprl.cloud:7233, tls=true, and an API key via",
45
- " api_key or the TEMPORAL_API_KEY environment variable (env wins and is",
46
- " reported at startup). loopy selects a Namespace but never creates one.",
47
- "",
48
- "First run",
49
- " loopy loop starts the Worker Process. A worker.lock in the working directory",
50
- " prevents a second process for the same directory.",
10
+ "Loopy is a local runtime for one developer. It needs Node.js 24, git, and a",
11
+ "reachable Temporal Service. Install the CLI globally and add the package to the",
12
+ "project that owns your workflows:",
13
+ "",
14
+ " npm install --global @aicalas/loopy",
15
+ " npm install @aicalas/loopy",
16
+ "",
17
+ "Configuration",
18
+ " The default file is ~/.config/loopy/config.toml",
19
+ " ($XDG_CONFIG_HOME/loopy/config.toml). Pass -c/--config <path> to use another file.",
20
+ "",
21
+ " log_level debug, info, warning, or error. Defaults to info.",
22
+ " repository Workspace repository cloned for agents. Required.",
23
+ " default_branch Defaults to main.",
24
+ " workflows Workflow-module directory. Defaults to workflows.",
25
+ " project_directory Base for workflows and prompt files. Defaults to .",
26
+ " working_directory Clone, worktree, and bundle root. Defaults to .loopy.",
27
+ " poll_interval_seconds Watcher and control cadence. Defaults to 300.",
28
+ " drain_timeout_seconds Shutdown drain deadline. Defaults to 900.",
29
+ " shutdown_grace_seconds Activity shutdown grace. Defaults to 30.",
30
+ " agent_worker.max_concurrent_activities",
31
+ " Local agent concurrency. Defaults to 5.",
32
+ " temporal.address Defaults to localhost:7233.",
33
+ " temporal.namespace Defaults to default.",
34
+ " temporal.control_task_queue Required and unique to this runtime.",
35
+ " temporal.agent_task_queue Required and unique to this runtime.",
36
+ " temporal.tls Defaults to false.",
37
+ "",
38
+ " TEMPORAL_ADDRESS, TEMPORAL_NAMESPACE, TEMPORAL_CONTROL_TASK_QUEUE,",
39
+ " TEMPORAL_AGENT_TASK_QUEUE, TEMPORAL_TLS, and TEMPORAL_API_KEY override their",
40
+ " matching Temporal fields. Loopy does not create or store secrets; provide GitHub,",
41
+ " Temporal, and agent-provider credentials through the environment available to loopy.",
42
+ "",
43
+ "Typical Docker Compose deployment",
44
+ " Run the Temporal development server and loopy as separate services. Point",
45
+ " TEMPORAL_ADDRESS at the Temporal service name. Mount the config, workflows, and",
46
+ " prompt files into loopy, and preserve three independent volumes: Temporal's database,",
47
+ " loopy's working_directory, and the container user's provider home. The package README",
48
+ " contains a complete Compose, config.toml, and Dockerfile example.",
49
+ "",
50
+ "Credentials and git authentication",
51
+ " GITHUB_TOKEN or GH_TOKEN authenticates GitHub watchers, effects, attention, and",
52
+ " questions. Git clone, fetch, and agent pushes use git's own credential mechanism;",
53
+ " configure an HTTPS credential helper or SSH credentials in the same environment.",
54
+ " Authenticate each enabled agent provider with its supported environment variables or",
55
+ " login flow. Never commit secret files or provider authentication state.",
56
+ "",
57
+ "Agent environment",
58
+ " Agents run inside the loopy process environment. A container image must therefore be a",
59
+ " complete development environment for the target repository: language runtimes, package",
60
+ " managers, build and unit-test tools, system libraries, provider CLIs, MCP server",
61
+ " executables, repository instructions, and network access. Initialize and authenticate",
62
+ " MCP servers before unattended use. Verify the repository's real test commands from an",
63
+ " interactive shell in that image. OpenCode additionally requires an opencode executable",
64
+ " at version 1.18.3 or newer on PATH.",
65
+ "",
66
+ "State that must survive restart",
67
+ " Temporal state The Service's persistence contains Workflow Executions, Event",
68
+ " Histories, Schedules, and durable call state.",
69
+ " Loopy config Preserve the selected config file so the same repository,",
70
+ " Namespace, Task Queues, and directories are used after restart.",
71
+ " Working directory Preserve working_directory while any execution is open. It holds",
72
+ " the managed clone, worktrees, bundles, and worker lock.",
73
+ " Provider state Preserve each provider's own session data in the same configured",
74
+ " home/data location. A session ID in Temporal is not the transcript.",
75
+ "",
76
+ "Run",
77
+ " loopy loop starts the local runtime. One process owns a working directory; worker.lock",
78
+ " prevents a second process from racing the same worktrees.",
51
79
  ].join("\n"),
52
80
  };
53
81
  const WORKFLOWS = {
54
82
  name: "workflows",
55
- summary: "create, register, and change workflows",
83
+ summary: "author workflows, inputs, agents, effects, and human questions",
56
84
  body: [
57
85
  "loopy guide workflows",
58
86
  "",
59
- "A workflow is a TypeScript module; there is no separate spec language and no register",
60
- "command. Registration is discovery: loopy loop finds the modules and schedules them.",
87
+ "A workflow is a TypeScript module. There is no specification language or registration",
88
+ "command: loopy loop discovers the modules in the configured workflows directory.",
61
89
  "",
62
- "Create",
63
- " One file under the workflows/ directory defines one workflow:",
90
+ "Built-in input",
91
+ " One module default-exports one workflow definition:",
64
92
  "",
65
93
  " import { claude, defineWorkflow, githubAttention, githubPullRequests }",
66
94
  ' from "@aicalas/loopy/workflow";',
67
95
  "",
96
+ " const outcome = {",
97
+ ' type: "object",',
98
+ ' properties: { summary: { type: "string" } },',
99
+ ' required: ["summary"],',
100
+ " additionalProperties: false,",
101
+ " } as const;",
102
+ "",
68
103
  " export default defineWorkflow({",
69
104
  ' name: "review",',
70
105
  ' watcher: githubPullRequests({ repository: "owner/repo", label: "agent:review" }),',
71
106
  ' attention: githubAttention({ target: "trigger" }),',
72
107
  " async run(ctx) {",
73
- ' const agent = ctx.agent("reviewer", claude({ model: "claude-opus-4-8" }));',
74
- ' return await agent.run({ prompt: ["Review this PR."] });',
108
+ ' const agent = ctx.agent("reviewer",',
109
+ ' claude({ model: "claude-opus-4-8", effort: "high" }));',
110
+ ' ctx.progress("Reviewing the pull request");',
111
+ ' return await agent.run({ output: outcome, prompt: ["Review this pull request."] });',
75
112
  " },",
76
113
  " });",
77
114
  "",
78
- " The module must have no top-level side effects: it is imported both under Node (for",
79
- " metadata) and inside the Temporal isolate bundle, and a side effect breaks one or both.",
80
- " A workflow configures the built-in adapters (watcher, attention, and any effects/asks);",
81
- " it cannot define new ones.",
82
- "",
83
- "Schedule instead of watching",
84
- " A workflow declares exactly one intake: watcher or schedule. A schedule starts the user",
85
- " workflow directly; it needs no watcher and attention is optional:",
86
- "",
87
- " export default defineWorkflow({",
88
- ' name: "nightly-maintenance",',
89
- ' schedule: { cron: "0 2 * * *", timezone: "UTC" },',
90
- " async run(ctx) {",
91
- " return { source: ctx.trigger.source }; // schedule",
92
- " },",
93
- " });",
94
- "",
95
- " Use intervalSeconds instead of cron for a fixed cadence. overlap defaults to SKIP;",
96
- " BUFFER_ONE, BUFFER_ALL, CANCEL_OTHER, TERMINATE_OTHER, and ALLOW_ALL are available.",
97
- " A scheduled workflow with GitHub attention must target a fixed issue, not target: trigger.",
98
- "",
99
- "Register",
100
- " Drop the module in the workflows directory and run loopy loop. On startup loopy",
101
- " discovers every module, bundles them, and reconciles their Temporal Schedules.",
102
- " Watchers poll for labelled issues or PRs; declared schedules start their workflows on time.",
103
- "",
104
- "Add or change",
105
- " Edits reach a running Worker only on restart. The safe loop:",
106
- " 1. Edit, add, or delete workflow files.",
107
- " 2. Drain: send SIGINT/SIGTERM to loopy loop. It pauses this repo's Schedules and",
108
- " keeps serving open instances until drain_timeout_seconds; a second signal skips",
109
- " the wait. loopy has no workflow versioning, so draining is how you deploy an",
110
- " edit without an in-flight instance resuming under changed code.",
111
- " 3. Restart loopy loop. Schedules reconcile: new file adds a Schedule, a deleted",
112
- " file removes one, an existing one is updated in place (an operator pause is kept).",
115
+ " A GitHub watcher claims each labelled object before run(ctx) starts. A workflow may",
116
+ " instead declare a Temporal schedule with cron or intervalSeconds. A workflow declares",
117
+ " exactly one intake; watcher and schedule are the built-in choices. Attention is optional",
118
+ " for scheduled workflows.",
119
+ "",
120
+ "Authoring boundaries",
121
+ " Workflow code runs in Temporal's deterministic isolate. Keep top-level module evaluation",
122
+ " free of side effects; loopy imports modules under Node for discovery and again when it",
123
+ " builds the isolate bundle. Filesystem, network, provider, and git work belong behind",
124
+ " Activities such as inputs, agent harnesses, effects, attention, and channels.",
125
+ "",
126
+ " ctx.agent(id, harness) keeps one worktree and provider session across calls.",
127
+ " ctx.effect(id, effect) performs a declared idempotent external mutation once per id.",
128
+ " ctx.ask(id, channel, request) parks without occupying an agent slot until answered.",
129
+ " ctx.progress(details) replaces Temporal Current Details with the latest message.",
130
+ " Agent output accepts a Standard JSON Schema validator or literal JSON Schema.",
131
+ "",
132
+ "Built-in adapters",
133
+ " githubIssues / githubPullRequests Poll labelled GitHub objects. Edge mode consumes the",
134
+ " intake label; level mode repeats while it remains.",
135
+ " claude / codex / opencode Run a named resumable provider session in a worktree.",
136
+ " githubAttention Report halted, parked, stuck, and awaiting-answer runs.",
137
+ " githubLabels Apply an idempotent label change through ctx.effect.",
138
+ " githubComments Ask through ctx.ask and resume from a matching reply.",
139
+ " promptFile Read and interpolate a prompt outside the isolate.",
140
+ "",
141
+ " Harness configuration controls permissions and sandboxing. By default provider settings",
142
+ " and repository instructions remain available, including their tools and MCP servers.",
143
+ " Treat those settings as part of the workflow's effective capability and credential scope.",
144
+ "",
145
+ "Prompt files",
146
+ " promptFile(path, values?) works in agent prompts and ctx.ask human questions. Paths",
147
+ " resolve against project_directory outside the isolate. Files use named double-brace",
148
+ " placeholders such as {{ repository }}; names begin with a letter or underscore and may",
149
+ " continue with letters, digits, or underscores. Whitespace inside the braces is ignored.",
150
+ "",
151
+ ' promptFile("prompts/review.md", { repository: ctx.trigger.repository, issue: 42 })',
152
+ "",
153
+ " The values map is the template's only input. Strings are inserted verbatim; finite",
154
+ " numbers, booleans, and null use JSON scalar text. Unused values are allowed, but every",
155
+ " placeholder needs a value. Missing values, malformed placeholders, non-finite numbers,",
156
+ " and objects or arrays halt without retry before an agent or question channel is called.",
157
+ "",
158
+ "Deploy an edit",
159
+ " Workflow modules are bundled once when loopy loop starts. Send SIGINT or SIGTERM to pause",
160
+ " intake and drain open executions, then restart. A second signal skips the drain. Loopy has",
161
+ " no workflow versioning, so do not put an open execution under incompatible workflow code.",
113
162
  ].join("\n"),
114
163
  };
115
- const MONITOR = {
116
- name: "monitor",
117
- summary: "inspect instances with loopy status and act on the ones needing a human",
164
+ const RECOVERY = {
165
+ name: "recovery",
166
+ summary: "resume the local runtime and recover parked or interrupted work",
118
167
  body: [
119
- "loopy guide monitor",
120
- "",
121
- "loopy status [workflow-id]",
122
- " Prints one NDJSON row per instance (per Workflow ID), or one row for a single",
123
- " instance. Each row carries a domainStatus - loopy's own view, separate from",
124
- " Temporal's status.",
125
- "",
126
- "Domain statuses",
127
- " running Executing or waiting on an agent. Nothing to do.",
128
- " awaiting_recovery An agent call failed safely; the instance, workspace, and session",
129
- " are retained. Resolve: loopy resolve <id> --retry (or --halt).",
130
- " awaiting_reconciliation An agent call ended ambiguously and the instance parked.",
131
- " Resolve: loopy resolve <id> --retry (once the prior call can",
132
- " no longer mutate external state) or --halt to close it.",
133
- " awaiting_answer Parked on ctx.ask for a human answer. Reply on the channel,",
134
- ' or: loopy answer <id> "<text>". Unanswered, it halts in 2 days.',
135
- " completed Closed with a result. Re-label the trigger to run again.",
136
- " halted An expected failure closed it; cleanup ran. Read the reason,",
137
- " fix the cause, re-label to run again.",
138
- " stuck Open but its own code fails every attempt. Fix the workflow",
139
- " and restart loopy loop; it resumes automatically.",
140
- " unavailable The row could not be read (usually transient). Retry status.",
141
- "",
142
- "Push, not just polling",
143
- " Every state that needs a human also reaches the workflow's declared attention route",
144
- " (by default, a label and comment on the trigger issue/PR), so you are notified there",
145
- " without polling loopy status.",
146
- "",
147
- "When --call is required",
148
- " If more than one call is parked or awaiting an answer, pass --call <handle>/call/<n>;",
149
- " the error from resolve/answer lists the available call addresses.",
168
+ "loopy guide recovery",
169
+ "",
170
+ "Temporal preserves orchestration state; the local filesystem preserves the material an",
171
+ "agent needs to continue. Recovery requires the same Temporal Namespace and Task Queues,",
172
+ "the same loopy config, the same working_directory, and the provider's session data.",
173
+ "",
174
+ "Runtime restart",
175
+ " A graceful signal drains before exit. After an ordinary process or machine restart, run",
176
+ " loopy loop with the same config and storage. Temporal schedules new tasks for the restored",
177
+ " worker, and open executions continue. Closed executions need no local workspace.",
178
+ "",
179
+ "Agent-call outcomes",
180
+ " Explicit provider, validation, deadline, or session-resume failure parks the call for",
181
+ " recovery and retains its known session. Fix the cause, then run:",
182
+ "",
183
+ " loopy resolve <workflow-id> --retry",
184
+ "",
185
+ " Worker loss, heartbeat timeout, or a lost result is ambiguous because the old provider",
186
+ " invocation may have changed the worktree or remote repository. Confirm that it can no",
187
+ " longer mutate state before retrying. Loopy reuses the last session ID checkpointed in",
188
+ " Temporal when available; otherwise it retains an earlier known session or starts fresh.",
189
+ " The resolve result shows sessionId on the parked call. Use --halt when retry is unsafe.",
190
+ "",
191
+ " If several calls are parked, add --call <handle>/call/<n>. If ctx.ask is waiting and its",
192
+ " configured channel is unavailable, use loopy answer <workflow-id> <text>, with --call when",
193
+ " needed.",
194
+ "",
195
+ "Lost storage",
196
+ " A retained Temporal history cannot reconstruct an absent worktree or provider transcript.",
197
+ " Do not retry a session against a different path or empty provider state and assume it is",
198
+ " continuous. Inspect the execution and workspace, preserve any recoverable git work, then",
199
+ " terminate or reset through Temporal and start fresh. Remove orphaned worktrees manually",
200
+ " only after no open execution owns them.",
201
+ "",
202
+ "Temporal operations",
203
+ " Use Temporal UI or CLI to inspect executions and Event Histories, diagnose Workflow Task",
204
+ " failures, administer Schedules, and cancel, reset, or terminate executions. Loopy's",
205
+ " resolve and answer commands exist only for Loopy's parked-call and human-input contracts.",
150
206
  ].join("\n"),
151
207
  };
152
- /** Ordered so `loopy guide` (no topic) lists them in the sequence an operator meets them. */
153
- export const GUIDE_TOPICS = [SETUP, WORKFLOWS, MONITOR];
208
+ export const GUIDE_TOPICS = [SETUP, WORKFLOWS, RECOVERY];
154
209
  export function guideTopicNames() {
155
210
  return GUIDE_TOPICS.map((topic) => topic.name);
156
211
  }
157
212
  export function findGuideTopic(name) {
158
213
  return GUIDE_TOPICS.find((topic) => topic.name === name);
159
214
  }
160
- /** `loopy guide` with no topic: the topic list plus the one external pointer loopy makes. */
161
215
  export function renderGuideIndex() {
162
216
  const width = Math.max(...GUIDE_TOPICS.map((topic) => topic.name.length));
163
217
  const rows = GUIDE_TOPICS.map((topic) => ` ${topic.name.padEnd(width)} ${topic.summary}`).join("\n");
164
218
  return [
165
- "loopy guide <topic> - operator guidance, printed offline with no config needed.",
219
+ "loopy guide <topic> - offline guidance with no config or Temporal connection required.",
166
220
  "",
167
221
  "Topics:",
168
222
  rows,
@@ -170,19 +224,15 @@ export function renderGuideIndex() {
170
224
  TEMPORAL_SKILL_POINTER,
171
225
  ].join("\n");
172
226
  }
173
- /** Appended after `loopy --help`: the playbook that points at the guide topics. */
174
227
  export function helpPlaybook() {
175
228
  return [
176
229
  "Playbook:",
177
- " loopy loop Run the Worker Process (poll, run, drain on signal).",
178
- " loopy status [id] List instances, or describe one.",
179
- " loopy resolve <id> --retry Resume a recoverable call or reconcile an ambiguous one.",
180
- ' loopy answer <id> "<text>" Answer an instance parked on ctx.ask.',
181
- "",
182
- " To deploy a workflow change: edit files, then restart loopy loop.",
230
+ " loopy loop Run workflows and drain safely when interrupted.",
231
+ " loopy resolve <id> --retry Resume or reconcile a parked agent call.",
232
+ ' loopy answer <id> "<text>" Answer a workflow waiting for human input.',
233
+ " loopy guide Read setup, authoring, and recovery guidance.",
183
234
  "",
184
- "Guidance (offline, no config): loopy guide <" + guideTopicNames().join("|") + ">",
185
- " or run loopy guide for the topic list.",
235
+ "For inspection, histories, cancellation, and termination, use Temporal UI or CLI.",
186
236
  ].join("\n");
187
237
  }
188
238
  //# sourceMappingURL=cli-help.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env node
2
+ import { Command } from "commander";
2
3
  import type { AdapterRegistries } from "./adapters.js";
3
4
  import { buildWorkflowBundle, discoverWorkflows } from "./build/discover.js";
4
5
  import { type InstanceState, type ResolveRequest } from "./core/wire.js";
5
6
  import { ensureRepo } from "./git.js";
6
7
  import { type Settings } from "./settings.js";
7
8
  import { connectClient } from "./temporal/client.js";
8
- import { type InstanceView } from "./temporal/status.js";
9
9
  import { createWorkerRuntime } from "./temporal/worker.js";
10
10
  export interface CliServices {
11
11
  serve(settings: Settings, registries: AdapterRegistries): Promise<void>;
12
12
  resolve(workflowId: string, request: ResolveOptions, settings: Settings): Promise<InstanceState>;
13
13
  answer(workflowId: string, request: AnswerOptions, settings: Settings): Promise<InstanceState>;
14
- status(settings: Settings, workflowId: string | undefined): Promise<InstanceView[]>;
15
14
  }
16
15
  export interface ServeServices {
17
16
  ensureRepo: typeof ensureRepo;
@@ -28,10 +27,10 @@ export interface AnswerOptions {
28
27
  answer: string;
29
28
  callId?: string;
30
29
  }
30
+ export declare function createCli(services: CliServices): Command;
31
31
  export declare function main(argv: readonly string[], services: CliServices): Promise<void>;
32
32
  export declare function serve(settings: Settings, registries: AdapterRegistries, services: ServeServices): Promise<void>;
33
33
  export declare function resolveInstance(workflowId: string, request: ResolveOptions, settings: Settings, connect?: typeof connectClient): Promise<InstanceState>;
34
34
  export declare function answerInstance(workflowId: string, request: AnswerOptions, settings: Settings, connect?: typeof connectClient): Promise<InstanceState>;
35
- export declare function statusInstances(settings: Settings, workflowId: string | undefined, connect?: typeof connectClient): Promise<InstanceView[]>;
36
35
  export declare function runExecutable(argv: readonly string[], services: CliServices): Promise<void>;
37
36
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EACL,mBAAmB,EAEnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAY,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AASrD,OAAO,EAEL,KAAK,YAAY,EAGlB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAM3D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/F,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;CACjD;AAqBD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoGxF;AAED,wBAAsB,KAAK,CACzB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAkEf;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,OAAO,aAA6B,GAC5C,OAAO,CAAC,aAAa,CAAC,CAcxB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,OAAO,aAA6B,GAC5C,OAAO,CAAC,aAAa,CAAC,CAcxB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,GAAE,OAAO,aAA6B,GAC5C,OAAO,CAAC,YAAY,EAAE,CAAC,CAqBzB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAKA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EACL,mBAAmB,EAEnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAY,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AASrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAM3D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAChG;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;CACjD;AAoBD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAwFxD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAExF;AAED,wBAAsB,KAAK,CACzB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAkEf;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,OAAO,aAA6B,GAC5C,OAAO,CAAC,aAAa,CAAC,CAcxB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,OAAO,aAA6B,GAC5C,OAAO,CAAC,aAAa,CAAC,CAcxB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjG"}
package/dist/cli.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { join, resolve } from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
- import { WorkflowNotFoundError } from "@temporalio/client";
5
4
  import { Runtime } from "@temporalio/worker";
6
5
  import { Command, Option } from "commander";
7
6
  import { createAdapterRegistries } from "./adapters.js";
@@ -17,7 +16,6 @@ import { ANSWER_INSTANCE_UPDATE, INSTANCE_STATE_QUERY, RESOLVE_INSTANCE_UPDATE,
17
16
  import { drainOnSignal } from "./temporal/drain.js";
18
17
  import { countOpenExecutions } from "./temporal/executions.js";
19
18
  import { resumeDrainedSchedules, syncSchedules } from "./temporal/schedules.js";
20
- import { describeInstance, listInstances, } from "./temporal/status.js";
21
19
  import { createWorkerRuntime } from "./temporal/worker.js";
22
20
  import { LOOPY_VERSION } from "./version.js";
23
21
  import { WorkerLockError, WorkerProcessLock } from "./worker-lock.js";
@@ -34,12 +32,11 @@ const DEFAULT_CLI_SERVICES = {
34
32
  serve: (settings, registries) => serve(settings, registries, DEFAULT_SERVE_SERVICES),
35
33
  resolve: resolveInstance,
36
34
  answer: answerInstance,
37
- status: statusInstances,
38
35
  };
39
- export async function main(argv, services) {
36
+ export function createCli(services) {
40
37
  const program = new Command()
41
38
  .name("loopy")
42
- .description("Host the loopy Temporal Worker Process.")
39
+ .description("Run durable local agent workflows on Temporal.")
43
40
  .version(LOOPY_VERSION)
44
41
  .option("-c, --config <path>", "loopy config TOML (default: ~/.config/loopy/config.toml)")
45
42
  .addOption(new Option("--log-level <level>", "override the configured log level").choices([
@@ -48,7 +45,7 @@ export async function main(argv, services) {
48
45
  program.addHelpText("after", `\n${helpPlaybook()}`);
49
46
  program
50
47
  .command("guide")
51
- .description("Print operator guidance for a topic (offline; no config or Temporal needed).")
48
+ .description("Learn how to configure, author, run, and recover workflows.")
52
49
  .argument("[topic]", `one of: ${guideTopicNames().join(", ")}`)
53
50
  .action((topic) => {
54
51
  if (topic === undefined) {
@@ -63,7 +60,7 @@ export async function main(argv, services) {
63
60
  });
64
61
  program
65
62
  .command("loop")
66
- .description("Run the control and agent Worker Entities until interrupted.")
63
+ .description("Run workflows until interrupted.")
67
64
  .option("-w, --workflows <path>", "directory of workflow modules (overrides the config)")
68
65
  .action(async (loopOptions) => {
69
66
  const options = program.opts();
@@ -73,7 +70,7 @@ export async function main(argv, services) {
73
70
  });
74
71
  program
75
72
  .command("resolve")
76
- .description("Resume a recoverable call or reconcile an ambiguous external operation.")
73
+ .description("Resume or reconcile a parked agent call.")
77
74
  .argument("<workflow-id>", "instance Workflow ID")
78
75
  .option("--call <address>", "call address, for example reviewer/call/2")
79
76
  .option("--retry", "retry the call (an ambiguous prior call must no longer mutate state)")
@@ -94,7 +91,7 @@ export async function main(argv, services) {
94
91
  });
95
92
  program
96
93
  .command("answer")
97
- .description("Answer an instance call parked on ctx.ask, over any channel.")
94
+ .description("Answer a workflow waiting for human input.")
98
95
  .argument("<workflow-id>", "instance Workflow ID")
99
96
  .argument("<text>", "the answer text delivered to the waiting ask")
100
97
  .option("--call <address>", "call address, for example confirm-drop/call/1")
@@ -109,19 +106,10 @@ export async function main(argv, services) {
109
106
  const state = await services.answer(workflowId, request, settings);
110
107
  process.stdout.write(`${JSON.stringify(state)}\n`);
111
108
  });
112
- program
113
- .command("status")
114
- .description("Report loopy instance Executions from Temporal as NDJSON.")
115
- .argument("[workflow-id]", "describe one instance instead of listing all")
116
- .action(async (workflowId) => {
117
- const options = program.opts();
118
- const settings = loadSettings(options.config);
119
- startLogging(settings, options.logLevel);
120
- const views = await services.status(settings, workflowId);
121
- for (const view of views)
122
- process.stdout.write(`${JSON.stringify(view)}\n`);
123
- });
124
- await program.parseAsync([...argv]);
109
+ return program;
110
+ }
111
+ export async function main(argv, services) {
112
+ await createCli(services).parseAsync([...argv]);
125
113
  }
126
114
  export async function serve(settings, registries, services) {
127
115
  const processLock = new WorkerProcessLock(join(settings.workingDirectory, "worker.lock"));
@@ -218,30 +206,6 @@ export async function answerInstance(workflowId, request, settings, connect = co
218
206
  await connection.close();
219
207
  }
220
208
  }
221
- export async function statusInstances(settings, workflowId, connect = connectClient) {
222
- const connection = await connect(settings.temporal);
223
- try {
224
- const client = connection.client.workflow;
225
- if (workflowId !== undefined) {
226
- try {
227
- return [await describeInstance(client, workflowId)];
228
- }
229
- catch (error) {
230
- // A listing only describes IDs Visibility just returned, but an explicit ID comes from an
231
- // operator and may be stale or mistyped. Report that as a clean CLI error rather than
232
- // letting the raw WorkflowNotFoundError escape as an unhandled stack trace.
233
- if (error instanceof WorkflowNotFoundError) {
234
- throw new CliError(`no loopy instance found with ID ${JSON.stringify(workflowId)}`);
235
- }
236
- throw error;
237
- }
238
- }
239
- return await listInstances(client);
240
- }
241
- finally {
242
- await connection.close();
243
- }
244
- }
245
209
  export async function runExecutable(argv, services) {
246
210
  try {
247
211
  await main(argv, services);