@zixt/host 0.0.55 → 0.0.56

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 +206 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import { homedir } from "node:os";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.55",
34
+ version: "0.0.56",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -16023,6 +16023,10 @@ var UploadAttachmentRequest = external_exports.object({
16023
16023
  });
16024
16024
  var UploadAttachmentResponse = external_exports.object({ attachment: TaskAttachmentRef });
16025
16025
  var TASK_ARTIFACT_MAX_BYTES = 10 * 1024 * 1024;
16026
+ var TASK_ARTIFACT_CHAT_HREF_PREFIX = "/.zixt/task-files/";
16027
+ function taskArtifactChatHref(artifactId) {
16028
+ return `${TASK_ARTIFACT_CHAT_HREF_PREFIX}${artifactId}`;
16029
+ }
16026
16030
  var TaskArtifact = external_exports.object({
16027
16031
  id: TaskArtifactId,
16028
16032
  taskId: TaskId,
@@ -16032,6 +16036,7 @@ var TaskArtifact = external_exports.object({
16032
16036
  sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
16033
16037
  createdAt: IsoDate
16034
16038
  });
16039
+ var OrgFileResponse = external_exports.object({ artifact: TaskArtifact });
16035
16040
  var TaskFileCapability = external_exports.object({
16036
16041
  target: external_exports.enum(["zixt", "slack", "linear"]),
16037
16042
  operation: external_exports.enum(["download", "share", "issue_attachment"]),
@@ -18083,7 +18088,17 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
18083
18088
  terminalGroup: external_exports.string().min(1).max(200).nullable().optional()
18084
18089
  }).strict(),
18085
18090
  /** A Manager loop failure a person should see (provider outage, refusal). */
18086
- external_exports.object({ ...conversationEventBase, kind: external_exports.literal("error"), message: external_exports.string() }).strict()
18091
+ external_exports.object({
18092
+ ...conversationEventBase,
18093
+ kind: external_exports.literal("error"),
18094
+ message: external_exports.string(),
18095
+ /**
18096
+ * `notice` marks a record that is not a fault: the person stopped this
18097
+ * turn themselves. Absent on every historical row, so a missing value
18098
+ * keeps reading as the fault it always was.
18099
+ */
18100
+ severity: external_exports.enum(["error", "notice"]).optional()
18101
+ }).strict()
18087
18102
  ]);
18088
18103
  var ManagerIntegrationProvider = external_exports.enum(["slack", "github"]);
18089
18104
  var ManagerIntegrationOperation = external_exports.enum(["connect", "reconnect", "check", "remove"]);
@@ -18221,6 +18236,24 @@ var ConversationDetailResponse = external_exports.object({
18221
18236
  conversation: ConversationProjection,
18222
18237
  events: external_exports.array(ConversationEventProjection)
18223
18238
  }).strict();
