@rho-workspace/rho 0.5.5 → 0.5.6
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/dist/agent-connect.d.ts +8 -0
- package/dist/agent-connect.js +15 -0
- package/dist/browser-access.js +1 -1
- package/dist/cli.js +38 -8
- package/dist/contract.generated.d.ts +148 -5
- package/dist/contract.generated.js +1 -1
- package/dist/contracts/owners.generated.js +107 -12
- package/dist/conversations.d.ts +157 -4
- package/dist/conversations.js +69 -6
- package/dist/discovery.js +1 -1
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.js +12 -5
- package/dist/server.d.ts +2 -10
- package/dist/server.js +71 -8
- package/dist/web/.vite/manifest.json +61 -61
- package/dist/web/assets/{choices-b0XhrGQV.js → choices-D-YfnFP6.js} +1 -1
- package/dist/web/assets/{console-BSjLGe0T.js → console-Trqc0swD.js} +1 -1
- package/dist/web/assets/{dist-Buk0lwzI.js → dist-DZmszrjG.js} +1 -1
- package/dist/web/assets/{dist-Cw8hRIlT.js → dist-DpIHRk3B.js} +1 -1
- package/dist/web/assets/{dist-foH9IKc6.js → dist-eMx6b8N1.js} +1 -1
- package/dist/web/assets/{dist-Tzoe_zm-.js → dist-pF902jHA.js} +1 -1
- package/dist/web/assets/{explore-in-BVUy3ZW_.js → explore-in-BCHqjJ7B.js} +1 -1
- package/dist/web/assets/{graph-1OdIJ9l7.js → graph-lENgfQNH.js} +1 -1
- package/dist/web/assets/index-B3_OVy91.css +1 -0
- package/dist/web/assets/{index-CxmItXqa.js → index-BpL_Kl_s.js} +84 -83
- package/dist/web/assets/{notes-meaning-pVbbQUGP.js → notes-meaning-DcVGUBBY.js} +1 -1
- package/dist/web/assets/{overview-B9UtVJ32.js → overview-CDnVKlOt.js} +3 -3
- package/dist/web/assets/{preview-CksD_5KS.js → preview-BEC1E9MK.js} +1 -1
- package/dist/web/assets/{review-CMxQlQ-C.js → review-DYP0aCXb.js} +1 -1
- package/dist/web/assets/{skills-BFNSyrnD.js → skills-1ec0Z-jx.js} +1 -1
- package/dist/web/assets/{skills-work-BGPSnF_I.js → skills-work-DNexV4OJ.js} +1 -1
- package/dist/web/assets/{studio-process-CsRoTHOh.js → studio-process-EYQgikxq.js} +1 -1
- package/dist/web/assets/{timeline-events-BbuuFWHV.js → timeline-events-Chj2Gbx7.js} +1 -1
- package/dist/web/assets/{work-turns-BvJlIMmA.js → work-turns-CT9RVcWY.js} +1 -1
- package/dist/web/assets/{workspace-CWlkjLNx.js → workspace-COmCbGV3.js} +1 -1
- package/dist/web/composition.json +58 -58
- package/dist/web/index.html +2 -2
- package/dist/web/renderer.json +1 -1
- package/docs/FRONTEND.md +26 -18
- package/docs/HEADLESS.md +37 -27
- package/node_modules/@rho-workspace/plugin-agent/README.md +29 -0
- package/node_modules/@rho-workspace/plugin-agent/dist/acp-command.d.ts +1 -0
- package/node_modules/@rho-workspace/plugin-agent/dist/acp-command.js +9 -1
- package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.d.ts +1 -0
- package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.js +10 -0
- package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.js +10 -5
- package/node_modules/@rho-workspace/plugin-agent/dist/external-session.d.ts +12 -1
- package/node_modules/@rho-workspace/plugin-agent/dist/native-sessions.d.ts +70 -0
- package/node_modules/@rho-workspace/plugin-agent/dist/native-sessions.js +538 -0
- package/node_modules/@rho-workspace/plugin-agent/package.json +2 -1
- package/node_modules/hono/dist/adapter/aws-lambda/handler.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
- package/node_modules/hono/dist/cjs/client/fetch-result-please.js +1 -1
- package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +2 -1
- package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +5 -3
- package/node_modules/hono/dist/cjs/jsx/base.js +49 -30
- package/node_modules/hono/dist/cjs/jsx/components.js +2 -2
- package/node_modules/hono/dist/cjs/jsx/constants.js +2 -0
- package/node_modules/hono/dist/cjs/jsx/jsx-runtime.js +13 -17
- package/node_modules/hono/dist/cjs/middleware/etag/index.js +3 -1
- package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +1 -0
- package/node_modules/hono/dist/cjs/middleware/timing/timing.js +4 -3
- package/node_modules/hono/dist/cjs/utils/cookie.js +2 -2
- package/node_modules/hono/dist/cjs/utils/mime.js +1 -1
- package/node_modules/hono/dist/cjs/utils/url.js +1 -1
- package/node_modules/hono/dist/client/fetch-result-please.js +1 -1
- package/node_modules/hono/dist/helper/accepts/accepts.js +2 -1
- package/node_modules/hono/dist/helper/ssg/ssg.js +5 -3
- package/node_modules/hono/dist/jsx/base.js +49 -32
- package/node_modules/hono/dist/jsx/components.js +2 -2
- package/node_modules/hono/dist/jsx/constants.js +2 -1
- package/node_modules/hono/dist/jsx/jsx-runtime.js +15 -19
- package/node_modules/hono/dist/middleware/etag/index.js +3 -1
- package/node_modules/hono/dist/middleware/language/language.js +1 -1
- package/node_modules/hono/dist/middleware/pretty-json/index.js +1 -0
- package/node_modules/hono/dist/middleware/timing/timing.js +4 -3
- package/node_modules/hono/dist/utils/cookie.js +2 -2
- package/node_modules/hono/dist/utils/mime.js +1 -1
- package/node_modules/hono/dist/utils/url.js +1 -1
- package/node_modules/hono/package.json +1 -1
- package/package.json +2 -2
- package/protocol/index.json +39 -33
- package/protocol/operations/agent.sessions.list.json +49 -3
- package/protocol/operations/agent.sessions.read.json +53 -4
- package/protocol/operations/conversation.configure.json +29 -0
- package/protocol/operations/conversation.decide.json +29 -0
- package/protocol/operations/conversation.list.json +29 -0
- package/protocol/operations/conversation.permission.json +29 -0
- package/protocol/operations/conversation.read.json +29 -0
- package/protocol/operations/conversation.restore.json +29 -0
- package/protocol/operations/conversation.send.json +29 -0
- package/protocol/operations/conversation.settings.check.json +92 -0
- package/protocol/operations/conversation.settings.read.json +92 -0
- package/protocol/operations/conversation.settings.update.json +92 -0
- package/protocol/operations/conversation.start.json +46 -1
- package/protocol/operations/conversation.stop.json +29 -0
- package/protocol/operations/conversation.trash.json +29 -0
- package/protocol/operations/observation.snapshot.json +29 -0
- package/protocol/operations/session.instructions.json +43 -0
- package/vendor/composition.json +74 -74
- package/vendor/rho-workspace-plugin-agent-0.4.30.tgz +0 -0
- package/web/theme.css +12 -0
- package/dist/web/assets/index-CsC3sTRq.css +0 -1
- package/vendor/rho-workspace-plugin-agent-0.4.29.tgz +0 -0
|
@@ -429,3 +429,32 @@ local storage and observation work; they do not limit the native Agent.
|
|
|
429
429
|
`test/external-session.test.mjs` checks identity, prefix conflicts, omissions,
|
|
430
430
|
missing outcomes, redaction, project containment, retained failure and pagination.
|
|
431
431
|
The Rho application records its separate real Harness/browser acceptance.
|
|
432
|
+
|
|
433
|
+
### Native Claude Code and Codex sessions
|
|
434
|
+
|
|
435
|
+
Agent 0.4.30 exports `native-sessions`. `listNativeSessions(root, nativeSources(env))`
|
|
436
|
+
lists the Claude Code and Codex sessions whose recorded working folder is `root`,
|
|
437
|
+
read from the Agents' own records: `CLAUDE_CONFIG_DIR` (or `~/.claude`)
|
|
438
|
+
`/projects/<folder>/<id>.jsonl` and `CODEX_HOME` (or `~/.codex`)
|
|
439
|
+
`/sessions/**/rollout-*.jsonl`. Each summary keeps the native session ID, title,
|
|
440
|
+
times, turn counts, where it started (Claude Code's `entrypoint`, Codex's
|
|
441
|
+
`originator`), whether another process holds it now (Claude Code's live
|
|
442
|
+
`sessions/<pid>.json` with a running PID, Codex's `thread-writer-locks/<id>.lock`)
|
|
443
|
+
and the terminal resume command. `readNativeSession` streams one record into the
|
|
444
|
+
same turn shape as `readExternalSession`, with each turn's tools, results and
|
|
445
|
+
reply. Reading starts no Agent, takes no lock and writes nothing.
|
|
446
|
+
`nativeSessionLimits` names the budgets: 64 sessions per listing, 4,096 files
|
|
447
|
+
scanned per Claude Code folder and across Codex's sessions, 256 KiB read from each end of a file for a summary, at most 256 MiB
|
|
448
|
+
streamed from the end for a read, 200 turns, 256 tools per turn, and the text and
|
|
449
|
+
tool field limits above. Sidechains, injected reminders and local command output
|
|
450
|
+
are excluded. A recorded interruption is stopped. A last turn without an end record
|
|
451
|
+
is running while its file was written in the last minute; after that it is completed
|
|
452
|
+
when it has a reply and no unanswered tool, and unknown otherwise.
|
|
453
|
+
|
|
454
|
+
To continue such a session, the application passes its ID as `sessionId` (ACP
|
|
455
|
+
`session/load`). `forkFrom` instead asks the Agent for a separate copy through
|
|
456
|
+
`session/fork`; the connection is refused before sending when the Agent does not
|
|
457
|
+
advertise fork, or returns the same ID. `acpEnvironment` drops inherited Claude Code
|
|
458
|
+
session markers (`CLAUDECODE`, `CLAUDE_CODE_CHILD_SESSION` and related variables):
|
|
459
|
+
a Claude Code started under them saves no transcript, so its session could not be
|
|
460
|
+
listed or continued anywhere else.
|
|
@@ -7,6 +7,7 @@ export declare function acpCommand(agent: AcpAgent): {
|
|
|
7
7
|
* optional dependencies that an application need not install, so name the selected
|
|
8
8
|
* executable, else the one already named in the environment, else the client on PATH. */
|
|
9
9
|
export declare function acpEnvironment(agent: AcpAgent, env: NodeJS.ProcessEnv, executable?: string): NodeJS.ProcessEnv;
|
|
10
|
+
export declare function withoutSessionMarkers(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
10
11
|
/** Why the adapter could not start the person's client, or null when its executable is
|
|
11
12
|
* there. The adapters report a missing client only as a closed connection. */
|
|
12
13
|
export declare function missingClient(agent: AcpAgent, env: NodeJS.ProcessEnv): string | null;
|
|
@@ -14,7 +14,15 @@ const clientName = { claude: 'Claude Code', codex: 'Codex' };
|
|
|
14
14
|
* executable, else the one already named in the environment, else the client on PATH. */
|
|
15
15
|
export function acpEnvironment(agent, env, executable) {
|
|
16
16
|
const name = executableVariable[agent];
|
|
17
|
-
return { ...env, [name]: executable || env[name] || agent };
|
|
17
|
+
return { ...withoutSessionMarkers(env), [name]: executable || env[name] || agent };
|
|
18
|
+
}
|
|
19
|
+
// When Rho itself was started from inside a Claude Code session (an Agent ran the setup), the
|
|
20
|
+
// environment carries that session's markers. A Claude Code started with them takes itself for
|
|
21
|
+
// its child: it saves no transcript (so its session cannot be continued anywhere) and reports to
|
|
22
|
+
// the parent's socket. Rho's sessions are the person's own, so those markers are not passed on.
|
|
23
|
+
const sessionMarkers = /^(CLAUDECODE|CLAUDE_CODE_(CHILD_SESSION|ENTRYPOINT|SESSION_ID|SESSION_ATTENDED|MESSAGING_SOCKET|MESSAGING_TOKEN|EXECPATH|SSE_PORT)|CLAUDE_PID)$/;
|
|
24
|
+
export function withoutSessionMarkers(env) {
|
|
25
|
+
return Object.fromEntries(Object.entries(env).filter(([key]) => !sessionMarkers.test(key)));
|
|
18
26
|
}
|
|
19
27
|
/** Why the adapter could not start the person's client, or null when its executable is
|
|
20
28
|
* there. The adapters report a missing client only as a closed connection. */
|
|
@@ -211,6 +211,16 @@ export class AcpConversation {
|
|
|
211
211
|
throw new Error('This Agent cannot load the original session. Nothing was resent.');
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
+
else if (o.forkFrom) {
|
|
215
|
+
const caps = initialized.agentCapabilities;
|
|
216
|
+
if (!caps?.sessionCapabilities?.fork)
|
|
217
|
+
throw new Error('This Agent cannot continue a copy of a session. Nothing was sent.');
|
|
218
|
+
const forked = await connection.agent.request('session/fork', { ...params, sessionId: o.forkFrom });
|
|
219
|
+
if (typeof forked?.sessionId !== 'string' || forked.sessionId === o.forkFrom)
|
|
220
|
+
throw new Error('The Agent did not create a separate copy of the session. Nothing was sent.');
|
|
221
|
+
this.sessionId = forked.sessionId;
|
|
222
|
+
this.settings = forked.configOptions ?? [];
|
|
223
|
+
}
|
|
214
224
|
else {
|
|
215
225
|
const created = await connection.agent.request(acp.methods.agent.session.new, params);
|
|
216
226
|
this.sessionId = created.sessionId;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// A retained observation of another client's
|
|
1
|
+
// A conversation an Agent holds in its own record: a retained observation of another client's
|
|
2
|
+
// conversation, or a session the Agent keeps in its own files. Reading it starts nothing.
|
|
2
3
|
const text = { type: 'string' }, count = { type: 'integer', minimum: 0 };
|
|
3
4
|
const obj = (properties, required = Object.keys(properties)) => ({ type: 'object', properties, required, additionalProperties: false });
|
|
4
5
|
const array = (items, maxItems) => ({ type: 'array', items, maxItems });
|
|
@@ -6,10 +7,14 @@ export const externalSessionLimits = { maxSessions: 64, maxTurns: 200, maxTools:
|
|
|
6
7
|
const state = { enum: ['running', 'completed', 'failed', 'stopped', 'unknown'] };
|
|
7
8
|
export const externalResultSchema = obj({ path: text, id: text, version: text, projectId: text, toolId: text }, ['path', 'toolId']);
|
|
8
9
|
export const externalToolSchema = obj({ id: text, at: text, name: text, detail: text, output: text, outcome: { enum: ['requested', 'returned', 'failed', 'unknown'] }, exitCode: { type: 'integer' }, paths: array(text, 32) }, ['id', 'at', 'name', 'detail', 'output', 'outcome', 'paths']);
|
|
9
|
-
export const externalTurnSchema = obj({ id: text, at: text, endedAt: text, state, prompt: text, reply: text, messages: array(obj({ at: text, text }), 200), tools: array(externalToolSchema, externalSessionLimits.maxTools), results: array(externalResultSchema, 64), omittedTools: count, omittedChars: count }, ['id', 'at', 'state', 'prompt', 'reply', 'messages', 'tools', 'results', 'omittedTools', 'omittedChars']);
|
|
10
|
-
export const externalSessionSummarySchema = obj({ id: { type: 'string', pattern: '^x-[a-f0-9]{64}$' }, producer: text, sessionId: text, title: text, lastAt: text, observedAt: text, state, turns: count, sourceCursor: count, omittedTurns: count, problem: text, inputOwner: { const: 'external' }
|
|
10
|
+
export const externalTurnSchema = obj({ id: text, at: text, endedAt: text, state, prompt: text, reply: text, messages: array(obj({ at: text, text }), 200), tools: array(externalToolSchema, externalSessionLimits.maxTools), results: array(externalResultSchema, 64), omittedTools: count, omittedChars: count, where: text }, ['id', 'at', 'state', 'prompt', 'reply', 'messages', 'tools', 'results', 'omittedTools', 'omittedChars']);
|
|
11
|
+
export const externalSessionSummarySchema = obj({ id: { type: 'string', pattern: '^x-[a-f0-9]{64}$' }, producer: text, sessionId: text, title: text, lastAt: text, observedAt: text, state, turns: count, sourceCursor: count, omittedTurns: count, problem: text, inputOwner: { const: 'external' },
|
|
12
|
+
// Native sessions: where it was started, a live process holding it, the command that continues it in a terminal
|
|
13
|
+
// and its size. The application adds the Agent it continues with in Rho and the Rho conversation that continued it.
|
|
14
|
+
where: text, open: { anyOf: [{ type: 'null' }, obj({ where: text, since: text, pid: count }, ['where'])] }, resume: text, bytes: count,
|
|
15
|
+
continueWith: { enum: ['claude-acp', 'codex-acp', 'acp', null] }, conversationId: text }, ['id', 'producer', 'sessionId', 'title', 'lastAt', 'observedAt', 'state', 'turns', 'sourceCursor', 'omittedTurns']);
|
|
11
16
|
export const externalSessionSchemas = { summary: externalSessionSummarySchema, turn: externalTurnSchema };
|
|
12
17
|
export const externalSessionOperations = {
|
|
13
|
-
'agent.sessions.list': { inputSchema: obj({}), outputSchema: obj({ sessions: array(externalSessionSummarySchema,
|
|
14
|
-
'agent.sessions.read': { inputSchema: obj({ session: { type: 'string', pattern: '^x-[a-f0-9]{64}$' }, before: count, limit: { type: 'integer', minimum: 1, maximum:
|
|
18
|
+
'agent.sessions.list': { inputSchema: obj({}), outputSchema: obj({ sessions: array(externalSessionSummarySchema, 128), omitted: count }), requires: [], effect: 'read' },
|
|
19
|
+
'agent.sessions.read': { inputSchema: obj({ session: { type: 'string', pattern: '^x-[a-f0-9]{64}$' }, before: count, limit: { type: 'integer', minimum: 1, maximum: 50 } }, ['session']), outputSchema: obj({ session: externalSessionSummarySchema, first: count, turns: array(externalTurnSchema, 50) }), requires: [], effect: 'read' },
|
|
15
20
|
};
|
|
@@ -31,6 +31,7 @@ export interface ExternalTurn {
|
|
|
31
31
|
results: ExternalResult[];
|
|
32
32
|
omittedTools: number;
|
|
33
33
|
omittedChars: number;
|
|
34
|
+
where?: string;
|
|
34
35
|
}
|
|
35
36
|
export interface ExternalSessionSummary {
|
|
36
37
|
id: string;
|
|
@@ -44,7 +45,17 @@ export interface ExternalSessionSummary {
|
|
|
44
45
|
sourceCursor: number;
|
|
45
46
|
omittedTurns: number;
|
|
46
47
|
problem?: string;
|
|
47
|
-
inputOwner
|
|
48
|
+
inputOwner?: 'external';
|
|
49
|
+
where?: string;
|
|
50
|
+
open?: {
|
|
51
|
+
where: string;
|
|
52
|
+
since?: string;
|
|
53
|
+
pid?: number;
|
|
54
|
+
} | null;
|
|
55
|
+
resume?: string;
|
|
56
|
+
bytes?: number;
|
|
57
|
+
continueWith?: 'claude-acp' | 'codex-acp' | 'acp' | null;
|
|
58
|
+
conversationId?: string;
|
|
48
59
|
}
|
|
49
60
|
export interface ExternalSessionRecord {
|
|
50
61
|
format: 1;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type ExternalSessionSummary, type ExternalTurn } from './external-session.js';
|
|
2
|
+
export declare const nativeSessionLimits: {
|
|
3
|
+
maxSessions: number;
|
|
4
|
+
maxScanFiles: number;
|
|
5
|
+
maxHeadBytes: number;
|
|
6
|
+
maxTailBytes: number;
|
|
7
|
+
maxReadBytes: number;
|
|
8
|
+
maxTurns: number;
|
|
9
|
+
maxTools: number;
|
|
10
|
+
maxTextChars: number;
|
|
11
|
+
maxDetailChars: number;
|
|
12
|
+
activeMs: number;
|
|
13
|
+
};
|
|
14
|
+
export type NativeProducer = 'claude-code' | 'codex';
|
|
15
|
+
export interface NativeSessionSources {
|
|
16
|
+
claudeConfigDir?: string;
|
|
17
|
+
codexHome?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface NativeSessionSummary extends ExternalSessionSummary {
|
|
20
|
+
producer: NativeProducer;
|
|
21
|
+
where: string;
|
|
22
|
+
open: {
|
|
23
|
+
where: string;
|
|
24
|
+
since?: string;
|
|
25
|
+
pid?: number;
|
|
26
|
+
} | null;
|
|
27
|
+
resume: string;
|
|
28
|
+
bytes: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function nativeSources(env?: NodeJS.ProcessEnv): Required<NativeSessionSources>;
|
|
31
|
+
/** The Agents' own sessions whose working folder is `root`, newest first. Reads files only. */
|
|
32
|
+
export declare function listNativeSessions(root: string, sources?: NativeSessionSources): {
|
|
33
|
+
sessions: NativeSessionSummary[];
|
|
34
|
+
omitted: number;
|
|
35
|
+
};
|
|
36
|
+
/** One session's turns, read through its file (its last maxReadBytes when larger). */
|
|
37
|
+
export declare function readNativeSession(root: string, input: {
|
|
38
|
+
session: string;
|
|
39
|
+
before?: number;
|
|
40
|
+
limit?: number;
|
|
41
|
+
}, sources?: NativeSessionSources): Promise<{
|
|
42
|
+
session: {
|
|
43
|
+
turns: number;
|
|
44
|
+
omittedTurns: number;
|
|
45
|
+
producer: NativeProducer;
|
|
46
|
+
where: string;
|
|
47
|
+
open: {
|
|
48
|
+
where: string;
|
|
49
|
+
since?: string;
|
|
50
|
+
pid?: number;
|
|
51
|
+
} | null;
|
|
52
|
+
resume: string;
|
|
53
|
+
bytes: number;
|
|
54
|
+
id: string;
|
|
55
|
+
sessionId: string;
|
|
56
|
+
title: string;
|
|
57
|
+
lastAt: string;
|
|
58
|
+
observedAt: string;
|
|
59
|
+
state: ExternalTurn["state"];
|
|
60
|
+
sourceCursor: number;
|
|
61
|
+
problem?: string;
|
|
62
|
+
inputOwner?: "external";
|
|
63
|
+
continueWith?: "claude-acp" | "codex-acp" | "acp" | null;
|
|
64
|
+
conversationId?: string;
|
|
65
|
+
};
|
|
66
|
+
first: number;
|
|
67
|
+
turns: ExternalTurn[];
|
|
68
|
+
} | null>;
|
|
69
|
+
/** Whether `sessionId` names a session of this Agent in `root`, and its summary. */
|
|
70
|
+
export declare function nativeSession(root: string, producer: NativeProducer, sessionId: string, sources?: NativeSessionSources): NativeSessionSummary | null;
|