Class: Arcp::Runtime::JobContext

Inherits:
Object
  • Object
show all
Defined in:
lib/arcp/runtime/job_context.rb

Overview

Passed to an agent handler. Exposes emission seams (events, progress, tool calls, streamed result) and read-only state (job_id, agent, input, lease).

Defined Under Namespace

Classes: ChunkWriter

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(job_id:, agent:, input:, lease:, sink:) ⇒ JobContext

Returns a new instance of JobContext.



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/arcp/runtime/job_context.rb', line 15

def initialize(job_id:, agent:, input:, lease:, sink:)
  @job_id = job_id
  @agent = agent
  @input = input
  @lease = lease
  @sink = sink
  @event_seq = 0
  @result_id = nil
  @result_buffer = []
  @done = false
  @chunked = false
  @mutex = Mutex.new
end

Instance Attribute Details

#agentObject (readonly)

Returns the value of attribute agent.



13
14
15
# File 'lib/arcp/runtime/job_context.rb', line 13

def agent
  @agent
end

#event_seqObject (readonly)

Returns the value of attribute event_seq.



13
14
15
# File 'lib/arcp/runtime/job_context.rb', line 13

def event_seq
  @event_seq
end

#inputObject (readonly)

Returns the value of attribute input.



13
14
15
# File 'lib/arcp/runtime/job_context.rb', line 13

def input
  @input
end

#job_idObject (readonly)

Returns the value of attribute job_id.



13
14
15
# File 'lib/arcp/runtime/job_context.rb', line 13

def job_id
  @job_id
end

#leaseObject (readonly)

Returns the value of attribute lease.



13
14
15
# File 'lib/arcp/runtime/job_context.rb', line 13

def lease
  @lease
end

Instance Method Details

#emit(kind:, body:) ⇒ Object



29
30
31
32
33
# File 'lib/arcp/runtime/job_context.rb', line 29

def emit(kind:, body:)
  event = Arcp::Job::Event.new(kind: kind, body: body)
  @event_seq = @sink.publish_event(@job_id, event)
  event
end

#fail!(code:, message: nil, retryable: false, details: {}) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/arcp/runtime/job_context.rb', line 117

def fail!(code:, message: nil, retryable: false, details: {})
  raise Arcp::Errors::ProtocolViolation, 'result already finalized' if @done

  @done = true
  @sink.publish_error(
    @job_id,
    Arcp::Job::JobError.new(
      job_id: @job_id, final_status: 'error',
      code: code, message: message, retryable: retryable, details: details
    )
  )
end

#finish(result: nil) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/arcp/runtime/job_context.rb', line 96

def finish(result: nil)
  raise Arcp::Errors::ProtocolViolation, 'result already finalized' if @done

  if @chunked && !result.nil?
    raise Arcp::Errors::ProtocolViolation, 'cannot mix inline result with result_chunk stream'
  end

  @done = true

  @sink.publish_result(
    @job_id,
    Arcp::Job::Result.new(
      job_id: @job_id, final_status: 'success',
      result: result,
      result_id: @chunked ? @result_id : nil,
      result_size: @chunked ? @result_buffer[:bytes] : nil,
      completed_at: Time.now.utc.iso8601
    )
  )
end

#log(level:, message:, **fields) ⇒ Object



35
36
37
38
# File 'lib/arcp/runtime/job_context.rb', line 35

def log(level:, message:, **fields)
  emit(kind: Arcp::Job::EventKind::LOG,
       body: Arcp::Job::EventBody::Log.new(level: level, message: message, fields: fields))
end

#metric(name:, value:, unit: nil) ⇒ Object



46
47
48
49
# File 'lib/arcp/runtime/job_context.rb', line 46

def metric(name:, value:, unit: nil)
  emit(kind: Arcp::Job::EventKind::METRIC,
       body: Arcp::Job::EventBody::Metric.new(name: name, value: value, unit: unit))
end

#progress(current:, total: nil, units: nil, message: nil) ⇒ Object



40
41
42
43
44
# File 'lib/arcp/runtime/job_context.rb', line 40

def progress(current:, total: nil, units: nil, message: nil)
  emit(kind: Arcp::Job::EventKind::PROGRESS,
       body: Arcp::Job::EventBody::Progress.new(current: current, total: total, units: units,
                                                message: message))
end

#rotate_credential(id:, new_value:) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/arcp/runtime/job_context.rb', line 57

def rotate_credential(id:, new_value:)
  new_id = @sink.runtime.credential_registry&.rotate(
    job_id: job_id,
    credential_id: id,
    new_value: new_value
  )
  status(
    phase: 'credential_rotated',
    fields: { 'id' => new_id || id, 'value' => new_value }
  )
end

#status(phase:, message: nil, fields: {}) ⇒ Object



51
52
53
54
55
# File 'lib/arcp/runtime/job_context.rb', line 51

def status(phase:, message: nil, fields: {})
  emit(kind: Arcp::Job::EventKind::STATUS,
       body: Arcp::Job::EventBody::Status.new(phase: phase, message: message,
                                              fields: fields))
end

#stream_result(encoding: 'utf8', &block) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/arcp/runtime/job_context.rb', line 79

def stream_result(encoding: 'utf8', &block)
  raise Arcp::Errors::ProtocolViolation, 'result already finalized' if @done

  @chunked = true
  @result_id = Arcp::Ids.result_id

  writer = ChunkWriter.new(ctx: self, encoding: encoding, result_id: @result_id)
  if block
    yield writer
    writer.close
    @result_buffer = writer.totals
    @result_buffer
  else
    writer
  end
end

#tool_call(call_id:, tool:, args:) ⇒ Object



69
70
71
72
# File 'lib/arcp/runtime/job_context.rb', line 69

def tool_call(call_id:, tool:, args:)
  emit(kind: Arcp::Job::EventKind::TOOL_CALL,
       body: Arcp::Job::EventBody::ToolCall.new(call_id: call_id, tool: tool, args: args))
end

#tool_result(call_id:, result: nil, error: nil) ⇒ Object



74
75
76
77
# File 'lib/arcp/runtime/job_context.rb', line 74

def tool_result(call_id:, result: nil, error: nil)
  emit(kind: Arcp::Job::EventKind::TOOL_RESULT,
       body: Arcp::Job::EventBody::ToolResult.new(call_id: call_id, result: result, error: error))
end