delimit-cli 3.14.41 → 3.14.43
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/bin/delimit-cli.js +118 -0
- package/bin/delimit-setup.js +115 -14
- package/gateway/ai/founding_users.py +2 -1
- package/gateway/ai/notify.py +5 -6
- package/gateway/ai/server.py +3 -3
- package/gateway/ai/social_target.py +31 -83
- package/package.json +1 -1
package/bin/delimit-cli.js
CHANGED
|
@@ -1647,6 +1647,124 @@ program
|
|
|
1647
1647
|
} catch {}
|
|
1648
1648
|
});
|
|
1649
1649
|
|
|
1650
|
+
// Resume command — show what was happening last session (STR-047)
|
|
1651
|
+
program
|
|
1652
|
+
.command('resume')
|
|
1653
|
+
.description('Show what you were working on — context from your last session')
|
|
1654
|
+
.action(async () => {
|
|
1655
|
+
console.log(chalk.bold('\n Delimit — Resume Work\n'));
|
|
1656
|
+
|
|
1657
|
+
const DELIMIT_HOME = path.join(os.homedir(), '.delimit');
|
|
1658
|
+
|
|
1659
|
+
// 1. Last session handoff
|
|
1660
|
+
const sessionsDir = path.join(DELIMIT_HOME, 'sessions');
|
|
1661
|
+
if (fs.existsSync(sessionsDir)) {
|
|
1662
|
+
try {
|
|
1663
|
+
const sessions = fs.readdirSync(sessionsDir)
|
|
1664
|
+
.filter(f => f.endsWith('.json'))
|
|
1665
|
+
.sort()
|
|
1666
|
+
.reverse();
|
|
1667
|
+
|
|
1668
|
+
if (sessions.length > 0) {
|
|
1669
|
+
const lastSession = JSON.parse(fs.readFileSync(path.join(sessionsDir, sessions[0]), 'utf-8'));
|
|
1670
|
+
const ts = sessions[0].replace('session_', '').replace('.json', '').replace(/_/g, ' ');
|
|
1671
|
+
console.log(chalk.bold(' Last session:') + chalk.gray(` ${ts}`));
|
|
1672
|
+
if (lastSession.summary) {
|
|
1673
|
+
console.log(chalk.gray(` ${lastSession.summary.substring(0, 200)}`));
|
|
1674
|
+
}
|
|
1675
|
+
if (lastSession.tasks_completed && lastSession.tasks_completed.length > 0) {
|
|
1676
|
+
console.log(chalk.green(` ${lastSession.tasks_completed.length} task(s) completed`));
|
|
1677
|
+
}
|
|
1678
|
+
if (lastSession.pending && lastSession.pending.length > 0) {
|
|
1679
|
+
console.log(chalk.yellow(` ${lastSession.pending.length} item(s) pending`));
|
|
1680
|
+
lastSession.pending.slice(0, 3).forEach(p => {
|
|
1681
|
+
console.log(chalk.gray(` • ${typeof p === 'string' ? p : p.title || JSON.stringify(p).substring(0, 80)}`));
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
console.log('');
|
|
1685
|
+
}
|
|
1686
|
+
} catch {}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// 2. Open ledger items
|
|
1690
|
+
const ledgerDir = path.join(DELIMIT_HOME, 'ledger');
|
|
1691
|
+
if (fs.existsSync(ledgerDir)) {
|
|
1692
|
+
try {
|
|
1693
|
+
const ledgerFiles = fs.readdirSync(ledgerDir).filter(f => f.endsWith('.json'));
|
|
1694
|
+
let openItems = [];
|
|
1695
|
+
for (const lf of ledgerFiles) {
|
|
1696
|
+
try {
|
|
1697
|
+
const items = JSON.parse(fs.readFileSync(path.join(ledgerDir, lf), 'utf-8'));
|
|
1698
|
+
if (Array.isArray(items)) {
|
|
1699
|
+
openItems.push(...items.filter(i => i.status === 'open'));
|
|
1700
|
+
}
|
|
1701
|
+
} catch {}
|
|
1702
|
+
}
|
|
1703
|
+
if (openItems.length > 0) {
|
|
1704
|
+
// Sort by priority
|
|
1705
|
+
const priorityOrder = { P0: 0, P1: 1, P2: 2 };
|
|
1706
|
+
openItems.sort((a, b) => (priorityOrder[a.priority] || 3) - (priorityOrder[b.priority] || 3));
|
|
1707
|
+
|
|
1708
|
+
console.log(chalk.bold(` Open items: ${openItems.length}`));
|
|
1709
|
+
const p0 = openItems.filter(i => i.priority === 'P0');
|
|
1710
|
+
const p1 = openItems.filter(i => i.priority === 'P1');
|
|
1711
|
+
if (p0.length > 0) {
|
|
1712
|
+
console.log(chalk.red(` ${p0.length} urgent (P0):`));
|
|
1713
|
+
p0.slice(0, 3).forEach(i => console.log(chalk.gray(` ${i.id}: ${i.title.substring(0, 60)}`)));
|
|
1714
|
+
}
|
|
1715
|
+
if (p1.length > 0) {
|
|
1716
|
+
console.log(chalk.yellow(` ${p1.length} important (P1)`));
|
|
1717
|
+
}
|
|
1718
|
+
console.log('');
|
|
1719
|
+
}
|
|
1720
|
+
} catch {}
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// 3. Recent memory
|
|
1724
|
+
const memoryDir = path.join(DELIMIT_HOME, 'memory');
|
|
1725
|
+
if (fs.existsSync(memoryDir)) {
|
|
1726
|
+
try {
|
|
1727
|
+
const memFiles = fs.readdirSync(memoryDir)
|
|
1728
|
+
.filter(f => f.endsWith('.json'))
|
|
1729
|
+
.map(f => ({ name: f, mtime: fs.statSync(path.join(memoryDir, f)).mtimeMs }))
|
|
1730
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
1731
|
+
.slice(0, 3);
|
|
1732
|
+
|
|
1733
|
+
if (memFiles.length > 0) {
|
|
1734
|
+
console.log(chalk.bold(' Recent memory:'));
|
|
1735
|
+
for (const mf of memFiles) {
|
|
1736
|
+
try {
|
|
1737
|
+
const mem = JSON.parse(fs.readFileSync(path.join(memoryDir, mf.name), 'utf-8'));
|
|
1738
|
+
const key = mem.key || mf.name.replace('.json', '');
|
|
1739
|
+
const val = (mem.content || mem.value || '').substring(0, 60);
|
|
1740
|
+
console.log(chalk.gray(` ${key}: ${val}`));
|
|
1741
|
+
} catch {}
|
|
1742
|
+
}
|
|
1743
|
+
console.log('');
|
|
1744
|
+
}
|
|
1745
|
+
} catch {}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
// 4. Git context
|
|
1749
|
+
try {
|
|
1750
|
+
const branch = execSync('git branch --show-current 2>/dev/null', { encoding: 'utf-8', timeout: 3000 }).trim();
|
|
1751
|
+
const lastCommit = execSync('git log --oneline -1 2>/dev/null', { encoding: 'utf-8', timeout: 3000 }).trim();
|
|
1752
|
+
const status = execSync('git status --porcelain 2>/dev/null', { encoding: 'utf-8', timeout: 3000 }).trim();
|
|
1753
|
+
const changed = status ? status.split('\n').length : 0;
|
|
1754
|
+
|
|
1755
|
+
console.log(chalk.bold(' Git:'));
|
|
1756
|
+
console.log(chalk.gray(` Branch: ${branch}`));
|
|
1757
|
+
console.log(chalk.gray(` Last: ${lastCommit.substring(0, 60)}`));
|
|
1758
|
+
if (changed > 0) console.log(chalk.yellow(` ${changed} uncommitted file(s)`));
|
|
1759
|
+
console.log('');
|
|
1760
|
+
} catch {}
|
|
1761
|
+
|
|
1762
|
+
// 5. Suggested action
|
|
1763
|
+
console.log(chalk.bold(' Start here:'));
|
|
1764
|
+
console.log(` ${chalk.green('Ask your AI:')} "Check the ledger and work on the highest priority item"`);
|
|
1765
|
+
console.log('');
|
|
1766
|
+
});
|
|
1767
|
+
|
|
1650
1768
|
// Try command — zero-risk demo with Markdown report artifact (LED-264)
|
|
1651
1769
|
program
|
|
1652
1770
|
.command('try')
|
package/bin/delimit-setup.js
CHANGED
|
@@ -999,21 +999,122 @@ exit 127
|
|
|
999
999
|
|
|
1000
1000
|
log('');
|
|
1001
1001
|
|
|
1002
|
-
//
|
|
1003
|
-
log(
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1002
|
+
// Project scan — show what Delimit already knows (STR-046)
|
|
1003
|
+
log(` ${bold('Your project:')}`);
|
|
1004
|
+
const cwd = process.cwd();
|
|
1005
|
+
let projectFindings = 0;
|
|
1006
|
+
|
|
1007
|
+
// Detect framework
|
|
1008
|
+
const frameworks = [
|
|
1009
|
+
{ file: 'package.json', check: 'express', label: 'Express API' },
|
|
1010
|
+
{ file: 'package.json', check: 'fastify', label: 'Fastify API' },
|
|
1011
|
+
{ file: 'package.json', check: 'next', label: 'Next.js' },
|
|
1012
|
+
{ file: 'package.json', check: '@nestjs', label: 'NestJS' },
|
|
1013
|
+
{ file: 'requirements.txt', check: 'fastapi', label: 'FastAPI' },
|
|
1014
|
+
{ file: 'requirements.txt', check: 'django', label: 'Django' },
|
|
1015
|
+
{ file: 'requirements.txt', check: 'flask', label: 'Flask' },
|
|
1016
|
+
{ file: 'pyproject.toml', check: 'fastapi', label: 'FastAPI' },
|
|
1017
|
+
];
|
|
1018
|
+
for (const fw of frameworks) {
|
|
1019
|
+
const fwPath = path.join(cwd, fw.file);
|
|
1020
|
+
try {
|
|
1021
|
+
if (fs.existsSync(fwPath) && fs.readFileSync(fwPath, 'utf-8').toLowerCase().includes(fw.check)) {
|
|
1022
|
+
await logp(` ${green('✓')} Framework: ${fw.label}`);
|
|
1023
|
+
projectFindings++;
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
} catch {}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// Detect OpenAPI specs
|
|
1030
|
+
const specPatterns = ['openapi.yaml', 'openapi.yml', 'openapi.json', 'swagger.yaml', 'swagger.json', 'api.yaml'];
|
|
1031
|
+
let specFound = false;
|
|
1032
|
+
for (const sp of specPatterns) {
|
|
1033
|
+
if (fs.existsSync(path.join(cwd, sp))) {
|
|
1034
|
+
await logp(` ${green('✓')} API spec: ${sp}`);
|
|
1035
|
+
specFound = true;
|
|
1036
|
+
projectFindings++;
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (!specFound) {
|
|
1041
|
+
await logp(` ${dim(' No API spec found — run')} ${blue('delimit-cli lint')} ${dim('to detect one')}`);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// Count tests
|
|
1045
|
+
const testDirs = ['tests', 'test', '__tests__', 'spec'];
|
|
1046
|
+
for (const td of testDirs) {
|
|
1047
|
+
const testPath = path.join(cwd, td);
|
|
1048
|
+
if (fs.existsSync(testPath)) {
|
|
1049
|
+
try {
|
|
1050
|
+
const testFiles = fs.readdirSync(testPath).filter(f => f.includes('test') || f.includes('spec'));
|
|
1051
|
+
if (testFiles.length > 0) {
|
|
1052
|
+
await logp(` ${green('✓')} Tests: ${testFiles.length} test files in ${td}/`);
|
|
1053
|
+
projectFindings++;
|
|
1054
|
+
break;
|
|
1055
|
+
}
|
|
1056
|
+
} catch {}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// Check git status
|
|
1061
|
+
try {
|
|
1062
|
+
const gitStatus = execSync('git log --oneline -1 2>/dev/null', { encoding: 'utf-8', timeout: 3000 }).trim();
|
|
1063
|
+
if (gitStatus) {
|
|
1064
|
+
await logp(` ${green('✓')} Git: ${gitStatus.substring(0, 50)}`);
|
|
1065
|
+
projectFindings++;
|
|
1066
|
+
}
|
|
1067
|
+
} catch {}
|
|
1068
|
+
|
|
1069
|
+
// Check for existing .delimit context
|
|
1070
|
+
const ledgerDir = path.join(os.homedir(), '.delimit', 'ledger');
|
|
1071
|
+
if (fs.existsSync(ledgerDir)) {
|
|
1072
|
+
try {
|
|
1073
|
+
const ledgerFiles = fs.readdirSync(ledgerDir).filter(f => f.endsWith('.json'));
|
|
1074
|
+
let totalItems = 0;
|
|
1075
|
+
for (const lf of ledgerFiles) {
|
|
1076
|
+
try {
|
|
1077
|
+
const items = JSON.parse(fs.readFileSync(path.join(ledgerDir, lf), 'utf-8'));
|
|
1078
|
+
if (Array.isArray(items)) totalItems += items.filter(i => i.status === 'open').length;
|
|
1079
|
+
} catch {}
|
|
1080
|
+
}
|
|
1081
|
+
if (totalItems > 0) {
|
|
1082
|
+
await logp(` ${green('✓')} Ledger: ${totalItems} open items across ventures`);
|
|
1083
|
+
projectFindings++;
|
|
1084
|
+
}
|
|
1085
|
+
} catch {}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// Check for sessions
|
|
1089
|
+
const sessionsDir = path.join(os.homedir(), '.delimit', 'sessions');
|
|
1090
|
+
if (fs.existsSync(sessionsDir)) {
|
|
1091
|
+
try {
|
|
1092
|
+
const sessions = fs.readdirSync(sessionsDir).filter(f => f.endsWith('.json'));
|
|
1093
|
+
if (sessions.length > 0) {
|
|
1094
|
+
await logp(` ${green('✓')} Sessions: ${sessions.length} handoff(s) saved`);
|
|
1095
|
+
projectFindings++;
|
|
1096
|
+
}
|
|
1097
|
+
} catch {}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
if (projectFindings === 0) {
|
|
1101
|
+
log(` ${dim(' New project — run')} ${blue('delimit-cli demo')} ${dim('to see governance in action')}`);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
log('');
|
|
1105
|
+
|
|
1106
|
+
// Suggested next action based on findings
|
|
1107
|
+
log(` ${bold('Next action:')}`);
|
|
1108
|
+
if (specFound) {
|
|
1109
|
+
log(` ${green('delimit-cli lint')} — check your API spec for breaking changes`);
|
|
1110
|
+
} else if (projectFindings > 0) {
|
|
1111
|
+
log(` ${green('delimit-cli scan')} — detect API specs and potential issues`);
|
|
1112
|
+
} else {
|
|
1113
|
+
log(` ${green('delimit-cli demo')} — see governance in action (30 seconds)`);
|
|
1114
|
+
}
|
|
1013
1115
|
log('');
|
|
1014
|
-
log(` ${dim('
|
|
1015
|
-
log(` ${dim('
|
|
1016
|
-
log(` ${dim('Agents:')} ${AGENTS_DIR}`);
|
|
1116
|
+
log(` ${dim('Docs: https://delimit.ai/docs')}`);
|
|
1117
|
+
log(` ${dim('Try: https://delimit.ai/try')}`);
|
|
1017
1118
|
log('');
|
|
1018
1119
|
log(` ${bold('Keep Building.')}`);
|
|
1019
1120
|
log('');
|
|
@@ -4,6 +4,7 @@ Monitors Supabase for new signups, sends welcome emails,
|
|
|
4
4
|
tracks slots remaining, and manages the 12-month term.
|
|
5
5
|
"""
|
|
6
6
|
import json
|
|
7
|
+
import os
|
|
7
8
|
import smtplib
|
|
8
9
|
import imaplib
|
|
9
10
|
from email.mime.text import MIMEText
|
|
@@ -22,7 +23,7 @@ EMAIL = "pro@delimit.ai"
|
|
|
22
23
|
|
|
23
24
|
def _load_creds():
|
|
24
25
|
"""Load email credentials."""
|
|
25
|
-
return {"email": EMAIL, "password": "
|
|
26
|
+
return {"email": EMAIL, "password": os.environ.get("DELIMIT_FOUNDING_PASSWORD", "")}
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def _load_founding_users() -> dict:
|
package/gateway/ai/notify.py
CHANGED
|
@@ -37,7 +37,7 @@ INBOX_ROUTING_FILE = Path.home() / ".delimit" / "inbox_routing.jsonl"
|
|
|
37
37
|
IMAP_HOST = "mail.spacemail.com"
|
|
38
38
|
IMAP_PORT = 993
|
|
39
39
|
IMAP_USER = "pro@delimit.ai"
|
|
40
|
-
FORWARD_TO =
|
|
40
|
+
FORWARD_TO = os.environ.get("DELIMIT_FORWARD_TO", "")
|
|
41
41
|
|
|
42
42
|
# Domains/senders whose emails require owner action
|
|
43
43
|
OWNER_ACTION_DOMAINS = {
|
|
@@ -61,7 +61,7 @@ OWNER_ACTION_DOMAINS = {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
OWNER_ACTION_SENDERS = {
|
|
64
|
-
|
|
64
|
+
os.environ.get("DELIMIT_FORWARD_TO", ""),
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
# Subject patterns that indicate owner-action (compiled once)
|
|
@@ -222,13 +222,12 @@ def send_email(
|
|
|
222
222
|
"""Send an email notification via SMTP.
|
|
223
223
|
|
|
224
224
|
Args:
|
|
225
|
-
to: Recipient email address. Falls back to DELIMIT_SMTP_TO
|
|
226
|
-
jamsonsholdings@gmail.com.
|
|
225
|
+
to: Recipient email address. Falls back to DELIMIT_SMTP_TO env var.
|
|
227
226
|
subject: Email subject line.
|
|
228
227
|
body: Email body text (preferred). Falls back to 'message' for
|
|
229
228
|
backward compatibility.
|
|
230
229
|
from_account: Sender account key in ~/.delimit/secrets/smtp-all.json
|
|
231
|
-
(e.g. 'pro@delimit.ai', '
|
|
230
|
+
(e.g. 'pro@delimit.ai', '<configured-email>'). If provided, SMTP
|
|
232
231
|
credentials are loaded from that file instead of env vars.
|
|
233
232
|
message: Email body text (legacy parameter, use 'body' instead).
|
|
234
233
|
event_type: Event category for filtering/logging.
|
|
@@ -258,7 +257,7 @@ def send_email(
|
|
|
258
257
|
smtp_pass = os.environ.get("DELIMIT_SMTP_PASS", "")
|
|
259
258
|
smtp_from = os.environ.get("DELIMIT_SMTP_FROM", "")
|
|
260
259
|
|
|
261
|
-
smtp_to = to or os.environ.get("DELIMIT_SMTP_TO", "
|
|
260
|
+
smtp_to = to or os.environ.get("DELIMIT_SMTP_TO", "")
|
|
262
261
|
|
|
263
262
|
if not all([smtp_host, smtp_from, smtp_to]):
|
|
264
263
|
record = {
|
package/gateway/ai/server.py
CHANGED
|
@@ -5886,9 +5886,9 @@ def delimit_notify(channel: str = "webhook", message: str = "",
|
|
|
5886
5886
|
subject: Subject line (email only). Use [ACTION], [INFO], [ALERT] prefix.
|
|
5887
5887
|
event_type: Event category for filtering.
|
|
5888
5888
|
to: Recipient email address (email only). Overrides default DELIMIT_SMTP_TO.
|
|
5889
|
-
Send to any address — leave empty for default (
|
|
5889
|
+
Send to any address — leave empty for default (uses DELIMIT_SMTP_TO env var).
|
|
5890
5890
|
from_account: Sender account key from ~/.delimit/secrets/smtp-all.json
|
|
5891
|
-
(e.g. 'pro@delimit.ai', '
|
|
5891
|
+
(e.g. 'pro@delimit.ai', '<configured-email>'). Email only.
|
|
5892
5892
|
"""
|
|
5893
5893
|
from ai.notify import send_notification
|
|
5894
5894
|
return _with_next_steps("notify", _safe_call(
|
|
@@ -5994,7 +5994,7 @@ def delimit_notify_inbox(action: str = "status", limit: int = 10,
|
|
|
5994
5994
|
"""Check inbound email inbox, classify, and route (Pro).
|
|
5995
5995
|
|
|
5996
5996
|
Polls pro@delimit.ai via IMAP. Classifies emails as owner-action
|
|
5997
|
-
(forwards to
|
|
5997
|
+
(forwards to configured email) or non-owner (stays in inbox).
|
|
5998
5998
|
|
|
5999
5999
|
Args:
|
|
6000
6000
|
action: 'status' (show inbox state), 'poll' (classify and optionally forward),
|
|
@@ -201,87 +201,44 @@ def add_subreddits(venture: str, subreddits: List[str]) -> Dict[str, Any]:
|
|
|
201
201
|
return {"venture": venture, "added": new_subs, "total": config["subreddits"][venture]}
|
|
202
202
|
|
|
203
203
|
# -----------------------------------------------------------------------
|
|
204
|
-
# Per-venture routing config
|
|
204
|
+
# Per-venture routing config (loaded from ~/.delimit/social_target_ventures.json)
|
|
205
205
|
# -----------------------------------------------------------------------
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
"delimit": {
|
|
209
|
-
"topics": [
|
|
210
|
-
"API governance", "breaking changes", "OpenAPI", "API linting",
|
|
211
|
-
"MCP server", "MCP tools", "CLAUDE.md", "claude code",
|
|
212
|
-
"AI coding", "vibe coding", "semver",
|
|
213
|
-
],
|
|
214
|
-
"exclude_terms": ["delimit_ai"],
|
|
215
|
-
"owned_accounts": ["delimit_ai", "delimitdev"],
|
|
216
|
-
"priority": "P0",
|
|
217
|
-
},
|
|
218
|
-
"domainvested": {
|
|
219
|
-
"topics": [
|
|
220
|
-
"domain investing", "domain appraisal", "domain flipping",
|
|
221
|
-
"expired domains", "brandable domains", "domain valuation", "NamePros",
|
|
222
|
-
],
|
|
223
|
-
"exclude_terms": ["domainvested"],
|
|
224
|
-
"owned_accounts": ["domainvested"],
|
|
225
|
-
"priority": "P0",
|
|
226
|
-
},
|
|
227
|
-
"wirereport": {
|
|
228
|
-
"topics": [
|
|
229
|
-
"sports API", "live sports data", "sports scores API",
|
|
230
|
-
"sports news automation",
|
|
231
|
-
],
|
|
232
|
-
"exclude_terms": ["wire_report", "wirereport"],
|
|
233
|
-
"owned_accounts": ["wirereporthq"],
|
|
234
|
-
"priority": "P2",
|
|
235
|
-
},
|
|
236
|
-
"livetube": {
|
|
237
|
-
"topics": [
|
|
238
|
-
"live streaming aggregator", "multi-stream",
|
|
239
|
-
"twitch alternatives", "live stream discovery",
|
|
240
|
-
],
|
|
241
|
-
"exclude_terms": ["livetube"],
|
|
242
|
-
"owned_accounts": ["livetube_ai"],
|
|
243
|
-
"priority": "P2",
|
|
244
|
-
},
|
|
245
|
-
"stakeone": {
|
|
246
|
-
"topics": [
|
|
247
|
-
"Harmony ONE", "harmony validator", "ONE staking",
|
|
248
|
-
"harmony blockchain",
|
|
249
|
-
],
|
|
250
|
-
"exclude_terms": ["validatorone", "stake_one"],
|
|
251
|
-
"owned_accounts": ["validatorone"],
|
|
252
|
-
"priority": "P1",
|
|
253
|
-
},
|
|
254
|
-
}
|
|
207
|
+
_VENTURE_CONFIG_FILE = Path.home() / ".delimit" / "social_target_ventures.json"
|
|
255
208
|
|
|
256
209
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
210
|
+
def _load_venture_config() -> Dict[str, Any]:
|
|
211
|
+
"""Load venture config from ~/.delimit/social_target_ventures.json."""
|
|
212
|
+
if _VENTURE_CONFIG_FILE.exists():
|
|
213
|
+
try:
|
|
214
|
+
return json.loads(_VENTURE_CONFIG_FILE.read_text())
|
|
215
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
216
|
+
logger.warning("Failed to load venture config: %s", e)
|
|
217
|
+
return {}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _load_internal_users() -> set:
|
|
221
|
+
"""Load internal usernames from venture config file."""
|
|
222
|
+
config = _load_venture_config()
|
|
223
|
+
return set(config.get("internal_users", []))
|
|
260
224
|
|
|
261
|
-
VENTURE_GITHUB_QUERIES = {
|
|
262
|
-
"delimit": [
|
|
263
|
-
"openapi breaking changes",
|
|
264
|
-
"API governance CI",
|
|
265
|
-
"MCP server claude code",
|
|
266
|
-
"API linting github action",
|
|
267
|
-
],
|
|
268
|
-
"domainvested": [
|
|
269
|
-
"domain appraisal tool",
|
|
270
|
-
"domain valuation API",
|
|
271
|
-
],
|
|
272
|
-
"stakeone": [
|
|
273
|
-
"harmony one validator",
|
|
274
|
-
"harmony staking",
|
|
275
|
-
],
|
|
276
|
-
}
|
|
277
225
|
|
|
278
|
-
|
|
279
|
-
"
|
|
280
|
-
|
|
281
|
-
"
|
|
282
|
-
]
|
|
226
|
+
def _load_github_queries() -> Dict[str, List[str]]:
|
|
227
|
+
"""Load GitHub queries from venture config file."""
|
|
228
|
+
config = _load_venture_config()
|
|
229
|
+
return config.get("github_queries", {})
|
|
283
230
|
|
|
284
|
-
|
|
231
|
+
|
|
232
|
+
def _load_own_repos() -> List[str]:
|
|
233
|
+
"""Load own repo list from venture config file."""
|
|
234
|
+
config = _load_venture_config()
|
|
235
|
+
return config.get("own_repos", [])
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
VENTURE_CONFIG = _load_venture_config().get("ventures", {})
|
|
239
|
+
VENTURE_GITHUB_QUERIES = _load_github_queries()
|
|
240
|
+
OWN_REPOS = _load_own_repos()
|
|
241
|
+
INTERNAL_USERS = _load_internal_users()
|
|
285
242
|
|
|
286
243
|
|
|
287
244
|
# -----------------------------------------------------------------------
|
|
@@ -1002,15 +959,6 @@ def _get_rapidapi_key() -> str:
|
|
|
1002
959
|
return data.get("value", "")
|
|
1003
960
|
except Exception:
|
|
1004
961
|
pass
|
|
1005
|
-
# Fallback: wire report env
|
|
1006
|
-
wr_env = Path("/home/jamsons/ventures/wire-report/.wr_env")
|
|
1007
|
-
if wr_env.exists():
|
|
1008
|
-
try:
|
|
1009
|
-
for line in wr_env.read_text().splitlines():
|
|
1010
|
-
if line.startswith("RAPIDAPI_KEY="):
|
|
1011
|
-
return line.split("=", 1)[1].strip()
|
|
1012
|
-
except Exception:
|
|
1013
|
-
pass
|
|
1014
962
|
return os.environ.get("RAPIDAPI_KEY", "")
|
|
1015
963
|
|
|
1016
964
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "delimit-cli",
|
|
3
3
|
"mcpName": "io.github.delimit-ai/delimit-mcp-server",
|
|
4
|
-
"version": "3.14.
|
|
4
|
+
"version": "3.14.43",
|
|
5
5
|
"description": "Unify Claude Code, Codex, Cursor, and Gemini CLI with persistent context, governance, and multi-model debate.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|