opencode-heartbeat-approval 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.
package/dist/index.js CHANGED
@@ -12333,8 +12333,8 @@ tool.schema = exports_external;
12333
12333
  // src/plugin.ts
12334
12334
  var DEFAULT_RUNNER_URL = "http://127.0.0.1:3210";
12335
12335
  var POLL_INTERVAL_MS = 1e4;
12336
- function getRunnerUrl() {
12337
- return process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
12336
+ function getRunnerUrl(override) {
12337
+ return override ?? process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
12338
12338
  }
12339
12339
  function buildHeaders() {
12340
12340
  const headers = { "Content-Type": "application/json" };
@@ -12344,8 +12344,8 @@ function buildHeaders() {
12344
12344
  }
12345
12345
  return headers;
12346
12346
  }
12347
- async function createGate(params) {
12348
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
12347
+ async function createGate(runnerUrl, params) {
12348
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
12349
12349
  method: "POST",
12350
12350
  headers: buildHeaders(),
12351
12351
  body: JSON.stringify(params)
@@ -12359,8 +12359,8 @@ async function createGate(params) {
12359
12359
  }
12360
12360
  return await resp.json();
12361
12361
  }
12362
- async function pollGate() {
12363
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
12362
+ async function pollGate(runnerUrl) {
12363
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
12364
12364
  method: "GET",
12365
12365
  headers: buildHeaders()
12366
12366
  });
@@ -12398,7 +12398,8 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12398
12398
  prompt: tool.schema.string().describe("What you need from the human \u2014 be specific and concise"),
12399
12399
  type: tool.schema.string().optional().describe("Type of request: 'approval' (need permission) or 'assistance' (need human help). Default: 'approval'"),
12400
12400
  artifacts: tool.schema.string().optional().describe("Comma-separated list of relevant file paths or artifact names"),
12401
- deadline_hours: tool.schema.number().optional().describe("Hours before the request expires (default: 24, max: 168)")
12401
+ deadline_hours: tool.schema.number().optional().describe("Hours before the request expires (default: 24, max: 168)"),
12402
+ runner_url: tool.schema.string().optional().describe("URL of this role's heartbeat runner (e.g., http://127.0.0.1:3211). Required for multi-role setups.")
12402
12403
  },
12403
12404
  async execute(args, ctx) {
12404
12405
  const artifacts = args.artifacts ? args.artifacts.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
@@ -12412,9 +12413,10 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12412
12413
  });
12413
12414
  }
12414
12415
  const requestType = args.type === "assistance" ? "assistance" : "approval";
12416
+ const resolvedUrl = getRunnerUrl(args.runner_url);
12415
12417
  let gateResult;
