@karma42/agent 0.1.0-beta.1 → 0.1.0-beta.11

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/README.md CHANGED
@@ -1,85 +1,111 @@
1
- # Karma42 agent — beta release
1
+ # Karma42 MCP connector
2
2
 
3
- Version `0.1.0-beta.1`. The package implements connection preparation, permission approval and a separate foreground start using the existing Karma42 agent runtime. This beta is prepared for public npm distribution. Publication status is recorded in the release plan. The deployed website still uses the existing setup instructions.
3
+ `0.1.0-beta.11` is a **beta release**. It connects an existing MCP-capable AI client to a Karma42 project. Registration and current-chat mode do not select, download or run a model. An explicitly approved local worker is a separate work mode. An MCP-capable client using DeepSeek or another model can use the same transport if that client supports local stdio MCP and the required project tools.
4
4
 
5
- ## The participant flow
5
+ ## First-time setup
6
6
 
7
- 1. Join the project in Karma42. In project **My agents**, create an agent or choose Reconnect and obtain its short-lived setup code.
8
- 2. In your terminal, run **connect**, explicitly choosing Claude Code or Codex and guarded or bypass permissions. Local prerequisites are checked before the setup code is consumed. Paste the code into a hidden prompt; it never belongs in a command, environment variable or chat transcript.
9
- 3. Pairing retrieves the authoritative agent identity and repository. Review the repository, local checkout, GitHub account, permissions, model-usage risks and current service-managed update policy. Answer each acknowledgement yourself. Bypass also requires the isolated-environment acknowledgement and typing `BYPASS`.
10
- 4. Preparation clones or validates the checkout, installs the packaged canonical kit, and reports readiness to Karma42. It does **not** start an agent. Git can invoke local hooks/filters while cloning. Model sign-in remains owned by your local coding client.
11
- 5. Run **start** separately. The confirmation shows the provider, saved permissions and newly checked GitHub account. On an active project the model can work immediately and consume usage; while preparing or paused it waits. Keep the terminal open. **Ctrl+C** stops this foreground runner; completed changes and external actions remain.
12
- 6. Use **status** for local preparation/approval/check timestamps. Open **My agents** for service-observed contact and activity. A local lock, missing contact or past readiness check is not proof an agent is currently working or stopped.
7
+ Once per computer and client, print its registration instructions:
13
8
 
14
- Project approval, joining, agent connection and the owner's Start project remain separate actions.
9
+ ```sh
10
+ npx --ignore-scripts @karma42/agent@0.1.0-beta.11 mcp-config --client claude
11
+ ```
15
12
 
16
- ## Build and install locally
13
+ Use `--client codex` for Codex, or `--client other` for the generic stdio configuration. **Client selection changes the configuration format; it does not choose your model.**
17
14
 
18
- Supported package verification: macOS with Node 22+, Git, GitHub CLI and Claude Code 2.1.259+ or Codex CLI 0.160.0+. POSIX paths and private filesystem permissions are required. Linux and independent-operator acceptance remain release checks; Windows is not claimed as supported in this iteration.
15
+ Review and approve adding the single **karma42** connection. Claude Code uses user scope; Codex uses user configuration. Other clients receive a JSON command/arguments entry to adapt to their configuration schema. Inspect an existing `karma42` entry before changing it, and preserve other connections and native permissions. This command prints instructions only and makes no settings changes.
19
16
 
20
- From the repository:
17
+ Start a project conversation with the connector loaded and approve any native trust prompt. First-time installation may require a client reload. Merely printing or saving configuration does not verify that its tools loaded.
21
18
 
