@getbourdon/participants 0.3.0 → 0.4.0
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/base.js +1 -0
- package/dist/export-store-base.d.ts +96 -0
- package/dist/export-store-base.js +316 -0
- package/dist/index.cjs +497 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +170 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/network-base.js +1 -0
- package/dist/readers/bolt.d.ts +35 -0
- package/dist/readers/bolt.js +95 -0
- package/dist/readers/cascade.js +1 -0
- package/dist/readers/claude-code-automations.js +1 -0
- package/dist/readers/claude-code.js +1 -0
- package/dist/readers/claude-desktop-code.js +1 -0
- package/dist/readers/claude-desktop-cowork.js +1 -0
- package/dist/readers/codex-automations.js +1 -0
- package/dist/readers/codex-sessions.js +1 -0
- package/dist/readers/copilot-automations.js +1 -0
- package/dist/readers/copilot-cli.js +1 -0
- package/dist/readers/copilot-vscode.js +1 -0
- package/dist/readers/copilot.js +1 -0
- package/dist/readers/cursor-automations.js +1 -0
- package/dist/readers/cursor.js +1 -0
- package/dist/readers/github-copilot.js +1 -0
- package/dist/readers/hermes.js +1 -0
- package/dist/readers/lovable.d.ts +45 -0
- package/dist/readers/lovable.js +108 -0
- package/dist/readers/openclaw.js +1 -0
- package/dist/readers/v0.d.ts +37 -0
- package/dist/readers/v0.js +97 -0
- package/dist/registry.js +7 -0
- package/dist/sqlite-base.js +1 -0
- package/package.json +5 -5
package/dist/network-base.js
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StackBlitz Bolt.new participant — port of `participants/bolt.py`.
|
|
3
|
+
*
|
|
4
|
+
* Bolt.new builds and runs full-stack apps in WebContainers, in the browser,
|
|
5
|
+
* so nothing useful lands on the user's machine. It federates through an
|
|
6
|
+
* export directory; see {@link ExportStoreParticipant} for the store layout
|
|
7
|
+
* and the mechanics this shares with Lovable and v0.
|
|
8
|
+
*/
|
|
9
|
+
import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
|
|
10
|
+
import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
|
|
11
|
+
type Dict = Record<string, unknown>;
|
|
12
|
+
export declare const AGENT_ID = "bolt";
|
|
13
|
+
export declare const AGENT_TYPE = "code-assistant";
|
|
14
|
+
export declare const ROLE_NARRATIVE: string;
|
|
15
|
+
export declare const DEFAULT_POLICY: VisibilityPolicyModel;
|
|
16
|
+
/**
|
|
17
|
+
* One `projects.json` record to an Entity.
|
|
18
|
+
*
|
|
19
|
+
* Bolt caps the name at 80 characters, falls back to a generated summary when
|
|
20
|
+
* the record has no description, and inserts its own tag only when absent —
|
|
21
|
+
* all three differ from Lovable's mapper, deliberately. See the note in
|
|
22
|
+
* export-store-base.ts.
|
|
23
|
+
*/
|
|
24
|
+
export declare function projectToEntity(record: Dict): EntityModel | null;
|
|
25
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
26
|
+
export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
|
|
27
|
+
export declare const BOLT_CONFIG: ExportStoreConfig;
|
|
28
|
+
export declare class BoltParticipant extends ExportStoreParticipant {
|
|
29
|
+
constructor(options?: {
|
|
30
|
+
stateDir?: string;
|
|
31
|
+
env?: NodeJS.ProcessEnv;
|
|
32
|
+
});
|
|
33
|
+
static defaultNativePath(home?: string): string;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
/**
|
|
3
|
+
* StackBlitz Bolt.new participant — port of `participants/bolt.py`.
|
|
4
|
+
*
|
|
5
|
+
* Bolt.new builds and runs full-stack apps in WebContainers, in the browser,
|
|
6
|
+
* so nothing useful lands on the user's machine. It federates through an
|
|
7
|
+
* export directory; see {@link ExportStoreParticipant} for the store layout
|
|
8
|
+
* and the mechanics this shares with Lovable and v0.
|
|
9
|
+
*/
|
|
10
|
+
import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
|
|
11
|
+
import { redactText } from "@getbourdon/redaction";
|
|
12
|
+
import { ExportStoreParticipant, isoDate, parseVisibility, safeStr, safeStrList, } from "../export-store-base.js";
|
|
13
|
+
export const AGENT_ID = "bolt";
|
|
14
|
+
export const AGENT_TYPE = "code-assistant";
|
|
15
|
+
export const ROLE_NARRATIVE = "StackBlitz Bolt.new in-browser AI development environment. Builds, executes, " +
|
|
16
|
+
"and iterates full-stack applications in WebContainers from chat. Bourdon " +
|
|
17
|
+
"reads exported project and session state so other agents recognize what " +
|
|
18
|
+
"Bolt.new has developed.";
|
|
19
|
+
export const DEFAULT_POLICY = makeVisibilityPolicy({
|
|
20
|
+
default: Visibility.TEAM,
|
|
21
|
+
private_tags: ["personal", "credential", "secret", "client-confidential", "private"],
|
|
22
|
+
team_tags: ["bolt", "project", "webcontainer", "stackblitz"],
|
|
23
|
+
});
|
|
24
|
+
const MAX_SUMMARY_CHARS = 320;
|
|
25
|
+
const MAX_KEY_ACTION_CHARS = 300;
|
|
26
|
+
const NAME_LIMIT = 80;
|
|
27
|
+
/**
|
|
28
|
+
* One `projects.json` record to an Entity.
|
|
29
|
+
*
|
|
30
|
+
* Bolt caps the name at 80 characters, falls back to a generated summary when
|
|
31
|
+
* the record has no description, and inserts its own tag only when absent —
|
|
32
|
+
* all three differ from Lovable's mapper, deliberately. See the note in
|
|
33
|
+
* export-store-base.ts.
|
|
34
|
+
*/
|
|
35
|
+
export function projectToEntity(record) {
|
|
36
|
+
const rawName = record.name;
|
|
37
|
+
if (typeof rawName !== "string" || !rawName)
|
|
38
|
+
return null;
|
|
39
|
+
const name = safeStr(rawName, NAME_LIMIT);
|
|
40
|
+
if (!name)
|
|
41
|
+
return null;
|
|
42
|
+
const summary = safeStr(record.description ?? "", MAX_SUMMARY_CHARS) || `Bolt.new project ${name}`;
|
|
43
|
+
const tags = safeStrList(record.tags, 40);
|
|
44
|
+
if (!tags.includes("bolt"))
|
|
45
|
+
tags.unshift("bolt");
|
|
46
|
+
const updated = isoDate(record.updated_at);
|
|
47
|
+
const archived = Boolean(record.archived ?? false);
|
|
48
|
+
return makeEntity({
|
|
49
|
+
name,
|
|
50
|
+
type: "project",
|
|
51
|
+
summary,
|
|
52
|
+
tags,
|
|
53
|
+
last_touched: updated,
|
|
54
|
+
valid_from: isoDate(record.created_at),
|
|
55
|
+
valid_to: archived ? updated : null,
|
|
56
|
+
visibility: parseVisibility(record.visibility),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
60
|
+
export function sessionToRecord(record, fallbackDate) {
|
|
61
|
+
const date = isoDate(record.date) ?? fallbackDate;
|
|
62
|
+
if (!date)
|
|
63
|
+
return null;
|
|
64
|
+
const project = String(record.project ?? "").trim();
|
|
65
|
+
return makeSession({
|
|
66
|
+
date,
|
|
67
|
+
cwd: null, // cloud agent: there is no local working directory to name
|
|
68
|
+
project_focus: project ? [redactText(project, 120)] : [],
|
|
69
|
+
key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
|
|
70
|
+
files_touched: safeStrList(record.files_touched),
|
|
71
|
+
visibility: parseVisibility(record.visibility),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export const BOLT_CONFIG = {
|
|
75
|
+
agentId: AGENT_ID,
|
|
76
|
+
agentType: AGENT_TYPE,
|
|
77
|
+
displayName: "Bolt.new",
|
|
78
|
+
directoryName: ".bolt",
|
|
79
|
+
stateEnvVar: "BOLT_STATE_DIR",
|
|
80
|
+
roleNarrative: ROLE_NARRATIVE,
|
|
81
|
+
capabilities: ["in-browser-dev", "webcontainers", "full-stack-generation"],
|
|
82
|
+
policy: DEFAULT_POLICY,
|
|
83
|
+
label: "Bolt.new",
|
|
84
|
+
initCommand: "bourdon bolt init",
|
|
85
|
+
projectToEntity,
|
|
86
|
+
sessionToRecord,
|
|
87
|
+
};
|
|
88
|
+
export class BoltParticipant extends ExportStoreParticipant {
|
|
89
|
+
constructor(options = {}) {
|
|
90
|
+
super(BOLT_CONFIG, options);
|
|
91
|
+
}
|
|
92
|
+
static defaultNativePath(home) {
|
|
93
|
+
return ExportStoreParticipant.defaultNativePath(".bolt", home);
|
|
94
|
+
}
|
|
95
|
+
}
|
package/dist/readers/cascade.js
CHANGED
package/dist/readers/copilot.js
CHANGED
package/dist/readers/cursor.js
CHANGED
package/dist/readers/hermes.js
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lovable participant — port of `participants/lovable.py`.
|
|
3
|
+
*
|
|
4
|
+
* Lovable builds full-stack web apps from chat in the cloud, so nothing useful
|
|
5
|
+
* lands on the user's machine. It federates through an export directory; see
|
|
6
|
+
* {@link ExportStoreParticipant} for the store layout and the mechanics this
|
|
7
|
+
* shares with Bolt.new and v0.
|
|
8
|
+
*
|
|
9
|
+
* ⚠ The mapper below is NOT Bolt's with the names swapped, and must not be
|
|
10
|
+
* refactored into it. Lovable's oracle differs in four ways, each reproduced
|
|
11
|
+
* exactly here:
|
|
12
|
+
*
|
|
13
|
+
* 1. the project name is capped at 120 characters, not 80;
|
|
14
|
+
* 2. a record with no description yields a NULL summary, where Bolt
|
|
15
|
+
* synthesizes `"Bolt.new project <name>"`;
|
|
16
|
+
* 3. the `"lovable"` tag is APPENDED unconditionally, so a record that
|
|
17
|
+
* already carries it ends up with it twice — Bolt inserts only if absent;
|
|
18
|
+
* 4. `updated_at` falls back to `created_at`, where Bolt leaves
|
|
19
|
+
* `last_touched` null.
|
|
20
|
+
*
|
|
21
|
+
* (3) also means the tag lands LAST rather than first. None of this is
|
|
22
|
+
* defensible design; all of it is what the oracle does, and the mirror's job
|
|
23
|
+
* is to agree with the oracle, not to improve on it. Fixing any of it is an
|
|
24
|
+
* oracle-side change the conformance fixtures would have to absorb first.
|
|
25
|
+
*/
|
|
26
|
+
import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
|
|
27
|
+
import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
|
|
28
|
+
type Dict = Record<string, unknown>;
|
|
29
|
+
export declare const AGENT_ID = "lovable";
|
|
30
|
+
export declare const AGENT_TYPE = "code-assistant";
|
|
31
|
+
export declare const ROLE_NARRATIVE: string;
|
|
32
|
+
export declare const DEFAULT_POLICY: VisibilityPolicyModel;
|
|
33
|
+
/** One `projects.json` record to an Entity. See the four notes in the header. */
|
|
34
|
+
export declare function projectToEntity(record: Dict): EntityModel | null;
|
|
35
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
36
|
+
export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
|
|
37
|
+
export declare const LOVABLE_CONFIG: ExportStoreConfig;
|
|
38
|
+
export declare class LovableParticipant extends ExportStoreParticipant {
|
|
39
|
+
constructor(options?: {
|
|
40
|
+
stateDir?: string;
|
|
41
|
+
env?: NodeJS.ProcessEnv;
|
|
42
|
+
});
|
|
43
|
+
static defaultNativePath(home?: string): string;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
/**
|
|
3
|
+
* Lovable participant — port of `participants/lovable.py`.
|
|
4
|
+
*
|
|
5
|
+
* Lovable builds full-stack web apps from chat in the cloud, so nothing useful
|
|
6
|
+
* lands on the user's machine. It federates through an export directory; see
|
|
7
|
+
* {@link ExportStoreParticipant} for the store layout and the mechanics this
|
|
8
|
+
* shares with Bolt.new and v0.
|
|
9
|
+
*
|
|
10
|
+
* ⚠ The mapper below is NOT Bolt's with the names swapped, and must not be
|
|
11
|
+
* refactored into it. Lovable's oracle differs in four ways, each reproduced
|
|
12
|
+
* exactly here:
|
|
13
|
+
*
|
|
14
|
+
* 1. the project name is capped at 120 characters, not 80;
|
|
15
|
+
* 2. a record with no description yields a NULL summary, where Bolt
|
|
16
|
+
* synthesizes `"Bolt.new project <name>"`;
|
|
17
|
+
* 3. the `"lovable"` tag is APPENDED unconditionally, so a record that
|
|
18
|
+
* already carries it ends up with it twice — Bolt inserts only if absent;
|
|
19
|
+
* 4. `updated_at` falls back to `created_at`, where Bolt leaves
|
|
20
|
+
* `last_touched` null.
|
|
21
|
+
*
|
|
22
|
+
* (3) also means the tag lands LAST rather than first. None of this is
|
|
23
|
+
* defensible design; all of it is what the oracle does, and the mirror's job
|
|
24
|
+
* is to agree with the oracle, not to improve on it. Fixing any of it is an
|
|
25
|
+
* oracle-side change the conformance fixtures would have to absorb first.
|
|
26
|
+
*/
|
|
27
|
+
import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
|
|
28
|
+
import { redactText } from "@getbourdon/redaction";
|
|
29
|
+
import { ExportStoreParticipant, isoDate, parseVisibility, safeStrList, } from "../export-store-base.js";
|
|
30
|
+
export const AGENT_ID = "lovable";
|
|
31
|
+
export const AGENT_TYPE = "code-assistant";
|
|
32
|
+
export const ROLE_NARRATIVE = "Cloud app-building agent. Designs, builds, and iterates full-stack web " +
|
|
33
|
+
"applications from chat. Bourdon reads exported project and session state " +
|
|
34
|
+
"so other agents recognize what Lovable has built.";
|
|
35
|
+
export const DEFAULT_POLICY = makeVisibilityPolicy({
|
|
36
|
+
default: Visibility.TEAM,
|
|
37
|
+
private_tags: ["personal", "credential", "secret", "client-confidential"],
|
|
38
|
+
team_tags: ["lovable", "project", "client"],
|
|
39
|
+
});
|
|
40
|
+
const MAX_SUMMARY_CHARS = 320;
|
|
41
|
+
const MAX_KEY_ACTION_CHARS = 300;
|
|
42
|
+
const NAME_LIMIT = 120;
|
|
43
|
+
/** One `projects.json` record to an Entity. See the four notes in the header. */
|
|
44
|
+
export function projectToEntity(record) {
|
|
45
|
+
const name = String(record.name ?? "").trim();
|
|
46
|
+
if (!name)
|
|
47
|
+
return null;
|
|
48
|
+
const summary = record.description;
|
|
49
|
+
// (2) absent description -> null, not a synthesized sentence.
|
|
50
|
+
const summaryText = summary === null || summary === undefined || summary === ""
|
|
51
|
+
? null
|
|
52
|
+
: redactText(String(summary), MAX_SUMMARY_CHARS);
|
|
53
|
+
// (3) unconditional append: a record already tagged "lovable" gets it twice.
|
|
54
|
+
const tags = safeStrList(record.tags);
|
|
55
|
+
tags.push("lovable");
|
|
56
|
+
const archived = Boolean(record.archived);
|
|
57
|
+
// (4) updated_at falls back to created_at.
|
|
58
|
+
const updated = isoDate(record.updated_at) ?? isoDate(record.created_at);
|
|
59
|
+
return makeEntity({
|
|
60
|
+
name: redactText(name, NAME_LIMIT), // (1) 120, not 80
|
|
61
|
+
type: "project",
|
|
62
|
+
summary: summaryText,
|
|
63
|
+
tags,
|
|
64
|
+
last_touched: updated,
|
|
65
|
+
valid_from: isoDate(record.created_at),
|
|
66
|
+
valid_to: archived ? updated : null,
|
|
67
|
+
visibility: parseVisibility(record.visibility),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
71
|
+
export function sessionToRecord(record, fallbackDate) {
|
|
72
|
+
const date = isoDate(record.date) ?? fallbackDate;
|
|
73
|
+
if (!date)
|
|
74
|
+
return null;
|
|
75
|
+
const project = String(record.project ?? "").trim();
|
|
76
|
+
return makeSession({
|
|
77
|
+
date,
|
|
78
|
+
cwd: null, // cloud agent: there is no local working directory to name
|
|
79
|
+
project_focus: project ? [redactText(project, 120)] : [],
|
|
80
|
+
key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
|
|
81
|
+
// ⚠ No limit, so these are NOT redacted — the oracle's behaviour. Bolt and
|
|
82
|
+
// v0 redact the same field. Flagged, not silently corrected.
|
|
83
|
+
files_touched: safeStrList(record.files_touched),
|
|
84
|
+
visibility: parseVisibility(record.visibility),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export const LOVABLE_CONFIG = {
|
|
88
|
+
agentId: AGENT_ID,
|
|
89
|
+
agentType: AGENT_TYPE,
|
|
90
|
+
displayName: "Lovable",
|
|
91
|
+
directoryName: ".lovable",
|
|
92
|
+
stateEnvVar: "LOVABLE_STATE_DIR",
|
|
93
|
+
roleNarrative: ROLE_NARRATIVE,
|
|
94
|
+
capabilities: ["app-building", "full-stack-generation", "deploy-preview"],
|
|
95
|
+
policy: DEFAULT_POLICY,
|
|
96
|
+
label: "Lovable",
|
|
97
|
+
initCommand: "bourdon lovable init",
|
|
98
|
+
projectToEntity,
|
|
99
|
+
sessionToRecord,
|
|
100
|
+
};
|
|
101
|
+
export class LovableParticipant extends ExportStoreParticipant {
|
|
102
|
+
constructor(options = {}) {
|
|
103
|
+
super(LOVABLE_CONFIG, options);
|
|
104
|
+
}
|
|
105
|
+
static defaultNativePath(home) {
|
|
106
|
+
return ExportStoreParticipant.defaultNativePath(".lovable", home);
|
|
107
|
+
}
|
|
108
|
+
}
|
package/dist/readers/openclaw.js
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vercel v0 participant — port of `participants/v0.py`.
|
|
3
|
+
*
|
|
4
|
+
* v0 generates React / Next.js / Tailwind UI and full-stack web apps from
|
|
5
|
+
* chat, entirely server-side, so nothing useful lands on the user's machine.
|
|
6
|
+
* It federates through an export directory; see {@link ExportStoreParticipant}
|
|
7
|
+
* for the store layout and the mechanics this shares with Bolt.new and
|
|
8
|
+
* Lovable. The mapper below is byte-for-byte Bolt's rule with v0's own name
|
|
9
|
+
* and tag — that is the oracle's shape, not a shortcut taken here.
|
|
10
|
+
*/
|
|
11
|
+
import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
|
|
12
|
+
import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
|
|
13
|
+
type Dict = Record<string, unknown>;
|
|
14
|
+
export declare const AGENT_ID = "v0";
|
|
15
|
+
export declare const AGENT_TYPE = "code-assistant";
|
|
16
|
+
export declare const ROLE_NARRATIVE: string;
|
|
17
|
+
export declare const DEFAULT_POLICY: VisibilityPolicyModel;
|
|
18
|
+
/**
|
|
19
|
+
* One `projects.json` record to an Entity.
|
|
20
|
+
*
|
|
21
|
+
* Caps the name at 80 characters, falls back to a generated summary when the
|
|
22
|
+
* record has no description, and inserts its own tag only when absent. All
|
|
23
|
+
* three differ from Lovable's mapper, deliberately. See the note in
|
|
24
|
+
* export-store-base.ts.
|
|
25
|
+
*/
|
|
26
|
+
export declare function projectToEntity(record: Dict): EntityModel | null;
|
|
27
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
28
|
+
export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
|
|
29
|
+
export declare const V0_CONFIG: ExportStoreConfig;
|
|
30
|
+
export declare class V0Participant extends ExportStoreParticipant {
|
|
31
|
+
constructor(options?: {
|
|
32
|
+
stateDir?: string;
|
|
33
|
+
env?: NodeJS.ProcessEnv;
|
|
34
|
+
});
|
|
35
|
+
static defaultNativePath(home?: string): string;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
/**
|
|
3
|
+
* Vercel v0 participant — port of `participants/v0.py`.
|
|
4
|
+
*
|
|
5
|
+
* v0 generates React / Next.js / Tailwind UI and full-stack web apps from
|
|
6
|
+
* chat, entirely server-side, so nothing useful lands on the user's machine.
|
|
7
|
+
* It federates through an export directory; see {@link ExportStoreParticipant}
|
|
8
|
+
* for the store layout and the mechanics this shares with Bolt.new and
|
|
9
|
+
* Lovable. The mapper below is byte-for-byte Bolt's rule with v0's own name
|
|
10
|
+
* and tag — that is the oracle's shape, not a shortcut taken here.
|
|
11
|
+
*/
|
|
12
|
+
import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
|
|
13
|
+
import { redactText } from "@getbourdon/redaction";
|
|
14
|
+
import { ExportStoreParticipant, isoDate, parseVisibility, safeStr, safeStrList, } from "../export-store-base.js";
|
|
15
|
+
export const AGENT_ID = "v0";
|
|
16
|
+
export const AGENT_TYPE = "code-assistant";
|
|
17
|
+
export const ROLE_NARRATIVE = "Vercel v0 generative UI and full-stack web builder. Designs and iterates " +
|
|
18
|
+
"React, Next.js, and Tailwind components and web applications from chat. " +
|
|
19
|
+
"Bourdon reads exported project and session state so other agents recognize " +
|
|
20
|
+
"what v0 has designed and constructed.";
|
|
21
|
+
export const DEFAULT_POLICY = makeVisibilityPolicy({
|
|
22
|
+
default: Visibility.TEAM,
|
|
23
|
+
private_tags: ["personal", "credential", "secret", "client-confidential", "private"],
|
|
24
|
+
team_tags: ["v0", "project", "client", "ui", "component"],
|
|
25
|
+
});
|
|
26
|
+
const MAX_SUMMARY_CHARS = 320;
|
|
27
|
+
const MAX_KEY_ACTION_CHARS = 300;
|
|
28
|
+
const NAME_LIMIT = 80;
|
|
29
|
+
/**
|
|
30
|
+
* One `projects.json` record to an Entity.
|
|
31
|
+
*
|
|
32
|
+
* Caps the name at 80 characters, falls back to a generated summary when the
|
|
33
|
+
* record has no description, and inserts its own tag only when absent. All
|
|
34
|
+
* three differ from Lovable's mapper, deliberately. See the note in
|
|
35
|
+
* export-store-base.ts.
|
|
36
|
+
*/
|
|
37
|
+
export function projectToEntity(record) {
|
|
38
|
+
const rawName = record.name;
|
|
39
|
+
if (typeof rawName !== "string" || !rawName)
|
|
40
|
+
return null;
|
|
41
|
+
const name = safeStr(rawName, NAME_LIMIT);
|
|
42
|
+
if (!name)
|
|
43
|
+
return null;
|
|
44
|
+
const summary = safeStr(record.description ?? "", MAX_SUMMARY_CHARS) || `v0 project ${name}`;
|
|
45
|
+
const tags = safeStrList(record.tags, 40);
|
|
46
|
+
if (!tags.includes("v0"))
|
|
47
|
+
tags.unshift("v0");
|
|
48
|
+
const updated = isoDate(record.updated_at);
|
|
49
|
+
const archived = Boolean(record.archived ?? false);
|
|
50
|
+
return makeEntity({
|
|
51
|
+
name,
|
|
52
|
+
type: "project",
|
|
53
|
+
summary,
|
|
54
|
+
tags,
|
|
55
|
+
last_touched: updated,
|
|
56
|
+
valid_from: isoDate(record.created_at),
|
|
57
|
+
valid_to: archived ? updated : null,
|
|
58
|
+
visibility: parseVisibility(record.visibility),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** One `sessions/<id>.json` record to a Session, or null with no usable date. */
|
|
62
|
+
export function sessionToRecord(record, fallbackDate) {
|
|
63
|
+
const date = isoDate(record.date) ?? fallbackDate;
|
|
64
|
+
if (!date)
|
|
65
|
+
return null;
|
|
66
|
+
const project = String(record.project ?? "").trim();
|
|
67
|
+
return makeSession({
|
|
68
|
+
date,
|
|
69
|
+
cwd: null, // cloud agent: there is no local working directory to name
|
|
70
|
+
project_focus: project ? [redactText(project, 120)] : [],
|
|
71
|
+
key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
|
|
72
|
+
files_touched: safeStrList(record.files_touched),
|
|
73
|
+
visibility: parseVisibility(record.visibility),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
export const V0_CONFIG = {
|
|
77
|
+
agentId: AGENT_ID,
|
|
78
|
+
agentType: AGENT_TYPE,
|
|
79
|
+
displayName: "Vercel v0",
|
|
80
|
+
directoryName: ".v0",
|
|
81
|
+
stateEnvVar: "V0_STATE_DIR",
|
|
82
|
+
roleNarrative: ROLE_NARRATIVE,
|
|
83
|
+
capabilities: ["generative-ui", "full-stack-web", "react-nextjs"],
|
|
84
|
+
policy: DEFAULT_POLICY,
|
|
85
|
+
label: "v0",
|
|
86
|
+
initCommand: "bourdon v0 init",
|
|
87
|
+
projectToEntity,
|
|
88
|
+
sessionToRecord,
|
|
89
|
+
};
|
|
90
|
+
export class V0Participant extends ExportStoreParticipant {
|
|
91
|
+
constructor(options = {}) {
|
|
92
|
+
super(V0_CONFIG, options);
|
|
93
|
+
}
|
|
94
|
+
static defaultNativePath(home) {
|
|
95
|
+
return ExportStoreParticipant.defaultNativePath(".v0", home);
|
|
96
|
+
}
|
|
97
|
+
}
|
package/dist/registry.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
1
2
|
/**
|
|
2
3
|
* Participant discovery — a STATIC TS registry replacing Python's `pkgutil`
|
|
3
4
|
* package scan + entry-point duck-type (`participants/__init__.py`).
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
* interface conformance (checked structurally via {@link isParticipant}).
|
|
16
17
|
*/
|
|
17
18
|
import { isParticipant } from "./base.js";
|
|
19
|
+
import { BoltParticipant } from "./readers/bolt.js";
|
|
18
20
|
import { CascadeParticipant } from "./readers/cascade.js";
|
|
19
21
|
import { ClaudeCodeParticipant } from "./readers/claude-code.js";
|
|
20
22
|
import { ClaudeCodeAutomationsParticipant } from "./readers/claude-code-automations.js";
|
|
@@ -27,6 +29,8 @@ import { CopilotCliParticipant } from "./readers/copilot-cli.js";
|
|
|
27
29
|
import { CopilotVscodeParticipant } from "./readers/copilot-vscode.js";
|
|
28
30
|
import { CursorParticipant } from "./readers/cursor.js";
|
|
29
31
|
import { CursorAutomationsParticipant } from "./readers/cursor-automations.js";
|
|
32
|
+
import { LovableParticipant } from "./readers/lovable.js";
|
|
33
|
+
import { V0Participant } from "./readers/v0.js";
|
|
30
34
|
import { GitHubCopilotParticipant } from "./readers/github-copilot.js";
|
|
31
35
|
import { HermesParticipant } from "./readers/hermes.js";
|
|
32
36
|
import { OpenClawParticipant } from "./readers/openclaw.js";
|
|
@@ -37,6 +41,7 @@ import { OpenClawParticipant } from "./readers/openclaw.js";
|
|
|
37
41
|
* codex — the ~2.6k-line turn-compiler reader — is the only one still deferred.
|
|
38
42
|
*/
|
|
39
43
|
export const FIRST_PARTY = [
|
|
44
|
+
BoltParticipant,
|
|
40
45
|
CascadeParticipant,
|
|
41
46
|
ClaudeCodeParticipant,
|
|
42
47
|
ClaudeCodeAutomationsParticipant,
|
|
@@ -49,6 +54,8 @@ export const FIRST_PARTY = [
|
|
|
49
54
|
CopilotVscodeParticipant,
|
|
50
55
|
CursorParticipant,
|
|
51
56
|
CursorAutomationsParticipant,
|
|
57
|
+
LovableParticipant,
|
|
58
|
+
V0Participant,
|
|
52
59
|
GitHubCopilotParticipant,
|
|
53
60
|
HermesParticipant,
|
|
54
61
|
OpenClawParticipant,
|
package/dist/sqlite-base.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getbourdon/participants",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Bourdon participants — the external-agent → L5 reader layer (BUSL-1.1). Each participant normalizes a foreign agent's native memory store into a visibility-filtered, redacted L5 manifest: read-only SQLite readers (better-sqlite3 mode=ro: hermes), file/convention readers (claude-code), and network readers (github-copilot) with a TTL JSON cache + lazy AuthProvider that never persists a token. Four invariants enforced in code, not by trust: visibility-filter-before-emission, deterministic exportL5, healthCheck never throws, redact every native string. Discovery is a static TS registry (agent_id-sorted, first-wins, log-and-skip) replacing Python's pkgutil scan. Python (pip install bourdon) is the oracle; this mirror asserts against @getbourdon/conformance native_stores fixtures.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"type": "module",
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
"directory": "packages/participants"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"smol-toml": "^1.7.
|
|
36
|
+
"smol-toml": "^1.7.1",
|
|
37
37
|
"yaml": "^2.6.1",
|
|
38
|
-
"@getbourdon/l5": "0.
|
|
39
|
-
"@getbourdon/redaction": "0.1.
|
|
38
|
+
"@getbourdon/l5": "0.5.0",
|
|
39
|
+
"@getbourdon/redaction": "0.1.6"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
42
|
"better-sqlite3": "^12.2.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/better-sqlite3": "^7.6.12",
|
|
46
|
-
"@getbourdon/conformance": "0.
|
|
46
|
+
"@getbourdon/conformance": "0.8.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsup",
|