@miphamai/cli 0.3.0 → 0.5.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/bin/mipham.ts +188 -0
- package/dist/mipham +0 -0
- package/package.json +9 -9
- package/skills/mipham/om-artifact.mipham-skill.md +69 -0
- package/skills/mipham/om-model-optimize.mipham-skill.md +9 -6
- package/skills/mipham/om-security.mipham-skill.md +11 -8
- package/skills/standard/doc-generator.SKILL.md +6 -1
- package/skills/standard/github-ops.SKILL.md +12 -7
- package/skills/standard/memory.SKILL.md +1 -0
- package/skills/standard/self-review.SKILL.md +1 -0
- package/skills/standard/superpower.SKILL.md +7 -7
- package/skills/standard/web-search.SKILL.md +3 -0
- package/src/agent/agent-context.ts +56 -0
- package/src/agent/agent-registry.ts +134 -0
- package/src/agent/sub-agent.ts +73 -89
- package/src/agent/types.ts +39 -0
- package/src/agent-view/agent-view-manager.ts +217 -0
- package/src/agent-view/dashboard.tsx +218 -0
- package/src/agent-view/session-peek.tsx +72 -0
- package/src/agent-view/session-row.tsx +70 -0
- package/src/artifacts/manifest.ts +101 -0
- package/src/artifacts/server.ts +374 -0
- package/src/artifacts/versioning.ts +127 -0
- package/src/core/context-compact.ts +50 -0
- package/src/core/context-drain.ts +54 -0
- package/src/core/context-microcompact.ts +132 -0
- package/src/core/context-snip.ts +74 -0
- package/src/core/context-token.ts +108 -0
- package/src/core/context.ts +169 -0
- package/src/core/engine.ts +207 -58
- package/src/core/hooks-config.ts +52 -0
- package/src/core/hooks-executor.ts +113 -0
- package/src/core/hooks.ts +90 -30
- package/src/core/instructions.ts +12 -1
- package/src/core/memory/memory-loader.ts +23 -0
- package/src/core/memory/memory-manager.ts +192 -0
- package/src/core/memory/memory-writer.ts +72 -0
- package/src/core/permission-config.ts +34 -0
- package/src/core/permission-rules.ts +66 -0
- package/src/core/permission.ts +224 -34
- package/src/index.tsx +30 -2
- package/src/mcp/transport.ts +42 -5
- package/src/plugin/plugin-loader.ts +36 -0
- package/src/plugin/plugin-manager.ts +125 -0
- package/src/plugin/plugin-validator.ts +41 -0
- package/src/providers/fetch-utils.ts +1 -3
- package/src/providers/openai-compat.ts +2 -11
- package/src/shared/constants.ts +8 -1
- package/src/shared/types.ts +82 -2
- package/src/skills/fork-executor.ts +40 -0
- package/src/skills/loader.ts +48 -2
- package/src/tools/agent/agent.ts +20 -11
- package/src/tools/agent/skill.ts +32 -2
- package/src/tools/artifact/artifact.ts +144 -0
- package/src/tools/computer/app-launcher.ts +39 -0
- package/src/tools/computer/browser.ts +48 -0
- package/src/tools/computer/computer-use.ts +88 -0
- package/src/tools/computer/playwright.d.ts +7 -0
- package/src/tools/computer/screenshot.ts +57 -0
- package/src/tools/index.ts +6 -0
- package/src/ui/app.tsx +20 -7
- package/src/ui/chat.tsx +9 -5
- package/src/ui/commands.ts +185 -40
- package/src/ui/input.tsx +203 -27
- package/src/ui/picker.tsx +2 -5
- package/src/ui/vim-motions.ts +96 -0
- package/src/workflow/budget.ts +33 -0
- package/src/workflow/journal.ts +105 -0
- package/src/workflow/primitives/agent.ts +51 -0
- package/src/workflow/primitives/parallel.ts +8 -0
- package/src/workflow/primitives/phase.ts +19 -0
- package/src/workflow/primitives/pipeline.ts +24 -0
- package/src/workflow/runtime.ts +87 -0
- package/src/workflow/sandbox.ts +75 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createSandbox } from './sandbox'
|
|
2
|
+
import { createJournal, appendJournal } from './journal'
|
|
3
|
+
import { createBudget } from './budget'
|
|
4
|
+
import { workflowAgent } from './primitives/agent'
|
|
5
|
+
import { parallel } from './primitives/parallel'
|
|
6
|
+
import { pipeline } from './primitives/pipeline'
|
|
7
|
+
import { phase as phasePrimitive } from './primitives/phase'
|
|
8
|
+
import type { ProviderRegistry } from '../providers/registry'
|
|
9
|
+
import type { QueryEngine } from '../core/engine'
|
|
10
|
+
|
|
11
|
+
export interface WorkflowRunResult {
|
|
12
|
+
runId: string
|
|
13
|
+
result: unknown
|
|
14
|
+
journalEntries: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Execute a workflow script string.
|
|
19
|
+
*
|
|
20
|
+
* The script is evaluated in a sandboxed context with the workflow
|
|
21
|
+
* primitives (agent, parallel, pipeline, phase, args, budget) injected.
|
|
22
|
+
*/
|
|
23
|
+
export async function runWorkflow(
|
|
24
|
+
script: string,
|
|
25
|
+
engine: QueryEngine,
|
|
26
|
+
args: unknown = {},
|
|
27
|
+
budgetTotal: number | null = null,
|
|
28
|
+
): Promise<WorkflowRunResult> {
|
|
29
|
+
const runId = `run-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`
|
|
30
|
+
createJournal(runId, script)
|
|
31
|
+
|
|
32
|
+
const registry: ProviderRegistry = engine.getRegistry()
|
|
33
|
+
const toolRegistry = engine.getTools()
|
|
34
|
+
|
|
35
|
+
const budget = createBudget(budgetTotal)
|
|
36
|
+
|
|
37
|
+
// Wrap primitives with journal recording
|
|
38
|
+
const agent = async (prompt: string, opts?: Record<string, unknown>) => {
|
|
39
|
+
const result = await workflowAgent(
|
|
40
|
+
prompt,
|
|
41
|
+
registry,
|
|
42
|
+
toolRegistry,
|
|
43
|
+
opts as Record<string, unknown>,
|
|
44
|
+
)
|
|
45
|
+
appendJournal(runId, {
|
|
46
|
+
type: 'agent',
|
|
47
|
+
prompt,
|
|
48
|
+
opts: opts as Record<string, unknown> | undefined,
|
|
49
|
+
result,
|
|
50
|
+
})
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const wrappedPhase = (title: string) => {
|
|
55
|
+
phasePrimitive(title)
|
|
56
|
+
appendJournal(runId, { type: 'phase', message: title })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const log = (message: string) => {
|
|
60
|
+
appendJournal(runId, { type: 'log', message })
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const sandbox = createSandbox(args, budget)
|
|
64
|
+
|
|
65
|
+
// Build the script wrapper
|
|
66
|
+
const wrappedScript = `
|
|
67
|
+
return (async () => {
|
|
68
|
+
${script}
|
|
69
|
+
})()
|
|
70
|
+
`
|
|
71
|
+
|
|
72
|
+
// Execute in sandboxed context
|
|
73
|
+
const scriptFn = new Function(
|
|
74
|
+
'agent',
|
|
75
|
+
'parallel',
|
|
76
|
+
'pipeline',
|
|
77
|
+
'phase',
|
|
78
|
+
'log',
|
|
79
|
+
'args',
|
|
80
|
+
'budget',
|
|
81
|
+
wrappedScript,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
const result = await scriptFn(agent, parallel, pipeline, wrappedPhase, log, args, budget)
|
|
85
|
+
|
|
86
|
+
return { runId, result, journalEntries: 0 }
|
|
87
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** APIs disabled in workflow scripts to ensure deterministic replay. */
|
|
2
|
+
const FORBIDDEN = new Set(['Date.now', 'Math.random', 'crypto.randomUUID'])
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create a sandboxed global scope for workflow script execution.
|
|
6
|
+
* Blocks Date.now(), Math.random(), argless new Date(), crypto.randomUUID().
|
|
7
|
+
*/
|
|
8
|
+
export function createSandbox(
|
|
9
|
+
args: unknown,
|
|
10
|
+
budget: { total: number | null; spent(): number; remaining(): number },
|
|
11
|
+
): Record<string, unknown> {
|
|
12
|
+
const sandbox: Record<string, unknown> = {
|
|
13
|
+
args,
|
|
14
|
+
budget,
|
|
15
|
+
console: {
|
|
16
|
+
log: (..._a: unknown[]) => {}, // no-op in sandbox
|
|
17
|
+
error: (..._a: unknown[]) => {},
|
|
18
|
+
},
|
|
19
|
+
// Primitives are injected by the runtime, not the sandbox
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Override Date to block now() and argless constructor
|
|
23
|
+
const OriginalDate = Date
|
|
24
|
+
sandbox.Date = new Proxy(OriginalDate, {
|
|
25
|
+
construct(_target, constructorArgs) {
|
|
26
|
+
if (constructorArgs.length === 0) {
|
|
27
|
+
throw new Error('new Date() is disabled in workflow sandbox. Pass timestamps via args.')
|
|
28
|
+
}
|
|
29
|
+
return new (OriginalDate as unknown as new (...a: unknown[]) => Date)(
|
|
30
|
+
...(constructorArgs as [number]),
|
|
31
|
+
)
|
|
32
|
+
},
|
|
33
|
+
get(_target, prop) {
|
|
34
|
+
if (prop === 'now') {
|
|
35
|
+
throw new Error('Date.now() is disabled in workflow sandbox. Pass timestamps via args.')
|
|
36
|
+
}
|
|
37
|
+
const val = (OriginalDate as unknown as Record<string, unknown>)[prop as string]
|
|
38
|
+
return typeof val === 'function' ? (val as Function).bind(OriginalDate) : val
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Override Math.random
|
|
43
|
+
sandbox.Math = new Proxy(Math, {
|
|
44
|
+
get(_target, prop) {
|
|
45
|
+
if (prop === 'random') {
|
|
46
|
+
throw new Error('Math.random() is disabled in workflow sandbox. Use a seed from args.')
|
|
47
|
+
}
|
|
48
|
+
const val = (Math as unknown as Record<string, unknown>)[prop as string]
|
|
49
|
+
return typeof val === 'function' ? (val as Function).bind(Math) : val
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// Block crypto.randomUUID
|
|
54
|
+
const globalCrypto = (globalThis as Record<string, unknown>).crypto as
|
|
55
|
+
| { randomUUID?: unknown; [key: string]: unknown }
|
|
56
|
+
| undefined
|
|
57
|
+
if (globalCrypto) {
|
|
58
|
+
sandbox.crypto = new Proxy(globalCrypto, {
|
|
59
|
+
get(_target, prop) {
|
|
60
|
+
if (prop === 'randomUUID') {
|
|
61
|
+
throw new Error('crypto.randomUUID() is disabled in workflow sandbox.')
|
|
62
|
+
}
|
|
63
|
+
const val = (globalCrypto as Record<string, unknown>)[prop as string]
|
|
64
|
+
return typeof val === 'function' ? (val as Function).bind(globalCrypto) : val
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return sandbox
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Check whether a given API identifier is in the forbidden set. */
|
|
73
|
+
export function isForbidden(id: string): boolean {
|
|
74
|
+
return FORBIDDEN.has(id)
|
|
75
|
+
}
|