12416
12418
  try {
12417
- gateResult = await createGate({
12419
+ gateResult = await createGate(resolvedUrl, {
12418
12420
  prompt: args.prompt,
12419
12421
  artifacts,
12420
12422
  deadline_hours: args.deadline_hours,
@@ -12450,7 +12452,7 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12450
12452
  await sleep(POLL_INTERVAL_MS, ctx.abort);
12451
12453
  let poll;
12452
12454
  try {
12453
- poll = await pollGate();
12455
+ poll = await pollGate(resolvedUrl);
12454
12456
  } catch {
12455
12457
  await sleep(POLL_INTERVAL_MS, ctx.abort);
12456
12458
  continue;
package/dist/plugin.js CHANGED
@@ -12333,8 +12333,8 @@ tool.schema = exports_external;
12333
12333
  // src/plugin.ts
12334
12334
  var DEFAULT_RUNNER_URL = "http://127.0.0.1:3210";
12335
12335
  var POLL_INTERVAL_MS = 1e4;
12336
- function getRunnerUrl() {
12337
- return process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
12336
+ function getRunnerUrl(override) {
12337
+ return override ?? process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
12338
12338
  }
12339
12339
  function buildHeaders() {
12340
12340
  const headers = { "Content-Type": "application/json" };
@@ -12344,8 +12344,8 @@ function buildHeaders() {
12344
12344
  }
12345
12345
  return headers;
12346
12346
  }
12347
- async function createGate(params) {
12348
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
12347
+ async function createGate(runnerUrl, params) {
12348
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
12349
12349
  method: "POST",
12350
12350
  headers: buildHeaders(),
12351
12351
  body: JSON.stringify(params)
@@ -12359,8 +12359,8 @@ async function createGate(params) {
12359
12359
  }
12360
12360
  return await resp.json();
12361
12361
  }
12362
- async function pollGate() {
12363
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
12362
+ async function pollGate(runnerUrl) {
12363
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
12364
12364
  method: "GET",
12365
12365
  headers: buildHeaders()
12366
12366
  });
@@ -12398,7 +12398,8 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12398
12398
  prompt: tool.schema.string().describe("What you need from the human \u2014 be specific and concise"),
12399
12399
  type: tool.schema.string().optional().describe("Type of request: 'approval' (need permission) or 'assistance' (need human help). Default: 'approval'"),
12400
12400
  artifacts: tool.schema.string().optional().describe("Comma-separated list of relevant file paths or artifact names"),
12401
- deadline_hours: tool.schema.number().optional().describe("Hours before the request expires (default: 24, max: 168)")
12401
+ deadline_hours: tool.schema.number().optional().describe("Hours before the request expires (default: 24, max: 168)"),
12402
+ runner_url: tool.schema.string().optional().describe("URL of this role's heartbeat runner (e.g., http://127.0.0.1:3211). Required for multi-role setups.")
12402
12403
  },
12403
12404
  async execute(args, ctx) {
12404
12405
  const artifacts = args.artifacts ? args.artifacts.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
@@ -12412,9 +12413,10 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12412
12413
  });
12413
12414
  }
12414
12415
  const requestType = args.type === "assistance" ? "assistance" : "approval";
12416
+ const resolvedUrl = getRunnerUrl(args.runner_url);
12415
12417
  let gateResult;
12416
12418
  try {
12417
- gateResult = await createGate({
12419
+ gateResult = await createGate(resolvedUrl, {
12418
12420
  prompt: args.prompt,
12419
12421
  artifacts,
12420
12422
  deadline_hours: args.deadline_hours,
@@ -12450,7 +12452,7 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
12450
12452
  await sleep(POLL_INTERVAL_MS, ctx.abort);
12451
12453
  let poll;
12452
12454
  try {
12453
- poll = await pollGate();
12455
+ poll = await pollGate(resolvedUrl);
12454
12456
  } catch {
12455
12457
  await sleep(POLL_INTERVAL_MS, ctx.abort);
12456
12458
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-heartbeat-approval",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "OpenCode plugin providing request_human_input MCP tool for Heartbeat pipeline (approval + assistance)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/plugin.ts CHANGED
@@ -18,8 +18,8 @@ interface PollResponse {
18
18
  type?: string;
19
19
  }
20
20
 
21
- function getRunnerUrl(): string {
22
- return process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
21
+ function getRunnerUrl(override?: string): string {
22
+ return override ?? process.env.HEARTBEAT_RUNNER_URL ?? DEFAULT_RUNNER_URL;
23
23
  }
24
24
 
25
25
  function buildHeaders(): Record<string, string> {
@@ -37,14 +37,14 @@ interface ConflictResponse {
37
37
  existing_approval_id: string;
38
38
  }
39
39
 
40
- async function createGate(params: {
40
+ async function createGate(runnerUrl: string, params: {
41
41
  prompt: string;
42
42
  artifacts?: string[];
43
43
  deadline_hours?: number;
44
44
  phase?: string;
45
45
  type?: string;
46
46
  }): Promise<CreateResponse | ConflictResponse> {
47
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
47
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
48
48
  method: "POST",
49
49
  headers: buildHeaders(),
50
50
  body: JSON.stringify(params),
@@ -59,8 +59,8 @@ async function createGate(params: {
59
59
  return (await resp.json()) as CreateResponse;
60
60
  }
61
61
 
62
- async function pollGate(): Promise<PollResponse> {
63
- const resp = await fetch(`${getRunnerUrl()}/api/approval`, {
62
+ async function pollGate(runnerUrl: string): Promise<PollResponse> {
63
+ const resp = await fetch(`${runnerUrl}/api/approval`, {
64
64
  method: "GET",
65
65
  headers: buildHeaders(),
66
66
  });
@@ -106,6 +106,10 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
106
106
  .number()
107
107
  .optional()
108
108
  .describe("Hours before the request expires (default: 24, max: 168)"),
109
+ runner_url: tool.schema
110
+ .string()
111
+ .optional()
112
+ .describe("URL of this role's heartbeat runner (e.g., http://127.0.0.1:3211). Required for multi-role setups."),
109
113
  },
110
114
  async execute(args, ctx) {
111
115
  const artifacts = args.artifacts
@@ -121,10 +125,11 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
121
125
  });
122
126
  }
123
127
  const requestType = (args.type === "assistance" ? "assistance" : "approval") as "approval" | "assistance";
128
+ const resolvedUrl = getRunnerUrl(args.runner_url);
124
129
 
125
130
  let gateResult: CreateResponse | ConflictResponse;
126
131
  try {
127
- gateResult = await createGate({
132
+ gateResult = await createGate(resolvedUrl, {
128
133
  prompt: args.prompt,
129
134
  artifacts,
130
135
  deadline_hours: args.deadline_hours,
@@ -165,7 +170,7 @@ Returns: { status: "approved" | "rejected" | "expired" | "unavailable" | "cancel
165
170
 
166
171
  let poll: PollResponse;
167
172
  try {
168
- poll = await pollGate();
173
+ poll = await pollGate(resolvedUrl);
169
174
  } catch {
170
175
  await sleep(POLL_INTERVAL_MS, ctx.abort);
171
176
  continue;