18239
+ var ConversationInterruptTurnOutcome = external_exports.enum(["interrupted", "not_running"]);
18240
+ var ConversationInterruptTaskOutcome = external_exports.enum([
18241
+ "stop_requested",
18242
+ "already_finished",
18243
+ "not_stopped"
18244
+ ]);
18245
+ var ConversationInterruptTaskResult = external_exports.object({
18246
+ taskId: TaskId,
18247
+ outcome: ConversationInterruptTaskOutcome,
18248
+ /** Why the stop did not happen; null unless the outcome is `not_stopped`. */
18249
+ detail: external_exports.string().max(300).nullable()
18250
+ }).strict();
18251
+ var CONVERSATION_INTERRUPT_TASK_LIMIT = 100;
18252
+ var InterruptConversationResponse = external_exports.object({
18253
+ conversation: ConversationProjection,
18254
+ managerTurn: ConversationInterruptTurnOutcome,
18255
+ tasks: external_exports.array(ConversationInterruptTaskResult).max(CONVERSATION_INTERRUPT_TASK_LIMIT)
18256
+ }).strict();
18224
18257
  var ManagerStreamFrame = external_exports.discriminatedUnion("type", [
18225
18258
  external_exports.object({ type: external_exports.literal("event"), event: ConversationEventProjection }).strict(),
18226
18259
  external_exports.object({ type: external_exports.literal("delta"), text: external_exports.string() }).strict(),
@@ -19980,6 +20013,7 @@ async function discoverTools(params, fetchFn = fetch) {
19980
20013
  import { createHash } from "node:crypto";
19981
20014
  import { lstat, readFile, realpath } from "node:fs/promises";
19982
20015
  import { basename, extname, isAbsolute, relative, resolve, sep } from "node:path";
20016
+ import { fileURLToPath } from "node:url";
19983
20017
  var MEDIA_TYPES = {
19984
20018
  ".csv": "text/csv",
19985
20019
  ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -20042,6 +20076,146 @@ async function publishTaskFile(input) {
20042
20076
  data: bytes.toString("base64")
20043
20077
  });
20044
20078
  }
20079
+ function markdownLinkDestinations(markdown) {
20080
+ const ignored = new Uint8Array(markdown.length);
20081
+ let fence = null;
20082
+ let offset = 0;
20083
+ for (const line of markdown.split(/(?<=\n)/)) {
20084
+ const body = line.endsWith("\n") ? line.slice(0, -1) : line;
20085
+ const match = /^( {0,3})(`{3,}|~{3,})/.exec(body);
20086
+ const marker = match?.[2]?.[0];
20087
+ const markerLength = match?.[2]?.length ?? 0;
20088
+ const closes = fence !== null && marker === fence.marker && markerLength >= fence.length && body.slice(match?.[0].length ?? 0).trim() === "";
20089
+ if (fence || match) ignored.fill(1, offset, offset + line.length);
20090
+ if (!fence && marker) fence = { marker, length: markerLength };
20091
+ else if (closes) fence = null;
20092
+ offset += line.length;
20093
+ }
20094
+ for (let index = 0; index < markdown.length; index++) {
20095
+ if (ignored[index] || markdown[index] !== "`") continue;
20096
+ let length = 1;
20097
+ while (markdown[index + length] === "`") length++;
20098
+ const delimiter3 = "`".repeat(length);
20099
+ const close = markdown.indexOf(delimiter3, index + length);
20100
+ if (close < 0) continue;
20101
+ ignored.fill(1, index, close + length);
20102
+ index = close + length - 1;
20103
+ }
20104
+ const destinations = [];
20105
+ const escaped = (index) => {
20106
+ let slashes = 0;
20107
+ for (let cursor = index - 1; cursor >= 0 && markdown[cursor] === "\\"; cursor--) slashes++;
20108
+ return slashes % 2 === 1;
20109
+ };
20110
+ for (let index = 0; index < markdown.length; index++) {
20111
+ if (ignored[index] || markdown[index] !== "[" || escaped(index) || index > 0 && markdown[index - 1] === "!") {
20112
+ continue;
20113
+ }
20114
+ let labelDepth = 1;
20115
+ let closeLabel = index + 1;
20116
+ for (; closeLabel < markdown.length && labelDepth > 0; closeLabel++) {
20117
+ if (ignored[closeLabel] || escaped(closeLabel)) continue;
20118
+ if (markdown[closeLabel] === "[") labelDepth++;
20119
+ else if (markdown[closeLabel] === "]") labelDepth--;
20120
+ }
20121
+ if (labelDepth !== 0 || markdown[closeLabel] !== "(") continue;
20122
+ let cursor = closeLabel + 1;
20123
+ while (markdown[cursor] === " " || markdown[cursor] === " ") cursor++;
20124
+ if (markdown[cursor] === "<") {
20125
+ const start2 = cursor + 1;
20126
+ cursor = start2;
20127
+ while (cursor < markdown.length && markdown[cursor] !== "\n" && (markdown[cursor] !== ">" || escaped(cursor))) {
20128
+ cursor++;
20129
+ }
20130
+ if (markdown[cursor] !== ">") continue;
20131
+ destinations.push({ start: start2, end: cursor, value: markdown.slice(start2, cursor) });
20132
+ index = cursor;
20133
+ continue;
20134
+ }
20135
+ const start = cursor;
20136
+ let depth = 1;
20137
+ while (cursor < markdown.length) {
20138
+ if (escaped(cursor)) {
20139
+ cursor++;
20140
+ continue;
20141
+ }
20142
+ const char = markdown[cursor];
20143
+ if (char === "(") depth++;
20144
+ else if (char === ")") {
20145
+ depth--;
20146
+ if (depth === 0) break;
20147
+ } else if ((char === " " || char === " " || char === "\n") && depth === 1) {
20148
+ break;
20149
+ }
20150
+ cursor++;
20151
+ }
20152
+ if (cursor > start) {
20153
+ destinations.push({ start, end: cursor, value: markdown.slice(start, cursor) });
20154
+ index = cursor;
20155
+ }
20156
+ }
20157
+ return destinations;
20158
+ }
20159
+ function localPathFromMarkdownDestination(destination) {
20160
+ const unescaped = destination.replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g, "$1");
20161
+ if (/^file:\/\//i.test(unescaped)) {
20162
+ try {
20163
+ return fileURLToPath(unescaped);
20164
+ } catch {
20165
+ return null;
20166
+ }
20167
+ }
20168
+ const windowsAbsolute = /^[A-Za-z]:[\\/]/.test(unescaped);
20169
+ if (!windowsAbsolute && /^[A-Za-z][A-Za-z\d+.-]*:/.test(unescaped)) return null;
20170
+ if (unescaped.startsWith("#") || unescaped.startsWith("//")) return null;
20171
+ try {
20172
+ return decodeURIComponent(unescaped);
20173
+ } catch {
20174
+ return unescaped;
20175
+ }
20176
+ }
20177
+ async function publishLinkedTaskFiles(input) {
20178
+ const replacements = [];
20179
+ const publications = new Map(input.publishedArtifacts);
20180
+ const artifacts = [];
20181
+ for (const destination of markdownLinkDestinations(input.summary)) {
20182
+ const localPath = localPathFromMarkdownDestination(destination.value);
20183
+ if (!localPath) continue;
20184
+ const candidate = resolve(input.cwd, localPath);
20185
+ const key = await realpath(candidate).catch(() => candidate);
20186
+ let artifact = publications.get(key);
20187
+ if (artifact === void 0) {
20188
+ try {
20189
+ const outcome = await publishTaskFile({
20190
+ path: localPath,
20191
+ cwd: input.cwd,
20192
+ allowedRoots: input.allowedRoots,
20193
+ agentOp: input.agentOp
20194
+ });
20195
+ const parsed = TaskArtifact.safeParse(
20196
+ outcome.ok && outcome.result && typeof outcome.result === "object" ? outcome.result["artifact"] : void 0
20197
+ );
20198
+ artifact = parsed.success ? parsed.data : null;
20199
+ } catch {
20200
+ artifact = null;
20201
+ }
20202
+ publications.set(key, artifact);
20203
+ if (artifact) artifacts.push(artifact);
20204
+ }
20205
+ if (artifact) {
20206
+ replacements.push({
20207
+ start: destination.start,
20208
+ end: destination.end,
20209
+ href: taskArtifactChatHref(artifact.id)
20210
+ });
20211
+ }
20212
+ }
20213
+ let summary = input.summary;
20214
+ for (const replacement of replacements.reverse()) {
20215
+ summary = summary.slice(0, replacement.start) + replacement.href + summary.slice(replacement.end);
20216
+ }
20217
+ return { summary, artifacts };
20218
+ }
20045
20219
 
20046
20220
  // src/runners/exec.ts
20047
20221
  import { spawn } from "node:child_process";
@@ -35500,6 +35674,25 @@ function createCliRunner(adapter, opts = {}) {
35500
35674
  }
35501
35675
  }
35502
35676
  if (task.cancelledNow()) return cancelledBeforeRun();
35677
+ const publishedTaskFiles = /* @__PURE__ */ new Map();
35678
+ const publishFile = async (path, mediaType) => {
35679
+ const outcome = await publishTaskFile({
35680
+ path,
35681
+ ...mediaType ? { mediaType } : {},
35682
+ cwd,
35683
+ allowedRoots: [taskRoot, cwd],
35684
+ agentOp: (op) => task.agentOp(op)
35685
+ });
35686
+ const parsed = TaskArtifact.safeParse(
35687
+ outcome.ok && outcome.result && typeof outcome.result === "object" ? outcome.result["artifact"] : void 0
35688
+ );
35689
+ if (parsed.success) {
35690
+ const candidate = resolve9(cwd, path);
35691
+ const key = await realpath8(candidate).catch(() => candidate);
35692
+ publishedTaskFiles.set(key, parsed.data);
35693
+ }
35694
+ return outcome;
35695
+ };
35503
35696
  const [secrets, attachedConnections, providerGrants] = await Promise.all([
35504
35697
  task.secrets(),
35505
35698
  task.connections(),
@@ -35643,13 +35836,7 @@ function createCliRunner(adapter, opts = {}) {
35643
35836
  pendingAsks--;
35644
35837
  }
35645
35838
  },
35646
- publishFile: (path, mediaType) => publishTaskFile({
35647
- path,
35648
- ...mediaType ? { mediaType } : {},
35649
- cwd,
35650
- allowedRoots: [taskRoot, cwd],
35651
- agentOp: (op) => task.agentOp(op)
35652
- }),
35839
+ publishFile,
35653
35840
  agentOp: (op) => task.agentOp(op),
35654
35841
  // GitHub repository work belongs in the installed `git` and `gh`
35655
35842
  // commands backed by GithubShellAuth. Do not advertise the bundled
@@ -35955,6 +36142,16 @@ ${attachmentSection}` : prompt;
35955
36142
  opts.onUnsafeRunnerCleanup?.(result.summary);
35956
36143
  }
35957
36144
  }
36145
+ if (result.outcome === "done") {
36146
+ const linkedFiles = await publishLinkedTaskFiles({
36147
+ summary: result.summary,
36148
+ cwd,
36149
+ allowedRoots: [taskRoot, cwd],
36150
+ publishedArtifacts: publishedTaskFiles,
36151
+ agentOp: (op) => task.agentOp(op)
36152
+ });
36153
+ result = { ...result, summary: linkedFiles.summary };
36154
+ }
35958
36155
  task.event(
35959
36156
  "status",
35960
36157
  `${adapter.displayName} finished. Tokens in ${result.usage.inputTokens}, out ${result.usage.outputTokens}` + (result.usage.totalCostUsd !== void 0 ? `, cost $${result.usage.totalCostUsd.toFixed(4)}` : "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",