@adhdev/daemon-core 0.9.62 → 0.9.64

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.
@@ -32,6 +32,13 @@ export interface GitStashPushResult extends GitRepoIdentity {
32
32
  message: string;
33
33
  lastCheckedAt: number;
34
34
  }
35
+ export interface GitPushResult extends GitRepoIdentity {
36
+ remote: string;
37
+ branch: string;
38
+ output: string;
39
+ newBranch: boolean;
40
+ lastCheckedAt: number;
41
+ }
35
42
  export interface GitCommandServices {
36
43
  getStatus?: (params: {
37
44
  workspace: string;
@@ -90,6 +97,12 @@ export interface GitCommandServices {
90
97
  remoteUrl: string;
91
98
  remote: string;
92
99
  }>;
100
+ push?: (params: {
101
+ workspace: string;
102
+ remote?: string;
103
+ branch?: string;
104
+ setUpstream?: boolean;
105
+ }) => Promise<GitPushResult>;
93
106
  }
94
107
  type GitCommandFailure = {
95
108
  success: false;
@@ -130,6 +143,9 @@ type GitCommandSuccess = {
130
143
  success: true;
131
144
  remoteUrl: string;
132
145
  remote: string;
146
+ } | {
147
+ success: true;
148
+ push: GitPushResult;
133
149
  };
134
150
  export type GitCommandResult = GitCommandSuccess | GitCommandFailure;
135
151
  export declare function createDefaultGitCommandServices(): GitCommandServices;
@@ -110,4 +110,4 @@ export interface GitWorkspaceUpdate {
110
110
  seq: number;
111
111
  timestamp: number;
112
112
  }
113
- export type GitCommandName = 'git_status' | 'git_diff_summary' | 'git_diff_file' | 'git_snapshot_create' | 'git_snapshot_compare' | 'git_log' | 'git_checkpoint' | 'git_stash_push' | 'git_stash_pop' | 'git_checkout_files' | 'git_remote_url';
113
+ export type GitCommandName = 'git_status' | 'git_diff_summary' | 'git_diff_file' | 'git_snapshot_create' | 'git_snapshot_compare' | 'git_log' | 'git_checkpoint' | 'git_stash_push' | 'git_stash_pop' | 'git_checkout_files' | 'git_remote_url' | 'git_push';
package/dist/index.js CHANGED
@@ -5642,7 +5642,8 @@ var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
5642
5642
  "git_stash_push",
5643
5643
  "git_stash_pop",
5644
5644
  "git_checkout_files",
5645
- "git_remote_url"
5645
+ "git_remote_url",
5646
+ "git_push"
5646
5647
  ]);
5647
5648
  var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
5648
5649
  "session_baseline",
@@ -5688,7 +5689,8 @@ function createDefaultGitCommandServices() {
5688
5689
  stashPush: async ({ workspace, message, includeUntracked = false }) => gitStashPush(workspace, message, includeUntracked),
5689
5690
  stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
5690
5691
  checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
5691
- getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote)
5692
+ getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote),
5693
+ push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream)
5692
5694
  };
5693
5695
  }
5694
5696
  var defaultGitCommandServices = createDefaultGitCommandServices();
@@ -5856,6 +5858,20 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
5856
5858
  if ("success" in remoteResult) return remoteResult;
5857
5859
  return { success: true, remoteUrl: remoteResult.remoteUrl, remote: remoteResult.remote };
5858
5860
  }
5861
+ case "git_push": {
5862
+ if (!services.push) return serviceNotImplemented(command);
5863
+ const remote = typeof args?.remote === "string" && args.remote.trim() ? args.remote.trim() : "origin";
5864
+ const branch = typeof args?.branch === "string" && args.branch.trim() ? args.branch.trim() : void 0;
5865
+ const setUpstream = Boolean(args?.setUpstream);
5866
+ if (!/^[a-zA-Z0-9_.\-]+$/.test(remote)) {
5867
+ return failure("invalid_args", "remote must contain only alphanumeric characters, dots, hyphens, and underscores");
5868
+ }
5869
+ if (branch !== void 0 && !/^[a-zA-Z0-9/_.\-]+$/.test(branch)) {
5870
+ return failure("invalid_args", "branch must contain only alphanumeric characters, slashes, dots, hyphens, and underscores");
5871
+ }
5872
+ const pushResult = await runService(() => services.push({ workspace, remote, branch, setUpstream }));
5873
+ return "success" in pushResult ? pushResult : { success: true, push: pushResult };
5874
+ }
5859
5875
  default:
5860
5876
  return failure("invalid_args", `Unknown Git command: ${command}`);
5861
5877
  }
@@ -5958,6 +5974,49 @@ async function gitGetRemoteUrl(workspace, remote) {
5958
5974
  }
5959
5975
  return { remoteUrl, remote };
5960
5976
  }
