@ouro.bot/cli 0.1.0-alpha.247 → 0.1.0-alpha.248

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/changelog.json CHANGED
@@ -1,6 +1,13 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.248",
6
+ "changes": [
7
+ "feat(daemon): `ouro status` Git Sync now resolves and shows the actual remote URL via `git remote get-url`. Three states: `origin → git@github.com:me/foo.git` when the remote resolves, `local only` when sync is enabled but no remote is configured, `disabled` when sync is off. Previously you had to `cd` into the bundle and run `git remote -v` to find out where it pushes.",
8
+ "fix(heart/sync): `preTurnPull` now skips the pull when no git remote is configured, mirroring the existing `postTurnPush` behavior. Closes the half-implemented 'no-remote sync' (local-only commit log) story \u2014 previously, enabling sync without a remote produced a `syncFailure` on every turn from the failing `git pull` call."
9
+ ]
10
+ },
4
11
  {
5
12
  "version": "0.1.0-alpha.247",
6
13
  "changes": [
@@ -37,6 +37,7 @@ exports.listEnabledBundleAgents = listEnabledBundleAgents;
37
37
  exports.listBundleSyncRows = listBundleSyncRows;
38
38
  const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
+ const child_process_1 = require("child_process");
40
41
  const identity_1 = require("../identity");
41
42
  const runtime_1 = require("../../nerves/runtime");
42
43
  function listEnabledBundleAgents(options = {}) {
@@ -85,14 +86,21 @@ function listEnabledBundleAgents(options = {}) {
85
86
  * Used by the daemon (and stopped-state status renderer) to build per-agent
86
87
  * sync rows without depending on argv-derived global identity. Bundles that
87
88
  * cannot be read are skipped silently.
89
+ *
90
+ * For rows with sync enabled, also resolves the remote URL by shelling out to
91
+ * `git remote get-url <remote>` in the bundle directory. On any error (no
92
+ * remote, not a git repo, git missing) the URL is left undefined and the
93
+ * status renderer treats the bundle as "local only".
88
94
  */
89
95
  function listBundleSyncRows(options = {}) {
90
96
  const bundlesRoot = options.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
91
97
  const readFileSync = options.readFileSync ?? fs.readFileSync;
98
+ const execFileSync = options.execFileSync ?? child_process_1.execFileSync;
92
99
  const agents = listEnabledBundleAgents(options);
93
100
  const rows = [];
94
101
  for (const agent of agents) {
95
- const configPath = path.join(bundlesRoot, `${agent}.ouro`, "agent.json");
102
+ const bundleRoot = path.join(bundlesRoot, `${agent}.ouro`);
103
+ const configPath = path.join(bundleRoot, "agent.json");
96
104
  let enabled = false;
97
105
  let remote = "origin";
98
106
  try {
@@ -109,7 +117,22 @@ function listBundleSyncRows(options = {}) {
109
117
  catch {
110
118
  // Best-effort: bundle without readable config still gets a row with defaults
111
119
  }
112
- rows.push({ agent, enabled, remote });
120
+ let remoteUrl;
121
+ if (enabled) {
122
+ try {
123
+ const out = execFileSync("git", ["remote", "get-url", remote], {
124
+ cwd: bundleRoot,
125
+ stdio: "pipe",
126
+ timeout: 5000,
127
+ }).toString().trim();
128
+ if (out.length > 0)
129
+ remoteUrl = out;
130
+ }
131
+ catch {
132
+ // No remote configured, not a git repo, or git missing — leave undefined.
133
+ }
134
+ }
135
+ rows.push(remoteUrl !== undefined ? { agent, enabled, remote, remoteUrl } : { agent, enabled, remote });
113
136
  }
114
137
  return rows;
115
138
  }
@@ -147,7 +147,10 @@ function parseStatusPayload(data) {
147
147
  const remote = stringField(row.remote);
148
148
  if (!agent || enabled === null || !remote)
149
149
  return null;
150
- return { agent, enabled, remote };
150
+ const remoteUrl = stringField(row.remoteUrl) ?? undefined;
151
+ return remoteUrl !== undefined
152
+ ? { agent, enabled, remote, remoteUrl }
153
+ : { agent, enabled, remote };
151
154
  });
152
155
  if (parsedSenses.some((row) => row === null) ||
153
156
  parsedWorkers.some((row) => row === null) ||
@@ -317,7 +320,10 @@ function formatDaemonStatusOutput(response, fallback) {
317
320
  const name = row.agent.padEnd(agentNameWidth);
318
321
  const dot = row.enabled ? green("●") : dim("○");
319
322
  const stateText = (row.enabled ? "enabled " : "disabled").padEnd(10);
320
- const detail = row.enabled ? `remote: ${row.remote}` : "";
323
+ let detail = "";
324
+ if (row.enabled) {
325
+ detail = row.remoteUrl !== undefined ? `${row.remote} → ${row.remoteUrl}` : "local only";
326
+ }
321
327
  lines.push(` ${name} ${dot} ${stateText} ${dim(detail)}`);
322
328
  }
323
329
  lines.push("");
@@ -41,6 +41,11 @@ const path = __importStar(require("path"));
41
41
  const runtime_1 = require("../nerves/runtime");
42
42
  /**
43
43
  * Pre-turn pull: sync the agent bundle from remote before assembling the start-of-turn packet.
44
+ *
45
+ * If the bundle has no git remote configured, the pull is skipped and the function
46
+ * returns ok — matching the no-remote behavior of postTurnPush. This supports the
47
+ * "local-only sync" mode where the bundle accumulates a commit log without ever
48
+ * pushing or pulling from a remote.
44
49
  */
45
50
  function preTurnPull(agentRoot, config) {
46
51
  (0, runtime_1.emitNervesEvent)({
@@ -49,6 +54,33 @@ function preTurnPull(agentRoot, config) {
49
54
  message: "pre-turn pull starting",
50
55
  meta: { agentRoot, remote: config.remote },
51
56
  });
57
+ // Check if any remote is configured. If not, skip the pull (local-only mode).
58
+ try {
59
+ const remoteOutput = (0, child_process_1.execFileSync)("git", ["remote"], {
60
+ cwd: agentRoot,
61
+ stdio: "pipe",
62
+ timeout: 5000,
63
+ }).toString().trim();
64
+ if (remoteOutput.length === 0) {
65
+ (0, runtime_1.emitNervesEvent)({
66
+ component: "heart",
67
+ event: "heart.sync_pull_end",
68
+ message: "pre-turn pull skipped: no remote configured",
69
+ meta: { agentRoot },
70
+ });
71
+ return { ok: true };
72
+ }
73
+ }
74
+ catch (err) {
75
+ const error = err instanceof Error ? err.message : String(err);
76
+ (0, runtime_1.emitNervesEvent)({
77
+ component: "heart",
78
+ event: "heart.sync_pull_error",
79
+ message: "pre-turn pull failed: git remote check failed",
80
+ meta: { agentRoot, error },
81
+ });
82
+ return { ok: false, error };
83
+ }
52
84
  try {
53
85
  (0, child_process_1.execFileSync)("git", ["pull", config.remote], {
54
86
  cwd: agentRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.247",
3
+ "version": "0.1.0-alpha.248",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",