@zixt/host 0.0.55 → 0.0.57
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 +271 -10
- 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.
|
|
34
|
+
version: "0.0.57",
|
|
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"]),
|
|
@@ -16227,6 +16232,68 @@ var TaskEventRecord = external_exports.object({
|
|
|
16227
16232
|
attachments: external_exports.array(TaskAttachmentRef).max(TASK_MESSAGE_MAX_ATTACHMENTS).optional(),
|
|
16228
16233
|
at: IsoDate
|
|
16229
16234
|
});
|
|
16235
|
+
var TaskTimingPhaseKind = external_exports.enum([
|
|
16236
|
+
/** Waiting for a Machine: queue, dispatch, and re-queue between runs. */
|
|
16237
|
+
"queued",
|
|
16238
|
+
/** Assigned to a Machine, session not started yet. */
|
|
16239
|
+
"startup",
|
|
16240
|
+
/** Preparing the environment: dependencies, folders, tools, services. */
|
|
16241
|
+
"setup",
|
|
16242
|
+
/** Reading, searching, and browsing to find things out. */
|
|
16243
|
+
"research",
|
|
16244
|
+
/** Doing the Task's actual work: edits, writes, configuration, other tools. */
|
|
16245
|
+
"work",
|
|
16246
|
+
/** Running checks: tests, builds, linters, verification. */
|
|
16247
|
+
"validation",
|
|
16248
|
+
/** Work that happened after checks had already started in the same run. */
|
|
16249
|
+
"rework",
|
|
16250
|
+
/** Reporting and handing off the result: messages, pull requests, files. */
|
|
16251
|
+
"delivery",
|
|
16252
|
+
/** Parked on a question or an approval a person owed. */
|
|
16253
|
+
"awaiting_person",
|
|
16254
|
+
/** Nothing was running: the Task sat between runs with no one waiting on it. */
|
|
16255
|
+
"idle",
|
|
16256
|
+
/** Measured time the Task's activity record cannot break down. */
|
|
16257
|
+
"unattributed"
|
|
16258
|
+
]);
|
|
16259
|
+
var TaskTimingBasis = external_exports.enum(["measured", "estimated"]);
|
|
16260
|
+
var TaskTimingPhase = external_exports.object({
|
|
16261
|
+
kind: TaskTimingPhaseKind,
|
|
16262
|
+
durationMs: external_exports.number().int().min(0),
|
|
16263
|
+
basis: TaskTimingBasis,
|
|
16264
|
+
/** Activity steps behind an estimated phase; 0 for measured lifecycle phases. */
|
|
16265
|
+
steps: external_exports.number().int().min(0)
|
|
16266
|
+
}).strict();
|
|
16267
|
+
var TaskTimingRun = external_exports.object({
|
|
16268
|
+
epoch: external_exports.number().int().min(1),
|
|
16269
|
+
status: TaskStatus,
|
|
16270
|
+
startedAt: IsoDate.nullable(),
|
|
16271
|
+
finishedAt: IsoDate.nullable(),
|
|
16272
|
+
/** Waiting for this run's Machine, including re-queue after an earlier run. */
|
|
16273
|
+
waitingMs: external_exports.number().int().min(0),
|
|
16274
|
+
activeMs: external_exports.number().int().min(0),
|
|
16275
|
+
unattributedMs: external_exports.number().int().min(0)
|
|
16276
|
+
}).strict();
|
|
16277
|
+
var TASK_TIMING_MAX_RUNS = 50;
|
|
16278
|
+
var TaskTimingBreakdown = external_exports.object({
|
|
16279
|
+
schemaVersion: external_exports.literal(1),
|
|
16280
|
+
from: IsoDate,
|
|
16281
|
+
to: IsoDate,
|
|
16282
|
+
totalElapsedMs: external_exports.number().int().min(0),
|
|
16283
|
+
/** Time a Machine was running the Task, broken down or not. */
|
|
16284
|
+
activeMs: external_exports.number().int().min(0),
|
|
16285
|
+
/** Queue, startup, approval, and idle time: nothing was being worked on. */
|
|
16286
|
+
waitingMs: external_exports.number().int().min(0),
|
|
16287
|
+
/** Active time the activity record cannot name. */
|
|
16288
|
+
unattributedMs: external_exports.number().int().min(0),
|
|
16289
|
+
runCount: external_exports.number().int().min(0),
|
|
16290
|
+
/** False while the Task can still accrue time; the breakdown is then a snapshot. */
|
|
16291
|
+
settled: external_exports.boolean(),
|
|
16292
|
+
/** True once at least one estimated phase carries time worth showing. */
|
|
16293
|
+
attributed: external_exports.boolean(),
|
|
16294
|
+
phases: external_exports.array(TaskTimingPhase),
|
|
16295
|
+
runs: external_exports.array(TaskTimingRun).max(TASK_TIMING_MAX_RUNS)
|
|
16296
|
+
}).strict();
|
|
16230
16297
|
var CreateTaskInput = external_exports.object({
|
|
16231
16298
|
/** Stable client-generated key: retrying the same submission returns one Task. */
|
|
16232
16299
|
requestId: external_exports.uuid().optional(),
|
|
@@ -16486,7 +16553,9 @@ var TaskDetailResponse = external_exports.object({
|
|
|
16486
16553
|
reviewAuthorization: TaskReviewAuthorization,
|
|
16487
16554
|
context: TaskResolvedContext,
|
|
16488
16555
|
/** Newest host-observed folder/Git state; null until a current Host reports it. */
|
|
16489
|
-
workingContext: TaskWorkingContext.nullable().default(null)
|
|
16556
|
+
workingContext: TaskWorkingContext.nullable().default(null),
|
|
16557
|
+
/** TS-19 timing breakdown; null when the Task has no usable timing evidence. */
|
|
16558
|
+
timing: TaskTimingBreakdown.nullable().default(null)
|
|
16490
16559
|
});
|
|
16491
16560
|
var TaskSupportBundle = external_exports.object({
|
|
16492
16561
|
schemaVersion: external_exports.literal(1),
|
|
@@ -18083,7 +18152,17 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
|
|
|
18083
18152
|
terminalGroup: external_exports.string().min(1).max(200).nullable().optional()
|
|
18084
18153
|
}).strict(),
|
|
18085
18154
|
/** A Manager loop failure a person should see (provider outage, refusal). */
|
|
18086
|
-
external_exports.object({
|
|
18155
|
+
external_exports.object({
|
|
18156
|
+
...conversationEventBase,
|
|
18157
|
+
kind: external_exports.literal("error"),
|
|
18158
|
+
message: external_exports.string(),
|
|
18159
|
+
/**
|
|
18160
|
+
* `notice` marks a record that is not a fault: the person stopped this
|
|
18161
|
+
* turn themselves. Absent on every historical row, so a missing value
|
|
18162
|
+
* keeps reading as the fault it always was.
|
|
18163
|
+
*/
|
|
18164
|
+
severity: external_exports.enum(["error", "notice"]).optional()
|
|
18165
|
+
}).strict()
|
|
18087
18166
|
]);
|
|
18088
18167
|
var ManagerIntegrationProvider = external_exports.enum(["slack", "github"]);
|
|
18089
18168
|
var ManagerIntegrationOperation = external_exports.enum(["connect", "reconnect", "check", "remove"]);
|
|
@@ -18221,6 +18300,24 @@ var ConversationDetailResponse = external_exports.object({
|
|
|
18221
18300
|
conversation: ConversationProjection,
|
|
18222
18301
|
events: external_exports.array(ConversationEventProjection)
|
|
18223
18302
|
}).strict();
|
|
18303
|
+
var ConversationInterruptTurnOutcome = external_exports.enum(["interrupted", "not_running"]);
|
|
18304
|
+
var ConversationInterruptTaskOutcome = external_exports.enum([
|
|
18305
|
+
"stop_requested",
|
|
18306
|
+
"already_finished",
|
|
18307
|
+
"not_stopped"
|
|
18308
|
+
]);
|
|
18309
|
+
var ConversationInterruptTaskResult = external_exports.object({
|
|
18310
|
+
taskId: TaskId,
|
|
18311
|
+
outcome: ConversationInterruptTaskOutcome,
|
|
18312
|
+
/** Why the stop did not happen; null unless the outcome is `not_stopped`. */
|
|
18313
|
+
detail: external_exports.string().max(300).nullable()
|
|
18314
|
+
}).strict();
|
|
18315
|
+
var CONVERSATION_INTERRUPT_TASK_LIMIT = 100;
|
|
18316
|
+
var InterruptConversationResponse = external_exports.object({
|
|
18317
|
+
conversation: ConversationProjection,
|
|
18318
|
+
managerTurn: ConversationInterruptTurnOutcome,
|
|
18319
|
+
tasks: external_exports.array(ConversationInterruptTaskResult).max(CONVERSATION_INTERRUPT_TASK_LIMIT)
|
|
18320
|
+
}).strict();
|
|
18224
18321
|
var ManagerStreamFrame = external_exports.discriminatedUnion("type", [
|
|
18225
18322
|
external_exports.object({ type: external_exports.literal("event"), event: ConversationEventProjection }).strict(),
|
|
18226
18323
|
external_exports.object({ type: external_exports.literal("delta"), text: external_exports.string() }).strict(),
|
|
@@ -19980,6 +20077,7 @@ async function discoverTools(params, fetchFn = fetch) {
|
|
|
19980
20077
|
import { createHash } from "node:crypto";
|
|
19981
20078
|
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
19982
20079
|
import { basename, extname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
20080
|
+
import { fileURLToPath } from "node:url";
|
|
19983
20081
|
var MEDIA_TYPES = {
|
|
19984
20082
|
".csv": "text/csv",
|
|
19985
20083
|
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -20042,6 +20140,146 @@ async function publishTaskFile(input) {
|
|
|
20042
20140
|
data: bytes.toString("base64")
|
|
20043
20141
|
});
|
|
20044
20142
|
}
|
|
20143
|
+
function markdownLinkDestinations(markdown) {
|
|
20144
|
+
const ignored = new Uint8Array(markdown.length);
|
|
20145
|
+
let fence = null;
|
|
20146
|
+
let offset = 0;
|
|
20147
|
+
for (const line of markdown.split(/(?<=\n)/)) {
|
|
20148
|
+
const body = line.endsWith("\n") ? line.slice(0, -1) : line;
|
|
20149
|
+
const match = /^( {0,3})(`{3,}|~{3,})/.exec(body);
|
|
20150
|
+
const marker = match?.[2]?.[0];
|
|
20151
|
+
const markerLength = match?.[2]?.length ?? 0;
|
|
20152
|
+
const closes = fence !== null && marker === fence.marker && markerLength >= fence.length && body.slice(match?.[0].length ?? 0).trim() === "";
|
|
20153
|
+
if (fence || match) ignored.fill(1, offset, offset + line.length);
|
|
20154
|
+
if (!fence && marker) fence = { marker, length: markerLength };
|
|
20155
|
+
else if (closes) fence = null;
|
|
20156
|
+
offset += line.length;
|
|
20157
|
+
}
|
|
20158
|
+
for (let index = 0; index < markdown.length; index++) {
|
|
20159
|
+
if (ignored[index] || markdown[index] !== "`") continue;
|
|
20160
|
+
let length = 1;
|
|
20161
|
+
while (markdown[index + length] === "`") length++;
|
|
20162
|
+
const delimiter3 = "`".repeat(length);
|
|
20163
|
+
const close = markdown.indexOf(delimiter3, index + length);
|
|
20164
|
+
if (close < 0) continue;
|
|
20165
|
+
ignored.fill(1, index, close + length);
|
|
20166
|
+
index = close + length - 1;
|
|
20167
|
+
}
|
|
20168
|
+
const destinations = [];
|
|
20169
|
+
const escaped = (index) => {
|
|
20170
|
+
let slashes = 0;
|
|
20171
|
+
for (let cursor = index - 1; cursor >= 0 && markdown[cursor] === "\\"; cursor--) slashes++;
|
|
20172
|
+
return slashes % 2 === 1;
|
|
20173
|
+
};
|
|
20174
|
+
for (let index = 0; index < markdown.length; index++) {
|
|
20175
|
+
if (ignored[index] || markdown[index] !== "[" || escaped(index) || index > 0 && markdown[index - 1] === "!") {
|
|
20176
|
+
continue;
|
|
20177
|
+
}
|
|
20178
|
+
let labelDepth = 1;
|
|
20179
|
+
let closeLabel = index + 1;
|
|
20180
|
+
for (; closeLabel < markdown.length && labelDepth > 0; closeLabel++) {
|
|
20181
|
+
if (ignored[closeLabel] || escaped(closeLabel)) continue;
|
|
20182
|
+
if (markdown[closeLabel] === "[") labelDepth++;
|
|
20183
|
+
else if (markdown[closeLabel] === "]") labelDepth--;
|
|
20184
|
+
}
|
|
20185
|
+
if (labelDepth !== 0 || markdown[closeLabel] !== "(") continue;
|
|
20186
|
+
let cursor = closeLabel + 1;
|
|
20187
|
+
while (markdown[cursor] === " " || markdown[cursor] === " ") cursor++;
|
|
20188
|
+
if (markdown[cursor] === "<") {
|
|
20189
|
+
const start2 = cursor + 1;
|
|
20190
|
+
cursor = start2;
|
|
20191
|
+
while (cursor < markdown.length && markdown[cursor] !== "\n" && (markdown[cursor] !== ">" || escaped(cursor))) {
|
|
20192
|
+
cursor++;
|
|
20193
|
+
}
|
|
20194
|
+
if (markdown[cursor] !== ">") continue;
|
|
20195
|
+
destinations.push({ start: start2, end: cursor, value: markdown.slice(start2, cursor) });
|
|
20196
|
+
index = cursor;
|
|
20197
|
+
continue;
|
|
20198
|
+
}
|
|
20199
|
+
const start = cursor;
|
|
20200
|
+
let depth = 1;
|
|
20201
|
+
while (cursor < markdown.length) {
|
|
20202
|
+
if (escaped(cursor)) {
|
|
20203
|
+
cursor++;
|
|
20204
|
+
continue;
|
|
20205
|
+
}
|
|
20206
|
+
const char = markdown[cursor];
|
|
20207
|
+
if (char === "(") depth++;
|
|
20208
|
+
else if (char === ")") {
|
|
20209
|
+
depth--;
|
|
20210
|
+
if (depth === 0) break;
|
|
20211
|
+
} else if ((char === " " || char === " " || char === "\n") && depth === 1) {
|
|
20212
|
+
break;
|
|
20213
|
+
}
|
|
20214
|
+
cursor++;
|
|
20215
|
+
}
|
|
20216
|
+
if (cursor > start) {
|
|
20217
|
+
destinations.push({ start, end: cursor, value: markdown.slice(start, cursor) });
|
|
20218
|
+
index = cursor;
|
|
20219
|
+
}
|
|
20220
|
+
}
|
|
20221
|
+
return destinations;
|
|
20222
|
+
}
|
|
20223
|
+
function localPathFromMarkdownDestination(destination) {
|
|
20224
|
+
const unescaped = destination.replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g, "$1");
|
|
20225
|
+
if (/^file:\/\//i.test(unescaped)) {
|
|
20226
|
+
try {
|
|
20227
|
+
return fileURLToPath(unescaped);
|
|
20228
|
+
} catch {
|
|
20229
|
+
return null;
|
|
20230
|
+
}
|
|
20231
|
+
}
|
|
20232
|
+
const windowsAbsolute = /^[A-Za-z]:[\\/]/.test(unescaped);
|
|
20233
|
+
if (!windowsAbsolute && /^[A-Za-z][A-Za-z\d+.-]*:/.test(unescaped)) return null;
|
|
20234
|
+
if (unescaped.startsWith("#") || unescaped.startsWith("//")) return null;
|
|
20235
|
+
try {
|
|
20236
|
+
return decodeURIComponent(unescaped);
|
|
20237
|
+
} catch {
|
|
20238
|
+
return unescaped;
|
|
20239
|
+
}
|
|
20240
|
+
}
|
|
20241
|
+
async function publishLinkedTaskFiles(input) {
|
|
20242
|
+
const replacements = [];
|
|
20243
|
+
const publications = new Map(input.publishedArtifacts);
|
|
20244
|
+
const artifacts = [];
|
|
20245
|
+
for (const destination of markdownLinkDestinations(input.summary)) {
|
|
20246
|
+
const localPath = localPathFromMarkdownDestination(destination.value);
|
|
20247
|
+
if (!localPath) continue;
|
|
20248
|
+
const candidate = resolve(input.cwd, localPath);
|
|
20249
|
+
const key = await realpath(candidate).catch(() => candidate);
|
|
20250
|
+
let artifact = publications.get(key);
|
|
20251
|
+
if (artifact === void 0) {
|
|
20252
|
+
try {
|
|
20253
|
+
const outcome = await publishTaskFile({
|
|
20254
|
+
path: localPath,
|
|
20255
|
+
cwd: input.cwd,
|
|
20256
|
+
allowedRoots: input.allowedRoots,
|
|
20257
|
+
agentOp: input.agentOp
|
|
20258
|
+
});
|
|
20259
|
+
const parsed = TaskArtifact.safeParse(
|
|
20260
|
+
outcome.ok && outcome.result && typeof outcome.result === "object" ? outcome.result["artifact"] : void 0
|
|
20261
|
+
);
|
|
20262
|
+
artifact = parsed.success ? parsed.data : null;
|
|
20263
|
+
} catch {
|
|
20264
|
+
artifact = null;
|
|
20265
|
+
}
|
|
20266
|
+
publications.set(key, artifact);
|
|
20267
|
+
if (artifact) artifacts.push(artifact);
|
|
20268
|
+
}
|
|
20269
|
+
if (artifact) {
|
|
20270
|
+
replacements.push({
|
|
20271
|
+
start: destination.start,
|
|
20272
|
+
end: destination.end,
|
|
20273
|
+
href: taskArtifactChatHref(artifact.id)
|
|
20274
|
+
});
|
|
20275
|
+
}
|
|
20276
|
+
}
|
|
20277
|
+
let summary = input.summary;
|
|
20278
|
+
for (const replacement of replacements.reverse()) {
|
|
20279
|
+
summary = summary.slice(0, replacement.start) + replacement.href + summary.slice(replacement.end);
|
|
20280
|
+
}
|
|
20281
|
+
return { summary, artifacts };
|
|
20282
|
+
}
|
|
20045
20283
|
|
|
20046
20284
|
// src/runners/exec.ts
|
|
20047
20285
|
import { spawn } from "node:child_process";
|
|
@@ -35500,6 +35738,25 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
35500
35738
|
}
|
|
35501
35739
|
}
|
|
35502
35740
|
if (task.cancelledNow()) return cancelledBeforeRun();
|
|
35741
|
+
const publishedTaskFiles = /* @__PURE__ */ new Map();
|
|
35742
|
+
const publishFile = async (path, mediaType) => {
|
|
35743
|
+
const outcome = await publishTaskFile({
|
|
35744
|
+
path,
|
|
35745
|
+
...mediaType ? { mediaType } : {},
|
|
35746
|
+
cwd,
|
|
35747
|
+
allowedRoots: [taskRoot, cwd],
|
|
35748
|
+
agentOp: (op) => task.agentOp(op)
|
|
35749
|
+
});
|
|
35750
|
+
const parsed = TaskArtifact.safeParse(
|
|
35751
|
+
outcome.ok && outcome.result && typeof outcome.result === "object" ? outcome.result["artifact"] : void 0
|
|
35752
|
+
);
|
|
35753
|
+
if (parsed.success) {
|
|
35754
|
+
const candidate = resolve9(cwd, path);
|
|
35755
|
+
const key = await realpath8(candidate).catch(() => candidate);
|
|
35756
|
+
publishedTaskFiles.set(key, parsed.data);
|
|
35757
|
+
}
|
|
35758
|
+
return outcome;
|
|
35759
|
+
};
|
|
35503
35760
|
const [secrets, attachedConnections, providerGrants] = await Promise.all([
|
|
35504
35761
|
task.secrets(),
|
|
35505
35762
|
task.connections(),
|
|
@@ -35643,13 +35900,7 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
35643
35900
|
pendingAsks--;
|
|
35644
35901
|
}
|
|
35645
35902
|
},
|
|
35646
|
-
publishFile
|
|
35647
|
-
path,
|
|
35648
|
-
...mediaType ? { mediaType } : {},
|
|
35649
|
-
cwd,
|
|
35650
|
-
allowedRoots: [taskRoot, cwd],
|
|
35651
|
-
agentOp: (op) => task.agentOp(op)
|
|
35652
|
-
}),
|
|
35903
|
+
publishFile,
|
|
35653
35904
|
agentOp: (op) => task.agentOp(op),
|
|
35654
35905
|
// GitHub repository work belongs in the installed `git` and `gh`
|
|
35655
35906
|
// commands backed by GithubShellAuth. Do not advertise the bundled
|
|
@@ -35955,6 +36206,16 @@ ${attachmentSection}` : prompt;
|
|
|
35955
36206
|
opts.onUnsafeRunnerCleanup?.(result.summary);
|
|
35956
36207
|
}
|
|
35957
36208
|
}
|
|
36209
|
+
if (result.outcome === "done") {
|
|
36210
|
+
const linkedFiles = await publishLinkedTaskFiles({
|
|
36211
|
+
summary: result.summary,
|
|
36212
|
+
cwd,
|
|
36213
|
+
allowedRoots: [taskRoot, cwd],
|
|
36214
|
+
publishedArtifacts: publishedTaskFiles,
|
|
36215
|
+
agentOp: (op) => task.agentOp(op)
|
|
36216
|
+
});
|
|
36217
|
+
result = { ...result, summary: linkedFiles.summary };
|
|
36218
|
+
}
|
|
35958
36219
|
task.event(
|
|
35959
36220
|
"status",
|
|
35960
36221
|
`${adapter.displayName} finished. Tokens in ${result.usage.inputTokens}, out ${result.usage.outputTokens}` + (result.usage.totalCostUsd !== void 0 ? `, cost $${result.usage.totalCostUsd.toFixed(4)}` : "")
|