@miadi/connector 0.1.15 → 0.1.17

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/tools.js CHANGED
@@ -23,6 +23,9 @@ import { discoverProviders, jevConfigOf, resolveProvider, routerPreflight, PROVI
23
23
  import { authorizesActions, missionStatus, primaryIssueOf, resolveMissionSubject } from "./mission-status.js";
24
24
  import { candidatesFor, CRITICALITIES, jevAdapter, modelPreflight, PREFLIGHT_CONTRACT, PREFLIGHT_VERSION, TASK_TYPES, } from "./model-preflight.js";
25
25
  import { checkGrant, isBusy, steerAttempts, steeringGrantOf, steerSession } from "./steer.js";
26
+ import { factoryLedgerPath, readFactoryReceipts, receiptsForRecord, recordsForSession } from "./factory-receipt.js";
27
+ import { missionResult, redactResult } from "./mission-result.js";
28
+ import { factoryDir as defaultFactoryDir } from "./queue-state.js";
26
29
  import { join } from "node:path";
27
30
  import { artefactVisibility, readArtefactWeave, saveResearchArtefact } from "@miadi/inquiry-weave";
28
31
  import { ResearchUploads, UploadRefusal } from "./uploads.js";
@@ -109,6 +112,46 @@ export function githubAccess(status, hasToken) {
109
112
  return "forbidden_or_rate_limited";
110
113
  return `github_${status}`;
111
114
  }
115
+ /** GitHub answers kept briefly, so one status read does not spend the unauthenticated rate limit twice. */
116
+ const githubCache = new Map();
117
+ const GITHUB_CACHE_MS = 5 * 60_000;
118
+ /** A GitHub REST read as the connector can make it: GITHUB_TOKEN when the host has one, else anonymous. */
119
+ export function githubGetter(fetchImpl = fetch, token = process.env.GITHUB_TOKEN) {
120
+ return async (path) => {
121
+ // Keyed by whether a token was sent: an anonymous 404 is not a token's answer (#922 R9).
122
+ const key = `${token ? "token" : "anonymous"}:${path}`;
123
+ const hit = githubCache.get(key);
124
+ if (hit && Date.now() - hit.at < GITHUB_CACHE_MS)
125
+ return hit.answer;
126
+ const headers = { accept: "application/vnd.github+json", ...(token ? { authorization: "Bearer " + token } : {}) };
127
+ let answer;
128
+ try {
129
+ const res = await fetchImpl(`https://api.github.com${path}`, { headers, signal: AbortSignal.timeout(15_000) });
130
+ answer = res.ok ? { ok: true, json: await res.json() } : { ok: false, status: res.status, access: githubAccess(res.status, Boolean(token)) };
131
+ }
132
+ catch {
133
+ answer = { ok: false, status: 0, access: "unreachable" };
134
+ }
135
+ // Rate limits and outages are not kept: the next read asks again.
136
+ if (answer.ok || answer.status === 404) {
137
+ if (githubCache.size >= 500)
138
+ for (const [k, v] of githubCache)
139
+ if (Date.now() - v.at >= GITHUB_CACHE_MS)
140
+ githubCache.delete(k);
141
+ if (githubCache.size < 1000)
142
+ githubCache.set(key, { at: Date.now(), answer });
143
+ }
144
+ return answer;
145
+ };
146
+ }
147
+ /** Whether the steering transport works now: registered is not operational (jgwill/Miadi#909). */
148
+ export function steeringTransport(tmux) {
149
+ if (!tmux)
150
+ return { tool: "registered", transport: "unavailable", reason: "The connector host was started without a steering surface." };
151
+ if (tmux.available && !tmux.available())
152
+ return { tool: "registered", transport: "unavailable", reason: "The host's tmux server does not answer." };
153
+ return { tool: "registered", transport: "operational" };
154
+ }
112
155
  function episodeRef(input) {
113
156
  // miadi-chronicle://316, miadi-chronicle:316, chronicle:<folder>, a folder, or a number
114
157
  return encodeURIComponent(input.replace(/^miadi-chronicle:(\/\/)?/, "").replace(/^chronicle:/, "").trim());
@@ -137,15 +180,19 @@ export function registerTools(server, ctx) {
137
180
  if (!viewer || viewer.api_tier === "write" || r.actor.person_id === viewer.id)
138
181
  return r;
139
182
  const body = { ...r.body };
140
- for (const k of ["session", "cwd", "session_id"])
183
+ // A steer's binding, pane, target and artifact path name the seat as the session does (#922 R2).
184
+ for (const k of ["session", "cwd", "session_id", "binding", "pane"])
141
185
  delete body[k];
142
186
  for (const k of ["markdown", "transcript"])
143
187
  if (typeof body[k] === "string")
144
188
  body[k] = `${body[k].length} chars`;
145
189
  const receipt = r.completion_receipt ? { ...r.completion_receipt } : undefined;
146
190
  if (receipt)
147
- for (const k of ["to", "file", "session_id"])
191
+ for (const k of ["to", "file", "session_id", "target", "artifact"])
148
192
  delete receipt[k];
193
+ // A steer's message names its target pane.
194
+ if (receipt && r.kind === "session_steer_request")
195
+ delete receipt.message;
149
196
  return { ...r, body, ...(receipt ? { completion_receipt: receipt } : {}) };
150
197
  };
151
198
  const actorOf = (person, auth) => {
@@ -178,6 +225,9 @@ export function registerTools(server, ctx) {
178
225
  const records = () => all().map(redact);
179
226
  const uploads = new ResearchUploads(join(config.stateDir, "uploads"));
180
227
  const touching = (ref) => records().filter((r) => r.refs.includes(ref) || r.evidence_refs.includes(ref) || r.id === ref);
228
+ /** The factory runner's delivery receipts, read fresh: operator data, for the write tier only. */
229
+ const receipts = () => readFactoryReceipts(factoryLedgerPath(ctx.factoryDir ?? defaultFactoryDir()));
230
+ const github = githubGetter(ctx.approval?.fetchImpl ?? fetch);
181
231
  // ── reads ──────────────────────────────────────────────────────────────
182
232
  server.registerTool("get_capabilities", {
183
233
  title: "What this connector can do for you",
@@ -207,6 +257,8 @@ export function registerTools(server, ctx) {
207
257
  ledger: "connector ledger (append-only, /srv/miadi/connector)",
208
258
  },
209
259
  tools: TOOL_STATUS,
260
+ // Registered is not operational: whether a steer can reach a pane on this host now (jgwill/Miadi#909).
261
+ steering: steeringTransport(ctx.tmux),
210
262
  foundation_read: {
211
263
  permission: FOUNDATIONS_PERMISSION,
212
264
  held: foundations,
@@ -354,7 +406,13 @@ export function registerTools(server, ctx) {
354
406
  requireTier(person, "write");
355
407
  const id = session_id.replace(/^session:/, "");
356
408
  const session = await miadi.get(person.token, `/api/session/${encodeURIComponent(id)}`);
357
- return { ...session, connector_records: touching(`session:${id}`) };
409
+ // The missions the factory delivered to this session, by the runner's receipt (jgwill/Miadi#909).
410
+ const all = receipts();
411
+ const missions = recordsForSession(all, id).map((record) => {
412
+ const rc = all.filter((x) => x.record === record && x.session_id === id).sort((a, b) => b.at.localeCompare(a.at))[0];
413
+ return { record, binding: "factory_receipt", delivered_at: rc?.at, tmux_session: rc?.tmux_session, pane_id: rc?.pane_id, read: `mission_status with ${record}` };
414
+ });
415
+ return { ...session, missions, connector_records: touching(`session:${id}`) };
358
416
  }));
359
417
  server.registerTool("get_evidence", {
360
418
  title: "What an episode holds as evidence",
@@ -629,14 +687,23 @@ export function registerTools(server, ctx) {
629
687
  }));
630
688
  server.registerTool("get_run_result", {
631
689
  title: "Where a requested run stands",
632
- description: "A request's decision (approved, approved with changes, sent back for revision, declined), the approver's instructions, the brief queued for the factory intake once approved, whether the intake delivered it, and its receipt.",
690
+ description: "A request's decision (approved, approved with changes, sent back for revision, declined), the approver's instructions, the brief queued for the factory intake once approved, whether the intake delivered it, its receipt, and for a run or work proposal the result its agent submitted (summary, outputs with their checks, tests, blockers, the pending or decided completion). mission_status joins the live session and every stage.",
633
691
  inputSchema: { record_id: z.string().min(1) },
634
692
  annotations: READ,
635
693
  }, wrap(async ({ record_id }, extra) => {
636
- who(extra);
694
+ const { person } = who(extra);
637
695
  const r = records().find((x) => x.id === record_id);
638
696
  if (!r)
639
697
  return { state: "not_found", record_id };
698
+ const isMission = r.kind === "run_request" || r.kind === "work_proposal";
699
+ // The sessions a result must come from: the runner's receipts, for every tier, else the record's session refs (#922 R5).
700
+ const bound = new Set(receiptsForRecord(receipts(), r.id).flatMap((x) => (x.session_id ? [x.session_id] : [])));
701
+ if (!bound.size)
702
+ for (const ref of r.refs)
703
+ if (/^session:[0-9a-f-]{36}$/.test(ref))
704
+ bound.add(ref.slice(8));
705
+ const checked = isMission ? await missionResult(r, all(), bound, { githubGet: github, approvalUrl }) : undefined;
706
+ const result = checked && person.api_tier !== "write" ? redactResult(checked) : checked;
640
707
  return {
641
708
  record: r,
642
709
  version: versionOf(r),
@@ -648,11 +715,13 @@ export function registerTools(server, ctx) {
648
715
  ...(r.approval_state === "revision_requested"
649
716
  ? { revision: { instructions: r.completion_receipt?.instructions, next: `Revise it in place: revise_pending_request with request_id ${r.id} and expected_version ${versionOf(r)}.` } }
650
717
  : {}),
718
+ // What the agent returned (jgwill/Miadi#921). The projection above is the request; this is its result.
719
+ ...(result ? { result, mission_status: `mission_status with ${r.id} joins the live session, the stages and the human gates.` } : {}),
651
720
  };
652
721
  }));
653
722
  server.registerTool("mission_status", {
654
723
  title: "Where a mission stands",
655
- description: "One mission, joined and verified: its source request and decision, the sessions bound to it (live or not), its issues and PRs, what is approved, queued, delivered, running, merged, released or closed — each by its evidence, never inferred from an idle pane — and the next authorized action. An issue or session resolves only through the request that holds it as primary; several are ambiguous_mission, citations alone are related_only, and an inference authorizes nothing (identity.authorizes_actions). Released needs a release receipt with artifact, target, production check and a fresh time; closed needs an approved session ending that cites the mission. Operator details need Miadi's write tier. jgwill/Miadi#893, #913.",
724
+ description: "One mission, joined and verified: its source request and decision, the sessions bound to it (live or not), its issues and PRs, what is approved, queued, delivered, running, merged, released or closed — each by its evidence, never inferred from an idle pane — and the next authorized action. An issue or session resolves only through the request that holds it as primary; several are ambiguous_mission, citations alone are related_only, and an inference authorizes nothing (identity.authorizes_actions). Released needs a release receipt with artifact, target, production check and a fresh time; closed needs an approved session ending that cites the mission. A session the factory delivered a mission to resolves through the runner's receipt (factory_bound), cross-checked with Miadi's session registry (binding verified, receipt_only or unverified_association). result returns what the agent submitted through propose_session_completion naming the mission: summary, outputs with their checks, tests, blockers and the completion decision; mission_stage and pending_human_gates say where it stands and what waits on a person. Operator details need Miadi's write tier. jgwill/Miadi#893, #913, #909, #921.",
656
725
  inputSchema: {
657
726
  ref: z
658
727
  .string()
@@ -666,11 +735,13 @@ export function registerTools(server, ctx) {
666
735
  return missionStatus(ref.trim(), records(), {
667
736
  projectOf: (r) => requestProjection(r, { reviewBase: ctx.approval?.config.reviewUrl, factoryDir: ctx.factoryDir }),
668
737
  queueOf: (r) => (r.kind === "run_request" || r.kind === "work_proposal" ? readQueueState(r, ctx.factoryDir) : undefined),
669
- tmuxSessions: writeTier ? (ctx.tmuxSessions ?? (() => [])) : undefined,
738
+ // Without a lister the host cannot say which sessions live: unknown, never "absent" (jgwill/Miadi#909).
739
+ tmuxSessions: writeTier ? (ctx.tmuxSessions ?? (ctx.tmux?.listSessions ? () => ctx.tmux.listSessions() : undefined)) : undefined,
670
740
  paneBusy: writeTier && ctx.tmux
671
- ? (session) => {
741
+ ? (session, paneId) => {
672
742
  try {
673
- const pane = ctx.tmux.listPanes(session)[0];
743
+ const panes = ctx.tmux.listPanes(session);
744
+ const pane = paneId ? panes.find((p) => p.id === paneId) : panes[0];
674
745
  if (!pane)
675
746
  return "unknown";
676
747
  return isBusy(ctx.tmux.capture(`${session}:${pane.window}.${pane.pane}`)) ? "busy" : "idle";
@@ -680,6 +751,24 @@ export function registerTools(server, ctx) {
680
751
  }
681
752
  }
682
753
  : undefined,
754
+ panePresent: writeTier && ctx.tmux
755
+ ? (session, paneId) => {
756
+ try {
757
+ return ctx.tmux.listPanes(session).some((p) => p.id === paneId);
758
+ }
759
+ catch {
760
+ return undefined;
761
+ }
762
+ }
763
+ : undefined,
764
+ factoryReceiptsOf: writeTier ? (id) => receiptsForRecord(receipts(), id) : undefined,
765
+ recordsBoundTo: writeTier ? (sessionId) => recordsForSession(receipts(), sessionId) : undefined,
766
+ // What a result and a closure are checked against does not depend on who reads (#922 R5); only what is shown does.
767
+ boundSessionIdsOf: (id) => receiptsForRecord(receipts(), id).flatMap((x) => (x.session_id ? [x.session_id] : [])),
768
+ trustedRecords: all(),
769
+ operator: writeTier,
770
+ githubGet: github,
771
+ approvalUrl,
683
772
  sessionOf: writeTier ? (id) => miadi.get(person.token, `/api/session/${encodeURIComponent(id)}`) : undefined,
684
773
  issueOf: async (owner, repo, n) => {
685
774
  const f = ctx.approval?.fetchImpl ?? fetch;
@@ -1119,21 +1208,77 @@ export function registerTools(server, ctx) {
1119
1208
  .optional()
1120
1209
  .describe("The mission this ending closes, by record id. Only an approved exit or complete_then_exit that names the mission here closes it in mission_status (jgwill/Miadi#913)."),
1121
1210
  evidence_refs: refs,
1211
+ result: z
1212
+ .object({
1213
+ summary: z.string().max(4000).optional().describe("What was achieved, in the agent's words. Default: the reason."),
1214
+ outputs: z
1215
+ .array(z.object({
1216
+ ref: z.string().min(1).max(500).describe("A commit or file URL on GitHub, owner/repo#n, miadi-review:<uuid>, miadi-chronicle://<n>/<path>, a record id or a URL."),
1217
+ label: z.string().max(200).optional(),
1218
+ git_sha: z.string().regex(/^[0-9a-f]{7,40}$/).optional().describe("The commit sha, or the file's git blob sha, as submitted: a later change shows as changed_since_submission."),
1219
+ }))
1220
+ .max(30)
1221
+ .optional(),
1222
+ tests: z
1223
+ .object({
1224
+ command: z.string().max(300).optional(),
1225
+ passed: z.number().int().min(0).optional(),
1226
+ failed: z.number().int().min(0).optional(),
1227
+ skipped: z.number().int().min(0).optional(),
1228
+ note: z.string().max(1000).optional(),
1229
+ })
1230
+ .optional(),
1231
+ blockers: z.array(z.string().min(1).max(500)).max(20).optional(),
1232
+ })
1233
+ .optional()
1234
+ .describe("The mission's result as its agent returns it (jgwill/Miadi#921): mission_status and get_run_result read it back by the mission id. It is the agent's claim; outputs are checked when read."),
1122
1235
  },
1123
1236
  annotations: WRITE,
1124
1237
  }, wrap(async (a, extra) => {
1125
1238
  const { person, auth } = who(extra);
1126
1239
  requireContribute(auth);
1127
1240
  const id = a.session_id.replace(/^session:/, "");
1241
+ const startedAt = new Date().toISOString();
1128
1242
  const r = append("session_completion_proposal", person, auth, {
1129
1243
  circle: "continuity",
1130
1244
  refs: a.mission ? [`session:${id}`, a.mission] : [`session:${id}`],
1131
1245
  evidence_refs: a.evidence_refs,
1132
1246
  approval_state: "awaiting_approval",
1133
1247
  idempotency_key: a.mission ? `${id}:${a.ending}:${a.mission}` : `${id}:${a.ending}`,
1134
- body: { session_id: id, ending: a.ending, reason: a.reason, ...(a.mission ? { mission: a.mission } : {}) },
1248
+ body: {
1249
+ session_id: id,
1250
+ ending: a.ending,
1251
+ reason: a.reason,
1252
+ ...(a.mission ? { mission: a.mission } : {}),
1253
+ ...(a.result ? { result: a.result } : {}),
1254
+ // Set by the connector, never by the caller: a result is verified only when the write tier submits it (#922 R3).
1255
+ submitted_with_tier: person.api_tier ?? null,
1256
+ },
1135
1257
  });
1136
- return { ...r, approval_url: approvalUrl(r.id) };
1258
+ // The same session, ending and mission already awaiting a decision: it is handed back unchanged.
1259
+ const replayed = r.created_at < startedAt;
1260
+ const prior = r.body;
1261
+ const dropped = replayed
1262
+ ? [
1263
+ ...(prior.reason !== a.reason ? ["reason"] : []),
1264
+ ...(JSON.stringify(prior.result ?? null) !== JSON.stringify(a.result ?? null) ? ["result"] : []),
1265
+ ...(JSON.stringify(r.evidence_refs) !== JSON.stringify(a.evidence_refs ?? []) ? ["evidence_refs"] : []),
1266
+ ]
1267
+ : [];
1268
+ return {
1269
+ ...r,
1270
+ approval_url: approvalUrl(r.id),
1271
+ ...(replayed
1272
+ ? {
1273
+ replayed: true,
1274
+ ...(dropped.length ? { not_recorded: dropped } : {}),
1275
+ note: dropped.length
1276
+ ? `An ending for this session, ending and mission already awaits a decision; it stands as first submitted, and this call's ${dropped.join(", ")} were not recorded. Ask the person to decline it, then submit again.`
1277
+ : "An ending for this session, ending and mission already awaits a decision; it is returned unchanged and nothing new was recorded.",
1278
+ }
1279
+ : {}),
1280
+ ...(a.mission ? { read_back: `mission_status with ${a.mission}` } : {}),
1281
+ };
1137
1282
  }));
1138
1283
  // ── requests: recorded, approved by a person on the approval page, then run ──
1139
1284
  server.registerTool("request_authorized_run", {
@@ -1383,8 +1528,10 @@ export function registerTools(server, ctx) {
1383
1528
  const { person, auth } = who(extra);
1384
1529
  requireContribute(auth);
1385
1530
  requireTier(person, "write");
1386
- if (!ctx.tmux)
1387
- throw new ToolRefusal("unavailable", "The connector host has no steering surface; the steer is unstarted.");
1531
+ // No transport, no record: a steer that cannot reach a pane uses none of the grant (jgwill/Miadi#909).
1532
+ const transport = steeringTransport(ctx.tmux);
1533
+ if (transport.transport !== "operational")
1534
+ throw new ToolRefusal("unavailable", `${transport.reason} The steer is unstarted; no attempt was used.`);
1388
1535
  const grantRecord = all().find((r) => r.id === a.run_request);
1389
1536
  if (!grantRecord || (grantRecord.kind !== "run_request" && grantRecord.kind !== "work_proposal")) {
1390
1537
  throw new ToolRefusal("invalid_ref", "Give the id of the approved run_request or work_proposal this steer belongs to.");
@@ -1395,10 +1542,14 @@ export function registerTools(server, ctx) {
1395
1542
  const grant = steeringGrantOf(grantRecord);
1396
1543
  const priorAttempts = steerAttempts(all(), grantRecord.id);
1397
1544
  const covered = checkGrant(grant, priorAttempts) === "ok";
1545
+ // The pane the factory delivered this mission to: the steer goes there and nowhere else (jgwill/Miadi#909).
1546
+ const bound = receiptsForRecord(receipts(), grantRecord.id)[0];
1547
+ const binding = bound ? { session: bound.tmux_session, ...(bound.pane_id ? { pane_id: bound.pane_id } : {}) } : undefined;
1398
1548
  const body = {
1399
1549
  instruction: a.instruction,
1400
- session: a.session ?? grantRecord.body.session,
1550
+ session: a.session ?? bound?.tmux_session ?? grantRecord.body.session,
1401
1551
  pane: a.pane ?? grant?.pane,
1552
+ ...(binding ? { binding: { ...binding, by: "factory_receipt", delivered_at: bound.at, ...(bound.session_id ? { session_id: bound.session_id } : {}) } } : {}),
1402
1553
  };
1403
1554
  const fields = {
1404
1555
  circle: grantRecord.circle,
@@ -1421,8 +1572,9 @@ export function registerTools(server, ctx) {
1421
1572
  };
1422
1573
  }
1423
1574
  const r = append("session_steer_request", person, auth, { ...fields, approval_state: "not_required" });
1424
- const result = await steerSession({ tmux: ctx.tmux, stateDir: config.stateDir, ...(ctx.steerSettleMs !== undefined ? { settleMs: ctx.steerSettleMs } : {}) }, { record: r, grantRecord, priorAttempts });
1425
- const delivered = result.status === "accepted" || result.status === "submitted";
1575
+ const result = await steerSession({ tmux: ctx.tmux, stateDir: config.stateDir, ...(ctx.steerSettleMs !== undefined ? { settleMs: ctx.steerSettleMs } : {}) }, { record: r, grantRecord, priorAttempts, ...(binding ? { binding } : {}) });
1576
+ // A typed steer is never "failed": failed is re-runnable, and that would type it twice (#922 R8).
1577
+ const delivered = result.typed;
1426
1578
  ledger.append({
1427
1579
  id: newRecordId(r.kind),
1428
1580
  kind: r.kind,
@@ -1439,13 +1591,18 @@ export function registerTools(server, ctx) {
1439
1591
  decided_at: new Date().toISOString(),
1440
1592
  outcome: delivered ? result.status : "failed",
1441
1593
  steer_status: result.status,
1594
+ typed: result.typed,
1442
1595
  message: result.message,
1443
1596
  ...(result.target ? { target: result.target } : {}),
1444
1597
  ...(result.artifact ? { artifact: result.artifact } : {}),
1445
1598
  },
1446
1599
  body: r.body,
1447
1600
  });
1448
- return records().find((x) => x.id === r.id) ?? r;
1601
+ const after = steerAttempts(all(), grantRecord.id);
1602
+ return {
1603
+ ...(records().find((x) => x.id === r.id) ?? r),
1604
+ attempts: { used: after, ...(grant?.max_attempts !== undefined ? { max: grant.max_attempts } : {}), counted: result.typed },
1605
+ };
1449
1606
  }));
1450
1607
  server.registerTool("request_review_operation", {
1451
1608
  title: "Request a review operation",
@@ -1885,7 +2042,7 @@ export const TOOL_STATUS = {
1885
2042
  handoff_status: "live",
1886
2043
  list_records: "live",
1887
2044
  get_run_result: "live",
1888
- mission_status: "live (operator details need the Miadi write tier)",
2045
+ mission_status: "live (operator details need the Miadi write tier; returns the agent's submitted result)",
1889
2046
  mission_model_preflight: "live, Miadi write tier (static policy; Jev only with consult_jev and a Jev key on the host, otherwise router_unconfigured)",
1890
2047
  provider_capabilities: "live, Miadi write tier",
1891
2048
  search: "live",
@@ -1905,7 +2062,7 @@ export const TOOL_STATUS = {
1905
2062
  revise_pending_request: "live, contribute (a waiting or sent-back run or proposal gets its next version; same id, same card)",
1906
2063
  get_request_history: "live (every version of a request, oldest first; whoever asked, or the write tier)",
1907
2064
  supersede_pending_requests: "live, contribute (retires named earlier requests still waiting and joins them as earlier versions of the one that stands)",
1908
- request_session_steer: "live, contribute, write tier (runs inside an approved run's steering grant, else one scoped human decision)",
2065
+ request_session_steer: "live, contribute, write tier (runs inside an approved run's steering grant, else one scoped human decision; get_capabilities.steering says whether the transport works now)",
1909
2066
  request_review_operation: "live, contribute, needs_approval",
1910
2067
  request_deep_diver: "live, contribute, needs_approval",
1911
2068
  link_review_to_episode: "live, contribute, needs_approval",
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.1.15";
1
+ export declare const VERSION = "0.1.17";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.1.15";
1
+ export const VERSION = "0.1.17";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miadi/connector",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "The Miadi connector: one remote MCP service through which a person signed in with their Miadi person token, from ChatGPT or any MCP client, reads sessions, reviews, episodes and circles and records observations, inquiries, handoffs and proposals with their name on each record.",
5
5
  "license": "MIT",
6
6
  "author": "Miadi",