arctx-cli 0.3.0b1__tar.gz → 0.3.1b2__tar.gz
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.
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/.gitignore +3 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/PKG-INFO +2 -2
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/pyproject.toml +2 -2
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/append_batch.py +7 -7
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/__init__.py +42 -3
- arctx_cli-0.3.1b2/src/arctx_cli/commands/add.py +113 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/asset.py +138 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/attach.py +38 -14
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/cut.py +6 -6
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/export.py +2 -2
- arctx_cli-0.3.1b2/src/arctx_cli/commands/guide.py +135 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/lane.py +630 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/log.py +10 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/payload.py +7 -7
- arctx_cli-0.3.1b2/src/arctx_cli/commands/pr.py +272 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/reparent.py +128 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/serve.py +53 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/step.py +9 -9
- arctx_cli-0.3.1b2/src/arctx_cli/commands/sync_cmd.py +179 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/trace.py +2 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/uncut.py +99 -0
- arctx_cli-0.3.1b2/src/arctx_cli/commands/web.py +68 -0
- arctx_cli-0.3.1b2/src/arctx_cli/context.py +75 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/command/__init__.py +6 -6
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/__init__.py +5 -5
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/cherry_pick.py +9 -9
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/commit.py +10 -24
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/hook.py +17 -17
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/merge.py +14 -32
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/repo.py +7 -7
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/reset.py +10 -10
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/revert.py +9 -9
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/worktree.py +5 -5
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext_registry.py +8 -2
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/main.py +45 -3
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/paths.py +8 -0
- arctx_cli-0.3.1b2/tests/cli/test_asset_extension_cli.py +98 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_basic.py +61 -26
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_branch.py +5 -5
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_cherry_pick.py +4 -4
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_commit.py +8 -8
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_commit_guard.py +11 -11
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_dag_core_cli.py +146 -25
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_git_repo.py +4 -4
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_hook_post_merge.py +10 -10
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_hook_post_rewrite.py +11 -11
- arctx_cli-0.3.1b2/tests/cli/test_lane.py +303 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_merge.py +17 -61
- arctx_cli-0.3.1b2/tests/cli/test_pr.py +97 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_reset.py +10 -10
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_revert.py +6 -6
- arctx_cli-0.3.1b2/tests/cli/test_serve_api.py +794 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_show_history.py +2 -2
- arctx_cli-0.3.1b2/tests/cli/test_sync.py +53 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_verify.py +14 -14
- arctx_cli-0.3.0b1/src/arctx_cli/commands/add.py +0 -203
- arctx_cli-0.3.0b1/src/arctx_cli/commands/work_session.py +0 -330
- arctx_cli-0.3.0b1/src/arctx_cli/context.py +0 -38
- arctx_cli-0.3.0b1/src/arctx_cli/ext/claude_code/__init__.py +0 -320
- arctx_cli-0.3.0b1/src/arctx_cli/ext/codex/__init__.py +0 -302
- arctx_cli-0.3.0b1/tests/cli/test_claude_code_cmd.py +0 -267
- arctx_cli-0.3.0b1/tests/cli/test_codex_cmd.py +0 -220
- arctx_cli-0.3.0b1/tests/cli/test_git_worktree.py +0 -190
- arctx_cli-0.3.0b1/tests/cli/test_work_session.py +0 -115
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/README.md +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/__init__.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/alias.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/_targets.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/alias_cmd.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/current.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/dump.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/ext.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/graph.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/init.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/list.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/migrate.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/node.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/outcomes.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/reachable.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/show.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/commands/use.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/__init__.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/branch.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/ext/git/verify.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/payload_builder.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/src/arctx_cli/workspace.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/__init__.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/__init__.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_alias_cli.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_alias_resolve.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_command_extension.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_ext_cli.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_git_namespace_cli.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_hook_install.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_init_extension.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_init_hooks.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_init_stag_id.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_migrate.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/cli/test_paths.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/fixtures/__init__.py +0 -0
- {arctx_cli-0.3.0b1 → arctx_cli-0.3.1b2}/tests/fixtures/dummy_ext.py +0 -0
|
@@ -6,6 +6,7 @@ __pycache__/
|
|
|
6
6
|
.mypy_cache/
|
|
7
7
|
.ruff_cache/
|
|
8
8
|
.uv-cache/
|
|
9
|
+
.uv-tools/
|
|
9
10
|
.venv/
|
|
10
11
|
.coverage
|
|
11
12
|
htmlcov/
|
|
@@ -25,7 +26,9 @@ run.json
|
|
|
25
26
|
# Package build artifacts
|
|
26
27
|
dist/
|
|
27
28
|
*.egg-info/
|
|
29
|
+
packages/arctx/src/arctx/web/static/
|
|
28
30
|
|
|
29
31
|
# IDE / Agent state directories
|
|
30
32
|
.claude/
|
|
31
33
|
.antigravitycli/
|
|
34
|
+
.codex/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arctx-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1b2
|
|
4
4
|
Summary: CLI for ARCTX — append-only DAG editing and refactoring
|
|
5
5
|
Project-URL: Homepage, https://github.com/takumiecd/arctx
|
|
6
6
|
Project-URL: Repository, https://github.com/takumiecd/arctx
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
18
|
Classifier: Topic :: Utilities
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: arctx>=0.3.
|
|
20
|
+
Requires-Dist: arctx>=0.3.1b2
|
|
21
21
|
Provides-Extra: dev
|
|
22
22
|
Requires-Dist: black>=23.0; extra == 'dev'
|
|
23
23
|
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "arctx-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1b2"
|
|
8
8
|
description = "CLI for ARCTX — append-only DAG editing and refactoring"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -25,7 +25,7 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Utilities",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"arctx>=0.3.
|
|
28
|
+
"arctx>=0.3.1b2",
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
[project.optional-dependencies]
|
|
@@ -20,18 +20,18 @@ def maybe_append_or_save(
|
|
|
20
20
|
store,
|
|
21
21
|
handle,
|
|
22
22
|
user_id: str | None,
|
|
23
|
-
|
|
23
|
+
lane_id: str | None,
|
|
24
24
|
before: dict[str, set[str]],
|
|
25
25
|
) -> None:
|
|
26
26
|
"""Use append_batch for capable stores, otherwise fall back to save_run."""
|
|
27
|
-
if user_id is None or
|
|
27
|
+
if user_id is None or lane_id is None or not hasattr(store, "append_batch"):
|
|
28
28
|
store.save_run(handle)
|
|
29
29
|
return
|
|
30
30
|
store.append_batch(
|
|
31
31
|
build_append_batch(
|
|
32
32
|
handle,
|
|
33
33
|
user_id=user_id,
|
|
34
|
-
|
|
34
|
+
lane_id=lane_id,
|
|
35
35
|
before=before,
|
|
36
36
|
)
|
|
37
37
|
)
|
|
@@ -41,7 +41,7 @@ def build_append_batch(
|
|
|
41
41
|
handle,
|
|
42
42
|
*,
|
|
43
43
|
user_id: str,
|
|
44
|
-
|
|
44
|
+
lane_id: str,
|
|
45
45
|
before: dict[str, set[str]],
|
|
46
46
|
) -> AppendBatch:
|
|
47
47
|
"""Build an append batch from records added since *before*."""
|
|
@@ -67,12 +67,12 @@ def build_append_batch(
|
|
|
67
67
|
if not new_events:
|
|
68
68
|
raise RuntimeError("append batch requires at least one work event")
|
|
69
69
|
|
|
70
|
-
session = handle.run_graph.
|
|
70
|
+
session = handle.run_graph.lanes[lane_id]
|
|
71
71
|
return AppendBatch(
|
|
72
72
|
run_id=handle.run_id,
|
|
73
73
|
user_id=user_id,
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
lane_id=lane_id,
|
|
75
|
+
lane=session,
|
|
76
76
|
events=tuple(new_events),
|
|
77
77
|
records=tuple(records),
|
|
78
78
|
)
|
|
@@ -11,6 +11,8 @@ def core_cli_commands() -> list[CliCommand]:
|
|
|
11
11
|
from arctx_cli.commands.add import cli_add
|
|
12
12
|
from arctx_cli.commands.alias_cmd import add_parser as add_alias_parser
|
|
13
13
|
from arctx_cli.commands.alias_cmd import cli_alias
|
|
14
|
+
from arctx_cli.commands.asset import add_parser as add_asset_parser
|
|
15
|
+
from arctx_cli.commands.asset import cli_asset
|
|
14
16
|
from arctx_cli.commands.attach import add_parser as add_attach_parser
|
|
15
17
|
from arctx_cli.commands.attach import cli_attach
|
|
16
18
|
from arctx_cli.commands.current import add_parser as add_current_parser
|
|
@@ -25,38 +27,75 @@ def core_cli_commands() -> list[CliCommand]:
|
|
|
25
27
|
from arctx_cli.commands.ext import cli_ext
|
|
26
28
|
from arctx_cli.commands.graph import add_parser as add_graph_parser
|
|
27
29
|
from arctx_cli.commands.graph import cli_graph
|
|
30
|
+
from arctx_cli.commands.guide import add_parser as add_guide_parser
|
|
31
|
+
from arctx_cli.commands.guide import cli_guide
|
|
28
32
|
from arctx_cli.commands.init import add_parser as add_init_parser
|
|
29
33
|
from arctx_cli.commands.init import cli_init
|
|
34
|
+
from arctx_cli.commands.lane import add_parser as add_lane_parser
|
|
35
|
+
from arctx_cli.commands.lane import cli_lane
|
|
30
36
|
from arctx_cli.commands.list import add_parser as add_list_parser
|
|
31
37
|
from arctx_cli.commands.list import cli_list
|
|
32
38
|
from arctx_cli.commands.log import add_parser as add_log_parser
|
|
33
39
|
from arctx_cli.commands.log import cli_log
|
|
34
40
|
from arctx_cli.commands.migrate import add_parser as add_migrate_parser
|
|
35
41
|
from arctx_cli.commands.migrate import cli_migrate
|
|
42
|
+
from arctx_cli.commands.reparent import add_parser as add_reparent_parser
|
|
43
|
+
from arctx_cli.commands.reparent import cli_reparent
|
|
44
|
+
from arctx_cli.commands.uncut import add_parser as add_uncut_parser
|
|
45
|
+
from arctx_cli.commands.uncut import cli_uncut
|
|
46
|
+
from arctx_cli.commands.pr import (
|
|
47
|
+
add_accept_parser,
|
|
48
|
+
add_propose_parser,
|
|
49
|
+
add_reject_parser,
|
|
50
|
+
cli_accept,
|
|
51
|
+
cli_propose,
|
|
52
|
+
cli_reject,
|
|
53
|
+
)
|
|
54
|
+
from arctx_cli.commands.serve import add_parser as add_serve_parser
|
|
55
|
+
from arctx_cli.commands.serve import cli_serve
|
|
56
|
+
from arctx_cli.commands.sync_cmd import (
|
|
57
|
+
add_pull_parser,
|
|
58
|
+
add_push_parser,
|
|
59
|
+
add_remote_parser,
|
|
60
|
+
cli_pull,
|
|
61
|
+
cli_push,
|
|
62
|
+
cli_remote,
|
|
63
|
+
)
|
|
36
64
|
from arctx_cli.commands.show import add_parser as add_show_parser
|
|
37
65
|
from arctx_cli.commands.show import cli_show
|
|
38
66
|
from arctx_cli.commands.use import add_parser as add_use_parser
|
|
39
67
|
from arctx_cli.commands.use import cli_use
|
|
40
|
-
from arctx_cli.commands.
|
|
41
|
-
from arctx_cli.commands.
|
|
68
|
+
from arctx_cli.commands.web import add_parser as add_web_parser
|
|
69
|
+
from arctx_cli.commands.web import cli_web
|
|
42
70
|
|
|
43
71
|
return [
|
|
44
72
|
CliCommand("add", add_add_parser, cli_add),
|
|
45
73
|
CliCommand("alias", add_alias_parser, cli_alias),
|
|
74
|
+
CliCommand("asset", add_asset_parser, cli_asset),
|
|
46
75
|
CliCommand("attach", add_attach_parser, cli_attach),
|
|
47
76
|
CliCommand("current", add_current_parser, cli_current),
|
|
48
77
|
CliCommand("ext", add_ext_parser, cli_ext),
|
|
49
78
|
CliCommand("dump", add_dump_parser, cli_dump),
|
|
50
79
|
CliCommand("export", add_export_parser, cli_export),
|
|
51
80
|
CliCommand("graph", add_graph_parser, cli_graph),
|
|
81
|
+
CliCommand("guide", add_guide_parser, cli_guide),
|
|
52
82
|
CliCommand("init", add_init_parser, cli_init),
|
|
83
|
+
CliCommand("lane", add_lane_parser, cli_lane),
|
|
53
84
|
CliCommand("list", add_list_parser, cli_list),
|
|
54
85
|
CliCommand("log", add_log_parser, cli_log),
|
|
55
86
|
CliCommand("migrate", add_migrate_parser, cli_migrate),
|
|
56
87
|
CliCommand("cut", add_cut_parser, cli_cut),
|
|
88
|
+
CliCommand("uncut", add_uncut_parser, cli_uncut),
|
|
89
|
+
CliCommand("reparent", add_reparent_parser, cli_reparent),
|
|
90
|
+
CliCommand("propose", add_propose_parser, cli_propose),
|
|
91
|
+
CliCommand("accept", add_accept_parser, cli_accept),
|
|
92
|
+
CliCommand("reject", add_reject_parser, cli_reject),
|
|
93
|
+
CliCommand("remote", add_remote_parser, cli_remote),
|
|
94
|
+
CliCommand("push", add_push_parser, cli_push),
|
|
95
|
+
CliCommand("serve", add_serve_parser, cli_serve),
|
|
57
96
|
CliCommand("show", add_show_parser, cli_show),
|
|
58
97
|
CliCommand("use", add_use_parser, cli_use),
|
|
59
|
-
CliCommand("
|
|
98
|
+
CliCommand("web", add_web_parser, cli_web),
|
|
60
99
|
]
|
|
61
100
|
|
|
62
101
|
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""User-facing arctx add commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from arctx_cli.append_batch import graph_counts, maybe_append_or_save
|
|
10
|
+
from arctx_cli.commands._targets import step_view
|
|
11
|
+
from arctx_cli.context import (
|
|
12
|
+
resolve_run_id_from_args,
|
|
13
|
+
resolve_store,
|
|
14
|
+
resolve_user_id_from_args,
|
|
15
|
+
resolve_lane_id_from_args,
|
|
16
|
+
)
|
|
17
|
+
from arctx_cli.payload_builder import build_payload, parse_field_args, parse_json_object
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
21
|
+
parser = subparsers.add_parser("add", help="Add a Step from input Nodes")
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--from",
|
|
24
|
+
action="append",
|
|
25
|
+
required=True,
|
|
26
|
+
dest="input_nodes",
|
|
27
|
+
metavar="NODE_ID",
|
|
28
|
+
help="Input node (repeatable for multi-input steps)",
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument("--title", default=None)
|
|
31
|
+
parser.add_argument("--type", dest="payload_kind", default=None)
|
|
32
|
+
parser.add_argument("--payload-type", default="step_payload")
|
|
33
|
+
parser.add_argument("--field", action="append", default=None, help="Payload field as key=value")
|
|
34
|
+
parser.add_argument("--json", default=None, help="Payload fields as a JSON object")
|
|
35
|
+
parser.add_argument("--run", default=None)
|
|
36
|
+
parser.add_argument("--store-dir", default=None)
|
|
37
|
+
parser.add_argument("--user", default=None)
|
|
38
|
+
parser.add_argument("--lane", default=None)
|
|
39
|
+
|
|
40
|
+
return parser
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def run_add_step_command(
|
|
44
|
+
*,
|
|
45
|
+
run_id: str,
|
|
46
|
+
input_node_ids: list[str],
|
|
47
|
+
title: str | None,
|
|
48
|
+
payload_kind: str | None,
|
|
49
|
+
payload_type: str,
|
|
50
|
+
field_data: dict,
|
|
51
|
+
json_data: dict,
|
|
52
|
+
store_dir: str,
|
|
53
|
+
user_id: str | None = None,
|
|
54
|
+
lane_id: str | None = None,
|
|
55
|
+
) -> dict:
|
|
56
|
+
store = resolve_store(store_dir)
|
|
57
|
+
if not store.run_path(run_id).exists():
|
|
58
|
+
raise KeyError(f"unknown run_id: {run_id}")
|
|
59
|
+
handle = store.load_run(run_id)
|
|
60
|
+
data = dict(json_data or {})
|
|
61
|
+
data.update(field_data or {})
|
|
62
|
+
if title is not None:
|
|
63
|
+
data.setdefault("title", title)
|
|
64
|
+
data.setdefault("text", title)
|
|
65
|
+
if payload_kind is not None:
|
|
66
|
+
data.setdefault("type", payload_kind)
|
|
67
|
+
else:
|
|
68
|
+
data.setdefault("type", "step")
|
|
69
|
+
|
|
70
|
+
payload = build_payload(
|
|
71
|
+
payload_type=payload_type,
|
|
72
|
+
target_kind="step",
|
|
73
|
+
target_id="pending",
|
|
74
|
+
payload_id="pending",
|
|
75
|
+
json_data={},
|
|
76
|
+
field_data=data,
|
|
77
|
+
)
|
|
78
|
+
before = graph_counts(handle)
|
|
79
|
+
step = handle.add_step(
|
|
80
|
+
input_node_ids,
|
|
81
|
+
payload,
|
|
82
|
+
user_id=user_id,
|
|
83
|
+
lane_id=lane_id,
|
|
84
|
+
)
|
|
85
|
+
maybe_append_or_save(
|
|
86
|
+
store=store,
|
|
87
|
+
handle=handle,
|
|
88
|
+
user_id=user_id,
|
|
89
|
+
lane_id=lane_id,
|
|
90
|
+
before=before,
|
|
91
|
+
)
|
|
92
|
+
return {"step": step_view(step)}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def cli_add(args) -> int:
|
|
96
|
+
try:
|
|
97
|
+
result = run_add_step_command(
|
|
98
|
+
run_id=resolve_run_id_from_args(args),
|
|
99
|
+
input_node_ids=args.input_nodes,
|
|
100
|
+
title=args.title,
|
|
101
|
+
payload_kind=args.payload_kind,
|
|
102
|
+
payload_type=args.payload_type,
|
|
103
|
+
field_data=parse_field_args(args.field),
|
|
104
|
+
json_data=parse_json_object(args.json),
|
|
105
|
+
store_dir=args.store_dir,
|
|
106
|
+
user_id=resolve_user_id_from_args(args),
|
|
107
|
+
lane_id=resolve_lane_id_from_args(args),
|
|
108
|
+
)
|
|
109
|
+
print(json.dumps(result["step"], ensure_ascii=False, indent=2))
|
|
110
|
+
return 0
|
|
111
|
+
except (KeyError, ValueError, json.JSONDecodeError) as exc:
|
|
112
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
113
|
+
return 1
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""arctx asset command — attach and manage file assets (core payload)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from arctx_cli.append_batch import graph_counts, maybe_append_or_save
|
|
10
|
+
from arctx_cli.context import (
|
|
11
|
+
resolve_run_id_from_args,
|
|
12
|
+
resolve_store,
|
|
13
|
+
resolve_user_id_from_args,
|
|
14
|
+
resolve_lane_id_from_args,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
19
|
+
"""Register the ``asset`` command namespace."""
|
|
20
|
+
asset_parser = subparsers.add_parser("asset", help="Asset management commands")
|
|
21
|
+
asset_sub = asset_parser.add_subparsers(dest="asset_command", required=True)
|
|
22
|
+
|
|
23
|
+
sp_attach = asset_sub.add_parser("attach", help="Attach a file to a Node or Step")
|
|
24
|
+
sp_attach.add_argument("file_path", help="Path to the file to attach")
|
|
25
|
+
sp_attach.add_argument("--target", required=True, dest="target_id", help="Node or Step ID")
|
|
26
|
+
sp_attach.add_argument("--run", default=None)
|
|
27
|
+
sp_attach.add_argument("--store-dir", default=None)
|
|
28
|
+
sp_attach.add_argument("--user", default=None)
|
|
29
|
+
sp_attach.add_argument("--lane", default=None)
|
|
30
|
+
|
|
31
|
+
sp_list = asset_sub.add_parser("list", help="List assets for a Node or Step")
|
|
32
|
+
sp_list.add_argument("--target", required=True, dest="target_id", help="Node or Step ID")
|
|
33
|
+
sp_list.add_argument("--run", default=None)
|
|
34
|
+
sp_list.add_argument("--store-dir", default=None)
|
|
35
|
+
|
|
36
|
+
sp_show = asset_sub.add_parser("show", help="Show details of a specific asset payload")
|
|
37
|
+
sp_show.add_argument("payload_id", help="Payload ID of the asset")
|
|
38
|
+
sp_show.add_argument("--run", default=None)
|
|
39
|
+
sp_show.add_argument("--store-dir", default=None)
|
|
40
|
+
|
|
41
|
+
return asset_parser
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def cli_asset(args) -> int:
|
|
45
|
+
"""Dispatch ``arctx asset`` subcommands."""
|
|
46
|
+
if args.asset_command == "attach":
|
|
47
|
+
return _cli_asset_attach(args)
|
|
48
|
+
if args.asset_command == "list":
|
|
49
|
+
return _cli_asset_list(args)
|
|
50
|
+
if args.asset_command == "show":
|
|
51
|
+
return _cli_asset_show(args)
|
|
52
|
+
print(f"unknown asset subcommand: {args.asset_command}", file=sys.stderr)
|
|
53
|
+
return 1
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _cli_asset_attach(args) -> int:
|
|
57
|
+
store = resolve_store(args.store_dir)
|
|
58
|
+
run_id = resolve_run_id_from_args(args)
|
|
59
|
+
user_id = resolve_user_id_from_args(args)
|
|
60
|
+
lane_id = resolve_lane_id_from_args(args)
|
|
61
|
+
|
|
62
|
+
if not store.run_path(run_id).exists():
|
|
63
|
+
print(f"error: unknown run_id: {run_id}", file=sys.stderr)
|
|
64
|
+
return 1
|
|
65
|
+
|
|
66
|
+
handle = store.load_run(run_id)
|
|
67
|
+
if (
|
|
68
|
+
args.target_id not in handle.run_graph.nodes
|
|
69
|
+
and args.target_id not in handle.run_graph.steps
|
|
70
|
+
):
|
|
71
|
+
print(f"error: target_id not found: {args.target_id}", file=sys.stderr)
|
|
72
|
+
return 1
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
before = graph_counts(handle)
|
|
76
|
+
payload = handle.attach_asset(
|
|
77
|
+
args.target_id,
|
|
78
|
+
args.file_path,
|
|
79
|
+
user_id=user_id,
|
|
80
|
+
lane_id=lane_id,
|
|
81
|
+
)
|
|
82
|
+
except (KeyError, ValueError, FileNotFoundError) as exc:
|
|
83
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
84
|
+
return 1
|
|
85
|
+
|
|
86
|
+
maybe_append_or_save(
|
|
87
|
+
store=store,
|
|
88
|
+
handle=handle,
|
|
89
|
+
user_id=user_id,
|
|
90
|
+
lane_id=lane_id,
|
|
91
|
+
before=before,
|
|
92
|
+
)
|
|
93
|
+
print(json.dumps(payload.to_dict(), ensure_ascii=False, indent=2))
|
|
94
|
+
return 0
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _cli_asset_list(args) -> int:
|
|
98
|
+
store = resolve_store(args.store_dir)
|
|
99
|
+
run_id = resolve_run_id_from_args(args)
|
|
100
|
+
|
|
101
|
+
if not store.run_path(run_id).exists():
|
|
102
|
+
print(f"error: unknown run_id: {run_id}", file=sys.stderr)
|
|
103
|
+
return 1
|
|
104
|
+
|
|
105
|
+
handle = store.load_run(run_id)
|
|
106
|
+
if args.target_id in handle.run_graph.nodes:
|
|
107
|
+
raw_payloads = handle.run_graph.payloads_for_node(args.target_id)
|
|
108
|
+
elif args.target_id in handle.run_graph.steps:
|
|
109
|
+
raw_payloads = handle.run_graph.payloads_for_step(args.target_id)
|
|
110
|
+
else:
|
|
111
|
+
print(f"error: target_id not found: {args.target_id}", file=sys.stderr)
|
|
112
|
+
return 1
|
|
113
|
+
|
|
114
|
+
payloads = [
|
|
115
|
+
p.to_dict()
|
|
116
|
+
for p in raw_payloads
|
|
117
|
+
if getattr(p, "payload_type", None) == "asset"
|
|
118
|
+
]
|
|
119
|
+
print(json.dumps(payloads, ensure_ascii=False, indent=2))
|
|
120
|
+
return 0
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _cli_asset_show(args) -> int:
|
|
124
|
+
store = resolve_store(args.store_dir)
|
|
125
|
+
run_id = resolve_run_id_from_args(args)
|
|
126
|
+
|
|
127
|
+
if not store.run_path(run_id).exists():
|
|
128
|
+
print(f"error: unknown run_id: {run_id}", file=sys.stderr)
|
|
129
|
+
return 1
|
|
130
|
+
|
|
131
|
+
handle = store.load_run(run_id)
|
|
132
|
+
payload = handle.run_graph.payloads.get(args.payload_id)
|
|
133
|
+
if payload is None or getattr(payload, "payload_type", None) != "asset":
|
|
134
|
+
print(f"error: asset payload not found: {args.payload_id}", file=sys.stderr)
|
|
135
|
+
return 1
|
|
136
|
+
|
|
137
|
+
print(json.dumps(payload.to_dict(), ensure_ascii=False, indent=2))
|
|
138
|
+
return 0
|
|
@@ -7,14 +7,14 @@ import json
|
|
|
7
7
|
import sys
|
|
8
8
|
|
|
9
9
|
from arctx_cli.commands._targets import resolve_target_kind
|
|
10
|
-
from arctx_cli.
|
|
10
|
+
from arctx_cli.append_batch import graph_counts, maybe_append_or_save
|
|
11
11
|
from arctx_cli.context import (
|
|
12
12
|
resolve_run_id_from_args,
|
|
13
13
|
resolve_store,
|
|
14
14
|
resolve_user_id_from_args,
|
|
15
|
-
|
|
15
|
+
resolve_lane_id_from_args,
|
|
16
16
|
)
|
|
17
|
-
from arctx_cli.payload_builder import parse_field_args, parse_json_object
|
|
17
|
+
from arctx_cli.payload_builder import build_payload, parse_field_args, parse_json_object
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
@@ -27,7 +27,7 @@ def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
|
27
27
|
parser.add_argument("--run", default=None)
|
|
28
28
|
parser.add_argument("--store-dir", default=None)
|
|
29
29
|
parser.add_argument("--user", default=None)
|
|
30
|
-
parser.add_argument("--
|
|
30
|
+
parser.add_argument("--lane", default=None)
|
|
31
31
|
return parser
|
|
32
32
|
|
|
33
33
|
|
|
@@ -41,7 +41,7 @@ def run_attach_command(
|
|
|
41
41
|
json_data: dict,
|
|
42
42
|
store_dir: str,
|
|
43
43
|
user_id: str | None = None,
|
|
44
|
-
|
|
44
|
+
lane_id: str | None = None,
|
|
45
45
|
) -> dict:
|
|
46
46
|
store = resolve_store(store_dir)
|
|
47
47
|
if not store.run_path(run_id).exists():
|
|
@@ -57,18 +57,42 @@ def run_attach_command(
|
|
|
57
57
|
internal_payload_type = payload_type or (
|
|
58
58
|
"node_payload" if target_kind == "node" else "step_payload"
|
|
59
59
|
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
target_kind=target_kind,
|
|
63
|
-
target_id=target_id,
|
|
60
|
+
before = graph_counts(handle)
|
|
61
|
+
payload = build_payload(
|
|
64
62
|
payload_type=internal_payload_type,
|
|
65
|
-
|
|
63
|
+
target_kind=target_kind, # type: ignore[arg-type]
|
|
64
|
+
target_id=target_id,
|
|
65
|
+
payload_id=handle._next_id("pl"),
|
|
66
66
|
json_data={},
|
|
67
|
-
|
|
67
|
+
field_data=data,
|
|
68
|
+
)
|
|
69
|
+
if payload.target_kind == "node":
|
|
70
|
+
attached = handle.attach(
|
|
71
|
+
payload.target_id,
|
|
72
|
+
payload,
|
|
73
|
+
user_id=user_id,
|
|
74
|
+
lane_id=lane_id,
|
|
75
|
+
)
|
|
76
|
+
else:
|
|
77
|
+
handle.run_graph.attach_payload(payload)
|
|
78
|
+
handle.record_work_event(
|
|
79
|
+
user_id=user_id,
|
|
80
|
+
lane_id=lane_id,
|
|
81
|
+
event_type="payload_attached",
|
|
82
|
+
target_kind="step",
|
|
83
|
+
target_id=payload.target_id,
|
|
84
|
+
created_records=(payload.payload_id,),
|
|
85
|
+
)
|
|
86
|
+
attached = payload
|
|
87
|
+
|
|
88
|
+
maybe_append_or_save(
|
|
89
|
+
store=store,
|
|
90
|
+
handle=handle,
|
|
68
91
|
user_id=user_id,
|
|
69
|
-
|
|
92
|
+
lane_id=lane_id,
|
|
93
|
+
before=before,
|
|
70
94
|
)
|
|
71
|
-
return
|
|
95
|
+
return {"payload": attached.to_dict()}
|
|
72
96
|
|
|
73
97
|
|
|
74
98
|
def cli_attach(args) -> int:
|
|
@@ -82,7 +106,7 @@ def cli_attach(args) -> int:
|
|
|
82
106
|
json_data=parse_json_object(args.json),
|
|
83
107
|
store_dir=args.store_dir,
|
|
84
108
|
user_id=resolve_user_id_from_args(args),
|
|
85
|
-
|
|
109
|
+
lane_id=resolve_lane_id_from_args(args),
|
|
86
110
|
)
|
|
87
111
|
print(json.dumps(result["payload"], ensure_ascii=False, indent=2))
|
|
88
112
|
return 0
|
|
@@ -10,7 +10,7 @@ from arctx_cli.context import (
|
|
|
10
10
|
resolve_run_id_from_args,
|
|
11
11
|
resolve_store,
|
|
12
12
|
resolve_user_id_from_args,
|
|
13
|
-
|
|
13
|
+
resolve_lane_id_from_args,
|
|
14
14
|
)
|
|
15
15
|
from arctx_cli.append_batch import graph_counts, maybe_append_or_save
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
|
26
26
|
parser.add_argument("--reason", default=None)
|
|
27
27
|
parser.add_argument("--store-dir", default=None)
|
|
28
28
|
parser.add_argument("--user", default=None)
|
|
29
|
-
parser.add_argument("--
|
|
29
|
+
parser.add_argument("--lane", default=None)
|
|
30
30
|
return parser
|
|
31
31
|
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ def run_cut_command(
|
|
|
38
38
|
reason: str | None,
|
|
39
39
|
store_dir: str,
|
|
40
40
|
user_id: str | None = None,
|
|
41
|
-
|
|
41
|
+
lane_id: str | None = None,
|
|
42
42
|
) -> dict:
|
|
43
43
|
store = resolve_store(store_dir)
|
|
44
44
|
if not store.run_path(run_id).exists():
|
|
@@ -50,13 +50,13 @@ def run_cut_command(
|
|
|
50
50
|
target_kind=target_kind, # type: ignore[arg-type]
|
|
51
51
|
reason=reason,
|
|
52
52
|
user_id=user_id,
|
|
53
|
-
|
|
53
|
+
lane_id=lane_id,
|
|
54
54
|
)
|
|
55
55
|
maybe_append_or_save(
|
|
56
56
|
store=store,
|
|
57
57
|
handle=handle,
|
|
58
58
|
user_id=user_id,
|
|
59
|
-
|
|
59
|
+
lane_id=lane_id,
|
|
60
60
|
before=before,
|
|
61
61
|
)
|
|
62
62
|
return {"cut": cut.to_dict()}
|
|
@@ -96,7 +96,7 @@ def cli_cut(args) -> int:
|
|
|
96
96
|
reason=args.reason,
|
|
97
97
|
store_dir=args.store_dir,
|
|
98
98
|
user_id=resolve_user_id_from_args(args),
|
|
99
|
-
|
|
99
|
+
lane_id=resolve_lane_id_from_args(args),
|
|
100
100
|
)
|
|
101
101
|
print(json.dumps(result["cut"], ensure_ascii=False, indent=2))
|
|
102
102
|
return 0
|
|
@@ -21,9 +21,9 @@ def add_parser(subparsers) -> argparse.ArgumentParser:
|
|
|
21
21
|
parser.add_argument(
|
|
22
22
|
"--format",
|
|
23
23
|
dest="fmt",
|
|
24
|
-
choices=["md", "tex", "html"],
|
|
24
|
+
choices=["md", "tex", "html", "json"],
|
|
25
25
|
default="md",
|
|
26
|
-
help="Output format (default: md)",
|
|
26
|
+
help="Output format (default: md). json = machine-readable data contract for GUIs",
|
|
27
27
|
)
|
|
28
28
|
parser.add_argument("--node", dest="node_id", default=None,
|
|
29
29
|
help="Export only the subtree rooted at this node")
|