@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.
Files changed (74) hide show
  1. package/bin/mipham.ts +188 -0
  2. package/dist/mipham +0 -0
  3. package/package.json +9 -9
  4. package/skills/mipham/om-artifact.mipham-skill.md +69 -0
  5. package/skills/mipham/om-model-optimize.mipham-skill.md +9 -6
  6. package/skills/mipham/om-security.mipham-skill.md +11 -8
  7. package/skills/standard/doc-generator.SKILL.md +6 -1
  8. package/skills/standard/github-ops.SKILL.md +12 -7
  9. package/skills/standard/memory.SKILL.md +1 -0
  10. package/skills/standard/self-review.SKILL.md +1 -0
  11. package/skills/standard/superpower.SKILL.md +7 -7
  12. package/skills/standard/web-search.SKILL.md +3 -0
  13. package/src/agent/agent-context.ts +56 -0
  14. package/src/agent/agent-registry.ts +134 -0
  15. package/src/agent/sub-agent.ts +73 -89
  16. package/src/agent/types.ts +39 -0
  17. package/src/agent-view/agent-view-manager.ts +217 -0
  18. package/src/agent-view/dashboard.tsx +218 -0
  19. package/src/agent-view/session-peek.tsx +72 -0
  20. package/src/agent-view/session-row.tsx +70 -0
  21. package/src/artifacts/manifest.ts +101 -0
  22. package/src/artifacts/server.ts +374 -0
  23. package/src/artifacts/versioning.ts +127 -0
  24. package/src/core/context-compact.ts +50 -0
  25. package/src/core/context-drain.ts +54 -0
  26. package/src/core/context-microcompact.ts +132 -0
  27. package/src/core/context-snip.ts +74 -0
  28. package/src/core/context-token.ts +108 -0
  29. package/src/core/context.ts +169 -0
  30. package/src/core/engine.ts +207 -58
  31. package/src/core/hooks-config.ts +52 -0
  32. package/src/core/hooks-executor.ts +113 -0
  33. package/src/core/hooks.ts +90 -30
  34. package/src/core/instructions.ts +12 -1
  35. package/src/core/memory/memory-loader.ts +23 -0
  36. package/src/core/memory/memory-manager.ts +192 -0
  37. package/src/core/memory/memory-writer.ts +72 -0
  38. package/src/core/permission-config.ts +34 -0
  39. package/src/core/permission-rules.ts +66 -0
  40. package/src/core/permission.ts +224 -34
  41. package/src/index.tsx +30 -2
  42. package/src/mcp/transport.ts +42 -5
  43. package/src/plugin/plugin-loader.ts +36 -0
  44. package/src/plugin/plugin-manager.ts +125 -0
  45. package/src/plugin/plugin-validator.ts +41 -0
  46. package/src/providers/fetch-utils.ts +1 -3
  47. package/src/providers/openai-compat.ts +2 -11
  48. package/src/shared/constants.ts +8 -1
  49. package/src/shared/types.ts +82 -2
  50. package/src/skills/fork-executor.ts +40 -0
  51. package/src/skills/loader.ts +48 -2
  52. package/src/tools/agent/agent.ts +20 -11
  53. package/src/tools/agent/skill.ts +32 -2
  54. package/src/tools/artifact/artifact.ts +144 -0
  55. package/src/tools/computer/app-launcher.ts +39 -0
  56. package/src/tools/computer/browser.ts +48 -0
  57. package/src/tools/computer/computer-use.ts +88 -0
  58. package/src/tools/computer/playwright.d.ts +7 -0
  59. package/src/tools/computer/screenshot.ts +57 -0
  60. package/src/tools/index.ts +6 -0
  61. package/src/ui/app.tsx +20 -7
  62. package/src/ui/chat.tsx +9 -5
  63. package/src/ui/commands.ts +185 -40
  64. package/src/ui/input.tsx +203 -27
  65. package/src/ui/picker.tsx +2 -5
  66. package/src/ui/vim-motions.ts +96 -0
  67. package/src/workflow/budget.ts +33 -0
  68. package/src/workflow/journal.ts +105 -0
  69. package/src/workflow/primitives/agent.ts +51 -0
  70. package/src/workflow/primitives/parallel.ts +8 -0
  71. package/src/workflow/primitives/phase.ts +19 -0
  72. package/src/workflow/primitives/pipeline.ts +24 -0
  73. package/src/workflow/runtime.ts +87 -0
  74. 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
+ }