@integrity-labs/agt-cli 0.28.770 → 0.28.772

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/bin/agt.js CHANGED
@@ -41,7 +41,7 @@ import {
41
41
  success,
42
42
  table,
43
43
  warn
44
- } from "../chunk-E4YS6E4T.js";
44
+ } from "../chunk-SBAX57SN.js";
45
45
  import {
46
46
  getProjectDir,
47
47
  isSessionResumeDisabled,
@@ -5467,7 +5467,7 @@ import { execFileSync, execSync } from "child_process";
5467
5467
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5468
5468
  import chalk18 from "chalk";
5469
5469
  import ora16 from "ora";
5470
- var cliVersion = true ? "0.28.770" : "dev";
5470
+ var cliVersion = true ? "0.28.772" : "dev";
5471
5471
  async function fetchLatestVersion() {
5472
5472
  const host2 = getHost();
5473
5473
  if (!host2) return null;
@@ -6658,7 +6658,7 @@ function handleError(err) {
6658
6658
  }
6659
6659
 
6660
6660
  // src/bin/agt.ts
6661
- var cliVersion2 = true ? "0.28.770" : "dev";
6661
+ var cliVersion2 = true ? "0.28.772" : "dev";
6662
6662
  var program = new Command();
6663
6663
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6664
6664
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -6452,7 +6452,7 @@ function exchangeFailureKind(err) {
6452
6452
  }
6453
6453
 
6454
6454
  // src/lib/api-client.ts
6455
- var agtCliVersion = true ? "0.28.770" : "dev";
6455
+ var agtCliVersion = true ? "0.28.772" : "dev";
6456
6456
  var lastConfigHash = null;
6457
6457
  function setConfigHash(hash) {
6458
6458
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -10655,4 +10655,4 @@ export {
10655
10655
  managerInstallSystemUnitCommand,
10656
10656
  managerUninstallSystemUnitCommand
10657
10657
  };
10658
- //# sourceMappingURL=chunk-E4YS6E4T.js.map
10658
+ //# sourceMappingURL=chunk-SBAX57SN.js.map
@@ -58,7 +58,7 @@ import {
58
58
  safeWriteJsonAtomic,
59
59
  setConfigHash,
60
60
  tripClass
61
- } from "../chunk-E4YS6E4T.js";
61
+ } from "../chunk-SBAX57SN.js";
62
62
  import {
63
63
  getProjectDir as getProjectDir2,
64
64
  getReadyTasks,
@@ -13530,7 +13530,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13530
13530
  var lastVersionCheckAt = 0;
13531
13531
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13532
13532
  var lastResponsivenessProbeAt = 0;
13533
- var agtCliVersion = true ? "0.28.770" : "dev";
13533
+ var agtCliVersion = true ? "0.28.772" : "dev";
13534
13534
  function resolveBrewPath(execFileSync2) {
13535
13535
  try {
13536
13536
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
package/dist/mcp/xero.js CHANGED
@@ -116594,6 +116594,81 @@ async function getXeroRepeatingInvoice(repeatingInvoiceID) {
116594
116594
  }
116595
116595
  }
116596
116596
 
116597
+ // src/helpers/repeating-invoice-generation.ts
116598
+ function normaliseStatus(v) {
116599
+ if (v === void 0 || v === null) return null;
116600
+ if (typeof v !== "string" && typeof v !== "number") return null;
116601
+ const s = String(v).trim();
116602
+ return s.length > 0 ? s.toUpperCase() : null;
116603
+ }
116604
+ function generationVerdict(t) {
116605
+ const status = normaliseStatus(t.status);
116606
+ if (!status) {
116607
+ return {
116608
+ willGenerate: false,
116609
+ reason: "GENERATION UNKNOWN: Xero returned no status for this template."
116610
+ };
116611
+ }
116612
+ if (status === "DELETED" || status === "VOIDED") {
116613
+ return {
116614
+ willGenerate: false,
116615
+ reason: `WILL NOT GENERATE: template is ${status}.`
116616
+ };
116617
+ }
116618
+ if (status !== "AUTHORISED") {
116619
+ return {
116620
+ willGenerate: false,
116621
+ reason: `WILL NOT GENERATE: status is ${status}. Only AUTHORISED templates generate invoices. Set it with update-repeating-invoice \u2014 and confirm the amount, cadence and counterparty with a human first, because authorising a template starts billing someone on a schedule.`
116622
+ };
116623
+ }
116624
+ const end = t.schedule?.endDate;
116625
+ const next = t.schedule?.nextScheduledDate;
116626
+ if (end && isBoundaryAmbiguous(end)) {
116627
+ return {
116628
+ willGenerate: false,
116629
+ reason: `GENERATION UNKNOWN: AUTHORISED and the schedule ends ${end}, which is within a day of now. Xero generates in the organisation's time zone and this check compares in UTC, so the two can disagree by a calendar day at the boundary. Confirm in Xero before acting on this one.`
116630
+ };
116631
+ }
116632
+ if (end && isPast(end)) {
116633
+ return {
116634
+ willGenerate: false,
116635
+ reason: `WILL NOT GENERATE: AUTHORISED but the schedule ended ${end}.`
116636
+ };
116637
+ }
116638
+ if (!next) {
116639
+ return {
116640
+ willGenerate: false,
116641
+ reason: "GENERATION UNKNOWN: AUTHORISED but Xero returned no next scheduled date, so the next run cannot be confirmed from here."
116642
+ };
116643
+ }
116644
+ return {
116645
+ willGenerate: true,
116646
+ reason: `Generates: AUTHORISED, next invoice ${next}${end ? `, ends ${end}` : ""}.`
116647
+ };
116648
+ }
116649
+ function isPast(dateStr) {
116650
+ const t = Date.parse(dateStr);
116651
+ if (Number.isNaN(t)) return false;
116652
+ const endOfDay = new Date(t);
116653
+ endOfDay.setUTCHours(23, 59, 59, 999);
116654
+ return endOfDay.getTime() < Date.now();
116655
+ }
116656
+ var MAX_TZ_AHEAD_MS = 14 * 60 * 60 * 1e3;
116657
+ var MAX_TZ_BEHIND_MS = 12 * 60 * 60 * 1e3;
116658
+ function isBoundaryAmbiguous(dateStr) {
116659
+ const t = Date.parse(dateStr);
116660
+ if (Number.isNaN(t)) return false;
116661
+ const endOfDayUtc = new Date(t);
116662
+ endOfDayUtc.setUTCHours(23, 59, 59, 999);
116663
+ const end = endOfDayUtc.getTime();
116664
+ const now = Date.now();
116665
+ return now >= end - MAX_TZ_AHEAD_MS && now <= end + MAX_TZ_BEHIND_MS;
116666
+ }
116667
+ function sendSettingsLine(t) {
116668
+ const flag = (v) => v === void 0 ? "unknown" : v ? "yes" : "no";
116669
+ return `Sending: approvedForSending=${flag(t.approvedForSending)}, sendCopy=${flag(t.sendCopy)}, markAsSent=${flag(t.markAsSent)}, includePDF=${flag(t.includePDF)}` + (t.approvedForSending === false ? " \u2014 NOT approved for sending, so generated invoices are not emailed to the contact." : "");
116670
+ }
116671
+
116597
116672
  // src/tools/get/get-repeating-invoice.tool.ts
116598
116673
  var GetRepeatingInvoiceTool = CreateXeroTool(
116599
116674
  "get-repeating-invoice",
@@ -116630,6 +116705,8 @@ var GetRepeatingInvoiceTool = CreateXeroTool(
116630
116705
  type: "text",
116631
116706
  text: [
116632
116707
  `RepeatingInvoiceID: ${t.repeatingInvoiceID}`,
116708
+ // CS-1635: state the conclusion, not just the evidence.
116709
+ generationVerdict(t).reason,
116633
116710
  t.contact ? `Contact: ${t.contact.name} (${t.contact.contactID})` : null,
116634
116711
  t.type ? `Type: ${t.type}` : null,
116635
116712
  t.status ? `Status: ${t.status}` : null,
@@ -116638,6 +116715,7 @@ var GetRepeatingInvoiceTool = CreateXeroTool(
116638
116715
  t.subTotal !== void 0 ? `Sub Total: ${t.subTotal}` : null,
116639
116716
  t.totalTax !== void 0 ? `Total Tax: ${t.totalTax}` : null,
116640
116717
  t.currencyCode ? `Currency: ${t.currencyCode}` : null,
116718
+ sendSettingsLine(t),
116641
116719
  t.lineAmountTypes ? `Line Amount Types: ${t.lineAmountTypes}` : null,
116642
116720
  t.schedule ? `Schedule: every ${t.schedule.period ?? "?"} ${t.schedule.unit ?? ""}, start ${t.schedule.startDate ?? "?"}, due ${t.schedule.dueDate ?? "?"} (${t.schedule.dueDateType ?? "?"}), next ${t.schedule.nextScheduledDate ?? "?"}, end ${t.schedule.endDate ?? "open-ended"}` : null,
116643
116721
  t.lineItems?.length ? `Line Items:
@@ -116786,6 +116864,15 @@ async function listXeroAgedPayablesByContact(contactId, reportDate, invoicesFrom
116786
116864
  }
116787
116865
  }
116788
116866
 
116867
+ // src/helpers/unreconciled-blind-spot.ts
116868
+ var UNRECONCILED_BLIND_SPOT_NOTE = "INCOMPLETE BY DESIGN \u2014 read before quoting any figure from this result.\nXero's Accounting API exposes LEDGER records. Bank STATEMENT LINES that have never been matched into the ledger are not exposed at all, and neither are any notes left on them. Money can therefore be in the bank account and absent from this data.\nSo any receivables, payables, cashflow or aged-debtors figure derived from this may be INCOMPLETE OR INACCURATE, and THE SIZE AND DIRECTION OF THE ERROR CANNOT BE DETERMINED FROM THIS RESPONSE \u2014 an unmatched line might be a customer receipt, a supplier payment or a bank fee, and nothing here says which, or how many there are. An invoice can read AUTHORISED and fully unpaid while the customer's payment is already sitting in the bank account.\nWhen reporting a figure from this data, say that unmatched bank activity is not included and that you cannot see it. Do not describe a customer as overdue, and do not request or draft a payment chase, on this evidence alone: check the Xero bank reconciliation screen, or ask a human to. (CS-1638)";
116869
+ function unreconciledBlindSpotBlock() {
116870
+ return { type: "text", text: UNRECONCILED_BLIND_SPOT_NOTE };
116871
+ }
116872
+ function withUnreconciledBlindSpotNote(result) {
116873
+ return { ...result, content: [...result.content, unreconciledBlindSpotBlock()] };
116874
+ }
116875
+
116789
116876
  // src/tools/list/list-aged-payables-by-contact.tool.ts
116790
116877
  var ListAgedPayablesByContact = CreateXeroTool(
116791
116878
  "list-aged-payables-by-contact",
@@ -116811,7 +116898,7 @@ var ListAgedPayablesByContact = CreateXeroTool(
116811
116898
  }
116812
116899
  const agedPayablesReport = response.result;
116813
116900
  const filter2 = formatAgedReportFilter(invoicesFromDate, invoicesToDate);
116814
- return {
116901
+ return withUnreconciledBlindSpotNote({
116815
116902
  content: [
116816
116903
  {
116817
116904
  type: "text",
@@ -116830,7 +116917,7 @@ var ListAgedPayablesByContact = CreateXeroTool(
116830
116917
  text: JSON.stringify(agedPayablesReport.rows, null, 2)
116831
116918
  }
116832
116919
  ]
116833
- };
116920
+ });
116834
116921
  }
116835
116922
  );
116836
116923
  var list_aged_payables_by_contact_tool_default = ListAgedPayablesByContact;
@@ -116902,7 +116989,7 @@ var ListAgedReceivablesByContact = CreateXeroTool(
116902
116989
  }
116903
116990
  const agedReceivablesReport = response.result;
116904
116991
  const filter2 = formatAgedReportFilter(invoicesFromDate, invoicesToDate);
116905
- return {
116992
+ return withUnreconciledBlindSpotNote({
116906
116993
  content: [
116907
116994
  {
116908
116995
  type: "text",
@@ -116921,7 +117008,7 @@ var ListAgedReceivablesByContact = CreateXeroTool(
116921
117008
  text: JSON.stringify(agedReceivablesReport.rows, null, 2)
116922
117009
  }
116923
117010
  ]
116924
- };
117011
+ });
116925
117012
  }
116926
117013
  );
116927
117014
  var list_aged_receivables_by_contact_tool_default = ListAgedReceivablesByContact;
@@ -116982,7 +117069,14 @@ var formatLineItem = (lineItem) => {
116982
117069
  // src/tools/list/list-bank-transactions.tool.ts
116983
117070
  var ListBankTransactionsTool = CreateXeroTool(
116984
117071
  "list-bank-transactions",
116985
- `List all bank transactions in Xero.
117072
+ `List Xero BankTransaction LEDGER records (spend-money / receive-money), each
117073
+ flagged Reconciled or Unreconciled.
117074
+ This is NOT the bank account, and the distinction is the point. Xero's
117075
+ Accounting API exposes BankTransaction records only. Bank STATEMENT LINES that
117076
+ have never been matched into the ledger are not exposed at all, so money can be
117077
+ in the bank account and absent from this list entirely. A balance, receivables
117078
+ or cashflow figure derived from this may be incomplete, and nothing here reveals
117079
+ by how much. (CS-1638)
116986
117080
  Ask the user if they want to see bank transactions for a specific bank account,
116987
117081
  or to see all bank transactions before running.
116988
117082
  Ask the user if they want the next page of quotes after running this tool if
@@ -117006,7 +117100,7 @@ var ListBankTransactionsTool = CreateXeroTool(
117006
117100
  };
117007
117101
  }
117008
117102
  const bankTransactions = response.result;
117009
- return {
117103
+ return withUnreconciledBlindSpotNote({
117010
117104
  content: [
117011
117105
  {
117012
117106
  type: "text",
@@ -117032,7 +117126,7 @@ var ListBankTransactionsTool = CreateXeroTool(
117032
117126
  ].filter(Boolean).join("\n")
117033
117127
  })) || []
117034
117128
  ]
117035
- };
117129
+ });
117036
117130
  }
117037
117131
  );
117038
117132
  var list_bank_transactions_tool_default = ListBankTransactionsTool;
@@ -117289,7 +117383,7 @@ async function listXeroInvoices(page = 1, contactIds, invoiceNumbers) {
117289
117383
  // src/tools/list/list-invoices.tool.ts
117290
117384
  var ListInvoicesTool = CreateXeroTool(
117291
117385
  "list-invoices",
117292
- "List invoices in Xero. This includes Draft, Submitted, and Paid invoices. Ask the user if they want to see invoices for a specific contact, invoice number, or to see all invoices before running. Ask the user if they want the next page of invoices after running this tool if 10 invoices are returned. If they want the next page, call this tool again with the next page number and the contact or invoice number if one was provided in the previous call.",
117386
+ `List invoices in Xero. This includes Draft, Submitted, and Paid invoices. CS-1638: an invoice reads AUTHORISED and fully unpaid until the customer's payment is RECONCILED, so "unpaid" here means "not yet matched in Xero", not "the money has not arrived". Do not chase on this evidence alone. Ask the user if they want to see invoices for a specific contact, invoice number, or to see all invoices before running. Ask the user if they want the next page of invoices after running this tool if 10 invoices are returned. If they want the next page, call this tool again with the next page number and the contact or invoice number if one was provided in the previous call.`,
117293
117387
  {
117294
117388
  page: external_exports.number(),
117295
117389
  contactIds: external_exports.array(external_exports.string()).optional(),
@@ -117309,7 +117403,7 @@ var ListInvoicesTool = CreateXeroTool(
117309
117403
  }
117310
117404
  const invoices = response.result;
117311
117405
  const returnLineItems = (invoiceNumbers?.length ?? 0) > 0;
117312
- return {
117406
+ return withUnreconciledBlindSpotNote({
117313
117407
  content: [
117314
117408
  {
117315
117409
  type: "text",
@@ -117344,7 +117438,7 @@ var ListInvoicesTool = CreateXeroTool(
117344
117438
  ].filter(Boolean).join("\n")
117345
117439
  })) || []
117346
117440
  ]
117347
- };
117441
+ });
117348
117442
  }
117349
117443
  );
117350
117444
  var list_invoices_tool_default = ListInvoicesTool;
@@ -119042,7 +119136,7 @@ async function listXeroRepeatingInvoices() {
119042
119136
  // src/tools/list/list-repeating-invoices.tool.ts
119043
119137
  var ListRepeatingInvoicesTool = CreateXeroTool(
119044
119138
  "list-repeating-invoices",
119045
- "List every repeating (recurring) invoice template configured on the Xero tenant. Each template defines an invoice that Xero auto-generates on a schedule (weekly/monthly/etc.). Use this to look up the RepeatingInvoiceID before calling get-repeating-invoice or update-repeating-invoice. The endpoint does not support pagination \u2014 all templates are returned.",
119139
+ "List every repeating (recurring) invoice template configured on the Xero tenant. Each template defines an invoice that Xero auto-generates on a schedule (weekly/monthly/etc.). Use this to look up the RepeatingInvoiceID before calling get-repeating-invoice or update-repeating-invoice. The endpoint does not support pagination \u2014 all templates are returned. CS-1635: every row states outright whether it WILL GENERATE and why, plus its next scheduled date and its sending settings. A template can be perfectly configured, sit in DRAFT, and generate nothing \u2014 read the verdict line rather than inferring from Status.",
119046
119140
  {},
119047
119141
  async () => {
119048
119142
  const response = await listXeroRepeatingInvoices();
@@ -119067,6 +119161,10 @@ var ListRepeatingInvoicesTool = CreateXeroTool(
119067
119161
  type: "text",
119068
119162
  text: [
119069
119163
  `RepeatingInvoiceID: ${t.repeatingInvoiceID}`,
119164
+ // CS-1635: the conclusion, first, because it is the question being
119165
+ // asked. Printing Status and leaving the reader to know that DRAFT
119166
+ // means "silent" is how 14 of 15 templates sat dead unnoticed.
119167
+ generationVerdict(t).reason,
119070
119168
  t.contact ? `Contact: ${t.contact.name} (${t.contact.contactID})` : null,
119071
119169
  t.type ? `Type: ${t.type}` : null,
119072
119170
  t.status ? `Status: ${t.status}` : null,
@@ -119074,6 +119172,12 @@ var ListRepeatingInvoicesTool = CreateXeroTool(
119074
119172
  t.total !== void 0 ? `Total: ${t.total}` : null,
119075
119173
  t.currencyCode ? `Currency: ${t.currencyCode}` : null,
119076
119174
  t.schedule ? `Schedule: every ${t.schedule.period ?? "?"} ${t.schedule.unit ?? ""} starting ${t.schedule.startDate ?? "?"}` : null,
119175
+ t.schedule?.nextScheduledDate ? `Next scheduled: ${t.schedule.nextScheduledDate}` : null,
119176
+ t.schedule?.endDate ? `Schedule ends: ${t.schedule.endDate}` : null,
119177
+ // CS-1635 asks for this by name: the send setting was not exposed
119178
+ // anywhere, so a template could generate and never reach the
119179
+ // customer with nothing in any tool saying so.
119180
+ sendSettingsLine(t),
119077
119181
  t.lineAmountTypes ? `Line Amount Types: ${t.lineAmountTypes}` : null
119078
119182
  ].filter(Boolean).join("\n")
119079
119183
  }))
@@ -120609,12 +120713,12 @@ async function updateXeroRepeatingInvoice(repeatingInvoiceID, patch) {
120609
120713
  error: `RepeatingInvoice ${repeatingInvoiceID} not found.`
120610
120714
  };
120611
120715
  }
120612
- const noChange = patch.reference === void 0 && patch.lineItems === void 0 && patch.status === void 0 && patch.contactId === void 0;
120716
+ const noChange = patch.reference === void 0 && patch.lineItems === void 0 && patch.status === void 0 && patch.contactId === void 0 && patch.approvedForSending === void 0;
120613
120717
  if (noChange) {
120614
120718
  return {
120615
120719
  result: null,
120616
120720
  isError: true,
120617
- error: "No fields supplied to update. Pass at least one of reference, lineItems, status, or contactId."
120721
+ error: "No fields supplied to update. Pass at least one of reference, lineItems, status, contactId, or approvedForSending."
120618
120722
  };
120619
120723
  }
120620
120724
  const xeroPatch = {};
@@ -120625,6 +120729,9 @@ async function updateXeroRepeatingInvoice(repeatingInvoiceID, patch) {
120625
120729
  if (patch.contactId !== void 0) {
120626
120730
  xeroPatch.contact = { contactID: patch.contactId };
120627
120731
  }
120732
+ if (patch.approvedForSending !== void 0) {
120733
+ xeroPatch.approvedForSending = patch.approvedForSending;
120734
+ }
120628
120735
  if (patch.lineItems !== void 0) {
120629
120736
  xeroPatch.lineItems = patch.lineItems.map((li) => ({
120630
120737
  description: li.description,
@@ -120674,15 +120781,19 @@ var UpdateRepeatingInvoiceTool = CreateXeroTool(
120674
120781
  status: external_exports.enum(["DRAFT", "AUTHORISED"]).optional().describe(
120675
120782
  "Template status. DRAFT templates do NOT generate invoices; AUTHORISED templates do. Flipping a draft to AUTHORISED is high-risk and should be explicitly confirmed with the user."
120676
120783
  ),
120677
- contactId: external_exports.string().optional().describe("Replace the counterparty. Look up the ContactID via list-contacts first.")
120784
+ contactId: external_exports.string().optional().describe("Replace the counterparty. Look up the ContactID via list-contacts first."),
120785
+ approvedForSending: external_exports.boolean().optional().describe(
120786
+ 'CS-1635: whether Xero emails each generated invoice to the contact. A template can generate invoices perfectly and never send them, which looks identical to "working" from every other field. Setting this true starts emailing a customer on a schedule, so confirm it with a human first.'
120787
+ )
120678
120788
  },
120679
120789
  async (params) => {
120680
- const { repeatingInvoiceID, reference, lineItems, status, contactId } = params;
120790
+ const { repeatingInvoiceID, reference, lineItems, status, contactId, approvedForSending } = params;
120681
120791
  const result = await updateXeroRepeatingInvoice(repeatingInvoiceID, {
120682
120792
  reference,
120683
120793
  lineItems,
120684
120794
  status,
120685
- contactId
120795
+ contactId,
120796
+ approvedForSending
120686
120797
  });
120687
120798
  if (result.isError) {
120688
120799
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.770",
3
+ "version": "0.28.772",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {