agentproc 0.3.0__tar.gz → 0.4.1__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.
- {agentproc-0.3.0 → agentproc-0.4.1}/PKG-INFO +1 -1
- {agentproc-0.3.0 → agentproc-0.4.1}/pyproject.toml +1 -1
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc/cli.py +129 -29
- agentproc-0.4.1/src/agentproc/hub.py +582 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc/runner.py +252 -23
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc.egg-info/PKG-INFO +1 -1
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc.egg-info/SOURCES.txt +1 -0
- agentproc-0.4.1/tests/test_conformance.py +33 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/tests/test_hub.py +85 -12
- agentproc-0.3.0/src/agentproc/hub.py +0 -294
- {agentproc-0.3.0 → agentproc-0.4.1}/setup.cfg +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc/__init__.py +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc.egg-info/dependency_links.txt +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc.egg-info/entry_points.txt +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/src/agentproc.egg-info/top_level.txt +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/tests/test_agentproc.py +0 -0
- {agentproc-0.3.0 → agentproc-0.4.1}/tests/test_runner.py +0 -0
|
@@ -227,6 +227,27 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
227
227
|
def show_help() -> None:
|
|
228
228
|
sys.stdout.write(f"""agentproc v{PKG_VERSION} (protocol {PROTOCOL_VERSION})
|
|
229
229
|
|
|
230
|
+
The fastest way in:
|
|
231
|
+
agentproc hub list # see what's available
|
|
232
|
+
agentproc hub run echo-agent -p "hello" # smoke test (no API key)
|
|
233
|
+
cd ~/projects/my-app && agentproc hub run claude-code -p "explain this"
|
|
234
|
+
|
|
235
|
+
The CLI fetches the profile from the GitHub hub on first use, caches it at
|
|
236
|
+
~/.agentproc/cache/hub/<name>/ (24h TTL), and uses your current directory as
|
|
237
|
+
the agent's cwd. Set GITHUB_TOKEN to raise the rate limit (see `agentproc hub --help`).
|
|
238
|
+
|
|
239
|
+
Hub subcommands:
|
|
240
|
+
hub list List all profiles in the hub
|
|
241
|
+
hub show <name> Show a profile's README
|
|
242
|
+
hub run <name> [run-options] Fetch (if needed) and run a profile
|
|
243
|
+
hub install <name> Copy a profile to the current directory
|
|
244
|
+
|
|
245
|
+
Run `agentproc hub --help` for the full hub reference.
|
|
246
|
+
|
|
247
|
+
───────────────────────────────────────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
Advanced: run a local profile YAML directly (no hub fetch)
|
|
250
|
+
|
|
230
251
|
Usage:
|
|
231
252
|
agentproc --profile <path.yaml> --prompt "hello" [options]
|
|
232
253
|
|
|
@@ -240,7 +261,8 @@ Session:
|
|
|
240
261
|
--from <user> Sender identifier
|
|
241
262
|
|
|
242
263
|
Execution:
|
|
243
|
-
--cwd <path> Override profile.cwd
|
|
264
|
+
--cwd <path> Override profile.cwd (relative paths resolve
|
|
265
|
+
against the profile.yaml's directory)
|
|
244
266
|
--env KEY=VALUE Extra env var (repeatable)
|
|
245
267
|
--timeout <secs> Override profile.timeout_secs
|
|
246
268
|
--no-stream Set AGENT_STREAMING=0
|
|
@@ -263,9 +285,16 @@ Output semantics:
|
|
|
263
285
|
The final session id is printed on stderr as: agentproc:session:<id>
|
|
264
286
|
|
|
265
287
|
Examples:
|
|
266
|
-
|
|
267
|
-
agentproc
|
|
268
|
-
|
|
288
|
+
# Local profile (relative cwd resolves next to profile.yaml):
|
|
289
|
+
agentproc --profile ./hub/echo-agent/profile.yaml --prompt "hi"
|
|
290
|
+
|
|
291
|
+
# Local claude-code profile, claude runs against your project:
|
|
292
|
+
agentproc --profile ./hub/claude-code/profile.yaml \\
|
|
293
|
+
--prompt "explain this codebase" \\
|
|
294
|
+
--cwd /path/to/your/project
|
|
295
|
+
|
|
296
|
+
# Prompt from stdin:
|
|
297
|
+
cat prompt.txt | agentproc --profile prof.yaml --stdin
|
|
269
298
|
""")
|
|
270
299
|
|
|
271
300
|
|
|
@@ -288,9 +317,46 @@ def _run_hub_subcommand(args: List[str]) -> int:
|
|
|
288
317
|
sub = args[0]
|
|
289
318
|
rest = args[1:]
|
|
290
319
|
|
|
320
|
+
# Any subcommand with --help/-h shows the hub help uniformly.
|
|
321
|
+
if "--help" in rest or "-h" in rest:
|
|
322
|
+
_show_hub_help()
|
|
323
|
+
return 0
|
|
324
|
+
|
|
291
325
|
# Common flag
|
|
292
326
|
refresh = "--refresh" in rest
|
|
293
|
-
|
|
327
|
+
|
|
328
|
+
# Separate hub-level flags from runner-level flags and positional args.
|
|
329
|
+
# In the `hub run` context, `-p` means `--prompt` (the profile name is
|
|
330
|
+
# positional, not a path), so normalize it before handing off to argparse.
|
|
331
|
+
positional: List[str] = []
|
|
332
|
+
runner_args: List[str] = []
|
|
333
|
+
takes_value = {"--prompt", "-p", "--session", "--session-name", "--from",
|
|
334
|
+
"--cwd", "--env", "--timeout"}
|
|
335
|
+
boolean_flags = {"--no-stream", "--verbose", "--quiet", "--raw", "--stdin"}
|
|
336
|
+
i = 0
|
|
337
|
+
while i < len(rest):
|
|
338
|
+
a = rest[i]
|
|
339
|
+
if a in ("--refresh", "-h", "--help"):
|
|
340
|
+
i += 1
|
|
341
|
+
continue
|
|
342
|
+
if a in takes_value:
|
|
343
|
+
runner_args.append("--prompt" if a == "-p" else a)
|
|
344
|
+
if i + 1 < len(rest):
|
|
345
|
+
runner_args.append(rest[i + 1])
|
|
346
|
+
i += 2
|
|
347
|
+
else:
|
|
348
|
+
i += 1
|
|
349
|
+
continue
|
|
350
|
+
if a in boolean_flags:
|
|
351
|
+
runner_args.append(a)
|
|
352
|
+
i += 1
|
|
353
|
+
continue
|
|
354
|
+
if a.startswith("-"):
|
|
355
|
+
sys.stderr.write(f"error: unknown option: {a}\n\n")
|
|
356
|
+
_show_hub_help()
|
|
357
|
+
return 2
|
|
358
|
+
positional.append(a)
|
|
359
|
+
i += 1
|
|
294
360
|
|
|
295
361
|
def _log(msg: str) -> None:
|
|
296
362
|
sys.stderr.write(msg + "\n")
|
|
@@ -319,7 +385,14 @@ def _run_hub_subcommand(args: List[str]) -> int:
|
|
|
319
385
|
if not positional:
|
|
320
386
|
sys.stderr.write("error: hub install requires a profile name\n")
|
|
321
387
|
return 2
|
|
322
|
-
hub_mod.install_profile(positional[0], Path.cwd(), refresh=refresh, on_log=_log)
|
|
388
|
+
dest = hub_mod.install_profile(positional[0], Path.cwd(), refresh=refresh, on_log=_log)
|
|
389
|
+
# Tell the user exactly what they got and how to run it next.
|
|
390
|
+
rel_profile = os.path.relpath(str(dest / "profile.yaml"), str(Path.cwd()))
|
|
391
|
+
sys.stderr.write("\n")
|
|
392
|
+
sys.stderr.write(f"Next: edit {rel_profile} if you want, then run:\n")
|
|
393
|
+
sys.stderr.write(
|
|
394
|
+
f' agentproc --profile {rel_profile} --prompt "hi" --cwd <your-project>\n'
|
|
395
|
+
)
|
|
323
396
|
return 0
|
|
324
397
|
|
|
325
398
|
if sub == "run":
|
|
@@ -330,18 +403,20 @@ def _run_hub_subcommand(args: List[str]) -> int:
|
|
|
330
403
|
cache_dir = hub_mod.fetch_profile(profile_name, refresh=refresh, on_log=_log)
|
|
331
404
|
profile_path = str(cache_dir / "profile.yaml")
|
|
332
405
|
|
|
333
|
-
#
|
|
406
|
+
# Parse the runner-level flags we separated out above.
|
|
334
407
|
parser = build_parser()
|
|
335
|
-
# Drop the first positional (profile name) and --refresh from rest.
|
|
336
|
-
runner_args = [a for i, a in enumerate(rest) if not (
|
|
337
|
-
(not a.startswith("--") and i == 0) or a == "--refresh"
|
|
338
|
-
)]
|
|
339
408
|
opts = parser.parse_args(runner_args)
|
|
340
409
|
|
|
341
410
|
if not opts.prompt and not opts.stdin:
|
|
342
411
|
sys.stderr.write("error: hub run requires --prompt <text> or --stdin\n")
|
|
343
412
|
return 2
|
|
344
413
|
|
|
414
|
+
# hub run uses the user's current directory as the agent's cwd when
|
|
415
|
+
# --cwd is not given. Matches the hub docs and the right default for
|
|
416
|
+
# AI-CLI profiles where the agent should operate on the user's project.
|
|
417
|
+
if not opts.cwd:
|
|
418
|
+
opts.cwd = str(Path.cwd())
|
|
419
|
+
|
|
345
420
|
return _run_agent_with_profile(profile_path, opts)
|
|
346
421
|
|
|
347
422
|
sys.stderr.write(f"error: unknown hub subcommand: {sub}\n\n")
|
|
@@ -385,6 +460,7 @@ Profiles are cached at ~/.agentproc/cache/hub/<name>/ (24h TTL).
|
|
|
385
460
|
|
|
386
461
|
def _run_agent_with_profile(profile_path: str, opts) -> int:
|
|
387
462
|
"""Shared runner logic for both --profile path and hub run path."""
|
|
463
|
+
profile_dir = str(Path(profile_path).resolve().parent)
|
|
388
464
|
try:
|
|
389
465
|
yaml_text = Path(profile_path).resolve().read_text(encoding="utf-8")
|
|
390
466
|
profile_raw = parse_yaml(yaml_text)
|
|
@@ -426,6 +502,7 @@ def _run_agent_with_profile(profile_path: str, opts) -> int:
|
|
|
426
502
|
from_user=opts.from_user,
|
|
427
503
|
streaming=streaming,
|
|
428
504
|
cwd=opts.cwd,
|
|
505
|
+
profile_dir=profile_dir,
|
|
429
506
|
extra_env=extra_env,
|
|
430
507
|
timeout_secs=opts.timeout,
|
|
431
508
|
),
|
|
@@ -446,6 +523,7 @@ def _run_agent_with_profile(profile_path: str, opts) -> int:
|
|
|
446
523
|
from_user=opts.from_user,
|
|
447
524
|
streaming=streaming,
|
|
448
525
|
cwd=opts.cwd,
|
|
526
|
+
profile_dir=profile_dir,
|
|
449
527
|
extra_env=extra_env,
|
|
450
528
|
timeout_secs=opts.timeout,
|
|
451
529
|
on_partial=lambda t: verbose and sys.stderr.write(
|
|
@@ -478,26 +556,48 @@ def main(argv: Optional[List[str]] = None) -> int:
|
|
|
478
556
|
if argv is None:
|
|
479
557
|
argv = sys.argv[1:]
|
|
480
558
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
parser = build_parser()
|
|
486
|
-
opts = parser.parse_args(argv)
|
|
487
|
-
|
|
488
|
-
if opts.help:
|
|
489
|
-
show_help()
|
|
490
|
-
return 0
|
|
491
|
-
if opts.version:
|
|
492
|
-
show_version()
|
|
493
|
-
return 0
|
|
559
|
+
try:
|
|
560
|
+
# `agentproc hub <subcommand>` — defer to hub dispatcher.
|
|
561
|
+
if argv and argv[0] == "hub":
|
|
562
|
+
return _run_hub_subcommand(argv[1:])
|
|
494
563
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
564
|
+
parser = build_parser()
|
|
565
|
+
opts = parser.parse_args(argv)
|
|
566
|
+
|
|
567
|
+
if opts.help:
|
|
568
|
+
show_help()
|
|
569
|
+
return 0
|
|
570
|
+
if opts.version:
|
|
571
|
+
show_version()
|
|
572
|
+
return 0
|
|
573
|
+
|
|
574
|
+
if not opts.profile:
|
|
575
|
+
sys.stderr.write("error: --profile is required\n\n")
|
|
576
|
+
show_help()
|
|
577
|
+
return 2
|
|
499
578
|
|
|
500
|
-
|
|
579
|
+
return _run_agent_with_profile(opts.profile, opts)
|
|
580
|
+
except KeyboardInterrupt:
|
|
581
|
+
return 130
|
|
582
|
+
except Exception as e:
|
|
583
|
+
# Friendly handling for known hub errors: print the message + hint,
|
|
584
|
+
# never a raw stack trace.
|
|
585
|
+
from .hub import HubError
|
|
586
|
+
if isinstance(e, HubError):
|
|
587
|
+
sys.stderr.write(f"error: {e}\n")
|
|
588
|
+
if e.hint:
|
|
589
|
+
sys.stderr.write(f"\n{e.hint}\n")
|
|
590
|
+
return 1
|
|
591
|
+
# Network errors that slipped through unwrapped.
|
|
592
|
+
msg = str(e)
|
|
593
|
+
if any(s in msg for s in ("fetch failed", "ENOTFOUND", "ECONNREFUSED", "ECONNRESET", "urlopen error")):
|
|
594
|
+
sys.stderr.write(f"error: network error talking to GitHub: {msg}\n")
|
|
595
|
+
sys.stderr.write("\nThis is usually transient. Re-run the command, or run against a local checkout:\n")
|
|
596
|
+
sys.stderr.write(' agentproc --profile ./hub/<name>/profile.yaml --prompt "hi"\n')
|
|
597
|
+
return 1
|
|
598
|
+
# Everything else: surface the message without dumping a traceback.
|
|
599
|
+
sys.stderr.write(f"error: {msg}\n")
|
|
600
|
+
return 1
|
|
501
601
|
|
|
502
602
|
|
|
503
603
|
if __name__ == "__main__":
|