opencode-gitlab-duo-agentic-custom-tools 0.3.1 → 0.3.3

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 (2) hide show
  1. package/dist/index.js +55 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -359,16 +359,12 @@ async function createPluginHooks(input) {
359
359
  always: ["*"],
360
360
  metadata: {}
361
361
  });
362
- const url = new URL(`/session/${encodeURIComponent(ctx.sessionID)}/todo`, input.serverUrl);
363
- const response = await fetch(url);
364
- if (!response.ok) {
365
- throw new Error(`Failed to read todos: ${response.status} ${response.statusText}`);
366
- }
367
- const payload = await response.json();
368
- if (Array.isArray(payload)) {
369
- return JSON.stringify(payload, null, 2);
370
- }
371
- return "[]";
362
+ const response = await input.client.session.todo({
363
+ path: { id: ctx.sessionID },
364
+ throwOnError: true
365
+ });
366
+ const payload = response.data ?? [];
367
+ return JSON.stringify(payload, null, 2);
372
368
  }
373
369
  })
374
370
  },
@@ -1325,9 +1321,16 @@ function mapDuoToolRequest(toolName, args) {
1325
1321
  case "shell_command": {
1326
1322
  const command = asString2(args.command);
1327
1323
  if (!command) return { toolName, args };
1324
+ const bridged = mapTodoBridgeCommand(command);
1325
+ if (bridged) return bridged;
1328
1326
  return { toolName: "bash", args: { command, description: "Run shell command", workdir: "." } };
1329
1327
  }
1330
1328
  case "run_command": {
1329
+ const command = asString2(args.command);
1330
+ if (command) {
1331
+ const bridged = mapTodoBridgeCommand(command);
1332
+ if (bridged) return bridged;
1333
+ }
1331
1334
  const program = asString2(args.program);
1332
1335
  if (program === TODO_READ_PROGRAM) {
1333
1336
  return { toolName: "todoread", args: {} };
@@ -1341,7 +1344,6 @@ function mapDuoToolRequest(toolName, args) {
1341
1344
  if (Array.isArray(args.arguments)) parts.push(...args.arguments.map((a) => shellQuote(String(a))));
1342
1345
  return { toolName: "bash", args: { command: parts.join(" "), description: "Run command", workdir: "." } };
1343
1346
  }
1344
- const command = asString2(args.command);
1345
1347
  if (!command) return { toolName, args };
1346
1348
  return { toolName: "bash", args: { command, description: "Run command", workdir: "." } };
1347
1349
  }
@@ -1384,8 +1386,30 @@ function mapDuoToolRequest(toolName, args) {
1384
1386
  function asString2(value) {
1385
1387
  return typeof value === "string" ? value : void 0;
1386
1388
  }
1389
+ function mapTodoBridgeCommand(command) {
1390
+ const normalized = command.trim();
1391
+ if (normalized === TODO_READ_PROGRAM) {
1392
+ return { toolName: "todoread", args: {} };
1393
+ }
1394
+ if (normalized === TODO_WRITE_PROGRAM) {
1395
+ return invalidTool("todowrite", `${TODO_WRITE_PROGRAM} expects JSON payload after command prefix`);
1396
+ }
1397
+ if (!normalized.startsWith(`${TODO_WRITE_PROGRAM} `)) {
1398
+ return null;
1399
+ }
1400
+ const payload = normalized.slice(TODO_WRITE_PROGRAM.length).trim();
1401
+ if (!payload) {
1402
+ return invalidTool("todowrite", `${TODO_WRITE_PROGRAM} expects JSON payload after command prefix`);
1403
+ }
1404
+ return mapTodoWritePayload(payload);
1405
+ }
1387
1406
  function mapTodoWriteCall(rawArguments) {
1388
- const payloadResult = parseTodoPayload(rawArguments);
1407
+ const payloadResult = parseTodoPayloadFromArguments(rawArguments);
1408
+ if ("error" in payloadResult) return invalidTool("todowrite", payloadResult.error);
1409
+ return mapTodoWritePayload(payloadResult.payload);
1410
+ }
1411
+ function mapTodoWritePayload(rawPayload) {
1412
+ const payloadResult = parseTodoPayload(rawPayload);
1389
1413
  if ("error" in payloadResult) return invalidTool("todowrite", payloadResult.error);
1390
1414
  const todosResult = parseTodos(payloadResult.payload);
1391
1415
  if ("error" in todosResult) return invalidTool("todowrite", todosResult.error);
@@ -1396,7 +1420,7 @@ function mapTodoWriteCall(rawArguments) {
1396
1420
  }
1397
1421
  };
1398
1422
  }
1399
- function parseTodoPayload(rawArguments) {
1423
+ function parseTodoPayloadFromArguments(rawArguments) {
1400
1424
  if (!Array.isArray(rawArguments) || rawArguments.length === 0) {
1401
1425
  return {
1402
1426
  error: `${TODO_WRITE_PROGRAM} expects JSON payload in arguments[0]`
@@ -1408,8 +1432,12 @@ function parseTodoPayload(rawArguments) {
1408
1432
  error: `${TODO_WRITE_PROGRAM} expects arguments[0] to be a JSON string`
1409
1433
  };
1410
1434
  }
1435
+ return { payload: rawPayload };
1436
+ }
1437
+ function parseTodoPayload(rawPayload) {
1438
+ const normalized = unwrapWrappingQuotes(rawPayload);
1411
1439
  try {
1412
- const parsed = JSON.parse(rawPayload);
1440
+ const parsed = JSON.parse(normalized);
1413
1441
  if (!isRecord(parsed)) {
1414
1442
  return {
1415
1443
  error: `${TODO_WRITE_PROGRAM} payload must be a JSON object`
@@ -1422,6 +1450,16 @@ function parseTodoPayload(rawArguments) {
1422
1450
  };
1423
1451
  }
1424
1452
  }
1453
+ function unwrapWrappingQuotes(value) {
1454
+ const trimmed = value.trim();
1455
+ if (trimmed.length < 2) return trimmed;
1456
+ const first = trimmed[0];
1457
+ const last = trimmed[trimmed.length - 1];
1458
+ if (first === last && (first === "'" || first === '"')) {
1459
+ return trimmed.slice(1, -1);
1460
+ }
1461
+ return trimmed;
1462
+ }
1425
1463
  function parseTodos(payload) {
1426
1464
  const rawTodos = payload.todos;
1427
1465
  if (!Array.isArray(rawTodos)) {
@@ -1630,10 +1668,9 @@ var TOOL_ALLOWLIST = [
1630
1668
  ];
1631
1669
  var TODO_BRIDGE_INSTRUCTIONS = [
1632
1670
  "Todo bridge (required):",
1633
- '- For todo write/update, call run_command with program="__todo_write__".',
1634
- "- For __todo_write__, pass arguments[0] as a JSON string with shape:",
1635
- ' {"todos":[{"content":"...","status":"pending|in_progress|completed|cancelled","priority":"high|medium|low"}]}',
1636
- '- For todo read, call run_command with program="__todo_read__" and arguments=[].',
1671
+ "- For todo write/update, call run_command with command:",
1672
+ ' __todo_write__ {"todos":[{"content":"...","status":"pending|in_progress|completed|cancelled","priority":"high|medium|low"}]}',
1673
+ "- For todo read, call run_command with command: __todo_read__",
1637
1674
  "- Use strict JSON with double quotes.",
1638
1675
  "- If validation fails, correct payload and retry.",
1639
1676
  "- Do not use regular shell commands for todo operations."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gitlab-duo-agentic-custom-tools",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "OpenCode plugin and provider for GitLab Duo Agentic workflows",
5
5
  "license": "MIT",
6
6
  "type": "module",