@prismer/runtime 2.0.7 → 2.0.8
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.md +201 -0
- package/built-in-skills/agent-coordination/SKILL.md +235 -0
- package/built-in-skills/agent-meta/SKILL.md +52 -0
- package/built-in-skills/assets/SKILL.md +131 -0
- package/built-in-skills/canvas-design/LICENSE.txt +202 -0
- package/built-in-skills/canvas-design/SKILL.md +156 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/built-in-skills/claim-agent-ownership/SKILL.md +254 -0
- package/built-in-skills/claude-api/LICENSE.txt +202 -0
- package/built-in-skills/claude-api/SKILL.md +324 -0
- package/built-in-skills/claude-api/csharp/claude-api.md +402 -0
- package/built-in-skills/claude-api/curl/examples.md +216 -0
- package/built-in-skills/claude-api/curl/managed-agents.md +336 -0
- package/built-in-skills/claude-api/go/claude-api.md +421 -0
- package/built-in-skills/claude-api/go/managed-agents/README.md +561 -0
- package/built-in-skills/claude-api/java/claude-api.md +432 -0
- package/built-in-skills/claude-api/java/managed-agents/README.md +442 -0
- package/built-in-skills/claude-api/php/claude-api.md +375 -0
- package/built-in-skills/claude-api/php/managed-agents/README.md +435 -0
- package/built-in-skills/claude-api/python/claude-api/README.md +420 -0
- package/built-in-skills/claude-api/python/claude-api/batches.md +185 -0
- package/built-in-skills/claude-api/python/claude-api/files-api.md +165 -0
- package/built-in-skills/claude-api/python/claude-api/streaming.md +162 -0
- package/built-in-skills/claude-api/python/claude-api/tool-use.md +590 -0
- package/built-in-skills/claude-api/python/managed-agents/README.md +332 -0
- package/built-in-skills/claude-api/ruby/claude-api.md +113 -0
- package/built-in-skills/claude-api/ruby/managed-agents/README.md +389 -0
- package/built-in-skills/claude-api/shared/agent-design.md +101 -0
- package/built-in-skills/claude-api/shared/error-codes.md +213 -0
- package/built-in-skills/claude-api/shared/live-sources.md +135 -0
- package/built-in-skills/claude-api/shared/managed-agents-api-reference.md +378 -0
- package/built-in-skills/claude-api/shared/managed-agents-client-patterns.md +209 -0
- package/built-in-skills/claude-api/shared/managed-agents-core.md +238 -0
- package/built-in-skills/claude-api/shared/managed-agents-environments.md +215 -0
- package/built-in-skills/claude-api/shared/managed-agents-events.md +195 -0
- package/built-in-skills/claude-api/shared/managed-agents-memory.md +197 -0
- package/built-in-skills/claude-api/shared/managed-agents-multiagent.md +99 -0
- package/built-in-skills/claude-api/shared/managed-agents-onboarding.md +114 -0
- package/built-in-skills/claude-api/shared/managed-agents-outcomes.md +106 -0
- package/built-in-skills/claude-api/shared/managed-agents-overview.md +68 -0
- package/built-in-skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +173 -0
- package/built-in-skills/claude-api/shared/managed-agents-tools.md +321 -0
- package/built-in-skills/claude-api/shared/managed-agents-webhooks.md +110 -0
- package/built-in-skills/claude-api/shared/model-migration.md +779 -0
- package/built-in-skills/claude-api/shared/models.md +121 -0
- package/built-in-skills/claude-api/shared/prompt-caching.md +171 -0
- package/built-in-skills/claude-api/shared/tool-use-concepts.md +327 -0
- package/built-in-skills/claude-api/typescript/claude-api/README.md +333 -0
- package/built-in-skills/claude-api/typescript/claude-api/batches.md +106 -0
- package/built-in-skills/claude-api/typescript/claude-api/files-api.md +98 -0
- package/built-in-skills/claude-api/typescript/claude-api/streaming.md +178 -0
- package/built-in-skills/claude-api/typescript/claude-api/tool-use.md +527 -0
- package/built-in-skills/claude-api/typescript/managed-agents/README.md +359 -0
- package/built-in-skills/doc-coauthoring/SKILL.md +375 -0
- package/built-in-skills/frontend-design/LICENSE.txt +177 -0
- package/built-in-skills/frontend-design/SKILL.md +42 -0
- package/built-in-skills/human-approval/SKILL.md +114 -0
- package/built-in-skills/image-generate/SKILL.md +327 -0
- package/built-in-skills/ingest/SKILL.md +105 -0
- package/built-in-skills/internal-comms/LICENSE.txt +202 -0
- package/built-in-skills/internal-comms/SKILL.md +32 -0
- package/built-in-skills/internal-comms/examples/3p-updates.md +47 -0
- package/built-in-skills/internal-comms/examples/company-newsletter.md +65 -0
- package/built-in-skills/internal-comms/examples/faq-answers.md +30 -0
- package/built-in-skills/internal-comms/examples/general-comms.md +16 -0
- package/built-in-skills/liteparse/SKILL.md +156 -0
- package/built-in-skills/mcp-builder/LICENSE.txt +202 -0
- package/built-in-skills/mcp-builder/SKILL.md +236 -0
- package/built-in-skills/mcp-builder/reference/evaluation.md +602 -0
- package/built-in-skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/built-in-skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/built-in-skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/built-in-skills/mcp-builder/scripts/connections.py +151 -0
- package/built-in-skills/mcp-builder/scripts/evaluation.py +373 -0
- package/built-in-skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/built-in-skills/mcp-builder/scripts/requirements.txt +2 -0
- package/built-in-skills/memory/SKILL.md +106 -0
- package/built-in-skills/memory-curation/SKILL.md +135 -0
- package/built-in-skills/office-artifacts/SKILL.md +198 -0
- package/built-in-skills/prismer-im-collab/SKILL.md +148 -0
- package/built-in-skills/skill-authoring/SKILL.md +124 -0
- package/built-in-skills/skill-authoring/skill.json +74 -0
- package/built-in-skills/skill-creator/LICENSE.txt +202 -0
- package/built-in-skills/skill-creator/SKILL.md +485 -0
- package/built-in-skills/skill-creator/agents/analyzer.md +274 -0
- package/built-in-skills/skill-creator/agents/comparator.md +202 -0
- package/built-in-skills/skill-creator/agents/grader.md +223 -0
- package/built-in-skills/skill-creator/assets/eval_review.html +146 -0
- package/built-in-skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/built-in-skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/built-in-skills/skill-creator/references/schemas.md +430 -0
- package/built-in-skills/skill-creator/scripts/__init__.py +0 -0
- package/built-in-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/built-in-skills/skill-creator/scripts/generate_report.py +326 -0
- package/built-in-skills/skill-creator/scripts/improve_description.py +247 -0
- package/built-in-skills/skill-creator/scripts/package_skill.py +136 -0
- package/built-in-skills/skill-creator/scripts/quick_validate.py +103 -0
- package/built-in-skills/skill-creator/scripts/run_eval.py +310 -0
- package/built-in-skills/skill-creator/scripts/run_loop.py +328 -0
- package/built-in-skills/skill-creator/scripts/utils.py +47 -0
- package/built-in-skills/slack-gif-creator/LICENSE.txt +202 -0
- package/built-in-skills/slack-gif-creator/SKILL.md +271 -0
- package/built-in-skills/slack-gif-creator/core/easing.py +234 -0
- package/built-in-skills/slack-gif-creator/core/frame_composer.py +176 -0
- package/built-in-skills/slack-gif-creator/core/gif_builder.py +269 -0
- package/built-in-skills/slack-gif-creator/core/validators.py +136 -0
- package/built-in-skills/slack-gif-creator/requirements.txt +4 -0
- package/built-in-skills/tasks/SKILL.md +398 -0
- package/built-in-skills/team/SKILL.md +76 -0
- package/built-in-skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/built-in-skills/web-artifacts-builder/SKILL.md +104 -0
- package/built-in-skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/built-in-skills/web-artifacts-builder/scripts/init-artifact.sh +334 -0
- package/built-in-skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/built-in-skills/webapp-testing/LICENSE.txt +202 -0
- package/built-in-skills/webapp-testing/SKILL.md +96 -0
- package/built-in-skills/webapp-testing/examples/console_logging.py +35 -0
- package/built-in-skills/webapp-testing/examples/element_discovery.py +40 -0
- package/built-in-skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/built-in-skills/webapp-testing/scripts/with_server.py +106 -0
- package/dist/cli.cjs +6195 -1631
- package/dist/cli.js +6148 -1585
- package/dist/index.cjs +6032 -1468
- package/dist/index.d.cts +813 -43
- package/dist/index.d.ts +813 -43
- package/dist/index.js +6017 -1454
- package/package.json +4 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from playwright.sync_api import sync_playwright
|
|
2
|
+
|
|
3
|
+
# Example: Discovering buttons and other elements on a page
|
|
4
|
+
|
|
5
|
+
with sync_playwright() as p:
|
|
6
|
+
browser = p.chromium.launch(headless=True)
|
|
7
|
+
page = browser.new_page()
|
|
8
|
+
|
|
9
|
+
# Navigate to page and wait for it to fully load
|
|
10
|
+
page.goto('http://localhost:5173')
|
|
11
|
+
page.wait_for_load_state('networkidle')
|
|
12
|
+
|
|
13
|
+
# Discover all buttons on the page
|
|
14
|
+
buttons = page.locator('button').all()
|
|
15
|
+
print(f"Found {len(buttons)} buttons:")
|
|
16
|
+
for i, button in enumerate(buttons):
|
|
17
|
+
text = button.inner_text() if button.is_visible() else "[hidden]"
|
|
18
|
+
print(f" [{i}] {text}")
|
|
19
|
+
|
|
20
|
+
# Discover links
|
|
21
|
+
links = page.locator('a[href]').all()
|
|
22
|
+
print(f"\nFound {len(links)} links:")
|
|
23
|
+
for link in links[:5]: # Show first 5
|
|
24
|
+
text = link.inner_text().strip()
|
|
25
|
+
href = link.get_attribute('href')
|
|
26
|
+
print(f" - {text} -> {href}")
|
|
27
|
+
|
|
28
|
+
# Discover input fields
|
|
29
|
+
inputs = page.locator('input, textarea, select').all()
|
|
30
|
+
print(f"\nFound {len(inputs)} input fields:")
|
|
31
|
+
for input_elem in inputs:
|
|
32
|
+
name = input_elem.get_attribute('name') or input_elem.get_attribute('id') or "[unnamed]"
|
|
33
|
+
input_type = input_elem.get_attribute('type') or 'text'
|
|
34
|
+
print(f" - {name} ({input_type})")
|
|
35
|
+
|
|
36
|
+
# Take screenshot for visual reference
|
|
37
|
+
page.screenshot(path='/tmp/page_discovery.png', full_page=True)
|
|
38
|
+
print("\nScreenshot saved to /tmp/page_discovery.png")
|
|
39
|
+
|
|
40
|
+
browser.close()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from playwright.sync_api import sync_playwright
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
# Example: Automating interaction with static HTML files using file:// URLs
|
|
5
|
+
|
|
6
|
+
html_file_path = os.path.abspath('path/to/your/file.html')
|
|
7
|
+
file_url = f'file://{html_file_path}'
|
|
8
|
+
|
|
9
|
+
with sync_playwright() as p:
|
|
10
|
+
browser = p.chromium.launch(headless=True)
|
|
11
|
+
page = browser.new_page(viewport={'width': 1920, 'height': 1080})
|
|
12
|
+
|
|
13
|
+
# Navigate to local HTML file
|
|
14
|
+
page.goto(file_url)
|
|
15
|
+
|
|
16
|
+
# Take screenshot
|
|
17
|
+
page.screenshot(path='/mnt/user-data/outputs/static_page.png', full_page=True)
|
|
18
|
+
|
|
19
|
+
# Interact with elements
|
|
20
|
+
page.click('text=Click Me')
|
|
21
|
+
page.fill('#name', 'John Doe')
|
|
22
|
+
page.fill('#email', 'john@example.com')
|
|
23
|
+
|
|
24
|
+
# Submit form
|
|
25
|
+
page.click('button[type="submit"]')
|
|
26
|
+
page.wait_for_timeout(500)
|
|
27
|
+
|
|
28
|
+
# Take final screenshot
|
|
29
|
+
page.screenshot(path='/mnt/user-data/outputs/after_submit.png', full_page=True)
|
|
30
|
+
|
|
31
|
+
browser.close()
|
|
32
|
+
|
|
33
|
+
print("Static HTML automation completed!")
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Start one or more servers, wait for them to be ready, run a command, then clean up.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
# Single server
|
|
7
|
+
python scripts/with_server.py --server "npm run dev" --port 5173 -- python automation.py
|
|
8
|
+
python scripts/with_server.py --server "npm start" --port 3000 -- python test.py
|
|
9
|
+
|
|
10
|
+
# Multiple servers
|
|
11
|
+
python scripts/with_server.py \
|
|
12
|
+
--server "cd backend && python server.py" --port 3000 \
|
|
13
|
+
--server "cd frontend && npm run dev" --port 5173 \
|
|
14
|
+
-- python test.py
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import subprocess
|
|
18
|
+
import socket
|
|
19
|
+
import time
|
|
20
|
+
import sys
|
|
21
|
+
import argparse
|
|
22
|
+
|
|
23
|
+
def is_server_ready(port, timeout=30):
|
|
24
|
+
"""Wait for server to be ready by polling the port."""
|
|
25
|
+
start_time = time.time()
|
|
26
|
+
while time.time() - start_time < timeout:
|
|
27
|
+
try:
|
|
28
|
+
with socket.create_connection(('localhost', port), timeout=1):
|
|
29
|
+
return True
|
|
30
|
+
except (socket.error, ConnectionRefusedError):
|
|
31
|
+
time.sleep(0.5)
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main():
|
|
36
|
+
parser = argparse.ArgumentParser(description='Run command with one or more servers')
|
|
37
|
+
parser.add_argument('--server', action='append', dest='servers', required=True, help='Server command (can be repeated)')
|
|
38
|
+
parser.add_argument('--port', action='append', dest='ports', type=int, required=True, help='Port for each server (must match --server count)')
|
|
39
|
+
parser.add_argument('--timeout', type=int, default=30, help='Timeout in seconds per server (default: 30)')
|
|
40
|
+
parser.add_argument('command', nargs=argparse.REMAINDER, help='Command to run after server(s) ready')
|
|
41
|
+
|
|
42
|
+
args = parser.parse_args()
|
|
43
|
+
|
|
44
|
+
# Remove the '--' separator if present
|
|
45
|
+
if args.command and args.command[0] == '--':
|
|
46
|
+
args.command = args.command[1:]
|
|
47
|
+
|
|
48
|
+
if not args.command:
|
|
49
|
+
print("Error: No command specified to run")
|
|
50
|
+
sys.exit(1)
|
|
51
|
+
|
|
52
|
+
# Parse server configurations
|
|
53
|
+
if len(args.servers) != len(args.ports):
|
|
54
|
+
print("Error: Number of --server and --port arguments must match")
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
servers = []
|
|
58
|
+
for cmd, port in zip(args.servers, args.ports):
|
|
59
|
+
servers.append({'cmd': cmd, 'port': port})
|
|
60
|
+
|
|
61
|
+
server_processes = []
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
# Start all servers
|
|
65
|
+
for i, server in enumerate(servers):
|
|
66
|
+
print(f"Starting server {i+1}/{len(servers)}: {server['cmd']}")
|
|
67
|
+
|
|
68
|
+
# Use shell=True to support commands with cd and &&
|
|
69
|
+
process = subprocess.Popen(
|
|
70
|
+
server['cmd'],
|
|
71
|
+
shell=True,
|
|
72
|
+
stdout=subprocess.PIPE,
|
|
73
|
+
stderr=subprocess.PIPE
|
|
74
|
+
)
|
|
75
|
+
server_processes.append(process)
|
|
76
|
+
|
|
77
|
+
# Wait for this server to be ready
|
|
78
|
+
print(f"Waiting for server on port {server['port']}...")
|
|
79
|
+
if not is_server_ready(server['port'], timeout=args.timeout):
|
|
80
|
+
raise RuntimeError(f"Server failed to start on port {server['port']} within {args.timeout}s")
|
|
81
|
+
|
|
82
|
+
print(f"Server ready on port {server['port']}")
|
|
83
|
+
|
|
84
|
+
print(f"\nAll {len(servers)} server(s) ready")
|
|
85
|
+
|
|
86
|
+
# Run the command
|
|
87
|
+
print(f"Running: {' '.join(args.command)}\n")
|
|
88
|
+
result = subprocess.run(args.command)
|
|
89
|
+
sys.exit(result.returncode)
|
|
90
|
+
|
|
91
|
+
finally:
|
|
92
|
+
# Clean up all servers
|
|
93
|
+
print(f"\nStopping {len(server_processes)} server(s)...")
|
|
94
|
+
for i, process in enumerate(server_processes):
|
|
95
|
+
try:
|
|
96
|
+
process.terminate()
|
|
97
|
+
process.wait(timeout=5)
|
|
98
|
+
except subprocess.TimeoutExpired:
|
|
99
|
+
process.kill()
|
|
100
|
+
process.wait()
|
|
101
|
+
print(f"Server {i+1} stopped")
|
|
102
|
+
print("All servers stopped")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == '__main__':
|
|
106
|
+
main()
|