fix(opencode): support opencode 2.x only - session_v2, debug paths, session delete, --standalone (Issue #60)
Measured on opencode 2.0.32 (macOS):
- the TUI rejects --agent ("Unrecognized flag"), so create and resume could
not start opencode at all; the default agent is build. MAM now spawns
`opencode --auto --standalone` (resume adds --session <id>): the server
runs as the TUI's child and ends with it, and the per-user background
service is neither used nor started;
- sessions live in session_v2 (a fresh 2.x database has no `session` table;
a migrated one keeps the 1.x tables but no longer writes them). discover,
verify_artifact, reconcile drift C and status read session_v2, and
discover / drift C skip child (subagent) sessions;
- `db path` is gone (it prints the help and exits 0): the db comes from
the `db` line of `opencode debug paths`, else the default path;
- `opencode session delete` removes a session with its child sessions from
the 2.x tables (and leaves the 1.x ones): purge runs it with --standalone
for a session in session_v2, still deletes the 1.x message/part/session
rows, and residual also reports a session_v2 row left by a failed delete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
74333f87d0
commit
a311c23303
6 files changed
+92
-111
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
import os, sys, sqlite3, shutil
|
import os, sys, sqlite3, shutil, subprocess
|
||||||
from typing import Optional, Any, List
|
from typing import Optional, Any, List
|
||||||
from lib_py.agents.base import BaseAgentAdapter, DiscoveryContext, scan_names, db_rows_naming
|
from lib_py.agents.base import BaseAgentAdapter, DiscoveryContext, scan_names, db_rows_naming
|
||||||
from lib_py.verify_session import workspace_key
|
from lib_py.verify_session import workspace_key
|
||||||
@@ -59,56 +59,46 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
|||||||
# blanks after the ┃) or the `Build auto · <model>` status line.
|
# blanks after the ┃) or the `Build auto · <model>` status line.
|
||||||
return r'^\s{20,}\S|^\s*(Build|Plan)\b.*·'
|
return r'^\s{20,}\S|^\s*(Build|Plan)\b.*·'
|
||||||
|
|
||||||
def _resolve_db(self, ctx: DiscoveryContext) -> Optional[str]:
|
def _bin(self, ctx: DiscoveryContext) -> Optional[str]:
|
||||||
# 1. Try opencode CLI "opencode db path"
|
|
||||||
try:
|
|
||||||
import subprocess
|
|
||||||
bin_path = shutil.which("opencode")
|
bin_path = shutil.which("opencode")
|
||||||
if not bin_path:
|
if bin_path:
|
||||||
|
return bin_path
|
||||||
for candidate_bin in [
|
for candidate_bin in [
|
||||||
f"{ctx.home_dir}/.opencode/bin/opencode",
|
f"{ctx.home_dir}/.opencode/bin/opencode",
|
||||||
os.path.expanduser("~/.opencode/bin/opencode"),
|
os.path.expanduser("~/.opencode/bin/opencode"),
|
||||||
]:
|
]:
|
||||||
if os.path.exists(candidate_bin):
|
if os.path.exists(candidate_bin):
|
||||||
bin_path = candidate_bin
|
return candidate_bin
|
||||||
break
|
return None
|
||||||
if bin_path:
|
|
||||||
|
def _run(self, ctx: DiscoveryContext, args: list, timeout: int):
|
||||||
|
"""Run the opencode CLI against ctx's home (its data dir follows HOME and
|
||||||
|
XDG_DATA_HOME); None when there is no binary."""
|
||||||
|
bin_path = self._bin(ctx)
|
||||||
|
if not bin_path:
|
||||||
|
return None
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
if ctx.home_dir:
|
if ctx.home_dir:
|
||||||
env["HOME"] = ctx.home_dir
|
env["HOME"] = ctx.home_dir
|
||||||
env["HOME_DIR"] = ctx.home_dir
|
env["HOME_DIR"] = ctx.home_dir
|
||||||
env["XDG_DATA_HOME"] = os.path.join(ctx.home_dir, ".local/share")
|
env["XDG_DATA_HOME"] = os.path.join(ctx.home_dir, ".local/share")
|
||||||
cwd = ctx.workspace or ctx.cwd or os.getcwd()
|
cwd = ctx.workspace or ctx.cwd or os.getcwd()
|
||||||
res = subprocess.run(
|
return subprocess.run([bin_path] + args, capture_output=True, text=True, timeout=timeout,
|
||||||
[bin_path, "db", "path"],
|
env=env, cwd=cwd if os.path.exists(cwd) else None)
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
def _resolve_db(self, ctx: DiscoveryContext) -> Optional[str]:
|
||||||
timeout=2,
|
# opencode 2.x prints its paths with `debug paths` (the 1.x `db path`
|
||||||
env=env,
|
# is gone: it prints the help and exits 0). Fallback: the default.
|
||||||
cwd=cwd if os.path.exists(cwd) else None
|
try:
|
||||||
)
|
res = self._run(ctx, ["debug", "paths"], timeout=5)
|
||||||
if res.returncode == 0:
|
if res is not None and res.returncode == 0:
|
||||||
out = res.stdout.strip()
|
for line in res.stdout.splitlines():
|
||||||
if out and os.path.exists(out):
|
parts = line.split(None, 1)
|
||||||
return out
|
if len(parts) == 2 and parts[0] == "db":
|
||||||
|
return parts[1].strip()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
return f"{ctx.home_dir}/.local/share/opencode/opencode.db"
|
||||||
# 2. Filesystem fallbacks
|
|
||||||
base_dir = f"{ctx.home_dir}/.local/share/opencode"
|
|
||||||
candidates = [
|
|
||||||
f"{base_dir}/opencode.db",
|
|
||||||
f"{base_dir}/storage.db",
|
|
||||||
]
|
|
||||||
for cand in candidates:
|
|
||||||
if os.path.exists(cand):
|
|
||||||
return cand
|
|
||||||
if os.path.isdir(f"{base_dir}/project"):
|
|
||||||
for root, _, files in os.walk(f"{base_dir}/project"):
|
|
||||||
for f in files:
|
|
||||||
if f.endswith(".db"):
|
|
||||||
return os.path.join(root, f)
|
|
||||||
return candidates[0]
|
|
||||||
|
|
||||||
def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
|
def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
|
||||||
db = self._resolve_db(ctx)
|
db = self._resolve_db(ctx)
|
||||||
@@ -119,44 +109,18 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
|||||||
if not db or not os.path.exists(db):
|
if not db or not os.path.exists(db):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
|
# opencode 2.x keeps sessions in session_v2 (a 1.x `session` table
|
||||||
|
# survives a migration but is no longer written).
|
||||||
conn = sqlite3.connect(db)
|
conn = sqlite3.connect(db)
|
||||||
cursor = conn.cursor()
|
r = conn.execute("SELECT directory, time_created FROM session_v2 WHERE id=?", (uuid,)).fetchone()
|
||||||
cursor.execute("PRAGMA table_info(session)")
|
|
||||||
cols = [col[1] for col in cursor.fetchall()]
|
|
||||||
if not cols:
|
|
||||||
conn.close()
|
|
||||||
return False
|
|
||||||
|
|
||||||
cwd_col = "directory" if "directory" in cols else ("cwd" if "cwd" in cols else None)
|
|
||||||
time_col = "time_created" if "time_created" in cols else ("created_at" if "created_at" in cols else ("started_at" if "started_at" in cols else None))
|
|
||||||
|
|
||||||
query_cols = []
|
|
||||||
if cwd_col:
|
|
||||||
query_cols.append(cwd_col)
|
|
||||||
if time_col:
|
|
||||||
query_cols.append(time_col)
|
|
||||||
query = "SELECT " + (", ".join(query_cols) if query_cols else "id") + " FROM session WHERE id=?"
|
|
||||||
r = cursor.execute(query, (uuid,)).fetchone()
|
|
||||||
conn.close()
|
conn.close()
|
||||||
if not r:
|
if not r:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
found_cwd = None
|
found_cwd, started_at = r
|
||||||
started_at = None
|
|
||||||
idx = 0
|
|
||||||
if cwd_col:
|
|
||||||
found_cwd = r[idx]
|
|
||||||
idx += 1
|
|
||||||
if time_col:
|
|
||||||
started_at = r[idx]
|
|
||||||
idx += 1
|
|
||||||
|
|
||||||
if ctx.epoch and started_at is not None:
|
if ctx.epoch and started_at is not None:
|
||||||
try:
|
try:
|
||||||
val = float(started_at)
|
if float(started_at) / 1000.0 < float(ctx.epoch):
|
||||||
if time_col == "time_created" or val > 1e11:
|
|
||||||
val = val / 1000.0
|
|
||||||
if val < float(ctx.epoch):
|
|
||||||
return False
|
return False
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
@@ -169,7 +133,23 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
|||||||
def purge_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
|
def purge_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
|
||||||
purged = []
|
purged = []
|
||||||
db = self._resolve_db(ctx)
|
db = self._resolve_db(ctx)
|
||||||
|
if db and os.path.exists(db) and self._has_session(db, uuid):
|
||||||
|
# opencode deletes a 2.x session with its child sessions and every
|
||||||
|
# row it keeps for them; --standalone so no background service is
|
||||||
|
# started for it.
|
||||||
|
try:
|
||||||
|
res = self._run(ctx, ["session", "delete", "--standalone", "--", uuid], timeout=60)
|
||||||
|
if res is None:
|
||||||
|
sys.stderr.write(f"WARN: purge opencode: no opencode binary to delete session {uuid}\n")
|
||||||
|
elif res.returncode == 0:
|
||||||
|
purged.append(f"opencode session (with its child sessions): {uuid}")
|
||||||
|
else:
|
||||||
|
sys.stderr.write(f"WARN: purge opencode: session delete {uuid} exited {res.returncode}: "
|
||||||
|
f"{(res.stderr or res.stdout).strip()}\n")
|
||||||
|
except Exception as e:
|
||||||
|
sys.stderr.write(f"WARN: purge opencode: session delete {uuid} failed: {e}\n")
|
||||||
if db and os.path.exists(db):
|
if db and os.path.exists(db):
|
||||||
|
# Rows a 1.x opencode left in the tables a migration keeps.
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(db)
|
conn = sqlite3.connect(db)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@@ -189,25 +169,39 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
|||||||
conn.execute("DELETE FROM sessions WHERE id=?", (uuid,))
|
conn.execute("DELETE FROM sessions WHERE id=?", (uuid,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
if tables & {"message", "messages", "part", "parts", "session", "sessions"}:
|
||||||
purged.append(f"sqlite rows for session: {uuid}")
|
purged.append(f"sqlite rows for session: {uuid}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write(f"WARN: purge opencode db records failed: {e}\n")
|
sys.stderr.write(f"WARN: purge opencode db records failed: {e}\n")
|
||||||
return purged
|
return purged
|
||||||
|
|
||||||
|
def _has_session(self, db: str, uuid: str) -> bool:
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect(db)
|
||||||
|
try:
|
||||||
|
return conn.execute("SELECT 1 FROM session_v2 WHERE id=?", (uuid,)).fetchone() is not None
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
def residual_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
|
def residual_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
|
||||||
# Issue #31: the purge leaves event-sourced rows (event, todo, ...);
|
# Issue #31: whatever still names the session (event-sourced rows a
|
||||||
# deleting those is not known to be safe, so they are reported.
|
# 1.x opencode left, a failed `session delete`) is reported.
|
||||||
found = scan_names(f"{ctx.home_dir}/.local/share/opencode", uuid)
|
found = scan_names(f"{ctx.home_dir}/.local/share/opencode", uuid)
|
||||||
return found + db_rows_naming(self._resolve_db(ctx), uuid, ("session_id", "aggregate_id"),
|
return found + db_rows_naming(self._resolve_db(ctx), uuid, ("session_id", "aggregate_id"),
|
||||||
id_tables=(("session", "id"),))
|
id_tables=(("session", "id"), ("session_v2", "id")))
|
||||||
|
|
||||||
|
# opencode 2.x: the default agent is build (`--agent` is gone from the
|
||||||
|
# TUI), and --standalone keeps the server a child of the pane's TUI
|
||||||
|
# instead of the per-user background service.
|
||||||
def spawn_spec(self, binary: str, session_uuid: str = "", use_wrapper: bool = False) -> str:
|
def spawn_spec(self, binary: str, session_uuid: str = "", use_wrapper: bool = False) -> str:
|
||||||
return f"{binary} --auto --agent build"
|
return f"{binary} --auto --standalone"
|
||||||
|
|
||||||
def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
|
def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
|
||||||
if materialized and session_uuid:
|
if materialized and session_uuid:
|
||||||
return f"{binary} --session {session_uuid} --auto --agent build"
|
return f"{binary} --session {session_uuid} --auto --standalone"
|
||||||
return f"{binary} --auto --agent build"
|
return f"{binary} --auto --standalone"
|
||||||
|
|
||||||
def auth_ok(self, run_cmd: Optional[Any] = None) -> bool:
|
def auth_ok(self, run_cmd: Optional[Any] = None) -> bool:
|
||||||
if any(os.environ.get(v) for v in _PROVIDER_ENV_VARS):
|
if any(os.environ.get(v) for v in _PROVIDER_ENV_VARS):
|
||||||
@@ -221,38 +215,20 @@ class OpenCodeAgentAdapter(BaseAgentAdapter):
|
|||||||
if not db or not os.path.exists(db):
|
if not db or not os.path.exists(db):
|
||||||
return []
|
return []
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(db)
|
# Top-level sessions only: a subagent's session (parent_id set)
|
||||||
cursor = conn.cursor()
|
# shares the directory and is newer than the one the TUI shows.
|
||||||
cursor.execute("PRAGMA table_info(session)")
|
query = "SELECT id FROM session_v2 WHERE parent_id IS NULL"
|
||||||
cols = [col[1] for col in cursor.fetchall()]
|
|
||||||
if not cols:
|
|
||||||
conn.close()
|
|
||||||
return []
|
|
||||||
|
|
||||||
cwd_col = "directory" if "directory" in cols else ("cwd" if "cwd" in cols else None)
|
|
||||||
time_col = "time_created" if "time_created" in cols else ("created_at" if "created_at" in cols else ("started_at" if "started_at" in cols else None))
|
|
||||||
|
|
||||||
query = "SELECT id FROM session"
|
|
||||||
params = []
|
params = []
|
||||||
where_clauses = []
|
if ctx.workspace:
|
||||||
if cwd_col and ctx.workspace:
|
query += " AND directory = ?"
|
||||||
where_clauses.append(f"{cwd_col} = ?")
|
|
||||||
params.append(ctx.workspace)
|
params.append(ctx.workspace)
|
||||||
if time_col and ctx.epoch:
|
if ctx.epoch:
|
||||||
if time_col == "time_created":
|
query += " AND time_created >= ?"
|
||||||
where_clauses.append(f"{time_col} >= ?")
|
|
||||||
params.append(int(float(ctx.epoch) * 1000))
|
params.append(int(float(ctx.epoch) * 1000))
|
||||||
else:
|
query += " ORDER BY time_created DESC LIMIT 20"
|
||||||
where_clauses.append(f"{time_col} >= ?")
|
|
||||||
params.append(ctx.epoch)
|
|
||||||
|
|
||||||
if where_clauses:
|
conn = sqlite3.connect(db)
|
||||||
query += " WHERE " + " AND ".join(where_clauses)
|
rows = conn.execute(query, params).fetchall()
|
||||||
if time_col:
|
|
||||||
query += f" ORDER BY {time_col} DESC"
|
|
||||||
query += " LIMIT 20"
|
|
||||||
|
|
||||||
rows = cursor.execute(query, params).fetchall()
|
|
||||||
conn.close()
|
conn.close()
|
||||||
candidates = []
|
candidates = []
|
||||||
for (cand,) in rows:
|
for (cand,) in rows:
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ if [ -z "$CMD_FULL" ]; then
|
|||||||
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
||||||
hermes) CMD_FULL="${RESOLVED_BIN} --yolo --accept-hooks" ;;
|
hermes) CMD_FULL="${RESOLVED_BIN} --yolo --accept-hooks" ;;
|
||||||
grok) CMD_FULL="${RESOLVED_BIN} --permission-mode bypassPermissions" ;;
|
grok) CMD_FULL="${RESOLVED_BIN} --permission-mode bypassPermissions" ;;
|
||||||
opencode) CMD_FULL="${RESOLVED_BIN} --auto --agent build" ;;
|
opencode) CMD_FULL="${RESOLVED_BIN} --auto --standalone" ;;
|
||||||
codex) CMD_FULL="${RESOLVED_BIN} --dangerously-bypass-approvals-and-sandbox" ;;
|
codex) CMD_FULL="${RESOLVED_BIN} --dangerously-bypass-approvals-and-sandbox" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -952,15 +952,20 @@ for s in d.get('herdr_sessions', []):
|
|||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(odb)
|
conn = sqlite3.connect(odb)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute("PRAGMA table_info(session)")
|
# opencode 2.x keeps sessions in session_v2 (a migrated 1.x `session`
|
||||||
|
# table is no longer written).
|
||||||
|
cursor.execute("PRAGMA table_info(session_v2)")
|
||||||
cols = [col[1] for col in cursor.fetchall()]
|
cols = [col[1] for col in cursor.fetchall()]
|
||||||
if cols:
|
if cols:
|
||||||
cwd_col = "directory" if "directory" in cols else ("cwd" if "cwd" in cols else None)
|
cwd_col = "directory" if "directory" in cols else ("cwd" if "cwd" in cols else None)
|
||||||
time_col = "time_created" if "time_created" in cols else ("created_at" if "created_at" in cols else ("started_at" if "started_at" in cols else None))
|
time_col = "time_created" if "time_created" in cols else ("created_at" if "created_at" in cols else ("started_at" if "started_at" in cols else None))
|
||||||
|
|
||||||
query = "SELECT id FROM session"
|
query = "SELECT id FROM session_v2"
|
||||||
params = []
|
params = []
|
||||||
where_clauses = []
|
where_clauses = []
|
||||||
|
if "parent_id" in cols:
|
||||||
|
# a subagent's session shares the directory and is newer
|
||||||
|
where_clauses.append("parent_id IS NULL")
|
||||||
if cwd_col and cwd:
|
if cwd_col and cwd:
|
||||||
where_clauses.append(f"{cwd_col} = ?")
|
where_clauses.append(f"{cwd_col} = ?")
|
||||||
params.append(cwd)
|
params.append(cwd)
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ if [ "$FRESH_SPAWN" = "1" ]; then
|
|||||||
case "$AGENT" in
|
case "$AGENT" in
|
||||||
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions" ;;
|
||||||
hermes) CMD_FULL="${RESOLVED_BIN} --yolo --accept-hooks" ;;
|
hermes) CMD_FULL="${RESOLVED_BIN} --yolo --accept-hooks" ;;
|
||||||
opencode) CMD_FULL="${RESOLVED_BIN} --auto --agent build" ;;
|
opencode) CMD_FULL="${RESOLVED_BIN} --auto --standalone" ;;
|
||||||
codex) CMD_FULL="${RESOLVED_BIN} --dangerously-bypass-approvals-and-sandbox" ;;
|
codex) CMD_FULL="${RESOLVED_BIN} --dangerously-bypass-approvals-and-sandbox" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
@@ -190,7 +190,7 @@ else
|
|||||||
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions --conversation $UUID" ;;
|
agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions --conversation $UUID" ;;
|
||||||
hermes) CMD_FULL="${RESOLVED_BIN} --resume $UUID --no-restore-cwd --yolo --accept-hooks" ;;
|
hermes) CMD_FULL="${RESOLVED_BIN} --resume $UUID --no-restore-cwd --yolo --accept-hooks" ;;
|
||||||
grok) CMD_FULL="${RESOLVED_BIN} --resume $UUID --permission-mode bypassPermissions" ;;
|
grok) CMD_FULL="${RESOLVED_BIN} --resume $UUID --permission-mode bypassPermissions" ;;
|
||||||
opencode) CMD_FULL="${RESOLVED_BIN} --session $UUID --auto --agent build" ;;
|
opencode) CMD_FULL="${RESOLVED_BIN} --session $UUID --auto --standalone" ;;
|
||||||
codex) CMD_FULL="${RESOLVED_BIN} resume --dangerously-bypass-approvals-and-sandbox $UUID" ;;
|
codex) CMD_FULL="${RESOLVED_BIN} resume --dangerously-bypass-approvals-and-sandbox $UUID" ;;
|
||||||
*) echo "ERROR: unsupported agent: $AGENT" >&2; exit 2 ;;
|
*) echo "ERROR: unsupported agent: $AGENT" >&2; exit 2 ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -238,10 +238,10 @@ elif agent == 'grok':
|
|||||||
elif agent == 'opencode':
|
elif agent == 'opencode':
|
||||||
target['pane']['cmd'] = 'opencode'
|
target['pane']['cmd'] = 'opencode'
|
||||||
if uuid:
|
if uuid:
|
||||||
target['pane']['cmd_full'] = f'opencode --session {uuid} --auto --agent build'
|
target['pane']['cmd_full'] = f'opencode --session {uuid} --auto --standalone'
|
||||||
target['opencode_session_id_own'] = uuid
|
target['opencode_session_id_own'] = uuid
|
||||||
else:
|
else:
|
||||||
target['pane']['cmd_full'] = os.environ.get('CMD_FULL_OPT', '') or 'opencode --auto --agent build'
|
target['pane']['cmd_full'] = os.environ.get('CMD_FULL_OPT', '') or 'opencode --auto --standalone'
|
||||||
cp = os.environ.get('CHILD_PID', '0')
|
cp = os.environ.get('CHILD_PID', '0')
|
||||||
if cp.isdigit() and int(cp) > 0:
|
if cp.isdigit() and int(cp) > 0:
|
||||||
target['child_pid'] = int(cp)
|
target['child_pid'] = int(cp)
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ def resume_on_disk(s):
|
|||||||
try:
|
try:
|
||||||
import sqlite3
|
import sqlite3
|
||||||
conn = sqlite3.connect(odb)
|
conn = sqlite3.connect(odb)
|
||||||
r = conn.execute("SELECT 1 FROM session WHERE id=?", (u,)).fetchone()
|
r = conn.execute("SELECT 1 FROM session_v2 WHERE id=?", (u,)).fetchone() # opencode 2.x
|
||||||
conn.close()
|
conn.close()
|
||||||
return 'yes' if r else 'MISSING'
|
return 'yes' if r else 'MISSING'
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -334,7 +334,7 @@ def resume_on_disk(s):
|
|||||||
try:
|
try:
|
||||||
import sqlite3
|
import sqlite3
|
||||||
conn = sqlite3.connect(odb)
|
conn = sqlite3.connect(odb)
|
||||||
r = conn.execute("SELECT 1 FROM session WHERE id=?", (u,)).fetchone()
|
r = conn.execute("SELECT 1 FROM session_v2 WHERE id=?", (u,)).fetchone() # opencode 2.x
|
||||||
conn.close()
|
conn.close()
|
||||||
return 'yes' if r else 'MISSING'
|
return 'yes' if r else 'MISSING'
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
Reference in new issue
Block a user