codiedev 0.10.0-beta.3 → 0.10.0-beta.5
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 +7 -1
- package/assets/tui-brand-plugin.tsx +73 -0
- package/dist/backup/cache.js +1 -5
- package/dist/backup/match.js +0 -6
- package/dist/backup/run.js +3 -35
- package/dist/captureExclusions.js +0 -12
- package/dist/captureLog.js +0 -28
- package/dist/captureReadiness.js +0 -58
- package/dist/captureSignals.js +66 -3
- package/dist/cli.js +41 -18
- package/dist/codexHookTrust.js +61 -5
- package/dist/codexLimitScan.js +2 -109
- package/dist/codie.js +41 -56
- package/dist/codieBrandInstall.js +80 -0
- package/dist/codieLauncher.js +59 -59
- package/dist/codieRuntime.js +19 -23
- package/dist/codieRuntimeInstall.js +108 -23
- package/dist/codieStartup.js +0 -3
- package/dist/codieUsage.js +181 -0
- package/dist/commands/ask.js +0 -3
- package/dist/commands/capture.js +0 -2
- package/dist/commands/createTicket.js +0 -10
- package/dist/commands/doctor.js +41 -82
- package/dist/commands/inbox.js +0 -2
- package/dist/commands/library.js +0 -3
- package/dist/commands/pack.js +573 -0
- package/dist/commands/ping.js +0 -2
- package/dist/commands/pull.js +6 -10
- package/dist/commands/push.js +2 -12
- package/dist/commands/react.js +0 -2
- package/dist/commands/reverseTicket.js +0 -33
- package/dist/commands/search.js +0 -4
- package/dist/commands/send.js +0 -5
- package/dist/commands/share.js +0 -4
- package/dist/commands/shared.js +0 -35
- package/dist/commands/traces.js +280 -0
- package/dist/configDir.js +0 -10
- package/dist/connect.js +21 -77
- package/dist/connectFlow.js +0 -9
- package/dist/copilotHooks.js +395 -0
- package/dist/copilotInstallation.js +64 -0
- package/dist/cursorHooks.js +40 -17
- package/dist/cursorLifecycle.js +109 -0
- package/dist/detection.js +0 -30
- package/dist/harnessDirs.js +73 -0
- package/dist/hook.js +193 -316
- package/dist/inboxFormat.js +0 -24
- package/dist/launchContext.js +150 -0
- package/dist/launcher.js +140 -0
- package/dist/limitEvent.js +41 -35
- package/dist/limitEventReporter.js +1 -1
- package/dist/mcp.js +3 -77
- package/dist/nativeSteering.js +24 -0
- package/dist/packs/codie.js +182 -0
- package/dist/packs/harnesses.js +374 -0
- package/dist/packs/hookGate.js +256 -0
- package/dist/packs/install.js +285 -0
- package/dist/packs/manifest.js +126 -0
- package/dist/packs/paths.js +81 -0
- package/dist/packs/shim.js +214 -0
- package/dist/packs/store.js +155 -0
- package/dist/packs/sync.js +170 -0
- package/dist/prUrl.js +0 -5
- package/dist/repoResolver.js +0 -19
- package/dist/secret.js +0 -3
- package/dist/security.js +0 -20
- package/dist/securityDeepScan.js +1 -14
- package/dist/securityDoctor.js +0 -2
- package/dist/securityFeature.js +0 -1
- package/dist/securityInstall.js +6 -13
- package/dist/securityInventory.js +23 -13
- package/dist/securityPilot.js +0 -2
- package/dist/securityPolicy.js +0 -7
- package/dist/selfUpdate.js +331 -0
- package/dist/skillMarker.js +23 -0
- package/dist/subagents.js +135 -0
- package/dist/teamSkillContext.js +10 -0
- package/dist/transcriptModels.js +6 -8
- package/dist/upgradeNudge.js +0 -30
- package/dist/utils.js +286 -733
- package/dist/version.js +0 -10
- package/dist/versionCheck.js +0 -33
- package/package.json +8 -7
- package/dist/backup/cache.d.ts +0 -14
- package/dist/backup/match.d.ts +0 -2
- package/dist/backup/run.d.ts +0 -25
- package/dist/captureExclusions.d.ts +0 -30
- package/dist/captureLog.d.ts +0 -20
- package/dist/captureReadiness.d.ts +0 -65
- package/dist/captureSignals.d.ts +0 -19
- package/dist/cli.d.ts +0 -16
- package/dist/codexHookTrust.d.ts +0 -34
- package/dist/codexLimitScan.d.ts +0 -64
- package/dist/codie.d.ts +0 -2
- package/dist/codieLauncher.d.ts +0 -53
- package/dist/codieRuntime.d.ts +0 -29
- package/dist/codieRuntimeInstall.d.ts +0 -28
- package/dist/codieStartup.d.ts +0 -26
- package/dist/commands/ask.d.ts +0 -1
- package/dist/commands/capture.d.ts +0 -14
- package/dist/commands/createTicket.d.ts +0 -27
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/inbox.d.ts +0 -3
- package/dist/commands/library.d.ts +0 -2
- package/dist/commands/note.d.ts +0 -1
- package/dist/commands/ping.d.ts +0 -1
- package/dist/commands/promote.d.ts +0 -1
- package/dist/commands/pull.d.ts +0 -2
- package/dist/commands/push.d.ts +0 -33
- package/dist/commands/react.d.ts +0 -2
- package/dist/commands/reverseTicket.d.ts +0 -2
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/security.d.ts +0 -1
- package/dist/commands/send.d.ts +0 -2
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/shared.d.ts +0 -64
- package/dist/configDir.d.ts +0 -1
- package/dist/connect.d.ts +0 -1
- package/dist/connectFlow.d.ts +0 -13
- package/dist/cursorHooks.d.ts +0 -23
- package/dist/detection.d.ts +0 -30
- package/dist/hook.d.ts +0 -6
- package/dist/inboxFormat.d.ts +0 -38
- package/dist/limitEvent.d.ts +0 -16
- package/dist/limitEventReporter.d.ts +0 -21
- package/dist/mcp.d.ts +0 -12
- package/dist/prUrl.d.ts +0 -9
- package/dist/repoResolver.d.ts +0 -17
- package/dist/secret.d.ts +0 -1
- package/dist/security.d.ts +0 -102
- package/dist/securityDeepScan.d.ts +0 -41
- package/dist/securityDoctor.d.ts +0 -32
- package/dist/securityFeature.d.ts +0 -5
- package/dist/securityInstall.d.ts +0 -63
- package/dist/securityInventory.d.ts +0 -54
- package/dist/securityPilot.d.ts +0 -19
- package/dist/securityPolicy.d.ts +0 -33
- package/dist/securitySession.d.ts +0 -6
- package/dist/transcriptModels.d.ts +0 -18
- package/dist/upgradeNudge.d.ts +0 -25
- package/dist/utils.d.ts +0 -346
- package/dist/version.d.ts +0 -1
- package/dist/versionCheck.d.ts +0 -68
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SHIM_EVENTS = void 0;
|
|
37
|
+
exports.unsupportedShimEvents = unsupportedShimEvents;
|
|
38
|
+
exports.shimPacks = shimPacks;
|
|
39
|
+
exports.generateShimSource = generateShimSource;
|
|
40
|
+
exports.writeShim = writeShim;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const store_1 = require("./store");
|
|
43
|
+
exports.SHIM_EVENTS = ["SessionStart", "PreToolUse", "PostToolUse", "Stop"];
|
|
44
|
+
function normalizeHooks(hooks) {
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const event of exports.SHIM_EVENTS) {
|
|
47
|
+
const groups = hooks[event];
|
|
48
|
+
if (!Array.isArray(groups))
|
|
49
|
+
continue;
|
|
50
|
+
const normalized = [];
|
|
51
|
+
for (const groupValue of groups) {
|
|
52
|
+
const group = groupValue;
|
|
53
|
+
if (!group || !Array.isArray(group.hooks))
|
|
54
|
+
continue;
|
|
55
|
+
const handlers = [];
|
|
56
|
+
for (const handlerValue of group.hooks) {
|
|
57
|
+
const handler = handlerValue;
|
|
58
|
+
if (!handler || handler.type !== "command" || typeof handler.command !== "string")
|
|
59
|
+
continue;
|
|
60
|
+
handlers.push({
|
|
61
|
+
command: handler.command,
|
|
62
|
+
...(typeof handler.timeout === "number" && handler.timeout > 0 ? { timeout: handler.timeout } : {}),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (handlers.length === 0)
|
|
66
|
+
continue;
|
|
67
|
+
normalized.push({
|
|
68
|
+
...(typeof group.matcher === "string" ? { matcher: group.matcher } : {}),
|
|
69
|
+
hooks: handlers,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (normalized.length)
|
|
73
|
+
out[event] = normalized;
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function unsupportedShimEvents(packs) {
|
|
78
|
+
const out = new Map();
|
|
79
|
+
for (const pack of packs) {
|
|
80
|
+
const events = Object.keys(pack.hooks ?? {}).filter((e) => !exports.SHIM_EVENTS.includes(e)).sort();
|
|
81
|
+
if (events.length)
|
|
82
|
+
out.set(pack.slug, events);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function shimPacks(packs) {
|
|
87
|
+
return packs
|
|
88
|
+
.map((pack) => ({ slug: pack.slug, root: pack.root, hooks: normalizeHooks(pack.hooks) }))
|
|
89
|
+
.filter((pack) => Object.keys(pack.hooks).length > 0);
|
|
90
|
+
}
|
|
91
|
+
function generateShimSource(packs) {
|
|
92
|
+
const data = shimPacks(packs);
|
|
93
|
+
return `// Managed by \`codiedev pack install\`. Regenerated on every install; do not edit.
|
|
94
|
+
import { spawnSync } from "node:child_process";
|
|
95
|
+
import { existsSync } from "node:fs";
|
|
96
|
+
|
|
97
|
+
const PACKS = ${JSON.stringify(data, null, 2)};
|
|
98
|
+
|
|
99
|
+
// OpenCode tool ids are lowercase; Claude hook matchers use Claude casing.
|
|
100
|
+
const TOOL_NAMES = {
|
|
101
|
+
bash: "Bash", edit: "Edit", write: "Write", read: "Read", grep: "Grep",
|
|
102
|
+
glob: "Glob", list: "LS", ls: "LS", webfetch: "WebFetch", websearch: "WebSearch",
|
|
103
|
+
todowrite: "TodoWrite", todoread: "TodoRead", task: "Task", multiedit: "MultiEdit",
|
|
104
|
+
patch: "Edit", apply_patch: "Edit",
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export function claudeToolName(tool) {
|
|
108
|
+
const name = String(tool ?? "");
|
|
109
|
+
if (!name) return "unknown";
|
|
110
|
+
return TOOL_NAMES[name.toLowerCase()] ?? name.charAt(0).toUpperCase() + name.slice(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Claude semantics: empty or "*" matches everything; otherwise a regex that
|
|
114
|
+
// must match the whole tool name ("Edit|Write", "Notebook.*").
|
|
115
|
+
export function matches(matcher, value) {
|
|
116
|
+
if (matcher === undefined || matcher === null || matcher === "" || matcher === "*") return true;
|
|
117
|
+
try {
|
|
118
|
+
return new RegExp("^(?:" + matcher + ")$").test(value);
|
|
119
|
+
} catch {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function handlersFor(event, value) {
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const pack of PACKS) {
|
|
127
|
+
for (const group of pack.hooks[event] ?? []) {
|
|
128
|
+
if (!matches(group.matcher, value)) continue;
|
|
129
|
+
for (const handler of group.hooks) out.push({ ...handler, root: pack.root });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function run(handler, payload) {
|
|
136
|
+
const cwd = typeof payload.cwd === "string" && existsSync(payload.cwd) ? payload.cwd : undefined;
|
|
137
|
+
return spawnSync(handler.command, [], {
|
|
138
|
+
input: JSON.stringify(payload),
|
|
139
|
+
encoding: "utf8",
|
|
140
|
+
shell: true,
|
|
141
|
+
cwd,
|
|
142
|
+
timeout: (handler.timeout ?? 60) * 1000,
|
|
143
|
+
env: { ...process.env, CLAUDE_PLUGIN_ROOT: handler.root },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function sessionId(value) {
|
|
148
|
+
return value?.sessionID ?? value?.sessionId ?? value?.properties?.sessionID ?? value?.properties?.info?.id ?? undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const CodiedevPackHooks = async (ctx = {}) => {
|
|
152
|
+
const cwd = ctx?.worktree || ctx?.directory || process.cwd();
|
|
153
|
+
const childSessions = new Set();
|
|
154
|
+
return {
|
|
155
|
+
"tool.execute.before": async (input, output) => {
|
|
156
|
+
const tool_name = claudeToolName(input?.tool);
|
|
157
|
+
for (const handler of handlersFor("PreToolUse", tool_name)) {
|
|
158
|
+
const result = run(handler, {
|
|
159
|
+
hook_event_name: "PreToolUse",
|
|
160
|
+
session_id: sessionId(input),
|
|
161
|
+
cwd,
|
|
162
|
+
tool_name,
|
|
163
|
+
tool_input: output?.args ?? {},
|
|
164
|
+
});
|
|
165
|
+
if (result.status === 2) throw new Error(String(result.stderr ?? "").trim() || "Blocked by hook");
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"tool.execute.after": async (input, output) => {
|
|
169
|
+
const tool_name = claudeToolName(input?.tool);
|
|
170
|
+
for (const handler of handlersFor("PostToolUse", tool_name)) {
|
|
171
|
+
run(handler, {
|
|
172
|
+
hook_event_name: "PostToolUse",
|
|
173
|
+
session_id: sessionId(input),
|
|
174
|
+
cwd,
|
|
175
|
+
tool_name,
|
|
176
|
+
tool_input: input?.args ?? {},
|
|
177
|
+
tool_response: output ?? null,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
event: async ({ event } = {}) => {
|
|
182
|
+
// OpenCode also emits session.created/idle for subagent (child)
|
|
183
|
+
// sessions. Claude's SessionStart/Stop are top-level only, so remember
|
|
184
|
+
// children (info.parentID) and skip them. session.idle carries only the
|
|
185
|
+
// sessionID, hence the set.
|
|
186
|
+
const info = event?.properties?.info;
|
|
187
|
+
if (info?.id && info?.parentID) childSessions.add(info.id);
|
|
188
|
+
if (event?.type === "session.created") {
|
|
189
|
+
if (info?.parentID) return;
|
|
190
|
+
for (const handler of handlersFor("SessionStart", "startup")) {
|
|
191
|
+
run(handler, { hook_event_name: "SessionStart", session_id: sessionId(event), cwd, source: "startup" });
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (event?.type === "session.idle") {
|
|
196
|
+
const id = sessionId(event);
|
|
197
|
+
if (info?.parentID || (id && childSessions.has(id))) return;
|
|
198
|
+
for (const handler of handlersFor("Stop", "")) {
|
|
199
|
+
run(handler, { hook_event_name: "Stop", session_id: sessionId(event), cwd, stop_hook_active: false });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
function writeShim(file, packs) {
|
|
208
|
+
if (shimPacks(packs).length === 0) {
|
|
209
|
+
fs.rmSync(file, { force: true });
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
(0, store_1.writeFileAtomic)(file, generateShimSource(packs), 0o600);
|
|
213
|
+
return file;
|
|
214
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AGENT_LEVELS = void 0;
|
|
37
|
+
exports.pluginVersion = pluginVersion;
|
|
38
|
+
exports.writeFileAtomic = writeFileAtomic;
|
|
39
|
+
exports.portableAgentContent = portableAgentContent;
|
|
40
|
+
exports.pluginFiles = pluginFiles;
|
|
41
|
+
exports.writePluginDir = writePluginDir;
|
|
42
|
+
exports.readRegistry = readRegistry;
|
|
43
|
+
exports.writeRegistry = writeRegistry;
|
|
44
|
+
exports.marketplaceDocument = marketplaceDocument;
|
|
45
|
+
exports.writeMarketplace = writeMarketplace;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const skillMarker_1 = require("../skillMarker");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const paths_1 = require("./paths");
|
|
50
|
+
function pluginVersion(version) {
|
|
51
|
+
return `${version}.0.0`;
|
|
52
|
+
}
|
|
53
|
+
function writeFileAtomic(file, content, mode = 0o644) {
|
|
54
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
55
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
56
|
+
fs.writeFileSync(tmp, content, { encoding: "utf8", mode });
|
|
57
|
+
fs.renameSync(tmp, file);
|
|
58
|
+
}
|
|
59
|
+
exports.AGENT_LEVELS = new Set(["opus", "sonnet", "haiku"]);
|
|
60
|
+
function portableAgentContent(content) {
|
|
61
|
+
const fm = content.match(/^(\uFEFF?---\r?\n)([\s\S]*?)(\r?\n---[ \t]*(?:\r?\n|$))/);
|
|
62
|
+
if (!fm)
|
|
63
|
+
return content;
|
|
64
|
+
const lines = fm[2].split(/\r?\n/);
|
|
65
|
+
const kept = lines.filter((line) => {
|
|
66
|
+
const m = line.match(/^model\s*:\s*["']?([^"'\r\n]*?)["']?\s*$/);
|
|
67
|
+
return !m || m[1].includes("/");
|
|
68
|
+
});
|
|
69
|
+
if (kept.length === lines.length)
|
|
70
|
+
return content;
|
|
71
|
+
return fm[1] + kept.join("\n") + fm[3] + content.slice(fm[0].length);
|
|
72
|
+
}
|
|
73
|
+
function pluginFiles(manifest, options = {}) {
|
|
74
|
+
const files = {};
|
|
75
|
+
files[path.join(".claude-plugin", "plugin.json")] = JSON.stringify({
|
|
76
|
+
name: manifest.slug,
|
|
77
|
+
version: pluginVersion(manifest.version),
|
|
78
|
+
description: manifest.description || manifest.name,
|
|
79
|
+
}, null, 2) + "\n";
|
|
80
|
+
for (const skill of manifest.skills) {
|
|
81
|
+
files[path.join("skills", skill.name, "SKILL.md")] = (0, skillMarker_1.stampSkillMarker)(skill.content, skill.artifactId);
|
|
82
|
+
}
|
|
83
|
+
for (const agent of manifest.agents) {
|
|
84
|
+
files[path.join("agents", `${agent.name}.md`)] = options.portable ? portableAgentContent(agent.content) : agent.content;
|
|
85
|
+
}
|
|
86
|
+
if (manifest.hooksJson) {
|
|
87
|
+
files[path.join("hooks", "hooks.json")] = manifest.hooksJson;
|
|
88
|
+
}
|
|
89
|
+
return files;
|
|
90
|
+
}
|
|
91
|
+
function assertInside(parent, child) {
|
|
92
|
+
const rel = path.relative(parent, child);
|
|
93
|
+
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
94
|
+
throw new Error(`refusing to write outside the pack dir: ${child}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function writePluginDir(root, manifest, options = {}) {
|
|
98
|
+
const target = (0, paths_1.pluginDir)(root, manifest.slug);
|
|
99
|
+
const parent = (0, paths_1.pluginsDir)(root);
|
|
100
|
+
assertInside(parent, target);
|
|
101
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
102
|
+
const stamp = `${process.pid}-${Date.now()}`;
|
|
103
|
+
const tmp = path.join(parent, `.${manifest.slug}.tmp-${stamp}`);
|
|
104
|
+
const old = path.join(parent, `.${manifest.slug}.old-${stamp}`);
|
|
105
|
+
try {
|
|
106
|
+
for (const [rel, content] of Object.entries(pluginFiles(manifest, options))) {
|
|
107
|
+
const file = path.join(tmp, rel);
|
|
108
|
+
assertInside(tmp, file);
|
|
109
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
110
|
+
fs.writeFileSync(file, content, "utf8");
|
|
111
|
+
}
|
|
112
|
+
if (fs.existsSync(target))
|
|
113
|
+
fs.renameSync(target, old);
|
|
114
|
+
fs.renameSync(tmp, target);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
118
|
+
if (!fs.existsSync(target) && fs.existsSync(old))
|
|
119
|
+
fs.renameSync(old, target);
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
fs.rmSync(old, { recursive: true, force: true });
|
|
123
|
+
return target;
|
|
124
|
+
}
|
|
125
|
+
function readRegistry(root) {
|
|
126
|
+
try {
|
|
127
|
+
const parsed = JSON.parse(fs.readFileSync((0, paths_1.registryPath)(root), "utf8"));
|
|
128
|
+
if (parsed && typeof parsed === "object" && parsed.packs && typeof parsed.packs === "object") {
|
|
129
|
+
return { packs: parsed.packs };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
}
|
|
134
|
+
return { packs: {} };
|
|
135
|
+
}
|
|
136
|
+
function writeRegistry(root, registry) {
|
|
137
|
+
writeFileAtomic((0, paths_1.registryPath)(root), JSON.stringify(registry, null, 2) + "\n");
|
|
138
|
+
}
|
|
139
|
+
function marketplaceDocument(entries) {
|
|
140
|
+
const sorted = [...entries].sort((a, b) => a.slug.localeCompare(b.slug));
|
|
141
|
+
return {
|
|
142
|
+
name: paths_1.MARKETPLACE_NAME,
|
|
143
|
+
owner: { name: "Codiedev" },
|
|
144
|
+
metadata: { description: "Codiedev team starter packs" },
|
|
145
|
+
plugins: sorted.map((entry) => ({
|
|
146
|
+
name: entry.slug,
|
|
147
|
+
source: `./plugins/${entry.slug}`,
|
|
148
|
+
description: entry.description || entry.slug,
|
|
149
|
+
version: pluginVersion(entry.version),
|
|
150
|
+
})),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function writeMarketplace(root, entries) {
|
|
154
|
+
writeFileAtomic((0, paths_1.marketplacePath)(root), JSON.stringify(marketplaceDocument(entries), null, 2) + "\n");
|
|
155
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.EMPTY_RECHECK_MS = exports.NAG_INTERVAL_MS = exports.SYNC_INTERVAL_MS = void 0;
|
|
37
|
+
exports.isPackCiMode = isPackCiMode;
|
|
38
|
+
exports.readStatusCache = readStatusCache;
|
|
39
|
+
exports.writeStatusCache = writeStatusCache;
|
|
40
|
+
exports.autosyncDisabled = autosyncDisabled;
|
|
41
|
+
exports.decideSync = decideSync;
|
|
42
|
+
exports.cliEntry = cliEntry;
|
|
43
|
+
exports.maybeSpawnPackSync = maybeSpawnPackSync;
|
|
44
|
+
exports.packNagLine = packNagLine;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
49
|
+
const paths_1 = require("./paths");
|
|
50
|
+
const store_1 = require("./store");
|
|
51
|
+
exports.SYNC_INTERVAL_MS = 60 * 60 * 1000;
|
|
52
|
+
function isPackCiMode(env = process.env) {
|
|
53
|
+
const ci = (env.CI ?? "").trim().toLowerCase();
|
|
54
|
+
return (env.CODIEDEV_TOKEN ?? "").trim().startsWith("cdvci_") || ci === "true" || ci === "1";
|
|
55
|
+
}
|
|
56
|
+
exports.NAG_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
57
|
+
exports.EMPTY_RECHECK_MS = 24 * 60 * 60 * 1000;
|
|
58
|
+
function readStatusCache(root) {
|
|
59
|
+
try {
|
|
60
|
+
const parsed = JSON.parse(fs.readFileSync((0, paths_1.statusCachePath)(root), "utf8"));
|
|
61
|
+
if (typeof parsed?.checkedAt !== "number")
|
|
62
|
+
return null;
|
|
63
|
+
return {
|
|
64
|
+
checkedAt: parsed.checkedAt,
|
|
65
|
+
available: typeof parsed.available === "number" ? parsed.available : 0,
|
|
66
|
+
outdated: Array.isArray(parsed.outdated) ? parsed.outdated.filter((o) => typeof o?.slug === "string") : [],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function writeStatusCache(root, cache) {
|
|
74
|
+
try {
|
|
75
|
+
(0, store_1.writeFileAtomic)((0, paths_1.statusCachePath)(root), JSON.stringify(cache) + "\n");
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function mtime(file) {
|
|
81
|
+
try {
|
|
82
|
+
return fs.statSync(file).mtimeMs;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function registryNonEmpty(root) {
|
|
89
|
+
try {
|
|
90
|
+
const parsed = JSON.parse(fs.readFileSync((0, paths_1.registryPath)(root), "utf8"));
|
|
91
|
+
return Boolean(parsed?.packs && Object.keys(parsed.packs).length > 0);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function autosyncDisabled(env) {
|
|
98
|
+
const v = (env.CODIEDEV_PACK_AUTOSYNC ?? "").trim().toLowerCase();
|
|
99
|
+
return v === "0" || v === "false" || v === "off" || v === "no";
|
|
100
|
+
}
|
|
101
|
+
function decideSync(root, env, now) {
|
|
102
|
+
const last = mtime((0, paths_1.lastSyncPath)(root));
|
|
103
|
+
if (last !== null && now - last < exports.SYNC_INTERVAL_MS && last <= now)
|
|
104
|
+
return "throttled";
|
|
105
|
+
if (!registryNonEmpty(root)) {
|
|
106
|
+
const cache = readStatusCache(root);
|
|
107
|
+
if (cache && cache.available === 0 && now - cache.checkedAt < exports.EMPTY_RECHECK_MS)
|
|
108
|
+
return "no-packs";
|
|
109
|
+
}
|
|
110
|
+
return autosyncDisabled(env) ? "spawn-check" : "spawn-install";
|
|
111
|
+
}
|
|
112
|
+
function cliEntry() {
|
|
113
|
+
return path.join(__dirname, "..", "cli.js");
|
|
114
|
+
}
|
|
115
|
+
function maybeSpawnPackSync(options = {}) {
|
|
116
|
+
try {
|
|
117
|
+
if (options.connected === false)
|
|
118
|
+
return "not-connected";
|
|
119
|
+
const env = options.env ?? process.env;
|
|
120
|
+
if (isPackCiMode(env))
|
|
121
|
+
return "ci";
|
|
122
|
+
const root = (0, paths_1.packsRoot)(env, options.home ?? os.homedir());
|
|
123
|
+
const now = options.now ?? Date.now();
|
|
124
|
+
const decision = decideSync(root, env, now);
|
|
125
|
+
if (decision !== "spawn-install" && decision !== "spawn-check")
|
|
126
|
+
return decision;
|
|
127
|
+
fs.mkdirSync(root, { recursive: true });
|
|
128
|
+
fs.writeFileSync((0, paths_1.lastSyncPath)(root), String(now));
|
|
129
|
+
const time = new Date(now);
|
|
130
|
+
fs.utimesSync((0, paths_1.lastSyncPath)(root), time, time);
|
|
131
|
+
const args = decision === "spawn-install"
|
|
132
|
+
? ["pack", "install", "--quiet"]
|
|
133
|
+
: ["pack", "status", "--quiet", "--no-prune"];
|
|
134
|
+
const child = (options.spawn ?? child_process_1.spawn)(process.execPath, [options.cli ?? cliEntry(), ...args], {
|
|
135
|
+
detached: true,
|
|
136
|
+
stdio: "ignore",
|
|
137
|
+
env: { ...env, CODIEDEV_PACK_BACKGROUND: "1" },
|
|
138
|
+
});
|
|
139
|
+
child.on?.("error", () => { });
|
|
140
|
+
child.unref?.();
|
|
141
|
+
return decision;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return "error";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function packNagLine(options = {}) {
|
|
148
|
+
try {
|
|
149
|
+
const env = options.env ?? process.env;
|
|
150
|
+
if (env.CODIEDEV_PACK_BACKGROUND || isPackCiMode(env))
|
|
151
|
+
return null;
|
|
152
|
+
const root = (0, paths_1.packsRoot)(env, options.home ?? os.homedir());
|
|
153
|
+
const now = options.now ?? Date.now();
|
|
154
|
+
const cache = readStatusCache(root);
|
|
155
|
+
if (!cache || cache.outdated.length === 0)
|
|
156
|
+
return null;
|
|
157
|
+
const last = mtime((0, paths_1.lastNagPath)(root));
|
|
158
|
+
if (last !== null && now - last < exports.NAG_INTERVAL_MS && last <= now)
|
|
159
|
+
return null;
|
|
160
|
+
fs.writeFileSync((0, paths_1.lastNagPath)(root), String(now));
|
|
161
|
+
const time = new Date(now);
|
|
162
|
+
fs.utimesSync((0, paths_1.lastNagPath)(root), time, time);
|
|
163
|
+
const first = cache.outdated[0];
|
|
164
|
+
const more = cache.outdated.length > 1 ? ` (+${cache.outdated.length - 1} more)` : "";
|
|
165
|
+
return `Starter pack ${first.name || first.slug}${more} has updates. Run \`codiedev pack install\`.`;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/dist/prUrl.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// PR/MR URL parser. GitHub uses `/pull/<n>`, GitLab uses `/-/merge_requests/<n>`.
|
|
3
|
-
// Self-hosted GitLab keeps the same path shape on a different host (Sonifi
|
|
4
|
-
// runs git.sonifi.com behind a Cloudflare tunnel, for example). Nested groups
|
|
5
|
-
// land in `owner` as a slash-joined path so we can rebuild the full project
|
|
6
|
-
// path when calling the GitLab API.
|
|
7
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
3
|
exports.parsePrOrMrUrl = parsePrOrMrUrl;
|
|
9
4
|
function parsePrOrMrUrl(url) {
|
package/dist/repoResolver.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Pure resolver — given a captured remoteUrl, an optional client-cached
|
|
3
|
-
// repoId, and the company's current repo list, decide which repoId (if any)
|
|
4
|
-
// the session belongs to. Used both inline by the CLI hook and (mirrored
|
|
5
|
-
// in convex/repoResolver.ts) by the /api/captureSession endpoint so that
|
|
6
|
-
// repos added after the user's last `connect` still get matched.
|
|
7
|
-
//
|
|
8
|
-
// "unmatched" is intentional — the backend will accept the session anyway
|
|
9
|
-
// and surface it for triage rather than silently dropping it.
|
|
10
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
3
|
exports.resolveRepoForCapture = resolveRepoForCapture;
|
|
12
4
|
function parseRemoteUrl(url) {
|
|
@@ -17,12 +9,6 @@ function parseRemoteUrl(url) {
|
|
|
17
9
|
if (https) {
|
|
18
10
|
return { host: https[1].toLowerCase(), ownerName: https[2].toLowerCase() };
|
|
19
11
|
}
|
|
20
|
-
// Codie strips SSH userinfo before putting a remote in the gateway header,
|
|
21
|
-
// so `git@gitlab.com:owner/repo.git` arrives here as
|
|
22
|
-
// `gitlab.com:owner/repo.git`. Accept both forms; otherwise every SSH-cloned
|
|
23
|
-
// Harness checkout loses its repoId even though transcript capture can
|
|
24
|
-
// resolve the same raw remote correctly. Check this after URL forms so the
|
|
25
|
-
// colon in `https://` is never mistaken for an SCP separator.
|
|
26
12
|
const scp = s.match(/^(?:[^@\s]+@)?([^:/\s]+):([^/]+\/.+)$/);
|
|
27
13
|
if (scp) {
|
|
28
14
|
return { host: scp[1].toLowerCase(), ownerName: scp[2].toLowerCase() };
|
|
@@ -31,11 +17,6 @@ function parseRemoteUrl(url) {
|
|
|
31
17
|
}
|
|
32
18
|
function resolveRepoForCapture(input) {
|
|
33
19
|
const { remoteUrl, providedRepoId, companyRepos } = input;
|
|
34
|
-
// The remoteUrl is the ground truth of where the work happened — resolve it
|
|
35
|
-
// FIRST. A buggy client can send a wrong-but-valid providedRepoId (the Sonifi
|
|
36
|
-
// case: client matchRepo stamped every session with the org's first repo), so
|
|
37
|
-
// we must not blindly trust it over the URL. Keep providedRepoId only when it
|
|
38
|
-
// AGREES with the URL match, or when the URL can't be resolved at all.
|
|
39
20
|
const parsed = remoteUrl ? parseRemoteUrl(remoteUrl) : null;
|
|
40
21
|
const urlMatch = parsed
|
|
41
22
|
? companyRepos.find((r) => `${r.owner}/${r.name}`.toLowerCase() === parsed.ownerName)
|
package/dist/secret.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Display helpers for credential-shaped strings. Use anywhere a token /
|
|
3
|
-
// secret might end up in user-visible output (logs, success lines, error
|
|
4
|
-
// messages) so a stray `console.log` can't leak the full value.
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.maskToken = maskToken;
|
|
7
4
|
const PREFIX_LEN = 12;
|
package/dist/security.js
CHANGED
|
@@ -42,9 +42,6 @@ exports.buildSecurityWorkflowEvent = buildSecurityWorkflowEvent;
|
|
|
42
42
|
exports.buildSecurityPromptEvent = buildSecurityPromptEvent;
|
|
43
43
|
exports.buildBlockedSecurityPromptEvent = buildBlockedSecurityPromptEvent;
|
|
44
44
|
const crypto = __importStar(require("crypto"));
|
|
45
|
-
// Advances only when endpoint enforcement behavior changes. This is
|
|
46
|
-
// intentionally independent from the package version so security coverage can
|
|
47
|
-
// remain current across unrelated CLI releases.
|
|
48
45
|
exports.SECURITY_RUNTIME_VERSION = 1;
|
|
49
46
|
function withEndpointIdentity(event, identity) {
|
|
50
47
|
return {
|
|
@@ -140,12 +137,6 @@ function containsSecretValue(text) {
|
|
|
140
137
|
SECRET_ASSIGNMENT.lastIndex = 0;
|
|
141
138
|
return false;
|
|
142
139
|
}
|
|
143
|
-
/**
|
|
144
|
-
* Runs before a user prompt reaches the model. This is intentionally narrow:
|
|
145
|
-
* block credential material, but allow safe references such as
|
|
146
|
-
* `$OPENAI_API_KEY` so developers can ask agents to use environment variables
|
|
147
|
-
* without pasting their values.
|
|
148
|
-
*/
|
|
149
140
|
function evaluatePromptSecurity(prompt, policy, source) {
|
|
150
141
|
if (!prompt || !containsSecretValue(prompt))
|
|
151
142
|
return { action: "allow" };
|
|
@@ -210,7 +201,6 @@ function destructiveTargetOutsideWorkspace(command, cwd) {
|
|
|
210
201
|
const normalizedCwd = cwd.replace(/\/+$/, "");
|
|
211
202
|
return target !== normalizedCwd && !target.startsWith(`${normalizedCwd}/`);
|
|
212
203
|
}
|
|
213
|
-
/** Runs synchronously before a tool executes. No network or model is involved. */
|
|
214
204
|
function evaluateToolSecurity(input, phase, policy, source, sessionContext) {
|
|
215
205
|
if (phase !== "pre")
|
|
216
206
|
return { action: "allow" };
|
|
@@ -324,8 +314,6 @@ function redactString(value) {
|
|
|
324
314
|
return `[REDACTED_SECRET:${fingerprint(match)}]`;
|
|
325
315
|
});
|
|
326
316
|
}
|
|
327
|
-
// Keep hook payloads bounded. Full transcripts already use Codie's existing
|
|
328
|
-
// capture path; the detector only needs immediate causal context here.
|
|
329
317
|
if (redacted.length > 16_384)
|
|
330
318
|
redacted = `${redacted.slice(0, 16_384)}[TRUNCATED]`;
|
|
331
319
|
return { value: redacted, count };
|
|
@@ -386,12 +374,6 @@ function buildSecurityWorkflowEvent(input, phase, source, now = Date.now) {
|
|
|
386
374
|
redactionCount: sanitized.count,
|
|
387
375
|
};
|
|
388
376
|
}
|
|
389
|
-
/**
|
|
390
|
-
* Captures the intent side of the causal chain without weakening the local
|
|
391
|
-
* privacy boundary. A prompt that the deterministic policy blocks never
|
|
392
|
-
* becomes an uploadable event; allowed prompts are redacted and bounded using
|
|
393
|
-
* the same sanitizer as tool payloads.
|
|
394
|
-
*/
|
|
395
377
|
function buildSecurityPromptEvent(input, source, now = Date.now, policy) {
|
|
396
378
|
const sessionId = input.session_id ?? input.sessionId ?? "";
|
|
397
379
|
if (!sessionId || !input.prompt) {
|
|
@@ -415,8 +397,6 @@ function buildSecurityPromptEvent(input, source, now = Date.now, policy) {
|
|
|
415
397
|
localCategory: decision.action === "alert" ? decision.category : undefined,
|
|
416
398
|
};
|
|
417
399
|
}
|
|
418
|
-
/** Audit-safe evidence for a blocked prompt. The secret-bearing prompt is
|
|
419
|
-
* intentionally omitted; administrators still see that prevention occurred. */
|
|
420
400
|
function buildBlockedSecurityPromptEvent(input, source, category, now = Date.now) {
|
|
421
401
|
const sessionId = input.session_id ?? input.sessionId ?? "";
|
|
422
402
|
if (!sessionId)
|