lody 0.58.0 → 0.59.1

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.
@@ -6,6 +6,7 @@ import path__default from "node:path";
6
6
  import { execFile } from "node:child_process";
7
7
  import os__default from "node:os";
8
8
  import { watch, existsSync, readFileSync } from "node:fs";
9
+ import { createRequire } from "node:module";
9
10
  import { L as LoroDoc, C as Cursor, __tla as __tla_2 } from "./loro_wasm_bg-BV-n7JyC.js";
10
11
  import "fs";
11
12
  import "path";
@@ -45,7 +46,6 @@ import "assert";
45
46
  import "fs/promises";
46
47
  import "better-sqlite3";
47
48
  import "perf_hooks";
48
- import "node:module";
49
49
  import "node:stream/promises";
50
50
  import "node:string_decoder";
51
51
  import "node:assert";
@@ -53,7 +53,7 @@ import "node:buffer";
53
53
  import "node:async_hooks";
54
54
  import { __tla as __tla_3 } from "../index.js";
55
55
  import { bE, bF, bG, bH, bI, bJ, bK, bL, bM, bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, h, c6, c7, c8, r, u, c9, ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, H, cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz, cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM } from "../index.js";
56
- let CODE_COLLAB_PACKAGE, CodeCollabGuestSession, CodeCollabTextDocumentStore, DEFAULT_TEXT_DOCUMENT_UPDATE_TIMEOUT_MS, GuestRpcClient, WEB_JOIN_LINK_MAX_LENGTH, WEB_JOIN_LINK_WARNING_LENGTH, assertWebJoinLinkWithinBudget, buildCapturedTurnHistoryRecords, classifyHostFileWatchPathEvent, classifyHostLivenessFromPresences, computeHostFileWatcherMaxWaitMs, computeHostLoopSleepMs, computeHostTurnChanges, computeHostTurnChangesEffect, createDiskTokenForPath, createDiskTokenForPathEffect, createHostHydrationContextFromSession, createHostLoopWakeSignal, createHostSaveEchoSuppressorV1, createLoroCursorAnchorV1, createWebJoinLink, createWebJoinLinks, dispatchHostRpcEnvelopeV1, dispatchHostRpcEnvelopeV1Effect, downloadBlobObjectEffect, getHostLivenessStatusV1, getHostLivenessStatusV1Effect, handleHostFileWatcherEventV1, hydrateBlobFile, hydrateBlobFileEffect, hydrateTextFile, hydrateTextFileEffect, initializeTextSaveStateV1, initializeTextSaveStateV1Effect, makeHostLoopTelemetryHandlers, markTextSaveStateDirtyForSnapshotV1, parseHostCommandArgs, prepareHostSession, prepareHostSessionEffect, prepareHostSessionRuntime, prepareHostSessionRuntimeEffect, prepareTextHydrationBaselineV1Effect, processHostRpcBatchEffect$1, processHostRpcBatchV1, publishCursorStateV1, publishCursorStateV1Effect, publishHostCurrentChanges, publishHostCursorV1, publishHostParticipantPresenceV1, publishHostPresenceV1, publishHostPresenceV1Effect, publishHostSelectionV1, publishHostSession, publishHostSessionEffect, publishHostSessionRuntime, publishHostSessionRuntimeEffect, publishParticipantPresenceV1, publishParticipantPresenceV1Effect, publishPreparedHostSessionRuntime, publishPreparedHostSessionRuntimeEffect, publishSelectionStateV1, publishSelectionStateV1Effect, readCursorStateSnapshotV1, readCursorStateSnapshotV1Effect, readHostCursorsV1, readHostParticipantPresenceV1, readHostPresencePeerSnapshotV1, readHostPresencePeerSnapshotV1Effect, readHostPresenceSnapshotV1, readHostPresenceSnapshotV1Effect, readHostSelectionsV1, readParticipantPresenceSnapshotV1, readParticipantPresenceSnapshotV1Effect, readSelectionStateSnapshotV1, readSelectionStateSnapshotV1Effect, reconcileOpenTextDocumentRenamesByContent, reconcileOpenTextDocumentRenamesByContentEffect, recordTextHydrationBaselineV1Effect, reloadTextFileFromDiskIfChangedV1, reloadTextFileFromDiskIfChangedV1Effect, reloadTextFileFromDiskV1, reloadTextFileFromDiskV1Effect, requestPendingMetadataRescanV1, resolveHostLspDefinition, resolveHostLspDefinitionEffect, resolveHostLspReferences, resolveHostLspReferencesEffect, resolveLoroCursorAnchorOffsetV1, resolveSaveConflictV1, resolveSaveConflictV1Effect, runHostEventLoopEffect, runHostEventLoopV1, saveTextFileV1, saveTextFileV1Effect, shouldAutoSaveDirtyTextDocument, snapshotHostTurnHistoryFiles, snapshotHostTurnHistoryFilesEffect, startHostFileWatcher, startHostSession, startHostSessionEffect, startPreparedHostSession, startPreparedHostSessionEffect, takeDuePendingMetadataRescanV1, watchCursorStateV1, watchHostPresencePeerSnapshotV1, watchHostPresenceSnapshotV1, watchParticipantPresenceV1, watchSelectionStateV1;
56
+ let CODE_COLLAB_PACKAGE, CodeCollabGuestSession, CodeCollabTextDocumentStore, DEFAULT_TEXT_DOCUMENT_UPDATE_TIMEOUT_MS, GuestRpcClient, WEB_JOIN_LINK_MAX_LENGTH, WEB_JOIN_LINK_WARNING_LENGTH, assertWebJoinLinkWithinBudget, buildCapturedTurnHistoryRecords, classifyHostFileWatchPathEvent, classifyHostLivenessFromPresences, computeHostFileWatcherMaxWaitMs, computeHostLoopSleepMs, computeHostTurnChanges, computeHostTurnChangesEffect, createDiskTokenForPath, createDiskTokenForPathEffect, createHostHydrationContextFromSession, createHostLoopWakeSignal, createHostSaveEchoSuppressorV1, createLoroCursorAnchorV1, createWebJoinLink, createWebJoinLinks, dispatchHostRpcEnvelopeV1, dispatchHostRpcEnvelopeV1Effect, downloadBlobObjectEffect, getHostLivenessStatusV1, getHostLivenessStatusV1Effect, handleHostFileWatcherEventV1, hydrateBlobFile, hydrateBlobFileEffect, hydrateTextFile, hydrateTextFileEffect, initializeTextSaveStateV1, initializeTextSaveStateV1Effect, loadTypeScriptModule, makeHostLoopTelemetryHandlers, markTextSaveStateDirtyForSnapshotV1, parseHostCommandArgs, prepareHostSession, prepareHostSessionEffect, prepareHostSessionRuntime, prepareHostSessionRuntimeEffect, prepareTextHydrationBaselineV1Effect, processHostRpcBatchEffect$1, processHostRpcBatchV1, publishCursorStateV1, publishCursorStateV1Effect, publishHostCurrentChanges, publishHostCursorV1, publishHostParticipantPresenceV1, publishHostPresenceV1, publishHostPresenceV1Effect, publishHostSelectionV1, publishHostSession, publishHostSessionEffect, publishHostSessionRuntime, publishHostSessionRuntimeEffect, publishParticipantPresenceV1, publishParticipantPresenceV1Effect, publishPreparedHostSessionRuntime, publishPreparedHostSessionRuntimeEffect, publishSelectionStateV1, publishSelectionStateV1Effect, readCursorStateSnapshotV1, readCursorStateSnapshotV1Effect, readHostCursorsV1, readHostParticipantPresenceV1, readHostPresencePeerSnapshotV1, readHostPresencePeerSnapshotV1Effect, readHostPresenceSnapshotV1, readHostPresenceSnapshotV1Effect, readHostSelectionsV1, readParticipantPresenceSnapshotV1, readParticipantPresenceSnapshotV1Effect, readSelectionStateSnapshotV1, readSelectionStateSnapshotV1Effect, reconcileOpenTextDocumentRenamesByContent, reconcileOpenTextDocumentRenamesByContentEffect, recordTextHydrationBaselineV1Effect, reloadTextFileFromDiskIfChangedV1, reloadTextFileFromDiskIfChangedV1Effect, reloadTextFileFromDiskV1, reloadTextFileFromDiskV1Effect, requestPendingMetadataRescanV1, resolveHostLspDefinition, resolveHostLspDefinitionEffect, resolveHostLspReferences, resolveHostLspReferencesEffect, resolveLoroCursorAnchorOffsetV1, resolveSaveConflictV1, resolveSaveConflictV1Effect, runHostEventLoopEffect, runHostEventLoopV1, saveTextFileV1, saveTextFileV1Effect, shouldAutoSaveDirtyTextDocument, snapshotHostTurnHistoryFiles, snapshotHostTurnHistoryFilesEffect, startHostFileWatcher, startHostSession, startHostSessionEffect, startPreparedHostSession, startPreparedHostSessionEffect, takeDuePendingMetadataRescanV1, watchCursorStateV1, watchHostPresencePeerSnapshotV1, watchHostPresenceSnapshotV1, watchParticipantPresenceV1, watchSelectionStateV1;
57
57
  let __tla = Promise.all([
58
58
  (() => {
59
59
  try {
@@ -2794,16 +2794,19 @@ let __tla = Promise.all([
2794
2794
  }
2795
2795
  };
2796
2796
  }
2797
- let typeScriptModulePromise;
2798
- function loadTypeScriptModuleEffect() {
2799
- return tryPromiseEffect(async () => {
2800
- typeScriptModulePromise ??= import("typescript").then(async (m) => {
2801
- await m.__tla;
2802
- return m;
2803
- });
2804
- return await typeScriptModulePromise;
2805
- });
2806
- }
2797
+ loadTypeScriptModule = function(workspaceRoot) {
2798
+ const anchors = [
2799
+ path__default.join(path__default.resolve(workspaceRoot), "package.json"),
2800
+ import.meta.url
2801
+ ];
2802
+ for (const anchor of anchors) {
2803
+ try {
2804
+ return createRequire(anchor)("typescript");
2805
+ } catch {
2806
+ }
2807
+ }
2808
+ return void 0;
2809
+ };
2807
2810
  resolveHostLspDefinition = async function(input) {
2808
2811
  return runPromiseEffect(resolveHostLspDefinitionEffect(input));
2809
2812
  };
@@ -2866,7 +2869,10 @@ let __tla = Promise.all([
2866
2869
  if (!isTypeScriptLikePath(entry.path)) {
2867
2870
  return unsupported(`No host language service is configured for ${path__default.extname(entry.path) || "this file"}`);
2868
2871
  }
2869
- const ts = yield* loadTypeScriptModuleEffect();
2872
+ const ts = yield* trySyncEffect(() => loadTypeScriptModule(context.workspaceRoot));
2873
+ if (ts === void 0) {
2874
+ return unsupported("TypeScript is not installed in this workspace; add it to enable code navigation");
2875
+ }
2870
2876
  const liveText = yield* readOptionalLiveTextEffect(context, entry.fileId);
2871
2877
  const project = yield* trySyncEffect(() => createTypeScriptLspProject({
2872
2878
  currentFile: entry,
@@ -9977,6 +9983,7 @@ export {
9977
9983
  isMissingHostRpcStreamAppendError,
9978
9984
  ci as isRetryableHostRpcStreamReadError,
9979
9985
  cj as isStaleHostRpcStreamReadOffsetError,
9986
+ loadTypeScriptModule,
9980
9987
  logCodeCollabRuntimeDebug,
9981
9988
  ck as makeCodeCollabConfigLayer,
9982
9989
  cl as makeCodeCollabHostTelemetrySink,
package/dist/index.js CHANGED
@@ -52,12 +52,12 @@ import require$$0$a from "net";
52
52
  import require$$4$3 from "tls";
53
53
  import { i as imports, _ as __wbg_set_wasm$1, r as rawWasm, L as LoroDoc, E as EphemeralStoreWasm, U as UndoManager, c as callPendingEvents$3, a as LoroTree, b as LoroText, d as LoroMovableList, e as LoroList, f as LoroMap, g as __vite__initWasm, V as VersionVector, h as decodeImportBlobMeta, __tla as __tla_0 } from "./chunks/loro_wasm_bg-BV-n7JyC.js";
54
54
  import assert from "assert";
55
- import * as fs$2 from "fs/promises";
55
+ import * as fs$1 from "fs/promises";
56
56
  import fs__default$1, { statfs } from "fs/promises";
57
57
  import BetterSqlite3 from "better-sqlite3";
58
58
  import { performance as performance$1 } from "perf_hooks";
59
59
  import { createRequire as createRequire$1 } from "node:module";
60
- import * as fs$1 from "node:fs/promises";
60
+ import * as fs$2 from "node:fs/promises";
61
61
  import fs__default$2, { mkdir as mkdir$1, mkdtemp, chmod, writeFile, rm, rename, unlink, readFile as readFile$1, opendir, lstat, readlink, open, stat } from "node:fs/promises";
62
62
  import { pipeline } from "node:stream/promises";
63
63
  import { StringDecoder } from "node:string_decoder";
@@ -36827,7 +36827,7 @@ Mongoose Error Code: ${error2.code}` : ""}`
36827
36827
  return client;
36828
36828
  }
36829
36829
  const name$1 = "lody";
36830
- const version$4 = "0.58.0";
36830
+ const version$4 = "0.59.1";
36831
36831
  const description$1 = "Lody Agent CLI tool for managing remote command execution";
36832
36832
  const type$2 = "module";
36833
36833
  const main$4 = "dist/index.js";
@@ -46838,6 +46838,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46838
46838
  version: string$1().optional(),
46839
46839
  error: string$1().optional()
46840
46840
  }).strict();
46841
+ object$1({
46842
+ type: literal$1("machine/bug-report"),
46843
+ machineId: MachineIdSchema,
46844
+ workspaceId: WorkspaceIdSchema,
46845
+ description: string$1().trim().min(1),
46846
+ reporterUserId: string$1().trim().min(1),
46847
+ requestToken: string$1().trim().min(1)
46848
+ }).strict();
46849
+ object$1({
46850
+ type: literal$1("machine/bug-report_response"),
46851
+ machineId: MachineIdSchema,
46852
+ success: boolean(),
46853
+ bugReportId: string$1().optional(),
46854
+ error: string$1().optional()
46855
+ }).strict();
46841
46856
  const SessionCodeCollabHostStartStatusSchema = _enum$1([
46842
46857
  "started",
46843
46858
  "already-running",
@@ -113775,6 +113790,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
113775
113790
  "machine/acp-capabilities-refresh",
113776
113791
  "machine/acp-binary-status",
113777
113792
  "machine/acp-binary-install",
113793
+ "machine/bug-report",
113778
113794
  "session/code-collab-ingress",
113779
113795
  "session/code-collab-host-start",
113780
113796
  "session/preview-create",
@@ -113829,6 +113845,14 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
113829
113845
  agentType: string$1().trim().min(1)
113830
113846
  }).strict()
113831
113847
  }).strict();
113848
+ const LoroMachineBugReportRpcRequestSchema = BaseRpcRequestSchema.extend({
113849
+ method: literal$1("machine/bug-report"),
113850
+ params: object$1({
113851
+ description: string$1().trim().min(1),
113852
+ reporterUserId: string$1().trim().min(1),
113853
+ requestToken: string$1().trim().min(1)
113854
+ }).strict()
113855
+ }).strict();
113832
113856
  const LoroSessionCodeCollabHostStartRpcRequestSchema = BaseRpcRequestSchema.extend({
113833
113857
  method: literal$1("session/code-collab-host-start"),
113834
113858
  params: object$1({
@@ -113937,6 +113961,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
113937
113961
  LoroMachineAcpCapabilitiesRefreshRpcRequestSchema,
113938
113962
  LoroMachineAcpBinaryStatusRpcRequestSchema,
113939
113963
  LoroMachineAcpBinaryInstallRpcRequestSchema,
113964
+ LoroMachineBugReportRpcRequestSchema,
113940
113965
  LoroSessionCodeCollabIngressRpcRequestSchema,
113941
113966
  LoroSessionCodeCollabHostStartRpcRequestSchema,
113942
113967
  LoroSessionPreviewCreateRpcRequestSchema,
@@ -114311,6 +114336,22 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
114311
114336
  await this.appendResultResponse(request.replyTo, request.id, request.method, response);
114312
114337
  return;
114313
114338
  }
114339
+ case "machine/bug-report": {
114340
+ if (!this.deps.submitBugReport) {
114341
+ await this.appendErrorResponse(request.replyTo, request.id, request.method, {
114342
+ code: LORO_STREAMS_RPC_ERROR_CODES.methodUnavailable,
114343
+ message: "Bug report is not available on this machine."
114344
+ });
114345
+ return;
114346
+ }
114347
+ const response = await this.deps.submitBugReport({
114348
+ description: request.params.description,
114349
+ reporterUserId: request.params.reporterUserId,
114350
+ requestToken: request.params.requestToken
114351
+ });
114352
+ await this.appendResultResponse(request.replyTo, request.id, request.method, response);
114353
+ return;
114354
+ }
114314
114355
  case "session/code-collab-ingress": {
114315
114356
  if (!this.deps.ingressSessionCodeCollab) {
114316
114357
  await this.appendErrorResponse(request.replyTo, request.id, request.method, {
@@ -114462,6 +114503,252 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
114462
114503
  }
114463
114504
  }
114464
114505
  }
114506
+ const WorkspaceSummarySchema = object$1({
114507
+ id: string$1(),
114508
+ name: string$1(),
114509
+ slug: string$1().nullable(),
114510
+ role: string$1()
114511
+ });
114512
+ const WorkspaceGitHubRepositorySchema = object$1({
114513
+ id: number$3(),
114514
+ name: string$1(),
114515
+ fullName: string$1(),
114516
+ private: boolean()
114517
+ });
114518
+ const WorkspaceListResultSchema = discriminatedUnion("valid", [
114519
+ object$1({
114520
+ valid: literal$1(false),
114521
+ userId: _null(),
114522
+ workspaces: array$2(WorkspaceSummarySchema)
114523
+ }),
114524
+ object$1({
114525
+ valid: literal$1(true),
114526
+ userId: string$1(),
114527
+ workspaces: array$2(WorkspaceSummarySchema)
114528
+ })
114529
+ ]);
114530
+ const RegisterMachineAccessResultSchema = object$1({
114531
+ success: literal$1(true),
114532
+ existing: boolean(),
114533
+ sharedWithTeam: boolean()
114534
+ });
114535
+ const MachineAccessCheckResultSchema = discriminatedUnion("allowed", [
114536
+ object$1({
114537
+ allowed: literal$1(true)
114538
+ }),
114539
+ object$1({
114540
+ allowed: literal$1(false),
114541
+ reason: _enum$1([
114542
+ "requester_not_member",
114543
+ "machine_not_registered",
114544
+ "not_visible",
114545
+ "project_not_shared"
114546
+ ])
114547
+ })
114548
+ ]);
114549
+ const WorkspaceGitHubRepositoryListResultSchema = discriminatedUnion("valid", [
114550
+ object$1({
114551
+ valid: literal$1(false),
114552
+ repositories: array$2(WorkspaceGitHubRepositorySchema)
114553
+ }),
114554
+ object$1({
114555
+ valid: literal$1(true),
114556
+ repositories: array$2(WorkspaceGitHubRepositorySchema)
114557
+ })
114558
+ ]);
114559
+ function createAuthConvexClient() {
114560
+ if (!LODY_AUTH_URL) {
114561
+ throw new Error("LODY_AUTH_URL is not defined.");
114562
+ }
114563
+ return new ConvexHttpClient(LODY_AUTH_URL);
114564
+ }
114565
+ async function listWorkspacesForToken(token2) {
114566
+ const client = createAuthConvexClient();
114567
+ const raw2 = await client.query(api.deviceAuth.listMyWorkspacesForCliToken, {
114568
+ token: token2
114569
+ });
114570
+ const parsed = WorkspaceListResultSchema.parse(raw2);
114571
+ if (!parsed.valid) {
114572
+ throw new Error("CLI token is invalid or expired. Run `lody login` again.");
114573
+ }
114574
+ return parsed.workspaces;
114575
+ }
114576
+ async function listWorkspaceGitHubRepositoriesForCliToken(input2) {
114577
+ const client = createAuthConvexClient();
114578
+ const raw2 = await client.query(api.github.listWorkspaceRepositoriesForCliToken, {
114579
+ cliToken: input2.token,
114580
+ workspaceId: input2.workspaceId
114581
+ });
114582
+ const parsed = WorkspaceGitHubRepositoryListResultSchema.parse(raw2);
114583
+ if (!parsed.valid) {
114584
+ throw new Error("CLI token is invalid or expired. Run `lody login` again.");
114585
+ }
114586
+ return parsed.repositories;
114587
+ }
114588
+ async function registerMachineAccessForCliToken(input2) {
114589
+ const client = createAuthConvexClient();
114590
+ const raw2 = await client.mutation(api.machines.upsertMachineRegistrationFromCliToken, {
114591
+ cliToken: input2.token,
114592
+ workspaceId: input2.workspaceId,
114593
+ machineId: input2.machineId
114594
+ });
114595
+ return RegisterMachineAccessResultSchema.parse(raw2);
114596
+ }
114597
+ const LEGACY_LOCAL_PROJECT_ID_VALIDATOR_ERROR = /ArgumentValidationError[\s\S]*extra field `localProjectId`/;
114598
+ async function canUseMachineForCliToken(input2) {
114599
+ const client = createAuthConvexClient();
114600
+ const baseArgs = {
114601
+ cliToken: input2.token,
114602
+ workspaceId: input2.workspaceId,
114603
+ machineId: input2.machineId,
114604
+ requesterUserId: input2.requesterUserId
114605
+ };
114606
+ try {
114607
+ const raw2 = await client.query(api.machines.canUseMachineFromCliToken, {
114608
+ ...baseArgs,
114609
+ ...input2.localProjectId !== void 0 ? {
114610
+ localProjectId: input2.localProjectId
114611
+ } : {}
114612
+ });
114613
+ return MachineAccessCheckResultSchema.parse(raw2);
114614
+ } catch (error2) {
114615
+ if (input2.localProjectId !== void 0 && error2 instanceof Error && LEGACY_LOCAL_PROJECT_ID_VALIDATOR_ERROR.test(error2.message)) {
114616
+ const raw2 = await client.query(api.machines.canUseMachineFromCliToken, baseArgs);
114617
+ return MachineAccessCheckResultSchema.parse(raw2);
114618
+ }
114619
+ throw error2;
114620
+ }
114621
+ }
114622
+ const LOG_TAIL_MAX_BYTES = 4 * 1024 * 1024;
114623
+ const TRUNCATION_MARKER = "...[truncated: only the tail of this log file is included]\n";
114624
+ const BugReportCreateResponseSchema = object$1({
114625
+ bugReportId: string$1().min(1)
114626
+ });
114627
+ const formatBugReportLogDate = (date2) => {
114628
+ const year = date2.getFullYear();
114629
+ const month = String(date2.getMonth() + 1).padStart(2, "0");
114630
+ const day = String(date2.getDate()).padStart(2, "0");
114631
+ return `${year}-${month}-${day}`;
114632
+ };
114633
+ const tailOfLog = (content, maxBytes) => {
114634
+ const buffer2 = Buffer.from(content, "utf8");
114635
+ if (buffer2.byteLength <= maxBytes) {
114636
+ return {
114637
+ text: content,
114638
+ truncated: false
114639
+ };
114640
+ }
114641
+ return {
114642
+ text: buffer2.subarray(buffer2.byteLength - maxBytes).toString("utf8"),
114643
+ truncated: true
114644
+ };
114645
+ };
114646
+ const mergeBugReportLogs = (parts2) => parts2.map((part) => `===== ${part.fileName} =====
114647
+ ${part.truncated ? TRUNCATION_MARKER : ""}${part.content}`).join("\n\n");
114648
+ const collectBugReportLogs = async (now2 = /* @__PURE__ */ new Date(), logDir = LODY_LOG_DIR) => {
114649
+ const dates = [
114650
+ new Date(now2.getTime() - 24 * 60 * 60 * 1e3),
114651
+ now2
114652
+ ];
114653
+ const parts2 = [];
114654
+ for (const date2 of dates) {
114655
+ const fileName = `${formatBugReportLogDate(date2)}.log`;
114656
+ try {
114657
+ const raw2 = await fs$1.readFile(path$1.join(logDir, fileName), "utf8");
114658
+ const { text, truncated } = tailOfLog(raw2, LOG_TAIL_MAX_BYTES);
114659
+ parts2.push({
114660
+ fileName,
114661
+ content: text,
114662
+ truncated
114663
+ });
114664
+ } catch {
114665
+ }
114666
+ }
114667
+ return parts2;
114668
+ };
114669
+ const resolveConvexSiteUrl = () => {
114670
+ if (LODY_AUTH_SITE_URL) {
114671
+ return normalizeBaseUrl$1(LODY_AUTH_SITE_URL);
114672
+ }
114673
+ if (LODY_AUTH_URL) {
114674
+ return normalizeBaseUrl$1(deriveConvexSiteUrl(normalizeBaseUrl$1(LODY_AUTH_URL)));
114675
+ }
114676
+ return null;
114677
+ };
114678
+ const submitBugReportFromMachine = async (args2) => {
114679
+ const failure = (error2) => ({
114680
+ type: "machine/bug-report_response",
114681
+ machineId: args2.machineId,
114682
+ success: false,
114683
+ error: error2
114684
+ });
114685
+ if (args2.reporterUserId !== args2.machineUserId) {
114686
+ try {
114687
+ const access = await (args2.checkMachineAccess ?? canUseMachineForCliToken)({
114688
+ token: args2.token,
114689
+ workspaceId: args2.workspaceId,
114690
+ machineId: args2.machineId,
114691
+ requesterUserId: args2.reporterUserId
114692
+ });
114693
+ if (!access.allowed) {
114694
+ args2.logger.warn(`[bug-report] denied for requester ${args2.reporterUserId}: ${access.reason}`);
114695
+ return failure("This user is not allowed to request logs from this machine.");
114696
+ }
114697
+ } catch (error2) {
114698
+ const message = error2 instanceof Error ? error2.message : String(error2);
114699
+ args2.logger.warn(`[bug-report] machine access check failed: ${message}`);
114700
+ return failure("Could not verify machine access for this request.");
114701
+ }
114702
+ }
114703
+ const siteUrl = resolveConvexSiteUrl();
114704
+ if (!siteUrl) {
114705
+ return failure("Lody auth URL is not configured on this machine.");
114706
+ }
114707
+ try {
114708
+ const parts2 = await collectBugReportLogs();
114709
+ const logContent = mergeBugReportLogs(parts2);
114710
+ args2.logger.info(`[bug-report] uploading ${parts2.length} log file(s) (${logContent.length} chars) for workspace ${args2.workspaceId}`);
114711
+ const response = await fetch(`${siteUrl}/api/bug-reports/create`, {
114712
+ method: "POST",
114713
+ headers: {
114714
+ "Content-Type": "application/json",
114715
+ Authorization: `Bearer ${args2.token}`
114716
+ },
114717
+ body: JSON.stringify({
114718
+ workspaceId: args2.workspaceId,
114719
+ machineId: args2.machineId,
114720
+ description: args2.description,
114721
+ requestToken: args2.requestToken,
114722
+ ...logContent.length > 0 ? {
114723
+ logContent
114724
+ } : {},
114725
+ ...parts2.length > 0 ? {
114726
+ logFileNames: parts2.map((part) => part.fileName)
114727
+ } : {}
114728
+ })
114729
+ });
114730
+ if (!response.ok) {
114731
+ const detail = await response.text().catch(() => "");
114732
+ args2.logger.warn(`[bug-report] upload failed: status=${response.status} detail=${detail.slice(0, 500)}`);
114733
+ return failure(`Bug report upload failed with status ${response.status}.`);
114734
+ }
114735
+ const parsed = BugReportCreateResponseSchema.safeParse(await response.json());
114736
+ if (!parsed.success) {
114737
+ return failure("Bug report upload returned an invalid response.");
114738
+ }
114739
+ args2.logger.info(`[bug-report] created bug report ${parsed.data.bugReportId}`);
114740
+ return {
114741
+ type: "machine/bug-report_response",
114742
+ machineId: args2.machineId,
114743
+ success: true,
114744
+ bugReportId: parsed.data.bugReportId
114745
+ };
114746
+ } catch (error2) {
114747
+ const message = error2 instanceof Error ? error2.message : String(error2);
114748
+ args2.logger.warn(`[bug-report] upload failed: ${message}`);
114749
+ return failure(message);
114750
+ }
114751
+ };
114465
114752
  const normalizeGitHubRepo = (repo) => {
114466
114753
  const { owner, repo: repoName } = parseGitHubRepo(repo);
114467
114754
  return `${owner}/${repoName}`;
@@ -131825,11 +132112,11 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
131825
132112
  return null;
131826
132113
  }
131827
132114
  try {
131828
- const stat2 = await fs$1.stat(absolutePath);
132115
+ const stat2 = await fs$2.stat(absolutePath);
131829
132116
  if (!stat2.isFile() || stat2.size > (options?.maxBytes ?? defaultMaxTextFileBytes)) {
131830
132117
  return null;
131831
132118
  }
131832
- const content = await fs$1.readFile(absolutePath);
132119
+ const content = await fs$2.readFile(absolutePath);
131833
132120
  if (content.includes(0)) {
131834
132121
  return null;
131835
132122
  }
@@ -143320,7 +143607,7 @@ $mem | ConvertTo-Json -Compress
143320
143607
  await m.__tla;
143321
143608
  return m;
143322
143609
  }),
143323
- import("./chunks/index-dgDvn87c.js").then(async (m) => {
143610
+ import("./chunks/index-Dv4vvpJo.js").then(async (m) => {
143324
143611
  await m.__tla;
143325
143612
  return m;
143326
143613
  })
@@ -146486,122 +146773,6 @@ parentPort.on('message', (message) => {
146486
146773
  return readLocalFileAtRoot(rootPath, relativePath, maxBytes);
146487
146774
  }
146488
146775
  }
146489
- const WorkspaceSummarySchema = object$1({
146490
- id: string$1(),
146491
- name: string$1(),
146492
- slug: string$1().nullable(),
146493
- role: string$1()
146494
- });
146495
- const WorkspaceGitHubRepositorySchema = object$1({
146496
- id: number$3(),
146497
- name: string$1(),
146498
- fullName: string$1(),
146499
- private: boolean()
146500
- });
146501
- const WorkspaceListResultSchema = discriminatedUnion("valid", [
146502
- object$1({
146503
- valid: literal$1(false),
146504
- userId: _null(),
146505
- workspaces: array$2(WorkspaceSummarySchema)
146506
- }),
146507
- object$1({
146508
- valid: literal$1(true),
146509
- userId: string$1(),
146510
- workspaces: array$2(WorkspaceSummarySchema)
146511
- })
146512
- ]);
146513
- const RegisterMachineAccessResultSchema = object$1({
146514
- success: literal$1(true),
146515
- existing: boolean(),
146516
- sharedWithTeam: boolean()
146517
- });
146518
- const MachineAccessCheckResultSchema = discriminatedUnion("allowed", [
146519
- object$1({
146520
- allowed: literal$1(true)
146521
- }),
146522
- object$1({
146523
- allowed: literal$1(false),
146524
- reason: _enum$1([
146525
- "requester_not_member",
146526
- "machine_not_registered",
146527
- "not_visible",
146528
- "project_not_shared"
146529
- ])
146530
- })
146531
- ]);
146532
- const WorkspaceGitHubRepositoryListResultSchema = discriminatedUnion("valid", [
146533
- object$1({
146534
- valid: literal$1(false),
146535
- repositories: array$2(WorkspaceGitHubRepositorySchema)
146536
- }),
146537
- object$1({
146538
- valid: literal$1(true),
146539
- repositories: array$2(WorkspaceGitHubRepositorySchema)
146540
- })
146541
- ]);
146542
- function createAuthConvexClient() {
146543
- if (!LODY_AUTH_URL) {
146544
- throw new Error("LODY_AUTH_URL is not defined.");
146545
- }
146546
- return new ConvexHttpClient(LODY_AUTH_URL);
146547
- }
146548
- async function listWorkspacesForToken(token2) {
146549
- const client = createAuthConvexClient();
146550
- const raw2 = await client.query(api.deviceAuth.listMyWorkspacesForCliToken, {
146551
- token: token2
146552
- });
146553
- const parsed = WorkspaceListResultSchema.parse(raw2);
146554
- if (!parsed.valid) {
146555
- throw new Error("CLI token is invalid or expired. Run `lody login` again.");
146556
- }
146557
- return parsed.workspaces;
146558
- }
146559
- async function listWorkspaceGitHubRepositoriesForCliToken(input2) {
146560
- const client = createAuthConvexClient();
146561
- const raw2 = await client.query(api.github.listWorkspaceRepositoriesForCliToken, {
146562
- cliToken: input2.token,
146563
- workspaceId: input2.workspaceId
146564
- });
146565
- const parsed = WorkspaceGitHubRepositoryListResultSchema.parse(raw2);
146566
- if (!parsed.valid) {
146567
- throw new Error("CLI token is invalid or expired. Run `lody login` again.");
146568
- }
146569
- return parsed.repositories;
146570
- }
146571
- async function registerMachineAccessForCliToken(input2) {
146572
- const client = createAuthConvexClient();
146573
- const raw2 = await client.mutation(api.machines.upsertMachineRegistrationFromCliToken, {
146574
- cliToken: input2.token,
146575
- workspaceId: input2.workspaceId,
146576
- machineId: input2.machineId
146577
- });
146578
- return RegisterMachineAccessResultSchema.parse(raw2);
146579
- }
146580
- const LEGACY_LOCAL_PROJECT_ID_VALIDATOR_ERROR = /ArgumentValidationError[\s\S]*extra field `localProjectId`/;
146581
- async function canUseMachineForCliToken(input2) {
146582
- const client = createAuthConvexClient();
146583
- const baseArgs = {
146584
- cliToken: input2.token,
146585
- workspaceId: input2.workspaceId,
146586
- machineId: input2.machineId,
146587
- requesterUserId: input2.requesterUserId
146588
- };
146589
- try {
146590
- const raw2 = await client.query(api.machines.canUseMachineFromCliToken, {
146591
- ...baseArgs,
146592
- ...input2.localProjectId !== void 0 ? {
146593
- localProjectId: input2.localProjectId
146594
- } : {}
146595
- });
146596
- return MachineAccessCheckResultSchema.parse(raw2);
146597
- } catch (error2) {
146598
- if (input2.localProjectId !== void 0 && error2 instanceof Error && LEGACY_LOCAL_PROJECT_ID_VALIDATOR_ERROR.test(error2.message)) {
146599
- const raw2 = await client.query(api.machines.canUseMachineFromCliToken, baseArgs);
146600
- return MachineAccessCheckResultSchema.parse(raw2);
146601
- }
146602
- throw error2;
146603
- }
146604
- }
146605
146776
  const HTTP_HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
146606
146777
  "connection",
146607
146778
  "keep-alive",
@@ -148703,7 +148874,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
148703
148874
  const resolved = path__default.resolve(rootPath);
148704
148875
  let real = null;
148705
148876
  try {
148706
- real = await fs$2.realpath(resolved);
148877
+ real = await fs$1.realpath(resolved);
148707
148878
  } catch {
148708
148879
  real = null;
148709
148880
  }
@@ -150010,6 +150181,16 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
150010
150181
  workspaceId: this.workspaceId,
150011
150182
  agentType
150012
150183
  }),
150184
+ submitBugReport: async ({ description: description2, reporterUserId, requestToken }) => await submitBugReportFromMachine({
150185
+ workspaceId: this.workspaceId,
150186
+ machineId: this.machineId,
150187
+ description: description2,
150188
+ reporterUserId,
150189
+ requestToken,
150190
+ machineUserId: this.userId,
150191
+ token: this.token,
150192
+ logger: this.logger
150193
+ }),
150013
150194
  startSessionCodeCollabHost: async ({ sessionId, requestedByUserId }) => await this.startCodeCollabHostForRequest({
150014
150195
  type: "session/code-collab-host-start",
150015
150196
  machineId: this.machineId,
@@ -153164,6 +153345,18 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
153164
153345
  }, PERMISSION_REQUEST_TIMEOUT_MS);
153165
153346
  });
153166
153347
  }
153348
+ async resolveTitleConfig(sessionId, agentConfigId) {
153349
+ if (!agentConfigId) {
153350
+ return void 0;
153351
+ }
153352
+ try {
153353
+ const agentConfigMeta = await this.workspaceDocument.getAgentConfigById(agentConfigId);
153354
+ return agentConfigMeta?.titleGeneration;
153355
+ } catch (error2) {
153356
+ this.logger.debug(`[${sessionId}] Failed to load agent config ${agentConfigId} for title generation: ${formatErrorMessage$1(error2)}`);
153357
+ return void 0;
153358
+ }
153359
+ }
153167
153360
  async maybeGenerateAndStoreSessionTitle(sessionId, cliType, agentType, taskPrompt, env2, titleConfig) {
153168
153361
  if (this.titleGenerationInFlight.has(sessionId)) {
153169
153362
  return;
@@ -153179,6 +153372,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
153179
153372
  return;
153180
153373
  }
153181
153374
  this.logger.debug(`[${sessionId}] Generating session title because title is missing`);
153375
+ const resolvedTitleConfig = titleConfig ?? await this.resolveTitleConfig(sessionId, meta?.agentConfigId);
153182
153376
  const title2 = await generateTitleIsolated({
153183
153377
  cliType,
153184
153378
  agentType,
@@ -153186,7 +153380,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
153186
153380
  taskPrompt,
153187
153381
  logger: this.logger,
153188
153382
  env: env2,
153189
- titleConfig
153383
+ titleConfig: resolvedTitleConfig
153190
153384
  });
153191
153385
  if (!title2) {
153192
153386
  this.logger.debug(`[${sessionId}] Session title generation returned empty result`);
@@ -153478,18 +153672,21 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
153478
153672
  }
153479
153673
  let metaBranchName = null;
153480
153674
  let metaCustomAcp;
153675
+ let metaAgentConfigId;
153481
153676
  try {
153482
153677
  const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
153483
153678
  const meta = await sessionDoc.getMetaState();
153484
153679
  metaBranchName = meta?.branchName?.trim() || null;
153485
153680
  metaCustomAcp = meta?.customAcp;
153681
+ metaAgentConfigId = meta?.agentConfigId;
153486
153682
  if (metaBranchName && !metaBranchName.startsWith("session/")) {
153487
153683
  return;
153488
153684
  }
153489
153685
  } catch (error2) {
153490
153686
  this.logger.debug(`[${sessionId}] Failed to read session meta before branch rename: ${formatErrorMessage$1(error2)}`);
153491
153687
  }
153492
- const branchName = await this.generateBranchNameWithTimeout(cliType, agentType, trimmedPrompt, env2, 2e4, titleConfig, metaCustomAcp);
153688
+ const resolvedTitleConfig = titleConfig ?? await this.resolveTitleConfig(sessionId, metaAgentConfigId);
153689
+ const branchName = await this.generateBranchNameWithTimeout(cliType, agentType, trimmedPrompt, env2, 2e4, resolvedTitleConfig, metaCustomAcp);
153493
153690
  if (!branchName) {
153494
153691
  this.logger.debug(`[${sessionId}] Skipping branch rename: name generation timed out`);
153495
153692
  return;
@@ -160364,7 +160561,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
160364
160561
  const deps = {
160365
160562
  platform: process.platform,
160366
160563
  setPriority: os__default.setPriority,
160367
- writeFile: fs$2.writeFile,
160564
+ writeFile: fs$1.writeFile,
160368
160565
  ...options.deps ?? {}
160369
160566
  };
160370
160567
  if (deps.platform !== "linux") {
@@ -160415,10 +160612,10 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
160415
160612
  const defaultSandboxDeps = () => ({
160416
160613
  platform: process.platform,
160417
160614
  cgroupMount: DEFAULT_CGROUP_MOUNT,
160418
- fs: fs$2,
160615
+ fs: fs$1,
160419
160616
  spawnProcess: spawn,
160420
160617
  readSelfCgroupPath: async () => {
160421
- const content = await fs$2.readFile("/proc/self/cgroup", "utf8");
160618
+ const content = await fs$1.readFile("/proc/self/cgroup", "utf8");
160422
160619
  const line3 = content.split("\n").map((item) => item.trim()).find((item) => item.startsWith("0::"));
160423
160620
  if (!line3) {
160424
160621
  throw new Error("Unable to determine current cgroup path from /proc/self/cgroup");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lody",
3
- "version": "0.58.0",
3
+ "version": "0.59.1",
4
4
  "description": "Lody Agent CLI tool for managing remote command execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -74,12 +74,12 @@
74
74
  "winston-transport": "^4.7.1",
75
75
  "ws": "^8.18.3",
76
76
  "zod": "^4.1.5",
77
- "@lody/code-collab": "0.0.0",
78
77
  "@lody/cli-supervisor": "0.0.1",
78
+ "@lody/code-collab": "0.0.0",
79
79
  "@lody/code-session": "0.0.0",
80
+ "@lody/code-collab-testkit": "0.0.0",
80
81
  "@lody/convex": "0.0.1",
81
82
  "@lody/loro-streams-rpc": "0.0.1",
82
- "@lody/code-collab-testkit": "0.0.0",
83
83
  "@lody/shared": "0.0.1"
84
84
  },
85
85
  "files": [
@@ -89,7 +89,7 @@
89
89
  "LICENSE"
90
90
  ],
91
91
  "dependencies": {
92
- "better-sqlite3": "^11.10.0",
92
+ "better-sqlite3": "^12.10.0",
93
93
  "loro-crdt": "1.13.1",
94
94
  "shell-env": "^4.0.3",
95
95
  "typescript": "^5.9.3"