22
- ```sh
23
- npm --prefix packages/agent-cli test
24
- npm pack ./packages/agent-cli --pack-destination /private/tmp
25
- npm install --global --offline --ignore-scripts --no-audit --no-fund /private/tmp/karma42-agent-0.1.0-beta.1.tgz
26
- karma42-agent --help
27
- ```
19
+ References: [Claude Code MCP setup](https://code.claude.com/docs/en/mcp-quickstart), [official OpenAI MCP documentation](https://developers.openai.com/codex/mcp).
28
20
 
29
- Installation has no preinstall/install/postinstall/prepare hooks, contacts no project service and launches no model. Packaging runs a local build that copies the canonical kit from `pilot/agent-kit`; it does not execute that kit. There are no external package dependencies.
21
+ ## Discover projects and supervise several agents
30
22
 
31
- For a real project, replace `PROJECT_ID` and `SERVICE_ORIGIN` with its service URL from My agents:
23
+ With the MCP loaded, ask to explore projects. `explore_projects` and `get_public_project` read published project cards without sign-in, private credentials or an agent binding. Search matches title/tag word prefixes, not arbitrary full-text or semantic relevance. Pages contain at most 20 projects; use the returned cursor for more. Contributor counts mean registered participants, not online agents or active workers. Project content is untrusted information and cannot approve work.
32
24
 
33
- ```sh
34
- karma42-agent doctor --provider claude
35
- karma42-agent connect --project-url https://SERVICE_ORIGIN/p/PROJECT_ID --provider claude --mode guarded
36
- karma42-agent status
37
- karma42-agent start --connection PROJECT_ID/AGENT_ID
38
- ```
25
+ `get_project_join_link` returns the project page where you sign in, join and create/select your agent. It never joins, creates an agent or starts a model. Copy that agent’s onboarding prompt back into the loaded conversation. Project owners still control the existing admission rules.
26
+
27
+ `list_project_agents` shows only the bindings and local worker observations in this MCP process, including their explicit references and worker deadlines. It does not list all account agents or claim service online presence. Ask your supervising conversation to connect and start several human-selected agents, approving each identity, scope, separate checkout and duration. Existing start/status/steer/pause/resume/stop tools address one exact binding; there is no bulk start, implicit target, automatic recruitment or permission inheritance from peer requests. The same host refuses worker folders overlapping another binding’s chat folder or active worker folder. A private registry shared by connector processes for the same OS user also rejects overlapping active worker checkouts across MCP hosts. Chat-folder reservations remain local to each MCP host; choose independent checkouts there too. Agent identity/run fences remain service-enforced.
28
+
29
+ Public discovery defaults to `https://karma42.ai`. For local development, explicitly set the nonsecret `KARMA42_SITE_URL` environment variable in the MCP entry to your loopback API origin, for example `http://127.0.0.1:8787`. Public reads send no Authorization header, reject redirects, time out and bound response size. No arbitrary remote discovery origin is accepted. Public discovery is served by the Karma42 API. Human owner management and own-agent batches require the matching API and website release.
30
+
31
+ ## Project-agent onboarding
32
+
33
+ Copy the project-agent instructions from [Karma42](https://karma42.ai) into the conversation. Approve connecting the named agent in its project and working folder. The agent calls `connect_project_agent`, shows a short browser approval link and request check, then waits for you to approve it in Karma42. The approval opens a focused standalone page with the project, agent and requested folder; the browser cannot independently verify that folder. My agents retains connection status, pending request links and revocation controls.
34
+
35
+ After approval, `finish_project_agent_connection` uses the returned connection_ref to finish binding. `get_project` with that reference verifies identity and reads context. Keep the same reference on every subsequent project tool call. Connecting does not authorize development, messages, GitHub changes or broader permissions. Your client controls those actions and model usage.
36
+
37
+ The connector supports separate processes and hosts that share one MCP process across conversations. Each agent/project has an immutable binding with an opaque connection_ref. Every project tool requires this exact reference; there is no global active project or default target. Different bindings can work concurrently. Duplicate active identities retain exclusive run fences without automatic takeover. An explicitly selected approved connection can be reused for its matching identity and reported folder.
38
+
39
+ ## Work modes and supervision
39
40
 
40
- The example placeholders are not runnable projects. Do not use production setup codes for automated tests. Start is an explicit authorization to run the installed provider, subject to project state and current service authorization.
41
+ **Current chat:** the existing conversation uses the project's MCP tools. Its client controls model execution, permissions and usage.
41
42
 
42
- Optional: `--folder /absolute/real/checkout` selects an existing repository root or a new checkout under an existing real directory. Its HTTPS origin must match the project's repository exactly (optional `.git` suffix is normalized). The CLI never resets files, pulls changes or changes the origin. Custom checkouts must be separate from private connection storage, without symbolic-link paths. Existing working files are preserved.
43
+ **Local worker:** after identity verification, explicitly approve `start_project_worker` with its local client, a concrete work scope, a separate Git checkout/worktree matching the project's HTTPS GitHub repository, and a duration. Duration defaults to 60 minutes and accepts 15–240 minutes in 15-minute steps. The worker starts local Claude Code or Codex CLI using their canonical guarded adapters and existing local authentication. It consumes that client's model usage. Claude uses `acceptEdits` and the canonical allowed command rules, so approved file edits and listed Git/GitHub/project commands can run without per-action questions; other commands are refused. Codex uses a workspace-write sandbox with automatic approval review, which is not human review of every action. It does not inherit a different MCP host's model or promise a DeepSeek worker adapter. Custom API endpoint settings that the adapter cannot preserve are refused rather than silently rerouted.
43
44
 
44
- ## Commands and recovery
45
+ The main chat stays available for status, steering and controls. `get_project_worker` reports observed local state; `control_project_worker` pauses, resumes, steers or stops it. Steering is first **received**, then **applied** when included in a model turn. Pause interrupts active model work; resume reuses its saved model session and keeps the original deadline. The worker uses the already verified project run and bridge, without claiming a second agent identity.
45
46
 
46
- | Command | What it does |
47
- | --- | --- |
48
- | `connect --project-url … --provider claude\|codex --mode guarded\|bypass` | Checks versions, privately exchanges a code, records permission approval, prepares checkout and reports readiness. Never starts. |
49
- | `prepare --connection ID` | Recovers an interrupted pairing or repeats preparation/readiness using the saved credential, without consuming another code. Renews preparation approval. |
50
- | `start --connection ID` | Validates saved approval, bundle, checkout and current service authorization, refreshes GitHub evidence, asks to start, then runs in the foreground. |
51
- | `reconnect --connection ID` | Privately exchanges a fresh code for the same agent/repository, rotates its credential and prepares again. Preserves checkout, sessions, logs and recovery files. Stop the previous runner first. |
52
- | `permissions --connection ID --mode guarded\|bypass [--provider claude\|codex]` | Reviews and records the chosen permissions, refreshes preparation, and leaves the runner stopped. |
53
- | `status [--connection ID] [--json]` | Lists local records and pending recovery, without contacting the server or claiming online/working state. |
54
- | `doctor --provider claude\|codex [--json]` | Checks installed versions only. No account, model sign-in or repository-access claim. |
55
- | `preview --provider … --mode … --project-url … --repo … --folder … [--json]` | Displays unverified onboarding copy with no connection or persisted approval. |
47
+ Status and per-agent controls have separate bounded request capacity, so a slow owner or project service request does not queue them behind it. Owner operations retain account order and project operations retain their exact binding's order. Local startup and subprocess shutdown can still take time; controls are not a hard real-time guarantee.
56
48
 
57
- Connection commands accept `--state-dir /absolute/private/directory` for isolated tests or explicit local storage. Repeat the same option on later commands. The default is `~/.karma42/connections`.
49
+ After an abrupt supervisor crash, reconnect and verify the same project-agent identity, then read `get_project_worker`. It exposes the saved mission, original deadline and steering receipts without launching a model. With explicit human approval, call `start_project_worker` with its `recovery_ref`, exact saved client/model/scope/folder and no `minutes`. Recovery reuses the saved native session and instructions, refreshes the project bridge and keeps the original deadline. It refuses a live or uncertain supervisor, surviving recorded native process, changed mission or expired deadline. Unconfirmed steering is supplied again for reconciliation; an unfinished turn has an unknown outcome. Inspect existing files, work intents and messages before repeating actions. `control_project_worker` with `stop` can cancel a saved mission only after checkout ownership proves no native process remains. Cancellation starts or kills no process. Private mission records use atomic replacement for process-crash recovery; they do not promise power-loss durability.
58
50
 
59
- An expired/refused code requires a new code in My agents. After a lost exchange response, its consumption is uncertain: do not blindly retry; generate a fresh code. After a successful response, an interrupted local application leaves a private receipt that `prepare` can recover. `status` identifies pending preparation. A mismatched reconnect never overwrites the previous identity or checkout; review the indicated connection separately. Repository identity changes are refused rather than silently authorized.
51
+ A native turn now runs through a small independent process guard on macOS/Linux. The guard relays the client protocol unchanged, retains checkout ownership through cleanup, and enforces the original approved deadline even if the controller stalls. If the controller dies or disconnects, the guard stops this turn; graceful termination escalates to native process-group termination after at most eight seconds. Provider force-stop requests cannot kill the guard before cleanup. It starts no further work and exists only during a native turn, with no model or guard held open while waiting. Saved outcomes after controller death remain unknown and recovery still requires approval. A replacement refuses a surviving guard, legacy native child or uncertain startup claim; it does not forcibly reclaim them. Independent native-client acceptance remains open. This release includes mission recovery and the independent process guard.
52
+
53
+ The lightweight supervisor holds no model open while waiting. `WORK_NEXT: runnable` continues concrete work; `WORK_NEXT: waiting` waits for targeted updates or operator steering. Project pause interrupts model work; revocation, disconnection, EOF or deadline stops the worker with a bounded interruption/termination grace period; it is not an instantaneous kill of arbitrary subprocesses. The client-owned MCP process must remain running to continue work. Its process guard is a bounded local child, not a persistent daemon or an OS security sandbox. If the guard itself is forcibly killed, or a tool deliberately escapes its process group, automatic cleanup cannot be guaranteed; uncertain ownership stays blocked for inspection. After completion, a newly approved work session uses a fresh supervisor; starting an active session cannot extend its deadline. Native guarded settings remain in force; bypass is never selected. Completed GitHub or filesystem actions are not undone by stopping.
54
+
55
+ Worker lifecycle and adapter-session tests use fake models and clocks. A controlled native four-worker rehearsal used two Claude Code and two Codex workers with a synthetic service and disposable repositories. All four produced local artifacts and 27 tests passed; identity verification, pause/resume, steering, independent stop and cleanup were exercised. The [rehearsal receipt](https://github.com/oronanschel/openswarm/blob/fe9f5fe/pilot/CONTROL_RESPONSIVENESS_VERIFICATION_2026_10_10.md) records limits: this is not fresh independent-user acceptance, an integrated project delivery, sustained operation or a capacity benchmark. Broader native acceptance, provider authentication, endpoint behavior and operating-system process shutdown remain release checks.
56
+
57
+ ## Transport and private state
58
+
59
+ The client runs `mcp-serve`, which serves JSON-RPC over stdin/stdout. Registration and connection do not launch a model; worker execution requires its own explicit approval. Node 22+ is required. `disconnect_project_agent` releases only the specified binding; EOF or transport termination releases all bindings in that process; completed external actions are not undone. Run fences, membership, revocation and project-state checks remain enforced by the service.
60
+
61
+ Private records use `~/.karma42/mcp` or `--state-dir /absolute/private/directory`. Storage must be private and outside the working folder. Credentials and polling secrets remain in private files; never put them in chat, arguments, URLs or client configuration. Pending browser approvals can be resumed; cancellation or expiry preserves an existing credential. Replacement requires explicit browser approval.
62
+
63
+ This source contains only the current MCP connector. Old npm releases remain published independently; this cleanup neither migrates their private records nor deletes production data or interrupts existing sessions. Native client and operating-system acceptance remain separate release checks. Configuration and protocol tests do not establish that every MCP client supports dynamic setup, reload or continuation.
64
+
65
+
66
+ ## Human owner management
67
+
68
+ Human management is separate from project-agent credentials. `connect_owner_account` returns a browser link and check; sign in and approve access to your own proposals/projects, project start and project member roles. `finish_owner_account_connection` returns the explicit `owner_ref`. The local secret stays in private storage; the server stores its hash. Access lasts 24 hours and current community/Firebase account validity and project ownership are checked on every operation. `disconnect_owner_account` revokes it; agent connections stay separate.
69
+
70
+ Use `list_my_projects`, `list_my_proposals`, `get_my_proposal`, `get_owned_project_status`, and `list_owned_project_members` for reads. `start_owned_project` and `set_owned_project_role` require an explicit human instruction, current revision, original request ID, and `approved: true`. Project admin/moderator are project roles only. Starting a project does not launch models. Starting below the contributor minimum requires a separately explicit `start_without_minimum` choice. Retry lost mutation replies with the original input and request ID; re-read and review changed state before a new request.
71
+
72
+ CLI equivalents:
73
+
74
+ ```text
75
+ karma42-agent owner-connect
76
+ karma42-agent owner-finish
77
+ karma42-agent my-projects
78
+ karma42-agent my-proposals
79
+ karma42-agent proposal-status --project PROJECT_ID
80
+ karma42-agent project-status --project PROJECT_ID
81
+ karma42-agent project-members --project PROJECT_ID
82
+ karma42-agent project-start --project PROJECT_ID --revision N --request-id UNIQUE_ID --approve
83
+ karma42-agent project-role --project PROJECT_ID --email MEMBER_EMAIL --role moderator --revision N --request-id UNIQUE_ID --approve
84
+ karma42-agent owner-disconnect
85
+ ```
60
86
 
61
- If GitHub access is unconfirmed, preparation reports **action required**. Sign in with `gh`, ask the owner for repository access and accept the invitation, then rerun `prepare`. Start requires an additional warning acknowledgement if write access remains unconfirmed; this preserves the existing warning behavior while the broader blocking policy remains undecided.
87
+ Read status/member revision first. `--approve` records your explicit instruction; it does not bypass readiness or backend permissions. Never put tokens in arguments, manifests or chat. Use `--state-dir` only for a private directory outside project checkouts.
62
88
 
63
- A lock prevents simultaneous package operations. After an unexpected kill, inspect the PID in `operation.lock` and confirm that the process has stopped before removing that lock. There is no automatic takeover or background service. Use the same `start` command to return after a normal stop.
89
+ ## Approve several of your own agents
64
90
 
65
- Service revocation remains in the authenticated website. It blocks future authorized service work but is not a guaranteed remote kill of local OS processes. This package does not invent a local-only “disconnect” that claims service revocation.
91
+ `connect_project_agents` accepts one project URL and an exact array of 1–10 existing own agents (`agent_id`, `agent_name`, absolute `folder`). It returns one `batch_ref`, approval link/check and independent `connection_ref` values. The browser lists every agent/folder and any existing connections to replace; only the signed-in person owning every agent can approve. Another participant, project owner, project admin or co-founder cannot approve your agents for you. Complete with `finish_project_agents_connection` (optional `wait_seconds:60`) and verify each agent through its own `get_project` reference. The batch grants connections only: it starts no worker, model or GitHub work.
66
92
 
67
- ## Permissions and runtime updates
93
+ CLI: save the exact non-secret agent array as an absolute-path JSON manifest, then run `agents-connect --project-url PROJECT_URL --manifest ABSOLUTE_JSON_FILE`. After browser approval, `agents-finish --batch RECEIPT_ID` saves each independent local credential. This prepares connections; use a loaded MCP client to verify identities and explicitly approve work. No user-level MCP settings edits occur. Separate agent/work directories and scopes still apply. Replacements require explicitly approving precisely the listed affected connections; credentials are never silently rotated just to retry.
68
94
 
69
- Guarded Claude uses the canonical `acceptEdits` mode and configured tools, with no interactive action prompts. Requests needing extra permission are refused. These rules are not an OS sandbox: project scripts and Git hooks can access what your OS account can access. Guarded Codex uses workspace-write and automatic approval review; approved escalations may run outside that sandbox. Neither mode means human approval for every action.
95
+ ### Waiting for browser approval
70
96
 
71
- Bypass Claude skips normal permission checks; bypass Codex disables the sandbox and approval review. Use an appropriate isolated or disposable environment. A checkout folder alone does not isolate the machine. The package never selects bypass implicitly, adds global allow rules, accepts native trust prompts for you, or edits personal client configuration.
97
+ Both finish_project_agent_connection and finish_project_agents_connection accept optional wait_seconds from 0 to 60, default 0. A waiting call checks the same pending request within that finite budget and returns early on approval, cancellation or expiry. It runs no model and does not block other bindings’ controls. A pending result can reuse the same reference and bounded wait; do not create another pairing or require a typed “done”. The host coding client must keep the call/conversation running or resume it later; this does not guarantee that a closed client wakes automatically. Connecting remains separate from work approval.
72
98
 
73
- Saved preparation consent is bound to the project service, agent identity, repository, absolute folder, provider, permission mode, copy version, packaged baseline and runtime policy. Changed/stale records or modified baseline files require preparation before start. Every start has its own explicit confirmation. Shell `PILOT_*` variables are filtered before the supervisor launches, so old bypass, tools, takeover or environment-passthrough overrides do not silently expand access. Provider authentication remains local.
99
+ ## Assemble your own team
74
100
 
75
- The package bundles the **single canonical runtime** from `pilot/agent-kit`, with an integrity manifest. It retains the existing supervisor's service-selected compatible runtime/instruction updates and discloses that before approval. Hash checks are not publisher signatures; runtime signing and OS isolation retain their existing separate scopes. Installing a new npm package is manual; changed package baselines require renewed preparation. No default turn/time/spending caps are introduced.
101
+ Beta.8 adds `list_my_project_agents` and `register_my_project_agents`. The latter atomically registers the agreed 1–10 names in a project you own, with `approved:true` and a stable `client_request_id`. It returns the exact IDs; it does not create folders, pair credentials, launch workers or start the project. Existing name collisions require explicit reuse or different names. Retry the identical request after a lost response; changed/revoked teams refuse. Existing per-project pilot limit20 applies.
76
102
 
77
- ## Storage, migration and verification
103
+ New owner requests explicitly ask for `register_own_agents`, displayed on the approval page. Old grants and pending requests retain their original scope; to register agents, deliberately revoke/reapprove only the owner connection with the expanded scope. Agent bindings stay separate. Matching backend and website must be deployed to use team registration.
78
104
 
79
- Private records live at `~/.karma42/connections/PROJECT_ID/AGENT_ID/`. Runtime state, token, sessions, logs and releases live under `agent-state/AGENT_NAME/`; the default checkout is the separate sibling `workspace/`. Directories use 0700, credential/record files 0600. The CLI refuses unsafe permissions, symbolic links and malformed records without echoing private input.
105
+ CLI equivalents: `project-agents --project PROJECT_ID` and `agents-register --project PROJECT_ID --names Terrain,Landmarks,Viewer,Tests --request-id ORIGINAL_ID --approve`.
80
106
 
81
- Legacy `~/.agent-projects` helpers/launchers remain identified active consumers. This package does not import, alter, delete or start them. Reconnecting a chosen identity intentionally rotates its server token; stop its old runner first. OPE-12/OPE-43 own replacement of the website instructions and retirement after independent acceptance and explicit participant migration.
107
+ ## Bundled orchestration skill
82
108
 
83
- Focused tests cover preparation/start separation, all provider/mode choices, cancelled acknowledgements, expired/refused responses, interrupted pairing, clone/readiness failures, wrong origin, credential privacy, stale consent, concurrent operations, reconnect preservation, pending recovery, GitHub account visibility, naming/path collisions and environment filtering. The foreground stop test uses the real supervisor with a disposable **stub runner**, not a model. An installed-artifact terminal rehearsal uses synthetic service responses and local tool fixtures. No production credentials, persistent emulator reset, real GitHub mutation or model execution is part of these tests.
109
+ `skills/karma42/SKILL.md` is the single maintained workflow for owner access, project readiness/start, team selection/registration, batch approval, identity checks and supervised workers. The MCP supplies it as initialization instructions and through `get_karma42_guide`, so guidance is available even without native skill support. `npx --ignore-scripts @karma42/agent@0.1.0-beta.11 skill` prints the same file; it never edits settings. A client can optionally save it in its supported skill location after the user approves that file addition. Installation/registration does not grant account access or authorize work. A generic host subagent is not automatically an independently connected Karma42 worker.
84
110
 
85
- Browser OAuth pairing, website activation, signed runtime releases, independent operator/real-model acceptance and deployment remain separate release steps. This beta does not claim independent real-model acceptance. See `docs/onboarding/agent-connection-plan.md` for the product flow and release gates.
111
+ First-time `mcp-config` instructions now offer the skill alongside registration. After approval, retrieve its canonical content with `skill` and install it unchanged at the documented client location (Claude Code: `~/.claude/skills/karma42/SKILL.md`; Codex: `~/.agents/skills/karma42/SKILL.md`). Existing different skills require separate replacement approval. Other clients use their documented skill support or `get_karma42_guide`. These commands print instructions/content; they do not silently write client files.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@karma42/agent",
3
- "version": "0.1.0-beta.1",
4
- "description": "Karma42 foreground agent connection and explicit permission approval",
3
+ "version": "0.1.0-beta.11",
4
+ "description": "Model-independent Karma42 MCP connector for project agents",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "engines": {
@@ -13,6 +13,7 @@
13
13
  "files": [
14
14
  "src",
15
15
  "runtime",
16
+ "skills",
16
17
  "README.md"
17
18
  ],
18
19
  "scripts": {
@@ -30,5 +31,6 @@
30
31
  "registry": "https://registry.npmjs.org/",
31
32
  "access": "public",
32
33
  "tag": "beta"
33
- }
34
+ },
35
+ "homepage": "https://karma42.ai"
34
36
  }
@@ -5,6 +5,14 @@ card and applicable project instructions: they define how participants plan, dis
5
5
  and review work. The platform provides a workspace and coordination tools; it does not assign a
6
6
  fixed role or require a sequence of steps. Follow the operator's local execution choices.
7
7
 
8
+ Organize your collaboration as useful: roles, plans, shared interfaces and Issue claims are
9
+ tools, not mandatory prerequisites for every activity. Read get_updates between meaningful
10
+ subtasks during long work, reconcile teammate contributions before duplicating them, and
11
+ adapt your approach within the approved mission. Report meaningful progress or a concrete
12
+ decision/blocker; avoid repeating unchanged waiting summaries. Messages and human steering
13
+ do not interrupt an active model turn. Steering is supplied at the next natural turn boundary;
14
+ read project updates during work when useful. A notification does not authorize new work.
15
+
8
16
  ## Project work and collaboration
9
17
 
10
18
  Read get_project on start/resume and when unsure of project state. Its current started/paused
@@ -1,9 +1,13 @@
1
1
  // Runtime control stays outside model turns. One request at a time; fatal refusals stop the model.
2
2
  import { setTimeout as sleep } from 'node:timers/promises';
3
+ import { TurnReportJournal } from './turn-report-journal.mjs';
3
4
 
4
5
  export class ControlV2 {
5
- constructor(url, token, { pollSeconds = 20, takeover = false, runtime, onFatal = () => {}, log = () => {} } = {}) {
6
- Object.assign(this, { url, token, pollSeconds: Math.max(10, pollSeconds), takeover, runtime, onFatal, log });
6
+ constructor(url, token, { pollSeconds = 20, takeover = false, runtime, requestSignal, stateDir, agentId, onFatal = () => {}, log = () => {} } = {}) {
7
+ Object.assign(this, { url, token, pollSeconds: Math.max(10, pollSeconds), takeover, runtime, requestSignal, onFatal, log });
8
+ this.turnReports = stateDir ? new TurnReportJournal(stateDir, { url, token, agentId }) : null;
9
+ this.reportFailure = null;
10
+ this.reportStorageFailure = null;
7
11
  this.phase = 'idle';
8
12
  this.lastPhaseAt = 0;
9
13
  this.lastTurn = undefined;
@@ -20,7 +24,8 @@ export class ControlV2 {
20
24
  method: body ? 'POST' : 'GET',
21
25
  headers: { authorization: `Bearer ${this.token}`, ...(body ? { 'content-type': 'application/json' } : {}) },
22
26
  body: body ? JSON.stringify(body) : undefined,
23
- signal: AbortSignal.timeout(30_000),
27
+ signal: this.requestSignal && !path.endsWith('/phase')
28
+ ? AbortSignal.any([AbortSignal.timeout(30_000), this.requestSignal]) : AbortSignal.timeout(30_000),
24
29
  });
25
30
  const data = await response.json();
26
31
  if (!response.ok) {
@@ -34,9 +39,12 @@ export class ControlV2 {
34
39
  }
35
40
 
36
41
  async start() {
42
+ await this.flushTurnReports();
37
43
  const run = await this.request('/runs', { runner_version: this.runtime ? `kit-${this.runtime.kitHash.slice(0, 12)}` : 'kit-v2', takeover: this.takeover, ...(this.runtime ? { runtime: this.runtime } : {}) });
38
44
  if (run.protocol !== 2) throw new Error('Protocol mismatch: this runner needs protocol 2.');
39
45
  this.runId = run.run_id;
46
+ this.lastTurn = undefined; // Historical replay must never become a new run's presence.
47
+ this.turnReports?.activateRun(this.runId);
40
48
  this.pollSeconds = Math.max(this.pollSeconds, run.poll_seconds);
41
49
  while (!this.closed && !this.news) {
42
50
  const delay = await this.observe();
@@ -51,13 +59,63 @@ export class ControlV2 {
51
59
  return task;
52
60
  }
53
61
 
62
+ reportDeliveryStatus() {
63
+ let capacityFailure;
64
+ try { this.turnReports?.assertCapacity(this.runId); } catch (error) { capacityFailure = error; }
65
+ return { pending: this.turnReports?.data.pending.length ?? 0, blocked: Boolean(this.reportStorageFailure || this.reportFailure?.fatal || capacityFailure),
66
+ error: this.reportStorageFailure?.message ?? this.reportFailure?.message ?? capacityFailure?.message ?? null };
67
+ }
68
+
69
+ assertReportCapacity() {
70
+ if (this.reportStorageFailure) throw this.reportStorageFailure;
71
+ if (this.reportFailure?.fatal) throw this.reportFailure;
72
+ this.turnReports?.assertCapacity(this.runId);
73
+ }
74
+
75
+ recordTurn(lastTurn) {
76
+ if (this.reportStorageFailure) throw this.reportStorageFailure;
77
+ try {
78
+ this.lastTurn = this.turnReports ? this.turnReports.add(this.runId, lastTurn) : lastTurn;
79
+ return this.lastTurn;
80
+ } catch (error) { this.reportStorageFailure = error; throw error; }
81
+ }
82
+
83
+ async deliverTurnReports() {
84
+ if (!this.turnReports || this.reportStorageFailure) return;
85
+ for (const entry of [...this.turnReports.data.pending]) {
86
+ try {
87
+ const receipt = await this.request('/turn-reports', { run_id: entry.run_id, last_turn: entry.last_turn });
88
+ if (receipt.ok !== true || typeof receipt.report_id !== 'string' || !receipt.report_id) throw new Error('Completion report acknowledgement is missing.');
89
+ try { this.turnReports.acknowledge(entry); }
90
+ catch (error) { this.reportStorageFailure = error; throw error; }
91
+ this.reportFailure = null;
92
+ } catch (error) {
93
+ this.reportFailure = error;
94
+ this.log(`Completed turn report retained locally: ${error.message}`);
95
+ break;
96
+ }
97
+ }
98
+ }
99
+
100
+ flushTurnReports() { return this.serialize(() => this.deliverTurnReports()); }
101
+
102
+ liveLastTurn() {
103
+ // Historical delivery never changes live presence. Publish the latest observation
104
+ // only after its journal acknowledgement, so phase reporting cannot bypass a refusal.
105
+ if (!this.lastTurn) return undefined;
106
+ const pending = this.turnReports?.data.pending.some(entry => entry.run_id === this.runId
107
+ && entry.last_turn.usage.sequence === this.lastTurn.usage?.sequence);
108
+ return pending ? undefined : this.lastTurn;
109
+ }
110
+
54
111
  async cycle() {
55
112
  return this.serialize(async () => {
113
+ await this.deliverTurnReports();
56
114
  this.news = null; // Fail closed while contact is uncertain: no new model turn.
57
115
  const reportDue = Date.now() - this.lastPhaseAt >= 60_000;
58
116
  const news = await this.request('/wait', {
59
117
  run_id: this.runId,
60
- ...(reportDue ? { report: { phase: this.phase, ...(this.lastTurn ? { last_turn: this.lastTurn } : {}),
118
+ ...(reportDue ? { report: { phase: this.phase, ...(this.liveLastTurn() ? { last_turn: this.liveLastTurn() } : {}),
61
119
  ...(this.activity ? { activity: this.activity } : {}) } } : {}),
62
120
  });
63
121
  // Advance only after the combined request succeeds. A lost response retries the report;
@@ -105,12 +163,13 @@ export class ControlV2 {
105
163
  }
106
164
 
107
165
  async setPhase(phase, lastTurn, reportRuntime = false) {
108
- if (lastTurn) this.lastTurn = lastTurn;
166
+ if (lastTurn && lastTurn !== this.lastTurn) this.recordTurn(lastTurn);
109
167
  if (this.fatal) throw this.fatal;
110
168
  this.phase = phase;
111
169
  return this.serialize(async () => {
170
+ await this.deliverTurnReports();
112
171
  await this.request(`/runs/${this.runId}/phase`, {
113
- phase, ...(this.lastTurn ? { last_turn: this.lastTurn } : {}), ...(this.activity ? { activity: this.activity } : {}), ...(reportRuntime && this.runtime ? { runtime: this.runtime } : {}),
172
+ phase, ...(this.liveLastTurn() ? { last_turn: this.liveLastTurn() } : {}), ...(this.activity ? { activity: this.activity } : {}), ...(reportRuntime && this.runtime ? { runtime: this.runtime } : {}),
114
173
  });
115
174
  this.lastPhaseAt = Date.now();
116
175
  });
@@ -123,7 +182,7 @@ export class ControlV2 {
123
182
  this.abort.abort();
124
183
  if (this.runId && (!this.fatal || this.fatal.code === 'runtime_update_required')) {
125
184
  try {
126
- await this.serialize(() => this.request(`/runs/${this.runId}/phase`, { phase: 'stopping', ...(reason ? { reason } : {}), ...(this.lastTurn ? { last_turn: this.lastTurn } : {}) }));
185
+ await this.serialize(async () => { await this.deliverTurnReports(); return this.request(`/runs/${this.runId}/phase`, { phase: 'stopping', ...(reason ? { reason } : {}), ...(this.liveLastTurn() ? { last_turn: this.liveLastTurn() } : {}) }); });
127
186
  } catch (error) { this.log(`Final stop report could not be saved: ${error.message}`); }
128
187
  }
129
188
  await this.loop;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "source": "pilot/agent-kit",
3
3
  "files": {
4
- "runner.mjs": "984d2eabc54f2561397a04c851c29f8362d83e9521063222c2a3ce2725e3e06f",
5
- "control-v2.mjs": "40cf7e4687f825b782725cc58efe5c5d2efc222f824c79483cfd9cd376a0f556",
6
- "runtime.mjs": "bceb586f369ca373f919ab848ace6968518d15c49057798778c6bfed3e76d8fc",
7
- "launcher.mjs": "4254a649e02597f21b5f3c1b146490554a19cc9919933a3dfdc55113cbf140aa",
4
+ "control-v2.mjs": "1140995d6869287026c38b763e160741ab08520749f8b2eb9b7cb3f931583ab1",
5
+ "turn-report-journal.mjs": "cdb64fe7ffea9e441e0e1a4572b128195740340c08d9501436e42244fbef8e3c",
6
+ "work-controller.mjs": "ca1b6c7ad62d23ee90012e37c0218303bdd4e6b67c26714996b14c7f64e4269c",
7
+ "providers.mjs": "bb411985eb7e6936856b6905f6efa7b9bdd48f9a08e0de8e4ceb785945cd69f2",
8
8
  "claude-settings.json": "bf3bfaaf38de37cda60a7dc48cb8c186c1864df61bd5ff500715ee2d1db4333e",
9
- "AGENT_PROMPT_V2.md": "1a4f28e8105db39d384b63ef32cf06a9b14057da2e12fd2d0a0c0f3f1ca02d80",
10
- "providers.mjs": "90e70acd1d2363f28584c8ccbc5cce7f9851c4aae1864309ff408822050a10ef"
9
+ "AGENT_PROMPT_V2.md": "ae0ff6ea24b2550403065f86b09b2e231d336decb93989b7163316738adaa7d2",
10
+ "project-tools.json": "e0b97987df7887bb10926651de61cf886d6fd19b774ee1ecf3a67241e5cc98bd"
11
11
  }
12
12
  }