init
Release Please / release-please (push) Failing after 4m2s
Web CI / web typecheck + build (push) Successful in 3m39s
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 1h1m49s
CodeQL Analysis / Analyze (go) (push) Failing after 1h1m49s

This commit is contained in:
redlineo committed 2026-07-13 10:14:00 +03:00
commit d295c7f139
1527 files changed
+270726

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) the career-ops-plugin-{{NAME}} authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+38
View File
@@ -0,0 +1,38 @@
# career-ops-plugin-{{NAME}}
A community plugin for [career-ops](https://github.com/santifer/career-ops).
## What it does
TODO: one paragraph.
## Install
```bash
# Once it's in the career-ops registry:
node plugins.mjs add {{NAME}}
# Before listing (install directly from your repo at a pinned commit):
node plugins.mjs add <your-github-user>/career-ops-plugin-{{NAME}} --sha <40-hex-commit>
```
Then enable + consent:
```bash
node plugins.mjs enable {{NAME}} # shows the capability card
node plugins.mjs enable {{NAME}} --confirm # grants it
```
## Configure
- Secrets go in your `.env` (the names are in `manifest.json` → `requiredEnv`).
- Non-secret options go in `config/plugins.yml` under `plugins.{{NAME}}`.
## Get it listed as approved
Open a registry PR against career-ops (see
[docs/PLUGINS.md](https://github.com/santifer/career-ops/blob/main/docs/PLUGINS.md)).
## License
MIT
+22
View File
@@ -0,0 +1,22 @@
// @ts-check
// {{NAME}} — a career-ops plugin.
// Guide: https://github.com/santifer/career-ops/blob/main/docs/PLUGINS.md
//
// Rules the engine enforces for you:
// - Egress ONLY through ctx.fetch / ctx.fetchJson / ctx.fetchText (your manifest
// `allowedHosts` is applied + SSRF-guarded). Do NOT import node:http/net or
// call global fetch — community plugins are rejected for that.
// - Producers (provider/ingest/search) RETURN Job[] = { title, url, company, location };
// the engine writes them to the pipeline. Consumers (export/notify) push to
// the user's own store. There is no auto-submit hook.
// - Keys come from ctx.env (declare them in manifest.requiredEnv); non-secret
// settings come from ctx.settings (the user's config/plugins.yml block).
export default {
// Replace/add hooks to match manifest.hooks. Example ingest:
async ingest(ctx) {
// const data = await ctx.fetchJson('https://api.example.com/jobs');
// return data.results.map(j => ({ title: j.title, url: j.url, company: j.company, location: j.location || '' }));
return [];
},
};
+13
View File
@@ -0,0 +1,13 @@
{
"id": "{{NAME}}",
"name": "{{NAME}}",
"version": "0.1.0",
"apiVersion": 1,
"description": "TODO: one mission-framed line describing what this plugin does.",
"hooks": ["ingest"],
"requiredEnv": [],
"allowedHosts": [],
"skill": "skill.md",
"humanInTheLoop": true,
"homepage": "https://github.com/your-user/career-ops-plugin-{{NAME}}"
}
+25
View File
@@ -0,0 +1,25 @@
---
name: career-ops-plugin-{{NAME}}
description: How to use the {{NAME}} plugin and the data it produces.
license: MIT
---
# {{NAME}}
> This file teaches an AI agent how to drive THIS plugin. Keep it scoped to the
> plugin's own domain — it must not instruct the agent to edit core files, change
> scoring, or act outside the plugin's declared hooks.
## How to run it
- `node plugins.mjs run {{NAME}}` — runs the plugin's hook.
## What it produces
TODO: describe the data structure. For a producer hook, the `Job[]` fields you
emit (title, url, company, location). For an export hook, what you push and where.
## Settings
TODO: any non-secret options the user sets in `config/plugins.yml` under
`plugins.{{NAME}}` (these arrive as `ctx.settings`).
+21
View File
@@ -0,0 +1,21 @@
// Zero-network smoke test: the entry imports cleanly and exposes only valid
// hooks that match the manifest. Run by `plugins.mjs add` + the registry CI.
import assert from 'node:assert';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const here = path.dirname(fileURLToPath(import.meta.url));
const KINDS = ['provider', 'ingest', 'search', 'notify', 'export'];
const manifest = JSON.parse(readFileSync(path.join(here, '..', 'manifest.json'), 'utf8'));
const mod = await import(path.join(here, '..', manifest.entry || 'index.mjs'));
const hooks = mod.default;
assert(hooks && typeof hooks === 'object', 'default export must be an object of hooks');
const keys = Object.keys(hooks);
assert(keys.length > 0, 'declare at least one hook');
for (const k of keys) assert(KINDS.includes(k), `unknown hook "${k}"`);
for (const h of manifest.hooks) assert(keys.includes(h), `manifest declares hook "${h}" but index.mjs does not export it`);
console.log('✓ smoke ok:', keys.join(', '));