5977
+ async function gitPush(workspace, remote, branch, setUpstream) {
5978
+ const lastCheckedAt = Date.now();
5979
+ const repo = await resolveGitRepository(workspace);
5980
+ const repoRoot = repo.repoRoot;
5981
+ let resolvedBranch = branch;
5982
+ if (!resolvedBranch) {
5983
+ const branchResult = await runGit(repo, ["symbolic-ref", "--short", "HEAD"], { cwd: repoRoot });
5984
+ resolvedBranch = branchResult.stdout.trim();
5985
+ if (!resolvedBranch) {
5986
+ throw new GitCommandError("git_command_failed", "Cannot push: not on a branch (detached HEAD)");
5987
+ }
5988
+ }
5989
+ const pushArgs = ["push"];
5990
+ if (setUpstream) pushArgs.push("--set-upstream");
5991
+ pushArgs.push(remote, resolvedBranch);
5992
+ let output = "";
5993
+ let newBranch = false;
5994
+ try {
5995
+ const result = await runGit(repo, pushArgs, { cwd: repoRoot });
5996
+ output = (result.stdout + result.stderr).trim();
5997
+ newBranch = /\[new branch\]/i.test(output);
5998
+ } catch (err) {
5999
+ const errOutput = (err?.stdout ?? "") + (err?.stderr ?? "");
6000
+ if (!setUpstream && /no upstream branch|set-upstream/i.test(errOutput)) {
6001
+ const retryArgs = ["push", "--set-upstream", remote, resolvedBranch];
6002
+ const retryResult = await runGit(repo, retryArgs, { cwd: repoRoot });
6003
+ output = (retryResult.stdout + retryResult.stderr).trim();
6004
+ newBranch = /\[new branch\]/i.test(output);
6005
+ } else {
6006
+ throw new GitCommandError("git_command_failed", errOutput || err?.message || "git push failed");
6007
+ }
6008
+ }
6009
+ return {
6010
+ workspace: repo.workspace,
6011
+ repoRoot,
6012
+ isGitRepo: true,
6013
+ remote,
6014
+ branch: resolvedBranch,
6015
+ output,
6016
+ newBranch,
6017
+ lastCheckedAt
6018
+ };
6019
+ }
5961
6020
  function formatOptionalGitLogRangeArg(flag, value) {
5962
6021
  return value ? [`${flag}=${value}`] : [];
5963
6022
  }
@@ -12283,9 +12342,34 @@ function findLastMessageIndexBySignature(messages, signature) {
12283
12342
  }
12284
12343
  return -1;
12285
12344
  }
12345
+ function isReadChatConversationAnchorMessage(message) {
12346
+ if (!message) return false;
12347
+ const role = String(message.role || "").trim().toLowerCase();
12348
+ if (role !== "user" && role !== "assistant") return false;
12349
+ const kind = String(message.kind || "standard").trim().toLowerCase();
12350
+ return !kind || kind === "standard";
12351
+ }
12352
+ function buildVisibleReadChatTailMessages(messages, tailLimit) {
12353
+ const totalMessages = messages.length;
12354
+ if (tailLimit <= 0 || totalMessages <= tailLimit) return messages;
12355
+ const tailMessages = messages.slice(-tailLimit);
12356
+ if (tailMessages.some(isReadChatConversationAnchorMessage)) return tailMessages;
12357
+ const hiddenMessages = messages.slice(0, totalMessages - tailLimit);
12358
+ const anchors = [];
12359
+ const seenRoles = /* @__PURE__ */ new Set();
12360
+ for (let index = hiddenMessages.length - 1; index >= 0 && anchors.length < 2; index -= 1) {
12361
+ const message = hiddenMessages[index];
12362
+ if (!isReadChatConversationAnchorMessage(message)) continue;
12363
+ const role = String(message.role || "").trim().toLowerCase();
12364
+ if (seenRoles.has(role)) continue;
12365
+ seenRoles.add(role);
12366
+ anchors.unshift(message);
12367
+ }
12368
+ return anchors.length > 0 ? [...anchors, ...tailMessages] : tailMessages;
12369
+ }
12286
12370
  function buildBoundedTailSync(messages, cursor) {
12287
12371
  const totalMessages = messages.length;
12288
- const tailMessages = cursor.tailLimit > 0 && totalMessages > cursor.tailLimit ? messages.slice(-cursor.tailLimit) : messages;
12372
+ const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
12289
12373
  return {
12290
12374
  syncMode: "full",
12291
12375
  replaceFrom: 0,
@@ -12407,8 +12491,8 @@ function buildReadChatCommandResult(payload, args) {
12407
12491
  const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
12408
12492
  const cursor = normalizeReadChatCursor(args);
12409
12493
  if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
12410
- const tailMessages = messages.slice(-cursor.tailLimit);
12411
- const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
12494
+ const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
12495
+ const lastMessageSignature = getChatMessageSignature(messages[messages.length - 1]);
12412
12496
  return {
12413
12497
  success: true,
12414
12498
  ...validatedPayload,