@vibecontrols/vibe-plugin-tool-git 2026.512.1 → 2026.521.1
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/index.js +1 -1
- package/dist/ui-git/index.html +100 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __defProp=Object.defineProperty;var __returnValue=(v)=>v;function __exportSe
|
|
|
4
4
|
`);return}if(mode==="plain"){await opts.plain(data);return}if((mode==="interactive"||stdoutIsTty()&&!isCi())&&!!opts.interactive&&opts.interactive)try{await opts.interactive(data);return}catch{}await opts.plain(data)}function maybePrintJson(flags,data){if(!flags.json)return!1;return process.stdout.write(`${JSON.stringify(data,null,2)}
|
|
5
5
|
`),!0}var SENSITIVE_KEY_RE=/(token|secret|password|apikey|api_key|key|auth|credential|email)/i;function redact(value){return redactInner(value)}function redactInner(value){if(value===null||value===void 0)return value;if(Array.isArray(value))return value.map(redactInner);if(typeof value==="object"){let out={};for(let[k,v]of Object.entries(value)){if(SENSITIVE_KEY_RE.test(k)){out[k]="[redacted]";continue}out[k]=redactInner(v)}return out}return value}var TelemetryEmitter=class{constructor(pluginName,pluginVersion,hostServices){this.pluginName=pluginName,this.pluginVersion=pluginVersion,this.hostServices=hostServices}pluginName;pluginVersion;hostServices;emit(eventName,payload){let target=this.hostServices?.telemetry;if(!target)return;target.emit(eventName,{plugin:this.pluginName,version:this.pluginVersion,timestamp:new Date().toISOString(),...payload??{}})}emitReady(context){this.emit(`${this.pluginName}.ready`,context)}emitError(error,context){this.emit(`${this.pluginName}.error`,{message:error.message,...context??{}})}emitEvent(type,payload){this.emit(type,payload)}};async function loadCore(){return await import("@opentui/core")}async function interactiveDetail(opts){let core=await loadCore(),{createCliRenderer,BoxRenderable,TextRenderable}=core,renderer=await createCliRenderer({exitOnCtrlC:!0,targetFps:30}),ctx=renderer.root.ctx,root=new BoxRenderable(ctx,{width:"100%",height:"100%",flexDirection:"column",backgroundColor:"#0b0d12"}),title=new TextRenderable(ctx,{content:` ${opts.title}`,fg:"#8be9fd",height:1}),bodyBox=new BoxRenderable(ctx,{width:"100%",flexGrow:1,paddingLeft:2,paddingRight:2,backgroundColor:"#11141c"}),bodyText=new TextRenderable(ctx,{content:`
|
|
6
6
|
${opts.body}
|
|
7
|
-
`,fg:"#cdd6f4"}),footer=new TextRenderable(ctx,{content:` ${opts.footer??"q to quit"}`,fg:"#6c7086",height:1});bodyBox.add(bodyText),root.add(title),root.add(bodyBox),root.add(footer),renderer.root.add(root),await new Promise((resolve)=>{let cleanup=()=>{try{renderer.destroy()}catch{}resolve()};renderer.keyInput.on("keypress",(key)=>{if(key.name==="escape"||key.name==="q"||key.name==="return")cleanup()})})}var AGENT_BASE_URL=process.env.VIBE_AGENT_URL??"http://localhost:3005",API_KEY=process.env.VIBE_AGENT_API_KEY??"";async function apiFetch(urlPath,options){return fetch(`${AGENT_BASE_URL}${urlPath}`,{...options,headers:{"Content-Type":"application/json","x-agent-api-key":API_KEY,...options?.headers}})}var agentApiKey=null,PLUGIN_NAME="ungit",PLUGIN_VERSION="2026.509.2",createPlugin=(_ctx)=>{let lifecycle=createLifecycleHooks({name:PLUGIN_NAME,telemetryEventName:"tool.ready",onInit:async(hostServices)=>{new TelemetryEmitter(PLUGIN_NAME,PLUGIN_VERSION,hostServices).emitEvent("tool.ready",{provider:"git"})}});return{capabilities:{storage:"rw",subprocess:!0,audit:!0,telemetry:!0},name:PLUGIN_NAME,version:PLUGIN_VERSION,description:"Visual Git Client (Ungit)",tags:["frontend","integration"],hasUI:!0,cliCommand:"ungit",apiPrefix:"/api/ungit",publicPaths:["/ungit/"],async onServerStart(app,hostServices){await lifecycle.onServerStart(app,hostServices);let elysiaApp=app,{createUngitRoutes:createUngitRoutes2}=await Promise.resolve().then(() => (init_routes2(),exports_routes));elysiaApp.use(createUngitRoutes2(hostServices));try{agentApiKey=elysiaApp.decorator?.apiKey??null}catch{agentApiKey=process.env.AGENT_API_KEY??null}let{createUngitProxy:createUngitProxy2}=await Promise.resolve().then(() => (init_proxy(),exports_proxy));elysiaApp.use(createUngitProxy2(()=>getRunningPort(),(key)=>{if(!agentApiKey)return!1;return key===agentApiKey})),process.stdout.write(` Plugin 'ungit' registered routes: /api/ungit, /ungit
|
|
7
|
+
`,fg:"#cdd6f4"}),footer=new TextRenderable(ctx,{content:` ${opts.footer??"q to quit"}`,fg:"#6c7086",height:1});bodyBox.add(bodyText),root.add(title),root.add(bodyBox),root.add(footer),renderer.root.add(root),await new Promise((resolve)=>{let cleanup=()=>{try{renderer.destroy()}catch{}resolve()};renderer.keyInput.on("keypress",(key)=>{if(key.name==="escape"||key.name==="q"||key.name==="return")cleanup()})})}var AGENT_BASE_URL=process.env.VIBE_AGENT_URL??"http://localhost:3005",API_KEY=process.env.VIBE_AGENT_API_KEY??"";async function apiFetch(urlPath,options){return fetch(`${AGENT_BASE_URL}${urlPath}`,{...options,headers:{"Content-Type":"application/json","x-agent-api-key":API_KEY,...options?.headers}})}var agentApiKey=null,PLUGIN_NAME="ungit",PLUGIN_VERSION="2026.509.2",createPlugin=(_ctx)=>{let lifecycle=createLifecycleHooks({name:PLUGIN_NAME,telemetryEventName:"tool.ready",onInit:async(hostServices)=>{new TelemetryEmitter(PLUGIN_NAME,PLUGIN_VERSION,hostServices).emitEvent("tool.ready",{provider:"git"})}});return{capabilities:{storage:"rw",subprocess:!0,audit:!0,telemetry:!0},name:PLUGIN_NAME,version:PLUGIN_VERSION,description:"Visual Git Client (Ungit)",tags:["frontend","integration"],hasUI:!0,cliCommand:"ungit",apiPrefix:"/api/ungit",publicPaths:["/ungit/"],ui:{title:"GitOps",icon:"GitMerge",staticDir:`${import.meta.dir}/ui-git`,capabilities:{restPaths:["/ungit","/api/ungit","/ui/ungit"],wsTopics:[],rpcMethods:["getContext"]},contributions:[{mountPoint:"vibe.detailTab",id:"plugin:git",title:"Git",icon:"GitBranch",order:30,runtimes:["iframe"],capabilities:{restPaths:["/ui/ungit"],wsTopics:[],rpcMethods:["getContext"]}},{mountPoint:"vibe.detailTab",id:"plugin:gitops",title:"GitOps",icon:"GitMerge",order:95,runtimes:["iframe"],capabilities:{restPaths:["/ungit","/api/ungit"],wsTopics:[],rpcMethods:[]},meta:{url:"/ungit/"}}]},async onServerStart(app,hostServices){await lifecycle.onServerStart(app,hostServices);let elysiaApp=app,{createUngitRoutes:createUngitRoutes2}=await Promise.resolve().then(() => (init_routes2(),exports_routes));elysiaApp.use(createUngitRoutes2(hostServices));try{agentApiKey=elysiaApp.decorator?.apiKey??null}catch{agentApiKey=process.env.AGENT_API_KEY??null}let{createUngitProxy:createUngitProxy2}=await Promise.resolve().then(() => (init_proxy(),exports_proxy));elysiaApp.use(createUngitProxy2(()=>getRunningPort(),(key)=>{if(!agentApiKey)return!1;return key===agentApiKey})),process.stdout.write(` Plugin 'ungit' registered routes: /api/ungit, /ungit
|
|
8
8
|
`)},async onServerStop(){await stopUngit(),process.stdout.write(` Plugin 'ungit' stopped
|
|
9
9
|
`)},onCliSetup(programArg){let cmd=programArg.command("ungit").description("Visual Git Client (Ungit)");cmd.command("status").description("Show Ungit status").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(opts)=>{await runMultimode({mode:pickOutputMode(opts),fetchData:async()=>{return await(await apiFetch("/api/ungit/status")).json()},plain:(data)=>{process.stdout.write(`${JSON.stringify(data,null,2)}
|
|
10
10
|
`)},interactive:async(data)=>{await interactiveDetail({title:"ungit \u2014 status",body:JSON.stringify(data,null,2)})},json:(data)=>redact(data)})}),cmd.command("install").description("Install Ungit globally via npm").option("--json","Emit JSON").action(async(opts)=>{if(!opts.json)process.stdout.write(`Installing Ungit...
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
|
+
<title>Git</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: light dark; --bg: #fafafa; --fg: #111; --muted: #555; --border: #e3e6ed; }
|
|
9
|
+
:root[data-vibe-theme="dark"] { --bg: #0a0c12; --fg: #f4f5f8; --muted: #c1c6d2; --border: #2c3142; }
|
|
10
|
+
html, body { margin: 0; padding: 0; font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--fg); }
|
|
11
|
+
body { padding: 24px; }
|
|
12
|
+
h1 { margin: 0 0 8px; font-size: 18px; }
|
|
13
|
+
p { color: var(--muted); margin: 0 0 8px; }
|
|
14
|
+
.card { border: 1px solid var(--border); border-radius: 8px; padding: 12px; margin-top: 12px; }
|
|
15
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
|
|
16
|
+
pre { margin: 0; font-size: 12px; }
|
|
17
|
+
</style>
|
|
18
|
+
</head>
|
|
19
|
+
<body>
|
|
20
|
+
<h1>Git</h1>
|
|
21
|
+
<p>Per-Vibe Git metadata (branch / status / remote). This iframe replaces the inline Git tab once the
|
|
22
|
+
<code>vibes.tabs.git-iframe</code> feature flag is on.</p>
|
|
23
|
+
<div class="card" id="git-info" hidden>
|
|
24
|
+
<p><strong>Vibe:</strong> <code id="vibe-id"></code></p>
|
|
25
|
+
<p><strong>Branch:</strong> <code id="branch">—</code></p>
|
|
26
|
+
<p><strong>Status:</strong> <code id="status">—</code></p>
|
|
27
|
+
<p><strong>Remote:</strong> <code id="remote">—</code></p>
|
|
28
|
+
</div>
|
|
29
|
+
<script type="module">
|
|
30
|
+
const ENVELOPE_VERSION = 1;
|
|
31
|
+
function isAllowed(origin) {
|
|
32
|
+
try {
|
|
33
|
+
const u = new URL(origin);
|
|
34
|
+
return (
|
|
35
|
+
u.hostname === 'localhost' || u.hostname === '127.0.0.1' ||
|
|
36
|
+
u.hostname.endsWith('.local.burdenoff.com') ||
|
|
37
|
+
u.hostname === 'vibecontrols.com' || u.hostname.endsWith('.vibecontrols.com') ||
|
|
38
|
+
u.hostname === 'burdenoff.com' || u.hostname === 'app.burdenoff.com' || u.hostname === 'alphaapp.burdenoff.com'
|
|
39
|
+
);
|
|
40
|
+
} catch { return false; }
|
|
41
|
+
}
|
|
42
|
+
function send(kind, payload, requestId) {
|
|
43
|
+
const env = { v: ENVELOPE_VERSION, source: 'plugin', kind, payload };
|
|
44
|
+
if (requestId) env.requestId = requestId;
|
|
45
|
+
window.parent?.postMessage(env, '*');
|
|
46
|
+
}
|
|
47
|
+
function rpc(method, args) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const requestId = 'r-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 6);
|
|
50
|
+
const off = (event) => {
|
|
51
|
+
if (!isAllowed(event.origin)) return;
|
|
52
|
+
const d = event.data;
|
|
53
|
+
if (!d || d.v !== ENVELOPE_VERSION || d.source !== 'host') return;
|
|
54
|
+
if (d.kind === 'host:rpc-response' && d.requestId === requestId) {
|
|
55
|
+
window.removeEventListener('message', off);
|
|
56
|
+
if (d.payload?.ok) resolve(d.payload.result);
|
|
57
|
+
else reject(new Error(d.payload?.error?.message ?? 'rpc failed'));
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
window.addEventListener('message', off);
|
|
61
|
+
send('plugin:rpc-request', { method, args, streaming: false }, requestId);
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
window.removeEventListener('message', off);
|
|
64
|
+
reject(new Error('rpc timeout'));
|
|
65
|
+
}, 8000);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
window.addEventListener('message', async (event) => {
|
|
69
|
+
if (!isAllowed(event.origin)) return;
|
|
70
|
+
const d = event.data;
|
|
71
|
+
if (!d || d.v !== ENVELOPE_VERSION || d.source !== 'host') return;
|
|
72
|
+
if (d.kind === 'host:init') {
|
|
73
|
+
const init = d.payload ?? {};
|
|
74
|
+
const vibeId = init.context?.vibeId;
|
|
75
|
+
if (vibeId) document.getElementById('vibe-id').textContent = vibeId;
|
|
76
|
+
document.getElementById('git-info').hidden = false;
|
|
77
|
+
if (init.theme?.colorMode === 'dark') {
|
|
78
|
+
document.documentElement.setAttribute('data-vibe-theme', 'dark');
|
|
79
|
+
}
|
|
80
|
+
// Best-effort: ask the host for the cached Vibe so we can show
|
|
81
|
+
// branch / status / remote without an extra fetch.
|
|
82
|
+
try {
|
|
83
|
+
const vibe = await rpc('getContext', { include: ['vibe'] });
|
|
84
|
+
if (vibe?.gitBranch) document.getElementById('branch').textContent = vibe.gitBranch;
|
|
85
|
+
if (vibe?.gitStatus) document.getElementById('status').textContent = vibe.gitStatus;
|
|
86
|
+
if (vibe?.gitRemote) document.getElementById('remote').textContent = vibe.gitRemote;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// RPC not implemented yet — leave the dashes in place.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
send('plugin:ready', {
|
|
93
|
+
pluginId: 'ungit-git',
|
|
94
|
+
pluginVersion: '2026.521.1',
|
|
95
|
+
sdkVersion: '1',
|
|
96
|
+
declaredCapabilities: { restPaths: ['/ui/ungit'], wsTopics: [], rpcMethods: ['getContext'] },
|
|
97
|
+
});
|
|
98
|
+
</script>
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibecontrols/vibe-plugin-tool-git",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.521.1",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"bun": ">=1.3.0"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "bun build ./src/index.ts --outdir ./dist --target bun --minify-syntax --minify-whitespace --external elysia --external @opentui/core && tsc --emitDeclarationOnly --declaration --outDir ./dist",
|
|
10
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target bun --minify-syntax --minify-whitespace --external elysia --external @opentui/core && tsc --emitDeclarationOnly --declaration --outDir ./dist && cp -r ./src/ui-git ./dist/ui-git",
|
|
11
11
|
"dev": "tsc --watch",
|
|
12
12
|
"lint": "eslint ./src",
|
|
13
13
|
"format": "bunx prettier . --write",
|